Skip to content

Commit

Permalink
Start using pattern types in libcore
Browse files Browse the repository at this point in the history
  • Loading branch information
oli-obk committed Jan 27, 2025
1 parent 6c6b492 commit 0afd16b
Show file tree
Hide file tree
Showing 12 changed files with 130 additions and 24 deletions.
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 @@ -456,7 +456,18 @@ pub(crate) fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) ->
AdtKind::Enum => enums::build_enum_type_di_node(cx, unique_type_id),
},
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
5 changes: 1 addition & 4 deletions compiler/rustc_lint/src/foreign_modules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,10 +241,7 @@ fn structurally_same_type_impl<'tcx>(
if let ty::Adt(def, args) = *ty.kind() {
let is_transparent = def.repr().transparent();
let is_non_null = types::nonnull_optimization_guaranteed(tcx, def);
debug!(
"non_transparent_ty({:?}) -- type is transparent? {}, type is non-null? {}",
ty, is_transparent, is_non_null
);
debug!(?ty, is_transparent, is_non_null);
if is_transparent && !is_non_null {
debug_assert_eq!(def.variants().len(), 1);
let v = &def.variant(FIRST_VARIANT);
Expand Down
18 changes: 10 additions & 8 deletions compiler/rustc_lint/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -891,9 +891,13 @@ fn get_nullable_type<'tcx>(
};
return get_nullable_type(tcx, typing_env, inner_field_ty);
}
ty::Int(ty) => Ty::new_int(tcx, ty),
ty::Uint(ty) => Ty::new_uint(tcx, ty),
ty::RawPtr(ty, mutbl) => Ty::new_ptr(tcx, ty, mutbl),
ty::Pat(base, pat)
if let ty::PatternKind::Range { start: Some(start), end: None, .. } = *pat
&& start.try_to_bits(tcx, typing_env) == Some(1) =>
{
base
}
ty::Int(_) | ty::Uint(_) | ty::RawPtr(..) => ty,
// As these types are always non-null, the nullable equivalent of
// `Option<T>` of these types are their raw pointer counterparts.
ty::Ref(_region, ty, mutbl) => Ty::new_ptr(tcx, ty, mutbl),
Expand Down Expand Up @@ -1240,11 +1244,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
help: Some(fluent::lint_improper_ctypes_char_help),
},

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

ty::Int(ty::IntTy::I128) | ty::Uint(ty::UintTy::U128) => {
FfiUnsafe { ty, reason: fluent::lint_improper_ctypes_128bit, help: None }
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_mir_build/src/builder/matches/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
place = ref_str;
ty = ref_str_ty;
}
&ty::Pat(base, _) => {
assert_eq!(ty, value.ty());

ty = base;
expect_ty = base;
}
_ => {}
}

Expand Down
2 changes: 2 additions & 0 deletions library/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,8 @@
#![feature(no_core)]
#![feature(no_sanitize)]
#![feature(optimize_attribute)]
#![feature(pattern_type_macro)]
#![feature(pattern_types)]
#![feature(prelude_import)]
#![feature(repr_simd)]
#![feature(rustc_allow_const_fn_unstable)]
Expand Down
19 changes: 15 additions & 4 deletions library/core/src/num/niche_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,28 @@ use crate::cmp::Ordering;
use crate::fmt;
use crate::hash::{Hash, Hasher};
use crate::marker::StructuralPartialEq;
#[cfg(not(bootstrap))]
use crate::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);
)+) => {$(
#[derive(Clone, Copy, Eq)]
#[derive(Clone, Copy)]
#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start($low)]
#[rustc_layout_scalar_valid_range_end($high)]
#[cfg_attr(bootstrap, rustc_layout_scalar_valid_range_start($low))]
#[cfg_attr(bootstrap, rustc_layout_scalar_valid_range_end($high))]
$(#[$m])*
#[cfg(bootstrap)]
$vis struct $name($int);

#[derive(Clone, Copy)]
#[repr(transparent)]
$(#[$m])*
#[cfg(not(bootstrap))]
$vis struct $name(pattern_type!($int is $low..=$high));

const _: () = {
// With the `valid_range` attributes, it's always specified as unsigned
assert!(<$uint>::MIN == 0);
Expand All @@ -41,7 +50,7 @@ macro_rules! define_valid_range_type {
#[inline]
pub const unsafe fn new_unchecked(val: $int) -> Self {
// SAFETY: Caller promised that `val` is non-zero.
unsafe { $name(val) }
unsafe { $name(crate::mem::transmute(val)) }
}

#[inline]
Expand All @@ -57,6 +66,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
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 @@ -68,7 +68,7 @@ error[E0080]: it is undefined behavior to use this value
--> $DIR/raw-bytes.rs:59:1
|
LL | const NULL_U8: NonZero<u8> = unsafe { mem::transmute(0u8) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 0, but expected something greater or equal to 1
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1
|
= 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.
= note: the raw bytes of the constant (size: 1, align: 1) {
Expand All @@ -79,7 +79,7 @@ error[E0080]: it is undefined behavior to use this value
--> $DIR/raw-bytes.rs:61:1
|
LL | const NULL_USIZE: NonZero<usize> = unsafe { mem::transmute(0usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 0, but expected something greater or equal to 1
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1
|
= 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.
= note: the raw bytes of the constant (size: 8, align: 8) {
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 @@ -19,7 +19,7 @@ error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-nonnull.rs:24:1
|
LL | const NULL_U8: NonZero<u8> = unsafe { mem::transmute(0u8) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 0, but expected something greater or equal to 1
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1
|
= 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.
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
Expand All @@ -30,7 +30,7 @@ error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-nonnull.rs:26:1
|
LL | const NULL_USIZE: NonZero<usize> = unsafe { mem::transmute(0usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 0, but expected something greater or equal to 1
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1
|
= 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.
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
Expand Down
38 changes: 37 additions & 1 deletion tests/ui/lint/clashing-extern-fn.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,30 @@ LL | fn non_null_ptr() -> *const usize;
= note: expected `unsafe extern "C" fn() -> NonNull<usize>`
found `unsafe extern "C" fn() -> *const usize`

warning: `option_non_zero_usize` redeclared with a different signature
--> $DIR/clashing-extern-fn.rs:420:13
|
LL | fn option_non_zero_usize() -> usize;
| ------------------------------------ `option_non_zero_usize` previously declared here
...
LL | fn option_non_zero_usize() -> Option<core::num::NonZero<usize>>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
|
= note: expected `unsafe extern "C" fn() -> usize`
found `unsafe extern "C" fn() -> Option<NonZero<usize>>`

warning: `option_non_zero_isize` redeclared with a different signature
--> $DIR/clashing-extern-fn.rs:421:13
|
LL | fn option_non_zero_isize() -> isize;
| ------------------------------------ `option_non_zero_isize` previously declared here
...
LL | fn option_non_zero_isize() -> Option<core::num::NonZero<isize>>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
|
= note: expected `unsafe extern "C" fn() -> isize`
found `unsafe extern "C" fn() -> Option<NonZero<isize>>`

warning: `option_non_zero_usize_incorrect` redeclared with a different signature
--> $DIR/clashing-extern-fn.rs:425:13
|
Expand All @@ -234,6 +258,18 @@ LL | fn option_non_null_ptr_incorrect() -> *const isize;
= note: expected `unsafe extern "C" fn() -> *const usize`
found `unsafe extern "C" fn() -> *const isize`

warning: `hidden_niche_transparent` redeclared with a different signature
--> $DIR/clashing-extern-fn.rs:481:13
|
LL | fn hidden_niche_transparent() -> usize;
| --------------------------------------- `hidden_niche_transparent` previously declared here
...
LL | fn hidden_niche_transparent() -> Option<Transparent>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
|
= note: expected `unsafe extern "C" fn() -> usize`
found `unsafe extern "C" fn() -> Option<Transparent>`

warning: `hidden_niche_transparent_no_niche` redeclared with a different signature
--> $DIR/clashing-extern-fn.rs:483:13
|
Expand All @@ -258,5 +294,5 @@ LL | fn hidden_niche_unsafe_cell() -> Option<UnsafeCell<NonZero<usiz
= note: expected `unsafe extern "C" fn() -> usize`
found `unsafe extern "C" fn() -> Option<UnsafeCell<NonZero<usize>>>`

warning: 22 warnings emitted
warning: 25 warnings emitted

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
23 changes: 23 additions & 0 deletions tests/ui/type/pattern_types/matching.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#![feature(pattern_types, pattern_type_macro, structural_match)]

use std::marker::StructuralPartialEq;
use std::pat::pattern_type;

struct Thing(pattern_type!(u32 is 1..));

impl StructuralPartialEq for Thing {}
impl Eq for Thing {}
impl PartialEq for Thing {
fn eq(&self, other: &Thing) -> bool {
todo!()
}
}

const TWO: Thing = Thing(unsafe { std::mem::transmute(2_u32) });

const _: () = match TWO {
TWO => {}
_ => unreachable!(),
};

fn main() {}
20 changes: 20 additions & 0 deletions tests/ui/type/pattern_types/matching.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
error[E0405]: cannot find trait `StructuralPartialEq` in this scope
--> $DIR/matching.rs:7:6
|
LL | impl StructuralPartialEq for Thing {}
| ^^^^^^^^^^^^^^^^^^^ not found in this scope
|
help: consider importing this trait
|
LL + use std::marker::StructuralPartialEq;
|

error[E0405]: cannot find trait `StructuralEq` in this scope
--> $DIR/matching.rs:8:6
|
LL | impl StructuralEq for Thing {}
| ^^^^^^^^^^^^ not found in this scope

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0405`.

0 comments on commit 0afd16b

Please sign in to comment.