Use !null pattern type in libcore

This commit is contained in:
Oli Scherer
2025-05-17 14:35:25 +00:00
committed by Oli Scherer
parent 1fe72d3599
commit 834137afd7
32 changed files with 218 additions and 86 deletions
@@ -80,6 +80,7 @@ fn pat_to_ty_pat(cx: &mut ExtCtxt<'_>, pat: ast::Pat) -> TyPat {
TyPatKind::Or(variants.into_iter().map(|pat| pat_to_ty_pat(cx, pat)).collect())
}
ast::PatKind::Err(guar) => TyPatKind::Err(guar),
ast::PatKind::Paren(p) => pat_to_ty_pat(cx, *p).kind,
_ => TyPatKind::Err(cx.dcx().span_err(pat.span, "pattern not supported in pattern types")),
};
ty_pat(kind, pat.span)
@@ -8,6 +8,7 @@
rustc_attrs,
rustc_private,
transparent_unions,
pattern_types,
auto_traits,
freeze_impls
)]
@@ -15,6 +16,30 @@
#![no_core]
#![allow(dead_code, internal_features, ambiguous_wide_pointer_comparisons)]
#[lang = "pointee_trait"]
pub trait Pointee: PointeeSized {
#[lang = "metadata_type"]
// needed so that layout_of will return `TooGeneric` instead of `Unknown`
// when asked for the layout of `*const T`. Which is important for making
// transmutes between raw pointers (and especially pattern types of raw pointers)
// work.
type Metadata: Copy + Sync + Unpin + Freeze;
}
#[lang = "dyn_metadata"]
pub struct DynMetadata<Dyn: PointeeSized> {
_vtable_ptr: NonNull<VTable>,
_phantom: PhantomData<Dyn>,
}
unsafe extern "C" {
/// Opaque type for accessing vtables.
///
/// Private implementation detail of `DynMetadata::size_of` etc.
/// There is conceptually not actually any Abstract Machine memory behind this pointer.
type VTable;
}
#[lang = "pointee_sized"]
pub trait PointeeSized {}
@@ -105,7 +130,7 @@ unsafe impl<'a, T: PointeeSized> Sync for &'a T {}
unsafe impl<T: Sync, const N: usize> Sync for [T; N] {}
#[lang = "freeze"]
unsafe auto trait Freeze {}
pub unsafe auto trait Freeze {}
unsafe impl<T: PointeeSized> Freeze for PhantomData<T> {}
unsafe impl<T: PointeeSized> Freeze for *const T {}
@@ -570,10 +595,24 @@ pub trait Deref {
fn deref(&self) -> &Self::Target;
}
#[rustc_builtin_macro(pattern_type)]
#[macro_export]
macro_rules! pattern_type {
($($arg:tt)*) => {
/* compiler built-in */
};
}
impl<T: PointeeSized, U: PointeeSized> CoerceUnsized<pattern_type!(*const U is !null)> for pattern_type!(*const T is !null) where
T: Unsize<U>
{
}
impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<pattern_type!(U is !null)> for pattern_type!(T is !null) {}
#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start(1)]
#[rustc_nonnull_optimization_guaranteed]
pub struct NonNull<T: PointeeSized>(pub *const T);
pub struct NonNull<T: PointeeSized>(pub pattern_type!(*const T is !null));
impl<T: PointeeSized, U: PointeeSized> CoerceUnsized<NonNull<U>> for NonNull<T> where T: Unsize<U> {}
impl<T: PointeeSized, U: PointeeSized> DispatchFromDyn<NonNull<U>> for NonNull<T> where T: Unsize<U> {}
@@ -600,7 +639,16 @@ pub fn new(val: T) -> Box<T> {
let size = size_of::<T>();
let ptr = libc::malloc(size);
intrinsics::copy(&val as *const T as *const u8, ptr, size);
Box(Unique { pointer: NonNull(ptr as *const T), _marker: PhantomData }, Global)
Box(
Unique {
pointer: NonNull(intrinsics::transmute::<
*mut u8,
pattern_type!(*const T is !null),
>(ptr)),
_marker: PhantomData,
},
Global,
)
}
}
}
@@ -609,7 +657,9 @@ impl<T: ?Sized, A> Drop for Box<T, A> {
fn drop(&mut self) {
// inner value is dropped by compiler
unsafe {
libc::free(self.0.pointer.0 as *mut u8);
libc::free(intrinsics::transmute::<pattern_type!(*const T is !null), *const T>(
self.0.pointer.0,
) as *mut u8);
}
}
}
@@ -1,4 +1,13 @@
#![feature(no_core, lang_items, never_type, extern_types, thread_local, repr_simd, rustc_private)]
#![feature(
no_core,
lang_items,
never_type,
extern_types,
thread_local,
repr_simd,
pattern_types,
rustc_private
)]
#![cfg_attr(not(any(jit, target_vendor = "apple", windows)), feature(linkage))]
#![no_core]
#![allow(dead_code, non_camel_case_types, internal_features)]
@@ -153,7 +162,10 @@ extern "C" fn bool_struct_in_11(_arg0: bool_11) {}
#[allow(unreachable_code)] // FIXME false positive
fn main() {
take_unique(Unique { pointer: unsafe { NonNull(1 as *mut ()) }, _marker: PhantomData });
take_unique(Unique {
pointer: unsafe { NonNull(intrinsics::transmute(1 as *mut ())) },
_marker: PhantomData,
});
take_f32(0.1);
call_return_u128_pair();
@@ -219,7 +231,12 @@ fn main() {
let noisy_unsized_drop = const { intrinsics::needs_drop::<NoisyDropUnsized>() };
assert!(noisy_unsized_drop);
Unique { pointer: NonNull(1 as *mut &str), _marker: PhantomData } as Unique<dyn SomeTrait>;
Unique {
pointer: NonNull(intrinsics::transmute::<_, pattern_type!(*const &str is !null)>(
1 as *mut &str,
)),
_marker: PhantomData,
} as Unique<dyn SomeTrait>;
struct MyDst<T: ?Sized>(T);
@@ -9,6 +9,7 @@
transparent_unions,
auto_traits,
freeze_impls,
pattern_types,
thread_local
)]
#![no_core]
@@ -580,9 +581,16 @@ impl Allocator for () {}
impl Allocator for Global {}
#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start(1)]
#[rustc_nonnull_optimization_guaranteed]
pub struct NonNull<T: PointeeSized>(pub *const T);
pub struct NonNull<T: PointeeSized>(pub pattern_type!(*const T is !null));
#[rustc_builtin_macro(pattern_type)]
#[macro_export]
macro_rules! pattern_type {
($($arg:tt)*) => {
/* compiler built-in */
};
}
impl<T: PointeeSized, U: PointeeSized> CoerceUnsized<NonNull<U>> for NonNull<T> where T: Unsize<U> {}
impl<T: PointeeSized, U: PointeeSized> DispatchFromDyn<NonNull<U>> for NonNull<T> where T: Unsize<U> {}
+8 -1
View File
@@ -27,7 +27,7 @@
use rustc_middle::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem, MonoItemPartitions};
use rustc_middle::query::Providers;
use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout};
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
use rustc_middle::ty::{self, Instance, PatternKind, Ty, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_session::Session;
use rustc_session::config::{self, CrateType, EntryFnType};
@@ -273,6 +273,13 @@ pub(crate) fn coerce_unsized_into<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
let src_ty = src.layout.ty;
let dst_ty = dst.layout.ty;
match (src_ty.kind(), dst_ty.kind()) {
(&ty::Pat(s, sp), &ty::Pat(d, dp))
if let (PatternKind::NotNull, PatternKind::NotNull) = (*sp, *dp) =>
{
let src = src.project_type(bx, s);
let dst = dst.project_type(bx, d);
coerce_unsized_into(bx, src, dst)
}
(&ty::Ref(..), &ty::Ref(..) | &ty::RawPtr(..)) | (&ty::RawPtr(..), &ty::RawPtr(..)) => {
let (base, info) = match bx.load_operand(src).val {
OperandValue::Pair(base, info) => unsize_ptr(bx, base, src_ty, dst_ty, Some(info)),
@@ -124,7 +124,12 @@ fn walk_value(&mut self, v: &Self::V) -> InterpResult<'tcx> {
// ... that contains a `NonNull`... (gladly, only a single field here)
assert_eq!(nonnull_ptr.layout().fields.count(), 1);
let raw_ptr = self.ecx().project_field(&nonnull_ptr, FieldIdx::ZERO)?; // the actual raw ptr
let pat_ty = self.ecx().project_field(&nonnull_ptr, FieldIdx::ZERO)?; // `*mut T is !null`
let base = match *pat_ty.layout().ty.kind() {
ty::Pat(base, _) => self.ecx().layout_of(base)?,
_ => unreachable!(),
};
let raw_ptr = pat_ty.transmute(base, self.ecx())?; // The actual raw pointer
// ... whose only field finally is a raw ptr we can dereference.
self.visit_box(ty, &raw_ptr)?;
@@ -24,6 +24,7 @@ fn may_contain_reference<'tcx>(ty: Ty<'tcx>, depth: u32, tcx: TyCtxt<'tcx>) -> b
| ty::Str
| ty::FnDef(..)
| ty::Never => false,
ty::Pat(base, ..) => may_contain_reference(*base, depth, tcx),
// References and Boxes (`noalias` sources)
ty::Ref(..) => true,
ty::Adt(..) if ty.is_box() => true,
@@ -6,7 +6,7 @@
use rustc_middle::mir::visit::MutVisitor;
use rustc_middle::mir::*;
use rustc_middle::span_bug;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{self, PatternKind, Ty, TyCtxt};
use crate::patch::MirPatch;
@@ -137,8 +137,10 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
build_ptr_tys(tcx, boxed_ty, unique_def, nonnull_def);
new_projections.extend_from_slice(&build_projection(unique_ty, nonnull_ty));
// While we can't project into `NonNull<_>` in a basic block
// due to MCP#807, this is debug info where it's fine.
// While we can't project into a pattern type in a basic block,
// this is debug info where it's fine.
let pat_ty = Ty::new_pat(tcx, ptr_ty, tcx.mk_pat(PatternKind::NotNull));
new_projections.push(PlaceElem::Field(FieldIdx::ZERO, pat_ty));
new_projections.push(PlaceElem::Field(FieldIdx::ZERO, ptr_ty));
new_projections.push(PlaceElem::Deref);
} else if let Some(new_projections) = new_projections.as_mut() {
+2
View File
@@ -937,6 +937,8 @@ impl<T: PointeeSized> !UnsafeUnpin for UnsafePinned<T> {}
{T: PointeeSized} *mut T,
{T: PointeeSized} &T,
{T: PointeeSized} &mut T,
{T: PointeeSized} pattern_type!(*const T is !null),
{T: PointeeSized} pattern_type!(*mut T is !null),
}
/// Types that do not require any pinning guarantees.
+1 -4
View File
@@ -69,13 +69,10 @@
/// [null pointer optimization]: crate::option#representation
#[stable(feature = "nonnull", since = "1.25.0")]
#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start(1)]
#[rustc_nonnull_optimization_guaranteed]
#[rustc_diagnostic_item = "NonNull"]
pub struct NonNull<T: PointeeSized> {
// Remember to use `.as_ptr()` instead of `.pointer`, as field projecting to
// this is banned by <https://github.com/rust-lang/compiler-team/issues/807>.
pointer: *const T,
pointer: crate::pattern_type!(*const T is !null),
}
/// `NonNull` pointers are not `Send` because the data they reference may be aliased.
+1 -2
View File
@@ -2,8 +2,7 @@
#[test]
fn test_raw_fd_layout() {
// `OwnedFd` and `BorrowedFd` use `rustc_layout_scalar_valid_range_start`
// and `rustc_layout_scalar_valid_range_end`, with values that depend on
// `OwnedFd` and `BorrowedFd` use pattern types, with ranges that depend on
// the bit width of `RawFd`. If this ever changes, those values will need
// to be updated.
assert_eq!(size_of::<RawFd>(), 4);
+1 -2
View File
@@ -2,8 +2,7 @@
#[test]
fn test_raw_fd_layout() {
// `OwnedFd` and `BorrowedFd` use `rustc_layout_scalar_valid_range_start`
// and `rustc_layout_scalar_valid_range_end`, with values that depend on
// `OwnedFd` and `BorrowedFd` use pattern types with ranges that depend on
// the bit width of `RawFd`. If this ever changes, those values will need
// to be updated.
assert_eq!(size_of::<RawFd>(), 4);
@@ -242,6 +242,10 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx>
loop {
ty = cx.tcx.try_normalize_erasing_regions(cx.typing_env(), ty).unwrap_or(ty);
return match *ty.kind() {
ty::Pat(base, _) => {
ty = base;
continue;
},
ty::Array(sub_ty, _) if matches!(sub_ty.kind(), ty::Int(_) | ty::Uint(_)) => {
ReducedTy::TypeErasure { raw_ptr_only: false }
},
+46 -4
View File
@@ -22,6 +22,7 @@
auto_traits,
freeze_impls,
negative_impls,
pattern_types,
rustc_attrs,
decl_macro,
f16,
@@ -127,17 +128,42 @@ pub struct ManuallyDrop<T: PointeeSized> {
impl<T: Copy + PointeeSized> Copy for ManuallyDrop<T> {}
#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start(1)]
#[rustc_nonnull_optimization_guaranteed]
pub struct NonNull<T: ?Sized> {
pointer: *const T,
pointer: pattern_type!(*const T is !null),
}
impl<T: ?Sized> Copy for NonNull<T> {}
#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start(1)]
#[rustc_nonnull_optimization_guaranteed]
pub struct NonZero<T>(T);
pub struct NonZero<T: ZeroablePrimitive>(T::NonZeroInner);
pub trait ZeroablePrimitive {
type NonZeroInner;
}
macro_rules! define_valid_range_type {
($(
$name:ident($int:ident is $pat:pat);
)+) => {$(
#[repr(transparent)]
pub struct $name(pattern_type!($int is $pat));
impl ZeroablePrimitive for $int {
type NonZeroInner = $name;
}
)+};
}
define_valid_range_type! {
NonZeroU8Inner(u8 is 1..=0xFF);
NonZeroU16Inner(u16 is 1..=0xFFFF);
NonZeroU32Inner(u32 is 1..=0xFFFF_FFFF);
NonZeroU64Inner(u64 is 1..=0xFFFF_FFFF_FFFF_FFFF);
NonZeroI8Inner(i8 is (-128..=-1 | 1..=0x7F));
NonZeroI32Inner(i32 is (-0x8000_0000..=-1 | 1..=0x7FFF_FFFF));
}
pub struct Unique<T: ?Sized> {
pub pointer: NonNull<T>,
@@ -225,6 +251,14 @@ fn neg(self) -> i8 {
}
}
impl Neg for i32 {
type Output = i32;
fn neg(self) -> i32 {
loop {}
}
}
#[lang = "sync"]
pub trait Sync {}
impl_marker_trait!(
@@ -314,6 +348,14 @@ pub enum c_void {
__variant2,
}
#[rustc_builtin_macro(pattern_type)]
#[macro_export]
macro_rules! pattern_type {
($($arg:tt)*) => {
/* compiler built-in */
};
}
#[lang = "Ordering"]
#[repr(i8)]
pub enum Ordering {
@@ -13,8 +13,8 @@
StorageLive(_1);
- _1 = const 1_usize as std::boxed::Box<Never> (Transmute);
- _2 = copy ((_1.0: std::ptr::Unique<Never>).0: std::ptr::NonNull<Never>) as *const Never (Transmute);
+ _1 = const Box::<Never>(std::ptr::Unique::<Never> {{ pointer: NonNull::<Never> {{ pointer: {0x1 as *const Never} }}, _marker: PhantomData::<Never> }}, std::alloc::Global);
+ _2 = const std::ptr::NonNull::<Never> {{ pointer: {0x1 as *const Never} }} as *const Never (Transmute);
+ _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::NonNull::<Never> {{ pointer: {0x1 as *const Never} is !null }} as *const Never (Transmute);
unreachable;
}
}
@@ -13,8 +13,8 @@
StorageLive(_1);
- _1 = const 1_usize as std::boxed::Box<Never> (Transmute);
- _2 = copy ((_1.0: std::ptr::Unique<Never>).0: std::ptr::NonNull<Never>) as *const Never (Transmute);
+ _1 = const Box::<Never>(std::ptr::Unique::<Never> {{ pointer: NonNull::<Never> {{ pointer: {0x1 as *const Never} }}, _marker: PhantomData::<Never> }}, std::alloc::Global);
+ _2 = const std::ptr::NonNull::<Never> {{ pointer: {0x1 as *const Never} }} as *const Never (Transmute);
+ _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::NonNull::<Never> {{ pointer: {0x1 as *const Never} is !null }} as *const Never (Transmute);
unreachable;
}
}
@@ -34,14 +34,14 @@
StorageLive(_3);
StorageLive(_4);
StorageLive(_5);
_5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
_4 = const std::ptr::Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};
_5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} is !null }};
_4 = const std::ptr::Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} is !null }}, _marker: PhantomData::<[bool; 0]> }};
StorageDead(_5);
_3 = const std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }};
_3 = const std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }};
StorageDead(_4);
_2 = const Box::<[bool]>(std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global);
_2 = const Box::<[bool]>(std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global);
StorageDead(_3);
_1 = const A {{ foo: Box::<[bool]>(std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }};
_1 = const A {{ foo: Box::<[bool]>(std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }};
StorageDead(_2);
_0 = const ();
drop(_1) -> [return: bb1, unwind unreachable];
@@ -34,14 +34,14 @@
StorageLive(_3);
StorageLive(_4);
StorageLive(_5);
_5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
_4 = const std::ptr::Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};
_5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} is !null }};
_4 = const std::ptr::Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} is !null }}, _marker: PhantomData::<[bool; 0]> }};
StorageDead(_5);
_3 = const std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }};
_3 = const std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }};
StorageDead(_4);
_2 = const Box::<[bool]>(std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global);
_2 = const Box::<[bool]>(std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global);
StorageDead(_3);
_1 = const A {{ foo: Box::<[bool]>(std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }};
_1 = const A {{ foo: Box::<[bool]>(std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }};
StorageDead(_2);
_0 = const ();
drop(_1) -> [return: bb1, unwind: bb2];
@@ -34,14 +34,14 @@
StorageLive(_3);
StorageLive(_4);
StorageLive(_5);
_5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
_4 = const std::ptr::Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};
_5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} is !null }};
_4 = const std::ptr::Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} is !null }}, _marker: PhantomData::<[bool; 0]> }};
StorageDead(_5);
_3 = const std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }};
_3 = const std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }};
StorageDead(_4);
_2 = const Box::<[bool]>(std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global);
_2 = const Box::<[bool]>(std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global);
StorageDead(_3);
_1 = const A {{ foo: Box::<[bool]>(std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }};
_1 = const A {{ foo: Box::<[bool]>(std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }};
StorageDead(_2);
_0 = const ();
drop(_1) -> [return: bb1, unwind unreachable];
@@ -34,14 +34,14 @@
StorageLive(_3);
StorageLive(_4);
StorageLive(_5);
_5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
_4 = const std::ptr::Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};
_5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} is !null }};
_4 = const std::ptr::Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} is !null }}, _marker: PhantomData::<[bool; 0]> }};
StorageDead(_5);
_3 = const std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }};
_3 = const std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }};
StorageDead(_4);
_2 = const Box::<[bool]>(std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global);
_2 = const Box::<[bool]>(std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global);
StorageDead(_3);
_1 = const A {{ foo: Box::<[bool]>(std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }};
_1 = const A {{ foo: Box::<[bool]>(std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }};
StorageDead(_2);
_0 = const ();
drop(_1) -> [return: bb1, unwind: bb2];
@@ -36,17 +36,17 @@
StorageLive(_5);
- _5 = const <[bool; 0] as std::mem::SizedTypeProperties>::ALIGNMENT as std::ptr::NonNull<[bool; 0]> (Transmute);
- _4 = std::ptr::Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> };
+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
+ _4 = const std::ptr::Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};
+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} is !null }};
+ _4 = const std::ptr::Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} is !null }}, _marker: PhantomData::<[bool; 0]> }};
StorageDead(_5);
- _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize, Implicit));
+ _3 = const std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }};
+ _3 = const std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }};
StorageDead(_4);
- _2 = Box::<[bool]>(copy _3, const std::alloc::Global);
+ _2 = const Box::<[bool]>(std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global);
+ _2 = const Box::<[bool]>(std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global);
StorageDead(_3);
- _1 = A { foo: move _2 };
+ _1 = const A {{ foo: Box::<[bool]>(std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }};
+ _1 = const A {{ foo: Box::<[bool]>(std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }};
StorageDead(_2);
_0 = const ();
drop(_1) -> [return: bb1, unwind unreachable];
@@ -36,17 +36,17 @@
StorageLive(_5);
- _5 = const <[bool; 0] as std::mem::SizedTypeProperties>::ALIGNMENT as std::ptr::NonNull<[bool; 0]> (Transmute);
- _4 = std::ptr::Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> };
+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
+ _4 = const std::ptr::Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};
+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} is !null }};
+ _4 = const std::ptr::Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} is !null }}, _marker: PhantomData::<[bool; 0]> }};
StorageDead(_5);
- _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize, Implicit));
+ _3 = const std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }};
+ _3 = const std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }};
StorageDead(_4);
- _2 = Box::<[bool]>(copy _3, const std::alloc::Global);
+ _2 = const Box::<[bool]>(std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global);
+ _2 = const Box::<[bool]>(std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global);
StorageDead(_3);
- _1 = A { foo: move _2 };
+ _1 = const A {{ foo: Box::<[bool]>(std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }};
+ _1 = const A {{ foo: Box::<[bool]>(std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }};
StorageDead(_2);
_0 = const ();
drop(_1) -> [return: bb1, unwind: bb2];
@@ -36,17 +36,17 @@
StorageLive(_5);
- _5 = const <[bool; 0] as std::mem::SizedTypeProperties>::ALIGNMENT as std::ptr::NonNull<[bool; 0]> (Transmute);
- _4 = std::ptr::Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> };
+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
+ _4 = const std::ptr::Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};
+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} is !null }};
+ _4 = const std::ptr::Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} is !null }}, _marker: PhantomData::<[bool; 0]> }};
StorageDead(_5);
- _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize, Implicit));
+ _3 = const std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }};
+ _3 = const std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }};
StorageDead(_4);
- _2 = Box::<[bool]>(copy _3, const std::alloc::Global);
+ _2 = const Box::<[bool]>(std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global);
+ _2 = const Box::<[bool]>(std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global);
StorageDead(_3);
- _1 = A { foo: move _2 };
+ _1 = const A {{ foo: Box::<[bool]>(std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }};
+ _1 = const A {{ foo: Box::<[bool]>(std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }};
StorageDead(_2);
_0 = const ();
drop(_1) -> [return: bb1, unwind unreachable];
@@ -36,17 +36,17 @@
StorageLive(_5);
- _5 = const <[bool; 0] as std::mem::SizedTypeProperties>::ALIGNMENT as std::ptr::NonNull<[bool; 0]> (Transmute);
- _4 = std::ptr::Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> };
+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
+ _4 = const std::ptr::Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }};
+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} is !null }};
+ _4 = const std::ptr::Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} is !null }}, _marker: PhantomData::<[bool; 0]> }};
StorageDead(_5);
- _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize, Implicit));
+ _3 = const std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }};
+ _3 = const std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }};
StorageDead(_4);
- _2 = Box::<[bool]>(copy _3, const std::alloc::Global);
+ _2 = const Box::<[bool]>(std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global);
+ _2 = const Box::<[bool]>(std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global);
StorageDead(_3);
- _1 = A { foo: move _2 };
+ _1 = const A {{ foo: Box::<[bool]>(std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }};
+ _1 = const A {{ foo: Box::<[bool]>(std::ptr::Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }};
StorageDead(_2);
_0 = const ();
drop(_1) -> [return: bb1, unwind: bb2];
@@ -12,7 +12,7 @@
bb0: {
StorageLive(_1);
- _1 = const 1_usize as std::boxed::Box<Never> (Transmute);
+ _1 = const Box::<Never>(std::ptr::Unique::<Never> {{ pointer: NonNull::<Never> {{ pointer: {0x1 as *const Never} }}, _marker: PhantomData::<Never> }}, std::alloc::Global);
+ _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 = copy ((_1.0: std::ptr::Unique<Never>).0: std::ptr::NonNull<Never>) as *const Never (Transmute);
unreachable;
}
@@ -12,7 +12,7 @@
bb0: {
StorageLive(_1);
- _1 = const 1_usize as std::boxed::Box<Never> (Transmute);
+ _1 = const Box::<Never>(std::ptr::Unique::<Never> {{ pointer: NonNull::<Never> {{ pointer: {0x1 as *const Never} }}, _marker: PhantomData::<Never> }}, std::alloc::Global);
+ _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 = copy ((_1.0: std::ptr::Unique<Never>).0: std::ptr::NonNull<Never>) as *const Never (Transmute);
unreachable;
}
@@ -3,7 +3,7 @@
fn pointee(_1: Box<i32>) -> () {
- debug foo => (*_1);
+ debug foo => (*(((_1.0: std::ptr::Unique<i32>).0: std::ptr::NonNull<i32>).0: *const i32));
+ debug foo => (*((((_1.0: std::ptr::Unique<i32>).0: std::ptr::NonNull<i32>).0: (*const i32) is !null).0: *const i32));
let mut _0: ();
bb0: {
@@ -53,7 +53,7 @@ LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::tran
78 00 00 00 ff ff ff ff │ x.......
}
error[E0080]: constructing invalid value of type NonNull<u8>: encountered 0, but expected something greater or equal to 1
error[E0080]: constructing invalid value of type NonNull<u8>: at .pointer, encountered 0, but expected something greater or equal to 1
--> $DIR/raw-bytes.rs:58:1
|
LL | const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
@@ -108,7 +108,7 @@ LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) };
14 00 00 00 │ ....
}
error[E0080]: constructing invalid value of type NonNull<dyn Send>: encountered 0, but expected something greater or equal to 1
error[E0080]: constructing invalid value of type NonNull<dyn Send>: at .pointer, encountered 0, but expected something greater or equal to 1
--> $DIR/raw-bytes.rs:78:1
|
LL | const NULL_FAT_PTR: NonNull<dyn Send> = unsafe {
@@ -53,7 +53,7 @@ LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::tran
78 00 00 00 ff ff ff ff │ x.......
}
error[E0080]: constructing invalid value of type NonNull<u8>: encountered 0, but expected something greater or equal to 1
error[E0080]: constructing invalid value of type NonNull<u8>: at .pointer, encountered 0, but expected something greater or equal to 1
--> $DIR/raw-bytes.rs:58:1
|
LL | const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
@@ -108,7 +108,7 @@ LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) };
14 00 00 00 │ ....
}
error[E0080]: constructing invalid value of type NonNull<dyn Send>: encountered 0, but expected something greater or equal to 1
error[E0080]: constructing invalid value of type NonNull<dyn Send>: at .pointer, encountered 0, but expected something greater or equal to 1
--> $DIR/raw-bytes.rs:78:1
|
LL | const NULL_FAT_PTR: NonNull<dyn Send> = unsafe {
+3 -3
View File
@@ -1,4 +1,4 @@
error[E0080]: constructing invalid value of type NonNull<u8>: encountered 0, but expected something greater or equal to 1
error[E0080]: constructing invalid value of type NonNull<u8>: at .pointer, encountered 0, but expected something greater or equal to 1
--> $DIR/ub-nonnull.rs:16:1
|
LL | const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
@@ -69,7 +69,7 @@ LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) };
HEX_DUMP
}
error[E0080]: constructing invalid value of type NonNull<dyn Send>: encountered 0, but expected something greater or equal to 1
error[E0080]: constructing invalid value of type NonNull<dyn Send>: at .pointer, encountered 0, but expected something greater or equal to 1
--> $DIR/ub-nonnull.rs:53:1
|
LL | const NULL_FAT_PTR: NonNull<dyn Send> = unsafe {
@@ -80,7 +80,7 @@ LL | const NULL_FAT_PTR: NonNull<dyn Send> = unsafe {
HEX_DUMP
}
error[E0080]: constructing invalid value of type NonNull<()>: encountered a maybe-null pointer, but expected something that is definitely non-zero
error[E0080]: constructing invalid value of type NonNull<()>: at .pointer, encountered a maybe-null pointer, but expected something that is definitely non-zero
--> $DIR/ub-nonnull.rs:61:1
|
LL | const MAYBE_NULL_PTR: NonNull<()> = unsafe { mem::transmute((&raw const S).wrapping_add(4)) };
-2
View File
@@ -314,7 +314,6 @@ LL | let _val: NonNull<i32> = mem::uninitialized();
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
|
= note: `std::ptr::NonNull<i32>` must be non-null
= note: raw pointers must be initialized
error: the type `(NonZero<u32>, i32)` does not permit zero-initialization
--> $DIR/invalid_value.rs:94:41
@@ -623,7 +622,6 @@ LL | let _val: NonNull<i32> = MaybeUninit::uninit().assume_init();
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
|
= note: `std::ptr::NonNull<i32>` must be non-null
= note: raw pointers must be initialized
error: the type `bool` does not permit being left uninitialized
--> $DIR/invalid_value.rs:158:26
@@ -2,10 +2,10 @@
//@ compile-flags: -Z mir-opt-level=4
#![crate_type = "lib"]
#![feature(lang_items)]
#![feature(lang_items, pattern_type_macro, pattern_types)]
#![no_std]
struct NonNull<T: ?Sized>(*const T);
struct NonNull<T: ?Sized>(pattern_type!(*const T is !null));
struct Unique<T: ?Sized>(NonNull<T>);
@@ -20,7 +20,7 @@ fn drop(&mut self) {
}
#[inline(never)]
fn dealloc<T: ?Sized>(_: *const T) {}
fn dealloc<T: ?Sized>(_: pattern_type!(*const T is !null)) {}
pub struct Foo<T>(T);