From 916f9552e975287d2bc9aed16d3a1c35b7c52695 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 30 Jan 2025 08:41:20 +0000 Subject: [PATCH] Reject wrapping ranges of pattern types --- compiler/rustc_ty_utils/src/layout.rs | 28 +++++ tests/ui/type/pattern_types/range_patterns.rs | 6 +- .../type/pattern_types/range_patterns.stderr | 113 ++---------------- 3 files changed, 41 insertions(+), 106 deletions(-) diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 5a4bb2c95da..7334beb52c9 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -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(), diff --git a/tests/ui/type/pattern_types/range_patterns.rs b/tests/ui/type/pattern_types/range_patterns.rs index 3aa8426178a..dda7eb0ae4e 100644 --- a/tests/ui/type/pattern_types/range_patterns.rs +++ b/tests/ui/type/pattern_types/range_patterns.rs @@ -19,14 +19,14 @@ type A = Option; //~ 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) }; diff --git a/tests/ui/type/pattern_types/range_patterns.stderr b/tests/ui/type/pattern_types/range_patterns.stderr index b6abcf46224..a05995a33f9 100644 --- a/tests/ui/type/pattern_types/range_patterns.stderr +++ b/tests/ui/type/pattern_types/range_patterns.stderr @@ -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`.