Skip to content

Commit 12a0b47

Browse files
committed
Auto merge of #91486 - matthiaskrgr:rollup-699fo18, r=matthiaskrgr
Rollup of 10 pull requests Successful merges: - #88906 (Implement write() method for Box<MaybeUninit<T>>) - #90269 (Make `Option::expect` unstably const) - #90854 (Type can be unsized and uninhabited) - #91170 (rustdoc: preload fonts) - #91273 (Fix ICE #91268 by checking that the snippet ends with a `)`) - #91381 (Android: -ldl must appear after -lgcc when linking) - #91453 (Document Windows TLS drop behaviour) - #91462 (Use try_normalize_erasing_regions in needs_drop) - #91474 (suppress warning about set_errno being unused on DragonFly) - #91483 (Sync rustfmt subtree) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 267a342 + ad68bde commit 12a0b47

File tree

5 files changed

+57
-2
lines changed

5 files changed

+57
-2
lines changed

alloc/src/boxed.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -763,6 +763,42 @@ impl<T, A: Allocator> Box<mem::MaybeUninit<T>, A> {
763763
let (raw, alloc) = Box::into_raw_with_allocator(self);
764764
unsafe { Box::from_raw_in(raw as *mut T, alloc) }
765765
}
766+
767+
/// Writes the value and converts to `Box<T, A>`.
768+
///
769+
/// This method converts the box similarly to [`Box::assume_init`] but
770+
/// writes `value` into it before conversion thus guaranteeing safety.
771+
/// In some scenarios use of this method may improve performance because
772+
/// the compiler may be able to optimize copying from stack.
773+
///
774+
/// # Examples
775+
///
776+
/// ```
777+
/// #![feature(new_uninit)]
778+
///
779+
/// let big_box = Box::<[usize; 1024]>::new_uninit();
780+
///
781+
/// let mut array = [0; 1024];
782+
/// for (i, place) in array.iter_mut().enumerate() {
783+
/// *place = i;
784+
/// }
785+
///
786+
/// // The optimizer may be able to elide this copy, so previous code writes
787+
/// // to heap directly.
788+
/// let big_box = Box::write(big_box, array);
789+
///
790+
/// for (i, x) in big_box.iter().enumerate() {
791+
/// assert_eq!(*x, i);
792+
/// }
793+
/// ```
794+
#[unstable(feature = "new_uninit", issue = "63291")]
795+
#[inline]
796+
pub fn write(mut boxed: Self, value: T) -> Box<T, A> {
797+
unsafe {
798+
(*boxed).write(value);
799+
boxed.assume_init()
800+
}
801+
}
766802
}
767803

768804
impl<T, A: Allocator> Box<[mem::MaybeUninit<T>], A> {

core/src/option.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -703,7 +703,8 @@ impl<T> Option<T> {
703703
#[inline]
704704
#[track_caller]
705705
#[stable(feature = "rust1", since = "1.0.0")]
706-
pub fn expect(self, msg: &str) -> T {
706+
#[rustc_const_unstable(feature = "const_option", issue = "67441")]
707+
pub const fn expect(self, msg: &str) -> T {
707708
match self {
708709
Some(val) => val,
709710
None => expect_failed(msg),
@@ -1658,7 +1659,7 @@ impl<T, E> Option<Result<T, E>> {
16581659
#[inline(never)]
16591660
#[cold]
16601661
#[track_caller]
1661-
fn expect_failed(msg: &str) -> ! {
1662+
const fn expect_failed(msg: &str) -> ! {
16621663
panic!("{}", msg)
16631664
}
16641665

std/src/sys/unix/os.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ pub fn errno() -> i32 {
9797
}
9898

9999
#[cfg(target_os = "dragonfly")]
100+
#[allow(dead_code)]
100101
pub fn set_errno(e: i32) {
101102
extern "C" {
102103
#[thread_local]

std/src/thread/local.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,21 @@ use crate::fmt;
7676
/// destroyed, but not all platforms have this guard. Those platforms that do
7777
/// not guard typically have a synthetic limit after which point no more
7878
/// destructors are run.
79+
/// 3. When the process exits on Windows systems, TLS destructors may only be
80+
/// run on the thread that causes the process to exit. This is because the
81+
/// other threads may be forcibly terminated.
7982
///
83+
/// ## Synchronization in thread-local destructors
84+
///
85+
/// On Windows, synchronization operations (such as [`JoinHandle::join`]) in
86+
/// thread local destructors are prone to deadlocks and so should be avoided.
87+
/// This is because the [loader lock] is held while a destructor is run. The
88+
/// lock is acquired whenever a thread starts or exits or when a DLL is loaded
89+
/// or unloaded. Therefore these events are blocked for as long as a thread
90+
/// local destructor is running.
91+
///
92+
/// [loader lock]: https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-best-practices
93+
/// [`JoinHandle::join`]: crate::thread::JoinHandle::join
8094
/// [`with`]: LocalKey::with
8195
#[stable(feature = "rust1", since = "1.0.0")]
8296
pub struct LocalKey<T: 'static> {

unwind/build.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ fn main() {
1717
} else {
1818
println!("cargo:rustc-link-lib=gcc");
1919
}
20+
21+
// Android's unwinding library depends on dl_iterate_phdr in `libdl`.
22+
println!("cargo:rustc-link-lib=dl");
2023
} else if target.contains("freebsd") {
2124
println!("cargo:rustc-link-lib=gcc_s");
2225
} else if target.contains("netbsd") {

0 commit comments

Comments
 (0)