Skip to content

Commit 916f955

Browse files
committed
Reject wrapping ranges of pattern types
1 parent f38819c commit 916f955

File tree

3 files changed

+41
-106
lines changed

3 files changed

+41
-106
lines changed

compiler/rustc_ty_utils/src/layout.rs

+28
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,34 @@ fn layout_of_uncached<'tcx>(
220220
.try_to_bits(tcx, cx.typing_env)
221221
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
222222

223+
// FIXME(pattern_types): create implied bounds from pattern types in signatures
224+
// that require that the range end is >= the range start so that we can't hit
225+
// this error anymore without first having hit a trait solver error.
226+
// Very fuzzy on the details here, but pattern types are an internal impl detail,
227+
// so we can just go with this for now
228+
if scalar.is_signed() {
229+
let range = scalar.valid_range_mut();
230+
let start = layout.size.sign_extend(range.start);
231+
let end = layout.size.sign_extend(range.end);
232+
if end < start {
233+
let guar = tcx.dcx().err(format!(
234+
"pattern type ranges cannot wrap: {start}..={end}"
235+
));
236+
237+
return Err(error(cx, LayoutError::ReferencesError(guar)));
238+
}
239+
} else {
240+
let range = scalar.valid_range_mut();
241+
if range.end < range.start {
242+
let guar = tcx.dcx().err(format!(
243+
"pattern type ranges cannot wrap: {}..={}",
244+
range.start, range.end
245+
));
246+
247+
return Err(error(cx, LayoutError::ReferencesError(guar)));
248+
}
249+
};
250+
223251
let niche = Niche {
224252
offset: Size::ZERO,
225253
value: scalar.primitive(),

tests/ui/type/pattern_types/range_patterns.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@ type A = Option<std::num::NonZeroU32>; //~ ERROR layout_of
1919
struct NonZeroU32New(pattern_type!(u32 is 1..)); //~ ERROR layout_of
2020

2121
#[rustc_layout(debug)]
22-
type EMPTY = pattern_type!(u32 is 1..1); //~ ERROR layout_of
22+
type EMPTY = pattern_type!(u32 is 1..1); //~ ERROR unknown layout
2323

2424
#[rustc_layout(debug)]
2525
type WRAP = pattern_type!(u32 is 1..0); //~ ERROR unknown layout
2626
//~^ ERROR: evaluation of constant value failed
2727

2828
#[rustc_layout(debug)]
29-
type WRAP2 = pattern_type!(u32 is 5..2); //~ ERROR layout_of
29+
type WRAP2 = pattern_type!(u32 is 5..2); //~ ERROR unknown layout
3030

3131
#[rustc_layout(debug)]
3232
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
3535
type MIN = pattern_type!(i8 is -128..=0); //~ ERROR layout_of
3636

3737
#[rustc_layout(debug)]
38-
type SignedWrap = pattern_type!(i8 is 120..=-120); //~ ERROR layout_of
38+
type SignedWrap = pattern_type!(i8 is 120..=-120); //~ ERROR unknown layout
3939

4040
fn main() {
4141
let x: pattern_type!(u32 is 1..) = unsafe { std::mem::transmute(42_u32) };

tests/ui/type/pattern_types/range_patterns.stderr

+10-103
Original file line numberDiff line numberDiff line change
@@ -357,40 +357,9 @@ error: layout_of(NonZeroU32New) = Layout {
357357
LL | struct NonZeroU32New(pattern_type!(u32 is 1..));
358358
| ^^^^^^^^^^^^^^^^^^^^
359359

360-
error: layout_of((u32) is 1..=0) = Layout {
361-
size: Size(4 bytes),
362-
align: AbiAndPrefAlign {
363-
abi: Align(4 bytes),
364-
pref: $SOME_ALIGN,
365-
},
366-
backend_repr: Scalar(
367-
Initialized {
368-
value: Int(
369-
I32,
370-
false,
371-
),
372-
valid_range: (..=0) | (1..),
373-
},
374-
),
375-
fields: Primitive,
376-
largest_niche: Some(
377-
Niche {
378-
offset: Size(0 bytes),
379-
value: Int(
380-
I32,
381-
false,
382-
),
383-
valid_range: (..=0) | (1..),
384-
},
385-
),
386-
uninhabited: false,
387-
variants: Single {
388-
index: 0,
389-
},
390-
max_repr_align: None,
391-
unadjusted_abi_align: Align(4 bytes),
392-
randomization_seed: $SEED,
393-
}
360+
error: pattern type ranges cannot wrap: 1..=0
361+
362+
error: the type has an unknown layout
394363
--> $DIR/range_patterns.rs:22:1
395364
|
396365
LL | type EMPTY = pattern_type!(u32 is 1..1);
@@ -408,40 +377,9 @@ error: the type has an unknown layout
408377
LL | type WRAP = pattern_type!(u32 is 1..0);
409378
| ^^^^^^^^^
410379

411-
error: layout_of((u32) is 5..=1) = Layout {
412-
size: Size(4 bytes),
413-
align: AbiAndPrefAlign {
414-
abi: Align(4 bytes),
415-
pref: $SOME_ALIGN,
416-
},
417-
backend_repr: Scalar(
418-
Initialized {
419-
value: Int(
420-
I32,
421-
false,
422-
),
423-
valid_range: (..=1) | (5..),
424-
},
425-
),
426-
fields: Primitive,
427-
largest_niche: Some(
428-
Niche {
429-
offset: Size(0 bytes),
430-
value: Int(
431-
I32,
432-
false,
433-
),
434-
valid_range: (..=1) | (5..),
435-
},
436-
),
437-
uninhabited: false,
438-
variants: Single {
439-
index: 0,
440-
},
441-
max_repr_align: None,
442-
unadjusted_abi_align: Align(4 bytes),
443-
randomization_seed: $SEED,
444-
}
380+
error: pattern type ranges cannot wrap: 5..=1
381+
382+
error: the type has an unknown layout
445383
--> $DIR/range_patterns.rs:29:1
446384
|
447385
LL | type WRAP2 = pattern_type!(u32 is 5..2);
@@ -525,45 +463,14 @@ error: layout_of((i8) is i8::MIN..=0) = Layout {
525463
LL | type MIN = pattern_type!(i8 is -128..=0);
526464
| ^^^^^^^^
527465

528-
error: layout_of((i8) is 120..=-120) = Layout {
529-
size: Size(1 bytes),
530-
align: AbiAndPrefAlign {
531-
abi: Align(1 bytes),
532-
pref: $SOME_ALIGN,
533-
},
534-
backend_repr: Scalar(
535-
Initialized {
536-
value: Int(
537-
I8,
538-
true,
539-
),
540-
valid_range: 120..=136,
541-
},
542-
),
543-
fields: Primitive,
544-
largest_niche: Some(
545-
Niche {
546-
offset: Size(0 bytes),
547-
value: Int(
548-
I8,
549-
true,
550-
),
551-
valid_range: 120..=136,
552-
},
553-
),
554-
uninhabited: false,
555-
variants: Single {
556-
index: 0,
557-
},
558-
max_repr_align: None,
559-
unadjusted_abi_align: Align(1 bytes),
560-
randomization_seed: $SEED,
561-
}
466+
error: pattern type ranges cannot wrap: 120..=-120
467+
468+
error: the type has an unknown layout
562469
--> $DIR/range_patterns.rs:38:1
563470
|
564471
LL | type SignedWrap = pattern_type!(i8 is 120..=-120);
565472
| ^^^^^^^^^^^^^^^
566473

567-
error: aborting due to 12 previous errors
474+
error: aborting due to 15 previous errors
568475

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

0 commit comments

Comments
 (0)