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
13 changes: 12 additions & 1 deletion compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,18 @@ pub(crate) fn spanned_type_di_node<'ll, 'tcx>(
AdtKind::Enum => enums::build_enum_type_di_node(cx, unique_type_id, span),
},
ty::Tuple(_) => build_tuple_type_di_node(cx, unique_type_id),
_ => bug!("debuginfo: unexpected type in type_di_node(): {:?}", t),
ty::Pat(base, _) => return type_di_node(cx, base),
// FIXME(unsafe_binders): impl debug info
ty::UnsafeBinder(_) => unimplemented!(),
ty::Alias(..)
| ty::Param(_)
| ty::Bound(..)
| ty::Infer(_)
| ty::Placeholder(_)
| ty::CoroutineWitness(..)
| ty::Error(_) => {
bug!("debuginfo: unexpected type in type_di_node(): {:?}", t)
}
};

{
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_const_eval/src/interpret/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
let (_, field) = layout.non_1zst_field(self).unwrap();
self.unfold_transparent(field, may_unfold)
}
ty::Pat(base, _) => self.layout_of(*base).expect(
"if the layout of a pattern type could be computed, so can the layout of its base",
),
// Not a transparent type, no further unfolding.
_ => layout,
}
Expand Down
102 changes: 38 additions & 64 deletions library/core/src/num/niche_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,60 +5,47 @@
)]

use crate::cmp::Ordering;
use crate::fmt;
use crate::hash::{Hash, Hasher};
use crate::marker::StructuralPartialEq;
use crate::{fmt, pattern_type};

macro_rules! define_valid_range_type {
($(
$(#[$m:meta])*
$vis:vis struct $name:ident($int:ident as $uint:ident in $low:literal..=$high:literal);
$vis:vis struct $name:ident($int:ident is $pat:pat);
)+) => {$(
#[derive(Clone, Copy, Eq)]
#[derive(Clone, Copy)]
#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start($low)]
#[rustc_layout_scalar_valid_range_end($high)]
$(#[$m])*
$vis struct $name($int);

const _: () = {
// With the `valid_range` attributes, it's always specified as unsigned
assert!(<$uint>::MIN == 0);
let ulow: $uint = $low;
let uhigh: $uint = $high;
assert!(ulow <= uhigh);

assert!(size_of::<$int>() == size_of::<$uint>());
};

$vis struct $name(pattern_type!($int is $pat));
impl $name {
#[inline]
pub const fn new(val: $int) -> Option<Self> {
if (val as $uint) >= ($low as $uint) && (val as $uint) <= ($high as $uint) {
// SAFETY: just checked the inclusive range
Some(unsafe { $name(val) })
#[allow(non_contiguous_range_endpoints)]
if let $pat = val {
// SAFETY: just checked that the value matches the pattern
Some(unsafe { $name(crate::mem::transmute(val)) })
} else {
None
}
}

/// Constructs an instance of this type from the underlying integer
/// primitive without checking whether its zero.
/// primitive without checking whether its valid.
///
/// # Safety
/// Immediate language UB if `val` is not within the valid range for this
/// type, as it violates the validity invariant.
#[inline]
pub const unsafe fn new_unchecked(val: $int) -> Self {
// SAFETY: Caller promised that `val` is within the valid range.
unsafe { $name(val) }
unsafe { $name(crate::mem::transmute(val)) }
}

#[inline]
pub const fn as_inner(self) -> $int {
// SAFETY: This is a transparent wrapper, so unwrapping it is sound
// (Not using `.0` due to MCP#807.)
unsafe { crate::mem::transmute(self) }
// SAFETY: pattern types are always legal values of their base type
unsafe { crate::mem::transmute(self.0) }
}
}

Expand All @@ -67,6 +54,8 @@ macro_rules! define_valid_range_type {
// by <https://github.com/rust-lang/compiler-team/issues/807>.
impl StructuralPartialEq for $name {}

impl Eq for $name {}

impl PartialEq for $name {
#[inline]
fn eq(&self, other: &Self) -> bool {
Expand Down Expand Up @@ -104,7 +93,7 @@ macro_rules! define_valid_range_type {
}

define_valid_range_type! {
pub struct Nanoseconds(u32 as u32 in 0..=999_999_999);
pub struct Nanoseconds(u32 is 0..=999_999_999);
}

impl Nanoseconds {
Expand All @@ -120,47 +109,32 @@ impl const Default for Nanoseconds {
}
}

define_valid_range_type! {
pub struct NonZeroU8Inner(u8 as u8 in 1..=0xff);
pub struct NonZeroU16Inner(u16 as u16 in 1..=0xff_ff);
pub struct NonZeroU32Inner(u32 as u32 in 1..=0xffff_ffff);
pub struct NonZeroU64Inner(u64 as u64 in 1..=0xffffffff_ffffffff);
pub struct NonZeroU128Inner(u128 as u128 in 1..=0xffffffffffffffff_ffffffffffffffff);

pub struct NonZeroI8Inner(i8 as u8 in 1..=0xff);
pub struct NonZeroI16Inner(i16 as u16 in 1..=0xff_ff);
pub struct NonZeroI32Inner(i32 as u32 in 1..=0xffff_ffff);
pub struct NonZeroI64Inner(i64 as u64 in 1..=0xffffffff_ffffffff);
pub struct NonZeroI128Inner(i128 as u128 in 1..=0xffffffffffffffff_ffffffffffffffff);

pub struct NonZeroCharInner(char as u32 in 1..=0x10ffff);
}
const HALF_USIZE: usize = usize::MAX >> 1;

#[cfg(target_pointer_width = "16")]
define_valid_range_type! {
pub struct UsizeNoHighBit(usize as usize in 0..=0x7fff);
pub struct NonZeroUsizeInner(usize as usize in 1..=0xffff);
pub struct NonZeroIsizeInner(isize as usize in 1..=0xffff);
}
#[cfg(target_pointer_width = "32")]
define_valid_range_type! {
pub struct UsizeNoHighBit(usize as usize in 0..=0x7fff_ffff);
pub struct NonZeroUsizeInner(usize as usize in 1..=0xffff_ffff);
pub struct NonZeroIsizeInner(isize as usize in 1..=0xffff_ffff);
}
#[cfg(target_pointer_width = "64")]
define_valid_range_type! {
pub struct UsizeNoHighBit(usize as usize in 0..=0x7fff_ffff_ffff_ffff);
pub struct NonZeroUsizeInner(usize as usize in 1..=0xffff_ffff_ffff_ffff);
pub struct NonZeroIsizeInner(isize as usize in 1..=0xffff_ffff_ffff_ffff);
}
pub struct NonZeroU8Inner(u8 is 1..);
pub struct NonZeroU16Inner(u16 is 1..);
pub struct NonZeroU32Inner(u32 is 1..);
pub struct NonZeroU64Inner(u64 is 1..);
pub struct NonZeroU128Inner(u128 is 1..);

define_valid_range_type! {
pub struct U32NotAllOnes(u32 as u32 in 0..=0xffff_fffe);
pub struct I32NotAllOnes(i32 as u32 in 0..=0xffff_fffe);
pub struct NonZeroI8Inner(i8 is ..0 | 1..);
pub struct NonZeroI16Inner(i16 is ..0 | 1..);
pub struct NonZeroI32Inner(i32 is ..0 | 1..);
pub struct NonZeroI64Inner(i64 is ..0 | 1..);
pub struct NonZeroI128Inner(i128 is ..0 | 1..);

pub struct UsizeNoHighBit(usize is 0..=HALF_USIZE);
pub struct NonZeroUsizeInner(usize is 1..);
pub struct NonZeroIsizeInner(isize is ..0 | 1..);

pub struct U32NotAllOnes(u32 is 0..u32::MAX);
pub struct I32NotAllOnes(i32 is ..-1 | 0..);

pub struct U64NotAllOnes(u64 is 0..u64::MAX);
pub struct I64NotAllOnes(i64 is ..-1 | 0..);

pub struct U64NotAllOnes(u64 as u64 in 0..=0xffff_ffff_ffff_fffe);
pub struct I64NotAllOnes(i64 as u64 in 0..=0xffff_ffff_ffff_fffe);
pub struct NonZeroCharInner(char is '\u{1}' ..= '\u{10ffff}');
}

pub trait NotAllOnesHelper {
Expand All @@ -181,7 +155,7 @@ impl NotAllOnesHelper for i64 {
}

define_valid_range_type! {
pub struct CodePointInner(u32 as u32 in 0..=0x10ffff);
pub struct CodePointInner(u32 is 0..=0x10ffff);
}

impl CodePointInner {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error: Undefined Behavior: constructing invalid value at .0: encountered 0, but expected something greater or equal to 1
error: Undefined Behavior: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we use .0 for pattern types? 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In const eval diagnostics we use that for accessing wide pointer components, too

There's probably lots to improve here, but I just made pattern types behave the same

--> tests/fail/validity/cast_fn_ptr_invalid_callee_ret.rs:LL:CC
|
LL | f();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error: Undefined Behavior: constructing invalid value at .0: encountered 0, but expected something greater or equal to 1
error: Undefined Behavior: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1
--> tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs:LL:CC
|
LL | Call(_res = f(*ptr), ReturnTo(retblock), UnwindContinue())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
StorageLive(_4);
StorageLive(_5);
StorageLive(_6);
_6 = const NonZero::<usize>(core::num::niche_types::NonZeroUsizeInner(1_usize));
_6 = const NonZero::<usize>(core::num::niche_types::NonZeroUsizeInner(1_usize is 1..));
StorageLive(_7);
_7 = const {0x1 as *const [bool; 0]};
_5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
StorageLive(_4);
StorageLive(_5);
StorageLive(_6);
_6 = const NonZero::<usize>(core::num::niche_types::NonZeroUsizeInner(1_usize));
_6 = const NonZero::<usize>(core::num::niche_types::NonZeroUsizeInner(1_usize is 1..));
StorageLive(_7);
_7 = const {0x1 as *const [bool; 0]};
_5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
StorageLive(_4);
StorageLive(_5);
StorageLive(_6);
_6 = const NonZero::<usize>(core::num::niche_types::NonZeroUsizeInner(1_usize));
_6 = const NonZero::<usize>(core::num::niche_types::NonZeroUsizeInner(1_usize is 1..));
StorageLive(_7);
_7 = const {0x1 as *const [bool; 0]};
_5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
StorageLive(_4);
StorageLive(_5);
StorageLive(_6);
_6 = const NonZero::<usize>(core::num::niche_types::NonZeroUsizeInner(1_usize));
_6 = const NonZero::<usize>(core::num::niche_types::NonZeroUsizeInner(1_usize is 1..));
StorageLive(_7);
_7 = const {0x1 as *const [bool; 0]};
_5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
StorageLive(_5);
StorageLive(_6);
- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as std::num::NonZero<usize> (Transmute);
+ _6 = const NonZero::<usize>(core::num::niche_types::NonZeroUsizeInner(1_usize));
+ _6 = const NonZero::<usize>(core::num::niche_types::NonZeroUsizeInner(1_usize is 1..));
StorageLive(_7);
- _7 = copy _6 as *const [bool; 0] (Transmute);
- _5 = NonNull::<[bool; 0]> { pointer: copy _7 };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
StorageLive(_5);
StorageLive(_6);
- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as std::num::NonZero<usize> (Transmute);
+ _6 = const NonZero::<usize>(core::num::niche_types::NonZeroUsizeInner(1_usize));
+ _6 = const NonZero::<usize>(core::num::niche_types::NonZeroUsizeInner(1_usize is 1..));
StorageLive(_7);
- _7 = copy _6 as *const [bool; 0] (Transmute);
- _5 = NonNull::<[bool; 0]> { pointer: copy _7 };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
StorageLive(_5);
StorageLive(_6);
- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as std::num::NonZero<usize> (Transmute);
+ _6 = const NonZero::<usize>(core::num::niche_types::NonZeroUsizeInner(1_usize));
+ _6 = const NonZero::<usize>(core::num::niche_types::NonZeroUsizeInner(1_usize is 1..));
StorageLive(_7);
- _7 = copy _6 as *const [bool; 0] (Transmute);
- _5 = NonNull::<[bool; 0]> { pointer: copy _7 };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
StorageLive(_5);
StorageLive(_6);
- _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as std::num::NonZero<usize> (Transmute);
+ _6 = const NonZero::<usize>(core::num::niche_types::NonZeroUsizeInner(1_usize));
+ _6 = const NonZero::<usize>(core::num::niche_types::NonZeroUsizeInner(1_usize is 1..));
StorageLive(_7);
- _7 = copy _6 as *const [bool; 0] (Transmute);
- _5 = NonNull::<[bool; 0]> { pointer: copy _7 };
Expand Down
2 changes: 1 addition & 1 deletion tests/mir-opt/gvn_ptr_eq_with_constant.main.GVN.diff
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
StorageLive(_3);
- _3 = const std::ptr::Alignment::of::<u8>::{constant#0} as std::num::NonZero<usize> (Transmute);
- _2 = copy _3 as *mut u8 (Transmute);
+ _3 = const NonZero::<usize>(core::num::niche_types::NonZeroUsizeInner(1_usize));
+ _3 = const NonZero::<usize>(core::num::niche_types::NonZeroUsizeInner(1_usize is 1..));
+ _2 = const {0x1 as *mut u8};
StorageDead(_3);
StorageLive(_4);
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/consts/const-eval/raw-bytes.32bit.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ LL | const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
00 00 00 00 │ ....
}

error[E0080]: constructing invalid value at .0: encountered 0, but expected something greater or equal to 1
error[E0080]: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1
--> $DIR/raw-bytes.rs:61:1
|
LL | const NULL_U8: NonZero<u8> = unsafe { mem::transmute(0u8) };
Expand All @@ -75,7 +75,7 @@ LL | const NULL_U8: NonZero<u8> = unsafe { mem::transmute(0u8) };
00 │ .
}

error[E0080]: constructing invalid value at .0: encountered 0, but expected something greater or equal to 1
error[E0080]: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1
--> $DIR/raw-bytes.rs:63:1
|
LL | const NULL_USIZE: NonZero<usize> = unsafe { mem::transmute(0usize) };
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/consts/const-eval/raw-bytes.64bit.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ LL | const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
00 00 00 00 00 00 00 00 │ ........
}

error[E0080]: constructing invalid value at .0: encountered 0, but expected something greater or equal to 1
error[E0080]: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1
--> $DIR/raw-bytes.rs:61:1
|
LL | const NULL_U8: NonZero<u8> = unsafe { mem::transmute(0u8) };
Expand All @@ -75,7 +75,7 @@ LL | const NULL_U8: NonZero<u8> = unsafe { mem::transmute(0u8) };
00 │ .
}

error[E0080]: constructing invalid value at .0: encountered 0, but expected something greater or equal to 1
error[E0080]: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1
--> $DIR/raw-bytes.rs:63:1
|
LL | const NULL_USIZE: NonZero<usize> = unsafe { mem::transmute(0usize) };
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/consts/const-eval/ub-nonnull.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ error[E0080]: in-bounds pointer arithmetic failed: attempting to offset pointer
LL | let out_of_bounds_ptr = &ptr[255];
| ^^^^^^^^^ evaluation of `OUT_OF_BOUNDS_PTR` failed here

error[E0080]: constructing invalid value at .0: encountered 0, but expected something greater or equal to 1
error[E0080]: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1
--> $DIR/ub-nonnull.rs:26:1
|
LL | const NULL_U8: NonZero<u8> = unsafe { mem::transmute(0u8) };
Expand All @@ -26,7 +26,7 @@ LL | const NULL_U8: NonZero<u8> = unsafe { mem::transmute(0u8) };
HEX_DUMP
}

error[E0080]: constructing invalid value at .0: encountered 0, but expected something greater or equal to 1
error[E0080]: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1
--> $DIR/ub-nonnull.rs:28:1
|
LL | const NULL_USIZE: NonZero<usize> = unsafe { mem::transmute(0usize) };
Expand Down
2 changes: 0 additions & 2 deletions tests/ui/lint/invalid_value.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,6 @@ LL | let _val: (NonZero<u32>, i32) = mem::uninitialized();
|
= note: `std::num::NonZero<u32>` must be non-null
= note: because `core::num::niche_types::NonZeroU32Inner` must be non-null
= note: integers must be initialized

error: the type `*const dyn Send` does not permit zero-initialization
--> $DIR/invalid_value.rs:97:37
Expand Down Expand Up @@ -430,7 +429,6 @@ note: because `std::num::NonZero<u32>` must be non-null (in this field of the on
LL | Banana(NonZero<u32>),
| ^^^^^^^^^^^^
= note: because `core::num::niche_types::NonZeroU32Inner` must be non-null
= note: integers must be initialized

error: the type `bool` does not permit being left uninitialized
--> $DIR/invalid_value.rs:111:26
Expand Down
Loading