summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/transform/Fields.scala
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan@lightbend.com>2016-09-02 19:25:46 +0200
committerAdriaan Moors <adriaan@lightbend.com>2016-09-02 19:53:20 +0200
commitc1bd0eadd3412643f95b63d27519b369eabb755d (patch)
tree1453c7bbe92b18c070365b0cad88cfecd632d93a /src/compiler/scala/tools/nsc/transform/Fields.scala
parent50462a45dcbe91ef43652c235721b7a7ec0c8bb2 (diff)
downloadscala-c1bd0eadd3412643f95b63d27519b369eabb755d.tar.gz
scala-c1bd0eadd3412643f95b63d27519b369eabb755d.tar.bz2
scala-c1bd0eadd3412643f95b63d27519b369eabb755d.zip
More elegant holders for local lazy vals.
Diffstat (limited to 'src/compiler/scala/tools/nsc/transform/Fields.scala')
-rw-r--r--src/compiler/scala/tools/nsc/transform/Fields.scala42
1 files changed, 18 insertions, 24 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/Fields.scala b/src/compiler/scala/tools/nsc/transform/Fields.scala
index 3529fbd0eb..a383b65192 100644
--- a/src/compiler/scala/tools/nsc/transform/Fields.scala
+++ b/src/compiler/scala/tools/nsc/transform/Fields.scala
@@ -528,10 +528,7 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor
* def x$lzycompute(): Int =
* x$lzy.synchronized {
* if (x$lzy.initialized()) x$lzy.value()
- * else {
- * x$lzy.initialized = true
- * x$lzy.value = rhs
- * }
+ * else x$lzy.initialize(rhs) // for a Unit-typed lazy val, this becomes `{ rhs ; x$lzy.initialize() }` to avoid passing around BoxedUnit
* }
* def x(): Int = if (x$lzy.initialized()) x$lzy.value() else x$lzycompute()
* ```
@@ -543,6 +540,7 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor
val lazyValType = lazyVal.tpe.resultType
val refClass = lazyHolders.getOrElse(lazyValType.typeSymbol, LazyRefClass)
+ val isUnit = refClass == LazyUnitClass
val refTpe = if (refClass != LazyRefClass) refClass.tpe else appliedType(refClass.typeConstructor, List(lazyValType))
val lazyName = lazyVal.name.toTermName
@@ -556,33 +554,29 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor
// Must be marked LAZY to allow forward references, as in `def test2 { println(s.length) ; lazy val s = "abc" }
val holderSym = owner.newValue(localLazyName, pos, LAZY | ARTIFACT) setInfo refTpe
- val initializedGetter = refTpe.member(nme.initialized)
- val isUnit = refClass == LazyUnitClass
- val valueGetter = if (isUnit) NoSymbol else refTpe.member(nme.value)
- def getValue = if (isUnit) UNIT else Apply(Select(Ident(holderSym), valueGetter), Nil)
+ val initializedSym = refTpe.member(nme.initialized)
+ val initializeSym = refTpe.member(nme.initialize)
+
+ // LazyUnit does not have a `value` member
+ val valueSym = if (isUnit) NoSymbol else refTpe.member(nme.value)
- def mkChecked(alreadyComputed: Tree, compute: Tree) = If(Ident(holderSym) DOT initializedGetter, alreadyComputed, compute)
+ def initialized = Select(Ident(holderSym), initializedSym)
+ def initialize = Select(Ident(holderSym), initializeSym)
+ def getValue = if (isUnit) UNIT else Apply(Select(Ident(holderSym), valueSym), Nil)
val computerSym =
owner.newMethod(lazyName append nme.LAZY_SLOW_SUFFIX, pos, ARTIFACT | PRIVATE) setInfo MethodType(Nil, lazyValType)
val rhsAtComputer = rhs.changeOwner(lazyVal -> computerSym)
- val computer = mkAccessor(computerSym) {
- val setInitialized = Apply(Select(Ident(holderSym), initializedGetter.setterIn(refClass)), TRUE :: Nil)
-
- if (isUnit)
- gen.mkSynchronized(Ident(holderSym))(mkChecked(alreadyComputed = UNIT, compute = Block(List(rhsAtComputer, setInitialized), UNIT)))
- else {
- val valueSetter = Select(Ident(holderSym), valueGetter.setterIn(refClass))
-
- gen.mkSynchronized(Ident(holderSym))(mkChecked(
- alreadyComputed = getValue,
- compute = Block(Apply(valueSetter, rhsAtComputer :: Nil) :: setInitialized :: Nil, getValue))
- )
- }
- }
- val accessor = mkAccessor(lazyVal)(mkChecked(getValue, Apply(Ident(computerSym), Nil)))
+ val computer = mkAccessor(computerSym)(gen.mkSynchronized(Ident(holderSym))(
+ If(initialized, getValue,
+ if (isUnit) Block(rhsAtComputer :: Nil, Apply(initialize, Nil))
+ else Apply(initialize, rhsAtComputer :: Nil))))
+
+ val accessor = mkAccessor(lazyVal)(
+ If(initialized, getValue,
+ Apply(Ident(computerSym), Nil)))
// do last!
// remove STABLE: prevent replacing accessor call of type Unit by BoxedUnit.UNIT in erasure