Skip to content

Commit fbf8fb3

Browse files
BennoLossinojeda
authored andcommitted
rust: move pin-init API into its own directory
In preparation of splitting off the pin-init crate from the kernel crate, move all pin-init API code (including proc-macros) into `rust/pin-init`. Moved modules have their import path adjusted via the `#[path = "..."]` attribute. This allows the files to still be imported in the kernel crate even though the files are in different directories. Code that is moved out of files (but the file itself stays where it is) is imported via the `include!` macro. This also allows the code to be moved while still being part of the kernel crate. Note that this commit moves the generics parsing code out of the GPL-2.0 file `rust/macros/helpers.rs` into the Apache-2.0 OR MIT file `rust/pin_init/internal/src/helpers.rs`. I am the sole author of that code and it already is available with that license at [1]. The same is true for the entry-points of the proc-macros `pin_data`, `pinned_drop` and `derive_zeroable` in `rust/macros/lib.rs` that are moved to `rust/pin_data/internal/src/lib.rs`. Although there are some smaller patches that fix the doctests. Link: https://github.com/Rust-for-Linux/pinned-init [1] Signed-off-by: Benno Lossin <[email protected]> Reviewed-by: Andreas Hindborg <[email protected]> Reviewed-by: Fiona Behrens <[email protected]> Tested-by: Andreas Hindborg <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Miguel Ojeda <[email protected]>
1 parent 206dea3 commit fbf8fb3

File tree

11 files changed

+276
-266
lines changed

11 files changed

+276
-266
lines changed

rust/kernel/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ pub mod faux;
5050
#[cfg(CONFIG_RUST_FW_LOADER_ABSTRACTIONS)]
5151
pub mod firmware;
5252
pub mod fs;
53+
#[path = "../pin-init/src/lib.rs"]
5354
pub mod init;
5455
pub mod io;
5556
pub mod ioctl;

rust/macros/helpers.rs

Lines changed: 2 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -70,152 +70,6 @@ pub(crate) fn expect_end(it: &mut token_stream::IntoIter) {
7070
}
7171
}
7272

73-
/// Parsed generics.
74-
///
75-
/// See the field documentation for an explanation what each of the fields represents.
76-
///
77-
/// # Examples
78-
///
79-
/// ```rust,ignore
80-
/// # let input = todo!();
81-
/// let (Generics { decl_generics, impl_generics, ty_generics }, rest) = parse_generics(input);
82-
/// quote! {
83-
/// struct Foo<$($decl_generics)*> {
84-
/// // ...
85-
/// }
86-
///
87-
/// impl<$impl_generics> Foo<$ty_generics> {
88-
/// fn foo() {
89-
/// // ...
90-
/// }
91-
/// }
92-
/// }
93-
/// ```
94-
pub(crate) struct Generics {
95-
/// The generics with bounds and default values (e.g. `T: Clone, const N: usize = 0`).
96-
///
97-
/// Use this on type definitions e.g. `struct Foo<$decl_generics> ...` (or `union`/`enum`).
98-
pub(crate) decl_generics: Vec<TokenTree>,
99-
/// The generics with bounds (e.g. `T: Clone, const N: usize`).
100-
///
101-
/// Use this on `impl` blocks e.g. `impl<$impl_generics> Trait for ...`.
102-
pub(crate) impl_generics: Vec<TokenTree>,
103-
/// The generics without bounds and without default values (e.g. `T, N`).
104-
///
105-
/// Use this when you use the type that is declared with these generics e.g.
106-
/// `Foo<$ty_generics>`.
107-
pub(crate) ty_generics: Vec<TokenTree>,
108-
}
109-
110-
/// Parses the given `TokenStream` into `Generics` and the rest.
111-
///
112-
/// The generics are not present in the rest, but a where clause might remain.
113-
pub(crate) fn parse_generics(input: TokenStream) -> (Generics, Vec<TokenTree>) {
114-
// The generics with bounds and default values.
115-
let mut decl_generics = vec![];
116-
// `impl_generics`, the declared generics with their bounds.
117-
let mut impl_generics = vec![];
118-
// Only the names of the generics, without any bounds.
119-
let mut ty_generics = vec![];
120-
// Tokens not related to the generics e.g. the `where` token and definition.
121-
let mut rest = vec![];
122-
// The current level of `<`.
123-
let mut nesting = 0;
124-
let mut toks = input.into_iter();
125-
// If we are at the beginning of a generic parameter.
126-
let mut at_start = true;
127-
let mut skip_until_comma = false;
128-
while let Some(tt) = toks.next() {
129-
if nesting == 1 && matches!(&tt, TokenTree::Punct(p) if p.as_char() == '>') {
130-
// Found the end of the generics.
131-
break;
132-
} else if nesting >= 1 {
133-
decl_generics.push(tt.clone());
134-
}
135-
match tt.clone() {
136-
TokenTree::Punct(p) if p.as_char() == '<' => {
137-
if nesting >= 1 && !skip_until_comma {
138-
// This is inside of the generics and part of some bound.
139-
impl_generics.push(tt);
140-
}
141-
nesting += 1;
142-
}
143-
TokenTree::Punct(p) if p.as_char() == '>' => {
144-
// This is a parsing error, so we just end it here.
145-
if nesting == 0 {
146-
break;
147-
} else {
148-
nesting -= 1;
149-
if nesting >= 1 && !skip_until_comma {
150-
// We are still inside of the generics and part of some bound.
151-
impl_generics.push(tt);
152-
}
153-
}
154-
}
155-
TokenTree::Punct(p) if skip_until_comma && p.as_char() == ',' => {
156-
if nesting == 1 {
157-
impl_generics.push(tt.clone());
158-
impl_generics.push(tt);
159-
skip_until_comma = false;
160-
}
161-
}
162-
_ if !skip_until_comma => {
163-
match nesting {
164-
// If we haven't entered the generics yet, we still want to keep these tokens.
165-
0 => rest.push(tt),
166-
1 => {
167-
// Here depending on the token, it might be a generic variable name.
168-
match tt.clone() {
169-
TokenTree::Ident(i) if at_start && i.to_string() == "const" => {
170-
let Some(name) = toks.next() else {
171-
// Parsing error.
172-
break;
173-
};
174-
impl_generics.push(tt);
175-
impl_generics.push(name.clone());
176-
ty_generics.push(name.clone());
177-
decl_generics.push(name);
178-
at_start = false;
179-
}
180-
TokenTree::Ident(_) if at_start => {
181-
impl_generics.push(tt.clone());
182-
ty_generics.push(tt);
183-
at_start = false;
184-
}
185-
TokenTree::Punct(p) if p.as_char() == ',' => {
186-
impl_generics.push(tt.clone());
187-
ty_generics.push(tt);
188-
at_start = true;
189-
}
190-
// Lifetimes begin with `'`.
191-
TokenTree::Punct(p) if p.as_char() == '\'' && at_start => {
192-
impl_generics.push(tt.clone());
193-
ty_generics.push(tt);
194-
}
195-
// Generics can have default values, we skip these.
196-
TokenTree::Punct(p) if p.as_char() == '=' => {
197-
skip_until_comma = true;
198-
}
199-
_ => impl_generics.push(tt),
200-
}
201-
}
202-
_ => impl_generics.push(tt),
203-
}
204-
}
205-
_ => {}
206-
}
207-
}
208-
rest.extend(toks);
209-
(
210-
Generics {
211-
impl_generics,
212-
decl_generics,
213-
ty_generics,
214-
},
215-
rest,
216-
)
217-
}
218-
21973
/// Given a function declaration, finds the name of the function.
22074
pub(crate) fn function_name(input: TokenStream) -> Option<Ident> {
22175
let mut input = input.into_iter();
@@ -232,3 +86,5 @@ pub(crate) fn function_name(input: TokenStream) -> Option<Ident> {
23286
}
23387
None
23488
}
89+
90+
include!("../pin-init/internal/src/helpers.rs");

rust/macros/lib.rs

Lines changed: 4 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,12 @@ mod export;
1313
mod helpers;
1414
mod module;
1515
mod paste;
16+
#[path = "../pin-init/internal/src/pin_data.rs"]
1617
mod pin_data;
18+
#[path = "../pin-init/internal/src/pinned_drop.rs"]
1719
mod pinned_drop;
1820
mod vtable;
21+
#[path = "../pin-init/internal/src/zeroable.rs"]
1922
mod zeroable;
2023

2124
use proc_macro::TokenStream;
@@ -256,106 +259,6 @@ pub fn concat_idents(ts: TokenStream) -> TokenStream {
256259
concat_idents::concat_idents(ts)
257260
}
258261

259-
/// Used to specify the pinning information of the fields of a struct.
260-
///
261-
/// This is somewhat similar in purpose as
262-
/// [pin-project-lite](https://crates.io/crates/pin-project-lite).
263-
/// Place this macro on a struct definition and then `#[pin]` in front of the attributes of each
264-
/// field you want to structurally pin.
265-
///
266-
/// This macro enables the use of the [`pin_init!`] macro. When pin-initializing a `struct`,
267-
/// then `#[pin]` directs the type of initializer that is required.
268-
///
269-
/// If your `struct` implements `Drop`, then you need to add `PinnedDrop` as arguments to this
270-
/// macro, and change your `Drop` implementation to `PinnedDrop` annotated with
271-
/// `#[`[`macro@pinned_drop`]`]`, since dropping pinned values requires extra care.
272-
///
273-
/// # Examples
274-
///
275-
/// ```ignore
276-
/// # #![feature(lint_reasons)]
277-
/// # use kernel::prelude::*;
278-
/// # use std::{sync::Mutex, process::Command};
279-
/// # use kernel::macros::pin_data;
280-
/// #[pin_data]
281-
/// struct DriverData {
282-
/// #[pin]
283-
/// queue: Mutex<KVec<Command>>,
284-
/// buf: KBox<[u8; 1024 * 1024]>,
285-
/// }
286-
/// ```
287-
///
288-
/// ```ignore
289-
/// # #![feature(lint_reasons)]
290-
/// # use kernel::prelude::*;
291-
/// # use std::{sync::Mutex, process::Command};
292-
/// # use core::pin::Pin;
293-
/// # pub struct Info;
294-
/// # mod bindings {
295-
/// # pub unsafe fn destroy_info(_ptr: *mut super::Info) {}
296-
/// # }
297-
/// use kernel::macros::{pin_data, pinned_drop};
298-
///
299-
/// #[pin_data(PinnedDrop)]
300-
/// struct DriverData {
301-
/// #[pin]
302-
/// queue: Mutex<KVec<Command>>,
303-
/// buf: KBox<[u8; 1024 * 1024]>,
304-
/// raw_info: *mut Info,
305-
/// }
306-
///
307-
/// #[pinned_drop]
308-
/// impl PinnedDrop for DriverData {
309-
/// fn drop(self: Pin<&mut Self>) {
310-
/// unsafe { bindings::destroy_info(self.raw_info) };
311-
/// }
312-
/// }
313-
/// # fn main() {}
314-
/// ```
315-
///
316-
/// [`pin_init!`]: ../kernel/macro.pin_init.html
317-
// ^ cannot use direct link, since `kernel` is not a dependency of `macros`.
318-
#[proc_macro_attribute]
319-
pub fn pin_data(inner: TokenStream, item: TokenStream) -> TokenStream {
320-
pin_data::pin_data(inner, item)
321-
}
322-
323-
/// Used to implement `PinnedDrop` safely.
324-
///
325-
/// Only works on structs that are annotated via `#[`[`macro@pin_data`]`]`.
326-
///
327-
/// # Examples
328-
///
329-
/// ```ignore
330-
/// # #![feature(lint_reasons)]
331-
/// # use kernel::prelude::*;
332-
/// # use macros::{pin_data, pinned_drop};
333-
/// # use std::{sync::Mutex, process::Command};
334-
/// # use core::pin::Pin;
335-
/// # mod bindings {
336-
/// # pub struct Info;
337-
/// # pub unsafe fn destroy_info(_ptr: *mut Info) {}
338-
/// # }
339-
/// #[pin_data(PinnedDrop)]
340-
/// struct DriverData {
341-
/// #[pin]
342-
/// queue: Mutex<KVec<Command>>,
343-
/// buf: KBox<[u8; 1024 * 1024]>,
344-
/// raw_info: *mut bindings::Info,
345-
/// }
346-
///
347-
/// #[pinned_drop]
348-
/// impl PinnedDrop for DriverData {
349-
/// fn drop(self: Pin<&mut Self>) {
350-
/// unsafe { bindings::destroy_info(self.raw_info) };
351-
/// }
352-
/// }
353-
/// ```
354-
#[proc_macro_attribute]
355-
pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream {
356-
pinned_drop::pinned_drop(args, input)
357-
}
358-
359262
/// Paste identifiers together.
360263
///
361264
/// Within the `paste!` macro, identifiers inside `[<` and `>]` are concatenated together to form a
@@ -496,23 +399,4 @@ pub fn paste(input: TokenStream) -> TokenStream {
496399
tokens.into_iter().collect()
497400
}
498401

499-
/// Derives the [`Zeroable`] trait for the given struct.
500-
///
501-
/// This can only be used for structs where every field implements the [`Zeroable`] trait.
502-
///
503-
/// # Examples
504-
///
505-
/// ```ignore
506-
/// use kernel::macros::Zeroable;
507-
///
508-
/// #[derive(Zeroable)]
509-
/// pub struct DriverData {
510-
/// id: i64,
511-
/// buf_ptr: *mut u8,
512-
/// len: usize,
513-
/// }
514-
/// ```
515-
#[proc_macro_derive(Zeroable)]
516-
pub fn derive_zeroable(input: TokenStream) -> TokenStream {
517-
zeroable::derive(input)
518-
}
402+
include!("../pin-init/internal/src/lib.rs");

0 commit comments

Comments
 (0)