Fix invalid syntax in impl Trait parameter type suggestions for E0311
This commit is contained in:
parent
ef4046e4f3
commit
621d412241
14 changed files with 365 additions and 39 deletions
|
@ -2144,18 +2144,21 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
// suggest adding an explicit lifetime bound to it.
|
||||
let generics = self.tcx.generics_of(generic_param_scope);
|
||||
// type_param_span is (span, has_bounds)
|
||||
let mut is_synthetic = false;
|
||||
let mut ast_generics = None;
|
||||
let type_param_span = match bound_kind {
|
||||
GenericKind::Param(ref param) => {
|
||||
// Account for the case where `param` corresponds to `Self`,
|
||||
// which doesn't have the expected type argument.
|
||||
if !(generics.has_self && param.index == 0) {
|
||||
let type_param = generics.type_param(param, self.tcx);
|
||||
is_synthetic = type_param.kind.is_synthetic();
|
||||
type_param.def_id.as_local().map(|def_id| {
|
||||
// Get the `hir::Param` to verify whether it already has any bounds.
|
||||
// We do this to avoid suggesting code that ends up as `T: 'a'b`,
|
||||
// instead we suggest `T: 'a + 'b` in that case.
|
||||
let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
|
||||
let ast_generics = self.tcx.hir().get_generics(hir_id.owner.def_id);
|
||||
ast_generics = self.tcx.hir().get_generics(hir_id.owner.def_id);
|
||||
let bounds =
|
||||
ast_generics.and_then(|g| g.bounds_span_for_suggestions(def_id));
|
||||
// `sp` only covers `T`, change it so that it covers
|
||||
|
@ -2187,11 +2190,64 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
.unwrap_or("'lt".to_string())
|
||||
};
|
||||
|
||||
let add_lt_sugg = generics
|
||||
.params
|
||||
.first()
|
||||
.and_then(|param| param.def_id.as_local())
|
||||
.map(|def_id| (self.tcx.def_span(def_id).shrink_to_lo(), format!("{}, ", new_lt)));
|
||||
let mut add_lt_suggs: Vec<Option<_>> = vec![];
|
||||
if is_synthetic {
|
||||
if let Some(ast_generics) = ast_generics {
|
||||
let named_lifetime_param_exist = ast_generics.params.iter().any(|p| {
|
||||
matches!(
|
||||
p.kind,
|
||||
hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit }
|
||||
)
|
||||
});
|
||||
if named_lifetime_param_exist && let [param, ..] = ast_generics.params
|
||||
{
|
||||
add_lt_suggs.push(Some((
|
||||
self.tcx.def_span(param.def_id).shrink_to_lo(),
|
||||
format!("{new_lt}, "),
|
||||
)));
|
||||
} else {
|
||||
add_lt_suggs
|
||||
.push(Some((ast_generics.span.shrink_to_hi(), format!("<{new_lt}>"))));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if let [param, ..] = &generics.params[..] && let Some(def_id) = param.def_id.as_local()
|
||||
{
|
||||
add_lt_suggs
|
||||
.push(Some((self.tcx.def_span(def_id).shrink_to_lo(), format!("{new_lt}, "))));
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ast_generics) = ast_generics {
|
||||
for p in ast_generics.params {
|
||||
if p.is_elided_lifetime() {
|
||||
if self
|
||||
.tcx
|
||||
.sess
|
||||
.source_map()
|
||||
.span_to_prev_source(p.span.shrink_to_hi())
|
||||
.ok()
|
||||
.map_or(false, |s| *s.as_bytes().last().unwrap() == b'&')
|
||||
{
|
||||
add_lt_suggs
|
||||
.push(Some(
|
||||
(
|
||||
p.span.shrink_to_hi(),
|
||||
if let Ok(snip) = self.tcx.sess.source_map().span_to_next_source(p.span)
|
||||
&& snip.starts_with(' ')
|
||||
{
|
||||
format!("{new_lt}")
|
||||
} else {
|
||||
format!("{new_lt} ")
|
||||
}
|
||||
)
|
||||
));
|
||||
} else {
|
||||
add_lt_suggs.push(Some((p.span.shrink_to_hi(), format!("<{new_lt}>"))));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let labeled_user_string = match bound_kind {
|
||||
GenericKind::Param(ref p) => format!("the parameter type `{}`", p),
|
||||
|
@ -2215,20 +2271,22 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
);
|
||||
}
|
||||
|
||||
fn binding_suggestion<S: fmt::Display>(
|
||||
fn binding_suggestion<'tcx, S: fmt::Display>(
|
||||
err: &mut Diagnostic,
|
||||
type_param_span: Option<(Span, bool)>,
|
||||
bound_kind: GenericKind<'_>,
|
||||
bound_kind: GenericKind<'tcx>,
|
||||
sub: S,
|
||||
add_lt_sugg: Option<(Span, String)>,
|
||||
add_lt_suggs: Vec<Option<(Span, String)>>,
|
||||
) {
|
||||
let msg = "consider adding an explicit lifetime bound";
|
||||
if let Some((sp, has_lifetimes)) = type_param_span {
|
||||
let suggestion =
|
||||
if has_lifetimes { format!(" + {}", sub) } else { format!(": {}", sub) };
|
||||
let mut suggestions = vec![(sp, suggestion)];
|
||||
if let Some(add_lt_sugg) = add_lt_sugg {
|
||||
suggestions.push(add_lt_sugg);
|
||||
for add_lt_sugg in add_lt_suggs {
|
||||
if let Some(add_lt_sugg) = add_lt_sugg {
|
||||
suggestions.push(add_lt_sugg);
|
||||
}
|
||||
}
|
||||
err.multipart_suggestion_verbose(
|
||||
format!("{msg}..."),
|
||||
|
@ -2252,9 +2310,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
};
|
||||
let mut sugg =
|
||||
vec![(sp, suggestion), (span.shrink_to_hi(), format!(" + {}", new_lt))];
|
||||
if let Some(lt) = add_lt_sugg.clone() {
|
||||
sugg.push(lt);
|
||||
sugg.rotate_right(1);
|
||||
for add_lt_sugg in add_lt_suggs.clone() {
|
||||
if let Some(lt) = add_lt_sugg {
|
||||
sugg.push(lt);
|
||||
sugg.rotate_right(1);
|
||||
}
|
||||
}
|
||||
// `MaybeIncorrect` due to issue #41966.
|
||||
err.multipart_suggestion(msg, sugg, Applicability::MaybeIncorrect);
|
||||
|
@ -2358,7 +2418,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
// for the bound is not suitable for suggestions when `-Zverbose` is set because it
|
||||
// uses `Debug` output, so we handle it specially here so that suggestions are
|
||||
// always correct.
|
||||
binding_suggestion(&mut err, type_param_span, bound_kind, name, None);
|
||||
binding_suggestion(&mut err, type_param_span, bound_kind, name, vec![]);
|
||||
err
|
||||
}
|
||||
|
||||
|
@ -2371,7 +2431,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
"{} may not live long enough",
|
||||
labeled_user_string
|
||||
);
|
||||
binding_suggestion(&mut err, type_param_span, bound_kind, "'static", None);
|
||||
binding_suggestion(&mut err, type_param_span, bound_kind, "'static", vec![]);
|
||||
err
|
||||
}
|
||||
|
||||
|
@ -2410,7 +2470,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
type_param_span,
|
||||
bound_kind,
|
||||
new_lt,
|
||||
add_lt_sugg,
|
||||
add_lt_suggs,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue