diff options
author | Adriaan Moors <adriaan.moors@typesafe.com> | 2016-05-30 23:48:28 -0700 |
---|---|---|
committer | Adriaan Moors <adriaan@lightbend.com> | 2016-08-11 10:59:16 -0700 |
commit | b79c0d124e839e9e7ae5db883488c0134642472b (patch) | |
tree | 4ffe3199624d964b538f4b31c8d00238f4badbeb /src/compiler/scala/tools/nsc/transform/LambdaLift.scala | |
parent | 8f792280630721bdc1e6ee9199eb0cf8cb035fce (diff) | |
download | scala-b79c0d124e839e9e7ae5db883488c0134642472b.tar.gz scala-b79c0d124e839e9e7ae5db883488c0134642472b.tar.bz2 scala-b79c0d124e839e9e7ae5db883488c0134642472b.zip |
LambdaLift emits paramaccessor syms and defdefs
... instead of emitting ValDefs and field symbols, which are then
promptly unlinked and transformed by the "late trait methods"
logic in mixins...
Mixins still synthesizes implementations for these accessors
in subclasses.
A paramaccessor in a trait is a method without an underlying field.
Diffstat (limited to 'src/compiler/scala/tools/nsc/transform/LambdaLift.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/LambdaLift.scala | 35 |
1 files changed, 29 insertions, 6 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala index 074acc1332..2ccc44f234 100644 --- a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala +++ b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala @@ -254,15 +254,26 @@ abstract class LambdaLift extends InfoTransform { afterOwnPhase { for ((owner, freeValues) <- free.toList) { - val newFlags = SYNTHETIC | ( - if (owner.isClass) PARAMACCESSOR | PrivateLocal - else PARAM) + val newFlags = SYNTHETIC | (if (owner.isClass) PARAMACCESSOR else PARAM) proxies(owner) = for (fv <- freeValues.toList) yield { val proxyName = proxyNames.getOrElse(fv, fv.name) debuglog(s"new proxy ${proxyName} in ${owner.fullLocationString}") - val proxy = owner.newValue(proxyName.toTermName, owner.pos, newFlags.toLong) setInfo fv.info + val proxy = + if (owner.isTrait) { + // TODO preserve pre-erasure info for the accessors? + // TODO: do we need SYNTHESIZE_IMPL_IN_SUBCLASS to indicate that `notDeferred(setter)` should hold + val accessorFlags = newFlags.toLong | ACCESSOR | SYNTHESIZE_IMPL_IN_SUBCLASS + val setter = owner.newMethod(nme.expandedSetterName(proxyName.setterName, owner), fv.pos, accessorFlags) + setter setInfo MethodType(setter.newSyntheticValueParams(List(fv.info)), UnitTpe) + owner.info.decls enter setter + + val getter = owner.newMethod(proxyName.getterName, fv.pos, accessorFlags | STABLE) + getter setInfo MethodType(Nil, fv.info) + } else + owner.newValue(proxyName.toTermName, owner.pos, newFlags.toLong | PrivateLocal) setInfo fv.info + if (owner.isClass) owner.info.decls enter proxy proxy } @@ -320,7 +331,12 @@ abstract class LambdaLift extends InfoTransform { private def proxyRef(sym: Symbol) = { val psym = proxy(sym) - if (psym.isLocalToBlock) gen.mkAttributedIdent(psym) else memberRef(psym) + if (psym.isLocalToBlock) gen.mkAttributedIdent(psym) + else { + val ref = memberRef(psym) + if (psym.isMethod) Apply(ref, Nil) setType ref.tpe.resultType + else ref + } } def freeArgsOrNil(sym: Symbol) = free.getOrElse(sym, Nil).toList @@ -354,7 +370,14 @@ abstract class LambdaLift extends InfoTransform { } case ClassDef(_, _, _, _) => - val freeParamDefs = freeParams(sym) map (p => ValDef(p) setPos tree.pos setType NoType) + val freeParamSyms = freeParams(sym) + val freeParamDefs = + if (tree.symbol.isTrait) { + freeParamSyms flatMap { getter => + val setter = getter.setterIn(tree.symbol, hasExpandedName = true) + List(DefDef(getter, EmptyTree) setPos tree.pos setType NoType, DefDef(setter, EmptyTree) setPos tree.pos setType NoType) + } + } else freeParamSyms map (p => ValDef(p) setPos tree.pos setType NoType) if (freeParamDefs.isEmpty) tree else deriveClassDef(tree)(impl => deriveTemplate(impl)(_ ::: freeParamDefs)) |