Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for ElaborateBoxDerefVisitor<'a, 'tcx> {

let ptr_local = self.patch.new_temp(ptr_ty, source_info.span);

// Project to the first field (a `Unique`), then transmute that. We could project one
// Project to the first field (a `BoxRaw`), then transmute that. We could project one
// further but in the end we'd hit a pattern type so we'd always have to transmute.
let field_place =
Place::from(place.local).project_to_field(FieldIdx::ZERO, &*self.local_decls, tcx);
Expand Down
48 changes: 34 additions & 14 deletions library/alloc/src/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ use core::error::{self, Error};
use core::fmt;
use core::future::Future;
use core::hash::{Hash, Hasher};
use core::marker::{Tuple, Unsize};
use core::marker::{PhantomData, Tuple, Unsize};
#[cfg(not(no_global_oom_handling))]
use core::mem::MaybeUninit;
use core::mem::{self, SizedTypeProperties};
Expand All @@ -201,7 +201,7 @@ use core::ops::{
#[cfg(not(no_global_oom_handling))]
use core::ops::{Residual, Try};
use core::pin::{Pin, PinSafePointer};
use core::ptr::{self, NonNull, Unique};
use core::ptr::{self, NonNull};
use core::task::{Context, Poll};

#[cfg(not(no_global_oom_handling))]
Expand All @@ -223,6 +223,27 @@ pub use iter::BoxedArrayIntoIter;
#[unstable(feature = "thin_box", issue = "92791")]
pub use thin::ThinBox;

/// An internal wrapper type for the pointer + `PhantomData` inside a `Box`.
/// This type has no semantic meaning. It only exists because the layout of
/// `Box` is hard-coded into the compiler.
#[repr(transparent)]
struct BoxRaw<T: ?Sized> {
pointer: NonNull<T>,
_marker: PhantomData<T>,
}
impl<T: ?Sized> Clone for BoxRaw<T> {
#[inline]
fn clone(&self) -> Self {
*self
}
}
impl<T: ?Sized> Copy for BoxRaw<T> {}
unsafe impl<T: ?Sized + Send> Send for BoxRaw<T> {}
unsafe impl<T: ?Sized + Sync> Sync for BoxRaw<T> {}
impl<T: ?Sized + core::panic::UnwindSafe> core::panic::UnwindSafe for BoxRaw<T> {}
impl<T: ?Sized, U: ?Sized> CoerceUnsized<BoxRaw<U>> for BoxRaw<T> where T: Unsize<U> {}
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<BoxRaw<U>> for BoxRaw<T> where T: Unsize<U> {}

/// A pointer type that uniquely owns a heap allocation of type `T`.
///
/// See the [module-level documentation](../../std/boxed/index.html) for more.
Expand All @@ -236,7 +257,7 @@ pub use thin::ThinBox;
pub struct Box<
T: ?Sized,
#[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
>(Unique<T>, A);
>(BoxRaw<T>, A);

/// Monomorphic function for allocating an uninit `Box`.
#[inline]
Expand Down Expand Up @@ -1575,7 +1596,7 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
#[inline]
pub unsafe fn from_raw_in(raw: *mut T, alloc: A) -> Self {
// SAFETY: Upheld by caller.
Box(unsafe { Unique::new_unchecked(raw) }, alloc)
unsafe { Box(BoxRaw { pointer: NonNull::new_unchecked(raw), _marker: PhantomData }, alloc) }
}

/// Constructs a box from a `NonNull` pointer in the given allocator.
Expand Down Expand Up @@ -2000,7 +2021,7 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Box<T, A> {
fn drop(&mut self) {
// the T in the Box is dropped by the compiler before the destructor is run

let ptr = self.0;
let ptr = self.0.pointer;

// SAFETY: The construction site of the unsized box had ensured for us that the
// allocation was made with a valid layout (the size does not overflow an isize,
Expand All @@ -2011,7 +2032,7 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Box<T, A> {
// of this box and `layout` would fit that allocation. We also are the only ones
// responsible for doing this deallocation and know that the pointer must be valid.
unsafe {
self.1.deallocate(From::from(ptr.cast()), layout);
self.1.deallocate(ptr.cast(), layout);
}
}
}
Expand Down Expand Up @@ -2045,8 +2066,11 @@ impl<T> Default for Box<[T]> {
/// Creates an empty `[T]` inside a `Box`.
#[inline]
fn default() -> Self {
let ptr: Unique<[T]> = Unique::<[T; 0]>::dangling();
Box(ptr, Global)
// SAFETY: `[T; 0]` is a ZST, for which `dangling` is valid
Box(
BoxRaw { pointer: NonNull::<[T; 0]>::dangling(), _marker: core::marker::PhantomData },
Global,
)
}
}

Expand All @@ -2055,12 +2079,8 @@ impl<T> Default for Box<[T]> {
impl Default for Box<str> {
#[inline]
fn default() -> Self {
// SAFETY: This is the same as `Unique::cast<U>` but with an unsized `U = str`.
let ptr: Unique<str> = unsafe {
let bytes: Unique<[u8]> = Unique::<[u8; 0]>::dangling();
Unique::new_unchecked(bytes.as_ptr() as *mut str)
};
Box(ptr, Global)
// SAFETY: The empty byte slice is valid UTF-8
unsafe { crate::str::from_boxed_utf8_unchecked(Box::default()) }
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error: Undefined Behavior: deallocation of `pthread_mutex_t` is forbidden while the queue is non-empty
--> RUSTLIB/alloc/src/boxed.rs:LL:CC
|
LL | self.1.deallocate(From::from(ptr.cast()), layout);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
LL | self.1.deallocate(ptr.cast(), layout);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
Expand Down
4 changes: 2 additions & 2 deletions src/tools/miri/tests/fail/alloc/stack_free.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error: Undefined Behavior: deallocating ALLOC, which is stack variable memory, using Rust heap deallocation operation
--> RUSTLIB/alloc/src/boxed.rs:LL:CC
|
LL | self.1.deallocate(From::from(ptr.cast()), layout);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
LL | self.1.deallocate(ptr.cast(), layout);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error: Undefined Behavior: deallocating while item [Unique for <TAG>] is strongly protected
--> RUSTLIB/alloc/src/boxed.rs:LL:CC
|
LL | self.1.deallocate(From::from(ptr.cast()), layout);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
LL | self.1.deallocate(ptr.cast(), layout);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error: Undefined Behavior: deallocation through <TAG> at ALLOC[0x0] is forbidden
--> RUSTLIB/alloc/src/boxed.rs:LL:CC
|
LL | self.1.deallocate(From::from(ptr.cast()), layout);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
LL | self.1.deallocate(ptr.cast(), layout);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error: Undefined Behavior: not granting access to tag <TAG> because that would remove [Unique for <TAG>] which is strongly protected
--> RUSTLIB/alloc/src/boxed.rs:LL:CC
|
LL | Box(unsafe { Unique::new_unchecked(raw) }, alloc)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
LL | unsafe { Box(BoxRaw { pointer: NonNull::new_unchecked(raw), _marker: PhantomData }, alloc) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error: Undefined Behavior: deallocation through <TAG> at ALLOC[0x0] is forbidden
--> RUSTLIB/alloc/src/boxed.rs:LL:CC
|
LL | self.1.deallocate(From::from(ptr.cast()), layout);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
LL | self.1.deallocate(ptr.cast(), layout);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error: Undefined Behavior: not granting access to tag <TAG> because that would remove [Unique for <TAG>] which is strongly protected
--> RUSTLIB/alloc/src/boxed.rs:LL:CC
|
LL | Box(unsafe { Unique::new_unchecked(raw) }, alloc)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
LL | unsafe { Box(BoxRaw { pointer: NonNull::new_unchecked(raw), _marker: PhantomData }, alloc) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error: Undefined Behavior: deallocation through <TAG> at ALLOC[0x0] is forbidden
--> RUSTLIB/alloc/src/boxed.rs:LL:CC
|
LL | self.1.deallocate(From::from(ptr.cast()), layout);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
LL | self.1.deallocate(ptr.cast(), layout);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error: Undefined Behavior: deallocation through <TAG> at ALLOC[0x0] is forbidden
--> RUSTLIB/alloc/src/boxed.rs:LL:CC
|
LL | self.1.deallocate(From::from(ptr.cast()), layout);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
LL | self.1.deallocate(ptr.cast(), layout);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error: Undefined Behavior: deallocation through <TAG> at ALLOC[0x0] is forbidden
--> RUSTLIB/alloc/src/boxed.rs:LL:CC
|
LL | self.1.deallocate(From::from(ptr.cast()), layout);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
LL | self.1.deallocate(ptr.cast(), layout);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information
Expand Down
4 changes: 2 additions & 2 deletions src/tools/miri/tests/pass/alloc-access-tracking.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ LL | assert_eq!(*ptr, 42);
note: freed allocation ALLOC
--> RUSTLIB/alloc/src/boxed.rs:LL:CC
|
LL | self.1.deallocate(From::from(ptr.cast()), layout);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tracking was triggered here
LL | self.1.deallocate(ptr.cast(), layout);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tracking was triggered here
|
= note: stack backtrace:
0: <std::boxed::Box<std::mem::MaybeUninit<[u8; 123]>> as std::ops::Drop>::drop
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@
+ }
+
+ bb22: {
+ _14 = copy ((_1.0: std::ptr::Unique<HasDrop>).0: std::ptr::NonNull<HasDrop>) as *const HasDrop (Transmute);
+ _14 = copy ((_1.0: std::boxed::BoxRaw<HasDrop>).0: std::ptr::NonNull<HasDrop>) as *const HasDrop (Transmute);
+ goto -> bb21;
+ }
+
Expand All @@ -175,7 +175,7 @@
+ }
+
+ bb28 (cleanup): {
+ _17 = copy ((_1.0: std::ptr::Unique<HasDrop>).0: std::ptr::NonNull<HasDrop>) as *const HasDrop (Transmute);
+ _17 = copy ((_1.0: std::boxed::BoxRaw<HasDrop>).0: std::ptr::NonNull<HasDrop>) as *const HasDrop (Transmute);
+ goto -> bb27;
+ }
+
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@
+ }
+
+ bb13: {
+ _10 = copy ((_2.0: std::ptr::Unique<std::string::String>).0: std::ptr::NonNull<std::string::String>) as *const std::string::String (Transmute);
+ _10 = copy ((_2.0: std::boxed::BoxRaw<std::string::String>).0: std::ptr::NonNull<std::string::String>) as *const std::string::String (Transmute);
+ goto -> bb10;
}
}
Expand Down
2 changes: 1 addition & 1 deletion tests/mir-opt/box_partial_move.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
fn maybe_move(cond: bool, thing: Box<String>) -> Option<String> {
// CHECK-LABEL: fn maybe_move(
// CHECK: let mut [[PTR:_[0-9]+]]: *const std::string::String;
// CHECK: [[PTR]] = copy ((_2.0: std::ptr::Unique<std::string::String>).0: std::ptr::NonNull<std::string::String>) as *const std::string::String (Transmute);
// CHECK: [[PTR]] = copy ((_2.0: std::boxed::BoxRaw<std::string::String>).0: std::ptr::NonNull<std::string::String>) as *const std::string::String (Transmute);
// CHECK: drop((*[[PTR]]))
if cond { Some(*thing) } else { None }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
bb0: {
StorageLive(_1);
- _1 = const 1_usize as std::boxed::Box<Never> (Transmute);
- _2 = copy (_1.0: std::ptr::Unique<Never>) as *const Never (BoxDerefTransmute);
+ _1 = const Box::<Never>(std::ptr::Unique::<Never> {{ pointer: NonNull::<Never> {{ pointer: {0x1 as *const Never} is !null }}, _marker: PhantomData::<Never> }}, std::alloc::Global);
+ _2 = const std::ptr::Unique::<Never> {{ pointer: std::ptr::NonNull::<Never> {{ pointer: {0x1 as *const Never} is !null }}, _marker: std::marker::PhantomData::<Never> }} as *const Never (BoxDerefTransmute);
- _2 = copy (_1.0: std::boxed::BoxRaw<Never>) as *const Never (BoxDerefTransmute);
+ _1 = const Box::<Never>(boxed::BoxRaw::<Never> {{ pointer: NonNull::<Never> {{ pointer: {0x1 as *const Never} is !null }}, _marker: PhantomData::<Never> }}, std::alloc::Global);
+ _2 = const std::boxed::BoxRaw::<Never> {{ pointer: std::ptr::NonNull::<Never> {{ pointer: {0x1 as *const Never} is !null }}, _marker: std::marker::PhantomData::<Never> }} as *const Never (BoxDerefTransmute);
unreachable;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
bb0: {
StorageLive(_1);
- _1 = const 1_usize as std::boxed::Box<Never> (Transmute);
- _2 = copy (_1.0: std::ptr::Unique<Never>) as *const Never (BoxDerefTransmute);
+ _1 = const Box::<Never>(std::ptr::Unique::<Never> {{ pointer: NonNull::<Never> {{ pointer: {0x1 as *const Never} is !null }}, _marker: PhantomData::<Never> }}, std::alloc::Global);
+ _2 = const std::ptr::Unique::<Never> {{ pointer: std::ptr::NonNull::<Never> {{ pointer: {0x1 as *const Never} is !null }}, _marker: std::marker::PhantomData::<Never> }} as *const Never (BoxDerefTransmute);
- _2 = copy (_1.0: std::boxed::BoxRaw<Never>) as *const Never (BoxDerefTransmute);
+ _1 = const Box::<Never>(boxed::BoxRaw::<Never> {{ pointer: NonNull::<Never> {{ pointer: {0x1 as *const Never} is !null }}, _marker: PhantomData::<Never> }}, std::alloc::Global);
+ _2 = const std::boxed::BoxRaw::<Never> {{ pointer: std::ptr::NonNull::<Never> {{ pointer: {0x1 as *const Never} is !null }}, _marker: std::marker::PhantomData::<Never> }} as *const Never (BoxDerefTransmute);
unreachable;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// MIR for `build::{closure#0}` after built

| User Type Annotations
| 0: user_ty: Canonical { value: TypeOf(Box<^c_0>::new_uninit at <impl boxed::<{impl#0}> for Box<^c_1, ^c_2>>), max_universe: U0, var_kinds: [Ty { ui: U0, sub_root: 0 }, Ty { ui: U0, sub_root: 1 }, Ty { ui: U0, sub_root: 2 }] }, span: $SRC_DIR/alloc/src/macros.rs:LL:COL, inferred_ty: fn() -> std::boxed::Box<std::mem::MaybeUninit<[std::string::String; 5]>> {std::boxed::Box::<[std::string::String; 5]>::new_uninit}
| 0: user_ty: Canonical { value: TypeOf(Box<^c_0>::new_uninit at <impl boxed::<{impl#7}> for Box<^c_1, ^c_2>>), max_universe: U0, var_kinds: [Ty { ui: U0, sub_root: 0 }, Ty { ui: U0, sub_root: 1 }, Ty { ui: U0, sub_root: 2 }] }, span: $SRC_DIR/alloc/src/macros.rs:LL:COL, inferred_ty: fn() -> std::boxed::Box<std::mem::MaybeUninit<[std::string::String; 5]>> {std::boxed::Box::<[std::string::String; 5]>::new_uninit}
|
fn build::{closure#0}(_1: {async fn body of build()}, _2: std::future::ResumeTy) -> Vec<String>
yields ()
Expand Down
Loading
Loading