Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 15 pull requests #76317

Closed
wants to merge 38 commits into from
Closed
Changes from 1 commit
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
18ad5a5
Add a regression test for issue-72793
JohnTitor Aug 19, 2020
aa40c02
Unstable Book: add links to tracking issues for FFI features
ArekPiekarz Aug 26, 2020
f03d0b3
`impl Rc::new_cyclic`
mental32 Aug 27, 2020
42fb270
typo
mental32 Aug 29, 2020
bb5e79c
Link vec doc to & reference
pickfire Aug 29, 2020
20a6866
Try removing [prim@reference]
pickfire Aug 30, 2020
81e85ce
Move to Arc::clone(&x) over x.clone() in library/std
poliorcetics Aug 30, 2020
6b75e3d
Move to Arc::clone(&x) over x.clone() in library/core
poliorcetics Aug 30, 2020
0f301e8
Removed [inline] and copied over comments from Arc::new_cyclic
mental32 Sep 1, 2020
acac5c6
Add regression test
JulianKnodt Sep 2, 2020
8783c62
Add missing link in README
camelid Sep 2, 2020
3e29fdb
Remove a number of vec UI tests, make them unit tests in the alloc li…
CraftSpider Sep 3, 2020
791f93c
Allow try blocks as the argument to return expressions
scottmcm Sep 3, 2020
4231fbc
Condense StringReader's API to a single function
matklad Sep 3, 2020
4df6490
Link & primitive using relative link
pickfire Sep 3, 2020
ccf41dd
Rename IsJoint -> Spacing
matklad Sep 3, 2020
c6ab3ff
Add test for checking if-let or-patterns
JulianKnodt Aug 16, 2020
2278c72
Remove vec-to_str.rs, merge the remaining test in with vec
CraftSpider Sep 3, 2020
a2e077e
Make `Ipv4Addr` and `Ipv6Addr` const tests unit tests under `library`
CDirkx Sep 3, 2020
8c93125
Address review comments on `Peekable::next_if`
jyn514 Sep 3, 2020
7b823df
Link to `#capacity-and-reallocation` when using with_capacity
jyn514 Sep 3, 2020
538e198
Move various ui const tests to `library`
CDirkx Sep 4, 2020
85146b9
Add slice primitive link to vec
pickfire Sep 4, 2020
e1307f3
Rollup merge of #75580 - JulianKnodt:or_pattern, r=wesleywiser
matklad Sep 4, 2020
eb565f2
Rollup merge of #75695 - JohnTitor:regression-test, r=Dylan-DPC
matklad Sep 4, 2020
b3b9800
Rollup merge of #75954 - ArekPiekarz:unstable_book_ffi_tracking_issue…
matklad Sep 4, 2020
782fbd3
Rollup merge of #75994 - mental32:impl-rc-new-cyclic, r=KodrAus
matklad Sep 4, 2020
a741240
Rollup merge of #76060 - pickfire:patch-12, r=jyn514
matklad Sep 4, 2020
89a562b
Rollup merge of #76128 - poliorcetics:doc-use-arc-clone, r=KodrAus
matklad Sep 4, 2020
388e04d
Rollup merge of #76229 - camelid:patch-3, r=jonas-schievink
matklad Sep 4, 2020
64e87ec
Rollup merge of #76257 - JulianKnodt:i75777, r=Dylan-DPC
matklad Sep 4, 2020
8bda38e
Rollup merge of #76273 - CraftSpider:master, r=matklad
matklad Sep 4, 2020
8fae813
Rollup merge of #76274 - scottmcm:fix-76271, r=petrochenkov
matklad Sep 4, 2020
ca0210b
Rollup merge of #76291 - matklad:spacing, r=petrochenkov
matklad Sep 4, 2020
0ca512e
Rollup merge of #76299 - CDirkx:ip-tests, r=matklad
matklad Sep 4, 2020
cc7f1aa
Rollup merge of #76302 - jyn514:peekable-2, r=Dylan-DPC
matklad Sep 4, 2020
d5b20e6
Rollup merge of #76303 - jyn514:vec-assert-doc, r=Dylan-DPC
matklad Sep 4, 2020
02d1654
Rollup merge of #76305 - CDirkx:const-tests, r=matklad
matklad Sep 4, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions library/alloc/src/rc.rs
Original file line number Diff line number Diff line change
@@ -325,6 +325,40 @@ impl<T> Rc<T> {
)
}

/// Constructs a new `Rc<T>` using a weak reference to itself. Attempting
/// to upgrade the weak reference before this function retuns will result
/// in a `None` value. However, the weak reference may be cloned freely and
/// stored for use at a later time.
#[inline]
#[unstable(feature = "arc_new_cyclic", issue = "75861")]
pub fn new_cyclic(data_fn: impl FnOnce(&Weak<T>) -> T) -> Rc<T> {
let uninit_ptr: NonNull<_> = Box::leak(box RcBox {
strong: Cell::new(0),
weak: Cell::new(1),
value: mem::MaybeUninit::<T>::uninit(),
})
.into();

let init_ptr: NonNull<RcBox<T>> = uninit_ptr.cast();

let weak = Weak { ptr: init_ptr };

let data = data_fn(&weak);

unsafe {
let inner = init_ptr.as_ptr();
ptr::write(&raw mut (*inner).value, data);

let prev_value = (*inner).strong.get();
debug_assert_eq!(prev_value, 0, "No prior strong references should exist");
(*inner).strong.set(1);
}

let strong = Rc::from_inner(init_ptr);
mem::forget(weak);
strong
}

/// Constructs a new `Rc` with uninitialized contents.
///
/// # Examples
66 changes: 66 additions & 0 deletions library/alloc/src/rc/tests.rs
Original file line number Diff line number Diff line change
@@ -434,3 +434,69 @@ fn test_array_from_slice() {
let a: Result<Rc<[u32; 2]>, _> = r.clone().try_into();
assert!(a.is_err());
}

#[test]
fn test_rc_cyclic_with_zero_refs() {
struct ZeroRefs {
inner: Weak<ZeroRefs>,
}

let zero_refs = Rc::new_cyclic(|inner| {
assert_eq!(inner.strong_count(), 0);
assert!(inner.upgrade().is_none());
ZeroRefs { inner: Weak::new() }
});

assert_eq!(Rc::strong_count(&zero_refs), 1);
assert_eq!(Rc::weak_count(&zero_refs), 0);
assert_eq!(zero_refs.inner.strong_count(), 0);
assert_eq!(zero_refs.inner.weak_count(), 0);
}

#[test]
fn test_rc_cyclic_with_one_ref() {
struct OneRef {
inner: Weak<OneRef>,
}

let one_ref = Rc::new_cyclic(|inner| {
assert_eq!(inner.strong_count(), 0);
assert!(inner.upgrade().is_none());
OneRef { inner: inner.clone() }
});

assert_eq!(Rc::strong_count(&one_ref), 1);
assert_eq!(Rc::weak_count(&one_ref), 1);

let one_ref2 = Weak::upgrade(&one_ref.inner).unwrap();
assert!(Rc::ptr_eq(&one_ref, &one_ref2));

assert_eq!(one_ref.inner.strong_count(), 2);
assert_eq!(one_ref.inner.weak_count(), 1);
}

#[test]
fn test_rc_cyclic_with_two_ref() {
struct TwoRefs {
inner: Weak<TwoRefs>,
inner1: Weak<TwoRefs>,
}

let two_refs = Rc::new_cyclic(|inner| {
assert_eq!(inner.strong_count(), 0);
assert!(inner.upgrade().is_none());
TwoRefs { inner: inner.clone(), inner1: inner.clone() }
});

assert_eq!(Rc::strong_count(&two_refs), 1);
assert_eq!(Rc::weak_count(&two_refs), 2);

let two_ref3 = Weak::upgrade(&two_refs.inner).unwrap();
assert!(Rc::ptr_eq(&two_refs, &two_ref3));

let two_ref2 = Weak::upgrade(&two_refs.inner1).unwrap();
assert!(Rc::ptr_eq(&two_refs, &two_ref2));

assert_eq!(Rc::strong_count(&two_refs), 3);
assert_eq!(Rc::weak_count(&two_refs), 2);
}