Skip to content

Commit 294f7e4

Browse files
committed
Handle non_exhaustive in borrow checking
1 parent 5a1d028 commit 294f7e4

File tree

5 files changed

+84
-1
lines changed

5 files changed

+84
-1
lines changed

src/librustc_mir/build/matches/simplify.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
164164
self.hir.tcx().features().exhaustive_patterns &&
165165
!v.uninhabited_from(self.hir.tcx(), substs, adt_def.adt_kind()).is_empty()
166166
}
167-
});
167+
}) && (adt_def.did.is_local() || !adt_def.is_variant_list_non_exhaustive());
168168
if irrefutable {
169169
let place = tcx.mk_place_downcast(match_pair.place, adt_def, variant_index);
170170
candidate.match_pairs.extend(self.field_match_pairs(place, subpatterns));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#[non_exhaustive]
2+
pub enum NonExhaustiveMonovariant {
3+
Variant(u32),
4+
}
5+
6+
pub enum ExhaustiveMonovariant {
7+
Variant(u32),
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Test that the borrow checker doesn't consider checking an exhaustive pattern
2+
// as an access.
3+
4+
// check-pass
5+
6+
// aux-build:monovariants.rs
7+
extern crate monovariants;
8+
9+
use monovariants::ExhaustiveMonovariant;
10+
11+
enum Local {
12+
Variant(u32),
13+
}
14+
15+
#[non_exhaustive]
16+
enum LocalNonExhaustive {
17+
Variant(u32),
18+
}
19+
20+
fn main() {
21+
let mut x = ExhaustiveMonovariant::Variant(1);
22+
let y = &mut x;
23+
match x {
24+
ExhaustiveMonovariant::Variant(_) => {},
25+
_ => {},
26+
}
27+
drop(y);
28+
let mut x = Local::Variant(1);
29+
let y = &mut x;
30+
match x {
31+
Local::Variant(_) => {},
32+
_ => {},
33+
}
34+
drop(y);
35+
let mut x = LocalNonExhaustive::Variant(1);
36+
let y = &mut x;
37+
match x {
38+
LocalNonExhaustive::Variant(_) => {},
39+
_ => {},
40+
}
41+
drop(y);
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Test that the borrow checker considers `#[non_exhaustive]` when checking
2+
// whether a match contains a discriminant read.
3+
4+
// aux-build:monovariants.rs
5+
extern crate monovariants;
6+
7+
use monovariants::NonExhaustiveMonovariant;
8+
9+
fn main() {
10+
let mut x = NonExhaustiveMonovariant::Variant(1);
11+
let y = &mut x;
12+
match x {
13+
NonExhaustiveMonovariant::Variant(_) => {},
14+
//~^ ERROR cannot use `x` because it was mutably borrowed
15+
_ => {},
16+
}
17+
drop(y);
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0503]: cannot use `x` because it was mutably borrowed
2+
--> $DIR/borrowck-non-exhaustive.rs:13:9
3+
|
4+
LL | let y = &mut x;
5+
| ------ borrow of `x` occurs here
6+
LL | match x {
7+
LL | NonExhaustiveMonovariant::Variant(_) => {},
8+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of borrowed `x`
9+
...
10+
LL | drop(y);
11+
| - borrow later used here
12+
13+
error: aborting due to previous error
14+
15+
For more information about this error, try `rustc --explain E0503`.

0 commit comments

Comments
 (0)