dtolnay/serde-yaml

Singleton Map Recursion fails to compile due to recursion

Opened this issue · 0 comments

Hi!

I'm currently using rasn to parse ASN1. To verify outputs of various input files, I'm using serde-yaml to convert the final type into a string that I can store in files and then commit to the repository.

I'm hitting this error when trying to use the recursive version of a singleton map:

error: reached the recursion limit while instantiating `_::_serde::ser::impls::<impl Serialize for &singleton_map_recursive::SingletonMapRecursive<&singleton_map_recursive::SingletonMapRecursive<&...>>>::serialize::<...>`
   --> /home/btr/.cargo/registry/src/github.com-1ecc6299db9ec823/serde_yaml-0.9.32/src/with.rs:981:13
    |
981 | /             self.delegate.serialize(SingletonMapRecursive {
982 | |                 delegate: serializer,
983 | |             })
    | |______________^
    |
note: `_::_serde::ser::impls::<impl Serialize for &'a T>::serialize` defined here
   --> /home/btr/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.197/src/ser/impls.rs:506:1
    |
506 | / deref_impl! {
507 | |     <'a, T: ?Sized> Serialize for &'a T where T: Serialize
508 | | }
    | |_^
    = note: the full type name has been written to '/home/btr/Projects/_unimportant_/lib/target/debug/deps/_unimportant_-df951b3711978b56.long-type.txt'
    = note: this error originates in the macro `deref_impl` (in Nightly builds, run with -Z macro-backtrace for more info)

The full type mentioned in the error looks like this:

_::_serde::ser::impls::<impl Serialize for &singleton_map_recursive::SingletonMapRecursive<&singleton_map_recursive::SingletonMapRecursive<&singleton_map_recursive::SingletonMapRecursive<&singleton_map_recursive::SingletonMapRecursive<&singleton_map_recursive::SingletonMapRecursive<&singleton_map_recursive::SingletonMapRecursive<&iso_9506_mms_1::_::<impl Serialize for TypeSpecification>::serialize::__SerializeWith<'_>>>>>>>>::serialize::<singleton_map_recursive::SingletonMapRecursive<singleton_map_recursive::SingletonMapRecursive<singleton_map_recursive::SingletonMapRecursive<&mut serde_yaml::Serializer<&mut Vec<u8>>>>>>

The types involved in this recursion currently look like this:

/// ASN1:
/// See ISO 9506-1 14.2.1
#[derive(AsnType, Clone, Debug, Decode)]
#[cfg_attr(feature = "serde", derive(Serialize))]
#[rasn(choice)]
pub(crate) enum TypeDescription {
    #[rasn(tag(1))]
    Array(Box<Array>),
    #[rasn(tag(2))]
    Structure(Structure),
    #[rasn(tag(3))]
    Boolean(()),
    #[rasn(tag(4))]
    BitString(Integer32),
    #[rasn(tag(5))]
    Integer(Unsigned8),
    #[rasn(tag(6))]
    Unsigned(Unsigned8),
    #[rasn(tag(9))]
    OctetString(Integer32),
    #[rasn(tag(10))]
    VisibleString(Integer32),
    #[rasn(tag(11))]
    GeneralizedTime(()),
    #[rasn(tag(12))]
    BinaryTime(bool),
    #[rasn(tag(13))]
    BCD(Unsigned8),
    #[rasn(tag(15))]
    ObjectID(()),
}

#[derive(AsnType, Clone, Debug, Decode)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub(crate) struct Structure {
    #[rasn(tag(0), default(false))]
    packed: bool,
    #[rasn(tag(1))]
    components: SequenceOf<Component>,
}

#[derive(AsnType, Clone, Debug, Decode)]
#[cfg_attr(feature = "serde", derive(Serialize))]
struct Component {
    #[rasn(tag(0))]
    component_name: Option<Identifier>,
    #[rasn(tag(explicit(1)))]
    component_type: TypeSpecification,
}

#[derive(AsnType, Clone, Debug, Decode)]
#[cfg_attr(feature = "serde", derive(Serialize))]
#[rasn(choice)]
pub(crate) enum TypeSpecification {
    #[rasn(tag(explicit(0)))]
    Name(ObjectName),
    #[cfg_attr(
        feature = "serde",
        serde(with = "serde_yaml::with::singleton_map_recursive")
    )]
    Description(TypeDescription),
}

Also a minimal example would probably look like this? I can't seem to reproduce the above error in the playground.

#[derive(Clone, Debug, Serialize)]
enum TypeDescription {
    Structure(Structure),
}

#[derive(Clone, Debug, Serialize)]
struct Structure {
    components: Vec<Component>,
}

#[derive(Clone, Debug, Serialize)]
struct Component {
    component_type: TypeSpecification,
}

#[derive(Clone, Debug, Serialize)]
enum TypeSpecification {
    #[serde(with = "serde_yaml::with::singleton_map_recursive")]
    Description(TypeDescription),
}

I know there's recursion handling in runtime code (probably not related to this), but this is something that fails to compile, and something like the recursion_limit attribute does not help.

I'm not sure if there's even a solution for this. In the meantime I'm using just "singleton_map", but obviously my output is missing data. Not optimal, but not the worst for now, as my dbg!() output told me the result is good as it is.

Any advice on this? Is there maybe a fix? Anything I can do?