rust-lang / rust-lang/rust

Identify which tuple item fails to implement a trait when using fake variadics

Open
#141,258 15 comments 13 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

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

Description

Code
trait WorksOnDefault {
    fn do_something() {}
}

impl<T: Default> WorksOnDefault for T {}

fn main() {
    let _success = <(i32, u32, String)>::do_something();
    let _failure = <(i32, &u32, String)>::do_something();
}
Current output
error[E0599]: the function or associated item `do_something` exists for tuple `(i32, &u32, String)`, but its trait bounds were not satisfied
  --> examples/hello_world.rs:11:28
   |
11 |     <(i32, &u32, String)>::do_something();
   |                            ^^^^^^^^^^^^ function or associated item cannot be called on `(i32, &u32, String)` due to unsatisfied trait bounds
   |
note: the following trait bounds were not satisfied:
      `&(i32, &u32, String): Default`
      `&mut (i32, &u32, String): Default`
      `(i32, &u32, String): Default`
Desired output
No method `works_on_default` found for <(i32, &u32, String)>`

The method `do_something` is available via the `WorksOnDefault` trait for any type T where T implements the `Default` trait.

If every member of the tuple (i32, &u32, String) implemented the `Default` trait, the `Default` trait would be implemented for the tuple.

However, `&u32` does not implement the `Default` trait.

note: did you mean `u32`, which implements the `Default` trait?
Rationale and extra context

This is an extremely common pattern for Bevy, primarily in our system and bundle code patterns. The poor error messages are one of our largest UX / teaching problems,. See https://github.com/rust-lang/rust/issues/89681 for that specific issue, which could be fixed by more general improvements here.

This pattern occurs all over the place: the minimal example here uses Default, which relies on the same flavor of fake variadics for tuples where all tuple elements implement a given trait. Bevy's Bundle tuples matches this form exactly, while our Systems use the same sort of trick but with functions, where each parameter must implement SystemParam.

Other cases
fn main(){
    let _successful_default = <(i32, u32, String)>::default();
    let _failed_default = <(i32, &u32, String)>::default();
}

The error output when calling methods from the trait directly correctly identifies the problematic variant:

error[E0599]: the function or associated item `default` exists for tuple `(i32, &u32, String)`, but its trait bounds were not satisfied
 --> src/main.rs:3:50
  |
3 |     let _failed_default = <(i32, &u32, String)>::default();
  |                                                  ^^^^^^^ function or associated item cannot be called on `(i32, &u32, String)` due to unsatisfied trait bounds
  |
  = note: the following trait bounds were not satisfied:
          `&u32: Default`
          which is required by `(i32, &u32, String): Default`
``
Rust Version
rustc 1.87.0 (17067e9ac 2025-05-09)
binary: rustc
commit-hash: 17067e9ac6d7ecb70e50f92c1944e545188d2359
commit-date: 2025-05-09
host: x86_64-unknown-linux-gnu
release: 1.87.0
LLVM version: 20.1.1
Anything else?

Discussed with @estebank and @joshtriplett at RustWeek 2025, where I was encouraged to file an issue so we can improve diagnostics without waiting on full variadics!

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 diagnostic with the minimal example in examples/hello_world.rs and compare it with the direct Default case in src/main.rs using rustc 1.87.0. Start by examining how these tuple trait-bound errors are reported. Done means the fake-variadic case identifies the tuple element that lacks the required trait while preserving the existing diagnostic context.

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
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.