about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2024-08-07 13:08:24 -0400
committerMichael Goulet <michael@errs.io>2024-08-16 14:10:06 -0400
commitd850f85055b1d46278e29be39d9b4b938e90f199 (patch)
treea80488c1486b15cd6467f55dcd5ee4f1d9a5ca4b
parent833af65f38c4674e3ae6d886174e65f0fcabab3d (diff)
downloadrust-d850f85055b1d46278e29be39d9b4b938e90f199.tar.gz
rust-d850f85055b1d46278e29be39d9b4b938e90f199.zip
Don't ICE on Fn trait error for foreign fn
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs4
-rw-r--r--tests/ui/foreign/foreign-safe-fn-arg-mismatch.rs13
-rw-r--r--tests/ui/foreign/foreign-safe-fn-arg-mismatch.stderr44
3 files changed, 61 insertions, 0 deletions
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
index 326a0e4e35c..79ba9840130 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
@@ -2729,6 +2729,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(ref sig, _), .. })
             | Node::TraitItem(&hir::TraitItem {
                 kind: hir::TraitItemKind::Fn(ref sig, _), ..
+            })
+            | Node::ForeignItem(&hir::ForeignItem {
+                kind: hir::ForeignItemKind::Fn(ref sig, _, _),
+                ..
             }) => (
                 sig.span,
                 None,
diff --git a/tests/ui/foreign/foreign-safe-fn-arg-mismatch.rs b/tests/ui/foreign/foreign-safe-fn-arg-mismatch.rs
new file mode 100644
index 00000000000..bb1052b15e9
--- /dev/null
+++ b/tests/ui/foreign/foreign-safe-fn-arg-mismatch.rs
@@ -0,0 +1,13 @@
+// Make sure we don't ICE when a foreign fn doesn't implement `Fn` due to arg mismatch.
+
+unsafe extern "Rust" {
+    pub safe fn foo();
+    pub safe fn bar(x: u32);
+}
+
+fn test(_: impl Fn(i32)) {}
+
+fn main() {
+    test(foo); //~ ERROR function is expected to take 1 argument, but it takes 0 arguments
+    test(bar); //~ ERROR type mismatch in function arguments
+}
diff --git a/tests/ui/foreign/foreign-safe-fn-arg-mismatch.stderr b/tests/ui/foreign/foreign-safe-fn-arg-mismatch.stderr
new file mode 100644
index 00000000000..73ccecff5ab
--- /dev/null
+++ b/tests/ui/foreign/foreign-safe-fn-arg-mismatch.stderr
@@ -0,0 +1,44 @@
+error[E0593]: function is expected to take 1 argument, but it takes 0 arguments
+  --> $DIR/foreign-safe-fn-arg-mismatch.rs:11:10
+   |
+LL |     pub safe fn foo();
+   |     ------------------ takes 0 arguments
+...
+LL |     test(foo);
+   |     ---- ^^^ expected function that takes 1 argument
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `test`
+  --> $DIR/foreign-safe-fn-arg-mismatch.rs:8:17
+   |
+LL | fn test(_: impl Fn(i32)) {}
+   |                 ^^^^^^^ required by this bound in `test`
+
+error[E0631]: type mismatch in function arguments
+  --> $DIR/foreign-safe-fn-arg-mismatch.rs:12:10
+   |
+LL |     pub safe fn bar(x: u32);
+   |     ------------------------ found signature defined here
+...
+LL |     test(bar);
+   |     ---- ^^^ expected due to this
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = note: expected function signature `fn(i32) -> _`
+              found function signature `fn(u32) -> _`
+note: required by a bound in `test`
+  --> $DIR/foreign-safe-fn-arg-mismatch.rs:8:17
+   |
+LL | fn test(_: impl Fn(i32)) {}
+   |                 ^^^^^^^ required by this bound in `test`
+help: consider wrapping the function in a closure
+   |
+LL |     test(|arg0: i32| bar(/* u32 */));
+   |          +++++++++++    +++++++++++
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0593, E0631.
+For more information about an error, try `rustc --explain E0593`.