Skip to content

Commit 8ab5f00

Browse files
Handle symbol.defTree properly for nested definitions in bindings
Nested definitions in inlining bindings will get new symbols in `changeOwner`. The field `Symbol.defTree` is never set for those symbols. The problem is exhibited in the following test tests/pos/i10542.scala The fix in 0f034aa works by accident: ``` @@ -115,7 +115,9 @@ class ReTyper extends Typer with ReChecking { } override def typedUnadapted(tree: untpd.Tree, pt: Type, locked: TypeVars)(using Context): Tree = try super.typedUnadapted(tree, pt, locked) try super.typedUnadapted(tree, pt, locked) match case member: MemberDef => member.setDefTree case tree => tree ``` The reason is the following: - If we enable `-Ycheck:all`, it will sync the tree definition for all symbols during TreeChecker, thus no crash in initialization checker. - if we disable `-Ycheck:all`, the `defTree` for `<init>` is not set, initialization checker ignores the method, thus no crash. However, if we change `InlineTyper` instead of `Retyper`: ``` + override def typedUnadapted(tree: untpd.Tree, pt: Type, locked: TypeVars)(using Context): Tree = + super.typedUnadapted(tree, pt, locked) match + case member: MemberDef => member.setDefTree + case tree => tree ``` There will be some mysterious behavior in compiling `tests/pos/i10542.scala`: - Without `-Ycheck:all`, it succeeds. - With `-Ycheck:all`, the initialization check crashes due to missing `defTree` for the class `$anon`. The reason for the mysterious behavior is the following: - Without `-Ycheck:all`, there is no defTree for `<init>`, initialization check is skipped, thus no crash. - With `-Ycheck:all`, the method `Typer.typedDefDef` will set `Symbol.defTree` for `<init>`, called from the TreeChecker, which extends `Typer` indirectly via `ReTyper`. However, in `Typer.typedClassDef`, we never set `defTree` for class symbols, thus the `defTree` for the class symbol `$anon` is empty, causing an exception in initialization check. Co-authored-by: Nicolas Stucki <[email protected]>
1 parent ce30a1c commit 8ab5f00

File tree

2 files changed

+13
-6
lines changed

2 files changed

+13
-6
lines changed

compiler/src/dotty/tools/dotc/typer/Inliner.scala

+12-3
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) {
464464
if (isByName) DefDef(boundSym, arg.changeOwner(ctx.owner, boundSym))
465465
else ValDef(boundSym, arg)
466466
}.withSpan(boundSym.span)
467-
bindingsBuf += binding.setDefTree
467+
bindingsBuf += binding
468468
binding
469469
}
470470

@@ -521,7 +521,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) {
521521
ref(rhsClsSym.sourceModule)
522522
else
523523
inlineCallPrefix
524-
val binding = ValDef(selfSym.asTerm, QuoteUtils.changeOwnerOfTree(rhs, selfSym)).withSpan(selfSym.span).setDefTree
524+
val binding = ValDef(selfSym.asTerm, QuoteUtils.changeOwnerOfTree(rhs, selfSym)).withSpan(selfSym.span)
525525
bindingsBuf += binding
526526
inlining.println(i"proxy at $level: $selfSym = ${bindingsBuf.last}")
527527
lastSelf = selfSym
@@ -797,7 +797,12 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) {
797797
bindingsBuf.mapInPlace { binding =>
798798
// Set trees to symbols allow macros to see the definition tree.
799799
// This is used by `underlyingArgument`.
800-
reducer.normalizeBinding(binding)(using inlineCtx).setDefTree
800+
val binding1 = reducer.normalizeBinding(binding)(using inlineCtx).setDefTree
801+
binding1.foreachSubTree {
802+
case tree: MemberDef => tree.setDefTree
803+
case _ =>
804+
}
805+
binding1
801806
}
802807

803808
// Run a typing pass over the inlined tree. See InlineTyper for details.
@@ -1382,6 +1387,10 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) {
13821387
if Inliner.needsInlining(tree) then Inliner.inlineCall(tree)
13831388
else tree
13841389

1390+
override def typedUnadapted(tree: untpd.Tree, pt: Type, locked: TypeVars)(using Context): Tree =
1391+
super.typedUnadapted(tree, pt, locked) match
1392+
case member: MemberDef => member.setDefTree
1393+
case tree => tree
13851394
}
13861395

13871396
/** Drop any side-effect-free bindings that are unused in expansion or other reachable bindings.

compiler/src/dotty/tools/dotc/typer/ReTyper.scala

+1-3
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,7 @@ class ReTyper extends Typer with ReChecking {
115115
}
116116

117117
override def typedUnadapted(tree: untpd.Tree, pt: Type, locked: TypeVars)(using Context): Tree =
118-
try super.typedUnadapted(tree, pt, locked) match
119-
case member: MemberDef => member.setDefTree
120-
case tree => tree
118+
try super.typedUnadapted(tree, pt, locked)
121119
catch {
122120
case NonFatal(ex) =>
123121
if ctx.phase != Phases.typerPhase && ctx.phase != Phases.inliningPhase then

0 commit comments

Comments
 (0)