Skip to content

Commit 674b1c7

Browse files
y86-devojeda
authored andcommitted
rust: init: add support for arbitrary paths in init macros
Previously only `ident` and generic types were supported in the `{try_}{pin_}init!` macros. This patch allows arbitrary path fragments, so for example `Foo::Bar` but also very complex paths such as `<Foo as Baz>::Bar::<0, i32>`. Internally this is accomplished by using `path` fragments. Due to some peculiar declarative macro limitations, we have to "forget" certain additional parsing information in the token trees. This is achieved by using the `paste!` proc macro. It does not actually modify the input, since no `[< >]` will be present in the input, so it just strips the information held by declarative macros. For example, if a declarative macro takes `$t:path` as its input, it cannot sensibly propagate this to a macro that takes `$($p:tt)*` as its input, since the `$t` token will only be considered one `tt` token for the second macro. If we first pipe the tokens through `paste!`, then it parses as expected. Suggested-by: Asahi Lina <[email protected]> Reviewed-by: Martin Rodriguez Reboredo <[email protected]> Reviewed-by: Alice Ryhl <[email protected]> Reviewed-by: Gary Guo <[email protected]> Signed-off-by: Benno Lossin <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Miguel Ojeda <[email protected]>
1 parent 9e49439 commit 674b1c7

File tree

1 file changed

+35
-19
lines changed

1 file changed

+35
-19
lines changed

Diff for: rust/kernel/init/macros.rs

+35-19
Original file line numberDiff line numberDiff line change
@@ -1000,7 +1000,7 @@ macro_rules! __pin_data {
10001000
macro_rules! __init_internal {
10011001
(
10021002
@this($($this:ident)?),
1003-
@typ($t:ident $(::<$($generics:ty),*>)?),
1003+
@typ($t:path),
10041004
@fields($($fields:tt)*),
10051005
@error($err:ty),
10061006
// Either `PinData` or `InitData`, `$use_data` should only be present in the `PinData`
@@ -1014,7 +1014,7 @@ macro_rules! __init_internal {
10141014
) => {
10151015
$crate::__init_internal!(with_update_parsed:
10161016
@this($($this)?),
1017-
@typ($t $(::<$($generics),*>)? ),
1017+
@typ($t),
10181018
@fields($($fields)*),
10191019
@error($err),
10201020
@data($data, $($use_data)?),
@@ -1025,7 +1025,7 @@ macro_rules! __init_internal {
10251025
};
10261026
(
10271027
@this($($this:ident)?),
1028-
@typ($t:ident $(::<$($generics:ty),*>)?),
1028+
@typ($t:path),
10291029
@fields($($fields:tt)*),
10301030
@error($err:ty),
10311031
// Either `PinData` or `InitData`, `$use_data` should only be present in the `PinData`
@@ -1039,7 +1039,7 @@ macro_rules! __init_internal {
10391039
) => {
10401040
$crate::__init_internal!(with_update_parsed:
10411041
@this($($this)?),
1042-
@typ($t $(::<$($generics),*>)? ),
1042+
@typ($t),
10431043
@fields($($fields)*),
10441044
@error($err),
10451045
@data($data, $($use_data)?),
@@ -1050,7 +1050,7 @@ macro_rules! __init_internal {
10501050
};
10511051
(
10521052
@this($($this:ident)?),
1053-
@typ($t:ident $(::<$($generics:ty),*>)?),
1053+
@typ($t:path),
10541054
@fields($($fields:tt)*),
10551055
@error($err:ty),
10561056
// Either `PinData` or `InitData`, `$use_data` should only be present in the `PinData`
@@ -1064,7 +1064,7 @@ macro_rules! __init_internal {
10641064
) => {
10651065
$crate::__init_internal!(
10661066
@this($($this)?),
1067-
@typ($t $(::<$($generics),*>)? ),
1067+
@typ($t),
10681068
@fields($($fields)*),
10691069
@error($err),
10701070
@data($data, $($use_data)?),
@@ -1075,7 +1075,7 @@ macro_rules! __init_internal {
10751075
};
10761076
(with_update_parsed:
10771077
@this($($this:ident)?),
1078-
@typ($t:ident $(::<$($generics:ty),*>)?),
1078+
@typ($t:path),
10791079
@fields($($fields:tt)*),
10801080
@error($err:ty),
10811081
// Either `PinData` or `InitData`, `$use_data` should only be present in the `PinData`
@@ -1094,7 +1094,11 @@ macro_rules! __init_internal {
10941094
// Get the data about fields from the supplied type.
10951095
let data = unsafe {
10961096
use $crate::init::__internal::$has_data;
1097-
$t$(::<$($generics),*>)?::$get_data()
1097+
// Here we abuse `paste!` to retokenize `$t`. Declarative macros have some internal
1098+
// information that is associated to already parsed fragments, so a path fragment
1099+
// cannot be used in this position. Doing the retokenization results in valid rust
1100+
// code.
1101+
::kernel::macros::paste!($t::$get_data())
10981102
};
10991103
// Ensure that `data` really is of type `$data` and help with type inference:
11001104
let init = $crate::init::__internal::$data::make_closure::<_, __InitOk, $err>(
@@ -1253,7 +1257,7 @@ macro_rules! __init_internal {
12531257
};
12541258
(make_initializer:
12551259
@slot($slot:ident),
1256-
@type_name($t:ident),
1260+
@type_name($t:path),
12571261
@munch_fields(..Zeroable::zeroed() $(,)?),
12581262
@acc($($acc:tt)*),
12591263
) => {
@@ -1270,30 +1274,42 @@ macro_rules! __init_internal {
12701274
// not get executed, so it has no effect.
12711275
::core::ptr::write($slot, zeroed);
12721276
zeroed = ::core::mem::zeroed();
1273-
::core::ptr::write($slot, $t {
1274-
$($acc)*
1275-
..zeroed
1276-
});
1277+
// Here we abuse `paste!` to retokenize `$t`. Declarative macros have some internal
1278+
// information that is associated to already parsed fragments, so a path fragment
1279+
// cannot be used in this position. Doing the retokenization results in valid rust
1280+
// code.
1281+
::kernel::macros::paste!(
1282+
::core::ptr::write($slot, $t {
1283+
$($acc)*
1284+
..zeroed
1285+
});
1286+
);
12771287
}
12781288
};
12791289
(make_initializer:
12801290
@slot($slot:ident),
1281-
@type_name($t:ident),
1291+
@type_name($t:path),
12821292
@munch_fields($(,)?),
12831293
@acc($($acc:tt)*),
12841294
) => {
12851295
// Endpoint, nothing more to munch, create the initializer.
12861296
// Since we are in the closure that is never called, this will never get executed.
12871297
// We abuse `slot` to get the correct type inference here:
12881298
unsafe {
1289-
::core::ptr::write($slot, $t {
1290-
$($acc)*
1291-
});
1299+
// Here we abuse `paste!` to retokenize `$t`. Declarative macros have some internal
1300+
// information that is associated to already parsed fragments, so a path fragment
1301+
// cannot be used in this position. Doing the retokenization results in valid rust
1302+
// code.
1303+
::kernel::macros::paste!(
1304+
::core::ptr::write($slot, $t {
1305+
$($acc)*
1306+
});
1307+
);
12921308
}
12931309
};
12941310
(make_initializer:
12951311
@slot($slot:ident),
1296-
@type_name($t:ident),
1312+
@type_name($t:path),
12971313
@munch_fields($field:ident <- $val:expr, $($rest:tt)*),
12981314
@acc($($acc:tt)*),
12991315
) => {
@@ -1306,7 +1322,7 @@ macro_rules! __init_internal {
13061322
};
13071323
(make_initializer:
13081324
@slot($slot:ident),
1309-
@type_name($t:ident),
1325+
@type_name($t:path),
13101326
@munch_fields($field:ident $(: $val:expr)?, $($rest:tt)*),
13111327
@acc($($acc:tt)*),
13121328
) => {

0 commit comments

Comments
 (0)