1
Fork 0

Provide placeholder generic arguments for traits in "no method found for type parameter" suggestions

This commit is contained in:
dianne 2024-11-01 19:47:07 -07:00
parent de27914e8e
commit 02add7d0fb
4 changed files with 137 additions and 21 deletions

View file

@ -4,6 +4,7 @@
#![feature(array_windows)]
#![feature(box_patterns)]
#![feature(if_let_guard)]
#![feature(iter_intersperse)]
#![feature(let_chains)]
#![feature(never_type)]
#![feature(try_blocks)]

View file

@ -3874,22 +3874,52 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
param.name.ident(),
));
let bounds_span = hir_generics.bounds_span_for_suggestions(def_id);
let mut applicability = Applicability::MaybeIncorrect;
// Format the path of each suggested candidate, providing placeholders
// for any generic arguments without defaults.
let candidate_strs: Vec<_> = candidates
.iter()
.map(|cand| {
let cand_path = self.tcx.def_path_str(cand.def_id);
let cand_params = &self.tcx.generics_of(cand.def_id).own_params;
let cand_args: String = cand_params
.iter()
.skip(1)
.filter_map(|param| match param.kind {
ty::GenericParamDefKind::Type {
has_default: true,
..
}
| ty::GenericParamDefKind::Const {
has_default: true,
..
} => None,
_ => Some(param.name.as_str()),
})
.intersperse(", ")
.collect();
if cand_args.is_empty() {
cand_path
} else {
applicability = Applicability::HasPlaceholders;
format!("{cand_path}</* {cand_args} */>")
}
})
.collect();
if rcvr_ty.is_ref()
&& param.is_impl_trait()
&& let Some((bounds_span, _)) = bounds_span
{
err.multipart_suggestions(
msg,
candidates.iter().map(|t| {
candidate_strs.iter().map(|cand| {
vec![
(param.span.shrink_to_lo(), "(".to_string()),
(
bounds_span,
format!(" + {})", self.tcx.def_path_str(t.def_id)),
),
(bounds_span, format!(" + {cand})")),
]
}),
Applicability::MaybeIncorrect,
applicability,
);
return;
}
@ -3905,16 +3935,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
(param.span.shrink_to_hi(), Introducer::Colon, None)
};
let all_suggs = candidates.iter().map(|cand| {
let suggestion = format!(
"{} {}",
match introducer {
Introducer::Plus => " +",
Introducer::Colon => ":",
Introducer::Nothing => "",
},
self.tcx.def_path_str(cand.def_id)
);
let all_suggs = candidate_strs.iter().map(|cand| {
let suggestion = format!("{} {cand}", match introducer {
Introducer::Plus => " +",
Introducer::Colon => ":",
Introducer::Nothing => "",
},);
let mut suggs = vec![];
@ -3928,11 +3954,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
suggs
});
err.multipart_suggestions(
msg,
all_suggs,
Applicability::MaybeIncorrect,
);
err.multipart_suggestions(msg, all_suggs, applicability);
return;
}