diff options
author | Lukas Rytz <lukas.rytz@typesafe.com> | 2015-12-18 08:59:29 +0100 |
---|---|---|
committer | Lukas Rytz <lukas.rytz@typesafe.com> | 2015-12-18 08:59:29 +0100 |
commit | 1873db3fb78ba777c009bce11564466de875257a (patch) | |
tree | fb66fceac7223128171551269ce885edfb82239f /src/compiler/scala/tools/nsc/typechecker/RefChecks.scala | |
parent | 2d3625d9803912edc1d4a69fa4da0961719d5001 (diff) | |
parent | 6fb41ed2e0f001df7cea54ec70e378bdbe01aa65 (diff) | |
download | scala-1873db3fb78ba777c009bce11564466de875257a.tar.gz scala-1873db3fb78ba777c009bce11564466de875257a.tar.bz2 scala-1873db3fb78ba777c009bce11564466de875257a.zip |
Merge pull request #4729 from retronym/topic-trait-defaults-module
Desugar module var and accessor in refchecks/lazyvals
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/RefChecks.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/RefChecks.scala | 39 |
1 files changed, 29 insertions, 10 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 7252cae0b5..915ffcc7d0 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -1188,14 +1188,6 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans // set NoType so it will be ignored. val cdef = ClassDef(module.moduleClass, impl) setType NoType - def newInnerObject() = { - val moduleVar = site newModuleVarSymbol module - 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 - } def matchingInnerObject() = { val newFlags = (module.flags | STABLE) & ~MODULE val newInfo = NullaryMethodType(module.moduleClass.tpe) @@ -1208,10 +1200,36 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans // 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) => @@ -1643,11 +1661,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() => |