1 // SPDX-License-Identifier: GPL-2.0
3 use crate::helpers::{parse_generics, Generics};
4 use proc_macro::{TokenStream, TokenTree};
6 pub(crate) fn derive(input: TokenStream) -> TokenStream {
14 ) = parse_generics(input);
15 // This should be the body of the struct `{...}`.
16 let last = rest.pop();
17 // Now we insert `Zeroable` as a bound for every generic parameter in `impl_generics`.
18 let mut new_impl_generics = Vec::with_capacity(impl_generics.len());
19 // Are we inside of a generic where we want to add `Zeroable`?
20 let mut in_generic = !impl_generics.is_empty();
21 // Have we already inserted `Zeroable`?
22 let mut inserted = false;
23 // Level of `<>` nestings.
25 for tt in impl_generics {
27 // If we find a `,`, then we have finished a generic/constant/lifetime parameter.
28 TokenTree::Punct(p) if nested == 0 && p.as_char() == ',' => {
29 if in_generic && !inserted {
30 new_impl_generics.extend(quote! { : ::kernel::init::Zeroable });
34 new_impl_generics.push(tt);
36 // If we find `'`, then we are entering a lifetime.
37 TokenTree::Punct(p) if nested == 0 && p.as_char() == '\'' => {
39 new_impl_generics.push(tt);
41 TokenTree::Punct(p) if nested == 0 && p.as_char() == ':' => {
42 new_impl_generics.push(tt);
44 new_impl_generics.extend(quote! { ::kernel::init::Zeroable + });
48 TokenTree::Punct(p) if p.as_char() == '<' => {
50 new_impl_generics.push(tt);
52 TokenTree::Punct(p) if p.as_char() == '>' => {
55 new_impl_generics.push(tt);
57 _ => new_impl_generics.push(tt),
60 assert_eq!(nested, 0);
61 if in_generic && !inserted {
62 new_impl_generics.extend(quote! { : ::kernel::init::Zeroable });
65 ::kernel::__derive_zeroable!(
68 @impl_generics(#(#new_impl_generics)*),
69 @ty_generics(#(#ty_generics)*),