Skip to content

Commit dad350d

Browse files
author
Orion Gonzalez
committed
Improve the diagnostic of fn item in variadic fn
1 parent 5f8a240 commit dad350d

File tree

3 files changed

+32
-3
lines changed

3 files changed

+32
-3
lines changed

compiler/rustc_hir_typeck/messages.ftl

+5
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,11 @@ hir_typeck_field_multiply_specified_in_initializer =
7979
.label = used more than once
8080
.previous_use_label = first use of `{$ident}`
8181
82+
hir_typeck_fn_item_to_variadic_function = can't pass a function item to a variadic function
83+
.suggestion = use a function pointer instead
84+
.help = a function item is zero-sized and needs to be cast into a function pointer to be used in FFI
85+
.note = for more information on function items, visit https://doc.rust-lang.org/reference/types/function-item.html
86+
8287
hir_typeck_fru_expr = this expression does not end in a comma...
8388
hir_typeck_fru_expr2 = ... so this is interpreted as a `..` range expression, instead of functional record update syntax
8489
hir_typeck_fru_note = this expression may have been misinterpreted as a `..` range expression

compiler/rustc_hir_typeck/src/errors.rs

+10
Original file line numberDiff line numberDiff line change
@@ -797,3 +797,13 @@ pub(crate) struct PassToVariadicFunction<'a, 'tcx> {
797797
#[note(hir_typeck_teach_help)]
798798
pub(crate) teach: bool,
799799
}
800+
801+
#[derive(Diagnostic)]
802+
#[diag(hir_typeck_fn_item_to_variadic_function, code = E0617)]
803+
pub(crate) struct PassFnItemToVariadicFunction {
804+
#[primary_span]
805+
pub span: Span,
806+
#[suggestion(code = "{replace}", applicability = "machine-applicable")]
807+
pub sugg_span: Option<Span>,
808+
pub replace: String,
809+
}

compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

+17-3
Original file line numberDiff line numberDiff line change
@@ -472,9 +472,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
472472
variadic_error(tcx.sess, arg.span, arg_ty, "c_uint");
473473
}
474474
ty::FnDef(..) => {
475-
let ptr_ty = Ty::new_fn_ptr(self.tcx, arg_ty.fn_sig(self.tcx));
476-
let ptr_ty = self.resolve_vars_if_possible(ptr_ty);
477-
variadic_error(tcx.sess, arg.span, arg_ty, &ptr_ty.to_string());
475+
let sess = tcx.sess;
476+
let fn_item_span = arg.span;
477+
let fn_ptr = Ty::new_fn_ptr(self.tcx, arg_ty.fn_sig(self.tcx));
478+
let fn_ptr = self.resolve_vars_if_possible(fn_ptr).to_string();
479+
480+
let (sugg_span, replace) =
481+
if let Ok(fn_item) = sess.source_map().span_to_snippet(fn_item_span) {
482+
(Some(fn_item_span), format!("{fn_item} as {fn_ptr}"))
483+
} else {
484+
(None, "".to_string())
485+
};
486+
487+
sess.dcx().emit_err(errors::PassFnItemToVariadicFunction {
488+
span: fn_item_span,
489+
replace,
490+
sugg_span,
491+
});
478492
}
479493
_ => {}
480494
}

0 commit comments

Comments
 (0)