Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir-def/src/expr_store.rs1
-rw-r--r--crates/hir-def/src/expr_store/lower.rs12
-rw-r--r--crates/hir/src/diagnostics.rs6
-rw-r--r--crates/hir/src/lib.rs3
-rw-r--r--crates/ide-diagnostics/src/handlers/pattern_arg_in_extern_fn.rs86
-rw-r--r--crates/ide-diagnostics/src/lib.rs2
6 files changed, 105 insertions, 5 deletions
diff --git a/crates/hir-def/src/expr_store.rs b/crates/hir-def/src/expr_store.rs
index 51951896f2..f72419a3ae 100644
--- a/crates/hir-def/src/expr_store.rs
+++ b/crates/hir-def/src/expr_store.rs
@@ -303,6 +303,7 @@ pub enum ExpressionStoreDiagnostics {
UnreachableLabel { node: InFile<AstPtr<ast::Lifetime>>, name: Name },
AwaitOutsideOfAsync { node: InFile<AstPtr<ast::AwaitExpr>>, location: String },
UndeclaredLabel { node: InFile<AstPtr<ast::Lifetime>>, name: Name },
+ PatternArgInExternFn { node: InFile<AstPtr<ast::Pat>> },
}
impl ExpressionStoreBuilder {
diff --git a/crates/hir-def/src/expr_store/lower.rs b/crates/hir-def/src/expr_store/lower.rs
index 5c8e87c0e3..b86fad0420 100644
--- a/crates/hir-def/src/expr_store/lower.rs
+++ b/crates/hir-def/src/expr_store/lower.rs
@@ -2482,9 +2482,7 @@ impl<'db> ExprCollector<'db> {
let Some(pat) = pat else { return self.missing_pat() };
match &pat {
- ast::Pat::IdentPat(bp) => {
- // FIXME: Emit an error if `!bp.is_simple_ident()`.
-
+ ast::Pat::IdentPat(bp) if bp.is_simple_ident() => {
let name = bp.name().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
let hygiene = bp
.name()
@@ -2496,8 +2494,12 @@ impl<'db> ExprCollector<'db> {
self.add_definition_to_binding(binding, pat);
pat
}
- // FIXME: Emit an error.
- _ => self.missing_pat(),
+ _ => {
+ self.store.diagnostics.push(ExpressionStoreDiagnostics::PatternArgInExternFn {
+ node: self.expander.in_file(AstPtr::new(&pat)),
+ });
+ self.missing_pat()
+ }
}
}
diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs
index 32f0ac3dad..b2edac6c32 100644
--- a/crates/hir/src/diagnostics.rs
+++ b/crates/hir/src/diagnostics.rs
@@ -80,6 +80,7 @@ diagnostics![AnyDiagnostic<'db> ->
NeedMut,
NonExhaustiveLet,
NoSuchField,
+ PatternArgInExternFn,
PrivateAssocItem,
PrivateField,
RemoveTrailingReturn,
@@ -486,6 +487,11 @@ pub struct InvalidLhsOfAssignment {
pub lhs: InFile<AstPtr<Either<ast::Expr, ast::Pat>>>,
}
+#[derive(Debug)]
+pub struct PatternArgInExternFn {
+ pub node: InFile<AstPtr<ast::Pat>>,
+}
+
impl<'db> AnyDiagnostic<'db> {
pub(crate) fn body_validation_diagnostic(
db: &'db dyn HirDatabase,
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 8cc82113b3..20fae4fb0d 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -2388,6 +2388,9 @@ fn expr_store_diagnostics<'db>(
ExpressionStoreDiagnostics::UndeclaredLabel { node, name } => {
UndeclaredLabel { node: *node, name: name.clone() }.into()
}
+ ExpressionStoreDiagnostics::PatternArgInExternFn { node } => {
+ PatternArgInExternFn { node: *node }.into()
+ }
});
}
diff --git a/crates/ide-diagnostics/src/handlers/pattern_arg_in_extern_fn.rs b/crates/ide-diagnostics/src/handlers/pattern_arg_in_extern_fn.rs
new file mode 100644
index 0000000000..36031865fc
--- /dev/null
+++ b/crates/ide-diagnostics/src/handlers/pattern_arg_in_extern_fn.rs
@@ -0,0 +1,86 @@
+use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext};
+
+// Diagnostic: pattern-arg-in-extern-fn
+//
+// This diagnostic is triggered if a pattern was declared as an argument in a foreign function declaration.
+pub(crate) fn pattern_arg_in_extern_fn(
+ ctx: &DiagnosticsContext<'_>,
+ d: &hir::PatternArgInExternFn,
+) -> Diagnostic {
+ Diagnostic::new_with_syntax_node_ptr(
+ ctx,
+ DiagnosticCode::RustcHardError("E0130"),
+ "patterns aren't allowed in foreign function declarations",
+ d.node.map(Into::into),
+ )
+ .stable()
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::tests::check_diagnostics;
+
+ #[test]
+ fn tuple_pattern() {
+ check_diagnostics(
+ r#"
+unsafe extern { fn foo((a, b): (u32, u32)); }
+ // ^^^^^^ error: patterns aren't allowed in foreign function declarations
+ "#,
+ );
+ }
+
+ #[test]
+ fn struct_pattern() {
+ check_diagnostics(
+ r#"
+struct Foo(u32, u32);
+unsafe extern { fn foo(Foo(a, b): Foo); }
+ // ^^^^^^^^^ error: patterns aren't allowed in foreign function declarations
+ "#,
+ );
+
+ check_diagnostics(
+ r#"
+struct Foo{ bar: u32, baz: u32 }
+unsafe extern { fn foo(Foo { bar, baz }: Foo); }
+ // ^^^^^^^^^^^^^^^^ error: patterns aren't allowed in foreign function declarations
+ "#,
+ );
+ }
+
+ #[test]
+ fn pattern_is_second_arg() {
+ check_diagnostics(
+ r#"
+struct Foo(u32, u32);
+unsafe extern { fn foo(okay: u32, Foo(a, b): Foo); }
+ // ^^^^^^^^^ error: patterns aren't allowed in foreign function declarations
+ "#,
+ );
+ }
+
+ #[test]
+ fn non_simple_ident() {
+ check_diagnostics(
+ r#"
+unsafe extern { fn foo(ref a: u32); }
+ // ^^^^^ error: patterns aren't allowed in foreign function declarations
+ "#,
+ );
+
+ check_diagnostics(
+ r#"
+unsafe extern { fn foo(mut a: u32); }
+ // ^^^^^ error: patterns aren't allowed in foreign function declarations
+ "#,
+ );
+
+ check_diagnostics(
+ r#"
+unsafe extern { fn foo(a @ _: u32); }
+ // ^^^^^ error: patterns aren't allowed in foreign function declarations
+ "#,
+ );
+ }
+}
diff --git a/crates/ide-diagnostics/src/lib.rs b/crates/ide-diagnostics/src/lib.rs
index a083447335..adc32564aa 100644
--- a/crates/ide-diagnostics/src/lib.rs
+++ b/crates/ide-diagnostics/src/lib.rs
@@ -56,6 +56,7 @@ mod handlers {
pub(crate) mod no_such_field;
pub(crate) mod non_exhaustive_let;
pub(crate) mod parenthesized_generic_args_without_fn_trait;
+ pub(crate) mod pattern_arg_in_extern_fn;
pub(crate) mod private_assoc_item;
pub(crate) mod private_field;
pub(crate) mod remove_trailing_return;
@@ -483,6 +484,7 @@ pub fn semantic_diagnostics(
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::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),
};
res.push(d)
}