rust-lang / rust-lang/rust

E0283 doesn't always tell you to replace ("specify") generic parameters

Open
#128,585 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-diagnostics T-compiler
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

Code
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
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
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.

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
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
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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the E0283 diagnostics using the Rust Playground example in the issue, including both the direct call and the intermediate cast cases. Trace the compiler's generic-argument suggestion generation and add coverage for the desired wording, with completion shown by the suggestions consistently identifying generic parameter names that must be replaced.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.