Skip to content

Commit 638dc79

Browse files
committed
rust: macros: rewrite module! using syn
Now that `syn` and `quote` are available in the Kernel use them for the `module!` proc-macro instead of the current string based proc-macro approach. Proc-macros written using `syn` are a lot more readable and thus easier to maintain than proc-macros written using string manipulation. An additional advantage of `syn` is the improved error reporting, here is an example: module! { type: RustMinimal, name: "rust_minimal", author: "Rust for Linux Contributors", description: "Rust minimal sample", // we forgot to add a `license` field. } Prior to this patch, the error reads: error: proc macro panicked --> samples/rust/rust_minimal.rs:7:1 | 7 | / module! { 8 | | type: RustMinimal, 9 | | name: "rust_minimal", 10 | | author: "Rust for Linux Contributors", 11 | | description: "Rust minimal sample", 12 | | // license: "GPL", 13 | | } | |_^ | = help: message: Missing required key "license". error[E0425]: cannot find value `__LOG_PREFIX` in the crate root --> samples/rust/rust_minimal.rs:21:9 | 21 | pr_info!("Rust minimal sample (init)\n"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in the crate root | = note: this error originates in the macro `$crate::print_macro` which comes from the expansion of the macro `pr_info` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0425]: cannot find value `__LOG_PREFIX` in the crate root --> samples/rust/rust_minimal.rs:22:9 | 22 | pr_info!("Am I built-in? {}\n", !cfg!(MODULE)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in the crate root | = note: this error originates in the macro `$crate::print_macro` which comes from the expansion of the macro `pr_info` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0425]: cannot find value `__LOG_PREFIX` in the crate root --> samples/rust/rust_minimal.rs:35:9 | 35 | pr_info!("My numbers are {:?}\n", self.numbers); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in the crate root | = note: this error originates in the macro `$crate::print_macro` which comes from the expansion of the macro `pr_info` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0425]: cannot find value `__LOG_PREFIX` in the crate root --> samples/rust/rust_minimal.rs:36:9 | 36 | pr_info!("Rust minimal sample (exit)\n"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in the crate root | = note: this error originates in the macro `$crate::print_macro` which comes from the expansion of the macro `pr_info` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 5 previous errors After this patch, the error reads: error: Missing required key "license". --> samples/rust/rust_minimal.rs:8:5 | 8 | / type: RustMinimal, 9 | | name: "rust_minimal", 10 | | author: "Rust for Linux Contributors", 11 | | description: "Rust minimal sample", | |_______________________________________^ error: aborting due to 1 previous error Similar improvements in error quality apply to getting the order of the fields wrong and giving non-ascii strings as values for fields where it should be ascii-only. Signed-off-by: Benno Lossin <[email protected]>
1 parent 8938c4f commit 638dc79

File tree

3 files changed

+416
-276
lines changed

3 files changed

+416
-276
lines changed

rust/macros/helpers.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// SPDX-License-Identifier: GPL-2.0
22

3+
#![allow(dead_code)]
34
use proc_macro2::{token_stream, Group, TokenStream, TokenTree};
45

56
pub(crate) fn try_ident(it: &mut token_stream::IntoIter) -> Option<String> {

rust/macros/lib.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ mod vtable;
1212
mod zeroable;
1313

1414
use proc_macro::TokenStream;
15+
use quote::quote;
1516
use syn::parse_macro_input;
1617

1718
/// Declares a kernel module.
@@ -74,8 +75,20 @@ use syn::parse_macro_input;
7475
/// - `license`: byte array of the license of the kernel module (required).
7576
/// - `alias`: byte array of alias name of the kernel module.
7677
#[proc_macro]
77-
pub fn module(ts: TokenStream) -> TokenStream {
78-
module::module(ts.into()).into()
78+
pub fn module(input: TokenStream) -> TokenStream {
79+
match syn::parse(input) {
80+
Ok(input) => module::module(input),
81+
Err(err) => {
82+
let err = err.into_compile_error();
83+
quote! {
84+
// Supresses missing `__LOG_PREFIX` errors from printing macros.
85+
const __LOG_PREFIX: &[u8] = b"";
86+
// Due to this error, it will not compile, so an empty `__LOG_PREFIX` is fine.
87+
#err
88+
}
89+
}
90+
}
91+
.into()
7992
}
8093

8194
/// Declares or implements a vtable trait.

0 commit comments

Comments
 (0)