Make UniqueRc invariant for soundness
This commit is contained in:
parent
fb65a3ee57
commit
df57d65c70
3 changed files with 48 additions and 2 deletions
|
|
@ -3708,7 +3708,11 @@ pub struct UniqueRc<
|
|||
#[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
|
||||
> {
|
||||
ptr: NonNull<RcInner<T>>,
|
||||
phantom: PhantomData<RcInner<T>>,
|
||||
// Define the ownership of `RcInner<T>` for drop-check
|
||||
_marker: PhantomData<RcInner<T>>,
|
||||
// Invariance is necessary for soundness: once other `Weak`
|
||||
// references exist, we already have a form of shared mutability!
|
||||
_marker2: PhantomData<*mut T>,
|
||||
alloc: A,
|
||||
}
|
||||
|
||||
|
|
@ -3994,7 +3998,7 @@ impl<T, A: Allocator> UniqueRc<T, A> {
|
|||
},
|
||||
alloc,
|
||||
));
|
||||
Self { ptr: ptr.into(), phantom: PhantomData, alloc }
|
||||
Self { ptr: ptr.into(), _marker: PhantomData, _marker2: PhantomData, alloc }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
27
tests/ui/variance/variance-uniquerc.rs
Normal file
27
tests/ui/variance/variance-uniquerc.rs
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
// regression test of https://github.com/rust-lang/rust/pull/133572#issuecomment-2543007164
|
||||
// we should also test UniqueArc once implemented
|
||||
//
|
||||
// inline comments explain how this code *would* compile if UniqueRc was still covariant
|
||||
|
||||
#![feature(unique_rc_arc)]
|
||||
|
||||
use std::rc::UniqueRc;
|
||||
|
||||
fn extend_lifetime<'a, 'b>(x: &'a str) -> &'b str {
|
||||
let r = UniqueRc::new(""); // UniqueRc<&'static str>
|
||||
let w = UniqueRc::downgrade(&r); // Weak<&'static str>
|
||||
let mut r = r; // [IF COVARIANT]: ==>> UniqueRc<&'a str>
|
||||
*r = x; // assign the &'a str
|
||||
let _r = UniqueRc::into_rc(r); // Rc<&'a str>, but we only care to activate the weak
|
||||
let r = w.upgrade().unwrap(); // Rc<&'static str>
|
||||
*r // &'static str, coerces to &'b str
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let s = String::from("Hello World!");
|
||||
let r = extend_lifetime(&s);
|
||||
println!("{r}");
|
||||
drop(s);
|
||||
println!("{r}");
|
||||
}
|
||||
15
tests/ui/variance/variance-uniquerc.stderr
Normal file
15
tests/ui/variance/variance-uniquerc.stderr
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
error: lifetime may not live long enough
|
||||
--> $DIR/variance-uniquerc.rs:17:5
|
||||
|
|
||||
LL | fn extend_lifetime<'a, 'b>(x: &'a str) -> &'b str {
|
||||
| -- -- lifetime `'b` defined here
|
||||
| |
|
||||
| lifetime `'a` defined here
|
||||
...
|
||||
LL | *r // &'static str, coerces to &'b str
|
||||
| ^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
|
||||
|
|
||||
= help: consider adding the following bound: `'a: 'b`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue