Description
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
-
Note that this was introduced 1.41.0: (godbolt.org link). 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 sayingexpected DefaultParam<_>, found ...
, and the notes are sayingexpected DefaultParam<()>, found ...
. ↩