Skip to content

Conversation

estebank
Copy link
Contributor

error[E0004]: non-exhaustive patterns: type `X` is non-empty
 --> file.rs:9:11
  |
1 | / enum X {
2 | |     A,
  | |     - variant not covered
3 | |     B,
  | |     - variant not covered
4 | |     C,
  | |     - variant not covered
5 | | }
  | |_- `X` defined here
...
9 |       match x {
  |             ^
  |
  = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms

error[E0004]: non-exhaustive patterns: `B` and `C` not covered
  --> file.rs:11:11
   |
1  | / enum X {
2  | |     A,
3  | |     B,
4  | |     C,
   | |     - not covered
5  | | }
   | |_- `X` defined here
...
11 |       match x {
   |             ^ patterns `C` not covered

When a match expression doesn't have patterns covering every variant,
point at the enum's definition span. On a best effort basis, point at the
variant(s) that are missing. This does not handle the case when the missing
pattern is due to a field's enum variants:

enum E1 {
    A,
    B,
    C,
}
enum E2 {
    A(E1),
    B,
}
fn foo() {
    match E2::A(E1::A) {
        E2::A(E1::B) => {}
        E2::B => {}
    }
    //~^ ERROR `E2::A(E1::A)` and `E2::A(E1::C)` not handled
}

Unify look between match with no arms and match with some missing patterns.

Fix #37518.

@rust-highfive
Copy link
Contributor

r? @eddyb

(rust_highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Feb 11, 2019
@estebank
Copy link
Contributor Author

r? @zackmdavis

@rust-highfive rust-highfive assigned zackmdavis and unassigned eddyb Feb 11, 2019
@rust-highfive

This comment has been minimized.

Copy link
Contributor

@zackmdavis zackmdavis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

naming/commentary quibbles, otherwise r=me

@@ -204,25 +204,42 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
// is uninhabited.
let pat_ty = self.tables.node_id_to_type(scrut.hir_id);
let module = self.tcx.hir().get_module_parent(scrut.id);
let mut def_span = None;
let mut missing_variants = vec![];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I usually write empty vectors as Vec::new() (thinking, "no need to the macro sugar when there aren't any elements to initialize"), but rustfmt doesn't seem to have an opinion. (I guess you could argue that it's technically a semantic change.)

"ensure that all possible cases are being handled, \
possibly by adding wildcards or more match arms");
let mut err = create_e0004(self.tcx.sess, scrut.span, format!(
"non-exhaustive patterns: type `{}` is non-empty",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I realized that this was already here and not a part of the present changeset, but) do we even want to bother saying "type is non-empty" here? If we don't expect users to think or care about the empty enum very often, this might not be the most helpful time to educate them.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed to "non-exhaustive patterns: variant Foo of type Bar is not handled"

if def.variants.len() < 4 && !def.variants.is_empty() {
// keep around to point at the definition of non-covered variants
missing_variants = def.variants.iter()
.map(|variant| variant.ident.span)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we call the variable missing_variant_spans or similar? (I balked at err.span_label(*variant on line 241.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

collected the variant idents instead, keeping the vector name the same

LL | | }
| |_- `Terminator` defined here
...
LL | match x { //~ ERROR E0004
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(possibly a bad idea, probably out of scope for this PR) I find it counterintuitive for the primary span of a "non-exaustive patterns" error to point to the x in match x, rather than the body of match arms. (That could get very visually cluttered, though, especially with the secondary definition-spans introduced here. Also, pointing at the discriminant does seem intuitive when it's a pattern rather than an opaque variable, as in the examples in src/test/ui/check_match/issue-35609.stderr.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have the same thoughts you do, but I lay on the side of using the smallest possible primary span, for VSCode's sake.

@bors

This comment has been minimized.

estebank added 3 commits March 2, 2019 16:45
```
error[E0004]: non-exhaustive patterns: type `X` is non-empty
 --> file.rs:9:11
  |
1 | / enum X {
2 | |     A,
  | |     - variant not covered
3 | |     B,
  | |     - variant not covered
4 | |     C,
  | |     - variant not covered
5 | | }
  | |_- `X` defined here
...
9 |       match x {
  |             ^
  |
  = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms

error[E0004]: non-exhaustive patterns: `B` and `C` not covered
  --> file.rs:11:11
   |
1  | / enum X {
2  | |     A,
3  | |     B,
4  | |     C,
   | |     - not covered
5  | | }
   | |_- `X` defined here
...
11 |       match x {
   |             ^ patterns `C` not covered
```

When a match expression doesn't have patterns covering every variant,
point at the enum's definition span. On a best effort basis, point at the
variant(s) that are missing. This does not handle the case when the missing
pattern is due to a field's enum variants:

```
enum E1 {
    A,
    B,
    C,
}
enum E2 {
    A(E1),
    B,
}
fn foo() {
    match E2::A(E1::A) {
        E2::A(E1::B) => {}
        E2::B => {}
    }
    //~^ ERROR `E2::A(E1::A)` and `E2::A(E1::C)` not handled
}
```

Unify look between match with no arms and match with some missing patterns.

Fix rust-lang#37518.
@estebank estebank force-pushed the missing-match-pats branch from acba4dc to d651281 Compare March 3, 2019 01:50
@estebank
Copy link
Contributor Author

estebank commented Mar 4, 2019

@bors r=zackmdavis

@bors
Copy link
Collaborator

bors commented Mar 4, 2019

📌 Commit d651281 has been approved by zackmdavis

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Mar 4, 2019
@bors
Copy link
Collaborator

bors commented Mar 4, 2019

⌛ Testing commit d651281 with merge a9da8fc...

bors added a commit that referenced this pull request Mar 4, 2019
Point at enum definition when match patterns are not exhaustive

```
error[E0004]: non-exhaustive patterns: type `X` is non-empty
 --> file.rs:9:11
  |
1 | / enum X {
2 | |     A,
  | |     - variant not covered
3 | |     B,
  | |     - variant not covered
4 | |     C,
  | |     - variant not covered
5 | | }
  | |_- `X` defined here
...
9 |       match x {
  |             ^
  |
  = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms

error[E0004]: non-exhaustive patterns: `B` and `C` not covered
  --> file.rs:11:11
   |
1  | / enum X {
2  | |     A,
3  | |     B,
4  | |     C,
   | |     - not covered
5  | | }
   | |_- `X` defined here
...
11 |       match x {
   |             ^ patterns `C` not covered
```

When a match expression doesn't have patterns covering every variant,
point at the enum's definition span. On a best effort basis, point at the
variant(s) that are missing. This does not handle the case when the missing
pattern is due to a field's enum variants:

```
enum E1 {
    A,
    B,
    C,
}
enum E2 {
    A(E1),
    B,
}
fn foo() {
    match E2::A(E1::A) {
        E2::A(E1::B) => {}
        E2::B => {}
    }
    //~^ ERROR `E2::A(E1::A)` and `E2::A(E1::C)` not handled
}
```

Unify look between match with no arms and match with some missing patterns.

Fix #37518.
@bors
Copy link
Collaborator

bors commented Mar 4, 2019

☀️ Test successful - checks-travis, status-appveyor
Approved by: zackmdavis
Pushing a9da8fc to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Mar 4, 2019
@bors bors merged commit d651281 into rust-lang:master Mar 4, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants