From cf3e49aa1667fe619fa0d779609bee10f14ce71b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Fri, 10 Jan 2025 17:11:40 +0100 Subject: [PATCH] Add #[allow(unused_imports)] lint to unstable reexports (#21) Reexports marked as unstable no longer need to explicitly allow the unused_imports lint. --------- Co-authored-by: Josh McKinney --- example/src/lib.rs | 2 -- src/item_like.rs | 45 +++++++++++++++++++++++++++++++++++++++------ src/unstable.rs | 9 +++++++-- 3 files changed, 46 insertions(+), 10 deletions(-) diff --git a/example/src/lib.rs b/example/src/lib.rs index d2c1489..95ab695 100644 --- a/example/src/lib.rs +++ b/example/src/lib.rs @@ -265,7 +265,6 @@ pub use private::private_function as stable_reexport; /// /// This re-export is unstable. #[instability::unstable(feature = "reexport")] -#[allow(unused_imports)] pub use private::private_function as unstable_reexport; // This does not work as the unstable_private_function is only public within the crate and cannot @@ -281,5 +280,4 @@ pub use private::private_function as unstable_reexport; /// section of the unstable_private_function, which will look odd. Consider avoiding re-exporting /// unstable items like this, and instead only mark the re-export itself as unstable. #[instability::unstable(feature = "reexport")] -#[allow(unused_imports)] pub use private::unstable_private_function as unstable_unstable_export; diff --git a/src/item_like.rs b/src/item_like.rs index e95d6fb..cfc1e1c 100644 --- a/src/item_like.rs +++ b/src/item_like.rs @@ -15,11 +15,33 @@ pub trait ItemLike: Stability { fn is_public(&self) -> bool { matches!(self.visibility(), Visibility::Public(_)) } + + fn allowed_lints(&self) -> Vec; } -macro_rules! impl_has_visibility { -($($ty:ty),+ $(,)?) => { - $( +/// Implement `ItemLike` for the given type. +/// +/// This makes each of the syn::Item* types implement our `ItemLike` trait to make it possible to +/// work with them in a more uniform way. +/// +/// A single type can be passed to this macro, or multiple types can be passed at once. +/// Each type can be passed with a list of lints that are allowed for that type (defaulting to +/// `dead_code` if not specified). +macro_rules! impl_item_like { + // run impl_item_like for each item in a list of items + ($($(#[allow($($lint:ident),*)])? $ty:ty ),+ ,) => { + $( + impl_item_like!($(#[allow($($lint),*)])? $ty ); + )* + }; + + // run impl_item_like for a single item without any lints + ($ty:ty) => { + impl_item_like!(#[allow(dead_code)] $ty ); + }; + + // Implement `ItemLike` for the given type. + (#[allow($($lint:ident),*)] $ty:ty) => { impl Stability for $ty { fn attrs(&self) -> &[syn::Attribute] { &self.attrs @@ -38,12 +60,18 @@ macro_rules! impl_has_visibility { fn set_visibility(&mut self, visibility: Visibility) { self.vis = visibility; } + + fn allowed_lints(&self) -> Vec { + vec![ + $(syn::Ident::new(stringify!($lint), proc_macro2::Span::call_site()),)* + ] + } } - )* -}; + }; + } -impl_has_visibility!( +impl_item_like!( syn::ItemType, syn::ItemEnum, syn::ItemFn, @@ -51,6 +79,7 @@ impl_has_visibility!( syn::ItemTrait, syn::ItemConst, syn::ItemStatic, + #[allow(unused_imports)] syn::ItemUse, ); @@ -79,6 +108,10 @@ impl ItemLike for syn::ItemStruct { self.vis = visibility; } + + fn allowed_lints(&self) -> Vec { + vec![syn::Ident::new("dead_code", proc_macro2::Span::call_site())] + } } impl Stability for syn::ItemImpl { diff --git a/src/unstable.rs b/src/unstable.rs index 70bd595..2bbc7d7 100644 --- a/src/unstable.rs +++ b/src/unstable.rs @@ -59,13 +59,18 @@ impl UnstableAttribute { let mut hidden_item = item.clone(); hidden_item.set_visibility(parse_quote! { pub(crate) }); + let allows = item + .allowed_lints() + .into_iter() + .map(|ident| quote! { #[allow(#ident)] }); + quote! { #[cfg(any(doc, feature = #feature_flag))] #[cfg_attr(docsrs, doc(cfg(feature = #feature_flag)))] #item #[cfg(not(any(doc, feature = #feature_flag)))] - #[allow(dead_code)] + #(#allows)* #hidden_item } } @@ -383,7 +388,7 @@ mod tests { pub use crate::foo::bar; #[cfg(not(any(doc, feature = "unstable")))] - #[allow(dead_code)] + #[allow(unused_imports)] #[doc = #DEFAULT_DOC] pub(crate) use crate::foo::bar; };