Skip to content

Commit d91032a

Browse files
authored
Rollup merge of rust-lang#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 rust-lang#45045) so migrate mode should prevent this from being immediately breaking. r? @nikomatsakis Fixes rust-lang#56797
2 parents f1fa9d4 + cdd5373 commit d91032a

File tree

6 files changed

+73
-24
lines changed

6 files changed

+73
-24
lines changed

src/librustc_mir/borrow_check/mod.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
545545
self.mutate_place(
546546
ContextKind::SetDiscrim.new(location),
547547
(place, span),
548-
Shallow(Some(ArtificialField::Discriminant)),
548+
Shallow(None),
549549
JustWrite,
550550
flow_state,
551551
);
@@ -782,7 +782,6 @@ use self::AccessDepth::{Deep, Shallow};
782782

783783
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
784784
enum ArtificialField {
785-
Discriminant,
786785
ArrayLength,
787786
ShallowBorrow,
788787
}
@@ -1191,14 +1190,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
11911190

11921191
Rvalue::Len(ref place) | Rvalue::Discriminant(ref place) => {
11931192
let af = match *rvalue {
1194-
Rvalue::Len(..) => ArtificialField::ArrayLength,
1195-
Rvalue::Discriminant(..) => ArtificialField::Discriminant,
1193+
Rvalue::Len(..) => Some(ArtificialField::ArrayLength),
1194+
Rvalue::Discriminant(..) => None,
11961195
_ => unreachable!(),
11971196
};
11981197
self.access_place(
11991198
context,
12001199
(place, span),
1201-
(Shallow(Some(af)), Read(ReadKind::Copy)),
1200+
(Shallow(af), Read(ReadKind::Copy)),
12021201
LocalMutationIsAllowed::No,
12031202
flow_state,
12041203
);

src/librustc_mir/borrow_check/nll/invalidation.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ impl<'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx, 'gcx> {
9999
self.mutate_place(
100100
ContextKind::SetDiscrim.new(location),
101101
place,
102-
Shallow(Some(ArtificialField::Discriminant)),
102+
Shallow(None),
103103
JustWrite,
104104
);
105105
}
@@ -360,14 +360,14 @@ impl<'cg, 'cx, 'tcx, 'gcx> InvalidationGenerator<'cx, 'tcx, 'gcx> {
360360

361361
Rvalue::Len(ref place) | Rvalue::Discriminant(ref place) => {
362362
let af = match *rvalue {
363-
Rvalue::Len(..) => ArtificialField::ArrayLength,
364-
Rvalue::Discriminant(..) => ArtificialField::Discriminant,
363+
Rvalue::Len(..) => Some(ArtificialField::ArrayLength),
364+
Rvalue::Discriminant(..) => None,
365365
_ => unreachable!(),
366366
};
367367
self.access_place(
368368
context,
369369
place,
370-
(Shallow(Some(af)), Read(ReadKind::Copy)),
370+
(Shallow(af), Read(ReadKind::Copy)),
371371
LocalMutationIsAllowed::No,
372372
);
373373
}

src/librustc_mir/borrow_check/places_conflict.rs

+5-8
Original file line numberDiff line numberDiff line change
@@ -165,15 +165,12 @@ fn place_components_conflict<'gcx, 'tcx>(
165165
let base_ty = base.ty(mir, tcx).to_ty(tcx);
166166

167167
match (elem, &base_ty.sty, access) {
168-
(_, _, Shallow(Some(ArtificialField::Discriminant)))
169-
| (_, _, Shallow(Some(ArtificialField::ArrayLength)))
168+
(_, _, Shallow(Some(ArtificialField::ArrayLength)))
170169
| (_, _, Shallow(Some(ArtificialField::ShallowBorrow))) => {
171-
// The discriminant and array length are like
172-
// additional fields on the type; they do not
173-
// overlap any existing data there. Furthermore,
174-
// they cannot actually be a prefix of any
175-
// borrowed place (at least in MIR as it is
176-
// currently.)
170+
// The array length is like additional fields on the
171+
// type; it does not overlap any existing data there.
172+
// Furthermore, if cannot actually be a prefix of any
173+
// borrowed place (at least in MIR as it is currently.)
177174
//
178175
// e.g., a (mutable) borrow of `a[5]` while we read the
179176
// array length of `a`.

src/test/ui/borrowck/borrowck-anon-fields-variant.nll.stderr

+31-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,31 @@
1+
warning[E0503]: cannot use `y` because it was mutably borrowed
2+
--> $DIR/borrowck-anon-fields-variant.rs:27:7
3+
|
4+
LL | Foo::Y(ref mut a, _) => a,
5+
| --------- borrow of `y.0` occurs here
6+
...
7+
LL | Foo::Y(_, ref mut b) => b,
8+
| ^^^^^^^^^^^^^^^^^^^^ use of borrowed `y.0`
9+
...
10+
LL | *a += 1;
11+
| ------- borrow later used here
12+
|
13+
= warning: This error has been downgraded to a warning for backwards compatibility with previous releases.
14+
It represents potential unsoundness in your code.
15+
This warning will become a hard error in the future.
16+
17+
error[E0503]: cannot use `y` because it was mutably borrowed
18+
--> $DIR/borrowck-anon-fields-variant.rs:44:7
19+
|
20+
LL | Foo::Y(ref mut a, _) => a,
21+
| --------- borrow of `y.0` occurs here
22+
...
23+
LL | Foo::Y(ref mut b, _) => b, //~ ERROR cannot borrow
24+
| ^^^^^^^^^^^^^^^^^^^^ use of borrowed `y.0`
25+
...
26+
LL | *a += 1;
27+
| ------- borrow later used here
28+
129
error[E0499]: cannot borrow `y.0` as mutable more than once at a time
230
--> $DIR/borrowck-anon-fields-variant.rs:44:14
331
|
@@ -10,6 +38,7 @@ LL | Foo::Y(ref mut b, _) => b, //~ ERROR cannot borrow
1038
LL | *a += 1;
1139
| ------- first borrow later used here
1240

13-
error: aborting due to previous error
41+
error: aborting due to 2 previous errors
1442

15-
For more information about this error, try `rustc --explain E0499`.
43+
Some errors occurred: E0499, E0503.
44+
For more information about an error, try `rustc --explain E0499`.

src/test/ui/nll/match-on-borrowed.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@ fn enum_example(mut e: E) {
4646
E::V(ref mut x, _) => x,
4747
E::W => panic!(),
4848
};
49-
match e { // OK, no access of borrowed data
49+
match e { // Don't know that E uses a tag for its discriminant
5050
_ if false => (),
51-
E::V(_, r) => (),
51+
E::V(_, r) => (), //~ ERROR
5252
E::W => (),
5353
}
5454
x;
@@ -59,9 +59,9 @@ fn indirect_enum_example(mut f: &mut E) {
5959
E::V(ref mut x, _) => x,
6060
E::W => panic!(),
6161
};
62-
match f { // OK, no access of borrowed data
62+
match f { // Don't know that E uses a tag for its discriminant
6363
_ if false => (),
64-
E::V(_, r) => (),
64+
E::V(_, r) => (), //~ ERROR
6565
E::W => (),
6666
}
6767
x;

src/test/ui/nll/match-on-borrowed.stderr

+25-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,27 @@
1+
error[E0503]: cannot use `e` because it was mutably borrowed
2+
--> $DIR/match-on-borrowed.rs:51:9
3+
|
4+
LL | E::V(ref mut x, _) => x,
5+
| --------- borrow of `e.0` occurs here
6+
...
7+
LL | E::V(_, r) => (), //~ ERROR
8+
| ^^^^^^^^^^ use of borrowed `e.0`
9+
...
10+
LL | x;
11+
| - borrow later used here
12+
13+
error[E0503]: cannot use `*f` because it was mutably borrowed
14+
--> $DIR/match-on-borrowed.rs:64:9
15+
|
16+
LL | E::V(ref mut x, _) => x,
17+
| --------- borrow of `f.0` occurs here
18+
...
19+
LL | E::V(_, r) => (), //~ ERROR
20+
| ^^^^^^^^^^ use of borrowed `f.0`
21+
...
22+
LL | x;
23+
| - borrow later used here
24+
125
error[E0503]: cannot use `t` because it was mutably borrowed
226
--> $DIR/match-on-borrowed.rs:82:9
327
|
@@ -16,7 +40,7 @@ error[E0381]: use of possibly uninitialized variable: `n`
1640
LL | match n {} //~ ERROR
1741
| ^ use of possibly uninitialized `n`
1842

19-
error: aborting due to 2 previous errors
43+
error: aborting due to 4 previous errors
2044

2145
Some errors occurred: E0381, E0503.
2246
For more information about an error, try `rustc --explain E0381`.

0 commit comments

Comments
 (0)