Skip to content

Commit 3760401

Browse files
author
Danilo Krummrich
committed
Merge tag 'pin-init-v6.18' of https://github.com/Rust-for-Linux/linux into drm-rust-next
pin-init changes for v6.18 Changed: - `#[pin_data]` now generates a `*Projection` struct similar to the `pin-project` crate. - Add initializer code blocks to `[try_][pin_]init!` macros: make initializer macros accept any number of `_: {/* arbitrary code */},` & make them run the code at that point. - Make the `[try_][pin_]init!` macros expose initialized fields via a `let` binding as `&mut T` or `Pin<&mut T>` for later fields. Upstream dev news: - Released v0.0.10 before the changes included in this tag. - Inform users of the impending rename from `pinned-init` to `pin-init` (in the kernel the rename already happened). - More CI improvements. Signed-off-by: Danilo Krummrich <dakr@kernel.org> From: Benno Lossin <lossin@kernel.org> Link: https://lore.kernel.org/r/20250912174148.373530-1-lossin@kernel.org
2 parents cf4fd52 + 42415d1 commit 3760401

7 files changed

Lines changed: 227 additions & 49 deletions

File tree

rust/kernel/devres.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,11 +134,9 @@ impl<T: Send> Devres<T> {
134134
T: 'a,
135135
Error: From<E>,
136136
{
137-
let callback = Self::devres_callback;
138-
139137
try_pin_init!(&this in Self {
140138
dev: dev.into(),
141-
callback,
139+
callback: Self::devres_callback,
142140
// INVARIANT: `inner` is properly initialized.
143141
inner <- {
144142
// SAFETY: `this` is a valid pointer to uninitialized memory.
@@ -151,7 +149,7 @@ impl<T: Send> Devres<T> {
151149
// properly initialized, because we require `dev` (i.e. the *bound* device) to
152150
// live at least as long as the returned `impl PinInit<Self, Error>`.
153151
to_result(unsafe {
154-
bindings::devm_add_action(dev.as_raw(), Some(callback), inner.cast())
152+
bindings::devm_add_action(dev.as_raw(), Some(*callback), inner.cast())
155153
})?;
156154

157155
Opaque::pin_init(try_pin_init!(Inner {

rust/kernel/workqueue.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -356,18 +356,11 @@ struct ClosureWork<T> {
356356
func: Option<T>,
357357
}
358358

359-
impl<T> ClosureWork<T> {
360-
fn project(self: Pin<&mut Self>) -> &mut Option<T> {
361-
// SAFETY: The `func` field is not structurally pinned.
362-
unsafe { &mut self.get_unchecked_mut().func }
363-
}
364-
}
365-
366359
impl<T: FnOnce()> WorkItem for ClosureWork<T> {
367360
type Pointer = Pin<KBox<Self>>;
368361

369362
fn run(mut this: Pin<KBox<Self>>) {
370-
if let Some(func) = this.as_mut().project().take() {
363+
if let Some(func) = this.as_mut().project().func.take() {
371364
(func)()
372365
}
373366
}

rust/pin-init/README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,18 @@
66
![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/Rust-for-Linux/pin-init/test.yml)
77
# `pin-init`
88

9+
> [!NOTE]
10+
>
11+
> This crate was originally named [`pinned-init`], but the migration to
12+
> `pin-init` is not yet complete. The `legcay` branch contains the current
13+
> version of the `pinned-init` crate & the `main` branch already incorporates
14+
> the rename to `pin-init`.
15+
>
16+
> There are still some changes needed on the kernel side before the migration
17+
> can be completed.
18+
19+
[`pinned-init`]: https://crates.io/crates/pinned-init
20+
921
<!-- cargo-rdme start -->
1022

1123
Library to safely and fallibly initialize pinned `struct`s using in-place constructors.

rust/pin-init/examples/error.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,6 @@ impl From<AllocError> for Error {
2424
}
2525

2626
#[allow(dead_code)]
27-
fn main() {}
27+
fn main() {
28+
let _ = Error;
29+
}

rust/pin-init/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -740,6 +740,8 @@ macro_rules! stack_try_pin_init {
740740
/// As already mentioned in the examples above, inside of `pin_init!` a `struct` initializer with
741741
/// the following modifications is expected:
742742
/// - Fields that you want to initialize in-place have to use `<-` instead of `:`.
743+
/// - You can use `_: { /* run any user-code here */ },` anywhere where you can place fields in
744+
/// order to run arbitrary code.
743745
/// - In front of the initializer you can write `&this in` to have access to a [`NonNull<Self>`]
744746
/// pointer named `this` inside of the initializer.
745747
/// - Using struct update syntax one can place `..Zeroable::init_zeroed()` at the very end of the
@@ -994,7 +996,7 @@ macro_rules! try_init {
994996
/// }
995997
///
996998
/// impl<T> Foo<T> {
997-
/// fn project(self: Pin<&mut Self>) -> Pin<&mut T> {
999+
/// fn project_this(self: Pin<&mut Self>) -> Pin<&mut T> {
9981000
/// assert_pinned!(Foo<T>, elem, T, inline);
9991001
///
10001002
/// // SAFETY: The field is structurally pinned.

rust/pin-init/src/macros.rs

Lines changed: 205 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -831,6 +831,17 @@ macro_rules! __pin_data {
831831
$($fields)*
832832
}
833833

834+
$crate::__pin_data!(make_pin_projections:
835+
@vis($vis),
836+
@name($name),
837+
@impl_generics($($impl_generics)*),
838+
@ty_generics($($ty_generics)*),
839+
@decl_generics($($decl_generics)*),
840+
@where($($whr)*),
841+
@pinned($($pinned)*),
842+
@not_pinned($($not_pinned)*),
843+
);
844+
834845
// We put the rest into this const item, because it then will not be accessible to anything
835846
// outside.
836847
const _: () = {
@@ -980,6 +991,56 @@ macro_rules! __pin_data {
980991
stringify!($($rest)*),
981992
);
982993
};
994+
(make_pin_projections:
995+
@vis($vis:vis),
996+
@name($name:ident),
997+
@impl_generics($($impl_generics:tt)*),
998+
@ty_generics($($ty_generics:tt)*),
999+
@decl_generics($($decl_generics:tt)*),
1000+
@where($($whr:tt)*),
1001+
@pinned($($(#[$($p_attr:tt)*])* $pvis:vis $p_field:ident : $p_type:ty),* $(,)?),
1002+
@not_pinned($($(#[$($attr:tt)*])* $fvis:vis $field:ident : $type:ty),* $(,)?),
1003+
) => {
1004+
$crate::macros::paste! {
1005+
#[doc(hidden)]
1006+
$vis struct [< $name Projection >] <'__pin, $($decl_generics)*> {
1007+
$($(#[$($p_attr)*])* $pvis $p_field : ::core::pin::Pin<&'__pin mut $p_type>,)*
1008+
$($(#[$($attr)*])* $fvis $field : &'__pin mut $type,)*
1009+
___pin_phantom_data: ::core::marker::PhantomData<&'__pin mut ()>,
1010+
}
1011+
1012+
impl<$($impl_generics)*> $name<$($ty_generics)*>
1013+
where $($whr)*
1014+
{
1015+
/// Pin-projects all fields of `Self`.
1016+
///
1017+
/// These fields are structurally pinned:
1018+
$(#[doc = ::core::concat!(" - `", ::core::stringify!($p_field), "`")])*
1019+
///
1020+
/// These fields are **not** structurally pinned:
1021+
$(#[doc = ::core::concat!(" - `", ::core::stringify!($field), "`")])*
1022+
#[inline]
1023+
$vis fn project<'__pin>(
1024+
self: ::core::pin::Pin<&'__pin mut Self>,
1025+
) -> [< $name Projection >] <'__pin, $($ty_generics)*> {
1026+
// SAFETY: we only give access to `&mut` for fields not structurally pinned.
1027+
let this = unsafe { ::core::pin::Pin::get_unchecked_mut(self) };
1028+
[< $name Projection >] {
1029+
$(
1030+
// SAFETY: `$p_field` is structurally pinned.
1031+
$(#[$($p_attr)*])*
1032+
$p_field : unsafe { ::core::pin::Pin::new_unchecked(&mut this.$p_field) },
1033+
)*
1034+
$(
1035+
$(#[$($attr)*])*
1036+
$field : &mut this.$field,
1037+
)*
1038+
___pin_phantom_data: ::core::marker::PhantomData,
1039+
}
1040+
}
1041+
}
1042+
}
1043+
};
9831044
(make_pin_data:
9841045
@pin_data($pin_data:ident),
9851046
@impl_generics($($impl_generics:tt)*),
@@ -988,38 +1049,56 @@ macro_rules! __pin_data {
9881049
@pinned($($(#[$($p_attr:tt)*])* $pvis:vis $p_field:ident : $p_type:ty),* $(,)?),
9891050
@not_pinned($($(#[$($attr:tt)*])* $fvis:vis $field:ident : $type:ty),* $(,)?),
9901051
) => {
991-
// For every field, we create a projection function according to its projection type. If a
992-
// field is structurally pinned, then it must be initialized via `PinInit`, if it is not
993-
// structurally pinned, then it can be initialized via `Init`.
994-
//
995-
// The functions are `unsafe` to prevent accidentally calling them.
996-
#[allow(dead_code)]
997-
#[expect(clippy::missing_safety_doc)]
998-
impl<$($impl_generics)*> $pin_data<$($ty_generics)*>
999-
where $($whr)*
1000-
{
1001-
$(
1002-
$(#[$($p_attr)*])*
1003-
$pvis unsafe fn $p_field<E>(
1004-
self,
1005-
slot: *mut $p_type,
1006-
init: impl $crate::PinInit<$p_type, E>,
1007-
) -> ::core::result::Result<(), E> {
1008-
// SAFETY: TODO.
1009-
unsafe { $crate::PinInit::__pinned_init(init, slot) }
1010-
}
1011-
)*
1012-
$(
1013-
$(#[$($attr)*])*
1014-
$fvis unsafe fn $field<E>(
1015-
self,
1016-
slot: *mut $type,
1017-
init: impl $crate::Init<$type, E>,
1018-
) -> ::core::result::Result<(), E> {
1019-
// SAFETY: TODO.
1020-
unsafe { $crate::Init::__init(init, slot) }
1021-
}
1022-
)*
1052+
$crate::macros::paste! {
1053+
// For every field, we create a projection function according to its projection type. If a
1054+
// field is structurally pinned, then it must be initialized via `PinInit`, if it is not
1055+
// structurally pinned, then it can be initialized via `Init`.
1056+
//
1057+
// The functions are `unsafe` to prevent accidentally calling them.
1058+
#[allow(dead_code)]
1059+
#[expect(clippy::missing_safety_doc)]
1060+
impl<$($impl_generics)*> $pin_data<$($ty_generics)*>
1061+
where $($whr)*
1062+
{
1063+
$(
1064+
$(#[$($p_attr)*])*
1065+
$pvis unsafe fn $p_field<E>(
1066+
self,
1067+
slot: *mut $p_type,
1068+
init: impl $crate::PinInit<$p_type, E>,
1069+
) -> ::core::result::Result<(), E> {
1070+
// SAFETY: TODO.
1071+
unsafe { $crate::PinInit::__pinned_init(init, slot) }
1072+
}
1073+
1074+
$(#[$($p_attr)*])*
1075+
$pvis unsafe fn [<__project_ $p_field>]<'__slot>(
1076+
self,
1077+
slot: &'__slot mut $p_type,
1078+
) -> ::core::pin::Pin<&'__slot mut $p_type> {
1079+
::core::pin::Pin::new_unchecked(slot)
1080+
}
1081+
)*
1082+
$(
1083+
$(#[$($attr)*])*
1084+
$fvis unsafe fn $field<E>(
1085+
self,
1086+
slot: *mut $type,
1087+
init: impl $crate::Init<$type, E>,
1088+
) -> ::core::result::Result<(), E> {
1089+
// SAFETY: TODO.
1090+
unsafe { $crate::Init::__init(init, slot) }
1091+
}
1092+
1093+
$(#[$($attr)*])*
1094+
$fvis unsafe fn [<__project_ $field>]<'__slot>(
1095+
self,
1096+
slot: &'__slot mut $type,
1097+
) -> &'__slot mut $type {
1098+
slot
1099+
}
1100+
)*
1101+
}
10231102
}
10241103
};
10251104
}
@@ -1202,6 +1281,21 @@ macro_rules! __init_internal {
12021281
// have been initialized. Therefore we can now dismiss the guards by forgetting them.
12031282
$(::core::mem::forget($guards);)*
12041283
};
1284+
(init_slot($($use_data:ident)?):
1285+
@data($data:ident),
1286+
@slot($slot:ident),
1287+
@guards($($guards:ident,)*),
1288+
// arbitrary code block
1289+
@munch_fields(_: { $($code:tt)* }, $($rest:tt)*),
1290+
) => {
1291+
{ $($code)* }
1292+
$crate::__init_internal!(init_slot($($use_data)?):
1293+
@data($data),
1294+
@slot($slot),
1295+
@guards($($guards,)*),
1296+
@munch_fields($($rest)*),
1297+
);
1298+
};
12051299
(init_slot($use_data:ident): // `use_data` is present, so we use the `data` to init fields.
12061300
@data($data:ident),
12071301
@slot($slot:ident),
@@ -1216,6 +1310,13 @@ macro_rules! __init_internal {
12161310
// return when an error/panic occurs.
12171311
// We also use the `data` to require the correct trait (`Init` or `PinInit`) for `$field`.
12181312
unsafe { $data.$field(::core::ptr::addr_of_mut!((*$slot).$field), init)? };
1313+
// SAFETY:
1314+
// - the project function does the correct field projection,
1315+
// - the field has been initialized,
1316+
// - the reference is only valid until the end of the initializer.
1317+
#[allow(unused_variables)]
1318+
let $field = $crate::macros::paste!(unsafe { $data.[< __project_ $field >](&mut (*$slot).$field) });
1319+
12191320
// Create the drop guard:
12201321
//
12211322
// We rely on macro hygiene to make it impossible for users to access this local variable.
@@ -1247,6 +1348,14 @@ macro_rules! __init_internal {
12471348
// SAFETY: `slot` is valid, because we are inside of an initializer closure, we
12481349
// return when an error/panic occurs.
12491350
unsafe { $crate::Init::__init(init, ::core::ptr::addr_of_mut!((*$slot).$field))? };
1351+
1352+
// SAFETY:
1353+
// - the field is not structurally pinned, since the line above must compile,
1354+
// - the field has been initialized,
1355+
// - the reference is only valid until the end of the initializer.
1356+
#[allow(unused_variables)]
1357+
let $field = unsafe { &mut (*$slot).$field };
1358+
12501359
// Create the drop guard:
12511360
//
12521361
// We rely on macro hygiene to make it impossible for users to access this local variable.
@@ -1265,7 +1374,48 @@ macro_rules! __init_internal {
12651374
);
12661375
}
12671376
};
1268-
(init_slot($($use_data:ident)?):
1377+
(init_slot(): // No `use_data`, so all fields are not structurally pinned
1378+
@data($data:ident),
1379+
@slot($slot:ident),
1380+
@guards($($guards:ident,)*),
1381+
// Init by-value.
1382+
@munch_fields($field:ident $(: $val:expr)?, $($rest:tt)*),
1383+
) => {
1384+
{
1385+
$(let $field = $val;)?
1386+
// Initialize the field.
1387+
//
1388+
// SAFETY: The memory at `slot` is uninitialized.
1389+
unsafe { ::core::ptr::write(::core::ptr::addr_of_mut!((*$slot).$field), $field) };
1390+
}
1391+
1392+
#[allow(unused_variables)]
1393+
// SAFETY:
1394+
// - the field is not structurally pinned, since no `use_data` was required to create this
1395+
// initializer,
1396+
// - the field has been initialized,
1397+
// - the reference is only valid until the end of the initializer.
1398+
let $field = unsafe { &mut (*$slot).$field };
1399+
1400+
// Create the drop guard:
1401+
//
1402+
// We rely on macro hygiene to make it impossible for users to access this local variable.
1403+
// We use `paste!` to create new hygiene for `$field`.
1404+
$crate::macros::paste! {
1405+
// SAFETY: We forget the guard later when initialization has succeeded.
1406+
let [< __ $field _guard >] = unsafe {
1407+
$crate::__internal::DropGuard::new(::core::ptr::addr_of_mut!((*$slot).$field))
1408+
};
1409+
1410+
$crate::__init_internal!(init_slot():
1411+
@data($data),
1412+
@slot($slot),
1413+
@guards([< __ $field _guard >], $($guards,)*),
1414+
@munch_fields($($rest)*),
1415+
);
1416+
}
1417+
};
1418+
(init_slot($use_data:ident):
12691419
@data($data:ident),
12701420
@slot($slot:ident),
12711421
@guards($($guards:ident,)*),
@@ -1279,6 +1429,13 @@ macro_rules! __init_internal {
12791429
// SAFETY: The memory at `slot` is uninitialized.
12801430
unsafe { ::core::ptr::write(::core::ptr::addr_of_mut!((*$slot).$field), $field) };
12811431
}
1432+
// SAFETY:
1433+
// - the project function does the correct field projection,
1434+
// - the field has been initialized,
1435+
// - the reference is only valid until the end of the initializer.
1436+
#[allow(unused_variables)]
1437+
let $field = $crate::macros::paste!(unsafe { $data.[< __project_ $field >](&mut (*$slot).$field) });
1438+
12821439
// Create the drop guard:
12831440
//
12841441
// We rely on macro hygiene to make it impossible for users to access this local variable.
@@ -1289,14 +1446,28 @@ macro_rules! __init_internal {
12891446
$crate::__internal::DropGuard::new(::core::ptr::addr_of_mut!((*$slot).$field))
12901447
};
12911448

1292-
$crate::__init_internal!(init_slot($($use_data)?):
1449+
$crate::__init_internal!(init_slot($use_data):
12931450
@data($data),
12941451
@slot($slot),
12951452
@guards([< __ $field _guard >], $($guards,)*),
12961453
@munch_fields($($rest)*),
12971454
);
12981455
}
12991456
};
1457+
(make_initializer:
1458+
@slot($slot:ident),
1459+
@type_name($t:path),
1460+
@munch_fields(_: { $($code:tt)* }, $($rest:tt)*),
1461+
@acc($($acc:tt)*),
1462+
) => {
1463+
// code blocks are ignored for the initializer check
1464+
$crate::__init_internal!(make_initializer:
1465+
@slot($slot),
1466+
@type_name($t),
1467+
@munch_fields($($rest)*),
1468+
@acc($($acc)*),
1469+
);
1470+
};
13001471
(make_initializer:
13011472
@slot($slot:ident),
13021473
@type_name($t:path),

0 commit comments

Comments
 (0)