Skip to content

Commit 285cb31

Browse files
authored
Rollup merge of rust-lang#148405 - Kivooeo:static-span, r=JonathanBrouwer
Fix suggestion when there were a colon already in generics Finally found time to fix rust-lang#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`?
2 parents 7ed1f93 + 4e17091 commit 285cb31

File tree

3 files changed

+59
-12
lines changed

3 files changed

+59
-12
lines changed

compiler/rustc_trait_selection/src/error_reporting/infer/region.rs

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -774,20 +774,31 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
774774
// instead we suggest `T: 'a + 'b` in that case.
775775
let hir_generics = self.tcx.hir_get_generics(scope).unwrap();
776776
let sugg_span = match hir_generics.bounds_span_for_suggestions(def_id) {
777-
Some((span, open_paren_sp)) => Some((span, true, open_paren_sp)),
777+
Some((span, open_paren_sp)) => {
778+
Some((span, LifetimeSuggestion::NeedsPlus(open_paren_sp)))
779+
}
778780
// If `param` corresponds to `Self`, no usable suggestion span.
779781
None if generics.has_self && param.index == 0 => None,
780782
None => {
783+
let mut colon_flag = false;
781784
let span = if let Some(param) =
782785
hir_generics.params.iter().find(|param| param.def_id == def_id)
783786
&& let ParamName::Plain(ident) = param.name
784787
{
785-
ident.span.shrink_to_hi()
788+
if let Some(sp) = param.colon_span {
789+
colon_flag = true;
790+
sp.shrink_to_hi()
791+
} else {
792+
ident.span.shrink_to_hi()
793+
}
786794
} else {
787795
let span = self.tcx.def_span(def_id);
788796
span.shrink_to_hi()
789797
};
790-
Some((span, false, None))
798+
match colon_flag {
799+
true => Some((span, LifetimeSuggestion::HasColon)),
800+
false => Some((span, LifetimeSuggestion::NeedsColon)),
801+
}
791802
}
792803
};
793804
(scope, sugg_span)
@@ -811,17 +822,21 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
811822
let mut suggs = vec![];
812823
let lt_name = self.suggest_name_region(generic_param_scope, sub, &mut suggs);
813824

814-
if let Some((sp, has_lifetimes, open_paren_sp)) = type_param_sugg_span
825+
if let Some((sp, suggestion_type)) = type_param_sugg_span
815826
&& suggestion_scope == type_scope
816827
{
817-
let suggestion =
818-
if has_lifetimes { format!(" + {lt_name}") } else { format!(": {lt_name}") };
819-
820-
if let Some(open_paren_sp) = open_paren_sp {
821-
suggs.push((open_paren_sp, "(".to_string()));
822-
suggs.push((sp, format!("){suggestion}")));
823-
} else {
824-
suggs.push((sp, suggestion))
828+
match suggestion_type {
829+
LifetimeSuggestion::NeedsPlus(open_paren_sp) => {
830+
let suggestion = format!(" + {lt_name}");
831+
if let Some(open_paren_sp) = open_paren_sp {
832+
suggs.push((open_paren_sp, "(".to_string()));
833+
suggs.push((sp, format!("){suggestion}")));
834+
} else {
835+
suggs.push((sp, suggestion));
836+
}
837+
}
838+
LifetimeSuggestion::NeedsColon => suggs.push((sp, format!(": {lt_name}"))),
839+
LifetimeSuggestion::HasColon => suggs.push((sp, format!(" {lt_name}"))),
825840
}
826841
} else if let GenericKind::Alias(ref p) = bound_kind
827842
&& let ty::Projection = p.kind(self.tcx)
@@ -1056,6 +1071,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
10561071
}
10571072
}
10581073

1074+
enum LifetimeSuggestion {
1075+
NeedsPlus(Option<Span>),
1076+
NeedsColon,
1077+
HasColon,
1078+
}
1079+
10591080
pub(super) fn note_and_explain_region<'tcx>(
10601081
tcx: TyCtxt<'tcx>,
10611082
err: &mut Diag<'_>,
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
//! Regression test for <https://github.com/rust-lang/rust/issues/144215>
2+
3+
#[rustfmt::skip]
4+
struct S<T:>(&'static T);
5+
//~^ ERROR the parameter type `T` may not live long enough
6+
//~| HELP consider adding an explicit lifetime bound
7+
//~| SUGGESTION 'static
8+
9+
fn main() {}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error[E0310]: the parameter type `T` may not live long enough
2+
--> $DIR/missing-param-but-has-colon-144215.rs:4:14
3+
|
4+
LL | struct S<T:>(&'static T);
5+
| ^^^^^^^^^^
6+
| |
7+
| the parameter type `T` must be valid for the static lifetime...
8+
| ...so that the reference type `&'static T` does not outlive the data it points at
9+
|
10+
help: consider adding an explicit lifetime bound
11+
|
12+
LL | struct S<T: 'static>(&'static T);
13+
| +++++++
14+
15+
error: aborting due to 1 previous error
16+
17+
For more information about this error, try `rustc --explain E0310`.

0 commit comments

Comments
 (0)