Repository: bitflags/bitflags (Rust)

Issue:
Allow specifying attributes in `impl` mode
I'm considering `cfg`-gating the use of `bitflags!` in my libraries, and to that end it would be nice if it was possible to apply attributes to the generated `impl`s as well.

The naive solution would be:
```rust
pub struct Flags(u8);

#[cfg(feature = "bitflags")]
bitflags! {
    impl Flags: u8 {
        // ...
    }
}
```

However, that works poorly with the `doc_cfg` (and `doc_auto_cfg`) feature, as the attribute is only applied to the macro, and isn't passed down to each output item.

Instead, I would like to be able to do the following:
```rust
#![feature(doc_cfg)]

pub struct Flags(u8);

#[cfg(feature = "bitflags")]
bitflags! {
    #[doc(cfg(feature = "bitflags"))]
    impl Flags: u8 {
        // ...
    }
}
```


Discussion:
Thanks for the report @madsmtm! Anywhere attributes are allowed to be specified we should support in the macros as much as possible. I think this is just a missing piece of functionality for the impl mode.



Patch:
diff --git a/src/lib.rs b/src/lib.rs
index 8f722591..b5e8911b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -38,7 +38,7 @@ bitflags! {
 
 See the docs for the `bitflags` macro for the full syntax.
 
-Also see the [`example_generated`] module for an example of what the `bitflags` macro generates for a flags type.
+Also see the [`example_generated`](./example_generated/index.html) module for an example of what the `bitflags` macro generates for a flags type.
 
 ### Externally defined flags
 
@@ -530,6 +530,7 @@ macro_rules! bitflags {
         }
     };
     (
+        $(#[$outer:meta])*
         impl $BitFlags:ident: $T:ty {
             $(
                 $(#[$inner:ident $($args:tt)*])*
@@ -561,6 +562,7 @@ macro_rules! bitflags {
         )]
         const _: () = {
             $crate::__impl_public_bitflags! {
+                $(#[$outer])*
                 $BitFlags: $T, $BitFlags {
                     $(
                         $(#[$inner $($args)*])*
@@ -593,6 +595,7 @@ macro_rules! bitflags {
 #[doc(hidden)]
 macro_rules! __impl_bitflags {
     (
+        $(#[$outer:meta])*
         $PublicBitFlags:ident: $T:ty {
             fn empty() $empty:block
             fn all() $all:block
@@ -617,6 +620,7 @@ macro_rules! __impl_bitflags {
         }
     ) => {
         #[allow(dead_code, deprecated, unused_attributes)]
+        $(#[$outer])*
         impl $PublicBitFlags {
             /// Get a flags value with all bits unset.
             #[inline]
diff --git a/src/public.rs b/src/public.rs
index dc2d7267..feecdd67 100644
--- a/src/public.rs
+++ b/src/public.rs
@@ -26,9 +26,11 @@ macro_rules! __declare_public_bitflags {
 #[doc(hidden)]
 macro_rules! __impl_public_bitflags_forward {
     (
+        $(#[$outer:meta])*
         $PublicBitFlags:ident: $T:ty, $InternalBitFlags:ident
     ) => {
         $crate::__impl_bitflags! {
+            $(#[$outer])*
             $PublicBitFlags: $T {
                 fn empty() {
                     Self($InternalBitFlags::empty())
@@ -128,6 +130,7 @@ macro_rules! __impl_public_bitflags_forward {
 #[doc(hidden)]
 macro_rules! __impl_public_bitflags {
     (
+        $(#[$outer:meta])*
         $BitFlags:ident: $T:ty, $PublicBitFlags:ident {
             $(
                 $(#[$inner:ident $($args:tt)*])*
@@ -136,6 +139,7 @@ macro_rules! __impl_public_bitflags {
         }
     ) => {
         $crate::__impl_bitflags! {
+            $(#[$outer])*
             $BitFlags: $T {
                 fn empty() {
                     Self(<$T as $crate::Bits>::EMPTY)
@@ -271,7 +275,11 @@ macro_rules! __impl_public_bitflags {
 #[macro_export]
 #[doc(hidden)]
 macro_rules! __impl_public_bitflags_iter {
-    ($BitFlags:ident: $T:ty, $PublicBitFlags:ident) => {
+    (
+        $(#[$outer:meta])*
+        $BitFlags:ident: $T:ty, $PublicBitFlags:ident
+    ) => {
+        $(#[$outer])*
         impl $BitFlags {
             /// Yield a set of contained flags values.
             ///
@@ -300,6 +308,7 @@ macro_rules! __impl_public_bitflags_iter {
             }
         }
 
+        $(#[$outer:meta])*
         impl $crate::__private::core::iter::IntoIterator for $BitFlags {
             type Item = $PublicBitFlags;
             type IntoIter = $crate::iter::Iter<$PublicBitFlags>;
@@ -315,7 +324,12 @@ macro_rules! __impl_public_bitflags_iter {
 #[macro_export]
 #[doc(hidden)]
 macro_rules! __impl_public_bitflags_ops {
-    ($PublicBitFlags:ident) => {
+    (
+        $(#[$outer:meta])*
+        $PublicBitFlags:ident
+    ) => {
+
+        $(#[$outer])*
         impl $crate::__private::core::fmt::Binary for $PublicBitFlags {
             fn fmt(
                 &self,
@@ -326,6 +340,7 @@ macro_rules! __impl_public_bitflags_ops {
             }
         }
 
+        $(#[$outer])*
         impl $crate::__private::core::fmt::Octal for $PublicBitFlags {
             fn fmt(
                 &self,
@@ -336,6 +351,7 @@ macro_rules! __impl_public_bitflags_ops {
             }
         }
 
+        $(#[$outer])*
         impl $crate::__private::core::fmt::LowerHex for $PublicBitFlags {
             fn fmt(
                 &self,
@@ -346,6 +362,7 @@ macro_rules! __impl_public_bitflags_ops {
             }
         }
 
+        $(#[$outer])*
         impl $crate::__private::core::fmt::UpperHex for $PublicBitFlags {
             fn fmt(
                 &self,
@@ -356,6 +373,7 @@ macro_rules! __impl_public_bitflags_ops {
             }
         }
 
+        $(#[$outer])*
         impl $crate::__private::core::ops::BitOr for $PublicBitFlags {
             type Output = Self;
 
@@ -366,6 +384,7 @@ macro_rules! __impl_public_bitflags_ops {
             }
         }
 
+        $(#[$outer])*
         impl $crate::__private::core::ops::BitOrAssign for $PublicBitFlags {
             /// The bitwise or (`|`) of the bits in two flags values.
             #[inline]
@@ -374,6 +393,7 @@ macro_rules! __impl_public_bitflags_ops {
             }
         }
 
+        $(#[$outer])*
         impl $crate::__private::core::ops::BitXor for $PublicBitFlags {
             type Output = Self;
 
@@ -384,6 +404,7 @@ macro_rules! __impl_public_bitflags_ops {
             }
         }
 
+        $(#[$outer])*
         impl $crate::__private::core::ops::BitXorAssign for $PublicBitFlags {
             /// The bitwise exclusive-or (`^`) of the bits in two flags values.
             #[inline]
@@ -392,6 +413,7 @@ macro_rules! __impl_public_bitflags_ops {
             }
         }
 
+        $(#[$outer])*
         impl $crate::__private::core::ops::BitAnd for $PublicBitFlags {
             type Output = Self;
 
@@ -402,6 +424,7 @@ macro_rules! __impl_public_bitflags_ops {
             }
         }
 
+        $(#[$outer])*
         impl $crate::__private::core::ops::BitAndAssign for $PublicBitFlags {
             /// The bitwise and (`&`) of the bits in two flags values.
             #[inline]
@@ -410,6 +433,7 @@ macro_rules! __impl_public_bitflags_ops {
             }
         }
 
+        $(#[$outer])*
         impl $crate::__private::core::ops::Sub for $PublicBitFlags {
             type Output = Self;
 
@@ -423,6 +447,7 @@ macro_rules! __impl_public_bitflags_ops {
             }
         }
 
+        $(#[$outer])*
         impl $crate::__private::core::ops::SubAssign for $PublicBitFlags {
             /// The intersection of a source flags value with the complement of a target flags value (`&!`).
             ///
@@ -434,6 +459,7 @@ macro_rules! __impl_public_bitflags_ops {
             }
         }
 
+        $(#[$outer])*
         impl $crate::__private::core::ops::Not for $PublicBitFlags {
             type Output = Self;
 
@@ -444,6 +470,7 @@ macro_rules! __impl_public_bitflags_ops {
             }
         }
 
+        $(#[$outer])*
         impl $crate::__private::core::iter::Extend<$PublicBitFlags> for $PublicBitFlags {
             /// The bitwise or (`|`) of the bits in each flags value.
             fn extend<T: $crate::__private::core::iter::IntoIterator<Item = Self>>(
@@ -456,6 +483,7 @@ macro_rules! __impl_public_bitflags_ops {
             }
         }
 
+        $(#[$outer])*
         impl $crate::__private::core::iter::FromIterator<$PublicBitFlags> for $PublicBitFlags {
             /// The bitwise or (`|`) of the bits in each flags value.
             fn from_iter<T: $crate::__private::core::iter::IntoIterator<Item = Self>>(
@@ -476,6 +504,7 @@ macro_rules! __impl_public_bitflags_ops {
 #[doc(hidden)]
 macro_rules! __impl_public_bitflags_consts {
     (
+        $(#[$outer:meta])*
         $PublicBitFlags:ident: $T:ty {
             $(
                 $(#[$inner:ident $($args:tt)*])*
@@ -483,6 +512,7 @@ macro_rules! __impl_public_bitflags_consts {
             )*
         }
     ) => {
+        $(#[$outer])*
         impl $PublicBitFlags {
             $(
                 $crate::__bitflags_flag!({
@@ -500,6 +530,7 @@ macro_rules! __impl_public_bitflags_consts {
             )*
         }
 
+        $(#[$outer])*
         impl $crate::Flags for $PublicBitFlags {
             const FLAGS: &'static [$crate::Flag<$PublicBitFlags>] = &[
                 $(


Test patch:
diff --git a/tests/compile-pass/bitflags_impl_attrs.rs b/tests/compile-pass/bitflags_impl_attrs.rs
new file mode 100644
index 00000000..91d89823
--- /dev/null
+++ b/tests/compile-pass/bitflags_impl_attrs.rs
@@ -0,0 +1,13 @@
+extern crate bitflags;
+
+struct Example(u64);
+
+bitflags::bitflags! {
+    /// Docs on the `impl` block.
+    #[allow(dead_code)]
+    impl Example: u64 {
+        const flag = 0b01;
+    }
+}
+
+fn main() {}