Skip to content

Missing unreachable case warnings #4661

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
smarter opened this issue Jun 14, 2018 · 3 comments
Closed

Missing unreachable case warnings #4661

smarter opened this issue Jun 14, 2018 · 3 comments

Comments

@smarter
Copy link
Member

smarter commented Jun 14, 2018

Given:

trait Foo
class One extends Foo
class Two extends Foo
class Three extends Foo

object Test {
  def test(f: Foo) = f match {
    case f: Foo =>
    case f: One =>
    case f: Two =>
    case f: Three =>
  }
}

We should get three warnings since the three last cases are not reachable, but we only get one for the last case:

-- [E120] Only null matched Warning: try/caseun.scala:11:9 ---------------------
11 |    case f: Three =>
   |         ^^^^^^^^
   |         Only null is matched. Consider using `case null =>` instead.

(The warning itself is a bit confusing but that's a separate issue: #4660)

@liufengyun
Copy link
Contributor

@smarter Current implementation only check for the last case because the computation is a little expensive (much more than unreachable case analysis). We can still do the analysis for all cases, and see how it impacts performance.

abeln added a commit to abeln/dotty that referenced this issue Jul 27, 2018
@abeln
Copy link
Contributor

abeln commented Jul 27, 2018

I think there are several things going on here:

        val curr = project(pat)

        debug.println(s"---------------reachable? ${show(curr)}")
        debug.println(s"prev: ${show(prevs)}")

        var covered = simplify(intersect(curr, targetSpace))
        debug.println(s"covered: $covered")

The code above is what runs in a loop for the reachability checks.
When we project the pattern, the space we get is of the form Typ(x), but after the intersection we get an Or(x, null) space.

Looking at how we explicitly add a nullType to targetSpace https://github.com/lampepfl/dotty/blob/efb8115982cbb18aa7eed05f10b13b654e80acb5/compiler/src/dotty/tools/dotc/transform/patmat/Space.scala#L928), it seems that the intention is that Typ(x) types, when viewed as sets, don't include null. This also matches the definition of isSubType.

However, within intersect and specifically intersectUnrelatedAtomicTypes, there's a precondition that uses the weaker <:< (normal subtyping) relation, instead of isSubType.

  override def intersectUnrelatedAtomicTypes(tp1: Type, tp2: Type) = {
    val and = AndType(tp1, tp2)
    // Precondition: !(tp1 <:< tp2) && !(tp2 <:< tp1)
    // Then, no leaf of the and-type tree `and` is a subtype of `and`.
val res = inhabited(and)

This means that when we intersect Typ(Foo) with nullType, we end up constructing an AndType in intersectUnrelatedAtomicTypes (because neither is a subtype in the isSubType sense), but the AndType ends being just nullType (because it uses the regular notion of subtyping).

One solution, it seems to me, is to handle the null case separately when intersecting things, as in the proposed commit above: abeln@7d7a7d1

Incidentally, that also fixes #4660 as well.

@liufengyun does that make sense? What do you guys think?

@liufengyun
Copy link
Contributor

Thanks a lot for the in-depth diagnosis @abeln , I think that is the right fix. Could you please make a PR?

abeln added a commit to abeln/dotty that referenced this issue Jul 30, 2018
abeln added a commit to abeln/dotty that referenced this issue Jul 30, 2018
abeln added a commit to abeln/dotty that referenced this issue Jul 31, 2018
abeln added a commit to abeln/dotty that referenced this issue Aug 3, 2018
abeln added a commit to abeln/dotty that referenced this issue Aug 3, 2018
abeln added a commit to abeln/dotty that referenced this issue Aug 13, 2018
liufengyun added a commit that referenced this issue Aug 14, 2018
Fix #4661: Missing unreachable case warnings
abeln added a commit to abeln/dotty that referenced this issue Aug 15, 2018
The test case comes from scala#4660, which is a related bug.
abeln added a commit to abeln/dotty that referenced this issue Aug 15, 2018
The test case comes from scala#4660, which is a related bug.
liufengyun added a commit that referenced this issue Aug 15, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants