Rollup merge of #148405 - Kivooeo:static-span, r=JonathanBrouwer
Fix suggestion when there were a colon already in generics Finally found time to fix https://github.com/rust-lang/rust/issues/144215 I don't feel like this `colon_flag` is perfect solution and that it can be refactored, but I'd say that this is pretty good as it, I was tried to refactor this a little, but the thing is the scope where `param.colon_span` lives is very limited, so there is not much time to check was there colon or not, I tried to rewrite this into more functional style to address this, but it becomes way more unreadable than this one or even less performant, maybe some comments could push readability of this fix further, maybe a comment for enum or `colon_flag`?
This commit is contained in:
commit
285cb31aa1
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