serde
serde copied to clipboard
Fix incorrect representation of tuples with skipped fields
This PR fixes #2105 and give some insights about the current situation with skipped fields.
You can see what changed in the generated code by running the following commands:
- place skip.txt into
test_suite/tests
folder and change it extension to.rs
- run the following command:
where...\serde\test_suite> cargo expand --all-features --test skip > skip-N.rs
N
is some number.
When commit message contains words "Changes in generated code" that means that output of the command above was changed. I recommend to diff it against the previous result and explore the difference. There will be 4 files -- baseline and three changed.
Overall changes over all commits:
-
Tuple1as0
,Tuple1as0Default
,Tuple1as0With
:- removed
visit_newtype_struct
- changed
*_newtype_struct
->*_tuple_struct(0)
- removed
-
Tuple2as1
,Tuple2as1Default
,Tuple2as1With
:- added
visit_newtype_struct
- added
The table below summarizes the current behavior and the new behavior, introduced in this PR. Empty cells in the last column means that the behavior wasn't changed.
The behavior columns shows which methods are used to serialize or deserialize a type. The number in parenthesis is a count of fields which passed to the corresponding method.
Code | Current behavior | Fixed behavior |
---|---|---|
Unit representations | ||
|
| |
Tuple representations | ||
|
|
:information_source: It would be better to use Unit representation (see below) |
|
| |
|
| |
#2105 |
|
|
|
|
:information_source: It would be better to use Unit representation (see below) |
|
|
|
Struct representations | ||
|
| |
|
| |
|
| |
|
|
Enum variant representations
The following changes also was implemented by I plan to ship them in separate PR due to some debating changes. I left my finding here to have the overall picture about skipped fields in one place.
The first debating change is to how to represent tuple(0)
tuples? Should we represent them as a sequences with zero fields, or as a unit structs? Motivation for the unit structs is that that is the only way to skip all fields in a tuple and still represent it as a unit. This is currently done for Enum::Tuple1as0
, but only for it. Enum::Tuple2as0
no longer follows this agreement as well as all tuple structs, which introduces more confusion. I am inclined to this option, since to have an always empty sequence is somewhat strange.
The second debating change, maybe we should make the behavior configurable? Introduce a new attribute like #[serde(tuple)]
to produce tuple(0)
and tuple(1)
forms from TupleXas0
and TupleXas1
tuples?
Code | Current behavior | Suggested behavior |
---|---|---|
Enum::Unit representations | ||
|
| |
Enum::Tuple representations | ||
|
|
|
|
| |
|
| |
|
| |
|
|
|
#2224 |
|
|
Enum::Struct representations | ||
|
| |
|
| |
|
| |
|
|
List of inconsistencies
As I said before, the current behavior contains a bunch of inconsistencies.
For example, an enum tuple variant with zero fields represented as a tuple with zero fields, but tuple variant with one skipped field represented as a unit. At the same time, tuple variant with 2 or more fields, all skipped, again represented as a tuple with zero fields. The same is applied to tuples with one effective field -- sometimes it is represented as a newtype, sometimes as a tuple with one field. I suggest to unify behavior across all cases that I summarized in the following table:
Value | Serialized form | Suggested form |
---|---|---|
Types with zero fields in serialized form | ||
| Represented as a tuple with zero fields | unit |
| :warning: Incorrectly represented as a newtype struct (bug #2105) | unit |
| Represented as a tuple with zero fields | unit |
Types with 1 field in serialized form | ||
| Represented as a newtype x | |
| :exclamation: Represented as a tuple with 1 field | newtype |
Enum variants with zero fields in serialized form | ||
| Represented as a tuple with zero fields | unit |
| :exclamation: Represented as a unit struct | |
| Represented as a tuple with zero fields | unit |
Enum variants with 1 field in serialized form | ||
| Represented as a newtype x | |
| :exclamation: Represented as a tuple with 1 field (#2224) | newtype |
Legend:
- :warning: Bugs that leads to compilation errors
- :exclamation: Inconsistency in a block of similar table rows