about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-11-29 10:18:59 +0100
committerGitHub <noreply@github.com>2024-11-29 10:18:59 +0100
commit72cf40d9edd4d8172f5e1ff58f6cafe9734b2e2a (patch)
treeddf179c940af8b0cba63ccc98af99af99f92caee
parent8ca5a907a506c541a449c533fcb705b9a008361b (diff)
parent1e4817cd33a59f1e0ddb1a3e66bdc0794d0785be (diff)
downloadrust-72cf40d9edd4d8172f5e1ff58f6cafe9734b2e2a.tar.gz
rust-72cf40d9edd4d8172f5e1ff58f6cafe9734b2e2a.zip
Rollup merge of #133538 - dev-ardi:69232-better-diag, r=compiler-errors
Better diagnostic for fn items in variadic functions

closes #69232
-rw-r--r--compiler/rustc_hir_typeck/messages.ftl5
-rw-r--r--compiler/rustc_hir_typeck/src/errors.rs12
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs12
-rw-r--r--tests/ui/c-variadic/fn-item-diagnostic-issue-69232.rs13
-rw-r--r--tests/ui/c-variadic/fn-item-diagnostic-issue-69232.stderr16
-rw-r--r--tests/ui/c-variadic/issue-32201.rs5
-rw-r--r--tests/ui/c-variadic/issue-32201.stderr11
-rw-r--r--tests/ui/error-codes/E0617.rs5
-rw-r--r--tests/ui/error-codes/E0617.stderr8
9 files changed, 75 insertions, 12 deletions
diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl
index 3669100ed91..6001816ffbe 100644
--- a/compiler/rustc_hir_typeck/messages.ftl
+++ b/compiler/rustc_hir_typeck/messages.ftl
@@ -79,6 +79,11 @@ hir_typeck_field_multiply_specified_in_initializer =
     .label = used more than once
     .previous_use_label = first use of `{$ident}`
 
+hir_typeck_fn_item_to_variadic_function = can't pass a function item to a variadic function
+    .suggestion = use a function pointer instead
+    .help = a function item is zero-sized and needs to be cast into a function pointer to be used in FFI
+    .note = for more information on function items, visit https://doc.rust-lang.org/reference/types/function-item.html
+
 hir_typeck_fru_expr = this expression does not end in a comma...
 hir_typeck_fru_expr2 = ... so this is interpreted as a `..` range expression, instead of functional record update syntax
 hir_typeck_fru_note = this expression may have been misinterpreted as a `..` range expression
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index 4f579b05d83..fa27abd270f 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -797,3 +797,15 @@ pub(crate) struct PassToVariadicFunction<'a, 'tcx> {
     #[note(hir_typeck_teach_help)]
     pub(crate) teach: bool,
 }
+
+#[derive(Diagnostic)]
+#[diag(hir_typeck_fn_item_to_variadic_function, code = E0617)]
+#[help]
+#[note]
+pub(crate) struct PassFnItemToVariadicFunction {
+    #[primary_span]
+    pub span: Span,
+    #[suggestion(code = " as {replace}", applicability = "machine-applicable", style = "verbose")]
+    pub sugg_span: Span,
+    pub replace: String,
+}
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index f8f6564cf14..63777f82f1a 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -472,9 +472,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         variadic_error(tcx.sess, arg.span, arg_ty, "c_uint");
                     }
                     ty::FnDef(..) => {
-                        let ptr_ty = Ty::new_fn_ptr(self.tcx, arg_ty.fn_sig(self.tcx));
-                        let ptr_ty = self.resolve_vars_if_possible(ptr_ty);
-                        variadic_error(tcx.sess, arg.span, arg_ty, &ptr_ty.to_string());
+                        let fn_ptr = Ty::new_fn_ptr(self.tcx, arg_ty.fn_sig(self.tcx));
+                        let fn_ptr = self.resolve_vars_if_possible(fn_ptr).to_string();
+
+                        let fn_item_spa = arg.span;
+                        tcx.sess.dcx().emit_err(errors::PassFnItemToVariadicFunction {
+                            span: fn_item_spa,
+                            sugg_span: fn_item_spa.shrink_to_hi(),
+                            replace: fn_ptr,
+                        });
                     }
                     _ => {}
                 }
diff --git a/tests/ui/c-variadic/fn-item-diagnostic-issue-69232.rs b/tests/ui/c-variadic/fn-item-diagnostic-issue-69232.rs
new file mode 100644
index 00000000000..d0ef91b22b2
--- /dev/null
+++ b/tests/ui/c-variadic/fn-item-diagnostic-issue-69232.rs
@@ -0,0 +1,13 @@
+// https://github.com/rust-lang/rust/issues/69232
+
+extern "C" {
+    fn foo(x: usize, ...);
+}
+
+fn test() -> u8 {
+    127
+}
+
+fn main() {
+    unsafe { foo(1, test) }; //~ ERROR can't pass a function item to a variadic function
+}
diff --git a/tests/ui/c-variadic/fn-item-diagnostic-issue-69232.stderr b/tests/ui/c-variadic/fn-item-diagnostic-issue-69232.stderr
new file mode 100644
index 00000000000..6aa1c8a1091
--- /dev/null
+++ b/tests/ui/c-variadic/fn-item-diagnostic-issue-69232.stderr
@@ -0,0 +1,16 @@
+error[E0617]: can't pass a function item to a variadic function
+  --> $DIR/fn-item-diagnostic-issue-69232.rs:12:21
+   |
+LL |     unsafe { foo(1, test) };
+   |                     ^^^^
+   |
+   = help: a function item is zero-sized and needs to be cast into a function pointer to be used in FFI
+   = note: for more information on function items, visit https://doc.rust-lang.org/reference/types/function-item.html
+help: use a function pointer instead
+   |
+LL |     unsafe { foo(1, test as fn() -> u8) };
+   |                          +++++++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0617`.
diff --git a/tests/ui/c-variadic/issue-32201.rs b/tests/ui/c-variadic/issue-32201.rs
index f27bb1c2eb5..434711b7523 100644
--- a/tests/ui/c-variadic/issue-32201.rs
+++ b/tests/ui/c-variadic/issue-32201.rs
@@ -7,7 +7,8 @@ fn bar(_: *const u8) {}
 fn main() {
     unsafe {
         foo(0, bar);
-        //~^ ERROR can't pass `fn(*const u8) {bar}` to variadic function
-        //~| HELP cast the value to `fn(*const u8)`
+        //~^ ERROR can't pass a function item to a variadic function
+        //~| HELP a function item is zero-sized and needs to be cast into a function pointer to be used in FFI
+        ////~| HELP use a function pointer instead
     }
 }
diff --git a/tests/ui/c-variadic/issue-32201.stderr b/tests/ui/c-variadic/issue-32201.stderr
index 352db9f62f6..1cd85d7f07a 100644
--- a/tests/ui/c-variadic/issue-32201.stderr
+++ b/tests/ui/c-variadic/issue-32201.stderr
@@ -1,8 +1,15 @@
-error[E0617]: can't pass `fn(*const u8) {bar}` to variadic function
+error[E0617]: can't pass a function item to a variadic function
   --> $DIR/issue-32201.rs:9:16
    |
 LL |         foo(0, bar);
-   |                ^^^ help: cast the value to `fn(*const u8)`: `bar as fn(*const u8)`
+   |                ^^^
+   |
+   = help: a function item is zero-sized and needs to be cast into a function pointer to be used in FFI
+   = note: for more information on function items, visit https://doc.rust-lang.org/reference/types/function-item.html
+help: use a function pointer instead
+   |
+LL |         foo(0, bar as fn(*const u8));
+   |                    ++++++++++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/error-codes/E0617.rs b/tests/ui/error-codes/E0617.rs
index b71ba0ed88b..4a38174bc6f 100644
--- a/tests/ui/error-codes/E0617.rs
+++ b/tests/ui/error-codes/E0617.rs
@@ -20,7 +20,8 @@ fn main() {
         //~^ ERROR can't pass `u16` to variadic function
         //~| HELP cast the value to `c_uint`
         printf(::std::ptr::null(), printf);
-        //~^ ERROR can't pass `unsafe extern "C" fn(*const i8, ...) {printf}` to variadic function
-        //~| HELP cast the value to `unsafe extern "C" fn(*const i8, ...)`
+        //~^ ERROR can't pass a function item to a variadic function
+        //~| HELP a function item is zero-sized and needs to be cast into a function pointer to be used in FFI
+        //~| HELP use a function pointer instead
     }
 }
diff --git a/tests/ui/error-codes/E0617.stderr b/tests/ui/error-codes/E0617.stderr
index ea91ad08292..7193463e028 100644
--- a/tests/ui/error-codes/E0617.stderr
+++ b/tests/ui/error-codes/E0617.stderr
@@ -28,16 +28,18 @@ error[E0617]: can't pass `u16` to variadic function
 LL |         printf(::std::ptr::null(), 0u16);
    |                                    ^^^^ help: cast the value to `c_uint`: `0u16 as c_uint`
 
-error[E0617]: can't pass `unsafe extern "C" fn(*const i8, ...) {printf}` to variadic function
+error[E0617]: can't pass a function item to a variadic function
   --> $DIR/E0617.rs:22:36
    |
 LL |         printf(::std::ptr::null(), printf);
    |                                    ^^^^^^
    |
-help: cast the value to `unsafe extern "C" fn(*const i8, ...)`
+   = help: a function item is zero-sized and needs to be cast into a function pointer to be used in FFI
+   = note: for more information on function items, visit https://doc.rust-lang.org/reference/types/function-item.html
+help: use a function pointer instead
    |
 LL |         printf(::std::ptr::null(), printf as unsafe extern "C" fn(*const i8, ...));
-   |                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                                           +++++++++++++++++++++++++++++++++++++++
 
 error: aborting due to 6 previous errors