diff options
author | Martin Fischer <martin@push-f.com> | 2021-11-23 07:22:37 +0100 |
---|---|---|
committer | Martin Fischer <martin@push-f.com> | 2021-11-23 07:58:37 +0100 |
commit | 2ac214d58ba94e915907511a4468bbfa89b6d821 (patch) | |
tree | 0516ada8a262344c616696fe6c723bd2cb78271c | |
parent | 19dcb405cd4cfb960f51edbc1446e0a843772d6b (diff) |
improve README: explain crate before example
-rw-r--r-- | README.md | 38 |
1 files changed, 23 insertions, 15 deletions
@@ -1,8 +1,16 @@ # Dynamize -In order for a trait to be usable as a trait object it needs to fulfill -[several requirements](https://doc.rust-lang.org/reference/items/traits.html#object-safety). -For example: +In order to turn a trait into a [trait object] the trait must be [object-safe] +and the values of all [associated types] must be specified. Sometimes you +however want a trait object to be able to encompass trait implementations with +different associated type values. This crate provides a procedural macro to +achieve that. + +[trait object]: https://doc.rust-lang.org/book/ch17-02-trait-objects.html +[object-safe]: https://doc.rust-lang.org/reference/items/traits.html#object-safety +[associated types]: https://doc.rust-lang.org/book/ch19-03-advanced-traits.html + +The following code illustrates a scenario where dynamize can help you: ```rust ignore trait Client { @@ -23,10 +31,7 @@ The last line of the above code fails to compile with: > error\[E0191\]: the value of the associated type `Error` (from trait `Client`) > must be specified -Sometimes you however want a trait object to be able to encompass trait -implementations with different associated type values. This crate provides an -attribute macro to achieve that. To use dynamize you only have to make some -small changes: +To use dynamize you only have to make some small changes: ```rust ignore #[dynamize::dynamize] @@ -35,18 +40,21 @@ trait Client { fn get(&self, url: String) -> Result<Vec<u8>, Self::Error>; } - -let client: HttpClient = ...; -let object = &client as &dyn DynClient; ``` 1. You add the `#[dynamize::dynamize]` attribute to your trait. 2. You specify a trait bound for each associated type. -Dynamize defines a new trait for you, named after your trait but with the `Dyn` -prefix, so e.g. `Client` becomes `DynClient` in our example. The new -"dynamized" trait can then be used without having to specify the associated -type. +Dynamize defines a new trait for you, named after your trait but +with the `Dyn` prefix, so e.g. `Client` becomes `DynClient`: + +```rust ignore +let client: HttpClient = ...; +let object = &client as &dyn DynClient; +``` + +The new "dynamized" trait can then be used without having to specify the +associated type value. ## How does this work? @@ -100,7 +108,7 @@ Note that since these are resolved recursively you can actually nest these arbitrarily so e.g. the following also just works: ```rust ignore -fn example(&self) -> Result<Option<Self::Item>, Self::Error>; +fn example(&self) -> Result<Vec<Self::Item>, Self::Error>; ``` ## How does dynamize deal with method generics? |