Skip to content

Commit 4585dcb

Browse files
committed
Fix #1568 - avoid transforming error trees
If a tree has type error, subtrees may not have an assigned type. Therefore we should avoid transforming such trees.
1 parent 64332a7 commit 4585dcb

File tree

3 files changed

+97
-87
lines changed

3 files changed

+97
-87
lines changed

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

Lines changed: 92 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,95 +1069,100 @@ object Trees {
10691069
Template(tree: Tree)(constr, parents, self, body)
10701070
}
10711071

1072+
/** Hook to indicate that a transform of some subtree should be skipped */
1073+
protected def skipTransform(tree: Tree)(implicit ctx: Context): Boolean = false
1074+
10721075
abstract class TreeMap(val cpy: TreeCopier = inst.cpy) {
10731076

1074-
def transform(tree: Tree)(implicit ctx: Context): Tree = tree match {
1075-
case Ident(name) =>
1076-
tree
1077-
case Select(qualifier, name) =>
1078-
cpy.Select(tree)(transform(qualifier), name)
1079-
case This(qual) =>
1080-
tree
1081-
case Super(qual, mix) =>
1082-
cpy.Super(tree)(transform(qual), mix)
1083-
case Apply(fun, args) =>
1084-
cpy.Apply(tree)(transform(fun), transform(args))
1085-
case TypeApply(fun, args) =>
1086-
cpy.TypeApply(tree)(transform(fun), transform(args))
1087-
case Literal(const) =>
1088-
tree
1089-
case New(tpt) =>
1090-
cpy.New(tree)(transform(tpt))
1091-
case Typed(expr, tpt) =>
1092-
cpy.Typed(tree)(transform(expr), transform(tpt))
1093-
case NamedArg(name, arg) =>
1094-
cpy.NamedArg(tree)(name, transform(arg))
1095-
case Assign(lhs, rhs) =>
1096-
cpy.Assign(tree)(transform(lhs), transform(rhs))
1097-
case Block(stats, expr) =>
1098-
cpy.Block(tree)(transformStats(stats), transform(expr))
1099-
case If(cond, thenp, elsep) =>
1100-
cpy.If(tree)(transform(cond), transform(thenp), transform(elsep))
1101-
case Closure(env, meth, tpt) =>
1102-
cpy.Closure(tree)(transform(env), transform(meth), transform(tpt))
1103-
case Match(selector, cases) =>
1104-
cpy.Match(tree)(transform(selector), transformSub(cases))
1105-
case CaseDef(pat, guard, body) =>
1106-
cpy.CaseDef(tree)(transform(pat), transform(guard), transform(body))
1107-
case Return(expr, from) =>
1108-
cpy.Return(tree)(transform(expr), transformSub(from))
1109-
case Try(block, cases, finalizer) =>
1110-
cpy.Try(tree)(transform(block), transformSub(cases), transform(finalizer))
1111-
case SeqLiteral(elems, elemtpt) =>
1112-
cpy.SeqLiteral(tree)(transform(elems), transform(elemtpt))
1113-
case Inlined(call, bindings, expansion) =>
1114-
cpy.Inlined(tree)(call, transformSub(bindings), transform(expansion))
1115-
case TypeTree() =>
1116-
tree
1117-
case SingletonTypeTree(ref) =>
1118-
cpy.SingletonTypeTree(tree)(transform(ref))
1119-
case AndTypeTree(left, right) =>
1120-
cpy.AndTypeTree(tree)(transform(left), transform(right))
1121-
case OrTypeTree(left, right) =>
1122-
cpy.OrTypeTree(tree)(transform(left), transform(right))
1123-
case RefinedTypeTree(tpt, refinements) =>
1124-
cpy.RefinedTypeTree(tree)(transform(tpt), transformSub(refinements))
1125-
case AppliedTypeTree(tpt, args) =>
1126-
cpy.AppliedTypeTree(tree)(transform(tpt), transform(args))
1127-
case PolyTypeTree(tparams, body) =>
1128-
cpy.PolyTypeTree(tree)(transformSub(tparams), transform(body))
1129-
case ByNameTypeTree(result) =>
1130-
cpy.ByNameTypeTree(tree)(transform(result))
1131-
case TypeBoundsTree(lo, hi) =>
1132-
cpy.TypeBoundsTree(tree)(transform(lo), transform(hi))
1133-
case Bind(name, body) =>
1134-
cpy.Bind(tree)(name, transform(body))
1135-
case Alternative(trees) =>
1136-
cpy.Alternative(tree)(transform(trees))
1137-
case UnApply(fun, implicits, patterns) =>
1138-
cpy.UnApply(tree)(transform(fun), transform(implicits), transform(patterns))
1139-
case EmptyValDef =>
1140-
tree
1141-
case tree @ ValDef(name, tpt, _) =>
1142-
val tpt1 = transform(tpt)
1143-
val rhs1 = transform(tree.rhs)
1144-
cpy.ValDef(tree)(name, tpt1, rhs1)
1145-
case tree @ DefDef(name, tparams, vparamss, tpt, _) =>
1146-
cpy.DefDef(tree)(name, transformSub(tparams), vparamss mapConserve (transformSub(_)), transform(tpt), transform(tree.rhs))
1147-
case tree @ TypeDef(name, rhs) =>
1148-
cpy.TypeDef(tree)(name, transform(rhs))
1149-
case tree @ Template(constr, parents, self, _) =>
1150-
cpy.Template(tree)(transformSub(constr), transform(parents), transformSub(self), transformStats(tree.body))
1151-
case Import(expr, selectors) =>
1152-
cpy.Import(tree)(transform(expr), selectors)
1153-
case PackageDef(pid, stats) =>
1154-
cpy.PackageDef(tree)(transformSub(pid), transformStats(stats))
1155-
case Annotated(arg, annot) =>
1156-
cpy.Annotated(tree)(transform(arg), transform(annot))
1157-
case Thicket(trees) =>
1158-
val trees1 = transform(trees)
1159-
if (trees1 eq trees) tree else Thicket(trees1)
1160-
}
1077+
def transform(tree: Tree)(implicit ctx: Context): Tree =
1078+
if (skipTransform(tree)) tree
1079+
else tree match {
1080+
case Ident(name) =>
1081+
tree
1082+
case Select(qualifier, name) =>
1083+
cpy.Select(tree)(transform(qualifier), name)
1084+
case This(qual) =>
1085+
tree
1086+
case Super(qual, mix) =>
1087+
cpy.Super(tree)(transform(qual), mix)
1088+
case Apply(fun, args) =>
1089+
cpy.Apply(tree)(transform(fun), transform(args))
1090+
case TypeApply(fun, args) =>
1091+
cpy.TypeApply(tree)(transform(fun), transform(args))
1092+
case Literal(const) =>
1093+
tree
1094+
case New(tpt) =>
1095+
cpy.New(tree)(transform(tpt))
1096+
case Typed(expr, tpt) =>
1097+
cpy.Typed(tree)(transform(expr), transform(tpt))
1098+
case NamedArg(name, arg) =>
1099+
cpy.NamedArg(tree)(name, transform(arg))
1100+
case Assign(lhs, rhs) =>
1101+
cpy.Assign(tree)(transform(lhs), transform(rhs))
1102+
case Block(stats, expr) =>
1103+
cpy.Block(tree)(transformStats(stats), transform(expr))
1104+
case If(cond, thenp, elsep) =>
1105+
cpy.If(tree)(transform(cond), transform(thenp), transform(elsep))
1106+
case Closure(env, meth, tpt) =>
1107+
cpy.Closure(tree)(transform(env), transform(meth), transform(tpt))
1108+
case Match(selector, cases) =>
1109+
cpy.Match(tree)(transform(selector), transformSub(cases))
1110+
case CaseDef(pat, guard, body) =>
1111+
cpy.CaseDef(tree)(transform(pat), transform(guard), transform(body))
1112+
case Return(expr, from) =>
1113+
cpy.Return(tree)(transform(expr), transformSub(from))
1114+
case Try(block, cases, finalizer) =>
1115+
cpy.Try(tree)(transform(block), transformSub(cases), transform(finalizer))
1116+
case SeqLiteral(elems, elemtpt) =>
1117+
cpy.SeqLiteral(tree)(transform(elems), transform(elemtpt))
1118+
case Inlined(call, bindings, expansion) =>
1119+
cpy.Inlined(tree)(call, transformSub(bindings), transform(expansion))
1120+
case TypeTree() =>
1121+
tree
1122+
case SingletonTypeTree(ref) =>
1123+
cpy.SingletonTypeTree(tree)(transform(ref))
1124+
case AndTypeTree(left, right) =>
1125+
cpy.AndTypeTree(tree)(transform(left), transform(right))
1126+
case OrTypeTree(left, right) =>
1127+
cpy.OrTypeTree(tree)(transform(left), transform(right))
1128+
case RefinedTypeTree(tpt, refinements) =>
1129+
cpy.RefinedTypeTree(tree)(transform(tpt), transformSub(refinements))
1130+
case AppliedTypeTree(tpt, args) =>
1131+
cpy.AppliedTypeTree(tree)(transform(tpt), transform(args))
1132+
case PolyTypeTree(tparams, body) =>
1133+
cpy.PolyTypeTree(tree)(transformSub(tparams), transform(body))
1134+
case ByNameTypeTree(result) =>
1135+
cpy.ByNameTypeTree(tree)(transform(result))
1136+
case TypeBoundsTree(lo, hi) =>
1137+
cpy.TypeBoundsTree(tree)(transform(lo), transform(hi))
1138+
case Bind(name, body) =>
1139+
cpy.Bind(tree)(name, transform(body))
1140+
case Alternative(trees) =>
1141+
cpy.Alternative(tree)(transform(trees))
1142+
case UnApply(fun, implicits, patterns) =>
1143+
cpy.UnApply(tree)(transform(fun), transform(implicits), transform(patterns))
1144+
case EmptyValDef =>
1145+
tree
1146+
case tree @ ValDef(name, tpt, _) =>
1147+
val tpt1 = transform(tpt)
1148+
val rhs1 = transform(tree.rhs)
1149+
cpy.ValDef(tree)(name, tpt1, rhs1)
1150+
case tree @ DefDef(name, tparams, vparamss, tpt, _) =>
1151+
cpy.DefDef(tree)(name, transformSub(tparams), vparamss mapConserve (transformSub(_)), transform(tpt), transform(tree.rhs))
1152+
case tree @ TypeDef(name, rhs) =>
1153+
cpy.TypeDef(tree)(name, transform(rhs))
1154+
case tree @ Template(constr, parents, self, _) =>
1155+
cpy.Template(tree)(transformSub(constr), transform(parents), transformSub(self), transformStats(tree.body))
1156+
case Import(expr, selectors) =>
1157+
cpy.Import(tree)(transform(expr), selectors)
1158+
case PackageDef(pid, stats) =>
1159+
cpy.PackageDef(tree)(transformSub(pid), transformStats(stats))
1160+
case Annotated(arg, annot) =>
1161+
cpy.Annotated(tree)(transform(arg), transform(annot))
1162+
case Thicket(trees) =>
1163+
val trees1 = transform(trees)
1164+
if (trees1 eq trees) tree else Thicket(trees1)
1165+
}
11611166

11621167
def transformStats(trees: List[Tree])(implicit ctx: Context): List[Tree] =
11631168
transform(trees)

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,8 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
573573
Try(tree: Tree)(expr, cases, finalizer)
574574
}
575575

576+
override def skipTransform(tree: Tree)(implicit ctx: Context) = tree.tpe.isError
577+
576578
implicit class TreeOps[ThisTree <: tpd.Tree](val tree: ThisTree) extends AnyVal {
577579

578580
def isValue(implicit ctx: Context): Boolean =

tests/neg/i1568.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
object Test {
2+
inline def foo(n: Int) = foo(n) // error: cyclic reference
3+
}

0 commit comments

Comments
 (0)