Skip to content

Commit

Permalink
Merge pull request #9147 from dwijnand/exhaust-tuple
Browse files Browse the repository at this point in the history
Check all bindings exhaustively, e.g. tuples components
  • Loading branch information
lrytz committed Aug 18, 2020
2 parents 4a26288 + 93d1a5e commit 1de5f17
Show file tree
Hide file tree
Showing 6 changed files with 29 additions and 10 deletions.
7 changes: 3 additions & 4 deletions src/compiler/scala/tools/nsc/transform/patmat/Logic.scala
Expand Up @@ -398,10 +398,9 @@ trait Logic extends Debugging {

object gatherEqualities extends PropTraverser {
override def apply(p: Prop) = p match {
case Eq(v, c) =>
vars += v
v.registerEquality(c)
case _ => super.apply(p)
case Eq(v, NullConst) if !modelNull => vars += v // not modeling equality to null
case Eq(v, c) => vars += v; v.registerEquality(c)
case _ => super.apply(p)
}
}

Expand Down
Expand Up @@ -246,10 +246,6 @@ trait MatchApproximation extends TreeAndTypeAnalysis with ScalaLogic with MatchT
override def toString = s"T${id}C($prop)"
}

class TreeMakersToPropsIgnoreNullChecks(root: Symbol) extends TreeMakersToProps(root) {
override def uniqueNonNullProp(p: Tree): Prop = True
}

// returns (tree, tests), where `tree` will be used to refer to `root` in `tests`
class TreeMakersToProps(val root: Symbol) {
prepareNewAnalysis() // reset hash consing for Var and Const
Expand All @@ -261,7 +257,6 @@ trait MatchApproximation extends TreeAndTypeAnalysis with ScalaLogic with MatchT
def uniqueEqualityProp(testedPath: Tree, rhs: Tree): Prop =
uniqueEqualityProps getOrElseUpdate((testedPath, rhs), Eq(Var(testedPath), ValueConst(rhs)))

// overridden in TreeMakersToPropsIgnoreNullChecks
def uniqueNonNullProp (testedPath: Tree): Prop =
uniqueNonNullProps getOrElseUpdate(testedPath, Not(Eq(Var(testedPath), NullConst)))

Expand Down Expand Up @@ -537,7 +532,7 @@ trait MatchAnalysis extends MatchApproximation {
val start = if (StatisticsStatics.areSomeColdStatsEnabled) statistics.startTimer(statistics.patmatAnaExhaust) else null
var backoff = false

val approx = new TreeMakersToPropsIgnoreNullChecks(prevBinder)
val approx = new TreeMakersToProps(prevBinder)
val symbolicCases = approx.approximateMatch(cases, approx.onUnknown { tm =>
approx.fullRewrite.applyOrElse[TreeMaker, Prop](tm, {
case BodyTreeMaker(_, _) => True // irrelevant -- will be discarded by symbolCase later
Expand Down
11 changes: 11 additions & 0 deletions test/files/neg/t10019.check
@@ -0,0 +1,11 @@
t10019.scala:4: warning: match may not be exhaustive.
It would fail on the following input: Foo(None)
def single(t: Foo): Nothing = t match {
^
t10019.scala:8: warning: match may not be exhaustive.
It would fail on the following input: (Foo(None), _)
def tuple(s: Foo, t: Foo): Nothing = (s, t) match {
^
error: No warnings can be incurred under -Xfatal-warnings.
two warnings found
one error found
1 change: 1 addition & 0 deletions test/files/neg/t10019.flags
@@ -0,0 +1 @@
-Xfatal-warnings
11 changes: 11 additions & 0 deletions test/files/neg/t10019.scala
@@ -0,0 +1,11 @@
object Bug {
sealed case class Foo(e: Option[Int])

def single(t: Foo): Nothing = t match {
case Foo(Some(_)) => ???
}

def tuple(s: Foo, t: Foo): Nothing = (s, t) match {
case (Foo(Some(_)), _) => ???
}
}
2 changes: 2 additions & 0 deletions test/scaladoc/run/t10673.scala
Expand Up @@ -32,6 +32,8 @@ object Test extends ScaladocModelTest {
import access._
def showParents(e: MemberTemplateEntity): Unit = {
e.parentTypes.foreach(_._2.refEntity.foreach {
case (_, (LinkToMember(mbr, tpl), _)) => println(s"found link for member $mbr to $tpl")
case (_, (LinkToTpl(tpl), _)) => println(s"found link $tpl")
case (_, (LinkToExternalTpl(name, _, tpl), _)) => println(s"'$name' links to $tpl")
case (_, (Tooltip(name), _)) => println(s"'$name' no link!")
})
Expand Down

0 comments on commit 1de5f17

Please sign in to comment.