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 https://github.com/rust-lang/rust/issues/112072. This is a bit too involved for this PR though.
This commit is contained in:
commit
e6e4f7ed15
14 changed files with 90 additions and 19 deletions
|
@ -50,7 +50,6 @@ pub fn categorize(context: PlaceContext) -> Option<DefUse> {
|
||||||
PlaceContext::MutatingUse(MutatingUseContext::Borrow) |
|
PlaceContext::MutatingUse(MutatingUseContext::Borrow) |
|
||||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow) |
|
PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow) |
|
||||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow) |
|
PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow) |
|
||||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow) |
|
|
||||||
|
|
||||||
// `PlaceMention` and `AscribeUserType` both evaluate the place, which must not
|
// `PlaceMention` and `AscribeUserType` both evaluate the place, which must not
|
||||||
// contain dangling references.
|
// contain dangling references.
|
||||||
|
|
|
@ -766,8 +766,8 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
||||||
PlaceContext::MutatingUse(_) => ty::Invariant,
|
PlaceContext::MutatingUse(_) => ty::Invariant,
|
||||||
PlaceContext::NonUse(StorageDead | StorageLive | VarDebugInfo) => ty::Invariant,
|
PlaceContext::NonUse(StorageDead | StorageLive | VarDebugInfo) => ty::Invariant,
|
||||||
PlaceContext::NonMutatingUse(
|
PlaceContext::NonMutatingUse(
|
||||||
Inspect | Copy | Move | PlaceMention | SharedBorrow | ShallowBorrow | UniqueBorrow
|
Inspect | Copy | Move | PlaceMention | SharedBorrow | ShallowBorrow | AddressOf
|
||||||
| AddressOf | Projection,
|
| Projection,
|
||||||
) => ty::Covariant,
|
) => ty::Covariant,
|
||||||
PlaceContext::NonUse(AscribeUserTy(variance)) => variance,
|
PlaceContext::NonUse(AscribeUserTy(variance)) => variance,
|
||||||
}
|
}
|
||||||
|
|
|
@ -234,7 +234,6 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
|
||||||
| PlaceContext::NonMutatingUse(
|
| PlaceContext::NonMutatingUse(
|
||||||
NonMutatingUseContext::Inspect
|
NonMutatingUseContext::Inspect
|
||||||
| NonMutatingUseContext::SharedBorrow
|
| NonMutatingUseContext::SharedBorrow
|
||||||
| NonMutatingUseContext::UniqueBorrow
|
|
||||||
| NonMutatingUseContext::ShallowBorrow
|
| NonMutatingUseContext::ShallowBorrow
|
||||||
| NonMutatingUseContext::AddressOf
|
| NonMutatingUseContext::AddressOf
|
||||||
| NonMutatingUseContext::Projection,
|
| NonMutatingUseContext::Projection,
|
||||||
|
|
|
@ -412,9 +412,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
||||||
BorrowKind::Shallow => {
|
BorrowKind::Shallow => {
|
||||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow)
|
PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow)
|
||||||
}
|
}
|
||||||
BorrowKind::Unique => {
|
BorrowKind::Unique => PlaceContext::MutatingUse(MutatingUseContext::Borrow),
|
||||||
PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow)
|
|
||||||
}
|
|
||||||
BorrowKind::Mut { .. } => {
|
BorrowKind::Mut { .. } => {
|
||||||
PlaceContext::MutatingUse(MutatingUseContext::Borrow)
|
PlaceContext::MutatingUse(MutatingUseContext::Borrow)
|
||||||
}
|
}
|
||||||
|
|
|
@ -220,6 +220,11 @@ pub enum BorrowKind {
|
||||||
/// immutable, but not aliasable. This solves the problem. For
|
/// immutable, but not aliasable. This solves the problem. For
|
||||||
/// simplicity, we don't give users the way to express this
|
/// simplicity, we don't give users the way to express this
|
||||||
/// borrow, it's just used when translating closures.
|
/// borrow, it's just used when translating closures.
|
||||||
|
///
|
||||||
|
// FIXME(#112072): This is wrong. Unique borrows are mutable borrows except
|
||||||
|
// that they do not require their pointee to be marked as a mutable.
|
||||||
|
// They should still be treated as mutable borrows in every other way,
|
||||||
|
// e.g. for variance or overlap checking.
|
||||||
Unique,
|
Unique,
|
||||||
|
|
||||||
/// Data is mutable and not aliasable.
|
/// Data is mutable and not aliasable.
|
||||||
|
|
|
@ -650,8 +650,8 @@ macro_rules! make_mir_visitor {
|
||||||
BorrowKind::Shallow => PlaceContext::NonMutatingUse(
|
BorrowKind::Shallow => PlaceContext::NonMutatingUse(
|
||||||
NonMutatingUseContext::ShallowBorrow
|
NonMutatingUseContext::ShallowBorrow
|
||||||
),
|
),
|
||||||
BorrowKind::Unique => PlaceContext::NonMutatingUse(
|
BorrowKind::Unique => PlaceContext::MutatingUse(
|
||||||
NonMutatingUseContext::UniqueBorrow
|
MutatingUseContext::Borrow
|
||||||
),
|
),
|
||||||
BorrowKind::Mut { .. } =>
|
BorrowKind::Mut { .. } =>
|
||||||
PlaceContext::MutatingUse(MutatingUseContext::Borrow),
|
PlaceContext::MutatingUse(MutatingUseContext::Borrow),
|
||||||
|
@ -1265,8 +1265,6 @@ pub enum NonMutatingUseContext {
|
||||||
SharedBorrow,
|
SharedBorrow,
|
||||||
/// Shallow borrow.
|
/// Shallow borrow.
|
||||||
ShallowBorrow,
|
ShallowBorrow,
|
||||||
/// Unique borrow.
|
|
||||||
UniqueBorrow,
|
|
||||||
/// AddressOf for *const pointer.
|
/// AddressOf for *const pointer.
|
||||||
AddressOf,
|
AddressOf,
|
||||||
/// PlaceMention statement.
|
/// PlaceMention statement.
|
||||||
|
@ -1345,9 +1343,7 @@ impl PlaceContext {
|
||||||
matches!(
|
matches!(
|
||||||
self,
|
self,
|
||||||
PlaceContext::NonMutatingUse(
|
PlaceContext::NonMutatingUse(
|
||||||
NonMutatingUseContext::SharedBorrow
|
NonMutatingUseContext::SharedBorrow | NonMutatingUseContext::ShallowBorrow
|
||||||
| NonMutatingUseContext::ShallowBorrow
|
|
||||||
| NonMutatingUseContext::UniqueBorrow
|
|
||||||
) | PlaceContext::MutatingUse(MutatingUseContext::Borrow)
|
) | PlaceContext::MutatingUse(MutatingUseContext::Borrow)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -199,8 +199,7 @@ impl DefUse {
|
||||||
| NonMutatingUseContext::Move
|
| NonMutatingUseContext::Move
|
||||||
| NonMutatingUseContext::PlaceMention
|
| NonMutatingUseContext::PlaceMention
|
||||||
| NonMutatingUseContext::ShallowBorrow
|
| NonMutatingUseContext::ShallowBorrow
|
||||||
| NonMutatingUseContext::SharedBorrow
|
| NonMutatingUseContext::SharedBorrow,
|
||||||
| NonMutatingUseContext::UniqueBorrow,
|
|
||||||
) => Some(DefUse::Use),
|
) => Some(DefUse::Use),
|
||||||
|
|
||||||
PlaceContext::MutatingUse(MutatingUseContext::Projection)
|
PlaceContext::MutatingUse(MutatingUseContext::Projection)
|
||||||
|
|
|
@ -772,7 +772,6 @@ impl<'tcx> Visitor<'tcx> for CanConstProp {
|
||||||
// mutation.
|
// mutation.
|
||||||
| NonMutatingUse(NonMutatingUseContext::SharedBorrow)
|
| NonMutatingUse(NonMutatingUseContext::SharedBorrow)
|
||||||
| NonMutatingUse(NonMutatingUseContext::ShallowBorrow)
|
| NonMutatingUse(NonMutatingUseContext::ShallowBorrow)
|
||||||
| NonMutatingUse(NonMutatingUseContext::UniqueBorrow)
|
|
||||||
| NonMutatingUse(NonMutatingUseContext::AddressOf)
|
| NonMutatingUse(NonMutatingUseContext::AddressOf)
|
||||||
| MutatingUse(MutatingUseContext::Borrow)
|
| MutatingUse(MutatingUseContext::Borrow)
|
||||||
| MutatingUse(MutatingUseContext::AddressOf) => {
|
| MutatingUse(MutatingUseContext::AddressOf) => {
|
||||||
|
|
|
@ -130,7 +130,6 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> {
|
||||||
PlaceContext::NonMutatingUse(
|
PlaceContext::NonMutatingUse(
|
||||||
NonMutatingUseContext::SharedBorrow
|
NonMutatingUseContext::SharedBorrow
|
||||||
| NonMutatingUseContext::ShallowBorrow
|
| NonMutatingUseContext::ShallowBorrow
|
||||||
| NonMutatingUseContext::UniqueBorrow
|
|
||||||
| NonMutatingUseContext::AddressOf,
|
| NonMutatingUseContext::AddressOf,
|
||||||
) => true,
|
) => true,
|
||||||
// For debuginfo, merging locals is ok.
|
// For debuginfo, merging locals is ok.
|
||||||
|
|
|
@ -216,7 +216,6 @@ impl<'tcx> Visitor<'tcx> for SsaVisitor<'_> {
|
||||||
PlaceContext::NonMutatingUse(
|
PlaceContext::NonMutatingUse(
|
||||||
NonMutatingUseContext::SharedBorrow
|
NonMutatingUseContext::SharedBorrow
|
||||||
| NonMutatingUseContext::ShallowBorrow
|
| NonMutatingUseContext::ShallowBorrow
|
||||||
| NonMutatingUseContext::UniqueBorrow
|
|
||||||
| NonMutatingUseContext::AddressOf,
|
| NonMutatingUseContext::AddressOf,
|
||||||
)
|
)
|
||||||
| PlaceContext::MutatingUse(_) => {
|
| PlaceContext::MutatingUse(_) => {
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
// edition:2021
|
||||||
|
|
||||||
|
// regression test for #112056
|
||||||
|
|
||||||
|
fn extend_lifetime<'a, 'b>(x: &mut (&'a str,), y: &'b str) {
|
||||||
|
let mut closure = |input| x.0 = input;
|
||||||
|
//~^ ERROR: lifetime may not live long enough
|
||||||
|
closure(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut tuple = ("static",);
|
||||||
|
{
|
||||||
|
let x = String::from("temporary");
|
||||||
|
extend_lifetime(&mut tuple, &x);
|
||||||
|
}
|
||||||
|
println!("{}", tuple.0);
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
error: lifetime may not live long enough
|
||||||
|
--> $DIR/unique-borrows-are-invariant-1.rs:6:31
|
||||||
|
|
|
||||||
|
LL | fn extend_lifetime<'a, 'b>(x: &mut (&'a str,), y: &'b str) {
|
||||||
|
| -- -- lifetime `'b` defined here
|
||||||
|
| |
|
||||||
|
| lifetime `'a` defined here
|
||||||
|
LL | let mut closure = |input| x.0 = input;
|
||||||
|
| ^^^^^^^^^^^ assignment requires that `'b` must outlive `'a`
|
||||||
|
|
|
||||||
|
= help: consider adding the following bound: `'b: 'a`
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
// edition:2021
|
||||||
|
|
||||||
|
// regression test for #112056
|
||||||
|
|
||||||
|
struct Spooky<'b> {
|
||||||
|
owned: Option<&'static u32>,
|
||||||
|
borrowed: &'b &'static u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'b> Spooky<'b> {
|
||||||
|
fn create_self_reference<'a>(&'a mut self) {
|
||||||
|
let mut closure = || {
|
||||||
|
if let Some(owned) = &self.owned {
|
||||||
|
let borrow: &'a &'static u32 = owned;
|
||||||
|
self.borrowed = borrow;
|
||||||
|
//~^ ERROR: lifetime may not live long enough
|
||||||
|
}
|
||||||
|
};
|
||||||
|
closure();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut spooky: Spooky<'static> = Spooky {
|
||||||
|
owned: Some(&1),
|
||||||
|
borrowed: &&1,
|
||||||
|
};
|
||||||
|
spooky.create_self_reference();
|
||||||
|
spooky.owned = None;
|
||||||
|
println!("{}", **spooky.borrowed);
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
error: lifetime may not live long enough
|
||||||
|
--> $DIR/unique-borrows-are-invariant-2.rs:15:17
|
||||||
|
|
|
||||||
|
LL | impl<'b> Spooky<'b> {
|
||||||
|
| -- lifetime `'b` defined here
|
||||||
|
LL | fn create_self_reference<'a>(&'a mut self) {
|
||||||
|
| -- lifetime `'a` defined here
|
||||||
|
...
|
||||||
|
LL | self.borrowed = borrow;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b`
|
||||||
|
|
|
||||||
|
= help: consider adding the following bound: `'a: 'b`
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue