mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 01:04:41 +01:00
rust: macros: use quote! from vendored crate
With `quote` crate now vendored in the kernel, we can remove our custom `quote!` macro implementation and just rely on that crate instead. The `quote` crate uses types from the `proc-macro2` library so we also update to use that, and perform conversion in the top-level lib.rs. Clippy complains about unnecessary `.to_string()` as `proc-macro2` provides additional `PartialEq` impl, so they are removed. Reviewed-by: Tamir Duberstein <tamird@gmail.com> Reviewed-by: Benno Lossin <lossin@kernel.org> Signed-off-by: Gary Guo <gary@garyguo.net> Acked-by: David Gow <davidgow@google.com> # for kunit Link: https://patch.msgid.link/20260112170919.1888584-3-gary@kernel.org Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
This commit is contained in:
parent
99ba0fa10d
commit
f637bafe1f
10 changed files with 32 additions and 205 deletions
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
use proc_macro::{token_stream, Ident, TokenStream, TokenTree};
|
||||
use proc_macro2::{token_stream, Ident, TokenStream, TokenTree};
|
||||
|
||||
use crate::helpers::expect_punct;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
|
||||
use crate::helpers::function_name;
|
||||
use proc_macro::TokenStream;
|
||||
|
||||
/// Please see [`crate::export`] for documentation.
|
||||
pub(crate) fn export(_attr: TokenStream, ts: TokenStream) -> TokenStream {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
use proc_macro::{Ident, TokenStream, TokenTree};
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use proc_macro2::{Ident, TokenStream, TokenTree};
|
||||
use quote::quote_spanned;
|
||||
|
||||
/// Please see [`crate::fmt`] for documentation.
|
||||
pub(crate) fn fmt(input: TokenStream) -> TokenStream {
|
||||
let mut input = input.into_iter();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
use proc_macro::{token_stream, Group, Ident, TokenStream, TokenTree};
|
||||
use proc_macro2::{token_stream, Group, Ident, TokenStream, TokenTree};
|
||||
|
||||
pub(crate) fn try_ident(it: &mut token_stream::IntoIter) -> Option<String> {
|
||||
if let Some(TokenTree::Ident(ident)) = it.next() {
|
||||
|
|
@ -86,7 +86,7 @@ pub(crate) fn function_name(input: TokenStream) -> Option<Ident> {
|
|||
let mut input = input.into_iter();
|
||||
while let Some(token) = input.next() {
|
||||
match token {
|
||||
TokenTree::Ident(i) if i.to_string() == "fn" => {
|
||||
TokenTree::Ident(i) if i == "fn" => {
|
||||
if let Some(TokenTree::Ident(i)) = input.next() {
|
||||
return Some(i);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,10 +4,11 @@
|
|||
//!
|
||||
//! Copyright (c) 2023 José Expósito <jose.exposito89@gmail.com>
|
||||
|
||||
use proc_macro::{Delimiter, Group, TokenStream, TokenTree};
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::Write;
|
||||
|
||||
use proc_macro2::{Delimiter, Group, TokenStream, TokenTree};
|
||||
|
||||
pub(crate) fn kunit_tests(attr: TokenStream, ts: TokenStream) -> TokenStream {
|
||||
let attr = attr.to_string();
|
||||
|
||||
|
|
@ -59,7 +60,7 @@ pub(crate) fn kunit_tests(attr: TokenStream, ts: TokenStream) -> TokenStream {
|
|||
}
|
||||
_ => (),
|
||||
},
|
||||
TokenTree::Ident(i) if i.to_string() == "fn" && attributes.contains_key("test") => {
|
||||
TokenTree::Ident(i) if i == "fn" && attributes.contains_key("test") => {
|
||||
if let Some(TokenTree::Ident(test_name)) = body_it.next() {
|
||||
tests.push((test_name, attributes.remove("cfg").unwrap_or_default()))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,8 +11,6 @@
|
|||
// to avoid depending on the full `proc_macro_span` on Rust >= 1.88.0.
|
||||
#![cfg_attr(not(CONFIG_RUSTC_HAS_SPAN_FILE), feature(proc_macro_span))]
|
||||
|
||||
#[macro_use]
|
||||
mod quote;
|
||||
mod concat_idents;
|
||||
mod export;
|
||||
mod fmt;
|
||||
|
|
@ -132,7 +130,7 @@ use proc_macro::TokenStream;
|
|||
/// the kernel module.
|
||||
#[proc_macro]
|
||||
pub fn module(ts: TokenStream) -> TokenStream {
|
||||
module::module(ts)
|
||||
module::module(ts.into()).into()
|
||||
}
|
||||
|
||||
/// Declares or implements a vtable trait.
|
||||
|
|
@ -207,7 +205,7 @@ pub fn module(ts: TokenStream) -> TokenStream {
|
|||
/// [`kernel::error::VTABLE_DEFAULT_ERROR`]: ../kernel/error/constant.VTABLE_DEFAULT_ERROR.html
|
||||
#[proc_macro_attribute]
|
||||
pub fn vtable(attr: TokenStream, ts: TokenStream) -> TokenStream {
|
||||
vtable::vtable(attr, ts)
|
||||
vtable::vtable(attr.into(), ts.into()).into()
|
||||
}
|
||||
|
||||
/// Export a function so that C code can call it via a header file.
|
||||
|
|
@ -230,7 +228,7 @@ pub fn vtable(attr: TokenStream, ts: TokenStream) -> TokenStream {
|
|||
/// automatically exported with `EXPORT_SYMBOL_GPL`.
|
||||
#[proc_macro_attribute]
|
||||
pub fn export(attr: TokenStream, ts: TokenStream) -> TokenStream {
|
||||
export::export(attr, ts)
|
||||
export::export(attr.into(), ts.into()).into()
|
||||
}
|
||||
|
||||
/// Like [`core::format_args!`], but automatically wraps arguments in [`kernel::fmt::Adapter`].
|
||||
|
|
@ -248,7 +246,7 @@ pub fn export(attr: TokenStream, ts: TokenStream) -> TokenStream {
|
|||
/// [`pr_info!`]: ../kernel/macro.pr_info.html
|
||||
#[proc_macro]
|
||||
pub fn fmt(input: TokenStream) -> TokenStream {
|
||||
fmt::fmt(input)
|
||||
fmt::fmt(input.into()).into()
|
||||
}
|
||||
|
||||
/// Concatenate two identifiers.
|
||||
|
|
@ -306,7 +304,7 @@ pub fn fmt(input: TokenStream) -> TokenStream {
|
|||
/// ```
|
||||
#[proc_macro]
|
||||
pub fn concat_idents(ts: TokenStream) -> TokenStream {
|
||||
concat_idents::concat_idents(ts)
|
||||
concat_idents::concat_idents(ts.into()).into()
|
||||
}
|
||||
|
||||
/// Paste identifiers together.
|
||||
|
|
@ -444,9 +442,12 @@ pub fn concat_idents(ts: TokenStream) -> TokenStream {
|
|||
/// [`paste`]: https://docs.rs/paste/
|
||||
#[proc_macro]
|
||||
pub fn paste(input: TokenStream) -> TokenStream {
|
||||
let mut tokens = input.into_iter().collect();
|
||||
let mut tokens = proc_macro2::TokenStream::from(input).into_iter().collect();
|
||||
paste::expand(&mut tokens);
|
||||
tokens.into_iter().collect()
|
||||
tokens
|
||||
.into_iter()
|
||||
.collect::<proc_macro2::TokenStream>()
|
||||
.into()
|
||||
}
|
||||
|
||||
/// Registers a KUnit test suite and its test cases using a user-space like syntax.
|
||||
|
|
@ -473,5 +474,5 @@ pub fn paste(input: TokenStream) -> TokenStream {
|
|||
/// ```
|
||||
#[proc_macro_attribute]
|
||||
pub fn kunit_tests(attr: TokenStream, ts: TokenStream) -> TokenStream {
|
||||
kunit::kunit_tests(attr, ts)
|
||||
kunit::kunit_tests(attr.into(), ts.into()).into()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
use crate::helpers::*;
|
||||
use proc_macro::{token_stream, Delimiter, Literal, TokenStream, TokenTree};
|
||||
use std::fmt::Write;
|
||||
|
||||
use proc_macro2::{token_stream, Delimiter, Literal, TokenStream, TokenTree};
|
||||
|
||||
use crate::helpers::*;
|
||||
|
||||
fn expect_string_array(it: &mut token_stream::IntoIter) -> Vec<String> {
|
||||
let group = expect_group(it);
|
||||
assert_eq!(group.delimiter(), Delimiter::Bracket);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
use proc_macro::{Delimiter, Group, Ident, Spacing, Span, TokenTree};
|
||||
use proc_macro2::{Delimiter, Group, Ident, Spacing, Span, TokenTree};
|
||||
|
||||
fn concat_helper(tokens: &[TokenTree]) -> Vec<(String, Span)> {
|
||||
let mut tokens = tokens.iter();
|
||||
|
|
|
|||
|
|
@ -1,182 +0,0 @@
|
|||
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
|
||||
use proc_macro::{TokenStream, TokenTree};
|
||||
|
||||
pub(crate) trait ToTokens {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream);
|
||||
}
|
||||
|
||||
impl<T: ToTokens> ToTokens for Option<T> {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
if let Some(v) = self {
|
||||
v.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for proc_macro::Group {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
tokens.extend([TokenTree::from(self.clone())]);
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for proc_macro::Ident {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
tokens.extend([TokenTree::from(self.clone())]);
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for TokenTree {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
tokens.extend([self.clone()]);
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for TokenStream {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
tokens.extend(self.clone());
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts tokens into [`proc_macro::TokenStream`] and performs variable interpolations with
|
||||
/// the given span.
|
||||
///
|
||||
/// This is a similar to the
|
||||
/// [`quote_spanned!`](https://docs.rs/quote/latest/quote/macro.quote_spanned.html) macro from the
|
||||
/// `quote` crate but provides only just enough functionality needed by the current `macros` crate.
|
||||
macro_rules! quote_spanned {
|
||||
($span:expr => $($tt:tt)*) => {{
|
||||
let mut tokens = ::proc_macro::TokenStream::new();
|
||||
{
|
||||
#[allow(unused_variables)]
|
||||
let span = $span;
|
||||
quote_spanned!(@proc tokens span $($tt)*);
|
||||
}
|
||||
tokens
|
||||
}};
|
||||
(@proc $v:ident $span:ident) => {};
|
||||
(@proc $v:ident $span:ident #$id:ident $($tt:tt)*) => {
|
||||
$crate::quote::ToTokens::to_tokens(&$id, &mut $v);
|
||||
quote_spanned!(@proc $v $span $($tt)*);
|
||||
};
|
||||
(@proc $v:ident $span:ident #(#$id:ident)* $($tt:tt)*) => {
|
||||
for token in $id {
|
||||
$crate::quote::ToTokens::to_tokens(&token, &mut $v);
|
||||
}
|
||||
quote_spanned!(@proc $v $span $($tt)*);
|
||||
};
|
||||
(@proc $v:ident $span:ident ( $($inner:tt)* ) $($tt:tt)*) => {
|
||||
#[allow(unused_mut)]
|
||||
let mut tokens = ::proc_macro::TokenStream::new();
|
||||
quote_spanned!(@proc tokens $span $($inner)*);
|
||||
$v.extend([::proc_macro::TokenTree::Group(::proc_macro::Group::new(
|
||||
::proc_macro::Delimiter::Parenthesis,
|
||||
tokens,
|
||||
))]);
|
||||
quote_spanned!(@proc $v $span $($tt)*);
|
||||
};
|
||||
(@proc $v:ident $span:ident [ $($inner:tt)* ] $($tt:tt)*) => {
|
||||
let mut tokens = ::proc_macro::TokenStream::new();
|
||||
quote_spanned!(@proc tokens $span $($inner)*);
|
||||
$v.extend([::proc_macro::TokenTree::Group(::proc_macro::Group::new(
|
||||
::proc_macro::Delimiter::Bracket,
|
||||
tokens,
|
||||
))]);
|
||||
quote_spanned!(@proc $v $span $($tt)*);
|
||||
};
|
||||
(@proc $v:ident $span:ident { $($inner:tt)* } $($tt:tt)*) => {
|
||||
let mut tokens = ::proc_macro::TokenStream::new();
|
||||
quote_spanned!(@proc tokens $span $($inner)*);
|
||||
$v.extend([::proc_macro::TokenTree::Group(::proc_macro::Group::new(
|
||||
::proc_macro::Delimiter::Brace,
|
||||
tokens,
|
||||
))]);
|
||||
quote_spanned!(@proc $v $span $($tt)*);
|
||||
};
|
||||
(@proc $v:ident $span:ident :: $($tt:tt)*) => {
|
||||
$v.extend([::proc_macro::Spacing::Joint, ::proc_macro::Spacing::Alone].map(|spacing| {
|
||||
::proc_macro::TokenTree::Punct(::proc_macro::Punct::new(':', spacing))
|
||||
}));
|
||||
quote_spanned!(@proc $v $span $($tt)*);
|
||||
};
|
||||
(@proc $v:ident $span:ident : $($tt:tt)*) => {
|
||||
$v.extend([::proc_macro::TokenTree::Punct(
|
||||
::proc_macro::Punct::new(':', ::proc_macro::Spacing::Alone),
|
||||
)]);
|
||||
quote_spanned!(@proc $v $span $($tt)*);
|
||||
};
|
||||
(@proc $v:ident $span:ident , $($tt:tt)*) => {
|
||||
$v.extend([::proc_macro::TokenTree::Punct(
|
||||
::proc_macro::Punct::new(',', ::proc_macro::Spacing::Alone),
|
||||
)]);
|
||||
quote_spanned!(@proc $v $span $($tt)*);
|
||||
};
|
||||
(@proc $v:ident $span:ident @ $($tt:tt)*) => {
|
||||
$v.extend([::proc_macro::TokenTree::Punct(
|
||||
::proc_macro::Punct::new('@', ::proc_macro::Spacing::Alone),
|
||||
)]);
|
||||
quote_spanned!(@proc $v $span $($tt)*);
|
||||
};
|
||||
(@proc $v:ident $span:ident ! $($tt:tt)*) => {
|
||||
$v.extend([::proc_macro::TokenTree::Punct(
|
||||
::proc_macro::Punct::new('!', ::proc_macro::Spacing::Alone),
|
||||
)]);
|
||||
quote_spanned!(@proc $v $span $($tt)*);
|
||||
};
|
||||
(@proc $v:ident $span:ident ; $($tt:tt)*) => {
|
||||
$v.extend([::proc_macro::TokenTree::Punct(
|
||||
::proc_macro::Punct::new(';', ::proc_macro::Spacing::Alone),
|
||||
)]);
|
||||
quote_spanned!(@proc $v $span $($tt)*);
|
||||
};
|
||||
(@proc $v:ident $span:ident + $($tt:tt)*) => {
|
||||
$v.extend([::proc_macro::TokenTree::Punct(
|
||||
::proc_macro::Punct::new('+', ::proc_macro::Spacing::Alone),
|
||||
)]);
|
||||
quote_spanned!(@proc $v $span $($tt)*);
|
||||
};
|
||||
(@proc $v:ident $span:ident = $($tt:tt)*) => {
|
||||
$v.extend([::proc_macro::TokenTree::Punct(
|
||||
::proc_macro::Punct::new('=', ::proc_macro::Spacing::Alone),
|
||||
)]);
|
||||
quote_spanned!(@proc $v $span $($tt)*);
|
||||
};
|
||||
(@proc $v:ident $span:ident # $($tt:tt)*) => {
|
||||
$v.extend([::proc_macro::TokenTree::Punct(
|
||||
::proc_macro::Punct::new('#', ::proc_macro::Spacing::Alone),
|
||||
)]);
|
||||
quote_spanned!(@proc $v $span $($tt)*);
|
||||
};
|
||||
(@proc $v:ident $span:ident & $($tt:tt)*) => {
|
||||
$v.extend([::proc_macro::TokenTree::Punct(
|
||||
::proc_macro::Punct::new('&', ::proc_macro::Spacing::Alone),
|
||||
)]);
|
||||
quote_spanned!(@proc $v $span $($tt)*);
|
||||
};
|
||||
(@proc $v:ident $span:ident _ $($tt:tt)*) => {
|
||||
$v.extend([::proc_macro::TokenTree::Ident(
|
||||
::proc_macro::Ident::new("_", $span),
|
||||
)]);
|
||||
quote_spanned!(@proc $v $span $($tt)*);
|
||||
};
|
||||
(@proc $v:ident $span:ident $id:ident $($tt:tt)*) => {
|
||||
$v.extend([::proc_macro::TokenTree::Ident(
|
||||
::proc_macro::Ident::new(stringify!($id), $span),
|
||||
)]);
|
||||
quote_spanned!(@proc $v $span $($tt)*);
|
||||
};
|
||||
}
|
||||
|
||||
/// Converts tokens into [`proc_macro::TokenStream`] and performs variable interpolations with
|
||||
/// mixed site span ([`Span::mixed_site()`]).
|
||||
///
|
||||
/// This is a similar to the [`quote!`](https://docs.rs/quote/latest/quote/macro.quote.html) macro
|
||||
/// from the `quote` crate but provides only just enough functionality needed by the current
|
||||
/// `macros` crate.
|
||||
///
|
||||
/// [`Span::mixed_site()`]: https://doc.rust-lang.org/proc_macro/struct.Span.html#method.mixed_site
|
||||
macro_rules! quote {
|
||||
($($tt:tt)*) => {
|
||||
quote_spanned!(::proc_macro::Span::mixed_site() => $($tt)*)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,10 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
use proc_macro::{Delimiter, Group, TokenStream, TokenTree};
|
||||
use std::collections::HashSet;
|
||||
use std::fmt::Write;
|
||||
|
||||
use proc_macro2::{Delimiter, Group, TokenStream, TokenTree};
|
||||
|
||||
pub(crate) fn vtable(_attr: TokenStream, ts: TokenStream) -> TokenStream {
|
||||
let mut tokens: Vec<_> = ts.into_iter().collect();
|
||||
|
||||
|
|
@ -31,7 +32,7 @@ pub(crate) fn vtable(_attr: TokenStream, ts: TokenStream) -> TokenStream {
|
|||
let mut consts = HashSet::new();
|
||||
while let Some(token) = body_it.next() {
|
||||
match token {
|
||||
TokenTree::Ident(ident) if ident.to_string() == "fn" => {
|
||||
TokenTree::Ident(ident) if ident == "fn" => {
|
||||
let fn_name = match body_it.next() {
|
||||
Some(TokenTree::Ident(ident)) => ident.to_string(),
|
||||
// Possibly we've encountered a fn pointer type instead.
|
||||
|
|
@ -39,7 +40,7 @@ pub(crate) fn vtable(_attr: TokenStream, ts: TokenStream) -> TokenStream {
|
|||
};
|
||||
functions.push(fn_name);
|
||||
}
|
||||
TokenTree::Ident(ident) if ident.to_string() == "const" => {
|
||||
TokenTree::Ident(ident) if ident == "const" => {
|
||||
let const_name = match body_it.next() {
|
||||
Some(TokenTree::Ident(ident)) => ident.to_string(),
|
||||
// Possibly we've encountered an inline const block instead.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue