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
This commit is contained in:
Mazdak Farrokhzad 2018-12-16 14:08:29 +01:00 committed by GitHub
commit d91032a9ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 73 additions and 24 deletions

View File

@ -545,7 +545,7 @@ fn visit_statement_entry(
self.mutate_place(
ContextKind::SetDiscrim.new(location),
(place, span),
Shallow(Some(ArtificialField::Discriminant)),
Shallow(None),
JustWrite,
flow_state,
);
@ -782,7 +782,6 @@ enum MutateMode {
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
enum ArtificialField {
Discriminant,
ArrayLength,
ShallowBorrow,
}
@ -1191,14 +1190,14 @@ fn consume_rvalue(
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,
);

View File

@ -99,7 +99,7 @@ fn visit_statement(&mut self,
self.mutate_place(
ContextKind::SetDiscrim.new(location),
place,
Shallow(Some(ArtificialField::Discriminant)),
Shallow(None),
JustWrite,
);
}
@ -360,14 +360,14 @@ fn consume_rvalue(
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,
);
}

View File

@ -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`.

View File

@ -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`.

View File

@ -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;

View File

@ -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`.