Skip to content

Commit

Permalink
Take empty where into account when suggesting predicates
Browse files Browse the repository at this point in the history
  • Loading branch information
gurry committed Feb 10, 2024
1 parent 98aa362 commit 0815067
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 2 deletions.
8 changes: 7 additions & 1 deletion compiler/rustc_middle/src/ty/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,11 +358,17 @@ pub fn suggest_constraining_type_params<'a>(
// trait Foo<T=()> {... }
// - insert: `where T: Zar`
if matches!(param.kind, hir::GenericParamKind::Type { default: Some(_), .. }) {
// If we are here and the where clause span is of non-zero length
// it means we're dealing with an empty where clause like this:
// fn foo<X>(x: X) where { ... }
// In that case we don't want to add another "where" (Fixes #120838)
let where_prefix = if generics.where_clause_span.is_empty() { " where" } else { "" };

// Suggest a bound, but there is no existing `where` clause *and* the type param has a
// default (`<T=Foo>`), so we suggest adding `where T: Bar`.
suggestions.push((
generics.tail_span_for_predicate_suggestion(),
format!(" where {param_name}: {constraint}"),
format!("{where_prefix} {param_name}: {constraint}"),
SuggestChangingConstraintsMessage::RestrictTypeFurther { ty: param_name },
));
continue;
Expand Down
9 changes: 9 additions & 0 deletions tests/ui/trait-impl-bound-suggestions.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,13 @@ trait InsufficientlyConstrainedGeneric<X=()> where X: std::marker::Copy {
}
}

// Regression test for #120838
#[allow(dead_code)]
trait InsufficientlyConstrainedGenericWithEmptyWhere<X=()> where X: std::marker::Copy {
fn return_the_constrained_type(&self, x: X) -> ConstrainedStruct<X> {
//~^ ERROR the trait bound `X: Copy` is not satisfied
ConstrainedStruct { x }
}
}

pub fn main() { }
9 changes: 9 additions & 0 deletions tests/ui/trait-impl-bound-suggestions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,13 @@ trait InsufficientlyConstrainedGeneric<X=()> {
}
}

// Regression test for #120838
#[allow(dead_code)]
trait InsufficientlyConstrainedGenericWithEmptyWhere<X=()> where {
fn return_the_constrained_type(&self, x: X) -> ConstrainedStruct<X> {
//~^ ERROR the trait bound `X: Copy` is not satisfied
ConstrainedStruct { x }
}
}

pub fn main() { }
18 changes: 17 additions & 1 deletion tests/ui/trait-impl-bound-suggestions.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,22 @@ help: consider further restricting type parameter `X`
LL | trait InsufficientlyConstrainedGeneric<X=()> where X: std::marker::Copy {
| ++++++++++++++++++++++++++

error: aborting due to 1 previous error
error[E0277]: the trait bound `X: Copy` is not satisfied
--> $DIR/trait-impl-bound-suggestions.rs:23:52
|
LL | fn return_the_constrained_type(&self, x: X) -> ConstrainedStruct<X> {
| ^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `X`
|
note: required by a bound in `ConstrainedStruct`
--> $DIR/trait-impl-bound-suggestions.rs:8:29
|
LL | struct ConstrainedStruct<X: Copy> {
| ^^^^ required by this bound in `ConstrainedStruct`
help: consider further restricting type parameter `X`
|
LL | trait InsufficientlyConstrainedGenericWithEmptyWhere<X=()> where X: std::marker::Copy {
| ++++++++++++++++++++

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0277`.

0 comments on commit 0815067

Please sign in to comment.