aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Fischer <martin@push-f.com>2021-11-20 18:53:55 +0100
committerMartin Fischer <martin@push-f.com>2021-11-20 19:19:29 +0100
commit9044eb941a310e4120dab93a43e6630efef72e4a (patch)
tree40940640b1ace6a11a6b89ea04a0d70b1f67e38a
parent3170127a4ef79c43018775934c7e0444dc828b2d (diff)
assert that dynamized traits are object-safe
-rw-r--r--README.md2
-rw-r--r--src/lib.rs10
-rw-r--r--tests/doctests.md19
3 files changed, 30 insertions, 1 deletions
diff --git a/README.md b/README.md
index e6c715e..77d28d1 100644
--- a/README.md
+++ b/README.md
@@ -20,7 +20,7 @@ let object = &client as &dyn Client;
The last line of the above code fails to compile with:
-> error[E0191]: the value of the associated type `Error` (from trait `Client`)
+> 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
diff --git a/src/lib.rs b/src/lib.rs
index a190cb9..85718d0 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -308,12 +308,18 @@ pub fn dynamize(_attr: TokenStream, input: TokenStream) -> TokenStream {
let blanket_impl = generate_blanket_impl(&dyn_trait, &original_trait, &method_impls);
+ let dyn_trait_name = &dyn_trait.ident;
+ let (impl_generics, ty_generics, where_clause) = dyn_trait.generics.split_for_impl();
+
let expanded = quote! {
#original_trait
#(#dyn_trait_attrs)*
#dyn_trait
+ // assert that dyn_trait can actually be made into an object
+ impl #impl_generics dyn #dyn_trait_name #ty_generics #where_clause {}
+
#(#blanket_impl_attrs)*
#blanket_impl
};
@@ -432,3 +438,7 @@ fn path_segment_for_trait(sometrait: &ItemTrait) -> PathSegment {
},
}
}
+
+#[doc = include_str!("../tests/doctests.md")]
+#[cfg(doctest)]
+struct Doctests;
diff --git a/tests/doctests.md b/tests/doctests.md
new file mode 100644
index 0000000..ef557fe
--- /dev/null
+++ b/tests/doctests.md
@@ -0,0 +1,19 @@
+Tests that the object-safety assertion via `impl dyn` is working:
+
+```rust compile_fail
+trait ObjectUnsafe: Sized {}
+
+#[dynamize::dynamize]
+trait Trait: ObjectUnsafe {}
+```
+
+```rust compile_fail
+trait ObjectUnsafe: Sized {}
+
+#[dynamize::dynamize]
+trait Trait {
+ type A: ObjectUnsafe;
+
+ fn f(&self) -> Self::A;
+}
+```