Skip to content

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

Open
@Nemo157

Description

@Nemo157

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions