@@ -65,6 +65,8 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
65
65
66
66
private var useNecessaryEither = false
67
67
68
+ private var ignoreNulls = false
69
+
68
70
/** Is a subtype check in progress? In that case we may not
69
71
* permanently instantiate type variables, because the corresponding
70
72
* constraint might still be retracted and the instantiation should
@@ -133,12 +135,24 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
133
135
}
134
136
}
135
137
138
+ def topLevelSubTypeIgnoringNulls (tp1 : Type , tp2 : Type ): Boolean =
139
+ val saved = ignoreNulls
140
+ ignoreNulls = true
141
+ try topLevelSubType(tp1, tp2)
142
+ finally ignoreNulls = saved
143
+
136
144
def necessarySubType (tp1 : Type , tp2 : Type ): Boolean =
137
145
val saved = useNecessaryEither
138
146
useNecessaryEither = true
139
147
try topLevelSubType(tp1, tp2)
140
148
finally useNecessaryEither = saved
141
149
150
+ def necessarySubTypeIgnoringNulls (tp1 : Type , tp2 : Type ): Boolean =
151
+ val saved = useNecessaryEither
152
+ useNecessaryEither = true
153
+ try topLevelSubTypeIgnoringNulls(tp1, tp2)
154
+ finally useNecessaryEither = saved
155
+
142
156
def testSubType (tp1 : Type , tp2 : Type ): CompareResult =
143
157
GADTused = false
144
158
if ! topLevelSubType(tp1, tp2) then CompareResult .Fail
@@ -333,7 +347,11 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
333
347
case AndType (tp21, tp22) =>
334
348
recur(tp1, tp21) && recur(tp1, tp22)
335
349
case OrType (tp21, tp22) =>
336
- if (tp21.stripTypeVar eq tp22.stripTypeVar) recur(tp1, tp21)
350
+ if ignoreNulls && tp22.isNullType then
351
+ tp1.isNullType || recur(tp1, tp21)
352
+ else if ignoreNulls && tp21.isNullType then
353
+ tp1.isNullType || recur(tp1, tp22)
354
+ else if tp21.stripTypeVar eq tp22.stripTypeVar then recur(tp1, tp21)
337
355
else secondTry
338
356
case TypeErasure .ErasedValueType (tycon1, underlying2) =>
339
357
def compareErasedValueType = tp1 match {
@@ -463,10 +481,12 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
463
481
case OrType (tp1, tp2) => containsAnd(tp1) || containsAnd(tp2)
464
482
case _ => false
465
483
466
- widenOK
467
- || joinOK
468
- || (tp1.isSoft || constrainRHSVars(tp2)) && recur(tp11, tp2) && recur(tp12, tp2)
469
- || containsAnd(tp1) && recur(tp1.join, tp2)
484
+ if ignoreNulls && tp12.isNullType then recur(tp11, tp2)
485
+ else if ignoreNulls && tp11.isNullType then recur(tp12, tp2)
486
+ else widenOK
487
+ || joinOK
488
+ || (tp1.isSoft || constrainRHSVars(tp2)) && recur(tp11, tp2) && recur(tp12, tp2)
489
+ || containsAnd(tp1) && recur(tp1.join, tp2)
470
490
case tp1 : MatchType =>
471
491
val reduced = tp1.reduced
472
492
if (reduced.exists) recur(reduced, tp2) else thirdTry
@@ -632,6 +652,10 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
632
652
case Some (b) => return b
633
653
case _ =>
634
654
655
+ if ignoreNulls then
656
+ if tp22.isNullType then return recur(tp1, tp21)
657
+ if tp21.isNullType then return recur(tp1, tp22)
658
+
635
659
// The next clause handles a situation like the one encountered in i2745.scala.
636
660
// We have:
637
661
//
@@ -754,7 +778,9 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
754
778
isSubType(hi1, tp2, approx.addLow) || compareGADT || tryLiftedToThis1
755
779
case _ =>
756
780
def isNullable (tp : Type ): Boolean = tp.widenDealias match {
757
- case tp : TypeRef => tp.symbol.isNullableClass
781
+ case tp : TypeRef =>
782
+ if ignoreNulls then tp.symbol.isNullableClassAfterErasure
783
+ else tp.symbol.isNullableClass
758
784
case tp : RefinedOrRecType => isNullable(tp.parent)
759
785
case tp : AppliedType => isNullable(tp.tycon)
760
786
case AndType (tp1, tp2) => isNullable(tp1) && isNullable(tp2)
@@ -2550,9 +2576,15 @@ object TypeComparer {
2550
2576
def topLevelSubType (tp1 : Type , tp2 : Type )(using Context ): Boolean =
2551
2577
comparing(_.topLevelSubType(tp1, tp2))
2552
2578
2579
+ def topLevelSubTypeIgnoringNulls (tp1 : Type , tp2 : Type )(using Context ): Boolean =
2580
+ comparing(_.topLevelSubTypeIgnoringNulls(tp1, tp2))
2581
+
2553
2582
def necessarySubType (tp1 : Type , tp2 : Type )(using Context ): Boolean =
2554
2583
comparing(_.necessarySubType(tp1, tp2))
2555
2584
2585
+ def necessarySubTypeIgnoringNulls (tp1 : Type , tp2 : Type )(using Context ): Boolean =
2586
+ comparing(_.necessarySubTypeIgnoringNulls(tp1, tp2))
2587
+
2556
2588
def isSubType (tp1 : Type , tp2 : Type )(using Context ): Boolean =
2557
2589
comparing(_.isSubType(tp1, tp2))
2558
2590
0 commit comments