@@ -512,23 +512,28 @@ class SpaceEngine(using Context) extends SpaceLogic {
512512 if converted == null then tp else ConstantType (converted)
513513 case _ => tp
514514
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+ }
520532
521533 /** 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
532537 }
533538
534539 def isSameUnapply (tp1 : TermRef , tp2 : TermRef ): Boolean =
@@ -911,7 +916,8 @@ class SpaceEngine(using Context) extends SpaceLogic {
911916 && ! sel.tpe.widen.isRef(defn.QuotedTypeClass )
912917
913918 def checkRedundancy (_match : Match ): Unit = {
914- val Match (sel, cases) = _match
919+ val Match (sel, _) = _match
920+ val cases = _match.cases.toIndexedSeq
915921 debug.println(i " checking redundancy in $_match" )
916922
917923 if (! redundancyCheckable(sel)) return
@@ -925,7 +931,14 @@ class SpaceEngine(using Context) extends SpaceLogic {
925931 else project(selTyp)
926932 debug.println(s " targetSpace: ${show(targetSpace)}" )
927933
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+
929942 debug.println(i " case pattern: $pat" )
930943
931944 val curr = project(pat)
@@ -937,18 +950,24 @@ class SpaceEngine(using Context) extends SpaceLogic {
937950 val covered = simplify(intersect(curr, targetSpace))
938951 debug.println(s " covered: ${show(covered)}" )
939952
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)
947957 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
948966 }
949967
950968 // 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
952971 }
953972 }
954973}
0 commit comments