@@ -17,13 +17,16 @@ import reporting.trace
17
17
/** Provides methods to compare types.
18
18
*/
19
19
class TypeComparer (initctx : Context ) extends DotClass with ConstraintHandling {
20
+ import TypeComparer .show
21
+
20
22
implicit val ctx = initctx
21
23
22
24
val state = ctx.typerState
23
25
import state .constraint
24
26
25
27
private [this ] var pendingSubTypes : mutable.Set [(Type , Type )] = null
26
28
private [this ] var recCount = 0
29
+ private [this ] var monitored = false
27
30
28
31
private [this ] var needsGc = false
29
32
@@ -101,9 +104,11 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
101
104
if (tp2 eq NoType ) return false
102
105
if ((tp2 eq tp1) || (tp2 eq WildcardType )) return true
103
106
try isSubType(tp1, tp2)
104
- finally
107
+ finally {
108
+ monitored = false
105
109
if (Config .checkConstraintsSatisfiable)
106
110
assert(isSatisfiable, constraint.show)
111
+ }
107
112
}
108
113
109
114
protected def isSubType (tp1 : Type , tp2 : Type ): Boolean = trace(s " isSubType ${traceInfo(tp1, tp2)}" , subtyping) {
@@ -114,9 +119,8 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
114
119
val savedSuccessCount = successCount
115
120
try {
116
121
recCount = recCount + 1
117
- val result =
118
- if (recCount < Config .LogPendingSubTypesThreshold ) firstTry(tp1, tp2)
119
- else monitoredIsSubType(tp1, tp2)
122
+ if (recCount >= Config .LogPendingSubTypesThreshold ) monitored = true
123
+ val result = if (monitored) monitoredIsSubType(tp1, tp2) else firstTry(tp1, tp2)
120
124
recCount = recCount - 1
121
125
if (! result) state.resetConstraintTo(saved)
122
126
else if (recCount == 0 && needsGc) {
@@ -300,6 +304,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
300
304
if (isSubType(info1.alias, tp2)) return true
301
305
if (tp1.prefix.isStable) return false
302
306
case _ =>
307
+ if (tp1 eq NothingType ) return tp1 == tp2.bottomType
303
308
}
304
309
thirdTry(tp1, tp2)
305
310
case tp1 : TypeParamRef =>
@@ -1577,7 +1582,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
1577
1582
1578
1583
/** Show subtype goal that led to an assertion failure */
1579
1584
def showGoal (tp1 : Type , tp2 : Type )(implicit ctx : Context ) = {
1580
- println(i " assertion failure for $tp1 <:< $tp2, frozen = $frozenConstraint" )
1585
+ println(i " assertion failure for ${show( tp1)} <:< ${show( tp2)} , frozen = $frozenConstraint" )
1581
1586
def explainPoly (tp : Type ) = tp match {
1582
1587
case tp : TypeParamRef => ctx.echo(s " TypeParamRef ${tp.show} found in ${tp.binder.show}" )
1583
1588
case tp : TypeRef if tp.symbol.exists => ctx.echo(s " typeref ${tp.show} found in ${tp.symbol.owner.show}" )
@@ -1609,6 +1614,11 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
1609
1614
1610
1615
object TypeComparer {
1611
1616
1617
+ private [core] def show (res : Any )(implicit ctx : Context ) = res match {
1618
+ case res : printing.Showable if ! ctx.settings.YexplainLowlevel .value => res.show
1619
+ case _ => String .valueOf(res)
1620
+ }
1621
+
1612
1622
/** Show trace of comparison operations when performing `op` as result string */
1613
1623
def explained [T ](op : Context => T )(implicit ctx : Context ): String = {
1614
1624
val nestedCtx = ctx.fresh.setTypeComparerFn(new ExplainingTypeComparer (_))
@@ -1619,6 +1629,8 @@ object TypeComparer {
1619
1629
1620
1630
/** A type comparer that can record traces of subtype operations */
1621
1631
class ExplainingTypeComparer (initctx : Context ) extends TypeComparer (initctx) {
1632
+ import TypeComparer .show
1633
+
1622
1634
private [this ] var indent = 0
1623
1635
private val b = new StringBuilder
1624
1636
@@ -1635,11 +1647,6 @@ class ExplainingTypeComparer(initctx: Context) extends TypeComparer(initctx) {
1635
1647
res
1636
1648
}
1637
1649
1638
- private def show (res : Any ) = res match {
1639
- case res : printing.Showable if ! ctx.settings.YexplainLowlevel .value => res.show
1640
- case _ => String .valueOf(res)
1641
- }
1642
-
1643
1650
override def isSubType (tp1 : Type , tp2 : Type ) =
1644
1651
traceIndented(s " ${show(tp1)} <:< ${show(tp2)}${if (Config .verboseExplainSubtype) s " ${tp1.getClass} ${tp2.getClass}" else " " }${if (frozenConstraint) " frozen" else " " }" ) {
1645
1652
super .isSubType(tp1, tp2)
0 commit comments