Skip to content

#[borsh(skip)] should ask for Default implementation on the field's type, rather than its type parameters #339

Open
@DanikVitek

Description

Current behavior

For a code like this:

#[derive(BorshDeserialize)]
enum I1<K, V, R> {
    B {
        #[borsh(skip)]
        x: HashMap<K, V>,
        y: String,
    },
    C(K, Vec<R>),
}

the generated BorshDeserialize implementation looks like this (path prefixes removed for readability):

impl<K, V, R> BorshDeserialize for I1<K, V, R>
where
    K: BorshDeserialize,
    R: BorshDeserialize,
    K: Default,
    V: Default,
{
    fn deserialize_reader<R: borsh::io::Read>(reader: &mut R) -> Result<Self, borsh::io::Error> {
        let tag = <u8 as BorshDeserialize>::deserialize_reader(reader)?;
        <Self as borsh::de::EnumExt>::deserialize_variant(reader, tag)
    }
}
impl<K, V, R> borsh::de::EnumExt for I1<K, V, R>
where
    K: BorshDeserialize,
    R: BorshDeserialize,
    K: Default,
    V: Default,
{
    fn deserialize_variant<R: borsh::io::Read>(reader: &mut R, variant_tag: u8) -> Result<Self, borsh::io::Error> {
        let mut return_value = if variant_tag == 0u8 {
            I1::B {
                x: Default::default(),
                y: BorshDeserialize::deserialize_reader(reader)?,
            }
        } else if variant_tag == 1u8 {
            I1::C(
                BorshDeserialize::deserialize_reader(reader)?,
                BorshDeserialize::deserialize_reader(reader)?
            )
        } else {
            return Err(borsh::io::Error::new(
                borsh::io::ErrorKind::InvalidData,
                format!("Unexpected variant tag: {:?}", variant_tag)
            ))
        };
        Ok(return_value)
    }
}

Meanwhile, HashMap<K, V> does not require the Default implementation for its type parameters, and yet, the implementation for BorshDeserialize does.
So rather than generating

K: Default,
V: Default,

bound, it should generate

HashMap<K, V>: Default

bound. Same goes if the field would be of any other type, e.g. Option<T> or Vec<T>, as those types do not require Default to be implemented for their type parameters
This can be fixed and released as a patch, because the existing API would not be reduced, but broadened in applicability.

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions