rust-lang / rust-lang/rust

Applying `do_not_recommend` to tuple implementations causes them to not be decomposed in diagnostics

Open
#142,961 1 comment 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
#[diagnostic::on_unimplemented(note = "this is implemented on tuples of implementors too")]
trait SomeTrait {}

struct AnImplementor;
struct AnotherImplementor;

impl SomeTrait for AnImplementor {}
impl SomeTrait for AnotherImplementor {}

#[diagnostic::do_not_recommend]
impl<T: SomeTrait> SomeTrait for (T,) {}
#[diagnostic::do_not_recommend]
impl<T: SomeTrait, U: SomeTrait> SomeTrait for (T, U) {}
#[diagnostic::do_not_recommend]
impl<T: SomeTrait, U: SomeTrait, V: SomeTrait> SomeTrait for (T, U, V) {}

fn foo(_: impl SomeTrait) {}

pub fn bar() {
    foo((AnImplementor, 5u32));
}
Current output
error[E0277]: the trait bound `(AnImplementor, u32): SomeTrait` is not satisfied
  --> src/lib.rs:20:25
   |
20 |     foo((AnImplementor, 5u32));
   |                         ^^^^ the trait `SomeTrait` is not implemented for `(AnImplementor, u32)`
   |
   = note: this is implemented on tuples of implementors too
   = help: the following other types implement trait `SomeTrait`:
             AnImplementor
             AnotherImplementor
note: required by a bound in `foo`
  --> src/lib.rs:17:16
   |
17 | fn foo(_: impl SomeTrait) {}
   |                ^^^^^^^^^ required by this bound in `foo`
Desired output
error[E0277]: the trait bound `u32: SomeTrait` is not satisfied
  --> src/lib.rs:21:29
   |
21 |         foo((AnImplementor, 5u32));
   |                             ^^^^ the trait `SomeTrait` is not implemented for `u32`
   |
   = note: this is implemented on tuples of implementors too
   = help: the following other types implement trait `SomeTrait`:
             AnImplementor
             AnotherImplementor
note: required by a bound in `foo`
  --> src/lib.rs:18:20
   |
18 |     fn foo(_: impl SomeTrait) {}
   |                    ^^^^^^^^^ required by this bound in `foo`
Rationale and extra context

Playground containing both with/without diagnostic attributes.

For variadic tuple implementations it's not useful to see all the tuples in the "the following other types implement trait", but they're still useful to be decomposed to only inform the user of the specific element of the tuple that is violating the trait impl.

It's interesting to see in the current error message it does point directly to the u32, even though it refers to the type of the whole tuple.

Other cases

Without the diagnostic attributes

trait SomeTrait {}

struct AnImplementor;
struct AnotherImplementor;

impl SomeTrait for AnImplementor {}
impl SomeTrait for AnotherImplementor {}

impl<T: SomeTrait> SomeTrait for (T,) {}
impl<T: SomeTrait, U: SomeTrait> SomeTrait for (T, U) {}
impl<T: SomeTrait, U: SomeTrait, V: SomeTrait> SomeTrait for (T, U, V) {}

fn foo(_: impl SomeTrait) {}

pub fn bar() {
    foo((AnImplementor, 5u32));
}

The output looks like

error[E0277]: the trait bound `u32: SomeTrait` is not satisfied
  --> src/lib.rs:16:25
   |
16 |     foo((AnImplementor, 5u32));
   |     ---                 ^^^^ the trait `SomeTrait` is not implemented for `u32`
   |     |
   |     required by a bound introduced by this call
   |
   = help: the following other types implement trait `SomeTrait`:
             (T, U)
             (T, U, V)
             (T,)
             AnImplementor
             AnotherImplementor
note: required for `(AnImplementor, u32)` to implement `SomeTrait`
  --> src/lib.rs:10:34
   |
10 | impl<T: SomeTrait, U: SomeTrait> SomeTrait for (T, U) {}
   |                       ---------  ^^^^^^^^^     ^^^^^^
   |                       |
   |                       unsatisfied trait bound introduced here
note: required by a bound in `foo`
  --> src/lib.rs:13:16
   |
13 | fn foo(_: impl SomeTrait) {}
   |                ^^^^^^^^^ required by this bound in `foo`
Rust Version
1.90.0-nightly (2025-06-23 706f244db581212cabf2)
Anything else?

No response

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

Start with the Rust reproducer in src/lib.rs and compare diagnostics with and without #[diagnostic::do_not_recommend]. Trace the compiler's trait-diagnostic handling for tuple implementations and this attribute; done means tuple impls stay omitted from the help list while diagnostics identify the unsatisfied tuple element as shown in the desired output.

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
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.