@@ -302,8 +302,14 @@ trait MethodSynthesis {
302
302
def derivedSym : Symbol = tree.symbol
303
303
def derivedTree : Tree = EmptyTree
304
304
305
- // TODO: also don't need field when type is a ConstantType, right? Use typeNeedsNoStorage
306
- def noFieldNeeded = isDeferred || (mods.isLazy && definitions.isUnitType(basisSym.tpe))
305
+ // - abstract vals have no value and thus need for a field (until they become concrete, potentially)
306
+ // - traits store the RHS of the field in the getter;
307
+ // constructors will move the assignment to the constructor, abstracting over the field using the field setter
308
+ // - lazy or not, a val that stores a statically known value (unit / ConstantType) doesn't need a field either,
309
+ // although the lazy value will need to consult the init bitmap to make sure the lazy compute method is only run once
310
+ def noFieldNeeded = isDeferred ||
311
+ derivedSym.owner.isTrait ||
312
+ typeNeedsNoStorage(basisSym.tpe)
307
313
308
314
def isSetter = false
309
315
def isDeferred = mods.isDeferred
@@ -337,7 +343,7 @@ trait MethodSynthesis {
337
343
case _ => NoSymbol
338
344
}
339
345
private def setterRhs =
340
- if (isDeferred || derivedSym.isOverloaded) EmptyTree
346
+ if (noFieldNeeded || derivedSym.isOverloaded) EmptyTree
341
347
else Assign (fieldSelection, Ident (setterParam))
342
348
343
349
private def setterDef = DefDef (derivedSym, setterRhs)
@@ -380,7 +386,7 @@ trait MethodSynthesis {
380
386
}
381
387
case class Getter (tree : ValDef ) extends BaseGetter (tree) {
382
388
override def derivedSym = if (isDeferred) basisSym else basisSym.getterIn(enclClass)
383
- private def derivedRhs = if (isDeferred) EmptyTree else fieldSelection
389
+ private def derivedRhs = if (noFieldNeeded) tree.rhs else fieldSelection
384
390
private def derivedTpt = {
385
391
// For existentials, don't specify a type for the getter, even one derived
386
392
// from the symbol! This leads to incompatible existentials for the field and
@@ -401,12 +407,14 @@ trait MethodSynthesis {
401
407
}
402
408
override def derivedTree : DefDef = newDefDef(derivedSym, derivedRhs)(tpt = derivedTpt)
403
409
}
410
+
404
411
/** Implements lazy value accessors:
405
- * - for lazy values of type Unit and all lazy fields inside traits,
406
- * the rhs is the initializer itself
407
- * - for all other lazy values z the accessor is a block of this form:
408
- * { z = <rhs>; z } where z can be an identifier or a field.
409
- */
412
+ * - for lazy values of type Unit and all lazy fields inside traits,
413
+ * the rhs is the initializer itself, because we'll just "compute" the result on every access
414
+ * ("computing" unit / constant type is free -- the side-effect is still only run once, using the init bitmap)
415
+ * - for all other lazy values z the accessor is a block of this form:
416
+ * { z = <rhs>; z } where z can be an identifier or a field.
417
+ */
410
418
case class LazyValGetter (tree : ValDef ) extends BaseGetter (tree) {
411
419
class ChangeOwnerAndModuleClassTraverser (oldowner : Symbol , newowner : Symbol )
412
420
extends ChangeOwnerTraverser (oldowner, newowner) {
0 commit comments