Skip to content

Commit 7e4ccc2

Browse files
committed
Maintain a list of types permitted per pattern
1 parent ded0836 commit 7e4ccc2

File tree

10 files changed

+211
-2
lines changed

10 files changed

+211
-2
lines changed

compiler/rustc_hir_analysis/messages.ftl

+3-1
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,9 @@ hir_analysis_inherent_ty_outside_relevant = cannot define inherent `impl` for a
234234
.help = consider moving this inherent impl into the crate defining the type if possible
235235
.span_help = alternatively add `#[rustc_allow_incoherent_impl]` to the relevant impl items
236236
237+
hir_analysis_invalid_base_type = `{$ty}` is not a valid base type for range patterns
238+
.note = range patterns only support integers
239+
237240
hir_analysis_invalid_generic_receiver_ty = invalid generic `self` parameter type: `{$receiver_ty}`
238241
.note = type of `self` must not be a method generic parameter type
239242
@@ -438,7 +441,6 @@ hir_analysis_pattern_type_wild_pat = wildcard patterns are not permitted for pat
438441
.label = this type is the same as the inner type without a pattern
439442
hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind}
440443
.label = not allowed in type signatures
441-
442444
hir_analysis_precise_capture_self_alias = `Self` can't be captured in `use<...>` precise captures list, since it is an alias
443445
.label = `Self` is not a generic argument, but an alias to the type of the {$what}
444446

compiler/rustc_hir_analysis/src/errors/pattern_types.rs

+12
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use rustc_macros::Diagnostic;
2+
use rustc_middle::ty::Ty;
23
use rustc_span::Span;
34

45
#[derive(Diagnostic)]
@@ -7,3 +8,14 @@ pub(crate) struct WildPatTy {
78
#[primary_span]
89
pub span: Span,
910
}
11+
12+
#[derive(Diagnostic)]
13+
#[diag(hir_analysis_invalid_base_type)]
14+
pub(crate) struct InvalidBaseType<'tcx> {
15+
pub ty: Ty<'tcx>,
16+
#[primary_span]
17+
pub ty_span: Span,
18+
pub pat: &'static str,
19+
#[note]
20+
pub pat_span: Span,
21+
}

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

+14-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ use tracing::{debug, instrument};
5353

5454
use crate::bounds::Bounds;
5555
use crate::check::check_abi_fn_ptr;
56-
use crate::errors::{AmbiguousLifetimeBound, BadReturnTypeNotation, WildPatTy};
56+
use crate::errors::{AmbiguousLifetimeBound, BadReturnTypeNotation, InvalidBaseType, WildPatTy};
5757
use crate::hir_ty_lowering::errors::{GenericsArgsErrExtend, prohibit_assoc_item_constraint};
5858
use crate::hir_ty_lowering::generics::{check_generic_arg_count, lower_generic_args};
5959
use crate::middle::resolve_bound_vars as rbv;
@@ -2432,13 +2432,26 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
24322432
self.ty_infer(None, hir_ty.span)
24332433
}
24342434
hir::TyKind::Pat(ty, pat) => {
2435+
let ty_span = ty.span;
24352436
let ty = self.lower_ty(ty);
24362437
let pat_ty = match pat.kind {
24372438
hir::PatKind::Wild => {
24382439
let err = self.dcx().emit_err(WildPatTy { span: pat.span });
24392440
Ty::new_error(tcx, err)
24402441
}
24412442
hir::PatKind::Range(start, end, include_end) => {
2443+
let ty = match ty.kind() {
2444+
ty::Int(_) | ty::Uint(_) | ty::Char => ty,
2445+
_ => Ty::new_error(
2446+
tcx,
2447+
self.dcx().emit_err(InvalidBaseType {
2448+
ty,
2449+
pat: "range",
2450+
ty_span,
2451+
pat_span: pat.span,
2452+
}),
2453+
),
2454+
};
24422455
let expr_to_const = |expr: &'tcx hir::PatExpr<'tcx>| -> ty::Const<'tcx> {
24432456
let (c, c_ty) = match expr.kind {
24442457
hir::PatExprKind::Lit { lit, negated } => {

tests/ui/type/pattern_types/chars.rs

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//! Check that chars can be used in ranges
2+
3+
//@ check-pass
4+
5+
#![feature(pattern_types)]
6+
#![feature(pattern_type_macro)]
7+
8+
use std::pat::pattern_type;
9+
10+
const LOWERCASE: pattern_type!(char is 'a'..='z') = unsafe { std::mem::transmute('b') };
11+
12+
fn main() {}

tests/ui/type/pattern_types/nested.rs

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//! Check that pattern types can only have specific base types
2+
3+
#![feature(pattern_types)]
4+
#![feature(pattern_type_macro)]
5+
6+
use std::pat::pattern_type;
7+
8+
// Undoing an inner pattern type's restrictions should either be forbidden,
9+
// or still validate correctly.
10+
const BAD_NESTING: pattern_type!(pattern_type!(u32 is 1..) is 0..) = todo!();
11+
//~^ ERROR: not a valid base type for range patterns
12+
13+
// We want to get the most narrowest version that a pattern could be
14+
const BAD_NESTING2: pattern_type!(pattern_type!(i32 is 1..) is ..=-1) = todo!();
15+
//~^ ERROR: not a valid base type for range patterns
16+
17+
const BAD_NESTING3: pattern_type!(pattern_type!(i32 is 1..) is ..0) = todo!();
18+
//~^ ERROR: not a valid base type for range patterns
19+
20+
const BAD_NESTING4: pattern_type!(() is ..0) = todo!();
21+
//~^ ERROR: not a valid base type for range patterns
22+
23+
const BAD_NESTING5: pattern_type!(f32 is 1.0 .. 2.0) = todo!();
24+
//~^ ERROR: not a valid base type for range patterns
25+
26+
fn main() {}
+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
error: `(u32) is 1..=` is not a valid base type for range patterns
2+
--> $DIR/nested.rs:10:34
3+
|
4+
LL | const BAD_NESTING: pattern_type!(pattern_type!(u32 is 1..) is 0..) = todo!();
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
note: range patterns only support integers
8+
--> $DIR/nested.rs:10:63
9+
|
10+
LL | const BAD_NESTING: pattern_type!(pattern_type!(u32 is 1..) is 0..) = todo!();
11+
| ^^^
12+
13+
error: `(i32) is 1..=` is not a valid base type for range patterns
14+
--> $DIR/nested.rs:14:35
15+
|
16+
LL | const BAD_NESTING2: pattern_type!(pattern_type!(i32 is 1..) is ..=-1) = todo!();
17+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
18+
|
19+
note: range patterns only support integers
20+
--> $DIR/nested.rs:14:64
21+
|
22+
LL | const BAD_NESTING2: pattern_type!(pattern_type!(i32 is 1..) is ..=-1) = todo!();
23+
| ^^^^^
24+
25+
error: `(i32) is 1..=` is not a valid base type for range patterns
26+
--> $DIR/nested.rs:17:35
27+
|
28+
LL | const BAD_NESTING3: pattern_type!(pattern_type!(i32 is 1..) is ..0) = todo!();
29+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
30+
|
31+
note: range patterns only support integers
32+
--> $DIR/nested.rs:17:64
33+
|
34+
LL | const BAD_NESTING3: pattern_type!(pattern_type!(i32 is 1..) is ..0) = todo!();
35+
| ^^^
36+
37+
error: `()` is not a valid base type for range patterns
38+
--> $DIR/nested.rs:20:35
39+
|
40+
LL | const BAD_NESTING4: pattern_type!(() is ..0) = todo!();
41+
| ^^
42+
|
43+
note: range patterns only support integers
44+
--> $DIR/nested.rs:20:41
45+
|
46+
LL | const BAD_NESTING4: pattern_type!(() is ..0) = todo!();
47+
| ^^^
48+
49+
error: `f32` is not a valid base type for range patterns
50+
--> $DIR/nested.rs:23:35
51+
|
52+
LL | const BAD_NESTING5: pattern_type!(f32 is 1.0 .. 2.0) = todo!();
53+
| ^^^
54+
|
55+
note: range patterns only support integers
56+
--> $DIR/nested.rs:23:42
57+
|
58+
LL | const BAD_NESTING5: pattern_type!(f32 is 1.0 .. 2.0) = todo!();
59+
| ^^^^^^^^^^
60+
61+
error: aborting due to 5 previous errors
62+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//! Check that pattern types patterns must be of the type of the base type
2+
3+
//@ known-bug: unknown
4+
//@ failure-status: 101
5+
//@ normalize-stderr: "note: .*\n\n" -> ""
6+
//@ normalize-stderr: "thread 'rustc' panicked.*\n" -> ""
7+
//@ normalize-stderr: "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: "
8+
//@ normalize-stderr: "(delayed at compiler/rustc_mir_transform/src/lib.rs:)\d+:\d+" -> "$1:LL:CC"
9+
//@ rustc-env:RUST_BACKTRACE=0
10+
11+
#![feature(pattern_types)]
12+
#![feature(pattern_type_macro)]
13+
14+
use std::pat::pattern_type;
15+
16+
const BAD_NESTING4: pattern_type!(u8 is 'a'..='a') = todo!();
17+
18+
const BAD_NESTING5: pattern_type!(char is 1..=1) = todo!();
19+
20+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
error: internal compiler error: ty::ConstKind::Error constructed but no error reported
2+
|
3+
= error: internal compiler error: ty::ConstKind::Error constructed but no error reported
4+
|
5+
= note: delayed at compiler/rustc_mir_build/src/thir/constant.rs:72:21 - disabled backtrace
6+
= error: internal compiler error: mir_const_qualif: MIR had errors
7+
--> $DIR/pattern_type_mismatch.rs:16:1
8+
|
9+
LL | const BAD_NESTING4: pattern_type!(u8 is 'a'..='a') = todo!();
10+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
11+
|
12+
note: delayed at compiler/rustc_mir_transform/src/lib.rs::LL:CC - disabled backtrace
13+
--> $DIR/pattern_type_mismatch.rs:16:1
14+
|
15+
LL | const BAD_NESTING4: pattern_type!(u8 is 'a'..='a') = todo!();
16+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
17+
18+
error: internal compiler error: mir_const_qualif: MIR had errors
19+
--> $DIR/pattern_type_mismatch.rs:18:1
20+
|
21+
LL | const BAD_NESTING5: pattern_type!(char is 1..=1) = todo!();
22+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
23+
|
24+
note: delayed at compiler/rustc_mir_transform/src/lib.rs::LL:CC - disabled backtrace
25+
--> $DIR/pattern_type_mismatch.rs:18:1
26+
|
27+
LL | const BAD_NESTING5: pattern_type!(char is 1..=1) = todo!();
28+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
29+
30+
query stack during panic:
31+
end of query stack
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//! Check that the range start must be smaller than the range end
2+
//@ known-bug: unknown
3+
//@ failure-status: 101
4+
//@ normalize-stderr: "note: .*\n\n" -> ""
5+
//@ normalize-stderr: "thread 'rustc' panicked.*\n" -> ""
6+
//@ normalize-stderr: "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: "
7+
//@ rustc-env:RUST_BACKTRACE=0
8+
9+
#![feature(pattern_types)]
10+
#![feature(pattern_type_macro)]
11+
12+
use std::pat::pattern_type;
13+
14+
const NONE: pattern_type!(u8 is 1..0) = unsafe { std::mem::transmute(3_u8) };
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error[E0601]: `main` function not found in crate `reverse_range`
2+
--> $DIR/reverse_range.rs:14:78
3+
|
4+
LL | const NONE: pattern_type!(u8 is 1..0) = unsafe { std::mem::transmute(3_u8) };
5+
| ^ consider adding a `main` function to `$DIR/reverse_range.rs`
6+
7+
8+
assertion failed: end <= max_value
9+
error: the compiler unexpectedly panicked. this is a bug.
10+
11+
query stack during panic:
12+
#0 [eval_to_allocation_raw] const-evaluating + checking `NONE`
13+
#1 [eval_to_const_value_raw] simplifying constant for the type system `NONE`
14+
... and 1 other queries... use `env RUST_BACKTRACE=1` to see the full query stack
15+
error: aborting due to 1 previous error
16+
17+
For more information about this error, try `rustc --explain E0601`.

0 commit comments

Comments
 (0)