From 775fcc21f5e4007fe2998eee1cc68f06d1830200 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Tue, 12 May 2026 13:19:14 +0100 Subject: [PATCH 1/4] examples: fix incorrect drop Remove the drop and associated clippy allow. The warning reported by Clippy here is genuine; the binding created is `Pin<&mut T>` so dropping it does nothing. `stack_pin_init` created bindings are only dropped at the end of scope. Signed-off-by: Gary Guo --- examples/mutex.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/examples/mutex.rs b/examples/mutex.rs index 35ecb5f6..882f3e23 100644 --- a/examples/mutex.rs +++ b/examples/mutex.rs @@ -91,7 +91,7 @@ impl CMutex { pub fn lock(&self) -> Pin> { let mut sguard = self.spin_lock.acquire(); if self.locked.get() { - stack_pin_init!(let wait_entry = WaitEntry::insert_new(&self.wait_list)); + stack_pin_init!(let _wait_entry = WaitEntry::insert_new(&self.wait_list)); // println!("wait list length: {}", self.wait_list.size()); while self.locked.get() { drop(sguard); @@ -99,9 +99,6 @@ impl CMutex { thread::park(); sguard = self.spin_lock.acquire(); } - // This does have an effect, as the ListHead inside wait_entry implements Drop! - #[expect(clippy::drop_non_drop)] - drop(wait_entry); } self.locked.set(true); unsafe { From 51af11da758750ec953e87b320ec2d9bfd0547aa Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Tue, 12 May 2026 13:20:26 +0100 Subject: [PATCH 2/4] remove redundant clippy expects in doc tests These lints are automatically suppressed inside doc tests. Previously this is needed because kernel builds doc tests with the default set of clippy flags; but now `clippy::disallowed_names` is globally allowed inside doc tests. Signed-off-by: Gary Guo --- src/lib.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index fd40c8f2..90e9d501 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -70,7 +70,6 @@ //! that you need to write `<-` instead of `:` for fields that you want to initialize in-place. //! //! ```rust -//! # #![expect(clippy::disallowed_names)] //! # #![feature(allocator_api)] //! # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*; //! # use core::pin::Pin; @@ -94,7 +93,6 @@ //! (or just the stack) to actually initialize a `Foo`: //! //! ```rust -//! # #![expect(clippy::disallowed_names)] //! # #![feature(allocator_api)] //! # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*; //! # use core::{alloc::AllocError, pin::Pin}; @@ -456,7 +454,6 @@ pub use ::pin_init_internal::MaybeZeroable; /// # Examples /// /// ```rust -/// # #![expect(clippy::disallowed_names)] /// # #![feature(allocator_api)] /// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*; /// # use pin_init::*; @@ -508,7 +505,6 @@ macro_rules! stack_pin_init { /// # Examples /// /// ```rust -/// # #![expect(clippy::disallowed_names)] /// # #![feature(allocator_api)] /// # #[path = "../examples/error.rs"] mod error; use error::Error; /// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*; @@ -535,7 +531,6 @@ macro_rules! stack_pin_init { /// ``` /// /// ```rust -/// # #![expect(clippy::disallowed_names)] /// # #![feature(allocator_api)] /// # #[path = "../examples/error.rs"] mod error; use error::Error; /// # #[path = "../examples/mutex.rs"] mod mutex; use mutex::*; @@ -658,7 +653,6 @@ macro_rules! stack_try_pin_init { /// Users of `Foo` can now create it like this: /// /// ```rust -/// # #![expect(clippy::disallowed_names)] /// # use pin_init::*; /// # use core::pin::Pin; /// # #[pin_data] @@ -1031,7 +1025,6 @@ pub unsafe trait Init: PinInit { /// # Examples /// /// ```rust - /// # #![expect(clippy::disallowed_names)] /// use pin_init::{init, init_zeroed, Init}; /// /// struct Foo { From e54f16f7d8d07ec78a8d751b7ebaefa676abd346 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Tue, 12 May 2026 13:23:18 +0100 Subject: [PATCH 3/4] internal: stop using `expect` in macro expansion Most warnings are suppressed from external macro expansions by default, and `unfulfilled_lint_expectations` is one of them. All of our `expect`s inside macros therefore do nothing, and actually mislead people to the lints would be actually emitted without them. All `#[expect]`s on lints that do not fire inside external macros (and without spans from users) are removed, while the rest is coverted to `#[allow]`. Signed-off-by: Gary Guo --- internal/src/init.rs | 2 +- internal/src/pin_data.rs | 3 --- tests/ui/expand/many_generics.expanded.rs | 1 - tests/ui/expand/pin-data.expanded.rs | 3 --- tests/ui/expand/pinned_drop.expanded.rs | 1 - tests/ui/expand/simple-init.expanded.rs | 2 +- 6 files changed, 2 insertions(+), 10 deletions(-) diff --git a/internal/src/init.rs b/internal/src/init.rs index 28d30805..c1197a99 100644 --- a/internal/src/init.rs +++ b/internal/src/init.rs @@ -334,7 +334,7 @@ fn make_field_check( }), }; quote! { - #[allow(unreachable_code, clippy::diverging_sub_expression)] + #[allow(unreachable_code)] // We use unreachable code to perform field checks. They're still checked by the compiler. // SAFETY: this code is never executed. let _ = || unsafe { diff --git a/internal/src/pin_data.rs b/internal/src/pin_data.rs index 263f6730..44381076 100644 --- a/internal/src/pin_data.rs +++ b/internal/src/pin_data.rs @@ -245,7 +245,6 @@ fn generate_drop_impl(ident: &Ident, generics: &Generics, args: Args) -> TokenSt // `Drop`. Additionally we will implement this trait for the struct leading to a conflict, // if it also implements `Drop` trait MustNotImplDrop {} - #[expect(drop_bounds)] impl MustNotImplDrop for T {} impl #impl_generics MustNotImplDrop for #ident #ty_generics #whr @@ -253,7 +252,6 @@ fn generate_drop_impl(ident: &Ident, generics: &Generics, args: Args) -> TokenSt // We also take care to prevent users from writing a useless `PinnedDrop` implementation. // They might implement `PinnedDrop` correctly for the struct, but forget to give // `PinnedDrop` as the parameter to `#[pin_data]`. - #[expect(non_camel_case_types)] trait UselessPinnedDropImpl_you_need_to_specify_PinnedDrop {} impl UselessPinnedDropImpl_you_need_to_specify_PinnedDrop for T {} @@ -432,7 +430,6 @@ fn generate_the_pin_data( {} #[allow(dead_code)] // Some functions might never be used and private. - #[expect(clippy::missing_safety_doc)] impl #impl_generics __ThePinData #ty_generics #whr { diff --git a/tests/ui/expand/many_generics.expanded.rs b/tests/ui/expand/many_generics.expanded.rs index 5e182d65..e5dd67f7 100644 --- a/tests/ui/expand/many_generics.expanded.rs +++ b/tests/ui/expand/many_generics.expanded.rs @@ -72,7 +72,6 @@ const _: () = { T: Bar<'a, 1>, {} #[allow(dead_code)] - #[expect(clippy::missing_safety_doc)] impl< 'a, 'b: 'a, diff --git a/tests/ui/expand/pin-data.expanded.rs b/tests/ui/expand/pin-data.expanded.rs index 12f1596f..0df053da 100644 --- a/tests/ui/expand/pin-data.expanded.rs +++ b/tests/ui/expand/pin-data.expanded.rs @@ -44,7 +44,6 @@ const _: () = { } impl ::core::marker::Copy for __ThePinData {} #[allow(dead_code)] - #[expect(clippy::missing_safety_doc)] impl __ThePinData { /// Type inference helper function. #[inline(always)] @@ -111,10 +110,8 @@ const _: () = { __Unpin<'__pin>: ::core::marker::Unpin, {} trait MustNotImplDrop {} - #[expect(drop_bounds)] impl MustNotImplDrop for T {} impl MustNotImplDrop for Foo {} - #[expect(non_camel_case_types)] trait UselessPinnedDropImpl_you_need_to_specify_PinnedDrop {} impl< T: ::pin_init::PinnedDrop + ?::core::marker::Sized, diff --git a/tests/ui/expand/pinned_drop.expanded.rs b/tests/ui/expand/pinned_drop.expanded.rs index 4cd7407d..6b971eeb 100644 --- a/tests/ui/expand/pinned_drop.expanded.rs +++ b/tests/ui/expand/pinned_drop.expanded.rs @@ -44,7 +44,6 @@ const _: () = { } impl ::core::marker::Copy for __ThePinData {} #[allow(dead_code)] - #[expect(clippy::missing_safety_doc)] impl __ThePinData { /// Type inference helper function. #[inline(always)] diff --git a/tests/ui/expand/simple-init.expanded.rs b/tests/ui/expand/simple-init.expanded.rs index ee3d0096..d001aa69 100644 --- a/tests/ui/expand/simple-init.expanded.rs +++ b/tests/ui/expand/simple-init.expanded.rs @@ -11,7 +11,7 @@ fn main() { _, ::core::convert::Infallible, >(move |slot| { - #[allow(unreachable_code, clippy::diverging_sub_expression)] + #[allow(unreachable_code)] let _ = || unsafe { ::core::ptr::write(slot, Foo {}) }; Ok(unsafe { ::pin_init::__internal::InitOk::new() }) }); From d3bb96d6e72ddfd9d1ee5b347fd3b4addc2031f4 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Fri, 10 Jul 2026 14:16:41 +0100 Subject: [PATCH 4/4] internal: generate brace in macro for init code blocks `init!` support interleaving code execution and initialization, and code execution is done using `_: { ... }` syntax. If the code inside block is a single statement, Rust may add a lint about unused braces, but the suggestion will be incorrect as block is required by pin-init. Currently we use `unused_brace` to suppress this, but this affect everything nested inside as well. Use an alternative approach by generating the block from the macro, then rustc will know to not emit the lint. Signed-off-by: Gary Guo --- internal/src/init.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/internal/src/init.rs b/internal/src/init.rs index c1197a99..fd0b5ea4 100644 --- a/internal/src/init.rs +++ b/internal/src/init.rs @@ -233,10 +233,12 @@ fn init_fields( InitializerKind::Value { ident, .. } => ident, InitializerKind::Init { ident, .. } => ident, InitializerKind::Code { block, .. } => { + let stmt = &block.stmts; res.extend(quote! { #(#attrs)* - #[allow(unused_braces)] - #block + { + #(#stmt)* + } }); continue; }