Ported FunctionPointerSuggestion

This commit is contained in:
IQuant 2023-02-23 16:38:12 +03:00
parent be8e5ba157
commit 37f55691f4
3 changed files with 75 additions and 21 deletions

View file

@ -348,3 +348,8 @@ infer_prlf_known_limitation = this is a known limitation that will be removed in
infer_opaque_captures_lifetime = hidden type for `{$opaque_ty}` captures lifetime that does not appear in bounds infer_opaque_captures_lifetime = hidden type for `{$opaque_ty}` captures lifetime that does not appear in bounds
.label = opaque type defined here .label = opaque type defined here
infer_fps_use_ref = consider using a reference
infer_fps_remove_ref = consider removing the reference
infer_fps_cast = consider casting to a fn pointer
infer_fps_items_are_distinct = fn items are distinct from fn pointers

View file

@ -1157,3 +1157,63 @@ pub struct OpaqueCapturesLifetime<'tcx> {
pub opaque_ty_span: Span, pub opaque_ty_span: Span,
pub opaque_ty: Ty<'tcx>, pub opaque_ty: Ty<'tcx>,
} }
#[derive(Subdiagnostic)]
pub enum FunctionPointerSuggestion<'a> {
#[suggestion(
infer_fps_use_ref,
code = "&{fn_name}",
style = "verbose",
applicability = "maybe-incorrect"
)]
UseRef {
#[primary_span]
span: Span,
#[skip_arg]
fn_name: String,
},
#[suggestion(
infer_fps_remove_ref,
code = "{fn_name}",
style = "verbose",
applicability = "maybe-incorrect"
)]
RemoveRef {
#[primary_span]
span: Span,
#[skip_arg]
fn_name: String,
},
#[suggestion(
infer_fps_cast,
code = "&({fn_name} as {sig})",
style = "verbose",
applicability = "maybe-incorrect"
)]
CastRef {
#[primary_span]
span: Span,
#[skip_arg]
fn_name: String,
#[skip_arg]
sig: Binder<'a, FnSig<'a>>,
},
#[suggestion(
infer_fps_cast,
code = "{fn_name} as {sig}",
style = "verbose",
applicability = "maybe-incorrect"
)]
Cast {
#[primary_span]
span: Span,
#[skip_arg]
fn_name: String,
#[skip_arg]
sig: Binder<'a, FnSig<'a>>,
},
}
#[derive(Subdiagnostic)]
#[note(infer_fps_items_are_distinct)]
pub struct FnItemsAreDistinct;

View file

@ -13,7 +13,8 @@ use rustc_span::{sym, BytePos, Span};
use rustc_target::abi::FieldIdx; use rustc_target::abi::FieldIdx;
use crate::errors::{ use crate::errors::{
ConsiderAddingAwait, SuggAddLetForLetChains, SuggestRemoveSemiOrReturnBinding, ConsiderAddingAwait, FnItemsAreDistinct, FunctionPointerSuggestion, SuggAddLetForLetChains,
SuggestRemoveSemiOrReturnBinding,
}; };
use super::TypeErrCtxt; use super::TypeErrCtxt;
@ -362,31 +363,19 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
return; return;
} }
let (msg, sug) = match (expected.is_ref(), found.is_ref()) { let sugg = match (expected.is_ref(), found.is_ref()) {
(true, false) => { (true, false) => FunctionPointerSuggestion::UseRef { span, fn_name },
let msg = "consider using a reference"; (false, true) => FunctionPointerSuggestion::RemoveRef { span, fn_name },
let sug = format!("&{fn_name}");
(msg, sug)
}
(false, true) => {
let msg = "consider removing the reference";
let sug = format!("{fn_name}");
(msg, sug)
}
(true, true) => { (true, true) => {
diag.note("fn items are distinct from fn pointers"); diag.subdiagnostic(FnItemsAreDistinct);
let msg = "consider casting to a fn pointer"; FunctionPointerSuggestion::CastRef { span, fn_name, sig: *sig }
let sug = format!("&({fn_name} as {sig})");
(msg, sug)
} }
(false, false) => { (false, false) => {
diag.note("fn items are distinct from fn pointers"); diag.subdiagnostic(FnItemsAreDistinct);
let msg = "consider casting to a fn pointer"; FunctionPointerSuggestion::Cast { span, fn_name, sig: *sig }
let sug = format!("{fn_name} as {sig}");
(msg, sug)
} }
}; };
diag.span_suggestion_verbose(span, msg, sug, Applicability::MaybeIncorrect); diag.subdiagnostic(sugg);
} }
(ty::FnDef(did1, substs1), ty::FnDef(did2, substs2)) => { (ty::FnDef(did1, substs1), ty::FnDef(did2, substs2)) => {
let expected_sig = let expected_sig =