Skip to content

Commit 7c28934

Browse files
Merge pull request #22347 from WaterWhisperer/diagnostic-range-pat-e0029
feat: add diagnostic for E0029
2 parents e056d43 + 4524dd8 commit 7c28934

5 files changed

Lines changed: 72 additions & 1 deletion

File tree

crates/hir-ty/src/infer.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,10 @@ pub enum InferenceDiagnostic {
302302
pat: PatId,
303303
found: StoredTy,
304304
},
305+
InvalidRangePatType {
306+
#[type_visitable(ignore)]
307+
pat: PatId,
308+
},
305309
DuplicateField {
306310
#[type_visitable(ignore)]
307311
field: ExprOrPatId,

crates/hir-ty/src/infer/pat.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -843,7 +843,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
843843
if let (Some((true, ..)), _) | (_, Some((true, ..))) = (lhs, rhs) {
844844
// There exists a side that didn't meet our criteria that the end-point
845845
// be of a numeric or char type, as checked in `calc_side` above.
846-
// FIXME: Emit an error.
846+
self.push_diagnostic(InferenceDiagnostic::InvalidRangePatType { pat });
847847
return self.types.types.error;
848848
}
849849

crates/hir/src/diagnostics.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ diagnostics![AnyDiagnostic<'db> ->
115115
InvalidCast<'db>,
116116
InvalidDeriveTarget,
117117
InvalidLhsOfAssignment,
118+
InvalidRangePatType,
118119
MacroDefError,
119120
MacroError,
120121
MacroExpansionParseError,
@@ -303,6 +304,11 @@ pub struct ExpectedArrayOrSlicePat<'db> {
303304
pub found: Type<'db>,
304305
}
305306

307+
#[derive(Debug)]
308+
pub struct InvalidRangePatType {
309+
pub pat: InFile<ExprOrPatPtr>,
310+
}
311+
306312
#[derive(Debug)]
307313
pub struct ExpectedFunction<'db> {
308314
pub call: InFile<ExprOrPatPtr>,
@@ -788,6 +794,10 @@ impl<'db> AnyDiagnostic<'db> {
788794
let pat = pat_syntax(*pat)?.map(Into::into);
789795
ExpectedArrayOrSlicePat { pat, found: Type::new(db, def, found.as_ref()) }.into()
790796
}
797+
&InferenceDiagnostic::InvalidRangePatType { pat } => {
798+
let pat = pat_syntax(pat)?.map(Into::into);
799+
InvalidRangePatType { pat }.into()
800+
}
791801
&InferenceDiagnostic::DuplicateField { field: expr, variant } => {
792802
let expr_or_pat = match expr {
793803
ExprOrPatId::ExprId(expr) => {
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext};
2+
3+
// Diagnostic: invalid-range-pat-type
4+
//
5+
// This diagnostic is triggered when a range pattern is used with a type that
6+
// is neither `char` nor numeric.
7+
pub(crate) fn invalid_range_pat_type(
8+
ctx: &DiagnosticsContext<'_, '_>,
9+
d: &hir::InvalidRangePatType,
10+
) -> Diagnostic {
11+
Diagnostic::new_with_syntax_node_ptr(
12+
ctx,
13+
DiagnosticCode::RustcHardError("E0029"),
14+
"only `char` and numeric types are allowed in range patterns",
15+
d.pat.map(Into::into),
16+
)
17+
.stable()
18+
}
19+
20+
#[cfg(test)]
21+
mod tests {
22+
use crate::tests::check_diagnostics;
23+
24+
#[test]
25+
fn bool_range_pattern() {
26+
check_diagnostics(
27+
r#"
28+
fn f(x: bool) {
29+
match x {
30+
false..=true => {}
31+
//^^^^^^^^^^^^ error: only `char` and numeric types are allowed in range patterns
32+
}
33+
}
34+
"#,
35+
);
36+
}
37+
38+
#[test]
39+
fn numeric_and_char_range_patterns() {
40+
check_diagnostics(
41+
r#"
42+
fn f(x: u8, c: char) {
43+
match x {
44+
0..=9 => {}
45+
_ => {}
46+
}
47+
match c {
48+
'a'..='z' => {}
49+
_ => {}
50+
}
51+
}
52+
"#,
53+
);
54+
}
55+
}

crates/ide-diagnostics/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ mod handlers {
4747
pub(crate) mod invalid_cast;
4848
pub(crate) mod invalid_derive_target;
4949
pub(crate) mod invalid_lhs_of_assignment;
50+
pub(crate) mod invalid_range_pat_type;
5051
pub(crate) mod macro_error;
5152
pub(crate) mod malformed_derive;
5253
pub(crate) mod mismatched_arg_count;
@@ -519,6 +520,7 @@ pub fn semantic_diagnostics(
519520
AnyDiagnostic::ElidedLifetimesInPath(d) => handlers::elided_lifetimes_in_path::elided_lifetimes_in_path(&ctx, &d),
520521
AnyDiagnostic::GenericDefaultRefersToSelf(d) => handlers::generic_default_refers_to_self::generic_default_refers_to_self(&ctx, &d),
521522
AnyDiagnostic::InvalidLhsOfAssignment(d) => handlers::invalid_lhs_of_assignment::invalid_lhs_of_assignment(&ctx, &d),
523+
AnyDiagnostic::InvalidRangePatType(d) => handlers::invalid_range_pat_type::invalid_range_pat_type(&ctx, &d),
522524
AnyDiagnostic::TypeMustBeKnown(d) => handlers::type_must_be_known::type_must_be_known(&ctx, &d),
523525
AnyDiagnostic::PatternArgInExternFn(d) => handlers::pattern_arg_in_extern_fn::pattern_arg_in_extern_fn(&ctx, &d),
524526
AnyDiagnostic::UnionExprMustHaveExactlyOneField(d) => handlers::union_expr_must_have_exactly_one_field::union_expr_must_have_exactly_one_field(&ctx, &d),

0 commit comments

Comments
 (0)