-
Notifications
You must be signed in to change notification settings - Fork 87
Description
The implementation of BorshDeserialize for Box<T> has the following bounds, which I find quite strange:
impl<T, U> BorshDeserialize for Box<T>
where
U: Into<Box<T>> + Borrow<T>,
T: ToOwned<Owned = U> + ?Sized,
T::Owned: BorshDeserialize,
{
// ...
}I guess this has been done with the intention to reuse the impl of BorshDeserialize for String when deserializing Box<str>.
Unfortunately, for Box<[T]>, these bounds require [T]: ToOwned and, thus, T: Clone.
First, this differs from the impl for Vec<T>, which only requires T: BorshDeserialize without the additional bound of T: Clone. Second, this has a nasty interaction with deriving and generic parameters.
So, while the following code compiles:
#[derive(BorshDeserialize)]
pub struct Items<T> {
pub items: Vec<T>,
}The version with Box<[T]> fails to compile:
#[derive(BorshDeserialize)]
pub struct Items<T> {
pub items: Box<[T]>,
}...with the following error:
error[E0277]: the trait bound `[T]: ToOwned` is not satisfied
--> borsh-bug/src/lib.rs:3:10
|
3 | #[derive(BorshDeserialize)]
| ^^^^^^^^^^^^^^^^ the trait `ToOwned` is not implemented for `[T]`, which is required by `Box<[T]>: BorshDeserialize`
|
= note: required for `Box<[T]>` to implement `BorshDeserialize`
= note: this error originates in the derive macro `BorshDeserialize` (in Nightly builds, run with -Z macro-backtrace for more info)
Semantically, however, deserializing Box<[T]> is the same as Vec<T>. Therefore, there should be no differences in bounds.
I believe it would have been much better if there were just separate implementations for sized and unsized types:
impl<T: BorshDeserialize> BorshDeserialize for Box<T> { ... }
impl<T: BorshDeserialize> BorshDeserialize for Box<[T]> { ... }
impl BorshDeserialize for Box<str> { ... }
impl BorshDeserialize for Box<CStr> { ... }
impl BorshDeserialize for Box<OsStr> { ... }But this will be a breaking change if it is changed to this now. Maybe it can at least be special cased in borsh-derive.