From b36dcc1a382d1a05099b80a8fe59279656ffed12 Mon Sep 17 00:00:00 2001 From: Orion Gonzalez Date: Wed, 27 Nov 2024 15:06:40 +0100 Subject: [PATCH 1/2] Improve the diagnostic of fn item in variadic fn --- compiler/rustc_hir_typeck/messages.ftl | 5 +++++ compiler/rustc_hir_typeck/src/errors.rs | 10 ++++++++++ compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs | 12 +++++++++--- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl index 3669100ed9167..6001816ffbec6 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 4f579b05d83b6..936f80c75fa45 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -797,3 +797,13 @@ 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)] +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 f8f6564cf14d9..63777f82f1ae3 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, + }); } _ => {} } From 1e4817cd33a59f1e0ddb1a3e66bdc0794d0785be Mon Sep 17 00:00:00 2001 From: Orion Gonzalez Date: Wed, 27 Nov 2024 15:37:27 +0100 Subject: [PATCH 2/2] bless the tests and add a new one --- compiler/rustc_hir_typeck/src/errors.rs | 2 ++ .../c-variadic/fn-item-diagnostic-issue-69232.rs | 13 +++++++++++++ .../fn-item-diagnostic-issue-69232.stderr | 16 ++++++++++++++++ tests/ui/c-variadic/issue-32201.rs | 5 +++-- tests/ui/c-variadic/issue-32201.stderr | 11 +++++++++-- tests/ui/error-codes/E0617.rs | 5 +++-- tests/ui/error-codes/E0617.stderr | 8 +++++--- 7 files changed, 51 insertions(+), 9 deletions(-) create mode 100644 tests/ui/c-variadic/fn-item-diagnostic-issue-69232.rs create mode 100644 tests/ui/c-variadic/fn-item-diagnostic-issue-69232.stderr diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 936f80c75fa45..fa27abd270ff2 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -800,6 +800,8 @@ pub(crate) struct PassToVariadicFunction<'a, 'tcx> { #[derive(Diagnostic)] #[diag(hir_typeck_fn_item_to_variadic_function, code = E0617)] +#[help] +#[note] pub(crate) struct PassFnItemToVariadicFunction { #[primary_span] pub span: Span, 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 0000000000000..d0ef91b22b234 --- /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 0000000000000..6aa1c8a109159 --- /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 f27bb1c2eb5b6..434711b75236e 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 352db9f62f6d8..1cd85d7f07af3 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 b71ba0ed88b9f..4a38174bc6fef 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 ea91ad0829230..7193463e02831 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