Skip to content

Commit 68f62fe

Browse files
committed
specialized lazy vals now behave like regular lazy vals
1 parent a2fa123 commit 68f62fe

File tree

4 files changed

+23
-6
lines changed

4 files changed

+23
-6
lines changed

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,9 @@ trait AccessorSynthesis extends Transform with ast.TreeDSL {
315315
* This way the inliner should optimize the fast path because the method body is small enough.
316316
*/
317317
def expandLazyClassMember(lazyVar: Symbol, lazyAccessor: Symbol, transformedRhs: Tree, nullables: Map[Symbol, List[Symbol]]): Tree = {
318-
def nullify(sym: Symbol) = Select(thisRef, sym.accessedOrSelf) === LIT(null)
318+
// use cast so that specialization can turn null.asInstanceOf[T] into null.asInstanceOf[Long]
319+
def nullify(sym: Symbol) =
320+
Select(thisRef, sym.accessedOrSelf) === gen.mkAsInstanceOf(NULL, sym.info.resultType)
319321
val nulls = nullables.getOrElse(lazyAccessor, Nil) map nullify
320322

321323
if (nulls.nonEmpty)

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

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -723,7 +723,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
723723
} else if (!sClass.isTrait && m.isMethod && m.hasFlag(LAZY)) {
724724
forwardToOverload(m)
725725

726-
} else if (m.isValue && !m.isMethod && !m.hasFlag(LAZY)) { // concrete value definition
726+
} else if (m.isValue && !m.isMethod) { // concrete value definition
727727
def mkAccessor(field: Symbol, name: Name) = {
728728
val newFlags = (SPECIALIZED | m.getterIn(clazz).flags) & ~(LOCAL | CASEACCESSOR | PARAMACCESSOR)
729729
// we rely on the super class to initialize param accessors
@@ -744,7 +744,14 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
744744
enterMember(specVal)
745745
// create accessors
746746

747-
if (nme.isLocalName(m.name)) {
747+
if (m.isLazy) {
748+
// no getters needed (we'll specialize the compute method and accessor separately), can stay private
749+
// m.setFlag(PRIVATE) -- TODO: figure out how to leave the non-specialized lazy var private
750+
// (the implementation needs it to be visible while duplicating and retypechecking,
751+
// but it really could be private in bytecode)
752+
specVal.setFlag(PRIVATE)
753+
}
754+
else if (nme.isLocalName(m.name)) {
748755
val specGetter = mkAccessor(specVal, specVal.getterName) setInfo MethodType(Nil, specVal.info)
749756
val origGetter = overrideIn(sClass, m.getterIn(clazz))
750757
info(origGetter) = Forward(specGetter)

test/files/run/t5552.check

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
1+
lazy: 3
12
(3,3)
3+
(3,3)
4+
lazy: 3.0
5+
(3.0,3.0)
26
(3.0,3.0)

test/files/run/t5552.scala

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
class C[@specialized(Int) A](a:A) {
2-
lazy val b = (a, a)
2+
lazy val b = {println(s"lazy: $a"); (a, a)} // there should only be two instances of "lazy" in the output
33
def c = b
44
}
55
object Test {
66
def main(args:Array[String]) {
7-
println(new C(3).c)
8-
println(new C(3.0).c)
7+
val cInt = new C(3)
8+
println(cInt.c)
9+
println(cInt.c)
10+
val cFloat = new C(3.0)
11+
println(cFloat.c)
12+
println(cFloat.c)
913
}
1014
}

0 commit comments

Comments
 (0)