rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
96.73k stars 12.5k forks source link

Duplicate error messages when RPIT comes from function whose generics don't satisfy bounds #128756

Open Baptistemontan opened 1 month ago

Baptistemontan commented 1 month ago

Code

I tried this code:

use std::fmt::Display;

fn foo<T: Display>(x: T) -> impl Display {
    x
}

struct Bar; // does'nt impl `Display`

fn main() {
    let x = foo(Bar);
    println!("{}", x);
}

I expected to see this happen:

The error to be reported on the call to foo() only:

error[E0277]: `Bar` doesn't implement `std::fmt::Display`
  --> src\lib.rs:10:17
   |
10 |     let x = foo(Bar);
   |             --- ^^^ `Bar` cannot be formatted with the default formatter
   |             |
   |             required by a bound introduced by this call
   |
   = help: the trait `std::fmt::Display` is not implemented for `Bar`
   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
note: required by a bound in `foo`
  --> src\lib.rs:3:11
   |
3  | fn foo<T: Display>(x: T) -> impl Display {
   |           ^^^^^^^ required by this bound in `foo`

For more information about this error, try `rustc --explain E0277`.

Instead, this happened:

The error is propagated to the use of the println! macro call, without supposing x to implement Display:

error[E0277]: `Bar` doesn't implement `std::fmt::Display`
  --> src\lib.rs:10:17
   |
10 |     let x = foo(Bar);
   |             --- ^^^ `Bar` cannot be formatted with the default formatter
   |             |
   |             required by a bound introduced by this call
   |
   = help: the trait `std::fmt::Display` is not implemented for `Bar`
   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
note: required by a bound in `foo`
  --> src\lib.rs:3:11
   |
3  | fn foo<T: Display>(x: T) -> impl Display {
   |           ^^^^^^^ required by this bound in `foo`

error[E0277]: `Bar` doesn't implement `std::fmt::Display`
  --> src\lib.rs:10:13
   |
10 |     let x = foo(Bar);
   |             ^^^^^^^^ `Bar` cannot be formatted with the default formatter
   |
   = help: the trait `std::fmt::Display` is not implemented for `Bar`
   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
note: required by a bound in `foo`
  --> src\lib.rs:3:11
   |
3  | fn foo<T: Display>(x: T) -> impl Display {
   |           ^^^^^^^ required by this bound in `foo`

error[E0277]: `Bar` doesn't implement `std::fmt::Display`
  --> src\lib.rs:11:15
   |
11 |     println!("{}", x);
   |               ^^ `Bar` cannot be formatted with the default formatter
   |
   = help: the trait `std::fmt::Display` is not implemented for `Bar`
   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
   = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)

For more information about this error, try `rustc --explain E0277`.

Version it worked on

It most recently worked on: Rust 1.77

Version with regression

rustc --version --verbose:

rustc 1.80.0 (051478957 2024-07-21)
binary: rustc
commit-hash: 051478957371ee0084a7c0913941d2a8c4757bb9
commit-date: 2024-07-21
host: x86_64-pc-windows-msvc
release: 1.80.0
LLVM version: 18.1.7

Backtrace

Backtrace

``` ```

Baptistemontan commented 1 month ago

This problem is quite annoying with macros, as it propagate the error through the whole macro generated code and stop pin-pointing the source of the problem.

Baptistemontan commented 1 month ago

The behavior change came with 1.78, I tried 1.78, 1.79, 1.80, 1.81-nightly and 1.82-nightly.

compiler-errors commented 1 month ago

This isn't leaking RPITs. This code has the same error:

use std::fmt::Display;

fn foo<T: Display>(_x: T) -> impl Display {
    ""
}

struct Bar; // doesn't impl `Display`

fn main() {
    let x = foo(Bar);
    println!("{}", x);
}

This just has to do with bad error spans and a lack of error deduplications. The root cause of all 3 of these errors is still the T: Display bound.

Baptistemontan commented 1 month ago

@compiler-errors True, this was a supposition on my part, and I did'nt really know how to name the issue, any suggestion how to rename it ?

compiler-errors commented 1 month ago

This is purely a diagnostics regression so this doesn't need triaging.

I caused this in #122341. I may spend some time looking into how to deduplicate these error messages.