Skip to content

Commit 8a65184

Browse files
committed
Auto merge of rust-lang#81089 - m-ou-se:rollup-z7iac6i, r=m-ou-se
Rollup of 17 pull requests Successful merges: - rust-lang#78455 (Introduce {Ref, RefMut}::try_map for optional projections in RefCell) - rust-lang#80144 (Remove giant badge in README) - rust-lang#80614 (Explain why borrows can't be held across yield point in async blocks) - rust-lang#80670 (TrustedRandomAaccess specialization composes incorrectly for nested iter::Zips) - rust-lang#80681 (Clarify what the effects of a 'logic error' are) - rust-lang#80764 (Re-stabilize Weak::as_ptr and friends for unsized T) - rust-lang#80901 (Make `x.py --color always` apply to logging too) - rust-lang#80902 (Add a regression test for rust-lang#76281) - rust-lang#80941 (Do not suggest invalid code in pattern with loop) - rust-lang#80968 (Stabilize the poll_map feature) - rust-lang#80971 (Put all feature gate tests under `feature-gates/`) - rust-lang#81021 (Remove doctree::Import) - rust-lang#81040 (doctest: Reset errors before dropping the parse session) - rust-lang#81060 (Add a regression test for rust-lang#50041) - rust-lang#81065 (codegen_cranelift: Fix redundant semicolon warn) - rust-lang#81069 (Add sample code for Rc::new_cyclic) - rust-lang#81081 (Add test for rust-lang#34792) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 492b83c + a6b2e1f commit 8a65184

38 files changed

+606
-225
lines changed

README.md

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
<a href = "https://www.rust-lang.org/">
2-
<img width = "90%" height = "auto" src = "https://img.shields.io/badge/Rust-Programming%20Language-black?style=flat&logo=rust" alt = "The Rust Programming Language">
3-
</a>
1+
# The Rust Programming Language
42

53
This is the main source code repository for [Rust]. It contains the compiler,
64
standard library, and documentation.

compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -824,7 +824,7 @@ pub(crate) fn codegen_intrinsic_call<'tcx>(
824824
}
825825
ty => unreachable!("bswap {}", ty),
826826
}
827-
};
827+
}
828828
let res = CValue::by_val(swap(&mut fx.bcx, arg), fx.layout_of(T));
829829
ret.write_cvalue(fx, res);
830830
};

compiler/rustc_error_codes/src/error_codes/E0373.md

+21
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,24 @@ fn foo() -> Box<Fn(u32) -> u32> {
5050

5151
Now that the closure has its own copy of the data, there's no need to worry
5252
about safety.
53+
54+
This error may also be encountered while using `async` blocks:
55+
56+
```compile_fail,E0373,edition2018
57+
use std::future::Future;
58+
59+
async fn f() {
60+
let v = vec![1, 2, 3i32];
61+
spawn(async { //~ ERROR E0373
62+
println!("{:?}", v)
63+
});
64+
}
65+
66+
fn spawn<F: Future + Send + 'static>(future: F) {
67+
unimplemented!()
68+
}
69+
```
70+
71+
Similarly to closures, `async` blocks are not executed immediately and may
72+
capture closed-over data by reference. For more information, see
73+
https://rust-lang.github.io/async-book/03_async_await/01_chapter.html.

compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs

+18-6
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
141141
self.add_moved_or_invoked_closure_note(location, used_place, &mut err);
142142

143143
let mut is_loop_move = false;
144+
let mut in_pattern = false;
144145

145146
for move_site in &move_site_vec {
146147
let move_out = self.move_data.moves[(*move_site).moi];
@@ -256,6 +257,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
256257
"ref ".to_string(),
257258
Applicability::MachineApplicable,
258259
);
260+
in_pattern = true;
259261
}
260262

261263
if let Some(DesugaringKind::ForLoop(_)) = move_span.desugaring_kind() {
@@ -302,7 +304,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
302304
let place = &self.move_data.move_paths[mpi].place;
303305
let ty = place.ty(self.body, self.infcx.tcx).ty;
304306

305-
if is_loop_move {
307+
// If we're in pattern, we do nothing in favor of the previous suggestion (#80913).
308+
if is_loop_move & !in_pattern {
306309
if let ty::Ref(_, _, hir::Mutability::Mut) = ty.kind() {
307310
// We have a `&mut` ref, we need to reborrow on each iteration (#62112).
308311
err.span_suggestion_verbose(
@@ -1318,21 +1321,30 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
13181321
Applicability::MachineApplicable,
13191322
);
13201323

1321-
let msg = match category {
1324+
match category {
13221325
ConstraintCategory::Return(_) | ConstraintCategory::OpaqueType => {
1323-
format!("{} is returned here", kind)
1326+
let msg = format!("{} is returned here", kind);
1327+
err.span_note(constraint_span, &msg);
13241328
}
13251329
ConstraintCategory::CallArgument => {
13261330
fr_name.highlight_region_name(&mut err);
1327-
format!("function requires argument type to outlive `{}`", fr_name)
1331+
if matches!(use_span.generator_kind(), Some(GeneratorKind::Async(_))) {
1332+
err.note(
1333+
"async blocks are not executed immediately and must either take a \
1334+
reference or ownership of outside variables they use",
1335+
);
1336+
} else {
1337+
let msg = format!("function requires argument type to outlive `{}`", fr_name);
1338+
err.span_note(constraint_span, &msg);
1339+
}
13281340
}
13291341
_ => bug!(
13301342
"report_escaping_closure_capture called with unexpected constraint \
13311343
category: `{:?}`",
13321344
category
13331345
),
1334-
};
1335-
err.span_note(constraint_span, &msg);
1346+
}
1347+
13361348
err
13371349
}
13381350

library/alloc/src/collections/binary_heap.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,10 @@ use super::SpecExtend;
161161
/// It is a logic error for an item to be modified in such a way that the
162162
/// item's ordering relative to any other item, as determined by the `Ord`
163163
/// trait, changes while it is in the heap. This is normally only possible
164-
/// through `Cell`, `RefCell`, global state, I/O, or unsafe code.
164+
/// through `Cell`, `RefCell`, global state, I/O, or unsafe code. The
165+
/// behavior resulting from such a logic error is not specified, but will
166+
/// not result in undefined behavior. This could include panics, incorrect
167+
/// results, aborts, memory leaks, and non-termination.
165168
///
166169
/// # Examples
167170
///

library/alloc/src/collections/btree/map.rs

+3
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ pub(super) const MIN_LEN: usize = node::MIN_LEN_AFTER_SPLIT;
5151
/// It is a logic error for a key to be modified in such a way that the key's ordering relative to
5252
/// any other key, as determined by the [`Ord`] trait, changes while it is in the map. This is
5353
/// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code.
54+
/// The behavior resulting from such a logic error is not specified, but will not result in
55+
/// undefined behavior. This could include panics, incorrect results, aborts, memory leaks, and
56+
/// non-termination.
5457
///
5558
/// [`Cell`]: core::cell::Cell
5659
/// [`RefCell`]: core::cell::RefCell

library/alloc/src/collections/btree/set.rs

+3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ use super::Recover;
2222
/// It is a logic error for an item to be modified in such a way that the item's ordering relative
2323
/// to any other item, as determined by the [`Ord`] trait, changes while it is in the set. This is
2424
/// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code.
25+
/// The behavior resulting from such a logic error is not specified, but will not result in
26+
/// undefined behavior. This could include panics, incorrect results, aborts, memory leaks, and
27+
/// non-termination.
2528
///
2629
/// [`Ord`]: core::cmp::Ord
2730
/// [`Cell`]: core::cell::Cell

library/alloc/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@
120120
#![feature(receiver_trait)]
121121
#![cfg_attr(bootstrap, feature(min_const_generics))]
122122
#![feature(min_specialization)]
123+
#![feature(set_ptr_value)]
123124
#![feature(slice_ptr_get)]
124125
#![feature(slice_ptr_len)]
125126
#![feature(staged_api)]

library/alloc/src/rc.rs

+56-49
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,26 @@ impl<T> Rc<T> {
353353
/// to upgrade the weak reference before this function returns will result
354354
/// in a `None` value. However, the weak reference may be cloned freely and
355355
/// stored for use at a later time.
356+
///
357+
/// # Examples
358+
///
359+
/// ```
360+
/// #![feature(arc_new_cyclic)]
361+
/// #![allow(dead_code)]
362+
/// use std::rc::{Rc, Weak};
363+
///
364+
/// struct Gadget {
365+
/// self_weak: Weak<Self>,
366+
/// // ... more fields
367+
/// }
368+
/// impl Gadget {
369+
/// pub fn new() -> Rc<Self> {
370+
/// Rc::new_cyclic(|self_weak| {
371+
/// Gadget { self_weak: self_weak.clone(), /* ... */ }
372+
/// })
373+
/// }
374+
/// }
375+
/// ```
356376
#[unstable(feature = "arc_new_cyclic", issue = "75861")]
357377
pub fn new_cyclic(data_fn: impl FnOnce(&Weak<T>) -> T) -> Rc<T> {
358378
// Construct the inner in the "uninitialized" state with a single
@@ -829,8 +849,8 @@ impl<T: ?Sized> Rc<T> {
829849
let offset = unsafe { data_offset(ptr) };
830850

831851
// Reverse the offset to find the original RcBox.
832-
let fake_ptr = ptr as *mut RcBox<T>;
833-
let rc_ptr = unsafe { set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset)) };
852+
let rc_ptr =
853+
unsafe { (ptr as *mut RcBox<T>).set_ptr_value((ptr as *mut u8).offset(-offset)) };
834854

835855
unsafe { Self::from_ptr(rc_ptr) }
836856
}
@@ -850,7 +870,7 @@ impl<T: ?Sized> Rc<T> {
850870
pub fn downgrade(this: &Self) -> Weak<T> {
851871
this.inner().inc_weak();
852872
// Make sure we do not create a dangling Weak
853-
debug_assert!(!is_dangling(this.ptr));
873+
debug_assert!(!is_dangling(this.ptr.as_ptr()));
854874
Weak { ptr: this.ptr }
855875
}
856876

@@ -1164,7 +1184,7 @@ impl<T: ?Sized> Rc<T> {
11641184
Self::allocate_for_layout(
11651185
Layout::for_value(&*ptr),
11661186
|layout| Global.allocate(layout),
1167-
|mem| set_data_ptr(ptr as *mut T, mem) as *mut RcBox<T>,
1187+
|mem| (ptr as *mut RcBox<T>).set_ptr_value(mem),
11681188
)
11691189
}
11701190
}
@@ -1203,20 +1223,7 @@ impl<T> Rc<[T]> {
12031223
)
12041224
}
12051225
}
1206-
}
1207-
1208-
/// Sets the data pointer of a `?Sized` raw pointer.
1209-
///
1210-
/// For a slice/trait object, this sets the `data` field and leaves the rest
1211-
/// unchanged. For a sized raw pointer, this simply sets the pointer.
1212-
unsafe fn set_data_ptr<T: ?Sized, U>(mut ptr: *mut T, data: *mut U) -> *mut T {
1213-
unsafe {
1214-
ptr::write(&mut ptr as *mut _ as *mut *mut u8, data as *mut u8);
1215-
}
1216-
ptr
1217-
}
12181226

1219-
impl<T> Rc<[T]> {
12201227
/// Copy elements from slice into newly allocated Rc<\[T\]>
12211228
///
12221229
/// Unsafe because the caller must either take ownership or bind `T: Copy`
@@ -1860,8 +1867,8 @@ impl<T> Weak<T> {
18601867
}
18611868
}
18621869

1863-
pub(crate) fn is_dangling<T: ?Sized>(ptr: NonNull<T>) -> bool {
1864-
let address = ptr.as_ptr() as *mut () as usize;
1870+
pub(crate) fn is_dangling<T: ?Sized>(ptr: *mut T) -> bool {
1871+
let address = ptr as *mut () as usize;
18651872
address == usize::MAX
18661873
}
18671874

@@ -1872,7 +1879,7 @@ struct WeakInner<'a> {
18721879
strong: &'a Cell<usize>,
18731880
}
18741881

1875-
impl<T> Weak<T> {
1882+
impl<T: ?Sized> Weak<T> {
18761883
/// Returns a raw pointer to the object `T` pointed to by this `Weak<T>`.
18771884
///
18781885
/// The pointer is valid only if there are some strong references. The pointer may be dangling,
@@ -1902,15 +1909,15 @@ impl<T> Weak<T> {
19021909
pub fn as_ptr(&self) -> *const T {
19031910
let ptr: *mut RcBox<T> = NonNull::as_ptr(self.ptr);
19041911

1905-
// SAFETY: we must offset the pointer manually, and said pointer may be
1906-
// a dangling weak (usize::MAX) if T is sized. data_offset is safe to call,
1907-
// because we know that a pointer to unsized T was derived from a real
1908-
// unsized T, as dangling weaks are only created for sized T. wrapping_offset
1909-
// is used so that we can use the same code path for the non-dangling
1910-
// unsized case and the potentially dangling sized case.
1911-
unsafe {
1912-
let offset = data_offset(ptr as *mut T);
1913-
set_data_ptr(ptr as *mut T, (ptr as *mut u8).wrapping_offset(offset))
1912+
if is_dangling(ptr) {
1913+
// If the pointer is dangling, we return the sentinel directly. This cannot be
1914+
// a valid payload address, as the payload is at least as aligned as RcBox (usize).
1915+
ptr as *const T
1916+
} else {
1917+
// SAFETY: if is_dangling returns false, then the pointer is dereferencable.
1918+
// The payload may be dropped at this point, and we have to maintain provenance,
1919+
// so use raw pointer manipulation.
1920+
unsafe { &raw const (*ptr).value }
19141921
}
19151922
}
19161923

@@ -1992,22 +1999,24 @@ impl<T> Weak<T> {
19921999
/// [`new`]: Weak::new
19932000
#[stable(feature = "weak_into_raw", since = "1.45.0")]
19942001
pub unsafe fn from_raw(ptr: *const T) -> Self {
1995-
// SAFETY: data_offset is safe to call, because this pointer originates from a Weak.
19962002
// See Weak::as_ptr for context on how the input pointer is derived.
1997-
let offset = unsafe { data_offset(ptr) };
19982003

1999-
// Reverse the offset to find the original RcBox.
2000-
// SAFETY: we use wrapping_offset here because the pointer may be dangling (but only if T: Sized).
2001-
let ptr = unsafe {
2002-
set_data_ptr(ptr as *mut RcBox<T>, (ptr as *mut u8).wrapping_offset(-offset))
2004+
let ptr = if is_dangling(ptr as *mut T) {
2005+
// This is a dangling Weak.
2006+
ptr as *mut RcBox<T>
2007+
} else {
2008+
// Otherwise, we're guaranteed the pointer came from a nondangling Weak.
2009+
// SAFETY: data_offset is safe to call, as ptr references a real (potentially dropped) T.
2010+
let offset = unsafe { data_offset(ptr) };
2011+
// Thus, we reverse the offset to get the whole RcBox.
2012+
// SAFETY: the pointer originated from a Weak, so this offset is safe.
2013+
unsafe { (ptr as *mut RcBox<T>).set_ptr_value((ptr as *mut u8).offset(-offset)) }
20032014
};
20042015

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

2010-
impl<T: ?Sized> Weak<T> {
20112020
/// Attempts to upgrade the `Weak` pointer to an [`Rc`], delaying
20122021
/// dropping of the inner value if successful.
20132022
///
@@ -2070,7 +2079,7 @@ impl<T: ?Sized> Weak<T> {
20702079
/// (i.e., when this `Weak` was created by `Weak::new`).
20712080
#[inline]
20722081
fn inner(&self) -> Option<WeakInner<'_>> {
2073-
if is_dangling(self.ptr) {
2082+
if is_dangling(self.ptr.as_ptr()) {
20742083
None
20752084
} else {
20762085
// We are careful to *not* create a reference covering the "data" field, as
@@ -2325,21 +2334,19 @@ impl<T: ?Sized> AsRef<T> for Rc<T> {
23252334
#[stable(feature = "pin", since = "1.33.0")]
23262335
impl<T: ?Sized> Unpin for Rc<T> {}
23272336

2328-
/// Get the offset within an `RcBox` for
2329-
/// a payload of type described by a pointer.
2337+
/// Get the offset within an `RcBox` for the payload behind a pointer.
23302338
///
23312339
/// # Safety
23322340
///
2333-
/// This has the same safety requirements as `align_of_val_raw`. In effect:
2334-
///
2335-
/// - This function is safe for any argument if `T` is sized, and
2336-
/// - if `T` is unsized, the pointer must have appropriate pointer metadata
2337-
/// acquired from the real instance that you are getting this offset for.
2341+
/// The pointer must point to (and have valid metadata for) a previously
2342+
/// valid instance of T, but the T is allowed to be dropped.
23382343
unsafe fn data_offset<T: ?Sized>(ptr: *const T) -> isize {
2339-
// Align the unsized value to the end of the `RcBox`.
2340-
// Because it is ?Sized, it will always be the last field in memory.
2341-
// Note: This is a detail of the current implementation of the compiler,
2342-
// and is not a guaranteed language detail. Do not rely on it outside of std.
2344+
// Align the unsized value to the end of the RcBox.
2345+
// Because RcBox is repr(C), it will always be the last field in memory.
2346+
// SAFETY: since the only unsized types possible are slices, trait objects,
2347+
// and extern types, the input safety requirement is currently enough to
2348+
// satisfy the requirements of align_of_val_raw; this is an implementation
2349+
// detail of the language that may not be relied upon outside of std.
23432350
unsafe { data_offset_align(align_of_val_raw(ptr)) }
23442351
}
23452352

library/alloc/src/rc/tests.rs

+41
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,30 @@ fn into_from_weak_raw() {
208208
}
209209
}
210210

211+
#[test]
212+
fn test_into_from_weak_raw_unsized() {
213+
use std::fmt::Display;
214+
use std::string::ToString;
215+
216+
let arc: Rc<str> = Rc::from("foo");
217+
let weak: Weak<str> = Rc::downgrade(&arc);
218+
219+
let ptr = Weak::into_raw(weak.clone());
220+
let weak2 = unsafe { Weak::from_raw(ptr) };
221+
222+
assert_eq!(unsafe { &*ptr }, "foo");
223+
assert!(weak.ptr_eq(&weak2));
224+
225+
let arc: Rc<dyn Display> = Rc::new(123);
226+
let weak: Weak<dyn Display> = Rc::downgrade(&arc);
227+
228+
let ptr = Weak::into_raw(weak.clone());
229+
let weak2 = unsafe { Weak::from_raw(ptr) };
230+
231+
assert_eq!(unsafe { &*ptr }.to_string(), "123");
232+
assert!(weak.ptr_eq(&weak2));
233+
}
234+
211235
#[test]
212236
fn get_mut() {
213237
let mut x = Rc::new(3);
@@ -294,6 +318,23 @@ fn test_unsized() {
294318
assert_eq!(foo, foo.clone());
295319
}
296320

321+
#[test]
322+
fn test_maybe_thin_unsized() {
323+
// If/when custom thin DSTs exist, this test should be updated to use one
324+
use std::ffi::{CStr, CString};
325+
326+
let x: Rc<CStr> = Rc::from(CString::new("swordfish").unwrap().into_boxed_c_str());
327+
assert_eq!(format!("{:?}", x), "\"swordfish\"");
328+
let y: Weak<CStr> = Rc::downgrade(&x);
329+
drop(x);
330+
331+
// At this point, the weak points to a dropped DST
332+
assert!(y.upgrade().is_none());
333+
// But we still need to be able to get the alloc layout to drop.
334+
// CStr has no drop glue, but custom DSTs might, and need to work.
335+
drop(y);
336+
}
337+
297338
#[test]
298339
fn test_from_owned() {
299340
let foo = 123;

0 commit comments

Comments
 (0)