Skip to content

Commit 430db4f

Browse files
committed
Reject wrapping ranges of pattern types
1 parent c08e3a5 commit 430db4f

File tree

3 files changed

+43
-103
lines changed

3 files changed

+43
-103
lines changed

Diff for: compiler/rustc_ty_utils/src/layout.rs

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

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

Diff for: 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) };

Diff for: tests/ui/type/pattern_types/range_patterns.stderr

+12-100
Original file line numberDiff line numberDiff line change
@@ -357,39 +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-
abi: 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-
variants: Single {
387-
index: 0,
388-
},
389-
max_repr_align: None,
390-
unadjusted_abi_align: Align(4 bytes),
391-
randomization_seed: $SEED,
392-
}
360+
error: pattern type ranges cannot wrap: 1..=0
361+
362+
error: the type has an unknown layout
393363
--> $DIR/range_patterns.rs:22:1
394364
|
395365
LL | type EMPTY = pattern_type!(u32 is 1..1);
@@ -407,39 +377,9 @@ error: the type has an unknown layout
407377
LL | type WRAP = pattern_type!(u32 is 1..0);
408378
| ^^^^^^^^^
409379

410-
error: layout_of((u32) is 5..=1) = Layout {
411-
size: Size(4 bytes),
412-
align: AbiAndPrefAlign {
413-
abi: Align(4 bytes),
414-
pref: $SOME_ALIGN,
415-
},
416-
abi: Scalar(
417-
Initialized {
418-
value: Int(
419-
I32,
420-
false,
421-
),
422-
valid_range: (..=1) | (5..),
423-
},
424-
),
425-
fields: Primitive,
426-
largest_niche: Some(
427-
Niche {
428-
offset: Size(0 bytes),
429-
value: Int(
430-
I32,
431-
false,
432-
),
433-
valid_range: (..=1) | (5..),
434-
},
435-
),
436-
variants: Single {
437-
index: 0,
438-
},
439-
max_repr_align: None,
440-
unadjusted_abi_align: Align(4 bytes),
441-
randomization_seed: $SEED,
442-
}
380+
error: pattern type ranges cannot wrap: 5..=1
381+
382+
error: the type has an unknown layout
443383
--> $DIR/range_patterns.rs:29:1
444384
|
445385
LL | type WRAP2 = pattern_type!(u32 is 5..2);
@@ -471,6 +411,7 @@ error: layout_of((i8) is -10..=10) = Layout {
471411
valid_range: (..=10) | (246..),
472412
},
473413
),
414+
uninhabited: false,
474415
variants: Single {
475416
index: 0,
476417
},
@@ -509,6 +450,7 @@ error: layout_of((i8) is i8::MIN..=0) = Layout {
509450
valid_range: (..=0) | (128..),
510451
},
511452
),
453+
uninhabited: false,
512454
variants: Single {
513455
index: 0,
514456
},
@@ -521,44 +463,14 @@ error: layout_of((i8) is i8::MIN..=0) = Layout {
521463
LL | type MIN = pattern_type!(i8 is -128..=0);
522464
| ^^^^^^^^
523465

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

562-
error: aborting due to 12 previous errors
474+
error: aborting due to 15 previous errors
563475

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

0 commit comments

Comments
 (0)