Skip to content

Unable to use Compact on generic T: HasCompact #218

Closed
@kianenigma

Description

@kianenigma

The below code demonstrates the problem. It is an attempt at doing a custom Encode implementation of a complex type which takes advantage of the fact that the internals of the complex type are all compact-encodable.

use parity_scale_codec::{Encode, Decode, HasCompact, Compact, CompactAs};

#[derive(Default)]
struct Solution<V, T, W> {
	votes1: Vec<(V, T)>,
	votes2: Vec<(V, (T, W), T)>,
	votes3: Vec<(V, [(T, W); 2usize], T)>,
}

#[derive(Default)]
struct BareSolution {
	votes1: Vec<(u32, u16)>,
	votes2: Vec<(u32, (u16, u64), u16)>,
	votes3: Vec<(u32, [(u16, u64); 2usize], u16)>,
}

// This works fine
impl Encode for BareSolution {
	fn encode(&self) -> Vec<u8> {
		let mut r = vec![];
		self.votes1
			.iter()
			.map(|(v, t)| (<Compact<u32>>::from(*v), <Compact<u16>>::from(*t)))
			.for_each(|(v, t)| {
				v.encode_to(&mut r);
				t.encode_to(&mut r);
			});
		r
	}
}

// This will not work.
impl<V: HasCompact + CompactAs + Copy, T: HasCompact + CompactAs + Copy, W: HasCompact + CompactAs + Copy> Encode for Solution<V, T, W> {
	fn encode(&self) -> Vec<u8> {
		let mut r = vec![];
		self.votes1
			.iter()
			.map(|(v, t)| (Compact::from(*v), Compact::from(*t)))
			.for_each(|(v, t)| {
				// will not work because the compiler fails to identify `impl Encode` for `V`
				// v.encode_to(&mut r);
				// will trigger recursive derive error.
				// <Compact<T> as Encode>::encode_to(&t, &mut r);
			});
		r
	}
}

Looking at the code, it seems to be that <Comact<T> as Encode> should work fine as long as T: HasCompact + CompactAs, based on:

impl<T> Encode for Compact<T>
where
for<'a> CompactRef<'a, T>: Encode,
{

and

impl<'a, T> Encode for CompactRef<'a, T>
where
T: CompactAs,
for<'b> CompactRef<'b, T::As>: Encode,

Albeit I might be missing something.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions