@@ -63,7 +63,7 @@ case object Empty extends Space
6363 * @param decomposed: does the space result from decomposition? Used for pretty print
6464 *
6565 */
66- case class Typ (tp : Type , decomposed : Boolean ) extends Space
66+ case class Typ (tp : Type , decomposed : Boolean = true ) extends Space
6767
6868/** Space representing an extractor pattern */
6969case class Prod (tp : Type , unappTp : Type , unappSym : Symbol , params : List [Space ], full : Boolean ) extends Space
@@ -315,6 +315,8 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
315315 else
316316 Typ (ConstantType (c), false )
317317 case _ : BackquotedIdent => Typ (pat.tpe, false )
318+ case Ident (nme.WILDCARD ) =>
319+ Or (Typ (pat.tpe.stripAnnots, false ) :: Typ (ConstantType (Constant (null ))) :: Nil )
318320 case Ident (_) | Select (_, _) =>
319321 Typ (pat.tpe.stripAnnots, false )
320322 case Alternative (trees) => Or (trees.map(project(_)))
@@ -374,7 +376,7 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
374376
375377 /** Is `tp1` a subtype of `tp2`? */
376378 def isSubType (tp1 : Type , tp2 : Type ): Boolean = {
377- val res = tp1 <:< tp2
379+ val res = tp1 <:< tp2 && (tp1 != ConstantType ( Constant ( null )) || tp2 == ConstantType ( Constant ( null )))
378380 debug.println(s " ${tp1.show} <:< ${tp2.show} = $res" )
379381 res
380382 }
@@ -547,13 +549,6 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
547549 case tp => tp.isSingleton
548550 }
549551
550- def superType (tp : Type ): Type = tp match {
551- case tp : TypeProxy => tp.superType
552- case OrType (tp1, tp2) => OrType (superType(tp1), superType(tp2))
553- case AndType (tp1, tp2) => AndType (superType(tp1), superType(tp2))
554- case _ => tp
555- }
556-
557552 def recur (tp : Type ): Boolean = tp.dealias match {
558553 case AndType (tp1, tp2) =>
559554 recur(tp1) && recur(tp2) && {
@@ -574,8 +569,8 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
574569 noClassConflict &&
575570 (! isSingleton(tp1) || tp1 <:< tp2) &&
576571 (! isSingleton(tp2) || tp2 <:< tp1) &&
577- (! bases1.exists(_ is Final ) || tp1 <:< superType( tp2) ) &&
578- (! bases2.exists(_ is Final ) || tp2 <:< superType( tp1) )
572+ (! bases1.exists(_ is Final ) || tp1 <:< tp2) &&
573+ (! bases2.exists(_ is Final ) || tp2 <:< tp1)
579574 }
580575 case OrType (tp1, tp2) =>
581576 recur(tp1) || recur(tp2)
@@ -894,8 +889,9 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
894889 val checkGADTSAT = shouldCheckExamples(selTyp)
895890
896891 val uncovered =
897- flatten(simplify(minus(Typ (selTyp, true ), patternSpace), aggressive = true ))
898- .filter(s => s != Empty && (! checkGADTSAT || satisfiable(s)))
892+ flatten(simplify(minus(Typ (selTyp, true ), patternSpace), aggressive = true )).filter { s =>
893+ s != Empty && (! checkGADTSAT || satisfiable(s))
894+ }
899895
900896 if (uncovered.nonEmpty)
901897 ctx.warning(PatternMatchExhaustivity (show(Or (uncovered))), sel.pos)
@@ -908,6 +904,12 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
908904 val Match (sel, cases) = _match
909905 val selTyp = sel.tpe.widen.dealias
910906
907+ def targetSpace : Space =
908+ if (selTyp.classSymbol.isPrimitiveValueClass)
909+ Typ (selTyp, true )
910+ else
911+ Or (Typ (selTyp, true ) :: Typ (ConstantType (Constant (null ))) :: Nil )
912+
911913 if (! redundancyCheckable(sel)) return
912914
913915 (0 until cases.length).foreach { i =>
@@ -921,13 +923,20 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
921923 else Empty
922924 }.reduce((a, b) => Or (List (a, b)))
923925
924- if (cases(i).pat != EmptyTree ) { // rethrow case of catch
926+ if (cases(i).pat != EmptyTree ) { // rethrow case of catch uses EmptyTree
925927 val curr = project(cases(i).pat)
926928
927929 debug.println(s " ---------------reachable? ${show(curr)}" )
928930 debug.println(s " prev: ${show(prevs)}" )
929931
930- if (isSubspace(intersect(curr, Typ (selTyp, false )), prevs)) {
932+ var covered = simplify(intersect(curr, targetSpace))
933+ debug.println(s " covered: $covered" )
934+
935+ // `covered == Empty` may happen for primitive types with auto-conversion
936+ // see tests/patmat/reader.scala tests/patmat/byte.scala
937+ if (covered == Empty ) covered = curr
938+
939+ if (isSubspace(covered, prevs)) {
931940 ctx.warning(MatchCaseUnreachable (), cases(i).body.pos)
932941 }
933942 }
0 commit comments