Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backport "Consistently use TypeMismatch in TreeChecker" to LTS #22119

Merged
merged 1 commit into from
Dec 4, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 17 additions & 31 deletions compiler/src/dotty/tools/dotc/transform/TreeChecker.scala
Original file line number Diff line number Diff line change
Expand Up @@ -397,19 +397,8 @@ object TreeChecker {
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))
if tree.hasType then // it might not be typed because Typer sometimes constructs new untyped trees and resubmits them to typedUnadapted
checkType(tree1.tpe, tree.typeOpt, tree, "typedUnadapted")
tree1
checkNoOrphans(res.tpe)
phasesToCheck.foreach(_.checkPostCondition(res))
Expand Down Expand Up @@ -747,28 +736,25 @@ object TreeChecker {
override def adapt(tree: Tree, pt: Type, locked: TypeVars)(using Context): Tree = {
def isPrimaryConstructorReturn =
ctx.owner.isPrimaryConstructor && pt.isRef(ctx.owner.owner) && tree.tpe.isRef(defn.UnitClass)
def infoStr(tp: Type) = tp match {
case tp: TypeRef =>
val sym = tp.symbol
i"${sym.showLocated} with ${tp.designator}, flags = ${sym.flagsString}, underlying = ${tp.underlyingIterator.toList}%, %"
case _ =>
"??"
}
if (ctx.mode.isExpr &&
!tree.isEmpty &&
!isPrimaryConstructorReturn &&
!pt.isInstanceOf[FunOrPolyProto])
assert(tree.tpe <:< pt, {
val mismatch = TypeMismatch(tree.tpe, pt, Some(tree))
i"""|${mismatch.msg}
|found: ${infoStr(tree.tpe)}
|expected: ${infoStr(pt)}
|tree = $tree""".stripMargin
})
if ctx.mode.isExpr
&& !tree.isEmpty
&& !isPrimaryConstructorReturn
&& !pt.isInstanceOf[FunOrPolyProto]
then
checkType(tree.tpe, pt, tree, "adapt")
tree
}

override def simplify(tree: Tree, pt: Type, locked: TypeVars)(using Context): tree.type = tree

private def checkType(tp1: Type, tp2: Type, tree: untpd.Tree, step: String)(using Context) =
// Accept NoType <:< NoType as true
assert((tp1 eq tp2) || (tp1 <:< tp2), {
val mismatch = TypeMismatch(tp1, tp2, None)
i"""|Type Mismatch (while checking $step):
|${mismatch.message}${mismatch.explanation}
|tree = $tree ${tree.className}""".stripMargin
})
}

/** Tree checker that can be applied to a local tree. */
Expand Down
Loading