Struct synstructure::Structure
source · pub struct Structure<'a> { /* private fields */ }
Expand description
A wrapper around a syn::DeriveInput
which provides utilities for creating
custom derive trait implementations.
Implementations§
source§impl<'a> Structure<'a>
impl<'a> Structure<'a>
sourcepub fn new(ast: &'a DeriveInput) -> Self
pub fn new(ast: &'a DeriveInput) -> Self
Create a new Structure
with the variants and fields from the passed-in
DeriveInput
.
Panics
This method will panic if the provided AST node represents an untagged union.
sourcepub fn try_new(ast: &'a DeriveInput) -> Result<Self>
pub fn try_new(ast: &'a DeriveInput) -> Result<Self>
Create a new Structure
with the variants and fields from the passed-in
DeriveInput
.
Unlike Structure::new
, this method does not panic if the provided AST
node represents an untagged union.
sourcepub fn variants(&self) -> &[VariantInfo<'a>]
pub fn variants(&self) -> &[VariantInfo<'a>]
Returns a slice of the variants in this Structure.
sourcepub fn variants_mut(&mut self) -> &mut [VariantInfo<'a>]
pub fn variants_mut(&mut self) -> &mut [VariantInfo<'a>]
Returns a mut slice of the variants in this Structure.
sourcepub fn ast(&self) -> &'a DeriveInput
pub fn ast(&self) -> &'a DeriveInput
Returns a reference to the underlying syn
AST node which this
Structure
was created from.
sourcepub fn omitted_variants(&self) -> bool
pub fn omitted_variants(&self) -> bool
True if any variants were omitted due to a filter_variants
call.
sourcepub fn each<F, R>(&self, f: F) -> TokenStreamwhere
F: FnMut(&BindingInfo<'_>) -> R,
R: ToTokens,
pub fn each<F, R>(&self, f: F) -> TokenStreamwhere F: FnMut(&BindingInfo<'_>) -> R, R: ToTokens,
Runs the passed-in function once for each bound field, passing in a BindingInfo
.
and generating match
arms which evaluate the returned tokens.
This method will ignore variants or fields which are ignored through the
filter
and filter_variant
methods.
Example
let di: syn::DeriveInput = syn::parse_quote! {
enum A {
B(i32, i32),
C(u32),
}
};
let s = Structure::new(&di);
assert_eq!(
s.each(|bi| quote!(println!("{:?}", #bi))).to_string(),
quote!{
A::B(ref __binding_0, ref __binding_1,) => {
{ println!("{:?}", __binding_0) }
{ println!("{:?}", __binding_1) }
}
A::C(ref __binding_0,) => {
{ println!("{:?}", __binding_0) }
}
}.to_string()
);
sourcepub fn fold<F, I, R>(&self, init: I, f: F) -> TokenStreamwhere
F: FnMut(TokenStream, &BindingInfo<'_>) -> R,
I: ToTokens,
R: ToTokens,
pub fn fold<F, I, R>(&self, init: I, f: F) -> TokenStreamwhere F: FnMut(TokenStream, &BindingInfo<'_>) -> R, I: ToTokens, R: ToTokens,
Runs the passed-in function once for each bound field, passing in the
result of the previous call, and a BindingInfo
. generating match
arms which evaluate to the resulting tokens.
This method will ignore variants or fields which are ignored through the
filter
and filter_variant
methods.
If a variant has been ignored, it will return the init
value.
Example
let di: syn::DeriveInput = syn::parse_quote! {
enum A {
B(i32, i32),
C(u32),
}
};
let s = Structure::new(&di);
assert_eq!(
s.fold(quote!(0), |acc, bi| quote!(#acc + #bi)).to_string(),
quote!{
A::B(ref __binding_0, ref __binding_1,) => {
0 + __binding_0 + __binding_1
}
A::C(ref __binding_0,) => {
0 + __binding_0
}
}.to_string()
);
sourcepub fn each_variant<F, R>(&self, f: F) -> TokenStreamwhere
F: FnMut(&VariantInfo<'_>) -> R,
R: ToTokens,
pub fn each_variant<F, R>(&self, f: F) -> TokenStreamwhere F: FnMut(&VariantInfo<'_>) -> R, R: ToTokens,
Runs the passed-in function once for each variant, passing in a
VariantInfo
. and generating match
arms which evaluate the returned
tokens.
This method will ignore variants and not bind fields which are ignored
through the filter
and filter_variant
methods.
Example
let di: syn::DeriveInput = syn::parse_quote! {
enum A {
B(i32, i32),
C(u32),
}
};
let s = Structure::new(&di);
assert_eq!(
s.each_variant(|v| {
let name = &v.ast().ident;
quote!(println!(stringify!(#name)))
}).to_string(),
quote!{
A::B(ref __binding_0, ref __binding_1,) => {
println!(stringify!(B))
}
A::C(ref __binding_0,) => {
println!(stringify!(C))
}
}.to_string()
);
sourcepub fn filter<F>(&mut self, f: F) -> &mut Selfwhere
F: FnMut(&BindingInfo<'_>) -> bool,
pub fn filter<F>(&mut self, f: F) -> &mut Selfwhere F: FnMut(&BindingInfo<'_>) -> bool,
Filter the bindings created by this Structure
object. This has 2 effects:
-
The bindings will no longer appear in match arms generated by methods on this
Structure
or its subobjects. -
Impl blocks created with the
bound_impl
orunsafe_bound_impl
method only consider type parameters referenced in the types of non-filtered fields.
Example
let di: syn::DeriveInput = syn::parse_quote! {
enum A {
B{ a: i32, b: i32 },
C{ a: u32 },
}
};
let mut s = Structure::new(&di);
s.filter(|bi| {
bi.ast().ident == Some(quote::format_ident!("a"))
});
assert_eq!(
s.each(|bi| quote!(println!("{:?}", #bi))).to_string(),
quote!{
A::B{ a: ref __binding_0, .. } => {
{ println!("{:?}", __binding_0) }
}
A::C{ a: ref __binding_0, } => {
{ println!("{:?}", __binding_0) }
}
}.to_string()
);
sourcepub fn add_where_predicate(&mut self, pred: WherePredicate) -> &mut Self
pub fn add_where_predicate(&mut self, pred: WherePredicate) -> &mut Self
Specify additional where predicate bounds which should be generated by
impl-generating functions such as gen_impl
, bound_impl
, and
unsafe_bound_impl
.
Example
let di: syn::DeriveInput = syn::parse_quote! {
enum A<T, U> {
B(T),
C(Option<U>),
}
};
let mut s = Structure::new(&di);
// Add an additional where predicate.
s.add_where_predicate(syn::parse_quote!(T: std::fmt::Display));
assert_eq!(
s.bound_impl(quote!(krate::Trait), quote!{
fn a() {}
}).to_string(),
quote!{
#[allow(non_upper_case_globals)]
#[doc(hidden)]
const _DERIVE_krate_Trait_FOR_A: () = {
extern crate krate;
impl<T, U> krate::Trait for A<T, U>
where T: std::fmt::Display,
T: krate::Trait,
Option<U>: krate::Trait,
U: krate::Trait
{
fn a() {}
}
};
}.to_string()
);
sourcepub fn add_bounds(&mut self, mode: AddBounds) -> &mut Self
pub fn add_bounds(&mut self, mode: AddBounds) -> &mut Self
Specify which bounds should be generated by impl-generating functions
such as gen_impl
, bound_impl
, and unsafe_bound_impl
.
The default behaviour is to generate both field and generic bounds from type parameters.
Example
let di: syn::DeriveInput = syn::parse_quote! {
enum A<T, U> {
B(T),
C(Option<U>),
}
};
let mut s = Structure::new(&di);
// Limit bounds to only generics.
s.add_bounds(AddBounds::Generics);
assert_eq!(
s.bound_impl(quote!(krate::Trait), quote!{
fn a() {}
}).to_string(),
quote!{
#[allow(non_upper_case_globals)]
#[doc(hidden)]
const _DERIVE_krate_Trait_FOR_A: () = {
extern crate krate;
impl<T, U> krate::Trait for A<T, U>
where T: krate::Trait,
U: krate::Trait
{
fn a() {}
}
};
}.to_string()
);
sourcepub fn filter_variants<F>(&mut self, f: F) -> &mut Selfwhere
F: FnMut(&VariantInfo<'_>) -> bool,
pub fn filter_variants<F>(&mut self, f: F) -> &mut Selfwhere F: FnMut(&VariantInfo<'_>) -> bool,
Filter the variants matched by this Structure
object. This has 2 effects:
-
Match arms destructuring these variants will no longer be generated by methods on this
Structure
-
Impl blocks created with the
bound_impl
orunsafe_bound_impl
method only consider type parameters referenced in the types of fields in non-fitered variants.
Example
let di: syn::DeriveInput = syn::parse_quote! {
enum A {
B(i32, i32),
C(u32),
}
};
let mut s = Structure::new(&di);
s.filter_variants(|v| v.ast().ident != "B");
assert_eq!(
s.each(|bi| quote!(println!("{:?}", #bi))).to_string(),
quote!{
A::C(ref __binding_0,) => {
{ println!("{:?}", __binding_0) }
}
_ => {}
}.to_string()
);
sourcepub fn remove_variant(&mut self, idx: usize) -> &mut Self
pub fn remove_variant(&mut self, idx: usize) -> &mut Self
sourcepub fn bind_with<F>(&mut self, f: F) -> &mut Selfwhere
F: FnMut(&BindingInfo<'_>) -> BindStyle,
pub fn bind_with<F>(&mut self, f: F) -> &mut Selfwhere F: FnMut(&BindingInfo<'_>) -> BindStyle,
Updates the BindStyle
for each of the passed-in fields by calling the
passed-in function for each BindingInfo
.
Example
let di: syn::DeriveInput = syn::parse_quote! {
enum A {
B(i32, i32),
C(u32),
}
};
let mut s = Structure::new(&di);
s.bind_with(|bi| BindStyle::RefMut);
assert_eq!(
s.each(|bi| quote!(println!("{:?}", #bi))).to_string(),
quote!{
A::B(ref mut __binding_0, ref mut __binding_1,) => {
{ println!("{:?}", __binding_0) }
{ println!("{:?}", __binding_1) }
}
A::C(ref mut __binding_0,) => {
{ println!("{:?}", __binding_0) }
}
}.to_string()
);
sourcepub fn binding_name<F>(&mut self, f: F) -> &mut Selfwhere
F: FnMut(&Field, usize) -> Ident,
pub fn binding_name<F>(&mut self, f: F) -> &mut Selfwhere F: FnMut(&Field, usize) -> Ident,
Updates the binding name for each fo the passed-in fields by calling the
passed-in function for each BindingInfo
.
The function will be called with the BindingInfo
and its index in the
enclosing variant.
The default name is __binding_{}
where {}
is replaced with an
increasing number.
Example
let di: syn::DeriveInput = syn::parse_quote! {
enum A {
B{ a: i32, b: i32 },
C{ a: u32 },
}
};
let mut s = Structure::new(&di);
s.binding_name(|bi, i| bi.ident.clone().unwrap());
assert_eq!(
s.each(|bi| quote!(println!("{:?}", #bi))).to_string(),
quote!{
A::B{ a: ref a, b: ref b, } => {
{ println!("{:?}", a) }
{ println!("{:?}", b) }
}
A::C{ a: ref a, } => {
{ println!("{:?}", a) }
}
}.to_string()
);
sourcepub fn referenced_ty_params(&self) -> Vec<&'a Ident>
pub fn referenced_ty_params(&self) -> Vec<&'a Ident>
Returns a list of the type parameters which are refrenced in the types of non-filtered fields / variants.
Caveat
If the struct contains any macros in type position, all parameters will be considered bound. This is because we cannot determine which type parameters are bound by type macros.
Example
let di: syn::DeriveInput = syn::parse_quote! {
enum A<T, U> {
B(T, i32),
C(Option<U>),
}
};
let mut s = Structure::new(&di);
s.filter_variants(|v| v.ast().ident != "C");
assert_eq!(
s.referenced_ty_params(),
&["e::format_ident!("T")]
);
sourcepub fn add_impl_generic(&mut self, param: GenericParam) -> &mut Self
pub fn add_impl_generic(&mut self, param: GenericParam) -> &mut Self
Adds an impl<>
generic parameter.
This can be used when the trait to be derived needs some extra generic parameters.
Example
let di: syn::DeriveInput = syn::parse_quote! {
enum A<T, U> {
B(T),
C(Option<U>),
}
};
let mut s = Structure::new(&di);
let generic: syn::GenericParam = syn::parse_quote!(X: krate::AnotherTrait);
assert_eq!(
s.add_impl_generic(generic)
.bound_impl(quote!(krate::Trait<X>),
quote!{
fn a() {}
}
).to_string(),
quote!{
#[allow(non_upper_case_globals)]
#[doc(hidden)]
const _DERIVE_krate_Trait_X_FOR_A: () = {
extern crate krate;
impl<T, U, X: krate::AnotherTrait> krate::Trait<X> for A<T, U>
where T : krate :: Trait < X >,
Option<U>: krate::Trait<X>,
U: krate::Trait<X>
{
fn a() {}
}
};
}.to_string()
);
sourcepub fn add_trait_bounds(
&self,
bound: &TraitBound,
where_clause: &mut Option<WhereClause>,
mode: AddBounds
)
pub fn add_trait_bounds( &self, bound: &TraitBound, where_clause: &mut Option<WhereClause>, mode: AddBounds )
Add trait bounds for a trait with the given path for each type parmaeter referenced in the types of non-filtered fields.
Caveat
If the method contains any macros in type position, all parameters will be considered bound. This is because we cannot determine which type parameters are bound by type macros.
sourcepub fn underscore_const(&mut self, enabled: bool) -> &mut Self
pub fn underscore_const(&mut self, enabled: bool) -> &mut Self
Configure whether to use const _
instead of a generated const name in
code generated by gen_impl
and bound_impl
.
This syntax is only supported by rust 1.37, and later versions.
Defaults to false
for backwards compatibility reasons.
Example
let di: syn::DeriveInput = syn::parse_quote! {
struct MyStruct;
};
let mut s = Structure::new(&di);
assert_eq!(
s.underscore_const(true)
.gen_impl(quote! { gen impl Trait for @Self { } })
.to_string(),
quote! {
const _: () = {
impl Trait for MyStruct { }
};
}
.to_string()
);
assert_eq!(
s.underscore_const(false)
.gen_impl(quote! { gen impl Trait for @Self { } })
.to_string(),
quote! {
#[allow(non_upper_case_globals)]
const _DERIVE_Trait_FOR_MyStruct: () = {
impl Trait for MyStruct { }
};
}
.to_string()
);
sourcepub fn bound_impl<P: ToTokens, B: ToTokens>(
&self,
path: P,
body: B
) -> TokenStream
pub fn bound_impl<P: ToTokens, B: ToTokens>( &self, path: P, body: B ) -> TokenStream
NOTE: This methods’ features are superceded by
Structure::gen_impl
.
Creates an impl
block with the required generic type fields filled in
to implement the trait path
.
This method also adds where clauses to the impl requiring that all
referenced type parmaeters implement the trait path
.
Hygiene and Paths
This method wraps the impl block inside of a const
(see the example
below). In this scope, the first segment of the passed-in path is
extern crate
-ed in. If you don’t want to generate that extern crate
item, use a global path.
This means that if you are implementing my_crate::Trait
, you simply
write s.bound_impl(quote!(my_crate::Trait), quote!(...))
, and for the
entirety of the definition, you can refer to your crate as my_crate
.
Caveat
If the method contains any macros in type position, all parameters will be considered bound. This is because we cannot determine which type parameters are bound by type macros.
Panics
Panics if the path string parameter is not a valid TraitBound
.
Example
let di: syn::DeriveInput = syn::parse_quote! {
enum A<T, U> {
B(T),
C(Option<U>),
}
};
let mut s = Structure::new(&di);
s.filter_variants(|v| v.ast().ident != "B");
assert_eq!(
s.bound_impl(quote!(krate::Trait), quote!{
fn a() {}
}).to_string(),
quote!{
#[allow(non_upper_case_globals)]
#[doc(hidden)]
const _DERIVE_krate_Trait_FOR_A: () = {
extern crate krate;
impl<T, U> krate::Trait for A<T, U>
where Option<U>: krate::Trait,
U: krate::Trait
{
fn a() {}
}
};
}.to_string()
);
sourcepub fn unsafe_bound_impl<P: ToTokens, B: ToTokens>(
&self,
path: P,
body: B
) -> TokenStream
pub fn unsafe_bound_impl<P: ToTokens, B: ToTokens>( &self, path: P, body: B ) -> TokenStream
NOTE: This methods’ features are superceded by
Structure::gen_impl
.
Creates an impl
block with the required generic type fields filled in
to implement the unsafe trait path
.
This method also adds where clauses to the impl requiring that all
referenced type parmaeters implement the trait path
.
Hygiene and Paths
This method wraps the impl block inside of a const
(see the example
below). In this scope, the first segment of the passed-in path is
extern crate
-ed in. If you don’t want to generate that extern crate
item, use a global path.
This means that if you are implementing my_crate::Trait
, you simply
write s.bound_impl(quote!(my_crate::Trait), quote!(...))
, and for the
entirety of the definition, you can refer to your crate as my_crate
.
Caveat
If the method contains any macros in type position, all parameters will be considered bound. This is because we cannot determine which type parameters are bound by type macros.
Panics
Panics if the path string parameter is not a valid TraitBound
.
Example
let di: syn::DeriveInput = syn::parse_quote! {
enum A<T, U> {
B(T),
C(Option<U>),
}
};
let mut s = Structure::new(&di);
s.filter_variants(|v| v.ast().ident != "B");
assert_eq!(
s.unsafe_bound_impl(quote!(krate::Trait), quote!{
fn a() {}
}).to_string(),
quote!{
#[allow(non_upper_case_globals)]
#[doc(hidden)]
const _DERIVE_krate_Trait_FOR_A: () = {
extern crate krate;
unsafe impl<T, U> krate::Trait for A<T, U>
where Option<U>: krate::Trait,
U: krate::Trait
{
fn a() {}
}
};
}.to_string()
);
sourcepub fn unbound_impl<P: ToTokens, B: ToTokens>(
&self,
path: P,
body: B
) -> TokenStream
pub fn unbound_impl<P: ToTokens, B: ToTokens>( &self, path: P, body: B ) -> TokenStream
NOTE: This methods’ features are superceded by
Structure::gen_impl
.
Creates an impl
block with the required generic type fields filled in
to implement the trait path
.
This method will not add any where clauses to the impl.
Hygiene and Paths
This method wraps the impl block inside of a const
(see the example
below). In this scope, the first segment of the passed-in path is
extern crate
-ed in. If you don’t want to generate that extern crate
item, use a global path.
This means that if you are implementing my_crate::Trait
, you simply
write s.bound_impl(quote!(my_crate::Trait), quote!(...))
, and for the
entirety of the definition, you can refer to your crate as my_crate
.
Panics
Panics if the path string parameter is not a valid TraitBound
.
Example
let di: syn::DeriveInput = syn::parse_quote! {
enum A<T, U> {
B(T),
C(Option<U>),
}
};
let mut s = Structure::new(&di);
s.filter_variants(|v| v.ast().ident != "B");
assert_eq!(
s.unbound_impl(quote!(krate::Trait), quote!{
fn a() {}
}).to_string(),
quote!{
#[allow(non_upper_case_globals)]
#[doc(hidden)]
const _DERIVE_krate_Trait_FOR_A: () = {
extern crate krate;
impl<T, U> krate::Trait for A<T, U> {
fn a() {}
}
};
}.to_string()
);
sourcepub fn unsafe_unbound_impl<P: ToTokens, B: ToTokens>(
&self,
path: P,
body: B
) -> TokenStream
👎Deprecated
pub fn unsafe_unbound_impl<P: ToTokens, B: ToTokens>( &self, path: P, body: B ) -> TokenStream
NOTE: This methods’ features are superceded by
Structure::gen_impl
.
Creates an impl
block with the required generic type fields filled in
to implement the unsafe trait path
.
This method will not add any where clauses to the impl.
Hygiene and Paths
This method wraps the impl block inside of a const
(see the example
below). In this scope, the first segment of the passed-in path is
extern crate
-ed in. If you don’t want to generate that extern crate
item, use a global path.
This means that if you are implementing my_crate::Trait
, you simply
write s.bound_impl(quote!(my_crate::Trait), quote!(...))
, and for the
entirety of the definition, you can refer to your crate as my_crate
.
Panics
Panics if the path string parameter is not a valid TraitBound
.
Example
let di: syn::DeriveInput = syn::parse_quote! {
enum A<T, U> {
B(T),
C(Option<U>),
}
};
let mut s = Structure::new(&di);
s.filter_variants(|v| v.ast().ident != "B");
assert_eq!(
s.unsafe_unbound_impl(quote!(krate::Trait), quote!{
fn a() {}
}).to_string(),
quote!{
#[allow(non_upper_case_globals)]
#[doc(hidden)]
const _DERIVE_krate_Trait_FOR_A: () = {
extern crate krate;
unsafe impl<T, U> krate::Trait for A<T, U> {
fn a() {}
}
};
}.to_string()
);
sourcepub fn gen_impl(&self, cfg: TokenStream) -> TokenStream
pub fn gen_impl(&self, cfg: TokenStream) -> TokenStream
Generate an impl block for the given struct. This impl block will automatically use hygiene tricks to avoid polluting the caller’s namespace, and will automatically add trait bounds for generic type parameters.
Syntax
This function accepts its arguments as a TokenStream
. The recommended way
to call this function is passing the result of invoking the quote!
macro to it.
s.gen_impl(quote! {
// You can write any items which you want to import into scope here.
// For example, you may want to include an `extern crate` for the
// crate which implements your trait. These items will only be
// visible to the code you generate, and won't be exposed to the
// consuming crate
extern crate krate;
// You can also add `use` statements here to bring types or traits
// into scope.
//
// WARNING: Try not to use common names here, because the stable
// version of syn does not support hygiene and you could accidentally
// shadow types from the caller crate.
use krate::Trait as MyTrait;
// The actual impl block is a `gen impl` or `gen unsafe impl` block.
// You can use `@Self` to refer to the structure's type.
gen impl MyTrait for @Self {
fn f(&self) { ... }
}
})
The most common usage of this trait involves loading the crate the
target trait comes from with extern crate
, and then invoking a gen impl
block.
Hygiene
This method tries to handle hygiene intelligenly for both stable and unstable proc-macro implementations, however there are visible differences.
The output of every gen_impl
function is wrapped in a dummy const
value, to ensure that it is given its own scope, and any values brought
into scope are not leaked to the calling crate.
By default, the above invocation may generate an output like the following:
const _DERIVE_krate_Trait_FOR_Struct: () = {
extern crate krate;
use krate::Trait as MyTrait;
impl<T> MyTrait for Struct<T> where T: MyTrait {
fn f(&self) { ... }
}
};
The Structure
may also be confired with the [underscore_const
] method
to generate const _
instead.
const _: () = {
extern crate krate;
use krate::Trait as MyTrait;
impl<T> MyTrait for Struct<T> where T: MyTrait {
fn f(&self) { ... }
}
};
Using the std
crate
If you are using quote!()
to implement your trait, with the
proc-macro2/nightly
feature, std
isn’t considered to be in scope for
your macro. This means that if you use types from std
in your
procedural macro, you’ll want to explicitly load it with an extern crate std;
.
Absolute paths
You should generally avoid using absolute paths in your generated code,
as they will resolve very differently when using the stable and nightly
versions of proc-macro2
. Instead, load the crates you need to use
explictly with extern crate
and
Trait Bounds
This method will automatically add trait bounds for any type parameters which are referenced within the types of non-ignored fields.
Additional type parameters may be added with the generics syntax after
the impl
keyword.
Type Macro Caveat
If the method contains any macros in type position, all parameters will be considered bound. This is because we cannot determine which type parameters are bound by type macros.
Errors
This function will generate a compile_error!
if additional type
parameters added by impl<..>
conflict with generic type parameters on
the original struct.
Panics
This function will panic if the input TokenStream
is not well-formed.
Example Usage
let di: syn::DeriveInput = syn::parse_quote! {
enum A<T, U> {
B(T),
C(Option<U>),
}
};
let mut s = Structure::new(&di);
s.filter_variants(|v| v.ast().ident != "B");
assert_eq!(
s.gen_impl(quote! {
extern crate krate;
gen impl krate::Trait for @Self {
fn a() {}
}
}).to_string(),
quote!{
#[allow(non_upper_case_globals)]
const _DERIVE_krate_Trait_FOR_A: () = {
extern crate krate;
impl<T, U> krate::Trait for A<T, U>
where
Option<U>: krate::Trait,
U: krate::Trait
{
fn a() {}
}
};
}.to_string()
);
// NOTE: You can also add extra generics after the impl
assert_eq!(
s.gen_impl(quote! {
extern crate krate;
gen impl<X: krate::OtherTrait> krate::Trait<X> for @Self
where
X: Send + Sync,
{
fn a() {}
}
}).to_string(),
quote!{
#[allow(non_upper_case_globals)]
const _DERIVE_krate_Trait_X_FOR_A: () = {
extern crate krate;
impl<X: krate::OtherTrait, T, U> krate::Trait<X> for A<T, U>
where
X: Send + Sync,
Option<U>: krate::Trait<X>,
U: krate::Trait<X>
{
fn a() {}
}
};
}.to_string()
);
// NOTE: you can generate multiple traits with a single call
assert_eq!(
s.gen_impl(quote! {
extern crate krate;
gen impl krate::Trait for @Self {
fn a() {}
}
gen impl krate::OtherTrait for @Self {
fn b() {}
}
}).to_string(),
quote!{
#[allow(non_upper_case_globals)]
const _DERIVE_krate_Trait_FOR_A: () = {
extern crate krate;
impl<T, U> krate::Trait for A<T, U>
where
Option<U>: krate::Trait,
U: krate::Trait
{
fn a() {}
}
impl<T, U> krate::OtherTrait for A<T, U>
where
Option<U>: krate::OtherTrait,
U: krate::OtherTrait
{
fn b() {}
}
};
}.to_string()
);
Use add_bounds
to change which bounds are generated.