//! //! # Ambassador - Delegate trait implementations via procedural macros //! //! //! //! Crates.io version //! //! //! //! docs.rs docs //! //! //!
//! //! //! Delegating the implementation of traits to enum variants or fields of a struct normally requires a lot of boilerplate code. Ambassador is an attempt to eliminate that boilerplate by deriving the delegating trait implementation via procedural macros. //! //! **The minimum supported Rust version is 1.53.0.** //! //! See individual macro documentation for detailed instructions. //! //! This is one example combining a large number of features: //! //! ``` //! extern crate ambassador; //! //! use std::collections::{HashMap, BTreeMap}; //! use std::borrow::Borrow; //! use std::cmp::{Eq, Ord}; //! use std::hash::{Hash, BuildHasher}; //! use std::ops::Deref; //! use ambassador::{delegatable_trait, delegate_remote, delegate_to_remote_methods, Delegate}; //! //! #[delegatable_trait] //! pub trait Map { //! type V; //! } //! //! #[delegatable_trait] //! pub trait Get: Map { //! fn get(&self, k: &Q) -> Option<&Self::V>; //! } //! //! impl Map for HashMap { //! type V = V; //! } //! //! impl Map for BTreeMap { //! type V = V; //! } //! //! //! // No automatic where clause provided for target = "self" //! #[delegate_remote] //! #[delegate(Get, target = "self", generics = "X", where = "K: Hash + Eq + Borrow, S: BuildHasher, X: Hash + Eq + ?Sized")] //! struct HashMap(); //! //! #[delegate_remote] //! #[delegate(Get, target = "self", generics = "X", where = "K: Ord + Borrow, X: Ord + ?Sized")] //! struct BTreeMap(); //! //! #[derive(Delegate)] //! #[delegate(Map)] //! #[delegate(Get, generics = "X", where = "X: ?Sized, B: Map")] //auto where clause misses required on super trait //! pub enum Either { //! Left(A), //! Right(B), //! } //! //! #[delegate_to_remote_methods] //! #[delegate(Map, target_ref = "deref")] //! #[delegate(Get, target_ref = "deref", generics = "X", where = "X: ?Sized")] //! impl Box { //! fn deref(&self) -> &M; //! } //! //! pub fn main() { //! let x: HashMap<&'static str, u32> = [("a", 1)].into(); //! let my_map: Either>, BTreeMap<&'static str, u32>> = Either::Left(Box::new(x)); //! assert_eq!(my_map.get("a"), Some(&1)); //! } //! ``` //! //! # Cross module uses //! Modules using delegateable traits should add `use ::ambassador_impl_;` //! where `` is the path to the module which used either //! [`macro@delegatable_trait`] or [`macro@delegatable_trait_remote`] //! ### Example //! ``` //! mod m{ //! pub mod m1 { //! use ambassador::delegatable_trait; //! #[delegatable_trait] //! pub trait Shout { //! fn shout(&self); //! } //! } //! //! mod m2 { //! use ambassador::Delegate; //! use super::m1::{Shout, ambassador_impl_Shout}; //! //! #[derive(Delegate)] //! #[delegate(Shout)] //! struct Wrap(X); //! } //! } //! //! ``` //! //! # Backwards Compatibility //! ## 0.3.x -> 0.4.x //! ### Creating delegateable traits //! Delagatable trait macros `ambassador_impl_Trait` are no longer exported at the crate root, and //! are instead exported in the module where [`macro@delegatable_trait`] or //! [`macro@delegatable_trait_remote`] are used. If these traits are public then upgrading is also //! a breaking change for users of your library. The "backward_compatible" is also removed. //! ### Using delegateable traits //! Switching versions does not affect usages of delegateable traits //! ## 0.2.x -> 0.3.x //! Since delegateable traits from one crate can be used in anther crate backwards compatibility of switching to 0.3.x depends on the use case //! ### Self Contained Crate //! Switching to 0.3.x should just work, //! in this case it safe to disable the "backward_compatible" feature //! ### Library with public delegatable traits //! Make sure use the "backward_compatible" feature (enabled by default), //! this makes sure users of your library using an older version of ambassador aren't affected by the upgrade //! ### Users of a library with public delegatable traits //! Try to use the same version of ambassador as the library you're using extern crate core; extern crate proc_macro; mod delegate_shared; mod delegate_to_methods; mod derive; mod register; mod util; use proc_macro::TokenStream; use quote::quote; use crate::register::build_register_trait; /// Delegate the implementation of a trait to a struct field/enum variants by adding `#[derive(Delegate)]` and its associated attribute `#[delegate(Trait)]` to it: /// /// ``` /// use ambassador::{Delegate, delegatable_trait}; /// /// #[delegatable_trait] /// pub trait Shout { /// fn shout(&self, input: &str) -> String; /// } /// /// pub struct Cat; /// /// impl Shout for Cat { /// fn shout(&self, input: &str) -> String { /// format!("{} - meow!", input) /// } /// } /// /// #[derive(Delegate)] // <------- /// #[delegate(Shout)] // <-------- Delegate implementation of Shout to struct field /// pub struct WrappedCat(Cat); /// ``` /// ///#### `#[delegate(..., target = "foo")]` - `target` key /// /// For structs with multiple fields, the field that should act as delegation target can be specified via the `target` key: /// /// ``` /// # use ambassador::{Delegate, delegatable_trait}; /// # #[delegatable_trait] /// # pub trait Shout { /// # fn shout(&self, input: &str) -> String; /// # } /// # pub struct Cat; /// # /// # impl Shout for Cat { /// # fn shout(&self, input: &str) -> String { /// # format!("{} - meow!", input) /// # } /// # } /// /// #[derive(Delegate)] /// #[delegate(Shout, target = "foo")] // <-------- Delegate implementation of Shout to struct field .foo /// pub struct WrappedCats { /// foo: Cat, /// bar: Cat, /// } /// ``` /// This also works for tuple structs with multiple fields, by using their index as a target key: /// /// ``` /// # use ambassador::{Delegate, delegatable_trait}; /// # #[delegatable_trait] /// # pub trait Shout { /// # fn shout(&self, input: &str) -> String; /// # } /// # pub struct Cat; /// # /// # impl Shout for Cat { /// # fn shout(&self, input: &str) -> String { /// # format!("{} - meow!", input) /// # } /// # } /// /// #[derive(Delegate)] /// #[delegate(Shout, target = "1")] // <-------- Delegate implementation of Shout to second field /// pub struct WrappedCats(Cat, Cat); /// ``` /// /// #### `#[delegate(..., target = "self")]` - `target="self"` /// Types that implement all the methods of a trait without implementing the trait itself, /// can be made to implement that trait by setting `target="self"`. /// This doesn't work for traits with associated types and constants, and requires the where clause to be added explicitly (see `where` key). /// If the type doesn't actually implement the methods (possibly due to an incomplete `where` clause) this can cause a `[unconditional_recursion]` error. /// /// A possible use case of this is when refactoring some methods of a public type into a trait, /// the type still needs to implement the methods outside the trait for semver reasons, /// and using this feature reduces the boilderplate of implementing the trait with the same methods. /// /// /// ``` /// # use ambassador::{Delegate, delegatable_trait}; /// # #[delegatable_trait] /// # pub trait Shout { /// # fn shout(&self, input: &str) -> String; /// # } /// #[derive(Delegate)] /// #[delegate(Shout, target="self")] /// pub struct Cat; /// /// impl Cat { /// fn shout(&self, input: &str) -> String { /// format!("{} - meow!", input) /// } /// } /// ``` /// /// #### `#[delegate(..., where = "A: Debug")]` - `where` key /// /// To make a delegation apply only for certain generic bounds, similar to a [native where clause](https://doc.rust-lang.org/stable/rust-by-example/generics/where.html), you can specify a `where` attribute: /// /// A where clause is automatically applied that makes sure the target field implements the trait being delegated /// ``` /// # use ambassador::{Delegate, delegatable_trait}; /// # #[delegatable_trait] /// # pub trait Shout { /// # fn shout(&self, input: &str) -> String; /// # } /// use std::fmt::Debug; /// /// #[derive(Delegate)] /// #[delegate(Shout, where = "A: Debug")] // <---- Delegate implementation of Shout to .foo field if foo field implements Debug /// // "A: Shout" is automatically added /// pub struct WrappedFoo { /// foo: A, /// } /// ``` /// /// /// #### `#[delegate(Shout, generics = "X")]` - trait generics /// /// We can also delegate traits with generics. /// The type parameters listed in the `generics` key are treated as fully generic. /// The automatically added where clause ensures they are valid for the inner type being delegated to. /// Explict where clauses to further refine these types can be added as normal. /// /// ``` /// use ambassador::{delegatable_trait, Delegate}; /// use std::fmt::Display; /// /// #[delegatable_trait] /// pub trait Shout { /// fn shout(&self, input: T) -> String; /// } /// /// pub struct Cat; /// /// impl Shout for Cat { /// fn shout(&self, input: T) -> String { /// format!("{} - meow!", input) /// } /// } /// /// #[derive(Delegate)] /// #[delegate(Shout, generics = "X")] // <-------- `X` is fully generic /// // The automatic where clause ensures X: Display /// // We could also use #[delegate(Shout<& 'a str>, generics = "'a")] to only delegate for &str /// pub struct WrappedCat(Cat); /// ``` /// /// /// #### `#[delegate(Shout, automatic_where_clause = "false")]` - inhibit automatic generation of `where` clause. /// /// Normally `#[derive(Delegate)]` generates code to ensure that chosen field /// indeed implements the trait you want to implement for the container struct. /// /// For example, the `#[derive(Delegate)]` + `#[delegate(Shout, generics = "X")]` /// in the example above will emit code that requires `Cat` (the type we're /// delegating to) to implement `Shout`: `Cat: Shout`. /// /// However, you may want to delegate implementation to a type that does not in /// fact fully implement the trait in question but instead has _compatible /// methods_ that can be called as if the trait were in fact implemented. /// /// One notable examples of this is delegating a trait implementation to /// container types holding a trait object; i.e. `MyTrait` for /// `Box`. In this example, `Box` even though `Box` does not actually /// implement `MyTrait`. /// /// `automatic_where_clause = "false"` lets us create a delegated impl of /// `MyTrait` that takes advantage of this. /// /// ``` /// use ambassador::{delegatable_trait, Delegate}; /// use std::fmt::Display; /// /// #[delegatable_trait] /// pub trait Shout { /// fn shout(&self, input: &str) -> String; /// } /// /// pub struct Cat; /// /// impl Shout for Cat { /// fn shout(&self, input: &str) -> String { /// format!("{} - meow!", input) /// } /// } /// /// #[derive(Delegate)] /// #[delegate(Shout, automatic_where_clause = "false")] /// pub struct BoxedAnimal(pub Box); /// /// // Can accept both `Cat` and `BoxedAnimal`. /// fn recording_studio(voice_actor: S){} /// ``` /// /// Note that it is also possible to create such a delegated impl by making use /// of [`macro@delegate_to_remote_methods`] with [`Deref::deref`] and /// [`DerefMut::deref_mut`] as the target methods. The docs on /// [`macro@delegate_to_remote_methods`] contain an example of this. /// /// [`Deref::deref`]: core::ops::Deref::deref /// [`DerefMut::deref_mut`]: core::ops::DerefMut::deref_mut #[proc_macro_derive(Delegate, attributes(delegate))] pub fn delegate_macro(input: TokenStream) -> TokenStream { derive::delegate_macro(input) } /// Delegate the implementation of a trait to a type's methods by adding `#[delegate_to_methods]` and its associated attribute `#[delegate(Trait)]` to the relevant impl block /// /// #### `#[delegate(..., target_owned = "foo", target_ref = "bar", target_mut = "baz")]` - `target` keys /// Three different target methods can be specified depending on the receiver of of the trait method being delegated. /// These methods must have the signatures target_owned: "fn foo(self) -> X", target_ref: "fn bar(&self) -> &X", and target_mut: "fn baz(&mut self) -> &mut X" /// where X is the same type for all three. /// Excluding some of these attributes is allowed as long as the trait being delegated to doesn't have any methods with the relevant receiver /// Additional methods that don't have any of the relevant signature types may be included in the impl block as long as they are never used as targets. /// /// #### The `where` and `generics` keys described in [`Delegate`] are also supported and function the same way /// /// ``` /// use std::ops::{Deref, DerefMut}; /// use ambassador::{delegate_to_methods, delegatable_trait}; /// /// #[delegatable_trait] /// pub trait Shout { /// fn shout(&self, input: &str) -> String; /// } /// /// pub struct Cat; /// /// impl Shout for Cat { /// fn shout(&self, input: &str) -> String { /// format!("{} - meow!", input) /// } /// } /// /// pub struct BoxedCat(Box); // Target is hidden behind a box /// /// #[delegate_to_methods] /// #[delegate(Shout, target_ref = "inner", target_mut = "inner_mut")] /// impl BoxedCat { /// fn inner(&self) -> &Cat { /// self.0.deref() /// } /// /// // Note we don't need target_mut = "inner_mut" in this case but it is included as an example /// // The return type must be &mut Cat to match inner's return type &Cat /// fn inner_mut(&mut self) -> &mut Cat { /// self.0.deref_mut() /// } /// /// // You can also have extra methods here: /// fn another_one(&self) { } /// } /// ``` /// /// #### `delegate_to_methods` on an `impl Trait for ...` block /// /// It's also valid to use `delegate_to_methods` with a trait impl; i.e. to use /// the methods from a different trait to delegate a trait. For example: /// ``` /// # use std::ops::{Deref, DerefMut}; /// # use ambassador::{delegate_to_methods, delegatable_trait}; /// # #[delegatable_trait] /// # pub trait Shout { /// # fn shout(&self, input: &str) -> String; /// # } /// # pub struct Cat; /// # impl Shout for Cat { /// # fn shout(&self, input: &str) -> String { /// # format!("{} - meow!", input) /// # } /// # } /// /// pub struct RefCat<'a>(&'a Cat); /// /// #[delegate_to_methods] /// #[delegate(Shout, target_ref = "deref")] /// impl<'a> Deref for RefCat<'a> { /// type Target = Cat; /// /// fn deref(&self) -> &Cat { &self.0 } /// } /// ``` /// /// Note that this has a caveat: if the target methods you are delegating to /// share the same name as any of the methods in the trait being delegated you /// will likely get errors about ambiguity. For example: /// /// ```rust,compile_fail /// # use std::ops::{Deref, DerefMut}; /// # use ambassador::{delegate_to_methods, delegatable_trait}; /// # #[delegatable_trait] /// # pub trait Shout { /// # fn shout(&self, input: &str) -> String; /// # } /// # pub struct Cat; /// # impl Shout for Cat { /// # fn shout(&self, input: &str) -> String { /// # format!("{} - meow!", input) /// # } /// # } /// /// pub struct RefCat<'a>(&'a Cat); /// /// trait GetAShouter { /// type Shouter: Shout; /// /// fn shout(&self) -> &Self::Shouter; /// } /// /// #[delegate_to_methods] /// #[delegate(Shout, target_ref = "shout")] /// impl<'a> GetAShouter for RefCat<'a> { /// type Shouter = Cat; /// /// fn shout(&self) -> &Cat { &self.0 } /// } /// ``` /// /// Yields: /// ```text /// error[E0034]: multiple applicable items in scope /// --> src/lib.rs:363:32 /// | /// 26 | #[delegate(Shout, target_ref = "shout")] /// | ^^^^^^^ multiple `shout` found /// | /// note: candidate #1 is defined in an impl of the trait `Shout` for the type `RefCat<'a>` /// --> src/lib.rs:345:5 /// | /// 8 | fn shout(&self, input: &str) -> String; /// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /// ... /// 25 | #[delegate_to_methods] /// | ---------------------- in this procedural macro expansion /// note: candidate #2 is defined in an impl of the trait `GetAShouter` for the type `RefCat<'a>` /// --> src/lib.rs:367:5 /// | /// 30 | fn shout(&self) -> &Cat { &self.0 } /// | ^^^^^^^^^^^^^^^^^^^^^^^ /// = note: this error originates in the macro `ambassador_impl_Shout` (in Nightly builds, run with -Z macro-backtrace for more info) /// ``` /// /// This is not an issue when the target methods are _inherent_ since inherent /// methods explicitly [have priority over trait methods](https://dtolnay.github.io/rust-quiz/23) /// during method resolution. /// /// The workaround is to create wrapper inherent methods for the trait's methods: /// ``` /// # use std::ops::{Deref, DerefMut}; /// # use ambassador::{delegate_to_methods, delegatable_trait}; /// # #[delegatable_trait] /// # pub trait Shout { /// # fn shout(&self, input: &str) -> String; /// # } /// # pub struct Cat; /// # impl Shout for Cat { /// # fn shout(&self, input: &str) -> String { /// # format!("{} - meow!", input) /// # } /// # } /// /// pub struct RefCat<'a>(&'a Cat); /// /// trait GetAShouter { /// type Shouter: Shout; /// /// fn shout(&self) -> &Self::Shouter; /// } /// /// impl<'a> GetAShouter for RefCat<'a> { /// type Shouter = Cat; /// /// fn shout(&self) -> &Cat { &self.0 } /// } /// /// #[delegate_to_methods] /// #[delegate(Shout, target_ref = "get_a_shouter")] /// impl<'a> RefCat<'a> { fn get_a_shouter(&self) -> &Cat { GetAShouter::shout(self) } } /// ``` #[proc_macro_attribute] pub fn delegate_to_methods(_attr: TokenStream, input: TokenStream) -> TokenStream { delegate_to_methods::delegate_macro(input, true) } /// Delegate the implementation of a trait to methods on a type that are defined /// _elsewhere_. /// /// This macro is identical to [`macro@delegate_to_methods`] except that it does not /// actually produce an `impl` block on the type for the target methods; instead /// it assumes that the methods are implemented elsewhere. /// ``` /// use ambassador::{delegate_to_remote_methods, delegatable_trait}; /// /// #[delegatable_trait] /// pub trait Shout { /// fn shout(&self, input: &str) -> String; /// } /// /// pub struct Cat; /// /// impl Shout for Cat { /// fn shout(&self, input: &str) -> String { /// format!("{} - meow!", input) /// } /// } /// /// pub struct BoxedCat(Box); /// /// impl BoxedCat { /// fn inner(&self) -> &Cat { &self.0 } /// } /// /// #[delegate_to_remote_methods] /// #[delegate(Shout, target_ref = "inner")] /// impl BoxedCat { /// // `inner` can be defined anywhere: trait method or inherent method, in /// // this crate or elsewhere /// fn inner(&self) -> &Cat; /// } /// ``` /// /// As such, this macro will actually error if you provide it with methods with /// blocks, method signatures that aren't used by a `delegate` attribute on the /// impl, or other impl items: /// ```rust,compile_fail /// # use ambassador::{delegate_to_remote_methods, delegatable_trait}; /// # #[delegatable_trait] /// # pub trait Shout { fn shout(&self, input: &str) -> String; } /// # pub struct Cat; /// # impl Shout for Cat { /// # fn shout(&self, input: &str) -> String { format!("{} - meow!", input) } /// # } /// # pub struct BoxedCat(Box); /// # impl BoxedCat { fn inner(&self) -> &Cat { &self.0 } } /// /// #[delegate_to_remote_methods] /// #[delegate(Shout, target_ref = "inner")] /// impl BoxedCat { /// fn inner(&self) -> &Cat { &self.0 } // This is an error, method bodies /// // aren't accepted /// /// fn extra(&self); // Extra methods are also error since no /// // `impl BoxedCat { ... }` is actually /// // emitted /// /// const CONST: () = (); // This is also an error. /// } /// ``` /// /// Target methods can come from a trait or be inherent methods whose actual /// implementation lives elsewhere. You can mix and match: /// ``` /// # use ambassador::{delegate_to_remote_methods, delegatable_trait}; /// # #[delegatable_trait] /// # pub trait Shout { fn shout(&self, input: &str) -> String; } /// # pub struct Cat; /// # impl Shout for Cat { /// # fn shout(&self, input: &str) -> String { format!("{} - meow!", input) } /// # } /// # pub struct BoxedCat(Box); /// # impl BoxedCat { fn inner(&self) -> &Cat { &self.0 } } /// use std::ops::{Deref, DerefMut}; /// /// impl Deref for BoxedCat { /// type Target = Cat; /// /// fn deref(&self) -> &Self::Target { &self.0 } /// } /// /// impl DerefMut for BoxedCat { /// fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } /// } /// /// #[delegate_to_remote_methods] /// #[delegate(Shout, target_ref = "inner", target_mut = "deref_mut")] /// impl BoxedCat { /// fn inner(&self) -> &Cat; /// fn deref_mut(&mut self) -> &mut Cat; /// } /// ``` /// Note that if you do use target methods from a trait, the trait must be in /// scope. /// /// Because this macro does not implement any inherent methods on the type being /// delegated to, the type can be remote (like with [`macro@delegate_remote`]): /// ``` /// # use ambassador::{delegate_to_remote_methods, delegatable_trait}; /// # #[delegatable_trait] /// # pub trait Shout { fn shout(&self, input: &str) -> String; } /// # pub struct Cat; /// # impl Shout for Cat { /// # fn shout(&self, input: &str) -> String { format!("{} - meow!", input) } /// # } /// use std::ops::{Deref, DerefMut}; /// /// // Note that this impl says `Deref for Box`. /// // /// // The trait in this impl is ignored and only serves as documentation here. /// #[delegate_to_remote_methods] /// #[delegate(Shout, target_ref = "deref")] /// impl Deref for Box { /// fn deref(&self) -> &Cat; /// } /// /// fn shout(_: &impl Shout) { } /// /// fn main() { /// let c = Cat; /// shout(&c); /// /// let boxed: Box = Box::new(c); /// shout(&boxed); /// } /// ``` /// /// This can be used in conjunction with generics to provide blanket delegated /// implementations of a local trait without needing to create intermediary /// local traits that provide target methods to use: /// ``` /// # use ambassador::{delegatable_trait, delegate_to_remote_methods}; /// # use std::ops::{Deref, DerefMut}; /// # #[delegatable_trait] /// # pub trait Shout { fn shout(&self, input: &str) -> String; } /// # pub struct Cat; /// # impl Shout for Cat { fn shout(&self, input: &str) -> String { format!("{} - meow!", input) } } /// use std::{sync::Arc, rc::Rc}; /// /// pub struct Dog; /// impl Shout for Dog { /// fn shout(&self, input: &str) -> String { format!("{} - wuff!", input) } /// } /// /// #[delegate_to_remote_methods] /// #[delegate(Shout, target_ref = "deref")] /// impl> T { /// fn deref(&self) -> &S; /// } /// /// pub fn shout(pet: &impl Shout) { println!("{}", pet.shout("hi")); } /// /// pub fn main() { /// shout(&Cat); /// shout(&Dog); /// /// let a: Box = Box::new(Cat); /// let b: Arc = Arc::new(Dog); /// let c: Rc = Rc::new(Cat); /// shout(&a); /// shout(&b); /// shout(&c); /// /// let d: Box = Box::new(Cat); /// shout(&d); /// } /// ``` #[proc_macro_attribute] pub fn delegate_to_remote_methods(_attr: TokenStream, input: TokenStream) -> TokenStream { delegate_to_methods::delegate_macro(input, false) } /// Make an existing type that lives outside you crate delegate traits to it's members /// /// This can be done by copy-pasting it's definition into your code under this attribute. /// /// If the type is a struct, not all the fields have to be public, only the ones being delegated to. /// /// ``` /// use ambassador::{delegate_remote, delegatable_trait}; /// /// #[delegatable_trait] /// pub trait Shout { /// fn shout(&self, input: &str) -> String; /// } /// /// pub struct Cat; /// /// impl Shout for Cat { /// fn shout(&self, input: &str) -> String { /// format!("{} - meow!", input) /// } /// } /// /// mod wrapped { /// pub struct WrappedAnimals { /// pub foo: A, /// pub bar: B, /// baz: u32, // private field /// } /// } /// /// use wrapped::*; /// /// #[delegate_remote] /// #[delegate(Shout, target = "bar")] /// struct WrappedAnimals { /// foo: A, /// bar: B, /// // We don't even have to include baz since we don't delegate to it /// } /// ``` #[proc_macro_attribute] pub fn delegate_remote(_attr: TokenStream, input: TokenStream) -> TokenStream { derive::delegate_macro(input) } /// Make a trait available for delegation /// /// This also makes your trait delegatable in other crates: /// /// ``` /// use ambassador::delegatable_trait; /// /// #[delegatable_trait] // <------- /// pub trait Shout { /// fn shout(&self, input: &str) -> String; /// } /// ``` #[proc_macro_attribute] pub fn delegatable_trait(_attr: TokenStream, item: TokenStream) -> TokenStream { let original_item: syn::ItemTrait = syn::parse(item).unwrap(); let register_trait = build_register_trait(&original_item); let expanded = quote! { #original_item #register_trait }; TokenStream::from(expanded) } /// Make an existing trait that lives outside you crate available for delegation. /// /// This can be done by copy-pasting the existing traits signature into your code under this attribute /// /// ``` /// use ambassador::{Delegate, delegatable_trait_remote}; /// use std::fmt::Display; /// /// #[delegatable_trait_remote] /// trait Display { /// fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error>; /// } /// /// struct Cat; /// /// impl Display for Cat { /// fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error>{ /// f.write_str("Cat") /// } /// } /// /// #[derive(Delegate)] /// #[delegate(Display)] // <-------- Delegate implementation of Display to struct field /// pub struct WrappedCat(Cat); /// ``` #[proc_macro_attribute] pub fn delegatable_trait_remote(_attr: TokenStream, item: TokenStream) -> TokenStream { let original_item: syn::ItemTrait = syn::parse(item).unwrap(); let register_trait = build_register_trait(&original_item); TokenStream::from(register_trait) }