Skip to content

Commit 9dd390f

Browse files
committed
Point at uncovered variants in enum definition in note instead of a span_label
This makes the order of the output always consistent: 1. Place of the `match` missing arms 2. The `enum` definition span 3. The structured suggestion to add a fallthrough arm
1 parent 37cd037 commit 9dd390f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1033
-696
lines changed

compiler/rustc_mir_build/src/thir/pattern/check_match.rs

+19-7
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use rustc_session::lint::builtin::{
1717
BINDINGS_WITH_VARIANT_NAME, IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS,
1818
};
1919
use rustc_session::Session;
20-
use rustc_span::{DesugaringKind, ExpnKind, Span};
20+
use rustc_span::{DesugaringKind, ExpnKind, MultiSpan, Span};
2121

2222
crate fn check_match(tcx: TyCtxt<'_>, def_id: DefId) {
2323
let body_id = match def_id.as_local() {
@@ -671,15 +671,27 @@ fn adt_defined_here<'p, 'tcx>(
671671
) {
672672
let ty = ty.peel_refs();
673673
if let ty::Adt(def, _) = ty.kind() {
674-
if let Some(sp) = cx.tcx.hir().span_if_local(def.did) {
675-
err.span_label(sp, format!("`{}` defined here", ty));
676-
}
677-
678-
if witnesses.len() < 4 {
674+
let mut spans = vec![];
675+
if witnesses.len() < 5 {
679676
for sp in maybe_point_at_variant(cx, def, witnesses.iter()) {
680-
err.span_label(sp, "not covered");
677+
spans.push(sp);
681678
}
682679
}
680+
let def_span = cx
681+
.tcx
682+
.hir()
683+
.get_if_local(def.did)
684+
.and_then(|node| node.ident())
685+
.map(|ident| ident.span)
686+
.unwrap_or_else(|| cx.tcx.def_span(def.did));
687+
let mut span: MultiSpan =
688+
if spans.is_empty() { def_span.into() } else { spans.clone().into() };
689+
690+
span.push_span_label(def_span, String::new());
691+
for pat in spans {
692+
span.push_span_label(pat, "not covered".to_string());
693+
}
694+
err.span_note(span, &format!("`{}` defined here", ty));
683695
}
684696
}
685697

src/test/ui/closures/2229_closure_analysis/match/issue-88331.stderr

+10-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
error[E0004]: non-exhaustive patterns: `Opcode(0_u8)` and `Opcode(2_u8..=u8::MAX)` not covered
22
--> $DIR/issue-88331.rs:11:20
33
|
4-
LL | pub struct Opcode(pub u8);
5-
| -------------------------- `Opcode` defined here
6-
...
74
LL | move |i| match msg_type {
85
| ^^^^^^^^ patterns `Opcode(0_u8)` and `Opcode(2_u8..=u8::MAX)` not covered
96
|
7+
note: `Opcode` defined here
8+
--> $DIR/issue-88331.rs:4:12
9+
|
10+
LL | pub struct Opcode(pub u8);
11+
| ^^^^^^
1012
= note: the matched value is of type `Opcode`
1113
help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
1214
|
@@ -17,12 +19,14 @@ LL ~ Opcode(0_u8) | Opcode(2_u8..=u8::MAX) => todo!(),
1719
error[E0004]: non-exhaustive patterns: `Opcode2(Opcode(0_u8))` and `Opcode2(Opcode(2_u8..=u8::MAX))` not covered
1820
--> $DIR/issue-88331.rs:27:20
1921
|
20-
LL | pub struct Opcode2(Opcode);
21-
| --------------------------- `Opcode2` defined here
22-
...
2322
LL | move |i| match msg_type {
2423
| ^^^^^^^^ patterns `Opcode2(Opcode(0_u8))` and `Opcode2(Opcode(2_u8..=u8::MAX))` not covered
2524
|
25+
note: `Opcode2` defined here
26+
--> $DIR/issue-88331.rs:18:12
27+
|
28+
LL | pub struct Opcode2(Opcode);
29+
| ^^^^^^^
2630
= note: the matched value is of type `Opcode2`
2731
help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
2832
|

src/test/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr

+15-6
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
error[E0004]: non-exhaustive patterns: `B` not covered
22
--> $DIR/non-exhaustive-match.rs:26:25
33
|
4-
LL | enum L1 { A, B }
5-
| ----------------
6-
| | |
7-
| | not covered
8-
| `L1` defined here
9-
...
104
LL | let _b = || { match l1 { L1::A => () } };
115
| ^^ pattern `B` not covered
126
|
7+
note: `L1` defined here
8+
--> $DIR/non-exhaustive-match.rs:12:14
9+
|
10+
LL | enum L1 { A, B }
11+
| -- ^ not covered
1312
= note: the matched value is of type `L1`
1413
help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
1514
|
@@ -22,6 +21,11 @@ error[E0004]: non-exhaustive patterns: type `E1` is non-empty
2221
LL | let _d = || { match e1 {} };
2322
| ^^
2423
|
24+
note: `E1` defined here
25+
--> $DIR/auxiliary/match_non_exhaustive_lib.rs:2:1
26+
|
27+
LL | pub enum E1 {}
28+
| ^^^^^^^^^^^^^^
2529
= note: the matched value is of type `E1`, which is marked as non-exhaustive
2630
help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
2731
|
@@ -36,6 +40,11 @@ error[E0004]: non-exhaustive patterns: `_` not covered
3640
LL | let _e = || { match e2 { E2::A => (), E2::B => () } };
3741
| ^^ pattern `_` not covered
3842
|
43+
note: `E2` defined here
44+
--> $DIR/auxiliary/match_non_exhaustive_lib.rs:5:1
45+
|
46+
LL | pub enum E2 { A, B }
47+
| ^^^^^^^^^^^^^^^^^^^^
3948
= note: the matched value is of type `E2`, which is marked as non-exhaustive
4049
help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
4150
|

src/test/ui/empty/empty-never-array.stderr

+9-10
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
error[E0005]: refutable pattern in local binding: `T(_, _)` not covered
22
--> $DIR/empty-never-array.rs:10:9
33
|
4-
LL | / enum Helper<T, U> {
5-
LL | | T(T, [!; 0]),
6-
| | - not covered
7-
LL | | #[allow(dead_code)]
8-
LL | | U(U),
9-
LL | | }
10-
| |_- `Helper<T, U>` defined here
11-
...
12-
LL | let Helper::U(u) = Helper::T(t, []);
13-
| ^^^^^^^^^^^^ pattern `T(_, _)` not covered
4+
LL | let Helper::U(u) = Helper::T(t, []);
5+
| ^^^^^^^^^^^^ pattern `T(_, _)` not covered
146
|
157
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
168
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
9+
note: `Helper<T, U>` defined here
10+
--> $DIR/empty-never-array.rs:4:5
11+
|
12+
LL | enum Helper<T, U> {
13+
| ------
14+
LL | T(T, [!; 0]),
15+
| ^ not covered
1716
= note: the matched value is of type `Helper<T, U>`
1817
help: you might want to use `if let` to ignore the variant that isn't matched
1918
|

src/test/ui/error-codes/E0004-2.stderr

+13-7
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,20 @@ error[E0004]: non-exhaustive patterns: `None` and `Some(_)` not covered
44
LL | match x { }
55
| ^ patterns `None` and `Some(_)` not covered
66
|
7-
::: $SRC_DIR/core/src/option.rs:LL:COL
8-
|
9-
LL | None,
10-
| ---- not covered
11-
...
12-
LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T),
13-
| ---- not covered
7+
note: `Option<i32>` defined here
8+
--> $SRC_DIR/core/src/option.rs:LL:COL
149
|
10+
LL | / pub enum Option<T> {
11+
LL | | /// No value.
12+
LL | | #[lang = "None"]
13+
LL | | #[stable(feature = "rust1", since = "1.0.0")]
14+
LL | | None,
15+
| | ^^^^ not covered
16+
... |
17+
LL | | Some(#[stable(feature = "rust1", since = "1.0.0")] T),
18+
| | ^^^^ not covered
19+
LL | | }
20+
| |_-
1521
= note: the matched value is of type `Option<i32>`
1622
help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
1723
|

src/test/ui/error-codes/E0004.stderr

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
error[E0004]: non-exhaustive patterns: `HastaLaVistaBaby` not covered
22
--> $DIR/E0004.rs:9:11
33
|
4-
LL | / enum Terminator {
5-
LL | | HastaLaVistaBaby,
6-
| | ---------------- not covered
7-
LL | | TalkToMyHand,
8-
LL | | }
9-
| |_- `Terminator` defined here
10-
...
11-
LL | match x {
12-
| ^ pattern `HastaLaVistaBaby` not covered
4+
LL | match x {
5+
| ^ pattern `HastaLaVistaBaby` not covered
136
|
7+
note: `Terminator` defined here
8+
--> $DIR/E0004.rs:2:5
9+
|
10+
LL | enum Terminator {
11+
| ----------
12+
LL | HastaLaVistaBaby,
13+
| ^^^^^^^^^^^^^^^^ not covered
1414
= note: the matched value is of type `Terminator`
1515
help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
1616
|

src/test/ui/error-codes/E0005.stderr

+13-5
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,21 @@ error[E0005]: refutable pattern in local binding: `None` not covered
44
LL | let Some(y) = x;
55
| ^^^^^^^ pattern `None` not covered
66
|
7-
::: $SRC_DIR/core/src/option.rs:LL:COL
8-
|
9-
LL | None,
10-
| ---- not covered
11-
|
127
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
138
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
9+
note: `Option<i32>` defined here
10+
--> $SRC_DIR/core/src/option.rs:LL:COL
11+
|
12+
LL | / pub enum Option<T> {
13+
LL | | /// No value.
14+
LL | | #[lang = "None"]
15+
LL | | #[stable(feature = "rust1", since = "1.0.0")]
16+
LL | | None,
17+
| | ^^^^ not covered
18+
... |
19+
LL | | Some(#[stable(feature = "rust1", since = "1.0.0")] T),
20+
LL | | }
21+
| |_-
1422
= note: the matched value is of type `Option<i32>`
1523
help: you might want to use `if let` to ignore the variant that isn't matched
1624
|

src/test/ui/error-codes/E0297.stderr

+12-4
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,19 @@ error[E0005]: refutable pattern in `for` loop binding: `None` not covered
44
LL | for Some(x) in xs {}
55
| ^^^^^^^ pattern `None` not covered
66
|
7-
::: $SRC_DIR/core/src/option.rs:LL:COL
8-
|
9-
LL | None,
10-
| ---- not covered
7+
note: `Option<i32>` defined here
8+
--> $SRC_DIR/core/src/option.rs:LL:COL
119
|
10+
LL | / pub enum Option<T> {
11+
LL | | /// No value.
12+
LL | | #[lang = "None"]
13+
LL | | #[stable(feature = "rust1", since = "1.0.0")]
14+
LL | | None,
15+
| | ^^^^ not covered
16+
... |
17+
LL | | Some(#[stable(feature = "rust1", since = "1.0.0")] T),
18+
LL | | }
19+
| |_-
1220
= note: the matched value is of type `Option<i32>`
1321

1422
error: aborting due to previous error

src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr

+12-5
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,20 @@ error[E0005]: refutable pattern in local binding: `Err(_)` not covered
44
LL | let Ok(_x) = foo();
55
| ^^^^^^ pattern `Err(_)` not covered
66
|
7-
::: $SRC_DIR/core/src/result.rs:LL:COL
8-
|
9-
LL | Err(#[stable(feature = "rust1", since = "1.0.0")] E),
10-
| --- not covered
11-
|
127
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
138
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
9+
note: `Result<u32, !>` defined here
10+
--> $SRC_DIR/core/src/result.rs:LL:COL
11+
|
12+
LL | / pub enum Result<T, E> {
13+
LL | | /// Contains the success value
14+
LL | | #[lang = "Ok"]
15+
LL | | #[stable(feature = "rust1", since = "1.0.0")]
16+
... |
17+
LL | | Err(#[stable(feature = "rust1", since = "1.0.0")] E),
18+
| | ^^^ not covered
19+
LL | | }
20+
| |_-
1421
= note: the matched value is of type `Result<u32, !>`
1522
help: you might want to use `if let` to ignore the variant that isn't matched
1623
|

src/test/ui/match/match_non_exhaustive.stderr

+15-6
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
error[E0004]: non-exhaustive patterns: `B` not covered
22
--> $DIR/match_non_exhaustive.rs:23:11
33
|
4-
LL | enum L { A, B }
5-
| ---------------
6-
| | |
7-
| | not covered
8-
| `L` defined here
9-
...
104
LL | match l { L::A => () };
115
| ^ pattern `B` not covered
126
|
7+
note: `L` defined here
8+
--> $DIR/match_non_exhaustive.rs:10:13
9+
|
10+
LL | enum L { A, B }
11+
| - ^ not covered
1312
= note: the matched value is of type `L`
1413
help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
1514
|
@@ -22,6 +21,11 @@ error[E0004]: non-exhaustive patterns: type `E1` is non-empty
2221
LL | match e1 {};
2322
| ^^
2423
|
24+
note: `E1` defined here
25+
--> $DIR/auxiliary/match_non_exhaustive_lib.rs:2:1
26+
|
27+
LL | pub enum E1 {}
28+
| ^^^^^^^^^^^^^^
2529
= note: the matched value is of type `E1`, which is marked as non-exhaustive
2630
help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
2731
|
@@ -36,6 +40,11 @@ error[E0004]: non-exhaustive patterns: `_` not covered
3640
LL | match e2 { E2::A => (), E2::B => () };
3741
| ^^ pattern `_` not covered
3842
|
43+
note: `E2` defined here
44+
--> $DIR/auxiliary/match_non_exhaustive_lib.rs:5:1
45+
|
46+
LL | pub enum E2 { A, B }
47+
| ^^^^^^^^^^^^^^^^^^^^
3948
= note: the matched value is of type `E2`, which is marked as non-exhaustive
4049
help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
4150
|

src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr

+7-7
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@ LL + }
1616
error[E0004]: non-exhaustive patterns: type `Foo` is non-empty
1717
--> $DIR/always-inhabited-union-ref.rs:27:11
1818
|
19-
LL | / pub union Foo {
20-
LL | | foo: !,
21-
LL | | }
22-
| |_- `Foo` defined here
23-
...
24-
LL | match uninhab_union() {
25-
| ^^^^^^^^^^^^^^^
19+
LL | match uninhab_union() {
20+
| ^^^^^^^^^^^^^^^
2621
|
22+
note: `Foo` defined here
23+
--> $DIR/always-inhabited-union-ref.rs:10:11
24+
|
25+
LL | pub union Foo {
26+
| ^^^
2727
= note: the matched value is of type `Foo`
2828
help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
2929
|

0 commit comments

Comments
 (0)