Skip to content

Commit 0a59f11

Browse files
committed
Auto merge of rust-lang#125552 - matthiaskrgr:rollup-f1yybpn, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - rust-lang#121377 (Stabilize `LazyCell` and `LazyLock`) - rust-lang#122986 (Fix c_char on AIX) - rust-lang#123803 (Fix `VecDeque::shrink_to` UB when `handle_alloc_error` unwinds.) - rust-lang#124080 (Some unstable changes to where opaque types get defined) - rust-lang#124667 (Stabilize `div_duration`) - rust-lang#125472 (tidy: validate LLVM component names in tests) - rust-lang#125523 (Exit the process a short time after entering our ctrl-c handler) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 1ba35e9 + 0ded36f commit 0a59f11

File tree

76 files changed

+590
-222
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+590
-222
lines changed

compiler/rustc_const_eval/src/check_consts/ops.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
309309
}
310310

311311
if let ConstContext::Static(_) = ccx.const_kind() {
312-
err.note("consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell");
312+
err.note("consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`");
313313
}
314314

315315
err

compiler/rustc_data_structures/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
#![feature(extend_one)]
2525
#![feature(hash_raw_entry)]
2626
#![feature(hasher_prefixfree_extras)]
27-
#![feature(lazy_cell)]
2827
#![feature(lint_reasons)]
2928
#![feature(macro_metavar_expr)]
3029
#![feature(map_try_insert)]

compiler/rustc_driver_impl/src/lib.rs

+8-9
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ use std::process::{self, Command, Stdio};
5757
use std::str;
5858
use std::sync::atomic::{AtomicBool, Ordering};
5959
use std::sync::{Arc, OnceLock};
60-
use std::time::{Instant, SystemTime};
60+
use std::time::{Duration, Instant, SystemTime};
6161
use time::OffsetDateTime;
6262
use tracing::trace;
6363

@@ -1502,14 +1502,13 @@ pub fn init_logger(early_dcx: &EarlyDiagCtxt, cfg: rustc_log::LoggerConfig) {
15021502
pub fn install_ctrlc_handler() {
15031503
#[cfg(not(target_family = "wasm"))]
15041504
ctrlc::set_handler(move || {
1505-
// Indicate that we have been signaled to stop. If we were already signaled, exit
1506-
// immediately. In our interpreter loop we try to consult this value often, but if for
1507-
// whatever reason we don't get to that check or the cleanup we do upon finding that
1508-
// this bool has become true takes a long time, the exit here will promptly exit the
1509-
// process on the second Ctrl-C.
1510-
if CTRL_C_RECEIVED.swap(true, Ordering::Relaxed) {
1511-
std::process::exit(1);
1512-
}
1505+
// Indicate that we have been signaled to stop, then give the rest of the compiler a bit of
1506+
// time to check CTRL_C_RECEIVED and run its own shutdown logic, but after a short amount
1507+
// of time exit the process. This sleep+exit ensures that even if nobody is checking
1508+
// CTRL_C_RECEIVED, the compiler exits reasonably promptly.
1509+
CTRL_C_RECEIVED.store(true, Ordering::Relaxed);
1510+
std::thread::sleep(Duration::from_millis(100));
1511+
std::process::exit(1);
15131512
})
15141513
.expect("Unable to install ctrlc handler");
15151514
}

compiler/rustc_error_messages/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#![doc(rust_logo)]
22
#![feature(rustdoc_internals)]
3-
#![feature(lazy_cell)]
43
#![feature(rustc_attrs)]
54
#![feature(type_alias_impl_trait)]
65
#![allow(internal_features)]

compiler/rustc_feature/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
#![allow(internal_features)]
1515
#![feature(rustdoc_internals)]
1616
#![doc(rust_logo)]
17-
#![feature(lazy_cell)]
1817

1918
mod accepted;
2019
mod builtin_attrs;

compiler/rustc_hir_analysis/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ This API is completely unstable and subject to change.
6868
#![feature(iter_intersperse)]
6969
#![feature(let_chains)]
7070
#![feature(never_type)]
71-
#![feature(lazy_cell)]
7271
#![feature(slice_partition_dedup)]
7372
#![feature(try_blocks)]
7473

compiler/rustc_interface/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#![feature(decl_macro)]
2-
#![feature(lazy_cell)]
32
#![feature(let_chains)]
43
#![feature(thread_spawn_unchecked)]
54
#![feature(try_blocks)]

compiler/rustc_lint_defs/src/builtin.rs

+3-7
Original file line numberDiff line numberDiff line change
@@ -1316,10 +1316,8 @@ declare_lint! {
13161316
/// * If you are trying to perform a one-time initialization of a global:
13171317
/// * If the value can be computed at compile-time, consider using
13181318
/// const-compatible values (see [Constant Evaluation]).
1319-
/// * For more complex single-initialization cases, consider using a
1320-
/// third-party crate, such as [`lazy_static`] or [`once_cell`].
1321-
/// * If you are using the [nightly channel], consider the new
1322-
/// [`lazy`] module in the standard library.
1319+
/// * For more complex single-initialization cases, consider using
1320+
/// [`std::sync::LazyLock`].
13231321
/// * If you truly need a mutable global, consider using a [`static`],
13241322
/// which has a variety of options:
13251323
/// * Simple data types can be directly defined and mutated with an
@@ -1334,9 +1332,7 @@ declare_lint! {
13341332
/// [Constant Evaluation]: https://doc.rust-lang.org/reference/const_eval.html
13351333
/// [`static`]: https://doc.rust-lang.org/reference/items/static-items.html
13361334
/// [mutable `static`]: https://doc.rust-lang.org/reference/items/static-items.html#mutable-statics
1337-
/// [`lazy`]: https://doc.rust-lang.org/nightly/std/lazy/index.html
1338-
/// [`lazy_static`]: https://crates.io/crates/lazy_static
1339-
/// [`once_cell`]: https://crates.io/crates/once_cell
1335+
/// [`std::sync::LazyLock`]: https://doc.rust-lang.org/stable/std/sync/struct.LazyLock.html
13401336
/// [`atomic`]: https://doc.rust-lang.org/std/sync/atomic/index.html
13411337
/// [`Mutex`]: https://doc.rust-lang.org/std/sync/struct.Mutex.html
13421338
pub CONST_ITEM_MUTATION,

compiler/rustc_session/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#![feature(let_chains)]
2-
#![feature(lazy_cell)]
32
#![feature(option_get_or_insert_default)]
43
#![feature(rustc_attrs)]
54
#![feature(map_many_mut)]

compiler/rustc_trait_selection/src/traits/select/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -2539,7 +2539,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
25392539
let InferOk { obligations, .. } = self
25402540
.infcx
25412541
.at(&cause, obligation.param_env)
2542-
.eq(DefineOpaqueTypes::No, placeholder_obligation_trait_ref, impl_trait_ref)
2542+
.eq(DefineOpaqueTypes::Yes, placeholder_obligation_trait_ref, impl_trait_ref)
25432543
.map_err(|e| {
25442544
debug!("match_impl: failed eq_trait_refs due to `{}`", e.to_string(self.tcx()))
25452545
})?;
@@ -2594,7 +2594,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
25942594
self.infcx
25952595
.at(&obligation.cause, obligation.param_env)
25962596
.eq(
2597-
DefineOpaqueTypes::No,
2597+
DefineOpaqueTypes::Yes,
25982598
upcast_principal.map_bound(|trait_ref| {
25992599
ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)
26002600
}),
@@ -2631,7 +2631,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
26312631
nested.extend(
26322632
self.infcx
26332633
.at(&obligation.cause, obligation.param_env)
2634-
.eq(DefineOpaqueTypes::No, source_projection, target_projection)
2634+
.eq(DefineOpaqueTypes::Yes, source_projection, target_projection)
26352635
.map_err(|_| SelectionError::Unimplemented)?
26362636
.into_obligations(),
26372637
);

library/alloc/Cargo.toml

+4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ rand_xorshift = "0.3.0"
2020
name = "alloctests"
2121
path = "tests/lib.rs"
2222

23+
[[test]]
24+
name = "vec_deque_alloc_error"
25+
path = "tests/vec_deque_alloc_error.rs"
26+
2327
[[bench]]
2428
name = "allocbenches"
2529
path = "benches/lib.rs"

library/alloc/src/collections/vec_deque/mod.rs

+65-1
Original file line numberDiff line numberDiff line change
@@ -982,6 +982,8 @@ impl<T, A: Allocator> VecDeque<T, A> {
982982
// `head` and `len` are at most `isize::MAX` and `target_cap < self.capacity()`, so nothing can
983983
// overflow.
984984
let tail_outside = (target_cap + 1..=self.capacity()).contains(&(self.head + self.len));
985+
// Used in the drop guard below.
986+
let old_head = self.head;
985987

986988
if self.len == 0 {
987989
self.head = 0;
@@ -1034,12 +1036,74 @@ impl<T, A: Allocator> VecDeque<T, A> {
10341036
}
10351037
self.head = new_head;
10361038
}
1037-
self.buf.shrink_to_fit(target_cap);
1039+
1040+
struct Guard<'a, T, A: Allocator> {
1041+
deque: &'a mut VecDeque<T, A>,
1042+
old_head: usize,
1043+
target_cap: usize,
1044+
}
1045+
1046+
impl<T, A: Allocator> Drop for Guard<'_, T, A> {
1047+
#[cold]
1048+
fn drop(&mut self) {
1049+
unsafe {
1050+
// SAFETY: This is only called if `buf.shrink_to_fit` unwinds,
1051+
// which is the only time it's safe to call `abort_shrink`.
1052+
self.deque.abort_shrink(self.old_head, self.target_cap)
1053+
}
1054+
}
1055+
}
1056+
1057+
let guard = Guard { deque: self, old_head, target_cap };
1058+
1059+
guard.deque.buf.shrink_to_fit(target_cap);
1060+
1061+
// Don't drop the guard if we didn't unwind.
1062+
mem::forget(guard);
10381063

10391064
debug_assert!(self.head < self.capacity() || self.capacity() == 0);
10401065
debug_assert!(self.len <= self.capacity());
10411066
}
10421067

1068+
/// Reverts the deque back into a consistent state in case `shrink_to` failed.
1069+
/// This is necessary to prevent UB if the backing allocator returns an error
1070+
/// from `shrink` and `handle_alloc_error` subsequently unwinds (see #123369).
1071+
///
1072+
/// `old_head` refers to the head index before `shrink_to` was called. `target_cap`
1073+
/// is the capacity that it was trying to shrink to.
1074+
unsafe fn abort_shrink(&mut self, old_head: usize, target_cap: usize) {
1075+
// Moral equivalent of self.head + self.len <= target_cap. Won't overflow
1076+
// because `self.len <= target_cap`.
1077+
if self.head <= target_cap - self.len {
1078+
// The deque's buffer is contiguous, so no need to copy anything around.
1079+
return;
1080+
}
1081+
1082+
// `shrink_to` already copied the head to fit into the new capacity, so this won't overflow.
1083+
let head_len = target_cap - self.head;
1084+
// `self.head > target_cap - self.len` => `self.len > target_cap - self.head =: head_len` so this must be positive.
1085+
let tail_len = self.len - head_len;
1086+
1087+
if tail_len <= cmp::min(head_len, self.capacity() - target_cap) {
1088+
// There's enough spare capacity to copy the tail to the back (because `tail_len < self.capacity() - target_cap`),
1089+
// and copying the tail should be cheaper than copying the head (because `tail_len <= head_len`).
1090+
1091+
unsafe {
1092+
// The old tail and the new tail can't overlap because the head slice lies between them. The
1093+
// head slice ends at `target_cap`, so that's where we copy to.
1094+
self.copy_nonoverlapping(0, target_cap, tail_len);
1095+
}
1096+
} else {
1097+
// Either there's not enough spare capacity to make the deque contiguous, or the head is shorter than the tail
1098+
// (and therefore hopefully cheaper to copy).
1099+
unsafe {
1100+
// The old and the new head slice can overlap, so we can't use `copy_nonoverlapping` here.
1101+
self.copy(self.head, old_head, head_len);
1102+
self.head = old_head;
1103+
}
1104+
}
1105+
}
1106+
10431107
/// Shortens the deque, keeping the first `len` elements and dropping
10441108
/// the rest.
10451109
///
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#![feature(alloc_error_hook, allocator_api)]
2+
3+
use std::{
4+
alloc::{set_alloc_error_hook, AllocError, Allocator, Layout, System},
5+
collections::VecDeque,
6+
panic::{catch_unwind, AssertUnwindSafe},
7+
ptr::NonNull,
8+
};
9+
10+
#[test]
11+
fn test_shrink_to_unwind() {
12+
// This tests that `shrink_to` leaves the deque in a consistent state when
13+
// the call to `RawVec::shrink_to_fit` unwinds. The code is adapted from #123369
14+
// but changed to hopefully not have any UB even if the test fails.
15+
16+
struct BadAlloc;
17+
18+
unsafe impl Allocator for BadAlloc {
19+
fn allocate(&self, l: Layout) -> Result<NonNull<[u8]>, AllocError> {
20+
// We allocate zeroed here so that the whole buffer of the deque
21+
// is always initialized. That way, even if the deque is left in
22+
// an inconsistent state, no uninitialized memory should be accessed.
23+
System.allocate_zeroed(l)
24+
}
25+
26+
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
27+
unsafe { System.deallocate(ptr, layout) }
28+
}
29+
30+
unsafe fn shrink(
31+
&self,
32+
_ptr: NonNull<u8>,
33+
_old_layout: Layout,
34+
_new_layout: Layout,
35+
) -> Result<NonNull<[u8]>, AllocError> {
36+
Err(AllocError)
37+
}
38+
}
39+
40+
set_alloc_error_hook(|_| panic!("alloc error"));
41+
42+
let mut v = VecDeque::with_capacity_in(15, BadAlloc);
43+
v.push_back(1);
44+
v.push_front(2);
45+
// This should unwind because it calls `BadAlloc::shrink` and then `handle_alloc_error` which unwinds.
46+
assert!(catch_unwind(AssertUnwindSafe(|| v.shrink_to_fit())).is_err());
47+
// This should only pass if the deque is left in a consistent state.
48+
assert_eq!(v, [2, 1]);
49+
}

library/core/src/cell.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ use crate::ptr::{self, NonNull};
245245
mod lazy;
246246
mod once;
247247

248-
#[unstable(feature = "lazy_cell", issue = "109736")]
248+
#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
249249
pub use lazy::LazyCell;
250250
#[stable(feature = "once_cell", since = "1.70.0")]
251251
pub use once::OnceCell;

library/core/src/cell/lazy.rs

+7-13
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ enum State<T, F> {
1818
/// # Examples
1919
///
2020
/// ```
21-
/// #![feature(lazy_cell)]
22-
///
2321
/// use std::cell::LazyCell;
2422
///
2523
/// let lazy: LazyCell<i32> = LazyCell::new(|| {
@@ -36,7 +34,7 @@ enum State<T, F> {
3634
/// // 92
3735
/// // 92
3836
/// ```
39-
#[unstable(feature = "lazy_cell", issue = "109736")]
37+
#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
4038
pub struct LazyCell<T, F = fn() -> T> {
4139
state: UnsafeCell<State<T, F>>,
4240
}
@@ -47,8 +45,6 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> {
4745
/// # Examples
4846
///
4947
/// ```
50-
/// #![feature(lazy_cell)]
51-
///
5248
/// use std::cell::LazyCell;
5349
///
5450
/// let hello = "Hello, World!".to_string();
@@ -58,7 +54,8 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> {
5854
/// assert_eq!(&*lazy, "HELLO, WORLD!");
5955
/// ```
6056
#[inline]
61-
#[unstable(feature = "lazy_cell", issue = "109736")]
57+
#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
58+
#[rustc_const_stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
6259
pub const fn new(f: F) -> LazyCell<T, F> {
6360
LazyCell { state: UnsafeCell::new(State::Uninit(f)) }
6461
}
@@ -70,7 +67,6 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> {
7067
/// # Examples
7168
///
7269
/// ```
73-
/// #![feature(lazy_cell)]
7470
/// #![feature(lazy_cell_consume)]
7571
///
7672
/// use std::cell::LazyCell;
@@ -99,8 +95,6 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> {
9995
/// # Examples
10096
///
10197
/// ```
102-
/// #![feature(lazy_cell)]
103-
///
10498
/// use std::cell::LazyCell;
10599
///
106100
/// let lazy = LazyCell::new(|| 92);
@@ -109,7 +103,7 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> {
109103
/// assert_eq!(&*lazy, &92);
110104
/// ```
111105
#[inline]
112-
#[unstable(feature = "lazy_cell", issue = "109736")]
106+
#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
113107
pub fn force(this: &LazyCell<T, F>) -> &T {
114108
// SAFETY:
115109
// This invalidates any mutable references to the data. The resulting
@@ -173,7 +167,7 @@ impl<T, F> LazyCell<T, F> {
173167
}
174168
}
175169

176-
#[unstable(feature = "lazy_cell", issue = "109736")]
170+
#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
177171
impl<T, F: FnOnce() -> T> Deref for LazyCell<T, F> {
178172
type Target = T;
179173
#[inline]
@@ -182,7 +176,7 @@ impl<T, F: FnOnce() -> T> Deref for LazyCell<T, F> {
182176
}
183177
}
184178

185-
#[unstable(feature = "lazy_cell", issue = "109736")]
179+
#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
186180
impl<T: Default> Default for LazyCell<T> {
187181
/// Creates a new lazy value using `Default` as the initializing function.
188182
#[inline]
@@ -191,7 +185,7 @@ impl<T: Default> Default for LazyCell<T> {
191185
}
192186
}
193187

194-
#[unstable(feature = "lazy_cell", issue = "109736")]
188+
#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
195189
impl<T: fmt::Debug, F> fmt::Debug for LazyCell<T, F> {
196190
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
197191
let mut d = f.debug_tuple("LazyCell");

library/core/src/ffi/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,8 @@ mod c_char_definition {
133133
any(target_arch = "aarch64", target_arch = "riscv64")
134134
),
135135
all(target_os = "nto", target_arch = "aarch64"),
136-
target_os = "horizon"
136+
target_os = "horizon",
137+
target_os = "aix",
137138
))] {
138139
pub type c_char = u8;
139140
} else {

0 commit comments

Comments
 (0)