summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/RefChecks.scala')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala95
1 files changed, 48 insertions, 47 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index c5abd756f8..3860cc252d 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -6,15 +6,17 @@
package scala.tools.nsc
package typechecker
-import symtab.Flags._
-import scala.collection.{ mutable, immutable }
-import transform.InfoTransform
-import scala.collection.mutable.ListBuffer
import scala.language.postfixOps
+
+import scala.collection.mutable
+import scala.collection.mutable.ListBuffer
import scala.tools.nsc.settings.ScalaVersion
-import scala.tools.nsc.settings.AnyScalaVersion
import scala.tools.nsc.settings.NoScalaVersion
+import symtab.Flags._
+import transform.InfoTransform
+
+
/** <p>
* Post-attribution checking and transformation.
* </p>
@@ -48,7 +50,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
import global._
import definitions._
- import typer.{typed, typedOperator, atOwner}
+ import typer.typed
/** the following two members override abstract members in Transform */
val phaseName: String = "refchecks"
@@ -1182,59 +1184,54 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
private def eliminateModuleDefs(moduleDef: Tree): List[Tree] = exitingRefchecks {
val ModuleDef(_, _, impl) = moduleDef
val module = moduleDef.symbol
- val moduleClass = module.moduleClass
val site = module.owner
val moduleName = module.name.toTermName
// The typer doesn't take kindly to seeing this ClassDef; we have to
// set NoType so it will be ignored.
- val cdef = ClassDef(moduleClass, impl) setType NoType
-
- // This code is related to the fix of SI-9375, which stops adding `readResolve` methods to
- // non-static (nested) modules. Before the fix, the method would cause the module accessor
- // to become notPrivate. To prevent binary changes in the 2.11.x branch, we mimic that behavior.
- // There is a bit of code duplication between here and SyntheticMethods. We cannot call
- // makeNotPrivate already in SyntheticMethod: that is during type checking, and not all references
- // are resolved yet, so we cannot rename a definition. This code doesn't exist in the 2.12.x branch.
- def hasConcreteImpl(name: Name) = moduleClass.info.member(name).alternatives exists (m => !m.isDeferred)
- val hadReadResolveBeforeSI9375 = moduleClass.isSerializable && !hasConcreteImpl(nme.readResolve)
- if (hadReadResolveBeforeSI9375)
- moduleClass.sourceModule.makeNotPrivate(moduleClass.sourceModule.owner)
-
- // Create the module var unless the immediate owner is a class and
- // the module var already exists there. See SI-5012, SI-6712.
- def findOrCreateModuleVar() = {
- val vsym = (
- if (site.isTerm) NoSymbol
- else site.info decl nme.moduleVarName(moduleName)
- )
- vsym orElse (site newModuleVarSymbol module)
- }
- def newInnerObject() = {
- // Create the module var unless it is already in the module owner's scope.
- // The lookup is on module.enclClass and not module.owner lest there be a
- // nullary method between us and the class; see SI-5012.
- val moduleVar = findOrCreateModuleVar()
- val rhs = gen.newModule(module, moduleVar.tpe)
- val body = if (site.isTrait) rhs else gen.mkAssignAndReturn(moduleVar, rhs)
- val accessor = DefDef(module, body.changeOwner(moduleVar -> module))
-
- ValDef(moduleVar) :: accessor :: Nil
- }
+ val cdef = ClassDef(module.moduleClass, impl) setType NoType
+
def matchingInnerObject() = {
val newFlags = (module.flags | STABLE) & ~MODULE
- val newInfo = NullaryMethodType(moduleClass.tpe)
+ val newInfo = NullaryMethodType(module.moduleClass.tpe)
val accessor = site.newMethod(moduleName, module.pos, newFlags) setInfoAndEnter newInfo
DefDef(accessor, Select(This(site), module)) :: Nil
}
val newTrees = cdef :: (
if (module.isStatic)
+ // trait T { def f: Object }; object O extends T { object f }. Need to generate method f in O.
if (module.isOverridingSymbol) matchingInnerObject() else Nil
else
- newInnerObject()
+ newInnerObject(site, module)
)
transformTrees(newTrees map localTyper.typedPos(moduleDef.pos))
}
+ def newInnerObject(site: Symbol, module: Symbol): List[Tree] = {
+ if (site.isTrait)
+ DefDef(module, EmptyTree) :: Nil
+ else {
+ val moduleVar = site newModuleVarSymbol module
+ // used for the mixin case: need a new symbol owned by the subclass for the accessor, rather than repurposing the module symbol
+ def mkAccessorSymbol =
+ site.newMethod(module.name.toTermName, site.pos, STABLE | MODULE | MIXEDIN)
+ .setInfo(moduleVar.tpe)
+ .andAlso(self => if (module.isPrivate) self.expandName(module.owner))
+
+ val accessor = if (module.owner == site) module else mkAccessorSymbol
+ val accessorDef = DefDef(accessor, gen.mkAssignAndReturn(moduleVar, gen.newModule(module, moduleVar.tpe)).changeOwner(moduleVar -> accessor))
+
+ ValDef(moduleVar) :: accessorDef :: Nil
+ }
+ }
+
+ def mixinModuleDefs(clazz: Symbol): List[Tree] = {
+ val res = for {
+ mixinClass <- clazz.mixinClasses.iterator
+ module <- mixinClass.info.decls.iterator.filter(_.isModule)
+ newMember <- newInnerObject(clazz, module)
+ } yield transform(localTyper.typedPos(clazz.pos)(newMember))
+ res.toList
+ }
def transformStat(tree: Tree, index: Int): List[Tree] = tree match {
case t if treeInfo.isSelfConstrCall(t) =>
@@ -1480,10 +1477,13 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
case m: MemberDef =>
val sym = m.symbol
applyChecks(sym.annotations)
- // validate implicitNotFoundMessage
- analyzer.ImplicitNotFoundMsg.check(sym) foreach { warn =>
- reporter.warning(tree.pos, f"Invalid implicitNotFound message for ${sym}%s${sym.locationString}%s:%n$warn")
- }
+
+ def messageWarning(name: String)(warn: String) =
+ reporter.warning(tree.pos, f"Invalid $name message for ${sym}%s${sym.locationString}%s:%n$warn")
+
+ // validate implicitNotFoundMessage and implicitAmbiguousMessage
+ analyzer.ImplicitNotFoundMsg.check(sym) foreach messageWarning("implicitNotFound")
+ analyzer.ImplicitAmbiguousMsg.check(sym) foreach messageWarning("implicitAmbiguous")
case tpt@TypeTree() =>
if(tpt.original != null) {
@@ -1663,11 +1663,12 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
// SI-7870 default getters for constructors live in the companion module
checkOverloadedRestrictions(currentOwner, currentOwner.companionModule)
val bridges = addVarargBridges(currentOwner)
+ val moduleDesugared = if (currentOwner.isTrait) Nil else mixinModuleDefs(currentOwner)
checkAllOverrides(currentOwner)
checkAnyValSubclass(currentOwner)
if (currentOwner.isDerivedValueClass)
currentOwner.primaryConstructor makeNotPrivate NoSymbol // SI-6601, must be done *after* pickler!
- if (bridges.nonEmpty) deriveTemplate(tree)(_ ::: bridges) else tree
+ if (bridges.nonEmpty || moduleDesugared.nonEmpty) deriveTemplate(tree)(_ ::: bridges ::: moduleDesugared) else tree
case dc@TypeTreeWithDeferredRefCheck() => abort("adapt should have turned dc: TypeTreeWithDeferredRefCheck into tpt: TypeTree, with tpt.original == dc")
case tpt@TypeTree() =>