Skip to content

Commit

Permalink
Rollup merge of rust-lang#66722 - matthewjasper:non_exhaustive_borrow…
Browse files Browse the repository at this point in the history
…ck, r=varkor

Handle non_exhaustive in borrow checking

Borrow check can tell whether a pattern is exhaustive or not, make sure that `non_exhaustive` prevents this.
  • Loading branch information
tmandry authored Nov 27, 2019
2 parents 71f20b8 + 294f7e4 commit 61b8105
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/librustc_mir/build/matches/simplify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
self.hir.tcx().features().exhaustive_patterns &&
!v.uninhabited_from(self.hir.tcx(), substs, adt_def.adt_kind()).is_empty()
}
});
}) && (adt_def.did.is_local() || !adt_def.is_variant_list_non_exhaustive());
if irrefutable {
let place = tcx.mk_place_downcast(match_pair.place, adt_def, variant_index);
candidate.match_pairs.extend(self.field_match_pairs(place, subpatterns));
Expand Down
8 changes: 8 additions & 0 deletions src/test/ui/rfc-2008-non-exhaustive/auxiliary/monovariants.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#[non_exhaustive]
pub enum NonExhaustiveMonovariant {
Variant(u32),
}

pub enum ExhaustiveMonovariant {
Variant(u32),
}
42 changes: 42 additions & 0 deletions src/test/ui/rfc-2008-non-exhaustive/borrowck-exhaustive.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Test that the borrow checker doesn't consider checking an exhaustive pattern
// as an access.

// check-pass

// aux-build:monovariants.rs
extern crate monovariants;

use monovariants::ExhaustiveMonovariant;

enum Local {
Variant(u32),
}

#[non_exhaustive]
enum LocalNonExhaustive {
Variant(u32),
}

fn main() {
let mut x = ExhaustiveMonovariant::Variant(1);
let y = &mut x;
match x {
ExhaustiveMonovariant::Variant(_) => {},
_ => {},
}
drop(y);
let mut x = Local::Variant(1);
let y = &mut x;
match x {
Local::Variant(_) => {},
_ => {},
}
drop(y);
let mut x = LocalNonExhaustive::Variant(1);
let y = &mut x;
match x {
LocalNonExhaustive::Variant(_) => {},
_ => {},
}
drop(y);
}
18 changes: 18 additions & 0 deletions src/test/ui/rfc-2008-non-exhaustive/borrowck-non-exhaustive.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Test that the borrow checker considers `#[non_exhaustive]` when checking
// whether a match contains a discriminant read.

// aux-build:monovariants.rs
extern crate monovariants;

use monovariants::NonExhaustiveMonovariant;

fn main() {
let mut x = NonExhaustiveMonovariant::Variant(1);
let y = &mut x;
match x {
NonExhaustiveMonovariant::Variant(_) => {},
//~^ ERROR cannot use `x` because it was mutably borrowed
_ => {},
}
drop(y);
}
15 changes: 15 additions & 0 deletions src/test/ui/rfc-2008-non-exhaustive/borrowck-non-exhaustive.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error[E0503]: cannot use `x` because it was mutably borrowed
--> $DIR/borrowck-non-exhaustive.rs:13:9
|
LL | let y = &mut x;
| ------ borrow of `x` occurs here
LL | match x {
LL | NonExhaustiveMonovariant::Variant(_) => {},
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of borrowed `x`
...
LL | drop(y);
| - borrow later used here

error: aborting due to previous error

For more information about this error, try `rustc --explain E0503`.

0 comments on commit 61b8105

Please sign in to comment.