Quoting my answer from the Github issue:
It is intentional (here is the historical
record), but there is a
possibility the situation could be improved in the future, and at
least the error message should be rewritten to explain why it refuses
to compile.
The underlying issue is that #[derive]
macros need to "forward"
their trait requirements to all the fields of the struct. For
MyStruct
to be Debug
, the type of field
must also be Debug
.
Consider this one:
#[derive(Debug)] struct MyStruct<T: FromStr> {
field: T
}
We need to generate impl<T: FromStr> Debug for MyStruct<T> where T:
Debug { ... }
(you'll see why I picked
FromStr
in a
second). However in this case:
#[derive(Debug)] struct MyStruct<T> {
field: T::Err
}
Here the field is an associated type, so the generated code actually
needs to be impl<T: FromStr> Debug for MyStruct<T> where T::Err:
Debug { ... }
.
The derive macros actually scan the field types to see whether they
need to bound T
or an associated type. But if you use a type macro,
this breaks. The code generation can't see through the macro, so it
doesn't know what bounds to generate.
When this was discovered we couldn't decide whether to let the type
macro be expanded eagerly (seems like you could get into a loop or
ordering issues), just copy the macro into the where
clause (derives
normally don't do this because it could expand to a private type,
causing type errors in generated code), or something
else, so we punted and
made it an error.
The problem can't really be fixed while obeying the "policies" of deriving: (1) it generates the bounds for you, and (2) it only generates code that compiles. But since custom derive is stable, there are crates you can use, like derivative, that sidestep the problem by letting you rewrite the bound:
#[derive(Derivative)]
#[derivative(Debug)]
struct MyStruct<T> {
#[derivative(Debug(bound="T: ::std::fmt::Debug"))]
field_list: [T; count!()],
}