add enum to address lifetime with colon problem
This commit is contained in:
parent
73e6c9ebd9
commit
4e17091cf8
3 changed files with 59 additions and 12 deletions
|
|
@ -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<Span>),
|
||||
NeedsColon,
|
||||
HasColon,
|
||||
}
|
||||
|
||||
pub(super) fn note_and_explain_region<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
err: &mut Diag<'_>,
|
||||
|
|
|
|||
9
tests/ui/generics/missing-param-but-has-colon-144215.rs
Normal file
9
tests/ui/generics/missing-param-but-has-colon-144215.rs
Normal file
|
|
@ -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
tests/ui/generics/missing-param-but-has-colon-144215.stderr
Normal file
17
tests/ui/generics/missing-param-but-has-colon-144215.stderr
Normal file
|
|
@ -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…
Add table
Add a link
Reference in a new issue