Skip to content

Commit 87f5347

Browse files
committed
Accept untyped children of typed trees in error cases
This happens, e.g. in realApply in Applications. Change TreeAccumulator and TreeMap to survive on untyped tree nodes in error cases. Also, add a configurable check that typed nodes point to untyped ones only in error cases.
1 parent 915ff94 commit 87f5347

File tree

2 files changed

+32
-1
lines changed

2 files changed

+32
-1
lines changed

compiler/src/dotty/tools/dotc/ast/Trees.scala

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import collection.mutable.ListBuffer
1313
import parsing.Tokens.Token
1414
import printing.Printer
1515
import util.{Stats, Attachment, Property, DotClass}
16+
import config.Config
1617
import annotation.unchecked.uncheckedVariance
1718
import language.implicitConversions
1819

@@ -113,10 +114,30 @@ object Trees {
113114
* type. (Overridden by empty trees)
114115
*/
115116
def withType(tpe: Type)(implicit ctx: Context): ThisTree[Type] = {
116-
if (tpe.isInstanceOf[ErrorType]) assert(ctx.reporter.errorsReported)
117+
if (tpe.isInstanceOf[ErrorType])
118+
assert(ctx.reporter.errorsReported)
119+
else if (Config.checkTreesConsistent)
120+
checkChildrenTyped(productIterator)
117121
withTypeUnchecked(tpe)
118122
}
119123

124+
/** Check that typed trees don't refer to untyped ones, except if
125+
* - the parent tree is an import, or
126+
* - the child tree is an identifier, or
127+
* - errors were reported
128+
*/
129+
private def checkChildrenTyped(it: Iterator[Any])(implicit ctx: Context): Unit =
130+
if (!this.isInstanceOf[Import[_]])
131+
while (it.hasNext)
132+
it.next match {
133+
case x: Ident[_] => // untyped idents are used in a number of places in typed trees
134+
case x: Tree[_] =>
135+
assert(x.hasType || ctx.reporter.errorsReported,
136+
s"$this has untyped child $x")
137+
case xs: List[_] => checkChildrenTyped(xs.iterator)
138+
case _ =>
139+
}
140+
120141
def withTypeUnchecked(tpe: Type): ThisTree[Type] = {
121142
val tree =
122143
(if (myTpe == null ||
@@ -1177,6 +1198,8 @@ object Trees {
11771198
case Thicket(trees) =>
11781199
val trees1 = transform(trees)
11791200
if (trees1 eq trees) tree else Thicket(trees1)
1201+
case _ if ctx.reporter.errorsReported =>
1202+
tree
11801203
}
11811204

11821205
def transformStats(trees: List[Tree])(implicit ctx: Context): List[Tree] =
@@ -1282,6 +1305,9 @@ object Trees {
12821305
this(this(x, arg), annot)
12831306
case Thicket(ts) =>
12841307
this(x, ts)
1308+
case _ if ctx.reporter.errorsReported =>
1309+
// in case of errors it may be that typed trees point to untyped ones.
1310+
x
12851311
}
12861312
}
12871313
}

compiler/src/dotty/tools/dotc/config/Config.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ object Config {
7272
/** Check positions for consistency after parsing */
7373
final val checkPositions = true
7474

75+
/** Check that typed trees don't point to untyped ones */
76+
final val checkTreesConsistent = false
77+
7578
/** Show subtype traces for all deep subtype recursions */
7679
final val traceDeepSubTypeRecursions = false
7780

@@ -163,4 +166,6 @@ object Config {
163166
* when findMemberLimit is set.
164167
*/
165168
final val PendingFindMemberLimit = LogPendingFindMemberThreshold * 4
169+
170+
final val ignoreStaleInIDE = true
166171
}

0 commit comments

Comments
 (0)