Repository: rust
Issue: E0283 doesn't always tell you to replace ("specify") generic parameters
Labels: A-diagnostics,T-compiler

### Code

```Rust
use std::num::NonZero;
trait Trait {}
impl<T: ?Sized + Trait> Trait for &mut T {}
impl Trait for [u8] {}
impl Trait for [NonZero<u8>] {}

fn expect<B: Trait>(_: B) {}

fn test(slice: &mut [u32]) {
    // Doesn't tell you to replace `B`
    expect(bytemuck::cast_slice_mut(slice));

    // Does tell you to replace `B`
    // let cast = bytemuck::cast_slice_mut(slice);
    // expect(cast);
}
```


### Current output

```Shell
error[E0283]: type annotations needed
   --> src/lib.rs:11:12
    |
11  |     expect(bytemuck::cast_slice_mut(slice));
    |            ^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `B` declared on the function `cast_slice_mut`
    |
    = note: cannot satisfy `_: NoUninit`
    = help: the following types implement trait `NoUninit`:
              NonZero<i128>
              NonZero<i16>
              NonZero<i32>
              NonZero<i64>
              NonZero<i8>
              NonZero<isize>
              NonZero<u128>
              NonZero<u16>
            and 6 others
note: required by a bound in `bytemuck::cast_slice_mut`
   --> /playground/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bytemuck-1.16.3/src/lib.rs:367:6
    |
365 | pub fn cast_slice_mut<
    |        -------------- required by a bound in this function
366 |   A: NoUninit + AnyBitPattern,
367 |   B: NoUninit + AnyBitPattern,
    |      ^^^^^^^^ required by this bound in `cast_slice_mut`
help: consider specifying the generic arguments
    |
11  |     expect(bytemuck::cast_slice_mut::<u32, B>(slice));
    |                                    ++++++++++

error[E0283]: type annotations needed
  --> src/lib.rs:11:5
   |
11 |     expect(bytemuck::cast_slice_mut(slice));
   |     ^^^^^^ cannot infer type of the type parameter `B` declared on the function `expect`
   |
note: multiple `impl`s satisfying `[_]: Trait` found
  --> src/lib.rs:4:1
   |
4  | impl Trait for [u8] {}
   | ^^^^^^^^^^^^^^^^^^^
5  | impl Trait for [NonZero<u8>] {}
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: required for `&mut [_]` to implement `Trait`
  --> src/lib.rs:3:25
   |
3  | impl<T: ?Sized + Trait> Trait for &mut T {}
   |                  -----  ^^^^^     ^^^^^^
   |                  |
   |                  unsatisfied trait bound introduced here
note: required by a bound in `expect`
  --> src/lib.rs:7:14
   |
7  | fn expect<B: Trait>(_: B) {}
   |              ^^^^^ required by this bound in `expect`
help: consider specifying the generic argument
   |
11 |     expect::<&mut [B]>(bytemuck::cast_slice_mut(slice));
   |           ++++++++++++
```


### Desired output

```Shell
error[E0283]: type annotations needed
   --> src/lib.rs:11:12
    |
11  |     expect(bytemuck::cast_slice_mut(slice));
    |            ^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `B` declared on the function `cast_slice_mut`
    |
    = note: cannot satisfy `_: NoUninit`
    = help: the following types implement trait `NoUninit`:
              NonZero<i128>
              NonZero<i16>
              NonZero<i32>
              NonZero<i64>
              NonZero<i8>
              NonZero<isize>
              NonZero<u128>
              NonZero<u16>
            and 6 others
note: required by a bound in `bytemuck::cast_slice_mut`
   --> /playground/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bytemuck-1.16.3/src/lib.rs:367:6
    |
365 | pub fn cast_slice_mut<
    |        -------------- required by a bound in this function
366 |   A: NoUninit + AnyBitPattern,
367 |   B: NoUninit + AnyBitPattern,
    |      ^^^^^^^^ required by this bound in `cast_slice_mut`
help: consider specifying the generic arguments, where the type for type parameter `B` is specified
    |
11  |     expect(bytemuck::cast_slice_mut::<u32, B>(slice));
    |                                    ++++++++++

error[E0283]: type annotations needed
  --> src/lib.rs:11:5
   |
11 |     expect(bytemuck::cast_slice_mut(slice));
   |     ^^^^^^ cannot infer type of the type parameter `B` declared on the function `expect`
   |
note: multiple `impl`s satisfying `[_]: Trait` found
  --> src/lib.rs:4:1
   |
4  | impl Trait for [u8] {}
   | ^^^^^^^^^^^^^^^^^^^
5  | impl Trait for [NonZero<u8>] {}
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: required for `&mut [_]` to implement `Trait`
  --> src/lib.rs:3:25
   |
3  | impl<T: ?Sized + Trait> Trait for &mut T {}
   |                  -----  ^^^^^     ^^^^^^
   |                  |
   |                  unsatisfied trait bound introduced here
note: required by a bound in `expect`
  --> src/lib.rs:7:14
   |
7  | fn expect<B: Trait>(_: B) {}
   |              ^^^^^ required by this bound in `expect`
help: consider specifying the generic argument, where the type for type parameter `B` is specified
   |
11 |     expect::<&mut [B]>(bytemuck::cast_slice_mut(slice));
   |           ++++++++++++
```


### Rationale and extra context

In the face of ambiguity, E0283 suggestions print the name of generic parameters which were specified on the trait or function being called.  Sometimes they tell you that you need to replace ("specify") those generic parameter names with concrete names, and sometimes they do not.  The above code is an example of a case where they do not.

[Here's the URLO issue that prompted this report.](https://users.rust-lang.org/t/unsafe-code-traits-problem-with-generic-inference/115420)

> The compiler-suggested fix,
>
> `bytemuck::cast_slice_mut::<u32, B>(&mut mapped_slice[range_start + 1..range_end]),`
>
> won't work because there is no "`B`" in scope at that point.

If you comment the the top half of `test` and uncomment the bottom half, you get the output under "Other cases" instead (which does tell you to replace the generic parameter name).

### Other cases

```Rust
error[E0283]: type annotations needed for `&mut [_]`
   --> src/lib.rs:14:9
    |
14  |     let cast = bytemuck::cast_slice_mut(slice);
    |         ^^^^   ------------------------------- type must be known at this point
    |
    = note: cannot satisfy `_: NoUninit`
    = help: the following types implement trait `NoUninit`:
              NonZero<i128>
              NonZero<i16>
              NonZero<i32>
              NonZero<i64>
              NonZero<i8>
              NonZero<isize>
              NonZero<u128>
              NonZero<u16>
            and 6 others
note: required by a bound in `bytemuck::cast_slice_mut`
   --> /playground/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bytemuck-1.16.3/src/lib.rs:367:6
    |
365 | pub fn cast_slice_mut<
    |        -------------- required by a bound in this function
366 |   A: NoUninit + AnyBitPattern,
367 |   B: NoUninit + AnyBitPattern,
    |      ^^^^^^^^ required by this bound in `cast_slice_mut`
help: consider giving `cast` an explicit type, where the type for type parameter `B` is specified
    |
14  |     let cast: &mut [B] = bytemuck::cast_slice_mut(slice);
    |             ++++++++++

error[E0283]: type annotations needed for `&mut [_]`
  --> src/lib.rs:14:9
   |
14 |     let cast = bytemuck::cast_slice_mut(slice);
   |         ^^^^
15 |     expect(cast);
   |     ------------ type must be known at this point
   |
note: multiple `impl`s satisfying `[_]: Trait` found
  --> src/lib.rs:4:1
   |
4  | impl Trait for [u8] {}
   | ^^^^^^^^^^^^^^^^^^^
5  | impl Trait for [NonZero<u8>] {}
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: required for `&mut [_]` to implement `Trait`
  --> src/lib.rs:3:25
   |
3  | impl<T: ?Sized + Trait> Trait for &mut T {}
   |                  -----  ^^^^^     ^^^^^^
   |                  |
   |                  unsatisfied trait bound introduced here
note: required by a bound in `expect`
  --> src/lib.rs:7:14
   |
7  | fn expect<B: Trait>(_: B) {}
   |              ^^^^^ required by this bound in `expect`
help: consider giving `cast` an explicit type, where the type for slice `[_]` is specified
   |
14 |     let cast: &mut [B] = bytemuck::cast_slice_mut(slice);
   |             ++++++++++
```


### Rust Version

```Shell
Rust playground

Stable channel
Build using the Stable version: 1.80.0

Beta channel
Build using the Beta version: 1.81.0-beta.2
(2024-07-25 08328a323ecd80b443a8)

Nightly channel
Build using the Nightly version: 1.82.0-nightly
(2024-08-02 fd8d6fbe505ecf913f5e)
```


### Anything else?

I don't know if "is specified" is the most immediately understandable suggestion, but that's really orthogonal to the point of this issue -- the messaging should consistently point out that the name used is a generic parameter name which you have to replace.