@@ -137,14 +137,10 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor
137
137
// not stored, no side-effect
138
138
val pureConstant = tp.isInstanceOf [ConstantType ]
139
139
140
- val stored = ! (pureConstant) // || isUnitType(tp))
141
-
142
-
143
- // println(s"fieldMemoizationIn $sym $site = $tp")
144
- def assignSym : Symbol =
145
- if (! stored) NoSymbol
146
- else if (accessorOrField hasFlag ACCESSOR ) accessorOrField.setterIn(site)
147
- else accessorOrField
140
+ // if !stored, may still have a side-effect
141
+ // (currently not distinguished -- used to think we could drop unit-typed vals,
142
+ // but the memory model cares about writes to unit-typed fields)
143
+ val stored = ! pureConstant // || isUnitType(tp))
148
144
}
149
145
150
146
private def fieldTypeForGetterIn (getter : Symbol , pre : Type ): Type = getter.info.finalResultType.asSeenFrom(pre, getter.owner)
@@ -262,7 +258,7 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor
262
258
afterOwnPhase { mixin.info }.decls.toList.filter(accessorImplementedInSubclass)
263
259
}
264
260
265
- // println(s"mixing in $accessorsMaybeNeedingImpl from ${clazz.mixinClasses}")
261
+ // println(s"mixing in for $clazz: $accessorsMaybeNeedingImpl from ${clazz.mixinClasses}")
266
262
267
263
// TODO: setter conflicts?
268
264
def accessorConflictsExistingVal (accessor : Symbol ): Boolean = {
@@ -289,7 +285,6 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor
289
285
// a trait setter for an overridden val will receive a unit body in the tree transform
290
286
if (nme.isTraitSetterName(accessor.name)) {
291
287
val getter = accessor.getterIn(accessor.owner)
292
- // println(s"mixing in trait setter ${accessor.defString}: $overridden")
293
288
val clone = cloneAccessor()
294
289
295
290
clone filterAnnotations (ai => ! ai.matches(TraitSetterAnnotationClass )) // only supposed to be set in trait
@@ -372,7 +367,7 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor
372
367
else fieldAccess(getter)
373
368
}
374
369
375
- // println(s"accessorsAndFieldsNeedingTrees: $accessorsAndFieldsNeedingTrees")
370
+ // println(s"accessorsAndFieldsNeedingTrees for $templateSym : $accessorsAndFieldsNeedingTrees")
376
371
def setterBody (setter : Symbol ): Tree = {
377
372
// trait setter in trait
378
373
if (clazz.isTrait) EmptyTree
@@ -393,48 +388,11 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor
393
388
def rhsAtOwner (stat : ValOrDefDef , newOwner : Symbol ): Tree =
394
389
atOwner(newOwner)(super .transform(stat.rhs.changeOwner(stat.symbol -> newOwner)))
395
390
396
- private def deriveStoredAccessor (clazz : Symbol , stat : ValOrDefDef , fieldMemoization : FieldMemoization , exprOwner : Symbol ): List [Tree ] = {
397
- // Which symbol should own `rhs`, as the expression is lifted from `statSym` to the class's template?
398
- // Normally, the local dummy (`exprOwner`) is the owner for stats in the template (not `clazz`!)
399
- // when we get owners wrong, the following fails:
400
- // - stackoverflow in uncurry when bootstrapping
401
- // - compiling scala.util.Properties,
402
- // where some references from the impl class are still pointing to the trait interface, not the impl class
403
- // - test/files/trait-defaults/ultimate-nesting.scala,
404
- // where a nested module class is separated from its module, as well as from the `settings` reference
405
- // (this was due to changeOwner not changing a module's moduleClass's owner in addition to the module's owner)
406
- val initEffect = {
407
- // println(s"initEffect: owner $statSym --> $exprOwner (currentOwner= $currentOwner)")
408
- // println(s"initEffect for $assignSym is $rhs")
409
-
410
- val lifted = rhsAtOwner(stat, exprOwner)
411
- import fieldMemoization .assignSym
412
-
413
- if (assignSym eq NoSymbol ) lifted
414
- else localTyper.typedPos(stat.pos) {
415
- val qual = Select (This (clazz), assignSym)
416
- if (assignSym.isSetter) Apply (qual, List (lifted))
417
- else Assign (qual, lifted)
418
- }
419
- }
420
-
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
391
private def transformStat (exprOwner : Symbol )(stat : Tree ): List [Tree ] = {
434
392
val clazz = currentOwner
435
393
val statSym = stat.symbol
436
394
437
- // println(s"transformStat $statSym in ${exprOwner.ownerChain}")
395
+ // println(s"transformStat $statSym in ${exprOwner.ownerChain}")
438
396
// currentRun.trackerFactory.snapshot()
439
397
440
398
/*
@@ -452,29 +410,38 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor
452
410
*/
453
411
stat match {
454
412
// TODO: consolidate with ValDef case
455
- case stat@ DefDef (_, _, _, _, _, rhs) if (rhs ne EmptyTree ) && ( statSym hasFlag ACCESSOR ) && ! excludedAccessorOrFieldByFlags(statSym) =>
413
+ case stat@ DefDef (_, _, _, _, _, rhs) if (statSym hasFlag ACCESSOR ) && ! excludedAccessorOrFieldByFlags(statSym) =>
456
414
/* 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) */
415
+ (until then, trees should not be constant-folded -- only their type tracks the resulting constant)
416
+ TODO: also remove ACCESSOR flag since there won't be an underlying field to access?
417
+ */
458
418
def statInlinedConstantRhs =
459
419
if (clazz.isTrait) stat // we've already done this for traits.. the asymmetry will be solved by the above todo
460
420
else deriveDefDef(stat)(_ => gen.mkAttributedQualifier(rhs.tpe))
461
421
462
- val fieldMemoization = fieldMemoizationIn(statSym, clazz)
422
+ if (rhs ne EmptyTree ) {
423
+ val fieldMemoization = fieldMemoizationIn(statSym, clazz)
463
424
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
425
+ // if we decide to have non-stored fields with initialization effects, the stat's RHS should be replaced by unit
426
+ // if (!fieldMemoization.stored) deriveUnitDef(stat) else stat
466
427
467
- if (fieldMemoization.pureConstant) statInlinedConstantRhs :: Nil
468
- else if (clazz.isTrait) deriveStoredAccessor(clazz, stat, fieldMemoization, exprOwner)
469
- else stat :: Nil
428
+ if (fieldMemoization.pureConstant) statInlinedConstantRhs :: Nil
429
+ else super .transform(stat) :: Nil
430
+ } else {
431
+ stat :: Nil
432
+ }
470
433
471
- case stat@ ValDef (mods, _, _, rhs) if (rhs ne EmptyTree ) && ! excludedAccessorOrFieldByFlags(statSym) =>
472
- val fieldMemoization = fieldMemoizationIn(statSym, clazz)
434
+ case stat@ ValDef (mods, _, _, rhs) if ! excludedAccessorOrFieldByFlags(statSym) =>
435
+ if (rhs ne EmptyTree ) {
436
+ val fieldMemoization = fieldMemoizationIn(statSym, clazz)
473
437
474
- // drop the val for (a) constant (pure & not-stored) and (b) not-stored (but still effectful) fields
475
- if (fieldMemoization.pureConstant) Nil // (a)
476
- else if (fieldMemoization.stored) deriveStoredAccessor(clazz, stat, fieldMemoization, exprOwner)
477
- else rhsAtOwner(stat, exprOwner) :: Nil // (b) -- not used currently
438
+ // drop the val for (a) constant (pure & not-stored) and (b) not-stored (but still effectful) fields
439
+ if (fieldMemoization.pureConstant) Nil // (a)
440
+ else super .transform(stat) :: Nil // if (fieldMemoization.stored)
441
+ // else rhsAtOwner(transformStat, exprOwner) :: Nil // (b) -- not used currently
442
+ } else {
443
+ stat :: Nil
444
+ }
478
445
479
446
case tree => List (
480
447
if (exprOwner != currentOwner && tree.isTerm) atOwner(exprOwner)(super .transform(tree))
0 commit comments