From 294f7e479019d574dc4083cc9603e92957cc6368 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 24 Nov 2019 22:39:05 +0000 Subject: [PATCH] Handle non_exhaustive in borrow checking --- src/librustc_mir/build/matches/simplify.rs | 2 +- .../auxiliary/monovariants.rs | 8 ++++ .../borrowck-exhaustive.rs | 42 +++++++++++++++++++ .../borrowck-non-exhaustive.rs | 18 ++++++++ .../borrowck-non-exhaustive.stderr | 15 +++++++ 5 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/rfc-2008-non-exhaustive/auxiliary/monovariants.rs create mode 100644 src/test/ui/rfc-2008-non-exhaustive/borrowck-exhaustive.rs create mode 100644 src/test/ui/rfc-2008-non-exhaustive/borrowck-non-exhaustive.rs create mode 100644 src/test/ui/rfc-2008-non-exhaustive/borrowck-non-exhaustive.stderr diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs index 9b7bccca2ddf3..3e71b871801d1 100644 --- a/src/librustc_mir/build/matches/simplify.rs +++ b/src/librustc_mir/build/matches/simplify.rs @@ -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)); diff --git a/src/test/ui/rfc-2008-non-exhaustive/auxiliary/monovariants.rs b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/monovariants.rs new file mode 100644 index 0000000000000..5f86db86d4477 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/monovariants.rs @@ -0,0 +1,8 @@ +#[non_exhaustive] +pub enum NonExhaustiveMonovariant { + Variant(u32), +} + +pub enum ExhaustiveMonovariant { + Variant(u32), +} diff --git a/src/test/ui/rfc-2008-non-exhaustive/borrowck-exhaustive.rs b/src/test/ui/rfc-2008-non-exhaustive/borrowck-exhaustive.rs new file mode 100644 index 0000000000000..be775b37f7b77 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/borrowck-exhaustive.rs @@ -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); +} diff --git a/src/test/ui/rfc-2008-non-exhaustive/borrowck-non-exhaustive.rs b/src/test/ui/rfc-2008-non-exhaustive/borrowck-non-exhaustive.rs new file mode 100644 index 0000000000000..00dcf89c7aa67 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/borrowck-non-exhaustive.rs @@ -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); +} diff --git a/src/test/ui/rfc-2008-non-exhaustive/borrowck-non-exhaustive.stderr b/src/test/ui/rfc-2008-non-exhaustive/borrowck-non-exhaustive.stderr new file mode 100644 index 0000000000000..9edfa84cbc085 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/borrowck-non-exhaustive.stderr @@ -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`.