rust-lang / rust-lang/rust

`#[diagnostic::on_unimplemented]` fails to trigger when certain impls are present

Open
#130,563 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

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

Description

Consider the following code:

#[diagnostic::on_unimplemented(note = "A custom Foo message!")]
trait Foo {}

#[diagnostic::on_unimplemented(note = "A custom Bar message!")]
trait Bar {}

impl<'a, T> Bar for &'a T {}

fn takes_foo<T: Foo>(_t: T) {}
fn takes_bar<T: Bar>(_t: T) {}

fn main() {
    takes_foo(());
    takes_bar(());
}

I would expect the #[diagnostic::on_unimplemented] note to be present in the error output for both calls in main. However, what I get instead is:

error[E0277]: the trait bound `(): Foo` is not satisfied
  --> src/main.rs:13:15
   |
13 |     takes_foo(());
   |     --------- ^^ the trait `Foo` is not implemented for `()`
   |     |
   |     required by a bound introduced by this call
   |
   = note: A custom Foo message!
help: this trait has no implementations, consider adding one
  --> src/main.rs:2:1
   |
2  | trait Foo {}
   | ^^^^^^^^^
note: required by a bound in `takes_foo`
  --> src/main.rs:9:17
   |
9  | fn takes_foo<T: Foo>(_t: T) {}
   |                 ^^^ required by this bound in `takes_foo`

error[E0277]: the trait bound `(): Bar` is not satisfied
  --> src/main.rs:14:15
   |
14 |     takes_bar(());
   |     --------- ^^ the trait `Bar` is not implemented for `()`
   |     |
   |     required by a bound introduced by this call
   |
note: required by a bound in `takes_bar`
  --> src/main.rs:10:17
   |
10 | fn takes_bar<T: Bar>(_t: T) {}
   |                 ^^^ required by this bound in `takes_bar`
help: consider borrowing here
   |
14 |     takes_bar(&());
   |               +

While the custom note is emitted for Foo, it's not for Bar. The culprit seems to be the impl of Bar for &T, which leads rustc down the wrong path and has it suggest only that borrowing is an option. However, that's not always the right suggestion.

cc https://github.com/google/zerocopy/issues/1296, https://github.com/google/zerocopy/pull/1682

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 reduced Rust program in the issue and trace rustc's handling of #[diagnostic::on_unimplemented] when the Bar implementation for &T is present. Compare the diagnostics for Foo and Bar; done means the Bar error includes its custom note and does not incorrectly prioritize the borrowing suggestion.

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.