summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@typesafe.com>2016-05-30 23:48:28 -0700
committerAdriaan Moors <adriaan@lightbend.com>2016-08-11 10:59:16 -0700
commitb79c0d124e839e9e7ae5db883488c0134642472b (patch)
tree4ffe3199624d964b538f4b31c8d00238f4badbeb /src/compiler/scala/tools/nsc/transform/LambdaLift.scala
parent8f792280630721bdc1e6ee9199eb0cf8cb035fce (diff)
downloadscala-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.scala35
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))