ron icon indicating copy to clipboard operation
ron copied to clipboard

Roundtrip failure when using flatten and newtype together

Open mxgrey opened this issue 11 months ago • 1 comments

I'm working off of the master branch at commit 7466647 attempting to take advantage of the ability to parse maps into structs so that I can use #[serde(flatten)]. It almost works, but I get a strange parsing error during a roundtrip for a particular structure. Here's a minimal reproducible example:

use serde::{Serialize, Deserialize};
use ron::ser::*;

fn main() {
    let data = Outer {
        inner: Inner { new_type: NewType(vec![]) },
    };

    let serialized = to_string_pretty(&data, PrettyConfig::default()).unwrap();
    println!("{serialized}");
    let deserialized: Outer = ron::from_str(&serialized).unwrap();
}

#[derive(Serialize, Deserialize)]
struct Outer {
    #[serde(flatten)] // Without this attribute, everything works
    inner: Inner,
}

#[derive(Serialize, Deserialize)]
struct Inner {
    new_type: NewType,
}

#[derive(Serialize, Deserialize)]
// #[serde(transparent)] // With this attribute, everything works
struct NewType(Vec<u32>);

The error I get is

SpannedError { code: InvalidValueForType { expected: "u32", found: "a sequence" }, position: Position { line: 3, col: 1 } }

Strangely if I add #[serde(transparent)] to NewType or if I remove #[serde(flatten)] from Outer then everything works. In my specific case, I definitely don't mind using #[serde(transparent)], but it seems like the error is probably a bug that's worth addressing.

mxgrey avatar Jan 20 '25 13:01 mxgrey

I think what's going on here is the following:

  1. Non-transparent newtypes in RON are serialised like single-member tuples (so far so good)
  2. Deserialising a flattened struct invokes the deserialize_any pathway, which gets the equivalent of Seq([Seq([])]) (so far so good)
  3. Newtype asks serde's internal FlatMapDeserializer to deserialize_newtype here: https://github.com/serde-rs/serde/blob/master/serde/src/private/de.rs#L2584 (so far so good)
  4. This method doesn't check for single-tuples (even though newtypes accept them in serde) and just forwards directly (bad)
  5. We're now trying to deserialize Vec from Seq([Seq([])]) (error)

In the end, this is blocked on https://github.com/serde-rs/serde/issues/1183, which may hopefully get a fix in the future, allowing formats like RON to use their own rules during any-content deserialisation.

juntyr avatar Mar 23 '25 07:03 juntyr