diff options
author | Martin Fischer <martin@push-f.com> | 2021-11-25 10:30:54 +0100 |
---|---|---|
committer | Martin Fischer <martin@push-f.com> | 2021-11-26 11:45:53 +0100 |
commit | 7489a3c2246e7ea2483446dd2ed3fdbfaf462c1a (patch) | |
tree | fc2670f56f7cc16567eb10d88f9439abb9098298 /README.md | |
parent | 43950edc4f26a07055fb917fa8bbb262276e2a08 (diff) |
introduce #[convert] attribute
Diffstat (limited to 'README.md')
-rw-r--r-- | README.md | 55 |
1 files changed, 55 insertions, 0 deletions
@@ -169,6 +169,61 @@ trait Client: Sync { Note that it is important that the `#[dynamize]` attribute comes before the `#[async_trait]` attribute, since dynamize must run before async_trait. +## Dynamized supertraits + +In Rust a macro only operates on the passed input; it does not have access to +the surrounding source code. This also means that a `#[dynamize]` macro cannot +know which other traits have been dynamized. When you want to dynamize a trait +with a dynamized supertrait, you have to tell dynamize about it with the +`#[dynamized(...)]` attribute: + +```rust ignore +#[dynamize::dynamize] +trait Client { + type Error: Into<SuperError>; + + fn get(&self, url: String) -> Result<Vec<u8>, Self::Error>; +} + +#[dynamize::dynamize] +#[dynamized(Client)] +trait ClientWithCache: Client { + type Error: Into<SuperError>; + + fn get_with_cache<C: Cache>( + &self, + url: String, + cache: C, + ) -> Result<Vec<u8>, <Self as ClientWithCache>::Error>; +} +``` + +This results in `DynClientWithCache` having the dynamized `DynClient` supertrait. + +With the above code both traits have independent associated types. So a trait +could implement one trait with one `Error` type and and the other trait with +another `Error` type. If you don't want that to be possible you can change the +second trait to: + +```rust ignore +#[dynamize::dynamize] +#[dynamized(Client)] +#[convert = |x: <Self as Client>::Error| -> SuperError {x.into()}] +trait ClientWithCache: Client { + fn get_with_cache<C: Cache>( + &self, + url: String, + cache: C, + ) -> Result<Vec<u8>, <Self as Client>::Error>; +} +``` + +Note that we removed the associated type and are now using the associated type +from the supertrait by qualifying `Self as Client`. Since the `#[dynamize]` +attribute on the `ClientWithCache` trait however cannot know the associated +type from another trait, we also need to add a `#[convert = ...]` attribute to +tell dynamize how to convert `<Self as Client>::Error>`. + ## Using dynamize with other collections Dynamize automatically recognizes collections from the standard library like |