@@ -512,23 +512,28 @@ class SpaceEngine(using Context) extends SpaceLogic {
512
512
if converted == null then tp else ConstantType (converted)
513
513
case _ => tp
514
514
515
- /** Adapt types by performing primitive value boxing. #12805 */
516
- def maybeBox (tp1 : Type , tp2 : Type ): Type =
517
- if tp1.classSymbol.isPrimitiveValueClass && ! tp2.classSymbol.isPrimitiveValueClass then
518
- defn.boxedType(tp1).narrow
519
- else tp1
515
+ def isPrimToBox (tp : Type , pt : Type ) =
516
+ tp.classSymbol.isPrimitiveValueClass && (defn.boxedType(tp).classSymbol eq pt.classSymbol)
517
+
518
+ /** Adapt types by performing primitive value unboxing or boxing, or numeric constant conversion. #12805
519
+ *
520
+ * This makes these isSubType cases work like this:
521
+ * {{{
522
+ * 1 <:< Integer => (<skolem> : Integer) <:< Integer = true
523
+ * ONE <:< Int => (<skolem> : Int) <:< Int = true
524
+ * Integer <:< (1: Int) => (<skolem> : Int) <:< (1: Int) = false
525
+ * }}}
526
+ */
527
+ def adaptType (tp1 : Type , tp2 : Type ): Type = trace(i " adaptType( $tp1, $tp2) " , show = true ) {
528
+ if isPrimToBox(tp1, tp2) then defn.boxedType(tp1).narrow
529
+ else if isPrimToBox(tp2, tp1) then defn.unboxedType(tp1).narrow
530
+ else convertConstantType(tp1, tp2)
531
+ }
520
532
521
533
/** Is `tp1` a subtype of `tp2`? */
522
- def isSubType (_tp1 : Type , tp2 : Type ): Boolean = {
523
- val tp1 = maybeBox(convertConstantType(_tp1, tp2), tp2)
524
- // debug.println(TypeComparer.explained(_.isSubType(tp1, tp2)))
525
- val res = if (ctx.explicitNulls) {
526
- tp1 <:< tp2
527
- } else {
528
- (tp1 != constantNullType || tp2 == constantNullType) && tp1 <:< tp2
529
- }
530
- debug.println(i " $tp1 <:< $tp2 = $res" )
531
- res
534
+ def isSubType (tp1 : Type , tp2 : Type ): Boolean = trace(i " $tp1 <:< $tp2" , debug, show = true ) {
535
+ if tp1 == constantNullType && ! ctx.explicitNulls then tp2 == constantNullType
536
+ else adaptType(tp1, tp2) <:< tp2
532
537
}
533
538
534
539
def isSameUnapply (tp1 : TermRef , tp2 : TermRef ): Boolean =
@@ -911,7 +916,8 @@ class SpaceEngine(using Context) extends SpaceLogic {
911
916
&& ! sel.tpe.widen.isRef(defn.QuotedTypeClass )
912
917
913
918
def checkRedundancy (_match : Match ): Unit = {
914
- val Match (sel, cases) = _match
919
+ val Match (sel, _) = _match
920
+ val cases = _match.cases.toIndexedSeq
915
921
debug.println(i " checking redundancy in $_match" )
916
922
917
923
if (! redundancyCheckable(sel)) return
@@ -925,7 +931,14 @@ class SpaceEngine(using Context) extends SpaceLogic {
925
931
else project(selTyp)
926
932
debug.println(s " targetSpace: ${show(targetSpace)}" )
927
933
928
- cases.iterator.zipWithIndex.foldLeft(Nil : List [Space ]) { case (prevs, (CaseDef (pat, guard, _), i)) =>
934
+ var i = 0
935
+ val len = cases.length
936
+ var prevs = List .empty[Space ]
937
+ var deferred = List .empty[Tree ]
938
+
939
+ while (i < len) {
940
+ val CaseDef (pat, guard, _) = cases(i)
941
+
929
942
debug.println(i " case pattern: $pat" )
930
943
931
944
val curr = project(pat)
@@ -937,18 +950,24 @@ class SpaceEngine(using Context) extends SpaceLogic {
937
950
val covered = simplify(intersect(curr, targetSpace))
938
951
debug.println(s " covered: ${show(covered)}" )
939
952
940
- if pat != EmptyTree // rethrow case of catch uses EmptyTree
941
- && prev != Empty // avoid isSubspace(Empty, Empty) - one of the previous cases much be reachable
942
- && isSubspace(covered, prev)
943
- then {
944
- if isNullable && i == cases.length - 1 && isWildcardArg(pat) then
945
- report.warning(MatchCaseOnlyNullWarning (), pat.srcPos)
946
- else
953
+ if prev == Empty && covered == Empty then // defer until a case is reachable
954
+ deferred ::= pat
955
+ else {
956
+ for (pat <- deferred.reverseIterator)
947
957
report.warning(MatchCaseUnreachable (), pat.srcPos)
958
+ if pat != EmptyTree // rethrow case of catch uses EmptyTree
959
+ && isSubspace(covered, prev)
960
+ then {
961
+ val nullOnly = isNullable && i == len - 1 && isWildcardArg(pat)
962
+ val msg = if nullOnly then MatchCaseOnlyNullWarning () else MatchCaseUnreachable ()
963
+ report.warning(msg, pat.srcPos)
964
+ }
965
+ deferred = Nil
948
966
}
949
967
950
968
// in redundancy check, take guard as false in order to soundly approximate
951
- (if guard.isEmpty then covered else Empty ) :: prevs
969
+ prevs ::= (if guard.isEmpty then covered else Empty )
970
+ i += 1
952
971
}
953
972
}
954
973
}
0 commit comments