Skip to content

Commit 103e077

Browse files
Backport "Avoid crash when superType does not exist after erasure" to LTS (#21067)
Backports #20188 to the LTS branch. PR submitted by the release tooling. [skip ci]
2 parents 40f497b + e2b1370 commit 103e077

File tree

5 files changed

+40
-37
lines changed

5 files changed

+40
-37
lines changed

compiler/src/dotty/tools/dotc/core/TypeErasure.scala

+4-4
Original file line numberDiff line numberDiff line change
@@ -751,12 +751,12 @@ class TypeErasure(sourceLanguage: SourceLanguage, semiEraseVCs: Boolean, isConst
751751
private def checkedSuperType(tp: TypeProxy)(using Context): Type =
752752
val tp1 = tp.translucentSuperType
753753
if !tp1.exists then
754-
val msg = tp.typeConstructor match
754+
val typeErr = tp.typeConstructor match
755755
case tycon: TypeRef =>
756-
MissingType(tycon.prefix, tycon.name).toMessage.message
756+
MissingType(tycon.prefix, tycon.name)
757757
case _ =>
758-
i"Cannot resolve reference to $tp"
759-
throw FatalError(msg)
758+
TypeError(em"Cannot resolve reference to $tp")
759+
throw typeErr
760760
tp1
761761

762762
/** Widen term ref, skipping any `()` parameter of an eventual getter. Used to erase a TermRef.

compiler/src/dotty/tools/dotc/core/TypeErrors.scala

+2-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ abstract class TypeError(using creationContext: Context) extends Exception(""):
4646
def toMessage(using Context): Message
4747

4848
/** Uses creationContext to produce the message */
49-
override def getMessage: String = toMessage.message
49+
override def getMessage: String =
50+
try toMessage.message catch case ex: Throwable => "TypeError"
5051

5152
object TypeError:
5253
def apply(msg: Message)(using Context) = new TypeError:

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

+29-25
Original file line numberDiff line numberDiff line change
@@ -388,31 +388,35 @@ object TreeChecker {
388388
}
389389

390390
override def typedUnadapted(tree: untpd.Tree, pt: Type, locked: TypeVars)(using Context): Tree = {
391-
val res = tree match {
392-
case _: untpd.TypedSplice | _: untpd.Thicket | _: EmptyValDef[?] =>
393-
super.typedUnadapted(tree, pt, locked)
394-
case _ if tree.isType =>
395-
promote(tree)
396-
case _ =>
397-
val tree1 = super.typedUnadapted(tree, pt, locked)
398-
def isSubType(tp1: Type, tp2: Type) =
399-
(tp1 eq tp2) || // accept NoType / NoType
400-
(tp1 <:< tp2)
401-
def divergenceMsg(tp1: Type, tp2: Type) =
402-
s"""Types differ
403-
|Original type : ${tree.typeOpt.show}
404-
|After checking: ${tree1.tpe.show}
405-
|Original tree : ${tree.show}
406-
|After checking: ${tree1.show}
407-
|Why different :
408-
""".stripMargin + core.TypeComparer.explained(_.isSubType(tp1, tp2))
409-
if (tree.hasType) // it might not be typed because Typer sometimes constructs new untyped trees and resubmits them to typedUnadapted
410-
assert(isSubType(tree1.tpe, tree.typeOpt), divergenceMsg(tree1.tpe, tree.typeOpt))
411-
tree1
412-
}
413-
checkNoOrphans(res.tpe)
414-
phasesToCheck.foreach(_.checkPostCondition(res))
415-
res
391+
try
392+
val res = tree match
393+
case _: untpd.TypedSplice | _: untpd.Thicket | _: EmptyValDef[?] =>
394+
super.typedUnadapted(tree, pt, locked)
395+
case _ if tree.isType =>
396+
promote(tree)
397+
case _ =>
398+
val tree1 = super.typedUnadapted(tree, pt, locked)
399+
def isSubType(tp1: Type, tp2: Type) =
400+
(tp1 eq tp2) || // accept NoType / NoType
401+
(tp1 <:< tp2)
402+
def divergenceMsg(tp1: Type, tp2: Type) =
403+
s"""Types differ
404+
|Original type : ${tree.typeOpt.show}
405+
|After checking: ${tree1.tpe.show}
406+
|Original tree : ${tree.show}
407+
|After checking: ${tree1.show}
408+
|Why different :
409+
""".stripMargin + core.TypeComparer.explained(_.isSubType(tp1, tp2))
410+
if (tree.hasType) // it might not be typed because Typer sometimes constructs new untyped trees and resubmits them to typedUnadapted
411+
assert(isSubType(tree1.tpe, tree.typeOpt), divergenceMsg(tree1.tpe, tree.typeOpt))
412+
tree1
413+
checkNoOrphans(res.tpe)
414+
phasesToCheck.foreach(_.checkPostCondition(res))
415+
res
416+
catch case NonFatal(ex) if !ctx.run.enrichedErrorMessage =>
417+
val treeStr = tree.show(using ctx.withPhase(ctx.phase.prev.megaPhase))
418+
println(ctx.run.enrichErrorMessage(s"exception while retyping $treeStr of class ${tree.className} # ${tree.uniqueId}"))
419+
throw ex
416420
}
417421

418422
def checkNotRepeated(tree: Tree)(using Context): tree.type = {

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

-7
Original file line numberDiff line numberDiff line change
@@ -149,13 +149,6 @@ class ReTyper(nestingLevel: Int = 0) extends Typer(nestingLevel) with ReChecking
149149
override def addCanThrowCapabilities(expr: untpd.Tree, cases: List[CaseDef])(using Context): untpd.Tree =
150150
expr
151151

152-
override def typedUnadapted(tree: untpd.Tree, pt: Type, locked: TypeVars)(using Context): Tree =
153-
try super.typedUnadapted(tree, pt, locked)
154-
catch case NonFatal(ex) if ctx.phase != Phases.typerPhase && ctx.phase != Phases.inliningPhase && !ctx.run.enrichedErrorMessage =>
155-
val treeStr = tree.show(using ctx.withPhase(ctx.phase.prev.megaPhase))
156-
println(ctx.run.enrichErrorMessage(s"exception while retyping $treeStr of class ${tree.className} # ${tree.uniqueId}"))
157-
throw ex
158-
159152
override def inlineExpansion(mdef: DefDef)(using Context): List[Tree] = mdef :: Nil
160153

161154
override def inferView(from: Tree, to: Type)(using Context): Implicits.SearchResult =

tests/pos/i19929.scala

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
trait A:
2+
private type M
3+
4+
def foo(a: A{type M = Int}) =
5+
val _: a.M = ??? // was crash

0 commit comments

Comments
 (0)