To some extent you got different error messages because your user code was different. You didn't show the code, but I think you wrote let a1 = nex::A1((), ());
, let a4 = nex::A4 {};
, etc, so it is no wonder that the error message are different.
I wrote this:
let a0 = A0 {};
let a1 = A1 {};
let a2 = A2 {};
let a3 = A3 {};
let a4 = A4 {};
let a5 = A5 {};
let a6 = A6 {};
and got the following errors:
error: cannot construct `rust_test::A0` with struct literal syntax due to private fields
--> src/main.rs:4:14
|
4 | let a0 = A0 {};
| ^^
|
= note: ... and other private field `0` that was not provided
error: cannot construct `rust_test::A1` with struct literal syntax due to private fields
--> src/main.rs:5:14
|
5 | let a1 = A1 {};
| ^^
|
= note: ... and other private fields `0` and `1` that were not provided
error[E0639]: cannot create non-exhaustive struct using struct expression
--> src/main.rs:6:14
|
6 | let a2 = A2 {};
| ^^^^^
error[E0639]: cannot create non-exhaustive struct using struct expression
--> src/main.rs:7:14
|
7 | let a3 = A3 {};
| ^^^^^
error: cannot construct `rust_test::A3` with struct literal syntax due to private fields
--> src/main.rs:7:14
|
7 | let a3 = A3 {};
| ^^
|
= note: ... and other private field `0` that was not provided
error[E0639]: cannot create non-exhaustive struct using struct expression
--> src/main.rs:8:14
|
8 | let a4 = A4 {};
| ^^^^^
error: cannot construct `rust_test::A5` with struct literal syntax due to private fields
--> src/main.rs:9:14
|
9 | let a5 = A5 {};
| ^^
|
= note: ... and other private field `a` that was not provided
error[E0639]: cannot create non-exhaustive struct using struct expression
--> src/main.rs:10:14
|
10 | let a6 = A6 {};
| ^^^^^
error: cannot construct `rust_test::A6` with struct literal syntax due to private fields
|
10 | let a6 = A6 {};
| ^^
|
= note: ... and other private field `a` that was not provided
There are only two different errors here, which makes sense if you accept the idea that non_exhaustive
is different API from private fields. I still don't quite buy this, but I accept that there is perhaps a rationale for thinking of non_exhaustive
differently.
In cases like A6 where there is both non-exhaustive and private fields, I don't think it's really necessary to talk about non-exhaustive because at this point the non-exhaustive really doesn't matter to you any more.
There are additional notes at the bottom about specific private field names. The notes are weird though, for instance it says: "and other private field a
that was not provided" when actually it's the only private field. Why "and other"?
I think that note is misleading -- it suggests that I should be providing a
when it's not going to work if I do. I think it would be better to simply tell me I cannot construct the struct because the definition is opaque, rather than telling me which private fields are missing.
Next I changed the code to try to construct with a specific private field:
let a0 = A0 { a: () };
let a1 = A1 { a: () };
let a2 = A2 { a: () };
let a3 = A3 { a: () };
let a4 = A4 { a: () };
let a5 = A5 { a: () };
let a6 = A6 { a: () };
Now I get:
error[E0560]: struct `rust_test::A0` has no field named `a`
--> src/main.rs:4:19
|
4 | let a0 = A0 { a: () };
| ^ field does not exist
|
::: /home/tomek/code/rust-test/src/lib.rs:1:12
|
1 | pub struct A0(());
| -- `rust_test::A0` defined here
|
help: `rust_test::A0` is a tuple struct, use the appropriate syntax
|
4 | let a0 = rust_test::A0(/* fields */);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~
error[E0560]: struct `rust_test::A1` has no field named `a`
--> src/main.rs:5:19
|
5 | let a1 = A1 { a: () };
| ^ field does not exist
|
::: /home/tomek/code/rust-test/src/lib.rs:3:12
|
3 | pub struct A1((), ());
| -- `rust_test::A1` defined here
|
help: `rust_test::A1` is a tuple struct, use the appropriate syntax
|
5 | let a1 = rust_test::A1(/* fields */);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~
error[E0639]: cannot create non-exhaustive struct using struct expression
--> src/main.rs:6:14
|
6 | let a2 = A2 { a: () };
| ^^^^^^^^^^^^
error[E0560]: struct `rust_test::A2` has no field named `a`
--> src/main.rs:6:19
|
6 | let a2 = A2 { a: () };
| ^ `rust_test::A2` does not have this field
error[E0639]: cannot create non-exhaustive struct using struct expression
--> src/main.rs:7:14
|
7 | let a3 = A3 { a: () };
| ^^^^^^^^^^^^
::: /home/tomek/code/rust-test/src/lib.rs:9:12
|
9 | pub struct A3(());
| -- `rust_test::A3` defined here
|
help: `rust_test::A3` is a tuple struct, use the appropriate syntax
|
7 | let a3 = rust_test::A3(/* fields */);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~
error[E0639]: cannot create non-exhaustive struct using struct expression
--> src/main.rs:8:14
|
8 | let a4 = A4 { a: () };
| ^^^^^^^^^^^^
error[E0560]: struct `rust_test::A4` has no field named `a`
--> src/main.rs:8:19
|
8 | let a4 = A4 { a: () };
| ^ `rust_test::A4` does not have this field
error[E0639]: cannot create non-exhaustive struct using struct expression
--> src/main.rs:10:14
|
10 | let a6 = A6 { a: () };
| ^^^^^^^^^^^^
Still only two types of errors, but I didn't get an error for A5, I guess the compiler didn't get to that. If I comment out all the lines other than let a5
I get the third type of error:
error[E0451]: field `a` of struct `rust_test::A5` is private
--> src/main.rs:9:19
|
9 | let a5 = A5 { a: () };
| ^^^^^ private field
The notes at the bottom of errors for A0, A1 and A3 telling me to use tuple syntax are misleading and shouldn't be there. The compiler is advising me to use syntax that is not going to work!!
I think these errors would be a lot better if they all simply told me that I cannot use the struct expression at all because the type is opaque to me, rather than advising me about trying to use a different syntax (that will not work anyway) or telling me which private fields are missing (which again won't work).
In the case of A5 you could argue that maybe the mistake is in the other crate and the field shouldn't be private -- perhaps. Still I think it could be the same error message about trying to build an opaque type, with maybe an extra note at the bottom mentioning that perhaps the field in the other crate shouldn't be private (except if the other crate is std
, in which case there is no point writing that).