Skip to content

Commit 822913e

Browse files
committed
refactor accessor/field derivation
in preparation of moving to compute-method style which in turn hopefully will be more manageable for specialization
1 parent cf845ab commit 822913e

File tree

1 file changed

+44
-33
lines changed

1 file changed

+44
-33
lines changed

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

Lines changed: 44 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -390,13 +390,10 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor
390390
}
391391
}
392392

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)))
399395

396+
private def deriveStoredAccessor(clazz: Symbol, stat: ValOrDefDef, fieldMemoization: FieldMemoization, exprOwner: Symbol): List[Tree] = {
400397
// Which symbol should own `rhs`, as the expression is lifted from `statSym` to the class's template?
401398
// Normally, the local dummy (`exprOwner`) is the owner for stats in the template (not `clazz`!)
402399
// when we get owners wrong, the following fails:
@@ -406,21 +403,39 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor
406403
// - test/files/trait-defaults/ultimate-nesting.scala,
407404
// where a nested module class is separated from its module, as well as from the `settings` reference
408405
// (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 = {
410407
// println(s"initEffect: owner $statSym --> $exprOwner (currentOwner= $currentOwner)")
411408
// println(s"initEffect for $assignSym is $rhs")
412409

413-
val lifted = atOwner(exprOwner)(super.transform(rhs.changeOwner(statSym -> exprOwner)))
410+
val lifted = rhsAtOwner(stat, exprOwner)
411+
import fieldMemoization.assignSym
414412

415413
if (assignSym eq NoSymbol) lifted
416-
else localTyper.typedPos(rhs.pos) {
414+
else localTyper.typedPos(stat.pos) {
417415
val qual = Select(This(clazz), assignSym)
418416
if (assignSym.isSetter) Apply(qual, List(lifted))
419417
else Assign(qual, lifted)
420418
}
421419
}
422420

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()
424439

425440
/*
426441
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
431446
432447
All others (getter for trait field, valdef for class field) have their rhs moved to an initialization statement.
433448
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.)
437452
*/
438453
stat match {
439454
// 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))
443461

444-
def dropRhs = deriveDefDef(stat)(_ => EmptyTree)
445-
implicit val fieldMemoization = fieldMemoizationIn(statSym, clazz)
462+
val fieldMemoization = fieldMemoizationIn(statSym, clazz)
446463

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
451466

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
458470

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)
462473

463474
// drop the val for (a) constant (pure & not-stored) and (b) not-stored (but still effectful) fields
464475
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
467478

468479
case tree => List (
469480
if (exprOwner != currentOwner && tree.isTerm) atOwner(exprOwner)(super.transform(tree))

0 commit comments

Comments
 (0)