summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@typesafe.com>2016-05-26 20:10:47 -0700
committerAdriaan Moors <adriaan@lightbend.com>2016-08-11 10:59:15 -0700
commite26b4f49d80caa8f71a1986f604cca7f4714e3c3 (patch)
tree6c04be043061379186a9311d82d770a477678761
parent1f6f7f8aa94c622665a35343de8108ea66a787b7 (diff)
downloadscala-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.
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala7
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala26
-rw-r--r--src/compiler/scala/tools/reflect/ReflectGlobal.scala3
-rw-r--r--src/reflect/scala/reflect/internal/Phase.scala4
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala6
-rw-r--r--src/reflect/scala/reflect/internal/transform/RefChecks.scala14
-rw-r--r--src/reflect/scala/reflect/internal/transform/Transforms.scala5
-rw-r--r--src/reflect/scala/reflect/internal/transform/UnCurry.scala7
-rw-r--r--test/files/run/t6240-universe-code-gen.scala2
11 files changed, 24 insertions, 54 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)
}
diff --git a/test/files/run/t6240-universe-code-gen.scala b/test/files/run/t6240-universe-code-gen.scala
index 60e1f76b54..80b60bab7e 100644
--- a/test/files/run/t6240-universe-code-gen.scala
+++ b/test/files/run/t6240-universe-code-gen.scala
@@ -54,7 +54,7 @@ object Test extends App {
|
|${forceCode("this", JavaUniverseTpe)}
|${forceCode("definitions", DefinitionsModule.info)}
- |${forceCode("refChecks", typeOf[scala.reflect.internal.transform.RefChecks])}
+ |
|${forceCode("uncurry", typeOf[scala.reflect.internal.transform.UnCurry])}
|${forceCode("erasure", typeOf[scala.reflect.internal.transform.Erasure])}
| }