Start using pattern types in libcore

This commit is contained in:
Oli Scherer 2025-01-24 15:57:13 +00:00 committed by Oli Scherer
parent 06cafcbe08
commit 85e8282fab
10 changed files with 65 additions and 75 deletions

View file

@ -479,7 +479,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)
}
};
{

View file

@ -91,6 +91,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,
}

View file

@ -5,45 +5,33 @@
)]
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
@ -51,13 +39,13 @@ macro_rules! define_valid_range_type {
#[inline]
pub const unsafe fn new_unchecked(val: $int) -> Self {
// SAFETY: Caller promised that `val` is within the valid range.
unsafe { $name(val) }
unsafe { 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.)
// SAFETY: pattern types are always legal values of their base type
// (Not using `.0` because that has perf regressions.)
unsafe { crate::mem::transmute(self) }
}
}
@ -67,6 +55,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 {
@ -104,7 +94,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 {
@ -120,47 +110,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);
}
#[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);
}
const HALF_USIZE: usize = usize::MAX >> 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 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..);
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 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 NonZeroCharInner(char is '\u{1}' ..= '\u{10ffff}');
}
pub trait NotAllOnesHelper {
@ -181,7 +156,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 {

View file

@ -2184,6 +2184,9 @@ Please disable assertions with `rust.debug-assertions = false`.
for flag in targetflags {
cmd.arg("--target-rustcflags").arg(flag);
}
if target.is_synthetic() {
cmd.arg("--target-rustcflags").arg("-Zunstable-options");
}
cmd.arg("--python").arg(
builder.config.python.as_ref().expect("python is required for running rustdoc tests"),

View file

@ -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_callee_ret.rs:LL:CC
|
LL | f();

View file

@ -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())

View file

@ -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) };
@ -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) };

View file

@ -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) };
@ -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) };

View file

@ -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) };
@ -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) };

View file

@ -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
@ -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