Repository: rust
Issue: Apparent duplicated diagnostic note for type mismatch involving type with defaulted type parameter.
Labels: A-diagnostics,T-compiler

<!--
Thank you for filing a bug report! 🐛 Please provide a short summary of the bug,
along with any information you feel relevant to replicating the bug.

If you cannot produce a minimal reproduction case (something that would work in
isolation), please provide the steps or even link to a repository that causes
the problematic output to occur.
-->

Given the following code: ([playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=15e3017cac972e1fdb1c0614e56b56a1))

```rust
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:

<details><summary>Current output</summary>

(`*_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

```

</details>

<!-- The following is not always necessary. -->
Ideally the output should look like:

<details><summary>Ideal output (diff)</summary>

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.)

```diff
--- 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

```

</details>

<!--
If the problem is not self-explanatory, please provide a rationale for the
change.
-->

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 message[^2].

(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.

<!--
If dramatically different output is caused by small changes, consider also
adding them here.

If you're using the stable version of the compiler, you should also check if the
bug also exists in the beta or nightly versions. The output might also be
different depending on the Edition.
-->

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]).

<details><summary>Rust version</summary>

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
```
</details>

[^1]: Note that this was introduced 1.41.0: ([godbolt.org link](https://rust.godbolt.org/z/voKhs56Gj)). Previously, the note with duplicate information appears to have always been printed.
[^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 ...`.