Open taiki-e opened 4 years ago
This is a bug, but I'm not sure if it can be fully fixed.
This also affects doc-comment on fields (as that is actually#[doc = "..."]
attributes).
Another case: https://github.com/taiki-e/pin-project-lite/pull/28#issuecomment-702176944
The
#[project]
(and#[project_ref]
) attribute must precede the other attributes except for#[doc]
:pin_project! { /// documents (`#[doc]`) can be placed before `#[project]`. #[derive(Clone)] // <--- Error #[project = EnumProj] #[derive(Debug)] // <--- Ok enum Enum<T, U> { Struct { #[pin] pinned: T, unpinned: U, }, Unit, } }
Workaround: If the attribute is #[doc]
(doc comment), this can be avoided by changing it to normal comment.
pin_project! {
#[derive(serde::Deserialize)]
struct Struct1<T, U> {
- /// description
+ // description
pinned: Option<T>,
unpinned: U,
}
}
Note: This issue is about attributes that apply only to the original struct/enum.
Proper handling of cfg/cfg_attr on fields and variants requires a more complex approach than the fix for this (it needs to be aware of the kind of attribute and propagate some of it to projected type). Even pin-project could not find the correct solution other than "leave to the compiler". And it is impossible to use the same trick in pin-project-lite.
See https://github.com/taiki-e/pin-project/issues/68#issuecomment-528318870 and https://github.com/hyperium/hyper/issues/2388#issuecomment-758304097 for a known workaround of the cfg issue.
(The cfg issue is not a "limitation that may be fixed" but a "limitation that is considered impossible to fix" and is a similar category as "wontfix". Actually, pin-project-lite cannot handle it properly on both fields and variants.)
I have written a macro as a workaround for #[cfg]
attributes on enum variants and fields.
https://gist.github.com/tesaguri/2a1c0790a48bbda3dd7f71c26d02a793
What this does is to rewrite something like this:
enum Foo {
#[cfg(a)]
A { /* ... */ }
#[cfg(b)]
B { /* ... */ }
}
to this:
#[cfg(all(a, b))]
enum Foo {
A { /* ... */ }
B { /* ... */ }
}
#[cfg(all(a, not(b)))]
enum Foo {
A { /* ... */ }
}
#[cfg(all(not(a), b))]
enum Foo {
B { /* ... */ }
}
#[cfg(all(not(a), not(b)))]
enum Foo {
}
and pass the token tree to pin_project!
.
Workaround: If the attribute is #[doc] (doc comment), this can be avoided by changing it to normal comment.
This doesn't work if you actually want the comment in the generated documentation. And if you have #![deny(missing_docs)]
enabled on your crate, you are really in a pickle, because if the field is public, it will give you an error if it isn't documented, and you can't use #[allow(missing_docs)]
or #[doc(hidden)]
either.
In the current implementation, an error will occur if the field has an attribute other than
#[pin]
.