Skip to content

Commit ed90eb8

Browse files
committed
Start using pattern types in libcore
1 parent 6c6b492 commit ed90eb8

File tree

11 files changed

+100
-30
lines changed

11 files changed

+100
-30
lines changed

compiler/rustc_borrowck/src/type_check/mod.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -2153,11 +2153,15 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
21532153
}
21542154
}
21552155
CastKind::Transmute => {
2156-
span_mirbug!(
2157-
self,
2158-
rvalue,
2159-
"Unexpected CastKind::Transmute, which is not permitted in Analysis MIR",
2160-
);
2156+
let ty_from = op.ty(body, tcx);
2157+
match ty_from.kind() {
2158+
ty::Pat(base, _) if base == ty => {}
2159+
_ => span_mirbug!(
2160+
self,
2161+
rvalue,
2162+
"Unexpected CastKind::Transmute {ty_from:?} -> {ty:?}, which is not permitted in Analysis MIR",
2163+
),
2164+
}
21612165
}
21622166
}
21632167
}

compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,18 @@ pub(crate) fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) ->
456456
AdtKind::Enum => enums::build_enum_type_di_node(cx, unique_type_id),
457457
},
458458
ty::Tuple(_) => build_tuple_type_di_node(cx, unique_type_id),
459-
_ => bug!("debuginfo: unexpected type in type_di_node(): {:?}", t),
459+
ty::Pat(base, _) => return type_di_node(cx, base),
460+
// FIXME(unsafe_binders): impl debug info
461+
ty::UnsafeBinder(_) => unimplemented!(),
462+
ty::Alias(..)
463+
| ty::Param(_)
464+
| ty::Bound(..)
465+
| ty::Infer(_)
466+
| ty::Placeholder(_)
467+
| ty::CoroutineWitness(..)
468+
| ty::Error(_) => {
469+
bug!("debuginfo: unexpected type in type_di_node(): {:?}", t)
470+
}
460471
};
461472

462473
{

compiler/rustc_lint/src/foreign_modules.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -241,10 +241,7 @@ fn structurally_same_type_impl<'tcx>(
241241
if let ty::Adt(def, args) = *ty.kind() {
242242
let is_transparent = def.repr().transparent();
243243
let is_non_null = types::nonnull_optimization_guaranteed(tcx, def);
244-
debug!(
245-
"non_transparent_ty({:?}) -- type is transparent? {}, type is non-null? {}",
246-
ty, is_transparent, is_non_null
247-
);
244+
debug!(?ty, is_transparent, is_non_null);
248245
if is_transparent && !is_non_null {
249246
debug_assert_eq!(def.variants().len(), 1);
250247
let v = &def.variant(FIRST_VARIANT);

compiler/rustc_lint/src/types.rs

+6-8
Original file line numberDiff line numberDiff line change
@@ -891,9 +891,8 @@ fn get_nullable_type<'tcx>(
891891
};
892892
return get_nullable_type(tcx, typing_env, inner_field_ty);
893893
}
894-
ty::Int(ty) => Ty::new_int(tcx, ty),
895-
ty::Uint(ty) => Ty::new_uint(tcx, ty),
896-
ty::RawPtr(ty, mutbl) => Ty::new_ptr(tcx, ty, mutbl),
894+
ty::Pat(base, ..) => return get_nullable_type(tcx, typing_env, base),
895+
ty::Int(_) | ty::Uint(_) | ty::RawPtr(..) => ty,
897896
// As these types are always non-null, the nullable equivalent of
898897
// `Option<T>` of these types are their raw pointer counterparts.
899898
ty::Ref(_region, ty, mutbl) => Ty::new_ptr(tcx, ty, mutbl),
@@ -934,6 +933,7 @@ fn is_niche_optimization_candidate<'tcx>(
934933
!non_exhaustive && empty
935934
}
936935
ty::Tuple(tys) => tys.is_empty(),
936+
ty::Pat(..) => true,
937937
_ => false,
938938
}
939939
}
@@ -1240,11 +1240,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
12401240
help: Some(fluent::lint_improper_ctypes_char_help),
12411241
},
12421242

1243-
ty::Pat(..) => FfiUnsafe {
1244-
ty,
1245-
reason: fluent::lint_improper_ctypes_pat_reason,
1246-
help: Some(fluent::lint_improper_ctypes_pat_help),
1247-
},
1243+
// It's just extra invariants on the type that you need to uphold,
1244+
// but only the base type is relevant for being representable in FFI.
1245+
ty::Pat(base, ..) => self.check_type_for_ffi(acc, base),
12481246

12491247
ty::Int(ty::IntTy::I128) | ty::Uint(ty::UintTy::U128) => {
12501248
FfiUnsafe { ty, reason: fluent::lint_improper_ctypes_128bit, help: None }

compiler/rustc_mir_build/src/builder/matches/test.rs

+26-2
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
146146
let success_block = target_block(TestBranch::Success);
147147
let fail_block = target_block(TestBranch::Failure);
148148

149-
let expect_ty = value.ty();
150-
let expect = self.literal_operand(test.span, value);
149+
let mut expect_ty = value.ty();
150+
let mut expect = self.literal_operand(test.span, value);
151151

152152
let mut place = place;
153153
let mut block = block;
@@ -177,6 +177,30 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
177177
place = ref_str;
178178
ty = ref_str_ty;
179179
}
180+
&ty::Pat(base, _) => {
181+
assert_eq!(ty, value.ty());
182+
183+
let transmuted_place = self.temp(base, test.span);
184+
self.cfg.push_assign(
185+
block,
186+
self.source_info(scrutinee_span),
187+
transmuted_place,
188+
Rvalue::Cast(CastKind::Transmute, Operand::Copy(place), base),
189+
);
190+
191+
let transmuted_expect = self.temp(base, test.span);
192+
self.cfg.push_assign(
193+
block,
194+
self.source_info(test.span),
195+
transmuted_expect,
196+
Rvalue::Cast(CastKind::Transmute, expect, base),
197+
);
198+
199+
place = transmuted_place;
200+
expect = Operand::Copy(transmuted_expect);
201+
ty = base;
202+
expect_ty = base;
203+
}
180204
_ => {}
181205
}
182206

library/core/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,8 @@
181181
#![feature(no_core)]
182182
#![feature(no_sanitize)]
183183
#![feature(optimize_attribute)]
184+
#![feature(pattern_type_macro)]
185+
#![feature(pattern_types)]
184186
#![feature(prelude_import)]
185187
#![feature(repr_simd)]
186188
#![feature(rustc_allow_const_fn_unstable)]

library/core/src/num/niche_types.rs

+15-4
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,28 @@ use crate::cmp::Ordering;
88
use crate::fmt;
99
use crate::hash::{Hash, Hasher};
1010
use crate::marker::StructuralPartialEq;
11+
#[cfg(not(bootstrap))]
12+
use crate::pattern_type;
1113

1214
macro_rules! define_valid_range_type {
1315
($(
1416
$(#[$m:meta])*
1517
$vis:vis struct $name:ident($int:ident as $uint:ident in $low:literal..=$high:literal);
1618
)+) => {$(
17-
#[derive(Clone, Copy, Eq)]
19+
#[derive(Clone, Copy)]
1820
#[repr(transparent)]
19-
#[rustc_layout_scalar_valid_range_start($low)]
20-
#[rustc_layout_scalar_valid_range_end($high)]
21+
#[cfg_attr(bootstrap, rustc_layout_scalar_valid_range_start($low))]
22+
#[cfg_attr(bootstrap, rustc_layout_scalar_valid_range_end($high))]
2123
$(#[$m])*
24+
#[cfg(bootstrap)]
2225
$vis struct $name($int);
2326

27+
#[derive(Clone, Copy)]
28+
#[repr(transparent)]
29+
$(#[$m])*
30+
#[cfg(not(bootstrap))]
31+
$vis struct $name(pattern_type!($int is $low..=$high));
32+
2433
const _: () = {
2534
// With the `valid_range` attributes, it's always specified as unsigned
2635
assert!(<$uint>::MIN == 0);
@@ -41,7 +50,7 @@ macro_rules! define_valid_range_type {
4150
#[inline]
4251
pub const unsafe fn new_unchecked(val: $int) -> Self {
4352
// SAFETY: Caller promised that `val` is non-zero.
44-
unsafe { $name(val) }
53+
unsafe { $name(crate::mem::transmute(val)) }
4554
}
4655

4756
#[inline]
@@ -57,6 +66,8 @@ macro_rules! define_valid_range_type {
5766
// by <https://github.com/rust-lang/compiler-team/issues/807>.
5867
impl StructuralPartialEq for $name {}
5968

69+
impl Eq for $name {}
70+
6071
impl PartialEq for $name {
6172
#[inline]
6273
fn eq(&self, other: &Self) -> bool {

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ error[E0080]: it is undefined behavior to use this value
6868
--> $DIR/raw-bytes.rs:59:1
6969
|
7070
LL | const NULL_U8: NonZero<u8> = unsafe { mem::transmute(0u8) };
71-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 0, but expected something greater or equal to 1
71+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1
7272
|
7373
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
7474
= note: the raw bytes of the constant (size: 1, align: 1) {
@@ -79,7 +79,7 @@ error[E0080]: it is undefined behavior to use this value
7979
--> $DIR/raw-bytes.rs:61:1
8080
|
8181
LL | const NULL_USIZE: NonZero<usize> = unsafe { mem::transmute(0usize) };
82-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 0, but expected something greater or equal to 1
82+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1
8383
|
8484
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
8585
= note: the raw bytes of the constant (size: 8, align: 8) {

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ error[E0080]: it is undefined behavior to use this value
1919
--> $DIR/ub-nonnull.rs:24:1
2020
|
2121
LL | const NULL_U8: NonZero<u8> = unsafe { mem::transmute(0u8) };
22-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 0, but expected something greater or equal to 1
22+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1
2323
|
2424
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
2525
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
@@ -30,7 +30,7 @@ error[E0080]: it is undefined behavior to use this value
3030
--> $DIR/ub-nonnull.rs:26:1
3131
|
3232
LL | const NULL_USIZE: NonZero<usize> = unsafe { mem::transmute(0usize) };
33-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 0, but expected something greater or equal to 1
33+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1
3434
|
3535
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
3636
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {

tests/ui/lint/invalid_value.stderr

-2
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
+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#![feature(pattern_types, pattern_type_macro, structural_match)]
2+
3+
//@ check-pass
4+
5+
use std::marker::StructuralPartialEq;
6+
use std::pat::pattern_type;
7+
8+
struct Thing(pattern_type!(u32 is 1..));
9+
10+
impl StructuralPartialEq for Thing {}
11+
impl Eq for Thing {}
12+
impl PartialEq for Thing {
13+
fn eq(&self, other: &Thing) -> bool {
14+
todo!()
15+
}
16+
}
17+
18+
const TWO: Thing = Thing(unsafe { std::mem::transmute(2_u32) });
19+
20+
const _: () = match TWO {
21+
TWO => {}
22+
_ => unreachable!(),
23+
};
24+
25+
fn main() {}

0 commit comments

Comments
 (0)