@@ -339,29 +339,34 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor
339
339
}
340
340
}
341
341
342
- private def transformStat (templateSym : Symbol )(stat : Tree ): List [Tree ] = {
343
- val clazz = templateSym.owner
342
+ private def transformStat (exprOwner : Symbol )(stat : Tree ): List [Tree ] = {
343
+ val clazz = currentOwner
344
+ val statSym = stat.symbol
345
+
346
+ // println(s"transformStat $statSym in ${exprOwner.ownerChain}")
347
+ // currentRun.trackerFactory.snapshot()
344
348
345
- // TODO do we need to .changeOwner(statSym -> owner)) `rhs` before transforming?
346
- // changing owners as proposed above causes a stackoverflow in uncurry when bootstrapping
347
- // maybe go from statSym -> statSym.owner?
348
- // there's another (conflicting) issue when compiling scala.util.Properties,
349
- // where some references from the impl class are still pointing to the trait interface, not the impl class
350
- def initEffect (rhs : Tree , assignSym : Symbol ) =
351
- if (assignSym eq NoSymbol ) rhs
349
+ // TODO: which symbol should own `rhs`, as the expression is lifted from `statSym` to the class's template?
350
+ // Normally, the local dummy (`exprOwner`) is the owner for stats in the template (not `clazz`!)
351
+ // when we get owners wrong, the following fails:
352
+ // - stackoverflow in uncurry when bootstrapping
353
+ // - compiling scala.util.Properties,
354
+ // where some references from the impl class are still pointing to the trait interface, not the impl class
355
+ // - test/files/trait-defaults/ultimate-nesting.scala,
356
+ // where a nested module class is separated from its module, as well as from the `settings` reference
357
+ def initEffect (rhs : Tree , assignSym : Symbol ) = {
358
+ // println(s"initEffect: owner $statSym --> $exprOwner (currentOwner= $currentOwner)")
359
+ // println(s"initEffect for $assignSym is $rhs")
360
+
361
+ val lifted = atOwner(exprOwner)(super .transform(rhs.changeOwner(statSym -> exprOwner)))
362
+
363
+ if (assignSym eq NoSymbol ) lifted
352
364
else localTyper.typedPos(rhs.pos) {
353
365
val qual = Select (This (clazz), assignSym)
354
- if (assignSym.isSetter) Apply (qual, List (rhs ))
355
- else Assign (qual, rhs )
366
+ if (assignSym.isSetter) Apply (qual, List (lifted ))
367
+ else Assign (qual, lifted )
356
368
}
357
-
358
- val statSym = stat.symbol
359
- // println(s"transformStat $statSym in ${templateSym.ownerChain}")
360
-
361
- // `clazz` is not the right owner, local dummy is more accurate at this phase,
362
- // since it's the symbol of the template and thus the owner of template statements
363
- // currentRun.trackerFactory.snapshot()
364
- def lifted (rhs : Tree ) = super .transform(rhs.changeOwner(statSym -> templateSym))
369
+ }
365
370
366
371
stat match {
367
372
case DefDef (_, _, _, _, _, rhs) if (rhs ne EmptyTree ) && (statSym hasFlag ACCESSOR ) && ! (statSym hasFlag LAZY ) =>
@@ -371,7 +376,7 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor
371
376
// TODO: consolidate with ValDef case
372
377
if (clazz.isTrait) {
373
378
// there's a synthetic setter if val is not mutable (symbol is created in info transform)
374
- if (fieldMemoization.effectful) deriveDefDef(stat)(getterRhs) :: initEffect(lifted( rhs) , fieldMemoization.assignSym) :: Nil
379
+ if (fieldMemoization.effectful) deriveDefDef(stat)(getterRhs) :: initEffect(rhs, fieldMemoization.assignSym) :: Nil
375
380
else stat :: Nil
376
381
} else (
377
382
// regular getter -- field will be preserved (see case ValDef)
@@ -386,25 +391,37 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor
386
391
case ValDef (mods, _, _, rhs) if (rhs ne EmptyTree ) && ! (statSym hasFlag LAZY ) && ! (mods hasFlag PRESUPER ) =>
387
392
val fieldMemoization = fieldMemoizationIn(statSym, clazz)
388
393
389
- if (fieldMemoization.needsField) deriveValDef(stat)(_ => EmptyTree ) :: initEffect(lifted( rhs) , fieldMemoization.assignSym) :: Nil
390
- else if (fieldMemoization.effectOnly) initEffect(lifted( rhs) , NoSymbol ) :: Nil // drop the val entirely -- it could not have been referenced outside accesors
394
+ if (fieldMemoization.needsField) deriveValDef(stat)(_ => EmptyTree ) :: initEffect(rhs, fieldMemoization.assignSym) :: Nil
395
+ else if (fieldMemoization.effectOnly) initEffect(rhs, NoSymbol ) :: Nil // drop the val entirely -- it could not have been referenced outside accesors
391
396
else Nil
392
397
393
- case tree => List (super .transform(tree))
398
+ // case Template(parents, self, body) =>
399
+ // treeCopy.Template(tree, transformTrees(parents), transformValDef(self), transformStats(body, tree.symbol))
400
+
401
+ case tree => List (
402
+ if (exprOwner != currentOwner && tree.isTerm) atOwner(exprOwner)(super .transform(tree))
403
+ else super .transform(tree)
404
+ )
394
405
}
395
406
}
396
407
397
- override def transformTemplate (tree : Template ): Template = {
398
- // println(s"transforming stats in ${currentOwner}")
399
- // Skip interfaces (they have no concrete methods, so no work to be done)
400
- if (! currentOwner.isClass || currentOwner.isPackageClass || currentOwner.isInterface) super .transformTemplate(tree)
408
+ override def transformStats (stats : List [Tree ], exprOwner : Symbol ): List [Tree ] =
409
+ if (! currentOwner.isClass || currentOwner.isPackageClass || currentOwner.isInterface) super .transformStats(stats, exprOwner)
401
410
else afterOwnPhase {
402
- currentOwner.info // TODO remove -- for debugging
403
- deriveTemplate(tree)(stats => {
404
- val templateSym = tree.symbol
405
- fieldsAndAccessors(templateSym) ++ stats.flatMap(transformStat(templateSym))
406
- })
411
+ fieldsAndAccessors(exprOwner) ++ (stats flatMap transformStat(exprOwner))
407
412
}
408
- }
413
+
414
+ // override def transformTemplate(tree: Template): Template = {
415
+ // // println(s"transforming stats in ${currentOwner}")
416
+ // // Skip interfaces (they have no concrete methods, so no work to be done)
417
+ // else afterOwnPhase {
418
+ // currentOwner.info // TODO remove -- for debugging
419
+ // deriveTemplate(tree)(stats => {
420
+ // val templateSym = tree.symbol
421
+ // fieldsAndAccessors(templateSym) ++ stats.flatMap(transformStat(templateSym))
422
+ // })
423
+ // }
424
+ // }
425
+
409
426
}
410
427
}
0 commit comments