Reject wrapping ranges of pattern types

This commit is contained in:
Oli Scherer 2025-01-30 08:41:20 +00:00
parent f38819ce17
commit 916f9552e9
3 changed files with 41 additions and 106 deletions

View file

@ -220,6 +220,34 @@ fn layout_of_uncached<'tcx>(
.try_to_bits(tcx, cx.typing_env)
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
// FIXME(pattern_types): create implied bounds from pattern types in signatures
// that require that the range end is >= the range start so that we can't hit
// this error anymore without first having hit a trait solver error.
// Very fuzzy on the details here, but pattern types are an internal impl detail,
// so we can just go with this for now
if scalar.is_signed() {
let range = scalar.valid_range_mut();
let start = layout.size.sign_extend(range.start);
let end = layout.size.sign_extend(range.end);
if end < start {
let guar = tcx.dcx().err(format!(
"pattern type ranges cannot wrap: {start}..={end}"
));
return Err(error(cx, LayoutError::ReferencesError(guar)));
}
} else {
let range = scalar.valid_range_mut();
if range.end < range.start {
let guar = tcx.dcx().err(format!(
"pattern type ranges cannot wrap: {}..={}",
range.start, range.end
));
return Err(error(cx, LayoutError::ReferencesError(guar)));
}
};
let niche = Niche {
offset: Size::ZERO,
value: scalar.primitive(),

View file

@ -19,14 +19,14 @@ type A = Option<std::num::NonZeroU32>; //~ ERROR layout_of
struct NonZeroU32New(pattern_type!(u32 is 1..)); //~ ERROR layout_of
#[rustc_layout(debug)]
type EMPTY = pattern_type!(u32 is 1..1); //~ ERROR layout_of
type EMPTY = pattern_type!(u32 is 1..1); //~ ERROR unknown layout
#[rustc_layout(debug)]
type WRAP = pattern_type!(u32 is 1..0); //~ ERROR unknown layout
//~^ ERROR: evaluation of constant value failed
#[rustc_layout(debug)]
type WRAP2 = pattern_type!(u32 is 5..2); //~ ERROR layout_of
type WRAP2 = pattern_type!(u32 is 5..2); //~ ERROR unknown layout
#[rustc_layout(debug)]
type SIGN = pattern_type!(i8 is -10..=10); //~ ERROR layout_of
@ -35,7 +35,7 @@ type SIGN = pattern_type!(i8 is -10..=10); //~ ERROR layout_of
type MIN = pattern_type!(i8 is -128..=0); //~ ERROR layout_of
#[rustc_layout(debug)]
type SignedWrap = pattern_type!(i8 is 120..=-120); //~ ERROR layout_of
type SignedWrap = pattern_type!(i8 is 120..=-120); //~ ERROR unknown layout
fn main() {
let x: pattern_type!(u32 is 1..) = unsafe { std::mem::transmute(42_u32) };

View file

@ -357,40 +357,9 @@ error: layout_of(NonZeroU32New) = Layout {
LL | struct NonZeroU32New(pattern_type!(u32 is 1..));
| ^^^^^^^^^^^^^^^^^^^^
error: layout_of((u32) is 1..=0) = Layout {
size: Size(4 bytes),
align: AbiAndPrefAlign {
abi: Align(4 bytes),
pref: $SOME_ALIGN,
},
backend_repr: Scalar(
Initialized {
value: Int(
I32,
false,
),
valid_range: (..=0) | (1..),
},
),
fields: Primitive,
largest_niche: Some(
Niche {
offset: Size(0 bytes),
value: Int(
I32,
false,
),
valid_range: (..=0) | (1..),
},
),
uninhabited: false,
variants: Single {
index: 0,
},
max_repr_align: None,
unadjusted_abi_align: Align(4 bytes),
randomization_seed: $SEED,
}
error: pattern type ranges cannot wrap: 1..=0
error: the type has an unknown layout
--> $DIR/range_patterns.rs:22:1
|
LL | type EMPTY = pattern_type!(u32 is 1..1);
@ -408,40 +377,9 @@ error: the type has an unknown layout
LL | type WRAP = pattern_type!(u32 is 1..0);
| ^^^^^^^^^
error: layout_of((u32) is 5..=1) = Layout {
size: Size(4 bytes),
align: AbiAndPrefAlign {
abi: Align(4 bytes),
pref: $SOME_ALIGN,
},
backend_repr: Scalar(
Initialized {
value: Int(
I32,
false,
),
valid_range: (..=1) | (5..),
},
),
fields: Primitive,
largest_niche: Some(
Niche {
offset: Size(0 bytes),
value: Int(
I32,
false,
),
valid_range: (..=1) | (5..),
},
),
uninhabited: false,
variants: Single {
index: 0,
},
max_repr_align: None,
unadjusted_abi_align: Align(4 bytes),
randomization_seed: $SEED,
}
error: pattern type ranges cannot wrap: 5..=1
error: the type has an unknown layout
--> $DIR/range_patterns.rs:29:1
|
LL | type WRAP2 = pattern_type!(u32 is 5..2);
@ -525,45 +463,14 @@ error: layout_of((i8) is i8::MIN..=0) = Layout {
LL | type MIN = pattern_type!(i8 is -128..=0);
| ^^^^^^^^
error: layout_of((i8) is 120..=-120) = Layout {
size: Size(1 bytes),
align: AbiAndPrefAlign {
abi: Align(1 bytes),
pref: $SOME_ALIGN,
},
backend_repr: Scalar(
Initialized {
value: Int(
I8,
true,
),
valid_range: 120..=136,
},
),
fields: Primitive,
largest_niche: Some(
Niche {
offset: Size(0 bytes),
value: Int(
I8,
true,
),
valid_range: 120..=136,
},
),
uninhabited: false,
variants: Single {
index: 0,
},
max_repr_align: None,
unadjusted_abi_align: Align(1 bytes),
randomization_seed: $SEED,
}
error: pattern type ranges cannot wrap: 120..=-120
error: the type has an unknown layout
--> $DIR/range_patterns.rs:38:1
|
LL | type SignedWrap = pattern_type!(i8 is 120..=-120);
| ^^^^^^^^^^^^^^^
error: aborting due to 12 previous errors
error: aborting due to 15 previous errors
For more information about this error, try `rustc --explain E0080`.