Skip to content

Commit 5529041

Browse files
committed
Auto merge of #144624 - Zalathar:rollup-w803jmq, r=Zalathar
Rollup of 10 pull requests Successful merges: - #143883 (Add `--link-targets-dir` argument to linkchecker) - #144236 (Add `core::mem::DropGuard`) - #144367 (Move dist-apple-various from x86_64 to aarch64) - #144539 (constify with_exposed_provenance) - #144569 (rustc-dev-guide subtree update) - #144573 (Raw Pointers are Constant PatKinds too) - #144575 (fixed typo chunks->as_chunks) - #144578 (Ensure correct aligement of rustc_hir::Lifetime on platforms with lower default alignments.) - #144582 (fix `Atomic*::as_ptr` wording) - #144616 (coverage: Regression test for "function name is empty" bug) r? `@ghost` `@rustbot` modify labels: rollup
2 parents cb6785f + cac55bd commit 5529041

File tree

29 files changed

+1045
-281
lines changed

29 files changed

+1045
-281
lines changed

compiler/rustc_hir/src/hir.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,11 @@ impl From<Ident> for LifetimeSyntax {
148148
/// `LifetimeSource::OutlivesBound` or `LifetimeSource::PreciseCapturing`
149149
/// — there's no way to "elide" these lifetimes.
150150
#[derive(Debug, Copy, Clone, HashStable_Generic)]
151+
// Raise the aligement to at least 4 bytes - this is relied on in other parts of the compiler(for pointer tagging):
152+
// https://github.com/rust-lang/rust/blob/ce5fdd7d42aba9a2925692e11af2bd39cf37798a/compiler/rustc_data_structures/src/tagged_ptr.rs#L163
153+
// Removing this `repr(4)` will cause the compiler to not build on platforms like `m68k` Linux, where the aligement of u32 and usize is only 2.
154+
// Since `repr(align)` may only raise aligement, this has no effect on platforms where the aligement is already sufficient.
155+
#[repr(align(4))]
151156
pub struct Lifetime {
152157
#[stable_hasher(ignore)]
153158
pub hir_id: HirId,

compiler/rustc_middle/src/thir.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -838,6 +838,8 @@ pub enum PatKind<'tcx> {
838838
/// * integer, bool, char or float (represented as a valtree), which will be handled by
839839
/// exhaustiveness to cover exactly its own value, similar to `&str`, but these values are
840840
/// much simpler.
841+
/// * raw pointers derived from integers, other raw pointers will have already resulted in an
842+
// error.
841843
/// * `String`, if `string_deref_patterns` is enabled.
842844
Constant {
843845
value: mir::Const<'tcx>,

library/core/src/mem/drop_guard.rs

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
use crate::fmt::{self, Debug};
2+
use crate::mem::ManuallyDrop;
3+
use crate::ops::{Deref, DerefMut};
4+
5+
/// Wrap a value and run a closure when dropped.
6+
///
7+
/// This is useful for quickly creating desructors inline.
8+
///
9+
/// # Examples
10+
///
11+
/// ```rust
12+
/// # #![allow(unused)]
13+
/// #![feature(drop_guard)]
14+
///
15+
/// use std::mem::DropGuard;
16+
///
17+
/// {
18+
/// // Create a new guard around a string that will
19+
/// // print its value when dropped.
20+
/// let s = String::from("Chashu likes tuna");
21+
/// let mut s = DropGuard::new(s, |s| println!("{s}"));
22+
///
23+
/// // Modify the string contained in the guard.
24+
/// s.push_str("!!!");
25+
///
26+
/// // The guard will be dropped here, printing:
27+
/// // "Chashu likes tuna!!!"
28+
/// }
29+
/// ```
30+
#[unstable(feature = "drop_guard", issue = "144426")]
31+
#[doc(alias = "ScopeGuard")]
32+
#[doc(alias = "defer")]
33+
pub struct DropGuard<T, F>
34+
where
35+
F: FnOnce(T),
36+
{
37+
inner: ManuallyDrop<T>,
38+
f: ManuallyDrop<F>,
39+
}
40+
41+
impl<T, F> DropGuard<T, F>
42+
where
43+
F: FnOnce(T),
44+
{
45+
/// Create a new instance of `DropGuard`.
46+
///
47+
/// # Example
48+
///
49+
/// ```rust
50+
/// # #![allow(unused)]
51+
/// #![feature(drop_guard)]
52+
///
53+
/// use std::mem::DropGuard;
54+
///
55+
/// let value = String::from("Chashu likes tuna");
56+
/// let guard = DropGuard::new(value, |s| println!("{s}"));
57+
/// ```
58+
#[unstable(feature = "drop_guard", issue = "144426")]
59+
#[must_use]
60+
pub const fn new(inner: T, f: F) -> Self {
61+
Self { inner: ManuallyDrop::new(inner), f: ManuallyDrop::new(f) }
62+
}
63+
64+
/// Consumes the `DropGuard`, returning the wrapped value.
65+
///
66+
/// This will not execute the closure. This is implemented as an associated
67+
/// function to prevent any potential conflicts with any other methods called
68+
/// `into_inner` from the `Deref` and `DerefMut` impls.
69+
///
70+
/// It is typically preferred to call this function instead of `mem::forget`
71+
/// because it will return the stored value and drop variables captured
72+
/// by the closure instead of leaking their owned resources.
73+
///
74+
/// # Example
75+
///
76+
/// ```rust
77+
/// # #![allow(unused)]
78+
/// #![feature(drop_guard)]
79+
///
80+
/// use std::mem::DropGuard;
81+
///
82+
/// let value = String::from("Nori likes chicken");
83+
/// let guard = DropGuard::new(value, |s| println!("{s}"));
84+
/// assert_eq!(DropGuard::into_inner(guard), "Nori likes chicken");
85+
/// ```
86+
#[unstable(feature = "drop_guard", issue = "144426")]
87+
#[inline]
88+
pub fn into_inner(guard: Self) -> T {
89+
// First we ensure that dropping the guard will not trigger
90+
// its destructor
91+
let mut guard = ManuallyDrop::new(guard);
92+
93+
// Next we manually read the stored value from the guard.
94+
//
95+
// SAFETY: this is safe because we've taken ownership of the guard.
96+
let value = unsafe { ManuallyDrop::take(&mut guard.inner) };
97+
98+
// Finally we drop the stored closure. We do this *after* having read
99+
// the value, so that even if the closure's `drop` function panics,
100+
// unwinding still tries to drop the value.
101+
//
102+
// SAFETY: this is safe because we've taken ownership of the guard.
103+
unsafe { ManuallyDrop::drop(&mut guard.f) };
104+
value
105+
}
106+
}
107+
108+
#[unstable(feature = "drop_guard", issue = "144426")]
109+
impl<T, F> Deref for DropGuard<T, F>
110+
where
111+
F: FnOnce(T),
112+
{
113+
type Target = T;
114+
115+
fn deref(&self) -> &T {
116+
&*self.inner
117+
}
118+
}
119+
120+
#[unstable(feature = "drop_guard", issue = "144426")]
121+
impl<T, F> DerefMut for DropGuard<T, F>
122+
where
123+
F: FnOnce(T),
124+
{
125+
fn deref_mut(&mut self) -> &mut T {
126+
&mut *self.inner
127+
}
128+
}
129+
130+
#[unstable(feature = "drop_guard", issue = "144426")]
131+
impl<T, F> Drop for DropGuard<T, F>
132+
where
133+
F: FnOnce(T),
134+
{
135+
fn drop(&mut self) {
136+
// SAFETY: `DropGuard` is in the process of being dropped.
137+
let inner = unsafe { ManuallyDrop::take(&mut self.inner) };
138+
139+
// SAFETY: `DropGuard` is in the process of being dropped.
140+
let f = unsafe { ManuallyDrop::take(&mut self.f) };
141+
142+
f(inner);
143+
}
144+
}
145+
146+
#[unstable(feature = "drop_guard", issue = "144426")]
147+
impl<T, F> Debug for DropGuard<T, F>
148+
where
149+
T: Debug,
150+
F: FnOnce(T),
151+
{
152+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
153+
fmt::Debug::fmt(&**self, f)
154+
}
155+
}

library/core/src/mem/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ mod transmutability;
2121
#[unstable(feature = "transmutability", issue = "99571")]
2222
pub use transmutability::{Assume, TransmuteFrom};
2323

24+
mod drop_guard;
25+
#[unstable(feature = "drop_guard", issue = "144426")]
26+
pub use drop_guard::DropGuard;
27+
2428
// This one has to be a re-export (rather than wrapping the underlying intrinsic) so that we can do
2529
// the special magic "types have equal size" check at the call site.
2630
#[stable(feature = "rust1", since = "1.0.0")]

library/core/src/ptr/mod.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -974,9 +974,10 @@ pub const fn dangling_mut<T>() -> *mut T {
974974
#[must_use]
975975
#[inline(always)]
976976
#[stable(feature = "exposed_provenance", since = "1.84.0")]
977+
#[rustc_const_unstable(feature = "const_exposed_provenance", issue = "144538")]
977978
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
978979
#[allow(fuzzy_provenance_casts)] // this *is* the explicit provenance API one should use instead
979-
pub fn with_exposed_provenance<T>(addr: usize) -> *const T {
980+
pub const fn with_exposed_provenance<T>(addr: usize) -> *const T {
980981
addr as *const T
981982
}
982983

@@ -1014,9 +1015,10 @@ pub fn with_exposed_provenance<T>(addr: usize) -> *const T {
10141015
#[must_use]
10151016
#[inline(always)]
10161017
#[stable(feature = "exposed_provenance", since = "1.84.0")]
1018+
#[rustc_const_unstable(feature = "const_exposed_provenance", issue = "144538")]
10171019
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
10181020
#[allow(fuzzy_provenance_casts)] // this *is* the explicit provenance API one should use instead
1019-
pub fn with_exposed_provenance_mut<T>(addr: usize) -> *mut T {
1021+
pub const fn with_exposed_provenance_mut<T>(addr: usize) -> *mut T {
10201022
addr as *mut T
10211023
}
10221024

library/core/src/slice/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1230,7 +1230,7 @@ impl<T> [T] {
12301230
///
12311231
/// [`chunks`]: slice::chunks
12321232
/// [`rchunks_exact`]: slice::rchunks_exact
1233-
/// [`as_chunks`]: slice::chunks
1233+
/// [`as_chunks`]: slice::as_chunks
12341234
#[stable(feature = "chunks_exact", since = "1.31.0")]
12351235
#[rustc_const_unstable(feature = "const_slice_make_iter", issue = "137737")]
12361236
#[inline]

library/core/src/sync/atomic.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1245,8 +1245,8 @@ impl AtomicBool {
12451245
/// Returning an `*mut` pointer from a shared reference to this atomic is safe because the
12461246
/// atomic types work with interior mutability. All modifications of an atomic change the value
12471247
/// through a shared reference, and can do so safely as long as they use atomic operations. Any
1248-
/// use of the returned raw pointer requires an `unsafe` block and still has to uphold the same
1249-
/// restriction in [Memory model for atomic accesses].
1248+
/// use of the returned raw pointer requires an `unsafe` block and still has to uphold the
1249+
/// requirements of the [memory model].
12501250
///
12511251
/// # Examples
12521252
///
@@ -1265,7 +1265,7 @@ impl AtomicBool {
12651265
/// # }
12661266
/// ```
12671267
///
1268-
/// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
1268+
/// [memory model]: self#memory-model-for-atomic-accesses
12691269
#[inline]
12701270
#[stable(feature = "atomic_as_ptr", since = "1.70.0")]
12711271
#[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")]
@@ -2489,8 +2489,8 @@ impl<T> AtomicPtr<T> {
24892489
/// Returning an `*mut` pointer from a shared reference to this atomic is safe because the
24902490
/// atomic types work with interior mutability. All modifications of an atomic change the value
24912491
/// through a shared reference, and can do so safely as long as they use atomic operations. Any
2492-
/// use of the returned raw pointer requires an `unsafe` block and still has to uphold the same
2493-
/// restriction in [Memory model for atomic accesses].
2492+
/// use of the returned raw pointer requires an `unsafe` block and still has to uphold the
2493+
/// requirements of the [memory model].
24942494
///
24952495
/// # Examples
24962496
///
@@ -2510,7 +2510,7 @@ impl<T> AtomicPtr<T> {
25102510
/// }
25112511
/// ```
25122512
///
2513-
/// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
2513+
/// [memory model]: self#memory-model-for-atomic-accesses
25142514
#[inline]
25152515
#[stable(feature = "atomic_as_ptr", since = "1.70.0")]
25162516
#[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")]
@@ -3623,8 +3623,8 @@ macro_rules! atomic_int {
36233623
/// Returning an `*mut` pointer from a shared reference to this atomic is safe because the
36243624
/// atomic types work with interior mutability. All modifications of an atomic change the value
36253625
/// through a shared reference, and can do so safely as long as they use atomic operations. Any
3626-
/// use of the returned raw pointer requires an `unsafe` block and still has to uphold the same
3627-
/// restriction in [Memory model for atomic accesses].
3626+
/// use of the returned raw pointer requires an `unsafe` block and still has to uphold the
3627+
/// requirements of the [memory model].
36283628
///
36293629
/// # Examples
36303630
///
@@ -3645,7 +3645,7 @@ macro_rules! atomic_int {
36453645
/// # }
36463646
/// ```
36473647
///
3648-
/// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
3648+
/// [memory model]: self#memory-model-for-atomic-accesses
36493649
#[inline]
36503650
#[stable(feature = "atomic_as_ptr", since = "1.70.0")]
36513651
#[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")]

library/coretests/tests/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#![feature(core_private_diy_float)]
3030
#![feature(cstr_display)]
3131
#![feature(dec2flt)]
32+
#![feature(drop_guard)]
3233
#![feature(duration_constants)]
3334
#![feature(duration_constructors)]
3435
#![feature(duration_constructors_lite)]

library/coretests/tests/mem.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use core::mem::*;
22
use core::{array, ptr};
3+
use std::cell::Cell;
34
#[cfg(panic = "unwind")]
45
use std::rc::Rc;
56

@@ -795,3 +796,48 @@ fn const_maybe_uninit_zeroed() {
795796

796797
assert_eq!(unsafe { (*UNINIT.0.cast::<[[u8; SIZE]; 1]>())[0] }, [0u8; SIZE]);
797798
}
799+
800+
#[test]
801+
fn drop_guards_only_dropped_by_closure_when_run() {
802+
let value_drops = Cell::new(0);
803+
let value = DropGuard::new((), |()| value_drops.set(1 + value_drops.get()));
804+
let closure_drops = Cell::new(0);
805+
let guard = DropGuard::new(value, |_| closure_drops.set(1 + closure_drops.get()));
806+
assert_eq!(value_drops.get(), 0);
807+
assert_eq!(closure_drops.get(), 0);
808+
drop(guard);
809+
assert_eq!(value_drops.get(), 1);
810+
assert_eq!(closure_drops.get(), 1);
811+
}
812+
813+
#[test]
814+
fn drop_guard_into_inner() {
815+
let dropped = Cell::new(false);
816+
let value = DropGuard::new(42, |_| dropped.set(true));
817+
let guard = DropGuard::new(value, |_| dropped.set(true));
818+
let inner = DropGuard::into_inner(guard);
819+
assert_eq!(dropped.get(), false);
820+
assert_eq!(*inner, 42);
821+
}
822+
823+
#[test]
824+
#[cfg(panic = "unwind")]
825+
fn drop_guard_always_drops_value_if_closure_drop_unwinds() {
826+
// Create a value with a destructor, which we will validate ran successfully.
827+
let mut value_was_dropped = false;
828+
let value_with_tracked_destruction = DropGuard::new((), |_| value_was_dropped = true);
829+
830+
// Create a closure that will begin unwinding when dropped.
831+
let drop_bomb = DropGuard::new((), |_| panic!());
832+
let closure_that_panics_on_drop = move |_| {
833+
let _drop_bomb = drop_bomb;
834+
};
835+
836+
// This will run the closure, which will panic when dropped. This should
837+
// run the destructor of the value we passed, which we validate.
838+
let _ = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
839+
let guard = DropGuard::new(value_with_tracked_destruction, closure_that_panics_on_drop);
840+
DropGuard::into_inner(guard);
841+
}));
842+
assert!(value_was_dropped);
843+
}

library/std/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,7 @@
330330
#![feature(clone_to_uninit)]
331331
#![feature(core_intrinsics)]
332332
#![feature(core_io_borrowed_buf)]
333+
#![feature(drop_guard)]
333334
#![feature(duration_constants)]
334335
#![feature(error_generic_member_access)]
335336
#![feature(error_iter)]

0 commit comments

Comments
 (0)