Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
4f4f7f2
Remove giant badge in README
frewsxcv Dec 18, 2020
d2cc79e
Bring back a top level heading
frewsxcv Dec 23, 2020
6bc772c
Re-stabilize Weak::as_ptr &friends for unsized T
CAD97 Jan 6, 2021
f00b458
Tighten/clarify documentation of rc data_offset
CAD97 Jan 7, 2021
b10b9e2
Remove "pointer describes" terminology
CAD97 Jan 7, 2021
1e578c9
Reclarify Weak<->raw pointer safety comments
CAD97 Jan 7, 2021
4901c55
Replace set_data_ptr with pointer::set_ptr_value
CAD97 Jan 7, 2021
747dbcb
Provide reasoning for rc data_offset safety
CAD97 Jan 9, 2021
5ccef56
Explain why borrows can't be held across yield point in async blocks
sledgehammervampire Jan 2, 2021
12f1795
Fix location of error message explanation
sledgehammervampire Jan 2, 2021
2b9c8ff
Update issue-78938-async-block.rs
sledgehammervampire Jan 2, 2021
9e345a5
Revise async block error message
sledgehammervampire Jan 9, 2021
757bd23
Remove trailing whitespace
sledgehammervampire Jan 9, 2021
b5b6760
Weak::into_raw shouldn't translate sentinel value
CAD97 Jan 11, 2021
04b6036
Make `--color always` apply to logging too
jyn514 Jan 11, 2021
3ee3071
Update src/test/ui/async-await/issues/issue-78938-async-block.stderr
sledgehammervampire Jan 12, 2021
4362da1
Do not suggest invalid code in pattern with loop
JohnTitor Jan 12, 2021
b2f5048
stabilize the poll_map feature
KodrAus Jan 13, 2021
c200036
Put all feature gate tests under `feature-gates/`
camelid Jan 13, 2021
7f41465
Move help link to error index
sledgehammervampire Jan 13, 2021
f5c4287
Bless test output
sledgehammervampire Jan 13, 2021
a9ead34
Fix whitespace
sledgehammervampire Jan 13, 2021
c14e919
Apply suggestions from code review
CAD97 Jan 13, 2021
174135f
Fix error E0373 documentation
sledgehammervampire Jan 14, 2021
63deae5
Fix E0373 code example
sledgehammervampire Jan 14, 2021
5468d98
Simplify E0373 async code example
sledgehammervampire Jan 15, 2021
0660b8b
Introduce {Ref, RefMut}::try_map for optional projections
udoprog Oct 27, 2020
3e9c95b
Update compiler/rustc_mir/src/borrow_check/diagnostics/conflict_error…
sledgehammervampire Jan 15, 2021
e8757af
Use Result and rename to filter_map
udoprog Dec 17, 2020
e3274fd
Remove doctree::Import
CraftSpider Jan 14, 2021
2a0c9e2
Address nit
CraftSpider Jan 14, 2021
e42c1b9
Fix JSON test
CraftSpider Jan 15, 2021
31b17f5
Add warning to compare.py about error messages
CraftSpider Jan 15, 2021
af0d099
Add a regression test for #50041
nagisa Jan 14, 2021
c625b97
add tracking issue to cell_filter_map
KodrAus Jan 16, 2021
eef383f
doctest: Reset errors before dropping the parse session
osa1 Jan 15, 2021
0ef5557
Add a test
osa1 Jan 16, 2021
b681631
codegen_cranelift: Fix redundant semicolon warn
osa1 Jan 16, 2021
ae4b5a2
Add `as_rchunks` (and friends) to slices
scottmcm Nov 6, 2020
132307c
Rename as_chunks_mut_unchecked -> as_chunks_unchecked_mut
scottmcm Jan 16, 2021
8797986
Add a regression test for #76281
JohnTitor Jan 11, 2021
9952632
Add sample code for Rc::new_cyclic
ogoffart Jan 16, 2021
78d9192
Clarify what the effects of a 'logic error' are
ChrisJefferson Jan 4, 2021
bdc7ff7
Add test for #34792
bugadani Jan 16, 2021
2a950cb
Rollup merge of #78455 - udoprog:refcell-opt-map, r=KodrAus
m-ou-se Jan 16, 2021
50e048e
Rollup merge of #78818 - scottmcm:as_rchunks, r=KodrAus
m-ou-se Jan 16, 2021
3c3d5cb
Rollup merge of #80144 - rust-lang:frewsxcv-patch-3, r=nikomatsakis
m-ou-se Jan 16, 2021
7517446
Rollup merge of #80614 - 1000teslas:issue-78938-fix, r=tmandry
m-ou-se Jan 16, 2021
b8f3d64
Rollup merge of #80681 - ChrisJefferson:logic-error-doc, r=m-ou-se
m-ou-se Jan 16, 2021
708faf1
Rollup merge of #80764 - CAD97:weak-unsized-as-ptr-again, r=RalfJung
m-ou-se Jan 16, 2021
ad8b2f3
Rollup merge of #80901 - jyn514:better-colors, r=Mark-Simulacrum
m-ou-se Jan 16, 2021
78eeb20
Rollup merge of #80902 - JohnTitor:issue-76281, r=Mark-Simulacrum
m-ou-se Jan 16, 2021
cf39af8
Rollup merge of #80941 - JohnTitor:ref-mut-pat-in-loops, r=varkor
m-ou-se Jan 16, 2021
944ee6f
Rollup merge of #80968 - KodrAus:stabilize/poll_map, r=Mark-Simulacrum
m-ou-se Jan 16, 2021
9064f1a
Rollup merge of #80971 - camelid:feature-gate-testsuite-organization,…
m-ou-se Jan 16, 2021
69dd8f2
Rollup merge of #81021 - CraftSpider:rustdoc-remove-import, r=jyn514
m-ou-se Jan 16, 2021
3bc88b3
Rollup merge of #81040 - osa1:fix_80992, r=jyn514
m-ou-se Jan 16, 2021
706796c
Rollup merge of #81060 - nagisa:nagisa/regression-50041, r=Mark-Simul…
m-ou-se Jan 16, 2021
82a66d6
Rollup merge of #81065 - osa1:cranelift_semicolon_warning, r=jyn514
m-ou-se Jan 16, 2021
a481a02
Rollup merge of #81069 - ogoffart:rc_new_cyclic_doc, r=Mark-Simulacrum
m-ou-se Jan 16, 2021
ce803a1
Rollup merge of #81081 - bugadani:double-partialeq, r=Mark-Simulacrum
m-ou-se Jan 16, 2021
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
Prev Previous commit
Next Next commit
Re-stabilize Weak::as_ptr &friends for unsized T
As per T-lang consensus, this uses a branch to handle the dangling case.
The discussed optimization of only doing the branch in the T: ?Sized
case is left for a followup patch, as doing so is not trivial
(as it requires specialization for correctness, not just optimization).
  • Loading branch information
CAD97 committed Jan 7, 2021
commit 6bc772cdc0a9021a6286ebd550c2f6221179f21d
1 change: 1 addition & 0 deletions library/alloc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@
#![feature(receiver_trait)]
#![cfg_attr(bootstrap, feature(min_const_generics))]
#![feature(min_specialization)]
#![feature(set_ptr_value)]
#![feature(slice_ptr_get)]
#![feature(slice_ptr_len)]
#![feature(staged_api)]
Expand Down
41 changes: 23 additions & 18 deletions library/alloc/src/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1862,7 +1862,7 @@ struct WeakInner<'a> {
strong: &'a Cell<usize>,
}

impl<T> Weak<T> {
impl<T: ?Sized> Weak<T> {
/// Returns a raw pointer to the object `T` pointed to by this `Weak<T>`.
///
/// The pointer is valid only if there are some strong references. The pointer may be dangling,
Expand Down Expand Up @@ -1892,15 +1892,17 @@ impl<T> Weak<T> {
pub fn as_ptr(&self) -> *const T {
let ptr: *mut RcBox<T> = NonNull::as_ptr(self.ptr);

// SAFETY: we must offset the pointer manually, and said pointer may be
// a dangling weak (usize::MAX) if T is sized. data_offset is safe to call,
// because we know that a pointer to unsized T was derived from a real
// unsized T, as dangling weaks are only created for sized T. wrapping_offset
// is used so that we can use the same code path for the non-dangling
// unsized case and the potentially dangling sized case.
unsafe {
let offset = data_offset(ptr as *mut T);
set_data_ptr(ptr as *mut T, (ptr as *mut u8).wrapping_offset(offset))
if is_dangling(self.ptr) {
// If the pointer is dangling, we return a null pointer as the dangling sentinel.
// We can't return the usize::MAX sentinel, as that could valid if T is ZST.
// SAFETY: we have to return a known sentinel here that cannot be produced for
// a valid pointer, so that `from_raw` can reverse this transformation.
(ptr as *mut T).set_ptr_value(ptr::null_mut())
} else {
// SAFETY: If the pointer is not dangling, it describes to a valid allocation.
// The payload may be dropped at this point, and we have to maintain provenance,
// so use raw pointer manipulation.
unsafe { &raw mut (*ptr).value }
}
}

Expand Down Expand Up @@ -1982,22 +1984,25 @@ impl<T> Weak<T> {
/// [`new`]: Weak::new
#[stable(feature = "weak_into_raw", since = "1.45.0")]
pub unsafe fn from_raw(ptr: *const T) -> Self {
// SAFETY: data_offset is safe to call, because this pointer originates from a Weak.
// See Weak::as_ptr for context on how the input pointer is derived.
let offset = unsafe { data_offset(ptr) };

// Reverse the offset to find the original RcBox.
// SAFETY: we use wrapping_offset here because the pointer may be dangling (but only if T: Sized).
let ptr = unsafe {
set_data_ptr(ptr as *mut RcBox<T>, (ptr as *mut u8).wrapping_offset(-offset))
let ptr = if ptr.is_null() {
// If we get a null pointer, this is a dangling weak.
// SAFETY: this is the same sentinel as used in Weak::new and is_dangling
(ptr as *mut RcBox<T>).set_ptr_value(usize::MAX as *mut _)
} else {
// Otherwise, this describes a real allocation.
// SAFETY: data_offset is safe to call, as ptr describes a real allocation.
let offset = unsafe { data_offset(ptr) };
// Thus, we reverse the offset to get the whole RcBox.
// SAFETY: the pointer originated from a Weak, so this offset is safe.
unsafe { (ptr as *mut RcBox<T>).set_ptr_value((ptr as *mut u8).offset(-offset)) }
};

// SAFETY: we now have recovered the original Weak pointer, so can create the Weak.
Weak { ptr: unsafe { NonNull::new_unchecked(ptr) } }
}
}

impl<T: ?Sized> Weak<T> {
/// Attempts to upgrade the `Weak` pointer to an [`Rc`], delaying
/// dropping of the inner value if successful.
///
Expand Down
41 changes: 41 additions & 0 deletions library/alloc/src/rc/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,30 @@ fn into_from_weak_raw() {
}
}

#[test]
fn test_into_from_weak_raw_unsized() {
use std::fmt::Display;
use std::string::ToString;

let arc: Rc<str> = Rc::from("foo");
let weak: Weak<str> = Rc::downgrade(&arc);

let ptr = Weak::into_raw(weak.clone());
let weak2 = unsafe { Weak::from_raw(ptr) };

assert_eq!(unsafe { &*ptr }, "foo");
assert!(weak.ptr_eq(&weak2));

let arc: Rc<dyn Display> = Rc::new(123);
let weak: Weak<dyn Display> = Rc::downgrade(&arc);

let ptr = Weak::into_raw(weak.clone());
let weak2 = unsafe { Weak::from_raw(ptr) };

assert_eq!(unsafe { &*ptr }.to_string(), "123");
assert!(weak.ptr_eq(&weak2));
}

#[test]
fn get_mut() {
let mut x = Rc::new(3);
Expand Down Expand Up @@ -294,6 +318,23 @@ fn test_unsized() {
assert_eq!(foo, foo.clone());
}

#[test]
fn test_maybe_thin_unsized() {
// If/when custom thin DSTs exist, this test should be updated to use one
use std::ffi::{CStr, CString};

let x: Rc<CStr> = Rc::from(CString::new("swordfish").unwrap().into_boxed_c_str());
assert_eq!(format!("{:?}", x), "\"swordfish\"");
let y: Weak<CStr> = Rc::downgrade(&x);
drop(x);

// At this point, the weak points to a dropped DST
assert!(y.upgrade().is_none());
// But we still need to be able to get the alloc layout to drop.
// CStr has no drop glue, but custom DSTs might, and need to work.
drop(y);
}

#[test]
fn test_from_owned() {
let foo = 123;
Expand Down
41 changes: 24 additions & 17 deletions library/alloc/src/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1648,7 +1648,7 @@ struct WeakInner<'a> {
strong: &'a atomic::AtomicUsize,
}

impl<T> Weak<T> {
impl<T: ?Sized> Weak<T> {
/// Returns a raw pointer to the object `T` pointed to by this `Weak<T>`.
///
/// The pointer is valid only if there are some strong references. The pointer may be dangling,
Expand Down Expand Up @@ -1678,15 +1678,17 @@ impl<T> Weak<T> {
pub fn as_ptr(&self) -> *const T {
let ptr: *mut ArcInner<T> = NonNull::as_ptr(self.ptr);

// SAFETY: we must offset the pointer manually, and said pointer may be
// a dangling weak (usize::MAX) if T is sized. data_offset is safe to call,
// because we know that a pointer to unsized T was derived from a real
// unsized T, as dangling weaks are only created for sized T. wrapping_offset
// is used so that we can use the same code path for the non-dangling
// unsized case and the potentially dangling sized case.
unsafe {
let offset = data_offset(ptr as *mut T);
set_data_ptr(ptr as *mut T, (ptr as *mut u8).wrapping_offset(offset))
if is_dangling(self.ptr) {
// If the pointer is dangling, we return a null pointer as the dangling sentinel.
// We can't return the usize::MAX sentinel, as that could valid if T is ZST.
// SAFETY: we have to return a known sentinel here that cannot be produced for
// a valid pointer, so that `from_raw` can reverse this transformation.
(ptr as *mut T).set_ptr_value(ptr::null_mut())
} else {
// SAFETY: If the pointer is not dangling, it describes to a valid allocation.
// The payload may be dropped at this point, and we have to maintain provenance,
// so use raw pointer manipulation.
unsafe { &raw mut (*ptr).data }
}
}

Expand Down Expand Up @@ -1768,18 +1770,23 @@ impl<T> Weak<T> {
/// [`forget`]: std::mem::forget
#[stable(feature = "weak_into_raw", since = "1.45.0")]
pub unsafe fn from_raw(ptr: *const T) -> Self {
// SAFETY: data_offset is safe to call, because this pointer originates from a Weak.
// See Weak::as_ptr for context on how the input pointer is derived.
let offset = unsafe { data_offset(ptr) };

// Reverse the offset to find the original ArcInner.
// SAFETY: we use wrapping_offset here because the pointer may be dangling (but only if T: Sized)
let ptr = unsafe {
set_data_ptr(ptr as *mut ArcInner<T>, (ptr as *mut u8).wrapping_offset(-offset))
let ptr = if ptr.is_null() {
// If we get a null pointer, this is a dangling weak.
// SAFETY: this is the same sentinel as used in Weak::new and is_dangling
(ptr as *mut ArcInner<T>).set_ptr_value(usize::MAX as *mut _)
} else {
// Otherwise, this describes a real allocation.
// SAFETY: data_offset is safe to call, as ptr describes a real allocation.
let offset = unsafe { data_offset(ptr) };
// Thus, we reverse the offset to get the whole RcBox.
// SAFETY: the pointer originated from a Weak, so this offset is safe.
unsafe { (ptr as *mut ArcInner<T>).set_ptr_value((ptr as *mut u8).offset(-offset)) }
};

// SAFETY: we now have recovered the original Weak pointer, so can create the Weak.
unsafe { Weak { ptr: NonNull::new_unchecked(ptr) } }
Weak { ptr: unsafe { NonNull::new_unchecked(ptr) } }
}
}

Expand Down
41 changes: 41 additions & 0 deletions library/alloc/src/sync/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,30 @@ fn into_from_weak_raw() {
}
}

#[test]
fn test_into_from_weak_raw_unsized() {
use std::fmt::Display;
use std::string::ToString;

let arc: Arc<str> = Arc::from("foo");
let weak: Weak<str> = Arc::downgrade(&arc);

let ptr = Weak::into_raw(weak.clone());
let weak2 = unsafe { Weak::from_raw(ptr) };

assert_eq!(unsafe { &*ptr }, "foo");
assert!(weak.ptr_eq(&weak2));

let arc: Arc<dyn Display> = Arc::new(123);
let weak: Weak<dyn Display> = Arc::downgrade(&arc);

let ptr = Weak::into_raw(weak.clone());
let weak2 = unsafe { Weak::from_raw(ptr) };

assert_eq!(unsafe { &*ptr }.to_string(), "123");
assert!(weak.ptr_eq(&weak2));
}

#[test]
fn test_cowarc_clone_make_mut() {
let mut cow0 = Arc::new(75);
Expand Down Expand Up @@ -329,6 +353,23 @@ fn test_unsized() {
assert!(y.upgrade().is_none());
}

#[test]
fn test_maybe_thin_unsized() {
// If/when custom thin DSTs exist, this test should be updated to use one
use std::ffi::{CStr, CString};

let x: Arc<CStr> = Arc::from(CString::new("swordfish").unwrap().into_boxed_c_str());
assert_eq!(format!("{:?}", x), "\"swordfish\"");
let y: Weak<CStr> = Arc::downgrade(&x);
drop(x);

// At this point, the weak points to a dropped DST
assert!(y.upgrade().is_none());
// But we still need to be able to get the alloc layout to drop.
// CStr has no drop glue, but custom DSTs might, and need to work.
drop(y);
}

#[test]
fn test_from_owned() {
let foo = 123;
Expand Down