`syn` support
Subsystems (4)
Miguel Ojeda
maintainerv2 cover `syn` support
This patch series introduces support for syn (and its dependencies):
Syn is a parsing library for parsing a stream of Rust tokens into a syntax tree of Rust source code.
Currently this library is geared toward use in Rust procedural macros, but contains some APIs that may be useful more generally.
It is the most downloaded Rust crate (according to crates.io), and it is also used by the Rust compiler itself. Having such support allows to greatly simplify writing complex macros such as pin-init. We will use it in the macros crate too.
Benno has already prepared the pin-init version based on this, and on top of that, we will be able to simplify the macros crate too. I think Jesung is working on updating the TryFrom and Into upcoming derive macros to use syn too.
The series starts with a few preparation commits (two fixes were already merged in mainline that were discovered by this series), then each crate is added. Finally, support for using the new crates from our macros crate is introduced.
This has been a long time coming, e.g. even before Rust for Linux was merged into the Linux kernel, Gary and Benno have wanted to use syn. The first iterations of this, from 2022 and 2023 (with serde too, another popular crate), are at:
https://github.com/Rust-for-Linux/linux/pull/910 https://github.com/Rust-for-Linux/linux/pull/1007
After those, we considered picking these from the distributions where possible. However, after discussing it, it is not really worth the
complexity: vendoring makes things less complex and is less fragile.
In particular, we avoid having to support and test several versions, we avoid having to introduce Cargo just to properly fetch the right versions from the registry, we can easily customize the crates if needed (e.g. dropping the unicode_idents dependency like it is done in this series) and we simplify the configuration of the build for users for which the "default" paths/registries would not have worked.
Moreover, nowadays, the ~57k lines introduced are not that much compared to years ago (it dwarfed the actual Rust kernel code). Moreover, back then it wasn't clear the Rust experiment would be a success, so it would have been a bit pointless/risky to add many lines for nothing. Our macro needs were also smaller in the early days.
So, finally, in Kangrejos 2025 we discussed going with the original, simpler approach. Thus here it is the result.
There should not be many updates needed for these, and even if there are, they should not be too big, e.g. +7k -3k lines across the 3 crates in the last year.
Note that syn does not have all the features enabled, since we do not need them so far, but they can easily be enabled just adding them to the list.
v2:
- Drop condvar patch.
- Add note about := in commit log.
- Add comment about rustfmt and note it in the log.
- Rename hostlibrary to procmacrolibrary.
- Split a couple changes into two new commits (rustc_test_library, rustc_procmacro). I applied the tags to those, since the changes are still the same and the log is simple.
- Add new commit with the macros support for the new crates.
v1: https://lore.kernel.org/rust-for-linux/[email protected]/
Miguel Ojeda (20):
rust: kbuild: introduce core-flags and core-skip_flags
rust: kbuild: simplify --cfg handling
rust: kbuild: add proc macro library support
rust: kbuild: support skipping flags in rustc_test_library
rust: kbuild: support using libraries in rustc_procmacro
rust: proc-macro2: import crate
rust: proc-macro2: add SPDX License Identifiers
rust: proc-macro2: remove unicode_ident dependency
rust: proc-macro2: add README.md
rust: proc-macro2: enable support in kbuild
rust: quote: import crate
rust: quote: add SPDX License Identifiers
rust: quote: add README.md
rust: quote: enable support in kbuild
rust: syn: import crate
rust: syn: add SPDX License Identifiers
rust: syn: remove unicode-ident dependency
rust: syn: add README.md
rust: syn: enable support in kbuild
rust: macros: support proc-macro2, quote and syn
.gitignore | 1 + Makefile | 7 + rust/Makefile | 147 +- rust/proc-macro2/README.md | 13 + rust/proc-macro2/detection.rs | 77 + rust/proc-macro2/extra.rs | 153 + rust/proc-macro2/fallback.rs | 1258 +++++ rust/proc-macro2/lib.rs | 1351 ++++++ rust/proc-macro2/location.rs | 31 + rust/proc-macro2/marker.rs | 19 + rust/proc-macro2/parse.rs | 997 ++++ rust/proc-macro2/probe.rs | 12 + rust/proc-macro2/probe/proc_macro_span.rs | 53 + .../proc-macro2/probe/proc_macro_span_file.rs | 16 + .../probe/proc_macro_span_location.rs | 23 + rust/proc-macro2/rcvec.rs | 148 + rust/proc-macro2/wrapper.rs | 986 ++++ rust/quote/README.md | 12 + rust/quote/ext.rs | 112 + rust/quote/format.rs | 170 + rust/quote/ident_fragment.rs | 90 + rust/quote/lib.rs | 1456 ++++++ rust/quote/runtime.rs | 494 ++ rust/quote/spanned.rs | 52 + rust/quote/to_tokens.rs | 273 ++ rust/syn/README.md | 13 + rust/syn/attr.rs | 838 ++++ rust/syn/bigint.rs | 68 + rust/syn/buffer.rs | 436 ++ rust/syn/classify.rs | 313 ++ rust/syn/custom_keyword.rs | 262 ++ rust/syn/custom_punctuation.rs | 306 ++ rust/syn/data.rs | 426 ++ rust/syn/derive.rs | 261 ++ rust/syn/discouraged.rs | 227 + rust/syn/drops.rs | 60 + rust/syn/error.rs | 469 ++ rust/syn/export.rs | 75 + rust/syn/expr.rs | 4175 +++++++++++++++++ rust/syn/ext.rs | 138 + rust/syn/file.rs | 127 + rust/syn/fixup.rs | 775 +++ rust/syn/gen/clone.rs | 2269 +++++++++ rust/syn/gen/debug.rs | 3240 +++++++++++++ rust/syn/gen/eq.rs | 2308 +++++++++ rust/syn/gen/fold.rs | 3904 +++++++++++++++ rust/syn/gen/hash.rs | 2878 ++++++++++++ rust/syn/gen/visit.rs | 3943 ++++++++++++++++ rust/syn/gen/visit_mut.rs | 3761 +++++++++++++++ rust/syn/generics.rs | 1479 ++++++ rust/syn/group.rs | 293 ++ rust/syn/ident.rs | 110 + rust/syn/item.rs | 3492 ++++++++++++++ rust/syn/lib.rs | 1013 ++++ rust/syn/lifetime.rs | 158 + rust/syn/lit.rs | 1862 ++++++++ rust/syn/lookahead.rs | 334 ++ rust/syn/mac.rs | 227 + rust/syn/macros.rs | 184 + rust/syn/meta.rs | 429 ++ rust/syn/op.rs | 221 + rust/syn/parse.rs | 1421 ++++++ rust/syn/parse_macro_input.rs | 130 + rust/syn/parse_quote.rs | 242 + rust/syn/pat.rs | 957 ++++ rust/syn/path.rs | 968 ++++ rust/syn/precedence.rs | 212 + rust/syn/print.rs | 18 + rust/syn/punctuated.rs | 1157 +++++ rust/syn/restriction.rs | 180 + rust/syn/scan_expr.rs | 267 ++ rust/syn/sealed.rs | 6 + rust/syn/span.rs | 65 + rust/syn/spanned.rs | 120 + rust/syn/stmt.rs | 486 ++ rust/syn/thread.rs | 62 + rust/syn/token.rs | 1098 +++++ rust/syn/tt.rs | 109 + rust/syn/ty.rs | 1273 +++++ rust/syn/verbatim.rs | 35 + rust/syn/whitespace.rs | 67 + scripts/generate_rust_analyzer.py | 25 +- 82 files changed, 57906 insertions(+), 17 deletions(-) create mode 100644 rust/proc-macro2/README.md create mode 100644 rust/proc-macro2/detection.rs create mode 100644 rust/proc-macro2/extra.rs create mode 100644 rust/proc-macro2/fallback.rs create mode 100644 rust/proc-macro2/lib.rs create mode 100644 rust/proc-macro2/location.rs create mode 100644 rust/proc-macro2/marker.rs create mode 100644 rust/proc-macro2/parse.rs create mode 100644 rust/proc-macro2/probe.rs create mode 100644 rust/proc-macro2/probe/proc_macro_span.rs create mode 100644 rust/proc-macro2/probe/proc_macro_span_file.rs create mode 100644 rust/proc-macro2/probe/proc_macro_span_location.rs create mode 100644 rust/proc-macro2/rcvec.rs create mode 100644 rust/proc-macro2/wrapper.rs create mode 100644 rust/quote/README.md create mode 100644 rust/quote/ext.rs create mode 100644 rust/quote/format.rs create mode 100644 rust/quote/ident_fragment.rs create mode 100644 rust/quote/lib.rs create mode 100644 rust/quote/runtime.rs create mode 100644 rust/quote/spanned.rs create mode 100644 rust/quote/to_tokens.rs create mode 100644 rust/syn/README.md create mode 100644 rust/syn/attr.rs create mode 100644 rust/syn/bigint.rs create mode 100644 rust/syn/buffer.rs create mode 100644 rust/syn/classify.rs create mode 100644 rust/syn/custom_keyword.rs create mode 100644 rust/syn/custom_punctuation.rs create mode 100644 rust/syn/data.rs create mode 100644 rust/syn/derive.rs create mode 100644 rust/syn/discouraged.rs create mode 100644 rust/syn/drops.rs create mode 100644 rust/syn/error.rs create mode 100644 rust/syn/export.rs create mode 100644 rust/syn/expr.rs create mode 100644 rust/syn/ext.rs create mode 100644 rust/syn/file.rs create mode 100644 rust/syn/fixup.rs create mode 100644 rust/syn/gen/clone.rs create mode 100644 rust/syn/gen/debug.rs create mode 100644 rust/syn/gen/eq.rs create mode 100644 rust/syn/gen/fold.rs create mode 100644 rust/syn/gen/hash.rs create mode 100644 rust/syn/gen/visit.rs create mode 100644 rust/syn/gen/visit_mut.rs create mode 100644 rust/syn/generics.rs create mode 100644 rust/syn/group.rs create mode 100644 rust/syn/ident.rs create mode 100644 rust/syn/item.rs create mode 100644 rust/syn/lib.rs create mode 100644 rust/syn/lifetime.rs create mode 100644 rust/syn/lit.rs create mode 100644 rust/syn/lookahead.rs create mode 100644 rust/syn/mac.rs create mode 100644 rust/syn/macros.rs create mode 100644 rust/syn/meta.rs create mode 100644 rust/syn/op.rs create mode 100644 rust/syn/parse.rs create mode 100644 rust/syn/parse_macro_input.rs create mode 100644 rust/syn/parse_quote.rs create mode 100644 rust/syn/pat.rs create mode 100644 rust/syn/path.rs create mode 100644 rust/syn/precedence.rs create mode 100644 rust/syn/print.rs create mode 100644 rust/syn/punctuated.rs create mode 100644 rust/syn/restriction.rs create mode 100644 rust/syn/scan_expr.rs create mode 100644 rust/syn/sealed.rs create mode 100644 rust/syn/span.rs create mode 100644 rust/syn/spanned.rs create mode 100644 rust/syn/stmt.rs create mode 100644 rust/syn/thread.rs create mode 100644 rust/syn/token.rs create mode 100644 rust/syn/tt.rs create mode 100644 rust/syn/ty.rs create mode 100644 rust/syn/verbatim.rs create mode 100644 rust/syn/whitespace.rs
base-commit: bc197e24a3acd13dd0b7b07c1448c5c225946546 --
2.52.0
Miguel Ojeda
maintainerPATCH v2 1/20 rust: kbuild: introduce `core-flags` and `core-skip_flags`
In the next commits we are introducing *-{cfgs,skip_flags,flags} variables for other crates.
Thus do so here for core, which simplifies a bit the Makefile (including the next commit) and makes it more consistent.
This means we stop passing -Wrustdoc::unescaped_backticks to rustc and -Wunreachable_pub to rustdoc, i.e. we skip more, which is fine since it shouldn't have an effect.
In addition, use := for core-cfgs to make it consistent with the upcoming additions.
--- rust/Makefile | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-)
rust/Makefile +14 -5
@@ -60,11 +60,20 @@ rustdoc_test_quiet=--test-args -q rustdoc_test_kernel_quiet=>/dev/null endif -core-cfgs = \ +core-cfgs := \ --cfg no_fp_fmt_parse core-edition := $(if $(call rustc-min-version,108700),2024,2021) +core-skip_flags := \ + --edition=2021 \ + -Wunreachable_pub \ + -Wrustdoc::unescaped_backticks + +core-flags := \ + --edition=$(core-edition) \ + $(core-cfgs) + # `rustdoc` did not save the target modifiers, thus workaround for # the time being (https://github.com/rust-lang/rust/issues/144521). rustdoc_modifiers_workaround := $(if $(call rustc-min-version,108800),-Cunsafe-allow-abi-mismatch=fixed-x18)
@@ -122,8 +131,8 @@ rustdoc-macros: $(src)/macros/lib.rs rustdoc-clean FORCE # Starting with Rust 1.82.0, skipping `-Wrustdoc::unescaped_backticks` should # not be needed -- see https://github.com/rust-lang/rust/pull/128307. -rustdoc-core: private skip_flags = --edition=2021 -Wrustdoc::unescaped_backticks -rustdoc-core: private rustc_target_flags = --edition=$(core-edition) $(core-cfgs) +rustdoc-core: private skip_flags = $(core-skip_flags) +rustdoc-core: private rustc_target_flags = $(core-flags) rustdoc-core: $(RUST_LIB_SRC)/core/src/lib.rs rustdoc-clean FORCE +$(call if_changed,rustdoc)
@@ -499,9 +508,9 @@ $(obj)/helpers/helpers.o: $(src)/helpers/helpers.c $(recordmcount_source) FORCE $(obj)/exports.o: private skip_gendwarfksyms = 1 $(obj)/core.o: private skip_clippy = 1 -$(obj)/core.o: private skip_flags = --edition=2021 -Wunreachable_pub +$(obj)/core.o: private skip_flags = $(core-skip_flags) $(obj)/core.o: private rustc_objcopy = $(foreach sym,$(redirect-intrinsics),--redefine-sym $(sym)=__rust$(sym)) -$(obj)/core.o: private rustc_target_flags = --edition=$(core-edition) $(core-cfgs) +$(obj)/core.o: private rustc_target_flags = $(core-flags) $(obj)/core.o: $(RUST_LIB_SRC)/core/src/lib.rs \ $(wildcard $(objtree)/include/config/RUSTC_VERSION_TEXT) FORCE +$(call if_changed_rule,rustc_library)
Signature · 1 line
2.52.0
Miguel Ojeda
maintainerPATCH v2 2/20 rust: kbuild: simplify `--cfg` handling
In reply to Miguel OjedaWe need to handle cfgs in both rustc and rust-analyzer, and in future commits some of those contain double quotes, which complicates things further.
Thus, instead of removing the --cfg part in the rust-analyzer generation script, have the *-cfgs variables contain just the actual cfg, and use that to generate the actual flags in *-flags.
--- rust/Makefile | 6 ++++-- scripts/generate_rust_analyzer.py | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-)
rust/Makefile +4 -2
@@ -60,8 +60,10 @@ rustdoc_test_quiet=--test-args -q rustdoc_test_kernel_quiet=>/dev/null endif +cfgs-to-flags = $(patsubst %,--cfg='%',$1) + core-cfgs := \ - --cfg no_fp_fmt_parse + no_fp_fmt_parse core-edition := $(if $(call rustc-min-version,108700),2024,2021)
@@ -72,7 +74,7 @@ core-skip_flags := \ core-flags := \ --edition=$(core-edition) \ - $(core-cfgs) + $(call cfgs-to-flags,$(core-cfgs)) # `rustdoc` did not save the target modifiers, thus workaround for # the time being (https://github.com/rust-lang/rust/issues/144521).
scripts/generate_rust_analyzer.py +1 -1
@@ -15,7 +15,7 @@ def args_crates_cfgs(cfgs): crates_cfgs = {} for cfg in cfgs: crate, vals = cfg.split("=", 1) - crates_cfgs[crate] = vals.replace("--cfg", "").split() + crates_cfgs[crate] = vals.split() return crates_cfgs
Signature · 1 line
2.52.0
Miguel Ojeda
maintainerPATCH v2 3/20 rust: kbuild: add proc macro library support
In reply to Miguel OjedaAdd the proc macro library rule that produces .rlib files to be used by proc macros such as the macros crate.
--- .gitignore | 1 + rust/Makefile | 10 ++++++++++ 2 files changed, 11 insertions(+)
.gitignore +1 -0
@@ -41,6 +41,7 @@ *.o.* *.patch *.pyc +*.rlib *.rmeta *.rpm *.rsi
rust/Makefile +10 -0
@@ -421,6 +421,16 @@ $(obj)/exports_bindings_generated.h: $(obj)/bindings.o FORCE $(obj)/exports_kernel_generated.h: $(obj)/kernel.o FORCE $(call if_changed,exports) +quiet_cmd_rustc_procmacrolibrary = $(RUSTC_OR_CLIPPY_QUIET) PL $@ + cmd_rustc_procmacrolibrary = \ + $(if $(skip_clippy),$(RUSTC),$(RUSTC_OR_CLIPPY)) \ + $(filter-out $(skip_flags),$(rust_common_flags) $(rustc_target_flags)) \ + --emit=dep-info,link --crate-type rlib -O \ + --out-dir $(objtree)/$(obj) -L$(objtree)/$(obj) \ + --crate-name $(patsubst lib%.rlib,%,$(notdir $@)) $<; \ + mv $(objtree)/$(obj)/$(patsubst lib%.rlib,%,$(notdir $@)).d $(depfile); \ + sed -i '/^\#/d' $(depfile) + quiet_cmd_rustc_procmacro = $(RUSTC_OR_CLIPPY_QUIET) P $@ cmd_rustc_procmacro = \ $(RUSTC_OR_CLIPPY) $(rust_common_flags) $(rustc_target_flags) \
Signature · 1 line
2.52.0
Miguel Ojeda
maintainerPATCH v2 4/20 rust: kbuild: support skipping flags in `rustc_test_library`
In reply to Miguel OjedaCrates like quote (added later) will need the ability to skip flags in the rustc_test_library command.
Thus add the support for it.
--- rust/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
rust/Makefile +2 -2
@@ -172,8 +172,8 @@ rustdoc-clean: FORCE quiet_cmd_rustc_test_library = $(RUSTC_OR_CLIPPY_QUIET) TL $< cmd_rustc_test_library = \ OBJTREE=$(abspath $(objtree)) \ - $(RUSTC_OR_CLIPPY) $(rust_common_flags) \ - @$(objtree)/include/generated/rustc_cfg $(rustc_target_flags) \ + $(RUSTC_OR_CLIPPY) $(filter-out $(skip_flags),$(rust_common_flags) $(rustc_target_flags)) \ + @$(objtree)/include/generated/rustc_cfg \ --crate-type $(if $(rustc_test_library_proc),proc-macro,rlib) \ --out-dir $(objtree)/$(obj)/test --cfg testlib \ -L$(objtree)/$(obj)/test \
Signature · 1 line
2.52.0
Miguel Ojeda
maintainerPATCH v2 5/20 rust: kbuild: support using libraries in `rustc_procmacro`
In reply to Miguel OjedaProc macros such as macros and pin-init will need the ability to use libraries such as syn (added later) in the rustc_procmacro command.
Thus add the support for it.
--- rust/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
rust/Makefile +1 -1
@@ -437,7 +437,7 @@ quiet_cmd_rustc_procmacro = $(RUSTC_OR_CLIPPY_QUIET) P $@ -Clinker-flavor=gcc -Clinker=$(HOSTCC) \ -Clink-args='$(call escsq,$(KBUILD_PROCMACROLDFLAGS))' \ --emit=dep-info=$(depfile) --emit=link=$@ --extern proc_macro \ - --crate-type proc-macro \ + --crate-type proc-macro -L$(objtree)/$(obj) \ --crate-name $(patsubst lib%.$(libmacros_extension),%,$(notdir $@)) \ @$(objtree)/include/generated/rustc_cfg $<
Signature · 1 line
2.52.0
Miguel Ojeda
maintainerPATCH v2 6/20 rust: proc-macro2: import crate
In reply to Miguel OjedaThis is a subset of the Rust proc-macro2 crate, version 1.0.101 (released 2025-08-16), licensed under "Apache-2.0 OR MIT", from:
https://github.com/dtolnay/proc-macro2/raw/1.0.101/src
The files are copied as-is, with no modifications whatsoever (not even adding the SPDX identifiers).
For copyright details, please see:
https://github.com/dtolnay/proc-macro2/blob/1.0.101/README.md#license https://github.com/dtolnay/proc-macro2/blob/1.0.101/LICENSE-APACHE https://github.com/dtolnay/proc-macro2/blob/1.0.101/LICENSE-MIT
The next two patches modify these files as needed for use within the kernel. This patch split allows reviewers to double-check the import and to clearly see the differences introduced.
The following script may be used to verify the contents:
for path in $(cd rust/proc-macro2/ && find . -type f -name '*.rs'); do
curl --silent --show-error --location \
https://github.com/dtolnay/proc-macro2/raw/1.0.101/src/$path \
| diff --unified rust/proc-macro2/$path - && echo $path: OK
done--- rust/proc-macro2/detection.rs | 75 + rust/proc-macro2/extra.rs | 151 ++ rust/proc-macro2/fallback.rs | 1256 +++++++++++++++ rust/proc-macro2/lib.rs | 1349 +++++++++++++++++ rust/proc-macro2/location.rs | 29 + rust/proc-macro2/marker.rs | 17 + rust/proc-macro2/parse.rs | 995 ++++++++++++ rust/proc-macro2/probe.rs | 10 + rust/proc-macro2/probe/proc_macro_span.rs | 51 + .../proc-macro2/probe/proc_macro_span_file.rs | 14 + .../probe/proc_macro_span_location.rs | 21 + rust/proc-macro2/rcvec.rs | 146 ++ rust/proc-macro2/wrapper.rs | 984 ++++++++++++ 13 files changed, 5098 insertions(+) create mode 100644 rust/proc-macro2/detection.rs create mode 100644 rust/proc-macro2/extra.rs create mode 100644 rust/proc-macro2/fallback.rs create mode 100644 rust/proc-macro2/lib.rs create mode 100644 rust/proc-macro2/location.rs create mode 100644 rust/proc-macro2/marker.rs create mode 100644 rust/proc-macro2/parse.rs create mode 100644 rust/proc-macro2/probe.rs create mode 100644 rust/proc-macro2/probe/proc_macro_span.rs create mode 100644 rust/proc-macro2/probe/proc_macro_span_file.rs create mode 100644 rust/proc-macro2/probe/proc_macro_span_location.rs create mode 100644 rust/proc-macro2/rcvec.rs create mode 100644 rust/proc-macro2/wrapper.rs
rust/proc-macro2/detection.rs new file +75 -0
@@ -0,0 +1,75 @@ +use core::sync::atomic::{AtomicUsize ,Ordering }; +use std::sync::Once ; + +static WORKS :AtomicUsize =AtomicUsize ::new (0 ); +static INIT :Once =Once ::new (); + +pub (crate )fn inside_proc_macro () ->bool { +match WORKS .load (Ordering ::Relaxed ) { +1 =>return false , +2 =>return true , + _ => {} + } + +INIT .call_once (initialize); +inside_proc_macro () +} + +pub (crate )fn force_fallback () { +WORKS .store (1 ,Ordering ::Relaxed ); +} + +pub (crate )fn unforce_fallback () { +initialize (); +} + +#[cfg(not(no_is_available))] +fn initialize () { +let available = proc_macro::is_available (); +WORKS .store (availableas usize +1 ,Ordering ::Relaxed ); +} + +// Swap in a null panic hook to avoid printing "thread panicked" to stderr, +// then use catch_unwind to determine whether the compiler's proc_macro is +// working. When proc-macro2 is used from outside of a procedural macro all +// of the proc_macro crate's APIs currently panic. +// +// The Once is to prevent the possibility of this ordering: +// +// thread 1 calls take_hook, gets the user's original hook +// thread 1 calls set_hook with the null hook +// thread 2 calls take_hook, thinks null hook is the original hook +// thread 2 calls set_hook with the null hook +// thread 1 calls set_hook with the actual original hook +// thread 2 calls set_hook with what it thinks is the original hook +// +// in which the user's hook has been lost. +// +// There is still a race condition where a panic in a different thread can +// happen during the interval that the user's original panic hook is +// unregistered such that their hook is incorrectly not called. This is +// sufficiently unlikely and less bad than printing panic messages to stderr +// on correct use of this crate. Maybe there is a libstd feature request +// here. For now, if a user needs to guarantee that this failure mode does +// not occur, they need to call e.g. `proc_macro2::Span::call_site()` from +// the main thread before launching any other threads. +#[cfg(no_is_available)] +fn initialize () { +use std::panic::{self,PanicInfo }; + +type PanicHook =dyn Fn (&PanicInfo ) +Sync +Send + 'static; + +let null_hook:Box <PanicHook > =Box ::new (|_panic_info| {/* ignore */ }); +let sanity_check = &*null_hookas *const PanicHook ; +let original_hook = panic::take_hook (); + panic::set_hook (null_hook); + +let works = panic::catch_unwind (proc_macro::Span ::call_site).is_ok (); +WORKS .store (worksas usize +1 ,Ordering ::Relaxed ); + +let hopefully_null_hook = panic::take_hook (); + panic::set_hook (original_hook); +if sanity_check != &*hopefully_null_hook { +panic! ("observed race condition in proc_macro2::inside_proc_macro" ); + } +}
rust/proc-macro2/extra.rs new file +151 -0
151 lines not on this page · raw message
rust/proc-macro2/fallback.rs new file +1256 -0
1,256 lines not on this page · raw message
rust/proc-macro2/lib.rs new file +1349 -0
1,349 lines not on this page · raw message
rust/proc-macro2/location.rs new file +29 -0
@@ -0,0 +1,29 @@ +use core::cmp::Ordering ; + +/// A line-column pair representing the start or end of a `Span`. +/// +/// This type is semver exempt and not exposed by default. +#[cfg_attr(docsrs, doc(cfg(feature = "span-locations" )))] +#[derive( Copy , Clone , Debug , PartialEq , Eq , Hash )] +pub struct LineColumn { +/// The 1-indexed line in the source file on which the span starts or ends +/// (inclusive). +pub line:usize , +/// The 0-indexed column (in UTF-8 characters) in the source file on which +/// the span starts or ends (inclusive). +pub column:usize , +} + +impl Ord for LineColumn { +fn cmp (&self, other: &Self ) ->Ordering { + self.line + .cmp (&other.line) + .then (self.column.cmp (&other.column)) + } +} + +impl PartialOrd for LineColumn { +fn partial_cmp (&self, other: &Self ) ->Option <Ordering > { +Some (self.cmp (other)) + } +}
rust/proc-macro2/marker.rs new file +17 -0
@@ -0,0 +1,17 @@ +use alloc::rc::Rc ; +use core::marker::PhantomData ; +use core::panic::{RefUnwindSafe ,UnwindSafe }; + +// Zero sized marker with the correct set of autotrait impls we want all proc +// macro types to have. +#[derive( Copy , Clone )] +#[cfg_attr( +all(procmacro2_semver_exempt, any(not(wrap_proc_macro), super_unstable)), +derive( PartialEq , Eq ) +)] +pub (crate )struct ProcMacroAutoTraits (PhantomData <Rc <()>>); + +pub (crate )const MARKER :ProcMacroAutoTraits =ProcMacroAutoTraits (PhantomData ); + +impl UnwindSafe for ProcMacroAutoTraits {} +impl RefUnwindSafe for ProcMacroAutoTraits {}
rust/proc-macro2/parse.rs new file +995 -0
123 lines not on this page · raw message
rust/proc-macro2/probe/proc_macro_span.rs new file +51 -0
51 lines not on this page · raw message
rust/proc-macro2/probe/proc_macro_span_file.rs new file +14 -0
Lines of this file are not shown. View the raw message.
rust/proc-macro2/probe/proc_macro_span_location.rs new file +21 -0
Lines of this file are not shown. View the raw message.
rust/proc-macro2/rcvec.rs new file +146 -0
146 lines not on this page · raw message
rust/proc-macro2/wrapper.rs new file +984 -0
984 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
Signature · 1 line
2.52.0
Part of the diff is not shown here. View the raw message.
Miguel Ojeda
maintainerPATCH v2 7/20 rust: proc-macro2: add SPDX License Identifiers
In reply to Miguel OjedaOriginally, when the Rust upstream alloc standard library crate was vendored in commit 057b8d257107 ("rust: adapt alloc crate to the kernel"), the SPDX License Identifiers were added to every file so that the license on those was clear.
Thus do the same for the proc-macro2 crate.
This makes scripts/spdxcheck.py pass.
--- rust/proc-macro2/detection.rs | 2 ++ rust/proc-macro2/extra.rs | 2 ++ rust/proc-macro2/fallback.rs | 2 ++ rust/proc-macro2/lib.rs | 2 ++ rust/proc-macro2/location.rs | 2 ++ rust/proc-macro2/marker.rs | 2 ++ rust/proc-macro2/parse.rs | 2 ++ rust/proc-macro2/probe.rs | 2 ++ rust/proc-macro2/probe/proc_macro_span.rs | 2 ++ rust/proc-macro2/probe/proc_macro_span_file.rs | 2 ++ rust/proc-macro2/probe/proc_macro_span_location.rs | 2 ++ rust/proc-macro2/rcvec.rs | 2 ++ rust/proc-macro2/wrapper.rs | 2 ++ 13 files changed, 26 insertions(+)
rust/proc-macro2/detection.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +use core::sync::atomic::{AtomicUsize ,Ordering };use std::sync::Once ;
rust/proc-macro2/extra.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +//! Items which do not have a correspondence to any API in the proc_macro crate, //! but are necessary to include in proc-macro2.
rust/proc-macro2/fallback.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +#[cfg(wrap_proc_macro)] use crate ::imp;#[cfg(span_locations)]
rust/proc-macro2/lib.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +//! [![github]](https://github.com/dtolnay/proc-macro2) [![crates-io]](https://crates.io/crates/proc-macro2) [![docs-rs]](crate) //! //! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
rust/proc-macro2/location.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +use core::cmp::Ordering ;/// A line-column pair representing the start or end of a `Span`.
rust/proc-macro2/marker.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +use alloc::rc::Rc ;use core::marker::PhantomData ;use core::panic::{RefUnwindSafe ,UnwindSafe };
rust/proc-macro2/parse.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +use crate ::fallback::{ self, is_ident_continue, is_ident_start,Group ,Ident ,LexError ,Literal ,Span ,TokenStream ,TokenStreamBuilder ,
rust/proc-macro2/probe.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +#![allow(dead_code)] #[cfg(proc_macro_span)]
rust/proc-macro2/probe/proc_macro_span.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// This code exercises the surface area that we expect of Span's unstable API. // If the current toolchain is able to compile it, then proc-macro2 is able to // offer these APIs too.
rust/proc-macro2/probe/proc_macro_span_file.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// The subset of Span's API stabilized in Rust 1.88. extern crate proc_macro;
rust/proc-macro2/probe/proc_macro_span_location.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// The subset of Span's API stabilized in Rust 1.88. extern crate proc_macro;
rust/proc-macro2/rcvec.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +use alloc::rc::Rc ;use alloc::vec;use core::mem;
rust/proc-macro2/wrapper.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +use crate ::detection::inside_proc_macro;use crate ::fallback::{self,FromStr2 as _};#[cfg(span_locations)]
Signature · 1 line
2.52.0
Miguel Ojeda
maintainerPATCH v2 8/20 rust: proc-macro2: remove `unicode_ident` dependency
In reply to Miguel OjedaThe proc-macro2 crate depends on the unicode-ident crate to determine whether characters have the XID_Start or XID_Continue properties according to Unicode Standard Annex #31.
However, we only need ASCII identifiers in the kernel, thus we can simplify the check and remove completely that dependency.
--- rust/proc-macro2/fallback.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
rust/proc-macro2/fallback.rs +2 -2
@@ -818,11 +818,11 @@ pub(crate) fn set_span(&mut self, span: Span) { }pub (crate )fn is_ident_start (c:char ) ->bool { - c =='_' || unicode_ident::is_xid_start (c) + c =='_' || c.is_ascii_alphabetic () }pub (crate )fn is_ident_continue (c:char ) ->bool { - unicode_ident::is_xid_continue (c) + c =='_' || c.is_ascii_alphanumeric () }#[track_caller]
Signature · 1 line
2.52.0
Miguel Ojeda
maintainerPATCH v2 9/20 rust: proc-macro2: add `README.md`
In reply to Miguel OjedaOriginally, when the Rust upstream alloc standard library crate was vendored in commit 057b8d257107 ("rust: adapt alloc crate to the kernel"), a README.md file was added to explain the provenance and licensing of the source files.
Thus do the same for the proc-macro2 crate.
--- rust/proc-macro2/README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 rust/proc-macro2/README.md
rust/proc-macro2/README.md new file +13 -0
@@ -0,0 +1,13 @@ +# `proc-macro2` + +These source files come from the Rust `proc-macro2` crate, version +1.0.101 (released 2025-08-16), hosted in the +<https://github.com/dtolnay/proc-macro2> repository, licensed under +"Apache-2.0 OR MIT" and only modified to add the SPDX license +identifiers and to remove the `unicode-ident` dependency. + +For copyright details, please see: + + https://github.com/dtolnay/proc-macro2/blob/1.0.101/README.md#license + https://github.com/dtolnay/proc-macro2/blob/1.0.101/LICENSE-APACHE + https://github.com/dtolnay/proc-macro2/blob/1.0.101/LICENSE-MIT
Signature · 1 line
2.52.0
Miguel Ojeda
maintainerPATCH v2 10/20 rust: proc-macro2: enable support in kbuild
In reply to Miguel OjedaWith all the new files in place and ready from the new crate, enable the support for it in the build system.
proc_macro_byte_character and proc_macro_c_str_literals were stabilized in Rust 1.79.0 [1] and were implemented earlier than our minimum Rust version (1.78) [2][3]. Thus just enable them instead of using the cfg that proc-macro2 uses to emulate them in older compilers.
In addition, skip formatting for this vendored crate and take the chance to add a comment mentioning this.
--- Makefile | 5 +++++ rust/Makefile | 32 +++++++++++++++++++++++++++++-- scripts/generate_rust_analyzer.py | 7 +++++++ 3 files changed, 42 insertions(+), 2 deletions(-)
Makefile +5 -0
@@ -1826,10 +1826,15 @@ rusttest: prepare $(Q)$(MAKE) $(build)=rust $@ # Formatting targets +# +# Generated files as well as vendored crates are skipped. PHONY += rustfmt rustfmtcheck rustfmt: $(Q)find $(srctree) $(RCS_FIND_IGNORE) \ + \( \ + -path $(srctree)/rust/proc-macro2 \ + \) -prune -o \ -type f -a -name '*.rs' -a ! -name '*generated*' -print \ | xargs $(RUSTFMT) $(rustfmt_flags)
rust/Makefile +30 -2
@@ -27,6 +27,8 @@ endif obj-$(CONFIG_RUST) += exports.o +always-$(CONFIG_RUST) += libproc_macro2.rlib + always-$(CONFIG_RUST_KERNEL_DOCTESTS) += doctests_kernel_generated.rs always-$(CONFIG_RUST_KERNEL_DOCTESTS) += doctests_kernel_generated_kunit.c
@@ -76,6 +78,17 @@ core-flags := \ --edition=$(core-edition) \ $(call cfgs-to-flags,$(core-cfgs)) +proc_macro2-cfgs := \ + feature="proc-macro" \ + wrap_proc_macro \ + $(if $(call rustc-min-version,108800),proc_macro_span_file proc_macro_span_location) + +# Stable since Rust 1.79.0: `feature(proc_macro_byte_character,proc_macro_c_str_literals)`. +proc_macro2-flags := \ + --cap-lints=allow \ + -Zcrate-attr='feature(proc_macro_byte_character,proc_macro_c_str_literals)' \ + $(call cfgs-to-flags,$(proc_macro2-cfgs)) + # `rustdoc` did not save the target modifiers, thus workaround for # the time being (https://github.com/rust-lang/rust/issues/144521). rustdoc_modifiers_workaround := $(if $(call rustc-min-version,108800),-Cunsafe-allow-abi-mismatch=fixed-x18)
@@ -125,10 +138,15 @@ rustdoc: rustdoc-core rustdoc-macros rustdoc-compiler_builtins \ $(Q)for f in $(rustdoc_output)/static.files/rustdoc-*.css; do \ echo ".logo-container > img { object-fit: contain; }" >> $$f; done +rustdoc-proc_macro2: private rustdoc_host = yes +rustdoc-proc_macro2: private rustc_target_flags = $(proc_macro2-flags) +rustdoc-proc_macro2: $(src)/proc-macro2/lib.rs rustdoc-clean FORCE + +$(call if_changed,rustdoc) + rustdoc-macros: private rustdoc_host = yes rustdoc-macros: private rustc_target_flags = --crate-type proc-macro \ --extern proc_macro -rustdoc-macros: $(src)/macros/lib.rs rustdoc-clean FORCE +rustdoc-macros: $(src)/macros/lib.rs rustdoc-clean rustdoc-proc_macro2 FORCE +$(call if_changed,rustdoc) # Starting with Rust 1.82.0, skipping `-Wrustdoc::unescaped_backticks` should
@@ -185,6 +203,10 @@ rusttestlib-build_error: $(src)/build_error.rs FORCE rusttestlib-ffi: $(src)/ffi.rs FORCE +$(call if_changed,rustc_test_library) +rusttestlib-proc_macro2: private rustc_target_flags = $(proc_macro2-flags) +rusttestlib-proc_macro2: $(src)/proc-macro2/lib.rs FORCE + +$(call if_changed,rustc_test_library) + rusttestlib-macros: private rustc_target_flags = --extern proc_macro rusttestlib-macros: private rustc_test_library_proc = yes rusttestlib-macros: $(src)/macros/lib.rs FORCE
@@ -431,6 +453,11 @@ quiet_cmd_rustc_procmacrolibrary = $(RUSTC_OR_CLIPPY_QUIET) PL $@ mv $(objtree)/$(obj)/$(patsubst lib%.rlib,%,$(notdir $@)).d $(depfile); \ sed -i '/^\#/d' $(depfile) +$(obj)/libproc_macro2.rlib: private skip_clippy = 1 +$(obj)/libproc_macro2.rlib: private rustc_target_flags = $(proc_macro2-flags) +$(obj)/libproc_macro2.rlib: $(src)/proc-macro2/lib.rs FORCE + +$(call if_changed_dep,rustc_procmacrolibrary) + quiet_cmd_rustc_procmacro = $(RUSTC_OR_CLIPPY_QUIET) P $@ cmd_rustc_procmacro = \ $(RUSTC_OR_CLIPPY) $(rust_common_flags) $(rustc_target_flags) \
@@ -442,7 +469,7 @@ quiet_cmd_rustc_procmacro = $(RUSTC_OR_CLIPPY_QUIET) P $@ @$(objtree)/include/generated/rustc_cfg $< # Procedural macros can only be used with the `rustc` that compiled it. -$(obj)/$(libmacros_name): $(src)/macros/lib.rs FORCE +$(obj)/$(libmacros_name): $(src)/macros/lib.rs $(obj)/libproc_macro2.rlib FORCE +$(call if_changed_dep,rustc_procmacro) $(obj)/$(libpin_init_internal_name): private rustc_target_flags = --cfg kernel
@@ -465,6 +492,7 @@ quiet_cmd_rustc_library = $(if $(skip_clippy),RUSTC,$(RUSTC_OR_CLIPPY_QUIET)) L rust-analyzer: $(Q)MAKEFLAGS= $(srctree)/scripts/generate_rust_analyzer.py \ --cfgs='core=$(core-cfgs)' $(core-edition) \ + --cfgs='proc_macro2=$(proc_macro2-cfgs)' \ $(realpath $(srctree)) $(realpath $(objtree)) \ $(rustc_sysroot) $(RUST_LIB_SRC) $(if $(KBUILD_EXTMOD),$(srcroot)) \ > rust-project.json
scripts/generate_rust_analyzer.py +7 -0
@@ -86,6 +86,13 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edit [], ) + append_crate( + "proc_macro2", + srctree / "rust" / "proc-macro2" / "lib.rs", + ["core", "alloc", "std", "proc_macro"], + cfg=crates_cfgs["proc_macro2"], + ) + append_crate( "macros", srctree / "rust" / "macros" / "lib.rs",
Signature · 1 line
2.52.0
Miguel Ojeda
maintainerPATCH v2 11/20 rust: quote: import crate
In reply to Miguel OjedaThis is a subset of the Rust quote crate, version 1.0.40 (released 2025-03-12), licensed under "Apache-2.0 OR MIT", from:
https://github.com/dtolnay/quote/raw/1.0.40/src
The files are copied as-is, with no modifications whatsoever (not even adding the SPDX identifiers).
For copyright details, please see:
https://github.com/dtolnay/quote/blob/1.0.40/README.md#license https://github.com/dtolnay/quote/blob/1.0.40/LICENSE-APACHE https://github.com/dtolnay/quote/blob/1.0.40/LICENSE-MIT
The next patch modifies these files as needed for use within the kernel. This patch split allows reviewers to double-check the import and to clearly see the differences introduced.
The following script may be used to verify the contents:
for path in $(cd rust/quote/ && find . -type f -name '*.rs'); do
curl --silent --show-error --location \
https://github.com/dtolnay/quote/raw/1.0.40/src/$path \
| diff --unified rust/quote/$path - && echo $path: OK
done--- rust/quote/ext.rs | 110 +++ rust/quote/format.rs | 168 ++++ rust/quote/ident_fragment.rs | 88 ++ rust/quote/lib.rs | 1454 ++++++++++++++++++++++++++++++++++ rust/quote/runtime.rs | 492 ++++++++++++ rust/quote/spanned.rs | 50 ++ rust/quote/to_tokens.rs | 271 +++++++ 7 files changed, 2633 insertions(+) create mode 100644 rust/quote/ext.rs create mode 100644 rust/quote/format.rs create mode 100644 rust/quote/ident_fragment.rs create mode 100644 rust/quote/lib.rs create mode 100644 rust/quote/runtime.rs create mode 100644 rust/quote/spanned.rs create mode 100644 rust/quote/to_tokens.rs
rust/quote/ext.rs new file +110 -0
@@ -0,0 +1,110 @@ +use super ::ToTokens ; +use core::iter; +use proc_macro2::{TokenStream ,TokenTree }; + +/// TokenStream extension trait with methods for appending tokens. +/// +/// This trait is sealed and cannot be implemented outside of the `quote` crate. +pub trait TokenStreamExt : private::Sealed { +/// For use by `ToTokens` implementations. +/// +/// Appends the token specified to this list of tokens. +fn append <U >(&mut self, token:U ) +where +U :Into <TokenTree >; + +/// For use by `ToTokens` implementations. +/// +/// ``` +/// # use quote::{quote, TokenStreamExt, ToTokens}; +/// # use proc_macro2::TokenStream; +/// # +/// struct X; +/// +/// impl ToTokens for X { +/// fn to_tokens(&self, tokens: &mut TokenStream) { +/// tokens.append_all(&[true, false]); +/// } +/// } +/// +/// let tokens = quote!(#X); +/// assert_eq!(tokens.to_string(), "true false"); +/// ``` +fn append_all <I >(&mut self, iter:I ) +where +I :IntoIterator , +I ::Item :ToTokens ; + +/// For use by `ToTokens` implementations. +/// +/// Appends all of the items in the iterator `I`, separated by the tokens +/// `U`. +fn append_separated <I ,U >(&mut self, iter:I , op:U ) +where +I :IntoIterator , +I ::Item :ToTokens , +U :ToTokens ; + +/// For use by `ToTokens` implementations. +/// +/// Appends all tokens in the iterator `I`, appending `U` after each +/// element, including after the last element of the iterator. +fn append_terminated <I ,U >(&mut self, iter:I , term:U ) +where +I :IntoIterator , +I ::Item :ToTokens , +U :ToTokens ; +} + +impl TokenStreamExt for TokenStream { +fn append <U >(&mut self, token:U ) +where +U :Into <TokenTree >, + { + self.extend (iter::once (token.into ())); + } + +fn append_all <I >(&mut self, iter:I ) +where +I :IntoIterator , +I ::Item :ToTokens , + { +for tokenin iter { + token.to_tokens (self); + } + } + +fn append_separated <I ,U >(&mut self, iter:I , op:U ) +where +I :IntoIterator , +I ::Item :ToTokens , +U :ToTokens , + { +for (i, token)in iter.into_iter ().enumerate () { +if i >0 { + op.to_tokens (self); + } + token.to_tokens (self); + } + } + +fn append_terminated <I ,U >(&mut self, iter:I , term:U ) +where +I :IntoIterator , +I ::Item :ToTokens , +U :ToTokens , + { +for tokenin iter { + token.to_tokens (self); + term.to_tokens (self); + } + } +} + +mod private { +use proc_macro2::TokenStream ; + +pub trait Sealed {} + +impl Sealed for TokenStream {} +}
rust/quote/format.rs new file +168 -0
168 lines not on this page · raw message
rust/quote/ident_fragment.rs new file +88 -0
88 lines not on this page · raw message
rust/quote/lib.rs new file +1454 -0
1,454 lines not on this page · raw message
rust/quote/runtime.rs new file +492 -0
492 lines not on this page · raw message
rust/quote/spanned.rs new file +50 -0
50 lines not on this page · raw message
rust/quote/to_tokens.rs new file +271 -0
271 lines not on this page · raw message
Signature · 1 line
2.52.0
Miguel Ojeda
maintainerPATCH v2 12/20 rust: quote: add SPDX License Identifiers
In reply to Miguel OjedaOriginally, when the Rust upstream alloc standard library crate was vendored in commit 057b8d257107 ("rust: adapt alloc crate to the kernel"), the SPDX License Identifiers were added to every file so that the license on those was clear.
Thus do the same for the quote crate.
This makes scripts/spdxcheck.py pass.
--- rust/quote/ext.rs | 2 ++ rust/quote/format.rs | 2 ++ rust/quote/ident_fragment.rs | 2 ++ rust/quote/lib.rs | 2 ++ rust/quote/runtime.rs | 2 ++ rust/quote/spanned.rs | 2 ++ rust/quote/to_tokens.rs | 2 ++ 7 files changed, 14 insertions(+)
rust/quote/ext.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +use super ::ToTokens ;use core::iter;use proc_macro2::{TokenStream ,TokenTree };
rust/quote/format.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +/// Formatting macro for constructing `Ident`s. /// /// <br>
rust/quote/ident_fragment.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +use alloc::borrow::Cow ;use core::fmt;use proc_macro2::{Ident ,Span };
rust/quote/lib.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +//! [![github]](https://github.com/dtolnay/quote) [![crates-io]](https://crates.io/crates/quote) [![docs-rs]](https://docs.rs/quote) //! //! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
rust/quote/runtime.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +use self::get_span::{GetSpan ,GetSpanBase ,GetSpanInner };use crate ::{IdentFragment ,ToTokens ,TokenStreamExt };use core::fmt;
rust/quote/spanned.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +use crate ::ToTokens ;use proc_macro2::extra::DelimSpan ;use proc_macro2::{Span ,TokenStream };
rust/quote/to_tokens.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +use super ::TokenStreamExt ;use alloc::borrow::Cow ;use alloc::rc::Rc ;
Signature · 1 line
2.52.0
Miguel Ojeda
maintainerPATCH v2 13/20 rust: quote: add `README.md`
In reply to Miguel OjedaOriginally, when the Rust upstream alloc standard library crate was vendored in commit 057b8d257107 ("rust: adapt alloc crate to the kernel"), a README.md file was added to explain the provenance and licensing of the source files.
Thus do the same for the quote crate.
--- rust/quote/README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 rust/quote/README.md
rust/quote/README.md new file +12 -0
@@ -0,0 +1,12 @@ +# `quote` + +These source files come from the Rust `quote` crate, version 1.0.40 +(released 2025-03-12), hosted in the <https://github.com/dtolnay/quote> +repository, licensed under "Apache-2.0 OR MIT" and only modified to add +the SPDX license identifiers. + +For copyright details, please see: + + https://github.com/dtolnay/quote/blob/1.0.40/README.md#license + https://github.com/dtolnay/quote/blob/1.0.40/LICENSE-APACHE + https://github.com/dtolnay/quote/blob/1.0.40/LICENSE-MIT
Signature · 1 line
2.52.0
Miguel Ojeda
maintainerPATCH v2 14/20 rust: quote: enable support in kbuild
In reply to Miguel OjedaWith all the new files in place and ready from the new crate, enable the support for it in the build system.
--- Makefile | 1 + rust/Makefile | 38 ++++++++++++++++++++++++++++--- scripts/generate_rust_analyzer.py | 7 ++++++ 3 files changed, 43 insertions(+), 3 deletions(-)
Makefile +1 -0
@@ -1834,6 +1834,7 @@ rustfmt: $(Q)find $(srctree) $(RCS_FIND_IGNORE) \ \( \ -path $(srctree)/rust/proc-macro2 \ + -o -path $(srctree)/rust/quote \ \) -prune -o \ -type f -a -name '*.rs' -a ! -name '*generated*' -print \ | xargs $(RUSTFMT) $(rustfmt_flags)
rust/Makefile +35 -3
@@ -27,7 +27,7 @@ endif obj-$(CONFIG_RUST) += exports.o -always-$(CONFIG_RUST) += libproc_macro2.rlib +always-$(CONFIG_RUST) += libproc_macro2.rlib libquote.rlib always-$(CONFIG_RUST_KERNEL_DOCTESTS) += doctests_kernel_generated.rs always-$(CONFIG_RUST_KERNEL_DOCTESTS) += doctests_kernel_generated_kunit.c
@@ -89,6 +89,18 @@ proc_macro2-flags := \ -Zcrate-attr='feature(proc_macro_byte_character,proc_macro_c_str_literals)' \ $(call cfgs-to-flags,$(proc_macro2-cfgs)) +quote-cfgs := \ + feature="proc-macro" + +quote-skip_flags := \ + --edition=2021 + +quote-flags := \ + --edition=2018 \ + --cap-lints=allow \ + --extern proc_macro2 \ + $(call cfgs-to-flags,$(quote-cfgs)) + # `rustdoc` did not save the target modifiers, thus workaround for # the time being (https://github.com/rust-lang/rust/issues/144521). rustdoc_modifiers_workaround := $(if $(call rustc-min-version,108800),-Cunsafe-allow-abi-mismatch=fixed-x18)
@@ -143,10 +155,17 @@ rustdoc-proc_macro2: private rustc_target_flags = $(proc_macro2-flags) rustdoc-proc_macro2: $(src)/proc-macro2/lib.rs rustdoc-clean FORCE +$(call if_changed,rustdoc) +rustdoc-quote: private rustdoc_host = yes +rustdoc-quote: private rustc_target_flags = $(quote-flags) +rustdoc-quote: private skip_flags = $(quote-skip_flags) +rustdoc-quote: $(src)/quote/lib.rs rustdoc-clean rustdoc-proc_macro2 FORCE + +$(call if_changed,rustdoc) + rustdoc-macros: private rustdoc_host = yes rustdoc-macros: private rustc_target_flags = --crate-type proc-macro \ --extern proc_macro -rustdoc-macros: $(src)/macros/lib.rs rustdoc-clean rustdoc-proc_macro2 FORCE +rustdoc-macros: $(src)/macros/lib.rs rustdoc-clean rustdoc-proc_macro2 \ + rustdoc-quote FORCE +$(call if_changed,rustdoc) # Starting with Rust 1.82.0, skipping `-Wrustdoc::unescaped_backticks` should
@@ -207,6 +226,11 @@ rusttestlib-proc_macro2: private rustc_target_flags = $(proc_macro2-flags) rusttestlib-proc_macro2: $(src)/proc-macro2/lib.rs FORCE +$(call if_changed,rustc_test_library) +rusttestlib-quote: private skip_flags = $(quote-skip_flags) +rusttestlib-quote: private rustc_target_flags = $(quote-flags) +rusttestlib-quote: $(src)/quote/lib.rs rusttestlib-proc_macro2 FORCE + +$(call if_changed,rustc_test_library) + rusttestlib-macros: private rustc_target_flags = --extern proc_macro rusttestlib-macros: private rustc_test_library_proc = yes rusttestlib-macros: $(src)/macros/lib.rs FORCE
@@ -458,6 +482,12 @@ $(obj)/libproc_macro2.rlib: private rustc_target_flags = $(proc_macro2-flags) $(obj)/libproc_macro2.rlib: $(src)/proc-macro2/lib.rs FORCE +$(call if_changed_dep,rustc_procmacrolibrary) +$(obj)/libquote.rlib: private skip_clippy = 1 +$(obj)/libquote.rlib: private skip_flags = $(quote-skip_flags) +$(obj)/libquote.rlib: private rustc_target_flags = $(quote-flags) +$(obj)/libquote.rlib: $(src)/quote/lib.rs $(obj)/libproc_macro2.rlib FORCE + +$(call if_changed_dep,rustc_procmacrolibrary) + quiet_cmd_rustc_procmacro = $(RUSTC_OR_CLIPPY_QUIET) P $@ cmd_rustc_procmacro = \ $(RUSTC_OR_CLIPPY) $(rust_common_flags) $(rustc_target_flags) \
@@ -469,7 +499,8 @@ quiet_cmd_rustc_procmacro = $(RUSTC_OR_CLIPPY_QUIET) P $@ @$(objtree)/include/generated/rustc_cfg $< # Procedural macros can only be used with the `rustc` that compiled it. -$(obj)/$(libmacros_name): $(src)/macros/lib.rs $(obj)/libproc_macro2.rlib FORCE +$(obj)/$(libmacros_name): $(src)/macros/lib.rs $(obj)/libproc_macro2.rlib \ + $(obj)/libquote.rlib FORCE +$(call if_changed_dep,rustc_procmacro) $(obj)/$(libpin_init_internal_name): private rustc_target_flags = --cfg kernel
@@ -493,6 +524,7 @@ rust-analyzer: $(Q)MAKEFLAGS= $(srctree)/scripts/generate_rust_analyzer.py \ --cfgs='core=$(core-cfgs)' $(core-edition) \ --cfgs='proc_macro2=$(proc_macro2-cfgs)' \ + --cfgs='quote=$(quote-cfgs)' \ $(realpath $(srctree)) $(realpath $(objtree)) \ $(rustc_sysroot) $(RUST_LIB_SRC) $(if $(KBUILD_EXTMOD),$(srcroot)) \ > rust-project.json
scripts/generate_rust_analyzer.py +7 -0
@@ -93,6 +93,13 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edit cfg=crates_cfgs["proc_macro2"], ) + append_crate( + "quote", + srctree / "rust" / "quote" / "lib.rs", + ["alloc", "proc_macro", "proc_macro2"], + cfg=crates_cfgs["quote"], + ) + append_crate( "macros", srctree / "rust" / "macros" / "lib.rs",
Signature · 1 line
2.52.0
Miguel Ojeda
maintainerPATCH v2 15/20 rust: syn: import crate
In reply to Miguel OjedaThis is a subset of the Rust syn crate, version 2.0.106 (released 2025-08-16), licensed under "Apache-2.0 OR MIT", from:
https://github.com/dtolnay/syn/raw/2.0.106/src
The files are copied as-is, with no modifications whatsoever (not even adding the SPDX identifiers).
For copyright details, please see:
https://github.com/dtolnay/syn/blob/2.0.106/README.md#license https://github.com/dtolnay/syn/blob/2.0.106/LICENSE-APACHE https://github.com/dtolnay/syn/blob/2.0.106/LICENSE-MIT
The next two patches modify these files as needed for use within the kernel. This patch split allows reviewers to double-check the import and to clearly see the differences introduced.
The following script may be used to verify the contents:
for path in $(cd rust/syn/ && find . -type f -name '*.rs'); do
curl --silent --show-error --location \
https://github.com/dtolnay/syn/raw/2.0.106/src/$path \
| diff --unified rust/syn/$path - && echo $path: OK
done--- rust/syn/attr.rs | 836 +++++++ rust/syn/bigint.rs | 66 + rust/syn/buffer.rs | 434 ++++ rust/syn/classify.rs | 311 +++ rust/syn/custom_keyword.rs | 260 ++ rust/syn/custom_punctuation.rs | 304 +++ rust/syn/data.rs | 424 ++++ rust/syn/derive.rs | 259 ++ rust/syn/discouraged.rs | 225 ++ rust/syn/drops.rs | 58 + rust/syn/error.rs | 467 ++++ rust/syn/export.rs | 73 + rust/syn/expr.rs | 4173 ++++++++++++++++++++++++++++++++ rust/syn/ext.rs | 136 ++ rust/syn/file.rs | 125 + rust/syn/fixup.rs | 773 ++++++ rust/syn/gen/clone.rs | 2267 +++++++++++++++++ rust/syn/gen/debug.rs | 3238 +++++++++++++++++++++++++ rust/syn/gen/eq.rs | 2306 ++++++++++++++++++ rust/syn/gen/fold.rs | 3902 +++++++++++++++++++++++++++++ rust/syn/gen/hash.rs | 2876 ++++++++++++++++++++++ rust/syn/gen/visit.rs | 3941 ++++++++++++++++++++++++++++++ rust/syn/gen/visit_mut.rs | 3759 ++++++++++++++++++++++++++++ rust/syn/generics.rs | 1477 +++++++++++ rust/syn/group.rs | 291 +++ rust/syn/ident.rs | 108 + rust/syn/item.rs | 3490 ++++++++++++++++++++++++++ rust/syn/lib.rs | 1011 ++++++++ rust/syn/lifetime.rs | 156 ++ rust/syn/lit.rs | 1860 ++++++++++++++ rust/syn/lookahead.rs | 332 +++ rust/syn/mac.rs | 225 ++ rust/syn/macros.rs | 182 ++ rust/syn/meta.rs | 427 ++++ rust/syn/op.rs | 219 ++ rust/syn/parse.rs | 1419 +++++++++++ rust/syn/parse_macro_input.rs | 128 + rust/syn/parse_quote.rs | 240 ++ rust/syn/pat.rs | 955 ++++++++ rust/syn/path.rs | 966 ++++++++ rust/syn/precedence.rs | 210 ++ rust/syn/print.rs | 16 + rust/syn/punctuated.rs | 1155 +++++++++ rust/syn/restriction.rs | 178 ++ rust/syn/scan_expr.rs | 265 ++ rust/syn/sealed.rs | 4 + rust/syn/span.rs | 63 + rust/syn/spanned.rs | 118 + rust/syn/stmt.rs | 484 ++++ rust/syn/thread.rs | 60 + rust/syn/token.rs | 1096 +++++++++ rust/syn/tt.rs | 107 + rust/syn/ty.rs | 1271 ++++++++++ rust/syn/verbatim.rs | 33 + rust/syn/whitespace.rs | 65 + 55 files changed, 49824 insertions(+) create mode 100644 rust/syn/attr.rs create mode 100644 rust/syn/bigint.rs create mode 100644 rust/syn/buffer.rs create mode 100644 rust/syn/classify.rs create mode 100644 rust/syn/custom_keyword.rs create mode 100644 rust/syn/custom_punctuation.rs create mode 100644 rust/syn/data.rs create mode 100644 rust/syn/derive.rs create mode 100644 rust/syn/discouraged.rs create mode 100644 rust/syn/drops.rs create mode 100644 rust/syn/error.rs create mode 100644 rust/syn/export.rs create mode 100644 rust/syn/expr.rs create mode 100644 rust/syn/ext.rs create mode 100644 rust/syn/file.rs create mode 100644 rust/syn/fixup.rs create mode 100644 rust/syn/gen/clone.rs create mode 100644 rust/syn/gen/debug.rs create mode 100644 rust/syn/gen/eq.rs create mode 100644 rust/syn/gen/fold.rs create mode 100644 rust/syn/gen/hash.rs create mode 100644 rust/syn/gen/visit.rs create mode 100644 rust/syn/gen/visit_mut.rs create mode 100644 rust/syn/generics.rs create mode 100644 rust/syn/group.rs create mode 100644 rust/syn/ident.rs create mode 100644 rust/syn/item.rs create mode 100644 rust/syn/lib.rs create mode 100644 rust/syn/lifetime.rs create mode 100644 rust/syn/lit.rs create mode 100644 rust/syn/lookahead.rs create mode 100644 rust/syn/mac.rs create mode 100644 rust/syn/macros.rs create mode 100644 rust/syn/meta.rs create mode 100644 rust/syn/op.rs create mode 100644 rust/syn/parse.rs create mode 100644 rust/syn/parse_macro_input.rs create mode 100644 rust/syn/parse_quote.rs create mode 100644 rust/syn/pat.rs create mode 100644 rust/syn/path.rs create mode 100644 rust/syn/precedence.rs create mode 100644 rust/syn/print.rs create mode 100644 rust/syn/punctuated.rs create mode 100644 rust/syn/restriction.rs create mode 100644 rust/syn/scan_expr.rs create mode 100644 rust/syn/sealed.rs create mode 100644 rust/syn/span.rs create mode 100644 rust/syn/spanned.rs create mode 100644 rust/syn/stmt.rs create mode 100644 rust/syn/thread.rs create mode 100644 rust/syn/token.rs create mode 100644 rust/syn/tt.rs create mode 100644 rust/syn/ty.rs create mode 100644 rust/syn/verbatim.rs create mode 100644 rust/syn/whitespace.rs
rust/syn/attr.rs new file +836 -0
@@ -0,0 +1,836 @@ +#[cfg(feature = "parsing" )] +use crate ::error::Error ; +#[cfg(feature = "parsing" )] +use crate ::error::Result ; +use crate ::expr::Expr ; +use crate ::mac::MacroDelimiter ; +#[cfg(feature = "parsing" )] +use crate ::meta::{self,ParseNestedMeta }; +#[cfg(feature = "parsing" )] +use crate ::parse::{Parse ,ParseStream ,Parser }; +use crate ::path::Path ; +use crate ::token; +use proc_macro2::TokenStream ; +#[cfg(feature = "printing" )] +use std::iter; +#[cfg(feature = "printing" )] +use std::slice; + +ast_struct! { +/// An attribute, like `#[repr(transparent)]`. +/// +/// <br> +/// +/// # Syntax +/// +/// Rust has six types of attributes. +/// +/// - Outer attributes like `#[repr(transparent)]`. These appear outside or +/// in front of the item they describe. +/// +/// - Inner attributes like `#![feature(proc_macro)]`. These appear inside +/// of the item they describe, usually a module. +/// +/// - Outer one-line doc comments like `/// Example`. +/// +/// - Inner one-line doc comments like `//! Please file an issue`. +/// +/// - Outer documentation blocks `/** Example */`. +/// +/// - Inner documentation blocks `/*! Please file an issue */`. +/// +/// The `style` field of type `AttrStyle` distinguishes whether an attribute +/// is outer or inner. +/// +/// Every attribute has a `path` that indicates the intended interpretation +/// of the rest of the attribute's contents. The path and the optional +/// additional contents are represented together in the `meta` field of the +/// attribute in three possible varieties: +/// +/// - Meta::Path — attributes whose information content conveys just a +/// path, for example the `#[test]` attribute. +/// +/// - Meta::List — attributes that carry arbitrary tokens after the +/// path, surrounded by a delimiter (parenthesis, bracket, or brace). For +/// example `#[derive(Copy)]` or `#[precondition(x < 5)]`. +/// +/// - Meta::NameValue — attributes with an `=` sign after the path, +/// followed by a Rust expression. For example `#[path = +/// "sys/windows.rs"]`. +/// +/// All doc comments are represented in the NameValue style with a path of +/// "doc", as this is how they are processed by the compiler and by +/// `macro_rules!` macros. +/// +/// ```text +/// #[derive(Copy, Clone)] +/// ~~~~~~Path +/// ^^^^^^^^^^^^^^^^^^^Meta::List +/// +/// #[path = "sys/windows.rs"] +/// ~~~~Path +/// ^^^^^^^^^^^^^^^^^^^^^^^Meta::NameValue +/// +/// #[test] +/// ^^^^Meta::Path +/// ``` +/// +/// <br> +/// +/// # Parsing from tokens to Attribute +/// +/// This type does not implement the [`Parse`] trait and thus cannot be +/// parsed directly by [`ParseStream::parse`]. Instead use +/// [`ParseStream::call`] with one of the two parser functions +/// [`Attribute::parse_outer`] or [`Attribute::parse_inner`] depending on +/// which you intend to parse. +/// +/// [`Parse`]: crate::parse::Parse +/// [`ParseStream::parse`]: crate::parse::ParseBuffer::parse +/// [`ParseStream::call`]: crate::parse::ParseBuffer::call +/// +/// ``` +/// use syn::{Attribute, Ident, Result, Token}; +/// use syn::parse::{Parse, ParseStream}; +/// +/// // Parses a unit struct with attributes. +/// // +/// // #[path = "s.tmpl"] +/// // struct S; +/// struct UnitStruct { +/// attrs: Vec<Attribute>, +/// struct_token: Token![struct], +/// name: Ident, +/// semi_token: Token![;], +/// } +/// +/// impl Parse for UnitStruct { +/// fn parse(input: ParseStream) -> Result<Self> { +/// Ok(UnitStruct { +/// attrs: input.call(Attribute::parse_outer)?, +/// struct_token: input.parse()?, +/// name: input.parse()?, +/// semi_token: input.parse()?, +/// }) +/// } +/// } +/// ``` +/// +/// <p><br></p> +/// +/// # Parsing from Attribute to structured arguments +/// +/// The grammar of attributes in Rust is very flexible, which makes the +/// syntax tree not that useful on its own. In particular, arguments of the +/// `Meta::List` variety of attribute are held in an arbitrary `tokens: +/// TokenStream`. Macros are expected to check the `path` of the attribute, +/// decide whether they recognize it, and then parse the remaining tokens +/// according to whatever grammar they wish to require for that kind of +/// attribute. Use [`parse_args()`] to parse those tokens into the expected +/// data structure. +/// +/// [`parse_args()`]: Attribute::parse_args +/// +/// <p><br></p> +/// +/// # Doc comments +/// +/// The compiler transforms doc comments, such as `/// comment` and `/*! +/// comment */`, into attributes before macros are expanded. Each comment is +/// expanded into an attribute of the form `#[doc = r"comment"]`. +/// +/// As an example, the following `mod` items are expanded identically: +/// +/// ``` +/// # use syn::{ItemMod, parse_quote}; +/// let doc: ItemMod = parse_quote! { +/// /// Single line doc comments +/// /// We write so many! +/// /** +/// * Multi-line comments... +/// * May span many lines +/// */ +/// mod example { +/// //! Of course, they can be inner too +/// /*! And fit in a single line */ +/// } +/// }; +/// let attr: ItemMod = parse_quote! { +/// #[doc = r" Single line doc comments"] +/// #[doc = r" We write so many!"] +/// #[doc = r" +/// * Multi-line comments... +/// * May span many lines +/// "] +/// mod example { +/// #![doc = r" Of course, they can be inner too"] +/// #![doc = r" And fit in a single line "] +/// } +/// }; +/// assert_eq!(doc, attr); +/// ``` +#[cfg_attr(docsrs, doc(cfg(any(feature = "full" , feature = "derive" ))))] +pub struct Attribute { +pub pound_token:Token! [#], +pub style:AttrStyle , +pub bracket_token: token::Bracket , +pub meta:Meta , + } +} + +impl Attribute { +/// Returns the path that identifies the interpretation of this attribute. +/// +/// For example this would return the `test` in `#[test]`, the `derive` in +/// `#[derive(Copy)]`, and the `path` in `#[path = "sys/windows.rs"]`. +pub fn path (&self) -> &Path { + self.meta.path () + } + +/// Parse the arguments to the attribute as a syntax tree. +/// +/// This is similar to pulling out the `TokenStream` from `Meta::List` and +/// doing `syn::parse2::<T>(meta_list.tokens)`, except that using +/// `parse_args` the error message has a more useful span when `tokens` is +/// empty. +/// +/// The surrounding delimiters are *not* included in the input to the +/// parser. +/// +/// ```text +/// #[my_attr(value < 5)] +/// ^^^^^^^^^ what gets parsed +/// ``` +/// +/// # Example +/// +/// ``` +/// use syn::{parse_quote, Attribute, Expr}; +/// +/// let attr: Attribute = parse_quote! { +/// #[precondition(value < 5)] +/// }; +/// +/// if attr.path().is_ident("precondition") { +/// let precondition: Expr = attr.parse_args()?; +/// // ... +/// } +/// # anyhow::Ok(()) +/// ``` +#[cfg(feature = "parsing" )] +#[cfg_attr(docsrs, doc(cfg(feature = "parsing" )))] +pub fn parse_args <T :Parse >(&self) ->Result <T > { + self.parse_args_with (T ::parse) + } + +/// Parse the arguments to the attribute using the given parser. +/// +/// # Example +/// +/// ``` +/// use syn::{parse_quote, Attribute}; +/// +/// let attr: Attribute = parse_quote! { +/// #[inception { #[brrrrrrraaaaawwwwrwrrrmrmrmmrmrmmmmm] }] +/// }; +/// +/// let bwom = attr.parse_args_with(Attribute::parse_outer)?; +/// +/// // Attribute does not have a Parse impl, so we couldn't directly do: +/// // let bwom: Attribute = attr.parse_args()?; +/// # anyhow::Ok(()) +/// ``` +#[cfg(feature = "parsing" )] +#[cfg_attr(docsrs, doc(cfg(feature = "parsing" )))] +pub fn parse_args_with <F :Parser >(&self, parser:F ) ->Result <F ::Output > { +match &self.meta { +Meta ::Path (path) =>Err (crate ::error::new2 ( + path.segments.first ().unwrap ().ident.span (), + path.segments.last ().unwrap ().ident.span (), +format! ( +"expected attribute arguments in parentheses: {}[{}(...)]" , + parsing::DisplayAttrStyle (&self.style), + parsing::DisplayPath (path), + ), + )), +Meta ::NameValue (meta) =>Err (Error ::new ( + meta.eq_token.span, +format_args! ( +"expected parentheses: {}[{}(...)]" , + parsing::DisplayAttrStyle (&self.style), + parsing::DisplayPath (&meta.path), + ), + )), +Meta ::List (meta) => meta.parse_args_with (parser), + } + } + +/// Parse the arguments to the attribute, expecting it to follow the +/// conventional structure used by most of Rust's built-in attributes. +/// +/// The [*Meta Item Attribute Syntax*][syntax] section in the Rust reference +/// explains the convention in more detail. Not all attributes follow this +/// convention, so [`parse_args()`][Self::parse_args] is available if you +/// need to parse arbitrarily goofy attribute syntax. +/// +/// [syntax]: https://doc.rust-lang.org/reference/attributes.html#meta-item-attribute-syntax +/// +/// # Example +/// +/// We'll parse a struct, and then parse some of Rust's `#[repr]` attribute +/// syntax. +/// +/// ``` +/// use syn::{parenthesized, parse_quote, token, ItemStruct, LitInt}; +/// +/// let input: ItemStruct = parse_quote! { +/// #[repr(C, align(4))] +/// pub struct MyStruct(u16, u32); +/// }; +/// +/// let mut repr_c = false; +/// let mut repr_transparent = false; +/// let mut repr_align = None::<usize>; +/// let mut repr_packed = None::<usize>; +/// for attr in &input.attrs { +/// if attr.path().is_ident("repr") { +/// attr.parse_nested_meta(|meta| { +/// // #[repr(C)] +/// if meta.path.is_ident("C") { +/// repr_c = true; +/// return Ok(()); +/// } +/// +/// // #[repr(transparent)] +/// if meta.path.is_ident("transparent") { +/// repr_transparent = true; +/// return Ok(()); +/// } +/// +/// // #[repr(align(N))] +/// if meta.path.is_ident("align") { +/// let content; +/// parenthesized!(content in meta.input); +/// let lit: LitInt = content.parse()?; +/// let n: usize = lit.base10_parse()?; +/// repr_align = Some(n); +/// return Ok(()); +/// } +/// +/// // #[repr(packed)] or #[repr(packed(N))], omitted N means 1 +/// if meta.path.is_ident("packed") { +/// if meta.input.peek(token::Paren) { +/// let content; +/// parenthesized!(content in meta.input); +/// let lit: LitInt = content.parse()?; +/// let n: usize = lit.base10_parse()?; +/// repr_packed = Some(n); +/// } else { +/// repr_packed = Some(1); +/// } +/// return Ok(()); +/// } +/// +/// Err(meta.error("unrecognized repr")) +/// })?; +/// } +/// } +/// # anyhow::Ok(()) +/// ``` +/// +/// # Alternatives +/// +/// In some cases, for attributes which have nested layers of structured +/// content, the following less flexible approach might be more convenient: +/// +/// ``` +/// # use syn::{parse_quote, ItemStruct}; +/// # +/// # let input: ItemStruct = parse_quote! { +/// # #[repr(C, align(4))] +/// # pub struct MyStruct(u16, u32); +/// # }; +/// # +/// use syn::punctuated::Punctuated; +/// use syn::{parenthesized, token, Error, LitInt, Meta, Token}; +/// +/// let mut repr_c = false; +/// let mut repr_transparent = false; +/// let mut repr_align = None::<usize>; +/// let mut repr_packed = None::<usize>; +/// for attr in &input.attrs { +/// if attr.path().is_ident("repr") { +/// let nested = attr.parse_args_with(Punctuated::<Meta, Token![,]>::parse_terminated)?; +/// for meta in nested { +/// match meta { +/// // #[repr(C)] +/// Meta::Path(path) if path.is_ident("C") => { +/// repr_c = true; +/// } +/// +/// // #[repr(align(N))] +/// Meta::List(meta) if meta.path.is_ident("align") => { +/// let lit: LitInt = meta.parse_args()?; +/// let n: usize = lit.base10_parse()?; +/// repr_align = Some(n); +/// } +/// +/// /* ... */ +/// +/// _ => { +/// return Err(Error::new_spanned(meta, "unrecognized repr")); +/// } +/// } +/// } +/// } +/// } +/// # Ok(()) +/// ``` +#[cfg(feature = "parsing" )] +#[cfg_attr(docsrs, doc(cfg(feature = "parsing" )))] +pub fn parse_nested_meta ( + &self, + logic:impl FnMut (ParseNestedMeta ) ->Result <()>, + ) ->Result <()> { + self.parse_args_with (meta::parser (logic)) + } + +/// Parses zero or more outer attributes from the stream. +/// +/// # Example +/// +/// See +/// [*Parsing from tokens to Attribute*](#parsing-from-tokens-to-attribute). +#[cfg(feature = "parsing" )] +#[cfg_attr(docsrs, doc(cfg(feature = "parsing" )))] +pub fn parse_outer (input:ParseStream ) ->Result <Vec <Self >> { +let mut attrs =Vec ::new (); +while input.peek (Token! [#]) { + attrs.push (input.call (parsing::single_parse_outer)?); + } +Ok (attrs) + } + +/// Parses zero or more inner attributes from the stream. +/// +/// # Example +/// +/// See +/// [*Parsing from tokens to Attribute*](#parsing-from-tokens-to-attribute). +#[cfg(feature = "parsing" )] +#[cfg_attr(docsrs, doc(cfg(feature = "parsing" )))] +pub fn parse_inner (input:ParseStream ) ->Result <Vec <Self >> { +let mut attrs =Vec ::new (); + parsing::parse_inner (input, &mut attrs)?; +Ok (attrs) + } +} + +ast_enum! { +/// Distinguishes between attributes that decorate an item and attributes +/// that are contained within an item. +/// +/// # Outer attributes +/// +/// - `#[repr(transparent)]` +/// - `/// # Example` +/// - `/** Please file an issue */` +/// +/// # Inner attributes +/// +/// - `#![feature(proc_macro)]` +/// - `//! # Example` +/// - `/*! Please file an issue */` +#[cfg_attr(docsrs, doc(cfg(any(feature = "full" , feature = "derive" ))))] +pub enum AttrStyle { +Outer , +Inner (Token! [!]), + } +} + +ast_enum! { +/// Content of a compile-time structured attribute. +/// +/// ## Path +/// +/// A meta path is like the `test` in `#[test]`. +/// +/// ## List +/// +/// A meta list is like the `derive(Copy)` in `#[derive(Copy)]`. +/// +/// ## NameValue +/// +/// A name-value meta is like the `path = "..."` in `#[path = +/// "sys/windows.rs"]`. +/// +/// # Syntax tree enum +/// +/// This type is a [syntax tree enum]. +/// +/// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums +#[cfg_attr(docsrs, doc(cfg(any(feature = "full" , feature = "derive" ))))] +pub enum Meta { +Path (Path ), + +/// A structured list within an attribute, like `derive(Copy, Clone)`. +List (MetaList ), + +/// A name-value pair within an attribute, like `feature = "nightly"`. +NameValue (MetaNameValue ), + } +} + +ast_struct! { +/// A structured list within an attribute, like `derive(Copy, Clone)`. +#[cfg_attr(docsrs, doc(cfg(any(feature = "full" , feature = "derive" ))))] +pub struct MetaList { +pub path:Path , +pub delimiter:MacroDelimiter , +pub tokens:TokenStream , + } +} + +ast_struct! { +/// A name-value pair within an attribute, like `feature = "nightly"`. +#[cfg_attr(docsrs, doc(cfg(any(feature = "full" , feature = "derive" ))))] +pub struct MetaNameValue { +pub path:Path , +pub eq_token:Token! [=], +pub value:Expr , + } +} + +impl Meta { +/// Returns the path that begins this structured meta item. +/// +/// For example this would return the `test` in `#[test]`, the `derive` in +/// `#[derive(Copy)]`, and the `path` in `#[path = "sys/windows.rs"]`. +pub fn path (&self) -> &Path { +match self { +Meta ::Path (path) => path, +Meta ::List (meta) => &meta.path, +Meta ::NameValue (meta) => &meta.path, + } + } + +/// Error if this is a `Meta::List` or `Meta::NameValue`. +#[cfg(feature = "parsing" )] +#[cfg_attr(docsrs, doc(cfg(feature = "parsing" )))] +pub fn require_path_only (&self) ->Result <&Path > { +let error_span =match self { +Meta ::Path (path) =>return Ok (path), +Meta ::List (meta) => meta.delimiter.span ().open (), +Meta ::NameValue (meta) => meta.eq_token.span, + }; +Err (Error ::new (error_span,"unexpected token in attribute" )) + } + +/// Error if this is a `Meta::Path` or `Meta::NameValue`. +#[cfg(feature = "parsing" )] +#[cfg_attr(docsrs, doc(cfg(feature = "parsing" )))] +pub fn require_list (&self) ->Result <&MetaList > { +match self { +Meta ::List (meta) =>Ok (meta), +Meta ::Path (path) =>Err (crate ::error::new2 ( + path.segments.first ().unwrap ().ident.span (), + path.segments.last ().unwrap ().ident.span (), +format! ( +"expected attribute arguments in parentheses: `{}(...)`" , + parsing::DisplayPath (path), + ), + )), +Meta ::NameValue (meta) =>Err (Error ::new (meta.eq_token.span,"expected `(`" )), + } + } + +/// Error if this is a `Meta::Path` or `Meta::List`. +#[cfg(feature = "parsing" )] +#[cfg_attr(docsrs, doc(cfg(feature = "parsing" )))] +pub fn require_name_value (&self) ->Result <&MetaNameValue > { +match self { +Meta ::NameValue (meta) =>Ok (meta), +Meta ::Path (path) =>Err (crate ::error::new2 ( + path.segments.first ().unwrap ().ident.span (), + path.segments.last ().unwrap ().ident.span (), +format! ( +"expected a value for this attribute: `{} = ...`" , + parsing::DisplayPath (path), + ), + )), +Meta ::List (meta) =>Err (Error ::new (meta.delimiter.span ().open (),"expected `=`" )), + } + } +} + +impl MetaList { +/// See [`Attribute::parse_args`]. +#[cfg(feature = "parsing" )] +#[cfg_attr(docsrs, doc(cfg(feature = "parsing" )))] +pub fn parse_args <T :Parse >(&self) ->Result <T > { + self.parse_args_with (T ::parse) + } + +/// See [`Attribute::parse_args_with`]. +#[cfg(feature = "parsing" )] +#[cfg_attr(docsrs, doc(cfg(feature = "parsing" )))] +pub fn parse_args_with <F :Parser >(&self, parser:F ) ->Result <F ::Output > { +let scope = self.delimiter.span ().close (); +crate ::parse::parse_scoped (parser, scope, self.tokens.clone ()) + } + +/// See [`Attribute::parse_nested_meta`]. +#[cfg(feature = "parsing" )] +#[cfg_attr(docsrs, doc(cfg(feature = "parsing" )))] +pub fn parse_nested_meta ( + &self, + logic:impl FnMut (ParseNestedMeta ) ->Result <()>, + ) ->Result <()> { + self.parse_args_with (meta::parser (logic)) + } +} + +#[cfg(feature = "printing" )] +pub (crate )trait FilterAttrs <'a> { +type Ret :Iterator <Item = &'aAttribute >; + +fn outer (self) ->Self ::Ret ; +#[cfg(feature = "full" )] +fn inner (self) ->Self ::Ret ; +} + +#[cfg(feature = "printing" )] +impl <'a>FilterAttrs <'a>for &'a [Attribute ] { +type Ret = iter::Filter <slice::Iter <'a,Attribute >,fn (&&Attribute ) ->bool >; + +fn outer (self) ->Self ::Ret { +fn is_outer (attr: &&Attribute ) ->bool { +match attr.style { +AttrStyle ::Outer =>true , +AttrStyle ::Inner (_) =>false , + } + } + self.iter ().filter (is_outer) + } + +#[cfg(feature = "full" )] +fn inner (self) ->Self ::Ret { +fn is_inner (attr: &&Attribute ) ->bool { +match attr.style { +AttrStyle ::Inner (_) =>true , +AttrStyle ::Outer =>false , + } + } + self.iter ().filter (is_inner) + } +} + +impl From <Path >for Meta { +fn from (meta:Path ) ->Meta { +Meta ::Path (meta) + } +} + +impl From <MetaList >for Meta { +fn from (meta:MetaList ) ->Meta { +Meta ::List (meta) + } +} + +impl From <MetaNameValue >for Meta { +fn from (meta:MetaNameValue ) ->Meta { +Meta ::NameValue (meta) + } +} + +#[cfg(feature = "parsing" )] +pub (crate )mod parsing { +use crate ::attr::{AttrStyle ,Attribute ,Meta ,MetaList ,MetaNameValue }; +use crate ::error::Result ; +use crate ::expr::{Expr ,ExprLit }; +use crate ::lit::Lit ; +use crate ::parse::discouraged::Speculative as _; +use crate ::parse::{Parse ,ParseStream }; +use crate ::path::Path ; +use crate ::{mac, token}; +use proc_macro2::Ident ; +use std::fmt::{self,Display }; + +pub (crate )fn parse_inner (input:ParseStream , attrs: &mut Vec <Attribute >) ->Result <()> { +while input.peek (Token! [#]) && input.peek2 (Token! [!]) { + attrs.push (input.call (single_parse_inner)?); + } +Ok (()) + } + +pub (crate )fn single_parse_inner (input:ParseStream ) ->Result <Attribute > { +let content; +Ok (Attribute { + pound_token: input.parse ()?, + style:AttrStyle ::Inner (input.parse ()?), + bracket_token:bracketed! (content in input), + meta: content.parse ()?, + }) + } + +pub (crate )fn single_parse_outer (input:ParseStream ) ->Result <Attribute > { +let content; +Ok (Attribute { + pound_token: input.parse ()?, + style:AttrStyle ::Outer , + bracket_token:bracketed! (content in input), + meta: content.parse ()?, + }) + } + +#[cfg_attr(docsrs, doc(cfg(feature = "parsing" )))] +impl Parse for Meta { +fn parse (input:ParseStream ) ->Result <Self > { +let path =parse_outermost_meta_path (input)?; +parse_meta_after_path (path, input) + } + } + +#[cfg_attr(docsrs, doc(cfg(feature = "parsing" )))] +impl Parse for MetaList { +fn parse (input:ParseStream ) ->Result <Self > { +let path =parse_outermost_meta_path (input)?; +parse_meta_list_after_path (path, input) + } + } + +#[cfg_attr(docsrs, doc(cfg(feature = "parsing" )))] +impl Parse for MetaNameValue { +fn parse (input:ParseStream ) ->Result <Self > { +let path =parse_outermost_meta_path (input)?; +parse_meta_name_value_after_path (path, input) + } + } + +// Unlike meta::parse_meta_path which accepts arbitrary keywords in the path, +// only the `unsafe` keyword is accepted as an attribute's outermost path. +fn parse_outermost_meta_path (input:ParseStream ) ->Result <Path > { +if input.peek (Token! [unsafe ]) { +let unsafe_token:Token! [unsafe ] = input.parse ()?; +Ok (Path ::from (Ident ::new ("unsafe" , unsafe_token.span))) + }else { +Path ::parse_mod_style (input) + } + } + +pub (crate )fn parse_meta_after_path (path:Path , input:ParseStream ) ->Result <Meta > { +if input.peek (token::Paren ) || input.peek (token::Bracket ) || input.peek (token::Brace ) { +parse_meta_list_after_path (path, input).map (Meta ::List ) + }else if input.peek (Token! [=]) { +parse_meta_name_value_after_path (path, input).map (Meta ::NameValue ) + }else { +Ok (Meta ::Path (path)) + } + } + +fn parse_meta_list_after_path (path:Path , input:ParseStream ) ->Result <MetaList > { +let (delimiter, tokens) = mac::parse_delimiter (input)?; +Ok (MetaList { + path, + delimiter, + tokens, + }) + } + +fn parse_meta_name_value_after_path (path:Path , input:ParseStream ) ->Result <MetaNameValue > { +let eq_token:Token! [=] = input.parse ()?; +let ahead = input.fork (); +let lit:Option <Lit > = ahead.parse ()?; +let value =if let (Some (lit),true ) = (lit, ahead.is_empty ()) { + input.advance_to (&ahead); +Expr ::Lit (ExprLit { + attrs:Vec ::new (), + lit, + }) + }else if input.peek (Token! [#]) && input.peek2 (token::Bracket ) { +return Err (input.error ("unexpected attribute inside of attribute" )); + }else { + input.parse ()? + }; +Ok (MetaNameValue { + path, + eq_token, + value, + }) + } + +pub (super )struct DisplayAttrStyle <'a>(pub &'aAttrStyle ); + +impl <'a>Display for DisplayAttrStyle <'a> { +fn fmt (&self, formatter: &mut fmt::Formatter ) -> fmt::Result { + formatter.write_str (match self.0 { +AttrStyle ::Outer =>"#" , +AttrStyle ::Inner (_) =>"#!" , + }) + } + } + +pub (super )struct DisplayPath <'a>(pub &'aPath ); + +impl <'a>Display for DisplayPath <'a> { +fn fmt (&self, formatter: &mut fmt::Formatter ) -> fmt::Result { +for (i, segment)in self.0 .segments.iter ().enumerate () { +if i >0 || self.0 .leading_colon.is_some () { + formatter.write_str ("::" )?; + } +write! (formatter,"{}" , segment.ident)?; + } +Ok (()) + } + } +} + +#[cfg(feature = "printing" )] +mod printing { +use crate ::attr::{AttrStyle ,Attribute ,Meta ,MetaList ,MetaNameValue }; +use crate ::path; +use crate ::path::printing::PathStyle ; +use proc_macro2::TokenStream ; +use quote::ToTokens ; + +#[cfg_attr(docsrs, doc(cfg(feature = "printing" )))] +impl ToTokens for Attribute { +fn to_tokens (&self, tokens: &mut TokenStream ) { + self.pound_token.to_tokens (tokens); +if let AttrStyle ::Inner (b) = &self.style { + b.to_tokens (tokens); + } + self.bracket_token.surround (tokens, |tokens| { + self.meta.to_tokens (tokens); + }); + } + } + +#[cfg_attr(docsrs, doc(cfg(feature = "printing" )))] +impl ToTokens for Meta { +fn to_tokens (&self, tokens: &mut TokenStream ) { +match self { +Meta ::Path (path) => path::printing::print_path (tokens, path,PathStyle ::Mod ), +Meta ::List (meta_list) => meta_list.to_tokens (tokens), +Meta ::NameValue (meta_name_value) => meta_name_value.to_tokens (tokens), + } + } + } + +#[cfg_attr(docsrs, doc(cfg(feature = "printing" )))] +impl ToTokens for MetaList { +fn to_tokens (&self, tokens: &mut TokenStream ) { + path::printing::print_path (tokens, &self.path,PathStyle ::Mod ); + self.delimiter.surround (tokens, self.tokens.clone ()); + } + } + +#[cfg_attr(docsrs, doc(cfg(feature = "printing" )))] +impl ToTokens for MetaNameValue { +fn to_tokens (&self, tokens: &mut TokenStream ) { + path::printing::print_path (tokens, &self.path,PathStyle ::Mod ); + self.eq_token.to_tokens (tokens); + self.value.to_tokens (tokens); + } + } +}
rust/syn/bigint.rs new file +66 -0
66 lines not on this page · raw message
rust/syn/buffer.rs new file +434 -0
434 lines not on this page · raw message
rust/syn/classify.rs new file +311 -0
311 lines not on this page · raw message
rust/syn/custom_keyword.rs new file +260 -0
260 lines not on this page · raw message
rust/syn/custom_punctuation.rs new file +304 -0
304 lines not on this page · raw message
rust/syn/data.rs new file +424 -0
424 lines not on this page · raw message
rust/syn/derive.rs new file +259 -0
259 lines not on this page · raw message
rust/syn/discouraged.rs new file +225 -0
106 lines not on this page · raw message
rust/syn/drops.rs new file +58 -0
58 lines not on this page · raw message
rust/syn/error.rs new file +467 -0
467 lines not on this page · raw message
rust/syn/export.rs new file +73 -0
73 lines not on this page · raw message
rust/syn/expr.rs new file +4173 -0
4,173 lines not on this page · raw message
rust/syn/ext.rs new file +136 -0
136 lines not on this page · raw message
rust/syn/file.rs new file +125 -0
125 lines not on this page · raw message
rust/syn/fixup.rs new file +773 -0
773 lines not on this page · raw message
rust/syn/gen/clone.rs new file +2267 -0
2,267 lines not on this page · raw message
rust/syn/gen/debug.rs new file +3238 -0
3,238 lines not on this page · raw message
rust/syn/gen/eq.rs new file +2306 -0
2,306 lines not on this page · raw message
rust/syn/gen/fold.rs new file +3902 -0
3,902 lines not on this page · raw message
rust/syn/gen/hash.rs new file +2876 -0
2,876 lines not on this page · raw message
rust/syn/gen/visit.rs new file +3941 -0
3,941 lines not on this page · raw message
rust/syn/gen/visit_mut.rs new file +3759 -0
3,759 lines not on this page · raw message
rust/syn/generics.rs new file +1477 -0
1,477 lines not on this page · raw message
rust/syn/group.rs new file +291 -0
291 lines not on this page · raw message
rust/syn/ident.rs new file +108 -0
108 lines not on this page · raw message
rust/syn/item.rs new file +3490 -0
3,490 lines not on this page · raw message
rust/syn/lib.rs new file +1011 -0
1,011 lines not on this page · raw message
rust/syn/lifetime.rs new file +156 -0
156 lines not on this page · raw message
rust/syn/lit.rs new file +1860 -0
1,860 lines not on this page · raw message
rust/syn/lookahead.rs new file +332 -0
332 lines not on this page · raw message
rust/syn/mac.rs new file +225 -0
225 lines not on this page · raw message
rust/syn/macros.rs new file +182 -0
182 lines not on this page · raw message
rust/syn/meta.rs new file +427 -0
427 lines not on this page · raw message
rust/syn/op.rs new file +219 -0
219 lines not on this page · raw message
rust/syn/parse.rs new file +1419 -0
1,419 lines not on this page · raw message
rust/syn/parse_macro_input.rs new file +128 -0
128 lines not on this page · raw message
rust/syn/parse_quote.rs new file +240 -0
240 lines not on this page · raw message
rust/syn/pat.rs new file +955 -0
955 lines not on this page · raw message
rust/syn/path.rs new file +966 -0
966 lines not on this page · raw message
rust/syn/precedence.rs new file +210 -0
210 lines not on this page · raw message
rust/syn/punctuated.rs new file +1155 -0
1,155 lines not on this page · raw message
rust/syn/restriction.rs new file +178 -0
178 lines not on this page · raw message
rust/syn/scan_expr.rs new file +265 -0
265 lines not on this page · raw message
rust/syn/span.rs new file +63 -0
63 lines not on this page · raw message
rust/syn/spanned.rs new file +118 -0
118 lines not on this page · raw message
rust/syn/stmt.rs new file +484 -0
484 lines not on this page · raw message
rust/syn/thread.rs new file +60 -0
60 lines not on this page · raw message
rust/syn/token.rs new file +1096 -0
1,096 lines not on this page · raw message
rust/syn/tt.rs new file +107 -0
107 lines not on this page · raw message
rust/syn/ty.rs new file +1271 -0
1,271 lines not on this page · raw message
rust/syn/whitespace.rs new file +65 -0
65 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
Signature · 1 line
2.52.0
Part of the diff is not shown here. View the raw message.
Miguel Ojeda
maintainerPATCH v2 16/20 rust: syn: add SPDX License Identifiers
In reply to Miguel OjedaOriginally, when the Rust upstream alloc standard library crate was vendored in commit 057b8d257107 ("rust: adapt alloc crate to the kernel"), the SPDX License Identifiers were added to every file so that the license on those was clear.
Thus do the same for the syn crate.
This makes scripts/spdxcheck.py pass.
--- rust/syn/attr.rs | 2 ++ rust/syn/bigint.rs | 2 ++ rust/syn/buffer.rs | 2 ++ rust/syn/classify.rs | 2 ++ rust/syn/custom_keyword.rs | 2 ++ rust/syn/custom_punctuation.rs | 2 ++ rust/syn/data.rs | 2 ++ rust/syn/derive.rs | 2 ++ rust/syn/discouraged.rs | 2 ++ rust/syn/drops.rs | 2 ++ rust/syn/error.rs | 2 ++ rust/syn/export.rs | 2 ++ rust/syn/expr.rs | 2 ++ rust/syn/ext.rs | 2 ++ rust/syn/file.rs | 2 ++ rust/syn/fixup.rs | 2 ++ rust/syn/gen/clone.rs | 2 ++ rust/syn/gen/debug.rs | 2 ++ rust/syn/gen/eq.rs | 2 ++ rust/syn/gen/fold.rs | 2 ++ rust/syn/gen/hash.rs | 2 ++ rust/syn/gen/visit.rs | 2 ++ rust/syn/gen/visit_mut.rs | 2 ++ rust/syn/generics.rs | 2 ++ rust/syn/group.rs | 2 ++ rust/syn/ident.rs | 2 ++ rust/syn/item.rs | 2 ++ rust/syn/lib.rs | 2 ++ rust/syn/lifetime.rs | 2 ++ rust/syn/lit.rs | 2 ++ rust/syn/lookahead.rs | 2 ++ rust/syn/mac.rs | 2 ++ rust/syn/macros.rs | 2 ++ rust/syn/meta.rs | 2 ++ rust/syn/op.rs | 2 ++ rust/syn/parse.rs | 2 ++ rust/syn/parse_macro_input.rs | 2 ++ rust/syn/parse_quote.rs | 2 ++ rust/syn/pat.rs | 2 ++ rust/syn/path.rs | 2 ++ rust/syn/precedence.rs | 2 ++ rust/syn/print.rs | 2 ++ rust/syn/punctuated.rs | 2 ++ rust/syn/restriction.rs | 2 ++ rust/syn/scan_expr.rs | 2 ++ rust/syn/sealed.rs | 2 ++ rust/syn/span.rs | 2 ++ rust/syn/spanned.rs | 2 ++ rust/syn/stmt.rs | 2 ++ rust/syn/thread.rs | 2 ++ rust/syn/token.rs | 2 ++ rust/syn/tt.rs | 2 ++ rust/syn/ty.rs | 2 ++ rust/syn/verbatim.rs | 2 ++ rust/syn/whitespace.rs | 2 ++ 55 files changed, 110 insertions(+)
rust/syn/attr.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +#[cfg(feature = "parsing" )] use crate ::error::Error ;#[cfg(feature = "parsing" )]
rust/syn/bigint.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +use std::ops::{AddAssign ,MulAssign };// For implementing base10_digits() accessor on LitInt.
rust/syn/buffer.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +//! A stably addressed token buffer supporting efficient traversal based on a //! cheaply copyable cursor.
rust/syn/classify.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +#[cfg(feature = "full" )] use crate ::expr::Expr ;#[cfg(any(feature = "printing" , feature = "full" ))]
rust/syn/custom_keyword.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +/// Define a type that supports parsing and printing a given identifier as if it /// were a keyword. ///
rust/syn/custom_punctuation.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +/// Define a type that supports parsing and printing a multi-character symbol /// as if it were a punctuation token. ///
rust/syn/data.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +use crate ::attr::Attribute ;use crate ::expr::{Expr ,Index ,Member };use crate ::ident::Ident ;
rust/syn/derive.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +use crate ::attr::Attribute ;use crate ::data::{Fields ,FieldsNamed ,Variant };use crate ::generics::Generics ;
rust/syn/discouraged.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +//! Extensions to the parsing API with niche applicability. use crate ::buffer::Cursor ;
rust/syn/drops.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +use std::iter;use std::mem::ManuallyDrop ;use std::ops::{Deref ,DerefMut };
rust/syn/error.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +#[cfg(feature = "parsing" )] use crate ::buffer::Cursor ;use crate ::thread::ThreadBound ;
rust/syn/export.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +#[doc(hidden)] pub use std::clone::Clone ;#[doc(hidden)]
rust/syn/expr.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +use crate ::attr::Attribute ;#[cfg(all(feature = "parsing" , feature = "full" ))] use crate ::error::Result ;
rust/syn/ext.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +//! Extension traits to provide parsing methods on foreign types. use crate ::buffer::Cursor ;
rust/syn/file.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +use crate ::attr::Attribute ;use crate ::item::Item ;
rust/syn/fixup.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +use crate ::classify;use crate ::expr::Expr ;#[cfg(feature = "full" )]
rust/syn/gen/clone.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// This file is @generated by syn-internal-codegen. // It is not intended for manual editing.
rust/syn/gen/debug.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// This file is @generated by syn-internal-codegen. // It is not intended for manual editing.
rust/syn/gen/eq.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// This file is @generated by syn-internal-codegen. // It is not intended for manual editing.
rust/syn/gen/fold.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// This file is @generated by syn-internal-codegen. // It is not intended for manual editing.
rust/syn/gen/hash.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// This file is @generated by syn-internal-codegen. // It is not intended for manual editing.
rust/syn/gen/visit.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// This file is @generated by syn-internal-codegen. // It is not intended for manual editing.
rust/syn/gen/visit_mut.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +// This file is @generated by syn-internal-codegen. // It is not intended for manual editing.
rust/syn/generics.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +use crate ::attr::Attribute ;use crate ::expr::Expr ;use crate ::ident::Ident ;
rust/syn/group.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +use crate ::error::Result ;use crate ::parse::ParseBuffer ;use crate ::token;
rust/syn/ident.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +#[cfg(feature = "parsing" )] use crate ::lookahead;
rust/syn/item.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +use crate ::attr::Attribute ;use crate ::data::{Fields ,FieldsNamed ,Variant };use crate ::derive::{Data ,DataEnum ,DataStruct ,DataUnion ,DeriveInput };
rust/syn/lib.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +//! [![github]](https://github.com/dtolnay/syn) [![crates-io]](https://crates.io/crates/syn) [![docs-rs]](crate) //! //! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
rust/syn/lifetime.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +#[cfg(feature = "parsing" )] use crate ::lookahead;use proc_macro2::{Ident ,Span };
rust/syn/lit.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +#[cfg(feature = "parsing" )] use crate ::lookahead;#[cfg(feature = "parsing" )]
rust/syn/lookahead.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +use crate ::buffer::Cursor ;use crate ::error::{self,Error };use crate ::sealed::lookahead::Sealed ;
rust/syn/mac.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +#[cfg(feature = "parsing" )] use crate ::error::Result ;#[cfg(feature = "parsing" )]
rust/syn/macros.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT + #[cfg_attr( not(any(feature = "full", feature = "derive")), allow(unknown_lints, unused_macro_rules)
rust/syn/meta.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +//! Facility for interpreting structured content inside of an `Attribute`. use crate ::error::{Error ,Result };
rust/syn/op.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +ast_enum! {/// A binary operator: `+`, `+=`, `&`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full" , feature = "derive" ))))]
rust/syn/parse.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +//! Parsing interface for parsing a token stream into a syntax tree node. //! //! Parsing in Syn is built on parser functions that take in a [`ParseStream`]
rust/syn/parse_macro_input.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +/// Parse the input TokenStream of a macro, triggering a compile error if the /// tokens fail to parse. ///
rust/syn/parse_quote.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +/// Quasi-quotation macro that accepts input like the [`quote!`] macro but uses /// type inference to figure out a return type for those tokens. ///
rust/syn/pat.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +use crate ::attr::Attribute ;use crate ::expr::Member ;use crate ::ident::Ident ;
rust/syn/path.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +#[cfg(feature = "parsing" )] use crate ::error::Result ;use crate ::expr::Expr ;
rust/syn/precedence.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +#[cfg(all(feature = "printing" , feature = "full" ))] use crate ::attr::{AttrStyle ,Attribute };#[cfg(feature = "printing" )]
rust/syn/print.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +use proc_macro2::TokenStream ;use quote::ToTokens ;
rust/syn/punctuated.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +//! A punctuated sequence of syntax tree nodes separated by punctuation. //! //! Lots of things in Rust are punctuated sequences.
rust/syn/restriction.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +use crate ::path::Path ;use crate ::token;
rust/syn/scan_expr.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +use self::{Action ::*,Input ::*};use proc_macro2::{Delimiter ,Ident ,Spacing ,TokenTree };use syn::parse::{ParseStream ,Result };
rust/syn/sealed.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +#[cfg(feature = "parsing" )] pub (crate )mod lookahead {pub trait Sealed :Copy {}
rust/syn/span.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +use proc_macro2::extra::DelimSpan ;use proc_macro2::{Delimiter ,Group ,Span ,TokenStream };
rust/syn/spanned.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +//! A trait that can provide the `Span` of the complete contents of a syntax //! tree node. //!
rust/syn/stmt.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +use crate ::attr::Attribute ;use crate ::expr::Expr ;use crate ::item::Item ;
rust/syn/thread.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +use std::fmt::{self,Debug };use std::thread::{self,ThreadId };
rust/syn/token.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +//! Tokens representing Rust punctuation, keywords, and delimiters. //! //! The type names in this module can be difficult to keep straight, so we
rust/syn/tt.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +use proc_macro2::{Delimiter ,TokenStream ,TokenTree };use std::hash::{Hash ,Hasher };
rust/syn/ty.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +use crate ::attr::Attribute ;use crate ::expr::Expr ;use crate ::generics::{BoundLifetimes ,TypeParamBound };
rust/syn/verbatim.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +use crate ::parse::ParseStream ;use proc_macro2::{Delimiter ,TokenStream };use std::cmp::Ordering ;
rust/syn/whitespace.rs +2 -0
@@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT +pub (crate )fn skip (mut s: &str ) -> &str { 'skip:while !s.is_empty () {let byte = s.as_bytes ()[0 ];
Signature · 1 line
2.52.0
Miguel Ojeda
maintainerPATCH v2 17/20 rust: syn: remove `unicode-ident` dependency
In reply to Miguel OjedaThe syn crate depends on the unicode-ident crate to determine whether characters have the XID_Start or XID_Continue properties according to Unicode Standard Annex #31.
However, we only need ASCII identifiers in the kernel, thus we can simplify the check and remove completely that dependency.
--- rust/syn/ident.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
rust/syn/ident.rs +2 -2
@@ -39,11 +39,11 @@ fn from(token: Token![_]) -> Ident {pub (crate )fn xid_ok (symbol: &str ) ->bool {let mut chars = symbol.chars ();let first = chars.next ().unwrap (); -if !(first =='_' || unicode_ident::is_xid_start (first)) { +if !(first =='_' || first.is_ascii_alphabetic ()) {return false ; }for chin chars { -if !unicode_ident::is_xid_continue (ch) { +if !(ch =='_' || ch.is_ascii_alphanumeric ()) {return false ; } }
Signature · 1 line
2.52.0
Miguel Ojeda
maintainerPATCH v2 18/20 rust: syn: add `README.md`
In reply to Miguel OjedaOriginally, when the Rust upstream alloc standard library crate was vendored in commit 057b8d257107 ("rust: adapt alloc crate to the kernel"), a README.md file was added to explain the provenance and licensing of the source files.
Thus do the same for the syn crate.
--- rust/syn/README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 rust/syn/README.md
rust/syn/README.md new file +13 -0
@@ -0,0 +1,13 @@ +# `syn` + +These source files come from the Rust `syn` crate, version 2.0.106 +(released 2025-08-16), hosted in the <https://github.com/dtolnay/syn> +repository, licensed under "Apache-2.0 OR MIT" and only modified to add +the SPDX license identifiers and to remove the `unicode-ident` +dependency. + +For copyright details, please see: + + https://github.com/dtolnay/syn/blob/2.0.106/README.md#license + https://github.com/dtolnay/syn/blob/2.0.106/LICENSE-APACHE + https://github.com/dtolnay/syn/blob/2.0.106/LICENSE-MIT
Signature · 1 line
2.52.0
Miguel Ojeda
maintainerPATCH v2 19/20 rust: syn: enable support in kbuild
In reply to Miguel OjedaWith all the new files in place and ready from the new crate, enable the support for it in the build system.
--- Makefile | 1 + rust/Makefile | 37 ++++++++++++++++++++++++++++--- scripts/generate_rust_analyzer.py | 7 ++++++ 3 files changed, 42 insertions(+), 3 deletions(-)
Makefile +1 -0
@@ -1835,6 +1835,7 @@ rustfmt: \( \ -path $(srctree)/rust/proc-macro2 \ -o -path $(srctree)/rust/quote \ + -o -path $(srctree)/rust/syn \ \) -prune -o \ -type f -a -name '*.rs' -a ! -name '*generated*' -print \ | xargs $(RUSTFMT) $(rustfmt_flags)
rust/Makefile +34 -3
@@ -27,7 +27,7 @@ endif obj-$(CONFIG_RUST) += exports.o -always-$(CONFIG_RUST) += libproc_macro2.rlib libquote.rlib +always-$(CONFIG_RUST) += libproc_macro2.rlib libquote.rlib libsyn.rlib always-$(CONFIG_RUST_KERNEL_DOCTESTS) += doctests_kernel_generated.rs always-$(CONFIG_RUST_KERNEL_DOCTESTS) += doctests_kernel_generated_kunit.c
@@ -101,6 +101,22 @@ quote-flags := \ --extern proc_macro2 \ $(call cfgs-to-flags,$(quote-cfgs)) +# `extra-traits`, `fold` and `visit` may be enabled if needed. +syn-cfgs := \ + feature="clone-impls" \ + feature="derive" \ + feature="full" \ + feature="parsing" \ + feature="printing" \ + feature="proc-macro" \ + feature="visit-mut" + +syn-flags := \ + --cap-lints=allow \ + --extern proc_macro2 \ + --extern quote \ + $(call cfgs-to-flags,$(syn-cfgs)) + # `rustdoc` did not save the target modifiers, thus workaround for # the time being (https://github.com/rust-lang/rust/issues/144521). rustdoc_modifiers_workaround := $(if $(call rustc-min-version,108800),-Cunsafe-allow-abi-mismatch=fixed-x18)
@@ -161,11 +177,16 @@ rustdoc-quote: private skip_flags = $(quote-skip_flags) rustdoc-quote: $(src)/quote/lib.rs rustdoc-clean rustdoc-proc_macro2 FORCE +$(call if_changed,rustdoc) +rustdoc-syn: private rustdoc_host = yes +rustdoc-syn: private rustc_target_flags = $(syn-flags) +rustdoc-syn: $(src)/syn/lib.rs rustdoc-clean rustdoc-quote FORCE + +$(call if_changed,rustdoc) + rustdoc-macros: private rustdoc_host = yes rustdoc-macros: private rustc_target_flags = --crate-type proc-macro \ --extern proc_macro rustdoc-macros: $(src)/macros/lib.rs rustdoc-clean rustdoc-proc_macro2 \ - rustdoc-quote FORCE + rustdoc-quote rustdoc-syn FORCE +$(call if_changed,rustdoc) # Starting with Rust 1.82.0, skipping `-Wrustdoc::unescaped_backticks` should
@@ -231,6 +252,10 @@ rusttestlib-quote: private rustc_target_flags = $(quote-flags) rusttestlib-quote: $(src)/quote/lib.rs rusttestlib-proc_macro2 FORCE +$(call if_changed,rustc_test_library) +rusttestlib-syn: private rustc_target_flags = $(syn-flags) +rusttestlib-syn: $(src)/syn/lib.rs rusttestlib-quote FORCE + +$(call if_changed,rustc_test_library) + rusttestlib-macros: private rustc_target_flags = --extern proc_macro rusttestlib-macros: private rustc_test_library_proc = yes rusttestlib-macros: $(src)/macros/lib.rs FORCE
@@ -488,6 +513,11 @@ $(obj)/libquote.rlib: private rustc_target_flags = $(quote-flags) $(obj)/libquote.rlib: $(src)/quote/lib.rs $(obj)/libproc_macro2.rlib FORCE +$(call if_changed_dep,rustc_procmacrolibrary) +$(obj)/libsyn.rlib: private skip_clippy = 1 +$(obj)/libsyn.rlib: private rustc_target_flags = $(syn-flags) +$(obj)/libsyn.rlib: $(src)/syn/lib.rs $(obj)/libquote.rlib FORCE + +$(call if_changed_dep,rustc_procmacrolibrary) + quiet_cmd_rustc_procmacro = $(RUSTC_OR_CLIPPY_QUIET) P $@ cmd_rustc_procmacro = \ $(RUSTC_OR_CLIPPY) $(rust_common_flags) $(rustc_target_flags) \
@@ -500,7 +530,7 @@ quiet_cmd_rustc_procmacro = $(RUSTC_OR_CLIPPY_QUIET) P $@ # Procedural macros can only be used with the `rustc` that compiled it. $(obj)/$(libmacros_name): $(src)/macros/lib.rs $(obj)/libproc_macro2.rlib \ - $(obj)/libquote.rlib FORCE + $(obj)/libquote.rlib $(obj)/libsyn.rlib FORCE +$(call if_changed_dep,rustc_procmacro) $(obj)/$(libpin_init_internal_name): private rustc_target_flags = --cfg kernel
@@ -525,6 +555,7 @@ rust-analyzer: --cfgs='core=$(core-cfgs)' $(core-edition) \ --cfgs='proc_macro2=$(proc_macro2-cfgs)' \ --cfgs='quote=$(quote-cfgs)' \ + --cfgs='syn=$(syn-cfgs)' \ $(realpath $(srctree)) $(realpath $(objtree)) \ $(rustc_sysroot) $(RUST_LIB_SRC) $(if $(KBUILD_EXTMOD),$(srcroot)) \ > rust-project.json
scripts/generate_rust_analyzer.py +7 -0
@@ -100,6 +100,13 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edit cfg=crates_cfgs["quote"], ) + append_crate( + "syn", + srctree / "rust" / "syn" / "lib.rs", + ["proc_macro", "proc_macro2", "quote"], + cfg=crates_cfgs["syn"], + ) + append_crate( "macros", srctree / "rust" / "macros" / "lib.rs",
Signature · 1 line
2.52.0
Re: [PATCH v2 19/20] rust: syn: enable support in kbuild
Quoted 126 lines · Miguel Ojeda
With all the new files in place and ready from the new crate, enable the support for it in the build system.
Reviewed-by Alice Ryhl <[email protected]>Reviewed-by Gary Guo <[email protected]>Tested-by Gary Guo <[email protected]>Tested-by Jesung Yang <[email protected]>Signed-off-by Miguel Ojeda <[email protected]>--- Makefile | 1 + rust/Makefile | 37 ++++++++++++++++++++++++++++--- scripts/generate_rust_analyzer.py | 7 ++++++ 3 files changed, 42 insertions(+), 3 deletions(-)Makefile +1
-0@@ -1835,6 +1835,7 @@ rustfmt: \( \ -path $(srctree)/rust/proc-macro2 \ -o -path $(srctree)/rust/quote \ + -o -path $(srctree)/rust/syn \ \) -prune -o \ -type f -a -name '*.rs' -a ! -name '*generated*' -print \ | xargs $(RUSTFMT) $(rustfmt_flags)rust/Makefile +34
-3@@ -27,7 +27,7 @@ endif obj-$(CONFIG_RUST) += exports.o -always-$(CONFIG_RUST) += libproc_macro2.rlib libquote.rlib +always-$(CONFIG_RUST) += libproc_macro2.rlib libquote.rlib libsyn.rlib always-$(CONFIG_RUST_KERNEL_DOCTESTS) += doctests_kernel_generated.rs always-$(CONFIG_RUST_KERNEL_DOCTESTS) += doctests_kernel_generated_kunit.c@@ -101,6 +101,22 @@ quote-flags := \ --extern proc_macro2 \ $(call cfgs-to-flags,$(quote-cfgs)) +# `extra-traits`, `fold` and `visit` may be enabled if needed. +syn-cfgs := \ + feature="clone-impls" \ + feature="derive" \ + feature="full" \ + feature="parsing" \ + feature="printing" \ + feature="proc-macro" \ + feature="visit-mut" + +syn-flags := \ + --cap-lints=allow \ + --extern proc_macro2 \ + --extern quote \ + $(call cfgs-to-flags,$(syn-cfgs)) + # `rustdoc` did not save the target modifiers, thus workaround for # the time being (https://github.com/rust-lang/rust/issues/144521). rustdoc_modifiers_workaround := $(if $(call rustc-min-version,108800),-Cunsafe-allow-abi-mismatch=fixed-x18)@@ -161,11 +177,16 @@ rustdoc-quote: private skip_flags = $(quote-skip_flags) rustdoc-quote: $(src)/quote/lib.rs rustdoc-clean rustdoc-proc_macro2 FORCE +$(call if_changed,rustdoc) +rustdoc-syn: private rustdoc_host = yes +rustdoc-syn: private rustc_target_flags = $(syn-flags) +rustdoc-syn: $(src)/syn/lib.rs rustdoc-clean rustdoc-quote FORCE + +$(call if_changed,rustdoc) + rustdoc-macros: private rustdoc_host = yes rustdoc-macros: private rustc_target_flags = --crate-type proc-macro \ --extern proc_macro rustdoc-macros: $(src)/macros/lib.rs rustdoc-clean rustdoc-proc_macro2 \ - rustdoc-quote FORCE + rustdoc-quote rustdoc-syn FORCE +$(call if_changed,rustdoc) # Starting with Rust 1.82.0, skipping `-Wrustdoc::unescaped_backticks` should@@ -231,6 +252,10 @@ rusttestlib-quote: private rustc_target_flags = $(quote-flags) rusttestlib-quote: $(src)/quote/lib.rs rusttestlib-proc_macro2 FORCE +$(call if_changed,rustc_test_library) +rusttestlib-syn: private rustc_target_flags = $(syn-flags) +rusttestlib-syn: $(src)/syn/lib.rs rusttestlib-quote FORCE + +$(call if_changed,rustc_test_library) + rusttestlib-macros: private rustc_target_flags = --extern proc_macro rusttestlib-macros: private rustc_test_library_proc = yes rusttestlib-macros: $(src)/macros/lib.rs FORCE@@ -488,6 +513,11 @@ $(obj)/libquote.rlib: private rustc_target_flags = $(quote-flags) $(obj)/libquote.rlib: $(src)/quote/lib.rs $(obj)/libproc_macro2.rlib FORCE +$(call if_changed_dep,rustc_procmacrolibrary) +$(obj)/libsyn.rlib: private skip_clippy = 1 +$(obj)/libsyn.rlib: private rustc_target_flags = $(syn-flags) +$(obj)/libsyn.rlib: $(src)/syn/lib.rs $(obj)/libquote.rlib FORCE + +$(call if_changed_dep,rustc_procmacrolibrary) + quiet_cmd_rustc_procmacro = $(RUSTC_OR_CLIPPY_QUIET) P $@ cmd_rustc_procmacro = \ $(RUSTC_OR_CLIPPY) $(rust_common_flags) $(rustc_target_flags) \@@ -500,7 +530,7 @@ quiet_cmd_rustc_procmacro = $(RUSTC_OR_CLIPPY_QUIET) P $@ # Procedural macros can only be used with the `rustc` that compiled it. $(obj)/$(libmacros_name): $(src)/macros/lib.rs $(obj)/libproc_macro2.rlib \ - $(obj)/libquote.rlib FORCE + $(obj)/libquote.rlib $(obj)/libsyn.rlib FORCE +$(call if_changed_dep,rustc_procmacro) $(obj)/$(libpin_init_internal_name): private rustc_target_flags = --cfg kernel@@ -525,6 +555,7 @@ rust-analyzer: --cfgs='core=$(core-cfgs)' $(core-edition) \ --cfgs='proc_macro2=$(proc_macro2-cfgs)' \ --cfgs='quote=$(quote-cfgs)' \ + --cfgs='syn=$(syn-cfgs)' \ $(realpath $(srctree)) $(realpath $(objtree)) \ $(rustc_sysroot) $(RUST_LIB_SRC) $(if $(KBUILD_EXTMOD),$(srcroot)) \ > rust-project.jsonscripts/generate_rust_analyzer.py +0
-0
scripts/generate_rust_analyzer.py def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edit · line 108
Quoted 9 lines
scripts/generate_rust_analyzer.py +6
-0@@ -100,6 +100,13 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edit cfg=crates_cfgs["quote"], ) + append_crate( + "syn", + srctree / "rust" / "syn" / "lib.rs", + ["proc_macro", "proc_macro2", "quote"], + cfg=crates_cfgs["syn"], + )
I think we need to add "std" here -- without it, navigating to methods on e.g. Vec items defined in syn doesn't work (it does work with "std" added).
Quoted 8 lines
scripts/generate_rust_analyzer.py +1
-1+ append_crate( "macros", srctree / "rust" / "macros" / "lib.rs", --2.52.0
Jesung Yang
reviewerRe: [PATCH v2 19/20] rust: syn: enable support in kbuild
Quoted 1 line · Tamir Duberstein
On Mon, Nov 24, 2025 at 10:25 AM Miguel Ojeda <[email protected]> wrote:
[...]
Quoted 8 lines
Quoted 8 lines
scripts/generate_rust_analyzer.py +0
-0@@ -100,6 +100,13 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edit cfg=crates_cfgs["quote"], )
Quoted 10 lines
scripts/generate_rust_analyzer.py def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edit · line 108
Quoted 6 lines
scripts/generate_rust_analyzer.py +6
-0+ append_crate( + "syn", + srctree / "rust" / "syn" / "lib.rs", + ["proc_macro", "proc_macro2", "quote"], + cfg=crates_cfgs["syn"], + )I think we need to add "std" here -- without it, navigating to methods on e.g. Vec items defined in syn doesn't work (it does work with "std" added).
This was handled in [1], but hasn't landed yet, probably due to lack of Reviewed-by or Tested-by tags. If anyone has a moment to take a look and provide some tags, it would be appreciated!
Best regards,
Jesung
Miguel Ojeda
maintainerPATCH v2 20/20 rust: macros: support `proc-macro2`, `quote` and `syn`
In reply to Miguel OjedaOne of the two main uses cases for adding proc-macro2, quote and syn is the macros crates (and the other pin-init).
Thus add the support for the crates in macros already.
--- rust/Makefile | 13 +++++++++---- scripts/generate_rust_analyzer.py | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-)
rust/Makefile +9 -4
@@ -184,7 +184,7 @@ rustdoc-syn: $(src)/syn/lib.rs rustdoc-clean rustdoc-quote FORCE rustdoc-macros: private rustdoc_host = yes rustdoc-macros: private rustc_target_flags = --crate-type proc-macro \ - --extern proc_macro + --extern proc_macro --extern proc_macro2 --extern quote --extern syn rustdoc-macros: $(src)/macros/lib.rs rustdoc-clean rustdoc-proc_macro2 \ rustdoc-quote rustdoc-syn FORCE +$(call if_changed,rustdoc)
@@ -256,9 +256,11 @@ rusttestlib-syn: private rustc_target_flags = $(syn-flags) rusttestlib-syn: $(src)/syn/lib.rs rusttestlib-quote FORCE +$(call if_changed,rustc_test_library) -rusttestlib-macros: private rustc_target_flags = --extern proc_macro +rusttestlib-macros: private rustc_target_flags = --extern proc_macro \ + --extern proc_macro2 --extern quote --extern syn rusttestlib-macros: private rustc_test_library_proc = yes -rusttestlib-macros: $(src)/macros/lib.rs FORCE +rusttestlib-macros: $(src)/macros/lib.rs \ + rusttestlib-proc_macro2 rusttestlib-quote rusttestlib-syn FORCE +$(call if_changed,rustc_test_library) rusttestlib-pin_init_internal: private rustc_target_flags = --cfg kernel \
@@ -339,7 +341,8 @@ quiet_cmd_rustc_test = $(RUSTC_OR_CLIPPY_QUIET) T $< rusttest: rusttest-macros rusttest-macros: private rustc_target_flags = --extern proc_macro \ - --extern macros --extern kernel --extern pin_init + --extern macros --extern kernel --extern pin_init \ + --extern proc_macro2 --extern quote --extern syn rusttest-macros: private rustdoc_test_target_flags = --crate-type proc-macro rusttest-macros: $(src)/macros/lib.rs \ rusttestlib-macros rusttestlib-kernel rusttestlib-pin_init FORCE
@@ -529,6 +532,8 @@ quiet_cmd_rustc_procmacro = $(RUSTC_OR_CLIPPY_QUIET) P $@ @$(objtree)/include/generated/rustc_cfg $< # Procedural macros can only be used with the `rustc` that compiled it. +$(obj)/$(libmacros_name): private rustc_target_flags = \ + --extern proc_macro2 --extern quote --extern syn $(obj)/$(libmacros_name): $(src)/macros/lib.rs $(obj)/libproc_macro2.rlib \ $(obj)/libquote.rlib $(obj)/libsyn.rlib FORCE +$(call if_changed_dep,rustc_procmacro)
scripts/generate_rust_analyzer.py +1 -1
@@ -110,7 +110,7 @@ def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs, core_edit append_crate( "macros", srctree / "rust" / "macros" / "lib.rs", - ["std", "proc_macro"], + ["std", "proc_macro", "proc_macro2", "quote", "syn"], is_proc_macro=True, )
Signature · 1 line
2.52.0
Miguel Ojeda
AppliedQuoted 8 lines · Miguel Ojeda
This patch series introduces support for
syn(and its dependencies):Syn is a parsing library for parsing a stream of Rust tokens into a syntax tree of Rust source code.
Currently this library is geared toward use in Rust procedural macros, but contains some APIs that may be useful more generally.
Applied to rust-next -- thanks everyone!
I mostly sent this to show how it will look like and because I will use the expanded cover letter as a merge commit to keep it around, since it has now even more context, and it is a nice approach for a long series like this.
Cheers,
Miguel