diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index 0765434d3c435..e225656af852c 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -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) @@ -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) @@ -1056,6 +1071,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } +enum LifetimeSuggestion { + NeedsPlus(Option), + NeedsColon, + HasColon, +} + pub(super) fn note_and_explain_region<'tcx>( tcx: TyCtxt<'tcx>, err: &mut Diag<'_>, diff --git a/tests/ui/generics/missing-param-but-has-colon-144215.rs b/tests/ui/generics/missing-param-but-has-colon-144215.rs new file mode 100644 index 0000000000000..31a9dd49e5c65 --- /dev/null +++ b/tests/ui/generics/missing-param-but-has-colon-144215.rs @@ -0,0 +1,9 @@ +//! Regression test for + +#[rustfmt::skip] +struct S(&'static T); +//~^ ERROR the parameter type `T` may not live long enough +//~| HELP consider adding an explicit lifetime bound +//~| SUGGESTION 'static + +fn main() {} diff --git a/tests/ui/generics/missing-param-but-has-colon-144215.stderr b/tests/ui/generics/missing-param-but-has-colon-144215.stderr new file mode 100644 index 0000000000000..bf6cee035e2e6 --- /dev/null +++ b/tests/ui/generics/missing-param-but-has-colon-144215.stderr @@ -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(&'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(&'static T); + | +++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0310`.