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 17 pull requests #81085

Closed
wants to merge 61 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
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
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
<a href = "https://www.rust-lang.org/">
<img width = "90%" height = "auto" src = "https://img.shields.io/badge/Rust-Programming%20Language-black?style=flat&logo=rust" alt = "The Rust Programming Language">
</a>
# The Rust Programming Language

This is the main source code repository for [Rust]. It contains the compiler,
standard library, and documentation.
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -824,7 +824,7 @@ pub(crate) fn codegen_intrinsic_call<'tcx>(
}
ty => unreachable!("bswap {}", ty),
}
};
}
let res = CValue::by_val(swap(&mut fx.bcx, arg), fx.layout_of(T));
ret.write_cvalue(fx, res);
};
Expand Down
21 changes: 21 additions & 0 deletions compiler/rustc_error_codes/src/error_codes/E0373.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,24 @@ fn foo() -> Box<Fn(u32) -> u32> {

Now that the closure has its own copy of the data, there's no need to worry
about safety.

This error may also be encountered while using `async` blocks:

```compile_fail,E0373,edition2018
use std::future::Future;

async fn f() {
let v = vec![1, 2, 3i32];
spawn(async { //~ ERROR E0373
println!("{:?}", v)
});
}

fn spawn<F: Future + Send + 'static>(future: F) {
unimplemented!()
}
```

Similarly to closures, `async` blocks are not executed immediately and may
capture closed-over data by reference. For more information, see
https://rust-lang.github.io/async-book/03_async_await/01_chapter.html.
24 changes: 18 additions & 6 deletions compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
self.add_moved_or_invoked_closure_note(location, used_place, &mut err);

let mut is_loop_move = false;
let mut in_pattern = false;

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

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

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

let msg = match category {
match category {
ConstraintCategory::Return(_) | ConstraintCategory::OpaqueType => {
format!("{} is returned here", kind)
let msg = format!("{} is returned here", kind);
err.span_note(constraint_span, &msg);
}
ConstraintCategory::CallArgument => {
fr_name.highlight_region_name(&mut err);
format!("function requires argument type to outlive `{}`", fr_name)
if matches!(use_span.generator_kind(), Some(GeneratorKind::Async(_))) {
err.note(
"async blocks are not executed immediately and must either take a \
reference or ownership of outside variables they use",
);
} else {
let msg = format!("function requires argument type to outlive `{}`", fr_name);
err.span_note(constraint_span, &msg);
}
}
_ => bug!(
"report_escaping_closure_capture called with unexpected constraint \
category: `{:?}`",
category
),
};
err.span_note(constraint_span, &msg);
}

err
}

Expand Down
5 changes: 4 additions & 1 deletion library/alloc/src/collections/binary_heap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,10 @@ use super::SpecExtend;
/// It is a logic error for an item to be modified in such a way that the
/// item's ordering relative to any other item, as determined by the `Ord`
/// trait, changes while it is in the heap. This is normally only possible
/// through `Cell`, `RefCell`, global state, I/O, or unsafe code.
/// through `Cell`, `RefCell`, global state, I/O, or unsafe code. The
/// behavior resulting from such a logic error is not specified, but will
/// not result in undefined behavior. This could include panics, incorrect
/// results, aborts, memory leaks, and non-termination.
///
/// # Examples
///
Expand Down
3 changes: 3 additions & 0 deletions library/alloc/src/collections/btree/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ pub(super) const MIN_LEN: usize = node::MIN_LEN_AFTER_SPLIT;
/// It is a logic error for a key to be modified in such a way that the key's ordering relative to
/// any other key, as determined by the [`Ord`] trait, changes while it is in the map. This is
/// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code.
/// The behavior resulting from such a logic error is not specified, but will not result in
/// undefined behavior. This could include panics, incorrect results, aborts, memory leaks, and
/// non-termination.
///
/// [`Cell`]: core::cell::Cell
/// [`RefCell`]: core::cell::RefCell
Expand Down
3 changes: 3 additions & 0 deletions library/alloc/src/collections/btree/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ use super::Recover;
/// It is a logic error for an item to be modified in such a way that the item's ordering relative
/// to any other item, as determined by the [`Ord`] trait, changes while it is in the set. This is
/// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code.
/// The behavior resulting from such a logic error is not specified, but will not result in
/// undefined behavior. This could include panics, incorrect results, aborts, memory leaks, and
/// non-termination.
///
/// [`Ord`]: core::cmp::Ord
/// [`Cell`]: core::cell::Cell
Expand Down
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
105 changes: 56 additions & 49 deletions library/alloc/src/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,26 @@ impl<T> Rc<T> {
/// to upgrade the weak reference before this function returns will result
/// in a `None` value. However, the weak reference may be cloned freely and
/// stored for use at a later time.
///
/// # Examples
///
/// ```
/// #![feature(arc_new_cyclic)]
/// #![allow(dead_code)]
/// use std::rc::{Rc, Weak};
///
/// struct Gadget {
/// self_weak: Weak<Self>,
/// // ... more fields
/// }
/// impl Gadget {
/// pub fn new() -> Rc<Self> {
/// Rc::new_cyclic(|self_weak| {
/// Gadget { self_weak: self_weak.clone(), /* ... */ }
/// })
/// }
/// }
/// ```
#[unstable(feature = "arc_new_cyclic", issue = "75861")]
pub fn new_cyclic(data_fn: impl FnOnce(&Weak<T>) -> T) -> Rc<T> {
// Construct the inner in the "uninitialized" state with a single
Expand Down Expand Up @@ -829,8 +849,8 @@ impl<T: ?Sized> Rc<T> {
let offset = unsafe { data_offset(ptr) };

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

unsafe { Self::from_ptr(rc_ptr) }
}
Expand All @@ -850,7 +870,7 @@ impl<T: ?Sized> Rc<T> {
pub fn downgrade(this: &Self) -> Weak<T> {
this.inner().inc_weak();
// Make sure we do not create a dangling Weak
debug_assert!(!is_dangling(this.ptr));
debug_assert!(!is_dangling(this.ptr.as_ptr()));
Weak { ptr: this.ptr }
}

Expand Down Expand Up @@ -1164,7 +1184,7 @@ impl<T: ?Sized> Rc<T> {
Self::allocate_for_layout(
Layout::for_value(&*ptr),
|layout| Global.allocate(layout),
|mem| set_data_ptr(ptr as *mut T, mem) as *mut RcBox<T>,
|mem| (ptr as *mut RcBox<T>).set_ptr_value(mem),
)
}
}
Expand Down Expand Up @@ -1203,20 +1223,7 @@ impl<T> Rc<[T]> {
)
}
}
}

/// Sets the data pointer of a `?Sized` raw pointer.
///
/// For a slice/trait object, this sets the `data` field and leaves the rest
/// unchanged. For a sized raw pointer, this simply sets the pointer.
unsafe fn set_data_ptr<T: ?Sized, U>(mut ptr: *mut T, data: *mut U) -> *mut T {
unsafe {
ptr::write(&mut ptr as *mut _ as *mut *mut u8, data as *mut u8);
}
ptr
}

impl<T> Rc<[T]> {
/// Copy elements from slice into newly allocated Rc<\[T\]>
///
/// Unsafe because the caller must either take ownership or bind `T: Copy`
Expand Down Expand Up @@ -1860,8 +1867,8 @@ impl<T> Weak<T> {
}
}

pub(crate) fn is_dangling<T: ?Sized>(ptr: NonNull<T>) -> bool {
let address = ptr.as_ptr() as *mut () as usize;
pub(crate) fn is_dangling<T: ?Sized>(ptr: *mut T) -> bool {
let address = ptr as *mut () as usize;
address == usize::MAX
}

Expand All @@ -1872,7 +1879,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 @@ -1902,15 +1909,15 @@ 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(ptr) {
// If the pointer is dangling, we return the sentinel directly. This cannot be
// a valid payload address, as the payload is at least as aligned as RcBox (usize).
ptr as *const T
} else {
// SAFETY: if is_dangling returns false, then the pointer is dereferencable.
// The payload may be dropped at this point, and we have to maintain provenance,
// so use raw pointer manipulation.
unsafe { &raw const (*ptr).value }
}
}

Expand Down Expand Up @@ -1992,22 +1999,24 @@ 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 is_dangling(ptr as *mut T) {
// This is a dangling Weak.
ptr as *mut RcBox<T>
} else {
// Otherwise, we're guaranteed the pointer came from a nondangling Weak.
// SAFETY: data_offset is safe to call, as ptr references a real (potentially dropped) T.
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 Expand Up @@ -2070,7 +2079,7 @@ impl<T: ?Sized> Weak<T> {
/// (i.e., when this `Weak` was created by `Weak::new`).
#[inline]
fn inner(&self) -> Option<WeakInner<'_>> {
if is_dangling(self.ptr) {
if is_dangling(self.ptr.as_ptr()) {
None
} else {
// We are careful to *not* create a reference covering the "data" field, as
Expand Down Expand Up @@ -2325,21 +2334,19 @@ impl<T: ?Sized> AsRef<T> for Rc<T> {
#[stable(feature = "pin", since = "1.33.0")]
impl<T: ?Sized> Unpin for Rc<T> {}

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

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
Loading