Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 33 additions & 12 deletions compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
Original file line number Diff line number Diff line change
Expand Up @@ -774,20 +774,31 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
// instead we suggest `T: 'a + 'b` in that case.
let hir_generics = self.tcx.hir_get_generics(scope).unwrap();
let sugg_span = match hir_generics.bounds_span_for_suggestions(def_id) {
Some((span, open_paren_sp)) => Some((span, true, open_paren_sp)),
Some((span, open_paren_sp)) => {
Some((span, LifetimeSuggestion::NeedsPlus(open_paren_sp)))
}
// If `param` corresponds to `Self`, no usable suggestion span.
None if generics.has_self && param.index == 0 => None,
None => {
let mut colon_flag = false;
let span = if let Some(param) =
hir_generics.params.iter().find(|param| param.def_id == def_id)
&& let ParamName::Plain(ident) = param.name
{
ident.span.shrink_to_hi()
if let Some(sp) = param.colon_span {
colon_flag = true;
sp.shrink_to_hi()
} else {
ident.span.shrink_to_hi()
}
} else {
let span = self.tcx.def_span(def_id);
span.shrink_to_hi()
};
Some((span, false, None))
match colon_flag {
true => Some((span, LifetimeSuggestion::HasColon)),
false => Some((span, LifetimeSuggestion::NeedsColon)),
}
}
};
(scope, sugg_span)
Expand All @@ -811,17 +822,21 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
let mut suggs = vec![];
let lt_name = self.suggest_name_region(generic_param_scope, sub, &mut suggs);

if let Some((sp, has_lifetimes, open_paren_sp)) = type_param_sugg_span
if let Some((sp, suggestion_type)) = type_param_sugg_span
&& suggestion_scope == type_scope
{
let suggestion =
if has_lifetimes { format!(" + {lt_name}") } else { format!(": {lt_name}") };

if let Some(open_paren_sp) = open_paren_sp {
suggs.push((open_paren_sp, "(".to_string()));
suggs.push((sp, format!("){suggestion}")));
} else {
suggs.push((sp, suggestion))
match suggestion_type {
LifetimeSuggestion::NeedsPlus(open_paren_sp) => {
let suggestion = format!(" + {lt_name}");
if let Some(open_paren_sp) = open_paren_sp {
suggs.push((open_paren_sp, "(".to_string()));
suggs.push((sp, format!("){suggestion}")));
} else {
suggs.push((sp, suggestion));
}
}
LifetimeSuggestion::NeedsColon => suggs.push((sp, format!(": {lt_name}"))),
LifetimeSuggestion::HasColon => suggs.push((sp, format!(" {lt_name}"))),
}
} else if let GenericKind::Alias(ref p) = bound_kind
&& let ty::Projection = p.kind(self.tcx)
Expand Down Expand Up @@ -1056,6 +1071,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}
}

enum LifetimeSuggestion {
NeedsPlus(Option<Span>),
NeedsColon,
HasColon,
}

pub(super) fn note_and_explain_region<'tcx>(
tcx: TyCtxt<'tcx>,
err: &mut Diag<'_>,
Expand Down
9 changes: 9 additions & 0 deletions tests/ui/generics/missing-param-but-has-colon-144215.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//! Regression test for <https://github.com/rust-lang/rust/issues/144215>

#[rustfmt::skip]
struct S<T:>(&'static T);
//~^ ERROR the parameter type `T` may not live long enough
//~| HELP consider adding an explicit lifetime bound
//~| SUGGESTION 'static

fn main() {}
17 changes: 17 additions & 0 deletions tests/ui/generics/missing-param-but-has-colon-144215.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/missing-param-but-has-colon-144215.rs:4:14
|
LL | struct S<T:>(&'static T);
| ^^^^^^^^^^
| |
| the parameter type `T` must be valid for the static lifetime...
| ...so that the reference type `&'static T` does not outlive the data it points at
|
help: consider adding an explicit lifetime bound
|
LL | struct S<T: 'static>(&'static T);
| +++++++

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0310`.
Loading