about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2018-12-16 14:08:29 +0100
committerGitHub <noreply@github.com>2018-12-16 14:08:29 +0100
commitd91032a9efab1f552ce5a50d0f213d185b06129d (patch)
tree83042c1bd0c1b08d24c1417e0264cb81326aa12d
parentf1fa9d42611cd8c75ae14436ddaca4d06e8a11a5 (diff)
parentcdd537339eb9fe009f75f285a99aa8257775e656 (diff)
downloadrust-d91032a9efab1f552ce5a50d0f213d185b06129d.tar.gz
rust-d91032a9efab1f552ce5a50d0f213d185b06129d.zip
Rollup merge of #56790 - rust-lang:borrowck-niche-discriminants, r=nikomatsakis
Make RValue::Discriminant a normal Shallow read

Enum layout optimizations mean that the discriminant of an enum may not be stored in a tag disjoint from the rest of the fields of the enum. Stop borrow checking as though they are.

Run with MIRI to see why this is needed: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=09a3236685a06b6096e2e2e3968b852c.

This issue exists with the lexical borrow checker as well (see #45045) so migrate mode should prevent this from being immediately breaking.

r? @nikomatsakis

Fixes #56797
-rw-r--r--src/librustc_mir/borrow_check/mod.rs9
-rw-r--r--src/librustc_mir/borrow_check/nll/invalidation.rs8
-rw-r--r--src/librustc_mir/borrow_check/places_conflict.rs13
-rw-r--r--src/test/ui/borrowck/borrowck-anon-fields-variant.nll.stderr33
-rw-r--r--src/test/ui/nll/match-on-borrowed.rs8
-rw-r--r--src/test/ui/nll/match-on-borrowed.stderr26
6 files changed, 73 insertions, 24 deletions
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index e3029c6a19d..5eca62938f7 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -545,7 +545,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
                 self.mutate_place(
                     ContextKind::SetDiscrim.new(location),
                     (place, span),
-                    Shallow(Some(ArtificialField::Discriminant)),
+                    Shallow(None),
                     JustWrite,
                     flow_state,
                 );
@@ -782,7 +782,6 @@ use self::AccessDepth::{Deep, Shallow};
 
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 enum ArtificialField {
-    Discriminant,
     ArrayLength,
     ShallowBorrow,
 }
@@ -1191,14 +1190,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
 
             Rvalue::Len(ref place) | Rvalue::Discriminant(ref place) => {
                 let af = match *rvalue {
-                    Rvalue::Len(..) => ArtificialField::ArrayLength,
-                    Rvalue::Discriminant(..) => ArtificialField::Discriminant,
+                    Rvalue::Len(..) => Some(ArtificialField::ArrayLength),
+                    Rvalue::Discriminant(..) => None,
                     _ => unreachable!(),
                 };
                 self.access_place(
                     context,
                     (place, span),
-                    (Shallow(Some(af)), Read(ReadKind::Copy)),
+                    (Shallow(af), Read(ReadKind::Copy)),
                     LocalMutationIsAllowed::No,
                     flow_state,
                 );
diff --git a/src/librustc_mir/borrow_check/nll/invalidation.rs b/src/librustc_mir/borrow_check/nll/invalidation.rs
index 8af23a8813a..07bda8af626 100644
--- a/src/librustc_mir/borrow_check/nll/invalidation.rs
+++ b/src/librustc_mir/borrow_check/nll/invalidation.rs
@@ -99,7 +99,7 @@ impl<'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx, 'gcx> {
                 self.mutate_place(
                     ContextKind::SetDiscrim.new(location),
                     place,
-                    Shallow(Some(ArtificialField::Discriminant)),
+                    Shallow(None),
                     JustWrite,
                 );
             }
@@ -360,14 +360,14 @@ impl<'cg, 'cx, 'tcx, 'gcx> InvalidationGenerator<'cx, 'tcx, 'gcx> {
 
             Rvalue::Len(ref place) | Rvalue::Discriminant(ref place) => {
                 let af = match *rvalue {
-                    Rvalue::Len(..) => ArtificialField::ArrayLength,
-                    Rvalue::Discriminant(..) => ArtificialField::Discriminant,
+                    Rvalue::Len(..) => Some(ArtificialField::ArrayLength),
+                    Rvalue::Discriminant(..) => None,
                     _ => unreachable!(),
                 };
                 self.access_place(
                     context,
                     place,
-                    (Shallow(Some(af)), Read(ReadKind::Copy)),
+                    (Shallow(af), Read(ReadKind::Copy)),
                     LocalMutationIsAllowed::No,
                 );
             }
diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs
index eeac915cff3..e24586cca09 100644
--- a/src/librustc_mir/borrow_check/places_conflict.rs
+++ b/src/librustc_mir/borrow_check/places_conflict.rs
@@ -165,15 +165,12 @@ fn place_components_conflict<'gcx, 'tcx>(
                 let base_ty = base.ty(mir, tcx).to_ty(tcx);
 
                 match (elem, &base_ty.sty, access) {
-                    (_, _, Shallow(Some(ArtificialField::Discriminant)))
-                    | (_, _, Shallow(Some(ArtificialField::ArrayLength)))
+                    (_, _, Shallow(Some(ArtificialField::ArrayLength)))
                     | (_, _, Shallow(Some(ArtificialField::ShallowBorrow))) => {
-                        // The discriminant and array length are like
-                        // additional fields on the type; they do not
-                        // overlap any existing data there. Furthermore,
-                        // they cannot actually be a prefix of any
-                        // borrowed place (at least in MIR as it is
-                        // currently.)
+                        // The array length is like  additional fields on the
+                        // type; it does not overlap any existing data there.
+                        // Furthermore, if cannot actually be a prefix of any
+                        // borrowed place (at least in MIR as it is currently.)
                         //
                         // e.g., a (mutable) borrow of `a[5]` while we read the
                         // array length of `a`.
diff --git a/src/test/ui/borrowck/borrowck-anon-fields-variant.nll.stderr b/src/test/ui/borrowck/borrowck-anon-fields-variant.nll.stderr
index 17722bf226d..6f72de0edee 100644
--- a/src/test/ui/borrowck/borrowck-anon-fields-variant.nll.stderr
+++ b/src/test/ui/borrowck/borrowck-anon-fields-variant.nll.stderr
@@ -1,3 +1,31 @@
+warning[E0503]: cannot use `y` because it was mutably borrowed
+  --> $DIR/borrowck-anon-fields-variant.rs:27:7
+   |
+LL |       Foo::Y(ref mut a, _) => a,
+   |              --------- borrow of `y.0` occurs here
+...
+LL |       Foo::Y(_, ref mut b) => b,
+   |       ^^^^^^^^^^^^^^^^^^^^ use of borrowed `y.0`
+...
+LL |     *a += 1;
+   |     ------- borrow later used here
+   |
+   = warning: This error has been downgraded to a warning for backwards compatibility with previous releases.
+           It represents potential unsoundness in your code.
+           This warning will become a hard error in the future.
+
+error[E0503]: cannot use `y` because it was mutably borrowed
+  --> $DIR/borrowck-anon-fields-variant.rs:44:7
+   |
+LL |       Foo::Y(ref mut a, _) => a,
+   |              --------- borrow of `y.0` occurs here
+...
+LL |       Foo::Y(ref mut b, _) => b, //~ ERROR cannot borrow
+   |       ^^^^^^^^^^^^^^^^^^^^ use of borrowed `y.0`
+...
+LL |     *a += 1;
+   |     ------- borrow later used here
+
 error[E0499]: cannot borrow `y.0` as mutable more than once at a time
   --> $DIR/borrowck-anon-fields-variant.rs:44:14
    |
@@ -10,6 +38,7 @@ LL |       Foo::Y(ref mut b, _) => b, //~ ERROR cannot borrow
 LL |     *a += 1;
    |     ------- first borrow later used here
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0499`.
+Some errors occurred: E0499, E0503.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/src/test/ui/nll/match-on-borrowed.rs b/src/test/ui/nll/match-on-borrowed.rs
index 6a8ce03e8fd..edce2b185df 100644
--- a/src/test/ui/nll/match-on-borrowed.rs
+++ b/src/test/ui/nll/match-on-borrowed.rs
@@ -46,9 +46,9 @@ fn enum_example(mut e: E) {
         E::V(ref mut x, _) => x,
         E::W => panic!(),
     };
-    match e { // OK, no access of borrowed data
+    match e { // Don't know that E uses a tag for its discriminant
         _ if false => (),
-        E::V(_, r) => (),
+        E::V(_, r) => (), //~ ERROR
         E::W => (),
     }
     x;
@@ -59,9 +59,9 @@ fn indirect_enum_example(mut f: &mut E) {
         E::V(ref mut x, _) => x,
         E::W => panic!(),
     };
-    match f { // OK, no access of borrowed data
+    match f { // Don't know that E uses a tag for its discriminant
         _ if false => (),
-        E::V(_, r) => (),
+        E::V(_, r) => (), //~ ERROR
         E::W => (),
     }
     x;
diff --git a/src/test/ui/nll/match-on-borrowed.stderr b/src/test/ui/nll/match-on-borrowed.stderr
index cdff29d44b8..2d34dd7805d 100644
--- a/src/test/ui/nll/match-on-borrowed.stderr
+++ b/src/test/ui/nll/match-on-borrowed.stderr
@@ -1,3 +1,27 @@
+error[E0503]: cannot use `e` because it was mutably borrowed
+  --> $DIR/match-on-borrowed.rs:51:9
+   |
+LL |         E::V(ref mut x, _) => x,
+   |              --------- borrow of `e.0` occurs here
+...
+LL |         E::V(_, r) => (), //~ ERROR
+   |         ^^^^^^^^^^ use of borrowed `e.0`
+...
+LL |     x;
+   |     - borrow later used here
+
+error[E0503]: cannot use `*f` because it was mutably borrowed
+  --> $DIR/match-on-borrowed.rs:64:9
+   |
+LL |         E::V(ref mut x, _) => x,
+   |              --------- borrow of `f.0` occurs here
+...
+LL |         E::V(_, r) => (), //~ ERROR
+   |         ^^^^^^^^^^ use of borrowed `f.0`
+...
+LL |     x;
+   |     - borrow later used here
+
 error[E0503]: cannot use `t` because it was mutably borrowed
   --> $DIR/match-on-borrowed.rs:82:9
    |
@@ -16,7 +40,7 @@ error[E0381]: use of possibly uninitialized variable: `n`
 LL |     match n {} //~ ERROR
    |           ^ use of possibly uninitialized `n`
 
-error: aborting due to 2 previous errors
+error: aborting due to 4 previous errors
 
 Some errors occurred: E0381, E0503.
 For more information about an error, try `rustc --explain E0381`.