Open
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.