diff --git a/max-encoded-len/derive/src/lib.rs b/max-encoded-len/derive/src/lib.rs index 34bf42f30cb33..bda30a40a52db 100644 --- a/max-encoded-len/derive/src/lib.rs +++ b/max-encoded-len/derive/src/lib.rs @@ -42,6 +42,16 @@ fn generate_crate_access_2018(def_crate: &str) -> Result { /// Derive `MaxEncodedLen`. #[proc_macro_derive(MaxEncodedLen, attributes(max_encoded_len_crate))] pub fn derive_max_encoded_len(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + parse_and_generate_mel(input, false) +} + +/// Derive `MaxEncodedLen` but do not bound any generics. +#[proc_macro_derive(MaxEncodedLenNoBound, attributes(max_encoded_len_crate))] +pub fn derive_max_encoded_len_no_bound(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + parse_and_generate_mel(input, true) +} + +fn parse_and_generate_mel(input: proc_macro::TokenStream, no_bound: bool) -> proc_macro::TokenStream { let input: DeriveInput = match syn::parse(input) { Ok(input) => input, Err(e) => return e.to_compile_error().into(), @@ -53,7 +63,11 @@ pub fn derive_max_encoded_len(input: proc_macro::TokenStream) -> proc_macro::Tok }; let name = &input.ident; - let generics = add_trait_bounds(input.generics, mel_trait.clone()); + let generics = if no_bound { + input.generics + } else { + add_trait_bounds(input.generics, mel_trait.clone()) + }; let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); let data_expr = data_length_expr(&input.data); diff --git a/max-encoded-len/src/lib.rs b/max-encoded-len/src/lib.rs index e216d3b174159..c2cbc13505f35 100644 --- a/max-encoded-len/src/lib.rs +++ b/max-encoded-len/src/lib.rs @@ -48,6 +48,11 @@ use primitive_types::{H160, H256, H512}; #[cfg(feature = "derive")] pub use max_encoded_len_derive::MaxEncodedLen; +/// Same as `MaxEncodedLen`, but without bounding the generics on the derived type with +/// `MaxEncodedLen`. +#[cfg(feature = "derive")] +pub use max_encoded_len_derive::MaxEncodedLenNoBound; + /// Items implementing `MaxEncodedLen` have a statically known maximum encoded size. /// /// Some containers, such as `BoundedVec`, have enforced size limits and this trait diff --git a/max-encoded-len/tests/max_encoded_len.rs b/max-encoded-len/tests/max_encoded_len.rs index 665ac8fa98a4f..aa928eda79a7d 100644 --- a/max-encoded-len/tests/max_encoded_len.rs +++ b/max-encoded-len/tests/max_encoded_len.rs @@ -19,7 +19,8 @@ #![cfg(feature = "derive")] -use max_encoded_len::MaxEncodedLen; +use max_encoded_len::{MaxEncodedLen, MaxEncodedLenNoBound}; +use std::marker::PhantomData; use codec::{Compact, Encode}; // These structs won't even compile if the macro isn't working right. @@ -76,6 +77,16 @@ fn two_generics_max_length() { ); } +#[derive(Encode, MaxEncodedLenNoBound)] +struct NoBoundGeneric { + one: PhantomData, +} + +#[test] +fn no_bound_generic() { + assert_eq!(NoBoundGeneric::::max_encoded_len(), 0); +} + #[derive(Encode, MaxEncodedLen)] struct UnitStruct;