Skip to content

Commit bb8b30a

Browse files
committed
Auto merge of rust-lang#148537 - oli-obk:push-yxuttqrqqyvu, r=dianqk
Start using pattern types in libcore (NonZero and friends) part of rust-lang#136006 This PR only changes the internal representation of `NonZero`, `NonMax`, ... and other integral range types in libcore. This subsequently affects other types made up of it, but nothing really changes except that the field of `NonZero` is now accessible safely in contrast to the `rustc_layout_scalar_range_start` attribute, which has all kinds of obscure rules on how to properly access its field.
2 parents 7ad4e69 + 85e8282 commit bb8b30a

File tree

10 files changed

+64
-74
lines changed

10 files changed

+64
-74
lines changed

compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,18 @@ pub(crate) fn spanned_type_di_node<'ll, 'tcx>(
479479
AdtKind::Enum => enums::build_enum_type_di_node(cx, unique_type_id, span),
480480
},
481481
ty::Tuple(_) => build_tuple_type_di_node(cx, unique_type_id),
482-
_ => bug!("debuginfo: unexpected type in type_di_node(): {:?}", t),
482+
ty::Pat(base, _) => return type_di_node(cx, base),
483+
// FIXME(unsafe_binders): impl debug info
484+
ty::UnsafeBinder(_) => unimplemented!(),
485+
ty::Alias(..)
486+
| ty::Param(_)
487+
| ty::Bound(..)
488+
| ty::Infer(_)
489+
| ty::Placeholder(_)
490+
| ty::CoroutineWitness(..)
491+
| ty::Error(_) => {
492+
bug!("debuginfo: unexpected type in type_di_node(): {:?}", t)
493+
}
483494
};
484495

485496
{

compiler/rustc_const_eval/src/interpret/call.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
9191
let (_, field) = layout.non_1zst_field(self).unwrap();
9292
self.unfold_transparent(field, may_unfold)
9393
}
94+
ty::Pat(base, _) => self.layout_of(*base).expect(
95+
"if the layout of a pattern type could be computed, so can the layout of its base",
96+
),
9497
// Not a transparent type, no further unfolding.
9598
_ => layout,
9699
}

library/core/src/num/niche_types.rs

Lines changed: 38 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -5,59 +5,47 @@
55
)]
66

77
use crate::cmp::Ordering;
8-
use crate::fmt;
98
use crate::hash::{Hash, Hasher};
109
use crate::marker::StructuralPartialEq;
10+
use crate::{fmt, pattern_type};
1111

1212
macro_rules! define_valid_range_type {
1313
($(
1414
$(#[$m:meta])*
15-
$vis:vis struct $name:ident($int:ident as $uint:ident in $low:literal..=$high:literal);
15+
$vis:vis struct $name:ident($int:ident is $pat:pat);
1616
)+) => {$(
17-
#[derive(Clone, Copy, Eq)]
17+
#[derive(Clone, Copy)]
1818
#[repr(transparent)]
19-
#[rustc_layout_scalar_valid_range_start($low)]
20-
#[rustc_layout_scalar_valid_range_end($high)]
2119
$(#[$m])*
22-
$vis struct $name($int);
23-
24-
const _: () = {
25-
// With the `valid_range` attributes, it's always specified as unsigned
26-
assert!(<$uint>::MIN == 0);
27-
let ulow: $uint = $low;
28-
let uhigh: $uint = $high;
29-
assert!(ulow <= uhigh);
30-
31-
assert!(size_of::<$int>() == size_of::<$uint>());
32-
};
33-
20+
$vis struct $name(pattern_type!($int is $pat));
3421
impl $name {
3522
#[inline]
3623
pub const fn new(val: $int) -> Option<Self> {
37-
if (val as $uint) >= ($low as $uint) && (val as $uint) <= ($high as $uint) {
38-
// SAFETY: just checked the inclusive range
39-
Some(unsafe { $name(val) })
24+
#[allow(non_contiguous_range_endpoints)]
25+
if let $pat = val {
26+
// SAFETY: just checked that the value matches the pattern
27+
Some(unsafe { $name(crate::mem::transmute(val)) })
4028
} else {
4129
None
4230
}
4331
}
4432

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

5745
#[inline]
5846
pub const fn as_inner(self) -> $int {
59-
// SAFETY: This is a transparent wrapper, so unwrapping it is sound
60-
// (Not using `.0` due to MCP#807.)
47+
// SAFETY: pattern types are always legal values of their base type
48+
// (Not using `.0` because that has perf regressions.)
6149
unsafe { crate::mem::transmute(self) }
6250
}
6351
}
@@ -67,6 +55,8 @@ macro_rules! define_valid_range_type {
6755
// by <https://github.com/rust-lang/compiler-team/issues/807>.
6856
impl StructuralPartialEq for $name {}
6957

58+
impl Eq for $name {}
59+
7060
impl PartialEq for $name {
7161
#[inline]
7262
fn eq(&self, other: &Self) -> bool {
@@ -104,7 +94,7 @@ macro_rules! define_valid_range_type {
10494
}
10595

10696
define_valid_range_type! {
107-
pub struct Nanoseconds(u32 as u32 in 0..=999_999_999);
97+
pub struct Nanoseconds(u32 is 0..=999_999_999);
10898
}
10999

110100
impl Nanoseconds {
@@ -120,47 +110,32 @@ impl const Default for Nanoseconds {
120110
}
121111
}
122112

123-
define_valid_range_type! {
124-
pub struct NonZeroU8Inner(u8 as u8 in 1..=0xff);
125-
pub struct NonZeroU16Inner(u16 as u16 in 1..=0xff_ff);
126-
pub struct NonZeroU32Inner(u32 as u32 in 1..=0xffff_ffff);
127-
pub struct NonZeroU64Inner(u64 as u64 in 1..=0xffffffff_ffffffff);
128-
pub struct NonZeroU128Inner(u128 as u128 in 1..=0xffffffffffffffff_ffffffffffffffff);
129-
130-
pub struct NonZeroI8Inner(i8 as u8 in 1..=0xff);
131-
pub struct NonZeroI16Inner(i16 as u16 in 1..=0xff_ff);
132-
pub struct NonZeroI32Inner(i32 as u32 in 1..=0xffff_ffff);
133-
pub struct NonZeroI64Inner(i64 as u64 in 1..=0xffffffff_ffffffff);
134-
pub struct NonZeroI128Inner(i128 as u128 in 1..=0xffffffffffffffff_ffffffffffffffff);
135-
136-
pub struct NonZeroCharInner(char as u32 in 1..=0x10ffff);
137-
}
113+
const HALF_USIZE: usize = usize::MAX >> 1;
138114

139-
#[cfg(target_pointer_width = "16")]
140-
define_valid_range_type! {
141-
pub struct UsizeNoHighBit(usize as usize in 0..=0x7fff);
142-
pub struct NonZeroUsizeInner(usize as usize in 1..=0xffff);
143-
pub struct NonZeroIsizeInner(isize as usize in 1..=0xffff);
144-
}
145-
#[cfg(target_pointer_width = "32")]
146115
define_valid_range_type! {
147-
pub struct UsizeNoHighBit(usize as usize in 0..=0x7fff_ffff);
148-
pub struct NonZeroUsizeInner(usize as usize in 1..=0xffff_ffff);
149-
pub struct NonZeroIsizeInner(isize as usize in 1..=0xffff_ffff);
150-
}
151-
#[cfg(target_pointer_width = "64")]
152-
define_valid_range_type! {
153-
pub struct UsizeNoHighBit(usize as usize in 0..=0x7fff_ffff_ffff_ffff);
154-
pub struct NonZeroUsizeInner(usize as usize in 1..=0xffff_ffff_ffff_ffff);
155-
pub struct NonZeroIsizeInner(isize as usize in 1..=0xffff_ffff_ffff_ffff);
156-
}
116+
pub struct NonZeroU8Inner(u8 is 1..);
117+
pub struct NonZeroU16Inner(u16 is 1..);
118+
pub struct NonZeroU32Inner(u32 is 1..);
119+
pub struct NonZeroU64Inner(u64 is 1..);
120+
pub struct NonZeroU128Inner(u128 is 1..);
157121

158-
define_valid_range_type! {
159-
pub struct U32NotAllOnes(u32 as u32 in 0..=0xffff_fffe);
160-
pub struct I32NotAllOnes(i32 as u32 in 0..=0xffff_fffe);
122+
pub struct NonZeroI8Inner(i8 is ..0 | 1..);
123+
pub struct NonZeroI16Inner(i16 is ..0 | 1..);
124+
pub struct NonZeroI32Inner(i32 is ..0 | 1..);
125+
pub struct NonZeroI64Inner(i64 is ..0 | 1..);
126+
pub struct NonZeroI128Inner(i128 is ..0 | 1..);
127+
128+
pub struct UsizeNoHighBit(usize is 0..=HALF_USIZE);
129+
pub struct NonZeroUsizeInner(usize is 1..);
130+
pub struct NonZeroIsizeInner(isize is ..0 | 1..);
131+
132+
pub struct U32NotAllOnes(u32 is 0..u32::MAX);
133+
pub struct I32NotAllOnes(i32 is ..-1 | 0..);
134+
135+
pub struct U64NotAllOnes(u64 is 0..u64::MAX);
136+
pub struct I64NotAllOnes(i64 is ..-1 | 0..);
161137

162-
pub struct U64NotAllOnes(u64 as u64 in 0..=0xffff_ffff_ffff_fffe);
163-
pub struct I64NotAllOnes(i64 as u64 in 0..=0xffff_ffff_ffff_fffe);
138+
pub struct NonZeroCharInner(char is '\u{1}' ..= '\u{10ffff}');
164139
}
165140

166141
pub trait NotAllOnesHelper {
@@ -181,7 +156,7 @@ impl NotAllOnesHelper for i64 {
181156
}
182157

183158
define_valid_range_type! {
184-
pub struct CodePointInner(u32 as u32 in 0..=0x10ffff);
159+
pub struct CodePointInner(u32 is 0..=0x10ffff);
185160
}
186161

187162
impl CodePointInner {

src/bootstrap/src/core/build_steps/test.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2184,6 +2184,9 @@ Please disable assertions with `rust.debug-assertions = false`.
21842184
for flag in targetflags {
21852185
cmd.arg("--target-rustcflags").arg(flag);
21862186
}
2187+
if target.is_synthetic() {
2188+
cmd.arg("--target-rustcflags").arg("-Zunstable-options");
2189+
}
21872190

21882191
cmd.arg("--python").arg(
21892192
builder.config.python.as_ref().expect("python is required for running rustdoc tests"),

src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_ret.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: Undefined Behavior: constructing invalid value at .0: encountered 0, but expected something greater or equal to 1
1+
error: Undefined Behavior: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1
22
--> tests/fail/validity/cast_fn_ptr_invalid_callee_ret.rs:LL:CC
33
|
44
LL | f();

src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: Undefined Behavior: constructing invalid value at .0: encountered 0, but expected something greater or equal to 1
1+
error: Undefined Behavior: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1
22
--> tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs:LL:CC
33
|
44
LL | Call(_res = f(*ptr), ReturnTo(retblock), UnwindContinue())

tests/ui/consts/const-eval/raw-bytes.32bit.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ LL | const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
6464
00 00 00 00 │ ....
6565
}
6666

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

78-
error[E0080]: constructing invalid value at .0: encountered 0, but expected something greater or equal to 1
78+
error[E0080]: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1
7979
--> $DIR/raw-bytes.rs:63:1
8080
|
8181
LL | const NULL_USIZE: NonZero<usize> = unsafe { mem::transmute(0usize) };

tests/ui/consts/const-eval/raw-bytes.64bit.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ LL | const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
6464
00 00 00 00 00 00 00 00 │ ........
6565
}
6666

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

78-
error[E0080]: constructing invalid value at .0: encountered 0, but expected something greater or equal to 1
78+
error[E0080]: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1
7979
--> $DIR/raw-bytes.rs:63:1
8080
|
8181
LL | const NULL_USIZE: NonZero<usize> = unsafe { mem::transmute(0usize) };

tests/ui/consts/const-eval/ub-nonnull.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ error[E0080]: in-bounds pointer arithmetic failed: attempting to offset pointer
1515
LL | let out_of_bounds_ptr = &ptr[255];
1616
| ^^^^^^^^^ evaluation of `OUT_OF_BOUNDS_PTR` failed here
1717

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

29-
error[E0080]: constructing invalid value at .0: encountered 0, but expected something greater or equal to 1
29+
error[E0080]: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1
3030
--> $DIR/ub-nonnull.rs:28:1
3131
|
3232
LL | const NULL_USIZE: NonZero<usize> = unsafe { mem::transmute(0usize) };

tests/ui/lint/invalid_value.stderr

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,6 @@ LL | let _val: (NonZero<u32>, i32) = mem::uninitialized();
333333
|
334334
= note: `std::num::NonZero<u32>` must be non-null
335335
= note: because `core::num::niche_types::NonZeroU32Inner` must be non-null
336-
= note: integers must be initialized
337336

338337
error: the type `*const dyn Send` does not permit zero-initialization
339338
--> $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
430429
LL | Banana(NonZero<u32>),
431430
| ^^^^^^^^^^^^
432431
= note: because `core::num::niche_types::NonZeroU32Inner` must be non-null
433-
= note: integers must be initialized
434432

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

0 commit comments

Comments
 (0)