Rollup merge of #95970 - WaffleLapkin:nicer_trait_suggestions, r=compiler-errors
Fix suggestions in case of `T:` bounds This PR fixes a corner case in `suggest_constraining_type_params` that was causing incorrect suggestions. For the following functions: ```rust fn a<T:>(t: T) { [t, t]; } fn b<T>(t: T) where T: { [t, t]; } ``` We previously suggested the following: ```text ... help: consider restricting type parameter `T` | 1 | fn a<T: Copy:>(t: T) { [t, t]; } | ++++++ ... help: consider further restricting this bound | 2 | fn b<T>(t: T) where T: + Copy { [t, t]; } | ++++++ ``` Note that neither `T: Copy:` not `where T: + Copy` is a correct bound. With this commit the suggestions are correct: ```text ... help: consider restricting type parameter `T` | 1 | fn a<T: Copy>(t: T) { [t, t]; } | ++++ ... help: consider further restricting this bound | 2 | fn b<T>(t: T) where T: Copy { [t, t]; } | ++++ ``` r? `@compiler-errors` I've tried fixing #95898 here too, but got too confused with how `suggest_traits_to_import` works and what it does 😅
This commit is contained in:
commit
d63a46ad28
5 changed files with 124 additions and 9 deletions
|
@ -336,10 +336,14 @@ pub fn suggest_constraining_type_params<'a>(
|
|||
}
|
||||
|
||||
let constraint = constraints.iter().map(|&(c, _)| c).collect::<Vec<_>>().join(" + ");
|
||||
let mut suggest_restrict = |span| {
|
||||
let mut suggest_restrict = |span, bound_list_non_empty| {
|
||||
suggestions.push((
|
||||
span,
|
||||
format!(" + {}", constraint),
|
||||
if bound_list_non_empty {
|
||||
format!(" + {}", constraint)
|
||||
} else {
|
||||
format!(" {}", constraint)
|
||||
},
|
||||
SuggestChangingConstraintsMessage::RestrictBoundFurther,
|
||||
))
|
||||
};
|
||||
|
@ -360,7 +364,10 @@ pub fn suggest_constraining_type_params<'a>(
|
|||
// |
|
||||
// replace with: `impl Foo + Bar`
|
||||
|
||||
suggest_restrict(param.span.shrink_to_hi());
|
||||
// `impl Trait` must have at least one trait in the list
|
||||
let bound_list_non_empty = true;
|
||||
|
||||
suggest_restrict(param.span.shrink_to_hi(), bound_list_non_empty);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -383,15 +390,25 @@ pub fn suggest_constraining_type_params<'a>(
|
|||
// --
|
||||
// |
|
||||
// replace with: `T: Bar +`
|
||||
suggest_restrict(span);
|
||||
|
||||
// `bounds_span_for_suggestions` returns `None` if the list is empty
|
||||
let bound_list_non_empty = true;
|
||||
|
||||
suggest_restrict(span, bound_list_non_empty);
|
||||
} else {
|
||||
let (colon, span) = match param.colon_span_for_suggestions(tcx.sess.source_map()) {
|
||||
// If there is already a colon after generic, do not suggest adding it again
|
||||
Some(sp) => ("", sp.shrink_to_hi()),
|
||||
None => (":", param.span.shrink_to_hi()),
|
||||
};
|
||||
|
||||
// If user hasn't provided any bounds, suggest adding a new one:
|
||||
//
|
||||
// fn foo<T>(t: T) { ... }
|
||||
// - help: consider restricting this type parameter with `T: Foo`
|
||||
suggestions.push((
|
||||
param.span.shrink_to_hi(),
|
||||
format!(": {}", constraint),
|
||||
span,
|
||||
format!("{colon} {constraint}"),
|
||||
SuggestChangingConstraintsMessage::RestrictType { ty: param_name },
|
||||
));
|
||||
}
|
||||
|
@ -459,17 +476,21 @@ pub fn suggest_constraining_type_params<'a>(
|
|||
));
|
||||
} else {
|
||||
let mut param_spans = Vec::new();
|
||||
let mut non_empty = false;
|
||||
|
||||
for predicate in generics.where_clause.predicates {
|
||||
if let WherePredicate::BoundPredicate(WhereBoundPredicate {
|
||||
span,
|
||||
bounded_ty,
|
||||
bounds,
|
||||
..
|
||||
}) = predicate
|
||||
{
|
||||
if let TyKind::Path(QPath::Resolved(_, path)) = &bounded_ty.kind {
|
||||
if let Some(segment) = path.segments.first() {
|
||||
if segment.ident.to_string() == param_name {
|
||||
non_empty = !bounds.is_empty();
|
||||
|
||||
param_spans.push(span);
|
||||
}
|
||||
}
|
||||
|
@ -478,7 +499,7 @@ pub fn suggest_constraining_type_params<'a>(
|
|||
}
|
||||
|
||||
match param_spans[..] {
|
||||
[¶m_span] => suggest_restrict(param_span.shrink_to_hi()),
|
||||
[¶m_span] => suggest_restrict(param_span.shrink_to_hi(), non_empty),
|
||||
_ => {
|
||||
suggestions.push((
|
||||
generics.where_clause.tail_span_for_suggestion(),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue