@@ -246,7 +246,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
246246 // }
247247 assert(! ctx.settings.YnoDeepSubtypes .value)
248248 if (Config .traceDeepSubTypeRecursions && ! this .isInstanceOf [ExplainingTypeComparer ])
249- report.log(explained(_.isSubType(tp1, tp2, approx)))
249+ report.log(explained(_.isSubType(tp1, tp2, approx), short = false ))
250250 }
251251 // Eliminate LazyRefs before checking whether we have seen a type before
252252 val normalize = new TypeMap {
@@ -2868,7 +2868,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
28682868 }
28692869 }
28702870
2871- protected def explainingTypeComparer = ExplainingTypeComparer (comparerContext)
2871+ protected def explainingTypeComparer ( short : Boolean ) = ExplainingTypeComparer (comparerContext, short )
28722872 protected def trackingTypeComparer = TrackingTypeComparer (comparerContext)
28732873
28742874 private def inSubComparer [T , Cmp <: TypeComparer ](comparer : Cmp )(op : Cmp => T ): T =
@@ -2878,8 +2878,8 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
28782878 finally myInstance = saved
28792879
28802880 /** The trace of comparison operations when performing `op` */
2881- def explained [T ](op : ExplainingTypeComparer => T , header : String = " Subtype trace:" )(using Context ): String =
2882- val cmp = explainingTypeComparer
2881+ def explained [T ](op : ExplainingTypeComparer => T , header : String = " Subtype trace:" , short : Boolean )(using Context ): String =
2882+ val cmp = explainingTypeComparer(short)
28832883 inSubComparer(cmp)(op)
28842884 cmp.lastTrace(header)
28852885
@@ -3038,8 +3038,8 @@ object TypeComparer {
30383038 def constrainPatternType (pat : Type , scrut : Type , forceInvariantRefinement : Boolean = false )(using Context ): Boolean =
30393039 comparing(_.constrainPatternType(pat, scrut, forceInvariantRefinement))
30403040
3041- def explained [T ](op : ExplainingTypeComparer => T , header : String = " Subtype trace:" )(using Context ): String =
3042- comparing(_.explained(op, header))
3041+ def explained [T ](op : ExplainingTypeComparer => T , header : String = " Subtype trace:" , short : Boolean = false )(using Context ): String =
3042+ comparing(_.explained(op, header, short ))
30433043
30443044 def tracked [T ](op : TrackingTypeComparer => T )(using Context ): T =
30453045 comparing(_.tracked(op))
@@ -3207,30 +3207,47 @@ class TrackingTypeComparer(initctx: Context) extends TypeComparer(initctx) {
32073207 }
32083208}
32093209
3210- /** A type comparer that can record traces of subtype operations */
3211- class ExplainingTypeComparer (initctx : Context ) extends TypeComparer (initctx) {
3210+ /** A type comparer that can record traces of subtype operations
3211+ * @param short if true print only failing forward traces; never print succesful
3212+ * subtraces; never print backtraces starting with `<==`.
3213+ */
3214+ class ExplainingTypeComparer (initctx : Context , short : Boolean ) extends TypeComparer (initctx) {
32123215 import TypeComparer ._
32133216
32143217 init(initctx)
32153218
3216- override def explainingTypeComparer = this
3219+ override def explainingTypeComparer (short : Boolean ) =
3220+ if short == this .short then this
3221+ else ExplainingTypeComparer (comparerContext, short)
32173222
32183223 private var indent = 0
32193224 private val b = new StringBuilder
3220-
3221- private var skipped = false
3225+ private var lastForwardGoal : String | Null = null
32223226
32233227 override def traceIndented [T ](str : String )(op : => T ): T =
3224- if (skipped) op
3225- else {
3228+ val str1 = str.replace('\n ' , ' ' )
3229+ if short && str1 == lastForwardGoal then
3230+ op // repeated goal, skip for clarity
3231+ else
3232+ lastForwardGoal = str1
3233+ val curLength = b.length
32263234 indent += 2
3227- val str1 = str.replace('\n ' , ' ' )
32283235 b.append(" \n " ).append(" " * indent).append(" ==> " ).append(str1)
32293236 val res = op
3230- b.append(" \n " ).append(" " * indent).append(" <== " ).append(str1).append(" = " ).append(show(res))
3237+ if short then
3238+ if res == false then
3239+ if lastForwardGoal != null then // last was deepest goal that failed
3240+ b.append(" = false" )
3241+ lastForwardGoal = null
3242+ else
3243+ b.length = curLength // don't show successful subtraces
3244+ else
3245+ b.append(" \n " ).append(" " * indent).append(" <== " ).append(str1).append(" = " ).append(show(res))
32313246 indent -= 2
32323247 res
3233- }
3248+
3249+ private def traceIndentedIfNotShort [T ](str : String )(op : => T ): T =
3250+ if short then op else traceIndented(str)(op)
32343251
32353252 private def frozenNotice : String =
32363253 if frozenConstraint then " in frozen constraint" else " "
@@ -3241,7 +3258,8 @@ class ExplainingTypeComparer(initctx: Context) extends TypeComparer(initctx) {
32413258 then s " ${tp1.getClass} ${tp2.getClass}"
32423259 else " "
32433260 val approx = approxState
3244- traceIndented(s " ${show(tp1)} <: ${show(tp2)}$moreInfo${approx.show}$frozenNotice" ) {
3261+ def approxStr = if short then " " else approx.show
3262+ traceIndented(s " ${show(tp1)} <: ${show(tp2)}$moreInfo${approxStr}$frozenNotice" ) {
32453263 super .recur(tp1, tp2)
32463264 }
32473265
@@ -3251,12 +3269,12 @@ class ExplainingTypeComparer(initctx: Context) extends TypeComparer(initctx) {
32513269 }
32523270
32533271 override def lub (tp1 : Type , tp2 : Type , canConstrain : Boolean , isSoft : Boolean ): Type =
3254- traceIndented (s " lub( ${show(tp1)}, ${show(tp2)}, canConstrain= $canConstrain, isSoft= $isSoft) " ) {
3272+ traceIndentedIfNotShort (s " lub( ${show(tp1)}, ${show(tp2)}, canConstrain= $canConstrain, isSoft= $isSoft) " ) {
32553273 super .lub(tp1, tp2, canConstrain, isSoft)
32563274 }
32573275
32583276 override def glb (tp1 : Type , tp2 : Type ): Type =
3259- traceIndented (s " glb( ${show(tp1)}, ${show(tp2)}) " ) {
3277+ traceIndentedIfNotShort (s " glb( ${show(tp1)}, ${show(tp2)}) " ) {
32603278 super .glb(tp1, tp2)
32613279 }
32623280
0 commit comments