Make error message for malformed fn/fn_mut lang item more specific

This commit is contained in:
Fabian Wolff 2021-09-24 18:55:14 +02:00
parent 4337089098
commit cb6c13977a
3 changed files with 34 additions and 15 deletions

View file

@ -203,25 +203,41 @@ pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
let encl_trait_hir_id = tcx.hir().get_parent_item(hir_id);
let encl_trait = tcx.hir().expect_item(encl_trait_hir_id);
if [tcx.lang_items().fn_trait(), tcx.lang_items().fn_mut_trait()]
.contains(&Some(encl_trait.def_id.to_def_id()))
&& trait_item.ident.name.to_ident_string() == "call"
let encl_trait_def_id = encl_trait.def_id.to_def_id();
let fn_lang_item_name = if Some(encl_trait_def_id) == tcx.lang_items().fn_trait() {
Some("fn")
} else if Some(encl_trait_def_id) == tcx.lang_items().fn_mut_trait() {
Some("fn_mut")
} else {
None
};
if let (Some(fn_lang_item_name), "call") =
(fn_lang_item_name, trait_item.ident.name.to_ident_string().as_str())
{
// We are looking at the `call` function of the `fn` or `fn_mut` lang item.
// Do some rudimentary sanity checking to avoid an ICE later (issue #83471).
if let Some(method_sig @ hir::FnSig { decl, .. }) = method_sig {
if let Some(hir::FnSig { decl, span, .. }) = method_sig {
if let &[self_ty, _] = &decl.inputs {
if !matches!(self_ty.kind, hir::TyKind::Rptr(_, _)) {
tcx.sess.struct_span_err(
self_ty.span,
"first argument of `call` in `fn`/`fn_mut` lang item must be a reference",
).emit();
tcx.sess
.struct_span_err(
self_ty.span,
&format!(
"first argument of `call` in `{}` lang item must be a reference",
fn_lang_item_name
),
)
.emit();
}
} else {
tcx.sess
.struct_span_err(
method_sig.span,
"`call` function in `fn`/`fn_mut` lang item takes exactly two arguments",
*span,
&format!(
"`call` function in `{}` lang item takes exactly two arguments",
fn_lang_item_name
),
)
.emit();
}
@ -229,7 +245,10 @@ pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
tcx.sess
.struct_span_err(
trait_item.span,
"`call` trait item in `fn`/`fn_mut` lang item must be a function",
&format!(
"`call` trait item in `{}` lang item must be a function",
fn_lang_item_name
),
)
.emit();
}

View file

@ -8,13 +8,13 @@
#[lang = "fn"]
trait MyFn<T> {
const call: i32 = 42;
//~^ ERROR: `call` trait item in `fn`/`fn_mut` lang item must be a function
//~^ ERROR: `call` trait item in `fn` lang item must be a function
}
#[lang = "fn_mut"]
trait MyFnMut<T> {
fn call(i: i32, j: i32) -> i32 { i + j }
//~^ ERROR: first argument of `call` in `fn`/`fn_mut` lang item must be a reference
//~^ ERROR: first argument of `call` in `fn_mut` lang item must be a reference
}
fn main() {

View file

@ -1,10 +1,10 @@
error: `call` trait item in `fn`/`fn_mut` lang item must be a function
error: `call` trait item in `fn` lang item must be a function
--> $DIR/fn-fn_mut-call-ill-formed.rs:10:5
|
LL | const call: i32 = 42;
| ^^^^^^^^^^^^^^^^^^^^^
error: first argument of `call` in `fn`/`fn_mut` lang item must be a reference
error: first argument of `call` in `fn_mut` lang item must be a reference
--> $DIR/fn-fn_mut-call-ill-formed.rs:16:16
|
LL | fn call(i: i32, j: i32) -> i32 { i + j }