Skip to content

Commit

Permalink
Unrolled build for rust-lang#135379
Browse files Browse the repository at this point in the history
Rollup merge of rust-lang#135379 - steffahn:uniquerc-invariant, r=Mark-Simulacrum

Make (unstable API) `UniqueRc` invariant for soundness

Add test case from rust-lang#133572 (comment) (comment in review of `UniqueArc`), and fix the issue for `UniqueRc`.
  • Loading branch information
rust-timer authored Jan 12, 2025
2 parents 13f3924 + df57d65 commit 4373e01
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 2 deletions.
8 changes: 6 additions & 2 deletions library/alloc/src/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}

Expand Down Expand Up @@ -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 }
}
}

Expand Down
27 changes: 27 additions & 0 deletions tests/ui/variance/variance-uniquerc.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 15 additions & 0 deletions tests/ui/variance/variance-uniquerc.stderr
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 4373e01

Please sign in to comment.