Skip to content

Commit 2845be6

Browse files
committed
Allow int literals for pattern types with int base types
1 parent 905909d commit 2845be6

File tree

6 files changed

+58
-130
lines changed

6 files changed

+58
-130
lines changed

compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

+17-1
Original file line numberDiff line numberDiff line change
@@ -1617,7 +1617,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16171617
ast::LitKind::Char(_) => tcx.types.char,
16181618
ast::LitKind::Int(_, ast::LitIntType::Signed(t)) => Ty::new_int(tcx, ty::int_ty(t)),
16191619
ast::LitKind::Int(_, ast::LitIntType::Unsigned(t)) => Ty::new_uint(tcx, ty::uint_ty(t)),
1620-
ast::LitKind::Int(_, ast::LitIntType::Unsuffixed) => {
1620+
ast::LitKind::Int(i, ast::LitIntType::Unsuffixed) => {
16211621
let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() {
16221622
ty::Int(_) | ty::Uint(_) => Some(ty),
16231623
// These exist to direct casts like `0x61 as char` to use
@@ -1626,6 +1626,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16261626
ty::Char => Some(tcx.types.u8),
16271627
ty::RawPtr(..) => Some(tcx.types.usize),
16281628
ty::FnDef(..) | ty::FnPtr(..) => Some(tcx.types.usize),
1629+
&ty::Pat(base, _) if base.is_integral() => {
1630+
let layout = tcx
1631+
.layout_of(self.typing_env(self.param_env).as_query_input(ty))
1632+
.ok()?;
1633+
if layout.uninhabited {
1634+
None
1635+
} else {
1636+
match layout.backend_repr {
1637+
rustc_abi::BackendRepr::Scalar(scalar) => scalar
1638+
.valid_range(&tcx)
1639+
.contains(u128::from(i.get()))
1640+
.then_some(ty),
1641+
_ => unreachable!(),
1642+
}
1643+
}
1644+
}
16291645
_ => None,
16301646
});
16311647
opt_ty.unwrap_or_else(|| self.next_int_var())

compiler/rustc_mir_build/src/builder/expr/as_constant.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,12 @@ fn lit_to_mir_constant<'tcx>(tcx: TyCtxt<'tcx>, lit_input: LitToConstInput<'tcx>
117117
ConstValue::Scalar(Scalar::from_uint(result, width))
118118
};
119119

120-
let value = match (lit, ty.kind()) {
120+
let lit_ty = match *ty.kind() {
121+
ty::Pat(base, _) => base,
122+
_ => ty,
123+
};
124+
125+
let value = match (lit, lit_ty.kind()) {
121126
(ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => {
122127
let s = s.as_str();
123128
let allocation = Allocation::from_bytes_byte_aligned_immutable(s.as_bytes());

tests/ui/type/pattern_types/literals.rs

+2-9
Original file line numberDiff line numberDiff line change
@@ -12,27 +12,24 @@ fn out_of_range() -> pattern_type!(u32 is 1..) {
1212

1313
fn at_range_start() -> pattern_type!(u32 is 1..) {
1414
1
15-
//~^ mismatched types
1615
}
1716

1817
fn in_range() -> pattern_type!(u32 is 1..) {
1918
2
20-
//~^ mismatched types
2119
}
2220

2321
fn negative_lit_on_unsigned_ty() -> pattern_type!(u32 is 1..) {
2422
-3
25-
//~^ mismatched types
23+
//~^ ERROR: cannot apply unary operator `-` to type `(u32) is 1..`
2624
}
2725

2826
fn negative_lit_in_range() -> pattern_type!(i8 is -5..5) {
2927
-2
30-
//~^ mismatched types
28+
//~^ ERROR: cannot apply unary operator `-` to type `(i8) is -5..=4`
3129
}
3230

3331
fn positive_lit_in_range_of_signed() -> pattern_type!(i8 is -5..5) {
3432
2
35-
//~^ mismatched types
3633
}
3734

3835
fn negative_lit_at_range_start() -> pattern_type!(i8 is -5..5) {
@@ -42,7 +39,6 @@ fn negative_lit_at_range_start() -> pattern_type!(i8 is -5..5) {
4239

4340
fn positive_lit_at_range_end() -> pattern_type!(i8 is -5..5) {
4441
4
45-
//~^ mismatched types
4642
}
4743

4844
fn lit_one_beyond_range_end() -> pattern_type!(i8 is -5..5) {
@@ -67,12 +63,10 @@ fn char_lit_out_of_range() -> pattern_type!(char is 'a'..'z') {
6763

6864
fn lit_at_unsigned_range_inclusive_end() -> pattern_type!(u32 is 0..=1) {
6965
1
70-
//~^ mismatched types
7166
}
7267

7368
fn single_element_range() -> pattern_type!(u32 is 0..=0) {
7469
0
75-
//~^ mismatched types
7670
}
7771

7872
fn lit_oob_single_element_range() -> pattern_type!(u32 is 0..=0) {
@@ -87,7 +81,6 @@ fn lit_oob_single_element_range_exclusive() -> pattern_type!(u32 is 0..1) {
8781

8882
fn single_element_range_exclusive() -> pattern_type!(u32 is 0..1) {
8983
0
90-
//~^ mismatched types
9184
}
9285

9386
fn empty_range_at_base_type_min() -> pattern_type!(u32 is 0..0) {
+28-111
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,29 @@
11
error[E0080]: evaluation of constant value failed
2-
--> $DIR/literals.rs:93:62
2+
--> $DIR/literals.rs:86:62
33
|
44
LL | fn empty_range_at_base_type_min() -> pattern_type!(u32 is 0..0) {
55
| ^ attempt to compute `0_u32 - 1_u32`, which would overflow
66

77
error[E0080]: evaluation of constant value failed
8-
--> $DIR/literals.rs:98:63
8+
--> $DIR/literals.rs:91:63
99
|
1010
LL | fn empty_range_at_base_type_min2() -> pattern_type!(u32 is 0..0) {
1111
| ^ attempt to compute `0_u32 - 1_u32`, which would overflow
1212

1313
error[E0080]: evaluation of constant value failed
14-
--> $DIR/literals.rs:113:65
14+
--> $DIR/literals.rs:106:65
1515
|
1616
LL | fn wraparound_range_at_base_ty_end() -> pattern_type!(u32 is 1..0) {
1717
| ^ attempt to compute `0_u32 - 1_u32`, which would overflow
1818

1919
error[E0080]: evaluation of constant value failed
20-
--> $DIR/literals.rs:118:66
20+
--> $DIR/literals.rs:111:66
2121
|
2222
LL | fn wraparound_range_at_base_ty_end2() -> pattern_type!(u32 is 1..0) {
2323
| ^ attempt to compute `0_u32 - 1_u32`, which would overflow
2424

2525
error[E0080]: evaluation of constant value failed
26-
--> $DIR/literals.rs:123:66
26+
--> $DIR/literals.rs:116:66
2727
|
2828
LL | fn wraparound_range_at_base_ty_end3() -> pattern_type!(u32 is 1..0) {
2929
| ^ attempt to compute `0_u32 - 1_u32`, which would overflow
@@ -39,63 +39,20 @@ LL | 0
3939
= note: expected pattern type `(u32) is 1..`
4040
found type `{integer}`
4141

42-
error[E0308]: mismatched types
43-
--> $DIR/literals.rs:14:5
44-
|
45-
LL | fn at_range_start() -> pattern_type!(u32 is 1..) {
46-
| ------------------------- expected `(u32) is 1..` because of return type
47-
LL | 1
48-
| ^ expected `(u32) is 1..`, found integer
49-
|
50-
= note: expected pattern type `(u32) is 1..`
51-
found type `{integer}`
52-
53-
error[E0308]: mismatched types
54-
--> $DIR/literals.rs:19:5
55-
|
56-
LL | fn in_range() -> pattern_type!(u32 is 1..) {
57-
| ------------------------- expected `(u32) is 1..` because of return type
58-
LL | 2
59-
| ^ expected `(u32) is 1..`, found integer
60-
|
61-
= note: expected pattern type `(u32) is 1..`
62-
found type `{integer}`
63-
64-
error[E0308]: mismatched types
65-
--> $DIR/literals.rs:24:5
42+
error[E0600]: cannot apply unary operator `-` to type `(u32) is 1..`
43+
--> $DIR/literals.rs:22:5
6644
|
67-
LL | fn negative_lit_on_unsigned_ty() -> pattern_type!(u32 is 1..) {
68-
| ------------------------- expected `(u32) is 1..` because of return type
6945
LL | -3
70-
| ^^ expected `(u32) is 1..`, found integer
71-
|
72-
= note: expected pattern type `(u32) is 1..`
73-
found type `{integer}`
46+
| ^^ cannot apply unary operator `-`
7447

75-
error[E0308]: mismatched types
76-
--> $DIR/literals.rs:29:5
48+
error[E0600]: cannot apply unary operator `-` to type `(i8) is -5..=4`
49+
--> $DIR/literals.rs:27:5
7750
|
78-
LL | fn negative_lit_in_range() -> pattern_type!(i8 is -5..5) {
79-
| -------------------------- expected `(i8) is -5..=4` because of return type
8051
LL | -2
81-
| ^^ expected `(i8) is -5..=4`, found integer
82-
|
83-
= note: expected pattern type `(i8) is -5..=4`
84-
found type `{integer}`
52+
| ^^ cannot apply unary operator `-`
8553

8654
error[E0308]: mismatched types
87-
--> $DIR/literals.rs:34:5
88-
|
89-
LL | fn positive_lit_in_range_of_signed() -> pattern_type!(i8 is -5..5) {
90-
| -------------------------- expected `(i8) is -5..=4` because of return type
91-
LL | 2
92-
| ^ expected `(i8) is -5..=4`, found integer
93-
|
94-
= note: expected pattern type `(i8) is -5..=4`
95-
found type `{integer}`
96-
97-
error[E0308]: mismatched types
98-
--> $DIR/literals.rs:39:5
55+
--> $DIR/literals.rs:36:5
9956
|
10057
LL | fn negative_lit_at_range_start() -> pattern_type!(i8 is -5..5) {
10158
| -------------------------- expected `(i8) is -5..=4` because of return type
@@ -106,18 +63,7 @@ LL | -5
10663
found type `{integer}`
10764

10865
error[E0308]: mismatched types
109-
--> $DIR/literals.rs:44:5
110-
|
111-
LL | fn positive_lit_at_range_end() -> pattern_type!(i8 is -5..5) {
112-
| -------------------------- expected `(i8) is -5..=4` because of return type
113-
LL | 4
114-
| ^ expected `(i8) is -5..=4`, found integer
115-
|
116-
= note: expected pattern type `(i8) is -5..=4`
117-
found type `{integer}`
118-
119-
error[E0308]: mismatched types
120-
--> $DIR/literals.rs:49:5
66+
--> $DIR/literals.rs:45:5
12167
|
12268
LL | fn lit_one_beyond_range_end() -> pattern_type!(i8 is -5..5) {
12369
| -------------------------- expected `(i8) is -5..=4` because of return type
@@ -128,7 +74,7 @@ LL | 5
12874
found type `{integer}`
12975

13076
error[E0308]: mismatched types
131-
--> $DIR/literals.rs:54:5
77+
--> $DIR/literals.rs:50:5
13278
|
13379
LL | fn wrong_lit_kind() -> pattern_type!(u32 is 1..) {
13480
| ------------------------- expected `(u32) is 1..` because of return type
@@ -139,7 +85,7 @@ LL | '3'
13985
found type `char`
14086

14187
error[E0308]: mismatched types
142-
--> $DIR/literals.rs:59:5
88+
--> $DIR/literals.rs:55:5
14389
|
14490
LL | fn char_lit_in_range() -> pattern_type!(char is 'a'..'z') {
14591
| ------------------------------- expected `(char) is 'a'..='y'` because of return type
@@ -150,7 +96,7 @@ LL | 'b'
15096
found type `char`
15197

15298
error[E0308]: mismatched types
153-
--> $DIR/literals.rs:64:5
99+
--> $DIR/literals.rs:60:5
154100
|
155101
LL | fn char_lit_out_of_range() -> pattern_type!(char is 'a'..'z') {
156102
| ------------------------------- expected `(char) is 'a'..='y'` because of return type
@@ -161,29 +107,7 @@ LL | 'A'
161107
found type `char`
162108

163109
error[E0308]: mismatched types
164-
--> $DIR/literals.rs:69:5
165-
|
166-
LL | fn lit_at_unsigned_range_inclusive_end() -> pattern_type!(u32 is 0..=1) {
167-
| --------------------------- expected `(u32) is 0..=1` because of return type
168-
LL | 1
169-
| ^ expected `(u32) is 0..=1`, found integer
170-
|
171-
= note: expected pattern type `(u32) is 0..=1`
172-
found type `{integer}`
173-
174-
error[E0308]: mismatched types
175-
--> $DIR/literals.rs:74:5
176-
|
177-
LL | fn single_element_range() -> pattern_type!(u32 is 0..=0) {
178-
| --------------------------- expected `(u32) is 0..=0` because of return type
179-
LL | 0
180-
| ^ expected `(u32) is 0..=0`, found integer
181-
|
182-
= note: expected pattern type `(u32) is 0..=0`
183-
found type `{integer}`
184-
185-
error[E0308]: mismatched types
186-
--> $DIR/literals.rs:79:5
110+
--> $DIR/literals.rs:73:5
187111
|
188112
LL | fn lit_oob_single_element_range() -> pattern_type!(u32 is 0..=0) {
189113
| --------------------------- expected `(u32) is 0..=0` because of return type
@@ -194,7 +118,7 @@ LL | 1
194118
found type `{integer}`
195119

196120
error[E0308]: mismatched types
197-
--> $DIR/literals.rs:84:5
121+
--> $DIR/literals.rs:78:5
198122
|
199123
LL | fn lit_oob_single_element_range_exclusive() -> pattern_type!(u32 is 0..1) {
200124
| -------------------------- expected `(u32) is 0..=0` because of return type
@@ -204,19 +128,10 @@ LL | 1
204128
= note: expected pattern type `(u32) is 0..=0`
205129
found type `{integer}`
206130

207-
error[E0308]: mismatched types
208-
--> $DIR/literals.rs:89:5
209-
|
210-
LL | fn single_element_range_exclusive() -> pattern_type!(u32 is 0..1) {
211-
| -------------------------- expected `(u32) is 0..=0` because of return type
212-
LL | 0
213-
| ^ expected `(u32) is 0..=0`, found integer
214-
|
215-
= note: expected pattern type `(u32) is 0..=0`
216-
found type `{integer}`
131+
error: pattern type ranges cannot wrap: 1..=0
217132

218133
error[E0308]: mismatched types
219-
--> $DIR/literals.rs:104:5
134+
--> $DIR/literals.rs:97:5
220135
|
221136
LL | fn empty_range() -> pattern_type!(u32 is 1..1) {
222137
| -------------------------- expected `(u32) is 1..=0` because of return type
@@ -227,7 +142,7 @@ LL | 0
227142
found type `{integer}`
228143

229144
error[E0308]: mismatched types
230-
--> $DIR/literals.rs:109:5
145+
--> $DIR/literals.rs:102:5
231146
|
232147
LL | fn empty_range2() -> pattern_type!(u32 is 1..1) {
233148
| -------------------------- expected `(u32) is 1..=0` because of return type
@@ -237,8 +152,10 @@ LL | 1
237152
= note: expected pattern type `(u32) is 1..=0`
238153
found type `{integer}`
239154

155+
error: pattern type ranges cannot wrap: 2..=0
156+
240157
error[E0308]: mismatched types
241-
--> $DIR/literals.rs:129:5
158+
--> $DIR/literals.rs:122:5
242159
|
243160
LL | fn wraparound_range() -> pattern_type!(u32 is 2..1) {
244161
| -------------------------- expected `(u32) is 2..=0` because of return type
@@ -249,7 +166,7 @@ LL | 1
249166
found type `{integer}`
250167

251168
error[E0308]: mismatched types
252-
--> $DIR/literals.rs:134:5
169+
--> $DIR/literals.rs:127:5
253170
|
254171
LL | fn lit_in_wraparound_range() -> pattern_type!(u32 is 2..1) {
255172
| -------------------------- expected `(u32) is 2..=0` because of return type
@@ -260,7 +177,7 @@ LL | 0
260177
found type `{integer}`
261178

262179
error[E0308]: mismatched types
263-
--> $DIR/literals.rs:139:5
180+
--> $DIR/literals.rs:132:5
264181
|
265182
LL | fn lit_at_wraparound_range_start() -> pattern_type!(u32 is 2..1) {
266183
| -------------------------- expected `(u32) is 2..=0` because of return type
@@ -270,7 +187,7 @@ LL | 2
270187
= note: expected pattern type `(u32) is 2..=0`
271188
found type `{integer}`
272189

273-
error: aborting due to 27 previous errors
190+
error: aborting due to 22 previous errors
274191

275-
Some errors have detailed explanations: E0080, E0308.
192+
Some errors have detailed explanations: E0080, E0308, E0600.
276193
For more information about an error, try `rustc --explain E0080`.

tests/ui/type/pattern_types/nested.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Check that pattern types can only have specific base types
22
3-
#![feature(pattern_types)]
3+
#![feature(pattern_types, const_trait_impl, pattern_type_range_trait)]
44
#![feature(pattern_type_macro)]
55

66
use std::pat::pattern_type;
@@ -14,7 +14,7 @@ const BAD_NESTING: pattern_type!(pattern_type!(u32 is 1..) is 0..) = todo!();
1414
// We want to get the most narrowest version that a pattern could be
1515
const BAD_NESTING2: pattern_type!(pattern_type!(i32 is 1..) is ..=-1) = todo!();
1616
//~^ ERROR: not a valid base type for range patterns
17-
//~| ERROR: mismatched types
17+
//~| ERROR: cannot apply unary operator `-` to type `(i32) is 1..`
1818

1919
const BAD_NESTING3: pattern_type!(pattern_type!(i32 is 1..) is ..0) = todo!();
2020
//~^ ERROR: not a valid base type for range patterns

0 commit comments

Comments
 (0)