aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Fischer <martin@push-f.com>2021-11-23 07:22:37 +0100
committerMartin Fischer <martin@push-f.com>2021-11-23 07:58:37 +0100
commit2ac214d58ba94e915907511a4468bbfa89b6d821 (patch)
tree0516ada8a262344c616696fe6c723bd2cb78271c
parent19dcb405cd4cfb960f51edbc1446e0a843772d6b (diff)
improve README: explain crate before example
-rw-r--r--README.md38
1 files changed, 23 insertions, 15 deletions
diff --git a/README.md b/README.md
index ab688ee..6a80661 100644
--- a/README.md
+++ b/README.md
@@ -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?