diff options
Diffstat (limited to 'src/compiler')
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/Fields.scala | 59 |
1 files changed, 29 insertions, 30 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/Fields.scala b/src/compiler/scala/tools/nsc/transform/Fields.scala index 6cf6a5abce..aa2ccd9788 100644 --- a/src/compiler/scala/tools/nsc/transform/Fields.scala +++ b/src/compiler/scala/tools/nsc/transform/Fields.scala @@ -193,20 +193,6 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor // not be emitted as ACC_FINAL. They are FINAL in the Scala sense, though: cannot be overridden. private final val ModuleOrLazyFieldFlags = FINAL | PrivateLocal | SYNTHETIC | NEEDS_TREES - private def newModuleVarSymbol(owner: Symbol, module: Symbol, tp: Type): TermSymbol = { -// println(s"new module var in $site for $module of type $tp") - val flags = MODULEVAR | (if (owner.isClass) ModuleOrLazyFieldFlags else 0) - - val moduleVar = - (owner.newVariable(nme.moduleVarName(module.name.toTermName), module.pos.focus, flags) - setInfo tp - addAnnotation VolatileAttr) - - moduleOrLazyVarOf(module) = moduleVar - - moduleVar - } - private def moduleInit(module: Symbol, moduleVar: Symbol) = { // println(s"moduleInit for $module in ${module.ownerChain} --> ${moduleVarOf.get(module)}") def moduleVarRef = gen.mkAttributedRef(moduleVar) @@ -380,8 +366,16 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor (existingGetter ne NoSymbol) && (tp matches (site memberInfo existingGetter).resultType) // !existingGetter.isDeferred && -- see (3) } - def newModuleVarMember(member: Symbol): TermSymbol = - newModuleVarSymbol(clazz, member, site.memberType(member).resultType) + def newModuleVarMember(module: Symbol): TermSymbol = { + val moduleVar = + (clazz.newVariable(nme.moduleVarName(module.name.toTermName), module.pos.focus, MODULEVAR | ModuleOrLazyFieldFlags) + setInfo site.memberType(module).resultType + addAnnotation VolatileAttr) + + moduleOrLazyVarOf(module) = moduleVar + + moduleVar + } def newLazyVarMember(member: Symbol): TermSymbol = Fields.this.newLazyVarMember(clazz, member, site.memberType(member).resultType) @@ -531,7 +525,9 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor def mkTypedValDef(sym: Symbol, rhs: Tree = EmptyTree) = typedPos(sym.pos)(ValDef(sym, rhs)).asInstanceOf[ValDef] /** - * Desugar a local `lazy val x: Int = rhs` into + * Desugar a local `lazy val x: Int = rhs` + * or a local `object x { ...}` (the rhs will be instantiating the module's class) into: + * * ``` * val x$lzy = new scala.runtime.LazyInt() * def x$lzycompute(): Int = @@ -541,22 +537,24 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor * } * def x(): Int = if (x$lzy.initialized()) x$lzy.value() else x$lzycompute() * ``` + * + * The expansion is the same for local lazy vals and local objects, + * except for the suffix of the underlying val's name ($lzy or $module) */ - private def mkLazyLocalDef(lazyVal: Symbol, rhs: Tree): Tree = { + private def mkLazyLocalDef(lazySym: Symbol, rhs: Tree): Tree = { import CODE._ - import scala.reflect.NameTransformer.LAZY_LOCAL_SUFFIX_STRING - val owner = lazyVal.owner + import scala.reflect.{NameTransformer => nx} + val owner = lazySym.owner - val lazyValType = lazyVal.tpe.resultType + val lazyValType = lazySym.tpe.resultType val refClass = lazyHolders.getOrElse(lazyValType.typeSymbol, LazyRefClass) val isUnit = refClass == LazyUnitClass val refTpe = if (refClass != LazyRefClass) refClass.tpe else appliedType(refClass.typeConstructor, List(lazyValType)) - val lazyName = lazyVal.name.toTermName - val pos = lazyVal.pos.focus + val lazyName = lazySym.name.toTermName + val pos = lazySym.pos.focus - // used twice: once in the same owner as the lazy val, another time inside the compute method - val localLazyName = lazyName append LAZY_LOCAL_SUFFIX_STRING + val localLazyName = lazyName append (if (lazySym.isModule) nx.MODULE_VAR_SUFFIX_STRING else nx.LAZY_LOCAL_SUFFIX_STRING) // The lazy holder val need not be mutable, as we write to its field. // In fact, it MUST not be mutable to avoid capturing it as an ObjectRef in lambdalift @@ -576,14 +574,14 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor val computerSym = owner.newMethod(lazyName append nme.LAZY_SLOW_SUFFIX, pos, ARTIFACT | PRIVATE) setInfo MethodType(Nil, lazyValType) - val rhsAtComputer = rhs.changeOwner(lazyVal -> computerSym) + val rhsAtComputer = rhs.changeOwner(lazySym -> computerSym) val computer = mkAccessor(computerSym)(gen.mkSynchronized(Ident(holderSym))( If(initialized, getValue, if (isUnit) Block(rhsAtComputer :: Nil, Apply(initialize, Nil)) else Apply(initialize, rhsAtComputer :: Nil)))) - val accessor = mkAccessor(lazyVal)( + val accessor = mkAccessor(lazySym)( If(initialized, getValue, Apply(Ident(computerSym), Nil))) @@ -591,7 +589,7 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor // remove STABLE: prevent replacing accessor call of type Unit by BoxedUnit.UNIT in erasure // remove ACCESSOR: prevent constructors from eliminating the method body if the lazy val is // lifted into a trait (TODO: not sure about the details here) - lazyVal.resetFlag(STABLE | ACCESSOR) + lazySym.resetFlag(STABLE | ACCESSOR) Thicket(mkTypedValDef(holderSym, New(refTpe)) :: computer :: accessor :: Nil) } @@ -730,8 +728,9 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor val cd = super.transform(ClassDef(statSym.moduleClass, impl) setType NoType) if (currOwner.isClass) cd else { // local module -- symbols cannot be generated by info transformer, so do it all here - val moduleVar = newModuleVarSymbol(currOwner, statSym, statSym.info.resultType) - Thicket(cd :: mkTypedValDef(moduleVar) :: mkAccessor(statSym)(moduleInit(statSym, moduleVar)) :: Nil) + val Block(stats, _) = mkLazyLocalDef(statSym, gen.newModule(statSym, statSym.info.resultType)) + + Thicket(cd :: stats) } case tree => |