@@ -130,20 +130,30 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] {
130
130
}
131
131
}
132
132
133
- private [this ] var approx : ApproxState = NoApprox
133
+ private [this ] var approx : ApproxState = FreshApprox
134
134
protected def approxState : ApproxState = approx
135
135
136
+ private [this ] var leftRoot : Type = null
137
+
136
138
protected def isSubType (tp1 : Type , tp2 : Type , a : ApproxState ): Boolean = {
137
- val saved = approx
138
- this .approx = a
139
+ val savedApprox = approx
140
+ val savedLeftRoot = leftRoot
141
+ if (a == FreshApprox ) {
142
+ this .approx = NoApprox
143
+ this .leftRoot = tp1
144
+ }
145
+ else this .approx = a
139
146
try recur(tp1, tp2)
140
147
catch {
141
148
case ex : Throwable => handleRecursive(" subtype" , i " $tp1 <:< $tp2" , ex, weight = 2 )
142
149
}
143
- finally this .approx = saved
150
+ finally {
151
+ this .approx = savedApprox
152
+ this .leftRoot = savedLeftRoot
153
+ }
144
154
}
145
155
146
- def isSubType (tp1 : Type , tp2 : Type )(implicit nc : AbsentContext ): Boolean = isSubType(tp1, tp2, NoApprox )
156
+ def isSubType (tp1 : Type , tp2 : Type )(implicit nc : AbsentContext ): Boolean = isSubType(tp1, tp2, FreshApprox )
147
157
148
158
protected def recur (tp1 : Type , tp2 : Type ): Boolean = trace(s " isSubType ${traceInfo(tp1, tp2)} $approx" , subtyping) {
149
159
@@ -277,7 +287,7 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] {
277
287
case tp2 : SuperType =>
278
288
def compareSuper = tp1 match {
279
289
case tp1 : SuperType =>
280
- isSubType (tp1.thistpe, tp2.thistpe) &&
290
+ recur (tp1.thistpe, tp2.thistpe) &&
281
291
isSameType(tp1.supertpe, tp2.supertpe)
282
292
case _ =>
283
293
secondTry
@@ -355,7 +365,7 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] {
355
365
}
356
366
case tp1 : SkolemType =>
357
367
tp2 match {
358
- case tp2 : SkolemType if ! ctx.phase.isTyper && isSubType (tp1.info, tp2.info) => true
368
+ case tp2 : SkolemType if ! ctx.phase.isTyper && recur (tp1.info, tp2.info) => true
359
369
case _ => thirdTry
360
370
}
361
371
case tp1 : TypeVar =>
@@ -449,7 +459,7 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] {
449
459
// So if the constraint is not yet frozen, we do the same comparison again
450
460
// with a frozen constraint, which means that we get a chance to do the
451
461
// widening in `fourthTry` before adding to the constraint.
452
- if (frozenConstraint) isSubType (tp1, bounds(tp2).lo)
462
+ if (frozenConstraint) recur (tp1, bounds(tp2).lo)
453
463
else isSubTypeWhenFrozen(tp1, tp2)
454
464
alwaysTrue || {
455
465
if (canConstrain(tp2) && ! approx.low)
@@ -879,7 +889,7 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] {
879
889
compareLower(info2, tyconIsTypeRef = true )
880
890
case info2 : ClassInfo =>
881
891
tycon2.name.toString.startsWith(" Tuple" ) &&
882
- defn.isTupleType(tp2) && isSubType (tp1, tp2.toNestedPairs) ||
892
+ defn.isTupleType(tp2) && recur (tp1, tp2.toNestedPairs) ||
883
893
tryBaseType(info2.cls)
884
894
case _ =>
885
895
fourthTry
@@ -1029,7 +1039,14 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] {
1029
1039
arg2.contains(arg1norm)
1030
1040
case _ =>
1031
1041
arg1 match {
1032
- case arg1 : TypeBounds => false
1042
+ case arg1 : TypeBounds =>
1043
+ tparam match {
1044
+ case tparam : Symbol if leftRoot.isStable =>
1045
+ val captured = TypeRef (leftRoot, tparam)
1046
+ isSubArg(captured, arg2)
1047
+ case _ =>
1048
+ false
1049
+ }
1033
1050
case _ =>
1034
1051
(v > 0 || isSubType(arg2, arg1)) &&
1035
1052
(v < 0 || isSubType(arg1, arg2))
@@ -1809,6 +1826,8 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] {
1809
1826
1810
1827
object TypeComparer {
1811
1828
1829
+ val oldScheme = true
1830
+
1812
1831
/** Class for unification variables used in `natValue`. */
1813
1832
private class AnyConstantType extends UncachedGroundType with ValueType {
1814
1833
var tpe : Type = NoType
@@ -1835,6 +1854,7 @@ object TypeComparer {
1835
1854
}
1836
1855
1837
1856
val NoApprox : ApproxState = new ApproxState (0 )
1857
+ val FreshApprox : ApproxState = new ApproxState (4 )
1838
1858
1839
1859
/** Show trace of comparison operations when performing `op` as result string */
1840
1860
def explaining [T ](say : String => Unit )(op : Context => T )(implicit ctx : Context ): T = {
0 commit comments