Handle `impl Trait` where `Trait` has an assoc type with missing bounds
When encountering a type parameter that needs more bounds the trivial case is `T` `where T: Bound`, but it can also be an `impl Trait` param that needs to be decomposed to a type param for cleaner code. For example, given
```rust
fn foo(constraints: impl Iterator) {
for constraint in constraints {
println!("{:?}", constraint);
}
}
```
the previous output was
```
error[E0277]: `<impl Iterator as std::iter::Iterator>::Item` doesn't implement `std::fmt::Debug`
--> src/main.rs:3:26
|
1 | fn foo(constraints: impl Iterator) {
| - help: consider further restricting the associated type: `where <impl Iterator as std::iter::Iterator>::Item: std::fmt::Debug`
2 | for constraint in constraints {
3 | println!("{:?}", constraint);
| ^^^^^^^^^^ `<impl Iterator as std::iter::Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug`
|
= help: the trait `std::fmt::Debug` is not implemented for `<impl Iterator as std::iter::Iterator>::Item`
= note: required by `std::fmt::Debug::fmt`
```
which is incorrect as `where <impl Iterator as std::iter::Iterator>::Item: std::fmt::Debug` is not valid syntax nor would it restrict the positional `impl Iterator` parameter if it were.
The output being introduced is
```
error[E0277]: `<impl Iterator as std::iter::Iterator>::Item` doesn't implement `std::fmt::Debug`
--> src/main.rs:3:26
|
3 | println!("{:?}", constraint);
| ^^^^^^^^^^ `<impl Iterator as std::iter::Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug`
|
= help: the trait `std::fmt::Debug` is not implemented for `<impl Iterator as std::iter::Iterator>::Item`
= note: required by `std::fmt::Debug::fmt`
help: introduce a type parameter with a trait bound instead of using `impl Trait`
|
LL | fn foo<T: Iterator>(constraints: T) where <T as std::iter::Iterator>::Item: std::fmt::Debug {
| ^^^^^^^^^^^^^ ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
```
This suggestion is correct and lead the user in the right direction: because you have an associated type restriction you can no longer use `impl Trait`, the only reasonable alternative is to introduce a named type parameter, bound by `Trait` and with a `where` binding on the associated type for the new type parameter `as Trait` for the missing bound.
*Ideally*, we would want to suggest something like the following, but that is not valid syntax today
```
error[E0277]: `<impl Iterator as std::iter::Iterator>::Item` doesn't implement `std::fmt::Debug`
--> src/main.rs:3:26
|
3 | println!("{:?}", constraint);
| ^^^^^^^^^^ `<impl Iterator as std::iter::Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug`
|
= help: the trait `std::fmt::Debug` is not implemented for `<impl Iterator as std::iter::Iterator>::Item`
= note: required by `std::fmt::Debug::fmt`
help: introduce a type parameter with a trait bound instead of using `impl Trait`
|
LL | fn foo(constraints: impl Iterator<Item: std::fmt::Debug>) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
```
Fix #69638.
|
||
|---|---|---|
| .. | ||
| assembly | ||
| auxiliary | ||
| codegen | ||
| codegen-units | ||
| compile-fail | ||
| debuginfo | ||
| incremental | ||
| mir-opt | ||
| pretty | ||
| run-fail | ||
| run-make | ||
| run-make-fulldeps | ||
| run-pass-valgrind | ||
| rustdoc | ||
| rustdoc-js | ||
| rustdoc-js-std | ||
| rustdoc-ui | ||
| rustfix | ||
| ui | ||
| ui-fulldeps | ||
| COMPILER_TESTS.md | ||