Skip to contentSkip to conversation

rust: pin-init upstream sync for v7.2 (round 1)

PATCH Applied Gary Guo 1 participant 13 messages Apr 28 – May 10

Subsystems (2)
lore
Share & tools
lore

Gary Guo

author maintainer
#0 lore raw

cover rust: pin-init upstream sync for v7.2 (round 1)

This series collects all upstream developments of pin-init to date and synchronize them to the kernel tree.

Last cycle Benno sent a single sync late in the development cycle, but I expect a lot of developments this cycle so I'll probably be sending multiple of them; for bigger changes they'll be sent as their own series instead of part of a round of sync.

A major change in this cycle is the bump of MSRV to 1.82 to get rid of unstable features, following the kernel version bump in 7.1. The MSRV is bumped straight to 1.85 as pin-init can also be used outside kernel, so we avoid bumping unless there is a need for new version.

Here are the list of merged changes included in the series:

- examples: mark as #[inline] all From::from()s for Error
https://github.com/Rust-for-Linux/pin-init/pull/126
- bump minimum Rust version to 1.82
https://github.com/Rust-for-Linux/pin-init/pull/129
- cleanup Zeroable and ZeroableOptions
https://github.com/Rust-for-Linux/pin-init/pull/118
- internal: add missing where clause to projection types
https://github.com/Rust-for-Linux/pin-init/pull/121
- internal: internal: remove redundant #[pin] filtering
https://github.com/Rust-for-Linux/pin-init/pull/131
- add mailmap and relicense internal/zeroable.rs & .clippy.toml
https://github.com/Rust-for-Linux/pin-init/pull/137

Here are the list of changes that I intend to merge soon to upstream pin-init, which I also included in the series:

- cleanup workaround for old Rust compiler
https://github.com/Rust-for-Linux/pin-init/pull/141
- internal: turn PhantomPinned error into warnings
https://github.com/Rust-for-Linux/pin-init/pull/135

For information, here are the list of upstream-only changes, which are related to Cargo or tests/CI changes only.

- build.rs: use option_env! to register env variable dependency
https://github.com/Rust-for-Linux/pin-init/pull/128
- clean up dependencies
https://github.com/Rust-for-Linux/pin-init/pull/130
- tests: add test for check correct macro hygiene
https://github.com/Rust-for-Linux/pin-init/pull/133
- ci: use tagged release of actions
https://github.com/Rust-for-Linux/pin-init/pull/134
- ci: have a single job to gate all required jobs
https://github.com/Rust-for-Linux/pin-init/pull/138
- ci: various cleanups
https://github.com/Rust-for-Linux/pin-init/pull/139

Best,
Gary

---
Alistair Francis (1):
rust: pin-init: examples: mark as #[inline] all From::from()s for Error

Benno Lossin (1):
rust: pin-init: internal: adjust license identifier of zeroable.rs

Gary Guo (5):
rust: pin-init: bump minimum Rust version to 1.82
rust: pin-init: internal: remove redundant #[pin] filtering
rust: pin-init: fix badge URL in README
rust: pin-init: cleanup workaround for old Rust compiler
rust: pin-init: internal: turn PhantomPinned error into warnings

Mohamad Alsadhan (3):
rust: pin-init: cleanup Zeroable and ZeroableOptions
rust: pin-init: extend impl_zeroable_option macro to handle generics
rust: pin-init: internal: add missing where clause to projection types

 rust/pin-init/README.md                       |  2 +-
 rust/pin-init/examples/big_struct_in_place.rs |  3 -
 rust/pin-init/examples/error.rs               |  2 +
 rust/pin-init/examples/linked_list.rs         |  2 -
 rust/pin-init/examples/mutex.rs               |  2 -
 rust/pin-init/examples/pthread_mutex.rs       |  2 -
 rust/pin-init/examples/static_init.rs         |  2 -
 rust/pin-init/internal/src/diagnostics.rs     | 14 +++++
 rust/pin-init/internal/src/init.rs            |  9 +--
 rust/pin-init/internal/src/lib.rs             |  1 -
 rust/pin-init/internal/src/pin_data.rs        | 10 ++--
 rust/pin-init/internal/src/zeroable.rs        |  2 +-
 rust/pin-init/src/lib.rs                      | 79 ++++++++++-----------------
 13 files changed, 52 insertions(+), 78 deletions(-)

---
base-commit: 1c7cc4904160c6fc6377564140062d68a3dc93a0
change-id: 20260414-pin-init-sync-ae407945a726

Best regards,

Signature · 1 line
Gary Guo <[email protected]>
author maintainer
#1 lore raw

PATCH 1/10 rust: pin-init: examples: mark as `#[inline]` all `From::from()`s for `Error`

From: Alistair Francis <[email protected]>

There was a recent request in kernel [1] to mark as #[inline] the simple From::from() functions implemented for Error.

Thus mark all of the existing

    impl From<...> for Error {
        fn from(err: ...) -> Self {
            ...
        }
    }

functions as #[inline].

While in pin-init crate the relevant code is just examples, it nevertheless does not hurt to use good practice for them.

---
 rust/pin-init/examples/error.rs | 2 ++
 1 file changed, 2 insertions(+)
rust/pin-init/examples/error.rs +2 -0
index 8f4e135eb8ba..96f095398e8d 100644
@@ -11,6 +11,7 @@
 pub struct Error;
 
 impl From<Infallible> for Error {
+    #[inline]
     fn from(e: Infallible) -> Self {
         match e {}
     }
@@ -18,6 +19,7 @@ fn from(e: Infallible) -> Self {
 
 #[cfg(feature = "alloc")]
 impl From<AllocError> for Error {
+    #[inline]
     fn from(_: AllocError) -> Self {
         Self
     }
Signature · 1 line
2.51.2
author maintainer
#2 lore raw

PATCH 2/10 rust: pin-init: bump minimum Rust version to 1.82

In reply to Gary Guo

Following the kernel minimum version bump in commit f32fb9c58a5b ("rust:
bump Rust minimum supported version to 1.85.0 (Debian Trixie)"), bump pin-init's minimum Rust version to 1.82.

This removes the lint_reasons feature which is stabilized in 1.81 and the raw_ref_ops and new_uninit features which are stabilized in 1.82.

Given we do not use any features that are stabilized in 1.82..=1.85 range, and pin-init crate is useful for other projects which may have their own MSRV requirements, the minimum version is not straightly bumped to 1.85.

---
 rust/pin-init/examples/big_struct_in_place.rs | 3 ---
 rust/pin-init/examples/linked_list.rs         | 2 --
 rust/pin-init/examples/mutex.rs               | 2 --
 rust/pin-init/examples/pthread_mutex.rs       | 2 --
 rust/pin-init/examples/static_init.rs         | 2 --
 rust/pin-init/internal/src/lib.rs             | 1 -
 rust/pin-init/src/lib.rs                      | 6 ------
 7 files changed, 18 deletions(-)
rust/pin-init/examples/big_struct_in_place.rs +0 -3
index 80f89b5f8fd6..c05139927486 100644
@@ -1,8 +1,5 @@
 // SPDX-License-Identifier: Apache-2.0 OR MIT
 
-#![cfg_attr(USE_RUSTC_FEATURES, feature(lint_reasons))]
-#![cfg_attr(USE_RUSTC_FEATURES, feature(raw_ref_op))]
-
 use pin_init::*;
 
 // Struct with size over 1GiB
rust/pin-init/examples/linked_list.rs +0 -2
index 119169e4dc41..424585fe226d 100644
@@ -2,8 +2,6 @@
 
 #![allow(clippy::undocumented_unsafe_blocks)]
 #![cfg_attr(feature = "alloc", feature(allocator_api))]
-#![cfg_attr(USE_RUSTC_FEATURES, feature(lint_reasons))]
-#![cfg_attr(USE_RUSTC_FEATURES, feature(raw_ref_op))]
 
 use core::{
     cell::Cell,
rust/pin-init/examples/mutex.rs +0 -2
index d53671f0edb8..8ed2d3219eb1 100644
@@ -2,8 +2,6 @@
 
 #![allow(clippy::undocumented_unsafe_blocks)]
 #![cfg_attr(feature = "alloc", feature(allocator_api))]
-#![cfg_attr(USE_RUSTC_FEATURES, feature(lint_reasons))]
-#![cfg_attr(USE_RUSTC_FEATURES, feature(raw_ref_op))]
 #![allow(clippy::missing_safety_doc)]
 
 use core::{
rust/pin-init/examples/pthread_mutex.rs +0 -2
index f3b5cc9b7134..4a66316471af 100644
@@ -3,8 +3,6 @@
 // inspired by <https://github.com/nbdd0121/pin-init/blob/trunk/examples/pthread_mutex.rs>
 #![allow(clippy::undocumented_unsafe_blocks)]
 #![cfg_attr(feature = "alloc", feature(allocator_api))]
-#![cfg_attr(USE_RUSTC_FEATURES, feature(lint_reasons))]
-#![cfg_attr(USE_RUSTC_FEATURES, feature(raw_ref_op))]
 
 #[cfg(not(windows))]
 mod pthread_mtx {
rust/pin-init/examples/static_init.rs +0 -2
index f7e53d1a5ae6..906b96c5d4b9 100644
@@ -2,8 +2,6 @@
 
 #![allow(clippy::undocumented_unsafe_blocks)]
 #![cfg_attr(feature = "alloc", feature(allocator_api))]
-#![cfg_attr(USE_RUSTC_FEATURES, feature(lint_reasons))]
-#![cfg_attr(USE_RUSTC_FEATURES, feature(raw_ref_op))]
 #![allow(unused_imports)]
 
 use core::{
rust/pin-init/internal/src/lib.rs +0 -1
index b08dfe003031..60d5093f3128 100644
@@ -6,7 +6,6 @@
 
 //! `pin-init` proc macros.
 
-#![cfg_attr(USE_RUSTC_FEATURES, feature(lint_reasons))]
 // Documentation is done in the pin-init crate instead.
 #![allow(missing_docs)]
 
rust/pin-init/src/lib.rs +0 -6
index 64eec095c859..4f50994bd268 100644
@@ -263,12 +263,6 @@
 //! [`impl Init<T, E>`]: crate::Init
 //! [Rust-for-Linux]: https://rust-for-linux.com/
 
-#![cfg_attr(USE_RUSTC_FEATURES, feature(lint_reasons))]
-#![cfg_attr(USE_RUSTC_FEATURES, feature(raw_ref_op))]
-#![cfg_attr(
-    all(any(feature = "alloc", feature = "std"), USE_RUSTC_FEATURES),
-    feature(new_uninit)
-)]
 #![forbid(missing_docs, unsafe_op_in_unsafe_fn)]
 #![cfg_attr(not(feature = "std"), no_std)]
 #![cfg_attr(feature = "alloc", feature(allocator_api))]
Signature · 1 line
2.51.2
author maintainer
#3 lore raw

PATCH 3/10 rust: pin-init: cleanup `Zeroable` and `ZeroableOptions`

In reply to Gary Guo

From: Mohamad Alsadhan <[email protected]>

Place definitions and implementations (incl. macro invocations) of the Zeroable trait first in the relevant section of src/lib.rs, followed by the ZeroableOption trait and its implementations.

Rename impl_non_zero_int_zeroable_option to impl_zeroable_option for consistency.

This commit should not introduce any functional changes.

---
 rust/pin-init/src/lib.rs | 46 +++++++++++++++++++++++-----------------------
 1 file changed, 23 insertions(+), 23 deletions(-)
rust/pin-init/src/lib.rs +23 -23
index 4f50994bd268..e34c9bdb88c3 100644
@@ -1517,27 +1517,6 @@ fn zeroed() -> Self
     }
 }
 
-/// Marker trait for types that allow `Option<Self>` to be set to all zeroes in order to write
-/// `None` to that location.
-///
-/// # Safety
-///
-/// The implementer needs to ensure that `unsafe impl Zeroable for Option<Self> {}` is sound.
-pub unsafe trait ZeroableOption {}
-
-// SAFETY: by the safety requirement of `ZeroableOption`, this is valid.
-unsafe impl<T: ZeroableOption> Zeroable for Option<T> {}
-
-// SAFETY: `Option<&T>` is part of the option layout optimization guarantee:
-// <https://doc.rust-lang.org/stable/std/option/index.html#representation>.
-unsafe impl<T> ZeroableOption for &T {}
-// SAFETY: `Option<&mut T>` is part of the option layout optimization guarantee:
-// <https://doc.rust-lang.org/stable/std/option/index.html#representation>.
-unsafe impl<T> ZeroableOption for &mut T {}
-// SAFETY: `Option<NonNull<T>>` is part of the option layout optimization guarantee:
-// <https://doc.rust-lang.org/stable/std/option/index.html#representation>.
-unsafe impl<T> ZeroableOption for NonNull<T> {}
-
 /// Create an initializer for a zeroed `T`.
 ///
 /// The returned initializer will write `0x00` to every byte of the given `slot`.
@@ -1643,6 +1622,27 @@ unsafe impl<$first: Zeroable, $($t: Zeroable),*> Zeroable for ($first, $($t),*)
 
 impl_tuple_zeroable!(A, B, C, D, E, F, G, H, I, J);
 
+/// Marker trait for types that allow `Option<Self>` to be set to all zeroes in order to write
+/// `None` to that location.
+///
+/// # Safety
+///
+/// The implementer needs to ensure that `unsafe impl Zeroable for Option<Self> {}` is sound.
+pub unsafe trait ZeroableOption {}
+
+// SAFETY: by the safety requirement of `ZeroableOption`, this is valid.
+unsafe impl<T: ZeroableOption> Zeroable for Option<T> {}
+
+// SAFETY: `Option<&T>` is part of the option layout optimization guarantee:
+// <https://doc.rust-lang.org/stable/std/option/index.html#representation>.
+unsafe impl<T> ZeroableOption for &T {}
+// SAFETY: `Option<&mut T>` is part of the option layout optimization guarantee:
+// <https://doc.rust-lang.org/stable/std/option/index.html#representation>.
+unsafe impl<T> ZeroableOption for &mut T {}
+// SAFETY: `Option<NonNull<T>>` is part of the option layout optimization guarantee:
+// <https://doc.rust-lang.org/stable/std/option/index.html#representation>.
+unsafe impl<T> ZeroableOption for NonNull<T> {}
+
 macro_rules! impl_fn_zeroable_option {
     ([$($abi:literal),* $(,)?] $args:tt) => {
         $(impl_fn_zeroable_option!({extern $abi} $args);)*
@@ -1668,14 +1668,14 @@ unsafe impl<$ret, $($rest),*> ZeroableOption for $($prefix)* fn($($rest),*) -> $
 
 impl_fn_zeroable_option!(["Rust", "C"] { A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U });
 
-macro_rules! impl_non_zero_int_zeroable_option {
+macro_rules! impl_zeroable_option {
     ($($int:ty),* $(,)?) => {
         // SAFETY: Safety comment written in the macro invocation.
         $(unsafe impl ZeroableOption for $int {})*
     };
 }
 
-impl_non_zero_int_zeroable_option! {
+impl_zeroable_option! {
     // SAFETY: All zeros is equivalent to `None` (option layout optimization guarantee:
     // <https://doc.rust-lang.org/stable/std/option/index.html#representation>).
     NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize,
Signature · 1 line
2.51.2
author maintainer
#4 lore raw

PATCH 4/10 rust: pin-init: extend `impl_zeroable_option` macro to handle generics

In reply to Gary Guo

From: Mohamad Alsadhan <[email protected]>

Improve impl_zeroable_option macro to handle generic impls for types like &T, &mut T, NonNull<T>, and others (for which Option<T> is guaranteed to be zeroable) with similar approach to impl_zeroable.

Also, update old declarations to use generics e.g. NonZeroU8 to NonZero<u8>.

---
 rust/pin-init/src/lib.rs | 29 ++++++++++++++---------------
 1 file changed, 14 insertions(+), 15 deletions(-)
rust/pin-init/src/lib.rs +14 -15
index e34c9bdb88c3..9b76cf5597c6 100644
@@ -1633,16 +1633,6 @@ pub unsafe trait ZeroableOption {}
 // SAFETY: by the safety requirement of `ZeroableOption`, this is valid.
 unsafe impl<T: ZeroableOption> Zeroable for Option<T> {}
 
-// SAFETY: `Option<&T>` is part of the option layout optimization guarantee:
-// <https://doc.rust-lang.org/stable/std/option/index.html#representation>.
-unsafe impl<T> ZeroableOption for &T {}
-// SAFETY: `Option<&mut T>` is part of the option layout optimization guarantee:
-// <https://doc.rust-lang.org/stable/std/option/index.html#representation>.
-unsafe impl<T> ZeroableOption for &mut T {}
-// SAFETY: `Option<NonNull<T>>` is part of the option layout optimization guarantee:
-// <https://doc.rust-lang.org/stable/std/option/index.html#representation>.
-unsafe impl<T> ZeroableOption for NonNull<T> {}
-
 macro_rules! impl_fn_zeroable_option {
     ([$($abi:literal),* $(,)?] $args:tt) => {
         $(impl_fn_zeroable_option!({extern $abi} $args);)*
@@ -1669,17 +1659,26 @@ unsafe impl<$ret, $($rest),*> ZeroableOption for $($prefix)* fn($($rest),*) -> $
 impl_fn_zeroable_option!(["Rust", "C"] { A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U });
 
 macro_rules! impl_zeroable_option {
-    ($($int:ty),* $(,)?) => {
-        // SAFETY: Safety comment written in the macro invocation.
-        $(unsafe impl ZeroableOption for $int {})*
+    ($($({$($generics:tt)*})? $t:ty, )*) => {
+        // SAFETY: Safety comments written in the macro invocation.
+        $(unsafe impl$($($generics)*)? ZeroableOption for $t {})*
     };
 }
 
 impl_zeroable_option! {
+    // SAFETY: `Option<&T>` is part of the option layout optimization guarantee:
+    // <https://doc.rust-lang.org/stable/std/option/index.html#representation>.
+    {<T: ?Sized>} &T,
+    // SAFETY: `Option<&mut T>` is part of the option layout optimization guarantee:
+    // <https://doc.rust-lang.org/stable/std/option/index.html#representation>.
+    {<T: ?Sized>} &mut T,
+    // SAFETY: `Option<NonNull<T>>` is part of the option layout optimization guarantee:
+    // <https://doc.rust-lang.org/stable/std/option/index.html#representation>.
+    {<T: ?Sized>} NonNull<T>,
     // SAFETY: All zeros is equivalent to `None` (option layout optimization guarantee:
     // <https://doc.rust-lang.org/stable/std/option/index.html#representation>).
-    NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize,
-    NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize,
+    NonZero<u8>, NonZero<u16>, NonZero<u32>, NonZero<u64>, NonZero<u128>, NonZero<usize>,
+    NonZero<i8>, NonZero<i16>, NonZero<i32>, NonZero<i64>, NonZero<i128>, NonZero<isize>,
 }
 
 /// This trait allows creating an instance of `Self` which contains exactly one
Signature · 1 line
2.51.2
author maintainer
#5 lore raw

PATCH 5/10 rust: pin-init: internal: add missing where clause to projection types

In reply to Gary Guo

From: Mohamad Alsadhan <[email protected]>

#[pin_data] failed to propagate the struct's where clause to the generated projection struct. As a result, bounds written in a where clause could be dropped during expansion, causing type errors when fields depended on those bounds.

Fix this by adding the missing where clause to the generated projection struct.

---
 rust/pin-init/internal/src/pin_data.rs | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
rust/pin-init/internal/src/pin_data.rs +3 -1
index 7d871236b49c..6b1b8f26379a 100644
@@ -304,7 +304,9 @@ fn generate_projections(
         #[doc = #docs]
         #[allow(dead_code)]
         #[doc(hidden)]
-        #vis struct #projection #generics_with_pin_lt {
+        #vis struct #projection #generics_with_pin_lt
+            #whr
+        {
             #(#fields_decl)*
             ___pin_phantom_data: ::core::marker::PhantomData<&'__pin mut ()>,
         }
Signature · 1 line
2.51.2
author maintainer
#6 lore raw

PATCH 6/10 rust: pin-init: internal: remove redundant `#[pin]` filtering

In reply to Gary Guo

The generate_projections and generate_the_pin_data function already receive filtered field lists, they do not need to filter out #[pin] again.

---
 rust/pin-init/internal/src/pin_data.rs | 4 ----
 1 file changed, 4 deletions(-)
rust/pin-init/internal/src/pin_data.rs +0 -4
index 6b1b8f26379a..76cd11bf28eb 100644
@@ -258,8 +258,6 @@ fn generate_projections(
                 ..
             },
         )| {
-            let mut attrs = attrs.clone();
-            attrs.retain(|a| !a.path().is_ident("pin"));
             let mut no_doc_attrs = attrs.clone();
             no_doc_attrs.retain(|a| !a.path().is_ident("doc"));
             let ident = ident
@@ -360,8 +358,6 @@ fn handle_field(
         struct_ident: &Ident,
         pinned: bool,
     ) -> TokenStream {
-        let mut attrs = attrs.clone();
-        attrs.retain(|a| !a.path().is_ident("pin"));
         let ident = ident
             .as_ref()
             .expect("only structs with named fields are supported");
Signature · 1 line
2.51.2
author maintainer
#7 lore raw

PATCH 7/10 rust: pin-init: internal: adjust license identifier of `zeroable.rs`

In reply to Gary Guo

From: Benno Lossin <[email protected]>

The pin-init crate has been licensed under Apache-2.0 OR MIT since the beginning. I introduced in commit 071cedc84e90 ("rust: add derive macro for Zeroable") zeroable.rs with incompatible GPL-2.0 SPDX identifier. The file has not been modified by other authors, so relicense it under the above license.

[ Reworded commit message - Gary ]
---
 rust/pin-init/internal/src/zeroable.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
rust/pin-init/internal/src/zeroable.rs +1 -1
index 05683319b0f7..b11feaeb1ca6 100644
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: Apache-2.0 OR MIT
 
 use proc_macro2::TokenStream;
 use quote::quote;
Signature · 1 line
2.51.2
author maintainer
#8 lore raw

PATCH 8/10 rust: pin-init: fix badge URL in README

In reply to Gary Guo

The old CI workflow has been deleted ~1 year ago. Fix the URL to point to the correct one.

---
 rust/pin-init/README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
rust/pin-init/README.md +1 -1
index 9095d6661ff6..2312c9e75f8c 100644
@@ -3,7 +3,7 @@
 [![Dependency status](https://deps.rs/repo/github/Rust-for-Linux/pin-init/status.svg)](https://deps.rs/repo/github/Rust-for-Linux/pin-init)
 ![License](https://img.shields.io/crates/l/pin-init)
 [![Toolchain](https://img.shields.io/badge/toolchain-nightly-red)](#nightly-only)
-![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/Rust-for-Linux/pin-init/test.yml)
+![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/Rust-for-Linux/pin-init/ci.yml)
 # `pin-init`
 
 > [!NOTE]
Signature · 1 line
2.51.2
author maintainer
#9 lore raw

PATCH 9/10 rust: pin-init: cleanup workaround for old Rust compiler

In reply to Gary Guo

The workaround mentions it's for Rust versions before 1.81. The minimum is now 1.82, thus clean up.

---
 rust/pin-init/internal/src/init.rs |  9 +--------
 rust/pin-init/src/lib.rs           | 18 ++----------------
 2 files changed, 3 insertions(+), 24 deletions(-)
rust/pin-init/internal/src/init.rs +1 -8
index daa3f1c6466e..a37309e7b10a 100644
@@ -172,14 +172,7 @@ fn assert_zeroable<T: ?::core::marker::Sized>(_: *mut T)
             init(slot).map(|__InitOk| ())
         };
         // SAFETY: TODO
-        let init = unsafe { ::pin_init::#init_from_closure::<_, #error>(init) };
-        // FIXME: this let binding is required to avoid a compiler error (cycle when computing the
-        // opaque type returned by this function) before Rust 1.81. Remove after MSRV bump.
-        #[allow(
-            clippy::let_and_return,
-            reason = "some clippy versions warn about the let binding"
-        )]
-        init
+        unsafe { ::pin_init::#init_from_closure::<_, #error>(init) }
     }})
 }
 
rust/pin-init/src/lib.rs +2 -16
index 9b76cf5597c6..80c476e605f7 100644
@@ -1139,14 +1139,7 @@ unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
 pub const unsafe fn cast_pin_init<T, U, E>(init: impl PinInit<T, E>) -> impl PinInit<U, E> {
     // SAFETY: initialization delegated to a valid initializer. Cast is valid by function safety
     // requirements.
-    let res = unsafe { pin_init_from_closure(|ptr: *mut U| init.__pinned_init(ptr.cast::<T>())) };
-    // FIXME: this let binding is required to avoid a compiler error (cycle when computing the opaque
-    // type returned by this function) before Rust 1.81. Remove after MSRV bump.
-    #[allow(
-        clippy::let_and_return,
-        reason = "some clippy versions warn about the let binding"
-    )]
-    res
+    unsafe { pin_init_from_closure(|ptr: *mut U| init.__pinned_init(ptr.cast::<T>())) }
 }
 
 /// Changes the to be initialized type.
@@ -1158,14 +1151,7 @@ unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
 pub const unsafe fn cast_init<T, U, E>(init: impl Init<T, E>) -> impl Init<U, E> {
     // SAFETY: initialization delegated to a valid initializer. Cast is valid by function safety
     // requirements.
-    let res = unsafe { init_from_closure(|ptr: *mut U| init.__init(ptr.cast::<T>())) };
-    // FIXME: this let binding is required to avoid a compiler error (cycle when computing the opaque
-    // type returned by this function) before Rust 1.81. Remove after MSRV bump.
-    #[allow(
-        clippy::let_and_return,
-        reason = "some clippy versions warn about the let binding"
-    )]
-    res
+    unsafe { init_from_closure(|ptr: *mut U| init.__init(ptr.cast::<T>())) }
 }
 
 /// An initializer that leaves the memory uninitialized.
Signature · 1 line
2.51.2
author maintainer
#10 lore raw

PATCH 10/10 rust: pin-init: internal: turn `PhantomPinned` error into warnings

In reply to Gary Guo

The PhantomPinned detection is just a lint, and is emitted as an error because there is no compile_warning!() macro, and proc-macro-diagnostics is not stable.

Use of #[deprecated = ""] attribute to approximate custom proc-macro warnings. A new line is added before message for visual clarity.

An example warning with this trick looks like this:

warning: use of deprecated function _::warn:
The field pin of type PhantomPinned only has an effect if it has the #[pin] attribute
--> test.rs:9:5
|
9 | pin: marker::PhantomPinned,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^

---
 rust/pin-init/internal/src/diagnostics.rs | 14 ++++++++++++++
 rust/pin-init/internal/src/pin_data.rs    |  2 +-
 2 files changed, 15 insertions(+), 1 deletion(-)
rust/pin-init/internal/src/diagnostics.rs +14 -0
index 3bdb477c2f2b..c7d9b3e624fc 100644
@@ -3,6 +3,7 @@
 use std::fmt::Display;
 
 use proc_macro2::TokenStream;
+use quote::quote_spanned;
 use syn::{spanned::Spanned, Error};
 
 pub(crate) struct DiagCtxt(TokenStream);
@@ -15,6 +16,19 @@ pub(crate) fn error(&mut self, span: impl Spanned, msg: impl Display) -> ErrorGu
         ErrorGuaranteed(())
     }
 
+    pub(crate) fn warn(&mut self, span: impl Spanned, msg: impl Display) {
+        // Have the message start on a new line for visual clarity.
+        let msg = format!("\n{}", msg);
+        self.0.extend(quote_spanned!(span.span() =>
+            // Approximate using deprecated warning while `proc_macro_diagnostic` is unstable.
+            const _: () = {
+                #[deprecated = #msg]
+                const fn warn() {}
+                warn();
+            };
+        ));
+    }
+
     pub(crate) fn with(
         fun: impl FnOnce(&mut DiagCtxt) -> Result<TokenStream, ErrorGuaranteed>,
     ) -> TokenStream {
rust/pin-init/internal/src/pin_data.rs +1 -1
index 76cd11bf28eb..163a31ed1556 100644
@@ -85,7 +85,7 @@ pub(crate) fn pin_data(
 
     for (pinned, field) in &fields {
         if !pinned && is_phantom_pinned(&field.ty) {
-            dcx.error(
+            dcx.warn(
                 field,
                 format!(
                     "The field `{}` of type `PhantomPinned` only has an effect \
Signature · 1 line
2.51.2
author maintainer
#11 lore raw

PATCH 11/11 rust: pin-init: internal: remove `collect_tuple` polyfill after MSRV bump

In reply to Gary Guo

Tuples implement FromIterator since Rust 1.79. Remove the collect_tuple polyfill now the MSRV is above 1.79.

To avoid over-identing the closure, I move the Field destructure from the closure parameter to a let binding. This keeps the diff small.

---
I've missed out one remaining case where we kept a workaround for old MSRV.
Send as a follow up to the series as this'll be in the same upstream PR as patch 9 in this series.

---
 rust/pin-init/internal/src/pin_data.rs | 27 ++++++++------------------
 1 file changed, 8 insertions(+), 19 deletions(-)
rust/pin-init/internal/src/pin_data.rs +8 -19
index 163a31ed1556..be3d97a38225 100644
@@ -247,17 +247,17 @@ fn generate_projections(
     let projection = format_ident!("{ident}Projection");
     let this = format_ident!("this");
 
-    let (fields_decl, fields_proj) = collect_tuple(fields.iter().map(
-        |(
-            pinned,
-            Field {
+    let (fields_decl, fields_proj): (Vec<_>, Vec<_>) = fields
+        .iter()
+        .map(|(pinned, field)| {
+            let Field {
                 vis,
                 ident,
                 ty,
                 attrs,
                 ..
-            },
-        )| {
+            } = field;
+
             let mut no_doc_attrs = attrs.clone();
             no_doc_attrs.retain(|a| !a.path().is_ident("doc"));
             let ident = ident
@@ -287,8 +287,8 @@ fn generate_projections(
                     ),
                 )
             }
-        },
-    ));
+        })
+        .collect();
     let structurally_pinned_fields_docs = fields
         .iter()
         .filter_map(|(pinned, field)| pinned.then_some(field))
@@ -498,14 +498,3 @@ fn visit_item_mut(&mut self, _: &mut Item) {
         // Do not descend into items, since items reset/change what `Self` refers to.
     }
 }
-
-// replace with `.collect()` once MSRV is above 1.79
-fn collect_tuple<A, B>(iter: impl Iterator<Item = (A, B)>) -> (Vec<A>, Vec<B>) {
-    let mut res_a = vec![];
-    let mut res_b = vec![];
-    for (a, b) in iter {
-        res_a.push(a);
-        res_b.push(b);
-    }
-    (res_a, res_b)
-}

base-commit: 320c27bef338777831ec8615a8ec7e08812d0374

Signature · 1 line
2.51.2
author maintainer Applied
#12 lore raw
In reply to Gary Guo
Quoted 13 lines · Gary Guo

Alistair Francis (1):
rust: pin-init: examples: mark as #[inline] all From::from()s for Error

Benno Lossin (1):
rust: pin-init: internal: adjust license identifier of zeroable.rs

Gary Guo (5):
rust: pin-init: bump minimum Rust version to 1.82
rust: pin-init: internal: remove redundant #[pin] filtering
rust: pin-init: fix badge URL in README
rust: pin-init: cleanup workaround for old Rust compiler
rust: pin-init: internal: turn PhantomPinned error into warnings

Quoted 4 lines

Mohamad Alsadhan (3):
rust: pin-init: cleanup Zeroable and ZeroableOptions
rust: pin-init: extend impl_zeroable_option macro to handle generics
rust: pin-init: internal: add missing where clause to projection types

Applied to pin-init-next.

Best,
Gary

Quoted 15 lines
 rust/pin-init/README.md                       |  2 +-
 rust/pin-init/examples/big_struct_in_place.rs |  3 -
 rust/pin-init/examples/error.rs               |  2 +
 rust/pin-init/examples/linked_list.rs         |  2 -
 rust/pin-init/examples/mutex.rs               |  2 -
 rust/pin-init/examples/pthread_mutex.rs       |  2 -
 rust/pin-init/examples/static_init.rs         |  2 -
 rust/pin-init/internal/src/diagnostics.rs     | 14 +++++
 rust/pin-init/internal/src/init.rs            |  9 +--
 rust/pin-init/internal/src/lib.rs             |  1 -
 rust/pin-init/internal/src/pin_data.rs        | 10 ++--
 rust/pin-init/internal/src/zeroable.rs        |  2 +-
 rust/pin-init/src/lib.rs                      | 79 ++++++++++-----------------
 13 files changed, 52 insertions(+), 78 deletions(-)