aboutsummaryrefslogtreecommitdiff
path: root/README.md
diff options
context:
space:
mode:
authorMartin Fischer <martin@push-f.com>2021-11-25 10:30:54 +0100
committerMartin Fischer <martin@push-f.com>2021-11-26 11:45:53 +0100
commit7489a3c2246e7ea2483446dd2ed3fdbfaf462c1a (patch)
treefc2670f56f7cc16567eb10d88f9439abb9098298 /README.md
parent43950edc4f26a07055fb917fa8bbb262276e2a08 (diff)
introduce #[convert] attribute
Diffstat (limited to 'README.md')
-rw-r--r--README.md55
1 files changed, 55 insertions, 0 deletions
diff --git a/README.md b/README.md
index 3fb8d39..6067520 100644
--- a/README.md
+++ b/README.md
@@ -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