Skip to content

Commit 60591f8

Browse files
committed
Fix #2924: make TreeChecker.typedBlock iterative
1 parent c071dcf commit 60591f8

File tree

3 files changed

+4064
-28
lines changed

3 files changed

+4064
-28
lines changed

compiler/src/dotty/tools/dotc/transform/TreeChecker.scala

Lines changed: 49 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -149,34 +149,42 @@ class TreeChecker extends Phase with SymTransformer {
149149

150150
def withDefinedSym[T](tree: untpd.Tree)(op: => T)(implicit ctx: Context): T = tree match {
151151
case tree: untpd.DefTree =>
152-
val sym = tree.symbol
153-
assert(isValidJVMName(sym.name.encode), s"${sym.name.debugString} name is invalid on jvm")
154-
everDefinedSyms.get(sym) match {
155-
case Some(t) =>
156-
if (t ne tree)
157-
ctx.warning(i"symbol ${sym.fullName} is defined at least twice in different parts of AST")
158-
// should become an error
159-
case None =>
160-
everDefinedSyms(sym) = tree
161-
}
162-
assert(!nowDefinedSyms.contains(sym), i"doubly defined symbol: ${sym.fullName} in $tree")
163-
164-
if (ctx.settings.YcheckMods.value) {
165-
tree match {
166-
case t: untpd.MemberDef =>
167-
if (t.name ne sym.name) ctx.warning(s"symbol ${sym.fullName} name doesn't correspond to AST: ${t}")
168-
// todo: compare trees inside annotations
169-
case _ =>
170-
}
152+
preWithDefinedSym(tree)
153+
postWithDefinedSym(tree)(op)
154+
case _ => op
155+
}
156+
157+
private def preWithDefinedSym[T](tree: untpd.DefTree)(implicit ctx: Context): Unit = {
158+
val sym = tree.symbol
159+
assert(isValidJVMName(sym.name.encode), s"${sym.name.debugString} name is invalid on jvm")
160+
everDefinedSyms.get(sym) match {
161+
case Some(t) =>
162+
if (t ne tree)
163+
ctx.warning(i"symbol ${sym.fullName} is defined at least twice in different parts of AST")
164+
// should become an error
165+
case None =>
166+
everDefinedSyms(sym) = tree
167+
}
168+
assert(!nowDefinedSyms.contains(sym), i"doubly defined symbol: ${sym.fullName} in $tree")
169+
170+
if (ctx.settings.YcheckMods.value) {
171+
tree match {
172+
case t: untpd.MemberDef =>
173+
if (t.name ne sym.name) ctx.warning(s"symbol ${sym.fullName} name doesn't correspond to AST: ${t}")
174+
// todo: compare trees inside annotations
175+
case _ =>
171176
}
177+
}
178+
}
172179

173-
nowDefinedSyms += tree.symbol
174-
//ctx.echo(i"defined: ${tree.symbol}")
175-
val res = op
176-
nowDefinedSyms -= tree.symbol
177-
//ctx.echo(i"undefined: ${tree.symbol}")
178-
res
179-
case _ => op
180+
private def postWithDefinedSym[T](tree: untpd.DefTree)(op: => T)(implicit ctx: Context): T = {
181+
val sym = tree.symbol
182+
nowDefinedSyms += sym
183+
//ctx.echo(i"defined: ${tree.symbol}")
184+
val res = op
185+
nowDefinedSyms -= sym
186+
//ctx.echo(i"undefined: ${tree.symbol}")
187+
res
180188
}
181189

182190
def withDefinedSyms[T](trees: List[untpd.Tree])(op: => T)(implicit ctx: Context) =
@@ -411,8 +419,21 @@ class TreeChecker extends Phase with SymTransformer {
411419
}
412420
}
413421

414-
override def typedBlock(tree: untpd.Block, pt: Type)(implicit ctx: Context) =
415-
withDefinedSyms(tree.stats) { super.typedBlock(tree, pt) }
422+
override def typedBlock(tree: untpd.Block, pt: Type)(implicit ctx: Context) = {
423+
var locally = List.empty[Symbol]
424+
for (stat <- tree.stats) {
425+
stat match {
426+
case stat: untpd.DefTree =>
427+
preWithDefinedSym(stat)
428+
locally = stat.symbol :: locally
429+
nowDefinedSyms += stat.symbol
430+
case _ =>
431+
}
432+
}
433+
val res = super.typedBlock(tree, pt)
434+
nowDefinedSyms --= locally
435+
res
436+
}
416437

417438
override def typedInlined(tree: untpd.Inlined, pt: Type)(implicit ctx: Context) =
418439
withDefinedSyms(tree.bindings) { super.typedInlined(tree, pt) }

0 commit comments

Comments
 (0)