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..936f80c75fa 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 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, + }); } _ => {} }