Skip to content

Commit f7d5f45

Browse files
committed
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.
1 parent 32a2068 commit f7d5f45

File tree

2 files changed

+14
-11
lines changed

2 files changed

+14
-11
lines changed

src/compiler/scala/tools/nsc/transform/Mixin.scala

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -903,14 +903,14 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
903903

904904
if (sym.isLazy && !isEmpty && !clazz.isImplClass) {
905905
assert(fieldOffset contains sym, sym)
906-
deriveDefDef(stat)(rhs =>
907-
if (isUnit)
908-
mkLazyDef(clazz, sym, List(rhs), UNIT, fieldOffset(sym))
909-
else {
910-
val Block(stats, res) = rhs
906+
deriveDefDef(stat) {
907+
case t if isUnit => mkLazyDef(clazz, sym, List(t), UNIT, fieldOffset(sym))
908+
909+
case Block(stats, res) =>
911910
mkLazyDef(clazz, sym, stats, Select(This(clazz), res.symbol), fieldOffset(sym))
912-
}
913-
)
911+
912+
case t => t // pass specialized lazy vals through
913+
}
914914
}
915915
else if (needsInitFlag(sym) && !isEmpty && !clazz.hasFlag(IMPLCLASS | TRAIT)) {
916916
assert(fieldOffset contains sym, sym)

src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -666,16 +666,19 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
666666
// log("other concrete " + m)
667667
forwardToOverload(m)
668668

669-
} else if (m.isValue && !m.isMethod) { // concrete value definition
669+
} else if (m.isMethod && m.hasFlag(LAZY)) {
670+
forwardToOverload(m)
671+
672+
} else if (m.isValue && !m.isMethod && !m.hasFlag(LAZY)) { // concrete value definition
670673
def mkAccessor(field: Symbol, name: Name) = {
671-
val newFlags = (SPECIALIZED | m.getter(clazz).flags) & ~(LOCAL | CASEACCESSOR | PARAMACCESSOR | LAZY)
674+
val newFlags = (SPECIALIZED | m.getter(clazz).flags) & ~(LOCAL | CASEACCESSOR | PARAMACCESSOR)
672675
// we rely on the super class to initialize param accessors
673676
val sym = sClass.newMethod(name, field.pos, newFlags)
674677
info(sym) = SpecializedAccessor(field)
675678
sym
676679
}
677680
def overrideIn(clazz: Symbol, sym: Symbol) = {
678-
val newFlags = (sym.flags | OVERRIDE | SPECIALIZED) & ~(DEFERRED | CASEACCESSOR | PARAMACCESSOR | LAZY)
681+
val newFlags = (sym.flags | OVERRIDE | SPECIALIZED) & ~(DEFERRED | CASEACCESSOR | PARAMACCESSOR)
679682
val sym1 = sym.cloneSymbol(clazz, newFlags)
680683
sym1 modifyInfo (_ asSeenFrom (clazz.tpe, sym1.owner))
681684
}
@@ -881,7 +884,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
881884

882885
/** Return the specialized overload of `m`, in the given environment. */
883886
private def specializedOverload(owner: Symbol, sym: Symbol, env: TypeEnv): Symbol = {
884-
val newFlags = (sym.flags | SPECIALIZED) & ~(DEFERRED | CASEACCESSOR | ACCESSOR | LAZY)
887+
val newFlags = (sym.flags | SPECIALIZED) & ~(DEFERRED | CASEACCESSOR)
885888
// this method properly duplicates the symbol's info
886889
( sym.cloneSymbol(owner, newFlags, specializedName(sym, env))
887890
modifyInfo (info => subst(env, info.asSeenFrom(owner.thisType, sym.owner)))

0 commit comments

Comments
 (0)