diff options
author | Adriaan Moors <adriaan.moors@typesafe.com> | 2016-05-26 20:10:47 -0700 |
---|---|---|
committer | Adriaan Moors <adriaan@lightbend.com> | 2016-08-11 10:59:15 -0700 |
commit | e26b4f49d80caa8f71a1986f604cca7f4714e3c3 (patch) | |
tree | 6c04be043061379186a9311d82d770a477678761 /src | |
parent | 1f6f7f8aa94c622665a35343de8108ea66a787b7 (diff) | |
download | scala-e26b4f49d80caa8f71a1986f604cca7f4714e3c3.tar.gz scala-e26b4f49d80caa8f71a1986f604cca7f4714e3c3.tar.bz2 scala-e26b4f49d80caa8f71a1986f604cca7f4714e3c3.zip |
Uncurry's info transform: non-static module --> method
We do this during uncurry so we can insert the necessary
applications to the empty argument list. Fields is too late.
Refchecks is no longer an info transform.
Diffstat (limited to 'src')
10 files changed, 23 insertions, 53 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index c2d92ce7f9..af866e1a6f 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -456,7 +456,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) } with Pickler // phaseName = "refchecks" - override object refChecks extends { + object refChecks extends { val global: Global.this.type = Global.this val runsAfter = List("pickler") val runsRightAfter = None diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 289ac0cc02..dc62b40578 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -508,7 +508,7 @@ abstract class Erasure extends AddInterfaces // If `member` is a ModuleSymbol, the bridge should not also be a ModuleSymbol. Otherwise we // end up with two module symbols with the same name in the same scope, which is surprising // when implementing later phases. - if (member.isModule) newFlags = (newFlags | METHOD) & ~(MODULE | lateMETHOD | STABLE) + if (member.isModule) newFlags = (newFlags | METHOD) & ~(MODULE | STABLE) val bridge = other.cloneSymbolImpl(root, newFlags) setPos root.pos debuglog("generating bridge from %s (%s): %s to %s: %s".format( diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala index 374e8430d8..a337ab7359 100644 --- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala +++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala @@ -510,8 +510,11 @@ abstract class UnCurry extends InfoTransform case MethodType(_, _) => tree case tp => tree setType MethodType(Nil, tp.resultType) } - if (tree.symbol.isMethod && !tree.tpe.isInstanceOf[PolyType]) - gen.mkApplyIfNeeded(removeNullary()) + val sym = tree.symbol + // our info transformer may not have run yet, so duplicate flag logic instead of forcing it to run + val isMethodExitingUncurry = (sym hasFlag METHOD) || (sym hasFlag MODULE) && !sym.isStatic + if (isMethodExitingUncurry && !tree.tpe.isInstanceOf[PolyType]) + gen.mkApplyIfNeeded(removeNullary()) // apply () if tree.tpe has zero-arg MethodType else if (tree.isType) TypeTree(tree.tpe) setPos tree.pos else diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 46ad4b35a1..7021e12f1a 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -14,7 +14,7 @@ import scala.tools.nsc.settings.ScalaVersion import scala.tools.nsc.settings.NoScalaVersion import symtab.Flags._ -import transform.InfoTransform +import transform.Transform /** <p> @@ -43,7 +43,7 @@ import transform.InfoTransform * * @todo Check whether we always check type parameter bounds. */ -abstract class RefChecks extends InfoTransform with scala.reflect.internal.transform.RefChecks { +abstract class RefChecks extends Transform { val global: Global // need to repeat here because otherwise last mixin defines global as // SymbolTable. If we had DOT this would not be an issue @@ -54,31 +54,9 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans /** the following two members override abstract members in Transform */ val phaseName: String = "refchecks" - override def phaseNewFlags: Long = lateMETHOD def newTransformer(unit: CompilationUnit): RefCheckTransformer = new RefCheckTransformer(unit) - override def changesBaseClasses = false - - override def transformInfo(sym: Symbol, tp: Type): Type = { - // !!! This is a sketchy way to do things. - // It would be better to replace the module symbol with a method symbol - // rather than creating this module/method hybrid which must be special - // cased all over the place. Look for the call sites which use(d) some - // variation of "isMethod && !isModule", which to an observer looks like - // a nonsensical condition. (It is now "isModuleNotMethod".) - if (sym.isModule && !sym.isStatic) { - sym setFlag lateMETHOD | STABLE - // Note that this as far as we can see it works equally well - // to set the METHOD flag here and dump lateMETHOD, but it does - // mean that under separate compilation the typer will see - // modules as methods (albeit stable ones with singleton types.) - // So for now lateMETHOD lives while we try to convince ourselves - // we can live without it or deliver that info some other way. - log(s"Stabilizing module method for ${sym.fullLocationString}") - } - super.transformInfo(sym, tp) - } val toJavaRepeatedParam = new SubstSymMap(RepeatedParamClass -> JavaRepeatedParamClass) val toScalaRepeatedParam = new SubstSymMap(JavaRepeatedParamClass -> RepeatedParamClass) diff --git a/src/compiler/scala/tools/reflect/ReflectGlobal.scala b/src/compiler/scala/tools/reflect/ReflectGlobal.scala index e30d1ed7cd..b80524df2b 100644 --- a/src/compiler/scala/tools/reflect/ReflectGlobal.scala +++ b/src/compiler/scala/tools/reflect/ReflectGlobal.scala @@ -30,8 +30,7 @@ class ReflectGlobal(currentSettings: Settings, reporter: Reporter, override val override def transformedType(sym: Symbol) = postErasure.transformInfo(sym, erasure.transformInfo(sym, - uncurry.transformInfo(sym, - refChecks.transformInfo(sym, sym.info)))) + uncurry.transformInfo(sym, sym.info))) override def isCompilerUniverse = true diff --git a/src/reflect/scala/reflect/internal/Phase.scala b/src/reflect/scala/reflect/internal/Phase.scala index f56c41d71c..eb193adbf2 100644 --- a/src/reflect/scala/reflect/internal/Phase.scala +++ b/src/reflect/scala/reflect/internal/Phase.scala @@ -47,7 +47,9 @@ abstract class Phase(val prev: Phase) { final val specialized: Boolean = ((prev ne null) && (prev ne NoPhase)) && (prev.name == "specialize" || prev.specialized) final val refChecked: Boolean = ((prev ne null) && (prev ne NoPhase)) && (prev.name == "refchecks" || prev.refChecked) - // are we past the fields phase, so that we should allow writing to vals (as part of type checking trait setters) + // are we past the fields phase, so that: + // - we should allow writing to vals (as part of type checking trait setters) + // - modules have module accessors final val assignsFields: Boolean = ((prev ne null) && (prev ne NoPhase)) && (prev.name == "fields" || prev.assignsFields) /** This is used only in unsafeTypeParams, and at this writing is diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index fb78aa5009..7dda805378 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -3469,10 +3469,10 @@ trait Types if (!sym.isOverridableMember || sym.owner == pre.typeSymbol) sym else pre.nonPrivateMember(sym.name).suchThat { sym => // SI-7928 `isModuleNotMethod` is here to avoid crashing with spuriously "overloaded" module accessor and module symbols. - // These appear after refchecks eliminates ModuleDefs that implement an interface. + // These appear after the fields phase eliminates ModuleDefs that implement an interface. // Here, we exclude the module symbol, which allows us to bind to the accessor. - // SI-8054 We must only do this after refchecks, otherwise we exclude the module symbol which does not yet have an accessor! - val isModuleWithAccessor = phase.refChecked && sym.isModuleNotMethod + // SI-8054 We must only do this after fields, otherwise we exclude the module symbol which does not yet have an accessor! + val isModuleWithAccessor = phase.assignsFields && sym.isModuleNotMethod sym.isType || (!isModuleWithAccessor && sym.isStable && !sym.hasVolatileType) } orElse sym } diff --git a/src/reflect/scala/reflect/internal/transform/RefChecks.scala b/src/reflect/scala/reflect/internal/transform/RefChecks.scala index 4ca114e781..e69de29bb2 100644 --- a/src/reflect/scala/reflect/internal/transform/RefChecks.scala +++ b/src/reflect/scala/reflect/internal/transform/RefChecks.scala @@ -1,14 +0,0 @@ -package scala -package reflect -package internal -package transform - -trait RefChecks { - - val global: SymbolTable - import global._ - - def transformInfo(sym: Symbol, tp: Type): Type = - if (sym.isModule && !sym.isStatic) NullaryMethodType(tp) - else tp -} diff --git a/src/reflect/scala/reflect/internal/transform/Transforms.scala b/src/reflect/scala/reflect/internal/transform/Transforms.scala index 0d2f355aa5..de5bfbd39a 100644 --- a/src/reflect/scala/reflect/internal/transform/Transforms.scala +++ b/src/reflect/scala/reflect/internal/transform/Transforms.scala @@ -23,12 +23,10 @@ trait Transforms { self: SymbolTable => } } - private val refChecksLazy = new Lazy(new { val global: Transforms.this.type = self } with RefChecks) private val uncurryLazy = new Lazy(new { val global: Transforms.this.type = self } with UnCurry) private val erasureLazy = new Lazy(new { val global: Transforms.this.type = self } with Erasure) private val postErasureLazy = new Lazy(new { val global: Transforms.this.type = self } with PostErasure) - def refChecks = refChecksLazy.force def uncurry = uncurryLazy.force def erasure = erasureLazy.force def postErasure = postErasureLazy.force @@ -36,8 +34,7 @@ trait Transforms { self: SymbolTable => def transformedType(sym: Symbol) = postErasure.transformInfo(sym, erasure.transformInfo(sym, - uncurry.transformInfo(sym, - refChecks.transformInfo(sym, sym.info)))) + uncurry.transformInfo(sym, sym.info))) def transformedType(tpe: Type) = postErasure.elimErasedValueType(erasure.scalaErasure(uncurry.uncurry(tpe))) diff --git a/src/reflect/scala/reflect/internal/transform/UnCurry.scala b/src/reflect/scala/reflect/internal/transform/UnCurry.scala index 85e3ac60e8..a50084f40d 100644 --- a/src/reflect/scala/reflect/internal/transform/UnCurry.scala +++ b/src/reflect/scala/reflect/internal/transform/UnCurry.scala @@ -83,5 +83,10 @@ trait UnCurry { * @MAT: starting with this phase, the info of every symbol will be normalized */ def transformInfo(sym: Symbol, tp: Type): Type = - if (sym.isType) uncurryType(tp) else uncurry(tp) + if (sym.isType) uncurryType(tp) + else if ((sym hasFlag MODULE) && !sym.isStatic) { // see Fields::nonStaticModuleToMethod + sym setFlag METHOD | STABLE + MethodType(Nil, uncurry(tp)) + } + else uncurry(tp) } |