Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir-ty/src/infer.rs4
-rw-r--r--crates/hir-ty/src/infer/pat.rs2
-rw-r--r--crates/hir/src/diagnostics.rs10
-rw-r--r--crates/ide-diagnostics/src/handlers/invalid_range_pat_type.rs55
-rw-r--r--crates/ide-diagnostics/src/lib.rs2
5 files changed, 72 insertions, 1 deletions
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index 6a29b2cedb..8f17776d02 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -302,6 +302,10 @@ pub enum InferenceDiagnostic {
pat: PatId,
found: StoredTy,
},
+ InvalidRangePatType {
+ #[type_visitable(ignore)]
+ pat: PatId,
+ },
DuplicateField {
#[type_visitable(ignore)]
field: ExprOrPatId,
diff --git a/crates/hir-ty/src/infer/pat.rs b/crates/hir-ty/src/infer/pat.rs
index f21438647c..8e87d22a45 100644
--- a/crates/hir-ty/src/infer/pat.rs
+++ b/crates/hir-ty/src/infer/pat.rs
@@ -843,7 +843,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
if let (Some((true, ..)), _) | (_, Some((true, ..))) = (lhs, rhs) {
// There exists a side that didn't meet our criteria that the end-point
// be of a numeric or char type, as checked in `calc_side` above.
- // FIXME: Emit an error.
+ self.push_diagnostic(InferenceDiagnostic::InvalidRangePatType { pat });
return self.types.types.error;
}
diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs
index a044f24587..77a17f1c76 100644
--- a/crates/hir/src/diagnostics.rs
+++ b/crates/hir/src/diagnostics.rs
@@ -115,6 +115,7 @@ diagnostics![AnyDiagnostic<'db> ->
InvalidCast<'db>,
InvalidDeriveTarget,
InvalidLhsOfAssignment,
+ InvalidRangePatType,
MacroDefError,
MacroError,
MacroExpansionParseError,
@@ -304,6 +305,11 @@ pub struct ExpectedArrayOrSlicePat<'db> {
}
#[derive(Debug)]
+pub struct InvalidRangePatType {
+ pub pat: InFile<ExprOrPatPtr>,
+}
+
+#[derive(Debug)]
pub struct ExpectedFunction<'db> {
pub call: InFile<ExprOrPatPtr>,
pub found: Type<'db>,
@@ -788,6 +794,10 @@ impl<'db> AnyDiagnostic<'db> {
let pat = pat_syntax(*pat)?.map(Into::into);
ExpectedArrayOrSlicePat { pat, found: Type::new(db, def, found.as_ref()) }.into()
}
+ &InferenceDiagnostic::InvalidRangePatType { pat } => {
+ let pat = pat_syntax(pat)?.map(Into::into);
+ InvalidRangePatType { pat }.into()
+ }
&InferenceDiagnostic::DuplicateField { field: expr, variant } => {
let expr_or_pat = match expr {
ExprOrPatId::ExprId(expr) => {
diff --git a/crates/ide-diagnostics/src/handlers/invalid_range_pat_type.rs b/crates/ide-diagnostics/src/handlers/invalid_range_pat_type.rs
new file mode 100644
index 0000000000..465f59559d
--- /dev/null
+++ b/crates/ide-diagnostics/src/handlers/invalid_range_pat_type.rs
@@ -0,0 +1,55 @@
+use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext};
+
+// Diagnostic: invalid-range-pat-type
+//
+// This diagnostic is triggered when a range pattern is used with a type that
+// is neither `char` nor numeric.
+pub(crate) fn invalid_range_pat_type(
+ ctx: &DiagnosticsContext<'_, '_>,
+ d: &hir::InvalidRangePatType,
+) -> Diagnostic {
+ Diagnostic::new_with_syntax_node_ptr(
+ ctx,
+ DiagnosticCode::RustcHardError("E0029"),
+ "only `char` and numeric types are allowed in range patterns",
+ d.pat.map(Into::into),
+ )
+ .stable()
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::tests::check_diagnostics;
+
+ #[test]
+ fn bool_range_pattern() {
+ check_diagnostics(
+ r#"
+fn f(x: bool) {
+ match x {
+ false..=true => {}
+ //^^^^^^^^^^^^ error: only `char` and numeric types are allowed in range patterns
+ }
+}
+"#,
+ );
+ }
+
+ #[test]
+ fn numeric_and_char_range_patterns() {
+ check_diagnostics(
+ r#"
+fn f(x: u8, c: char) {
+ match x {
+ 0..=9 => {}
+ _ => {}
+ }
+ match c {
+ 'a'..='z' => {}
+ _ => {}
+ }
+}
+"#,
+ );
+ }
+}
diff --git a/crates/ide-diagnostics/src/lib.rs b/crates/ide-diagnostics/src/lib.rs
index 49b3234a11..967b965f51 100644
--- a/crates/ide-diagnostics/src/lib.rs
+++ b/crates/ide-diagnostics/src/lib.rs
@@ -47,6 +47,7 @@ mod handlers {
pub(crate) mod invalid_cast;
pub(crate) mod invalid_derive_target;
pub(crate) mod invalid_lhs_of_assignment;
+ pub(crate) mod invalid_range_pat_type;
pub(crate) mod macro_error;
pub(crate) mod malformed_derive;
pub(crate) mod mismatched_arg_count;
@@ -519,6 +520,7 @@ pub fn semantic_diagnostics(
AnyDiagnostic::ElidedLifetimesInPath(d) => handlers::elided_lifetimes_in_path::elided_lifetimes_in_path(&ctx, &d),
AnyDiagnostic::GenericDefaultRefersToSelf(d) => handlers::generic_default_refers_to_self::generic_default_refers_to_self(&ctx, &d),
AnyDiagnostic::InvalidLhsOfAssignment(d) => handlers::invalid_lhs_of_assignment::invalid_lhs_of_assignment(&ctx, &d),
+ AnyDiagnostic::InvalidRangePatType(d) => handlers::invalid_range_pat_type::invalid_range_pat_type(&ctx, &d),
AnyDiagnostic::TypeMustBeKnown(d) => handlers::type_must_be_known::type_must_be_known(&ctx, &d),
AnyDiagnostic::PatternArgInExternFn(d) => handlers::pattern_arg_in_extern_fn::pattern_arg_in_extern_fn(&ctx, &d),
AnyDiagnostic::UnionExprMustHaveExactlyOneField(d) => handlers::union_expr_must_have_exactly_one_field::union_expr_must_have_exactly_one_field(&ctx, &d),