diff options
author | Erik Osheim <d_m@plastic-idolatry.com> | 2012-05-14 00:13:16 -0400 |
---|---|---|
committer | Erik Osheim <d_m@plastic-idolatry.com> | 2012-05-14 00:13:16 -0400 |
commit | f7d5f45aa7d5b1977043aa169bf2cdb42f07a002 (patch) | |
tree | 82445a0574b8c233cf6b7f491ce5ca8eb88b3fad | |
parent | 32a2068e3cc40ccab32f3c207cff73cfb6cc2ef5 (diff) | |
download | scala-f7d5f45aa7d5b1977043aa169bf2cdb42f07a002.tar.gz scala-f7d5f45aa7d5b1977043aa169bf2cdb42f07a002.tar.bz2 scala-f7d5f45aa7d5b1977043aa169bf2cdb42f07a002.zip |
Specialize lazy vals (closes SI-5552)
Previously, specialized lazy vals would not work at all when used in
specialized classes, and would just return an uninitialized value.
After this patch, they work in the same way as other specialized fields
do (i.e. a new specialized field is created, and the specialized class
uses that instead of the base class' field).
Note that there are still known problems with specialized lazy vals
(for instance SI-4717) but it seemed to me that this was better than
nothing.
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/Mixin.scala | 14 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala | 11 |
2 files changed, 14 insertions, 11 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index 4ce5985af8..79b9317f20 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -903,14 +903,14 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { if (sym.isLazy && !isEmpty && !clazz.isImplClass) { assert(fieldOffset contains sym, sym) - deriveDefDef(stat)(rhs => - if (isUnit) - mkLazyDef(clazz, sym, List(rhs), UNIT, fieldOffset(sym)) - else { - val Block(stats, res) = rhs + deriveDefDef(stat) { + case t if isUnit => mkLazyDef(clazz, sym, List(t), UNIT, fieldOffset(sym)) + + case Block(stats, res) => mkLazyDef(clazz, sym, stats, Select(This(clazz), res.symbol), fieldOffset(sym)) - } - ) + + case t => t // pass specialized lazy vals through + } } else if (needsInitFlag(sym) && !isEmpty && !clazz.hasFlag(IMPLCLASS | TRAIT)) { assert(fieldOffset contains sym, sym) diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala index 7e780304e7..07a10ecb1f 100644 --- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala +++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala @@ -666,16 +666,19 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { // log("other concrete " + m) forwardToOverload(m) - } else if (m.isValue && !m.isMethod) { // concrete value definition + } else if (m.isMethod && m.hasFlag(LAZY)) { + forwardToOverload(m) + + } else if (m.isValue && !m.isMethod && !m.hasFlag(LAZY)) { // concrete value definition def mkAccessor(field: Symbol, name: Name) = { - val newFlags = (SPECIALIZED | m.getter(clazz).flags) & ~(LOCAL | CASEACCESSOR | PARAMACCESSOR | LAZY) + val newFlags = (SPECIALIZED | m.getter(clazz).flags) & ~(LOCAL | CASEACCESSOR | PARAMACCESSOR) // we rely on the super class to initialize param accessors val sym = sClass.newMethod(name, field.pos, newFlags) info(sym) = SpecializedAccessor(field) sym } def overrideIn(clazz: Symbol, sym: Symbol) = { - val newFlags = (sym.flags | OVERRIDE | SPECIALIZED) & ~(DEFERRED | CASEACCESSOR | PARAMACCESSOR | LAZY) + val newFlags = (sym.flags | OVERRIDE | SPECIALIZED) & ~(DEFERRED | CASEACCESSOR | PARAMACCESSOR) val sym1 = sym.cloneSymbol(clazz, newFlags) sym1 modifyInfo (_ asSeenFrom (clazz.tpe, sym1.owner)) } @@ -881,7 +884,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { /** Return the specialized overload of `m`, in the given environment. */ private def specializedOverload(owner: Symbol, sym: Symbol, env: TypeEnv): Symbol = { - val newFlags = (sym.flags | SPECIALIZED) & ~(DEFERRED | CASEACCESSOR | ACCESSOR | LAZY) + val newFlags = (sym.flags | SPECIALIZED) & ~(DEFERRED | CASEACCESSOR) // this method properly duplicates the symbol's info ( sym.cloneSymbol(owner, newFlags, specializedName(sym, env)) modifyInfo (info => subst(env, info.asSeenFrom(owner.thisType, sym.owner))) |