I’m writing a macro_rules!
macro that generates struct definitions with a provided field type T
. I then want to implement various traits on said struct when possible. One example is that I want to implement Clone
, Copy
, etc. for the struct whenever T
is Clone
, Copy
, etc. I’m trying to use trait bounds on T
to do this, like so:
macro_rules! make_thing {
($name:ident : $t:ty) => {
struct $name($t);
impl Clone for $name where $t: Clone {
fn clone(&self) -> Self { Self(self.0.clone()) }
}
};
}
For Clone
types, this works fine. However, if I try to provide it with a non-Clone
field type, I get an error:
struct Bar;
make_thing! { Foo : Bar }
error[E0277]: the trait bound `Bar: Clone` is not satisfied
--> src/lib.rs:68:36
|
68 | impl Clone for $name where $t: Clone {
| ^^^^^^^^^ the trait `Clone` is not implemented for `Bar`
...
74 | make_thing! { Foo : Bar }
| ------------------------- in this macro invocation
|
= help: see issue #48214
= note: this error originates in the macro `make_thing` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `Bar` with `#[derive(Clone)]`
|
73 + #[derive(Clone)]
74 | struct Bar;
Now in this toy example, I could just implement Clone
on Bar
and it would work. However, this is meant to be an exported macro in a library. My intention is to implement Clone
when possible, but not implement it otherwise. But Rust seems to immediately reject an unsafisfiable where clause instead of just treating it like any ordinary false where clause and silently ignoring the impl.
Are there any tricks that can be used to get around this? I want to avoid making users of this library manually (and conditionally) implement the traits themselves, so it would need to all be done in the macro.