@@ -320,21 +320,13 @@ class SpaceEngine(using Context) extends SpaceLogic {
320320 private val scalaConsType = defn.ConsClass .typeRef
321321
322322 private val constantNullType = ConstantType (Constant (null ))
323- private val constantNullSpace = Typ (constantNullType)
324323
325324 /** Does the given tree stand for the literal `null`? */
326325 def isNullLit (tree : Tree ): Boolean = tree match {
327326 case Literal (Constant (null )) => true
328327 case _ => false
329328 }
330329
331- /** Does the given space contain just the value `null`? */
332- def isNullSpace (space : Space ): Boolean = space match {
333- case Typ (tpe, _) => tpe.dealias == constantNullType || tpe.isNullType
334- case Or (spaces) => spaces.forall(isNullSpace)
335- case _ => false
336- }
337-
338330 override def intersectUnrelatedAtomicTypes (tp1 : Type , tp2 : Type ): Space = trace(s " atomic intersection: ${AndType (tp1, tp2).show}" , debug) {
339331 // Precondition: !isSubType(tp1, tp2) && !isSubType(tp2, tp1).
340332 if (! ctx.explicitNulls && (tp1.isNullType || tp2.isNullType)) {
@@ -355,18 +347,18 @@ class SpaceEngine(using Context) extends SpaceLogic {
355347 def project (pat : Tree ): Space = pat match {
356348 case Literal (c) =>
357349 if (c.value.isInstanceOf [Symbol ])
358- Typ (c.value.asInstanceOf [Symbol ].termRef, false )
350+ Typ (c.value.asInstanceOf [Symbol ].termRef, decomposed = false )
359351 else
360- Typ (ConstantType (c), false )
352+ Typ (ConstantType (c), decomposed = false )
361353
362354 case pat : Ident if isBackquoted(pat) =>
363- Typ (pat.tpe, false )
355+ Typ (pat.tpe, decomposed = false )
364356
365357 case Ident (nme.WILDCARD ) =>
366- Or ( Typ (erase(pat.tpe.stripAnnots), false ) :: constantNullSpace :: Nil )
358+ Typ (erase(pat.tpe.stripAnnots, isValue = true ), decomposed = false )
367359
368360 case Ident (_) | Select (_, _) =>
369- Typ (erase(pat.tpe.stripAnnots), false )
361+ Typ (erase(pat.tpe.stripAnnots, isValue = true ), decomposed = false )
370362
371363 case Alternative (trees) =>
372364 Or (trees.map(project(_)))
@@ -386,31 +378,31 @@ class SpaceEngine(using Context) extends SpaceLogic {
386378 else {
387379 val (arity, elemTp, resultTp) = unapplySeqInfo(fun.tpe.widen.finalResultType, fun.srcPos)
388380 if (elemTp.exists)
389- Prod (erase(pat.tpe.stripAnnots), funRef, projectSeq(pats) :: Nil )
381+ Prod (erase(pat.tpe.stripAnnots, isValue = false ), funRef, projectSeq(pats) :: Nil )
390382 else
391- Prod (erase(pat.tpe.stripAnnots), funRef, pats.take(arity - 1 ).map(project) :+ projectSeq(pats.drop(arity - 1 )))
383+ Prod (erase(pat.tpe.stripAnnots, isValue = false ), funRef, pats.take(arity - 1 ).map(project) :+ projectSeq(pats.drop(arity - 1 )))
392384 }
393385 else
394- Prod (erase(pat.tpe.stripAnnots), funRef, pats.map(project))
386+ Prod (erase(pat.tpe.stripAnnots, isValue = false ), funRef, pats.map(project))
395387
396388 case Typed (pat @ UnApply (_, _, _), _) =>
397389 project(pat)
398390
399391 case Typed (_, tpt) =>
400- Typ (erase(tpt.tpe.stripAnnots), true )
392+ Typ (erase(tpt.tpe.stripAnnots, isValue = true ), decomposed = false )
401393
402394 case This (_) =>
403- Typ (pat.tpe.stripAnnots, false )
395+ Typ (pat.tpe.stripAnnots, decomposed = false )
404396
405397 case EmptyTree => // default rethrow clause of try/catch, check tests/patmat/try2.scala
406- Typ (WildcardType , false )
398+ Typ (WildcardType , decomposed = false )
407399
408400 case Block (Nil , expr) =>
409401 project(expr)
410402
411403 case _ =>
412404 // Pattern is an arbitrary expression; assume a skolem (i.e. an unknown value) of the pattern type
413- Typ (pat.tpe.narrow, false )
405+ Typ (pat.tpe.narrow, decomposed = false )
414406 }
415407
416408 private def project (tp : Type ): Space = tp match {
@@ -458,29 +450,37 @@ class SpaceEngine(using Context) extends SpaceLogic {
458450 * case (IntExpr(_), IntExpr(_)) =>
459451 * case (BooleanExpr(_), BooleanExpr(_)) =>
460452 * }
453+ *
454+ * @param inArray whether `tp` is a type argument to `Array`
455+ * @param isValue whether `tp` is the type which match against values
456+ *
457+ * If `isValue` is true, then pattern-bound symbols are erased to its upper bound.
458+ * This is needed to avoid spurious unreachable warnings. See tests/patmat/i6197.scala.
461459 */
462- private def erase (tp : Type , inArray : Boolean = false ): Type = trace(i " $tp erased to " , debug) {
460+ private def erase (tp : Type , inArray : Boolean = false , isValue : Boolean = false ): Type = trace(i " $tp erased to " , debug) {
463461
464462 tp match {
465463 case tp @ AppliedType (tycon, args) =>
466464 if tycon.typeSymbol.isPatternBound then return WildcardType
467465
468466 val args2 =
469- if (tycon.isRef(defn.ArrayClass )) args.map(arg => erase(arg, inArray = true ))
470- else args.map(arg => erase(arg, inArray = false ))
471- tp.derivedAppliedType(erase(tycon, inArray), args2)
467+ if (tycon.isRef(defn.ArrayClass )) args.map(arg => erase(arg, inArray = true , isValue = false ))
468+ else args.map(arg => erase(arg, inArray = false , isValue = false ))
469+ tp.derivedAppliedType(erase(tycon, inArray, isValue = false ), args2)
472470
473471 case tp @ OrType (tp1, tp2) =>
474- OrType (erase(tp1, inArray), erase(tp2, inArray), tp.isSoft)
472+ OrType (erase(tp1, inArray, isValue ), erase(tp2, inArray, isValue ), tp.isSoft)
475473
476474 case AndType (tp1, tp2) =>
477- AndType (erase(tp1, inArray), erase(tp2, inArray))
475+ AndType (erase(tp1, inArray, isValue ), erase(tp2, inArray, isValue ))
478476
479477 case tp @ RefinedType (parent, _, _) =>
480- erase(parent)
478+ erase(parent, inArray, isValue )
481479
482480 case tref : TypeRef if tref.symbol.isPatternBound =>
483- if (inArray) tref.underlying else WildcardType
481+ if inArray then tref.underlying
482+ else if isValue then tref.superType
483+ else WildcardType
484484
485485 case _ => tp
486486 }
@@ -864,25 +864,28 @@ class SpaceEngine(using Context) extends SpaceLogic {
864864 && ! sel.tpe.widen.isRef(defn.QuotedTypeClass )
865865
866866 def checkRedundancy (_match : Match ): Unit = {
867+ debug.println(s " ---------------checking redundant patterns ${_match.show}" )
868+
867869 val Match (sel, cases) = _match
868870 val selTyp = sel.tpe.widen.dealias
869871
870872 if (! redundancyCheckable(sel)) return
871873
872874 val targetSpace =
873- if (ctx.explicitNulls || selTyp.classSymbol.isPrimitiveValueClass)
875+ if ! selTyp.classSymbol.isNullableClass then
874876 project(selTyp)
875877 else
876878 project(OrType (selTyp, constantNullType, soft = false ))
877879
878880 // in redundancy check, take guard as false in order to soundly approximate
879- def projectPrevCases ( cases : List [ CaseDef ]) : List [ Space ] =
880- cases.map { x =>
881+ val spaces = cases.map { x =>
882+ val res =
881883 if (x.guard.isEmpty) project(x.pat)
882884 else Empty
883- }
884885
885- val spaces = projectPrevCases(cases)
886+ debug.println(s " ${x.pat.show} ====> ${res}" )
887+ res
888+ }
886889
887890 (1 until cases.length).foreach { i =>
888891 val pat = cases(i).pat
@@ -902,20 +905,13 @@ class SpaceEngine(using Context) extends SpaceLogic {
902905 if (covered == Empty && ! isNullLit(pat)) covered = curr
903906
904907 if (isSubspace(covered, prevs)) {
905- report.warning(MatchCaseUnreachable (), pat.srcPos)
906- }
907-
908- // if last case is `_` and only matches `null`, produce a warning
909- // If explicit nulls are enabled, this check isn't needed because most of the cases
910- // that would trigger it would also trigger unreachability warnings.
911- if (! ctx.explicitNulls && i == cases.length - 1 && ! isNullLit(pat) ) {
912- val spaces = flatten(simplify(minus(covered, prevs)))
913- if spaces.lengthCompare(10 ) < 0 then
914- dedup(spaces).toList match
915- case Typ (`constantNullType`, _) :: Nil =>
916- report.warning(MatchCaseOnlyNullWarning (), pat.srcPos)
917- case s =>
918- debug.println(" `_` matches = " + s)
908+ if i == cases.length - 1
909+ && isWildcardArg(pat)
910+ && pat.tpe.classSymbol.isNullableClass
911+ then
912+ report.warning(MatchCaseOnlyNullWarning (), pat.srcPos)
913+ else
914+ report.warning(MatchCaseUnreachable (), pat.srcPos)
919915 }
920916 }
921917 }
0 commit comments