@@ -390,13 +390,10 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor
390
390
}
391
391
}
392
392
393
- private def transformStat (exprOwner : Symbol )(stat : Tree ): List [Tree ] = {
394
- val clazz = currentOwner
395
- val statSym = stat.symbol
396
-
397
- // println(s"transformStat $statSym in ${exprOwner.ownerChain}")
398
- // currentRun.trackerFactory.snapshot()
393
+ def rhsAtOwner (stat : ValOrDefDef , newOwner : Symbol ): Tree =
394
+ atOwner(newOwner)(super .transform(stat.rhs.changeOwner(stat.symbol -> newOwner)))
399
395
396
+ private def deriveStoredAccessor (clazz : Symbol , stat : ValOrDefDef , fieldMemoization : FieldMemoization , exprOwner : Symbol ): List [Tree ] = {
400
397
// Which symbol should own `rhs`, as the expression is lifted from `statSym` to the class's template?
401
398
// Normally, the local dummy (`exprOwner`) is the owner for stats in the template (not `clazz`!)
402
399
// when we get owners wrong, the following fails:
@@ -406,21 +403,39 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor
406
403
// - test/files/trait-defaults/ultimate-nesting.scala,
407
404
// where a nested module class is separated from its module, as well as from the `settings` reference
408
405
// (this was due to changeOwner not changing a module's moduleClass's owner in addition to the module's owner)
409
- def initEffect ( rhs : Tree , assignSym : Symbol ) = {
406
+ val initEffect = {
410
407
// println(s"initEffect: owner $statSym --> $exprOwner (currentOwner= $currentOwner)")
411
408
// println(s"initEffect for $assignSym is $rhs")
412
409
413
- val lifted = atOwner(exprOwner)(super .transform(rhs.changeOwner(statSym -> exprOwner)))
410
+ val lifted = rhsAtOwner(stat, exprOwner)
411
+ import fieldMemoization .assignSym
414
412
415
413
if (assignSym eq NoSymbol ) lifted
416
- else localTyper.typedPos(rhs .pos) {
414
+ else localTyper.typedPos(stat .pos) {
417
415
val qual = Select (This (clazz), assignSym)
418
416
if (assignSym.isSetter) Apply (qual, List (lifted))
419
417
else Assign (qual, lifted)
420
418
}
421
419
}
422
420
423
- def init (rhs : Tree )(implicit fieldMemoization : FieldMemoization ) = initEffect(rhs, fieldMemoization.assignSym) :: Nil
421
+ // DefDef(computeSym, rhsAtOwner(stat, computeSym))
422
+ // def deriveRhs(oldRhs: Tree) = localTyper.typedPos(oldRhs.pos)(Apply(gen.mkAttributedRef(computeSym), Nil))
423
+
424
+ def deriveRhs (oldRhs : Tree ) = EmptyTree
425
+ val derivedStat = stat match {
426
+ case dd : DefDef => deriveDefDef(stat)(deriveRhs)
427
+ case vd : ValDef => deriveValDef(stat)(deriveRhs)
428
+ }
429
+
430
+ derivedStat :: initEffect :: Nil
431
+ }
432
+
433
+ private def transformStat (exprOwner : Symbol )(stat : Tree ): List [Tree ] = {
434
+ val clazz = currentOwner
435
+ val statSym = stat.symbol
436
+
437
+ // println(s"transformStat $statSym in ${exprOwner.ownerChain}")
438
+ // currentRun.trackerFactory.snapshot()
424
439
425
440
/*
426
441
For traits, the getter has the val's RHS, which is already constant-folded. There is no valdef.
@@ -431,39 +446,35 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor
431
446
432
447
All others (getter for trait field, valdef for class field) have their rhs moved to an initialization statement.
433
448
Trait accessors for stored fields are made abstract (there can be no field in a trait).
434
- All accessors for non-stored, but effectful fields, receive a constant rhs ,
435
- as the effect is performed by the initialization statement.
436
- ( We could do this for unit-typed fields, but have chosen not to for backwards compatibility.)
449
+ (In some future version, accessors for non-stored, but effectful fields,
450
+ would receive a constant rhs, as the effect is performed by the initialization statement.
451
+ We could do this for unit-typed fields, but have chosen not to for backwards compatibility.)
437
452
*/
438
453
stat match {
439
454
// TODO: consolidate with ValDef case
440
- case DefDef (_, _, _, _, _, rhs) if (rhs ne EmptyTree ) && (statSym hasFlag ACCESSOR ) && ! excludedAccessorOrFieldByFlags(statSym) =>
441
- // for accessors defined in a class, this wasn't done yet ???
442
- def statInlinedConstantRhs = deriveDefDef(stat)(_ => gen.mkAttributedQualifier(rhs.tpe))
455
+ case stat@ DefDef (_, _, _, _, _, rhs) if (rhs ne EmptyTree ) && (statSym hasFlag ACCESSOR ) && ! excludedAccessorOrFieldByFlags(statSym) =>
456
+ /* TODO: defer replacing ConstantTyped tree by the corresponding constant until erasure
457
+ (until then, trees should not be constant-folded -- only their type tracks the resulting constant) */
458
+ def statInlinedConstantRhs =
459
+ if (clazz.isTrait) stat // we've already done this for traits.. the asymmetry will be solved by the above todo
460
+ else deriveDefDef(stat)(_ => gen.mkAttributedQualifier(rhs.tpe))
443
461
444
- def dropRhs = deriveDefDef(stat)(_ => EmptyTree )
445
- implicit val fieldMemoization = fieldMemoizationIn(statSym, clazz)
462
+ val fieldMemoization = fieldMemoizationIn(statSym, clazz)
446
463
447
- def deriveStoredAccessor (stat : Tree ) = stat
448
- // if we decide to have non-stored fields with initialization effects:
449
- // if (!fieldMemoization.stored) deriveUnitDef(stat)
450
- // else stat
464
+ // if we decide to have non-stored fields with initialization effects, the stat's RHS should be replaced by unit
465
+ // if (!fieldMemoization.stored) deriveUnitDef(stat) else stat
451
466
452
- if (clazz.isTrait)
453
- if (fieldMemoization.pureConstant) stat :: Nil
454
- else deriveStoredAccessor(dropRhs) :: init(rhs)
455
- else
456
- if (fieldMemoization.pureConstant) statInlinedConstantRhs :: Nil
457
- else deriveStoredAccessor(stat) :: Nil
467
+ if (fieldMemoization.pureConstant) statInlinedConstantRhs :: Nil
468
+ else if (clazz.isTrait) deriveStoredAccessor(clazz, stat, fieldMemoization, exprOwner)
469
+ else stat :: Nil
458
470
459
- case ValDef (mods, _, _, rhs) if (rhs ne EmptyTree ) && ! excludedAccessorOrFieldByFlags(statSym) =>
460
- def dropRhs = deriveValDef(stat)(_ => EmptyTree )
461
- implicit val fieldMemoization = fieldMemoizationIn(statSym, clazz)
471
+ case stat@ ValDef (mods, _, _, rhs) if (rhs ne EmptyTree ) && ! excludedAccessorOrFieldByFlags(statSym) =>
472
+ val fieldMemoization = fieldMemoizationIn(statSym, clazz)
462
473
463
474
// drop the val for (a) constant (pure & not-stored) and (b) not-stored (but still effectful) fields
464
475
if (fieldMemoization.pureConstant) Nil // (a)
465
- else if (fieldMemoization.stored) dropRhs :: init(rhs )
466
- else init(rhs) // (b) -- not used currently
476
+ else if (fieldMemoization.stored) deriveStoredAccessor(clazz, stat, fieldMemoization, exprOwner )
477
+ else rhsAtOwner(stat, exprOwner) :: Nil // (b) -- not used currently
467
478
468
479
case tree => List (
469
480
if (exprOwner != currentOwner && tree.isTerm) atOwner(exprOwner)(super .transform(tree))
0 commit comments