Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apparent duplicated diagnostic note for type mismatch involving type with defaulted type parameter. #101992

Open
zachs18 opened this issue Sep 18, 2022 · 0 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@zachs18
Copy link
Contributor

zachs18 commented Sep 18, 2022

Given the following code: (playground)

pub struct DefaultedParam<A = ()>(A);

fn takes_default_param(_: DefaultedParam) {}
fn calls_default_param_with_ref(x: &DefaultedParam) {
    takes_default_param(x); // (apparent) diagnostic duplication
}
fn returns_default_param(x: DefaultedParam) -> DefaultedParam {
    x; // (apparent) diagnostic duplication
}

pub struct WithParam<A>(A);

fn takes_with_param(_: WithParam<()>) {}
fn calls_with_param_with_ref(x: &WithParam<()>) {
    takes_with_param(x); // somewhat diagnostic duplication
}
fn returns_with_param(x: WithParam<()>) -> WithParam<()> {
    x; // somewhat diagnostic duplication
}

pub struct NoParam;

fn takes_no_param(_: NoParam) {}
fn calls_no_param_with_ref(x: &NoParam) {
    takes_no_param(x); // no diagnostic duplication
}
fn returns_no_param(x: NoParam) -> NoParam {
    x; // no diagnostic duplication
}

The current output is:

Current output

(*_no_param show the ideal diagnostics, *_default_param show cases where the diagnostic appears to the user to be completely duplicated, *_with_param show cases where the diagnostic appears to the user to be somewhat duplicated)

   Compiling rust-default-type-param-changes-diagnostics v0.1.0 (/home/zachary/Programming/mwe/rust-default-type-param-changes-diagnostics)
error[E0308]: mismatched types
 --> src/lib.rs:5:25
  |
5 |     takes_default_param(x); // (apparent) diagnostic duplication
  |     ------------------- ^ expected struct `DefaultedParam`, found `&DefaultedParam`
  |     |
  |     arguments to this function are incorrect
  |
  = note: expected struct `DefaultedParam`
          found reference `&DefaultedParam`
note: function defined here
 --> src/lib.rs:3:4
  |
3 | fn takes_default_param(_: DefaultedParam) {}
  |    ^^^^^^^^^^^^^^^^^^^ -----------------

error[E0308]: mismatched types
 --> src/lib.rs:7:48
  |
7 | fn returns_default_param(x: DefaultedParam) -> DefaultedParam {
  |    ---------------------                       ^^^^^^^^^^^^^^ expected struct `DefaultedParam`, found `()`
  |    |
  |    implicitly returns `()` as its body has no tail or `return` expression
8 |     x; // (apparent) diagnostic duplication
  |      - help: remove this semicolon
  |
  = note: expected struct `DefaultedParam`
          found unit type `()`

error[E0308]: mismatched types
  --> src/lib.rs:15:22
   |
15 |     takes_with_param(x); // somewhat diagnostic duplication
   |     ---------------- ^ expected struct `WithParam`, found `&WithParam<()>`
   |     |
   |     arguments to this function are incorrect
   |
   = note: expected struct `WithParam<()>`
           found reference `&WithParam<()>`
note: function defined here
  --> src/lib.rs:13:4
   |
13 | fn takes_with_param(_: WithParam<()>) {}
   |    ^^^^^^^^^^^^^^^^ ----------------

error[E0308]: mismatched types
  --> src/lib.rs:17:44
   |
17 | fn returns_with_param(x: WithParam<()>) -> WithParam<()> {
   |    ------------------                      ^^^^^^^^^^^^^ expected struct `WithParam`, found `()`
   |    |
   |    implicitly returns `()` as its body has no tail or `return` expression
18 |     x; // somewhat diagnostic duplication
   |      - help: remove this semicolon
   |
   = note: expected struct `WithParam<()>`
           found unit type `()`

error[E0308]: mismatched types
  --> src/lib.rs:25:20
   |
25 |     takes_no_param(x); // no diagnostic duplication
   |     -------------- ^ expected struct `NoParam`, found `&NoParam`
   |     |
   |     arguments to this function are incorrect
   |
note: function defined here
  --> src/lib.rs:23:4
   |
23 | fn takes_no_param(_: NoParam) {}
   |    ^^^^^^^^^^^^^^ ----------

error[E0308]: mismatched types
  --> src/lib.rs:27:36
   |
27 | fn returns_no_param(x: NoParam) -> NoParam {
   |    ----------------                ^^^^^^^ expected struct `NoParam`, found `()`
   |    |
   |    implicitly returns `()` as its body has no tail or `return` expression
28 |     x; // no diagnostic duplication
   |      - help: remove this semicolon

For more information about this error, try `rustc --explain E0308`.
error: could not compile `rust-default-type-param-changes-diagnostics` due to 6 previous errors

Ideally the output should look like:

Ideal output (diff)

Essentailly, have the diagnostics for calls_default_param_with_ref and calls_with_param_with_ref be the same as calls_no_param_with_ref, and the diagnostics for returns_default_param and returns_with_param be the same as returns_no_param (with the corresponding types).

(The diagnostics for *_with_param are technically not duplicated, since the note does give more information (the type parameter) that is not given by the error message. I have included them here since they are still mostly duplicated when all types involved are known, but it's debatable.)

--- err.out	2022-09-18 13:17:40.476817923 -0500
+++ better_err.out	2022-09-17 17:49:25.510427120 -0500
@@ -1,85 +1,75 @@
    Compiling rust-default-type-param-changes-diagnostics v0.1.0 (/home/zachary/Programming/mwe/rust-default-type-param-changes-diagnostics)
 error[E0308]: mismatched types
  --> src/lib.rs:5:25
   |
 5 |     takes_default_param(x); // (apparent) diagnostic duplication
   |     ------------------- ^ expected struct `DefaultedParam`, found `&DefaultedParam`
   |     |
   |     arguments to this function are incorrect
   |
-  = note: expected struct `DefaultedParam`
-          found reference `&DefaultedParam`
 note: function defined here
  --> src/lib.rs:3:4
   |
 3 | fn takes_default_param(_: DefaultedParam) {}
   |    ^^^^^^^^^^^^^^^^^^^ -----------------
 
 error[E0308]: mismatched types
  --> src/lib.rs:7:48
   |
 7 | fn returns_default_param(x: DefaultedParam) -> DefaultedParam {
   |    ---------------------                       ^^^^^^^^^^^^^^ expected struct `DefaultedParam`, found `()`
   |    |
   |    implicitly returns `()` as its body has no tail or `return` expression
 8 |     x; // (apparent) diagnostic duplication
   |      - help: remove this semicolon
-  |
-  = note: expected struct `DefaultedParam`
-          found unit type `()`
 
 error[E0308]: mismatched types
   --> src/lib.rs:15:22
    |
 15 |     takes_with_param(x); // somewhat diagnostic duplication
-   |     ---------------- ^ expected struct `WithParam`, found `&WithParam<()>`
+   |     ---------------- ^ expected struct `WithParam<()>`, found `&WithParam<()>`
    |     |
    |     arguments to this function are incorrect
    |
-   = note: expected struct `WithParam<()>`
-           found reference `&WithParam<()>`
 note: function defined here
   --> src/lib.rs:13:4
    |
 13 | fn takes_with_param(_: WithParam<()>) {}
    |    ^^^^^^^^^^^^^^^^ ----------------
 
 error[E0308]: mismatched types
   --> src/lib.rs:17:44
    |
 17 | fn returns_with_param(x: WithParam<()>) -> WithParam<()> {
-   |    ------------------                      ^^^^^^^^^^^^^ expected struct `WithParam`, found `()`
+   |    ------------------                      ^^^^^^^^^^^^^ expected struct `WithParam<()>`, found `()`
    |    |
    |    implicitly returns `()` as its body has no tail or `return` expression
 18 |     x; // somewhat diagnostic duplication
    |      - help: remove this semicolon
-   |
-   = note: expected struct `WithParam<()>`
-           found unit type `()`
 
 error[E0308]: mismatched types
   --> src/lib.rs:25:20
    |
 25 |     takes_no_param(x); // no diagnostic duplication
    |     -------------- ^ expected struct `NoParam`, found `&NoParam`
    |     |
    |     arguments to this function are incorrect
    |
 note: function defined here
   --> src/lib.rs:23:4
    |
 23 | fn takes_no_param(_: NoParam) {}
    |    ^^^^^^^^^^^^^^ ----------
 
 error[E0308]: mismatched types
   --> src/lib.rs:27:36
    |
 27 | fn returns_no_param(x: NoParam) -> NoParam {
    |    ----------------                ^^^^^^^ expected struct `NoParam`, found `()`
    |    |
    |    implicitly returns `()` as its body has no tail or `return` expression
 28 |     x; // no diagnostic duplication
    |      - help: remove this semicolon
 
 For more information about this error, try `rustc --explain E0308`.
 error: could not compile `rust-default-type-param-changes-diagnostics` due to 6 previous errors

Explanation: When there is a type mismatch where the error message already completely describes the two types, no note is printed (see the NoParam functions above)1. When a type mismatch occurs where the error message does not already completely describe the two types, a note is printed with the two complete types (see the WithParam functions above).

In the case where the only type parameter of a type has a default, and that default is used, this causes the note that is printed to contain the "same" types as the error message2.

(The diagnostics for *_with_param are technically not duplicated, since the note does give more information (the type parameter) that is not given by the error message. I have included them here since they are still mostly duplicated when all types involved are known, but it's debatable.)


I found this difference when adding a defaulted allocator type parameter to String in #101551, which added these notes to the outputs of a lot of UI tests.

The results are the same in all editions, and on stable and nightly (and 1.41.0, but not 1.40.0, which prints the duplicate note even for NoParam 1).

Rust version

Stable:

rustc 1.63.0 (4b91a6ea7 2022-08-08)
binary: rustc
commit-hash: 4b91a6ea7258a947e59c6522cd5898e7c0a6a88f
commit-date: 2022-08-08
host: x86_64-unknown-linux-gnu
release: 1.63.0
LLVM version: 14.0.5

Nightly:

rustc 1.65.0-nightly (750bd1a7f 2022-09-14)
binary: rustc
commit-hash: 750bd1a7ff3e010611b97ee75d30b7cbf5f3a03c
commit-date: 2022-09-14
host: x86_64-unknown-linux-gnu
release: 1.65.0-nightly
LLVM version: 15.0.0

Footnotes

  1. Note that this was introduced 1.41.0: (godbolt.org link). Previously, the note with duplicate information appears to have always been printed. 2

  2. I say "same" because what is printed is the same, but I think the error messages for *_default_param are really saying expected DefaultParam<_>, found ..., and the notes are saying expected DefaultParam<()>, found ....

@zachs18 zachs18 added A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Sep 18, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

1 participant