diff --git a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala index 0474aff4087a..48fb1bab2da1 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala @@ -751,12 +751,12 @@ class TypeErasure(sourceLanguage: SourceLanguage, semiEraseVCs: Boolean, isConst private def checkedSuperType(tp: TypeProxy)(using Context): Type = val tp1 = tp.translucentSuperType if !tp1.exists then - val msg = tp.typeConstructor match + val typeErr = tp.typeConstructor match case tycon: TypeRef => - MissingType(tycon.prefix, tycon.name).toMessage.message + MissingType(tycon.prefix, tycon.name) case _ => - i"Cannot resolve reference to $tp" - throw FatalError(msg) + TypeError(em"Cannot resolve reference to $tp") + throw typeErr tp1 /** Widen term ref, skipping any `()` parameter of an eventual getter. Used to erase a TermRef. diff --git a/compiler/src/dotty/tools/dotc/core/TypeErrors.scala b/compiler/src/dotty/tools/dotc/core/TypeErrors.scala index 240bc4eebd84..13fe02b712bc 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeErrors.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeErrors.scala @@ -46,7 +46,8 @@ abstract class TypeError(using creationContext: Context) extends Exception(""): def toMessage(using Context): Message /** Uses creationContext to produce the message */ - override def getMessage: String = toMessage.message + override def getMessage: String = + try toMessage.message catch case ex: Throwable => "TypeError" object TypeError: def apply(msg: Message)(using Context) = new TypeError: diff --git a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala index f1f703fb07ee..0515a6978a47 100644 --- a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala +++ b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala @@ -418,31 +418,35 @@ object TreeChecker { } override def typedUnadapted(tree: untpd.Tree, pt: Type, locked: TypeVars)(using Context): Tree = { - val res = tree match { - case _: untpd.TypedSplice | _: untpd.Thicket | _: EmptyValDef[?] => - super.typedUnadapted(tree, pt, locked) - case _ if tree.isType => - promote(tree) - case _ => - val tree1 = super.typedUnadapted(tree, pt, locked) - def isSubType(tp1: Type, tp2: Type) = - (tp1 eq tp2) || // accept NoType / NoType - (tp1 <:< tp2) - def divergenceMsg(tp1: Type, tp2: Type) = - s"""Types differ - |Original type : ${tree.typeOpt.show} - |After checking: ${tree1.tpe.show} - |Original tree : ${tree.show} - |After checking: ${tree1.show} - |Why different : - """.stripMargin + core.TypeComparer.explained(_.isSubType(tp1, tp2)) - if (tree.hasType) // it might not be typed because Typer sometimes constructs new untyped trees and resubmits them to typedUnadapted - assert(isSubType(tree1.tpe, tree.typeOpt), divergenceMsg(tree1.tpe, tree.typeOpt)) - tree1 - } - checkNoOrphans(res.tpe) - phasesToCheck.foreach(_.checkPostCondition(res)) - res + try + val res = tree match + case _: untpd.TypedSplice | _: untpd.Thicket | _: EmptyValDef[?] => + super.typedUnadapted(tree, pt, locked) + case _ if tree.isType => + promote(tree) + case _ => + val tree1 = super.typedUnadapted(tree, pt, locked) + def isSubType(tp1: Type, tp2: Type) = + (tp1 eq tp2) || // accept NoType / NoType + (tp1 <:< tp2) + def divergenceMsg(tp1: Type, tp2: Type) = + s"""Types differ + |Original type : ${tree.typeOpt.show} + |After checking: ${tree1.tpe.show} + |Original tree : ${tree.show} + |After checking: ${tree1.show} + |Why different : + """.stripMargin + core.TypeComparer.explained(_.isSubType(tp1, tp2)) + if (tree.hasType) // it might not be typed because Typer sometimes constructs new untyped trees and resubmits them to typedUnadapted + assert(isSubType(tree1.tpe, tree.typeOpt), divergenceMsg(tree1.tpe, tree.typeOpt)) + tree1 + checkNoOrphans(res.tpe) + phasesToCheck.foreach(_.checkPostCondition(res)) + res + catch case NonFatal(ex) if !ctx.run.enrichedErrorMessage => + val treeStr = tree.show(using ctx.withPhase(ctx.phase.prev.megaPhase)) + println(ctx.run.enrichErrorMessage(s"exception while retyping $treeStr of class ${tree.className} # ${tree.uniqueId}")) + throw ex } def checkNotRepeated(tree: Tree)(using Context): tree.type = { diff --git a/compiler/src/dotty/tools/dotc/typer/ReTyper.scala b/compiler/src/dotty/tools/dotc/typer/ReTyper.scala index e152b5e6b9c7..9741a366da89 100644 --- a/compiler/src/dotty/tools/dotc/typer/ReTyper.scala +++ b/compiler/src/dotty/tools/dotc/typer/ReTyper.scala @@ -170,13 +170,6 @@ class ReTyper(nestingLevel: Int = 0) extends Typer(nestingLevel) with ReChecking override def addCanThrowCapabilities(expr: untpd.Tree, cases: List[CaseDef])(using Context): untpd.Tree = expr - override def typedUnadapted(tree: untpd.Tree, pt: Type, locked: TypeVars)(using Context): Tree = - try super.typedUnadapted(tree, pt, locked) - catch case NonFatal(ex) if ctx.phase != Phases.typerPhase && ctx.phase != Phases.inliningPhase && !ctx.run.enrichedErrorMessage => - val treeStr = tree.show(using ctx.withPhase(ctx.phase.prev.megaPhase)) - println(ctx.run.enrichErrorMessage(s"exception while retyping $treeStr of class ${tree.className} # ${tree.uniqueId}")) - throw ex - override def inlineExpansion(mdef: DefDef)(using Context): List[Tree] = mdef :: Nil override def inferView(from: Tree, to: Type)(using Context): Implicits.SearchResult = diff --git a/tests/pos/i19929.scala b/tests/pos/i19929.scala new file mode 100644 index 000000000000..2e1c691af8f5 --- /dev/null +++ b/tests/pos/i19929.scala @@ -0,0 +1,5 @@ +trait A: + private type M + +def foo(a: A{type M = Int}) = + val _: a.M = ??? // was crash