Skip to content

Commit e6e4f7e

Browse files
committed
Auto merge of #112070 - lcnr:disjoint-closure-capture-ub, r=oli-obk
change `BorrowKind::Unique` to be a mutating `PlaceContext` fixes #112056 I believe that `BorrowKind::Unique` is a footgun in general, so I added a FIXME and opened #112072. This is a bit too involved for this PR though.
2 parents 9610dfe + 25f8f4c commit e6e4f7e

File tree

14 files changed

+90
-19
lines changed

14 files changed

+90
-19
lines changed

compiler/rustc_borrowck/src/def_use.rs

-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ pub fn categorize(context: PlaceContext) -> Option<DefUse> {
5050
PlaceContext::MutatingUse(MutatingUseContext::Borrow) |
5151
PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow) |
5252
PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow) |
53-
PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow) |
5453

5554
// `PlaceMention` and `AscribeUserType` both evaluate the place, which must not
5655
// contain dangling references.

compiler/rustc_borrowck/src/type_check/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -766,8 +766,8 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
766766
PlaceContext::MutatingUse(_) => ty::Invariant,
767767
PlaceContext::NonUse(StorageDead | StorageLive | VarDebugInfo) => ty::Invariant,
768768
PlaceContext::NonMutatingUse(
769-
Inspect | Copy | Move | PlaceMention | SharedBorrow | ShallowBorrow | UniqueBorrow
770-
| AddressOf | Projection,
769+
Inspect | Copy | Move | PlaceMention | SharedBorrow | ShallowBorrow | AddressOf
770+
| Projection,
771771
) => ty::Covariant,
772772
PlaceContext::NonUse(AscribeUserTy(variance)) => variance,
773773
}

compiler/rustc_codegen_ssa/src/mir/analyze.rs

-1
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,6 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
234234
| PlaceContext::NonMutatingUse(
235235
NonMutatingUseContext::Inspect
236236
| NonMutatingUseContext::SharedBorrow
237-
| NonMutatingUseContext::UniqueBorrow
238237
| NonMutatingUseContext::ShallowBorrow
239238
| NonMutatingUseContext::AddressOf
240239
| NonMutatingUseContext::Projection,

compiler/rustc_const_eval/src/transform/check_consts/check.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -412,9 +412,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
412412
BorrowKind::Shallow => {
413413
PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow)
414414
}
415-
BorrowKind::Unique => {
416-
PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow)
417-
}
415+
BorrowKind::Unique => PlaceContext::MutatingUse(MutatingUseContext::Borrow),
418416
BorrowKind::Mut { .. } => {
419417
PlaceContext::MutatingUse(MutatingUseContext::Borrow)
420418
}

compiler/rustc_middle/src/mir/syntax.rs

+5
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,11 @@ pub enum BorrowKind {
220220
/// immutable, but not aliasable. This solves the problem. For
221221
/// simplicity, we don't give users the way to express this
222222
/// borrow, it's just used when translating closures.
223+
///
224+
// FIXME(#112072): This is wrong. Unique borrows are mutable borrows except
225+
// that they do not require their pointee to be marked as a mutable.
226+
// They should still be treated as mutable borrows in every other way,
227+
// e.g. for variance or overlap checking.
223228
Unique,
224229

225230
/// Data is mutable and not aliasable.

compiler/rustc_middle/src/mir/visit.rs

+3-7
Original file line numberDiff line numberDiff line change
@@ -650,8 +650,8 @@ macro_rules! make_mir_visitor {
650650
BorrowKind::Shallow => PlaceContext::NonMutatingUse(
651651
NonMutatingUseContext::ShallowBorrow
652652
),
653-
BorrowKind::Unique => PlaceContext::NonMutatingUse(
654-
NonMutatingUseContext::UniqueBorrow
653+
BorrowKind::Unique => PlaceContext::MutatingUse(
654+
MutatingUseContext::Borrow
655655
),
656656
BorrowKind::Mut { .. } =>
657657
PlaceContext::MutatingUse(MutatingUseContext::Borrow),
@@ -1265,8 +1265,6 @@ pub enum NonMutatingUseContext {
12651265
SharedBorrow,
12661266
/// Shallow borrow.
12671267
ShallowBorrow,
1268-
/// Unique borrow.
1269-
UniqueBorrow,
12701268
/// AddressOf for *const pointer.
12711269
AddressOf,
12721270
/// PlaceMention statement.
@@ -1345,9 +1343,7 @@ impl PlaceContext {
13451343
matches!(
13461344
self,
13471345
PlaceContext::NonMutatingUse(
1348-
NonMutatingUseContext::SharedBorrow
1349-
| NonMutatingUseContext::ShallowBorrow
1350-
| NonMutatingUseContext::UniqueBorrow
1346+
NonMutatingUseContext::SharedBorrow | NonMutatingUseContext::ShallowBorrow
13511347
) | PlaceContext::MutatingUse(MutatingUseContext::Borrow)
13521348
)
13531349
}

compiler/rustc_mir_dataflow/src/impls/liveness.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -199,8 +199,7 @@ impl DefUse {
199199
| NonMutatingUseContext::Move
200200
| NonMutatingUseContext::PlaceMention
201201
| NonMutatingUseContext::ShallowBorrow
202-
| NonMutatingUseContext::SharedBorrow
203-
| NonMutatingUseContext::UniqueBorrow,
202+
| NonMutatingUseContext::SharedBorrow,
204203
) => Some(DefUse::Use),
205204

206205
PlaceContext::MutatingUse(MutatingUseContext::Projection)

compiler/rustc_mir_transform/src/const_prop.rs

-1
Original file line numberDiff line numberDiff line change
@@ -772,7 +772,6 @@ impl<'tcx> Visitor<'tcx> for CanConstProp {
772772
// mutation.
773773
| NonMutatingUse(NonMutatingUseContext::SharedBorrow)
774774
| NonMutatingUse(NonMutatingUseContext::ShallowBorrow)
775-
| NonMutatingUse(NonMutatingUseContext::UniqueBorrow)
776775
| NonMutatingUse(NonMutatingUseContext::AddressOf)
777776
| MutatingUse(MutatingUseContext::Borrow)
778777
| MutatingUse(MutatingUseContext::AddressOf) => {

compiler/rustc_mir_transform/src/copy_prop.rs

-1
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,6 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> {
130130
PlaceContext::NonMutatingUse(
131131
NonMutatingUseContext::SharedBorrow
132132
| NonMutatingUseContext::ShallowBorrow
133-
| NonMutatingUseContext::UniqueBorrow
134133
| NonMutatingUseContext::AddressOf,
135134
) => true,
136135
// For debuginfo, merging locals is ok.

compiler/rustc_mir_transform/src/ssa.rs

-1
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,6 @@ impl<'tcx> Visitor<'tcx> for SsaVisitor<'_> {
216216
PlaceContext::NonMutatingUse(
217217
NonMutatingUseContext::SharedBorrow
218218
| NonMutatingUseContext::ShallowBorrow
219-
| NonMutatingUseContext::UniqueBorrow
220219
| NonMutatingUseContext::AddressOf,
221220
)
222221
| PlaceContext::MutatingUse(_) => {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// edition:2021
2+
3+
// regression test for #112056
4+
5+
fn extend_lifetime<'a, 'b>(x: &mut (&'a str,), y: &'b str) {
6+
let mut closure = |input| x.0 = input;
7+
//~^ ERROR: lifetime may not live long enough
8+
closure(y);
9+
}
10+
11+
fn main() {
12+
let mut tuple = ("static",);
13+
{
14+
let x = String::from("temporary");
15+
extend_lifetime(&mut tuple, &x);
16+
}
17+
println!("{}", tuple.0);
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: lifetime may not live long enough
2+
--> $DIR/unique-borrows-are-invariant-1.rs:6:31
3+
|
4+
LL | fn extend_lifetime<'a, 'b>(x: &mut (&'a str,), y: &'b str) {
5+
| -- -- lifetime `'b` defined here
6+
| |
7+
| lifetime `'a` defined here
8+
LL | let mut closure = |input| x.0 = input;
9+
| ^^^^^^^^^^^ assignment requires that `'b` must outlive `'a`
10+
|
11+
= help: consider adding the following bound: `'b: 'a`
12+
13+
error: aborting due to previous error
14+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// edition:2021
2+
3+
// regression test for #112056
4+
5+
struct Spooky<'b> {
6+
owned: Option<&'static u32>,
7+
borrowed: &'b &'static u32,
8+
}
9+
10+
impl<'b> Spooky<'b> {
11+
fn create_self_reference<'a>(&'a mut self) {
12+
let mut closure = || {
13+
if let Some(owned) = &self.owned {
14+
let borrow: &'a &'static u32 = owned;
15+
self.borrowed = borrow;
16+
//~^ ERROR: lifetime may not live long enough
17+
}
18+
};
19+
closure();
20+
}
21+
}
22+
23+
fn main() {
24+
let mut spooky: Spooky<'static> = Spooky {
25+
owned: Some(&1),
26+
borrowed: &&1,
27+
};
28+
spooky.create_self_reference();
29+
spooky.owned = None;
30+
println!("{}", **spooky.borrowed);
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error: lifetime may not live long enough
2+
--> $DIR/unique-borrows-are-invariant-2.rs:15:17
3+
|
4+
LL | impl<'b> Spooky<'b> {
5+
| -- lifetime `'b` defined here
6+
LL | fn create_self_reference<'a>(&'a mut self) {
7+
| -- lifetime `'a` defined here
8+
...
9+
LL | self.borrowed = borrow;
10+
| ^^^^^^^^^^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b`
11+
|
12+
= help: consider adding the following bound: `'a: 'b`
13+
14+
error: aborting due to previous error
15+

0 commit comments

Comments
 (0)