mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 02:57:37 +00:00
Auto merge of #76678 - jonas-schievink:rollup-vzl9yhx, r=jonas-schievink
Rollup of 12 pull requests Successful merges: - #75559 (unions: test move behavior of non-Copy fields) - #76441 (Note that parallel-compiler = true causes tests to fail) - #76527 (Remove internal and unstable MaybeUninit::UNINIT.) - #76629 (Simplify iter zip struct doc) - #76640 (Simplify SyncOnceCell's `take` and `drop`.) - #76646 (Add mailmap entry) - #76651 (Remove Windows details from Unix and VmWorks symlink() docstrings) - #76663 (Simplify iter chain struct doc) - #76665 (slice::from_raw_parts: explicitly mention that data must be initialized) - #76667 (Fix CI LLVM to work on NixOS out of the box) - #76668 (Add visualization of rustc span in doc) - #76677 (note that test_stable_pointers does not reflect a stable guarantee) Failed merges: r? `@ghost`
This commit is contained in:
commit
f9a322a6fd
3
.mailmap
3
.mailmap
@ -55,6 +55,9 @@ Chris C Cerami <chrisccerami@users.noreply.github.com> Chris C Cerami <chrisccer
|
||||
Chris Pressey <cpressey@gmail.com>
|
||||
Chris Thorn <chris@thorn.co> Chris Thorn <thorn@thoughtbot.com>
|
||||
Chris Vittal <christopher.vittal@gmail.com> Christopher Vittal <christopher.vittal@gmail.com>
|
||||
Christiaan Dirkx <christiaan@dirkx.email> <christiaan@dirkx.com>
|
||||
Christiaan Dirkx <christiaan@dirkx.email> CDirkx <christiaan@dirkx.com>
|
||||
Christiaan Dirkx <christiaan@dirkx.email> CDirkx <christiaan@dirkx.email>
|
||||
Christian Poveda <git@christianpoveda.xyz> <christianpoveda@protonmail.com>
|
||||
Christian Poveda <git@christianpoveda.xyz> <cn.poveda.ruiz@gmail.com>
|
||||
Christian Poveda <git@christianpoveda.xyz> <z1mvader@protonmail.com>
|
||||
|
@ -544,6 +544,12 @@ impl Span {
|
||||
}
|
||||
|
||||
/// Returns a `Span` that would enclose both `self` and `end`.
|
||||
///
|
||||
/// ```text
|
||||
/// ____ ___
|
||||
/// self lorem ipsum end
|
||||
/// ^^^^^^^^^^^^^^^^^^^^
|
||||
/// ```
|
||||
pub fn to(self, end: Span) -> Span {
|
||||
let span_data = self.data();
|
||||
let end_data = end.data();
|
||||
@ -567,6 +573,12 @@ impl Span {
|
||||
}
|
||||
|
||||
/// Returns a `Span` between the end of `self` to the beginning of `end`.
|
||||
///
|
||||
/// ```text
|
||||
/// ____ ___
|
||||
/// self lorem ipsum end
|
||||
/// ^^^^^^^^^^^^^
|
||||
/// ```
|
||||
pub fn between(self, end: Span) -> Span {
|
||||
let span = self.data();
|
||||
let end = end.data();
|
||||
@ -577,7 +589,13 @@ impl Span {
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns a `Span` between the beginning of `self` to the beginning of `end`.
|
||||
/// Returns a `Span` from the beginning of `self` until the beginning of `end`.
|
||||
///
|
||||
/// ```text
|
||||
/// ____ ___
|
||||
/// self lorem ipsum end
|
||||
/// ^^^^^^^^^^^^^^^^^
|
||||
/// ```
|
||||
pub fn until(self, end: Span) -> Span {
|
||||
let span = self.data();
|
||||
let end = end.data();
|
||||
|
@ -393,6 +393,7 @@
|
||||
#incremental = false
|
||||
|
||||
# Build a multi-threaded rustc
|
||||
# FIXME(#75760): Some UI tests fail when this option is enabled.
|
||||
#parallel-compiler = false
|
||||
|
||||
# The default linker that will be hard-coded into the generated compiler for
|
||||
|
@ -78,8 +78,8 @@ impl<K, V> LeafNode<K, V> {
|
||||
LeafNode {
|
||||
// As a general policy, we leave fields uninitialized if they can be, as this should
|
||||
// be both slightly faster and easier to track in Valgrind.
|
||||
keys: [MaybeUninit::UNINIT; CAPACITY],
|
||||
vals: [MaybeUninit::UNINIT; CAPACITY],
|
||||
keys: MaybeUninit::uninit_array(),
|
||||
vals: MaybeUninit::uninit_array(),
|
||||
parent: ptr::null(),
|
||||
parent_idx: MaybeUninit::uninit(),
|
||||
len: 0,
|
||||
@ -111,7 +111,7 @@ impl<K, V> InternalNode<K, V> {
|
||||
/// `len` of 0), there must be one initialized and valid edge. This function does not set up
|
||||
/// such an edge.
|
||||
unsafe fn new() -> Self {
|
||||
InternalNode { data: unsafe { LeafNode::new() }, edges: [MaybeUninit::UNINIT; 2 * B] }
|
||||
InternalNode { data: unsafe { LeafNode::new() }, edges: MaybeUninit::uninit_array() }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,7 +100,6 @@
|
||||
#![feature(fn_traits)]
|
||||
#![feature(fundamental)]
|
||||
#![feature(inplace_iteration)]
|
||||
#![feature(internal_uninit_const)]
|
||||
#![feature(lang_items)]
|
||||
#![feature(layout_for_ptr)]
|
||||
#![feature(libc)]
|
||||
@ -135,7 +134,7 @@
|
||||
#![feature(unsized_locals)]
|
||||
#![feature(allocator_internals)]
|
||||
#![feature(slice_partition_dedup)]
|
||||
#![feature(maybe_uninit_extra, maybe_uninit_slice)]
|
||||
#![feature(maybe_uninit_extra, maybe_uninit_slice, maybe_uninit_uninit_array)]
|
||||
#![feature(alloc_layout_extra)]
|
||||
#![feature(trusted_random_access)]
|
||||
#![feature(try_trait)]
|
||||
|
@ -1511,6 +1511,9 @@ fn test_stable_pointers() {
|
||||
// Test that, if we reserved enough space, adding and removing elements does not
|
||||
// invalidate references into the vector (such as `v0`). This test also
|
||||
// runs in Miri, which would detect such problems.
|
||||
// Note that this test does *not* constitute a stable guarantee that all these functions do not
|
||||
// reallocate! Only what is explicitly documented at
|
||||
// <https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#guarantees> is stably guaranteed.
|
||||
let mut v = Vec::with_capacity(128);
|
||||
v.push(13);
|
||||
|
||||
|
@ -4,11 +4,8 @@ use crate::usize;
|
||||
|
||||
/// An iterator that links two iterators together, in a chain.
|
||||
///
|
||||
/// This `struct` is created by the [`chain`] method on [`Iterator`]. See its
|
||||
/// documentation for more.
|
||||
///
|
||||
/// [`chain`]: trait.Iterator.html#method.chain
|
||||
/// [`Iterator`]: trait.Iterator.html
|
||||
/// This `struct` is created by [`Iterator::chain`]. See its documentation
|
||||
/// for more.
|
||||
#[derive(Clone, Debug)]
|
||||
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -8,11 +8,8 @@ use super::super::{
|
||||
|
||||
/// An iterator that iterates two other iterators simultaneously.
|
||||
///
|
||||
/// This `struct` is created by the [`zip`] method on [`Iterator`]. See its
|
||||
/// documentation for more.
|
||||
///
|
||||
/// [`zip`]: trait.Iterator.html#method.zip
|
||||
/// [`Iterator`]: trait.Iterator.html
|
||||
/// This `struct` is created by [`Iterator::zip`]. See its documentation
|
||||
/// for more.
|
||||
#[derive(Clone)]
|
||||
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -306,14 +306,6 @@ impl<T> MaybeUninit<T> {
|
||||
unsafe { MaybeUninit::<[MaybeUninit<T>; LEN]>::uninit().assume_init() }
|
||||
}
|
||||
|
||||
/// A promotable constant, equivalent to `uninit()`.
|
||||
#[unstable(
|
||||
feature = "internal_uninit_const",
|
||||
issue = "none",
|
||||
reason = "hack to work around promotability"
|
||||
)]
|
||||
pub const UNINIT: Self = Self::uninit();
|
||||
|
||||
/// Creates a new `MaybeUninit<T>` in an uninitialized state, with the memory being
|
||||
/// filled with `0` bytes. It depends on `T` whether that already makes for
|
||||
/// proper initialization. For example, `MaybeUninit<usize>::zeroed()` is initialized,
|
||||
|
@ -6680,6 +6680,8 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunksExactMut<'a, T> {
|
||||
/// them from other data. You can obtain a pointer that is usable as `data`
|
||||
/// for zero-length slices using [`NonNull::dangling()`].
|
||||
///
|
||||
/// * `data` must point to `len` consecutive properly initialized values of type `T`.
|
||||
///
|
||||
/// * The memory referenced by the returned slice must not be mutated for the duration
|
||||
/// of lifetime `'a`, except inside an `UnsafeCell`.
|
||||
///
|
||||
@ -6767,6 +6769,8 @@ pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] {
|
||||
/// them from other data. You can obtain a pointer that is usable as `data`
|
||||
/// for zero-length slices using [`NonNull::dangling()`].
|
||||
///
|
||||
/// * `data` must point to `len` consecutive properly initialized values of type `T`.
|
||||
///
|
||||
/// * The memory referenced by the returned slice must not be accessed through any other pointer
|
||||
/// (not derived from the return value) for the duration of lifetime `'a`.
|
||||
/// Both read and write accesses are forbidden.
|
||||
|
@ -7,7 +7,7 @@ use crate::{
|
||||
cell::{Cell, UnsafeCell},
|
||||
fmt,
|
||||
marker::PhantomData,
|
||||
mem::{self, MaybeUninit},
|
||||
mem::MaybeUninit,
|
||||
ops::{Deref, Drop},
|
||||
panic::{RefUnwindSafe, UnwindSafe},
|
||||
sync::Once,
|
||||
@ -316,13 +316,7 @@ impl<T> SyncOnceCell<T> {
|
||||
/// ```
|
||||
#[unstable(feature = "once_cell", issue = "74465")]
|
||||
pub fn into_inner(mut self) -> Option<T> {
|
||||
// SAFETY: Safe because we immediately free `self` without dropping
|
||||
let inner = unsafe { self.take_inner() };
|
||||
|
||||
// Don't drop this `SyncOnceCell`. We just moved out one of the fields, but didn't set
|
||||
// the state to uninitialized.
|
||||
mem::forget(self);
|
||||
inner
|
||||
self.take()
|
||||
}
|
||||
|
||||
/// Takes the value out of this `SyncOnceCell`, moving it back to an uninitialized state.
|
||||
@ -348,22 +342,12 @@ impl<T> SyncOnceCell<T> {
|
||||
/// ```
|
||||
#[unstable(feature = "once_cell", issue = "74465")]
|
||||
pub fn take(&mut self) -> Option<T> {
|
||||
mem::take(self).into_inner()
|
||||
}
|
||||
|
||||
/// Takes the wrapped value out of a `SyncOnceCell`.
|
||||
/// Afterwards the cell is no longer initialized.
|
||||
///
|
||||
/// Safety: The cell must now be free'd WITHOUT dropping. No other usages of the cell
|
||||
/// are valid. Only used by `into_inner` and `drop`.
|
||||
unsafe fn take_inner(&mut self) -> Option<T> {
|
||||
// The mutable reference guarantees there are no other threads that can observe us
|
||||
// taking out the wrapped value.
|
||||
// Right after this function `self` is supposed to be freed, so it makes little sense
|
||||
// to atomically set the state to uninitialized.
|
||||
if self.is_initialized() {
|
||||
let value = mem::replace(&mut self.value, UnsafeCell::new(MaybeUninit::uninit()));
|
||||
Some(value.into_inner().assume_init())
|
||||
self.once = Once::new();
|
||||
// SAFETY: `self.value` is initialized and contains a valid `T`.
|
||||
// `self.once` is reset, so `is_initialized()` will be false again
|
||||
// which prevents the value from being read twice.
|
||||
unsafe { Some((&mut *self.value.get()).assume_init_read()) }
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -416,9 +400,12 @@ impl<T> SyncOnceCell<T> {
|
||||
|
||||
unsafe impl<#[may_dangle] T> Drop for SyncOnceCell<T> {
|
||||
fn drop(&mut self) {
|
||||
// SAFETY: The cell is being dropped, so it can't be accessed again.
|
||||
// We also don't touch the `T`, which validates our usage of #[may_dangle].
|
||||
unsafe { self.take_inner() };
|
||||
if self.is_initialized() {
|
||||
// Safety: The cell is initialized and being dropped, so it can't
|
||||
// be accessed again. We also don't touch the `T` other than
|
||||
// dropping it, which validates our usage of #[may_dangle].
|
||||
unsafe { (&mut *self.value.get()).assume_init_drop() };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,6 +191,7 @@ struct WaiterQueue<'a> {
|
||||
|
||||
impl Once {
|
||||
/// Creates a new `Once` value.
|
||||
#[inline]
|
||||
#[stable(feature = "once_new", since = "1.2.0")]
|
||||
#[rustc_const_stable(feature = "const_once_new", since = "1.32.0")]
|
||||
pub const fn new() -> Once {
|
||||
|
@ -836,15 +836,6 @@ impl DirEntryExt for fs::DirEntry {
|
||||
///
|
||||
/// The `dst` path will be a symbolic link pointing to the `src` path.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// On Windows, you must specify whether a symbolic link points to a file
|
||||
/// or directory. Use `os::windows::fs::symlink_file` to create a
|
||||
/// symbolic link to a file, or `os::windows::fs::symlink_dir` to create a
|
||||
/// symbolic link to a directory. Additionally, the process must have
|
||||
/// `SeCreateSymbolicLinkPrivilege` in order to be able to create a
|
||||
/// symbolic link.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
|
@ -774,15 +774,6 @@ impl DirEntryExt for fs::DirEntry {
|
||||
///
|
||||
/// The `dst` path will be a symbolic link pointing to the `src` path.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// On Windows, you must specify whether a symbolic link points to a file
|
||||
/// or directory. Use `os::windows::fs::symlink_file` to create a
|
||||
/// symbolic link to a file, or `os::windows::fs::symlink_dir` to create a
|
||||
/// symbolic link to a directory. Additionally, the process must have
|
||||
/// `SeCreateSymbolicLinkPrivilege` in order to be able to create a
|
||||
/// symbolic link.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
|
@ -429,6 +429,8 @@ class RustBuild(object):
|
||||
llvm_assertions = self.get_toml('assertions', 'llvm') == 'true'
|
||||
if self.program_out_of_date(self.llvm_stamp(), llvm_sha + str(llvm_assertions)):
|
||||
self._download_ci_llvm(llvm_sha, llvm_assertions)
|
||||
for binary in ["llvm-config", "FileCheck"]:
|
||||
self.fix_bin_or_dylib("{}/bin/{}".format(self.llvm_root(), binary))
|
||||
with output(self.llvm_stamp()) as llvm_stamp:
|
||||
llvm_stamp.write(self.date + llvm_sha + str(llvm_assertions))
|
||||
|
||||
|
@ -48,6 +48,11 @@ fn main() {
|
||||
{
|
||||
let y = Y { a: S };
|
||||
}
|
||||
assert_eq!(CHECK, 2); // 2, dtor of Y is called
|
||||
assert_eq!(CHECK, 2); // 2, Y has no dtor
|
||||
{
|
||||
let u2 = U { a: 1 };
|
||||
std::mem::forget(u2);
|
||||
}
|
||||
assert_eq!(CHECK, 2); // 2, dtor of U *not* called for u2
|
||||
}
|
||||
}
|
||||
|
53
src/test/ui/union/union-move.rs
Normal file
53
src/test/ui/union/union-move.rs
Normal file
@ -0,0 +1,53 @@
|
||||
//! Test the behavior of moving out of non-`Copy` union fields.
|
||||
//! Avoid types that `Drop`, we want to focus on moving.
|
||||
#![feature(untagged_unions)]
|
||||
|
||||
use std::cell::RefCell;
|
||||
|
||||
fn move_out<T>(x: T) {}
|
||||
|
||||
union U1 {
|
||||
f1_nocopy: RefCell<i32>,
|
||||
f2_nocopy: RefCell<i32>,
|
||||
f3_copy: i32,
|
||||
}
|
||||
|
||||
union U2 {
|
||||
f1_nocopy: RefCell<i32>,
|
||||
}
|
||||
impl Drop for U2 {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
fn test1(x: U1) {
|
||||
// Moving out of a nocopy field prevents accessing other nocopy field.
|
||||
unsafe {
|
||||
move_out(x.f1_nocopy);
|
||||
move_out(x.f2_nocopy); //~ ERROR use of moved value: `x`
|
||||
}
|
||||
}
|
||||
|
||||
fn test2(x: U1) {
|
||||
// "Moving" out of copy field doesn't prevent later field accesses.
|
||||
unsafe {
|
||||
move_out(x.f3_copy);
|
||||
move_out(x.f2_nocopy); // no error
|
||||
}
|
||||
}
|
||||
|
||||
fn test3(x: U1) {
|
||||
// Moving out of a nocopy field prevents accessing other copy field.
|
||||
unsafe {
|
||||
move_out(x.f2_nocopy);
|
||||
move_out(x.f3_copy); //~ ERROR use of moved value: `x`
|
||||
}
|
||||
}
|
||||
|
||||
fn test4(x: U2) {
|
||||
// Cannot move out of union that implements `Drop`.
|
||||
unsafe {
|
||||
move_out(x.f1_nocopy); //~ ERROR cannot move out of type `U2`, which implements the `Drop`
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
35
src/test/ui/union/union-move.stderr
Normal file
35
src/test/ui/union/union-move.stderr
Normal file
@ -0,0 +1,35 @@
|
||||
error[E0382]: use of moved value: `x`
|
||||
--> $DIR/union-move.rs:26:18
|
||||
|
|
||||
LL | fn test1(x: U1) {
|
||||
| - move occurs because `x` has type `U1`, which does not implement the `Copy` trait
|
||||
...
|
||||
LL | move_out(x.f1_nocopy);
|
||||
| ----------- value moved here
|
||||
LL | move_out(x.f2_nocopy);
|
||||
| ^^^^^^^^^^^ value used here after move
|
||||
|
||||
error[E0382]: use of moved value: `x`
|
||||
--> $DIR/union-move.rs:42:18
|
||||
|
|
||||
LL | fn test3(x: U1) {
|
||||
| - move occurs because `x` has type `U1`, which does not implement the `Copy` trait
|
||||
...
|
||||
LL | move_out(x.f2_nocopy);
|
||||
| ----------- value moved here
|
||||
LL | move_out(x.f3_copy);
|
||||
| ^^^^^^^^^ value used here after move
|
||||
|
||||
error[E0509]: cannot move out of type `U2`, which implements the `Drop` trait
|
||||
--> $DIR/union-move.rs:49:18
|
||||
|
|
||||
LL | move_out(x.f1_nocopy);
|
||||
| ^^^^^^^^^^^
|
||||
| |
|
||||
| cannot move out of here
|
||||
| move occurs because `x.f1_nocopy` has type `RefCell<i32>`, which does not implement the `Copy` trait
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0382, E0509.
|
||||
For more information about an error, try `rustc --explain E0382`.
|
Loading…
Reference in New Issue
Block a user