diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index 0f74ca40843b..5aab2e277693 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -3268,9 +3268,10 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling /** The trace of comparison operations when performing `op` */ def explained[T](op: ExplainingTypeComparer => T, header: String = "Subtype trace:", short: Boolean)(using Context): String = - val cmp = explainingTypeComparer(short) - inSubComparer(cmp)(op) - cmp.lastTrace(header) + explaining(cmp => { op(cmp); cmp.lastTrace(header) }, short) + + def explaining[T](op: ExplainingTypeComparer => T, short: Boolean)(using Context): T = + inSubComparer(explainingTypeComparer(short))(op) def reduceMatchWith[T](op: MatchReducer => T)(using Context): T = inSubComparer(matchReducer)(op) @@ -3440,6 +3441,9 @@ object TypeComparer { def explained[T](op: ExplainingTypeComparer => T, header: String = "Subtype trace:", short: Boolean = false)(using Context): String = comparing(_.explained(op, header, short)) + def explaining[T](op: ExplainingTypeComparer => T, short: Boolean = false)(using Context): T = + comparing(_.explaining(op, short)) + def reduceMatchWith[T](op: MatchReducer => T)(using Context): T = comparing(_.reduceMatchWith(op)) @@ -3873,7 +3877,7 @@ class ExplainingTypeComparer(initctx: Context, short: Boolean) extends TypeCompa override def recur(tp1: Type, tp2: Type): Boolean = def moreInfo = if Config.verboseExplainSubtype || ctx.settings.verbose.value - then s" ${tp1.getClass} ${tp2.getClass}" + then s" ${tp1.className} ${tp2.className}" else "" val approx = approxState def approxStr = if short then "" else approx.show diff --git a/compiler/src/dotty/tools/dotc/core/TypeOps.scala b/compiler/src/dotty/tools/dotc/core/TypeOps.scala index 8089735bdb0f..0d8801b646ee 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeOps.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeOps.scala @@ -691,11 +691,22 @@ object TypeOps: val hiBound = instantiate(bounds.hi, skolemizedArgTypes) val loBound = instantiate(bounds.lo, skolemizedArgTypes) - def check(using Context) = { - if (!(lo <:< hiBound)) violations += ((arg, "upper", hiBound)) - if (!(loBound <:< hi)) violations += ((arg, "lower", loBound)) + def check(tp1: Type, tp2: Type, which: String, bound: Type)(using Context) = { + val isSub = TypeComparer.explaining { cmp => + val isSub = cmp.isSubType(tp1, tp2) + if !isSub then + if !ctx.typerState.constraint.domainLambdas.isEmpty then + typr.println(i"${ctx.typerState.constraint}") + if !ctx.gadt.symbols.isEmpty then + typr.println(i"${ctx.gadt}") + typr.println(cmp.lastTrace(i"checkOverlapsBounds($lo, $hi, $arg, $bounds)($which)")) + //trace.dumpStack() + isSub + }//(using ctx.fresh.setSetting(ctx.settings.verbose, true)) // uncomment to enable moreInfo in ExplainingTypeComparer recur + if !isSub then violations += ((arg, which, bound)) } - check(using checkCtx) + check(lo, hiBound, "upper", hiBound)(using checkCtx) + check(loBound, hi, "lower", loBound)(using checkCtx) } def loop(args: List[Tree], boundss: List[TypeBounds]): Unit = args match diff --git a/compiler/src/dotty/tools/dotc/reporting/trace.scala b/compiler/src/dotty/tools/dotc/reporting/trace.scala index fbbc3d990969..732e779e9bf7 100644 --- a/compiler/src/dotty/tools/dotc/reporting/trace.scala +++ b/compiler/src/dotty/tools/dotc/reporting/trace.scala @@ -27,6 +27,18 @@ object trace extends TraceSyntax: object log extends TraceSyntax: inline def isEnabled: true = true protected val isForced = false + + def dumpStack(limit: Int = -1): Unit = { + val out = Console.out + val exc = new Exception("Dump Stack") + var stack = exc.getStackTrace + .filter(e => !e.getClassName.startsWith("dotty.tools.dotc.reporting.TraceSyntax")) + .filter(e => !e.getClassName.startsWith("dotty.tools.dotc.reporting.trace")) + if limit >= 0 then + stack = stack.take(limit) + exc.setStackTrace(stack) + exc.printStackTrace(out) + } end trace /** This module is carefully optimized to give zero overhead if Config.tracingEnabled