Skip to content

Commit

Permalink
Fix the List rewrite in patmat to use 2.13's UnapplySeqWrapper
Browse files Browse the repository at this point in the history
I didn't double-check, but what I expect happened is that all the
pattern matches that included a "case List()" stopped producing any
exhaustivity/unreachable warnings.  And then my guess is the impact
wasn't understood and the checkfiles were just updated?

In the next commit strict pattern matching becomes the default, which,
when bootstrapping, found a pattern match in the compiler that uses
"case List()" (with -Werror enabled).
  • Loading branch information
dwijnand committed Oct 8, 2020
1 parent 03574d8 commit df6b7f2
Show file tree
Hide file tree
Showing 5 changed files with 18 additions and 1 deletion.
Expand Up @@ -372,10 +372,11 @@ trait MatchApproximation extends TreeAndTypeAnalysis with ScalaLogic with MatchT
}

// special-case: interpret pattern `List()` as `Nil`
// as of 2.13, List.unapply returns an UnapplySeqWrapper (rather than a List)
// TODO: make it more general List(1, 2) => 1 :: 2 :: Nil -- not sure this is a good idea...
private val rewriteListPattern: PartialFunction[TreeMaker, Prop] = {
case p @ ExtractorTreeMaker(_, _, testedBinder)
if testedBinder.tpe.typeSymbol == ListClass && p.checkedLength == Some(0) =>
if testedBinder.tpe.typeSymbol == UnapplySeqWrapperClass && p.checkedLength == Some(0) =>
uniqueEqualityProp(binderToUniqueTree(p.prevBinder), unique(Ident(NilModule) setType NilModule.tpe))
}
val fullRewrite = (irrefutableExtractor orElse rewriteListPattern)
Expand Down
3 changes: 3 additions & 0 deletions src/reflect/scala/reflect/internal/Definitions.scala
Expand Up @@ -477,6 +477,9 @@ trait Definitions extends api.StandardDefinitions {
def List_cons = getMemberMethod(ListClass, nme.CONS)
@migration("SeqClass now refers to scala.collection.immutable.Seq", "2.13.0")
lazy val SeqClass = requiredClass[scala.collection.immutable.Seq[_]]
lazy val SeqFactoryClass = requiredModule[scala.collection.SeqFactory.type]
lazy val UnapplySeqWrapperClass = getTypeMember(SeqFactoryClass, tpnme.UnapplySeqWrapper)

lazy val JavaStringBuilderClass = requiredClass[java.lang.StringBuilder]
lazy val JavaStringBufferClass = requiredClass[java.lang.StringBuffer]
lazy val JavaCharSequenceClass = requiredClass[java.lang.CharSequence]
Expand Down
1 change: 1 addition & 0 deletions src/reflect/scala/reflect/internal/StdNames.scala
Expand Up @@ -284,6 +284,7 @@ trait StdNames {
final val TypeDef: NameType = nameType("TypeDef")
final val Quasiquote: NameType = nameType("Quasiquote")
final val macroImplLocation: NameType = nameType("macroImplLocation")
final val UnapplySeqWrapper: NameType = nameType("UnapplySeqWrapper")

// async
final val stateMachine: NameType = nameType("stateMachine$async")
Expand Down
2 changes: 2 additions & 0 deletions src/reflect/scala/reflect/runtime/JavaUniverseForce.scala
Expand Up @@ -297,6 +297,8 @@ trait JavaUniverseForce { self: runtime.JavaUniverse =>
definitions.IterableClass
definitions.ListClass
definitions.SeqClass
definitions.SeqFactoryClass
definitions.UnapplySeqWrapperClass
definitions.JavaStringBuilderClass
definitions.JavaStringBufferClass
definitions.JavaCharSequenceClass
Expand Down
10 changes: 10 additions & 0 deletions test/files/pos/patmat_list_rewrite.scala
@@ -0,0 +1,10 @@
// scalac: -Werror -Xstrict-patmat-analysis
//
class C {
def m(xs: List[String]) = xs match {
case List() => "z"
case y :: _ => y
}
// was: patmat_list_rewrite.scala:4: warning: match may not be exhaustive.
// It would fail on the following input: Nil
}

0 comments on commit df6b7f2

Please sign in to comment.