* [PATCH 00/18] `syn` support
@ 2025-11-10 9:50 Miguel Ojeda
2025-11-10 9:50 ` [PATCH 01/18] rust: condvar: avoid `pub` in example Miguel Ojeda
` (19 more replies)
0 siblings, 20 replies; 57+ messages in thread
From: Miguel Ojeda @ 2025-11-10 9:50 UTC (permalink / raw)
To: Miguel Ojeda, Alex Gaynor, Nathan Chancellor, Nicolas Schier
Cc: Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
rust-for-linux, linux-kbuild, linux-kernel, patches
This patch series introduces support for `syn` (and its dependencies).
Having such support allows to greatly simplify writing complex macros
such as `pin-init`.
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.
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.
This has been a long time coming -- the first iterations of this, from
2022 and 2023 (with `serde` too), 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.
I will be updating the webpage as well with the result of this:
https://rust-for-linux.com/third-party-crates
Please give it a test -- thanks!
Miguel Ojeda (18):
rust: condvar: avoid `pub` in example
rust: kbuild: introduce `core-flags` and `core-skip_flags`
rust: kbuild: simplify `--cfg` handling
rust: kbuild: add host library support
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
.gitignore | 1 +
Makefile | 5 +
rust/Makefile | 134 +-
rust/kernel/sync/condvar.rs | 2 +-
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 | 23 +-
83 files changed, 57895 insertions(+), 13 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
--
2.51.2
^ permalink raw reply [flat|nested] 57+ messages in thread
* [PATCH 01/18] rust: condvar: avoid `pub` in example
2025-11-10 9:50 [PATCH 00/18] `syn` support Miguel Ojeda
@ 2025-11-10 9:50 ` Miguel Ojeda
2025-11-10 10:24 ` Alice Ryhl
2025-11-10 9:50 ` [PATCH 02/18] rust: kbuild: introduce `core-flags` and `core-skip_flags` Miguel Ojeda
` (18 subsequent siblings)
19 siblings, 1 reply; 57+ messages in thread
From: Miguel Ojeda @ 2025-11-10 9:50 UTC (permalink / raw)
To: Miguel Ojeda, Alex Gaynor, Nathan Chancellor, Nicolas Schier
Cc: Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
rust-for-linux, linux-kbuild, linux-kernel, patches
The future move of pin-init to `syn` uncovers the following unreachable
public item in an example:
error: unreachable `pub` item
--> rust/doctests_kernel_generated.rs:14683:1
|
14683 | pub struct Example {
| ---^^^^^^^^^^^^^^^
| |
| help: consider restricting its visibility: `pub(crate)`
|
= help: or consider exporting it for use by other crates
= note: `-D unreachable-pub` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(unreachable_pub)]`
There is no real downside of keeping the example as-is until the
`syn`-based pin-init is introduced, so there is no need to treat it as
a fix nor to backport it. However, we still need to change it before
introducing the new pin-init.
Thus do so.
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
---
rust/kernel/sync/condvar.rs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/rust/kernel/sync/condvar.rs b/rust/kernel/sync/condvar.rs
index aa5b9a7a726d..1e66e9f548a3 100644
--- a/rust/kernel/sync/condvar.rs
+++ b/rust/kernel/sync/condvar.rs
@@ -46,7 +46,7 @@ macro_rules! new_condvar {
/// use kernel::sync::{new_condvar, new_mutex, CondVar, Mutex};
///
/// #[pin_data]
-/// pub struct Example {
+/// struct Example {
/// #[pin]
/// value: Mutex<u32>,
///
--
2.51.2
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH 02/18] rust: kbuild: introduce `core-flags` and `core-skip_flags`
2025-11-10 9:50 [PATCH 00/18] `syn` support Miguel Ojeda
2025-11-10 9:50 ` [PATCH 01/18] rust: condvar: avoid `pub` in example Miguel Ojeda
@ 2025-11-10 9:50 ` Miguel Ojeda
2025-11-10 10:19 ` Miguel Ojeda
` (2 more replies)
2025-11-10 9:50 ` [PATCH 03/18] rust: kbuild: simplify `--cfg` handling Miguel Ojeda
` (17 subsequent siblings)
19 siblings, 3 replies; 57+ messages in thread
From: Miguel Ojeda @ 2025-11-10 9:50 UTC (permalink / raw)
To: Miguel Ojeda, Alex Gaynor, Nathan Chancellor, Nicolas Schier
Cc: Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
rust-for-linux, linux-kbuild, linux-kernel, patches
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.
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
---
rust/Makefile | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/rust/Makefile b/rust/Makefile
index 3e545c1a0ff4..a001aae0da9d 100644
--- a/rust/Makefile
+++ b/rust/Makefile
@@ -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)
@@ -125,8 +134,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)
@@ -508,9 +517,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)
--
2.51.2
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH 03/18] rust: kbuild: simplify `--cfg` handling
2025-11-10 9:50 [PATCH 00/18] `syn` support Miguel Ojeda
2025-11-10 9:50 ` [PATCH 01/18] rust: condvar: avoid `pub` in example Miguel Ojeda
2025-11-10 9:50 ` [PATCH 02/18] rust: kbuild: introduce `core-flags` and `core-skip_flags` Miguel Ojeda
@ 2025-11-10 9:50 ` Miguel Ojeda
2025-11-10 10:33 ` Alice Ryhl
2025-11-10 9:50 ` [PATCH 04/18] rust: kbuild: add host library support Miguel Ojeda
` (16 subsequent siblings)
19 siblings, 1 reply; 57+ messages in thread
From: Miguel Ojeda @ 2025-11-10 9:50 UTC (permalink / raw)
To: Miguel Ojeda, Alex Gaynor, Nathan Chancellor, Nicolas Schier
Cc: Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
rust-for-linux, linux-kbuild, linux-kernel, patches
We need to handle `cfg`s 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`.
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
---
rust/Makefile | 6 ++++--
scripts/generate_rust_analyzer.py | 2 +-
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/rust/Makefile b/rust/Makefile
index a001aae0da9d..7efed88d032c 100644
--- a/rust/Makefile
+++ b/rust/Makefile
@@ -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).
diff --git a/scripts/generate_rust_analyzer.py b/scripts/generate_rust_analyzer.py
index fc27f0cca752..dedca470adc1 100755
--- a/scripts/generate_rust_analyzer.py
+++ b/scripts/generate_rust_analyzer.py
@@ -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
--
2.51.2
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH 04/18] rust: kbuild: add host library support
2025-11-10 9:50 [PATCH 00/18] `syn` support Miguel Ojeda
` (2 preceding siblings ...)
2025-11-10 9:50 ` [PATCH 03/18] rust: kbuild: simplify `--cfg` handling Miguel Ojeda
@ 2025-11-10 9:50 ` Miguel Ojeda
2025-11-10 10:43 ` Alice Ryhl
2025-11-10 9:50 ` [PATCH 05/18] rust: proc-macro2: import crate Miguel Ojeda
` (15 subsequent siblings)
19 siblings, 1 reply; 57+ messages in thread
From: Miguel Ojeda @ 2025-11-10 9:50 UTC (permalink / raw)
To: Miguel Ojeda, Alex Gaynor, Nathan Chancellor, Nicolas Schier
Cc: Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
rust-for-linux, linux-kbuild, linux-kernel, patches
Add the a host library rule that produces `.rlib` files to be used by the
`macros` crate.
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
---
.gitignore | 1 +
rust/Makefile | 10 ++++++++++
2 files changed, 11 insertions(+)
diff --git a/.gitignore b/.gitignore
index 86a1ba0d9035..3a7241c941f5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -41,6 +41,7 @@
*.o.*
*.patch
*.pyc
+*.rlib
*.rmeta
*.rpm
*.rsi
diff --git a/rust/Makefile b/rust/Makefile
index 7efed88d032c..9eea6563ef35 100644
--- a/rust/Makefile
+++ b/rust/Makefile
@@ -430,6 +430,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_hostlibrary = $(RUSTC_OR_CLIPPY_QUIET) H $@
+ cmd_rustc_hostlibrary = \
+ $(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) \
--
2.51.2
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH 05/18] rust: proc-macro2: import crate
2025-11-10 9:50 [PATCH 00/18] `syn` support Miguel Ojeda
` (3 preceding siblings ...)
2025-11-10 9:50 ` [PATCH 04/18] rust: kbuild: add host library support Miguel Ojeda
@ 2025-11-10 9:50 ` Miguel Ojeda
2025-11-10 9:50 ` [PATCH 06/18] rust: proc-macro2: add SPDX License Identifiers Miguel Ojeda
` (14 subsequent siblings)
19 siblings, 0 replies; 57+ messages in thread
From: Miguel Ojeda @ 2025-11-10 9:50 UTC (permalink / raw)
To: Miguel Ojeda, Alex Gaynor, Nathan Chancellor, Nicolas Schier
Cc: Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
rust-for-linux, linux-kbuild, linux-kernel, patches
This 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
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
---
rust/proc-macro2/detection.rs | 75 +
| 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
diff --git a/rust/proc-macro2/detection.rs b/rust/proc-macro2/detection.rs
new file mode 100644
index 000000000000..beba7b237395
--- /dev/null
+++ b/rust/proc-macro2/detection.rs
@@ -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(available as 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_hook as *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(works as 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");
+ }
+}
--git a/rust/proc-macro2/extra.rs b/rust/proc-macro2/extra.rs
new file mode 100644
index 000000000000..522a90e136be
--- /dev/null
+++ b/rust/proc-macro2/extra.rs
@@ -0,0 +1,151 @@
+//! Items which do not have a correspondence to any API in the proc_macro crate,
+//! but are necessary to include in proc-macro2.
+
+use crate::fallback;
+use crate::imp;
+use crate::marker::{ProcMacroAutoTraits, MARKER};
+use crate::Span;
+use core::fmt::{self, Debug};
+
+/// Invalidate any `proc_macro2::Span` that exist on the current thread.
+///
+/// The implementation of `Span` uses thread-local data structures and this
+/// function clears them. Calling any method on a `Span` on the current thread
+/// created prior to the invalidation will return incorrect values or crash.
+///
+/// This function is useful for programs that process more than 2<sup>32</sup>
+/// bytes of Rust source code on the same thread. Just like rustc, proc-macro2
+/// uses 32-bit source locations, and these wrap around when the total source
+/// code processed by the same thread exceeds 2<sup>32</sup> bytes (4
+/// gigabytes). After a wraparound, `Span` methods such as `source_text()` can
+/// return wrong data.
+///
+/// # Example
+///
+/// As of late 2023, there is 200 GB of Rust code published on crates.io.
+/// Looking at just the newest version of every crate, it is 16 GB of code. So a
+/// workload that involves parsing it all would overflow a 32-bit source
+/// location unless spans are being invalidated.
+///
+/// ```
+/// use flate2::read::GzDecoder;
+/// use std::ffi::OsStr;
+/// use std::io::{BufReader, Read};
+/// use std::str::FromStr;
+/// use tar::Archive;
+///
+/// rayon::scope(|s| {
+/// for krate in every_version_of_every_crate() {
+/// s.spawn(move |_| {
+/// proc_macro2::extra::invalidate_current_thread_spans();
+///
+/// let reader = BufReader::new(krate);
+/// let tar = GzDecoder::new(reader);
+/// let mut archive = Archive::new(tar);
+/// for entry in archive.entries().unwrap() {
+/// let mut entry = entry.unwrap();
+/// let path = entry.path().unwrap();
+/// if path.extension() != Some(OsStr::new("rs")) {
+/// continue;
+/// }
+/// let mut content = String::new();
+/// entry.read_to_string(&mut content).unwrap();
+/// match proc_macro2::TokenStream::from_str(&content) {
+/// Ok(tokens) => {/* ... */},
+/// Err(_) => continue,
+/// }
+/// }
+/// });
+/// }
+/// });
+/// #
+/// # fn every_version_of_every_crate() -> Vec<std::fs::File> {
+/// # Vec::new()
+/// # }
+/// ```
+///
+/// # Panics
+///
+/// This function is not applicable to and will panic if called from a
+/// procedural macro.
+#[cfg(span_locations)]
+#[cfg_attr(docsrs, doc(cfg(feature = "span-locations")))]
+pub fn invalidate_current_thread_spans() {
+ crate::imp::invalidate_current_thread_spans();
+}
+
+/// An object that holds a [`Group`]'s `span_open()` and `span_close()` together
+/// in a more compact representation than holding those 2 spans individually.
+///
+/// [`Group`]: crate::Group
+#[derive(Copy, Clone)]
+pub struct DelimSpan {
+ inner: DelimSpanEnum,
+ _marker: ProcMacroAutoTraits,
+}
+
+#[derive(Copy, Clone)]
+enum DelimSpanEnum {
+ #[cfg(wrap_proc_macro)]
+ Compiler {
+ join: proc_macro::Span,
+ open: proc_macro::Span,
+ close: proc_macro::Span,
+ },
+ Fallback(fallback::Span),
+}
+
+impl DelimSpan {
+ pub(crate) fn new(group: &imp::Group) -> Self {
+ #[cfg(wrap_proc_macro)]
+ let inner = match group {
+ imp::Group::Compiler(group) => DelimSpanEnum::Compiler {
+ join: group.span(),
+ open: group.span_open(),
+ close: group.span_close(),
+ },
+ imp::Group::Fallback(group) => DelimSpanEnum::Fallback(group.span()),
+ };
+
+ #[cfg(not(wrap_proc_macro))]
+ let inner = DelimSpanEnum::Fallback(group.span());
+
+ DelimSpan {
+ inner,
+ _marker: MARKER,
+ }
+ }
+
+ /// Returns a span covering the entire delimited group.
+ pub fn join(&self) -> Span {
+ match &self.inner {
+ #[cfg(wrap_proc_macro)]
+ DelimSpanEnum::Compiler { join, .. } => Span::_new(imp::Span::Compiler(*join)),
+ DelimSpanEnum::Fallback(span) => Span::_new_fallback(*span),
+ }
+ }
+
+ /// Returns a span for the opening punctuation of the group only.
+ pub fn open(&self) -> Span {
+ match &self.inner {
+ #[cfg(wrap_proc_macro)]
+ DelimSpanEnum::Compiler { open, .. } => Span::_new(imp::Span::Compiler(*open)),
+ DelimSpanEnum::Fallback(span) => Span::_new_fallback(span.first_byte()),
+ }
+ }
+
+ /// Returns a span for the closing punctuation of the group only.
+ pub fn close(&self) -> Span {
+ match &self.inner {
+ #[cfg(wrap_proc_macro)]
+ DelimSpanEnum::Compiler { close, .. } => Span::_new(imp::Span::Compiler(*close)),
+ DelimSpanEnum::Fallback(span) => Span::_new_fallback(span.last_byte()),
+ }
+ }
+}
+
+impl Debug for DelimSpan {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ Debug::fmt(&self.join(), f)
+ }
+}
diff --git a/rust/proc-macro2/fallback.rs b/rust/proc-macro2/fallback.rs
new file mode 100644
index 000000000000..1560105cfd25
--- /dev/null
+++ b/rust/proc-macro2/fallback.rs
@@ -0,0 +1,1256 @@
+#[cfg(wrap_proc_macro)]
+use crate::imp;
+#[cfg(span_locations)]
+use crate::location::LineColumn;
+use crate::parse::{self, Cursor};
+use crate::rcvec::{RcVec, RcVecBuilder, RcVecIntoIter, RcVecMut};
+use crate::{Delimiter, Spacing, TokenTree};
+#[cfg(all(span_locations, not(fuzzing)))]
+use alloc::collections::BTreeMap;
+#[cfg(all(span_locations, not(fuzzing)))]
+use core::cell::RefCell;
+#[cfg(span_locations)]
+use core::cmp;
+#[cfg(all(span_locations, not(fuzzing)))]
+use core::cmp::Ordering;
+use core::fmt::{self, Debug, Display, Write};
+use core::mem::ManuallyDrop;
+#[cfg(span_locations)]
+use core::ops::Range;
+use core::ops::RangeBounds;
+use core::ptr;
+use core::str;
+#[cfg(feature = "proc-macro")]
+use core::str::FromStr;
+use std::ffi::CStr;
+#[cfg(wrap_proc_macro)]
+use std::panic;
+#[cfg(span_locations)]
+use std::path::PathBuf;
+
+/// Force use of proc-macro2's fallback implementation of the API for now, even
+/// if the compiler's implementation is available.
+pub fn force() {
+ #[cfg(wrap_proc_macro)]
+ crate::detection::force_fallback();
+}
+
+/// Resume using the compiler's implementation of the proc macro API if it is
+/// available.
+pub fn unforce() {
+ #[cfg(wrap_proc_macro)]
+ crate::detection::unforce_fallback();
+}
+
+#[derive(Clone)]
+pub(crate) struct TokenStream {
+ inner: RcVec<TokenTree>,
+}
+
+#[derive(Debug)]
+pub(crate) struct LexError {
+ pub(crate) span: Span,
+}
+
+impl LexError {
+ pub(crate) fn span(&self) -> Span {
+ self.span
+ }
+
+ pub(crate) fn call_site() -> Self {
+ LexError {
+ span: Span::call_site(),
+ }
+ }
+}
+
+impl TokenStream {
+ pub(crate) fn new() -> Self {
+ TokenStream {
+ inner: RcVecBuilder::new().build(),
+ }
+ }
+
+ pub(crate) fn from_str_checked(src: &str) -> Result<Self, LexError> {
+ // Create a dummy file & add it to the source map
+ let mut cursor = get_cursor(src);
+
+ // Strip a byte order mark if present
+ const BYTE_ORDER_MARK: &str = "\u{feff}";
+ if cursor.starts_with(BYTE_ORDER_MARK) {
+ cursor = cursor.advance(BYTE_ORDER_MARK.len());
+ }
+
+ parse::token_stream(cursor)
+ }
+
+ #[cfg(feature = "proc-macro")]
+ pub(crate) fn from_str_unchecked(src: &str) -> Self {
+ Self::from_str_checked(src).unwrap()
+ }
+
+ pub(crate) fn is_empty(&self) -> bool {
+ self.inner.len() == 0
+ }
+
+ fn take_inner(self) -> RcVecBuilder<TokenTree> {
+ let nodrop = ManuallyDrop::new(self);
+ unsafe { ptr::read(&nodrop.inner) }.make_owned()
+ }
+}
+
+fn push_token_from_proc_macro(mut vec: RcVecMut<TokenTree>, token: TokenTree) {
+ // https://github.com/dtolnay/proc-macro2/issues/235
+ match token {
+ TokenTree::Literal(crate::Literal {
+ #[cfg(wrap_proc_macro)]
+ inner: crate::imp::Literal::Fallback(literal),
+ #[cfg(not(wrap_proc_macro))]
+ inner: literal,
+ ..
+ }) if literal.repr.starts_with('-') => {
+ push_negative_literal(vec, literal);
+ }
+ _ => vec.push(token),
+ }
+
+ #[cold]
+ fn push_negative_literal(mut vec: RcVecMut<TokenTree>, mut literal: Literal) {
+ literal.repr.remove(0);
+ let mut punct = crate::Punct::new('-', Spacing::Alone);
+ punct.set_span(crate::Span::_new_fallback(literal.span));
+ vec.push(TokenTree::Punct(punct));
+ vec.push(TokenTree::Literal(crate::Literal::_new_fallback(literal)));
+ }
+}
+
+// Nonrecursive to prevent stack overflow.
+impl Drop for TokenStream {
+ fn drop(&mut self) {
+ let mut stack = Vec::new();
+ let mut current = match self.inner.get_mut() {
+ Some(inner) => inner.take().into_iter(),
+ None => return,
+ };
+ loop {
+ while let Some(token) = current.next() {
+ let group = match token {
+ TokenTree::Group(group) => group.inner,
+ _ => continue,
+ };
+ #[cfg(wrap_proc_macro)]
+ let group = match group {
+ crate::imp::Group::Fallback(group) => group,
+ crate::imp::Group::Compiler(_) => continue,
+ };
+ let mut group = group;
+ if let Some(inner) = group.stream.inner.get_mut() {
+ stack.push(current);
+ current = inner.take().into_iter();
+ }
+ }
+ match stack.pop() {
+ Some(next) => current = next,
+ None => return,
+ }
+ }
+ }
+}
+
+pub(crate) struct TokenStreamBuilder {
+ inner: RcVecBuilder<TokenTree>,
+}
+
+impl TokenStreamBuilder {
+ pub(crate) fn new() -> Self {
+ TokenStreamBuilder {
+ inner: RcVecBuilder::new(),
+ }
+ }
+
+ pub(crate) fn with_capacity(cap: usize) -> Self {
+ TokenStreamBuilder {
+ inner: RcVecBuilder::with_capacity(cap),
+ }
+ }
+
+ pub(crate) fn push_token_from_parser(&mut self, tt: TokenTree) {
+ self.inner.push(tt);
+ }
+
+ pub(crate) fn build(self) -> TokenStream {
+ TokenStream {
+ inner: self.inner.build(),
+ }
+ }
+}
+
+#[cfg(span_locations)]
+fn get_cursor(src: &str) -> Cursor {
+ #[cfg(fuzzing)]
+ return Cursor { rest: src, off: 1 };
+
+ // Create a dummy file & add it to the source map
+ #[cfg(not(fuzzing))]
+ SOURCE_MAP.with(|sm| {
+ let mut sm = sm.borrow_mut();
+ let span = sm.add_file(src);
+ Cursor {
+ rest: src,
+ off: span.lo,
+ }
+ })
+}
+
+#[cfg(not(span_locations))]
+fn get_cursor(src: &str) -> Cursor {
+ Cursor { rest: src }
+}
+
+impl Display for LexError {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.write_str("cannot parse string into token stream")
+ }
+}
+
+impl Display for TokenStream {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let mut joint = false;
+ for (i, tt) in self.inner.iter().enumerate() {
+ if i != 0 && !joint {
+ write!(f, " ")?;
+ }
+ joint = false;
+ match tt {
+ TokenTree::Group(tt) => Display::fmt(tt, f),
+ TokenTree::Ident(tt) => Display::fmt(tt, f),
+ TokenTree::Punct(tt) => {
+ joint = tt.spacing() == Spacing::Joint;
+ Display::fmt(tt, f)
+ }
+ TokenTree::Literal(tt) => Display::fmt(tt, f),
+ }?;
+ }
+
+ Ok(())
+ }
+}
+
+impl Debug for TokenStream {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.write_str("TokenStream ")?;
+ f.debug_list().entries(self.clone()).finish()
+ }
+}
+
+#[cfg(feature = "proc-macro")]
+impl From<proc_macro::TokenStream> for TokenStream {
+ fn from(inner: proc_macro::TokenStream) -> Self {
+ TokenStream::from_str_unchecked(&inner.to_string())
+ }
+}
+
+#[cfg(feature = "proc-macro")]
+impl From<TokenStream> for proc_macro::TokenStream {
+ fn from(inner: TokenStream) -> Self {
+ proc_macro::TokenStream::from_str_unchecked(&inner.to_string())
+ }
+}
+
+impl From<TokenTree> for TokenStream {
+ fn from(tree: TokenTree) -> Self {
+ let mut stream = RcVecBuilder::new();
+ push_token_from_proc_macro(stream.as_mut(), tree);
+ TokenStream {
+ inner: stream.build(),
+ }
+ }
+}
+
+impl FromIterator<TokenTree> for TokenStream {
+ fn from_iter<I: IntoIterator<Item = TokenTree>>(tokens: I) -> Self {
+ let mut stream = TokenStream::new();
+ stream.extend(tokens);
+ stream
+ }
+}
+
+impl FromIterator<TokenStream> for TokenStream {
+ fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self {
+ let mut v = RcVecBuilder::new();
+
+ for stream in streams {
+ v.extend(stream.take_inner());
+ }
+
+ TokenStream { inner: v.build() }
+ }
+}
+
+impl Extend<TokenTree> for TokenStream {
+ fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, tokens: I) {
+ let mut vec = self.inner.make_mut();
+ tokens
+ .into_iter()
+ .for_each(|token| push_token_from_proc_macro(vec.as_mut(), token));
+ }
+}
+
+impl Extend<TokenStream> for TokenStream {
+ fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) {
+ self.inner.make_mut().extend(streams.into_iter().flatten());
+ }
+}
+
+pub(crate) type TokenTreeIter = RcVecIntoIter<TokenTree>;
+
+impl IntoIterator for TokenStream {
+ type Item = TokenTree;
+ type IntoIter = TokenTreeIter;
+
+ fn into_iter(self) -> TokenTreeIter {
+ self.take_inner().into_iter()
+ }
+}
+
+#[cfg(all(span_locations, not(fuzzing)))]
+thread_local! {
+ static SOURCE_MAP: RefCell<SourceMap> = RefCell::new(SourceMap {
+ // Start with a single dummy file which all call_site() and def_site()
+ // spans reference.
+ files: vec![FileInfo {
+ source_text: String::new(),
+ span: Span { lo: 0, hi: 0 },
+ lines: vec![0],
+ char_index_to_byte_offset: BTreeMap::new(),
+ }],
+ });
+}
+
+#[cfg(span_locations)]
+pub(crate) fn invalidate_current_thread_spans() {
+ #[cfg(not(fuzzing))]
+ SOURCE_MAP.with(|sm| sm.borrow_mut().files.truncate(1));
+}
+
+#[cfg(all(span_locations, not(fuzzing)))]
+struct FileInfo {
+ source_text: String,
+ span: Span,
+ lines: Vec<usize>,
+ char_index_to_byte_offset: BTreeMap<usize, usize>,
+}
+
+#[cfg(all(span_locations, not(fuzzing)))]
+impl FileInfo {
+ fn offset_line_column(&self, offset: usize) -> LineColumn {
+ assert!(self.span_within(Span {
+ lo: offset as u32,
+ hi: offset as u32,
+ }));
+ let offset = offset - self.span.lo as usize;
+ match self.lines.binary_search(&offset) {
+ Ok(found) => LineColumn {
+ line: found + 1,
+ column: 0,
+ },
+ Err(idx) => LineColumn {
+ line: idx,
+ column: offset - self.lines[idx - 1],
+ },
+ }
+ }
+
+ fn span_within(&self, span: Span) -> bool {
+ span.lo >= self.span.lo && span.hi <= self.span.hi
+ }
+
+ fn byte_range(&mut self, span: Span) -> Range<usize> {
+ let lo_char = (span.lo - self.span.lo) as usize;
+
+ // Look up offset of the largest already-computed char index that is
+ // less than or equal to the current requested one. We resume counting
+ // chars from that point.
+ let (&last_char_index, &last_byte_offset) = self
+ .char_index_to_byte_offset
+ .range(..=lo_char)
+ .next_back()
+ .unwrap_or((&0, &0));
+
+ let lo_byte = if last_char_index == lo_char {
+ last_byte_offset
+ } else {
+ let total_byte_offset = match self.source_text[last_byte_offset..]
+ .char_indices()
+ .nth(lo_char - last_char_index)
+ {
+ Some((additional_offset, _ch)) => last_byte_offset + additional_offset,
+ None => self.source_text.len(),
+ };
+ self.char_index_to_byte_offset
+ .insert(lo_char, total_byte_offset);
+ total_byte_offset
+ };
+
+ let trunc_lo = &self.source_text[lo_byte..];
+ let char_len = (span.hi - span.lo) as usize;
+ lo_byte..match trunc_lo.char_indices().nth(char_len) {
+ Some((offset, _ch)) => lo_byte + offset,
+ None => self.source_text.len(),
+ }
+ }
+
+ fn source_text(&mut self, span: Span) -> String {
+ let byte_range = self.byte_range(span);
+ self.source_text[byte_range].to_owned()
+ }
+}
+
+/// Computes the offsets of each line in the given source string
+/// and the total number of characters
+#[cfg(all(span_locations, not(fuzzing)))]
+fn lines_offsets(s: &str) -> (usize, Vec<usize>) {
+ let mut lines = vec![0];
+ let mut total = 0;
+
+ for ch in s.chars() {
+ total += 1;
+ if ch == '\n' {
+ lines.push(total);
+ }
+ }
+
+ (total, lines)
+}
+
+#[cfg(all(span_locations, not(fuzzing)))]
+struct SourceMap {
+ files: Vec<FileInfo>,
+}
+
+#[cfg(all(span_locations, not(fuzzing)))]
+impl SourceMap {
+ fn next_start_pos(&self) -> u32 {
+ // Add 1 so there's always space between files.
+ //
+ // We'll always have at least 1 file, as we initialize our files list
+ // with a dummy file.
+ self.files.last().unwrap().span.hi + 1
+ }
+
+ fn add_file(&mut self, src: &str) -> Span {
+ let (len, lines) = lines_offsets(src);
+ let lo = self.next_start_pos();
+ let span = Span {
+ lo,
+ hi: lo + (len as u32),
+ };
+
+ self.files.push(FileInfo {
+ source_text: src.to_owned(),
+ span,
+ lines,
+ // Populated lazily by source_text().
+ char_index_to_byte_offset: BTreeMap::new(),
+ });
+
+ span
+ }
+
+ fn find(&self, span: Span) -> usize {
+ match self.files.binary_search_by(|file| {
+ if file.span.hi < span.lo {
+ Ordering::Less
+ } else if file.span.lo > span.hi {
+ Ordering::Greater
+ } else {
+ assert!(file.span_within(span));
+ Ordering::Equal
+ }
+ }) {
+ Ok(i) => i,
+ Err(_) => unreachable!("Invalid span with no related FileInfo!"),
+ }
+ }
+
+ fn filepath(&self, span: Span) -> String {
+ let i = self.find(span);
+ if i == 0 {
+ "<unspecified>".to_owned()
+ } else {
+ format!("<parsed string {}>", i)
+ }
+ }
+
+ fn fileinfo(&self, span: Span) -> &FileInfo {
+ let i = self.find(span);
+ &self.files[i]
+ }
+
+ fn fileinfo_mut(&mut self, span: Span) -> &mut FileInfo {
+ let i = self.find(span);
+ &mut self.files[i]
+ }
+}
+
+#[derive(Clone, Copy, PartialEq, Eq)]
+pub(crate) struct Span {
+ #[cfg(span_locations)]
+ pub(crate) lo: u32,
+ #[cfg(span_locations)]
+ pub(crate) hi: u32,
+}
+
+impl Span {
+ #[cfg(not(span_locations))]
+ pub(crate) fn call_site() -> Self {
+ Span {}
+ }
+
+ #[cfg(span_locations)]
+ pub(crate) fn call_site() -> Self {
+ Span { lo: 0, hi: 0 }
+ }
+
+ pub(crate) fn mixed_site() -> Self {
+ Span::call_site()
+ }
+
+ #[cfg(procmacro2_semver_exempt)]
+ pub(crate) fn def_site() -> Self {
+ Span::call_site()
+ }
+
+ pub(crate) fn resolved_at(&self, _other: Span) -> Span {
+ // Stable spans consist only of line/column information, so
+ // `resolved_at` and `located_at` only select which span the
+ // caller wants line/column information from.
+ *self
+ }
+
+ pub(crate) fn located_at(&self, other: Span) -> Span {
+ other
+ }
+
+ #[cfg(span_locations)]
+ pub(crate) fn byte_range(&self) -> Range<usize> {
+ #[cfg(fuzzing)]
+ return 0..0;
+
+ #[cfg(not(fuzzing))]
+ {
+ if self.is_call_site() {
+ 0..0
+ } else {
+ SOURCE_MAP.with(|sm| sm.borrow_mut().fileinfo_mut(*self).byte_range(*self))
+ }
+ }
+ }
+
+ #[cfg(span_locations)]
+ pub(crate) fn start(&self) -> LineColumn {
+ #[cfg(fuzzing)]
+ return LineColumn { line: 0, column: 0 };
+
+ #[cfg(not(fuzzing))]
+ SOURCE_MAP.with(|sm| {
+ let sm = sm.borrow();
+ let fi = sm.fileinfo(*self);
+ fi.offset_line_column(self.lo as usize)
+ })
+ }
+
+ #[cfg(span_locations)]
+ pub(crate) fn end(&self) -> LineColumn {
+ #[cfg(fuzzing)]
+ return LineColumn { line: 0, column: 0 };
+
+ #[cfg(not(fuzzing))]
+ SOURCE_MAP.with(|sm| {
+ let sm = sm.borrow();
+ let fi = sm.fileinfo(*self);
+ fi.offset_line_column(self.hi as usize)
+ })
+ }
+
+ #[cfg(span_locations)]
+ pub(crate) fn file(&self) -> String {
+ #[cfg(fuzzing)]
+ return "<unspecified>".to_owned();
+
+ #[cfg(not(fuzzing))]
+ SOURCE_MAP.with(|sm| {
+ let sm = sm.borrow();
+ sm.filepath(*self)
+ })
+ }
+
+ #[cfg(span_locations)]
+ pub(crate) fn local_file(&self) -> Option<PathBuf> {
+ None
+ }
+
+ #[cfg(not(span_locations))]
+ pub(crate) fn join(&self, _other: Span) -> Option<Span> {
+ Some(Span {})
+ }
+
+ #[cfg(span_locations)]
+ pub(crate) fn join(&self, other: Span) -> Option<Span> {
+ #[cfg(fuzzing)]
+ return {
+ let _ = other;
+ None
+ };
+
+ #[cfg(not(fuzzing))]
+ SOURCE_MAP.with(|sm| {
+ let sm = sm.borrow();
+ // If `other` is not within the same FileInfo as us, return None.
+ if !sm.fileinfo(*self).span_within(other) {
+ return None;
+ }
+ Some(Span {
+ lo: cmp::min(self.lo, other.lo),
+ hi: cmp::max(self.hi, other.hi),
+ })
+ })
+ }
+
+ #[cfg(not(span_locations))]
+ pub(crate) fn source_text(&self) -> Option<String> {
+ None
+ }
+
+ #[cfg(span_locations)]
+ pub(crate) fn source_text(&self) -> Option<String> {
+ #[cfg(fuzzing)]
+ return None;
+
+ #[cfg(not(fuzzing))]
+ {
+ if self.is_call_site() {
+ None
+ } else {
+ Some(SOURCE_MAP.with(|sm| sm.borrow_mut().fileinfo_mut(*self).source_text(*self)))
+ }
+ }
+ }
+
+ #[cfg(not(span_locations))]
+ pub(crate) fn first_byte(self) -> Self {
+ self
+ }
+
+ #[cfg(span_locations)]
+ pub(crate) fn first_byte(self) -> Self {
+ Span {
+ lo: self.lo,
+ hi: cmp::min(self.lo.saturating_add(1), self.hi),
+ }
+ }
+
+ #[cfg(not(span_locations))]
+ pub(crate) fn last_byte(self) -> Self {
+ self
+ }
+
+ #[cfg(span_locations)]
+ pub(crate) fn last_byte(self) -> Self {
+ Span {
+ lo: cmp::max(self.hi.saturating_sub(1), self.lo),
+ hi: self.hi,
+ }
+ }
+
+ #[cfg(span_locations)]
+ fn is_call_site(&self) -> bool {
+ self.lo == 0 && self.hi == 0
+ }
+}
+
+impl Debug for Span {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ #[cfg(span_locations)]
+ return write!(f, "bytes({}..{})", self.lo, self.hi);
+
+ #[cfg(not(span_locations))]
+ write!(f, "Span")
+ }
+}
+
+pub(crate) fn debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span) {
+ #[cfg(span_locations)]
+ {
+ if span.is_call_site() {
+ return;
+ }
+ }
+
+ if cfg!(span_locations) {
+ debug.field("span", &span);
+ }
+}
+
+#[derive(Clone)]
+pub(crate) struct Group {
+ delimiter: Delimiter,
+ stream: TokenStream,
+ span: Span,
+}
+
+impl Group {
+ pub(crate) fn new(delimiter: Delimiter, stream: TokenStream) -> Self {
+ Group {
+ delimiter,
+ stream,
+ span: Span::call_site(),
+ }
+ }
+
+ pub(crate) fn delimiter(&self) -> Delimiter {
+ self.delimiter
+ }
+
+ pub(crate) fn stream(&self) -> TokenStream {
+ self.stream.clone()
+ }
+
+ pub(crate) fn span(&self) -> Span {
+ self.span
+ }
+
+ pub(crate) fn span_open(&self) -> Span {
+ self.span.first_byte()
+ }
+
+ pub(crate) fn span_close(&self) -> Span {
+ self.span.last_byte()
+ }
+
+ pub(crate) fn set_span(&mut self, span: Span) {
+ self.span = span;
+ }
+}
+
+impl Display for Group {
+ // We attempt to match libproc_macro's formatting.
+ // Empty parens: ()
+ // Nonempty parens: (...)
+ // Empty brackets: []
+ // Nonempty brackets: [...]
+ // Empty braces: { }
+ // Nonempty braces: { ... }
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let (open, close) = match self.delimiter {
+ Delimiter::Parenthesis => ("(", ")"),
+ Delimiter::Brace => ("{ ", "}"),
+ Delimiter::Bracket => ("[", "]"),
+ Delimiter::None => ("", ""),
+ };
+
+ f.write_str(open)?;
+ Display::fmt(&self.stream, f)?;
+ if self.delimiter == Delimiter::Brace && !self.stream.inner.is_empty() {
+ f.write_str(" ")?;
+ }
+ f.write_str(close)?;
+
+ Ok(())
+ }
+}
+
+impl Debug for Group {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ let mut debug = fmt.debug_struct("Group");
+ debug.field("delimiter", &self.delimiter);
+ debug.field("stream", &self.stream);
+ debug_span_field_if_nontrivial(&mut debug, self.span);
+ debug.finish()
+ }
+}
+
+#[derive(Clone)]
+pub(crate) struct Ident {
+ sym: Box<str>,
+ span: Span,
+ raw: bool,
+}
+
+impl Ident {
+ #[track_caller]
+ pub(crate) fn new_checked(string: &str, span: Span) -> Self {
+ validate_ident(string);
+ Ident::new_unchecked(string, span)
+ }
+
+ pub(crate) fn new_unchecked(string: &str, span: Span) -> Self {
+ Ident {
+ sym: Box::from(string),
+ span,
+ raw: false,
+ }
+ }
+
+ #[track_caller]
+ pub(crate) fn new_raw_checked(string: &str, span: Span) -> Self {
+ validate_ident_raw(string);
+ Ident::new_raw_unchecked(string, span)
+ }
+
+ pub(crate) fn new_raw_unchecked(string: &str, span: Span) -> Self {
+ Ident {
+ sym: Box::from(string),
+ span,
+ raw: true,
+ }
+ }
+
+ pub(crate) fn span(&self) -> Span {
+ self.span
+ }
+
+ pub(crate) fn set_span(&mut self, span: Span) {
+ self.span = span;
+ }
+}
+
+pub(crate) fn is_ident_start(c: char) -> bool {
+ c == '_' || unicode_ident::is_xid_start(c)
+}
+
+pub(crate) fn is_ident_continue(c: char) -> bool {
+ unicode_ident::is_xid_continue(c)
+}
+
+#[track_caller]
+fn validate_ident(string: &str) {
+ if string.is_empty() {
+ panic!("Ident is not allowed to be empty; use Option<Ident>");
+ }
+
+ if string.bytes().all(|digit| b'0' <= digit && digit <= b'9') {
+ panic!("Ident cannot be a number; use Literal instead");
+ }
+
+ fn ident_ok(string: &str) -> bool {
+ let mut chars = string.chars();
+ let first = chars.next().unwrap();
+ if !is_ident_start(first) {
+ return false;
+ }
+ for ch in chars {
+ if !is_ident_continue(ch) {
+ return false;
+ }
+ }
+ true
+ }
+
+ if !ident_ok(string) {
+ panic!("{:?} is not a valid Ident", string);
+ }
+}
+
+#[track_caller]
+fn validate_ident_raw(string: &str) {
+ validate_ident(string);
+
+ match string {
+ "_" | "super" | "self" | "Self" | "crate" => {
+ panic!("`r#{}` cannot be a raw identifier", string);
+ }
+ _ => {}
+ }
+}
+
+impl PartialEq for Ident {
+ fn eq(&self, other: &Ident) -> bool {
+ self.sym == other.sym && self.raw == other.raw
+ }
+}
+
+impl<T> PartialEq<T> for Ident
+where
+ T: ?Sized + AsRef<str>,
+{
+ fn eq(&self, other: &T) -> bool {
+ let other = other.as_ref();
+ if self.raw {
+ other.starts_with("r#") && *self.sym == other[2..]
+ } else {
+ *self.sym == *other
+ }
+ }
+}
+
+impl Display for Ident {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ if self.raw {
+ f.write_str("r#")?;
+ }
+ Display::fmt(&self.sym, f)
+ }
+}
+
+#[allow(clippy::missing_fields_in_debug)]
+impl Debug for Ident {
+ // Ident(proc_macro), Ident(r#union)
+ #[cfg(not(span_locations))]
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let mut debug = f.debug_tuple("Ident");
+ debug.field(&format_args!("{}", self));
+ debug.finish()
+ }
+
+ // Ident {
+ // sym: proc_macro,
+ // span: bytes(128..138)
+ // }
+ #[cfg(span_locations)]
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let mut debug = f.debug_struct("Ident");
+ debug.field("sym", &format_args!("{}", self));
+ debug_span_field_if_nontrivial(&mut debug, self.span);
+ debug.finish()
+ }
+}
+
+#[derive(Clone)]
+pub(crate) struct Literal {
+ pub(crate) repr: String,
+ span: Span,
+}
+
+macro_rules! suffixed_numbers {
+ ($($name:ident => $kind:ident,)*) => ($(
+ pub(crate) fn $name(n: $kind) -> Literal {
+ Literal::_new(format!(concat!("{}", stringify!($kind)), n))
+ }
+ )*)
+}
+
+macro_rules! unsuffixed_numbers {
+ ($($name:ident => $kind:ident,)*) => ($(
+ pub(crate) fn $name(n: $kind) -> Literal {
+ Literal::_new(n.to_string())
+ }
+ )*)
+}
+
+impl Literal {
+ pub(crate) fn _new(repr: String) -> Self {
+ Literal {
+ repr,
+ span: Span::call_site(),
+ }
+ }
+
+ pub(crate) fn from_str_checked(repr: &str) -> Result<Self, LexError> {
+ let mut cursor = get_cursor(repr);
+ #[cfg(span_locations)]
+ let lo = cursor.off;
+
+ let negative = cursor.starts_with_char('-');
+ if negative {
+ cursor = cursor.advance(1);
+ if !cursor.starts_with_fn(|ch| ch.is_ascii_digit()) {
+ return Err(LexError::call_site());
+ }
+ }
+
+ if let Ok((rest, mut literal)) = parse::literal(cursor) {
+ if rest.is_empty() {
+ if negative {
+ literal.repr.insert(0, '-');
+ }
+ literal.span = Span {
+ #[cfg(span_locations)]
+ lo,
+ #[cfg(span_locations)]
+ hi: rest.off,
+ };
+ return Ok(literal);
+ }
+ }
+ Err(LexError::call_site())
+ }
+
+ pub(crate) unsafe fn from_str_unchecked(repr: &str) -> Self {
+ Literal::_new(repr.to_owned())
+ }
+
+ suffixed_numbers! {
+ u8_suffixed => u8,
+ u16_suffixed => u16,
+ u32_suffixed => u32,
+ u64_suffixed => u64,
+ u128_suffixed => u128,
+ usize_suffixed => usize,
+ i8_suffixed => i8,
+ i16_suffixed => i16,
+ i32_suffixed => i32,
+ i64_suffixed => i64,
+ i128_suffixed => i128,
+ isize_suffixed => isize,
+
+ f32_suffixed => f32,
+ f64_suffixed => f64,
+ }
+
+ unsuffixed_numbers! {
+ u8_unsuffixed => u8,
+ u16_unsuffixed => u16,
+ u32_unsuffixed => u32,
+ u64_unsuffixed => u64,
+ u128_unsuffixed => u128,
+ usize_unsuffixed => usize,
+ i8_unsuffixed => i8,
+ i16_unsuffixed => i16,
+ i32_unsuffixed => i32,
+ i64_unsuffixed => i64,
+ i128_unsuffixed => i128,
+ isize_unsuffixed => isize,
+ }
+
+ pub(crate) fn f32_unsuffixed(f: f32) -> Literal {
+ let mut s = f.to_string();
+ if !s.contains('.') {
+ s.push_str(".0");
+ }
+ Literal::_new(s)
+ }
+
+ pub(crate) fn f64_unsuffixed(f: f64) -> Literal {
+ let mut s = f.to_string();
+ if !s.contains('.') {
+ s.push_str(".0");
+ }
+ Literal::_new(s)
+ }
+
+ pub(crate) fn string(string: &str) -> Literal {
+ let mut repr = String::with_capacity(string.len() + 2);
+ repr.push('"');
+ escape_utf8(string, &mut repr);
+ repr.push('"');
+ Literal::_new(repr)
+ }
+
+ pub(crate) fn character(ch: char) -> Literal {
+ let mut repr = String::new();
+ repr.push('\'');
+ if ch == '"' {
+ // escape_debug turns this into '\"' which is unnecessary.
+ repr.push(ch);
+ } else {
+ repr.extend(ch.escape_debug());
+ }
+ repr.push('\'');
+ Literal::_new(repr)
+ }
+
+ pub(crate) fn byte_character(byte: u8) -> Literal {
+ let mut repr = "b'".to_string();
+ #[allow(clippy::match_overlapping_arm)]
+ match byte {
+ b'\0' => repr.push_str(r"\0"),
+ b'\t' => repr.push_str(r"\t"),
+ b'\n' => repr.push_str(r"\n"),
+ b'\r' => repr.push_str(r"\r"),
+ b'\'' => repr.push_str(r"\'"),
+ b'\\' => repr.push_str(r"\\"),
+ b'\x20'..=b'\x7E' => repr.push(byte as char),
+ _ => {
+ let _ = write!(repr, r"\x{:02X}", byte);
+ }
+ }
+ repr.push('\'');
+ Literal::_new(repr)
+ }
+
+ pub(crate) fn byte_string(bytes: &[u8]) -> Literal {
+ let mut repr = "b\"".to_string();
+ let mut bytes = bytes.iter();
+ while let Some(&b) = bytes.next() {
+ #[allow(clippy::match_overlapping_arm)]
+ match b {
+ b'\0' => repr.push_str(match bytes.as_slice().first() {
+ // circumvent clippy::octal_escapes lint
+ Some(b'0'..=b'7') => r"\x00",
+ _ => r"\0",
+ }),
+ b'\t' => repr.push_str(r"\t"),
+ b'\n' => repr.push_str(r"\n"),
+ b'\r' => repr.push_str(r"\r"),
+ b'"' => repr.push_str("\\\""),
+ b'\\' => repr.push_str(r"\\"),
+ b'\x20'..=b'\x7E' => repr.push(b as char),
+ _ => {
+ let _ = write!(repr, r"\x{:02X}", b);
+ }
+ }
+ }
+ repr.push('"');
+ Literal::_new(repr)
+ }
+
+ pub(crate) fn c_string(string: &CStr) -> Literal {
+ let mut repr = "c\"".to_string();
+ let mut bytes = string.to_bytes();
+ while !bytes.is_empty() {
+ let (valid, invalid) = match str::from_utf8(bytes) {
+ Ok(all_valid) => {
+ bytes = b"";
+ (all_valid, bytes)
+ }
+ Err(utf8_error) => {
+ let (valid, rest) = bytes.split_at(utf8_error.valid_up_to());
+ let valid = str::from_utf8(valid).unwrap();
+ let invalid = utf8_error
+ .error_len()
+ .map_or(rest, |error_len| &rest[..error_len]);
+ bytes = &bytes[valid.len() + invalid.len()..];
+ (valid, invalid)
+ }
+ };
+ escape_utf8(valid, &mut repr);
+ for &byte in invalid {
+ let _ = write!(repr, r"\x{:02X}", byte);
+ }
+ }
+ repr.push('"');
+ Literal::_new(repr)
+ }
+
+ pub(crate) fn span(&self) -> Span {
+ self.span
+ }
+
+ pub(crate) fn set_span(&mut self, span: Span) {
+ self.span = span;
+ }
+
+ pub(crate) fn subspan<R: RangeBounds<usize>>(&self, range: R) -> Option<Span> {
+ #[cfg(not(span_locations))]
+ {
+ let _ = range;
+ None
+ }
+
+ #[cfg(span_locations)]
+ {
+ use core::ops::Bound;
+
+ let lo = match range.start_bound() {
+ Bound::Included(start) => {
+ let start = u32::try_from(*start).ok()?;
+ self.span.lo.checked_add(start)?
+ }
+ Bound::Excluded(start) => {
+ let start = u32::try_from(*start).ok()?;
+ self.span.lo.checked_add(start)?.checked_add(1)?
+ }
+ Bound::Unbounded => self.span.lo,
+ };
+ let hi = match range.end_bound() {
+ Bound::Included(end) => {
+ let end = u32::try_from(*end).ok()?;
+ self.span.lo.checked_add(end)?.checked_add(1)?
+ }
+ Bound::Excluded(end) => {
+ let end = u32::try_from(*end).ok()?;
+ self.span.lo.checked_add(end)?
+ }
+ Bound::Unbounded => self.span.hi,
+ };
+ if lo <= hi && hi <= self.span.hi {
+ Some(Span { lo, hi })
+ } else {
+ None
+ }
+ }
+ }
+}
+
+impl Display for Literal {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ Display::fmt(&self.repr, f)
+ }
+}
+
+impl Debug for Literal {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ let mut debug = fmt.debug_struct("Literal");
+ debug.field("lit", &format_args!("{}", self.repr));
+ debug_span_field_if_nontrivial(&mut debug, self.span);
+ debug.finish()
+ }
+}
+
+fn escape_utf8(string: &str, repr: &mut String) {
+ let mut chars = string.chars();
+ while let Some(ch) = chars.next() {
+ if ch == '\0' {
+ repr.push_str(
+ if chars
+ .as_str()
+ .starts_with(|next| '0' <= next && next <= '7')
+ {
+ // circumvent clippy::octal_escapes lint
+ r"\x00"
+ } else {
+ r"\0"
+ },
+ );
+ } else if ch == '\'' {
+ // escape_debug turns this into "\'" which is unnecessary.
+ repr.push(ch);
+ } else {
+ repr.extend(ch.escape_debug());
+ }
+ }
+}
+
+#[cfg(feature = "proc-macro")]
+pub(crate) trait FromStr2: FromStr<Err = proc_macro::LexError> {
+ #[cfg(wrap_proc_macro)]
+ fn valid(src: &str) -> bool;
+
+ #[cfg(wrap_proc_macro)]
+ fn from_str_checked(src: &str) -> Result<Self, imp::LexError> {
+ // Validate using fallback parser, because rustc is incapable of
+ // returning a recoverable Err for certain invalid token streams, and
+ // will instead permanently poison the compilation.
+ if !Self::valid(src) {
+ return Err(imp::LexError::CompilerPanic);
+ }
+
+ // Catch panic to work around https://github.com/rust-lang/rust/issues/58736.
+ match panic::catch_unwind(|| Self::from_str(src)) {
+ Ok(Ok(ok)) => Ok(ok),
+ Ok(Err(lex)) => Err(imp::LexError::Compiler(lex)),
+ Err(_panic) => Err(imp::LexError::CompilerPanic),
+ }
+ }
+
+ fn from_str_unchecked(src: &str) -> Self {
+ Self::from_str(src).unwrap()
+ }
+}
+
+#[cfg(feature = "proc-macro")]
+impl FromStr2 for proc_macro::TokenStream {
+ #[cfg(wrap_proc_macro)]
+ fn valid(src: &str) -> bool {
+ TokenStream::from_str_checked(src).is_ok()
+ }
+}
+
+#[cfg(feature = "proc-macro")]
+impl FromStr2 for proc_macro::Literal {
+ #[cfg(wrap_proc_macro)]
+ fn valid(src: &str) -> bool {
+ Literal::from_str_checked(src).is_ok()
+ }
+}
diff --git a/rust/proc-macro2/lib.rs b/rust/proc-macro2/lib.rs
new file mode 100644
index 000000000000..2984af335adc
--- /dev/null
+++ b/rust/proc-macro2/lib.rs
@@ -0,0 +1,1349 @@
+//! [![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
+//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
+//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs
+//!
+//! <br>
+//!
+//! A wrapper around the procedural macro API of the compiler's [`proc_macro`]
+//! crate. This library serves two purposes:
+//!
+//! - **Bring proc-macro-like functionality to other contexts like build.rs and
+//! main.rs.** Types from `proc_macro` are entirely specific to procedural
+//! macros and cannot ever exist in code outside of a procedural macro.
+//! Meanwhile `proc_macro2` types may exist anywhere including non-macro code.
+//! By developing foundational libraries like [syn] and [quote] against
+//! `proc_macro2` rather than `proc_macro`, the procedural macro ecosystem
+//! becomes easily applicable to many other use cases and we avoid
+//! reimplementing non-macro equivalents of those libraries.
+//!
+//! - **Make procedural macros unit testable.** As a consequence of being
+//! specific to procedural macros, nothing that uses `proc_macro` can be
+//! executed from a unit test. In order for helper libraries or components of
+//! a macro to be testable in isolation, they must be implemented using
+//! `proc_macro2`.
+//!
+//! [syn]: https://github.com/dtolnay/syn
+//! [quote]: https://github.com/dtolnay/quote
+//!
+//! # Usage
+//!
+//! The skeleton of a typical procedural macro typically looks like this:
+//!
+//! ```
+//! extern crate proc_macro;
+//!
+//! # const IGNORE: &str = stringify! {
+//! #[proc_macro_derive(MyDerive)]
+//! # };
+//! # #[cfg(wrap_proc_macro)]
+//! pub fn my_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
+//! let input = proc_macro2::TokenStream::from(input);
+//!
+//! let output: proc_macro2::TokenStream = {
+//! /* transform input */
+//! # input
+//! };
+//!
+//! proc_macro::TokenStream::from(output)
+//! }
+//! ```
+//!
+//! If parsing with [Syn], you'll use [`parse_macro_input!`] instead to
+//! propagate parse errors correctly back to the compiler when parsing fails.
+//!
+//! [`parse_macro_input!`]: https://docs.rs/syn/2.0/syn/macro.parse_macro_input.html
+//!
+//! # Unstable features
+//!
+//! The default feature set of proc-macro2 tracks the most recent stable
+//! compiler API. Functionality in `proc_macro` that is not yet stable is not
+//! exposed by proc-macro2 by default.
+//!
+//! To opt into the additional APIs available in the most recent nightly
+//! compiler, the `procmacro2_semver_exempt` config flag must be passed to
+//! rustc. We will polyfill those nightly-only APIs back to Rust 1.56.0. As
+//! these are unstable APIs that track the nightly compiler, minor versions of
+//! proc-macro2 may make breaking changes to them at any time.
+//!
+//! ```sh
+//! RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo build
+//! ```
+//!
+//! Note that this must not only be done for your crate, but for any crate that
+//! depends on your crate. This infectious nature is intentional, as it serves
+//! as a reminder that you are outside of the normal semver guarantees.
+//!
+//! Semver exempt methods are marked as such in the proc-macro2 documentation.
+//!
+//! # Thread-Safety
+//!
+//! Most types in this crate are `!Sync` because the underlying compiler
+//! types make use of thread-local memory, meaning they cannot be accessed from
+//! a different thread.
+
+// Proc-macro2 types in rustdoc of other crates get linked to here.
+#![doc(html_root_url = "https://docs.rs/proc-macro2/1.0.101")]
+#![cfg_attr(any(proc_macro_span, super_unstable), feature(proc_macro_span))]
+#![cfg_attr(super_unstable, feature(proc_macro_def_site))]
+#![cfg_attr(docsrs, feature(doc_cfg))]
+#![deny(unsafe_op_in_unsafe_fn)]
+#![allow(
+ clippy::cast_lossless,
+ clippy::cast_possible_truncation,
+ clippy::checked_conversions,
+ clippy::doc_markdown,
+ clippy::elidable_lifetime_names,
+ clippy::incompatible_msrv,
+ clippy::items_after_statements,
+ clippy::iter_without_into_iter,
+ clippy::let_underscore_untyped,
+ clippy::manual_assert,
+ clippy::manual_range_contains,
+ clippy::missing_panics_doc,
+ clippy::missing_safety_doc,
+ clippy::must_use_candidate,
+ clippy::needless_doctest_main,
+ clippy::needless_lifetimes,
+ clippy::new_without_default,
+ clippy::return_self_not_must_use,
+ clippy::shadow_unrelated,
+ clippy::trivially_copy_pass_by_ref,
+ clippy::unnecessary_wraps,
+ clippy::unused_self,
+ clippy::used_underscore_binding,
+ clippy::vec_init_then_push
+)]
+#![allow(unknown_lints, mismatched_lifetime_syntaxes)]
+
+#[cfg(all(procmacro2_semver_exempt, wrap_proc_macro, not(super_unstable)))]
+compile_error! {"\
+ Something is not right. If you've tried to turn on \
+ procmacro2_semver_exempt, you need to ensure that it \
+ is turned on for the compilation of the proc-macro2 \
+ build script as well.
+"}
+
+#[cfg(all(
+ procmacro2_nightly_testing,
+ feature = "proc-macro",
+ not(proc_macro_span)
+))]
+compile_error! {"\
+ Build script probe failed to compile.
+"}
+
+extern crate alloc;
+
+#[cfg(feature = "proc-macro")]
+extern crate proc_macro;
+
+mod marker;
+mod parse;
+mod probe;
+mod rcvec;
+
+#[cfg(wrap_proc_macro)]
+mod detection;
+
+// Public for proc_macro2::fallback::force() and unforce(), but those are quite
+// a niche use case so we omit it from rustdoc.
+#[doc(hidden)]
+pub mod fallback;
+
+pub mod extra;
+
+#[cfg(not(wrap_proc_macro))]
+use crate::fallback as imp;
+#[path = "wrapper.rs"]
+#[cfg(wrap_proc_macro)]
+mod imp;
+
+#[cfg(span_locations)]
+mod location;
+
+use crate::extra::DelimSpan;
+use crate::marker::{ProcMacroAutoTraits, MARKER};
+use core::cmp::Ordering;
+use core::fmt::{self, Debug, Display};
+use core::hash::{Hash, Hasher};
+#[cfg(span_locations)]
+use core::ops::Range;
+use core::ops::RangeBounds;
+use core::str::FromStr;
+use std::error::Error;
+use std::ffi::CStr;
+#[cfg(span_locations)]
+use std::path::PathBuf;
+
+#[cfg(span_locations)]
+#[cfg_attr(docsrs, doc(cfg(feature = "span-locations")))]
+pub use crate::location::LineColumn;
+
+/// An abstract stream of tokens, or more concretely a sequence of token trees.
+///
+/// This type provides interfaces for iterating over token trees and for
+/// collecting token trees into one stream.
+///
+/// Token stream is both the input and output of `#[proc_macro]`,
+/// `#[proc_macro_attribute]` and `#[proc_macro_derive]` definitions.
+#[derive(Clone)]
+pub struct TokenStream {
+ inner: imp::TokenStream,
+ _marker: ProcMacroAutoTraits,
+}
+
+/// Error returned from `TokenStream::from_str`.
+pub struct LexError {
+ inner: imp::LexError,
+ _marker: ProcMacroAutoTraits,
+}
+
+impl TokenStream {
+ fn _new(inner: imp::TokenStream) -> Self {
+ TokenStream {
+ inner,
+ _marker: MARKER,
+ }
+ }
+
+ fn _new_fallback(inner: fallback::TokenStream) -> Self {
+ TokenStream {
+ inner: imp::TokenStream::from(inner),
+ _marker: MARKER,
+ }
+ }
+
+ /// Returns an empty `TokenStream` containing no token trees.
+ pub fn new() -> Self {
+ TokenStream::_new(imp::TokenStream::new())
+ }
+
+ /// Checks if this `TokenStream` is empty.
+ pub fn is_empty(&self) -> bool {
+ self.inner.is_empty()
+ }
+}
+
+/// `TokenStream::default()` returns an empty stream,
+/// i.e. this is equivalent with `TokenStream::new()`.
+impl Default for TokenStream {
+ fn default() -> Self {
+ TokenStream::new()
+ }
+}
+
+/// Attempts to break the string into tokens and parse those tokens into a token
+/// stream.
+///
+/// May fail for a number of reasons, for example, if the string contains
+/// unbalanced delimiters or characters not existing in the language.
+///
+/// NOTE: Some errors may cause panics instead of returning `LexError`. We
+/// reserve the right to change these errors into `LexError`s later.
+impl FromStr for TokenStream {
+ type Err = LexError;
+
+ fn from_str(src: &str) -> Result<TokenStream, LexError> {
+ match imp::TokenStream::from_str_checked(src) {
+ Ok(tokens) => Ok(TokenStream::_new(tokens)),
+ Err(lex) => Err(LexError {
+ inner: lex,
+ _marker: MARKER,
+ }),
+ }
+ }
+}
+
+#[cfg(feature = "proc-macro")]
+#[cfg_attr(docsrs, doc(cfg(feature = "proc-macro")))]
+impl From<proc_macro::TokenStream> for TokenStream {
+ fn from(inner: proc_macro::TokenStream) -> Self {
+ TokenStream::_new(imp::TokenStream::from(inner))
+ }
+}
+
+#[cfg(feature = "proc-macro")]
+#[cfg_attr(docsrs, doc(cfg(feature = "proc-macro")))]
+impl From<TokenStream> for proc_macro::TokenStream {
+ fn from(inner: TokenStream) -> Self {
+ proc_macro::TokenStream::from(inner.inner)
+ }
+}
+
+impl From<TokenTree> for TokenStream {
+ fn from(token: TokenTree) -> Self {
+ TokenStream::_new(imp::TokenStream::from(token))
+ }
+}
+
+impl Extend<TokenTree> for TokenStream {
+ fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, streams: I) {
+ self.inner.extend(streams);
+ }
+}
+
+impl Extend<TokenStream> for TokenStream {
+ fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) {
+ self.inner
+ .extend(streams.into_iter().map(|stream| stream.inner));
+ }
+}
+
+/// Collects a number of token trees into a single stream.
+impl FromIterator<TokenTree> for TokenStream {
+ fn from_iter<I: IntoIterator<Item = TokenTree>>(streams: I) -> Self {
+ TokenStream::_new(streams.into_iter().collect())
+ }
+}
+impl FromIterator<TokenStream> for TokenStream {
+ fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self {
+ TokenStream::_new(streams.into_iter().map(|i| i.inner).collect())
+ }
+}
+
+/// Prints the token stream as a string that is supposed to be losslessly
+/// convertible back into the same token stream (modulo spans), except for
+/// possibly `TokenTree::Group`s with `Delimiter::None` delimiters and negative
+/// numeric literals.
+impl Display for TokenStream {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ Display::fmt(&self.inner, f)
+ }
+}
+
+/// Prints token in a form convenient for debugging.
+impl Debug for TokenStream {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ Debug::fmt(&self.inner, f)
+ }
+}
+
+impl LexError {
+ pub fn span(&self) -> Span {
+ Span::_new(self.inner.span())
+ }
+}
+
+impl Debug for LexError {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ Debug::fmt(&self.inner, f)
+ }
+}
+
+impl Display for LexError {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ Display::fmt(&self.inner, f)
+ }
+}
+
+impl Error for LexError {}
+
+/// A region of source code, along with macro expansion information.
+#[derive(Copy, Clone)]
+pub struct Span {
+ inner: imp::Span,
+ _marker: ProcMacroAutoTraits,
+}
+
+impl Span {
+ fn _new(inner: imp::Span) -> Self {
+ Span {
+ inner,
+ _marker: MARKER,
+ }
+ }
+
+ fn _new_fallback(inner: fallback::Span) -> Self {
+ Span {
+ inner: imp::Span::from(inner),
+ _marker: MARKER,
+ }
+ }
+
+ /// The span of the invocation of the current procedural macro.
+ ///
+ /// Identifiers created with this span will be resolved as if they were
+ /// written directly at the macro call location (call-site hygiene) and
+ /// other code at the macro call site will be able to refer to them as well.
+ pub fn call_site() -> Self {
+ Span::_new(imp::Span::call_site())
+ }
+
+ /// The span located at the invocation of the procedural macro, but with
+ /// local variables, labels, and `$crate` resolved at the definition site
+ /// of the macro. This is the same hygiene behavior as `macro_rules`.
+ pub fn mixed_site() -> Self {
+ Span::_new(imp::Span::mixed_site())
+ }
+
+ /// A span that resolves at the macro definition site.
+ ///
+ /// This method is semver exempt and not exposed by default.
+ #[cfg(procmacro2_semver_exempt)]
+ #[cfg_attr(docsrs, doc(cfg(procmacro2_semver_exempt)))]
+ pub fn def_site() -> Self {
+ Span::_new(imp::Span::def_site())
+ }
+
+ /// Creates a new span with the same line/column information as `self` but
+ /// that resolves symbols as though it were at `other`.
+ pub fn resolved_at(&self, other: Span) -> Span {
+ Span::_new(self.inner.resolved_at(other.inner))
+ }
+
+ /// Creates a new span with the same name resolution behavior as `self` but
+ /// with the line/column information of `other`.
+ pub fn located_at(&self, other: Span) -> Span {
+ Span::_new(self.inner.located_at(other.inner))
+ }
+
+ /// Convert `proc_macro2::Span` to `proc_macro::Span`.
+ ///
+ /// This method is available when building with a nightly compiler, or when
+ /// building with rustc 1.29+ *without* semver exempt features.
+ ///
+ /// # Panics
+ ///
+ /// Panics if called from outside of a procedural macro. Unlike
+ /// `proc_macro2::Span`, the `proc_macro::Span` type can only exist within
+ /// the context of a procedural macro invocation.
+ #[cfg(wrap_proc_macro)]
+ pub fn unwrap(self) -> proc_macro::Span {
+ self.inner.unwrap()
+ }
+
+ // Soft deprecated. Please use Span::unwrap.
+ #[cfg(wrap_proc_macro)]
+ #[doc(hidden)]
+ pub fn unstable(self) -> proc_macro::Span {
+ self.unwrap()
+ }
+
+ /// Returns the span's byte position range in the source file.
+ ///
+ /// This method requires the `"span-locations"` feature to be enabled.
+ ///
+ /// When executing in a procedural macro context, the returned range is only
+ /// accurate if compiled with a nightly toolchain. The stable toolchain does
+ /// not have this information available. When executing outside of a
+ /// procedural macro, such as main.rs or build.rs, the byte range is always
+ /// accurate regardless of toolchain.
+ #[cfg(span_locations)]
+ #[cfg_attr(docsrs, doc(cfg(feature = "span-locations")))]
+ pub fn byte_range(&self) -> Range<usize> {
+ self.inner.byte_range()
+ }
+
+ /// Get the starting line/column in the source file for this span.
+ ///
+ /// This method requires the `"span-locations"` feature to be enabled.
+ ///
+ /// When executing in a procedural macro context, the returned line/column
+ /// are only meaningful if compiled with a nightly toolchain. The stable
+ /// toolchain does not have this information available. When executing
+ /// outside of a procedural macro, such as main.rs or build.rs, the
+ /// line/column are always meaningful regardless of toolchain.
+ #[cfg(span_locations)]
+ #[cfg_attr(docsrs, doc(cfg(feature = "span-locations")))]
+ pub fn start(&self) -> LineColumn {
+ self.inner.start()
+ }
+
+ /// Get the ending line/column in the source file for this span.
+ ///
+ /// This method requires the `"span-locations"` feature to be enabled.
+ ///
+ /// When executing in a procedural macro context, the returned line/column
+ /// are only meaningful if compiled with a nightly toolchain. The stable
+ /// toolchain does not have this information available. When executing
+ /// outside of a procedural macro, such as main.rs or build.rs, the
+ /// line/column are always meaningful regardless of toolchain.
+ #[cfg(span_locations)]
+ #[cfg_attr(docsrs, doc(cfg(feature = "span-locations")))]
+ pub fn end(&self) -> LineColumn {
+ self.inner.end()
+ }
+
+ /// The path to the source file in which this span occurs, for display
+ /// purposes.
+ ///
+ /// This might not correspond to a valid file system path. It might be
+ /// remapped, or might be an artificial path such as `"<macro expansion>"`.
+ #[cfg(span_locations)]
+ #[cfg_attr(docsrs, doc(cfg(feature = "span-locations")))]
+ pub fn file(&self) -> String {
+ self.inner.file()
+ }
+
+ /// The path to the source file in which this span occurs on disk.
+ ///
+ /// This is the actual path on disk. It is unaffected by path remapping.
+ ///
+ /// This path should not be embedded in the output of the macro; prefer
+ /// `file()` instead.
+ #[cfg(span_locations)]
+ #[cfg_attr(docsrs, doc(cfg(feature = "span-locations")))]
+ pub fn local_file(&self) -> Option<PathBuf> {
+ self.inner.local_file()
+ }
+
+ /// Create a new span encompassing `self` and `other`.
+ ///
+ /// Returns `None` if `self` and `other` are from different files.
+ ///
+ /// Warning: the underlying [`proc_macro::Span::join`] method is
+ /// nightly-only. When called from within a procedural macro not using a
+ /// nightly compiler, this method will always return `None`.
+ pub fn join(&self, other: Span) -> Option<Span> {
+ self.inner.join(other.inner).map(Span::_new)
+ }
+
+ /// Compares two spans to see if they're equal.
+ ///
+ /// This method is semver exempt and not exposed by default.
+ #[cfg(procmacro2_semver_exempt)]
+ #[cfg_attr(docsrs, doc(cfg(procmacro2_semver_exempt)))]
+ pub fn eq(&self, other: &Span) -> bool {
+ self.inner.eq(&other.inner)
+ }
+
+ /// Returns the source text behind a span. This preserves the original
+ /// source code, including spaces and comments. It only returns a result if
+ /// the span corresponds to real source code.
+ ///
+ /// Note: The observable result of a macro should only rely on the tokens
+ /// and not on this source text. The result of this function is a best
+ /// effort to be used for diagnostics only.
+ pub fn source_text(&self) -> Option<String> {
+ self.inner.source_text()
+ }
+}
+
+/// Prints a span in a form convenient for debugging.
+impl Debug for Span {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ Debug::fmt(&self.inner, f)
+ }
+}
+
+/// A single token or a delimited sequence of token trees (e.g. `[1, (), ..]`).
+#[derive(Clone)]
+pub enum TokenTree {
+ /// A token stream surrounded by bracket delimiters.
+ Group(Group),
+ /// An identifier.
+ Ident(Ident),
+ /// A single punctuation character (`+`, `,`, `$`, etc.).
+ Punct(Punct),
+ /// A literal character (`'a'`), string (`"hello"`), number (`2.3`), etc.
+ Literal(Literal),
+}
+
+impl TokenTree {
+ /// Returns the span of this tree, delegating to the `span` method of
+ /// the contained token or a delimited stream.
+ pub fn span(&self) -> Span {
+ match self {
+ TokenTree::Group(t) => t.span(),
+ TokenTree::Ident(t) => t.span(),
+ TokenTree::Punct(t) => t.span(),
+ TokenTree::Literal(t) => t.span(),
+ }
+ }
+
+ /// Configures the span for *only this token*.
+ ///
+ /// Note that if this token is a `Group` then this method will not configure
+ /// the span of each of the internal tokens, this will simply delegate to
+ /// the `set_span` method of each variant.
+ pub fn set_span(&mut self, span: Span) {
+ match self {
+ TokenTree::Group(t) => t.set_span(span),
+ TokenTree::Ident(t) => t.set_span(span),
+ TokenTree::Punct(t) => t.set_span(span),
+ TokenTree::Literal(t) => t.set_span(span),
+ }
+ }
+}
+
+impl From<Group> for TokenTree {
+ fn from(g: Group) -> Self {
+ TokenTree::Group(g)
+ }
+}
+
+impl From<Ident> for TokenTree {
+ fn from(g: Ident) -> Self {
+ TokenTree::Ident(g)
+ }
+}
+
+impl From<Punct> for TokenTree {
+ fn from(g: Punct) -> Self {
+ TokenTree::Punct(g)
+ }
+}
+
+impl From<Literal> for TokenTree {
+ fn from(g: Literal) -> Self {
+ TokenTree::Literal(g)
+ }
+}
+
+/// Prints the token tree as a string that is supposed to be losslessly
+/// convertible back into the same token tree (modulo spans), except for
+/// possibly `TokenTree::Group`s with `Delimiter::None` delimiters and negative
+/// numeric literals.
+impl Display for TokenTree {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ TokenTree::Group(t) => Display::fmt(t, f),
+ TokenTree::Ident(t) => Display::fmt(t, f),
+ TokenTree::Punct(t) => Display::fmt(t, f),
+ TokenTree::Literal(t) => Display::fmt(t, f),
+ }
+ }
+}
+
+/// Prints token tree in a form convenient for debugging.
+impl Debug for TokenTree {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ // Each of these has the name in the struct type in the derived debug,
+ // so don't bother with an extra layer of indirection
+ match self {
+ TokenTree::Group(t) => Debug::fmt(t, f),
+ TokenTree::Ident(t) => {
+ let mut debug = f.debug_struct("Ident");
+ debug.field("sym", &format_args!("{}", t));
+ imp::debug_span_field_if_nontrivial(&mut debug, t.span().inner);
+ debug.finish()
+ }
+ TokenTree::Punct(t) => Debug::fmt(t, f),
+ TokenTree::Literal(t) => Debug::fmt(t, f),
+ }
+ }
+}
+
+/// A delimited token stream.
+///
+/// A `Group` internally contains a `TokenStream` which is surrounded by
+/// `Delimiter`s.
+#[derive(Clone)]
+pub struct Group {
+ inner: imp::Group,
+}
+
+/// Describes how a sequence of token trees is delimited.
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub enum Delimiter {
+ /// `( ... )`
+ Parenthesis,
+ /// `{ ... }`
+ Brace,
+ /// `[ ... ]`
+ Bracket,
+ /// `∅ ... ∅`
+ ///
+ /// An invisible delimiter, that may, for example, appear around tokens
+ /// coming from a "macro variable" `$var`. It is important to preserve
+ /// operator priorities in cases like `$var * 3` where `$var` is `1 + 2`.
+ /// Invisible delimiters may not survive roundtrip of a token stream through
+ /// a string.
+ ///
+ /// <div class="warning">
+ ///
+ /// Note: rustc currently can ignore the grouping of tokens delimited by `None` in the output
+ /// of a proc_macro. Only `None`-delimited groups created by a macro_rules macro in the input
+ /// of a proc_macro macro are preserved, and only in very specific circumstances.
+ /// Any `None`-delimited groups (re)created by a proc_macro will therefore not preserve
+ /// operator priorities as indicated above. The other `Delimiter` variants should be used
+ /// instead in this context. This is a rustc bug. For details, see
+ /// [rust-lang/rust#67062](https://github.com/rust-lang/rust/issues/67062).
+ ///
+ /// </div>
+ None,
+}
+
+impl Group {
+ fn _new(inner: imp::Group) -> Self {
+ Group { inner }
+ }
+
+ fn _new_fallback(inner: fallback::Group) -> Self {
+ Group {
+ inner: imp::Group::from(inner),
+ }
+ }
+
+ /// Creates a new `Group` with the given delimiter and token stream.
+ ///
+ /// This constructor will set the span for this group to
+ /// `Span::call_site()`. To change the span you can use the `set_span`
+ /// method below.
+ pub fn new(delimiter: Delimiter, stream: TokenStream) -> Self {
+ Group {
+ inner: imp::Group::new(delimiter, stream.inner),
+ }
+ }
+
+ /// Returns the punctuation used as the delimiter for this group: a set of
+ /// parentheses, square brackets, or curly braces.
+ pub fn delimiter(&self) -> Delimiter {
+ self.inner.delimiter()
+ }
+
+ /// Returns the `TokenStream` of tokens that are delimited in this `Group`.
+ ///
+ /// Note that the returned token stream does not include the delimiter
+ /// returned above.
+ pub fn stream(&self) -> TokenStream {
+ TokenStream::_new(self.inner.stream())
+ }
+
+ /// Returns the span for the delimiters of this token stream, spanning the
+ /// entire `Group`.
+ ///
+ /// ```text
+ /// pub fn span(&self) -> Span {
+ /// ^^^^^^^
+ /// ```
+ pub fn span(&self) -> Span {
+ Span::_new(self.inner.span())
+ }
+
+ /// Returns the span pointing to the opening delimiter of this group.
+ ///
+ /// ```text
+ /// pub fn span_open(&self) -> Span {
+ /// ^
+ /// ```
+ pub fn span_open(&self) -> Span {
+ Span::_new(self.inner.span_open())
+ }
+
+ /// Returns the span pointing to the closing delimiter of this group.
+ ///
+ /// ```text
+ /// pub fn span_close(&self) -> Span {
+ /// ^
+ /// ```
+ pub fn span_close(&self) -> Span {
+ Span::_new(self.inner.span_close())
+ }
+
+ /// Returns an object that holds this group's `span_open()` and
+ /// `span_close()` together (in a more compact representation than holding
+ /// those 2 spans individually).
+ pub fn delim_span(&self) -> DelimSpan {
+ DelimSpan::new(&self.inner)
+ }
+
+ /// Configures the span for this `Group`'s delimiters, but not its internal
+ /// tokens.
+ ///
+ /// This method will **not** set the span of all the internal tokens spanned
+ /// by this group, but rather it will only set the span of the delimiter
+ /// tokens at the level of the `Group`.
+ pub fn set_span(&mut self, span: Span) {
+ self.inner.set_span(span.inner);
+ }
+}
+
+/// Prints the group as a string that should be losslessly convertible back
+/// into the same group (modulo spans), except for possibly `TokenTree::Group`s
+/// with `Delimiter::None` delimiters.
+impl Display for Group {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ Display::fmt(&self.inner, formatter)
+ }
+}
+
+impl Debug for Group {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ Debug::fmt(&self.inner, formatter)
+ }
+}
+
+/// A `Punct` is a single punctuation character like `+`, `-` or `#`.
+///
+/// Multicharacter operators like `+=` are represented as two instances of
+/// `Punct` with different forms of `Spacing` returned.
+#[derive(Clone)]
+pub struct Punct {
+ ch: char,
+ spacing: Spacing,
+ span: Span,
+}
+
+/// Whether a `Punct` is followed immediately by another `Punct` or followed by
+/// another token or whitespace.
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub enum Spacing {
+ /// E.g. `+` is `Alone` in `+ =`, `+ident` or `+()`.
+ Alone,
+ /// E.g. `+` is `Joint` in `+=` or `'` is `Joint` in `'#`.
+ ///
+ /// Additionally, single quote `'` can join with identifiers to form
+ /// lifetimes `'ident`.
+ Joint,
+}
+
+impl Punct {
+ /// Creates a new `Punct` from the given character and spacing.
+ ///
+ /// The `ch` argument must be a valid punctuation character permitted by the
+ /// language, otherwise the function will panic.
+ ///
+ /// The returned `Punct` will have the default span of `Span::call_site()`
+ /// which can be further configured with the `set_span` method below.
+ pub fn new(ch: char, spacing: Spacing) -> Self {
+ if let '!' | '#' | '$' | '%' | '&' | '\'' | '*' | '+' | ',' | '-' | '.' | '/' | ':' | ';'
+ | '<' | '=' | '>' | '?' | '@' | '^' | '|' | '~' = ch
+ {
+ Punct {
+ ch,
+ spacing,
+ span: Span::call_site(),
+ }
+ } else {
+ panic!("unsupported proc macro punctuation character {:?}", ch);
+ }
+ }
+
+ /// Returns the value of this punctuation character as `char`.
+ pub fn as_char(&self) -> char {
+ self.ch
+ }
+
+ /// Returns the spacing of this punctuation character, indicating whether
+ /// it's immediately followed by another `Punct` in the token stream, so
+ /// they can potentially be combined into a multicharacter operator
+ /// (`Joint`), or it's followed by some other token or whitespace (`Alone`)
+ /// so the operator has certainly ended.
+ pub fn spacing(&self) -> Spacing {
+ self.spacing
+ }
+
+ /// Returns the span for this punctuation character.
+ pub fn span(&self) -> Span {
+ self.span
+ }
+
+ /// Configure the span for this punctuation character.
+ pub fn set_span(&mut self, span: Span) {
+ self.span = span;
+ }
+}
+
+/// Prints the punctuation character as a string that should be losslessly
+/// convertible back into the same character.
+impl Display for Punct {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ Display::fmt(&self.ch, f)
+ }
+}
+
+impl Debug for Punct {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ let mut debug = fmt.debug_struct("Punct");
+ debug.field("char", &self.ch);
+ debug.field("spacing", &self.spacing);
+ imp::debug_span_field_if_nontrivial(&mut debug, self.span.inner);
+ debug.finish()
+ }
+}
+
+/// A word of Rust code, which may be a keyword or legal variable name.
+///
+/// An identifier consists of at least one Unicode code point, the first of
+/// which has the XID_Start property and the rest of which have the XID_Continue
+/// property.
+///
+/// - The empty string is not an identifier. Use `Option<Ident>`.
+/// - A lifetime is not an identifier. Use `syn::Lifetime` instead.
+///
+/// An identifier constructed with `Ident::new` is permitted to be a Rust
+/// keyword, though parsing one through its [`Parse`] implementation rejects
+/// Rust keywords. Use `input.call(Ident::parse_any)` when parsing to match the
+/// behaviour of `Ident::new`.
+///
+/// [`Parse`]: https://docs.rs/syn/2.0/syn/parse/trait.Parse.html
+///
+/// # Examples
+///
+/// A new ident can be created from a string using the `Ident::new` function.
+/// A span must be provided explicitly which governs the name resolution
+/// behavior of the resulting identifier.
+///
+/// ```
+/// use proc_macro2::{Ident, Span};
+///
+/// fn main() {
+/// let call_ident = Ident::new("calligraphy", Span::call_site());
+///
+/// println!("{}", call_ident);
+/// }
+/// ```
+///
+/// An ident can be interpolated into a token stream using the `quote!` macro.
+///
+/// ```
+/// use proc_macro2::{Ident, Span};
+/// use quote::quote;
+///
+/// fn main() {
+/// let ident = Ident::new("demo", Span::call_site());
+///
+/// // Create a variable binding whose name is this ident.
+/// let expanded = quote! { let #ident = 10; };
+///
+/// // Create a variable binding with a slightly different name.
+/// let temp_ident = Ident::new(&format!("new_{}", ident), Span::call_site());
+/// let expanded = quote! { let #temp_ident = 10; };
+/// }
+/// ```
+///
+/// A string representation of the ident is available through the `to_string()`
+/// method.
+///
+/// ```
+/// # use proc_macro2::{Ident, Span};
+/// #
+/// # let ident = Ident::new("another_identifier", Span::call_site());
+/// #
+/// // Examine the ident as a string.
+/// let ident_string = ident.to_string();
+/// if ident_string.len() > 60 {
+/// println!("Very long identifier: {}", ident_string)
+/// }
+/// ```
+#[derive(Clone)]
+pub struct Ident {
+ inner: imp::Ident,
+ _marker: ProcMacroAutoTraits,
+}
+
+impl Ident {
+ fn _new(inner: imp::Ident) -> Self {
+ Ident {
+ inner,
+ _marker: MARKER,
+ }
+ }
+
+ fn _new_fallback(inner: fallback::Ident) -> Self {
+ Ident {
+ inner: imp::Ident::from(inner),
+ _marker: MARKER,
+ }
+ }
+
+ /// Creates a new `Ident` with the given `string` as well as the specified
+ /// `span`.
+ ///
+ /// The `string` argument must be a valid identifier permitted by the
+ /// language, otherwise the function will panic.
+ ///
+ /// Note that `span`, currently in rustc, configures the hygiene information
+ /// for this identifier.
+ ///
+ /// As of this time `Span::call_site()` explicitly opts-in to "call-site"
+ /// hygiene meaning that identifiers created with this span will be resolved
+ /// as if they were written directly at the location of the macro call, and
+ /// other code at the macro call site will be able to refer to them as well.
+ ///
+ /// Later spans like `Span::def_site()` will allow to opt-in to
+ /// "definition-site" hygiene meaning that identifiers created with this
+ /// span will be resolved at the location of the macro definition and other
+ /// code at the macro call site will not be able to refer to them.
+ ///
+ /// Due to the current importance of hygiene this constructor, unlike other
+ /// tokens, requires a `Span` to be specified at construction.
+ ///
+ /// # Panics
+ ///
+ /// Panics if the input string is neither a keyword nor a legal variable
+ /// name. If you are not sure whether the string contains an identifier and
+ /// need to handle an error case, use
+ /// <a href="https://docs.rs/syn/2.0/syn/fn.parse_str.html"><code
+ /// style="padding-right:0;">syn::parse_str</code></a><code
+ /// style="padding-left:0;">::<Ident></code>
+ /// rather than `Ident::new`.
+ #[track_caller]
+ pub fn new(string: &str, span: Span) -> Self {
+ Ident::_new(imp::Ident::new_checked(string, span.inner))
+ }
+
+ /// Same as `Ident::new`, but creates a raw identifier (`r#ident`). The
+ /// `string` argument must be a valid identifier permitted by the language
+ /// (including keywords, e.g. `fn`). Keywords which are usable in path
+ /// segments (e.g. `self`, `super`) are not supported, and will cause a
+ /// panic.
+ #[track_caller]
+ pub fn new_raw(string: &str, span: Span) -> Self {
+ Ident::_new(imp::Ident::new_raw_checked(string, span.inner))
+ }
+
+ /// Returns the span of this `Ident`.
+ pub fn span(&self) -> Span {
+ Span::_new(self.inner.span())
+ }
+
+ /// Configures the span of this `Ident`, possibly changing its hygiene
+ /// context.
+ pub fn set_span(&mut self, span: Span) {
+ self.inner.set_span(span.inner);
+ }
+}
+
+impl PartialEq for Ident {
+ fn eq(&self, other: &Ident) -> bool {
+ self.inner == other.inner
+ }
+}
+
+impl<T> PartialEq<T> for Ident
+where
+ T: ?Sized + AsRef<str>,
+{
+ fn eq(&self, other: &T) -> bool {
+ self.inner == other
+ }
+}
+
+impl Eq for Ident {}
+
+impl PartialOrd for Ident {
+ fn partial_cmp(&self, other: &Ident) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
+impl Ord for Ident {
+ fn cmp(&self, other: &Ident) -> Ordering {
+ self.to_string().cmp(&other.to_string())
+ }
+}
+
+impl Hash for Ident {
+ fn hash<H: Hasher>(&self, hasher: &mut H) {
+ self.to_string().hash(hasher);
+ }
+}
+
+/// Prints the identifier as a string that should be losslessly convertible back
+/// into the same identifier.
+impl Display for Ident {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ Display::fmt(&self.inner, f)
+ }
+}
+
+impl Debug for Ident {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ Debug::fmt(&self.inner, f)
+ }
+}
+
+/// A literal string (`"hello"`), byte string (`b"hello"`), character (`'a'`),
+/// byte character (`b'a'`), an integer or floating point number with or without
+/// a suffix (`1`, `1u8`, `2.3`, `2.3f32`).
+///
+/// Boolean literals like `true` and `false` do not belong here, they are
+/// `Ident`s.
+#[derive(Clone)]
+pub struct Literal {
+ inner: imp::Literal,
+ _marker: ProcMacroAutoTraits,
+}
+
+macro_rules! suffixed_int_literals {
+ ($($name:ident => $kind:ident,)*) => ($(
+ /// Creates a new suffixed integer literal with the specified value.
+ ///
+ /// This function will create an integer like `1u32` where the integer
+ /// value specified is the first part of the token and the integral is
+ /// also suffixed at the end. Literals created from negative numbers may
+ /// not survive roundtrips through `TokenStream` or strings and may be
+ /// broken into two tokens (`-` and positive literal).
+ ///
+ /// Literals created through this method have the `Span::call_site()`
+ /// span by default, which can be configured with the `set_span` method
+ /// below.
+ pub fn $name(n: $kind) -> Literal {
+ Literal::_new(imp::Literal::$name(n))
+ }
+ )*)
+}
+
+macro_rules! unsuffixed_int_literals {
+ ($($name:ident => $kind:ident,)*) => ($(
+ /// Creates a new unsuffixed integer literal with the specified value.
+ ///
+ /// This function will create an integer like `1` where the integer
+ /// value specified is the first part of the token. No suffix is
+ /// specified on this token, meaning that invocations like
+ /// `Literal::i8_unsuffixed(1)` are equivalent to
+ /// `Literal::u32_unsuffixed(1)`. Literals created from negative numbers
+ /// may not survive roundtrips through `TokenStream` or strings and may
+ /// be broken into two tokens (`-` and positive literal).
+ ///
+ /// Literals created through this method have the `Span::call_site()`
+ /// span by default, which can be configured with the `set_span` method
+ /// below.
+ pub fn $name(n: $kind) -> Literal {
+ Literal::_new(imp::Literal::$name(n))
+ }
+ )*)
+}
+
+impl Literal {
+ fn _new(inner: imp::Literal) -> Self {
+ Literal {
+ inner,
+ _marker: MARKER,
+ }
+ }
+
+ fn _new_fallback(inner: fallback::Literal) -> Self {
+ Literal {
+ inner: imp::Literal::from(inner),
+ _marker: MARKER,
+ }
+ }
+
+ suffixed_int_literals! {
+ u8_suffixed => u8,
+ u16_suffixed => u16,
+ u32_suffixed => u32,
+ u64_suffixed => u64,
+ u128_suffixed => u128,
+ usize_suffixed => usize,
+ i8_suffixed => i8,
+ i16_suffixed => i16,
+ i32_suffixed => i32,
+ i64_suffixed => i64,
+ i128_suffixed => i128,
+ isize_suffixed => isize,
+ }
+
+ unsuffixed_int_literals! {
+ u8_unsuffixed => u8,
+ u16_unsuffixed => u16,
+ u32_unsuffixed => u32,
+ u64_unsuffixed => u64,
+ u128_unsuffixed => u128,
+ usize_unsuffixed => usize,
+ i8_unsuffixed => i8,
+ i16_unsuffixed => i16,
+ i32_unsuffixed => i32,
+ i64_unsuffixed => i64,
+ i128_unsuffixed => i128,
+ isize_unsuffixed => isize,
+ }
+
+ /// Creates a new unsuffixed floating-point literal.
+ ///
+ /// This constructor is similar to those like `Literal::i8_unsuffixed` where
+ /// the float's value is emitted directly into the token but no suffix is
+ /// used, so it may be inferred to be a `f64` later in the compiler.
+ /// Literals created from negative numbers may not survive round-trips
+ /// through `TokenStream` or strings and may be broken into two tokens (`-`
+ /// and positive literal).
+ ///
+ /// # Panics
+ ///
+ /// This function requires that the specified float is finite, for example
+ /// if it is infinity or NaN this function will panic.
+ pub fn f64_unsuffixed(f: f64) -> Literal {
+ assert!(f.is_finite());
+ Literal::_new(imp::Literal::f64_unsuffixed(f))
+ }
+
+ /// Creates a new suffixed floating-point literal.
+ ///
+ /// This constructor will create a literal like `1.0f64` where the value
+ /// specified is the preceding part of the token and `f64` is the suffix of
+ /// the token. This token will always be inferred to be an `f64` in the
+ /// compiler. Literals created from negative numbers may not survive
+ /// round-trips through `TokenStream` or strings and may be broken into two
+ /// tokens (`-` and positive literal).
+ ///
+ /// # Panics
+ ///
+ /// This function requires that the specified float is finite, for example
+ /// if it is infinity or NaN this function will panic.
+ pub fn f64_suffixed(f: f64) -> Literal {
+ assert!(f.is_finite());
+ Literal::_new(imp::Literal::f64_suffixed(f))
+ }
+
+ /// Creates a new unsuffixed floating-point literal.
+ ///
+ /// This constructor is similar to those like `Literal::i8_unsuffixed` where
+ /// the float's value is emitted directly into the token but no suffix is
+ /// used, so it may be inferred to be a `f64` later in the compiler.
+ /// Literals created from negative numbers may not survive round-trips
+ /// through `TokenStream` or strings and may be broken into two tokens (`-`
+ /// and positive literal).
+ ///
+ /// # Panics
+ ///
+ /// This function requires that the specified float is finite, for example
+ /// if it is infinity or NaN this function will panic.
+ pub fn f32_unsuffixed(f: f32) -> Literal {
+ assert!(f.is_finite());
+ Literal::_new(imp::Literal::f32_unsuffixed(f))
+ }
+
+ /// Creates a new suffixed floating-point literal.
+ ///
+ /// This constructor will create a literal like `1.0f32` where the value
+ /// specified is the preceding part of the token and `f32` is the suffix of
+ /// the token. This token will always be inferred to be an `f32` in the
+ /// compiler. Literals created from negative numbers may not survive
+ /// round-trips through `TokenStream` or strings and may be broken into two
+ /// tokens (`-` and positive literal).
+ ///
+ /// # Panics
+ ///
+ /// This function requires that the specified float is finite, for example
+ /// if it is infinity or NaN this function will panic.
+ pub fn f32_suffixed(f: f32) -> Literal {
+ assert!(f.is_finite());
+ Literal::_new(imp::Literal::f32_suffixed(f))
+ }
+
+ /// String literal.
+ pub fn string(string: &str) -> Literal {
+ Literal::_new(imp::Literal::string(string))
+ }
+
+ /// Character literal.
+ pub fn character(ch: char) -> Literal {
+ Literal::_new(imp::Literal::character(ch))
+ }
+
+ /// Byte character literal.
+ pub fn byte_character(byte: u8) -> Literal {
+ Literal::_new(imp::Literal::byte_character(byte))
+ }
+
+ /// Byte string literal.
+ pub fn byte_string(bytes: &[u8]) -> Literal {
+ Literal::_new(imp::Literal::byte_string(bytes))
+ }
+
+ /// C string literal.
+ pub fn c_string(string: &CStr) -> Literal {
+ Literal::_new(imp::Literal::c_string(string))
+ }
+
+ /// Returns the span encompassing this literal.
+ pub fn span(&self) -> Span {
+ Span::_new(self.inner.span())
+ }
+
+ /// Configures the span associated for this literal.
+ pub fn set_span(&mut self, span: Span) {
+ self.inner.set_span(span.inner);
+ }
+
+ /// Returns a `Span` that is a subset of `self.span()` containing only
+ /// the source bytes in range `range`. Returns `None` if the would-be
+ /// trimmed span is outside the bounds of `self`.
+ ///
+ /// Warning: the underlying [`proc_macro::Literal::subspan`] method is
+ /// nightly-only. When called from within a procedural macro not using a
+ /// nightly compiler, this method will always return `None`.
+ pub fn subspan<R: RangeBounds<usize>>(&self, range: R) -> Option<Span> {
+ self.inner.subspan(range).map(Span::_new)
+ }
+
+ // Intended for the `quote!` macro to use when constructing a proc-macro2
+ // token out of a macro_rules $:literal token, which is already known to be
+ // a valid literal. This avoids reparsing/validating the literal's string
+ // representation. This is not public API other than for quote.
+ #[doc(hidden)]
+ pub unsafe fn from_str_unchecked(repr: &str) -> Self {
+ Literal::_new(unsafe { imp::Literal::from_str_unchecked(repr) })
+ }
+}
+
+impl FromStr for Literal {
+ type Err = LexError;
+
+ fn from_str(repr: &str) -> Result<Self, LexError> {
+ match imp::Literal::from_str_checked(repr) {
+ Ok(lit) => Ok(Literal::_new(lit)),
+ Err(lex) => Err(LexError {
+ inner: lex,
+ _marker: MARKER,
+ }),
+ }
+ }
+}
+
+impl Debug for Literal {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ Debug::fmt(&self.inner, f)
+ }
+}
+
+impl Display for Literal {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ Display::fmt(&self.inner, f)
+ }
+}
+
+/// Public implementation details for the `TokenStream` type, such as iterators.
+pub mod token_stream {
+ use crate::marker::{ProcMacroAutoTraits, MARKER};
+ use crate::{imp, TokenTree};
+ use core::fmt::{self, Debug};
+
+ pub use crate::TokenStream;
+
+ /// An iterator over `TokenStream`'s `TokenTree`s.
+ ///
+ /// The iteration is "shallow", e.g. the iterator doesn't recurse into
+ /// delimited groups, and returns whole groups as token trees.
+ #[derive(Clone)]
+ pub struct IntoIter {
+ inner: imp::TokenTreeIter,
+ _marker: ProcMacroAutoTraits,
+ }
+
+ impl Iterator for IntoIter {
+ type Item = TokenTree;
+
+ fn next(&mut self) -> Option<TokenTree> {
+ self.inner.next()
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.inner.size_hint()
+ }
+ }
+
+ impl Debug for IntoIter {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.write_str("TokenStream ")?;
+ f.debug_list().entries(self.clone()).finish()
+ }
+ }
+
+ impl IntoIterator for TokenStream {
+ type Item = TokenTree;
+ type IntoIter = IntoIter;
+
+ fn into_iter(self) -> IntoIter {
+ IntoIter {
+ inner: self.inner.into_iter(),
+ _marker: MARKER,
+ }
+ }
+ }
+}
diff --git a/rust/proc-macro2/location.rs b/rust/proc-macro2/location.rs
new file mode 100644
index 000000000000..7190e2d05255
--- /dev/null
+++ b/rust/proc-macro2/location.rs
@@ -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))
+ }
+}
diff --git a/rust/proc-macro2/marker.rs b/rust/proc-macro2/marker.rs
new file mode 100644
index 000000000000..23b94ce6fa85
--- /dev/null
+++ b/rust/proc-macro2/marker.rs
@@ -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 {}
diff --git a/rust/proc-macro2/parse.rs b/rust/proc-macro2/parse.rs
new file mode 100644
index 000000000000..b8be403f842f
--- /dev/null
+++ b/rust/proc-macro2/parse.rs
@@ -0,0 +1,995 @@
+use crate::fallback::{
+ self, is_ident_continue, is_ident_start, Group, Ident, LexError, Literal, Span, TokenStream,
+ TokenStreamBuilder,
+};
+use crate::{Delimiter, Punct, Spacing, TokenTree};
+use core::char;
+use core::str::{Bytes, CharIndices, Chars};
+
+#[derive(Copy, Clone, Eq, PartialEq)]
+pub(crate) struct Cursor<'a> {
+ pub(crate) rest: &'a str,
+ #[cfg(span_locations)]
+ pub(crate) off: u32,
+}
+
+impl<'a> Cursor<'a> {
+ pub(crate) fn advance(&self, bytes: usize) -> Cursor<'a> {
+ let (_front, rest) = self.rest.split_at(bytes);
+ Cursor {
+ rest,
+ #[cfg(span_locations)]
+ off: self.off + _front.chars().count() as u32,
+ }
+ }
+
+ pub(crate) fn starts_with(&self, s: &str) -> bool {
+ self.rest.starts_with(s)
+ }
+
+ pub(crate) fn starts_with_char(&self, ch: char) -> bool {
+ self.rest.starts_with(ch)
+ }
+
+ pub(crate) fn starts_with_fn<Pattern>(&self, f: Pattern) -> bool
+ where
+ Pattern: FnMut(char) -> bool,
+ {
+ self.rest.starts_with(f)
+ }
+
+ pub(crate) fn is_empty(&self) -> bool {
+ self.rest.is_empty()
+ }
+
+ fn len(&self) -> usize {
+ self.rest.len()
+ }
+
+ fn as_bytes(&self) -> &'a [u8] {
+ self.rest.as_bytes()
+ }
+
+ fn bytes(&self) -> Bytes<'a> {
+ self.rest.bytes()
+ }
+
+ fn chars(&self) -> Chars<'a> {
+ self.rest.chars()
+ }
+
+ fn char_indices(&self) -> CharIndices<'a> {
+ self.rest.char_indices()
+ }
+
+ fn parse(&self, tag: &str) -> Result<Cursor<'a>, Reject> {
+ if self.starts_with(tag) {
+ Ok(self.advance(tag.len()))
+ } else {
+ Err(Reject)
+ }
+ }
+}
+
+pub(crate) struct Reject;
+type PResult<'a, O> = Result<(Cursor<'a>, O), Reject>;
+
+fn skip_whitespace(input: Cursor) -> Cursor {
+ let mut s = input;
+
+ while !s.is_empty() {
+ let byte = s.as_bytes()[0];
+ if byte == b'/' {
+ if s.starts_with("//")
+ && (!s.starts_with("///") || s.starts_with("////"))
+ && !s.starts_with("//!")
+ {
+ let (cursor, _) = take_until_newline_or_eof(s);
+ s = cursor;
+ continue;
+ } else if s.starts_with("/**/") {
+ s = s.advance(4);
+ continue;
+ } else if s.starts_with("/*")
+ && (!s.starts_with("/**") || s.starts_with("/***"))
+ && !s.starts_with("/*!")
+ {
+ match block_comment(s) {
+ Ok((rest, _)) => {
+ s = rest;
+ continue;
+ }
+ Err(Reject) => return s,
+ }
+ }
+ }
+ match byte {
+ b' ' | 0x09..=0x0d => {
+ s = s.advance(1);
+ continue;
+ }
+ b if b.is_ascii() => {}
+ _ => {
+ let ch = s.chars().next().unwrap();
+ if is_whitespace(ch) {
+ s = s.advance(ch.len_utf8());
+ continue;
+ }
+ }
+ }
+ return s;
+ }
+ s
+}
+
+fn block_comment(input: Cursor) -> PResult<&str> {
+ if !input.starts_with("/*") {
+ return Err(Reject);
+ }
+
+ let mut depth = 0usize;
+ let bytes = input.as_bytes();
+ let mut i = 0usize;
+ let upper = bytes.len() - 1;
+
+ while i < upper {
+ if bytes[i] == b'/' && bytes[i + 1] == b'*' {
+ depth += 1;
+ i += 1; // eat '*'
+ } else if bytes[i] == b'*' && bytes[i + 1] == b'/' {
+ depth -= 1;
+ if depth == 0 {
+ return Ok((input.advance(i + 2), &input.rest[..i + 2]));
+ }
+ i += 1; // eat '/'
+ }
+ i += 1;
+ }
+
+ Err(Reject)
+}
+
+fn is_whitespace(ch: char) -> bool {
+ // Rust treats left-to-right mark and right-to-left mark as whitespace
+ ch.is_whitespace() || ch == '\u{200e}' || ch == '\u{200f}'
+}
+
+fn word_break(input: Cursor) -> Result<Cursor, Reject> {
+ match input.chars().next() {
+ Some(ch) if is_ident_continue(ch) => Err(Reject),
+ Some(_) | None => Ok(input),
+ }
+}
+
+// Rustc's representation of a macro expansion error in expression position or
+// type position.
+const ERROR: &str = "(/*ERROR*/)";
+
+pub(crate) fn token_stream(mut input: Cursor) -> Result<TokenStream, LexError> {
+ let mut trees = TokenStreamBuilder::new();
+ let mut stack = Vec::new();
+
+ loop {
+ input = skip_whitespace(input);
+
+ if let Ok((rest, ())) = doc_comment(input, &mut trees) {
+ input = rest;
+ continue;
+ }
+
+ #[cfg(span_locations)]
+ let lo = input.off;
+
+ let first = match input.bytes().next() {
+ Some(first) => first,
+ None => match stack.last() {
+ None => return Ok(trees.build()),
+ #[cfg(span_locations)]
+ Some((lo, _frame)) => {
+ return Err(LexError {
+ span: Span { lo: *lo, hi: *lo },
+ })
+ }
+ #[cfg(not(span_locations))]
+ Some(_frame) => return Err(LexError { span: Span {} }),
+ },
+ };
+
+ if let Some(open_delimiter) = match first {
+ b'(' if !input.starts_with(ERROR) => Some(Delimiter::Parenthesis),
+ b'[' => Some(Delimiter::Bracket),
+ b'{' => Some(Delimiter::Brace),
+ _ => None,
+ } {
+ input = input.advance(1);
+ let frame = (open_delimiter, trees);
+ #[cfg(span_locations)]
+ let frame = (lo, frame);
+ stack.push(frame);
+ trees = TokenStreamBuilder::new();
+ } else if let Some(close_delimiter) = match first {
+ b')' => Some(Delimiter::Parenthesis),
+ b']' => Some(Delimiter::Bracket),
+ b'}' => Some(Delimiter::Brace),
+ _ => None,
+ } {
+ let frame = match stack.pop() {
+ Some(frame) => frame,
+ None => return Err(lex_error(input)),
+ };
+ #[cfg(span_locations)]
+ let (lo, frame) = frame;
+ let (open_delimiter, outer) = frame;
+ if open_delimiter != close_delimiter {
+ return Err(lex_error(input));
+ }
+ input = input.advance(1);
+ let mut g = Group::new(open_delimiter, trees.build());
+ g.set_span(Span {
+ #[cfg(span_locations)]
+ lo,
+ #[cfg(span_locations)]
+ hi: input.off,
+ });
+ trees = outer;
+ trees.push_token_from_parser(TokenTree::Group(crate::Group::_new_fallback(g)));
+ } else {
+ let (rest, mut tt) = match leaf_token(input) {
+ Ok((rest, tt)) => (rest, tt),
+ Err(Reject) => return Err(lex_error(input)),
+ };
+ tt.set_span(crate::Span::_new_fallback(Span {
+ #[cfg(span_locations)]
+ lo,
+ #[cfg(span_locations)]
+ hi: rest.off,
+ }));
+ trees.push_token_from_parser(tt);
+ input = rest;
+ }
+ }
+}
+
+fn lex_error(cursor: Cursor) -> LexError {
+ #[cfg(not(span_locations))]
+ let _ = cursor;
+ LexError {
+ span: Span {
+ #[cfg(span_locations)]
+ lo: cursor.off,
+ #[cfg(span_locations)]
+ hi: cursor.off,
+ },
+ }
+}
+
+fn leaf_token(input: Cursor) -> PResult<TokenTree> {
+ if let Ok((input, l)) = literal(input) {
+ // must be parsed before ident
+ Ok((input, TokenTree::Literal(crate::Literal::_new_fallback(l))))
+ } else if let Ok((input, p)) = punct(input) {
+ Ok((input, TokenTree::Punct(p)))
+ } else if let Ok((input, i)) = ident(input) {
+ Ok((input, TokenTree::Ident(i)))
+ } else if input.starts_with(ERROR) {
+ let rest = input.advance(ERROR.len());
+ let repr = crate::Literal::_new_fallback(Literal::_new(ERROR.to_owned()));
+ Ok((rest, TokenTree::Literal(repr)))
+ } else {
+ Err(Reject)
+ }
+}
+
+fn ident(input: Cursor) -> PResult<crate::Ident> {
+ if [
+ "r\"", "r#\"", "r##", "b\"", "b\'", "br\"", "br#", "c\"", "cr\"", "cr#",
+ ]
+ .iter()
+ .any(|prefix| input.starts_with(prefix))
+ {
+ Err(Reject)
+ } else {
+ ident_any(input)
+ }
+}
+
+fn ident_any(input: Cursor) -> PResult<crate::Ident> {
+ let raw = input.starts_with("r#");
+ let rest = input.advance((raw as usize) << 1);
+
+ let (rest, sym) = ident_not_raw(rest)?;
+
+ if !raw {
+ let ident =
+ crate::Ident::_new_fallback(Ident::new_unchecked(sym, fallback::Span::call_site()));
+ return Ok((rest, ident));
+ }
+
+ match sym {
+ "_" | "super" | "self" | "Self" | "crate" => return Err(Reject),
+ _ => {}
+ }
+
+ let ident =
+ crate::Ident::_new_fallback(Ident::new_raw_unchecked(sym, fallback::Span::call_site()));
+ Ok((rest, ident))
+}
+
+fn ident_not_raw(input: Cursor) -> PResult<&str> {
+ let mut chars = input.char_indices();
+
+ match chars.next() {
+ Some((_, ch)) if is_ident_start(ch) => {}
+ _ => return Err(Reject),
+ }
+
+ let mut end = input.len();
+ for (i, ch) in chars {
+ if !is_ident_continue(ch) {
+ end = i;
+ break;
+ }
+ }
+
+ Ok((input.advance(end), &input.rest[..end]))
+}
+
+pub(crate) fn literal(input: Cursor) -> PResult<Literal> {
+ let rest = literal_nocapture(input)?;
+ let end = input.len() - rest.len();
+ Ok((rest, Literal::_new(input.rest[..end].to_string())))
+}
+
+fn literal_nocapture(input: Cursor) -> Result<Cursor, Reject> {
+ if let Ok(ok) = string(input) {
+ Ok(ok)
+ } else if let Ok(ok) = byte_string(input) {
+ Ok(ok)
+ } else if let Ok(ok) = c_string(input) {
+ Ok(ok)
+ } else if let Ok(ok) = byte(input) {
+ Ok(ok)
+ } else if let Ok(ok) = character(input) {
+ Ok(ok)
+ } else if let Ok(ok) = float(input) {
+ Ok(ok)
+ } else if let Ok(ok) = int(input) {
+ Ok(ok)
+ } else {
+ Err(Reject)
+ }
+}
+
+fn literal_suffix(input: Cursor) -> Cursor {
+ match ident_not_raw(input) {
+ Ok((input, _)) => input,
+ Err(Reject) => input,
+ }
+}
+
+fn string(input: Cursor) -> Result<Cursor, Reject> {
+ if let Ok(input) = input.parse("\"") {
+ cooked_string(input)
+ } else if let Ok(input) = input.parse("r") {
+ raw_string(input)
+ } else {
+ Err(Reject)
+ }
+}
+
+fn cooked_string(mut input: Cursor) -> Result<Cursor, Reject> {
+ let mut chars = input.char_indices();
+
+ while let Some((i, ch)) = chars.next() {
+ match ch {
+ '"' => {
+ let input = input.advance(i + 1);
+ return Ok(literal_suffix(input));
+ }
+ '\r' => match chars.next() {
+ Some((_, '\n')) => {}
+ _ => break,
+ },
+ '\\' => match chars.next() {
+ Some((_, 'x')) => {
+ backslash_x_char(&mut chars)?;
+ }
+ Some((_, 'n' | 'r' | 't' | '\\' | '\'' | '"' | '0')) => {}
+ Some((_, 'u')) => {
+ backslash_u(&mut chars)?;
+ }
+ Some((newline, ch @ ('\n' | '\r'))) => {
+ input = input.advance(newline + 1);
+ trailing_backslash(&mut input, ch as u8)?;
+ chars = input.char_indices();
+ }
+ _ => break,
+ },
+ _ch => {}
+ }
+ }
+ Err(Reject)
+}
+
+fn raw_string(input: Cursor) -> Result<Cursor, Reject> {
+ let (input, delimiter) = delimiter_of_raw_string(input)?;
+ let mut bytes = input.bytes().enumerate();
+ while let Some((i, byte)) = bytes.next() {
+ match byte {
+ b'"' if input.rest[i + 1..].starts_with(delimiter) => {
+ let rest = input.advance(i + 1 + delimiter.len());
+ return Ok(literal_suffix(rest));
+ }
+ b'\r' => match bytes.next() {
+ Some((_, b'\n')) => {}
+ _ => break,
+ },
+ _ => {}
+ }
+ }
+ Err(Reject)
+}
+
+fn byte_string(input: Cursor) -> Result<Cursor, Reject> {
+ if let Ok(input) = input.parse("b\"") {
+ cooked_byte_string(input)
+ } else if let Ok(input) = input.parse("br") {
+ raw_byte_string(input)
+ } else {
+ Err(Reject)
+ }
+}
+
+fn cooked_byte_string(mut input: Cursor) -> Result<Cursor, Reject> {
+ let mut bytes = input.bytes().enumerate();
+ while let Some((offset, b)) = bytes.next() {
+ match b {
+ b'"' => {
+ let input = input.advance(offset + 1);
+ return Ok(literal_suffix(input));
+ }
+ b'\r' => match bytes.next() {
+ Some((_, b'\n')) => {}
+ _ => break,
+ },
+ b'\\' => match bytes.next() {
+ Some((_, b'x')) => {
+ backslash_x_byte(&mut bytes)?;
+ }
+ Some((_, b'n' | b'r' | b't' | b'\\' | b'0' | b'\'' | b'"')) => {}
+ Some((newline, b @ (b'\n' | b'\r'))) => {
+ input = input.advance(newline + 1);
+ trailing_backslash(&mut input, b)?;
+ bytes = input.bytes().enumerate();
+ }
+ _ => break,
+ },
+ b if b.is_ascii() => {}
+ _ => break,
+ }
+ }
+ Err(Reject)
+}
+
+fn delimiter_of_raw_string(input: Cursor) -> PResult<&str> {
+ for (i, byte) in input.bytes().enumerate() {
+ match byte {
+ b'"' => {
+ if i > 255 {
+ // https://github.com/rust-lang/rust/pull/95251
+ return Err(Reject);
+ }
+ return Ok((input.advance(i + 1), &input.rest[..i]));
+ }
+ b'#' => {}
+ _ => break,
+ }
+ }
+ Err(Reject)
+}
+
+fn raw_byte_string(input: Cursor) -> Result<Cursor, Reject> {
+ let (input, delimiter) = delimiter_of_raw_string(input)?;
+ let mut bytes = input.bytes().enumerate();
+ while let Some((i, byte)) = bytes.next() {
+ match byte {
+ b'"' if input.rest[i + 1..].starts_with(delimiter) => {
+ let rest = input.advance(i + 1 + delimiter.len());
+ return Ok(literal_suffix(rest));
+ }
+ b'\r' => match bytes.next() {
+ Some((_, b'\n')) => {}
+ _ => break,
+ },
+ other => {
+ if !other.is_ascii() {
+ break;
+ }
+ }
+ }
+ }
+ Err(Reject)
+}
+
+fn c_string(input: Cursor) -> Result<Cursor, Reject> {
+ if let Ok(input) = input.parse("c\"") {
+ cooked_c_string(input)
+ } else if let Ok(input) = input.parse("cr") {
+ raw_c_string(input)
+ } else {
+ Err(Reject)
+ }
+}
+
+fn raw_c_string(input: Cursor) -> Result<Cursor, Reject> {
+ let (input, delimiter) = delimiter_of_raw_string(input)?;
+ let mut bytes = input.bytes().enumerate();
+ while let Some((i, byte)) = bytes.next() {
+ match byte {
+ b'"' if input.rest[i + 1..].starts_with(delimiter) => {
+ let rest = input.advance(i + 1 + delimiter.len());
+ return Ok(literal_suffix(rest));
+ }
+ b'\r' => match bytes.next() {
+ Some((_, b'\n')) => {}
+ _ => break,
+ },
+ b'\0' => break,
+ _ => {}
+ }
+ }
+ Err(Reject)
+}
+
+fn cooked_c_string(mut input: Cursor) -> Result<Cursor, Reject> {
+ let mut chars = input.char_indices();
+
+ while let Some((i, ch)) = chars.next() {
+ match ch {
+ '"' => {
+ let input = input.advance(i + 1);
+ return Ok(literal_suffix(input));
+ }
+ '\r' => match chars.next() {
+ Some((_, '\n')) => {}
+ _ => break,
+ },
+ '\\' => match chars.next() {
+ Some((_, 'x')) => {
+ backslash_x_nonzero(&mut chars)?;
+ }
+ Some((_, 'n' | 'r' | 't' | '\\' | '\'' | '"')) => {}
+ Some((_, 'u')) => {
+ if backslash_u(&mut chars)? == '\0' {
+ break;
+ }
+ }
+ Some((newline, ch @ ('\n' | '\r'))) => {
+ input = input.advance(newline + 1);
+ trailing_backslash(&mut input, ch as u8)?;
+ chars = input.char_indices();
+ }
+ _ => break,
+ },
+ '\0' => break,
+ _ch => {}
+ }
+ }
+ Err(Reject)
+}
+
+fn byte(input: Cursor) -> Result<Cursor, Reject> {
+ let input = input.parse("b'")?;
+ let mut bytes = input.bytes().enumerate();
+ let ok = match bytes.next().map(|(_, b)| b) {
+ Some(b'\\') => match bytes.next().map(|(_, b)| b) {
+ Some(b'x') => backslash_x_byte(&mut bytes).is_ok(),
+ Some(b'n' | b'r' | b't' | b'\\' | b'0' | b'\'' | b'"') => true,
+ _ => false,
+ },
+ b => b.is_some(),
+ };
+ if !ok {
+ return Err(Reject);
+ }
+ let (offset, _) = bytes.next().ok_or(Reject)?;
+ if !input.chars().as_str().is_char_boundary(offset) {
+ return Err(Reject);
+ }
+ let input = input.advance(offset).parse("'")?;
+ Ok(literal_suffix(input))
+}
+
+fn character(input: Cursor) -> Result<Cursor, Reject> {
+ let input = input.parse("'")?;
+ let mut chars = input.char_indices();
+ let ok = match chars.next().map(|(_, ch)| ch) {
+ Some('\\') => match chars.next().map(|(_, ch)| ch) {
+ Some('x') => backslash_x_char(&mut chars).is_ok(),
+ Some('u') => backslash_u(&mut chars).is_ok(),
+ Some('n' | 'r' | 't' | '\\' | '0' | '\'' | '"') => true,
+ _ => false,
+ },
+ ch => ch.is_some(),
+ };
+ if !ok {
+ return Err(Reject);
+ }
+ let (idx, _) = chars.next().ok_or(Reject)?;
+ let input = input.advance(idx).parse("'")?;
+ Ok(literal_suffix(input))
+}
+
+macro_rules! next_ch {
+ ($chars:ident @ $pat:pat) => {
+ match $chars.next() {
+ Some((_, ch)) => match ch {
+ $pat => ch,
+ _ => return Err(Reject),
+ },
+ None => return Err(Reject),
+ }
+ };
+}
+
+fn backslash_x_char<I>(chars: &mut I) -> Result<(), Reject>
+where
+ I: Iterator<Item = (usize, char)>,
+{
+ next_ch!(chars @ '0'..='7');
+ next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F');
+ Ok(())
+}
+
+fn backslash_x_byte<I>(chars: &mut I) -> Result<(), Reject>
+where
+ I: Iterator<Item = (usize, u8)>,
+{
+ next_ch!(chars @ b'0'..=b'9' | b'a'..=b'f' | b'A'..=b'F');
+ next_ch!(chars @ b'0'..=b'9' | b'a'..=b'f' | b'A'..=b'F');
+ Ok(())
+}
+
+fn backslash_x_nonzero<I>(chars: &mut I) -> Result<(), Reject>
+where
+ I: Iterator<Item = (usize, char)>,
+{
+ let first = next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F');
+ let second = next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F');
+ if first == '0' && second == '0' {
+ Err(Reject)
+ } else {
+ Ok(())
+ }
+}
+
+fn backslash_u<I>(chars: &mut I) -> Result<char, Reject>
+where
+ I: Iterator<Item = (usize, char)>,
+{
+ next_ch!(chars @ '{');
+ let mut value = 0;
+ let mut len = 0;
+ for (_, ch) in chars {
+ let digit = match ch {
+ '0'..='9' => ch as u8 - b'0',
+ 'a'..='f' => 10 + ch as u8 - b'a',
+ 'A'..='F' => 10 + ch as u8 - b'A',
+ '_' if len > 0 => continue,
+ '}' if len > 0 => return char::from_u32(value).ok_or(Reject),
+ _ => break,
+ };
+ if len == 6 {
+ break;
+ }
+ value *= 0x10;
+ value += u32::from(digit);
+ len += 1;
+ }
+ Err(Reject)
+}
+
+fn trailing_backslash(input: &mut Cursor, mut last: u8) -> Result<(), Reject> {
+ let mut whitespace = input.bytes().enumerate();
+ loop {
+ if last == b'\r' && whitespace.next().map_or(true, |(_, b)| b != b'\n') {
+ return Err(Reject);
+ }
+ match whitespace.next() {
+ Some((_, b @ (b' ' | b'\t' | b'\n' | b'\r'))) => {
+ last = b;
+ }
+ Some((offset, _)) => {
+ *input = input.advance(offset);
+ return Ok(());
+ }
+ None => return Err(Reject),
+ }
+ }
+}
+
+fn float(input: Cursor) -> Result<Cursor, Reject> {
+ let mut rest = float_digits(input)?;
+ if let Some(ch) = rest.chars().next() {
+ if is_ident_start(ch) {
+ rest = ident_not_raw(rest)?.0;
+ }
+ }
+ word_break(rest)
+}
+
+fn float_digits(input: Cursor) -> Result<Cursor, Reject> {
+ let mut chars = input.chars().peekable();
+ match chars.next() {
+ Some(ch) if '0' <= ch && ch <= '9' => {}
+ _ => return Err(Reject),
+ }
+
+ let mut len = 1;
+ let mut has_dot = false;
+ let mut has_exp = false;
+ while let Some(&ch) = chars.peek() {
+ match ch {
+ '0'..='9' | '_' => {
+ chars.next();
+ len += 1;
+ }
+ '.' => {
+ if has_dot {
+ break;
+ }
+ chars.next();
+ if chars
+ .peek()
+ .map_or(false, |&ch| ch == '.' || is_ident_start(ch))
+ {
+ return Err(Reject);
+ }
+ len += 1;
+ has_dot = true;
+ }
+ 'e' | 'E' => {
+ chars.next();
+ len += 1;
+ has_exp = true;
+ break;
+ }
+ _ => break,
+ }
+ }
+
+ if !(has_dot || has_exp) {
+ return Err(Reject);
+ }
+
+ if has_exp {
+ let token_before_exp = if has_dot {
+ Ok(input.advance(len - 1))
+ } else {
+ Err(Reject)
+ };
+ let mut has_sign = false;
+ let mut has_exp_value = false;
+ while let Some(&ch) = chars.peek() {
+ match ch {
+ '+' | '-' => {
+ if has_exp_value {
+ break;
+ }
+ if has_sign {
+ return token_before_exp;
+ }
+ chars.next();
+ len += 1;
+ has_sign = true;
+ }
+ '0'..='9' => {
+ chars.next();
+ len += 1;
+ has_exp_value = true;
+ }
+ '_' => {
+ chars.next();
+ len += 1;
+ }
+ _ => break,
+ }
+ }
+ if !has_exp_value {
+ return token_before_exp;
+ }
+ }
+
+ Ok(input.advance(len))
+}
+
+fn int(input: Cursor) -> Result<Cursor, Reject> {
+ let mut rest = digits(input)?;
+ if let Some(ch) = rest.chars().next() {
+ if is_ident_start(ch) {
+ rest = ident_not_raw(rest)?.0;
+ }
+ }
+ word_break(rest)
+}
+
+fn digits(mut input: Cursor) -> Result<Cursor, Reject> {
+ let base = if input.starts_with("0x") {
+ input = input.advance(2);
+ 16
+ } else if input.starts_with("0o") {
+ input = input.advance(2);
+ 8
+ } else if input.starts_with("0b") {
+ input = input.advance(2);
+ 2
+ } else {
+ 10
+ };
+
+ let mut len = 0;
+ let mut empty = true;
+ for b in input.bytes() {
+ match b {
+ b'0'..=b'9' => {
+ let digit = (b - b'0') as u64;
+ if digit >= base {
+ return Err(Reject);
+ }
+ }
+ b'a'..=b'f' => {
+ let digit = 10 + (b - b'a') as u64;
+ if digit >= base {
+ break;
+ }
+ }
+ b'A'..=b'F' => {
+ let digit = 10 + (b - b'A') as u64;
+ if digit >= base {
+ break;
+ }
+ }
+ b'_' => {
+ if empty && base == 10 {
+ return Err(Reject);
+ }
+ len += 1;
+ continue;
+ }
+ _ => break,
+ }
+ len += 1;
+ empty = false;
+ }
+ if empty {
+ Err(Reject)
+ } else {
+ Ok(input.advance(len))
+ }
+}
+
+fn punct(input: Cursor) -> PResult<Punct> {
+ let (rest, ch) = punct_char(input)?;
+ if ch == '\'' {
+ let (after_lifetime, _ident) = ident_any(rest)?;
+ if after_lifetime.starts_with_char('\'')
+ || (after_lifetime.starts_with_char('#') && !rest.starts_with("r#"))
+ {
+ Err(Reject)
+ } else {
+ Ok((rest, Punct::new('\'', Spacing::Joint)))
+ }
+ } else {
+ let kind = match punct_char(rest) {
+ Ok(_) => Spacing::Joint,
+ Err(Reject) => Spacing::Alone,
+ };
+ Ok((rest, Punct::new(ch, kind)))
+ }
+}
+
+fn punct_char(input: Cursor) -> PResult<char> {
+ if input.starts_with("//") || input.starts_with("/*") {
+ // Do not accept `/` of a comment as a punct.
+ return Err(Reject);
+ }
+
+ let mut chars = input.chars();
+ let first = match chars.next() {
+ Some(ch) => ch,
+ None => {
+ return Err(Reject);
+ }
+ };
+ let recognized = "~!@#$%^&*-=+|;:,<.>/?'";
+ if recognized.contains(first) {
+ Ok((input.advance(first.len_utf8()), first))
+ } else {
+ Err(Reject)
+ }
+}
+
+fn doc_comment<'a>(input: Cursor<'a>, trees: &mut TokenStreamBuilder) -> PResult<'a, ()> {
+ #[cfg(span_locations)]
+ let lo = input.off;
+ let (rest, (comment, inner)) = doc_comment_contents(input)?;
+ let fallback_span = Span {
+ #[cfg(span_locations)]
+ lo,
+ #[cfg(span_locations)]
+ hi: rest.off,
+ };
+ let span = crate::Span::_new_fallback(fallback_span);
+
+ let mut scan_for_bare_cr = comment;
+ while let Some(cr) = scan_for_bare_cr.find('\r') {
+ let rest = &scan_for_bare_cr[cr + 1..];
+ if !rest.starts_with('\n') {
+ return Err(Reject);
+ }
+ scan_for_bare_cr = rest;
+ }
+
+ let mut pound = Punct::new('#', Spacing::Alone);
+ pound.set_span(span);
+ trees.push_token_from_parser(TokenTree::Punct(pound));
+
+ if inner {
+ let mut bang = Punct::new('!', Spacing::Alone);
+ bang.set_span(span);
+ trees.push_token_from_parser(TokenTree::Punct(bang));
+ }
+
+ let doc_ident = crate::Ident::_new_fallback(Ident::new_unchecked("doc", fallback_span));
+ let mut equal = Punct::new('=', Spacing::Alone);
+ equal.set_span(span);
+ let mut literal = crate::Literal::_new_fallback(Literal::string(comment));
+ literal.set_span(span);
+ let mut bracketed = TokenStreamBuilder::with_capacity(3);
+ bracketed.push_token_from_parser(TokenTree::Ident(doc_ident));
+ bracketed.push_token_from_parser(TokenTree::Punct(equal));
+ bracketed.push_token_from_parser(TokenTree::Literal(literal));
+ let group = Group::new(Delimiter::Bracket, bracketed.build());
+ let mut group = crate::Group::_new_fallback(group);
+ group.set_span(span);
+ trees.push_token_from_parser(TokenTree::Group(group));
+
+ Ok((rest, ()))
+}
+
+fn doc_comment_contents(input: Cursor) -> PResult<(&str, bool)> {
+ if input.starts_with("//!") {
+ let input = input.advance(3);
+ let (input, s) = take_until_newline_or_eof(input);
+ Ok((input, (s, true)))
+ } else if input.starts_with("/*!") {
+ let (input, s) = block_comment(input)?;
+ Ok((input, (&s[3..s.len() - 2], true)))
+ } else if input.starts_with("///") {
+ let input = input.advance(3);
+ if input.starts_with_char('/') {
+ return Err(Reject);
+ }
+ let (input, s) = take_until_newline_or_eof(input);
+ Ok((input, (s, false)))
+ } else if input.starts_with("/**") && !input.rest[3..].starts_with('*') {
+ let (input, s) = block_comment(input)?;
+ Ok((input, (&s[3..s.len() - 2], false)))
+ } else {
+ Err(Reject)
+ }
+}
+
+fn take_until_newline_or_eof(input: Cursor) -> (Cursor, &str) {
+ let chars = input.char_indices();
+
+ for (i, ch) in chars {
+ if ch == '\n' {
+ return (input.advance(i), &input.rest[..i]);
+ } else if ch == '\r' && input.rest[i + 1..].starts_with('\n') {
+ return (input.advance(i + 1), &input.rest[..i]);
+ }
+ }
+
+ (input.advance(input.len()), input.rest)
+}
diff --git a/rust/proc-macro2/probe.rs b/rust/proc-macro2/probe.rs
new file mode 100644
index 000000000000..b67f52036218
--- /dev/null
+++ b/rust/proc-macro2/probe.rs
@@ -0,0 +1,10 @@
+#![allow(dead_code)]
+
+#[cfg(proc_macro_span)]
+pub(crate) mod proc_macro_span;
+
+#[cfg(proc_macro_span_file)]
+pub(crate) mod proc_macro_span_file;
+
+#[cfg(proc_macro_span_location)]
+pub(crate) mod proc_macro_span_location;
diff --git a/rust/proc-macro2/probe/proc_macro_span.rs b/rust/proc-macro2/probe/proc_macro_span.rs
new file mode 100644
index 000000000000..2d7d44e07708
--- /dev/null
+++ b/rust/proc-macro2/probe/proc_macro_span.rs
@@ -0,0 +1,51 @@
+// 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.
+
+#![cfg_attr(procmacro2_build_probe, feature(proc_macro_span))]
+
+extern crate proc_macro;
+
+use core::ops::{Range, RangeBounds};
+use proc_macro::{Literal, Span};
+use std::path::PathBuf;
+
+pub fn byte_range(this: &Span) -> Range<usize> {
+ this.byte_range()
+}
+
+pub fn start(this: &Span) -> Span {
+ this.start()
+}
+
+pub fn end(this: &Span) -> Span {
+ this.end()
+}
+
+pub fn line(this: &Span) -> usize {
+ this.line()
+}
+
+pub fn column(this: &Span) -> usize {
+ this.column()
+}
+
+pub fn file(this: &Span) -> String {
+ this.file()
+}
+
+pub fn local_file(this: &Span) -> Option<PathBuf> {
+ this.local_file()
+}
+
+pub fn join(this: &Span, other: Span) -> Option<Span> {
+ this.join(other)
+}
+
+pub fn subspan<R: RangeBounds<usize>>(this: &Literal, range: R) -> Option<Span> {
+ this.subspan(range)
+}
+
+// Include in sccache cache key.
+#[cfg(procmacro2_build_probe)]
+const _: Option<&str> = option_env!("RUSTC_BOOTSTRAP");
diff --git a/rust/proc-macro2/probe/proc_macro_span_file.rs b/rust/proc-macro2/probe/proc_macro_span_file.rs
new file mode 100644
index 000000000000..8b76bdf5007b
--- /dev/null
+++ b/rust/proc-macro2/probe/proc_macro_span_file.rs
@@ -0,0 +1,14 @@
+// The subset of Span's API stabilized in Rust 1.88.
+
+extern crate proc_macro;
+
+use proc_macro::Span;
+use std::path::PathBuf;
+
+pub fn file(this: &Span) -> String {
+ this.file()
+}
+
+pub fn local_file(this: &Span) -> Option<PathBuf> {
+ this.local_file()
+}
diff --git a/rust/proc-macro2/probe/proc_macro_span_location.rs b/rust/proc-macro2/probe/proc_macro_span_location.rs
new file mode 100644
index 000000000000..79da34af54af
--- /dev/null
+++ b/rust/proc-macro2/probe/proc_macro_span_location.rs
@@ -0,0 +1,21 @@
+// The subset of Span's API stabilized in Rust 1.88.
+
+extern crate proc_macro;
+
+use proc_macro::Span;
+
+pub fn start(this: &Span) -> Span {
+ this.start()
+}
+
+pub fn end(this: &Span) -> Span {
+ this.end()
+}
+
+pub fn line(this: &Span) -> usize {
+ this.line()
+}
+
+pub fn column(this: &Span) -> usize {
+ this.column()
+}
diff --git a/rust/proc-macro2/rcvec.rs b/rust/proc-macro2/rcvec.rs
new file mode 100644
index 000000000000..23edc77d597f
--- /dev/null
+++ b/rust/proc-macro2/rcvec.rs
@@ -0,0 +1,146 @@
+use alloc::rc::Rc;
+use alloc::vec;
+use core::mem;
+use core::panic::RefUnwindSafe;
+use core::slice;
+
+pub(crate) struct RcVec<T> {
+ inner: Rc<Vec<T>>,
+}
+
+pub(crate) struct RcVecBuilder<T> {
+ inner: Vec<T>,
+}
+
+pub(crate) struct RcVecMut<'a, T> {
+ inner: &'a mut Vec<T>,
+}
+
+#[derive(Clone)]
+pub(crate) struct RcVecIntoIter<T> {
+ inner: vec::IntoIter<T>,
+}
+
+impl<T> RcVec<T> {
+ pub(crate) fn is_empty(&self) -> bool {
+ self.inner.is_empty()
+ }
+
+ pub(crate) fn len(&self) -> usize {
+ self.inner.len()
+ }
+
+ pub(crate) fn iter(&self) -> slice::Iter<T> {
+ self.inner.iter()
+ }
+
+ pub(crate) fn make_mut(&mut self) -> RcVecMut<T>
+ where
+ T: Clone,
+ {
+ RcVecMut {
+ inner: Rc::make_mut(&mut self.inner),
+ }
+ }
+
+ pub(crate) fn get_mut(&mut self) -> Option<RcVecMut<T>> {
+ let inner = Rc::get_mut(&mut self.inner)?;
+ Some(RcVecMut { inner })
+ }
+
+ pub(crate) fn make_owned(mut self) -> RcVecBuilder<T>
+ where
+ T: Clone,
+ {
+ let vec = if let Some(owned) = Rc::get_mut(&mut self.inner) {
+ mem::take(owned)
+ } else {
+ Vec::clone(&self.inner)
+ };
+ RcVecBuilder { inner: vec }
+ }
+}
+
+impl<T> RcVecBuilder<T> {
+ pub(crate) fn new() -> Self {
+ RcVecBuilder { inner: Vec::new() }
+ }
+
+ pub(crate) fn with_capacity(cap: usize) -> Self {
+ RcVecBuilder {
+ inner: Vec::with_capacity(cap),
+ }
+ }
+
+ pub(crate) fn push(&mut self, element: T) {
+ self.inner.push(element);
+ }
+
+ pub(crate) fn extend(&mut self, iter: impl IntoIterator<Item = T>) {
+ self.inner.extend(iter);
+ }
+
+ pub(crate) fn as_mut(&mut self) -> RcVecMut<T> {
+ RcVecMut {
+ inner: &mut self.inner,
+ }
+ }
+
+ pub(crate) fn build(self) -> RcVec<T> {
+ RcVec {
+ inner: Rc::new(self.inner),
+ }
+ }
+}
+
+impl<'a, T> RcVecMut<'a, T> {
+ pub(crate) fn push(&mut self, element: T) {
+ self.inner.push(element);
+ }
+
+ pub(crate) fn extend(&mut self, iter: impl IntoIterator<Item = T>) {
+ self.inner.extend(iter);
+ }
+
+ pub(crate) fn as_mut(&mut self) -> RcVecMut<T> {
+ RcVecMut { inner: self.inner }
+ }
+
+ pub(crate) fn take(self) -> RcVecBuilder<T> {
+ let vec = mem::take(self.inner);
+ RcVecBuilder { inner: vec }
+ }
+}
+
+impl<T> Clone for RcVec<T> {
+ fn clone(&self) -> Self {
+ RcVec {
+ inner: Rc::clone(&self.inner),
+ }
+ }
+}
+
+impl<T> IntoIterator for RcVecBuilder<T> {
+ type Item = T;
+ type IntoIter = RcVecIntoIter<T>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ RcVecIntoIter {
+ inner: self.inner.into_iter(),
+ }
+ }
+}
+
+impl<T> Iterator for RcVecIntoIter<T> {
+ type Item = T;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.inner.next()
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.inner.size_hint()
+ }
+}
+
+impl<T> RefUnwindSafe for RcVec<T> where T: RefUnwindSafe {}
diff --git a/rust/proc-macro2/wrapper.rs b/rust/proc-macro2/wrapper.rs
new file mode 100644
index 000000000000..2e3eb5b4d04e
--- /dev/null
+++ b/rust/proc-macro2/wrapper.rs
@@ -0,0 +1,984 @@
+use crate::detection::inside_proc_macro;
+use crate::fallback::{self, FromStr2 as _};
+#[cfg(span_locations)]
+use crate::location::LineColumn;
+#[cfg(proc_macro_span)]
+use crate::probe::proc_macro_span;
+#[cfg(all(span_locations, proc_macro_span_file))]
+use crate::probe::proc_macro_span_file;
+#[cfg(all(span_locations, proc_macro_span_location))]
+use crate::probe::proc_macro_span_location;
+use crate::{Delimiter, Punct, Spacing, TokenTree};
+use core::fmt::{self, Debug, Display};
+#[cfg(span_locations)]
+use core::ops::Range;
+use core::ops::RangeBounds;
+use std::ffi::CStr;
+#[cfg(span_locations)]
+use std::path::PathBuf;
+
+#[derive(Clone)]
+pub(crate) enum TokenStream {
+ Compiler(DeferredTokenStream),
+ Fallback(fallback::TokenStream),
+}
+
+// Work around https://github.com/rust-lang/rust/issues/65080.
+// In `impl Extend<TokenTree> for TokenStream` which is used heavily by quote,
+// we hold on to the appended tokens and do proc_macro::TokenStream::extend as
+// late as possible to batch together consecutive uses of the Extend impl.
+#[derive(Clone)]
+pub(crate) struct DeferredTokenStream {
+ stream: proc_macro::TokenStream,
+ extra: Vec<proc_macro::TokenTree>,
+}
+
+pub(crate) enum LexError {
+ Compiler(proc_macro::LexError),
+ Fallback(fallback::LexError),
+
+ // Rustc was supposed to return a LexError, but it panicked instead.
+ // https://github.com/rust-lang/rust/issues/58736
+ CompilerPanic,
+}
+
+#[cold]
+fn mismatch(line: u32) -> ! {
+ #[cfg(procmacro2_backtrace)]
+ {
+ let backtrace = std::backtrace::Backtrace::force_capture();
+ panic!("compiler/fallback mismatch L{}\n\n{}", line, backtrace)
+ }
+ #[cfg(not(procmacro2_backtrace))]
+ {
+ panic!("compiler/fallback mismatch L{}", line)
+ }
+}
+
+impl DeferredTokenStream {
+ fn new(stream: proc_macro::TokenStream) -> Self {
+ DeferredTokenStream {
+ stream,
+ extra: Vec::new(),
+ }
+ }
+
+ fn is_empty(&self) -> bool {
+ self.stream.is_empty() && self.extra.is_empty()
+ }
+
+ fn evaluate_now(&mut self) {
+ // If-check provides a fast short circuit for the common case of `extra`
+ // being empty, which saves a round trip over the proc macro bridge.
+ // Improves macro expansion time in winrt by 6% in debug mode.
+ if !self.extra.is_empty() {
+ self.stream.extend(self.extra.drain(..));
+ }
+ }
+
+ fn into_token_stream(mut self) -> proc_macro::TokenStream {
+ self.evaluate_now();
+ self.stream
+ }
+}
+
+impl TokenStream {
+ pub(crate) fn new() -> Self {
+ if inside_proc_macro() {
+ TokenStream::Compiler(DeferredTokenStream::new(proc_macro::TokenStream::new()))
+ } else {
+ TokenStream::Fallback(fallback::TokenStream::new())
+ }
+ }
+
+ pub(crate) fn from_str_checked(src: &str) -> Result<Self, LexError> {
+ if inside_proc_macro() {
+ Ok(TokenStream::Compiler(DeferredTokenStream::new(
+ proc_macro::TokenStream::from_str_checked(src)?,
+ )))
+ } else {
+ Ok(TokenStream::Fallback(
+ fallback::TokenStream::from_str_checked(src)?,
+ ))
+ }
+ }
+
+ pub(crate) fn is_empty(&self) -> bool {
+ match self {
+ TokenStream::Compiler(tts) => tts.is_empty(),
+ TokenStream::Fallback(tts) => tts.is_empty(),
+ }
+ }
+
+ fn unwrap_nightly(self) -> proc_macro::TokenStream {
+ match self {
+ TokenStream::Compiler(s) => s.into_token_stream(),
+ TokenStream::Fallback(_) => mismatch(line!()),
+ }
+ }
+
+ fn unwrap_stable(self) -> fallback::TokenStream {
+ match self {
+ TokenStream::Compiler(_) => mismatch(line!()),
+ TokenStream::Fallback(s) => s,
+ }
+ }
+}
+
+impl Display for TokenStream {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ TokenStream::Compiler(tts) => Display::fmt(&tts.clone().into_token_stream(), f),
+ TokenStream::Fallback(tts) => Display::fmt(tts, f),
+ }
+ }
+}
+
+impl From<proc_macro::TokenStream> for TokenStream {
+ fn from(inner: proc_macro::TokenStream) -> Self {
+ TokenStream::Compiler(DeferredTokenStream::new(inner))
+ }
+}
+
+impl From<TokenStream> for proc_macro::TokenStream {
+ fn from(inner: TokenStream) -> Self {
+ match inner {
+ TokenStream::Compiler(inner) => inner.into_token_stream(),
+ TokenStream::Fallback(inner) => {
+ proc_macro::TokenStream::from_str_unchecked(&inner.to_string())
+ }
+ }
+ }
+}
+
+impl From<fallback::TokenStream> for TokenStream {
+ fn from(inner: fallback::TokenStream) -> Self {
+ TokenStream::Fallback(inner)
+ }
+}
+
+// Assumes inside_proc_macro().
+fn into_compiler_token(token: TokenTree) -> proc_macro::TokenTree {
+ match token {
+ TokenTree::Group(tt) => proc_macro::TokenTree::Group(tt.inner.unwrap_nightly()),
+ TokenTree::Punct(tt) => {
+ let spacing = match tt.spacing() {
+ Spacing::Joint => proc_macro::Spacing::Joint,
+ Spacing::Alone => proc_macro::Spacing::Alone,
+ };
+ let mut punct = proc_macro::Punct::new(tt.as_char(), spacing);
+ punct.set_span(tt.span().inner.unwrap_nightly());
+ proc_macro::TokenTree::Punct(punct)
+ }
+ TokenTree::Ident(tt) => proc_macro::TokenTree::Ident(tt.inner.unwrap_nightly()),
+ TokenTree::Literal(tt) => proc_macro::TokenTree::Literal(tt.inner.unwrap_nightly()),
+ }
+}
+
+impl From<TokenTree> for TokenStream {
+ fn from(token: TokenTree) -> Self {
+ if inside_proc_macro() {
+ TokenStream::Compiler(DeferredTokenStream::new(proc_macro::TokenStream::from(
+ into_compiler_token(token),
+ )))
+ } else {
+ TokenStream::Fallback(fallback::TokenStream::from(token))
+ }
+ }
+}
+
+impl FromIterator<TokenTree> for TokenStream {
+ fn from_iter<I: IntoIterator<Item = TokenTree>>(trees: I) -> Self {
+ if inside_proc_macro() {
+ TokenStream::Compiler(DeferredTokenStream::new(
+ trees.into_iter().map(into_compiler_token).collect(),
+ ))
+ } else {
+ TokenStream::Fallback(trees.into_iter().collect())
+ }
+ }
+}
+
+impl FromIterator<TokenStream> for TokenStream {
+ fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self {
+ let mut streams = streams.into_iter();
+ match streams.next() {
+ Some(TokenStream::Compiler(mut first)) => {
+ first.evaluate_now();
+ first.stream.extend(streams.map(|s| match s {
+ TokenStream::Compiler(s) => s.into_token_stream(),
+ TokenStream::Fallback(_) => mismatch(line!()),
+ }));
+ TokenStream::Compiler(first)
+ }
+ Some(TokenStream::Fallback(mut first)) => {
+ first.extend(streams.map(|s| match s {
+ TokenStream::Fallback(s) => s,
+ TokenStream::Compiler(_) => mismatch(line!()),
+ }));
+ TokenStream::Fallback(first)
+ }
+ None => TokenStream::new(),
+ }
+ }
+}
+
+impl Extend<TokenTree> for TokenStream {
+ fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, stream: I) {
+ match self {
+ TokenStream::Compiler(tts) => {
+ // Here is the reason for DeferredTokenStream.
+ for token in stream {
+ tts.extra.push(into_compiler_token(token));
+ }
+ }
+ TokenStream::Fallback(tts) => tts.extend(stream),
+ }
+ }
+}
+
+impl Extend<TokenStream> for TokenStream {
+ fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) {
+ match self {
+ TokenStream::Compiler(tts) => {
+ tts.evaluate_now();
+ tts.stream
+ .extend(streams.into_iter().map(TokenStream::unwrap_nightly));
+ }
+ TokenStream::Fallback(tts) => {
+ tts.extend(streams.into_iter().map(TokenStream::unwrap_stable));
+ }
+ }
+ }
+}
+
+impl Debug for TokenStream {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ TokenStream::Compiler(tts) => Debug::fmt(&tts.clone().into_token_stream(), f),
+ TokenStream::Fallback(tts) => Debug::fmt(tts, f),
+ }
+ }
+}
+
+impl LexError {
+ pub(crate) fn span(&self) -> Span {
+ match self {
+ LexError::Compiler(_) | LexError::CompilerPanic => Span::call_site(),
+ LexError::Fallback(e) => Span::Fallback(e.span()),
+ }
+ }
+}
+
+impl From<proc_macro::LexError> for LexError {
+ fn from(e: proc_macro::LexError) -> Self {
+ LexError::Compiler(e)
+ }
+}
+
+impl From<fallback::LexError> for LexError {
+ fn from(e: fallback::LexError) -> Self {
+ LexError::Fallback(e)
+ }
+}
+
+impl Debug for LexError {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ LexError::Compiler(e) => Debug::fmt(e, f),
+ LexError::Fallback(e) => Debug::fmt(e, f),
+ LexError::CompilerPanic => {
+ let fallback = fallback::LexError::call_site();
+ Debug::fmt(&fallback, f)
+ }
+ }
+ }
+}
+
+impl Display for LexError {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ LexError::Compiler(e) => Display::fmt(e, f),
+ LexError::Fallback(e) => Display::fmt(e, f),
+ LexError::CompilerPanic => {
+ let fallback = fallback::LexError::call_site();
+ Display::fmt(&fallback, f)
+ }
+ }
+ }
+}
+
+#[derive(Clone)]
+pub(crate) enum TokenTreeIter {
+ Compiler(proc_macro::token_stream::IntoIter),
+ Fallback(fallback::TokenTreeIter),
+}
+
+impl IntoIterator for TokenStream {
+ type Item = TokenTree;
+ type IntoIter = TokenTreeIter;
+
+ fn into_iter(self) -> TokenTreeIter {
+ match self {
+ TokenStream::Compiler(tts) => {
+ TokenTreeIter::Compiler(tts.into_token_stream().into_iter())
+ }
+ TokenStream::Fallback(tts) => TokenTreeIter::Fallback(tts.into_iter()),
+ }
+ }
+}
+
+impl Iterator for TokenTreeIter {
+ type Item = TokenTree;
+
+ fn next(&mut self) -> Option<TokenTree> {
+ let token = match self {
+ TokenTreeIter::Compiler(iter) => iter.next()?,
+ TokenTreeIter::Fallback(iter) => return iter.next(),
+ };
+ Some(match token {
+ proc_macro::TokenTree::Group(tt) => {
+ TokenTree::Group(crate::Group::_new(Group::Compiler(tt)))
+ }
+ proc_macro::TokenTree::Punct(tt) => {
+ let spacing = match tt.spacing() {
+ proc_macro::Spacing::Joint => Spacing::Joint,
+ proc_macro::Spacing::Alone => Spacing::Alone,
+ };
+ let mut o = Punct::new(tt.as_char(), spacing);
+ o.set_span(crate::Span::_new(Span::Compiler(tt.span())));
+ TokenTree::Punct(o)
+ }
+ proc_macro::TokenTree::Ident(s) => {
+ TokenTree::Ident(crate::Ident::_new(Ident::Compiler(s)))
+ }
+ proc_macro::TokenTree::Literal(l) => {
+ TokenTree::Literal(crate::Literal::_new(Literal::Compiler(l)))
+ }
+ })
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ match self {
+ TokenTreeIter::Compiler(tts) => tts.size_hint(),
+ TokenTreeIter::Fallback(tts) => tts.size_hint(),
+ }
+ }
+}
+
+#[derive(Copy, Clone)]
+pub(crate) enum Span {
+ Compiler(proc_macro::Span),
+ Fallback(fallback::Span),
+}
+
+impl Span {
+ pub(crate) fn call_site() -> Self {
+ if inside_proc_macro() {
+ Span::Compiler(proc_macro::Span::call_site())
+ } else {
+ Span::Fallback(fallback::Span::call_site())
+ }
+ }
+
+ pub(crate) fn mixed_site() -> Self {
+ if inside_proc_macro() {
+ Span::Compiler(proc_macro::Span::mixed_site())
+ } else {
+ Span::Fallback(fallback::Span::mixed_site())
+ }
+ }
+
+ #[cfg(super_unstable)]
+ pub(crate) fn def_site() -> Self {
+ if inside_proc_macro() {
+ Span::Compiler(proc_macro::Span::def_site())
+ } else {
+ Span::Fallback(fallback::Span::def_site())
+ }
+ }
+
+ pub(crate) fn resolved_at(&self, other: Span) -> Span {
+ match (self, other) {
+ (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.resolved_at(b)),
+ (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.resolved_at(b)),
+ (Span::Compiler(_), Span::Fallback(_)) => mismatch(line!()),
+ (Span::Fallback(_), Span::Compiler(_)) => mismatch(line!()),
+ }
+ }
+
+ pub(crate) fn located_at(&self, other: Span) -> Span {
+ match (self, other) {
+ (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.located_at(b)),
+ (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.located_at(b)),
+ (Span::Compiler(_), Span::Fallback(_)) => mismatch(line!()),
+ (Span::Fallback(_), Span::Compiler(_)) => mismatch(line!()),
+ }
+ }
+
+ pub(crate) fn unwrap(self) -> proc_macro::Span {
+ match self {
+ Span::Compiler(s) => s,
+ Span::Fallback(_) => panic!("proc_macro::Span is only available in procedural macros"),
+ }
+ }
+
+ #[cfg(span_locations)]
+ pub(crate) fn byte_range(&self) -> Range<usize> {
+ match self {
+ #[cfg(proc_macro_span)]
+ Span::Compiler(s) => proc_macro_span::byte_range(s),
+ #[cfg(not(proc_macro_span))]
+ Span::Compiler(_) => 0..0,
+ Span::Fallback(s) => s.byte_range(),
+ }
+ }
+
+ #[cfg(span_locations)]
+ pub(crate) fn start(&self) -> LineColumn {
+ match self {
+ #[cfg(proc_macro_span_location)]
+ Span::Compiler(s) => LineColumn {
+ line: proc_macro_span_location::line(s),
+ column: proc_macro_span_location::column(s).saturating_sub(1),
+ },
+ #[cfg(not(proc_macro_span_location))]
+ Span::Compiler(_) => LineColumn { line: 0, column: 0 },
+ Span::Fallback(s) => s.start(),
+ }
+ }
+
+ #[cfg(span_locations)]
+ pub(crate) fn end(&self) -> LineColumn {
+ match self {
+ #[cfg(proc_macro_span_location)]
+ Span::Compiler(s) => {
+ let end = proc_macro_span_location::end(s);
+ LineColumn {
+ line: proc_macro_span_location::line(&end),
+ column: proc_macro_span_location::column(&end).saturating_sub(1),
+ }
+ }
+ #[cfg(not(proc_macro_span_location))]
+ Span::Compiler(_) => LineColumn { line: 0, column: 0 },
+ Span::Fallback(s) => s.end(),
+ }
+ }
+
+ #[cfg(span_locations)]
+ pub(crate) fn file(&self) -> String {
+ match self {
+ #[cfg(proc_macro_span_file)]
+ Span::Compiler(s) => proc_macro_span_file::file(s),
+ #[cfg(not(proc_macro_span_file))]
+ Span::Compiler(_) => "<token stream>".to_owned(),
+ Span::Fallback(s) => s.file(),
+ }
+ }
+
+ #[cfg(span_locations)]
+ pub(crate) fn local_file(&self) -> Option<PathBuf> {
+ match self {
+ #[cfg(proc_macro_span_file)]
+ Span::Compiler(s) => proc_macro_span_file::local_file(s),
+ #[cfg(not(proc_macro_span_file))]
+ Span::Compiler(_) => None,
+ Span::Fallback(s) => s.local_file(),
+ }
+ }
+
+ pub(crate) fn join(&self, other: Span) -> Option<Span> {
+ let ret = match (self, other) {
+ #[cfg(proc_macro_span)]
+ (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(proc_macro_span::join(a, b)?),
+ (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.join(b)?),
+ _ => return None,
+ };
+ Some(ret)
+ }
+
+ #[cfg(super_unstable)]
+ pub(crate) fn eq(&self, other: &Span) -> bool {
+ match (self, other) {
+ (Span::Compiler(a), Span::Compiler(b)) => a.eq(b),
+ (Span::Fallback(a), Span::Fallback(b)) => a.eq(b),
+ _ => false,
+ }
+ }
+
+ pub(crate) fn source_text(&self) -> Option<String> {
+ match self {
+ #[cfg(not(no_source_text))]
+ Span::Compiler(s) => s.source_text(),
+ #[cfg(no_source_text)]
+ Span::Compiler(_) => None,
+ Span::Fallback(s) => s.source_text(),
+ }
+ }
+
+ fn unwrap_nightly(self) -> proc_macro::Span {
+ match self {
+ Span::Compiler(s) => s,
+ Span::Fallback(_) => mismatch(line!()),
+ }
+ }
+}
+
+impl From<proc_macro::Span> for crate::Span {
+ fn from(proc_span: proc_macro::Span) -> Self {
+ crate::Span::_new(Span::Compiler(proc_span))
+ }
+}
+
+impl From<fallback::Span> for Span {
+ fn from(inner: fallback::Span) -> Self {
+ Span::Fallback(inner)
+ }
+}
+
+impl Debug for Span {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ Span::Compiler(s) => Debug::fmt(s, f),
+ Span::Fallback(s) => Debug::fmt(s, f),
+ }
+ }
+}
+
+pub(crate) fn debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span) {
+ match span {
+ Span::Compiler(s) => {
+ debug.field("span", &s);
+ }
+ Span::Fallback(s) => fallback::debug_span_field_if_nontrivial(debug, s),
+ }
+}
+
+#[derive(Clone)]
+pub(crate) enum Group {
+ Compiler(proc_macro::Group),
+ Fallback(fallback::Group),
+}
+
+impl Group {
+ pub(crate) fn new(delimiter: Delimiter, stream: TokenStream) -> Self {
+ match stream {
+ TokenStream::Compiler(tts) => {
+ let delimiter = match delimiter {
+ Delimiter::Parenthesis => proc_macro::Delimiter::Parenthesis,
+ Delimiter::Bracket => proc_macro::Delimiter::Bracket,
+ Delimiter::Brace => proc_macro::Delimiter::Brace,
+ Delimiter::None => proc_macro::Delimiter::None,
+ };
+ Group::Compiler(proc_macro::Group::new(delimiter, tts.into_token_stream()))
+ }
+ TokenStream::Fallback(stream) => {
+ Group::Fallback(fallback::Group::new(delimiter, stream))
+ }
+ }
+ }
+
+ pub(crate) fn delimiter(&self) -> Delimiter {
+ match self {
+ Group::Compiler(g) => match g.delimiter() {
+ proc_macro::Delimiter::Parenthesis => Delimiter::Parenthesis,
+ proc_macro::Delimiter::Bracket => Delimiter::Bracket,
+ proc_macro::Delimiter::Brace => Delimiter::Brace,
+ proc_macro::Delimiter::None => Delimiter::None,
+ },
+ Group::Fallback(g) => g.delimiter(),
+ }
+ }
+
+ pub(crate) fn stream(&self) -> TokenStream {
+ match self {
+ Group::Compiler(g) => TokenStream::Compiler(DeferredTokenStream::new(g.stream())),
+ Group::Fallback(g) => TokenStream::Fallback(g.stream()),
+ }
+ }
+
+ pub(crate) fn span(&self) -> Span {
+ match self {
+ Group::Compiler(g) => Span::Compiler(g.span()),
+ Group::Fallback(g) => Span::Fallback(g.span()),
+ }
+ }
+
+ pub(crate) fn span_open(&self) -> Span {
+ match self {
+ Group::Compiler(g) => Span::Compiler(g.span_open()),
+ Group::Fallback(g) => Span::Fallback(g.span_open()),
+ }
+ }
+
+ pub(crate) fn span_close(&self) -> Span {
+ match self {
+ Group::Compiler(g) => Span::Compiler(g.span_close()),
+ Group::Fallback(g) => Span::Fallback(g.span_close()),
+ }
+ }
+
+ pub(crate) fn set_span(&mut self, span: Span) {
+ match (self, span) {
+ (Group::Compiler(g), Span::Compiler(s)) => g.set_span(s),
+ (Group::Fallback(g), Span::Fallback(s)) => g.set_span(s),
+ (Group::Compiler(_), Span::Fallback(_)) => mismatch(line!()),
+ (Group::Fallback(_), Span::Compiler(_)) => mismatch(line!()),
+ }
+ }
+
+ fn unwrap_nightly(self) -> proc_macro::Group {
+ match self {
+ Group::Compiler(g) => g,
+ Group::Fallback(_) => mismatch(line!()),
+ }
+ }
+}
+
+impl From<fallback::Group> for Group {
+ fn from(g: fallback::Group) -> Self {
+ Group::Fallback(g)
+ }
+}
+
+impl Display for Group {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ Group::Compiler(group) => Display::fmt(group, formatter),
+ Group::Fallback(group) => Display::fmt(group, formatter),
+ }
+ }
+}
+
+impl Debug for Group {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ Group::Compiler(group) => Debug::fmt(group, formatter),
+ Group::Fallback(group) => Debug::fmt(group, formatter),
+ }
+ }
+}
+
+#[derive(Clone)]
+pub(crate) enum Ident {
+ Compiler(proc_macro::Ident),
+ Fallback(fallback::Ident),
+}
+
+impl Ident {
+ #[track_caller]
+ pub(crate) fn new_checked(string: &str, span: Span) -> Self {
+ match span {
+ Span::Compiler(s) => Ident::Compiler(proc_macro::Ident::new(string, s)),
+ Span::Fallback(s) => Ident::Fallback(fallback::Ident::new_checked(string, s)),
+ }
+ }
+
+ #[track_caller]
+ pub(crate) fn new_raw_checked(string: &str, span: Span) -> Self {
+ match span {
+ Span::Compiler(s) => Ident::Compiler(proc_macro::Ident::new_raw(string, s)),
+ Span::Fallback(s) => Ident::Fallback(fallback::Ident::new_raw_checked(string, s)),
+ }
+ }
+
+ pub(crate) fn span(&self) -> Span {
+ match self {
+ Ident::Compiler(t) => Span::Compiler(t.span()),
+ Ident::Fallback(t) => Span::Fallback(t.span()),
+ }
+ }
+
+ pub(crate) fn set_span(&mut self, span: Span) {
+ match (self, span) {
+ (Ident::Compiler(t), Span::Compiler(s)) => t.set_span(s),
+ (Ident::Fallback(t), Span::Fallback(s)) => t.set_span(s),
+ (Ident::Compiler(_), Span::Fallback(_)) => mismatch(line!()),
+ (Ident::Fallback(_), Span::Compiler(_)) => mismatch(line!()),
+ }
+ }
+
+ fn unwrap_nightly(self) -> proc_macro::Ident {
+ match self {
+ Ident::Compiler(s) => s,
+ Ident::Fallback(_) => mismatch(line!()),
+ }
+ }
+}
+
+impl From<fallback::Ident> for Ident {
+ fn from(inner: fallback::Ident) -> Self {
+ Ident::Fallback(inner)
+ }
+}
+
+impl PartialEq for Ident {
+ fn eq(&self, other: &Ident) -> bool {
+ match (self, other) {
+ (Ident::Compiler(t), Ident::Compiler(o)) => t.to_string() == o.to_string(),
+ (Ident::Fallback(t), Ident::Fallback(o)) => t == o,
+ (Ident::Compiler(_), Ident::Fallback(_)) => mismatch(line!()),
+ (Ident::Fallback(_), Ident::Compiler(_)) => mismatch(line!()),
+ }
+ }
+}
+
+impl<T> PartialEq<T> for Ident
+where
+ T: ?Sized + AsRef<str>,
+{
+ fn eq(&self, other: &T) -> bool {
+ let other = other.as_ref();
+ match self {
+ Ident::Compiler(t) => t.to_string() == other,
+ Ident::Fallback(t) => t == other,
+ }
+ }
+}
+
+impl Display for Ident {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ Ident::Compiler(t) => Display::fmt(t, f),
+ Ident::Fallback(t) => Display::fmt(t, f),
+ }
+ }
+}
+
+impl Debug for Ident {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ Ident::Compiler(t) => Debug::fmt(t, f),
+ Ident::Fallback(t) => Debug::fmt(t, f),
+ }
+ }
+}
+
+#[derive(Clone)]
+pub(crate) enum Literal {
+ Compiler(proc_macro::Literal),
+ Fallback(fallback::Literal),
+}
+
+macro_rules! suffixed_numbers {
+ ($($name:ident => $kind:ident,)*) => ($(
+ pub(crate) fn $name(n: $kind) -> Literal {
+ if inside_proc_macro() {
+ Literal::Compiler(proc_macro::Literal::$name(n))
+ } else {
+ Literal::Fallback(fallback::Literal::$name(n))
+ }
+ }
+ )*)
+}
+
+macro_rules! unsuffixed_integers {
+ ($($name:ident => $kind:ident,)*) => ($(
+ pub(crate) fn $name(n: $kind) -> Literal {
+ if inside_proc_macro() {
+ Literal::Compiler(proc_macro::Literal::$name(n))
+ } else {
+ Literal::Fallback(fallback::Literal::$name(n))
+ }
+ }
+ )*)
+}
+
+impl Literal {
+ pub(crate) fn from_str_checked(repr: &str) -> Result<Self, LexError> {
+ if inside_proc_macro() {
+ let literal = proc_macro::Literal::from_str_checked(repr)?;
+ Ok(Literal::Compiler(literal))
+ } else {
+ let literal = fallback::Literal::from_str_checked(repr)?;
+ Ok(Literal::Fallback(literal))
+ }
+ }
+
+ pub(crate) unsafe fn from_str_unchecked(repr: &str) -> Self {
+ if inside_proc_macro() {
+ Literal::Compiler(proc_macro::Literal::from_str_unchecked(repr))
+ } else {
+ Literal::Fallback(unsafe { fallback::Literal::from_str_unchecked(repr) })
+ }
+ }
+
+ suffixed_numbers! {
+ u8_suffixed => u8,
+ u16_suffixed => u16,
+ u32_suffixed => u32,
+ u64_suffixed => u64,
+ u128_suffixed => u128,
+ usize_suffixed => usize,
+ i8_suffixed => i8,
+ i16_suffixed => i16,
+ i32_suffixed => i32,
+ i64_suffixed => i64,
+ i128_suffixed => i128,
+ isize_suffixed => isize,
+
+ f32_suffixed => f32,
+ f64_suffixed => f64,
+ }
+
+ unsuffixed_integers! {
+ u8_unsuffixed => u8,
+ u16_unsuffixed => u16,
+ u32_unsuffixed => u32,
+ u64_unsuffixed => u64,
+ u128_unsuffixed => u128,
+ usize_unsuffixed => usize,
+ i8_unsuffixed => i8,
+ i16_unsuffixed => i16,
+ i32_unsuffixed => i32,
+ i64_unsuffixed => i64,
+ i128_unsuffixed => i128,
+ isize_unsuffixed => isize,
+ }
+
+ pub(crate) fn f32_unsuffixed(f: f32) -> Literal {
+ if inside_proc_macro() {
+ Literal::Compiler(proc_macro::Literal::f32_unsuffixed(f))
+ } else {
+ Literal::Fallback(fallback::Literal::f32_unsuffixed(f))
+ }
+ }
+
+ pub(crate) fn f64_unsuffixed(f: f64) -> Literal {
+ if inside_proc_macro() {
+ Literal::Compiler(proc_macro::Literal::f64_unsuffixed(f))
+ } else {
+ Literal::Fallback(fallback::Literal::f64_unsuffixed(f))
+ }
+ }
+
+ pub(crate) fn string(string: &str) -> Literal {
+ if inside_proc_macro() {
+ Literal::Compiler(proc_macro::Literal::string(string))
+ } else {
+ Literal::Fallback(fallback::Literal::string(string))
+ }
+ }
+
+ pub(crate) fn character(ch: char) -> Literal {
+ if inside_proc_macro() {
+ Literal::Compiler(proc_macro::Literal::character(ch))
+ } else {
+ Literal::Fallback(fallback::Literal::character(ch))
+ }
+ }
+
+ pub(crate) fn byte_character(byte: u8) -> Literal {
+ if inside_proc_macro() {
+ Literal::Compiler({
+ #[cfg(not(no_literal_byte_character))]
+ {
+ proc_macro::Literal::byte_character(byte)
+ }
+
+ #[cfg(no_literal_byte_character)]
+ {
+ let fallback = fallback::Literal::byte_character(byte);
+ proc_macro::Literal::from_str_unchecked(&fallback.repr)
+ }
+ })
+ } else {
+ Literal::Fallback(fallback::Literal::byte_character(byte))
+ }
+ }
+
+ pub(crate) fn byte_string(bytes: &[u8]) -> Literal {
+ if inside_proc_macro() {
+ Literal::Compiler(proc_macro::Literal::byte_string(bytes))
+ } else {
+ Literal::Fallback(fallback::Literal::byte_string(bytes))
+ }
+ }
+
+ pub(crate) fn c_string(string: &CStr) -> Literal {
+ if inside_proc_macro() {
+ Literal::Compiler({
+ #[cfg(not(no_literal_c_string))]
+ {
+ proc_macro::Literal::c_string(string)
+ }
+
+ #[cfg(no_literal_c_string)]
+ {
+ let fallback = fallback::Literal::c_string(string);
+ proc_macro::Literal::from_str_unchecked(&fallback.repr)
+ }
+ })
+ } else {
+ Literal::Fallback(fallback::Literal::c_string(string))
+ }
+ }
+
+ pub(crate) fn span(&self) -> Span {
+ match self {
+ Literal::Compiler(lit) => Span::Compiler(lit.span()),
+ Literal::Fallback(lit) => Span::Fallback(lit.span()),
+ }
+ }
+
+ pub(crate) fn set_span(&mut self, span: Span) {
+ match (self, span) {
+ (Literal::Compiler(lit), Span::Compiler(s)) => lit.set_span(s),
+ (Literal::Fallback(lit), Span::Fallback(s)) => lit.set_span(s),
+ (Literal::Compiler(_), Span::Fallback(_)) => mismatch(line!()),
+ (Literal::Fallback(_), Span::Compiler(_)) => mismatch(line!()),
+ }
+ }
+
+ pub(crate) fn subspan<R: RangeBounds<usize>>(&self, range: R) -> Option<Span> {
+ match self {
+ #[cfg(proc_macro_span)]
+ Literal::Compiler(lit) => proc_macro_span::subspan(lit, range).map(Span::Compiler),
+ #[cfg(not(proc_macro_span))]
+ Literal::Compiler(_lit) => None,
+ Literal::Fallback(lit) => lit.subspan(range).map(Span::Fallback),
+ }
+ }
+
+ fn unwrap_nightly(self) -> proc_macro::Literal {
+ match self {
+ Literal::Compiler(s) => s,
+ Literal::Fallback(_) => mismatch(line!()),
+ }
+ }
+}
+
+impl From<fallback::Literal> for Literal {
+ fn from(s: fallback::Literal) -> Self {
+ Literal::Fallback(s)
+ }
+}
+
+impl Display for Literal {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ Literal::Compiler(t) => Display::fmt(t, f),
+ Literal::Fallback(t) => Display::fmt(t, f),
+ }
+ }
+}
+
+impl Debug for Literal {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ Literal::Compiler(t) => Debug::fmt(t, f),
+ Literal::Fallback(t) => Debug::fmt(t, f),
+ }
+ }
+}
+
+#[cfg(span_locations)]
+pub(crate) fn invalidate_current_thread_spans() {
+ if inside_proc_macro() {
+ panic!(
+ "proc_macro2::extra::invalidate_current_thread_spans is not available in procedural macros"
+ );
+ } else {
+ crate::fallback::invalidate_current_thread_spans();
+ }
+}
--
2.51.2
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH 06/18] rust: proc-macro2: add SPDX License Identifiers
2025-11-10 9:50 [PATCH 00/18] `syn` support Miguel Ojeda
` (4 preceding siblings ...)
2025-11-10 9:50 ` [PATCH 05/18] rust: proc-macro2: import crate Miguel Ojeda
@ 2025-11-10 9:50 ` Miguel Ojeda
2025-11-10 9:50 ` [PATCH 07/18] rust: proc-macro2: remove `unicode_ident` dependency Miguel Ojeda
` (13 subsequent siblings)
19 siblings, 0 replies; 57+ messages in thread
From: Miguel Ojeda @ 2025-11-10 9:50 UTC (permalink / raw)
To: Miguel Ojeda, Alex Gaynor, Nathan Chancellor, Nicolas Schier
Cc: Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
rust-for-linux, linux-kbuild, linux-kernel, patches
Originally, 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.
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
---
rust/proc-macro2/detection.rs | 2 ++
| 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(+)
diff --git a/rust/proc-macro2/detection.rs b/rust/proc-macro2/detection.rs
index beba7b237395..3de448cb2dde 100644
--- a/rust/proc-macro2/detection.rs
+++ b/rust/proc-macro2/detection.rs
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
use core::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Once;
--git a/rust/proc-macro2/extra.rs b/rust/proc-macro2/extra.rs
index 522a90e136be..55feb5ec7526 100644
--- a/rust/proc-macro2/extra.rs
+++ b/rust/proc-macro2/extra.rs
@@ -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.
diff --git a/rust/proc-macro2/fallback.rs b/rust/proc-macro2/fallback.rs
index 1560105cfd25..9e005d67f7f5 100644
--- a/rust/proc-macro2/fallback.rs
+++ b/rust/proc-macro2/fallback.rs
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
#[cfg(wrap_proc_macro)]
use crate::imp;
#[cfg(span_locations)]
diff --git a/rust/proc-macro2/lib.rs b/rust/proc-macro2/lib.rs
index 2984af335adc..7b78d065d51c 100644
--- a/rust/proc-macro2/lib.rs
+++ b/rust/proc-macro2/lib.rs
@@ -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
diff --git a/rust/proc-macro2/location.rs b/rust/proc-macro2/location.rs
index 7190e2d05255..3a11871e2943 100644
--- a/rust/proc-macro2/location.rs
+++ b/rust/proc-macro2/location.rs
@@ -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`.
diff --git a/rust/proc-macro2/marker.rs b/rust/proc-macro2/marker.rs
index 23b94ce6fa85..6f322424808c 100644
--- a/rust/proc-macro2/marker.rs
+++ b/rust/proc-macro2/marker.rs
@@ -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};
diff --git a/rust/proc-macro2/parse.rs b/rust/proc-macro2/parse.rs
index b8be403f842f..a005dea1fe88 100644
--- a/rust/proc-macro2/parse.rs
+++ b/rust/proc-macro2/parse.rs
@@ -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,
diff --git a/rust/proc-macro2/probe.rs b/rust/proc-macro2/probe.rs
index b67f52036218..d68aa8cfd85e 100644
--- a/rust/proc-macro2/probe.rs
+++ b/rust/proc-macro2/probe.rs
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
#![allow(dead_code)]
#[cfg(proc_macro_span)]
diff --git a/rust/proc-macro2/probe/proc_macro_span.rs b/rust/proc-macro2/probe/proc_macro_span.rs
index 2d7d44e07708..892a7eb3e5a0 100644
--- a/rust/proc-macro2/probe/proc_macro_span.rs
+++ b/rust/proc-macro2/probe/proc_macro_span.rs
@@ -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.
diff --git a/rust/proc-macro2/probe/proc_macro_span_file.rs b/rust/proc-macro2/probe/proc_macro_span_file.rs
index 8b76bdf5007b..f2dbc4056ebe 100644
--- a/rust/proc-macro2/probe/proc_macro_span_file.rs
+++ b/rust/proc-macro2/probe/proc_macro_span_file.rs
@@ -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;
diff --git a/rust/proc-macro2/probe/proc_macro_span_location.rs b/rust/proc-macro2/probe/proc_macro_span_location.rs
index 79da34af54af..ae19c93394fa 100644
--- a/rust/proc-macro2/probe/proc_macro_span_location.rs
+++ b/rust/proc-macro2/probe/proc_macro_span_location.rs
@@ -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;
diff --git a/rust/proc-macro2/rcvec.rs b/rust/proc-macro2/rcvec.rs
index 23edc77d597f..e224ebe277ef 100644
--- a/rust/proc-macro2/rcvec.rs
+++ b/rust/proc-macro2/rcvec.rs
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
use alloc::rc::Rc;
use alloc::vec;
use core::mem;
diff --git a/rust/proc-macro2/wrapper.rs b/rust/proc-macro2/wrapper.rs
index 2e3eb5b4d04e..6792e9834111 100644
--- a/rust/proc-macro2/wrapper.rs
+++ b/rust/proc-macro2/wrapper.rs
@@ -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)]
--
2.51.2
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH 07/18] rust: proc-macro2: remove `unicode_ident` dependency
2025-11-10 9:50 [PATCH 00/18] `syn` support Miguel Ojeda
` (5 preceding siblings ...)
2025-11-10 9:50 ` [PATCH 06/18] rust: proc-macro2: add SPDX License Identifiers Miguel Ojeda
@ 2025-11-10 9:50 ` Miguel Ojeda
2025-11-10 10:50 ` Alice Ryhl
2025-11-10 9:50 ` [PATCH 08/18] rust: proc-macro2: add `README.md` Miguel Ojeda
` (12 subsequent siblings)
19 siblings, 1 reply; 57+ messages in thread
From: Miguel Ojeda @ 2025-11-10 9:50 UTC (permalink / raw)
To: Miguel Ojeda, Alex Gaynor, Nathan Chancellor, Nicolas Schier
Cc: Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
rust-for-linux, linux-kbuild, linux-kernel, patches
The `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.
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
---
rust/proc-macro2/fallback.rs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/rust/proc-macro2/fallback.rs b/rust/proc-macro2/fallback.rs
index 9e005d67f7f5..9b43c97df97a 100644
--- a/rust/proc-macro2/fallback.rs
+++ b/rust/proc-macro2/fallback.rs
@@ -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]
--
2.51.2
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH 08/18] rust: proc-macro2: add `README.md`
2025-11-10 9:50 [PATCH 00/18] `syn` support Miguel Ojeda
` (6 preceding siblings ...)
2025-11-10 9:50 ` [PATCH 07/18] rust: proc-macro2: remove `unicode_ident` dependency Miguel Ojeda
@ 2025-11-10 9:50 ` Miguel Ojeda
2025-11-10 10:52 ` Alice Ryhl
2025-11-10 9:50 ` [PATCH 09/18] rust: proc-macro2: enable support in kbuild Miguel Ojeda
` (11 subsequent siblings)
19 siblings, 1 reply; 57+ messages in thread
From: Miguel Ojeda @ 2025-11-10 9:50 UTC (permalink / raw)
To: Miguel Ojeda, Alex Gaynor, Nathan Chancellor, Nicolas Schier
Cc: Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
rust-for-linux, linux-kbuild, linux-kernel, patches
Originally, 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.
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
---
rust/proc-macro2/README.md | 13 +++++++++++++
1 file changed, 13 insertions(+)
create mode 100644 rust/proc-macro2/README.md
diff --git a/rust/proc-macro2/README.md b/rust/proc-macro2/README.md
new file mode 100644
index 000000000000..af044fee4f59
--- /dev/null
+++ b/rust/proc-macro2/README.md
@@ -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
--
2.51.2
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH 09/18] rust: proc-macro2: enable support in kbuild
2025-11-10 9:50 [PATCH 00/18] `syn` support Miguel Ojeda
` (7 preceding siblings ...)
2025-11-10 9:50 ` [PATCH 08/18] rust: proc-macro2: add `README.md` Miguel Ojeda
@ 2025-11-10 9:50 ` Miguel Ojeda
2025-11-10 11:38 ` Alice Ryhl
2025-11-10 19:34 ` John Hubbard
2025-11-10 9:50 ` [PATCH 10/18] rust: quote: import crate Miguel Ojeda
` (10 subsequent siblings)
19 siblings, 2 replies; 57+ messages in thread
From: Miguel Ojeda @ 2025-11-10 9:50 UTC (permalink / raw)
To: Miguel Ojeda, Alex Gaynor, Nathan Chancellor, Nicolas Schier
Cc: Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
rust-for-linux, linux-kbuild, linux-kernel, patches
With 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.
Link: https://github.com/rust-lang/rust/pull/123431 [1]
Link: https://github.com/rust-lang/rust/pull/112711 [2]
Link: https://github.com/rust-lang/rust/pull/119651 [3]
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
---
Makefile | 3 +++
rust/Makefile | 32 +++++++++++++++++++++++++++++--
scripts/generate_rust_analyzer.py | 7 +++++++
3 files changed, 40 insertions(+), 2 deletions(-)
diff --git a/Makefile b/Makefile
index fb4389aa5d5f..6ff887523eee 100644
--- a/Makefile
+++ b/Makefile
@@ -1830,6 +1830,9 @@ 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)
diff --git a/rust/Makefile b/rust/Makefile
index 9eea6563ef35..a614a23023cb 100644
--- a/rust/Makefile
+++ b/rust/Makefile
@@ -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)
@@ -128,10 +141,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
@@ -194,6 +212,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
@@ -440,6 +462,11 @@ quiet_cmd_rustc_hostlibrary = $(RUSTC_OR_CLIPPY_QUIET) H $@
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_hostlibrary)
+
quiet_cmd_rustc_procmacro = $(RUSTC_OR_CLIPPY_QUIET) P $@
cmd_rustc_procmacro = \
$(RUSTC_OR_CLIPPY) $(rust_common_flags) $(rustc_target_flags) \
@@ -451,7 +478,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
@@ -474,6 +501,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
diff --git a/scripts/generate_rust_analyzer.py b/scripts/generate_rust_analyzer.py
index dedca470adc1..00c6b7cc94b7 100755
--- a/scripts/generate_rust_analyzer.py
+++ b/scripts/generate_rust_analyzer.py
@@ -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",
--
2.51.2
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH 10/18] rust: quote: import crate
2025-11-10 9:50 [PATCH 00/18] `syn` support Miguel Ojeda
` (8 preceding siblings ...)
2025-11-10 9:50 ` [PATCH 09/18] rust: proc-macro2: enable support in kbuild Miguel Ojeda
@ 2025-11-10 9:50 ` Miguel Ojeda
2025-11-10 9:50 ` [PATCH 11/18] rust: quote: add SPDX License Identifiers Miguel Ojeda
` (9 subsequent siblings)
19 siblings, 0 replies; 57+ messages in thread
From: Miguel Ojeda @ 2025-11-10 9:50 UTC (permalink / raw)
To: Miguel Ojeda, Alex Gaynor, Nathan Chancellor, Nicolas Schier
Cc: Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
rust-for-linux, linux-kbuild, linux-kernel, patches
This 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
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
---
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
diff --git a/rust/quote/ext.rs b/rust/quote/ext.rs
new file mode 100644
index 000000000000..92c2315b182d
--- /dev/null
+++ b/rust/quote/ext.rs
@@ -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 token in 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 token in iter {
+ token.to_tokens(self);
+ term.to_tokens(self);
+ }
+ }
+}
+
+mod private {
+ use proc_macro2::TokenStream;
+
+ pub trait Sealed {}
+
+ impl Sealed for TokenStream {}
+}
diff --git a/rust/quote/format.rs b/rust/quote/format.rs
new file mode 100644
index 000000000000..ec0bbf38ba37
--- /dev/null
+++ b/rust/quote/format.rs
@@ -0,0 +1,168 @@
+/// Formatting macro for constructing `Ident`s.
+///
+/// <br>
+///
+/// # Syntax
+///
+/// Syntax is copied from the [`format!`] macro, supporting both positional and
+/// named arguments.
+///
+/// Only a limited set of formatting traits are supported. The current mapping
+/// of format types to traits is:
+///
+/// * `{}` ⇒ [`IdentFragment`]
+/// * `{:o}` ⇒ [`Octal`](std::fmt::Octal)
+/// * `{:x}` ⇒ [`LowerHex`](std::fmt::LowerHex)
+/// * `{:X}` ⇒ [`UpperHex`](std::fmt::UpperHex)
+/// * `{:b}` ⇒ [`Binary`](std::fmt::Binary)
+///
+/// See [`std::fmt`] for more information.
+///
+/// <br>
+///
+/// # IdentFragment
+///
+/// Unlike `format!`, this macro uses the [`IdentFragment`] formatting trait by
+/// default. This trait is like `Display`, with a few differences:
+///
+/// * `IdentFragment` is only implemented for a limited set of types, such as
+/// unsigned integers and strings.
+/// * [`Ident`] arguments will have their `r#` prefixes stripped, if present.
+///
+/// [`IdentFragment`]: crate::IdentFragment
+/// [`Ident`]: proc_macro2::Ident
+///
+/// <br>
+///
+/// # Hygiene
+///
+/// The [`Span`] of the first `Ident` argument is used as the span of the final
+/// identifier, falling back to [`Span::call_site`] when no identifiers are
+/// provided.
+///
+/// ```
+/// # use quote::format_ident;
+/// # let ident = format_ident!("Ident");
+/// // If `ident` is an Ident, the span of `my_ident` will be inherited from it.
+/// let my_ident = format_ident!("My{}{}", ident, "IsCool");
+/// assert_eq!(my_ident, "MyIdentIsCool");
+/// ```
+///
+/// Alternatively, the span can be overridden by passing the `span` named
+/// argument.
+///
+/// ```
+/// # use quote::format_ident;
+/// # const IGNORE_TOKENS: &'static str = stringify! {
+/// let my_span = /* ... */;
+/// # };
+/// # let my_span = proc_macro2::Span::call_site();
+/// format_ident!("MyIdent", span = my_span);
+/// ```
+///
+/// [`Span`]: proc_macro2::Span
+/// [`Span::call_site`]: proc_macro2::Span::call_site
+///
+/// <p><br></p>
+///
+/// # Panics
+///
+/// This method will panic if the resulting formatted string is not a valid
+/// identifier.
+///
+/// <br>
+///
+/// # Examples
+///
+/// Composing raw and non-raw identifiers:
+/// ```
+/// # use quote::format_ident;
+/// let my_ident = format_ident!("My{}", "Ident");
+/// assert_eq!(my_ident, "MyIdent");
+///
+/// let raw = format_ident!("r#Raw");
+/// assert_eq!(raw, "r#Raw");
+///
+/// let my_ident_raw = format_ident!("{}Is{}", my_ident, raw);
+/// assert_eq!(my_ident_raw, "MyIdentIsRaw");
+/// ```
+///
+/// Integer formatting options:
+/// ```
+/// # use quote::format_ident;
+/// let num: u32 = 10;
+///
+/// let decimal = format_ident!("Id_{}", num);
+/// assert_eq!(decimal, "Id_10");
+///
+/// let octal = format_ident!("Id_{:o}", num);
+/// assert_eq!(octal, "Id_12");
+///
+/// let binary = format_ident!("Id_{:b}", num);
+/// assert_eq!(binary, "Id_1010");
+///
+/// let lower_hex = format_ident!("Id_{:x}", num);
+/// assert_eq!(lower_hex, "Id_a");
+///
+/// let upper_hex = format_ident!("Id_{:X}", num);
+/// assert_eq!(upper_hex, "Id_A");
+/// ```
+#[macro_export]
+macro_rules! format_ident {
+ ($fmt:expr) => {
+ $crate::format_ident_impl!([
+ $crate::__private::Option::None,
+ $fmt
+ ])
+ };
+
+ ($fmt:expr, $($rest:tt)*) => {
+ $crate::format_ident_impl!([
+ $crate::__private::Option::None,
+ $fmt
+ ] $($rest)*)
+ };
+}
+
+#[macro_export]
+#[doc(hidden)]
+macro_rules! format_ident_impl {
+ // Final state
+ ([$span:expr, $($fmt:tt)*]) => {
+ $crate::__private::mk_ident(
+ &$crate::__private::format!($($fmt)*),
+ $span,
+ )
+ };
+
+ // Span argument
+ ([$old:expr, $($fmt:tt)*] span = $span:expr) => {
+ $crate::format_ident_impl!([$old, $($fmt)*] span = $span,)
+ };
+ ([$old:expr, $($fmt:tt)*] span = $span:expr, $($rest:tt)*) => {
+ $crate::format_ident_impl!([
+ $crate::__private::Option::Some::<$crate::__private::Span>($span),
+ $($fmt)*
+ ] $($rest)*)
+ };
+
+ // Named argument
+ ([$span:expr, $($fmt:tt)*] $name:ident = $arg:expr) => {
+ $crate::format_ident_impl!([$span, $($fmt)*] $name = $arg,)
+ };
+ ([$span:expr, $($fmt:tt)*] $name:ident = $arg:expr, $($rest:tt)*) => {
+ match $crate::__private::IdentFragmentAdapter(&$arg) {
+ arg => $crate::format_ident_impl!([$span.or(arg.span()), $($fmt)*, $name = arg] $($rest)*),
+ }
+ };
+
+ // Positional argument
+ ([$span:expr, $($fmt:tt)*] $arg:expr) => {
+ $crate::format_ident_impl!([$span, $($fmt)*] $arg,)
+ };
+ ([$span:expr, $($fmt:tt)*] $arg:expr, $($rest:tt)*) => {
+ match $crate::__private::IdentFragmentAdapter(&$arg) {
+ arg => $crate::format_ident_impl!([$span.or(arg.span()), $($fmt)*, arg] $($rest)*),
+ }
+ };
+}
diff --git a/rust/quote/ident_fragment.rs b/rust/quote/ident_fragment.rs
new file mode 100644
index 000000000000..6c2a9a87acb4
--- /dev/null
+++ b/rust/quote/ident_fragment.rs
@@ -0,0 +1,88 @@
+use alloc::borrow::Cow;
+use core::fmt;
+use proc_macro2::{Ident, Span};
+
+/// Specialized formatting trait used by `format_ident!`.
+///
+/// [`Ident`] arguments formatted using this trait will have their `r#` prefix
+/// stripped, if present.
+///
+/// See [`format_ident!`] for more information.
+///
+/// [`format_ident!`]: crate::format_ident
+pub trait IdentFragment {
+ /// Format this value as an identifier fragment.
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result;
+
+ /// Span associated with this `IdentFragment`.
+ ///
+ /// If non-`None`, may be inherited by formatted identifiers.
+ fn span(&self) -> Option<Span> {
+ None
+ }
+}
+
+impl<T: IdentFragment + ?Sized> IdentFragment for &T {
+ fn span(&self) -> Option<Span> {
+ <T as IdentFragment>::span(*self)
+ }
+
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ IdentFragment::fmt(*self, f)
+ }
+}
+
+impl<T: IdentFragment + ?Sized> IdentFragment for &mut T {
+ fn span(&self) -> Option<Span> {
+ <T as IdentFragment>::span(*self)
+ }
+
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ IdentFragment::fmt(*self, f)
+ }
+}
+
+impl IdentFragment for Ident {
+ fn span(&self) -> Option<Span> {
+ Some(self.span())
+ }
+
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let id = self.to_string();
+ if let Some(id) = id.strip_prefix("r#") {
+ fmt::Display::fmt(id, f)
+ } else {
+ fmt::Display::fmt(&id[..], f)
+ }
+ }
+}
+
+impl<T> IdentFragment for Cow<'_, T>
+where
+ T: IdentFragment + ToOwned + ?Sized,
+{
+ fn span(&self) -> Option<Span> {
+ T::span(self)
+ }
+
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ T::fmt(self, f)
+ }
+}
+
+// Limited set of types which this is implemented for, as we want to avoid types
+// which will often include non-identifier characters in their `Display` impl.
+macro_rules! ident_fragment_display {
+ ($($T:ty),*) => {
+ $(
+ impl IdentFragment for $T {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Display::fmt(self, f)
+ }
+ }
+ )*
+ };
+}
+
+ident_fragment_display!(bool, str, String, char);
+ident_fragment_display!(u8, u16, u32, u64, u128, usize);
diff --git a/rust/quote/lib.rs b/rust/quote/lib.rs
new file mode 100644
index 000000000000..0a12d607f279
--- /dev/null
+++ b/rust/quote/lib.rs
@@ -0,0 +1,1454 @@
+//! [![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
+//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
+//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs
+//!
+//! <br>
+//!
+//! This crate provides the [`quote!`] macro for turning Rust syntax tree data
+//! structures into tokens of source code.
+//!
+//! Procedural macros in Rust receive a stream of tokens as input, execute
+//! arbitrary Rust code to determine how to manipulate those tokens, and produce
+//! a stream of tokens to hand back to the compiler to compile into the caller's
+//! crate. Quasi-quoting is a solution to one piece of that — producing
+//! tokens to return to the compiler.
+//!
+//! The idea of quasi-quoting is that we write *code* that we treat as *data*.
+//! Within the `quote!` macro, we can write what looks like code to our text
+//! editor or IDE. We get all the benefits of the editor's brace matching,
+//! syntax highlighting, indentation, and maybe autocompletion. But rather than
+//! compiling that as code into the current crate, we can treat it as data, pass
+//! it around, mutate it, and eventually hand it back to the compiler as tokens
+//! to compile into the macro caller's crate.
+//!
+//! This crate is motivated by the procedural macro use case, but is a
+//! general-purpose Rust quasi-quoting library and is not specific to procedural
+//! macros.
+//!
+//! ```toml
+//! [dependencies]
+//! quote = "1.0"
+//! ```
+//!
+//! <br>
+//!
+//! # Example
+//!
+//! The following quasi-quoted block of code is something you might find in [a]
+//! procedural macro having to do with data structure serialization. The `#var`
+//! syntax performs interpolation of runtime variables into the quoted tokens.
+//! Check out the documentation of the [`quote!`] macro for more detail about
+//! the syntax. See also the [`quote_spanned!`] macro which is important for
+//! implementing hygienic procedural macros.
+//!
+//! [a]: https://serde.rs/
+//!
+//! ```
+//! # use quote::quote;
+//! #
+//! # let generics = "";
+//! # let where_clause = "";
+//! # let field_ty = "";
+//! # let item_ty = "";
+//! # let path = "";
+//! # let value = "";
+//! #
+//! let tokens = quote! {
+//! struct SerializeWith #generics #where_clause {
+//! value: &'a #field_ty,
+//! phantom: core::marker::PhantomData<#item_ty>,
+//! }
+//!
+//! impl #generics serde::Serialize for SerializeWith #generics #where_clause {
+//! fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+//! where
+//! S: serde::Serializer,
+//! {
+//! #path(self.value, serializer)
+//! }
+//! }
+//!
+//! SerializeWith {
+//! value: #value,
+//! phantom: core::marker::PhantomData::<#item_ty>,
+//! }
+//! };
+//! ```
+//!
+//! <br>
+//!
+//! # Non-macro code generators
+//!
+//! When using `quote` in a build.rs or main.rs and writing the output out to a
+//! file, consider having the code generator pass the tokens through
+//! [prettyplease] before writing. This way if an error occurs in the generated
+//! code it is convenient for a human to read and debug.
+//!
+//! [prettyplease]: https://github.com/dtolnay/prettyplease
+
+// Quote types in rustdoc of other crates get linked to here.
+#![doc(html_root_url = "https://docs.rs/quote/1.0.40")]
+#![allow(
+ clippy::doc_markdown,
+ clippy::elidable_lifetime_names,
+ clippy::missing_errors_doc,
+ clippy::missing_panics_doc,
+ clippy::module_name_repetitions,
+ clippy::needless_lifetimes,
+ // false positive https://github.com/rust-lang/rust-clippy/issues/6983
+ clippy::wrong_self_convention,
+)]
+
+extern crate alloc;
+
+#[cfg(feature = "proc-macro")]
+extern crate proc_macro;
+
+mod ext;
+mod format;
+mod ident_fragment;
+mod to_tokens;
+
+// Not public API.
+#[doc(hidden)]
+#[path = "runtime.rs"]
+pub mod __private;
+
+pub use crate::ext::TokenStreamExt;
+pub use crate::ident_fragment::IdentFragment;
+pub use crate::to_tokens::ToTokens;
+
+// Not public API.
+#[doc(hidden)]
+pub mod spanned;
+
+macro_rules! __quote {
+ ($quote:item) => {
+ /// The whole point.
+ ///
+ /// Performs variable interpolation against the input and produces it as
+ /// [`proc_macro2::TokenStream`].
+ ///
+ /// Note: for returning tokens to the compiler in a procedural macro, use
+ /// `.into()` on the result to convert to [`proc_macro::TokenStream`].
+ ///
+ /// <br>
+ ///
+ /// # Interpolation
+ ///
+ /// Variable interpolation is done with `#var` (similar to `$var` in
+ /// `macro_rules!` macros). This grabs the `var` variable that is currently in
+ /// scope and inserts it in that location in the output tokens. Any type
+ /// implementing the [`ToTokens`] trait can be interpolated. This includes most
+ /// Rust primitive types as well as most of the syntax tree types from the [Syn]
+ /// crate.
+ ///
+ /// [Syn]: https://github.com/dtolnay/syn
+ ///
+ /// Repetition is done using `#(...)*` or `#(...),*` again similar to
+ /// `macro_rules!`. This iterates through the elements of any variable
+ /// interpolated within the repetition and inserts a copy of the repetition body
+ /// for each one. The variables in an interpolation may be a `Vec`, slice,
+ /// `BTreeSet`, or any `Iterator`.
+ ///
+ /// - `#(#var)*` — no separators
+ /// - `#(#var),*` — the character before the asterisk is used as a separator
+ /// - `#( struct #var; )*` — the repetition can contain other tokens
+ /// - `#( #k => println!("{}", #v), )*` — even multiple interpolations
+ ///
+ /// <br>
+ ///
+ /// # Hygiene
+ ///
+ /// Any interpolated tokens preserve the `Span` information provided by their
+ /// `ToTokens` implementation. Tokens that originate within the `quote!`
+ /// invocation are spanned with [`Span::call_site()`].
+ ///
+ /// [`Span::call_site()`]: proc_macro2::Span::call_site
+ ///
+ /// A different span can be provided through the [`quote_spanned!`] macro.
+ ///
+ /// <br>
+ ///
+ /// # Return type
+ ///
+ /// The macro evaluates to an expression of type `proc_macro2::TokenStream`.
+ /// Meanwhile Rust procedural macros are expected to return the type
+ /// `proc_macro::TokenStream`.
+ ///
+ /// The difference between the two types is that `proc_macro` types are entirely
+ /// specific to procedural macros and cannot ever exist in code outside of a
+ /// procedural macro, while `proc_macro2` types may exist anywhere including
+ /// tests and non-macro code like main.rs and build.rs. This is why even the
+ /// procedural macro ecosystem is largely built around `proc_macro2`, because
+ /// that ensures the libraries are unit testable and accessible in non-macro
+ /// contexts.
+ ///
+ /// There is a [`From`]-conversion in both directions so returning the output of
+ /// `quote!` from a procedural macro usually looks like `tokens.into()` or
+ /// `proc_macro::TokenStream::from(tokens)`.
+ ///
+ /// <br>
+ ///
+ /// # Examples
+ ///
+ /// ### Procedural macro
+ ///
+ /// The structure of a basic procedural macro is as follows. Refer to the [Syn]
+ /// crate for further useful guidance on using `quote!` as part of a procedural
+ /// macro.
+ ///
+ /// [Syn]: https://github.com/dtolnay/syn
+ ///
+ /// ```
+ /// # #[cfg(any())]
+ /// extern crate proc_macro;
+ /// # extern crate proc_macro2;
+ ///
+ /// # #[cfg(any())]
+ /// use proc_macro::TokenStream;
+ /// # use proc_macro2::TokenStream;
+ /// use quote::quote;
+ ///
+ /// # const IGNORE_TOKENS: &'static str = stringify! {
+ /// #[proc_macro_derive(HeapSize)]
+ /// # };
+ /// pub fn derive_heap_size(input: TokenStream) -> TokenStream {
+ /// // Parse the input and figure out what implementation to generate...
+ /// # const IGNORE_TOKENS: &'static str = stringify! {
+ /// let name = /* ... */;
+ /// let expr = /* ... */;
+ /// # };
+ /// #
+ /// # let name = 0;
+ /// # let expr = 0;
+ ///
+ /// let expanded = quote! {
+ /// // The generated impl.
+ /// impl heapsize::HeapSize for #name {
+ /// fn heap_size_of_children(&self) -> usize {
+ /// #expr
+ /// }
+ /// }
+ /// };
+ ///
+ /// // Hand the output tokens back to the compiler.
+ /// TokenStream::from(expanded)
+ /// }
+ /// ```
+ ///
+ /// <p><br></p>
+ ///
+ /// ### Combining quoted fragments
+ ///
+ /// Usually you don't end up constructing an entire final `TokenStream` in one
+ /// piece. Different parts may come from different helper functions. The tokens
+ /// produced by `quote!` themselves implement `ToTokens` and so can be
+ /// interpolated into later `quote!` invocations to build up a final result.
+ ///
+ /// ```
+ /// # use quote::quote;
+ /// #
+ /// let type_definition = quote! {...};
+ /// let methods = quote! {...};
+ ///
+ /// let tokens = quote! {
+ /// #type_definition
+ /// #methods
+ /// };
+ /// ```
+ ///
+ /// <p><br></p>
+ ///
+ /// ### Constructing identifiers
+ ///
+ /// Suppose we have an identifier `ident` which came from somewhere in a macro
+ /// input and we need to modify it in some way for the macro output. Let's
+ /// consider prepending the identifier with an underscore.
+ ///
+ /// Simply interpolating the identifier next to an underscore will not have the
+ /// behavior of concatenating them. The underscore and the identifier will
+ /// continue to be two separate tokens as if you had written `_ x`.
+ ///
+ /// ```
+ /// # use proc_macro2::{self as syn, Span};
+ /// # use quote::quote;
+ /// #
+ /// # let ident = syn::Ident::new("i", Span::call_site());
+ /// #
+ /// // incorrect
+ /// quote! {
+ /// let mut _#ident = 0;
+ /// }
+ /// # ;
+ /// ```
+ ///
+ /// The solution is to build a new identifier token with the correct value. As
+ /// this is such a common case, the [`format_ident!`] macro provides a
+ /// convenient utility for doing so correctly.
+ ///
+ /// ```
+ /// # use proc_macro2::{Ident, Span};
+ /// # use quote::{format_ident, quote};
+ /// #
+ /// # let ident = Ident::new("i", Span::call_site());
+ /// #
+ /// let varname = format_ident!("_{}", ident);
+ /// quote! {
+ /// let mut #varname = 0;
+ /// }
+ /// # ;
+ /// ```
+ ///
+ /// Alternatively, the APIs provided by Syn and proc-macro2 can be used to
+ /// directly build the identifier. This is roughly equivalent to the above, but
+ /// will not handle `ident` being a raw identifier.
+ ///
+ /// ```
+ /// # use proc_macro2::{self as syn, Span};
+ /// # use quote::quote;
+ /// #
+ /// # let ident = syn::Ident::new("i", Span::call_site());
+ /// #
+ /// let concatenated = format!("_{}", ident);
+ /// let varname = syn::Ident::new(&concatenated, ident.span());
+ /// quote! {
+ /// let mut #varname = 0;
+ /// }
+ /// # ;
+ /// ```
+ ///
+ /// <p><br></p>
+ ///
+ /// ### Making method calls
+ ///
+ /// Let's say our macro requires some type specified in the macro input to have
+ /// a constructor called `new`. We have the type in a variable called
+ /// `field_type` of type `syn::Type` and want to invoke the constructor.
+ ///
+ /// ```
+ /// # use quote::quote;
+ /// #
+ /// # let field_type = quote!(...);
+ /// #
+ /// // incorrect
+ /// quote! {
+ /// let value = #field_type::new();
+ /// }
+ /// # ;
+ /// ```
+ ///
+ /// This works only sometimes. If `field_type` is `String`, the expanded code
+ /// contains `String::new()` which is fine. But if `field_type` is something
+ /// like `Vec<i32>` then the expanded code is `Vec<i32>::new()` which is invalid
+ /// syntax. Ordinarily in handwritten Rust we would write `Vec::<i32>::new()`
+ /// but for macros often the following is more convenient.
+ ///
+ /// ```
+ /// # use quote::quote;
+ /// #
+ /// # let field_type = quote!(...);
+ /// #
+ /// quote! {
+ /// let value = <#field_type>::new();
+ /// }
+ /// # ;
+ /// ```
+ ///
+ /// This expands to `<Vec<i32>>::new()` which behaves correctly.
+ ///
+ /// A similar pattern is appropriate for trait methods.
+ ///
+ /// ```
+ /// # use quote::quote;
+ /// #
+ /// # let field_type = quote!(...);
+ /// #
+ /// quote! {
+ /// let value = <#field_type as core::default::Default>::default();
+ /// }
+ /// # ;
+ /// ```
+ ///
+ /// <p><br></p>
+ ///
+ /// ### Interpolating text inside of doc comments
+ ///
+ /// Neither doc comments nor string literals get interpolation behavior in
+ /// quote:
+ ///
+ /// ```compile_fail
+ /// quote! {
+ /// /// try to interpolate: #ident
+ /// ///
+ /// /// ...
+ /// }
+ /// ```
+ ///
+ /// ```compile_fail
+ /// quote! {
+ /// #[doc = "try to interpolate: #ident"]
+ /// }
+ /// ```
+ ///
+ /// Instead the best way to build doc comments that involve variables is by
+ /// formatting the doc string literal outside of quote.
+ ///
+ /// ```rust
+ /// # use proc_macro2::{Ident, Span};
+ /// # use quote::quote;
+ /// #
+ /// # const IGNORE: &str = stringify! {
+ /// let msg = format!(...);
+ /// # };
+ /// #
+ /// # let ident = Ident::new("var", Span::call_site());
+ /// # let msg = format!("try to interpolate: {}", ident);
+ /// quote! {
+ /// #[doc = #msg]
+ /// ///
+ /// /// ...
+ /// }
+ /// # ;
+ /// ```
+ ///
+ /// <p><br></p>
+ ///
+ /// ### Indexing into a tuple struct
+ ///
+ /// When interpolating indices of a tuple or tuple struct, we need them not to
+ /// appears suffixed as integer literals by interpolating them as [`syn::Index`]
+ /// instead.
+ ///
+ /// [`syn::Index`]: https://docs.rs/syn/2.0/syn/struct.Index.html
+ ///
+ /// ```compile_fail
+ /// let i = 0usize..self.fields.len();
+ ///
+ /// // expands to 0 + self.0usize.heap_size() + self.1usize.heap_size() + ...
+ /// // which is not valid syntax
+ /// quote! {
+ /// 0 #( + self.#i.heap_size() )*
+ /// }
+ /// ```
+ ///
+ /// ```
+ /// # use proc_macro2::{Ident, TokenStream};
+ /// # use quote::quote;
+ /// #
+ /// # mod syn {
+ /// # use proc_macro2::{Literal, TokenStream};
+ /// # use quote::{ToTokens, TokenStreamExt};
+ /// #
+ /// # pub struct Index(usize);
+ /// #
+ /// # impl From<usize> for Index {
+ /// # fn from(i: usize) -> Self {
+ /// # Index(i)
+ /// # }
+ /// # }
+ /// #
+ /// # impl ToTokens for Index {
+ /// # fn to_tokens(&self, tokens: &mut TokenStream) {
+ /// # tokens.append(Literal::usize_unsuffixed(self.0));
+ /// # }
+ /// # }
+ /// # }
+ /// #
+ /// # struct Struct {
+ /// # fields: Vec<Ident>,
+ /// # }
+ /// #
+ /// # impl Struct {
+ /// # fn example(&self) -> TokenStream {
+ /// let i = (0..self.fields.len()).map(syn::Index::from);
+ ///
+ /// // expands to 0 + self.0.heap_size() + self.1.heap_size() + ...
+ /// quote! {
+ /// 0 #( + self.#i.heap_size() )*
+ /// }
+ /// # }
+ /// # }
+ /// ```
+ $quote
+ };
+}
+
+#[cfg(doc)]
+__quote![
+ #[macro_export]
+ macro_rules! quote {
+ ($($tt:tt)*) => {
+ ...
+ };
+ }
+];
+
+#[cfg(not(doc))]
+__quote![
+ #[macro_export]
+ macro_rules! quote {
+ () => {
+ $crate::__private::TokenStream::new()
+ };
+
+ // Special case rule for a single tt, for performance.
+ ($tt:tt) => {{
+ let mut _s = $crate::__private::TokenStream::new();
+ $crate::quote_token!{$tt _s}
+ _s
+ }};
+
+ // Special case rules for two tts, for performance.
+ (# $var:ident) => {{
+ let mut _s = $crate::__private::TokenStream::new();
+ $crate::ToTokens::to_tokens(&$var, &mut _s);
+ _s
+ }};
+ ($tt1:tt $tt2:tt) => {{
+ let mut _s = $crate::__private::TokenStream::new();
+ $crate::quote_token!{$tt1 _s}
+ $crate::quote_token!{$tt2 _s}
+ _s
+ }};
+
+ // Rule for any other number of tokens.
+ ($($tt:tt)*) => {{
+ let mut _s = $crate::__private::TokenStream::new();
+ $crate::quote_each_token!{_s $($tt)*}
+ _s
+ }};
+ }
+];
+
+macro_rules! __quote_spanned {
+ ($quote_spanned:item) => {
+ /// Same as `quote!`, but applies a given span to all tokens originating within
+ /// the macro invocation.
+ ///
+ /// <br>
+ ///
+ /// # Syntax
+ ///
+ /// A span expression of type [`Span`], followed by `=>`, followed by the tokens
+ /// to quote. The span expression should be brief — use a variable for
+ /// anything more than a few characters. There should be no space before the
+ /// `=>` token.
+ ///
+ /// [`Span`]: proc_macro2::Span
+ ///
+ /// ```
+ /// # use proc_macro2::Span;
+ /// # use quote::quote_spanned;
+ /// #
+ /// # const IGNORE_TOKENS: &'static str = stringify! {
+ /// let span = /* ... */;
+ /// # };
+ /// # let span = Span::call_site();
+ /// # let init = 0;
+ ///
+ /// // On one line, use parentheses.
+ /// let tokens = quote_spanned!(span=> Box::into_raw(Box::new(#init)));
+ ///
+ /// // On multiple lines, place the span at the top and use braces.
+ /// let tokens = quote_spanned! {span=>
+ /// Box::into_raw(Box::new(#init))
+ /// };
+ /// ```
+ ///
+ /// The lack of space before the `=>` should look jarring to Rust programmers
+ /// and this is intentional. The formatting is designed to be visibly
+ /// off-balance and draw the eye a particular way, due to the span expression
+ /// being evaluated in the context of the procedural macro and the remaining
+ /// tokens being evaluated in the generated code.
+ ///
+ /// <br>
+ ///
+ /// # Hygiene
+ ///
+ /// Any interpolated tokens preserve the `Span` information provided by their
+ /// `ToTokens` implementation. Tokens that originate within the `quote_spanned!`
+ /// invocation are spanned with the given span argument.
+ ///
+ /// <br>
+ ///
+ /// # Example
+ ///
+ /// The following procedural macro code uses `quote_spanned!` to assert that a
+ /// particular Rust type implements the [`Sync`] trait so that references can be
+ /// safely shared between threads.
+ ///
+ /// ```
+ /// # use quote::{quote_spanned, TokenStreamExt, ToTokens};
+ /// # use proc_macro2::{Span, TokenStream};
+ /// #
+ /// # struct Type;
+ /// #
+ /// # impl Type {
+ /// # fn span(&self) -> Span {
+ /// # Span::call_site()
+ /// # }
+ /// # }
+ /// #
+ /// # impl ToTokens for Type {
+ /// # fn to_tokens(&self, _tokens: &mut TokenStream) {}
+ /// # }
+ /// #
+ /// # let ty = Type;
+ /// # let call_site = Span::call_site();
+ /// #
+ /// let ty_span = ty.span();
+ /// let assert_sync = quote_spanned! {ty_span=>
+ /// struct _AssertSync where #ty: Sync;
+ /// };
+ /// ```
+ ///
+ /// If the assertion fails, the user will see an error like the following. The
+ /// input span of their type is highlighted in the error.
+ ///
+ /// ```text
+ /// error[E0277]: the trait bound `*const (): std::marker::Sync` is not satisfied
+ /// --> src/main.rs:10:21
+ /// |
+ /// 10 | static ref PTR: *const () = &();
+ /// | ^^^^^^^^^ `*const ()` cannot be shared between threads safely
+ /// ```
+ ///
+ /// In this example it is important for the where-clause to be spanned with the
+ /// line/column information of the user's input type so that error messages are
+ /// placed appropriately by the compiler.
+ $quote_spanned
+ };
+}
+
+#[cfg(doc)]
+__quote_spanned![
+ #[macro_export]
+ macro_rules! quote_spanned {
+ ($span:expr=> $($tt:tt)*) => {
+ ...
+ };
+ }
+];
+
+#[cfg(not(doc))]
+__quote_spanned![
+ #[macro_export]
+ macro_rules! quote_spanned {
+ ($span:expr=>) => {{
+ let _: $crate::__private::Span = $crate::__private::get_span($span).__into_span();
+ $crate::__private::TokenStream::new()
+ }};
+
+ // Special case rule for a single tt, for performance.
+ ($span:expr=> $tt:tt) => {{
+ let mut _s = $crate::__private::TokenStream::new();
+ let _span: $crate::__private::Span = $crate::__private::get_span($span).__into_span();
+ $crate::quote_token_spanned!{$tt _s _span}
+ _s
+ }};
+
+ // Special case rules for two tts, for performance.
+ ($span:expr=> # $var:ident) => {{
+ let mut _s = $crate::__private::TokenStream::new();
+ let _: $crate::__private::Span = $crate::__private::get_span($span).__into_span();
+ $crate::ToTokens::to_tokens(&$var, &mut _s);
+ _s
+ }};
+ ($span:expr=> $tt1:tt $tt2:tt) => {{
+ let mut _s = $crate::__private::TokenStream::new();
+ let _span: $crate::__private::Span = $crate::__private::get_span($span).__into_span();
+ $crate::quote_token_spanned!{$tt1 _s _span}
+ $crate::quote_token_spanned!{$tt2 _s _span}
+ _s
+ }};
+
+ // Rule for any other number of tokens.
+ ($span:expr=> $($tt:tt)*) => {{
+ let mut _s = $crate::__private::TokenStream::new();
+ let _span: $crate::__private::Span = $crate::__private::get_span($span).__into_span();
+ $crate::quote_each_token_spanned!{_s _span $($tt)*}
+ _s
+ }};
+ }
+];
+
+// Extract the names of all #metavariables and pass them to the $call macro.
+//
+// in: pounded_var_names!(then!(...) a #b c #( #d )* #e)
+// out: then!(... b);
+// then!(... d);
+// then!(... e);
+#[macro_export]
+#[doc(hidden)]
+macro_rules! pounded_var_names {
+ ($call:ident! $extra:tt $($tts:tt)*) => {
+ $crate::pounded_var_names_with_context!{$call! $extra
+ (@ $($tts)*)
+ ($($tts)* @)
+ }
+ };
+}
+
+#[macro_export]
+#[doc(hidden)]
+macro_rules! pounded_var_names_with_context {
+ ($call:ident! $extra:tt ($($b1:tt)*) ($($curr:tt)*)) => {
+ $(
+ $crate::pounded_var_with_context!{$call! $extra $b1 $curr}
+ )*
+ };
+}
+
+#[macro_export]
+#[doc(hidden)]
+macro_rules! pounded_var_with_context {
+ ($call:ident! $extra:tt $b1:tt ( $($inner:tt)* )) => {
+ $crate::pounded_var_names!{$call! $extra $($inner)*}
+ };
+
+ ($call:ident! $extra:tt $b1:tt [ $($inner:tt)* ]) => {
+ $crate::pounded_var_names!{$call! $extra $($inner)*}
+ };
+
+ ($call:ident! $extra:tt $b1:tt { $($inner:tt)* }) => {
+ $crate::pounded_var_names!{$call! $extra $($inner)*}
+ };
+
+ ($call:ident!($($extra:tt)*) # $var:ident) => {
+ $crate::$call!($($extra)* $var);
+ };
+
+ ($call:ident! $extra:tt $b1:tt $curr:tt) => {};
+}
+
+#[macro_export]
+#[doc(hidden)]
+macro_rules! quote_bind_into_iter {
+ ($has_iter:ident $var:ident) => {
+ // `mut` may be unused if $var occurs multiple times in the list.
+ #[allow(unused_mut)]
+ let (mut $var, i) = $var.quote_into_iter();
+ let $has_iter = $has_iter | i;
+ };
+}
+
+#[macro_export]
+#[doc(hidden)]
+macro_rules! quote_bind_next_or_break {
+ ($var:ident) => {
+ let $var = match $var.next() {
+ Some(_x) => $crate::__private::RepInterp(_x),
+ None => break,
+ };
+ };
+}
+
+// The obvious way to write this macro is as a tt muncher. This implementation
+// does something more complex for two reasons.
+//
+// - With a tt muncher it's easy to hit Rust's built-in recursion_limit, which
+// this implementation avoids because it isn't tail recursive.
+//
+// - Compile times for a tt muncher are quadratic relative to the length of
+// the input. This implementation is linear, so it will be faster
+// (potentially much faster) for big inputs. However, the constant factors
+// of this implementation are higher than that of a tt muncher, so it is
+// somewhat slower than a tt muncher if there are many invocations with
+// short inputs.
+//
+// An invocation like this:
+//
+// quote_each_token!(_s a b c d e f g h i j);
+//
+// expands to this:
+//
+// quote_tokens_with_context!(_s
+// (@ @ @ @ @ @ a b c d e f g h i j)
+// (@ @ @ @ @ a b c d e f g h i j @)
+// (@ @ @ @ a b c d e f g h i j @ @)
+// (@ @ @ (a) (b) (c) (d) (e) (f) (g) (h) (i) (j) @ @ @)
+// (@ @ a b c d e f g h i j @ @ @ @)
+// (@ a b c d e f g h i j @ @ @ @ @)
+// (a b c d e f g h i j @ @ @ @ @ @)
+// );
+//
+// which gets transposed and expanded to this:
+//
+// quote_token_with_context!(_s @ @ @ @ @ @ a);
+// quote_token_with_context!(_s @ @ @ @ @ a b);
+// quote_token_with_context!(_s @ @ @ @ a b c);
+// quote_token_with_context!(_s @ @ @ (a) b c d);
+// quote_token_with_context!(_s @ @ a (b) c d e);
+// quote_token_with_context!(_s @ a b (c) d e f);
+// quote_token_with_context!(_s a b c (d) e f g);
+// quote_token_with_context!(_s b c d (e) f g h);
+// quote_token_with_context!(_s c d e (f) g h i);
+// quote_token_with_context!(_s d e f (g) h i j);
+// quote_token_with_context!(_s e f g (h) i j @);
+// quote_token_with_context!(_s f g h (i) j @ @);
+// quote_token_with_context!(_s g h i (j) @ @ @);
+// quote_token_with_context!(_s h i j @ @ @ @);
+// quote_token_with_context!(_s i j @ @ @ @ @);
+// quote_token_with_context!(_s j @ @ @ @ @ @);
+//
+// Without having used muncher-style recursion, we get one invocation of
+// quote_token_with_context for each original tt, with three tts of context on
+// either side. This is enough for the longest possible interpolation form (a
+// repetition with separator, as in `# (#var) , *`) to be fully represented with
+// the first or last tt in the middle.
+//
+// The middle tt (surrounded by parentheses) is the tt being processed.
+//
+// - When it is a `#`, quote_token_with_context can do an interpolation. The
+// interpolation kind will depend on the three subsequent tts.
+//
+// - When it is within a later part of an interpolation, it can be ignored
+// because the interpolation has already been done.
+//
+// - When it is not part of an interpolation it can be pushed as a single
+// token into the output.
+//
+// - When the middle token is an unparenthesized `@`, that call is one of the
+// first 3 or last 3 calls of quote_token_with_context and does not
+// correspond to one of the original input tokens, so turns into nothing.
+#[macro_export]
+#[doc(hidden)]
+macro_rules! quote_each_token {
+ ($tokens:ident $($tts:tt)*) => {
+ $crate::quote_tokens_with_context!{$tokens
+ (@ @ @ @ @ @ $($tts)*)
+ (@ @ @ @ @ $($tts)* @)
+ (@ @ @ @ $($tts)* @ @)
+ (@ @ @ $(($tts))* @ @ @)
+ (@ @ $($tts)* @ @ @ @)
+ (@ $($tts)* @ @ @ @ @)
+ ($($tts)* @ @ @ @ @ @)
+ }
+ };
+}
+
+// See the explanation on quote_each_token.
+#[macro_export]
+#[doc(hidden)]
+macro_rules! quote_each_token_spanned {
+ ($tokens:ident $span:ident $($tts:tt)*) => {
+ $crate::quote_tokens_with_context_spanned!{$tokens $span
+ (@ @ @ @ @ @ $($tts)*)
+ (@ @ @ @ @ $($tts)* @)
+ (@ @ @ @ $($tts)* @ @)
+ (@ @ @ $(($tts))* @ @ @)
+ (@ @ $($tts)* @ @ @ @)
+ (@ $($tts)* @ @ @ @ @)
+ ($($tts)* @ @ @ @ @ @)
+ }
+ };
+}
+
+// See the explanation on quote_each_token.
+#[macro_export]
+#[doc(hidden)]
+macro_rules! quote_tokens_with_context {
+ ($tokens:ident
+ ($($b3:tt)*) ($($b2:tt)*) ($($b1:tt)*)
+ ($($curr:tt)*)
+ ($($a1:tt)*) ($($a2:tt)*) ($($a3:tt)*)
+ ) => {
+ $(
+ $crate::quote_token_with_context!{$tokens $b3 $b2 $b1 $curr $a1 $a2 $a3}
+ )*
+ };
+}
+
+// See the explanation on quote_each_token.
+#[macro_export]
+#[doc(hidden)]
+macro_rules! quote_tokens_with_context_spanned {
+ ($tokens:ident $span:ident
+ ($($b3:tt)*) ($($b2:tt)*) ($($b1:tt)*)
+ ($($curr:tt)*)
+ ($($a1:tt)*) ($($a2:tt)*) ($($a3:tt)*)
+ ) => {
+ $(
+ $crate::quote_token_with_context_spanned!{$tokens $span $b3 $b2 $b1 $curr $a1 $a2 $a3}
+ )*
+ };
+}
+
+// See the explanation on quote_each_token.
+#[macro_export]
+#[doc(hidden)]
+macro_rules! quote_token_with_context {
+ // Unparenthesized `@` indicates this call does not correspond to one of the
+ // original input tokens. Ignore it.
+ ($tokens:ident $b3:tt $b2:tt $b1:tt @ $a1:tt $a2:tt $a3:tt) => {};
+
+ // A repetition with no separator.
+ ($tokens:ident $b3:tt $b2:tt $b1:tt (#) ( $($inner:tt)* ) * $a3:tt) => {{
+ use $crate::__private::ext::*;
+ let has_iter = $crate::__private::ThereIsNoIteratorInRepetition;
+ $crate::pounded_var_names!{quote_bind_into_iter!(has_iter) () $($inner)*}
+ let _: $crate::__private::HasIterator = has_iter;
+ // This is `while true` instead of `loop` because if there are no
+ // iterators used inside of this repetition then the body would not
+ // contain any `break`, so the compiler would emit unreachable code
+ // warnings on anything below the loop. We use has_iter to detect and
+ // fail to compile when there are no iterators, so here we just work
+ // around the unneeded extra warning.
+ while true {
+ $crate::pounded_var_names!{quote_bind_next_or_break!() () $($inner)*}
+ $crate::quote_each_token!{$tokens $($inner)*}
+ }
+ }};
+ // ... and one step later.
+ ($tokens:ident $b3:tt $b2:tt # (( $($inner:tt)* )) * $a2:tt $a3:tt) => {};
+ // ... and one step later.
+ ($tokens:ident $b3:tt # ( $($inner:tt)* ) (*) $a1:tt $a2:tt $a3:tt) => {};
+
+ // A repetition with separator.
+ ($tokens:ident $b3:tt $b2:tt $b1:tt (#) ( $($inner:tt)* ) $sep:tt *) => {{
+ use $crate::__private::ext::*;
+ let mut _i = 0usize;
+ let has_iter = $crate::__private::ThereIsNoIteratorInRepetition;
+ $crate::pounded_var_names!{quote_bind_into_iter!(has_iter) () $($inner)*}
+ let _: $crate::__private::HasIterator = has_iter;
+ while true {
+ $crate::pounded_var_names!{quote_bind_next_or_break!() () $($inner)*}
+ if _i > 0 {
+ $crate::quote_token!{$sep $tokens}
+ }
+ _i += 1;
+ $crate::quote_each_token!{$tokens $($inner)*}
+ }
+ }};
+ // ... and one step later.
+ ($tokens:ident $b3:tt $b2:tt # (( $($inner:tt)* )) $sep:tt * $a3:tt) => {};
+ // ... and one step later.
+ ($tokens:ident $b3:tt # ( $($inner:tt)* ) ($sep:tt) * $a2:tt $a3:tt) => {};
+ // (A special case for `#(var)**`, where the first `*` is treated as the
+ // repetition symbol and the second `*` is treated as an ordinary token.)
+ ($tokens:ident # ( $($inner:tt)* ) * (*) $a1:tt $a2:tt $a3:tt) => {
+ // https://github.com/dtolnay/quote/issues/130
+ $crate::quote_token!{* $tokens}
+ };
+ // ... and one step later.
+ ($tokens:ident # ( $($inner:tt)* ) $sep:tt (*) $a1:tt $a2:tt $a3:tt) => {};
+
+ // A non-repetition interpolation.
+ ($tokens:ident $b3:tt $b2:tt $b1:tt (#) $var:ident $a2:tt $a3:tt) => {
+ $crate::ToTokens::to_tokens(&$var, &mut $tokens);
+ };
+ // ... and one step later.
+ ($tokens:ident $b3:tt $b2:tt # ($var:ident) $a1:tt $a2:tt $a3:tt) => {};
+
+ // An ordinary token, not part of any interpolation.
+ ($tokens:ident $b3:tt $b2:tt $b1:tt ($curr:tt) $a1:tt $a2:tt $a3:tt) => {
+ $crate::quote_token!{$curr $tokens}
+ };
+}
+
+// See the explanation on quote_each_token, and on the individual rules of
+// quote_token_with_context.
+#[macro_export]
+#[doc(hidden)]
+macro_rules! quote_token_with_context_spanned {
+ ($tokens:ident $span:ident $b3:tt $b2:tt $b1:tt @ $a1:tt $a2:tt $a3:tt) => {};
+
+ ($tokens:ident $span:ident $b3:tt $b2:tt $b1:tt (#) ( $($inner:tt)* ) * $a3:tt) => {{
+ use $crate::__private::ext::*;
+ let has_iter = $crate::__private::ThereIsNoIteratorInRepetition;
+ $crate::pounded_var_names!{quote_bind_into_iter!(has_iter) () $($inner)*}
+ let _: $crate::__private::HasIterator = has_iter;
+ while true {
+ $crate::pounded_var_names!{quote_bind_next_or_break!() () $($inner)*}
+ $crate::quote_each_token_spanned!{$tokens $span $($inner)*}
+ }
+ }};
+ ($tokens:ident $span:ident $b3:tt $b2:tt # (( $($inner:tt)* )) * $a2:tt $a3:tt) => {};
+ ($tokens:ident $span:ident $b3:tt # ( $($inner:tt)* ) (*) $a1:tt $a2:tt $a3:tt) => {};
+
+ ($tokens:ident $span:ident $b3:tt $b2:tt $b1:tt (#) ( $($inner:tt)* ) $sep:tt *) => {{
+ use $crate::__private::ext::*;
+ let mut _i = 0usize;
+ let has_iter = $crate::__private::ThereIsNoIteratorInRepetition;
+ $crate::pounded_var_names!{quote_bind_into_iter!(has_iter) () $($inner)*}
+ let _: $crate::__private::HasIterator = has_iter;
+ while true {
+ $crate::pounded_var_names!{quote_bind_next_or_break!() () $($inner)*}
+ if _i > 0 {
+ $crate::quote_token_spanned!{$sep $tokens $span}
+ }
+ _i += 1;
+ $crate::quote_each_token_spanned!{$tokens $span $($inner)*}
+ }
+ }};
+ ($tokens:ident $span:ident $b3:tt $b2:tt # (( $($inner:tt)* )) $sep:tt * $a3:tt) => {};
+ ($tokens:ident $span:ident $b3:tt # ( $($inner:tt)* ) ($sep:tt) * $a2:tt $a3:tt) => {};
+ ($tokens:ident $span:ident # ( $($inner:tt)* ) * (*) $a1:tt $a2:tt $a3:tt) => {
+ // https://github.com/dtolnay/quote/issues/130
+ $crate::quote_token_spanned!{* $tokens $span}
+ };
+ ($tokens:ident $span:ident # ( $($inner:tt)* ) $sep:tt (*) $a1:tt $a2:tt $a3:tt) => {};
+
+ ($tokens:ident $span:ident $b3:tt $b2:tt $b1:tt (#) $var:ident $a2:tt $a3:tt) => {
+ $crate::ToTokens::to_tokens(&$var, &mut $tokens);
+ };
+ ($tokens:ident $span:ident $b3:tt $b2:tt # ($var:ident) $a1:tt $a2:tt $a3:tt) => {};
+
+ ($tokens:ident $span:ident $b3:tt $b2:tt $b1:tt ($curr:tt) $a1:tt $a2:tt $a3:tt) => {
+ $crate::quote_token_spanned!{$curr $tokens $span}
+ };
+}
+
+// These rules are ordered by approximate token frequency, at least for the
+// first 10 or so, to improve compile times. Having `ident` first is by far the
+// most important because it's typically 2-3x more common than the next most
+// common token.
+//
+// Separately, we put the token being matched in the very front so that failing
+// rules may fail to match as quickly as possible.
+#[macro_export]
+#[doc(hidden)]
+macro_rules! quote_token {
+ ($ident:ident $tokens:ident) => {
+ $crate::__private::push_ident(&mut $tokens, stringify!($ident));
+ };
+
+ (:: $tokens:ident) => {
+ $crate::__private::push_colon2(&mut $tokens);
+ };
+
+ (( $($inner:tt)* ) $tokens:ident) => {
+ $crate::__private::push_group(
+ &mut $tokens,
+ $crate::__private::Delimiter::Parenthesis,
+ $crate::quote!($($inner)*),
+ );
+ };
+
+ ([ $($inner:tt)* ] $tokens:ident) => {
+ $crate::__private::push_group(
+ &mut $tokens,
+ $crate::__private::Delimiter::Bracket,
+ $crate::quote!($($inner)*),
+ );
+ };
+
+ ({ $($inner:tt)* } $tokens:ident) => {
+ $crate::__private::push_group(
+ &mut $tokens,
+ $crate::__private::Delimiter::Brace,
+ $crate::quote!($($inner)*),
+ );
+ };
+
+ (# $tokens:ident) => {
+ $crate::__private::push_pound(&mut $tokens);
+ };
+
+ (, $tokens:ident) => {
+ $crate::__private::push_comma(&mut $tokens);
+ };
+
+ (. $tokens:ident) => {
+ $crate::__private::push_dot(&mut $tokens);
+ };
+
+ (; $tokens:ident) => {
+ $crate::__private::push_semi(&mut $tokens);
+ };
+
+ (: $tokens:ident) => {
+ $crate::__private::push_colon(&mut $tokens);
+ };
+
+ (+ $tokens:ident) => {
+ $crate::__private::push_add(&mut $tokens);
+ };
+
+ (+= $tokens:ident) => {
+ $crate::__private::push_add_eq(&mut $tokens);
+ };
+
+ (& $tokens:ident) => {
+ $crate::__private::push_and(&mut $tokens);
+ };
+
+ (&& $tokens:ident) => {
+ $crate::__private::push_and_and(&mut $tokens);
+ };
+
+ (&= $tokens:ident) => {
+ $crate::__private::push_and_eq(&mut $tokens);
+ };
+
+ (@ $tokens:ident) => {
+ $crate::__private::push_at(&mut $tokens);
+ };
+
+ (! $tokens:ident) => {
+ $crate::__private::push_bang(&mut $tokens);
+ };
+
+ (^ $tokens:ident) => {
+ $crate::__private::push_caret(&mut $tokens);
+ };
+
+ (^= $tokens:ident) => {
+ $crate::__private::push_caret_eq(&mut $tokens);
+ };
+
+ (/ $tokens:ident) => {
+ $crate::__private::push_div(&mut $tokens);
+ };
+
+ (/= $tokens:ident) => {
+ $crate::__private::push_div_eq(&mut $tokens);
+ };
+
+ (.. $tokens:ident) => {
+ $crate::__private::push_dot2(&mut $tokens);
+ };
+
+ (... $tokens:ident) => {
+ $crate::__private::push_dot3(&mut $tokens);
+ };
+
+ (..= $tokens:ident) => {
+ $crate::__private::push_dot_dot_eq(&mut $tokens);
+ };
+
+ (= $tokens:ident) => {
+ $crate::__private::push_eq(&mut $tokens);
+ };
+
+ (== $tokens:ident) => {
+ $crate::__private::push_eq_eq(&mut $tokens);
+ };
+
+ (>= $tokens:ident) => {
+ $crate::__private::push_ge(&mut $tokens);
+ };
+
+ (> $tokens:ident) => {
+ $crate::__private::push_gt(&mut $tokens);
+ };
+
+ (<= $tokens:ident) => {
+ $crate::__private::push_le(&mut $tokens);
+ };
+
+ (< $tokens:ident) => {
+ $crate::__private::push_lt(&mut $tokens);
+ };
+
+ (*= $tokens:ident) => {
+ $crate::__private::push_mul_eq(&mut $tokens);
+ };
+
+ (!= $tokens:ident) => {
+ $crate::__private::push_ne(&mut $tokens);
+ };
+
+ (| $tokens:ident) => {
+ $crate::__private::push_or(&mut $tokens);
+ };
+
+ (|= $tokens:ident) => {
+ $crate::__private::push_or_eq(&mut $tokens);
+ };
+
+ (|| $tokens:ident) => {
+ $crate::__private::push_or_or(&mut $tokens);
+ };
+
+ (? $tokens:ident) => {
+ $crate::__private::push_question(&mut $tokens);
+ };
+
+ (-> $tokens:ident) => {
+ $crate::__private::push_rarrow(&mut $tokens);
+ };
+
+ (<- $tokens:ident) => {
+ $crate::__private::push_larrow(&mut $tokens);
+ };
+
+ (% $tokens:ident) => {
+ $crate::__private::push_rem(&mut $tokens);
+ };
+
+ (%= $tokens:ident) => {
+ $crate::__private::push_rem_eq(&mut $tokens);
+ };
+
+ (=> $tokens:ident) => {
+ $crate::__private::push_fat_arrow(&mut $tokens);
+ };
+
+ (<< $tokens:ident) => {
+ $crate::__private::push_shl(&mut $tokens);
+ };
+
+ (<<= $tokens:ident) => {
+ $crate::__private::push_shl_eq(&mut $tokens);
+ };
+
+ (>> $tokens:ident) => {
+ $crate::__private::push_shr(&mut $tokens);
+ };
+
+ (>>= $tokens:ident) => {
+ $crate::__private::push_shr_eq(&mut $tokens);
+ };
+
+ (* $tokens:ident) => {
+ $crate::__private::push_star(&mut $tokens);
+ };
+
+ (- $tokens:ident) => {
+ $crate::__private::push_sub(&mut $tokens);
+ };
+
+ (-= $tokens:ident) => {
+ $crate::__private::push_sub_eq(&mut $tokens);
+ };
+
+ ($lifetime:lifetime $tokens:ident) => {
+ $crate::__private::push_lifetime(&mut $tokens, stringify!($lifetime));
+ };
+
+ (_ $tokens:ident) => {
+ $crate::__private::push_underscore(&mut $tokens);
+ };
+
+ ($other:tt $tokens:ident) => {
+ $crate::__private::parse(&mut $tokens, stringify!($other));
+ };
+}
+
+// See the comment above `quote_token!` about the rule ordering.
+#[macro_export]
+#[doc(hidden)]
+macro_rules! quote_token_spanned {
+ ($ident:ident $tokens:ident $span:ident) => {
+ $crate::__private::push_ident_spanned(&mut $tokens, $span, stringify!($ident));
+ };
+
+ (:: $tokens:ident $span:ident) => {
+ $crate::__private::push_colon2_spanned(&mut $tokens, $span);
+ };
+
+ (( $($inner:tt)* ) $tokens:ident $span:ident) => {
+ $crate::__private::push_group_spanned(
+ &mut $tokens,
+ $span,
+ $crate::__private::Delimiter::Parenthesis,
+ $crate::quote_spanned!($span=> $($inner)*),
+ );
+ };
+
+ ([ $($inner:tt)* ] $tokens:ident $span:ident) => {
+ $crate::__private::push_group_spanned(
+ &mut $tokens,
+ $span,
+ $crate::__private::Delimiter::Bracket,
+ $crate::quote_spanned!($span=> $($inner)*),
+ );
+ };
+
+ ({ $($inner:tt)* } $tokens:ident $span:ident) => {
+ $crate::__private::push_group_spanned(
+ &mut $tokens,
+ $span,
+ $crate::__private::Delimiter::Brace,
+ $crate::quote_spanned!($span=> $($inner)*),
+ );
+ };
+
+ (# $tokens:ident $span:ident) => {
+ $crate::__private::push_pound_spanned(&mut $tokens, $span);
+ };
+
+ (, $tokens:ident $span:ident) => {
+ $crate::__private::push_comma_spanned(&mut $tokens, $span);
+ };
+
+ (. $tokens:ident $span:ident) => {
+ $crate::__private::push_dot_spanned(&mut $tokens, $span);
+ };
+
+ (; $tokens:ident $span:ident) => {
+ $crate::__private::push_semi_spanned(&mut $tokens, $span);
+ };
+
+ (: $tokens:ident $span:ident) => {
+ $crate::__private::push_colon_spanned(&mut $tokens, $span);
+ };
+
+ (+ $tokens:ident $span:ident) => {
+ $crate::__private::push_add_spanned(&mut $tokens, $span);
+ };
+
+ (+= $tokens:ident $span:ident) => {
+ $crate::__private::push_add_eq_spanned(&mut $tokens, $span);
+ };
+
+ (& $tokens:ident $span:ident) => {
+ $crate::__private::push_and_spanned(&mut $tokens, $span);
+ };
+
+ (&& $tokens:ident $span:ident) => {
+ $crate::__private::push_and_and_spanned(&mut $tokens, $span);
+ };
+
+ (&= $tokens:ident $span:ident) => {
+ $crate::__private::push_and_eq_spanned(&mut $tokens, $span);
+ };
+
+ (@ $tokens:ident $span:ident) => {
+ $crate::__private::push_at_spanned(&mut $tokens, $span);
+ };
+
+ (! $tokens:ident $span:ident) => {
+ $crate::__private::push_bang_spanned(&mut $tokens, $span);
+ };
+
+ (^ $tokens:ident $span:ident) => {
+ $crate::__private::push_caret_spanned(&mut $tokens, $span);
+ };
+
+ (^= $tokens:ident $span:ident) => {
+ $crate::__private::push_caret_eq_spanned(&mut $tokens, $span);
+ };
+
+ (/ $tokens:ident $span:ident) => {
+ $crate::__private::push_div_spanned(&mut $tokens, $span);
+ };
+
+ (/= $tokens:ident $span:ident) => {
+ $crate::__private::push_div_eq_spanned(&mut $tokens, $span);
+ };
+
+ (.. $tokens:ident $span:ident) => {
+ $crate::__private::push_dot2_spanned(&mut $tokens, $span);
+ };
+
+ (... $tokens:ident $span:ident) => {
+ $crate::__private::push_dot3_spanned(&mut $tokens, $span);
+ };
+
+ (..= $tokens:ident $span:ident) => {
+ $crate::__private::push_dot_dot_eq_spanned(&mut $tokens, $span);
+ };
+
+ (= $tokens:ident $span:ident) => {
+ $crate::__private::push_eq_spanned(&mut $tokens, $span);
+ };
+
+ (== $tokens:ident $span:ident) => {
+ $crate::__private::push_eq_eq_spanned(&mut $tokens, $span);
+ };
+
+ (>= $tokens:ident $span:ident) => {
+ $crate::__private::push_ge_spanned(&mut $tokens, $span);
+ };
+
+ (> $tokens:ident $span:ident) => {
+ $crate::__private::push_gt_spanned(&mut $tokens, $span);
+ };
+
+ (<= $tokens:ident $span:ident) => {
+ $crate::__private::push_le_spanned(&mut $tokens, $span);
+ };
+
+ (< $tokens:ident $span:ident) => {
+ $crate::__private::push_lt_spanned(&mut $tokens, $span);
+ };
+
+ (*= $tokens:ident $span:ident) => {
+ $crate::__private::push_mul_eq_spanned(&mut $tokens, $span);
+ };
+
+ (!= $tokens:ident $span:ident) => {
+ $crate::__private::push_ne_spanned(&mut $tokens, $span);
+ };
+
+ (| $tokens:ident $span:ident) => {
+ $crate::__private::push_or_spanned(&mut $tokens, $span);
+ };
+
+ (|= $tokens:ident $span:ident) => {
+ $crate::__private::push_or_eq_spanned(&mut $tokens, $span);
+ };
+
+ (|| $tokens:ident $span:ident) => {
+ $crate::__private::push_or_or_spanned(&mut $tokens, $span);
+ };
+
+ (? $tokens:ident $span:ident) => {
+ $crate::__private::push_question_spanned(&mut $tokens, $span);
+ };
+
+ (-> $tokens:ident $span:ident) => {
+ $crate::__private::push_rarrow_spanned(&mut $tokens, $span);
+ };
+
+ (<- $tokens:ident $span:ident) => {
+ $crate::__private::push_larrow_spanned(&mut $tokens, $span);
+ };
+
+ (% $tokens:ident $span:ident) => {
+ $crate::__private::push_rem_spanned(&mut $tokens, $span);
+ };
+
+ (%= $tokens:ident $span:ident) => {
+ $crate::__private::push_rem_eq_spanned(&mut $tokens, $span);
+ };
+
+ (=> $tokens:ident $span:ident) => {
+ $crate::__private::push_fat_arrow_spanned(&mut $tokens, $span);
+ };
+
+ (<< $tokens:ident $span:ident) => {
+ $crate::__private::push_shl_spanned(&mut $tokens, $span);
+ };
+
+ (<<= $tokens:ident $span:ident) => {
+ $crate::__private::push_shl_eq_spanned(&mut $tokens, $span);
+ };
+
+ (>> $tokens:ident $span:ident) => {
+ $crate::__private::push_shr_spanned(&mut $tokens, $span);
+ };
+
+ (>>= $tokens:ident $span:ident) => {
+ $crate::__private::push_shr_eq_spanned(&mut $tokens, $span);
+ };
+
+ (* $tokens:ident $span:ident) => {
+ $crate::__private::push_star_spanned(&mut $tokens, $span);
+ };
+
+ (- $tokens:ident $span:ident) => {
+ $crate::__private::push_sub_spanned(&mut $tokens, $span);
+ };
+
+ (-= $tokens:ident $span:ident) => {
+ $crate::__private::push_sub_eq_spanned(&mut $tokens, $span);
+ };
+
+ ($lifetime:lifetime $tokens:ident $span:ident) => {
+ $crate::__private::push_lifetime_spanned(&mut $tokens, $span, stringify!($lifetime));
+ };
+
+ (_ $tokens:ident $span:ident) => {
+ $crate::__private::push_underscore_spanned(&mut $tokens, $span);
+ };
+
+ ($other:tt $tokens:ident $span:ident) => {
+ $crate::__private::parse_spanned(&mut $tokens, $span, stringify!($other));
+ };
+}
diff --git a/rust/quote/runtime.rs b/rust/quote/runtime.rs
new file mode 100644
index 000000000000..c704ca89411f
--- /dev/null
+++ b/rust/quote/runtime.rs
@@ -0,0 +1,492 @@
+use self::get_span::{GetSpan, GetSpanBase, GetSpanInner};
+use crate::{IdentFragment, ToTokens, TokenStreamExt};
+use core::fmt;
+use core::iter;
+use core::ops::BitOr;
+use proc_macro2::{Group, Ident, Punct, Spacing, TokenTree};
+
+#[doc(hidden)]
+pub use alloc::format;
+#[doc(hidden)]
+pub use core::option::Option;
+
+#[doc(hidden)]
+pub type Delimiter = proc_macro2::Delimiter;
+#[doc(hidden)]
+pub type Span = proc_macro2::Span;
+#[doc(hidden)]
+pub type TokenStream = proc_macro2::TokenStream;
+
+#[doc(hidden)]
+pub struct HasIterator; // True
+#[doc(hidden)]
+pub struct ThereIsNoIteratorInRepetition; // False
+
+impl BitOr<ThereIsNoIteratorInRepetition> for ThereIsNoIteratorInRepetition {
+ type Output = ThereIsNoIteratorInRepetition;
+ fn bitor(self, _rhs: ThereIsNoIteratorInRepetition) -> ThereIsNoIteratorInRepetition {
+ ThereIsNoIteratorInRepetition
+ }
+}
+
+impl BitOr<ThereIsNoIteratorInRepetition> for HasIterator {
+ type Output = HasIterator;
+ fn bitor(self, _rhs: ThereIsNoIteratorInRepetition) -> HasIterator {
+ HasIterator
+ }
+}
+
+impl BitOr<HasIterator> for ThereIsNoIteratorInRepetition {
+ type Output = HasIterator;
+ fn bitor(self, _rhs: HasIterator) -> HasIterator {
+ HasIterator
+ }
+}
+
+impl BitOr<HasIterator> for HasIterator {
+ type Output = HasIterator;
+ fn bitor(self, _rhs: HasIterator) -> HasIterator {
+ HasIterator
+ }
+}
+
+/// Extension traits used by the implementation of `quote!`. These are defined
+/// in separate traits, rather than as a single trait due to ambiguity issues.
+///
+/// These traits expose a `quote_into_iter` method which should allow calling
+/// whichever impl happens to be applicable. Calling that method repeatedly on
+/// the returned value should be idempotent.
+#[doc(hidden)]
+pub mod ext {
+ use super::RepInterp;
+ use super::{HasIterator as HasIter, ThereIsNoIteratorInRepetition as DoesNotHaveIter};
+ use crate::ToTokens;
+ use alloc::collections::btree_set::{self, BTreeSet};
+ use core::slice;
+
+ /// Extension trait providing the `quote_into_iter` method on iterators.
+ #[doc(hidden)]
+ pub trait RepIteratorExt: Iterator + Sized {
+ fn quote_into_iter(self) -> (Self, HasIter) {
+ (self, HasIter)
+ }
+ }
+
+ impl<T: Iterator> RepIteratorExt for T {}
+
+ /// Extension trait providing the `quote_into_iter` method for
+ /// non-iterable types. These types interpolate the same value in each
+ /// iteration of the repetition.
+ #[doc(hidden)]
+ pub trait RepToTokensExt {
+ /// Pretend to be an iterator for the purposes of `quote_into_iter`.
+ /// This allows repeated calls to `quote_into_iter` to continue
+ /// correctly returning DoesNotHaveIter.
+ fn next(&self) -> Option<&Self> {
+ Some(self)
+ }
+
+ fn quote_into_iter(&self) -> (&Self, DoesNotHaveIter) {
+ (self, DoesNotHaveIter)
+ }
+ }
+
+ impl<T: ToTokens + ?Sized> RepToTokensExt for T {}
+
+ /// Extension trait providing the `quote_into_iter` method for types that
+ /// can be referenced as an iterator.
+ #[doc(hidden)]
+ pub trait RepAsIteratorExt<'q> {
+ type Iter: Iterator;
+
+ fn quote_into_iter(&'q self) -> (Self::Iter, HasIter);
+ }
+
+ impl<'q, T: RepAsIteratorExt<'q> + ?Sized> RepAsIteratorExt<'q> for &T {
+ type Iter = T::Iter;
+
+ fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
+ <T as RepAsIteratorExt>::quote_into_iter(*self)
+ }
+ }
+
+ impl<'q, T: RepAsIteratorExt<'q> + ?Sized> RepAsIteratorExt<'q> for &mut T {
+ type Iter = T::Iter;
+
+ fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
+ <T as RepAsIteratorExt>::quote_into_iter(*self)
+ }
+ }
+
+ impl<'q, T: 'q> RepAsIteratorExt<'q> for [T] {
+ type Iter = slice::Iter<'q, T>;
+
+ fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
+ (self.iter(), HasIter)
+ }
+ }
+
+ impl<'q, T: 'q, const N: usize> RepAsIteratorExt<'q> for [T; N] {
+ type Iter = slice::Iter<'q, T>;
+
+ fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
+ (self.iter(), HasIter)
+ }
+ }
+
+ impl<'q, T: 'q> RepAsIteratorExt<'q> for Vec<T> {
+ type Iter = slice::Iter<'q, T>;
+
+ fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
+ (self.iter(), HasIter)
+ }
+ }
+
+ impl<'q, T: 'q> RepAsIteratorExt<'q> for BTreeSet<T> {
+ type Iter = btree_set::Iter<'q, T>;
+
+ fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
+ (self.iter(), HasIter)
+ }
+ }
+
+ impl<'q, T: RepAsIteratorExt<'q>> RepAsIteratorExt<'q> for RepInterp<T> {
+ type Iter = T::Iter;
+
+ fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
+ self.0.quote_into_iter()
+ }
+ }
+}
+
+// Helper type used within interpolations to allow for repeated binding names.
+// Implements the relevant traits, and exports a dummy `next()` method.
+#[derive(Copy, Clone)]
+#[doc(hidden)]
+pub struct RepInterp<T>(pub T);
+
+impl<T> RepInterp<T> {
+ // This method is intended to look like `Iterator::next`, and is called when
+ // a name is bound multiple times, as the previous binding will shadow the
+ // original `Iterator` object. This allows us to avoid advancing the
+ // iterator multiple times per iteration.
+ pub fn next(self) -> Option<T> {
+ Some(self.0)
+ }
+}
+
+impl<T: Iterator> Iterator for RepInterp<T> {
+ type Item = T::Item;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.0.next()
+ }
+}
+
+impl<T: ToTokens> ToTokens for RepInterp<T> {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.0.to_tokens(tokens);
+ }
+}
+
+#[doc(hidden)]
+#[inline]
+pub fn get_span<T>(span: T) -> GetSpan<T> {
+ GetSpan(GetSpanInner(GetSpanBase(span)))
+}
+
+mod get_span {
+ use core::ops::Deref;
+ use proc_macro2::extra::DelimSpan;
+ use proc_macro2::Span;
+
+ pub struct GetSpan<T>(pub(crate) GetSpanInner<T>);
+
+ pub struct GetSpanInner<T>(pub(crate) GetSpanBase<T>);
+
+ pub struct GetSpanBase<T>(pub(crate) T);
+
+ impl GetSpan<Span> {
+ #[inline]
+ pub fn __into_span(self) -> Span {
+ ((self.0).0).0
+ }
+ }
+
+ impl GetSpanInner<DelimSpan> {
+ #[inline]
+ pub fn __into_span(&self) -> Span {
+ (self.0).0.join()
+ }
+ }
+
+ impl<T> GetSpanBase<T> {
+ #[allow(clippy::unused_self)]
+ pub fn __into_span(&self) -> T {
+ unreachable!()
+ }
+ }
+
+ impl<T> Deref for GetSpan<T> {
+ type Target = GetSpanInner<T>;
+
+ #[inline]
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+ }
+
+ impl<T> Deref for GetSpanInner<T> {
+ type Target = GetSpanBase<T>;
+
+ #[inline]
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+ }
+}
+
+#[doc(hidden)]
+pub fn push_group(tokens: &mut TokenStream, delimiter: Delimiter, inner: TokenStream) {
+ tokens.append(Group::new(delimiter, inner));
+}
+
+#[doc(hidden)]
+pub fn push_group_spanned(
+ tokens: &mut TokenStream,
+ span: Span,
+ delimiter: Delimiter,
+ inner: TokenStream,
+) {
+ let mut g = Group::new(delimiter, inner);
+ g.set_span(span);
+ tokens.append(g);
+}
+
+#[doc(hidden)]
+pub fn parse(tokens: &mut TokenStream, s: &str) {
+ let s: TokenStream = s.parse().expect("invalid token stream");
+ tokens.extend(iter::once(s));
+}
+
+#[doc(hidden)]
+pub fn parse_spanned(tokens: &mut TokenStream, span: Span, s: &str) {
+ let s: TokenStream = s.parse().expect("invalid token stream");
+ tokens.extend(s.into_iter().map(|t| respan_token_tree(t, span)));
+}
+
+// Token tree with every span replaced by the given one.
+fn respan_token_tree(mut token: TokenTree, span: Span) -> TokenTree {
+ match &mut token {
+ TokenTree::Group(g) => {
+ let stream = g
+ .stream()
+ .into_iter()
+ .map(|token| respan_token_tree(token, span))
+ .collect();
+ *g = Group::new(g.delimiter(), stream);
+ g.set_span(span);
+ }
+ other => other.set_span(span),
+ }
+ token
+}
+
+#[doc(hidden)]
+pub fn push_ident(tokens: &mut TokenStream, s: &str) {
+ let span = Span::call_site();
+ push_ident_spanned(tokens, span, s);
+}
+
+#[doc(hidden)]
+pub fn push_ident_spanned(tokens: &mut TokenStream, span: Span, s: &str) {
+ tokens.append(ident_maybe_raw(s, span));
+}
+
+#[doc(hidden)]
+pub fn push_lifetime(tokens: &mut TokenStream, lifetime: &str) {
+ tokens.extend([
+ TokenTree::Punct(Punct::new('\'', Spacing::Joint)),
+ TokenTree::Ident(Ident::new(&lifetime[1..], Span::call_site())),
+ ]);
+}
+
+#[doc(hidden)]
+pub fn push_lifetime_spanned(tokens: &mut TokenStream, span: Span, lifetime: &str) {
+ tokens.extend([
+ TokenTree::Punct({
+ let mut apostrophe = Punct::new('\'', Spacing::Joint);
+ apostrophe.set_span(span);
+ apostrophe
+ }),
+ TokenTree::Ident(Ident::new(&lifetime[1..], span)),
+ ]);
+}
+
+macro_rules! push_punct {
+ ($name:ident $spanned:ident $char1:tt) => {
+ #[doc(hidden)]
+ pub fn $name(tokens: &mut TokenStream) {
+ tokens.append(Punct::new($char1, Spacing::Alone));
+ }
+ #[doc(hidden)]
+ pub fn $spanned(tokens: &mut TokenStream, span: Span) {
+ let mut punct = Punct::new($char1, Spacing::Alone);
+ punct.set_span(span);
+ tokens.append(punct);
+ }
+ };
+ ($name:ident $spanned:ident $char1:tt $char2:tt) => {
+ #[doc(hidden)]
+ pub fn $name(tokens: &mut TokenStream) {
+ tokens.append(Punct::new($char1, Spacing::Joint));
+ tokens.append(Punct::new($char2, Spacing::Alone));
+ }
+ #[doc(hidden)]
+ pub fn $spanned(tokens: &mut TokenStream, span: Span) {
+ let mut punct = Punct::new($char1, Spacing::Joint);
+ punct.set_span(span);
+ tokens.append(punct);
+ let mut punct = Punct::new($char2, Spacing::Alone);
+ punct.set_span(span);
+ tokens.append(punct);
+ }
+ };
+ ($name:ident $spanned:ident $char1:tt $char2:tt $char3:tt) => {
+ #[doc(hidden)]
+ pub fn $name(tokens: &mut TokenStream) {
+ tokens.append(Punct::new($char1, Spacing::Joint));
+ tokens.append(Punct::new($char2, Spacing::Joint));
+ tokens.append(Punct::new($char3, Spacing::Alone));
+ }
+ #[doc(hidden)]
+ pub fn $spanned(tokens: &mut TokenStream, span: Span) {
+ let mut punct = Punct::new($char1, Spacing::Joint);
+ punct.set_span(span);
+ tokens.append(punct);
+ let mut punct = Punct::new($char2, Spacing::Joint);
+ punct.set_span(span);
+ tokens.append(punct);
+ let mut punct = Punct::new($char3, Spacing::Alone);
+ punct.set_span(span);
+ tokens.append(punct);
+ }
+ };
+}
+
+push_punct!(push_add push_add_spanned '+');
+push_punct!(push_add_eq push_add_eq_spanned '+' '=');
+push_punct!(push_and push_and_spanned '&');
+push_punct!(push_and_and push_and_and_spanned '&' '&');
+push_punct!(push_and_eq push_and_eq_spanned '&' '=');
+push_punct!(push_at push_at_spanned '@');
+push_punct!(push_bang push_bang_spanned '!');
+push_punct!(push_caret push_caret_spanned '^');
+push_punct!(push_caret_eq push_caret_eq_spanned '^' '=');
+push_punct!(push_colon push_colon_spanned ':');
+push_punct!(push_colon2 push_colon2_spanned ':' ':');
+push_punct!(push_comma push_comma_spanned ',');
+push_punct!(push_div push_div_spanned '/');
+push_punct!(push_div_eq push_div_eq_spanned '/' '=');
+push_punct!(push_dot push_dot_spanned '.');
+push_punct!(push_dot2 push_dot2_spanned '.' '.');
+push_punct!(push_dot3 push_dot3_spanned '.' '.' '.');
+push_punct!(push_dot_dot_eq push_dot_dot_eq_spanned '.' '.' '=');
+push_punct!(push_eq push_eq_spanned '=');
+push_punct!(push_eq_eq push_eq_eq_spanned '=' '=');
+push_punct!(push_ge push_ge_spanned '>' '=');
+push_punct!(push_gt push_gt_spanned '>');
+push_punct!(push_le push_le_spanned '<' '=');
+push_punct!(push_lt push_lt_spanned '<');
+push_punct!(push_mul_eq push_mul_eq_spanned '*' '=');
+push_punct!(push_ne push_ne_spanned '!' '=');
+push_punct!(push_or push_or_spanned '|');
+push_punct!(push_or_eq push_or_eq_spanned '|' '=');
+push_punct!(push_or_or push_or_or_spanned '|' '|');
+push_punct!(push_pound push_pound_spanned '#');
+push_punct!(push_question push_question_spanned '?');
+push_punct!(push_rarrow push_rarrow_spanned '-' '>');
+push_punct!(push_larrow push_larrow_spanned '<' '-');
+push_punct!(push_rem push_rem_spanned '%');
+push_punct!(push_rem_eq push_rem_eq_spanned '%' '=');
+push_punct!(push_fat_arrow push_fat_arrow_spanned '=' '>');
+push_punct!(push_semi push_semi_spanned ';');
+push_punct!(push_shl push_shl_spanned '<' '<');
+push_punct!(push_shl_eq push_shl_eq_spanned '<' '<' '=');
+push_punct!(push_shr push_shr_spanned '>' '>');
+push_punct!(push_shr_eq push_shr_eq_spanned '>' '>' '=');
+push_punct!(push_star push_star_spanned '*');
+push_punct!(push_sub push_sub_spanned '-');
+push_punct!(push_sub_eq push_sub_eq_spanned '-' '=');
+
+#[doc(hidden)]
+pub fn push_underscore(tokens: &mut TokenStream) {
+ push_underscore_spanned(tokens, Span::call_site());
+}
+
+#[doc(hidden)]
+pub fn push_underscore_spanned(tokens: &mut TokenStream, span: Span) {
+ tokens.append(Ident::new("_", span));
+}
+
+// Helper method for constructing identifiers from the `format_ident!` macro,
+// handling `r#` prefixes.
+#[doc(hidden)]
+pub fn mk_ident(id: &str, span: Option<Span>) -> Ident {
+ let span = span.unwrap_or_else(Span::call_site);
+ ident_maybe_raw(id, span)
+}
+
+fn ident_maybe_raw(id: &str, span: Span) -> Ident {
+ if let Some(id) = id.strip_prefix("r#") {
+ Ident::new_raw(id, span)
+ } else {
+ Ident::new(id, span)
+ }
+}
+
+// Adapts from `IdentFragment` to `fmt::Display` for use by the `format_ident!`
+// macro, and exposes span information from these fragments.
+//
+// This struct also has forwarding implementations of the formatting traits
+// `Octal`, `LowerHex`, `UpperHex`, and `Binary` to allow for their use within
+// `format_ident!`.
+#[derive(Copy, Clone)]
+#[doc(hidden)]
+pub struct IdentFragmentAdapter<T: IdentFragment>(pub T);
+
+impl<T: IdentFragment> IdentFragmentAdapter<T> {
+ pub fn span(&self) -> Option<Span> {
+ self.0.span()
+ }
+}
+
+impl<T: IdentFragment> fmt::Display for IdentFragmentAdapter<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ IdentFragment::fmt(&self.0, f)
+ }
+}
+
+impl<T: IdentFragment + fmt::Octal> fmt::Octal for IdentFragmentAdapter<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Octal::fmt(&self.0, f)
+ }
+}
+
+impl<T: IdentFragment + fmt::LowerHex> fmt::LowerHex for IdentFragmentAdapter<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fmt::LowerHex::fmt(&self.0, f)
+ }
+}
+
+impl<T: IdentFragment + fmt::UpperHex> fmt::UpperHex for IdentFragmentAdapter<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fmt::UpperHex::fmt(&self.0, f)
+ }
+}
+
+impl<T: IdentFragment + fmt::Binary> fmt::Binary for IdentFragmentAdapter<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Binary::fmt(&self.0, f)
+ }
+}
diff --git a/rust/quote/spanned.rs b/rust/quote/spanned.rs
new file mode 100644
index 000000000000..6eba64445d89
--- /dev/null
+++ b/rust/quote/spanned.rs
@@ -0,0 +1,50 @@
+use crate::ToTokens;
+use proc_macro2::extra::DelimSpan;
+use proc_macro2::{Span, TokenStream};
+
+// Not public API other than via the syn crate. Use syn::spanned::Spanned.
+pub trait Spanned: private::Sealed {
+ fn __span(&self) -> Span;
+}
+
+impl Spanned for Span {
+ fn __span(&self) -> Span {
+ *self
+ }
+}
+
+impl Spanned for DelimSpan {
+ fn __span(&self) -> Span {
+ self.join()
+ }
+}
+
+impl<T: ?Sized + ToTokens> Spanned for T {
+ fn __span(&self) -> Span {
+ join_spans(self.into_token_stream())
+ }
+}
+
+fn join_spans(tokens: TokenStream) -> Span {
+ let mut iter = tokens.into_iter().map(|tt| tt.span());
+
+ let first = match iter.next() {
+ Some(span) => span,
+ None => return Span::call_site(),
+ };
+
+ iter.fold(None, |_prev, next| Some(next))
+ .and_then(|last| first.join(last))
+ .unwrap_or(first)
+}
+
+mod private {
+ use crate::ToTokens;
+ use proc_macro2::extra::DelimSpan;
+ use proc_macro2::Span;
+
+ pub trait Sealed {}
+ impl Sealed for Span {}
+ impl Sealed for DelimSpan {}
+ impl<T: ?Sized + ToTokens> Sealed for T {}
+}
diff --git a/rust/quote/to_tokens.rs b/rust/quote/to_tokens.rs
new file mode 100644
index 000000000000..f373092b650f
--- /dev/null
+++ b/rust/quote/to_tokens.rs
@@ -0,0 +1,271 @@
+use super::TokenStreamExt;
+use alloc::borrow::Cow;
+use alloc::rc::Rc;
+use core::iter;
+use proc_macro2::{Group, Ident, Literal, Punct, Span, TokenStream, TokenTree};
+use std::ffi::{CStr, CString};
+
+/// Types that can be interpolated inside a `quote!` invocation.
+pub trait ToTokens {
+ /// Write `self` to the given `TokenStream`.
+ ///
+ /// The token append methods provided by the [`TokenStreamExt`] extension
+ /// trait may be useful for implementing `ToTokens`.
+ ///
+ /// # Example
+ ///
+ /// Example implementation for a struct representing Rust paths like
+ /// `std::cmp::PartialEq`:
+ ///
+ /// ```
+ /// use proc_macro2::{TokenTree, Spacing, Span, Punct, TokenStream};
+ /// use quote::{TokenStreamExt, ToTokens};
+ ///
+ /// pub struct Path {
+ /// pub global: bool,
+ /// pub segments: Vec<PathSegment>,
+ /// }
+ ///
+ /// impl ToTokens for Path {
+ /// fn to_tokens(&self, tokens: &mut TokenStream) {
+ /// for (i, segment) in self.segments.iter().enumerate() {
+ /// if i > 0 || self.global {
+ /// // Double colon `::`
+ /// tokens.append(Punct::new(':', Spacing::Joint));
+ /// tokens.append(Punct::new(':', Spacing::Alone));
+ /// }
+ /// segment.to_tokens(tokens);
+ /// }
+ /// }
+ /// }
+ /// #
+ /// # pub struct PathSegment;
+ /// #
+ /// # impl ToTokens for PathSegment {
+ /// # fn to_tokens(&self, tokens: &mut TokenStream) {
+ /// # unimplemented!()
+ /// # }
+ /// # }
+ /// ```
+ fn to_tokens(&self, tokens: &mut TokenStream);
+
+ /// Convert `self` directly into a `TokenStream` object.
+ ///
+ /// This method is implicitly implemented using `to_tokens`, and acts as a
+ /// convenience method for consumers of the `ToTokens` trait.
+ fn to_token_stream(&self) -> TokenStream {
+ let mut tokens = TokenStream::new();
+ self.to_tokens(&mut tokens);
+ tokens
+ }
+
+ /// Convert `self` directly into a `TokenStream` object.
+ ///
+ /// This method is implicitly implemented using `to_tokens`, and acts as a
+ /// convenience method for consumers of the `ToTokens` trait.
+ fn into_token_stream(self) -> TokenStream
+ where
+ Self: Sized,
+ {
+ self.to_token_stream()
+ }
+}
+
+impl<T: ?Sized + ToTokens> ToTokens for &T {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ (**self).to_tokens(tokens);
+ }
+}
+
+impl<T: ?Sized + ToTokens> ToTokens for &mut T {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ (**self).to_tokens(tokens);
+ }
+}
+
+impl<'a, T: ?Sized + ToOwned + ToTokens> ToTokens for Cow<'a, T> {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ (**self).to_tokens(tokens);
+ }
+}
+
+impl<T: ?Sized + ToTokens> ToTokens for Box<T> {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ (**self).to_tokens(tokens);
+ }
+}
+
+impl<T: ?Sized + ToTokens> ToTokens for Rc<T> {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ (**self).to_tokens(tokens);
+ }
+}
+
+impl<T: ToTokens> ToTokens for Option<T> {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ if let Some(t) = self {
+ t.to_tokens(tokens);
+ }
+ }
+}
+
+impl ToTokens for str {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append(Literal::string(self));
+ }
+}
+
+impl ToTokens for String {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.as_str().to_tokens(tokens);
+ }
+}
+
+impl ToTokens for i8 {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append(Literal::i8_suffixed(*self));
+ }
+}
+
+impl ToTokens for i16 {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append(Literal::i16_suffixed(*self));
+ }
+}
+
+impl ToTokens for i32 {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append(Literal::i32_suffixed(*self));
+ }
+}
+
+impl ToTokens for i64 {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append(Literal::i64_suffixed(*self));
+ }
+}
+
+impl ToTokens for i128 {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append(Literal::i128_suffixed(*self));
+ }
+}
+
+impl ToTokens for isize {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append(Literal::isize_suffixed(*self));
+ }
+}
+
+impl ToTokens for u8 {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append(Literal::u8_suffixed(*self));
+ }
+}
+
+impl ToTokens for u16 {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append(Literal::u16_suffixed(*self));
+ }
+}
+
+impl ToTokens for u32 {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append(Literal::u32_suffixed(*self));
+ }
+}
+
+impl ToTokens for u64 {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append(Literal::u64_suffixed(*self));
+ }
+}
+
+impl ToTokens for u128 {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append(Literal::u128_suffixed(*self));
+ }
+}
+
+impl ToTokens for usize {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append(Literal::usize_suffixed(*self));
+ }
+}
+
+impl ToTokens for f32 {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append(Literal::f32_suffixed(*self));
+ }
+}
+
+impl ToTokens for f64 {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append(Literal::f64_suffixed(*self));
+ }
+}
+
+impl ToTokens for char {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append(Literal::character(*self));
+ }
+}
+
+impl ToTokens for bool {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ let word = if *self { "true" } else { "false" };
+ tokens.append(Ident::new(word, Span::call_site()));
+ }
+}
+
+impl ToTokens for CStr {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append(Literal::c_string(self));
+ }
+}
+
+impl ToTokens for CString {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append(Literal::c_string(self));
+ }
+}
+
+impl ToTokens for Group {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append(self.clone());
+ }
+}
+
+impl ToTokens for Ident {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append(self.clone());
+ }
+}
+
+impl ToTokens for Punct {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append(self.clone());
+ }
+}
+
+impl ToTokens for Literal {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append(self.clone());
+ }
+}
+
+impl ToTokens for TokenTree {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append(self.clone());
+ }
+}
+
+impl ToTokens for TokenStream {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.extend(iter::once(self.clone()));
+ }
+
+ fn into_token_stream(self) -> TokenStream {
+ self
+ }
+}
--
2.51.2
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH 11/18] rust: quote: add SPDX License Identifiers
2025-11-10 9:50 [PATCH 00/18] `syn` support Miguel Ojeda
` (9 preceding siblings ...)
2025-11-10 9:50 ` [PATCH 10/18] rust: quote: import crate Miguel Ojeda
@ 2025-11-10 9:50 ` Miguel Ojeda
2025-11-10 9:50 ` [PATCH 12/18] rust: quote: add `README.md` Miguel Ojeda
` (8 subsequent siblings)
19 siblings, 0 replies; 57+ messages in thread
From: Miguel Ojeda @ 2025-11-10 9:50 UTC (permalink / raw)
To: Miguel Ojeda, Alex Gaynor, Nathan Chancellor, Nicolas Schier
Cc: Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
rust-for-linux, linux-kbuild, linux-kernel, patches
Originally, 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.
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
---
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(+)
diff --git a/rust/quote/ext.rs b/rust/quote/ext.rs
index 92c2315b182d..977d2f0c5919 100644
--- a/rust/quote/ext.rs
+++ b/rust/quote/ext.rs
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
use super::ToTokens;
use core::iter;
use proc_macro2::{TokenStream, TokenTree};
diff --git a/rust/quote/format.rs b/rust/quote/format.rs
index ec0bbf38ba37..6e3d55b6e427 100644
--- a/rust/quote/format.rs
+++ b/rust/quote/format.rs
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
/// Formatting macro for constructing `Ident`s.
///
/// <br>
diff --git a/rust/quote/ident_fragment.rs b/rust/quote/ident_fragment.rs
index 6c2a9a87acb4..d98106f17666 100644
--- a/rust/quote/ident_fragment.rs
+++ b/rust/quote/ident_fragment.rs
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
use alloc::borrow::Cow;
use core::fmt;
use proc_macro2::{Ident, Span};
diff --git a/rust/quote/lib.rs b/rust/quote/lib.rs
index 0a12d607f279..cc1637660a75 100644
--- a/rust/quote/lib.rs
+++ b/rust/quote/lib.rs
@@ -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
diff --git a/rust/quote/runtime.rs b/rust/quote/runtime.rs
index c704ca89411f..09a94f5dd4fe 100644
--- a/rust/quote/runtime.rs
+++ b/rust/quote/runtime.rs
@@ -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;
diff --git a/rust/quote/spanned.rs b/rust/quote/spanned.rs
index 6eba64445d89..54ce9177f45e 100644
--- a/rust/quote/spanned.rs
+++ b/rust/quote/spanned.rs
@@ -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};
diff --git a/rust/quote/to_tokens.rs b/rust/quote/to_tokens.rs
index f373092b650f..1af1089e1423 100644
--- a/rust/quote/to_tokens.rs
+++ b/rust/quote/to_tokens.rs
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
use super::TokenStreamExt;
use alloc::borrow::Cow;
use alloc::rc::Rc;
--
2.51.2
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH 12/18] rust: quote: add `README.md`
2025-11-10 9:50 [PATCH 00/18] `syn` support Miguel Ojeda
` (10 preceding siblings ...)
2025-11-10 9:50 ` [PATCH 11/18] rust: quote: add SPDX License Identifiers Miguel Ojeda
@ 2025-11-10 9:50 ` Miguel Ojeda
2025-11-10 9:50 ` [PATCH 13/18] rust: quote: enable support in kbuild Miguel Ojeda
` (7 subsequent siblings)
19 siblings, 0 replies; 57+ messages in thread
From: Miguel Ojeda @ 2025-11-10 9:50 UTC (permalink / raw)
To: Miguel Ojeda, Alex Gaynor, Nathan Chancellor, Nicolas Schier
Cc: Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
rust-for-linux, linux-kbuild, linux-kernel, patches
Originally, 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.
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
---
rust/quote/README.md | 12 ++++++++++++
1 file changed, 12 insertions(+)
create mode 100644 rust/quote/README.md
diff --git a/rust/quote/README.md b/rust/quote/README.md
new file mode 100644
index 000000000000..186123eff1cb
--- /dev/null
+++ b/rust/quote/README.md
@@ -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
--
2.51.2
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH 13/18] rust: quote: enable support in kbuild
2025-11-10 9:50 [PATCH 00/18] `syn` support Miguel Ojeda
` (11 preceding siblings ...)
2025-11-10 9:50 ` [PATCH 12/18] rust: quote: add `README.md` Miguel Ojeda
@ 2025-11-10 9:50 ` Miguel Ojeda
2025-11-10 11:44 ` Alice Ryhl
2025-11-10 9:50 ` [PATCH 14/18] rust: syn: import crate Miguel Ojeda
` (6 subsequent siblings)
19 siblings, 1 reply; 57+ messages in thread
From: Miguel Ojeda @ 2025-11-10 9:50 UTC (permalink / raw)
To: Miguel Ojeda, Alex Gaynor, Nathan Chancellor, Nicolas Schier
Cc: Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
rust-for-linux, linux-kbuild, linux-kernel, patches
With all the new files in place and ready from the new crate, enable
the support for it in the build system.
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
---
Makefile | 1 +
rust/Makefile | 42 +++++++++++++++++++++++++++----
scripts/generate_rust_analyzer.py | 7 ++++++
3 files changed, 45 insertions(+), 5 deletions(-)
diff --git a/Makefile b/Makefile
index 6ff887523eee..f1b38b7fed1e 100644
--- a/Makefile
+++ b/Makefile
@@ -1832,6 +1832,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)
diff --git a/rust/Makefile b/rust/Makefile
index a614a23023cb..801a8cbf3bdd 100644
--- a/rust/Makefile
+++ b/rust/Makefile
@@ -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)
@@ -146,10 +158,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
@@ -199,8 +218,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 \
@@ -216,6 +235,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
@@ -467,6 +491,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_hostlibrary)
+$(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_hostlibrary)
+
quiet_cmd_rustc_procmacro = $(RUSTC_OR_CLIPPY_QUIET) P $@
cmd_rustc_procmacro = \
$(RUSTC_OR_CLIPPY) $(rust_common_flags) $(rustc_target_flags) \
@@ -478,7 +508,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
@@ -502,6 +533,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
diff --git a/scripts/generate_rust_analyzer.py b/scripts/generate_rust_analyzer.py
index 00c6b7cc94b7..4faf153ed2ee 100755
--- a/scripts/generate_rust_analyzer.py
+++ b/scripts/generate_rust_analyzer.py
@@ -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",
--
2.51.2
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH 14/18] rust: syn: import crate
2025-11-10 9:50 [PATCH 00/18] `syn` support Miguel Ojeda
` (12 preceding siblings ...)
2025-11-10 9:50 ` [PATCH 13/18] rust: quote: enable support in kbuild Miguel Ojeda
@ 2025-11-10 9:50 ` Miguel Ojeda
2025-11-10 10:26 ` Miguel Ojeda
2025-11-10 9:50 ` [PATCH 15/18] rust: syn: add SPDX License Identifiers Miguel Ojeda
` (5 subsequent siblings)
19 siblings, 1 reply; 57+ messages in thread
From: Miguel Ojeda @ 2025-11-10 9:50 UTC (permalink / raw)
To: Miguel Ojeda, Alex Gaynor, Nathan Chancellor, Nicolas Schier
Cc: Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
rust-for-linux, linux-kbuild, linux-kernel, patches
This 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
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
---
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
diff --git a/rust/syn/attr.rs b/rust/syn/attr.rs
new file mode 100644
index 000000000000..2bdf96ee7fa9
--- /dev/null
+++ b/rust/syn/attr.rs
@@ -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 = &'a Attribute>;
+
+ 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 &'a AttrStyle);
+
+ 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 &'a Path);
+
+ 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);
+ }
+ }
+}
diff --git a/rust/syn/bigint.rs b/rust/syn/bigint.rs
new file mode 100644
index 000000000000..66aaa9372540
--- /dev/null
+++ b/rust/syn/bigint.rs
@@ -0,0 +1,66 @@
+use std::ops::{AddAssign, MulAssign};
+
+// For implementing base10_digits() accessor on LitInt.
+pub(crate) struct BigInt {
+ digits: Vec<u8>,
+}
+
+impl BigInt {
+ pub(crate) fn new() -> Self {
+ BigInt { digits: Vec::new() }
+ }
+
+ pub(crate) fn to_string(&self) -> String {
+ let mut repr = String::with_capacity(self.digits.len());
+
+ let mut has_nonzero = false;
+ for digit in self.digits.iter().rev() {
+ has_nonzero |= *digit != 0;
+ if has_nonzero {
+ repr.push((*digit + b'0') as char);
+ }
+ }
+
+ if repr.is_empty() {
+ repr.push('0');
+ }
+
+ repr
+ }
+
+ fn reserve_two_digits(&mut self) {
+ let len = self.digits.len();
+ let desired =
+ len + !self.digits.ends_with(&[0, 0]) as usize + !self.digits.ends_with(&[0]) as usize;
+ self.digits.resize(desired, 0);
+ }
+}
+
+impl AddAssign<u8> for BigInt {
+ // Assumes increment <16.
+ fn add_assign(&mut self, mut increment: u8) {
+ self.reserve_two_digits();
+
+ let mut i = 0;
+ while increment > 0 {
+ let sum = self.digits[i] + increment;
+ self.digits[i] = sum % 10;
+ increment = sum / 10;
+ i += 1;
+ }
+ }
+}
+
+impl MulAssign<u8> for BigInt {
+ // Assumes base <=16.
+ fn mul_assign(&mut self, base: u8) {
+ self.reserve_two_digits();
+
+ let mut carry = 0;
+ for digit in &mut self.digits {
+ let prod = *digit * base + carry;
+ *digit = prod % 10;
+ carry = prod / 10;
+ }
+ }
+}
diff --git a/rust/syn/buffer.rs b/rust/syn/buffer.rs
new file mode 100644
index 000000000000..7b6a504eeb7c
--- /dev/null
+++ b/rust/syn/buffer.rs
@@ -0,0 +1,434 @@
+//! A stably addressed token buffer supporting efficient traversal based on a
+//! cheaply copyable cursor.
+
+// This module is heavily commented as it contains most of the unsafe code in
+// Syn, and caution should be used when editing it. The public-facing interface
+// is 100% safe but the implementation is fragile internally.
+
+use crate::Lifetime;
+use proc_macro2::extra::DelimSpan;
+use proc_macro2::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
+use std::cmp::Ordering;
+use std::marker::PhantomData;
+use std::ptr;
+
+/// Internal type which is used instead of `TokenTree` to represent a token tree
+/// within a `TokenBuffer`.
+enum Entry {
+ // Mimicking types from proc-macro.
+ // Group entries contain the offset to the matching End entry.
+ Group(Group, usize),
+ Ident(Ident),
+ Punct(Punct),
+ Literal(Literal),
+ // End entries contain the offset (negative) to the start of the buffer, and
+ // offset (negative) to the matching Group entry.
+ End(isize, isize),
+}
+
+/// A buffer that can be efficiently traversed multiple times, unlike
+/// `TokenStream` which requires a deep copy in order to traverse more than
+/// once.
+pub struct TokenBuffer {
+ // NOTE: Do not implement clone on this - while the current design could be
+ // cloned, other designs which could be desirable may not be cloneable.
+ entries: Box<[Entry]>,
+}
+
+impl TokenBuffer {
+ fn recursive_new(entries: &mut Vec<Entry>, stream: TokenStream) {
+ for tt in stream {
+ match tt {
+ TokenTree::Ident(ident) => entries.push(Entry::Ident(ident)),
+ TokenTree::Punct(punct) => entries.push(Entry::Punct(punct)),
+ TokenTree::Literal(literal) => entries.push(Entry::Literal(literal)),
+ TokenTree::Group(group) => {
+ let group_start_index = entries.len();
+ entries.push(Entry::End(0, 0)); // we replace this below
+ Self::recursive_new(entries, group.stream());
+ let group_end_index = entries.len();
+ let group_offset = group_end_index - group_start_index;
+ entries.push(Entry::End(
+ -(group_end_index as isize),
+ -(group_offset as isize),
+ ));
+ entries[group_start_index] = Entry::Group(group, group_offset);
+ }
+ }
+ }
+ }
+
+ /// Creates a `TokenBuffer` containing all the tokens from the input
+ /// `proc_macro::TokenStream`.
+ #[cfg(feature = "proc-macro")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "proc-macro")))]
+ pub fn new(stream: proc_macro::TokenStream) -> Self {
+ Self::new2(stream.into())
+ }
+
+ /// Creates a `TokenBuffer` containing all the tokens from the input
+ /// `proc_macro2::TokenStream`.
+ pub fn new2(stream: TokenStream) -> Self {
+ let mut entries = Vec::new();
+ Self::recursive_new(&mut entries, stream);
+ entries.push(Entry::End(-(entries.len() as isize), 0));
+ Self {
+ entries: entries.into_boxed_slice(),
+ }
+ }
+
+ /// Creates a cursor referencing the first token in the buffer and able to
+ /// traverse until the end of the buffer.
+ pub fn begin(&self) -> Cursor {
+ let ptr = self.entries.as_ptr();
+ unsafe { Cursor::create(ptr, ptr.add(self.entries.len() - 1)) }
+ }
+}
+
+/// A cheaply copyable cursor into a `TokenBuffer`.
+///
+/// This cursor holds a shared reference into the immutable data which is used
+/// internally to represent a `TokenStream`, and can be efficiently manipulated
+/// and copied around.
+///
+/// An empty `Cursor` can be created directly, or one may create a `TokenBuffer`
+/// object and get a cursor to its first token with `begin()`.
+pub struct Cursor<'a> {
+ // The current entry which the `Cursor` is pointing at.
+ ptr: *const Entry,
+ // This is the only `Entry::End` object which this cursor is allowed to
+ // point at. All other `End` objects are skipped over in `Cursor::create`.
+ scope: *const Entry,
+ // Cursor is covariant in 'a. This field ensures that our pointers are still
+ // valid.
+ marker: PhantomData<&'a Entry>,
+}
+
+impl<'a> Cursor<'a> {
+ /// Creates a cursor referencing a static empty TokenStream.
+ pub fn empty() -> Self {
+ // It's safe in this situation for us to put an `Entry` object in global
+ // storage, despite it not actually being safe to send across threads
+ // (`Ident` is a reference into a thread-local table). This is because
+ // this entry never includes a `Ident` object.
+ //
+ // This wrapper struct allows us to break the rules and put a `Sync`
+ // object in global storage.
+ struct UnsafeSyncEntry(Entry);
+ unsafe impl Sync for UnsafeSyncEntry {}
+ static EMPTY_ENTRY: UnsafeSyncEntry = UnsafeSyncEntry(Entry::End(0, 0));
+
+ Cursor {
+ ptr: &EMPTY_ENTRY.0,
+ scope: &EMPTY_ENTRY.0,
+ marker: PhantomData,
+ }
+ }
+
+ /// This create method intelligently exits non-explicitly-entered
+ /// `None`-delimited scopes when the cursor reaches the end of them,
+ /// allowing for them to be treated transparently.
+ unsafe fn create(mut ptr: *const Entry, scope: *const Entry) -> Self {
+ // NOTE: If we're looking at a `End`, we want to advance the cursor
+ // past it, unless `ptr == scope`, which means that we're at the edge of
+ // our cursor's scope. We should only have `ptr != scope` at the exit
+ // from None-delimited groups entered with `ignore_none`.
+ while let Entry::End(..) = unsafe { &*ptr } {
+ if ptr::eq(ptr, scope) {
+ break;
+ }
+ ptr = unsafe { ptr.add(1) };
+ }
+
+ Cursor {
+ ptr,
+ scope,
+ marker: PhantomData,
+ }
+ }
+
+ /// Get the current entry.
+ fn entry(self) -> &'a Entry {
+ unsafe { &*self.ptr }
+ }
+
+ /// Bump the cursor to point at the next token after the current one. This
+ /// is undefined behavior if the cursor is currently looking at an
+ /// `Entry::End`.
+ ///
+ /// If the cursor is looking at an `Entry::Group`, the bumped cursor will
+ /// point at the first token in the group (with the same scope end).
+ unsafe fn bump_ignore_group(self) -> Cursor<'a> {
+ unsafe { Cursor::create(self.ptr.offset(1), self.scope) }
+ }
+
+ /// While the cursor is looking at a `None`-delimited group, move it to look
+ /// at the first token inside instead. If the group is empty, this will move
+ /// the cursor past the `None`-delimited group.
+ ///
+ /// WARNING: This mutates its argument.
+ fn ignore_none(&mut self) {
+ while let Entry::Group(group, _) = self.entry() {
+ if group.delimiter() == Delimiter::None {
+ unsafe { *self = self.bump_ignore_group() };
+ } else {
+ break;
+ }
+ }
+ }
+
+ /// Checks whether the cursor is currently pointing at the end of its valid
+ /// scope.
+ pub fn eof(self) -> bool {
+ // We're at eof if we're at the end of our scope.
+ ptr::eq(self.ptr, self.scope)
+ }
+
+ /// If the cursor is pointing at a `Ident`, returns it along with a cursor
+ /// pointing at the next `TokenTree`.
+ pub fn ident(mut self) -> Option<(Ident, Cursor<'a>)> {
+ self.ignore_none();
+ match self.entry() {
+ Entry::Ident(ident) => Some((ident.clone(), unsafe { self.bump_ignore_group() })),
+ _ => None,
+ }
+ }
+
+ /// If the cursor is pointing at a `Punct`, returns it along with a cursor
+ /// pointing at the next `TokenTree`.
+ pub fn punct(mut self) -> Option<(Punct, Cursor<'a>)> {
+ self.ignore_none();
+ match self.entry() {
+ Entry::Punct(punct) if punct.as_char() != '\'' => {
+ Some((punct.clone(), unsafe { self.bump_ignore_group() }))
+ }
+ _ => None,
+ }
+ }
+
+ /// If the cursor is pointing at a `Literal`, return it along with a cursor
+ /// pointing at the next `TokenTree`.
+ pub fn literal(mut self) -> Option<(Literal, Cursor<'a>)> {
+ self.ignore_none();
+ match self.entry() {
+ Entry::Literal(literal) => Some((literal.clone(), unsafe { self.bump_ignore_group() })),
+ _ => None,
+ }
+ }
+
+ /// If the cursor is pointing at a `Lifetime`, returns it along with a
+ /// cursor pointing at the next `TokenTree`.
+ pub fn lifetime(mut self) -> Option<(Lifetime, Cursor<'a>)> {
+ self.ignore_none();
+ match self.entry() {
+ Entry::Punct(punct) if punct.as_char() == '\'' && punct.spacing() == Spacing::Joint => {
+ let next = unsafe { self.bump_ignore_group() };
+ let (ident, rest) = next.ident()?;
+ let lifetime = Lifetime {
+ apostrophe: punct.span(),
+ ident,
+ };
+ Some((lifetime, rest))
+ }
+ _ => None,
+ }
+ }
+
+ /// If the cursor is pointing at a `Group` with the given delimiter, returns
+ /// a cursor into that group and one pointing to the next `TokenTree`.
+ pub fn group(mut self, delim: Delimiter) -> Option<(Cursor<'a>, DelimSpan, Cursor<'a>)> {
+ // If we're not trying to enter a none-delimited group, we want to
+ // ignore them. We have to make sure to _not_ ignore them when we want
+ // to enter them, of course. For obvious reasons.
+ if delim != Delimiter::None {
+ self.ignore_none();
+ }
+
+ if let Entry::Group(group, end_offset) = self.entry() {
+ if group.delimiter() == delim {
+ let span = group.delim_span();
+ let end_of_group = unsafe { self.ptr.add(*end_offset) };
+ let inside_of_group = unsafe { Cursor::create(self.ptr.add(1), end_of_group) };
+ let after_group = unsafe { Cursor::create(end_of_group, self.scope) };
+ return Some((inside_of_group, span, after_group));
+ }
+ }
+
+ None
+ }
+
+ /// If the cursor is pointing at a `Group`, returns a cursor into the group
+ /// and one pointing to the next `TokenTree`.
+ pub fn any_group(self) -> Option<(Cursor<'a>, Delimiter, DelimSpan, Cursor<'a>)> {
+ if let Entry::Group(group, end_offset) = self.entry() {
+ let delimiter = group.delimiter();
+ let span = group.delim_span();
+ let end_of_group = unsafe { self.ptr.add(*end_offset) };
+ let inside_of_group = unsafe { Cursor::create(self.ptr.add(1), end_of_group) };
+ let after_group = unsafe { Cursor::create(end_of_group, self.scope) };
+ return Some((inside_of_group, delimiter, span, after_group));
+ }
+
+ None
+ }
+
+ pub(crate) fn any_group_token(self) -> Option<(Group, Cursor<'a>)> {
+ if let Entry::Group(group, end_offset) = self.entry() {
+ let end_of_group = unsafe { self.ptr.add(*end_offset) };
+ let after_group = unsafe { Cursor::create(end_of_group, self.scope) };
+ return Some((group.clone(), after_group));
+ }
+
+ None
+ }
+
+ /// Copies all remaining tokens visible from this cursor into a
+ /// `TokenStream`.
+ pub fn token_stream(self) -> TokenStream {
+ let mut tts = Vec::new();
+ let mut cursor = self;
+ while let Some((tt, rest)) = cursor.token_tree() {
+ tts.push(tt);
+ cursor = rest;
+ }
+ tts.into_iter().collect()
+ }
+
+ /// If the cursor is pointing at a `TokenTree`, returns it along with a
+ /// cursor pointing at the next `TokenTree`.
+ ///
+ /// Returns `None` if the cursor has reached the end of its stream.
+ ///
+ /// This method does not treat `None`-delimited groups as transparent, and
+ /// will return a `Group(None, ..)` if the cursor is looking at one.
+ pub fn token_tree(self) -> Option<(TokenTree, Cursor<'a>)> {
+ let (tree, len) = match self.entry() {
+ Entry::Group(group, end_offset) => (group.clone().into(), *end_offset),
+ Entry::Literal(literal) => (literal.clone().into(), 1),
+ Entry::Ident(ident) => (ident.clone().into(), 1),
+ Entry::Punct(punct) => (punct.clone().into(), 1),
+ Entry::End(..) => return None,
+ };
+
+ let rest = unsafe { Cursor::create(self.ptr.add(len), self.scope) };
+ Some((tree, rest))
+ }
+
+ /// Returns the `Span` of the current token, or `Span::call_site()` if this
+ /// cursor points to eof.
+ pub fn span(mut self) -> Span {
+ match self.entry() {
+ Entry::Group(group, _) => group.span(),
+ Entry::Literal(literal) => literal.span(),
+ Entry::Ident(ident) => ident.span(),
+ Entry::Punct(punct) => punct.span(),
+ Entry::End(_, offset) => {
+ self.ptr = unsafe { self.ptr.offset(*offset) };
+ if let Entry::Group(group, _) = self.entry() {
+ group.span_close()
+ } else {
+ Span::call_site()
+ }
+ }
+ }
+ }
+
+ /// Returns the `Span` of the token immediately prior to the position of
+ /// this cursor, or of the current token if there is no previous one.
+ #[cfg(any(feature = "full", feature = "derive"))]
+ pub(crate) fn prev_span(mut self) -> Span {
+ if start_of_buffer(self) < self.ptr {
+ self.ptr = unsafe { self.ptr.offset(-1) };
+ }
+ self.span()
+ }
+
+ /// Skip over the next token that is not a None-delimited group, without
+ /// cloning it. Returns `None` if this cursor points to eof.
+ ///
+ /// This method treats `'lifetimes` as a single token.
+ pub(crate) fn skip(mut self) -> Option<Cursor<'a>> {
+ self.ignore_none();
+
+ let len = match self.entry() {
+ Entry::End(..) => return None,
+
+ // Treat lifetimes as a single tt for the purposes of 'skip'.
+ Entry::Punct(punct) if punct.as_char() == '\'' && punct.spacing() == Spacing::Joint => {
+ match unsafe { &*self.ptr.add(1) } {
+ Entry::Ident(_) => 2,
+ _ => 1,
+ }
+ }
+
+ Entry::Group(_, end_offset) => *end_offset,
+ _ => 1,
+ };
+
+ Some(unsafe { Cursor::create(self.ptr.add(len), self.scope) })
+ }
+
+ pub(crate) fn scope_delimiter(self) -> Delimiter {
+ match unsafe { &*self.scope } {
+ Entry::End(_, offset) => match unsafe { &*self.scope.offset(*offset) } {
+ Entry::Group(group, _) => group.delimiter(),
+ _ => Delimiter::None,
+ },
+ _ => unreachable!(),
+ }
+ }
+}
+
+impl<'a> Copy for Cursor<'a> {}
+
+impl<'a> Clone for Cursor<'a> {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+
+impl<'a> Eq for Cursor<'a> {}
+
+impl<'a> PartialEq for Cursor<'a> {
+ fn eq(&self, other: &Self) -> bool {
+ ptr::eq(self.ptr, other.ptr)
+ }
+}
+
+impl<'a> PartialOrd for Cursor<'a> {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ if same_buffer(*self, *other) {
+ Some(cmp_assuming_same_buffer(*self, *other))
+ } else {
+ None
+ }
+ }
+}
+
+pub(crate) fn same_scope(a: Cursor, b: Cursor) -> bool {
+ ptr::eq(a.scope, b.scope)
+}
+
+pub(crate) fn same_buffer(a: Cursor, b: Cursor) -> bool {
+ ptr::eq(start_of_buffer(a), start_of_buffer(b))
+}
+
+fn start_of_buffer(cursor: Cursor) -> *const Entry {
+ unsafe {
+ match &*cursor.scope {
+ Entry::End(offset, _) => cursor.scope.offset(*offset),
+ _ => unreachable!(),
+ }
+ }
+}
+
+pub(crate) fn cmp_assuming_same_buffer(a: Cursor, b: Cursor) -> Ordering {
+ a.ptr.cmp(&b.ptr)
+}
+
+pub(crate) fn open_span_of_group(cursor: Cursor) -> Span {
+ match cursor.entry() {
+ Entry::Group(group, _) => group.span_open(),
+ _ => cursor.span(),
+ }
+}
diff --git a/rust/syn/classify.rs b/rust/syn/classify.rs
new file mode 100644
index 000000000000..8eab19dbc37c
--- /dev/null
+++ b/rust/syn/classify.rs
@@ -0,0 +1,311 @@
+#[cfg(feature = "full")]
+use crate::expr::Expr;
+#[cfg(any(feature = "printing", feature = "full"))]
+use crate::generics::TypeParamBound;
+#[cfg(any(feature = "printing", feature = "full"))]
+use crate::path::{Path, PathArguments};
+#[cfg(any(feature = "printing", feature = "full"))]
+use crate::punctuated::Punctuated;
+#[cfg(any(feature = "printing", feature = "full"))]
+use crate::ty::{ReturnType, Type};
+#[cfg(feature = "full")]
+use proc_macro2::{Delimiter, TokenStream, TokenTree};
+#[cfg(any(feature = "printing", feature = "full"))]
+use std::ops::ControlFlow;
+
+#[cfg(feature = "full")]
+pub(crate) fn requires_semi_to_be_stmt(expr: &Expr) -> bool {
+ match expr {
+ Expr::Macro(expr) => !expr.mac.delimiter.is_brace(),
+ _ => requires_comma_to_be_match_arm(expr),
+ }
+}
+
+#[cfg(feature = "full")]
+pub(crate) fn requires_comma_to_be_match_arm(expr: &Expr) -> bool {
+ match expr {
+ Expr::If(_)
+ | Expr::Match(_)
+ | Expr::Block(_) | Expr::Unsafe(_) // both under ExprKind::Block in rustc
+ | Expr::While(_)
+ | Expr::Loop(_)
+ | Expr::ForLoop(_)
+ | Expr::TryBlock(_)
+ | Expr::Const(_) => false,
+
+ Expr::Array(_)
+ | Expr::Assign(_)
+ | Expr::Async(_)
+ | Expr::Await(_)
+ | Expr::Binary(_)
+ | Expr::Break(_)
+ | Expr::Call(_)
+ | Expr::Cast(_)
+ | Expr::Closure(_)
+ | Expr::Continue(_)
+ | Expr::Field(_)
+ | Expr::Group(_)
+ | Expr::Index(_)
+ | Expr::Infer(_)
+ | Expr::Let(_)
+ | Expr::Lit(_)
+ | Expr::Macro(_)
+ | Expr::MethodCall(_)
+ | Expr::Paren(_)
+ | Expr::Path(_)
+ | Expr::Range(_)
+ | Expr::RawAddr(_)
+ | Expr::Reference(_)
+ | Expr::Repeat(_)
+ | Expr::Return(_)
+ | Expr::Struct(_)
+ | Expr::Try(_)
+ | Expr::Tuple(_)
+ | Expr::Unary(_)
+ | Expr::Yield(_)
+ | Expr::Verbatim(_) => true,
+ }
+}
+
+#[cfg(feature = "printing")]
+pub(crate) fn trailing_unparameterized_path(mut ty: &Type) -> bool {
+ loop {
+ match ty {
+ Type::BareFn(t) => match &t.output {
+ ReturnType::Default => return false,
+ ReturnType::Type(_, ret) => ty = ret,
+ },
+ Type::ImplTrait(t) => match last_type_in_bounds(&t.bounds) {
+ ControlFlow::Break(trailing_path) => return trailing_path,
+ ControlFlow::Continue(t) => ty = t,
+ },
+ Type::Path(t) => match last_type_in_path(&t.path) {
+ ControlFlow::Break(trailing_path) => return trailing_path,
+ ControlFlow::Continue(t) => ty = t,
+ },
+ Type::Ptr(t) => ty = &t.elem,
+ Type::Reference(t) => ty = &t.elem,
+ Type::TraitObject(t) => match last_type_in_bounds(&t.bounds) {
+ ControlFlow::Break(trailing_path) => return trailing_path,
+ ControlFlow::Continue(t) => ty = t,
+ },
+
+ Type::Array(_)
+ | Type::Group(_)
+ | Type::Infer(_)
+ | Type::Macro(_)
+ | Type::Never(_)
+ | Type::Paren(_)
+ | Type::Slice(_)
+ | Type::Tuple(_)
+ | Type::Verbatim(_) => return false,
+ }
+ }
+
+ fn last_type_in_path(path: &Path) -> ControlFlow<bool, &Type> {
+ match &path.segments.last().unwrap().arguments {
+ PathArguments::None => ControlFlow::Break(true),
+ PathArguments::AngleBracketed(_) => ControlFlow::Break(false),
+ PathArguments::Parenthesized(arg) => match &arg.output {
+ ReturnType::Default => ControlFlow::Break(false),
+ ReturnType::Type(_, ret) => ControlFlow::Continue(ret),
+ },
+ }
+ }
+
+ fn last_type_in_bounds(
+ bounds: &Punctuated<TypeParamBound, Token![+]>,
+ ) -> ControlFlow<bool, &Type> {
+ match bounds.last().unwrap() {
+ TypeParamBound::Trait(t) => last_type_in_path(&t.path),
+ TypeParamBound::Lifetime(_)
+ | TypeParamBound::PreciseCapture(_)
+ | TypeParamBound::Verbatim(_) => ControlFlow::Break(false),
+ }
+ }
+}
+
+/// Whether the expression's first token is the label of a loop/block.
+#[cfg(all(feature = "printing", feature = "full"))]
+pub(crate) fn expr_leading_label(mut expr: &Expr) -> bool {
+ loop {
+ match expr {
+ Expr::Block(e) => return e.label.is_some(),
+ Expr::ForLoop(e) => return e.label.is_some(),
+ Expr::Loop(e) => return e.label.is_some(),
+ Expr::While(e) => return e.label.is_some(),
+
+ Expr::Assign(e) => expr = &e.left,
+ Expr::Await(e) => expr = &e.base,
+ Expr::Binary(e) => expr = &e.left,
+ Expr::Call(e) => expr = &e.func,
+ Expr::Cast(e) => expr = &e.expr,
+ Expr::Field(e) => expr = &e.base,
+ Expr::Index(e) => expr = &e.expr,
+ Expr::MethodCall(e) => expr = &e.receiver,
+ Expr::Range(e) => match &e.start {
+ Some(start) => expr = start,
+ None => return false,
+ },
+ Expr::Try(e) => expr = &e.expr,
+
+ Expr::Array(_)
+ | Expr::Async(_)
+ | Expr::Break(_)
+ | Expr::Closure(_)
+ | Expr::Const(_)
+ | Expr::Continue(_)
+ | Expr::Group(_)
+ | Expr::If(_)
+ | Expr::Infer(_)
+ | Expr::Let(_)
+ | Expr::Lit(_)
+ | Expr::Macro(_)
+ | Expr::Match(_)
+ | Expr::Paren(_)
+ | Expr::Path(_)
+ | Expr::RawAddr(_)
+ | Expr::Reference(_)
+ | Expr::Repeat(_)
+ | Expr::Return(_)
+ | Expr::Struct(_)
+ | Expr::TryBlock(_)
+ | Expr::Tuple(_)
+ | Expr::Unary(_)
+ | Expr::Unsafe(_)
+ | Expr::Verbatim(_)
+ | Expr::Yield(_) => return false,
+ }
+ }
+}
+
+/// Whether the expression's last token is `}`.
+#[cfg(feature = "full")]
+pub(crate) fn expr_trailing_brace(mut expr: &Expr) -> bool {
+ loop {
+ match expr {
+ Expr::Async(_)
+ | Expr::Block(_)
+ | Expr::Const(_)
+ | Expr::ForLoop(_)
+ | Expr::If(_)
+ | Expr::Loop(_)
+ | Expr::Match(_)
+ | Expr::Struct(_)
+ | Expr::TryBlock(_)
+ | Expr::Unsafe(_)
+ | Expr::While(_) => return true,
+
+ Expr::Assign(e) => expr = &e.right,
+ Expr::Binary(e) => expr = &e.right,
+ Expr::Break(e) => match &e.expr {
+ Some(e) => expr = e,
+ None => return false,
+ },
+ Expr::Cast(e) => return type_trailing_brace(&e.ty),
+ Expr::Closure(e) => expr = &e.body,
+ Expr::Let(e) => expr = &e.expr,
+ Expr::Macro(e) => return e.mac.delimiter.is_brace(),
+ Expr::Range(e) => match &e.end {
+ Some(end) => expr = end,
+ None => return false,
+ },
+ Expr::RawAddr(e) => expr = &e.expr,
+ Expr::Reference(e) => expr = &e.expr,
+ Expr::Return(e) => match &e.expr {
+ Some(e) => expr = e,
+ None => return false,
+ },
+ Expr::Unary(e) => expr = &e.expr,
+ Expr::Verbatim(e) => return tokens_trailing_brace(e),
+ Expr::Yield(e) => match &e.expr {
+ Some(e) => expr = e,
+ None => return false,
+ },
+
+ Expr::Array(_)
+ | Expr::Await(_)
+ | Expr::Call(_)
+ | Expr::Continue(_)
+ | Expr::Field(_)
+ | Expr::Group(_)
+ | Expr::Index(_)
+ | Expr::Infer(_)
+ | Expr::Lit(_)
+ | Expr::MethodCall(_)
+ | Expr::Paren(_)
+ | Expr::Path(_)
+ | Expr::Repeat(_)
+ | Expr::Try(_)
+ | Expr::Tuple(_) => return false,
+ }
+ }
+
+ fn type_trailing_brace(mut ty: &Type) -> bool {
+ loop {
+ match ty {
+ Type::BareFn(t) => match &t.output {
+ ReturnType::Default => return false,
+ ReturnType::Type(_, ret) => ty = ret,
+ },
+ Type::ImplTrait(t) => match last_type_in_bounds(&t.bounds) {
+ ControlFlow::Break(trailing_brace) => return trailing_brace,
+ ControlFlow::Continue(t) => ty = t,
+ },
+ Type::Macro(t) => return t.mac.delimiter.is_brace(),
+ Type::Path(t) => match last_type_in_path(&t.path) {
+ Some(t) => ty = t,
+ None => return false,
+ },
+ Type::Ptr(t) => ty = &t.elem,
+ Type::Reference(t) => ty = &t.elem,
+ Type::TraitObject(t) => match last_type_in_bounds(&t.bounds) {
+ ControlFlow::Break(trailing_brace) => return trailing_brace,
+ ControlFlow::Continue(t) => ty = t,
+ },
+ Type::Verbatim(t) => return tokens_trailing_brace(t),
+
+ Type::Array(_)
+ | Type::Group(_)
+ | Type::Infer(_)
+ | Type::Never(_)
+ | Type::Paren(_)
+ | Type::Slice(_)
+ | Type::Tuple(_) => return false,
+ }
+ }
+ }
+
+ fn last_type_in_path(path: &Path) -> Option<&Type> {
+ match &path.segments.last().unwrap().arguments {
+ PathArguments::None | PathArguments::AngleBracketed(_) => None,
+ PathArguments::Parenthesized(arg) => match &arg.output {
+ ReturnType::Default => None,
+ ReturnType::Type(_, ret) => Some(ret),
+ },
+ }
+ }
+
+ fn last_type_in_bounds(
+ bounds: &Punctuated<TypeParamBound, Token![+]>,
+ ) -> ControlFlow<bool, &Type> {
+ match bounds.last().unwrap() {
+ TypeParamBound::Trait(t) => match last_type_in_path(&t.path) {
+ Some(t) => ControlFlow::Continue(t),
+ None => ControlFlow::Break(false),
+ },
+ TypeParamBound::Lifetime(_) | TypeParamBound::PreciseCapture(_) => {
+ ControlFlow::Break(false)
+ }
+ TypeParamBound::Verbatim(t) => ControlFlow::Break(tokens_trailing_brace(t)),
+ }
+ }
+
+ fn tokens_trailing_brace(tokens: &TokenStream) -> bool {
+ if let Some(TokenTree::Group(last)) = tokens.clone().into_iter().last() {
+ last.delimiter() == Delimiter::Brace
+ } else {
+ false
+ }
+ }
+}
diff --git a/rust/syn/custom_keyword.rs b/rust/syn/custom_keyword.rs
new file mode 100644
index 000000000000..cc4f632c981a
--- /dev/null
+++ b/rust/syn/custom_keyword.rs
@@ -0,0 +1,260 @@
+/// Define a type that supports parsing and printing a given identifier as if it
+/// were a keyword.
+///
+/// # Usage
+///
+/// As a convention, it is recommended that this macro be invoked within a
+/// module called `kw` or `keyword` and that the resulting parser be invoked
+/// with a `kw::` or `keyword::` prefix.
+///
+/// ```
+/// mod kw {
+/// syn::custom_keyword!(whatever);
+/// }
+/// ```
+///
+/// The generated syntax tree node supports the following operations just like
+/// any built-in keyword token.
+///
+/// - [Peeking] — `input.peek(kw::whatever)`
+///
+/// - [Parsing] — `input.parse::<kw::whatever>()?`
+///
+/// - [Printing] — `quote!( ... #whatever_token ... )`
+///
+/// - Construction from a [`Span`] — `let whatever_token = kw::whatever(sp)`
+///
+/// - Field access to its span — `let sp = whatever_token.span`
+///
+/// [Peeking]: crate::parse::ParseBuffer::peek
+/// [Parsing]: crate::parse::ParseBuffer::parse
+/// [Printing]: quote::ToTokens
+/// [`Span`]: proc_macro2::Span
+///
+/// # Example
+///
+/// This example parses input that looks like `bool = true` or `str = "value"`.
+/// The key must be either the identifier `bool` or the identifier `str`. If
+/// `bool`, the value may be either `true` or `false`. If `str`, the value may
+/// be any string literal.
+///
+/// The symbols `bool` and `str` are not reserved keywords in Rust so these are
+/// not considered keywords in the `syn::token` module. Like any other
+/// identifier that is not a keyword, these can be declared as custom keywords
+/// by crates that need to use them as such.
+///
+/// ```
+/// use syn::{LitBool, LitStr, Result, Token};
+/// use syn::parse::{Parse, ParseStream};
+///
+/// mod kw {
+/// syn::custom_keyword!(bool);
+/// syn::custom_keyword!(str);
+/// }
+///
+/// enum Argument {
+/// Bool {
+/// bool_token: kw::bool,
+/// eq_token: Token![=],
+/// value: LitBool,
+/// },
+/// Str {
+/// str_token: kw::str,
+/// eq_token: Token![=],
+/// value: LitStr,
+/// },
+/// }
+///
+/// impl Parse for Argument {
+/// fn parse(input: ParseStream) -> Result<Self> {
+/// let lookahead = input.lookahead1();
+/// if lookahead.peek(kw::bool) {
+/// Ok(Argument::Bool {
+/// bool_token: input.parse::<kw::bool>()?,
+/// eq_token: input.parse()?,
+/// value: input.parse()?,
+/// })
+/// } else if lookahead.peek(kw::str) {
+/// Ok(Argument::Str {
+/// str_token: input.parse::<kw::str>()?,
+/// eq_token: input.parse()?,
+/// value: input.parse()?,
+/// })
+/// } else {
+/// Err(lookahead.error())
+/// }
+/// }
+/// }
+/// ```
+#[macro_export]
+macro_rules! custom_keyword {
+ ($ident:ident) => {
+ #[allow(non_camel_case_types)]
+ pub struct $ident {
+ #[allow(dead_code)]
+ pub span: $crate::__private::Span,
+ }
+
+ #[doc(hidden)]
+ #[allow(dead_code, non_snake_case)]
+ pub fn $ident<__S: $crate::__private::IntoSpans<$crate::__private::Span>>(
+ span: __S,
+ ) -> $ident {
+ $ident {
+ span: $crate::__private::IntoSpans::into_spans(span),
+ }
+ }
+
+ const _: () = {
+ impl $crate::__private::Default for $ident {
+ fn default() -> Self {
+ $ident {
+ span: $crate::__private::Span::call_site(),
+ }
+ }
+ }
+
+ $crate::impl_parse_for_custom_keyword!($ident);
+ $crate::impl_to_tokens_for_custom_keyword!($ident);
+ $crate::impl_clone_for_custom_keyword!($ident);
+ $crate::impl_extra_traits_for_custom_keyword!($ident);
+ };
+ };
+}
+
+// Not public API.
+#[cfg(feature = "parsing")]
+#[doc(hidden)]
+#[macro_export]
+macro_rules! impl_parse_for_custom_keyword {
+ ($ident:ident) => {
+ // For peek.
+ impl $crate::__private::CustomToken for $ident {
+ fn peek(cursor: $crate::buffer::Cursor) -> $crate::__private::bool {
+ if let $crate::__private::Some((ident, _rest)) = cursor.ident() {
+ ident == $crate::__private::stringify!($ident)
+ } else {
+ false
+ }
+ }
+
+ fn display() -> &'static $crate::__private::str {
+ $crate::__private::concat!("`", $crate::__private::stringify!($ident), "`")
+ }
+ }
+
+ impl $crate::parse::Parse for $ident {
+ fn parse(input: $crate::parse::ParseStream) -> $crate::parse::Result<$ident> {
+ input.step(|cursor| {
+ if let $crate::__private::Some((ident, rest)) = cursor.ident() {
+ if ident == $crate::__private::stringify!($ident) {
+ return $crate::__private::Ok(($ident { span: ident.span() }, rest));
+ }
+ }
+ $crate::__private::Err(cursor.error($crate::__private::concat!(
+ "expected `",
+ $crate::__private::stringify!($ident),
+ "`",
+ )))
+ })
+ }
+ }
+ };
+}
+
+// Not public API.
+#[cfg(not(feature = "parsing"))]
+#[doc(hidden)]
+#[macro_export]
+macro_rules! impl_parse_for_custom_keyword {
+ ($ident:ident) => {};
+}
+
+// Not public API.
+#[cfg(feature = "printing")]
+#[doc(hidden)]
+#[macro_export]
+macro_rules! impl_to_tokens_for_custom_keyword {
+ ($ident:ident) => {
+ impl $crate::__private::ToTokens for $ident {
+ fn to_tokens(&self, tokens: &mut $crate::__private::TokenStream2) {
+ let ident = $crate::Ident::new($crate::__private::stringify!($ident), self.span);
+ $crate::__private::TokenStreamExt::append(tokens, ident);
+ }
+ }
+ };
+}
+
+// Not public API.
+#[cfg(not(feature = "printing"))]
+#[doc(hidden)]
+#[macro_export]
+macro_rules! impl_to_tokens_for_custom_keyword {
+ ($ident:ident) => {};
+}
+
+// Not public API.
+#[cfg(feature = "clone-impls")]
+#[doc(hidden)]
+#[macro_export]
+macro_rules! impl_clone_for_custom_keyword {
+ ($ident:ident) => {
+ impl $crate::__private::Copy for $ident {}
+
+ #[allow(clippy::expl_impl_clone_on_copy)]
+ impl $crate::__private::Clone for $ident {
+ fn clone(&self) -> Self {
+ *self
+ }
+ }
+ };
+}
+
+// Not public API.
+#[cfg(not(feature = "clone-impls"))]
+#[doc(hidden)]
+#[macro_export]
+macro_rules! impl_clone_for_custom_keyword {
+ ($ident:ident) => {};
+}
+
+// Not public API.
+#[cfg(feature = "extra-traits")]
+#[doc(hidden)]
+#[macro_export]
+macro_rules! impl_extra_traits_for_custom_keyword {
+ ($ident:ident) => {
+ impl $crate::__private::Debug for $ident {
+ fn fmt(&self, f: &mut $crate::__private::Formatter) -> $crate::__private::FmtResult {
+ $crate::__private::Formatter::write_str(
+ f,
+ $crate::__private::concat!(
+ "Keyword [",
+ $crate::__private::stringify!($ident),
+ "]",
+ ),
+ )
+ }
+ }
+
+ impl $crate::__private::Eq for $ident {}
+
+ impl $crate::__private::PartialEq for $ident {
+ fn eq(&self, _other: &Self) -> $crate::__private::bool {
+ true
+ }
+ }
+
+ impl $crate::__private::Hash for $ident {
+ fn hash<__H: $crate::__private::Hasher>(&self, _state: &mut __H) {}
+ }
+ };
+}
+
+// Not public API.
+#[cfg(not(feature = "extra-traits"))]
+#[doc(hidden)]
+#[macro_export]
+macro_rules! impl_extra_traits_for_custom_keyword {
+ ($ident:ident) => {};
+}
diff --git a/rust/syn/custom_punctuation.rs b/rust/syn/custom_punctuation.rs
new file mode 100644
index 000000000000..eef5f5458459
--- /dev/null
+++ b/rust/syn/custom_punctuation.rs
@@ -0,0 +1,304 @@
+/// Define a type that supports parsing and printing a multi-character symbol
+/// as if it were a punctuation token.
+///
+/// # Usage
+///
+/// ```
+/// syn::custom_punctuation!(LeftRightArrow, <=>);
+/// ```
+///
+/// The generated syntax tree node supports the following operations just like
+/// any built-in punctuation token.
+///
+/// - [Peeking] — `input.peek(LeftRightArrow)`
+///
+/// - [Parsing] — `input.parse::<LeftRightArrow>()?`
+///
+/// - [Printing] — `quote!( ... #lrarrow ... )`
+///
+/// - Construction from a [`Span`] — `let lrarrow = LeftRightArrow(sp)`
+///
+/// - Construction from multiple [`Span`] — `let lrarrow = LeftRightArrow([sp, sp, sp])`
+///
+/// - Field access to its spans — `let spans = lrarrow.spans`
+///
+/// [Peeking]: crate::parse::ParseBuffer::peek
+/// [Parsing]: crate::parse::ParseBuffer::parse
+/// [Printing]: quote::ToTokens
+/// [`Span`]: proc_macro2::Span
+///
+/// # Example
+///
+/// ```
+/// use proc_macro2::{TokenStream, TokenTree};
+/// use syn::parse::{Parse, ParseStream, Peek, Result};
+/// use syn::punctuated::Punctuated;
+/// use syn::Expr;
+///
+/// syn::custom_punctuation!(PathSeparator, </>);
+///
+/// // expr </> expr </> expr ...
+/// struct PathSegments {
+/// segments: Punctuated<Expr, PathSeparator>,
+/// }
+///
+/// impl Parse for PathSegments {
+/// fn parse(input: ParseStream) -> Result<Self> {
+/// let mut segments = Punctuated::new();
+///
+/// let first = parse_until(input, PathSeparator)?;
+/// segments.push_value(syn::parse2(first)?);
+///
+/// while input.peek(PathSeparator) {
+/// segments.push_punct(input.parse()?);
+///
+/// let next = parse_until(input, PathSeparator)?;
+/// segments.push_value(syn::parse2(next)?);
+/// }
+///
+/// Ok(PathSegments { segments })
+/// }
+/// }
+///
+/// fn parse_until<E: Peek>(input: ParseStream, end: E) -> Result<TokenStream> {
+/// let mut tokens = TokenStream::new();
+/// while !input.is_empty() && !input.peek(end) {
+/// let next: TokenTree = input.parse()?;
+/// tokens.extend(Some(next));
+/// }
+/// Ok(tokens)
+/// }
+///
+/// fn main() {
+/// let input = r#" a::b </> c::d::e "#;
+/// let _: PathSegments = syn::parse_str(input).unwrap();
+/// }
+/// ```
+#[macro_export]
+macro_rules! custom_punctuation {
+ ($ident:ident, $($tt:tt)+) => {
+ pub struct $ident {
+ #[allow(dead_code)]
+ pub spans: $crate::custom_punctuation_repr!($($tt)+),
+ }
+
+ #[doc(hidden)]
+ #[allow(dead_code, non_snake_case)]
+ pub fn $ident<__S: $crate::__private::IntoSpans<$crate::custom_punctuation_repr!($($tt)+)>>(
+ spans: __S,
+ ) -> $ident {
+ let _validate_len = 0 $(+ $crate::custom_punctuation_len!(strict, $tt))*;
+ $ident {
+ spans: $crate::__private::IntoSpans::into_spans(spans)
+ }
+ }
+
+ const _: () = {
+ impl $crate::__private::Default for $ident {
+ fn default() -> Self {
+ $ident($crate::__private::Span::call_site())
+ }
+ }
+
+ $crate::impl_parse_for_custom_punctuation!($ident, $($tt)+);
+ $crate::impl_to_tokens_for_custom_punctuation!($ident, $($tt)+);
+ $crate::impl_clone_for_custom_punctuation!($ident, $($tt)+);
+ $crate::impl_extra_traits_for_custom_punctuation!($ident, $($tt)+);
+ };
+ };
+}
+
+// Not public API.
+#[cfg(feature = "parsing")]
+#[doc(hidden)]
+#[macro_export]
+macro_rules! impl_parse_for_custom_punctuation {
+ ($ident:ident, $($tt:tt)+) => {
+ impl $crate::__private::CustomToken for $ident {
+ fn peek(cursor: $crate::buffer::Cursor) -> $crate::__private::bool {
+ $crate::__private::peek_punct(cursor, $crate::stringify_punct!($($tt)+))
+ }
+
+ fn display() -> &'static $crate::__private::str {
+ $crate::__private::concat!("`", $crate::stringify_punct!($($tt)+), "`")
+ }
+ }
+
+ impl $crate::parse::Parse for $ident {
+ fn parse(input: $crate::parse::ParseStream) -> $crate::parse::Result<$ident> {
+ let spans: $crate::custom_punctuation_repr!($($tt)+) =
+ $crate::__private::parse_punct(input, $crate::stringify_punct!($($tt)+))?;
+ Ok($ident(spans))
+ }
+ }
+ };
+}
+
+// Not public API.
+#[cfg(not(feature = "parsing"))]
+#[doc(hidden)]
+#[macro_export]
+macro_rules! impl_parse_for_custom_punctuation {
+ ($ident:ident, $($tt:tt)+) => {};
+}
+
+// Not public API.
+#[cfg(feature = "printing")]
+#[doc(hidden)]
+#[macro_export]
+macro_rules! impl_to_tokens_for_custom_punctuation {
+ ($ident:ident, $($tt:tt)+) => {
+ impl $crate::__private::ToTokens for $ident {
+ fn to_tokens(&self, tokens: &mut $crate::__private::TokenStream2) {
+ $crate::__private::print_punct($crate::stringify_punct!($($tt)+), &self.spans, tokens)
+ }
+ }
+ };
+}
+
+// Not public API.
+#[cfg(not(feature = "printing"))]
+#[doc(hidden)]
+#[macro_export]
+macro_rules! impl_to_tokens_for_custom_punctuation {
+ ($ident:ident, $($tt:tt)+) => {};
+}
+
+// Not public API.
+#[cfg(feature = "clone-impls")]
+#[doc(hidden)]
+#[macro_export]
+macro_rules! impl_clone_for_custom_punctuation {
+ ($ident:ident, $($tt:tt)+) => {
+ impl $crate::__private::Copy for $ident {}
+
+ #[allow(clippy::expl_impl_clone_on_copy)]
+ impl $crate::__private::Clone for $ident {
+ fn clone(&self) -> Self {
+ *self
+ }
+ }
+ };
+}
+
+// Not public API.
+#[cfg(not(feature = "clone-impls"))]
+#[doc(hidden)]
+#[macro_export]
+macro_rules! impl_clone_for_custom_punctuation {
+ ($ident:ident, $($tt:tt)+) => {};
+}
+
+// Not public API.
+#[cfg(feature = "extra-traits")]
+#[doc(hidden)]
+#[macro_export]
+macro_rules! impl_extra_traits_for_custom_punctuation {
+ ($ident:ident, $($tt:tt)+) => {
+ impl $crate::__private::Debug for $ident {
+ fn fmt(&self, f: &mut $crate::__private::Formatter) -> $crate::__private::FmtResult {
+ $crate::__private::Formatter::write_str(f, $crate::__private::stringify!($ident))
+ }
+ }
+
+ impl $crate::__private::Eq for $ident {}
+
+ impl $crate::__private::PartialEq for $ident {
+ fn eq(&self, _other: &Self) -> $crate::__private::bool {
+ true
+ }
+ }
+
+ impl $crate::__private::Hash for $ident {
+ fn hash<__H: $crate::__private::Hasher>(&self, _state: &mut __H) {}
+ }
+ };
+}
+
+// Not public API.
+#[cfg(not(feature = "extra-traits"))]
+#[doc(hidden)]
+#[macro_export]
+macro_rules! impl_extra_traits_for_custom_punctuation {
+ ($ident:ident, $($tt:tt)+) => {};
+}
+
+// Not public API.
+#[doc(hidden)]
+#[macro_export]
+macro_rules! custom_punctuation_repr {
+ ($($tt:tt)+) => {
+ [$crate::__private::Span; 0 $(+ $crate::custom_punctuation_len!(lenient, $tt))+]
+ };
+}
+
+// Not public API.
+#[doc(hidden)]
+#[macro_export]
+#[rustfmt::skip]
+macro_rules! custom_punctuation_len {
+ ($mode:ident, &) => { 1 };
+ ($mode:ident, &&) => { 2 };
+ ($mode:ident, &=) => { 2 };
+ ($mode:ident, @) => { 1 };
+ ($mode:ident, ^) => { 1 };
+ ($mode:ident, ^=) => { 2 };
+ ($mode:ident, :) => { 1 };
+ ($mode:ident, ,) => { 1 };
+ ($mode:ident, $) => { 1 };
+ ($mode:ident, .) => { 1 };
+ ($mode:ident, ..) => { 2 };
+ ($mode:ident, ...) => { 3 };
+ ($mode:ident, ..=) => { 3 };
+ ($mode:ident, =) => { 1 };
+ ($mode:ident, ==) => { 2 };
+ ($mode:ident, =>) => { 2 };
+ ($mode:ident, >=) => { 2 };
+ ($mode:ident, >) => { 1 };
+ ($mode:ident, <-) => { 2 };
+ ($mode:ident, <=) => { 2 };
+ ($mode:ident, <) => { 1 };
+ ($mode:ident, -) => { 1 };
+ ($mode:ident, -=) => { 2 };
+ ($mode:ident, !=) => { 2 };
+ ($mode:ident, !) => { 1 };
+ ($mode:ident, |) => { 1 };
+ ($mode:ident, |=) => { 2 };
+ ($mode:ident, ||) => { 2 };
+ ($mode:ident, ::) => { 2 };
+ ($mode:ident, %) => { 1 };
+ ($mode:ident, %=) => { 2 };
+ ($mode:ident, +) => { 1 };
+ ($mode:ident, +=) => { 2 };
+ ($mode:ident, #) => { 1 };
+ ($mode:ident, ?) => { 1 };
+ ($mode:ident, ->) => { 2 };
+ ($mode:ident, ;) => { 1 };
+ ($mode:ident, <<) => { 2 };
+ ($mode:ident, <<=) => { 3 };
+ ($mode:ident, >>) => { 2 };
+ ($mode:ident, >>=) => { 3 };
+ ($mode:ident, /) => { 1 };
+ ($mode:ident, /=) => { 2 };
+ ($mode:ident, *) => { 1 };
+ ($mode:ident, *=) => { 2 };
+ ($mode:ident, ~) => { 1 };
+ (lenient, $tt:tt) => { 0 };
+ (strict, $tt:tt) => {{ $crate::custom_punctuation_unexpected!($tt); 0 }};
+}
+
+// Not public API.
+#[doc(hidden)]
+#[macro_export]
+macro_rules! custom_punctuation_unexpected {
+ () => {};
+}
+
+// Not public API.
+#[doc(hidden)]
+#[macro_export]
+macro_rules! stringify_punct {
+ ($($tt:tt)+) => {
+ $crate::__private::concat!($($crate::__private::stringify!($tt)),+)
+ };
+}
diff --git a/rust/syn/data.rs b/rust/syn/data.rs
new file mode 100644
index 000000000000..96db2a0b7c6f
--- /dev/null
+++ b/rust/syn/data.rs
@@ -0,0 +1,424 @@
+use crate::attr::Attribute;
+use crate::expr::{Expr, Index, Member};
+use crate::ident::Ident;
+use crate::punctuated::{self, Punctuated};
+use crate::restriction::{FieldMutability, Visibility};
+use crate::token;
+use crate::ty::Type;
+
+ast_struct! {
+ /// An enum variant.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct Variant {
+ pub attrs: Vec<Attribute>,
+
+ /// Name of the variant.
+ pub ident: Ident,
+
+ /// Content stored in the variant.
+ pub fields: Fields,
+
+ /// Explicit discriminant: `Variant = 1`
+ pub discriminant: Option<(Token![=], Expr)>,
+ }
+}
+
+ast_enum_of_structs! {
+ /// Data stored within an enum variant or struct.
+ ///
+ /// # 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 Fields {
+ /// Named fields of a struct or struct variant such as `Point { x: f64,
+ /// y: f64 }`.
+ Named(FieldsNamed),
+
+ /// Unnamed fields of a tuple struct or tuple variant such as `Some(T)`.
+ Unnamed(FieldsUnnamed),
+
+ /// Unit struct or unit variant such as `None`.
+ Unit,
+ }
+}
+
+ast_struct! {
+ /// Named fields of a struct or struct variant such as `Point { x: f64,
+ /// y: f64 }`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct FieldsNamed {
+ pub brace_token: token::Brace,
+ pub named: Punctuated<Field, Token![,]>,
+ }
+}
+
+ast_struct! {
+ /// Unnamed fields of a tuple struct or tuple variant such as `Some(T)`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct FieldsUnnamed {
+ pub paren_token: token::Paren,
+ pub unnamed: Punctuated<Field, Token![,]>,
+ }
+}
+
+impl Fields {
+ /// Get an iterator over the borrowed [`Field`] items in this object. This
+ /// iterator can be used to iterate over a named or unnamed struct or
+ /// variant's fields uniformly.
+ pub fn iter(&self) -> punctuated::Iter<Field> {
+ match self {
+ Fields::Unit => crate::punctuated::empty_punctuated_iter(),
+ Fields::Named(f) => f.named.iter(),
+ Fields::Unnamed(f) => f.unnamed.iter(),
+ }
+ }
+
+ /// Get an iterator over the mutably borrowed [`Field`] items in this
+ /// object. This iterator can be used to iterate over a named or unnamed
+ /// struct or variant's fields uniformly.
+ pub fn iter_mut(&mut self) -> punctuated::IterMut<Field> {
+ match self {
+ Fields::Unit => crate::punctuated::empty_punctuated_iter_mut(),
+ Fields::Named(f) => f.named.iter_mut(),
+ Fields::Unnamed(f) => f.unnamed.iter_mut(),
+ }
+ }
+
+ /// Returns the number of fields.
+ pub fn len(&self) -> usize {
+ match self {
+ Fields::Unit => 0,
+ Fields::Named(f) => f.named.len(),
+ Fields::Unnamed(f) => f.unnamed.len(),
+ }
+ }
+
+ /// Returns `true` if there are zero fields.
+ pub fn is_empty(&self) -> bool {
+ match self {
+ Fields::Unit => true,
+ Fields::Named(f) => f.named.is_empty(),
+ Fields::Unnamed(f) => f.unnamed.is_empty(),
+ }
+ }
+
+ return_impl_trait! {
+ /// Get an iterator over the fields of a struct or variant as [`Member`]s.
+ /// This iterator can be used to iterate over a named or unnamed struct or
+ /// variant's fields uniformly.
+ ///
+ /// # Example
+ ///
+ /// The following is a simplistic [`Clone`] derive for structs. (A more
+ /// complete implementation would additionally want to infer trait bounds on
+ /// the generic type parameters.)
+ ///
+ /// ```
+ /// # use quote::quote;
+ /// #
+ /// fn derive_clone(input: &syn::ItemStruct) -> proc_macro2::TokenStream {
+ /// let ident = &input.ident;
+ /// let members = input.fields.members();
+ /// let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
+ /// quote! {
+ /// impl #impl_generics Clone for #ident #ty_generics #where_clause {
+ /// fn clone(&self) -> Self {
+ /// Self {
+ /// #(#members: self.#members.clone()),*
+ /// }
+ /// }
+ /// }
+ /// }
+ /// }
+ /// ```
+ ///
+ /// For structs with named fields, it produces an expression like `Self { a:
+ /// self.a.clone() }`. For structs with unnamed fields, `Self { 0:
+ /// self.0.clone() }`. And for unit structs, `Self {}`.
+ pub fn members(&self) -> impl Iterator<Item = Member> + Clone + '_ [Members] {
+ Members {
+ fields: self.iter(),
+ index: 0,
+ }
+ }
+ }
+}
+
+impl IntoIterator for Fields {
+ type Item = Field;
+ type IntoIter = punctuated::IntoIter<Field>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ match self {
+ Fields::Unit => Punctuated::<Field, ()>::new().into_iter(),
+ Fields::Named(f) => f.named.into_iter(),
+ Fields::Unnamed(f) => f.unnamed.into_iter(),
+ }
+ }
+}
+
+impl<'a> IntoIterator for &'a Fields {
+ type Item = &'a Field;
+ type IntoIter = punctuated::Iter<'a, Field>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.iter()
+ }
+}
+
+impl<'a> IntoIterator for &'a mut Fields {
+ type Item = &'a mut Field;
+ type IntoIter = punctuated::IterMut<'a, Field>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.iter_mut()
+ }
+}
+
+ast_struct! {
+ /// A field of a struct or enum variant.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct Field {
+ pub attrs: Vec<Attribute>,
+
+ pub vis: Visibility,
+
+ pub mutability: FieldMutability,
+
+ /// Name of the field, if any.
+ ///
+ /// Fields of tuple structs have no names.
+ pub ident: Option<Ident>,
+
+ pub colon_token: Option<Token![:]>,
+
+ pub ty: Type,
+ }
+}
+
+pub struct Members<'a> {
+ fields: punctuated::Iter<'a, Field>,
+ index: u32,
+}
+
+impl<'a> Iterator for Members<'a> {
+ type Item = Member;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ let field = self.fields.next()?;
+ let member = match &field.ident {
+ Some(ident) => Member::Named(ident.clone()),
+ None => {
+ #[cfg(all(feature = "parsing", feature = "printing"))]
+ let span = crate::spanned::Spanned::span(&field.ty);
+ #[cfg(not(all(feature = "parsing", feature = "printing")))]
+ let span = proc_macro2::Span::call_site();
+ Member::Unnamed(Index {
+ index: self.index,
+ span,
+ })
+ }
+ };
+ self.index += 1;
+ Some(member)
+ }
+}
+
+impl<'a> Clone for Members<'a> {
+ fn clone(&self) -> Self {
+ Members {
+ fields: self.fields.clone(),
+ index: self.index,
+ }
+ }
+}
+
+#[cfg(feature = "parsing")]
+pub(crate) mod parsing {
+ use crate::attr::Attribute;
+ use crate::data::{Field, Fields, FieldsNamed, FieldsUnnamed, Variant};
+ use crate::error::Result;
+ use crate::expr::Expr;
+ use crate::ext::IdentExt as _;
+ use crate::ident::Ident;
+ #[cfg(not(feature = "full"))]
+ use crate::parse::discouraged::Speculative as _;
+ use crate::parse::{Parse, ParseStream};
+ use crate::restriction::{FieldMutability, Visibility};
+ #[cfg(not(feature = "full"))]
+ use crate::scan_expr::scan_expr;
+ use crate::token;
+ use crate::ty::Type;
+ use crate::verbatim;
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for Variant {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let attrs = input.call(Attribute::parse_outer)?;
+ let _visibility: Visibility = input.parse()?;
+ let ident: Ident = input.parse()?;
+ let fields = if input.peek(token::Brace) {
+ Fields::Named(input.parse()?)
+ } else if input.peek(token::Paren) {
+ Fields::Unnamed(input.parse()?)
+ } else {
+ Fields::Unit
+ };
+ let discriminant = if input.peek(Token![=]) {
+ let eq_token: Token![=] = input.parse()?;
+ #[cfg(feature = "full")]
+ let discriminant: Expr = input.parse()?;
+ #[cfg(not(feature = "full"))]
+ let discriminant = {
+ let begin = input.fork();
+ let ahead = input.fork();
+ let mut discriminant: Result<Expr> = ahead.parse();
+ if discriminant.is_ok() {
+ input.advance_to(&ahead);
+ } else if scan_expr(input).is_ok() {
+ discriminant = Ok(Expr::Verbatim(verbatim::between(&begin, input)));
+ }
+ discriminant?
+ };
+ Some((eq_token, discriminant))
+ } else {
+ None
+ };
+ Ok(Variant {
+ attrs,
+ ident,
+ fields,
+ discriminant,
+ })
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for FieldsNamed {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let content;
+ Ok(FieldsNamed {
+ brace_token: braced!(content in input),
+ named: content.parse_terminated(Field::parse_named, Token![,])?,
+ })
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for FieldsUnnamed {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let content;
+ Ok(FieldsUnnamed {
+ paren_token: parenthesized!(content in input),
+ unnamed: content.parse_terminated(Field::parse_unnamed, Token![,])?,
+ })
+ }
+ }
+
+ impl Field {
+ /// Parses a named (braced struct) field.
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ pub fn parse_named(input: ParseStream) -> Result<Self> {
+ let attrs = input.call(Attribute::parse_outer)?;
+ let vis: Visibility = input.parse()?;
+
+ let unnamed_field = cfg!(feature = "full") && input.peek(Token![_]);
+ let ident = if unnamed_field {
+ input.call(Ident::parse_any)
+ } else {
+ input.parse()
+ }?;
+
+ let colon_token: Token![:] = input.parse()?;
+
+ let ty: Type = if unnamed_field
+ && (input.peek(Token![struct])
+ || input.peek(Token![union]) && input.peek2(token::Brace))
+ {
+ let begin = input.fork();
+ input.call(Ident::parse_any)?;
+ input.parse::<FieldsNamed>()?;
+ Type::Verbatim(verbatim::between(&begin, input))
+ } else {
+ input.parse()?
+ };
+
+ Ok(Field {
+ attrs,
+ vis,
+ mutability: FieldMutability::None,
+ ident: Some(ident),
+ colon_token: Some(colon_token),
+ ty,
+ })
+ }
+
+ /// Parses an unnamed (tuple struct) field.
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ pub fn parse_unnamed(input: ParseStream) -> Result<Self> {
+ Ok(Field {
+ attrs: input.call(Attribute::parse_outer)?,
+ vis: input.parse()?,
+ mutability: FieldMutability::None,
+ ident: None,
+ colon_token: None,
+ ty: input.parse()?,
+ })
+ }
+ }
+}
+
+#[cfg(feature = "printing")]
+mod printing {
+ use crate::data::{Field, FieldsNamed, FieldsUnnamed, Variant};
+ use crate::print::TokensOrDefault;
+ use proc_macro2::TokenStream;
+ use quote::{ToTokens, TokenStreamExt};
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for Variant {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(&self.attrs);
+ self.ident.to_tokens(tokens);
+ self.fields.to_tokens(tokens);
+ if let Some((eq_token, disc)) = &self.discriminant {
+ eq_token.to_tokens(tokens);
+ disc.to_tokens(tokens);
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for FieldsNamed {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.brace_token.surround(tokens, |tokens| {
+ self.named.to_tokens(tokens);
+ });
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for FieldsUnnamed {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.paren_token.surround(tokens, |tokens| {
+ self.unnamed.to_tokens(tokens);
+ });
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for Field {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(&self.attrs);
+ self.vis.to_tokens(tokens);
+ if let Some(ident) = &self.ident {
+ ident.to_tokens(tokens);
+ TokensOrDefault(&self.colon_token).to_tokens(tokens);
+ }
+ self.ty.to_tokens(tokens);
+ }
+ }
+}
diff --git a/rust/syn/derive.rs b/rust/syn/derive.rs
new file mode 100644
index 000000000000..3443ecfc05cb
--- /dev/null
+++ b/rust/syn/derive.rs
@@ -0,0 +1,259 @@
+use crate::attr::Attribute;
+use crate::data::{Fields, FieldsNamed, Variant};
+use crate::generics::Generics;
+use crate::ident::Ident;
+use crate::punctuated::Punctuated;
+use crate::restriction::Visibility;
+use crate::token;
+
+ast_struct! {
+ /// Data structure sent to a `proc_macro_derive` macro.
+ #[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
+ pub struct DeriveInput {
+ pub attrs: Vec<Attribute>,
+ pub vis: Visibility,
+ pub ident: Ident,
+ pub generics: Generics,
+ pub data: Data,
+ }
+}
+
+ast_enum! {
+ /// The storage of a struct, enum or union data structure.
+ ///
+ /// # Syntax tree enum
+ ///
+ /// This type is a [syntax tree enum].
+ ///
+ /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums
+ #[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
+ pub enum Data {
+ Struct(DataStruct),
+ Enum(DataEnum),
+ Union(DataUnion),
+ }
+}
+
+ast_struct! {
+ /// A struct input to a `proc_macro_derive` macro.
+ #[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
+ pub struct DataStruct {
+ pub struct_token: Token![struct],
+ pub fields: Fields,
+ pub semi_token: Option<Token![;]>,
+ }
+}
+
+ast_struct! {
+ /// An enum input to a `proc_macro_derive` macro.
+ #[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
+ pub struct DataEnum {
+ pub enum_token: Token![enum],
+ pub brace_token: token::Brace,
+ pub variants: Punctuated<Variant, Token![,]>,
+ }
+}
+
+ast_struct! {
+ /// An untagged union input to a `proc_macro_derive` macro.
+ #[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
+ pub struct DataUnion {
+ pub union_token: Token![union],
+ pub fields: FieldsNamed,
+ }
+}
+
+#[cfg(feature = "parsing")]
+pub(crate) mod parsing {
+ use crate::attr::Attribute;
+ use crate::data::{Fields, FieldsNamed, Variant};
+ use crate::derive::{Data, DataEnum, DataStruct, DataUnion, DeriveInput};
+ use crate::error::Result;
+ use crate::generics::{Generics, WhereClause};
+ use crate::ident::Ident;
+ use crate::parse::{Parse, ParseStream};
+ use crate::punctuated::Punctuated;
+ use crate::restriction::Visibility;
+ use crate::token;
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for DeriveInput {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let attrs = input.call(Attribute::parse_outer)?;
+ let vis = input.parse::<Visibility>()?;
+
+ let lookahead = input.lookahead1();
+ if lookahead.peek(Token![struct]) {
+ let struct_token = input.parse::<Token![struct]>()?;
+ let ident = input.parse::<Ident>()?;
+ let generics = input.parse::<Generics>()?;
+ let (where_clause, fields, semi) = data_struct(input)?;
+ Ok(DeriveInput {
+ attrs,
+ vis,
+ ident,
+ generics: Generics {
+ where_clause,
+ ..generics
+ },
+ data: Data::Struct(DataStruct {
+ struct_token,
+ fields,
+ semi_token: semi,
+ }),
+ })
+ } else if lookahead.peek(Token![enum]) {
+ let enum_token = input.parse::<Token![enum]>()?;
+ let ident = input.parse::<Ident>()?;
+ let generics = input.parse::<Generics>()?;
+ let (where_clause, brace, variants) = data_enum(input)?;
+ Ok(DeriveInput {
+ attrs,
+ vis,
+ ident,
+ generics: Generics {
+ where_clause,
+ ..generics
+ },
+ data: Data::Enum(DataEnum {
+ enum_token,
+ brace_token: brace,
+ variants,
+ }),
+ })
+ } else if lookahead.peek(Token![union]) {
+ let union_token = input.parse::<Token![union]>()?;
+ let ident = input.parse::<Ident>()?;
+ let generics = input.parse::<Generics>()?;
+ let (where_clause, fields) = data_union(input)?;
+ Ok(DeriveInput {
+ attrs,
+ vis,
+ ident,
+ generics: Generics {
+ where_clause,
+ ..generics
+ },
+ data: Data::Union(DataUnion {
+ union_token,
+ fields,
+ }),
+ })
+ } else {
+ Err(lookahead.error())
+ }
+ }
+ }
+
+ pub(crate) fn data_struct(
+ input: ParseStream,
+ ) -> Result<(Option<WhereClause>, Fields, Option<Token![;]>)> {
+ let mut lookahead = input.lookahead1();
+ let mut where_clause = None;
+ if lookahead.peek(Token![where]) {
+ where_clause = Some(input.parse()?);
+ lookahead = input.lookahead1();
+ }
+
+ if where_clause.is_none() && lookahead.peek(token::Paren) {
+ let fields = input.parse()?;
+
+ lookahead = input.lookahead1();
+ if lookahead.peek(Token![where]) {
+ where_clause = Some(input.parse()?);
+ lookahead = input.lookahead1();
+ }
+
+ if lookahead.peek(Token![;]) {
+ let semi = input.parse()?;
+ Ok((where_clause, Fields::Unnamed(fields), Some(semi)))
+ } else {
+ Err(lookahead.error())
+ }
+ } else if lookahead.peek(token::Brace) {
+ let fields = input.parse()?;
+ Ok((where_clause, Fields::Named(fields), None))
+ } else if lookahead.peek(Token![;]) {
+ let semi = input.parse()?;
+ Ok((where_clause, Fields::Unit, Some(semi)))
+ } else {
+ Err(lookahead.error())
+ }
+ }
+
+ pub(crate) fn data_enum(
+ input: ParseStream,
+ ) -> Result<(
+ Option<WhereClause>,
+ token::Brace,
+ Punctuated<Variant, Token![,]>,
+ )> {
+ let where_clause = input.parse()?;
+
+ let content;
+ let brace = braced!(content in input);
+ let variants = content.parse_terminated(Variant::parse, Token![,])?;
+
+ Ok((where_clause, brace, variants))
+ }
+
+ pub(crate) fn data_union(input: ParseStream) -> Result<(Option<WhereClause>, FieldsNamed)> {
+ let where_clause = input.parse()?;
+ let fields = input.parse()?;
+ Ok((where_clause, fields))
+ }
+}
+
+#[cfg(feature = "printing")]
+mod printing {
+ use crate::attr::FilterAttrs;
+ use crate::data::Fields;
+ use crate::derive::{Data, DeriveInput};
+ use crate::print::TokensOrDefault;
+ use proc_macro2::TokenStream;
+ use quote::ToTokens;
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for DeriveInput {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ for attr in self.attrs.outer() {
+ attr.to_tokens(tokens);
+ }
+ self.vis.to_tokens(tokens);
+ match &self.data {
+ Data::Struct(d) => d.struct_token.to_tokens(tokens),
+ Data::Enum(d) => d.enum_token.to_tokens(tokens),
+ Data::Union(d) => d.union_token.to_tokens(tokens),
+ }
+ self.ident.to_tokens(tokens);
+ self.generics.to_tokens(tokens);
+ match &self.data {
+ Data::Struct(data) => match &data.fields {
+ Fields::Named(fields) => {
+ self.generics.where_clause.to_tokens(tokens);
+ fields.to_tokens(tokens);
+ }
+ Fields::Unnamed(fields) => {
+ fields.to_tokens(tokens);
+ self.generics.where_clause.to_tokens(tokens);
+ TokensOrDefault(&data.semi_token).to_tokens(tokens);
+ }
+ Fields::Unit => {
+ self.generics.where_clause.to_tokens(tokens);
+ TokensOrDefault(&data.semi_token).to_tokens(tokens);
+ }
+ },
+ Data::Enum(data) => {
+ self.generics.where_clause.to_tokens(tokens);
+ data.brace_token.surround(tokens, |tokens| {
+ data.variants.to_tokens(tokens);
+ });
+ }
+ Data::Union(data) => {
+ self.generics.where_clause.to_tokens(tokens);
+ data.fields.to_tokens(tokens);
+ }
+ }
+ }
+ }
+}
diff --git a/rust/syn/discouraged.rs b/rust/syn/discouraged.rs
new file mode 100644
index 000000000000..c8d6bfe89a14
--- /dev/null
+++ b/rust/syn/discouraged.rs
@@ -0,0 +1,225 @@
+//! Extensions to the parsing API with niche applicability.
+
+use crate::buffer::Cursor;
+use crate::error::Result;
+use crate::parse::{inner_unexpected, ParseBuffer, Unexpected};
+use proc_macro2::extra::DelimSpan;
+use proc_macro2::Delimiter;
+use std::cell::Cell;
+use std::mem;
+use std::rc::Rc;
+
+/// Extensions to the `ParseStream` API to support speculative parsing.
+pub trait Speculative {
+ /// Advance this parse stream to the position of a forked parse stream.
+ ///
+ /// This is the opposite operation to [`ParseStream::fork`]. You can fork a
+ /// parse stream, perform some speculative parsing, then join the original
+ /// stream to the fork to "commit" the parsing from the fork to the main
+ /// stream.
+ ///
+ /// If you can avoid doing this, you should, as it limits the ability to
+ /// generate useful errors. That said, it is often the only way to parse
+ /// syntax of the form `A* B*` for arbitrary syntax `A` and `B`. The problem
+ /// is that when the fork fails to parse an `A`, it's impossible to tell
+ /// whether that was because of a syntax error and the user meant to provide
+ /// an `A`, or that the `A`s are finished and it's time to start parsing
+ /// `B`s. Use with care.
+ ///
+ /// Also note that if `A` is a subset of `B`, `A* B*` can be parsed by
+ /// parsing `B*` and removing the leading members of `A` from the
+ /// repetition, bypassing the need to involve the downsides associated with
+ /// speculative parsing.
+ ///
+ /// [`ParseStream::fork`]: ParseBuffer::fork
+ ///
+ /// # Example
+ ///
+ /// There has been chatter about the possibility of making the colons in the
+ /// turbofish syntax like `path::to::<T>` no longer required by accepting
+ /// `path::to<T>` in expression position. Specifically, according to [RFC
+ /// 2544], [`PathSegment`] parsing should always try to consume a following
+ /// `<` token as the start of generic arguments, and reset to the `<` if
+ /// that fails (e.g. the token is acting as a less-than operator).
+ ///
+ /// This is the exact kind of parsing behavior which requires the "fork,
+ /// try, commit" behavior that [`ParseStream::fork`] discourages. With
+ /// `advance_to`, we can avoid having to parse the speculatively parsed
+ /// content a second time.
+ ///
+ /// This change in behavior can be implemented in syn by replacing just the
+ /// `Parse` implementation for `PathSegment`:
+ ///
+ /// ```
+ /// # use syn::ext::IdentExt;
+ /// use syn::parse::discouraged::Speculative;
+ /// # use syn::parse::{Parse, ParseStream};
+ /// # use syn::{Ident, PathArguments, Result, Token};
+ ///
+ /// pub struct PathSegment {
+ /// pub ident: Ident,
+ /// pub arguments: PathArguments,
+ /// }
+ /// #
+ /// # impl<T> From<T> for PathSegment
+ /// # where
+ /// # T: Into<Ident>,
+ /// # {
+ /// # fn from(ident: T) -> Self {
+ /// # PathSegment {
+ /// # ident: ident.into(),
+ /// # arguments: PathArguments::None,
+ /// # }
+ /// # }
+ /// # }
+ ///
+ /// impl Parse for PathSegment {
+ /// fn parse(input: ParseStream) -> Result<Self> {
+ /// if input.peek(Token![super])
+ /// || input.peek(Token![self])
+ /// || input.peek(Token![Self])
+ /// || input.peek(Token![crate])
+ /// {
+ /// let ident = input.call(Ident::parse_any)?;
+ /// return Ok(PathSegment::from(ident));
+ /// }
+ ///
+ /// let ident = input.parse()?;
+ /// if input.peek(Token![::]) && input.peek3(Token![<]) {
+ /// return Ok(PathSegment {
+ /// ident,
+ /// arguments: PathArguments::AngleBracketed(input.parse()?),
+ /// });
+ /// }
+ /// if input.peek(Token![<]) && !input.peek(Token![<=]) {
+ /// let fork = input.fork();
+ /// if let Ok(arguments) = fork.parse() {
+ /// input.advance_to(&fork);
+ /// return Ok(PathSegment {
+ /// ident,
+ /// arguments: PathArguments::AngleBracketed(arguments),
+ /// });
+ /// }
+ /// }
+ /// Ok(PathSegment::from(ident))
+ /// }
+ /// }
+ ///
+ /// # syn::parse_str::<PathSegment>("a<b,c>").unwrap();
+ /// ```
+ ///
+ /// # Drawbacks
+ ///
+ /// The main drawback of this style of speculative parsing is in error
+ /// presentation. Even if the lookahead is the "correct" parse, the error
+ /// that is shown is that of the "fallback" parse. To use the same example
+ /// as the turbofish above, take the following unfinished "turbofish":
+ ///
+ /// ```text
+ /// let _ = f<&'a fn(), for<'a> serde::>();
+ /// ```
+ ///
+ /// If this is parsed as generic arguments, we can provide the error message
+ ///
+ /// ```text
+ /// error: expected identifier
+ /// --> src.rs:L:C
+ /// |
+ /// L | let _ = f<&'a fn(), for<'a> serde::>();
+ /// | ^
+ /// ```
+ ///
+ /// but if parsed using the above speculative parsing, it falls back to
+ /// assuming that the `<` is a less-than when it fails to parse the generic
+ /// arguments, and tries to interpret the `&'a` as the start of a labelled
+ /// loop, resulting in the much less helpful error
+ ///
+ /// ```text
+ /// error: expected `:`
+ /// --> src.rs:L:C
+ /// |
+ /// L | let _ = f<&'a fn(), for<'a> serde::>();
+ /// | ^^
+ /// ```
+ ///
+ /// This can be mitigated with various heuristics (two examples: show both
+ /// forks' parse errors, or show the one that consumed more tokens), but
+ /// when you can control the grammar, sticking to something that can be
+ /// parsed LL(3) and without the LL(*) speculative parsing this makes
+ /// possible, displaying reasonable errors becomes much more simple.
+ ///
+ /// [RFC 2544]: https://github.com/rust-lang/rfcs/pull/2544
+ /// [`PathSegment`]: crate::PathSegment
+ ///
+ /// # Performance
+ ///
+ /// This method performs a cheap fixed amount of work that does not depend
+ /// on how far apart the two streams are positioned.
+ ///
+ /// # Panics
+ ///
+ /// The forked stream in the argument of `advance_to` must have been
+ /// obtained by forking `self`. Attempting to advance to any other stream
+ /// will cause a panic.
+ fn advance_to(&self, fork: &Self);
+}
+
+impl<'a> Speculative for ParseBuffer<'a> {
+ fn advance_to(&self, fork: &Self) {
+ if !crate::buffer::same_scope(self.cursor(), fork.cursor()) {
+ panic!("fork was not derived from the advancing parse stream");
+ }
+
+ let (self_unexp, self_sp) = inner_unexpected(self);
+ let (fork_unexp, fork_sp) = inner_unexpected(fork);
+ if !Rc::ptr_eq(&self_unexp, &fork_unexp) {
+ match (fork_sp, self_sp) {
+ // Unexpected set on the fork, but not on `self`, copy it over.
+ (Some((span, delimiter)), None) => {
+ self_unexp.set(Unexpected::Some(span, delimiter));
+ }
+ // Unexpected unset. Use chain to propagate errors from fork.
+ (None, None) => {
+ fork_unexp.set(Unexpected::Chain(self_unexp));
+
+ // Ensure toplevel 'unexpected' tokens from the fork don't
+ // propagate up the chain by replacing the root `unexpected`
+ // pointer, only 'unexpected' tokens from existing group
+ // parsers should propagate.
+ fork.unexpected
+ .set(Some(Rc::new(Cell::new(Unexpected::None))));
+ }
+ // Unexpected has been set on `self`. No changes needed.
+ (_, Some(_)) => {}
+ }
+ }
+
+ // See comment on `cell` in the struct definition.
+ self.cell
+ .set(unsafe { mem::transmute::<Cursor, Cursor<'static>>(fork.cursor()) });
+ }
+}
+
+/// Extensions to the `ParseStream` API to support manipulating invisible
+/// delimiters the same as if they were visible.
+pub trait AnyDelimiter {
+ /// Returns the delimiter, the span of the delimiter token, and the nested
+ /// contents for further parsing.
+ fn parse_any_delimiter(&self) -> Result<(Delimiter, DelimSpan, ParseBuffer)>;
+}
+
+impl<'a> AnyDelimiter for ParseBuffer<'a> {
+ fn parse_any_delimiter(&self) -> Result<(Delimiter, DelimSpan, ParseBuffer)> {
+ self.step(|cursor| {
+ if let Some((content, delimiter, span, rest)) = cursor.any_group() {
+ let scope = span.close();
+ let nested = crate::parse::advance_step_cursor(cursor, content);
+ let unexpected = crate::parse::get_unexpected(self);
+ let content = crate::parse::new_parse_buffer(scope, nested, unexpected);
+ Ok(((delimiter, span, content), rest))
+ } else {
+ Err(cursor.error("expected any delimiter"))
+ }
+ })
+ }
+}
diff --git a/rust/syn/drops.rs b/rust/syn/drops.rs
new file mode 100644
index 000000000000..c54308f02c13
--- /dev/null
+++ b/rust/syn/drops.rs
@@ -0,0 +1,58 @@
+use std::iter;
+use std::mem::ManuallyDrop;
+use std::ops::{Deref, DerefMut};
+use std::option;
+use std::slice;
+
+#[repr(transparent)]
+pub(crate) struct NoDrop<T: ?Sized>(ManuallyDrop<T>);
+
+impl<T> NoDrop<T> {
+ pub(crate) fn new(value: T) -> Self
+ where
+ T: TrivialDrop,
+ {
+ NoDrop(ManuallyDrop::new(value))
+ }
+}
+
+impl<T: ?Sized> Deref for NoDrop<T> {
+ type Target = T;
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+impl<T: ?Sized> DerefMut for NoDrop<T> {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.0
+ }
+}
+
+pub(crate) trait TrivialDrop {}
+
+impl<T> TrivialDrop for iter::Empty<T> {}
+impl<T> TrivialDrop for slice::Iter<'_, T> {}
+impl<T> TrivialDrop for slice::IterMut<'_, T> {}
+impl<T> TrivialDrop for option::IntoIter<&T> {}
+impl<T> TrivialDrop for option::IntoIter<&mut T> {}
+
+#[test]
+fn test_needs_drop() {
+ use std::mem::needs_drop;
+
+ struct NeedsDrop;
+
+ impl Drop for NeedsDrop {
+ fn drop(&mut self) {}
+ }
+
+ assert!(needs_drop::<NeedsDrop>());
+
+ // Test each of the types with a handwritten TrivialDrop impl above.
+ assert!(!needs_drop::<iter::Empty<NeedsDrop>>());
+ assert!(!needs_drop::<slice::Iter<NeedsDrop>>());
+ assert!(!needs_drop::<slice::IterMut<NeedsDrop>>());
+ assert!(!needs_drop::<option::IntoIter<&NeedsDrop>>());
+ assert!(!needs_drop::<option::IntoIter<&mut NeedsDrop>>());
+}
diff --git a/rust/syn/error.rs b/rust/syn/error.rs
new file mode 100644
index 000000000000..63310543a3b4
--- /dev/null
+++ b/rust/syn/error.rs
@@ -0,0 +1,467 @@
+#[cfg(feature = "parsing")]
+use crate::buffer::Cursor;
+use crate::thread::ThreadBound;
+use proc_macro2::{
+ Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree,
+};
+#[cfg(feature = "printing")]
+use quote::ToTokens;
+use std::fmt::{self, Debug, Display};
+use std::slice;
+use std::vec;
+
+/// The result of a Syn parser.
+pub type Result<T> = std::result::Result<T, Error>;
+
+/// Error returned when a Syn parser cannot parse the input tokens.
+///
+/// # Error reporting in proc macros
+///
+/// The correct way to report errors back to the compiler from a procedural
+/// macro is by emitting an appropriately spanned invocation of
+/// [`compile_error!`] in the generated code. This produces a better diagnostic
+/// message than simply panicking the macro.
+///
+/// [`compile_error!`]: std::compile_error!
+///
+/// When parsing macro input, the [`parse_macro_input!`] macro handles the
+/// conversion to `compile_error!` automatically.
+///
+/// [`parse_macro_input!`]: crate::parse_macro_input!
+///
+/// ```
+/// # extern crate proc_macro;
+/// #
+/// use proc_macro::TokenStream;
+/// use syn::parse::{Parse, ParseStream, Result};
+/// use syn::{parse_macro_input, ItemFn};
+///
+/// # const IGNORE: &str = stringify! {
+/// #[proc_macro_attribute]
+/// # };
+/// pub fn my_attr(args: TokenStream, input: TokenStream) -> TokenStream {
+/// let args = parse_macro_input!(args as MyAttrArgs);
+/// let input = parse_macro_input!(input as ItemFn);
+///
+/// /* ... */
+/// # TokenStream::new()
+/// }
+///
+/// struct MyAttrArgs {
+/// # _k: [(); { stringify! {
+/// ...
+/// # }; 0 }]
+/// }
+///
+/// impl Parse for MyAttrArgs {
+/// fn parse(input: ParseStream) -> Result<Self> {
+/// # stringify! {
+/// ...
+/// # };
+/// # unimplemented!()
+/// }
+/// }
+/// ```
+///
+/// For errors that arise later than the initial parsing stage, the
+/// [`.to_compile_error()`] or [`.into_compile_error()`] methods can be used to
+/// perform an explicit conversion to `compile_error!`.
+///
+/// [`.to_compile_error()`]: Error::to_compile_error
+/// [`.into_compile_error()`]: Error::into_compile_error
+///
+/// ```
+/// # extern crate proc_macro;
+/// #
+/// # use proc_macro::TokenStream;
+/// # use syn::{parse_macro_input, DeriveInput};
+/// #
+/// # const IGNORE: &str = stringify! {
+/// #[proc_macro_derive(MyDerive)]
+/// # };
+/// pub fn my_derive(input: TokenStream) -> TokenStream {
+/// let input = parse_macro_input!(input as DeriveInput);
+///
+/// // fn(DeriveInput) -> syn::Result<proc_macro2::TokenStream>
+/// expand::my_derive(input)
+/// .unwrap_or_else(syn::Error::into_compile_error)
+/// .into()
+/// }
+/// #
+/// # mod expand {
+/// # use proc_macro2::TokenStream;
+/// # use syn::{DeriveInput, Result};
+/// #
+/// # pub fn my_derive(input: DeriveInput) -> Result<TokenStream> {
+/// # unimplemented!()
+/// # }
+/// # }
+/// ```
+pub struct Error {
+ messages: Vec<ErrorMessage>,
+}
+
+struct ErrorMessage {
+ // Span is implemented as an index into a thread-local interner to keep the
+ // size small. It is not safe to access from a different thread. We want
+ // errors to be Send and Sync to play nicely with ecosystem crates for error
+ // handling, so pin the span we're given to its original thread and assume
+ // it is Span::call_site if accessed from any other thread.
+ span: ThreadBound<SpanRange>,
+ message: String,
+}
+
+// Cannot use std::ops::Range<Span> because that does not implement Copy,
+// whereas ThreadBound<T> requires a Copy impl as a way to ensure no Drop impls
+// are involved.
+struct SpanRange {
+ start: Span,
+ end: Span,
+}
+
+#[cfg(test)]
+struct _Test
+where
+ Error: Send + Sync;
+
+impl Error {
+ /// Usually the [`ParseStream::error`] method will be used instead, which
+ /// automatically uses the correct span from the current position of the
+ /// parse stream.
+ ///
+ /// Use `Error::new` when the error needs to be triggered on some span other
+ /// than where the parse stream is currently positioned.
+ ///
+ /// [`ParseStream::error`]: crate::parse::ParseBuffer::error
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use syn::{Error, Ident, LitStr, Result, Token};
+ /// use syn::parse::ParseStream;
+ ///
+ /// // Parses input that looks like `name = "string"` where the key must be
+ /// // the identifier `name` and the value may be any string literal.
+ /// // Returns the string literal.
+ /// fn parse_name(input: ParseStream) -> Result<LitStr> {
+ /// let name_token: Ident = input.parse()?;
+ /// if name_token != "name" {
+ /// // Trigger an error not on the current position of the stream,
+ /// // but on the position of the unexpected identifier.
+ /// return Err(Error::new(name_token.span(), "expected `name`"));
+ /// }
+ /// input.parse::<Token![=]>()?;
+ /// let s: LitStr = input.parse()?;
+ /// Ok(s)
+ /// }
+ /// ```
+ pub fn new<T: Display>(span: Span, message: T) -> Self {
+ return new(span, message.to_string());
+
+ fn new(span: Span, message: String) -> Error {
+ Error {
+ messages: vec![ErrorMessage {
+ span: ThreadBound::new(SpanRange {
+ start: span,
+ end: span,
+ }),
+ message,
+ }],
+ }
+ }
+ }
+
+ /// Creates an error with the specified message spanning the given syntax
+ /// tree node.
+ ///
+ /// Unlike the `Error::new` constructor, this constructor takes an argument
+ /// `tokens` which is a syntax tree node. This allows the resulting `Error`
+ /// to attempt to span all tokens inside of `tokens`. While you would
+ /// typically be able to use the `Spanned` trait with the above `Error::new`
+ /// constructor, implementation limitations today mean that
+ /// `Error::new_spanned` may provide a higher-quality error message on
+ /// stable Rust.
+ ///
+ /// When in doubt it's recommended to stick to `Error::new` (or
+ /// `ParseStream::error`)!
+ #[cfg(feature = "printing")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ pub fn new_spanned<T: ToTokens, U: Display>(tokens: T, message: U) -> Self {
+ return new_spanned(tokens.into_token_stream(), message.to_string());
+
+ fn new_spanned(tokens: TokenStream, message: String) -> Error {
+ let mut iter = tokens.into_iter();
+ let start = iter.next().map_or_else(Span::call_site, |t| t.span());
+ let end = iter.last().map_or(start, |t| t.span());
+ Error {
+ messages: vec![ErrorMessage {
+ span: ThreadBound::new(SpanRange { start, end }),
+ message,
+ }],
+ }
+ }
+ }
+
+ /// The source location of the error.
+ ///
+ /// Spans are not thread-safe so this function returns `Span::call_site()`
+ /// if called from a different thread than the one on which the `Error` was
+ /// originally created.
+ pub fn span(&self) -> Span {
+ let SpanRange { start, end } = match self.messages[0].span.get() {
+ Some(span) => *span,
+ None => return Span::call_site(),
+ };
+ start.join(end).unwrap_or(start)
+ }
+
+ /// Render the error as an invocation of [`compile_error!`].
+ ///
+ /// The [`parse_macro_input!`] macro provides a convenient way to invoke
+ /// this method correctly in a procedural macro.
+ ///
+ /// [`compile_error!`]: std::compile_error!
+ /// [`parse_macro_input!`]: crate::parse_macro_input!
+ pub fn to_compile_error(&self) -> TokenStream {
+ self.messages
+ .iter()
+ .map(ErrorMessage::to_compile_error)
+ .collect()
+ }
+
+ /// Render the error as an invocation of [`compile_error!`].
+ ///
+ /// [`compile_error!`]: std::compile_error!
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// # extern crate proc_macro;
+ /// #
+ /// use proc_macro::TokenStream;
+ /// use syn::{parse_macro_input, DeriveInput, Error};
+ ///
+ /// # const _: &str = stringify! {
+ /// #[proc_macro_derive(MyTrait)]
+ /// # };
+ /// pub fn derive_my_trait(input: TokenStream) -> TokenStream {
+ /// let input = parse_macro_input!(input as DeriveInput);
+ /// my_trait::expand(input)
+ /// .unwrap_or_else(Error::into_compile_error)
+ /// .into()
+ /// }
+ ///
+ /// mod my_trait {
+ /// use proc_macro2::TokenStream;
+ /// use syn::{DeriveInput, Result};
+ ///
+ /// pub(crate) fn expand(input: DeriveInput) -> Result<TokenStream> {
+ /// /* ... */
+ /// # unimplemented!()
+ /// }
+ /// }
+ /// ```
+ pub fn into_compile_error(self) -> TokenStream {
+ self.to_compile_error()
+ }
+
+ /// Add another error message to self such that when `to_compile_error()` is
+ /// called, both errors will be emitted together.
+ pub fn combine(&mut self, another: Error) {
+ self.messages.extend(another.messages);
+ }
+}
+
+impl ErrorMessage {
+ fn to_compile_error(&self) -> TokenStream {
+ let (start, end) = match self.span.get() {
+ Some(range) => (range.start, range.end),
+ None => (Span::call_site(), Span::call_site()),
+ };
+
+ // ::core::compile_error!($message)
+ TokenStream::from_iter([
+ TokenTree::Punct({
+ let mut punct = Punct::new(':', Spacing::Joint);
+ punct.set_span(start);
+ punct
+ }),
+ TokenTree::Punct({
+ let mut punct = Punct::new(':', Spacing::Alone);
+ punct.set_span(start);
+ punct
+ }),
+ TokenTree::Ident(Ident::new("core", start)),
+ TokenTree::Punct({
+ let mut punct = Punct::new(':', Spacing::Joint);
+ punct.set_span(start);
+ punct
+ }),
+ TokenTree::Punct({
+ let mut punct = Punct::new(':', Spacing::Alone);
+ punct.set_span(start);
+ punct
+ }),
+ TokenTree::Ident(Ident::new("compile_error", start)),
+ TokenTree::Punct({
+ let mut punct = Punct::new('!', Spacing::Alone);
+ punct.set_span(start);
+ punct
+ }),
+ TokenTree::Group({
+ let mut group = Group::new(Delimiter::Brace, {
+ TokenStream::from_iter([TokenTree::Literal({
+ let mut string = Literal::string(&self.message);
+ string.set_span(end);
+ string
+ })])
+ });
+ group.set_span(end);
+ group
+ }),
+ ])
+ }
+}
+
+#[cfg(feature = "parsing")]
+pub(crate) fn new_at<T: Display>(scope: Span, cursor: Cursor, message: T) -> Error {
+ if cursor.eof() {
+ Error::new(scope, format!("unexpected end of input, {}", message))
+ } else {
+ let span = crate::buffer::open_span_of_group(cursor);
+ Error::new(span, message)
+ }
+}
+
+#[cfg(all(feature = "parsing", any(feature = "full", feature = "derive")))]
+pub(crate) fn new2<T: Display>(start: Span, end: Span, message: T) -> Error {
+ return new2(start, end, message.to_string());
+
+ fn new2(start: Span, end: Span, message: String) -> Error {
+ Error {
+ messages: vec![ErrorMessage {
+ span: ThreadBound::new(SpanRange { start, end }),
+ message,
+ }],
+ }
+ }
+}
+
+impl Debug for Error {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ if self.messages.len() == 1 {
+ formatter
+ .debug_tuple("Error")
+ .field(&self.messages[0])
+ .finish()
+ } else {
+ formatter
+ .debug_tuple("Error")
+ .field(&self.messages)
+ .finish()
+ }
+ }
+}
+
+impl Debug for ErrorMessage {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ Debug::fmt(&self.message, formatter)
+ }
+}
+
+impl Display for Error {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str(&self.messages[0].message)
+ }
+}
+
+impl Clone for Error {
+ fn clone(&self) -> Self {
+ Error {
+ messages: self.messages.clone(),
+ }
+ }
+}
+
+impl Clone for ErrorMessage {
+ fn clone(&self) -> Self {
+ ErrorMessage {
+ span: self.span,
+ message: self.message.clone(),
+ }
+ }
+}
+
+impl Clone for SpanRange {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+
+impl Copy for SpanRange {}
+
+impl std::error::Error for Error {}
+
+impl From<LexError> for Error {
+ fn from(err: LexError) -> Self {
+ Error::new(err.span(), err)
+ }
+}
+
+impl IntoIterator for Error {
+ type Item = Error;
+ type IntoIter = IntoIter;
+
+ fn into_iter(self) -> Self::IntoIter {
+ IntoIter {
+ messages: self.messages.into_iter(),
+ }
+ }
+}
+
+pub struct IntoIter {
+ messages: vec::IntoIter<ErrorMessage>,
+}
+
+impl Iterator for IntoIter {
+ type Item = Error;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ Some(Error {
+ messages: vec![self.messages.next()?],
+ })
+ }
+}
+
+impl<'a> IntoIterator for &'a Error {
+ type Item = Error;
+ type IntoIter = Iter<'a>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ Iter {
+ messages: self.messages.iter(),
+ }
+ }
+}
+
+pub struct Iter<'a> {
+ messages: slice::Iter<'a, ErrorMessage>,
+}
+
+impl<'a> Iterator for Iter<'a> {
+ type Item = Error;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ Some(Error {
+ messages: vec![self.messages.next()?.clone()],
+ })
+ }
+}
+
+impl Extend<Error> for Error {
+ fn extend<T: IntoIterator<Item = Error>>(&mut self, iter: T) {
+ for err in iter {
+ self.combine(err);
+ }
+ }
+}
diff --git a/rust/syn/export.rs b/rust/syn/export.rs
new file mode 100644
index 000000000000..b9ea5c747b75
--- /dev/null
+++ b/rust/syn/export.rs
@@ -0,0 +1,73 @@
+#[doc(hidden)]
+pub use std::clone::Clone;
+#[doc(hidden)]
+pub use std::cmp::{Eq, PartialEq};
+#[doc(hidden)]
+pub use std::concat;
+#[doc(hidden)]
+pub use std::default::Default;
+#[doc(hidden)]
+pub use std::fmt::Debug;
+#[doc(hidden)]
+pub use std::hash::{Hash, Hasher};
+#[doc(hidden)]
+pub use std::marker::Copy;
+#[doc(hidden)]
+pub use std::option::Option::{None, Some};
+#[doc(hidden)]
+pub use std::result::Result::{Err, Ok};
+#[doc(hidden)]
+pub use std::stringify;
+
+#[doc(hidden)]
+pub type Formatter<'a> = std::fmt::Formatter<'a>;
+#[doc(hidden)]
+pub type FmtResult = std::fmt::Result;
+
+#[doc(hidden)]
+pub type bool = std::primitive::bool;
+#[doc(hidden)]
+pub type str = std::primitive::str;
+
+#[cfg(feature = "printing")]
+#[doc(hidden)]
+pub use quote;
+
+#[doc(hidden)]
+pub type Span = proc_macro2::Span;
+#[doc(hidden)]
+pub type TokenStream2 = proc_macro2::TokenStream;
+
+#[cfg(feature = "parsing")]
+#[doc(hidden)]
+pub use crate::group::{parse_braces, parse_brackets, parse_parens};
+
+#[doc(hidden)]
+pub use crate::span::IntoSpans;
+
+#[cfg(all(feature = "parsing", feature = "printing"))]
+#[doc(hidden)]
+pub use crate::parse_quote::parse as parse_quote;
+
+#[cfg(feature = "parsing")]
+#[doc(hidden)]
+pub use crate::token::parsing::{peek_punct, punct as parse_punct};
+
+#[cfg(feature = "printing")]
+#[doc(hidden)]
+pub use crate::token::printing::punct as print_punct;
+
+#[cfg(feature = "parsing")]
+#[doc(hidden)]
+pub use crate::token::private::CustomToken;
+
+#[cfg(feature = "proc-macro")]
+#[doc(hidden)]
+pub type TokenStream = proc_macro::TokenStream;
+
+#[cfg(feature = "printing")]
+#[doc(hidden)]
+pub use quote::{ToTokens, TokenStreamExt};
+
+#[doc(hidden)]
+pub struct private(pub(crate) ());
diff --git a/rust/syn/expr.rs b/rust/syn/expr.rs
new file mode 100644
index 000000000000..1e49d9a6633e
--- /dev/null
+++ b/rust/syn/expr.rs
@@ -0,0 +1,4173 @@
+use crate::attr::Attribute;
+#[cfg(all(feature = "parsing", feature = "full"))]
+use crate::error::Result;
+#[cfg(feature = "parsing")]
+use crate::ext::IdentExt as _;
+#[cfg(feature = "full")]
+use crate::generics::BoundLifetimes;
+use crate::ident::Ident;
+#[cfg(any(feature = "parsing", feature = "full"))]
+use crate::lifetime::Lifetime;
+use crate::lit::Lit;
+use crate::mac::Macro;
+use crate::op::{BinOp, UnOp};
+#[cfg(feature = "parsing")]
+use crate::parse::ParseStream;
+#[cfg(feature = "full")]
+use crate::pat::Pat;
+use crate::path::{AngleBracketedGenericArguments, Path, QSelf};
+use crate::punctuated::Punctuated;
+#[cfg(feature = "full")]
+use crate::stmt::Block;
+use crate::token;
+#[cfg(feature = "full")]
+use crate::ty::ReturnType;
+use crate::ty::Type;
+use proc_macro2::{Span, TokenStream};
+#[cfg(feature = "printing")]
+use quote::IdentFragment;
+#[cfg(feature = "printing")]
+use std::fmt::{self, Display};
+use std::hash::{Hash, Hasher};
+#[cfg(all(feature = "parsing", feature = "full"))]
+use std::mem;
+
+ast_enum_of_structs! {
+ /// A Rust expression.
+ ///
+ /// *This type is available only if Syn is built with the `"derive"` or `"full"`
+ /// feature, but most of the variants are not available unless "full" is enabled.*
+ ///
+ /// # Syntax tree enums
+ ///
+ /// This type is a syntax tree enum. In Syn this and other syntax tree enums
+ /// are designed to be traversed using the following rebinding idiom.
+ ///
+ /// ```
+ /// # use syn::Expr;
+ /// #
+ /// # fn example(expr: Expr) {
+ /// # const IGNORE: &str = stringify! {
+ /// let expr: Expr = /* ... */;
+ /// # };
+ /// match expr {
+ /// Expr::MethodCall(expr) => {
+ /// /* ... */
+ /// }
+ /// Expr::Cast(expr) => {
+ /// /* ... */
+ /// }
+ /// Expr::If(expr) => {
+ /// /* ... */
+ /// }
+ ///
+ /// /* ... */
+ /// # _ => {}
+ /// # }
+ /// # }
+ /// ```
+ ///
+ /// We begin with a variable `expr` of type `Expr` that has no fields
+ /// (because it is an enum), and by matching on it and rebinding a variable
+ /// with the same name `expr` we effectively imbue our variable with all of
+ /// the data fields provided by the variant that it turned out to be. So for
+ /// example above if we ended up in the `MethodCall` case then we get to use
+ /// `expr.receiver`, `expr.args` etc; if we ended up in the `If` case we get
+ /// to use `expr.cond`, `expr.then_branch`, `expr.else_branch`.
+ ///
+ /// This approach avoids repeating the variant names twice on every line.
+ ///
+ /// ```
+ /// # use syn::{Expr, ExprMethodCall};
+ /// #
+ /// # fn example(expr: Expr) {
+ /// // Repetitive; recommend not doing this.
+ /// match expr {
+ /// Expr::MethodCall(ExprMethodCall { method, args, .. }) => {
+ /// # }
+ /// # _ => {}
+ /// # }
+ /// # }
+ /// ```
+ ///
+ /// In general, the name to which a syntax tree enum variant is bound should
+ /// be a suitable name for the complete syntax tree enum type.
+ ///
+ /// ```
+ /// # use syn::{Expr, ExprField};
+ /// #
+ /// # fn example(discriminant: ExprField) {
+ /// // Binding is called `base` which is the name I would use if I were
+ /// // assigning `*discriminant.base` without an `if let`.
+ /// if let Expr::Tuple(base) = *discriminant.base {
+ /// # }
+ /// # }
+ /// ```
+ ///
+ /// A sign that you may not be choosing the right variable names is if you
+ /// see names getting repeated in your code, like accessing
+ /// `receiver.receiver` or `pat.pat` or `cond.cond`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ #[non_exhaustive]
+ pub enum Expr {
+ /// A slice literal expression: `[a, b, c, d]`.
+ Array(ExprArray),
+
+ /// An assignment expression: `a = compute()`.
+ Assign(ExprAssign),
+
+ /// An async block: `async { ... }`.
+ Async(ExprAsync),
+
+ /// An await expression: `fut.await`.
+ Await(ExprAwait),
+
+ /// A binary operation: `a + b`, `a += b`.
+ Binary(ExprBinary),
+
+ /// A blocked scope: `{ ... }`.
+ Block(ExprBlock),
+
+ /// A `break`, with an optional label to break and an optional
+ /// expression.
+ Break(ExprBreak),
+
+ /// A function call expression: `invoke(a, b)`.
+ Call(ExprCall),
+
+ /// A cast expression: `foo as f64`.
+ Cast(ExprCast),
+
+ /// A closure expression: `|a, b| a + b`.
+ Closure(ExprClosure),
+
+ /// A const block: `const { ... }`.
+ Const(ExprConst),
+
+ /// A `continue`, with an optional label.
+ Continue(ExprContinue),
+
+ /// Access of a named struct field (`obj.k`) or unnamed tuple struct
+ /// field (`obj.0`).
+ Field(ExprField),
+
+ /// A for loop: `for pat in expr { ... }`.
+ ForLoop(ExprForLoop),
+
+ /// An expression contained within invisible delimiters.
+ ///
+ /// This variant is important for faithfully representing the precedence
+ /// of expressions and is related to `None`-delimited spans in a
+ /// `TokenStream`.
+ Group(ExprGroup),
+
+ /// An `if` expression with an optional `else` block: `if expr { ... }
+ /// else { ... }`.
+ ///
+ /// The `else` branch expression may only be an `If` or `Block`
+ /// expression, not any of the other types of expression.
+ If(ExprIf),
+
+ /// A square bracketed indexing expression: `vector[2]`.
+ Index(ExprIndex),
+
+ /// The inferred value of a const generic argument, denoted `_`.
+ Infer(ExprInfer),
+
+ /// A `let` guard: `let Some(x) = opt`.
+ Let(ExprLet),
+
+ /// A literal in place of an expression: `1`, `"foo"`.
+ Lit(ExprLit),
+
+ /// Conditionless loop: `loop { ... }`.
+ Loop(ExprLoop),
+
+ /// A macro invocation expression: `format!("{}", q)`.
+ Macro(ExprMacro),
+
+ /// A `match` expression: `match n { Some(n) => {}, None => {} }`.
+ Match(ExprMatch),
+
+ /// A method call expression: `x.foo::<T>(a, b)`.
+ MethodCall(ExprMethodCall),
+
+ /// A parenthesized expression: `(a + b)`.
+ Paren(ExprParen),
+
+ /// A path like `std::mem::replace` possibly containing generic
+ /// parameters and a qualified self-type.
+ ///
+ /// A plain identifier like `x` is a path of length 1.
+ Path(ExprPath),
+
+ /// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`.
+ Range(ExprRange),
+
+ /// Address-of operation: `&raw const place` or `&raw mut place`.
+ RawAddr(ExprRawAddr),
+
+ /// A referencing operation: `&a` or `&mut a`.
+ Reference(ExprReference),
+
+ /// An array literal constructed from one repeated element: `[0u8; N]`.
+ Repeat(ExprRepeat),
+
+ /// A `return`, with an optional value to be returned.
+ Return(ExprReturn),
+
+ /// A struct literal expression: `Point { x: 1, y: 1 }`.
+ ///
+ /// The `rest` provides the value of the remaining fields as in `S { a:
+ /// 1, b: 1, ..rest }`.
+ Struct(ExprStruct),
+
+ /// A try-expression: `expr?`.
+ Try(ExprTry),
+
+ /// A try block: `try { ... }`.
+ TryBlock(ExprTryBlock),
+
+ /// A tuple expression: `(a, b, c, d)`.
+ Tuple(ExprTuple),
+
+ /// A unary operation: `!x`, `*x`.
+ Unary(ExprUnary),
+
+ /// An unsafe block: `unsafe { ... }`.
+ Unsafe(ExprUnsafe),
+
+ /// Tokens in expression position not interpreted by Syn.
+ Verbatim(TokenStream),
+
+ /// A while loop: `while expr { ... }`.
+ While(ExprWhile),
+
+ /// A yield expression: `yield expr`.
+ Yield(ExprYield),
+
+ // For testing exhaustiveness in downstream code, use the following idiom:
+ //
+ // match expr {
+ // #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))]
+ //
+ // Expr::Array(expr) => {...}
+ // Expr::Assign(expr) => {...}
+ // ...
+ // Expr::Yield(expr) => {...}
+ //
+ // _ => { /* some sane fallback */ }
+ // }
+ //
+ // This way we fail your tests but don't break your library when adding
+ // a variant. You will be notified by a test failure when a variant is
+ // added, so that you can add code to handle it, but your library will
+ // continue to compile and work for downstream users in the interim.
+ }
+}
+
+ast_struct! {
+ /// A slice literal expression: `[a, b, c, d]`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ExprArray #full {
+ pub attrs: Vec<Attribute>,
+ pub bracket_token: token::Bracket,
+ pub elems: Punctuated<Expr, Token![,]>,
+ }
+}
+
+ast_struct! {
+ /// An assignment expression: `a = compute()`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ExprAssign #full {
+ pub attrs: Vec<Attribute>,
+ pub left: Box<Expr>,
+ pub eq_token: Token![=],
+ pub right: Box<Expr>,
+ }
+}
+
+ast_struct! {
+ /// An async block: `async { ... }`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ExprAsync #full {
+ pub attrs: Vec<Attribute>,
+ pub async_token: Token![async],
+ pub capture: Option<Token![move]>,
+ pub block: Block,
+ }
+}
+
+ast_struct! {
+ /// An await expression: `fut.await`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ExprAwait #full {
+ pub attrs: Vec<Attribute>,
+ pub base: Box<Expr>,
+ pub dot_token: Token![.],
+ pub await_token: Token![await],
+ }
+}
+
+ast_struct! {
+ /// A binary operation: `a + b`, `a += b`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct ExprBinary {
+ pub attrs: Vec<Attribute>,
+ pub left: Box<Expr>,
+ pub op: BinOp,
+ pub right: Box<Expr>,
+ }
+}
+
+ast_struct! {
+ /// A blocked scope: `{ ... }`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ExprBlock #full {
+ pub attrs: Vec<Attribute>,
+ pub label: Option<Label>,
+ pub block: Block,
+ }
+}
+
+ast_struct! {
+ /// A `break`, with an optional label to break and an optional
+ /// expression.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ExprBreak #full {
+ pub attrs: Vec<Attribute>,
+ pub break_token: Token![break],
+ pub label: Option<Lifetime>,
+ pub expr: Option<Box<Expr>>,
+ }
+}
+
+ast_struct! {
+ /// A function call expression: `invoke(a, b)`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct ExprCall {
+ pub attrs: Vec<Attribute>,
+ pub func: Box<Expr>,
+ pub paren_token: token::Paren,
+ pub args: Punctuated<Expr, Token![,]>,
+ }
+}
+
+ast_struct! {
+ /// A cast expression: `foo as f64`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct ExprCast {
+ pub attrs: Vec<Attribute>,
+ pub expr: Box<Expr>,
+ pub as_token: Token![as],
+ pub ty: Box<Type>,
+ }
+}
+
+ast_struct! {
+ /// A closure expression: `|a, b| a + b`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ExprClosure #full {
+ pub attrs: Vec<Attribute>,
+ pub lifetimes: Option<BoundLifetimes>,
+ pub constness: Option<Token![const]>,
+ pub movability: Option<Token![static]>,
+ pub asyncness: Option<Token![async]>,
+ pub capture: Option<Token![move]>,
+ pub or1_token: Token![|],
+ pub inputs: Punctuated<Pat, Token![,]>,
+ pub or2_token: Token![|],
+ pub output: ReturnType,
+ pub body: Box<Expr>,
+ }
+}
+
+ast_struct! {
+ /// A const block: `const { ... }`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ExprConst #full {
+ pub attrs: Vec<Attribute>,
+ pub const_token: Token![const],
+ pub block: Block,
+ }
+}
+
+ast_struct! {
+ /// A `continue`, with an optional label.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ExprContinue #full {
+ pub attrs: Vec<Attribute>,
+ pub continue_token: Token![continue],
+ pub label: Option<Lifetime>,
+ }
+}
+
+ast_struct! {
+ /// Access of a named struct field (`obj.k`) or unnamed tuple struct
+ /// field (`obj.0`).
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct ExprField {
+ pub attrs: Vec<Attribute>,
+ pub base: Box<Expr>,
+ pub dot_token: Token![.],
+ pub member: Member,
+ }
+}
+
+ast_struct! {
+ /// A for loop: `for pat in expr { ... }`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ExprForLoop #full {
+ pub attrs: Vec<Attribute>,
+ pub label: Option<Label>,
+ pub for_token: Token![for],
+ pub pat: Box<Pat>,
+ pub in_token: Token![in],
+ pub expr: Box<Expr>,
+ pub body: Block,
+ }
+}
+
+ast_struct! {
+ /// An expression contained within invisible delimiters.
+ ///
+ /// This variant is important for faithfully representing the precedence
+ /// of expressions and is related to `None`-delimited spans in a
+ /// `TokenStream`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ExprGroup {
+ pub attrs: Vec<Attribute>,
+ pub group_token: token::Group,
+ pub expr: Box<Expr>,
+ }
+}
+
+ast_struct! {
+ /// An `if` expression with an optional `else` block: `if expr { ... }
+ /// else { ... }`.
+ ///
+ /// The `else` branch expression may only be an `If` or `Block`
+ /// expression, not any of the other types of expression.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ExprIf #full {
+ pub attrs: Vec<Attribute>,
+ pub if_token: Token![if],
+ pub cond: Box<Expr>,
+ pub then_branch: Block,
+ pub else_branch: Option<(Token![else], Box<Expr>)>,
+ }
+}
+
+ast_struct! {
+ /// A square bracketed indexing expression: `vector[2]`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct ExprIndex {
+ pub attrs: Vec<Attribute>,
+ pub expr: Box<Expr>,
+ pub bracket_token: token::Bracket,
+ pub index: Box<Expr>,
+ }
+}
+
+ast_struct! {
+ /// The inferred value of a const generic argument, denoted `_`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ExprInfer #full {
+ pub attrs: Vec<Attribute>,
+ pub underscore_token: Token![_],
+ }
+}
+
+ast_struct! {
+ /// A `let` guard: `let Some(x) = opt`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ExprLet #full {
+ pub attrs: Vec<Attribute>,
+ pub let_token: Token![let],
+ pub pat: Box<Pat>,
+ pub eq_token: Token![=],
+ pub expr: Box<Expr>,
+ }
+}
+
+ast_struct! {
+ /// A literal in place of an expression: `1`, `"foo"`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct ExprLit {
+ pub attrs: Vec<Attribute>,
+ pub lit: Lit,
+ }
+}
+
+ast_struct! {
+ /// Conditionless loop: `loop { ... }`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ExprLoop #full {
+ pub attrs: Vec<Attribute>,
+ pub label: Option<Label>,
+ pub loop_token: Token![loop],
+ pub body: Block,
+ }
+}
+
+ast_struct! {
+ /// A macro invocation expression: `format!("{}", q)`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct ExprMacro {
+ pub attrs: Vec<Attribute>,
+ pub mac: Macro,
+ }
+}
+
+ast_struct! {
+ /// A `match` expression: `match n { Some(n) => {}, None => {} }`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ExprMatch #full {
+ pub attrs: Vec<Attribute>,
+ pub match_token: Token![match],
+ pub expr: Box<Expr>,
+ pub brace_token: token::Brace,
+ pub arms: Vec<Arm>,
+ }
+}
+
+ast_struct! {
+ /// A method call expression: `x.foo::<T>(a, b)`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct ExprMethodCall {
+ pub attrs: Vec<Attribute>,
+ pub receiver: Box<Expr>,
+ pub dot_token: Token![.],
+ pub method: Ident,
+ pub turbofish: Option<AngleBracketedGenericArguments>,
+ pub paren_token: token::Paren,
+ pub args: Punctuated<Expr, Token![,]>,
+ }
+}
+
+ast_struct! {
+ /// A parenthesized expression: `(a + b)`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct ExprParen {
+ pub attrs: Vec<Attribute>,
+ pub paren_token: token::Paren,
+ pub expr: Box<Expr>,
+ }
+}
+
+ast_struct! {
+ /// A path like `std::mem::replace` possibly containing generic
+ /// parameters and a qualified self-type.
+ ///
+ /// A plain identifier like `x` is a path of length 1.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct ExprPath {
+ pub attrs: Vec<Attribute>,
+ pub qself: Option<QSelf>,
+ pub path: Path,
+ }
+}
+
+ast_struct! {
+ /// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ExprRange #full {
+ pub attrs: Vec<Attribute>,
+ pub start: Option<Box<Expr>>,
+ pub limits: RangeLimits,
+ pub end: Option<Box<Expr>>,
+ }
+}
+
+ast_struct! {
+ /// Address-of operation: `&raw const place` or `&raw mut place`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ExprRawAddr #full {
+ pub attrs: Vec<Attribute>,
+ pub and_token: Token![&],
+ pub raw: Token![raw],
+ pub mutability: PointerMutability,
+ pub expr: Box<Expr>,
+ }
+}
+
+ast_struct! {
+ /// A referencing operation: `&a` or `&mut a`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct ExprReference {
+ pub attrs: Vec<Attribute>,
+ pub and_token: Token![&],
+ pub mutability: Option<Token![mut]>,
+ pub expr: Box<Expr>,
+ }
+}
+
+ast_struct! {
+ /// An array literal constructed from one repeated element: `[0u8; N]`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ExprRepeat #full {
+ pub attrs: Vec<Attribute>,
+ pub bracket_token: token::Bracket,
+ pub expr: Box<Expr>,
+ pub semi_token: Token![;],
+ pub len: Box<Expr>,
+ }
+}
+
+ast_struct! {
+ /// A `return`, with an optional value to be returned.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ExprReturn #full {
+ pub attrs: Vec<Attribute>,
+ pub return_token: Token![return],
+ pub expr: Option<Box<Expr>>,
+ }
+}
+
+ast_struct! {
+ /// A struct literal expression: `Point { x: 1, y: 1 }`.
+ ///
+ /// The `rest` provides the value of the remaining fields as in `S { a:
+ /// 1, b: 1, ..rest }`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct ExprStruct {
+ pub attrs: Vec<Attribute>,
+ pub qself: Option<QSelf>,
+ pub path: Path,
+ pub brace_token: token::Brace,
+ pub fields: Punctuated<FieldValue, Token![,]>,
+ pub dot2_token: Option<Token![..]>,
+ pub rest: Option<Box<Expr>>,
+ }
+}
+
+ast_struct! {
+ /// A try-expression: `expr?`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ExprTry #full {
+ pub attrs: Vec<Attribute>,
+ pub expr: Box<Expr>,
+ pub question_token: Token![?],
+ }
+}
+
+ast_struct! {
+ /// A try block: `try { ... }`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ExprTryBlock #full {
+ pub attrs: Vec<Attribute>,
+ pub try_token: Token![try],
+ pub block: Block,
+ }
+}
+
+ast_struct! {
+ /// A tuple expression: `(a, b, c, d)`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ExprTuple {
+ pub attrs: Vec<Attribute>,
+ pub paren_token: token::Paren,
+ pub elems: Punctuated<Expr, Token![,]>,
+ }
+}
+
+ast_struct! {
+ /// A unary operation: `!x`, `*x`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct ExprUnary {
+ pub attrs: Vec<Attribute>,
+ pub op: UnOp,
+ pub expr: Box<Expr>,
+ }
+}
+
+ast_struct! {
+ /// An unsafe block: `unsafe { ... }`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ExprUnsafe #full {
+ pub attrs: Vec<Attribute>,
+ pub unsafe_token: Token![unsafe],
+ pub block: Block,
+ }
+}
+
+ast_struct! {
+ /// A while loop: `while expr { ... }`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ExprWhile #full {
+ pub attrs: Vec<Attribute>,
+ pub label: Option<Label>,
+ pub while_token: Token![while],
+ pub cond: Box<Expr>,
+ pub body: Block,
+ }
+}
+
+ast_struct! {
+ /// A yield expression: `yield expr`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ExprYield #full {
+ pub attrs: Vec<Attribute>,
+ pub yield_token: Token![yield],
+ pub expr: Option<Box<Expr>>,
+ }
+}
+
+impl Expr {
+ /// An unspecified invalid expression.
+ ///
+ /// ```
+ /// use quote::ToTokens;
+ /// use std::mem;
+ /// use syn::{parse_quote, Expr};
+ ///
+ /// fn unparenthesize(e: &mut Expr) {
+ /// while let Expr::Paren(paren) = e {
+ /// *e = mem::replace(&mut *paren.expr, Expr::PLACEHOLDER);
+ /// }
+ /// }
+ ///
+ /// fn main() {
+ /// let mut e: Expr = parse_quote! { ((1 + 1)) };
+ /// unparenthesize(&mut e);
+ /// assert_eq!("1 + 1", e.to_token_stream().to_string());
+ /// }
+ /// ```
+ pub const PLACEHOLDER: Self = Expr::Path(ExprPath {
+ attrs: Vec::new(),
+ qself: None,
+ path: Path {
+ leading_colon: None,
+ segments: Punctuated::new(),
+ },
+ });
+
+ /// An alternative to the primary `Expr::parse` parser (from the [`Parse`]
+ /// trait) for ambiguous syntactic positions in which a trailing brace
+ /// should not be taken as part of the expression.
+ ///
+ /// [`Parse`]: crate::parse::Parse
+ ///
+ /// Rust grammar has an ambiguity where braces sometimes turn a path
+ /// expression into a struct initialization and sometimes do not. In the
+ /// following code, the expression `S {}` is one expression. Presumably
+ /// there is an empty struct `struct S {}` defined somewhere which it is
+ /// instantiating.
+ ///
+ /// ```
+ /// # struct S;
+ /// # impl std::ops::Deref for S {
+ /// # type Target = bool;
+ /// # fn deref(&self) -> &Self::Target {
+ /// # &true
+ /// # }
+ /// # }
+ /// let _ = *S {};
+ ///
+ /// // parsed by rustc as: `*(S {})`
+ /// ```
+ ///
+ /// We would want to parse the above using `Expr::parse` after the `=`
+ /// token.
+ ///
+ /// But in the following, `S {}` is *not* a struct init expression.
+ ///
+ /// ```
+ /// # const S: &bool = &true;
+ /// if *S {} {}
+ ///
+ /// // parsed by rustc as:
+ /// //
+ /// // if (*S) {
+ /// // /* empty block */
+ /// // }
+ /// // {
+ /// // /* another empty block */
+ /// // }
+ /// ```
+ ///
+ /// For that reason we would want to parse if-conditions using
+ /// `Expr::parse_without_eager_brace` after the `if` token. Same for similar
+ /// syntactic positions such as the condition expr after a `while` token or
+ /// the expr at the top of a `match`.
+ ///
+ /// The Rust grammar's choices around which way this ambiguity is resolved
+ /// at various syntactic positions is fairly arbitrary. Really either parse
+ /// behavior could work in most positions, and language designers just
+ /// decide each case based on which is more likely to be what the programmer
+ /// had in mind most of the time.
+ ///
+ /// ```
+ /// # struct S;
+ /// # fn doc() -> S {
+ /// if return S {} {}
+ /// # unreachable!()
+ /// # }
+ ///
+ /// // parsed by rustc as:
+ /// //
+ /// // if (return (S {})) {
+ /// // }
+ /// //
+ /// // but could equally well have been this other arbitrary choice:
+ /// //
+ /// // if (return S) {
+ /// // }
+ /// // {}
+ /// ```
+ ///
+ /// Note the grammar ambiguity on trailing braces is distinct from
+ /// precedence and is not captured by assigning a precedence level to the
+ /// braced struct init expr in relation to other operators. This can be
+ /// illustrated by `return 0..S {}` vs `match 0..S {}`. The former parses as
+ /// `return (0..(S {}))` implying tighter precedence for struct init than
+ /// `..`, while the latter parses as `match (0..S) {}` implying tighter
+ /// precedence for `..` than struct init, a contradiction.
+ #[cfg(all(feature = "full", feature = "parsing"))]
+ #[cfg_attr(docsrs, doc(cfg(all(feature = "full", feature = "parsing"))))]
+ pub fn parse_without_eager_brace(input: ParseStream) -> Result<Expr> {
+ parsing::ambiguous_expr(input, parsing::AllowStruct(false))
+ }
+
+ /// An alternative to the primary `Expr::parse` parser (from the [`Parse`]
+ /// trait) for syntactic positions in which expression boundaries are placed
+ /// more eagerly than done by the typical expression grammar. This includes
+ /// expressions at the head of a statement or in the right-hand side of a
+ /// `match` arm.
+ ///
+ /// [`Parse`]: crate::parse::Parse
+ ///
+ /// Compare the following cases:
+ ///
+ /// 1.
+ /// ```
+ /// # let result = ();
+ /// # let guard = false;
+ /// # let cond = true;
+ /// # let f = true;
+ /// # let g = f;
+ /// #
+ /// let _ = match result {
+ /// () if guard => if cond { f } else { g }
+ /// () => false,
+ /// };
+ /// ```
+ ///
+ /// 2.
+ /// ```
+ /// # let cond = true;
+ /// # let f = ();
+ /// # let g = f;
+ /// #
+ /// let _ = || {
+ /// if cond { f } else { g }
+ /// ()
+ /// };
+ /// ```
+ ///
+ /// 3.
+ /// ```
+ /// # let cond = true;
+ /// # let f = || ();
+ /// # let g = f;
+ /// #
+ /// let _ = [if cond { f } else { g } ()];
+ /// ```
+ ///
+ /// The same sequence of tokens `if cond { f } else { g } ()` appears in
+ /// expression position 3 times. The first two syntactic positions use eager
+ /// placement of expression boundaries, and parse as `Expr::If`, with the
+ /// adjacent `()` becoming `Pat::Tuple` or `Expr::Tuple`. In contrast, the
+ /// third case uses standard expression boundaries and parses as
+ /// `Expr::Call`.
+ ///
+ /// As with [`parse_without_eager_brace`], this ambiguity in the Rust
+ /// grammar is independent of precedence.
+ ///
+ /// [`parse_without_eager_brace`]: Self::parse_without_eager_brace
+ #[cfg(all(feature = "full", feature = "parsing"))]
+ #[cfg_attr(docsrs, doc(cfg(all(feature = "full", feature = "parsing"))))]
+ pub fn parse_with_earlier_boundary_rule(input: ParseStream) -> Result<Expr> {
+ parsing::parse_with_earlier_boundary_rule(input)
+ }
+
+ /// Returns whether the next token in the parse stream is one that might
+ /// possibly form the beginning of an expr.
+ ///
+ /// This classification is a load-bearing part of the grammar of some Rust
+ /// expressions, notably `return` and `break`. For example `return < …` will
+ /// never parse `<` as a binary operator regardless of what comes after,
+ /// because `<` is a legal starting token for an expression and so it's
+ /// required to be continued as a return value, such as `return <Struct as
+ /// Trait>::CONST`. Meanwhile `return > …` treats the `>` as a binary
+ /// operator because it cannot be a starting token for any Rust expression.
+ #[cfg(feature = "parsing")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ pub fn peek(input: ParseStream) -> bool {
+ input.peek(Ident::peek_any) && !input.peek(Token![as]) // value name or keyword
+ || input.peek(token::Paren) // tuple
+ || input.peek(token::Bracket) // array
+ || input.peek(token::Brace) // block
+ || input.peek(Lit) // literal
+ || input.peek(Token![!]) && !input.peek(Token![!=]) // operator not
+ || input.peek(Token![-]) && !input.peek(Token![-=]) && !input.peek(Token![->]) // unary minus
+ || input.peek(Token![*]) && !input.peek(Token![*=]) // dereference
+ || input.peek(Token![|]) && !input.peek(Token![|=]) // closure
+ || input.peek(Token![&]) && !input.peek(Token![&=]) // reference
+ || input.peek(Token![..]) // range
+ || input.peek(Token![<]) && !input.peek(Token![<=]) && !input.peek(Token![<<=]) // associated path
+ || input.peek(Token![::]) // absolute path
+ || input.peek(Lifetime) // labeled loop
+ || input.peek(Token![#]) // expression attributes
+ }
+
+ #[cfg(all(feature = "parsing", feature = "full"))]
+ pub(crate) fn replace_attrs(&mut self, new: Vec<Attribute>) -> Vec<Attribute> {
+ match self {
+ Expr::Array(ExprArray { attrs, .. })
+ | Expr::Assign(ExprAssign { attrs, .. })
+ | Expr::Async(ExprAsync { attrs, .. })
+ | Expr::Await(ExprAwait { attrs, .. })
+ | Expr::Binary(ExprBinary { attrs, .. })
+ | Expr::Block(ExprBlock { attrs, .. })
+ | Expr::Break(ExprBreak { attrs, .. })
+ | Expr::Call(ExprCall { attrs, .. })
+ | Expr::Cast(ExprCast { attrs, .. })
+ | Expr::Closure(ExprClosure { attrs, .. })
+ | Expr::Const(ExprConst { attrs, .. })
+ | Expr::Continue(ExprContinue { attrs, .. })
+ | Expr::Field(ExprField { attrs, .. })
+ | Expr::ForLoop(ExprForLoop { attrs, .. })
+ | Expr::Group(ExprGroup { attrs, .. })
+ | Expr::If(ExprIf { attrs, .. })
+ | Expr::Index(ExprIndex { attrs, .. })
+ | Expr::Infer(ExprInfer { attrs, .. })
+ | Expr::Let(ExprLet { attrs, .. })
+ | Expr::Lit(ExprLit { attrs, .. })
+ | Expr::Loop(ExprLoop { attrs, .. })
+ | Expr::Macro(ExprMacro { attrs, .. })
+ | Expr::Match(ExprMatch { attrs, .. })
+ | Expr::MethodCall(ExprMethodCall { attrs, .. })
+ | Expr::Paren(ExprParen { attrs, .. })
+ | Expr::Path(ExprPath { attrs, .. })
+ | Expr::Range(ExprRange { attrs, .. })
+ | Expr::RawAddr(ExprRawAddr { attrs, .. })
+ | Expr::Reference(ExprReference { attrs, .. })
+ | Expr::Repeat(ExprRepeat { attrs, .. })
+ | Expr::Return(ExprReturn { attrs, .. })
+ | Expr::Struct(ExprStruct { attrs, .. })
+ | Expr::Try(ExprTry { attrs, .. })
+ | Expr::TryBlock(ExprTryBlock { attrs, .. })
+ | Expr::Tuple(ExprTuple { attrs, .. })
+ | Expr::Unary(ExprUnary { attrs, .. })
+ | Expr::Unsafe(ExprUnsafe { attrs, .. })
+ | Expr::While(ExprWhile { attrs, .. })
+ | Expr::Yield(ExprYield { attrs, .. }) => mem::replace(attrs, new),
+ Expr::Verbatim(_) => Vec::new(),
+ }
+ }
+}
+
+ast_enum! {
+ /// A struct or tuple struct field accessed in a struct literal or field
+ /// expression.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub enum Member {
+ /// A named field like `self.x`.
+ Named(Ident),
+ /// An unnamed field like `self.0`.
+ Unnamed(Index),
+ }
+}
+
+impl From<Ident> for Member {
+ fn from(ident: Ident) -> Member {
+ Member::Named(ident)
+ }
+}
+
+impl From<Index> for Member {
+ fn from(index: Index) -> Member {
+ Member::Unnamed(index)
+ }
+}
+
+impl From<usize> for Member {
+ fn from(index: usize) -> Member {
+ Member::Unnamed(Index::from(index))
+ }
+}
+
+impl Eq for Member {}
+
+impl PartialEq for Member {
+ fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ (Member::Named(this), Member::Named(other)) => this == other,
+ (Member::Unnamed(this), Member::Unnamed(other)) => this == other,
+ _ => false,
+ }
+ }
+}
+
+impl Hash for Member {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ match self {
+ Member::Named(m) => m.hash(state),
+ Member::Unnamed(m) => m.hash(state),
+ }
+ }
+}
+
+#[cfg(feature = "printing")]
+impl IdentFragment for Member {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ Member::Named(m) => Display::fmt(m, formatter),
+ Member::Unnamed(m) => Display::fmt(&m.index, formatter),
+ }
+ }
+
+ fn span(&self) -> Option<Span> {
+ match self {
+ Member::Named(m) => Some(m.span()),
+ Member::Unnamed(m) => Some(m.span),
+ }
+ }
+}
+
+#[cfg(any(feature = "parsing", feature = "printing"))]
+impl Member {
+ pub(crate) fn is_named(&self) -> bool {
+ match self {
+ Member::Named(_) => true,
+ Member::Unnamed(_) => false,
+ }
+ }
+}
+
+ast_struct! {
+ /// The index of an unnamed tuple struct field.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct Index {
+ pub index: u32,
+ pub span: Span,
+ }
+}
+
+impl From<usize> for Index {
+ fn from(index: usize) -> Index {
+ assert!(index < u32::MAX as usize);
+ Index {
+ index: index as u32,
+ span: Span::call_site(),
+ }
+ }
+}
+
+impl Eq for Index {}
+
+impl PartialEq for Index {
+ fn eq(&self, other: &Self) -> bool {
+ self.index == other.index
+ }
+}
+
+impl Hash for Index {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ self.index.hash(state);
+ }
+}
+
+#[cfg(feature = "printing")]
+impl IdentFragment for Index {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ Display::fmt(&self.index, formatter)
+ }
+
+ fn span(&self) -> Option<Span> {
+ Some(self.span)
+ }
+}
+
+ast_struct! {
+ /// A field-value pair in a struct literal.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct FieldValue {
+ pub attrs: Vec<Attribute>,
+ pub member: Member,
+
+ /// The colon in `Struct { x: x }`. If written in shorthand like
+ /// `Struct { x }`, there is no colon.
+ pub colon_token: Option<Token![:]>,
+
+ pub expr: Expr,
+ }
+}
+
+#[cfg(feature = "full")]
+ast_struct! {
+ /// A lifetime labeling a `for`, `while`, or `loop`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct Label {
+ pub name: Lifetime,
+ pub colon_token: Token![:],
+ }
+}
+
+#[cfg(feature = "full")]
+ast_struct! {
+ /// One arm of a `match` expression: `0..=10 => { return true; }`.
+ ///
+ /// As in:
+ ///
+ /// ```
+ /// # fn f() -> bool {
+ /// # let n = 0;
+ /// match n {
+ /// 0..=10 => {
+ /// return true;
+ /// }
+ /// // ...
+ /// # _ => {}
+ /// }
+ /// # false
+ /// # }
+ /// ```
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct Arm {
+ pub attrs: Vec<Attribute>,
+ pub pat: Pat,
+ pub guard: Option<(Token![if], Box<Expr>)>,
+ pub fat_arrow_token: Token![=>],
+ pub body: Box<Expr>,
+ pub comma: Option<Token![,]>,
+ }
+}
+
+#[cfg(feature = "full")]
+ast_enum! {
+ /// Limit types of a range, inclusive or exclusive.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub enum RangeLimits {
+ /// Inclusive at the beginning, exclusive at the end.
+ HalfOpen(Token![..]),
+ /// Inclusive at the beginning and end.
+ Closed(Token![..=]),
+ }
+}
+
+#[cfg(feature = "full")]
+ast_enum! {
+ /// Mutability of a raw pointer (`*const T`, `*mut T`), in which non-mutable
+ /// isn't the implicit default.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub enum PointerMutability {
+ Const(Token![const]),
+ Mut(Token![mut]),
+ }
+}
+
+#[cfg(feature = "parsing")]
+pub(crate) mod parsing {
+ #[cfg(feature = "full")]
+ use crate::attr;
+ use crate::attr::Attribute;
+ #[cfg(feature = "full")]
+ use crate::classify;
+ use crate::error::{Error, Result};
+ #[cfg(feature = "full")]
+ use crate::expr::{
+ Arm, ExprArray, ExprAssign, ExprAsync, ExprAwait, ExprBlock, ExprBreak, ExprClosure,
+ ExprConst, ExprContinue, ExprForLoop, ExprIf, ExprInfer, ExprLet, ExprLoop, ExprMatch,
+ ExprRange, ExprRawAddr, ExprRepeat, ExprReturn, ExprTry, ExprTryBlock, ExprUnsafe,
+ ExprWhile, ExprYield, Label, PointerMutability, RangeLimits,
+ };
+ use crate::expr::{
+ Expr, ExprBinary, ExprCall, ExprCast, ExprField, ExprGroup, ExprIndex, ExprLit, ExprMacro,
+ ExprMethodCall, ExprParen, ExprPath, ExprReference, ExprStruct, ExprTuple, ExprUnary,
+ FieldValue, Index, Member,
+ };
+ #[cfg(feature = "full")]
+ use crate::generics::{self, BoundLifetimes};
+ use crate::ident::Ident;
+ #[cfg(feature = "full")]
+ use crate::lifetime::Lifetime;
+ use crate::lit::{Lit, LitFloat, LitInt};
+ use crate::mac::{self, Macro};
+ use crate::op::BinOp;
+ use crate::parse::discouraged::Speculative as _;
+ #[cfg(feature = "full")]
+ use crate::parse::ParseBuffer;
+ use crate::parse::{Parse, ParseStream};
+ #[cfg(feature = "full")]
+ use crate::pat::{Pat, PatType};
+ use crate::path::{self, AngleBracketedGenericArguments, Path, QSelf};
+ use crate::precedence::Precedence;
+ use crate::punctuated::Punctuated;
+ #[cfg(feature = "full")]
+ use crate::stmt::Block;
+ use crate::token;
+ use crate::ty;
+ #[cfg(feature = "full")]
+ use crate::ty::{ReturnType, Type};
+ use crate::verbatim;
+ #[cfg(feature = "full")]
+ use proc_macro2::{Span, TokenStream};
+ use std::mem;
+
+ // When we're parsing expressions which occur before blocks, like in an if
+ // statement's condition, we cannot parse a struct literal.
+ //
+ // Struct literals are ambiguous in certain positions
+ // https://github.com/rust-lang/rfcs/pull/92
+ #[cfg(feature = "full")]
+ pub(super) struct AllowStruct(pub bool);
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for Expr {
+ fn parse(input: ParseStream) -> Result<Self> {
+ ambiguous_expr(
+ input,
+ #[cfg(feature = "full")]
+ AllowStruct(true),
+ )
+ }
+ }
+
+ #[cfg(feature = "full")]
+ pub(super) fn parse_with_earlier_boundary_rule(input: ParseStream) -> Result<Expr> {
+ let mut attrs = input.call(expr_attrs)?;
+ let mut expr = if input.peek(token::Group) {
+ let allow_struct = AllowStruct(true);
+ let atom = expr_group(input, allow_struct)?;
+ if continue_parsing_early(&atom) {
+ trailer_helper(input, atom)?
+ } else {
+ atom
+ }
+ } else if input.peek(Token![if]) {
+ Expr::If(input.parse()?)
+ } else if input.peek(Token![while]) {
+ Expr::While(input.parse()?)
+ } else if input.peek(Token![for])
+ && !generics::parsing::choose_generics_over_qpath_after_keyword(input)
+ {
+ Expr::ForLoop(input.parse()?)
+ } else if input.peek(Token![loop]) {
+ Expr::Loop(input.parse()?)
+ } else if input.peek(Token![match]) {
+ Expr::Match(input.parse()?)
+ } else if input.peek(Token![try]) && input.peek2(token::Brace) {
+ Expr::TryBlock(input.parse()?)
+ } else if input.peek(Token![unsafe]) {
+ Expr::Unsafe(input.parse()?)
+ } else if input.peek(Token![const]) && input.peek2(token::Brace) {
+ Expr::Const(input.parse()?)
+ } else if input.peek(token::Brace) {
+ Expr::Block(input.parse()?)
+ } else if input.peek(Lifetime) {
+ atom_labeled(input)?
+ } else {
+ let allow_struct = AllowStruct(true);
+ unary_expr(input, allow_struct)?
+ };
+
+ if continue_parsing_early(&expr) {
+ attrs.extend(expr.replace_attrs(Vec::new()));
+ expr.replace_attrs(attrs);
+
+ let allow_struct = AllowStruct(true);
+ return parse_expr(input, expr, allow_struct, Precedence::MIN);
+ }
+
+ if input.peek(Token![.]) && !input.peek(Token![..]) || input.peek(Token![?]) {
+ expr = trailer_helper(input, expr)?;
+
+ attrs.extend(expr.replace_attrs(Vec::new()));
+ expr.replace_attrs(attrs);
+
+ let allow_struct = AllowStruct(true);
+ return parse_expr(input, expr, allow_struct, Precedence::MIN);
+ }
+
+ attrs.extend(expr.replace_attrs(Vec::new()));
+ expr.replace_attrs(attrs);
+ Ok(expr)
+ }
+
+ #[cfg(feature = "full")]
+ impl Copy for AllowStruct {}
+
+ #[cfg(feature = "full")]
+ impl Clone for AllowStruct {
+ fn clone(&self) -> Self {
+ *self
+ }
+ }
+
+ #[cfg(feature = "full")]
+ fn parse_expr(
+ input: ParseStream,
+ mut lhs: Expr,
+ allow_struct: AllowStruct,
+ base: Precedence,
+ ) -> Result<Expr> {
+ loop {
+ let ahead = input.fork();
+ if let Expr::Range(_) = lhs {
+ // A range cannot be the left-hand side of another binary operator.
+ break;
+ } else if let Ok(op) = ahead.parse::<BinOp>() {
+ let precedence = Precedence::of_binop(&op);
+ if precedence < base {
+ break;
+ }
+ if precedence == Precedence::Assign {
+ if let Expr::Range(_) = lhs {
+ break;
+ }
+ }
+ if precedence == Precedence::Compare {
+ if let Expr::Binary(lhs) = &lhs {
+ if Precedence::of_binop(&lhs.op) == Precedence::Compare {
+ return Err(input.error("comparison operators cannot be chained"));
+ }
+ }
+ }
+ input.advance_to(&ahead);
+ let right = parse_binop_rhs(input, allow_struct, precedence)?;
+ lhs = Expr::Binary(ExprBinary {
+ attrs: Vec::new(),
+ left: Box::new(lhs),
+ op,
+ right,
+ });
+ } else if Precedence::Assign >= base
+ && input.peek(Token![=])
+ && !input.peek(Token![=>])
+ && match lhs {
+ Expr::Range(_) => false,
+ _ => true,
+ }
+ {
+ let eq_token: Token![=] = input.parse()?;
+ let right = parse_binop_rhs(input, allow_struct, Precedence::Assign)?;
+ lhs = Expr::Assign(ExprAssign {
+ attrs: Vec::new(),
+ left: Box::new(lhs),
+ eq_token,
+ right,
+ });
+ } else if Precedence::Range >= base && input.peek(Token![..]) {
+ let limits: RangeLimits = input.parse()?;
+ let end = parse_range_end(input, &limits, allow_struct)?;
+ lhs = Expr::Range(ExprRange {
+ attrs: Vec::new(),
+ start: Some(Box::new(lhs)),
+ limits,
+ end,
+ });
+ } else if Precedence::Cast >= base && input.peek(Token![as]) {
+ let as_token: Token![as] = input.parse()?;
+ let allow_plus = false;
+ let allow_group_generic = false;
+ let ty = ty::parsing::ambig_ty(input, allow_plus, allow_group_generic)?;
+ check_cast(input)?;
+ lhs = Expr::Cast(ExprCast {
+ attrs: Vec::new(),
+ expr: Box::new(lhs),
+ as_token,
+ ty: Box::new(ty),
+ });
+ } else {
+ break;
+ }
+ }
+ Ok(lhs)
+ }
+
+ #[cfg(not(feature = "full"))]
+ fn parse_expr(input: ParseStream, mut lhs: Expr, base: Precedence) -> Result<Expr> {
+ loop {
+ let ahead = input.fork();
+ if let Ok(op) = ahead.parse::<BinOp>() {
+ let precedence = Precedence::of_binop(&op);
+ if precedence < base {
+ break;
+ }
+ if precedence == Precedence::Compare {
+ if let Expr::Binary(lhs) = &lhs {
+ if Precedence::of_binop(&lhs.op) == Precedence::Compare {
+ return Err(input.error("comparison operators cannot be chained"));
+ }
+ }
+ }
+ input.advance_to(&ahead);
+ let right = parse_binop_rhs(input, precedence)?;
+ lhs = Expr::Binary(ExprBinary {
+ attrs: Vec::new(),
+ left: Box::new(lhs),
+ op,
+ right,
+ });
+ } else if Precedence::Cast >= base && input.peek(Token![as]) {
+ let as_token: Token![as] = input.parse()?;
+ let allow_plus = false;
+ let allow_group_generic = false;
+ let ty = ty::parsing::ambig_ty(input, allow_plus, allow_group_generic)?;
+ check_cast(input)?;
+ lhs = Expr::Cast(ExprCast {
+ attrs: Vec::new(),
+ expr: Box::new(lhs),
+ as_token,
+ ty: Box::new(ty),
+ });
+ } else {
+ break;
+ }
+ }
+ Ok(lhs)
+ }
+
+ fn parse_binop_rhs(
+ input: ParseStream,
+ #[cfg(feature = "full")] allow_struct: AllowStruct,
+ precedence: Precedence,
+ ) -> Result<Box<Expr>> {
+ let mut rhs = unary_expr(
+ input,
+ #[cfg(feature = "full")]
+ allow_struct,
+ )?;
+ loop {
+ let next = peek_precedence(input);
+ if next > precedence || next == precedence && precedence == Precedence::Assign {
+ let cursor = input.cursor();
+ rhs = parse_expr(
+ input,
+ rhs,
+ #[cfg(feature = "full")]
+ allow_struct,
+ next,
+ )?;
+ if cursor == input.cursor() {
+ // Bespoke grammar restrictions separate from precedence can
+ // cause parsing to not advance, such as `..a` being
+ // disallowed in the left-hand side of binary operators,
+ // even ones that have lower precedence than `..`.
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ Ok(Box::new(rhs))
+ }
+
+ fn peek_precedence(input: ParseStream) -> Precedence {
+ if let Ok(op) = input.fork().parse() {
+ Precedence::of_binop(&op)
+ } else if input.peek(Token![=]) && !input.peek(Token![=>]) {
+ Precedence::Assign
+ } else if input.peek(Token![..]) {
+ Precedence::Range
+ } else if input.peek(Token![as]) {
+ Precedence::Cast
+ } else {
+ Precedence::MIN
+ }
+ }
+
+ // Parse an arbitrary expression.
+ pub(super) fn ambiguous_expr(
+ input: ParseStream,
+ #[cfg(feature = "full")] allow_struct: AllowStruct,
+ ) -> Result<Expr> {
+ let lhs = unary_expr(
+ input,
+ #[cfg(feature = "full")]
+ allow_struct,
+ )?;
+ parse_expr(
+ input,
+ lhs,
+ #[cfg(feature = "full")]
+ allow_struct,
+ Precedence::MIN,
+ )
+ }
+
+ #[cfg(feature = "full")]
+ fn expr_attrs(input: ParseStream) -> Result<Vec<Attribute>> {
+ let mut attrs = Vec::new();
+ while !input.peek(token::Group) && input.peek(Token![#]) {
+ attrs.push(input.call(attr::parsing::single_parse_outer)?);
+ }
+ Ok(attrs)
+ }
+
+ // <UnOp> <trailer>
+ // & <trailer>
+ // &mut <trailer>
+ // box <trailer>
+ #[cfg(feature = "full")]
+ fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
+ let begin = input.fork();
+ let attrs = input.call(expr_attrs)?;
+ if input.peek(token::Group) {
+ return trailer_expr(begin, attrs, input, allow_struct);
+ }
+
+ if input.peek(Token![&]) {
+ let and_token: Token![&] = input.parse()?;
+ let raw: Option<Token![raw]> = if input.peek(Token![raw])
+ && (input.peek2(Token![mut]) || input.peek2(Token![const]))
+ {
+ Some(input.parse()?)
+ } else {
+ None
+ };
+ let mutability: Option<Token![mut]> = input.parse()?;
+ let const_token: Option<Token![const]> = if raw.is_some() && mutability.is_none() {
+ Some(input.parse()?)
+ } else {
+ None
+ };
+ let expr = Box::new(unary_expr(input, allow_struct)?);
+ if let Some(raw) = raw {
+ Ok(Expr::RawAddr(ExprRawAddr {
+ attrs,
+ and_token,
+ raw,
+ mutability: match mutability {
+ Some(mut_token) => PointerMutability::Mut(mut_token),
+ None => PointerMutability::Const(const_token.unwrap()),
+ },
+ expr,
+ }))
+ } else {
+ Ok(Expr::Reference(ExprReference {
+ attrs,
+ and_token,
+ mutability,
+ expr,
+ }))
+ }
+ } else if input.peek(Token![*]) || input.peek(Token![!]) || input.peek(Token![-]) {
+ expr_unary(input, attrs, allow_struct).map(Expr::Unary)
+ } else {
+ trailer_expr(begin, attrs, input, allow_struct)
+ }
+ }
+
+ #[cfg(not(feature = "full"))]
+ fn unary_expr(input: ParseStream) -> Result<Expr> {
+ if input.peek(Token![&]) {
+ Ok(Expr::Reference(ExprReference {
+ attrs: Vec::new(),
+ and_token: input.parse()?,
+ mutability: input.parse()?,
+ expr: Box::new(unary_expr(input)?),
+ }))
+ } else if input.peek(Token![*]) || input.peek(Token![!]) || input.peek(Token![-]) {
+ Ok(Expr::Unary(ExprUnary {
+ attrs: Vec::new(),
+ op: input.parse()?,
+ expr: Box::new(unary_expr(input)?),
+ }))
+ } else {
+ trailer_expr(input)
+ }
+ }
+
+ // <atom> (..<args>) ...
+ // <atom> . <ident> (..<args>) ...
+ // <atom> . <ident> ...
+ // <atom> . <lit> ...
+ // <atom> [ <expr> ] ...
+ // <atom> ? ...
+ #[cfg(feature = "full")]
+ fn trailer_expr(
+ begin: ParseBuffer,
+ mut attrs: Vec<Attribute>,
+ input: ParseStream,
+ allow_struct: AllowStruct,
+ ) -> Result<Expr> {
+ let atom = atom_expr(input, allow_struct)?;
+ let mut e = trailer_helper(input, atom)?;
+
+ if let Expr::Verbatim(tokens) = &mut e {
+ *tokens = verbatim::between(&begin, input);
+ } else if !attrs.is_empty() {
+ if let Expr::Range(range) = e {
+ let spans: &[Span] = match &range.limits {
+ RangeLimits::HalfOpen(limits) => &limits.spans,
+ RangeLimits::Closed(limits) => &limits.spans,
+ };
+ return Err(crate::error::new2(
+ spans[0],
+ *spans.last().unwrap(),
+ "attributes are not allowed on range expressions starting with `..`",
+ ));
+ }
+ let inner_attrs = e.replace_attrs(Vec::new());
+ attrs.extend(inner_attrs);
+ e.replace_attrs(attrs);
+ }
+
+ Ok(e)
+ }
+
+ #[cfg(feature = "full")]
+ fn trailer_helper(input: ParseStream, mut e: Expr) -> Result<Expr> {
+ loop {
+ if input.peek(token::Paren) {
+ let content;
+ e = Expr::Call(ExprCall {
+ attrs: Vec::new(),
+ func: Box::new(e),
+ paren_token: parenthesized!(content in input),
+ args: content.parse_terminated(Expr::parse, Token![,])?,
+ });
+ } else if input.peek(Token![.])
+ && !input.peek(Token![..])
+ && match e {
+ Expr::Range(_) => false,
+ _ => true,
+ }
+ {
+ let mut dot_token: Token![.] = input.parse()?;
+
+ let float_token: Option<LitFloat> = input.parse()?;
+ if let Some(float_token) = float_token {
+ if multi_index(&mut e, &mut dot_token, float_token)? {
+ continue;
+ }
+ }
+
+ let await_token: Option<Token![await]> = input.parse()?;
+ if let Some(await_token) = await_token {
+ e = Expr::Await(ExprAwait {
+ attrs: Vec::new(),
+ base: Box::new(e),
+ dot_token,
+ await_token,
+ });
+ continue;
+ }
+
+ let member: Member = input.parse()?;
+ let turbofish = if member.is_named() && input.peek(Token![::]) {
+ Some(AngleBracketedGenericArguments::parse_turbofish(input)?)
+ } else {
+ None
+ };
+
+ if turbofish.is_some() || input.peek(token::Paren) {
+ if let Member::Named(method) = member {
+ let content;
+ e = Expr::MethodCall(ExprMethodCall {
+ attrs: Vec::new(),
+ receiver: Box::new(e),
+ dot_token,
+ method,
+ turbofish,
+ paren_token: parenthesized!(content in input),
+ args: content.parse_terminated(Expr::parse, Token![,])?,
+ });
+ continue;
+ }
+ }
+
+ e = Expr::Field(ExprField {
+ attrs: Vec::new(),
+ base: Box::new(e),
+ dot_token,
+ member,
+ });
+ } else if input.peek(token::Bracket) {
+ let content;
+ e = Expr::Index(ExprIndex {
+ attrs: Vec::new(),
+ expr: Box::new(e),
+ bracket_token: bracketed!(content in input),
+ index: content.parse()?,
+ });
+ } else if input.peek(Token![?])
+ && match e {
+ Expr::Range(_) => false,
+ _ => true,
+ }
+ {
+ e = Expr::Try(ExprTry {
+ attrs: Vec::new(),
+ expr: Box::new(e),
+ question_token: input.parse()?,
+ });
+ } else {
+ break;
+ }
+ }
+ Ok(e)
+ }
+
+ #[cfg(not(feature = "full"))]
+ fn trailer_expr(input: ParseStream) -> Result<Expr> {
+ let mut e = atom_expr(input)?;
+
+ loop {
+ if input.peek(token::Paren) {
+ let content;
+ e = Expr::Call(ExprCall {
+ attrs: Vec::new(),
+ func: Box::new(e),
+ paren_token: parenthesized!(content in input),
+ args: content.parse_terminated(Expr::parse, Token![,])?,
+ });
+ } else if input.peek(Token![.])
+ && !input.peek(Token![..])
+ && !input.peek2(Token![await])
+ {
+ let mut dot_token: Token![.] = input.parse()?;
+
+ let float_token: Option<LitFloat> = input.parse()?;
+ if let Some(float_token) = float_token {
+ if multi_index(&mut e, &mut dot_token, float_token)? {
+ continue;
+ }
+ }
+
+ let member: Member = input.parse()?;
+ let turbofish = if member.is_named() && input.peek(Token![::]) {
+ let colon2_token: Token![::] = input.parse()?;
+ let turbofish =
+ AngleBracketedGenericArguments::do_parse(Some(colon2_token), input)?;
+ Some(turbofish)
+ } else {
+ None
+ };
+
+ if turbofish.is_some() || input.peek(token::Paren) {
+ if let Member::Named(method) = member {
+ let content;
+ e = Expr::MethodCall(ExprMethodCall {
+ attrs: Vec::new(),
+ receiver: Box::new(e),
+ dot_token,
+ method,
+ turbofish,
+ paren_token: parenthesized!(content in input),
+ args: content.parse_terminated(Expr::parse, Token![,])?,
+ });
+ continue;
+ }
+ }
+
+ e = Expr::Field(ExprField {
+ attrs: Vec::new(),
+ base: Box::new(e),
+ dot_token,
+ member,
+ });
+ } else if input.peek(token::Bracket) {
+ let content;
+ e = Expr::Index(ExprIndex {
+ attrs: Vec::new(),
+ expr: Box::new(e),
+ bracket_token: bracketed!(content in input),
+ index: content.parse()?,
+ });
+ } else {
+ break;
+ }
+ }
+
+ Ok(e)
+ }
+
+ // Parse all atomic expressions which don't have to worry about precedence
+ // interactions, as they are fully contained.
+ #[cfg(feature = "full")]
+ fn atom_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
+ if input.peek(token::Group) {
+ expr_group(input, allow_struct)
+ } else if input.peek(Lit) {
+ input.parse().map(Expr::Lit)
+ } else if input.peek(Token![async])
+ && (input.peek2(token::Brace) || input.peek2(Token![move]) && input.peek3(token::Brace))
+ {
+ input.parse().map(Expr::Async)
+ } else if input.peek(Token![try]) && input.peek2(token::Brace) {
+ input.parse().map(Expr::TryBlock)
+ } else if input.peek(Token![|])
+ || input.peek(Token![move])
+ || input.peek(Token![for])
+ && generics::parsing::choose_generics_over_qpath_after_keyword(input)
+ || input.peek(Token![const]) && !input.peek2(token::Brace)
+ || input.peek(Token![static])
+ || input.peek(Token![async]) && (input.peek2(Token![|]) || input.peek2(Token![move]))
+ {
+ expr_closure(input, allow_struct).map(Expr::Closure)
+ } else if token::parsing::peek_keyword(input.cursor(), "builtin") && input.peek2(Token![#])
+ {
+ expr_builtin(input)
+ } else if input.peek(Ident)
+ || input.peek(Token![::])
+ || input.peek(Token![<])
+ || input.peek(Token![self])
+ || input.peek(Token![Self])
+ || input.peek(Token![super])
+ || input.peek(Token![crate])
+ || input.peek(Token![try]) && (input.peek2(Token![!]) || input.peek2(Token![::]))
+ {
+ path_or_macro_or_struct(input, allow_struct)
+ } else if input.peek(token::Paren) {
+ paren_or_tuple(input)
+ } else if input.peek(Token![break]) {
+ expr_break(input, allow_struct).map(Expr::Break)
+ } else if input.peek(Token![continue]) {
+ input.parse().map(Expr::Continue)
+ } else if input.peek(Token![return]) {
+ input.parse().map(Expr::Return)
+ } else if input.peek(Token![become]) {
+ expr_become(input)
+ } else if input.peek(token::Bracket) {
+ array_or_repeat(input)
+ } else if input.peek(Token![let]) {
+ expr_let(input, allow_struct).map(Expr::Let)
+ } else if input.peek(Token![if]) {
+ input.parse().map(Expr::If)
+ } else if input.peek(Token![while]) {
+ input.parse().map(Expr::While)
+ } else if input.peek(Token![for]) {
+ input.parse().map(Expr::ForLoop)
+ } else if input.peek(Token![loop]) {
+ input.parse().map(Expr::Loop)
+ } else if input.peek(Token![match]) {
+ input.parse().map(Expr::Match)
+ } else if input.peek(Token![yield]) {
+ input.parse().map(Expr::Yield)
+ } else if input.peek(Token![unsafe]) {
+ input.parse().map(Expr::Unsafe)
+ } else if input.peek(Token![const]) {
+ input.parse().map(Expr::Const)
+ } else if input.peek(token::Brace) {
+ input.parse().map(Expr::Block)
+ } else if input.peek(Token![..]) {
+ expr_range(input, allow_struct).map(Expr::Range)
+ } else if input.peek(Token![_]) {
+ input.parse().map(Expr::Infer)
+ } else if input.peek(Lifetime) {
+ atom_labeled(input)
+ } else {
+ Err(input.error("expected an expression"))
+ }
+ }
+
+ #[cfg(feature = "full")]
+ fn atom_labeled(input: ParseStream) -> Result<Expr> {
+ let the_label: Label = input.parse()?;
+ let mut expr = if input.peek(Token![while]) {
+ Expr::While(input.parse()?)
+ } else if input.peek(Token![for]) {
+ Expr::ForLoop(input.parse()?)
+ } else if input.peek(Token![loop]) {
+ Expr::Loop(input.parse()?)
+ } else if input.peek(token::Brace) {
+ Expr::Block(input.parse()?)
+ } else {
+ return Err(input.error("expected loop or block expression"));
+ };
+ match &mut expr {
+ Expr::While(ExprWhile { label, .. })
+ | Expr::ForLoop(ExprForLoop { label, .. })
+ | Expr::Loop(ExprLoop { label, .. })
+ | Expr::Block(ExprBlock { label, .. }) => *label = Some(the_label),
+ _ => unreachable!(),
+ }
+ Ok(expr)
+ }
+
+ #[cfg(not(feature = "full"))]
+ fn atom_expr(input: ParseStream) -> Result<Expr> {
+ if input.peek(token::Group) {
+ expr_group(input)
+ } else if input.peek(Lit) {
+ input.parse().map(Expr::Lit)
+ } else if input.peek(token::Paren) {
+ paren_or_tuple(input)
+ } else if input.peek(Ident)
+ || input.peek(Token![::])
+ || input.peek(Token![<])
+ || input.peek(Token![self])
+ || input.peek(Token![Self])
+ || input.peek(Token![super])
+ || input.peek(Token![crate])
+ {
+ path_or_macro_or_struct(input)
+ } else if input.is_empty() {
+ Err(input.error("expected an expression"))
+ } else {
+ if input.peek(token::Brace) {
+ let scan = input.fork();
+ let content;
+ braced!(content in scan);
+ if content.parse::<Expr>().is_ok() && content.is_empty() {
+ let expr_block = verbatim::between(input, &scan);
+ input.advance_to(&scan);
+ return Ok(Expr::Verbatim(expr_block));
+ }
+ }
+ Err(input.error("unsupported expression; enable syn's features=[\"full\"]"))
+ }
+ }
+
+ #[cfg(feature = "full")]
+ fn expr_builtin(input: ParseStream) -> Result<Expr> {
+ let begin = input.fork();
+
+ token::parsing::keyword(input, "builtin")?;
+ input.parse::<Token![#]>()?;
+ input.parse::<Ident>()?;
+
+ let args;
+ parenthesized!(args in input);
+ args.parse::<TokenStream>()?;
+
+ Ok(Expr::Verbatim(verbatim::between(&begin, input)))
+ }
+
+ fn path_or_macro_or_struct(
+ input: ParseStream,
+ #[cfg(feature = "full")] allow_struct: AllowStruct,
+ ) -> Result<Expr> {
+ let expr_style = true;
+ let (qself, path) = path::parsing::qpath(input, expr_style)?;
+ rest_of_path_or_macro_or_struct(
+ qself,
+ path,
+ input,
+ #[cfg(feature = "full")]
+ allow_struct,
+ )
+ }
+
+ fn rest_of_path_or_macro_or_struct(
+ qself: Option<QSelf>,
+ path: Path,
+ input: ParseStream,
+ #[cfg(feature = "full")] allow_struct: AllowStruct,
+ ) -> Result<Expr> {
+ if qself.is_none()
+ && input.peek(Token![!])
+ && !input.peek(Token![!=])
+ && path.is_mod_style()
+ {
+ let bang_token: Token![!] = input.parse()?;
+ let (delimiter, tokens) = mac::parse_delimiter(input)?;
+ return Ok(Expr::Macro(ExprMacro {
+ attrs: Vec::new(),
+ mac: Macro {
+ path,
+ bang_token,
+ delimiter,
+ tokens,
+ },
+ }));
+ }
+
+ #[cfg(not(feature = "full"))]
+ let allow_struct = (true,);
+ if allow_struct.0 && input.peek(token::Brace) {
+ return expr_struct_helper(input, qself, path).map(Expr::Struct);
+ }
+
+ Ok(Expr::Path(ExprPath {
+ attrs: Vec::new(),
+ qself,
+ path,
+ }))
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprMacro {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Ok(ExprMacro {
+ attrs: Vec::new(),
+ mac: input.parse()?,
+ })
+ }
+ }
+
+ fn paren_or_tuple(input: ParseStream) -> Result<Expr> {
+ let content;
+ let paren_token = parenthesized!(content in input);
+ if content.is_empty() {
+ return Ok(Expr::Tuple(ExprTuple {
+ attrs: Vec::new(),
+ paren_token,
+ elems: Punctuated::new(),
+ }));
+ }
+
+ let first: Expr = content.parse()?;
+ if content.is_empty() {
+ return Ok(Expr::Paren(ExprParen {
+ attrs: Vec::new(),
+ paren_token,
+ expr: Box::new(first),
+ }));
+ }
+
+ let mut elems = Punctuated::new();
+ elems.push_value(first);
+ while !content.is_empty() {
+ let punct = content.parse()?;
+ elems.push_punct(punct);
+ if content.is_empty() {
+ break;
+ }
+ let value = content.parse()?;
+ elems.push_value(value);
+ }
+ Ok(Expr::Tuple(ExprTuple {
+ attrs: Vec::new(),
+ paren_token,
+ elems,
+ }))
+ }
+
+ #[cfg(feature = "full")]
+ fn array_or_repeat(input: ParseStream) -> Result<Expr> {
+ let content;
+ let bracket_token = bracketed!(content in input);
+ if content.is_empty() {
+ return Ok(Expr::Array(ExprArray {
+ attrs: Vec::new(),
+ bracket_token,
+ elems: Punctuated::new(),
+ }));
+ }
+
+ let first: Expr = content.parse()?;
+ if content.is_empty() || content.peek(Token![,]) {
+ let mut elems = Punctuated::new();
+ elems.push_value(first);
+ while !content.is_empty() {
+ let punct = content.parse()?;
+ elems.push_punct(punct);
+ if content.is_empty() {
+ break;
+ }
+ let value = content.parse()?;
+ elems.push_value(value);
+ }
+ Ok(Expr::Array(ExprArray {
+ attrs: Vec::new(),
+ bracket_token,
+ elems,
+ }))
+ } else if content.peek(Token![;]) {
+ let semi_token: Token![;] = content.parse()?;
+ let len: Expr = content.parse()?;
+ Ok(Expr::Repeat(ExprRepeat {
+ attrs: Vec::new(),
+ bracket_token,
+ expr: Box::new(first),
+ semi_token,
+ len: Box::new(len),
+ }))
+ } else {
+ Err(content.error("expected `,` or `;`"))
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprArray {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let content;
+ let bracket_token = bracketed!(content in input);
+ let mut elems = Punctuated::new();
+
+ while !content.is_empty() {
+ let first: Expr = content.parse()?;
+ elems.push_value(first);
+ if content.is_empty() {
+ break;
+ }
+ let punct = content.parse()?;
+ elems.push_punct(punct);
+ }
+
+ Ok(ExprArray {
+ attrs: Vec::new(),
+ bracket_token,
+ elems,
+ })
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprRepeat {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let content;
+ Ok(ExprRepeat {
+ bracket_token: bracketed!(content in input),
+ attrs: Vec::new(),
+ expr: content.parse()?,
+ semi_token: content.parse()?,
+ len: content.parse()?,
+ })
+ }
+ }
+
+ #[cfg(feature = "full")]
+ fn continue_parsing_early(mut expr: &Expr) -> bool {
+ while let Expr::Group(group) = expr {
+ expr = &group.expr;
+ }
+ match expr {
+ Expr::If(_)
+ | Expr::While(_)
+ | Expr::ForLoop(_)
+ | Expr::Loop(_)
+ | Expr::Match(_)
+ | Expr::TryBlock(_)
+ | Expr::Unsafe(_)
+ | Expr::Const(_)
+ | Expr::Block(_) => false,
+ _ => true,
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprLit {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Ok(ExprLit {
+ attrs: Vec::new(),
+ lit: input.parse()?,
+ })
+ }
+ }
+
+ fn expr_group(
+ input: ParseStream,
+ #[cfg(feature = "full")] allow_struct: AllowStruct,
+ ) -> Result<Expr> {
+ let group = crate::group::parse_group(input)?;
+ let mut inner: Expr = group.content.parse()?;
+
+ match inner {
+ Expr::Path(mut expr) if expr.attrs.is_empty() => {
+ let grouped_len = expr.path.segments.len();
+ Path::parse_rest(input, &mut expr.path, true)?;
+ match rest_of_path_or_macro_or_struct(
+ expr.qself,
+ expr.path,
+ input,
+ #[cfg(feature = "full")]
+ allow_struct,
+ )? {
+ Expr::Path(expr) if expr.path.segments.len() == grouped_len => {
+ inner = Expr::Path(expr);
+ }
+ extended => return Ok(extended),
+ }
+ }
+ _ => {}
+ }
+
+ Ok(Expr::Group(ExprGroup {
+ attrs: Vec::new(),
+ group_token: group.token,
+ expr: Box::new(inner),
+ }))
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprParen {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let content;
+ Ok(ExprParen {
+ attrs: Vec::new(),
+ paren_token: parenthesized!(content in input),
+ expr: content.parse()?,
+ })
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprLet {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let allow_struct = AllowStruct(true);
+ expr_let(input, allow_struct)
+ }
+ }
+
+ #[cfg(feature = "full")]
+ fn expr_let(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprLet> {
+ Ok(ExprLet {
+ attrs: Vec::new(),
+ let_token: input.parse()?,
+ pat: Box::new(Pat::parse_multi_with_leading_vert(input)?),
+ eq_token: input.parse()?,
+ expr: Box::new({
+ let lhs = unary_expr(input, allow_struct)?;
+ parse_expr(input, lhs, allow_struct, Precedence::Compare)?
+ }),
+ })
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprIf {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let attrs = input.call(Attribute::parse_outer)?;
+
+ let mut clauses = Vec::new();
+ let mut expr;
+ loop {
+ let if_token: Token![if] = input.parse()?;
+ let cond = input.call(Expr::parse_without_eager_brace)?;
+ let then_branch: Block = input.parse()?;
+
+ expr = ExprIf {
+ attrs: Vec::new(),
+ if_token,
+ cond: Box::new(cond),
+ then_branch,
+ else_branch: None,
+ };
+
+ if !input.peek(Token![else]) {
+ break;
+ }
+
+ let else_token: Token![else] = input.parse()?;
+ let lookahead = input.lookahead1();
+ if lookahead.peek(Token![if]) {
+ expr.else_branch = Some((else_token, Box::new(Expr::PLACEHOLDER)));
+ clauses.push(expr);
+ } else if lookahead.peek(token::Brace) {
+ expr.else_branch = Some((
+ else_token,
+ Box::new(Expr::Block(ExprBlock {
+ attrs: Vec::new(),
+ label: None,
+ block: input.parse()?,
+ })),
+ ));
+ break;
+ } else {
+ return Err(lookahead.error());
+ }
+ }
+
+ while let Some(mut prev) = clauses.pop() {
+ *prev.else_branch.as_mut().unwrap().1 = Expr::If(expr);
+ expr = prev;
+ }
+ expr.attrs = attrs;
+ Ok(expr)
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprInfer {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Ok(ExprInfer {
+ attrs: input.call(Attribute::parse_outer)?,
+ underscore_token: input.parse()?,
+ })
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprForLoop {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let mut attrs = input.call(Attribute::parse_outer)?;
+ let label: Option<Label> = input.parse()?;
+ let for_token: Token![for] = input.parse()?;
+
+ let pat = Pat::parse_multi_with_leading_vert(input)?;
+
+ let in_token: Token![in] = input.parse()?;
+ let expr: Expr = input.call(Expr::parse_without_eager_brace)?;
+
+ let content;
+ let brace_token = braced!(content in input);
+ attr::parsing::parse_inner(&content, &mut attrs)?;
+ let stmts = content.call(Block::parse_within)?;
+
+ Ok(ExprForLoop {
+ attrs,
+ label,
+ for_token,
+ pat: Box::new(pat),
+ in_token,
+ expr: Box::new(expr),
+ body: Block { brace_token, stmts },
+ })
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprLoop {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let mut attrs = input.call(Attribute::parse_outer)?;
+ let label: Option<Label> = input.parse()?;
+ let loop_token: Token![loop] = input.parse()?;
+
+ let content;
+ let brace_token = braced!(content in input);
+ attr::parsing::parse_inner(&content, &mut attrs)?;
+ let stmts = content.call(Block::parse_within)?;
+
+ Ok(ExprLoop {
+ attrs,
+ label,
+ loop_token,
+ body: Block { brace_token, stmts },
+ })
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprMatch {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let mut attrs = input.call(Attribute::parse_outer)?;
+ let match_token: Token![match] = input.parse()?;
+ let expr = Expr::parse_without_eager_brace(input)?;
+
+ let content;
+ let brace_token = braced!(content in input);
+ attr::parsing::parse_inner(&content, &mut attrs)?;
+
+ let arms = Arm::parse_multiple(&content)?;
+
+ Ok(ExprMatch {
+ attrs,
+ match_token,
+ expr: Box::new(expr),
+ brace_token,
+ arms,
+ })
+ }
+ }
+
+ macro_rules! impl_by_parsing_expr {
+ (
+ $(
+ $expr_type:ty, $variant:ident, $msg:expr,
+ )*
+ ) => {
+ $(
+ #[cfg(all(feature = "full", feature = "printing"))]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for $expr_type {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let mut expr: Expr = input.parse()?;
+ loop {
+ match expr {
+ Expr::$variant(inner) => return Ok(inner),
+ Expr::Group(next) => expr = *next.expr,
+ _ => return Err(Error::new_spanned(expr, $msg)),
+ }
+ }
+ }
+ }
+ )*
+ };
+ }
+
+ impl_by_parsing_expr! {
+ ExprAssign, Assign, "expected assignment expression",
+ ExprAwait, Await, "expected await expression",
+ ExprBinary, Binary, "expected binary operation",
+ ExprCall, Call, "expected function call expression",
+ ExprCast, Cast, "expected cast expression",
+ ExprField, Field, "expected struct field access",
+ ExprIndex, Index, "expected indexing expression",
+ ExprMethodCall, MethodCall, "expected method call expression",
+ ExprRange, Range, "expected range expression",
+ ExprTry, Try, "expected try expression",
+ ExprTuple, Tuple, "expected tuple expression",
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprUnary {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let attrs = Vec::new();
+ let allow_struct = AllowStruct(true);
+ expr_unary(input, attrs, allow_struct)
+ }
+ }
+
+ #[cfg(feature = "full")]
+ fn expr_unary(
+ input: ParseStream,
+ attrs: Vec<Attribute>,
+ allow_struct: AllowStruct,
+ ) -> Result<ExprUnary> {
+ Ok(ExprUnary {
+ attrs,
+ op: input.parse()?,
+ expr: Box::new(unary_expr(input, allow_struct)?),
+ })
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprClosure {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let allow_struct = AllowStruct(true);
+ expr_closure(input, allow_struct)
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprRawAddr {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let allow_struct = AllowStruct(true);
+ Ok(ExprRawAddr {
+ attrs: Vec::new(),
+ and_token: input.parse()?,
+ raw: input.parse()?,
+ mutability: input.parse()?,
+ expr: Box::new(unary_expr(input, allow_struct)?),
+ })
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprReference {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let allow_struct = AllowStruct(true);
+ Ok(ExprReference {
+ attrs: Vec::new(),
+ and_token: input.parse()?,
+ mutability: input.parse()?,
+ expr: Box::new(unary_expr(input, allow_struct)?),
+ })
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprBreak {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let allow_struct = AllowStruct(true);
+ expr_break(input, allow_struct)
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprReturn {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Ok(ExprReturn {
+ attrs: Vec::new(),
+ return_token: input.parse()?,
+ expr: {
+ if Expr::peek(input) {
+ Some(input.parse()?)
+ } else {
+ None
+ }
+ },
+ })
+ }
+ }
+
+ #[cfg(feature = "full")]
+ fn expr_become(input: ParseStream) -> Result<Expr> {
+ let begin = input.fork();
+ input.parse::<Token![become]>()?;
+ input.parse::<Expr>()?;
+ Ok(Expr::Verbatim(verbatim::between(&begin, input)))
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprTryBlock {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Ok(ExprTryBlock {
+ attrs: Vec::new(),
+ try_token: input.parse()?,
+ block: input.parse()?,
+ })
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprYield {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Ok(ExprYield {
+ attrs: Vec::new(),
+ yield_token: input.parse()?,
+ expr: {
+ if Expr::peek(input) {
+ Some(input.parse()?)
+ } else {
+ None
+ }
+ },
+ })
+ }
+ }
+
+ #[cfg(feature = "full")]
+ fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> {
+ let lifetimes: Option<BoundLifetimes> = input.parse()?;
+ let constness: Option<Token![const]> = input.parse()?;
+ let movability: Option<Token![static]> = input.parse()?;
+ let asyncness: Option<Token![async]> = input.parse()?;
+ let capture: Option<Token![move]> = input.parse()?;
+ let or1_token: Token![|] = input.parse()?;
+
+ let mut inputs = Punctuated::new();
+ loop {
+ if input.peek(Token![|]) {
+ break;
+ }
+ let value = closure_arg(input)?;
+ inputs.push_value(value);
+ if input.peek(Token![|]) {
+ break;
+ }
+ let punct: Token![,] = input.parse()?;
+ inputs.push_punct(punct);
+ }
+
+ let or2_token: Token![|] = input.parse()?;
+
+ let (output, body) = if input.peek(Token![->]) {
+ let arrow_token: Token![->] = input.parse()?;
+ let ty: Type = input.parse()?;
+ let body: Block = input.parse()?;
+ let output = ReturnType::Type(arrow_token, Box::new(ty));
+ let block = Expr::Block(ExprBlock {
+ attrs: Vec::new(),
+ label: None,
+ block: body,
+ });
+ (output, block)
+ } else {
+ let body = ambiguous_expr(input, allow_struct)?;
+ (ReturnType::Default, body)
+ };
+
+ Ok(ExprClosure {
+ attrs: Vec::new(),
+ lifetimes,
+ constness,
+ movability,
+ asyncness,
+ capture,
+ or1_token,
+ inputs,
+ or2_token,
+ output,
+ body: Box::new(body),
+ })
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprAsync {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Ok(ExprAsync {
+ attrs: Vec::new(),
+ async_token: input.parse()?,
+ capture: input.parse()?,
+ block: input.parse()?,
+ })
+ }
+ }
+
+ #[cfg(feature = "full")]
+ fn closure_arg(input: ParseStream) -> Result<Pat> {
+ let attrs = input.call(Attribute::parse_outer)?;
+ let mut pat = Pat::parse_single(input)?;
+
+ if input.peek(Token![:]) {
+ Ok(Pat::Type(PatType {
+ attrs,
+ pat: Box::new(pat),
+ colon_token: input.parse()?,
+ ty: input.parse()?,
+ }))
+ } else {
+ match &mut pat {
+ Pat::Const(pat) => pat.attrs = attrs,
+ Pat::Ident(pat) => pat.attrs = attrs,
+ Pat::Lit(pat) => pat.attrs = attrs,
+ Pat::Macro(pat) => pat.attrs = attrs,
+ Pat::Or(pat) => pat.attrs = attrs,
+ Pat::Paren(pat) => pat.attrs = attrs,
+ Pat::Path(pat) => pat.attrs = attrs,
+ Pat::Range(pat) => pat.attrs = attrs,
+ Pat::Reference(pat) => pat.attrs = attrs,
+ Pat::Rest(pat) => pat.attrs = attrs,
+ Pat::Slice(pat) => pat.attrs = attrs,
+ Pat::Struct(pat) => pat.attrs = attrs,
+ Pat::Tuple(pat) => pat.attrs = attrs,
+ Pat::TupleStruct(pat) => pat.attrs = attrs,
+ Pat::Type(_) => unreachable!(),
+ Pat::Verbatim(_) => {}
+ Pat::Wild(pat) => pat.attrs = attrs,
+ }
+ Ok(pat)
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprWhile {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let mut attrs = input.call(Attribute::parse_outer)?;
+ let label: Option<Label> = input.parse()?;
+ let while_token: Token![while] = input.parse()?;
+ let cond = Expr::parse_without_eager_brace(input)?;
+
+ let content;
+ let brace_token = braced!(content in input);
+ attr::parsing::parse_inner(&content, &mut attrs)?;
+ let stmts = content.call(Block::parse_within)?;
+
+ Ok(ExprWhile {
+ attrs,
+ label,
+ while_token,
+ cond: Box::new(cond),
+ body: Block { brace_token, stmts },
+ })
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprConst {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let const_token: Token![const] = input.parse()?;
+
+ let content;
+ let brace_token = braced!(content in input);
+ let inner_attrs = content.call(Attribute::parse_inner)?;
+ let stmts = content.call(Block::parse_within)?;
+
+ Ok(ExprConst {
+ attrs: inner_attrs,
+ const_token,
+ block: Block { brace_token, stmts },
+ })
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for Label {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Ok(Label {
+ name: input.parse()?,
+ colon_token: input.parse()?,
+ })
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for Option<Label> {
+ fn parse(input: ParseStream) -> Result<Self> {
+ if input.peek(Lifetime) {
+ input.parse().map(Some)
+ } else {
+ Ok(None)
+ }
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprContinue {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Ok(ExprContinue {
+ attrs: Vec::new(),
+ continue_token: input.parse()?,
+ label: input.parse()?,
+ })
+ }
+ }
+
+ #[cfg(feature = "full")]
+ fn expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak> {
+ let break_token: Token![break] = input.parse()?;
+
+ let ahead = input.fork();
+ let label: Option<Lifetime> = ahead.parse()?;
+ if label.is_some() && ahead.peek(Token![:]) {
+ // Not allowed: `break 'label: loop {...}`
+ // Parentheses are required. `break ('label: loop {...})`
+ let _: Expr = input.parse()?;
+ let start_span = label.unwrap().apostrophe;
+ let end_span = input.cursor().prev_span();
+ return Err(crate::error::new2(
+ start_span,
+ end_span,
+ "parentheses required",
+ ));
+ }
+
+ input.advance_to(&ahead);
+ let expr = if Expr::peek(input) && (allow_struct.0 || !input.peek(token::Brace)) {
+ Some(input.parse()?)
+ } else {
+ None
+ };
+
+ Ok(ExprBreak {
+ attrs: Vec::new(),
+ break_token,
+ label,
+ expr,
+ })
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for FieldValue {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let attrs = input.call(Attribute::parse_outer)?;
+ let member: Member = input.parse()?;
+ let (colon_token, value) = if input.peek(Token![:]) || !member.is_named() {
+ let colon_token: Token![:] = input.parse()?;
+ let value: Expr = input.parse()?;
+ (Some(colon_token), value)
+ } else if let Member::Named(ident) = &member {
+ let value = Expr::Path(ExprPath {
+ attrs: Vec::new(),
+ qself: None,
+ path: Path::from(ident.clone()),
+ });
+ (None, value)
+ } else {
+ unreachable!()
+ };
+
+ Ok(FieldValue {
+ attrs,
+ member,
+ colon_token,
+ expr: value,
+ })
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprStruct {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let expr_style = true;
+ let (qself, path) = path::parsing::qpath(input, expr_style)?;
+ expr_struct_helper(input, qself, path)
+ }
+ }
+
+ fn expr_struct_helper(
+ input: ParseStream,
+ qself: Option<QSelf>,
+ path: Path,
+ ) -> Result<ExprStruct> {
+ let content;
+ let brace_token = braced!(content in input);
+
+ let mut fields = Punctuated::new();
+ while !content.is_empty() {
+ if content.peek(Token![..]) {
+ return Ok(ExprStruct {
+ attrs: Vec::new(),
+ qself,
+ path,
+ brace_token,
+ fields,
+ dot2_token: Some(content.parse()?),
+ rest: if content.is_empty() {
+ None
+ } else {
+ Some(Box::new(content.parse()?))
+ },
+ });
+ }
+
+ fields.push(content.parse()?);
+ if content.is_empty() {
+ break;
+ }
+ let punct: Token![,] = content.parse()?;
+ fields.push_punct(punct);
+ }
+
+ Ok(ExprStruct {
+ attrs: Vec::new(),
+ qself,
+ path,
+ brace_token,
+ fields,
+ dot2_token: None,
+ rest: None,
+ })
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprUnsafe {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let unsafe_token: Token![unsafe] = input.parse()?;
+
+ let content;
+ let brace_token = braced!(content in input);
+ let inner_attrs = content.call(Attribute::parse_inner)?;
+ let stmts = content.call(Block::parse_within)?;
+
+ Ok(ExprUnsafe {
+ attrs: inner_attrs,
+ unsafe_token,
+ block: Block { brace_token, stmts },
+ })
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprBlock {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let mut attrs = input.call(Attribute::parse_outer)?;
+ let label: Option<Label> = input.parse()?;
+
+ let content;
+ let brace_token = braced!(content in input);
+ attr::parsing::parse_inner(&content, &mut attrs)?;
+ let stmts = content.call(Block::parse_within)?;
+
+ Ok(ExprBlock {
+ attrs,
+ label,
+ block: Block { brace_token, stmts },
+ })
+ }
+ }
+
+ #[cfg(feature = "full")]
+ fn expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange> {
+ let limits: RangeLimits = input.parse()?;
+ let end = parse_range_end(input, &limits, allow_struct)?;
+ Ok(ExprRange {
+ attrs: Vec::new(),
+ start: None,
+ limits,
+ end,
+ })
+ }
+
+ #[cfg(feature = "full")]
+ fn parse_range_end(
+ input: ParseStream,
+ limits: &RangeLimits,
+ allow_struct: AllowStruct,
+ ) -> Result<Option<Box<Expr>>> {
+ if matches!(limits, RangeLimits::HalfOpen(_))
+ && (input.is_empty()
+ || input.peek(Token![,])
+ || input.peek(Token![;])
+ || input.peek(Token![.]) && !input.peek(Token![..])
+ || input.peek(Token![?])
+ || input.peek(Token![=>])
+ || !allow_struct.0 && input.peek(token::Brace)
+ || input.peek(Token![=])
+ || input.peek(Token![+])
+ || input.peek(Token![/])
+ || input.peek(Token![%])
+ || input.peek(Token![^])
+ || input.peek(Token![>])
+ || input.peek(Token![<=])
+ || input.peek(Token![!=])
+ || input.peek(Token![-=])
+ || input.peek(Token![*=])
+ || input.peek(Token![&=])
+ || input.peek(Token![|=])
+ || input.peek(Token![<<=])
+ || input.peek(Token![as]))
+ {
+ Ok(None)
+ } else {
+ let end = parse_binop_rhs(input, allow_struct, Precedence::Range)?;
+ Ok(Some(end))
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for RangeLimits {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let lookahead = input.lookahead1();
+ let dot_dot = lookahead.peek(Token![..]);
+ let dot_dot_eq = dot_dot && lookahead.peek(Token![..=]);
+ let dot_dot_dot = dot_dot && input.peek(Token![...]);
+ if dot_dot_eq {
+ input.parse().map(RangeLimits::Closed)
+ } else if dot_dot && !dot_dot_dot {
+ input.parse().map(RangeLimits::HalfOpen)
+ } else {
+ Err(lookahead.error())
+ }
+ }
+ }
+
+ #[cfg(feature = "full")]
+ impl RangeLimits {
+ pub(crate) fn parse_obsolete(input: ParseStream) -> Result<Self> {
+ let lookahead = input.lookahead1();
+ let dot_dot = lookahead.peek(Token![..]);
+ let dot_dot_eq = dot_dot && lookahead.peek(Token![..=]);
+ let dot_dot_dot = dot_dot && input.peek(Token![...]);
+ if dot_dot_eq {
+ input.parse().map(RangeLimits::Closed)
+ } else if dot_dot_dot {
+ let dot3: Token![...] = input.parse()?;
+ Ok(RangeLimits::Closed(Token))
+ } else if dot_dot {
+ input.parse().map(RangeLimits::HalfOpen)
+ } else {
+ Err(lookahead.error())
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ExprPath {
+ fn parse(input: ParseStream) -> Result<Self> {
+ #[cfg(not(feature = "full"))]
+ let attrs = Vec::new();
+ #[cfg(feature = "full")]
+ let attrs = input.call(Attribute::parse_outer)?;
+
+ let expr_style = true;
+ let (qself, path) = path::parsing::qpath(input, expr_style)?;
+
+ Ok(ExprPath { attrs, qself, path })
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for Member {
+ fn parse(input: ParseStream) -> Result<Self> {
+ if input.peek(Ident) {
+ input.parse().map(Member::Named)
+ } else if input.peek(LitInt) {
+ input.parse().map(Member::Unnamed)
+ } else {
+ Err(input.error("expected identifier or integer"))
+ }
+ }
+ }
+
+ #[cfg(feature = "full")]
+ impl Arm {
+ pub(crate) fn parse_multiple(input: ParseStream) -> Result<Vec<Self>> {
+ let mut arms = Vec::new();
+ while !input.is_empty() {
+ arms.push(input.call(Arm::parse)?);
+ }
+ Ok(arms)
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for Arm {
+ fn parse(input: ParseStream) -> Result<Arm> {
+ let requires_comma;
+ Ok(Arm {
+ attrs: input.call(Attribute::parse_outer)?,
+ pat: Pat::parse_multi_with_leading_vert(input)?,
+ guard: {
+ if input.peek(Token![if]) {
+ let if_token: Token![if] = input.parse()?;
+ let guard: Expr = input.parse()?;
+ Some((if_token, Box::new(guard)))
+ } else {
+ None
+ }
+ },
+ fat_arrow_token: input.parse()?,
+ body: {
+ let body = Expr::parse_with_earlier_boundary_rule(input)?;
+ requires_comma = classify::requires_comma_to_be_match_arm(&body);
+ Box::new(body)
+ },
+ comma: {
+ if requires_comma && !input.is_empty() {
+ Some(input.parse()?)
+ } else {
+ input.parse()?
+ }
+ },
+ })
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for Index {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let lit: LitInt = input.parse()?;
+ if lit.suffix().is_empty() {
+ Ok(Index {
+ index: lit
+ .base10_digits()
+ .parse()
+ .map_err(|err| Error::new(lit.span(), err))?,
+ span: lit.span(),
+ })
+ } else {
+ Err(Error::new(lit.span(), "expected unsuffixed integer"))
+ }
+ }
+ }
+
+ fn multi_index(e: &mut Expr, dot_token: &mut Token![.], float: LitFloat) -> Result<bool> {
+ let float_token = float.token();
+ let float_span = float_token.span();
+ let mut float_repr = float_token.to_string();
+ let trailing_dot = float_repr.ends_with('.');
+ if trailing_dot {
+ float_repr.truncate(float_repr.len() - 1);
+ }
+
+ let mut offset = 0;
+ for part in float_repr.split('.') {
+ let mut index: Index =
+ crate::parse_str(part).map_err(|err| Error::new(float_span, err))?;
+ let part_end = offset + part.len();
+ index.span = float_token.subspan(offset..part_end).unwrap_or(float_span);
+
+ let base = mem::replace(e, Expr::PLACEHOLDER);
+ *e = Expr::Field(ExprField {
+ attrs: Vec::new(),
+ base: Box::new(base),
+ dot_token: Token,
+ member: Member::Unnamed(index),
+ });
+
+ let dot_span = float_token
+ .subspan(part_end..part_end + 1)
+ .unwrap_or(float_span);
+ *dot_token = Token;
+ offset = part_end + 1;
+ }
+
+ Ok(!trailing_dot)
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for PointerMutability {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let lookahead = input.lookahead1();
+ if lookahead.peek(Token![const]) {
+ Ok(PointerMutability::Const(input.parse()?))
+ } else if lookahead.peek(Token![mut]) {
+ Ok(PointerMutability::Mut(input.parse()?))
+ } else {
+ Err(lookahead.error())
+ }
+ }
+ }
+
+ fn check_cast(input: ParseStream) -> Result<()> {
+ let kind = if input.peek(Token![.]) && !input.peek(Token![..]) {
+ if input.peek2(Token![await]) {
+ "`.await`"
+ } else if input.peek2(Ident) && (input.peek3(token::Paren) || input.peek3(Token![::])) {
+ "a method call"
+ } else {
+ "a field access"
+ }
+ } else if input.peek(Token![?]) {
+ "`?`"
+ } else if input.peek(token::Bracket) {
+ "indexing"
+ } else if input.peek(token::Paren) {
+ "a function call"
+ } else {
+ return Ok(());
+ };
+ let msg = format!("casts cannot be followed by {}", kind);
+ Err(input.error(msg))
+ }
+}
+
+#[cfg(feature = "printing")]
+pub(crate) mod printing {
+ use crate::attr::Attribute;
+ #[cfg(feature = "full")]
+ use crate::attr::FilterAttrs;
+ #[cfg(feature = "full")]
+ use crate::classify;
+ #[cfg(feature = "full")]
+ use crate::expr::{
+ Arm, ExprArray, ExprAssign, ExprAsync, ExprAwait, ExprBlock, ExprBreak, ExprClosure,
+ ExprConst, ExprContinue, ExprForLoop, ExprIf, ExprInfer, ExprLet, ExprLoop, ExprMatch,
+ ExprRange, ExprRawAddr, ExprRepeat, ExprReturn, ExprTry, ExprTryBlock, ExprUnsafe,
+ ExprWhile, ExprYield, Label, PointerMutability, RangeLimits,
+ };
+ use crate::expr::{
+ Expr, ExprBinary, ExprCall, ExprCast, ExprField, ExprGroup, ExprIndex, ExprLit, ExprMacro,
+ ExprMethodCall, ExprParen, ExprPath, ExprReference, ExprStruct, ExprTuple, ExprUnary,
+ FieldValue, Index, Member,
+ };
+ use crate::fixup::FixupContext;
+ use crate::op::BinOp;
+ use crate::path;
+ use crate::path::printing::PathStyle;
+ use crate::precedence::Precedence;
+ use crate::token;
+ #[cfg(feature = "full")]
+ use crate::ty::ReturnType;
+ use proc_macro2::{Literal, Span, TokenStream};
+ use quote::{ToTokens, TokenStreamExt};
+
+ #[cfg(feature = "full")]
+ pub(crate) fn outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
+ tokens.append_all(attrs.outer());
+ }
+
+ #[cfg(feature = "full")]
+ fn inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
+ tokens.append_all(attrs.inner());
+ }
+
+ #[cfg(not(feature = "full"))]
+ pub(crate) fn outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
+
+ pub(crate) fn print_subexpression(
+ expr: &Expr,
+ needs_group: bool,
+ tokens: &mut TokenStream,
+ mut fixup: FixupContext,
+ ) {
+ if needs_group {
+ // If we are surrounding the whole cond in parentheses, such as:
+ //
+ // if (return Struct {}) {}
+ //
+ // then there is no need for parenthesizing the individual struct
+ // expressions within. On the other hand if the whole cond is not
+ // parenthesized, then print_expr must parenthesize exterior struct
+ // literals.
+ //
+ // if x == (Struct {}) {}
+ //
+ fixup = FixupContext::NONE;
+ }
+
+ let do_print_expr = |tokens: &mut TokenStream| print_expr(expr, tokens, fixup);
+
+ if needs_group {
+ token::Paren::default().surround(tokens, do_print_expr);
+ } else {
+ do_print_expr(tokens);
+ }
+ }
+
+ pub(crate) fn print_expr(expr: &Expr, tokens: &mut TokenStream, mut fixup: FixupContext) {
+ #[cfg(feature = "full")]
+ let needs_group = fixup.parenthesize(expr);
+ #[cfg(not(feature = "full"))]
+ let needs_group = false;
+
+ if needs_group {
+ fixup = FixupContext::NONE;
+ }
+
+ let do_print_expr = |tokens: &mut TokenStream| match expr {
+ #[cfg(feature = "full")]
+ Expr::Array(e) => e.to_tokens(tokens),
+ #[cfg(feature = "full")]
+ Expr::Assign(e) => print_expr_assign(e, tokens, fixup),
+ #[cfg(feature = "full")]
+ Expr::Async(e) => e.to_tokens(tokens),
+ #[cfg(feature = "full")]
+ Expr::Await(e) => print_expr_await(e, tokens, fixup),
+ Expr::Binary(e) => print_expr_binary(e, tokens, fixup),
+ #[cfg(feature = "full")]
+ Expr::Block(e) => e.to_tokens(tokens),
+ #[cfg(feature = "full")]
+ Expr::Break(e) => print_expr_break(e, tokens, fixup),
+ Expr::Call(e) => print_expr_call(e, tokens, fixup),
+ Expr::Cast(e) => print_expr_cast(e, tokens, fixup),
+ #[cfg(feature = "full")]
+ Expr::Closure(e) => print_expr_closure(e, tokens, fixup),
+ #[cfg(feature = "full")]
+ Expr::Const(e) => e.to_tokens(tokens),
+ #[cfg(feature = "full")]
+ Expr::Continue(e) => e.to_tokens(tokens),
+ Expr::Field(e) => print_expr_field(e, tokens, fixup),
+ #[cfg(feature = "full")]
+ Expr::ForLoop(e) => e.to_tokens(tokens),
+ Expr::Group(e) => e.to_tokens(tokens),
+ #[cfg(feature = "full")]
+ Expr::If(e) => e.to_tokens(tokens),
+ Expr::Index(e) => print_expr_index(e, tokens, fixup),
+ #[cfg(feature = "full")]
+ Expr::Infer(e) => e.to_tokens(tokens),
+ #[cfg(feature = "full")]
+ Expr::Let(e) => print_expr_let(e, tokens, fixup),
+ Expr::Lit(e) => e.to_tokens(tokens),
+ #[cfg(feature = "full")]
+ Expr::Loop(e) => e.to_tokens(tokens),
+ Expr::Macro(e) => e.to_tokens(tokens),
+ #[cfg(feature = "full")]
+ Expr::Match(e) => e.to_tokens(tokens),
+ Expr::MethodCall(e) => print_expr_method_call(e, tokens, fixup),
+ Expr::Paren(e) => e.to_tokens(tokens),
+ Expr::Path(e) => e.to_tokens(tokens),
+ #[cfg(feature = "full")]
+ Expr::Range(e) => print_expr_range(e, tokens, fixup),
+ #[cfg(feature = "full")]
+ Expr::RawAddr(e) => print_expr_raw_addr(e, tokens, fixup),
+ Expr::Reference(e) => print_expr_reference(e, tokens, fixup),
+ #[cfg(feature = "full")]
+ Expr::Repeat(e) => e.to_tokens(tokens),
+ #[cfg(feature = "full")]
+ Expr::Return(e) => print_expr_return(e, tokens, fixup),
+ Expr::Struct(e) => e.to_tokens(tokens),
+ #[cfg(feature = "full")]
+ Expr::Try(e) => print_expr_try(e, tokens, fixup),
+ #[cfg(feature = "full")]
+ Expr::TryBlock(e) => e.to_tokens(tokens),
+ Expr::Tuple(e) => e.to_tokens(tokens),
+ Expr::Unary(e) => print_expr_unary(e, tokens, fixup),
+ #[cfg(feature = "full")]
+ Expr::Unsafe(e) => e.to_tokens(tokens),
+ Expr::Verbatim(e) => e.to_tokens(tokens),
+ #[cfg(feature = "full")]
+ Expr::While(e) => e.to_tokens(tokens),
+ #[cfg(feature = "full")]
+ Expr::Yield(e) => print_expr_yield(e, tokens, fixup),
+
+ #[cfg(not(feature = "full"))]
+ _ => unreachable!(),
+ };
+
+ if needs_group {
+ token::Paren::default().surround(tokens, do_print_expr);
+ } else {
+ do_print_expr(tokens);
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ExprArray {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ outer_attrs_to_tokens(&self.attrs, tokens);
+ self.bracket_token.surround(tokens, |tokens| {
+ self.elems.to_tokens(tokens);
+ });
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ExprAssign {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ print_expr_assign(self, tokens, FixupContext::NONE);
+ }
+ }
+
+ #[cfg(feature = "full")]
+ fn print_expr_assign(e: &ExprAssign, tokens: &mut TokenStream, mut fixup: FixupContext) {
+ outer_attrs_to_tokens(&e.attrs, tokens);
+
+ let needs_group = !e.attrs.is_empty();
+ if needs_group {
+ fixup = FixupContext::NONE;
+ }
+
+ let do_print_expr = |tokens: &mut TokenStream| {
+ let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
+ &e.left,
+ false,
+ false,
+ Precedence::Assign,
+ );
+ print_subexpression(&e.left, left_prec <= Precedence::Range, tokens, left_fixup);
+ e.eq_token.to_tokens(tokens);
+ print_expr(
+ &e.right,
+ tokens,
+ fixup.rightmost_subexpression_fixup(false, false, Precedence::Assign),
+ );
+ };
+
+ if needs_group {
+ token::Paren::default().surround(tokens, do_print_expr);
+ } else {
+ do_print_expr(tokens);
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ExprAsync {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ outer_attrs_to_tokens(&self.attrs, tokens);
+ self.async_token.to_tokens(tokens);
+ self.capture.to_tokens(tokens);
+ self.block.to_tokens(tokens);
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ExprAwait {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ print_expr_await(self, tokens, FixupContext::NONE);
+ }
+ }
+
+ #[cfg(feature = "full")]
+ fn print_expr_await(e: &ExprAwait, tokens: &mut TokenStream, fixup: FixupContext) {
+ outer_attrs_to_tokens(&e.attrs, tokens);
+ let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.base);
+ print_subexpression(
+ &e.base,
+ left_prec < Precedence::Unambiguous,
+ tokens,
+ left_fixup,
+ );
+ e.dot_token.to_tokens(tokens);
+ e.await_token.to_tokens(tokens);
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ExprBinary {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ print_expr_binary(self, tokens, FixupContext::NONE);
+ }
+ }
+
+ fn print_expr_binary(e: &ExprBinary, tokens: &mut TokenStream, mut fixup: FixupContext) {
+ outer_attrs_to_tokens(&e.attrs, tokens);
+
+ let needs_group = !e.attrs.is_empty();
+ if needs_group {
+ fixup = FixupContext::NONE;
+ }
+
+ let do_print_expr = |tokens: &mut TokenStream| {
+ let binop_prec = Precedence::of_binop(&e.op);
+ let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
+ &e.left,
+ #[cfg(feature = "full")]
+ match &e.op {
+ BinOp::Sub(_)
+ | BinOp::Mul(_)
+ | BinOp::And(_)
+ | BinOp::Or(_)
+ | BinOp::BitAnd(_)
+ | BinOp::BitOr(_)
+ | BinOp::Shl(_)
+ | BinOp::Lt(_) => true,
+ _ => false,
+ },
+ match &e.op {
+ BinOp::Shl(_) | BinOp::Lt(_) => true,
+ _ => false,
+ },
+ #[cfg(feature = "full")]
+ binop_prec,
+ );
+ let left_needs_group = match binop_prec {
+ Precedence::Assign => left_prec <= Precedence::Range,
+ Precedence::Compare => left_prec <= binop_prec,
+ _ => left_prec < binop_prec,
+ };
+
+ let right_fixup = fixup.rightmost_subexpression_fixup(
+ #[cfg(feature = "full")]
+ false,
+ #[cfg(feature = "full")]
+ false,
+ #[cfg(feature = "full")]
+ binop_prec,
+ );
+ let right_needs_group = binop_prec != Precedence::Assign
+ && right_fixup.rightmost_subexpression_precedence(&e.right) <= binop_prec;
+
+ print_subexpression(&e.left, left_needs_group, tokens, left_fixup);
+ e.op.to_tokens(tokens);
+ print_subexpression(&e.right, right_needs_group, tokens, right_fixup);
+ };
+
+ if needs_group {
+ token::Paren::default().surround(tokens, do_print_expr);
+ } else {
+ do_print_expr(tokens);
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ExprBlock {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ outer_attrs_to_tokens(&self.attrs, tokens);
+ self.label.to_tokens(tokens);
+ self.block.brace_token.surround(tokens, |tokens| {
+ inner_attrs_to_tokens(&self.attrs, tokens);
+ tokens.append_all(&self.block.stmts);
+ });
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ExprBreak {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ print_expr_break(self, tokens, FixupContext::NONE);
+ }
+ }
+
+ #[cfg(feature = "full")]
+ fn print_expr_break(e: &ExprBreak, tokens: &mut TokenStream, fixup: FixupContext) {
+ outer_attrs_to_tokens(&e.attrs, tokens);
+ e.break_token.to_tokens(tokens);
+ e.label.to_tokens(tokens);
+ if let Some(value) = &e.expr {
+ print_subexpression(
+ value,
+ // Parenthesize `break 'inner: loop { break 'inner 1 } + 1`
+ // ^---------------------------------^
+ e.label.is_none() && classify::expr_leading_label(value),
+ tokens,
+ fixup.rightmost_subexpression_fixup(true, true, Precedence::Jump),
+ );
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ExprCall {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ print_expr_call(self, tokens, FixupContext::NONE);
+ }
+ }
+
+ fn print_expr_call(e: &ExprCall, tokens: &mut TokenStream, fixup: FixupContext) {
+ outer_attrs_to_tokens(&e.attrs, tokens);
+
+ let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
+ &e.func,
+ #[cfg(feature = "full")]
+ true,
+ false,
+ #[cfg(feature = "full")]
+ Precedence::Unambiguous,
+ );
+ let needs_group = if let Expr::Field(func) = &*e.func {
+ func.member.is_named()
+ } else {
+ left_prec < Precedence::Unambiguous
+ };
+ print_subexpression(&e.func, needs_group, tokens, left_fixup);
+
+ e.paren_token.surround(tokens, |tokens| {
+ e.args.to_tokens(tokens);
+ });
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ExprCast {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ print_expr_cast(self, tokens, FixupContext::NONE);
+ }
+ }
+
+ fn print_expr_cast(e: &ExprCast, tokens: &mut TokenStream, mut fixup: FixupContext) {
+ outer_attrs_to_tokens(&e.attrs, tokens);
+
+ let needs_group = !e.attrs.is_empty();
+ if needs_group {
+ fixup = FixupContext::NONE;
+ }
+
+ let do_print_expr = |tokens: &mut TokenStream| {
+ let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
+ &e.expr,
+ #[cfg(feature = "full")]
+ false,
+ false,
+ #[cfg(feature = "full")]
+ Precedence::Cast,
+ );
+ print_subexpression(&e.expr, left_prec < Precedence::Cast, tokens, left_fixup);
+ e.as_token.to_tokens(tokens);
+ e.ty.to_tokens(tokens);
+ };
+
+ if needs_group {
+ token::Paren::default().surround(tokens, do_print_expr);
+ } else {
+ do_print_expr(tokens);
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ExprClosure {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ print_expr_closure(self, tokens, FixupContext::NONE);
+ }
+ }
+
+ #[cfg(feature = "full")]
+ fn print_expr_closure(e: &ExprClosure, tokens: &mut TokenStream, fixup: FixupContext) {
+ outer_attrs_to_tokens(&e.attrs, tokens);
+ e.lifetimes.to_tokens(tokens);
+ e.constness.to_tokens(tokens);
+ e.movability.to_tokens(tokens);
+ e.asyncness.to_tokens(tokens);
+ e.capture.to_tokens(tokens);
+ e.or1_token.to_tokens(tokens);
+ e.inputs.to_tokens(tokens);
+ e.or2_token.to_tokens(tokens);
+ e.output.to_tokens(tokens);
+ if matches!(e.output, ReturnType::Default)
+ || matches!(&*e.body, Expr::Block(body) if body.attrs.is_empty() && body.label.is_none())
+ {
+ print_expr(
+ &e.body,
+ tokens,
+ fixup.rightmost_subexpression_fixup(false, false, Precedence::Jump),
+ );
+ } else {
+ token::Brace::default().surround(tokens, |tokens| {
+ print_expr(&e.body, tokens, FixupContext::new_stmt());
+ });
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ExprConst {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ outer_attrs_to_tokens(&self.attrs, tokens);
+ self.const_token.to_tokens(tokens);
+ self.block.brace_token.surround(tokens, |tokens| {
+ inner_attrs_to_tokens(&self.attrs, tokens);
+ tokens.append_all(&self.block.stmts);
+ });
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ExprContinue {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ outer_attrs_to_tokens(&self.attrs, tokens);
+ self.continue_token.to_tokens(tokens);
+ self.label.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ExprField {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ print_expr_field(self, tokens, FixupContext::NONE);
+ }
+ }
+
+ fn print_expr_field(e: &ExprField, tokens: &mut TokenStream, fixup: FixupContext) {
+ outer_attrs_to_tokens(&e.attrs, tokens);
+ let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.base);
+ print_subexpression(
+ &e.base,
+ left_prec < Precedence::Unambiguous,
+ tokens,
+ left_fixup,
+ );
+ e.dot_token.to_tokens(tokens);
+ e.member.to_tokens(tokens);
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ExprForLoop {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ outer_attrs_to_tokens(&self.attrs, tokens);
+ self.label.to_tokens(tokens);
+ self.for_token.to_tokens(tokens);
+ self.pat.to_tokens(tokens);
+ self.in_token.to_tokens(tokens);
+ print_expr(&self.expr, tokens, FixupContext::new_condition());
+ self.body.brace_token.surround(tokens, |tokens| {
+ inner_attrs_to_tokens(&self.attrs, tokens);
+ tokens.append_all(&self.body.stmts);
+ });
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ExprGroup {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ outer_attrs_to_tokens(&self.attrs, tokens);
+ self.group_token.surround(tokens, |tokens| {
+ self.expr.to_tokens(tokens);
+ });
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ExprIf {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ outer_attrs_to_tokens(&self.attrs, tokens);
+
+ let mut expr = self;
+ loop {
+ expr.if_token.to_tokens(tokens);
+ print_expr(&expr.cond, tokens, FixupContext::new_condition());
+ expr.then_branch.to_tokens(tokens);
+
+ let (else_token, else_) = match &expr.else_branch {
+ Some(else_branch) => else_branch,
+ None => break,
+ };
+
+ else_token.to_tokens(tokens);
+ match &**else_ {
+ Expr::If(next) => {
+ expr = next;
+ }
+ Expr::Block(last) => {
+ last.to_tokens(tokens);
+ break;
+ }
+ // If this is not one of the valid expressions to exist in
+ // an else clause, wrap it in a block.
+ other => {
+ token::Brace::default().surround(tokens, |tokens| {
+ print_expr(other, tokens, FixupContext::new_stmt());
+ });
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ExprIndex {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ print_expr_index(self, tokens, FixupContext::NONE);
+ }
+ }
+
+ fn print_expr_index(e: &ExprIndex, tokens: &mut TokenStream, fixup: FixupContext) {
+ outer_attrs_to_tokens(&e.attrs, tokens);
+ let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
+ &e.expr,
+ #[cfg(feature = "full")]
+ true,
+ false,
+ #[cfg(feature = "full")]
+ Precedence::Unambiguous,
+ );
+ print_subexpression(
+ &e.expr,
+ left_prec < Precedence::Unambiguous,
+ tokens,
+ left_fixup,
+ );
+ e.bracket_token.surround(tokens, |tokens| {
+ e.index.to_tokens(tokens);
+ });
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ExprInfer {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ outer_attrs_to_tokens(&self.attrs, tokens);
+ self.underscore_token.to_tokens(tokens);
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ExprLet {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ print_expr_let(self, tokens, FixupContext::NONE);
+ }
+ }
+
+ #[cfg(feature = "full")]
+ fn print_expr_let(e: &ExprLet, tokens: &mut TokenStream, fixup: FixupContext) {
+ outer_attrs_to_tokens(&e.attrs, tokens);
+ e.let_token.to_tokens(tokens);
+ e.pat.to_tokens(tokens);
+ e.eq_token.to_tokens(tokens);
+ let (right_prec, right_fixup) = fixup.rightmost_subexpression(&e.expr, Precedence::Let);
+ print_subexpression(&e.expr, right_prec < Precedence::Let, tokens, right_fixup);
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ExprLit {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ outer_attrs_to_tokens(&self.attrs, tokens);
+ self.lit.to_tokens(tokens);
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ExprLoop {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ outer_attrs_to_tokens(&self.attrs, tokens);
+ self.label.to_tokens(tokens);
+ self.loop_token.to_tokens(tokens);
+ self.body.brace_token.surround(tokens, |tokens| {
+ inner_attrs_to_tokens(&self.attrs, tokens);
+ tokens.append_all(&self.body.stmts);
+ });
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ExprMacro {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ outer_attrs_to_tokens(&self.attrs, tokens);
+ self.mac.to_tokens(tokens);
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ExprMatch {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ outer_attrs_to_tokens(&self.attrs, tokens);
+ self.match_token.to_tokens(tokens);
+ print_expr(&self.expr, tokens, FixupContext::new_condition());
+ self.brace_token.surround(tokens, |tokens| {
+ inner_attrs_to_tokens(&self.attrs, tokens);
+ for (i, arm) in self.arms.iter().enumerate() {
+ arm.to_tokens(tokens);
+ // Ensure that we have a comma after a non-block arm, except
+ // for the last one.
+ let is_last = i == self.arms.len() - 1;
+ if !is_last
+ && classify::requires_comma_to_be_match_arm(&arm.body)
+ && arm.comma.is_none()
+ {
+ <Token![,]>::default().to_tokens(tokens);
+ }
+ }
+ });
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ExprMethodCall {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ print_expr_method_call(self, tokens, FixupContext::NONE);
+ }
+ }
+
+ fn print_expr_method_call(e: &ExprMethodCall, tokens: &mut TokenStream, fixup: FixupContext) {
+ outer_attrs_to_tokens(&e.attrs, tokens);
+ let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.receiver);
+ print_subexpression(
+ &e.receiver,
+ left_prec < Precedence::Unambiguous,
+ tokens,
+ left_fixup,
+ );
+ e.dot_token.to_tokens(tokens);
+ e.method.to_tokens(tokens);
+ if let Some(turbofish) = &e.turbofish {
+ path::printing::print_angle_bracketed_generic_arguments(
+ tokens,
+ turbofish,
+ PathStyle::Expr,
+ );
+ }
+ e.paren_token.surround(tokens, |tokens| {
+ e.args.to_tokens(tokens);
+ });
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ExprParen {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ outer_attrs_to_tokens(&self.attrs, tokens);
+ self.paren_token.surround(tokens, |tokens| {
+ self.expr.to_tokens(tokens);
+ });
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ExprPath {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ outer_attrs_to_tokens(&self.attrs, tokens);
+ path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ExprRange {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ print_expr_range(self, tokens, FixupContext::NONE);
+ }
+ }
+
+ #[cfg(feature = "full")]
+ fn print_expr_range(e: &ExprRange, tokens: &mut TokenStream, mut fixup: FixupContext) {
+ outer_attrs_to_tokens(&e.attrs, tokens);
+
+ let needs_group = !e.attrs.is_empty();
+ if needs_group {
+ fixup = FixupContext::NONE;
+ }
+
+ let do_print_expr = |tokens: &mut TokenStream| {
+ if let Some(start) = &e.start {
+ let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
+ start,
+ true,
+ false,
+ Precedence::Range,
+ );
+ print_subexpression(start, left_prec <= Precedence::Range, tokens, left_fixup);
+ }
+ e.limits.to_tokens(tokens);
+ if let Some(end) = &e.end {
+ let right_fixup =
+ fixup.rightmost_subexpression_fixup(false, true, Precedence::Range);
+ let right_prec = right_fixup.rightmost_subexpression_precedence(end);
+ print_subexpression(end, right_prec <= Precedence::Range, tokens, right_fixup);
+ }
+ };
+
+ if needs_group {
+ token::Paren::default().surround(tokens, do_print_expr);
+ } else {
+ do_print_expr(tokens);
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ExprRawAddr {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ print_expr_raw_addr(self, tokens, FixupContext::NONE);
+ }
+ }
+
+ #[cfg(feature = "full")]
+ fn print_expr_raw_addr(e: &ExprRawAddr, tokens: &mut TokenStream, fixup: FixupContext) {
+ outer_attrs_to_tokens(&e.attrs, tokens);
+ e.and_token.to_tokens(tokens);
+ e.raw.to_tokens(tokens);
+ e.mutability.to_tokens(tokens);
+ let (right_prec, right_fixup) = fixup.rightmost_subexpression(&e.expr, Precedence::Prefix);
+ print_subexpression(
+ &e.expr,
+ right_prec < Precedence::Prefix,
+ tokens,
+ right_fixup,
+ );
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ExprReference {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ print_expr_reference(self, tokens, FixupContext::NONE);
+ }
+ }
+
+ fn print_expr_reference(e: &ExprReference, tokens: &mut TokenStream, fixup: FixupContext) {
+ outer_attrs_to_tokens(&e.attrs, tokens);
+ e.and_token.to_tokens(tokens);
+ e.mutability.to_tokens(tokens);
+ let (right_prec, right_fixup) = fixup.rightmost_subexpression(
+ &e.expr,
+ #[cfg(feature = "full")]
+ Precedence::Prefix,
+ );
+ print_subexpression(
+ &e.expr,
+ right_prec < Precedence::Prefix,
+ tokens,
+ right_fixup,
+ );
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ExprRepeat {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ outer_attrs_to_tokens(&self.attrs, tokens);
+ self.bracket_token.surround(tokens, |tokens| {
+ self.expr.to_tokens(tokens);
+ self.semi_token.to_tokens(tokens);
+ self.len.to_tokens(tokens);
+ });
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ExprReturn {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ print_expr_return(self, tokens, FixupContext::NONE);
+ }
+ }
+
+ #[cfg(feature = "full")]
+ fn print_expr_return(e: &ExprReturn, tokens: &mut TokenStream, fixup: FixupContext) {
+ outer_attrs_to_tokens(&e.attrs, tokens);
+ e.return_token.to_tokens(tokens);
+ if let Some(expr) = &e.expr {
+ print_expr(
+ expr,
+ tokens,
+ fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump),
+ );
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ExprStruct {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ outer_attrs_to_tokens(&self.attrs, tokens);
+ path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
+ self.brace_token.surround(tokens, |tokens| {
+ self.fields.to_tokens(tokens);
+ if let Some(dot2_token) = &self.dot2_token {
+ dot2_token.to_tokens(tokens);
+ } else if self.rest.is_some() {
+ Token).to_tokens(tokens);
+ }
+ self.rest.to_tokens(tokens);
+ });
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ExprTry {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ print_expr_try(self, tokens, FixupContext::NONE);
+ }
+ }
+
+ #[cfg(feature = "full")]
+ fn print_expr_try(e: &ExprTry, tokens: &mut TokenStream, fixup: FixupContext) {
+ outer_attrs_to_tokens(&e.attrs, tokens);
+ let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.expr);
+ print_subexpression(
+ &e.expr,
+ left_prec < Precedence::Unambiguous,
+ tokens,
+ left_fixup,
+ );
+ e.question_token.to_tokens(tokens);
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ExprTryBlock {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ outer_attrs_to_tokens(&self.attrs, tokens);
+ self.try_token.to_tokens(tokens);
+ self.block.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ExprTuple {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ outer_attrs_to_tokens(&self.attrs, tokens);
+ self.paren_token.surround(tokens, |tokens| {
+ self.elems.to_tokens(tokens);
+ // If we only have one argument, we need a trailing comma to
+ // distinguish ExprTuple from ExprParen.
+ if self.elems.len() == 1 && !self.elems.trailing_punct() {
+ <Token![,]>::default().to_tokens(tokens);
+ }
+ });
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ExprUnary {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ print_expr_unary(self, tokens, FixupContext::NONE);
+ }
+ }
+
+ fn print_expr_unary(e: &ExprUnary, tokens: &mut TokenStream, fixup: FixupContext) {
+ outer_attrs_to_tokens(&e.attrs, tokens);
+ e.op.to_tokens(tokens);
+ let (right_prec, right_fixup) = fixup.rightmost_subexpression(
+ &e.expr,
+ #[cfg(feature = "full")]
+ Precedence::Prefix,
+ );
+ print_subexpression(
+ &e.expr,
+ right_prec < Precedence::Prefix,
+ tokens,
+ right_fixup,
+ );
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ExprUnsafe {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ outer_attrs_to_tokens(&self.attrs, tokens);
+ self.unsafe_token.to_tokens(tokens);
+ self.block.brace_token.surround(tokens, |tokens| {
+ inner_attrs_to_tokens(&self.attrs, tokens);
+ tokens.append_all(&self.block.stmts);
+ });
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ExprWhile {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ outer_attrs_to_tokens(&self.attrs, tokens);
+ self.label.to_tokens(tokens);
+ self.while_token.to_tokens(tokens);
+ print_expr(&self.cond, tokens, FixupContext::new_condition());
+ self.body.brace_token.surround(tokens, |tokens| {
+ inner_attrs_to_tokens(&self.attrs, tokens);
+ tokens.append_all(&self.body.stmts);
+ });
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ExprYield {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ print_expr_yield(self, tokens, FixupContext::NONE);
+ }
+ }
+
+ #[cfg(feature = "full")]
+ fn print_expr_yield(e: &ExprYield, tokens: &mut TokenStream, fixup: FixupContext) {
+ outer_attrs_to_tokens(&e.attrs, tokens);
+ e.yield_token.to_tokens(tokens);
+ if let Some(expr) = &e.expr {
+ print_expr(
+ expr,
+ tokens,
+ fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump),
+ );
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for Arm {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(&self.attrs);
+ self.pat.to_tokens(tokens);
+ if let Some((if_token, guard)) = &self.guard {
+ if_token.to_tokens(tokens);
+ guard.to_tokens(tokens);
+ }
+ self.fat_arrow_token.to_tokens(tokens);
+ print_expr(&self.body, tokens, FixupContext::new_match_arm());
+ self.comma.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for FieldValue {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ outer_attrs_to_tokens(&self.attrs, tokens);
+ self.member.to_tokens(tokens);
+ if let Some(colon_token) = &self.colon_token {
+ colon_token.to_tokens(tokens);
+ self.expr.to_tokens(tokens);
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for Index {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ let mut lit = Literal::i64_unsuffixed(i64::from(self.index));
+ lit.set_span(self.span);
+ tokens.append(lit);
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for Label {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.name.to_tokens(tokens);
+ self.colon_token.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for Member {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ match self {
+ Member::Named(ident) => ident.to_tokens(tokens),
+ Member::Unnamed(index) => index.to_tokens(tokens),
+ }
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for RangeLimits {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ match self {
+ RangeLimits::HalfOpen(t) => t.to_tokens(tokens),
+ RangeLimits::Closed(t) => t.to_tokens(tokens),
+ }
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for PointerMutability {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ match self {
+ PointerMutability::Const(const_token) => const_token.to_tokens(tokens),
+ PointerMutability::Mut(mut_token) => mut_token.to_tokens(tokens),
+ }
+ }
+ }
+}
diff --git a/rust/syn/ext.rs b/rust/syn/ext.rs
new file mode 100644
index 000000000000..5cd79e863a9d
--- /dev/null
+++ b/rust/syn/ext.rs
@@ -0,0 +1,136 @@
+//! Extension traits to provide parsing methods on foreign types.
+
+use crate::buffer::Cursor;
+use crate::error::Result;
+use crate::parse::ParseStream;
+use crate::parse::Peek;
+use crate::sealed::lookahead;
+use crate::token::CustomToken;
+use proc_macro2::Ident;
+
+/// Additional methods for `Ident` not provided by proc-macro2 or libproc_macro.
+///
+/// This trait is sealed and cannot be implemented for types outside of Syn. It
+/// is implemented only for `proc_macro2::Ident`.
+pub trait IdentExt: Sized + private::Sealed {
+ /// Parses any identifier including keywords.
+ ///
+ /// This is useful when parsing macro input which allows Rust keywords as
+ /// identifiers.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use syn::{Error, Ident, Result, Token};
+ /// use syn::ext::IdentExt;
+ /// use syn::parse::ParseStream;
+ ///
+ /// mod kw {
+ /// syn::custom_keyword!(name);
+ /// }
+ ///
+ /// // Parses input that looks like `name = NAME` where `NAME` can be
+ /// // any identifier.
+ /// //
+ /// // Examples:
+ /// //
+ /// // name = anything
+ /// // name = impl
+ /// fn parse_dsl(input: ParseStream) -> Result<Ident> {
+ /// input.parse::<kw::name>()?;
+ /// input.parse::<Token![=]>()?;
+ /// let name = input.call(Ident::parse_any)?;
+ /// Ok(name)
+ /// }
+ /// ```
+ fn parse_any(input: ParseStream) -> Result<Self>;
+
+ /// Peeks any identifier including keywords. Usage:
+ /// `input.peek(Ident::peek_any)`
+ ///
+ /// This is different from `input.peek(Ident)` which only returns true in
+ /// the case of an ident which is not a Rust keyword.
+ #[allow(non_upper_case_globals)]
+ const peek_any: private::PeekFn = private::PeekFn;
+
+ /// Strips the raw marker `r#`, if any, from the beginning of an ident.
+ ///
+ /// - unraw(`x`) = `x`
+ /// - unraw(`move`) = `move`
+ /// - unraw(`r#move`) = `move`
+ ///
+ /// # Example
+ ///
+ /// In the case of interop with other languages like Python that have a
+ /// different set of keywords than Rust, we might come across macro input
+ /// that involves raw identifiers to refer to ordinary variables in the
+ /// other language with a name that happens to be a Rust keyword.
+ ///
+ /// The function below appends an identifier from the caller's input onto a
+ /// fixed prefix. Without using `unraw()`, this would tend to produce
+ /// invalid identifiers like `__pyo3_get_r#move`.
+ ///
+ /// ```
+ /// use proc_macro2::Span;
+ /// use syn::Ident;
+ /// use syn::ext::IdentExt;
+ ///
+ /// fn ident_for_getter(variable: &Ident) -> Ident {
+ /// let getter = format!("__pyo3_get_{}", variable.unraw());
+ /// Ident::new(&getter, Span::call_site())
+ /// }
+ /// ```
+ fn unraw(&self) -> Ident;
+}
+
+impl IdentExt for Ident {
+ fn parse_any(input: ParseStream) -> Result<Self> {
+ input.step(|cursor| match cursor.ident() {
+ Some((ident, rest)) => Ok((ident, rest)),
+ None => Err(cursor.error("expected ident")),
+ })
+ }
+
+ fn unraw(&self) -> Ident {
+ let string = self.to_string();
+ if let Some(string) = string.strip_prefix("r#") {
+ Ident::new(string, self.span())
+ } else {
+ self.clone()
+ }
+ }
+}
+
+impl Peek for private::PeekFn {
+ type Token = private::IdentAny;
+}
+
+impl CustomToken for private::IdentAny {
+ fn peek(cursor: Cursor) -> bool {
+ cursor.ident().is_some()
+ }
+
+ fn display() -> &'static str {
+ "identifier"
+ }
+}
+
+impl lookahead::Sealed for private::PeekFn {}
+
+mod private {
+ use proc_macro2::Ident;
+
+ pub trait Sealed {}
+
+ impl Sealed for Ident {}
+
+ pub struct PeekFn;
+ pub struct IdentAny;
+
+ impl Copy for PeekFn {}
+ impl Clone for PeekFn {
+ fn clone(&self) -> Self {
+ *self
+ }
+ }
+}
diff --git a/rust/syn/file.rs b/rust/syn/file.rs
new file mode 100644
index 000000000000..8956d82eee93
--- /dev/null
+++ b/rust/syn/file.rs
@@ -0,0 +1,125 @@
+use crate::attr::Attribute;
+use crate::item::Item;
+
+ast_struct! {
+ /// A complete file of Rust source code.
+ ///
+ /// Typically `File` objects are created with [`parse_file`].
+ ///
+ /// [`parse_file`]: crate::parse_file
+ ///
+ /// # Example
+ ///
+ /// Parse a Rust source file into a `syn::File` and print out a debug
+ /// representation of the syntax tree.
+ ///
+ /// ```
+ /// use std::env;
+ /// use std::fs;
+ /// use std::process;
+ ///
+ /// fn main() {
+ /// # }
+ /// #
+ /// # fn fake_main() {
+ /// let mut args = env::args();
+ /// let _ = args.next(); // executable name
+ ///
+ /// let filename = match (args.next(), args.next()) {
+ /// (Some(filename), None) => filename,
+ /// _ => {
+ /// eprintln!("Usage: dump-syntax path/to/filename.rs");
+ /// process::exit(1);
+ /// }
+ /// };
+ ///
+ /// let src = fs::read_to_string(&filename).expect("unable to read file");
+ /// let syntax = syn::parse_file(&src).expect("unable to parse file");
+ ///
+ /// // Debug impl is available if Syn is built with "extra-traits" feature.
+ /// println!("{:#?}", syntax);
+ /// }
+ /// ```
+ ///
+ /// Running with its own source code as input, this program prints output
+ /// that begins with:
+ ///
+ /// ```text
+ /// File {
+ /// shebang: None,
+ /// attrs: [],
+ /// items: [
+ /// Use(
+ /// ItemUse {
+ /// attrs: [],
+ /// vis: Inherited,
+ /// use_token: Use,
+ /// leading_colon: None,
+ /// tree: Path(
+ /// UsePath {
+ /// ident: Ident(
+ /// std,
+ /// ),
+ /// colon2_token: Colon2,
+ /// tree: Name(
+ /// UseName {
+ /// ident: Ident(
+ /// env,
+ /// ),
+ /// },
+ /// ),
+ /// },
+ /// ),
+ /// semi_token: Semi,
+ /// },
+ /// ),
+ /// ...
+ /// ```
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct File {
+ pub shebang: Option<String>,
+ pub attrs: Vec<Attribute>,
+ pub items: Vec<Item>,
+ }
+}
+
+#[cfg(feature = "parsing")]
+pub(crate) mod parsing {
+ use crate::attr::Attribute;
+ use crate::error::Result;
+ use crate::file::File;
+ use crate::parse::{Parse, ParseStream};
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for File {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Ok(File {
+ shebang: None,
+ attrs: input.call(Attribute::parse_inner)?,
+ items: {
+ let mut items = Vec::new();
+ while !input.is_empty() {
+ items.push(input.parse()?);
+ }
+ items
+ },
+ })
+ }
+ }
+}
+
+#[cfg(feature = "printing")]
+mod printing {
+ use crate::attr::FilterAttrs;
+ use crate::file::File;
+ use proc_macro2::TokenStream;
+ use quote::{ToTokens, TokenStreamExt};
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for File {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.inner());
+ tokens.append_all(&self.items);
+ }
+ }
+}
diff --git a/rust/syn/fixup.rs b/rust/syn/fixup.rs
new file mode 100644
index 000000000000..6d2c3092d548
--- /dev/null
+++ b/rust/syn/fixup.rs
@@ -0,0 +1,773 @@
+use crate::classify;
+use crate::expr::Expr;
+#[cfg(feature = "full")]
+use crate::expr::{
+ ExprBreak, ExprRange, ExprRawAddr, ExprReference, ExprReturn, ExprUnary, ExprYield,
+};
+use crate::precedence::Precedence;
+#[cfg(feature = "full")]
+use crate::ty::ReturnType;
+
+pub(crate) struct FixupContext {
+ #[cfg(feature = "full")]
+ previous_operator: Precedence,
+ #[cfg(feature = "full")]
+ next_operator: Precedence,
+
+ // Print expression such that it can be parsed back as a statement
+ // consisting of the original expression.
+ //
+ // The effect of this is for binary operators in statement position to set
+ // `leftmost_subexpression_in_stmt` when printing their left-hand operand.
+ //
+ // (match x {}) - 1; // match needs parens when LHS of binary operator
+ //
+ // match x {}; // not when its own statement
+ //
+ #[cfg(feature = "full")]
+ stmt: bool,
+
+ // This is the difference between:
+ //
+ // (match x {}) - 1; // subexpression needs parens
+ //
+ // let _ = match x {} - 1; // no parens
+ //
+ // There are 3 distinguishable contexts in which `print_expr` might be
+ // called with the expression `$match` as its argument, where `$match`
+ // represents an expression of kind `ExprKind::Match`:
+ //
+ // - stmt=false leftmost_subexpression_in_stmt=false
+ //
+ // Example: `let _ = $match - 1;`
+ //
+ // No parentheses required.
+ //
+ // - stmt=false leftmost_subexpression_in_stmt=true
+ //
+ // Example: `$match - 1;`
+ //
+ // Must parenthesize `($match)`, otherwise parsing back the output as a
+ // statement would terminate the statement after the closing brace of
+ // the match, parsing `-1;` as a separate statement.
+ //
+ // - stmt=true leftmost_subexpression_in_stmt=false
+ //
+ // Example: `$match;`
+ //
+ // No parentheses required.
+ #[cfg(feature = "full")]
+ leftmost_subexpression_in_stmt: bool,
+
+ // Print expression such that it can be parsed as a match arm.
+ //
+ // This is almost equivalent to `stmt`, but the grammar diverges a tiny bit
+ // between statements and match arms when it comes to braced macro calls.
+ // Macro calls with brace delimiter terminate a statement without a
+ // semicolon, but do not terminate a match-arm without comma.
+ //
+ // m! {} - 1; // two statements: a macro call followed by -1 literal
+ //
+ // match () {
+ // _ => m! {} - 1, // binary subtraction operator
+ // }
+ //
+ #[cfg(feature = "full")]
+ match_arm: bool,
+
+ // This is almost equivalent to `leftmost_subexpression_in_stmt`, other than
+ // for braced macro calls.
+ //
+ // If we have `m! {} - 1` as an expression, the leftmost subexpression
+ // `m! {}` will need to be parenthesized in the statement case but not the
+ // match-arm case.
+ //
+ // (m! {}) - 1; // subexpression needs parens
+ //
+ // match () {
+ // _ => m! {} - 1, // no parens
+ // }
+ //
+ #[cfg(feature = "full")]
+ leftmost_subexpression_in_match_arm: bool,
+
+ // This is the difference between:
+ //
+ // if let _ = (Struct {}) {} // needs parens
+ //
+ // match () {
+ // () if let _ = Struct {} => {} // no parens
+ // }
+ //
+ #[cfg(feature = "full")]
+ condition: bool,
+
+ // This is the difference between:
+ //
+ // if break Struct {} == (break) {} // needs parens
+ //
+ // if break break == Struct {} {} // no parens
+ //
+ #[cfg(feature = "full")]
+ rightmost_subexpression_in_condition: bool,
+
+ // This is the difference between:
+ //
+ // if break ({ x }).field + 1 {} needs parens
+ //
+ // if break 1 + { x }.field {} // no parens
+ //
+ #[cfg(feature = "full")]
+ leftmost_subexpression_in_optional_operand: bool,
+
+ // This is the difference between:
+ //
+ // let _ = (return) - 1; // without paren, this would return -1
+ //
+ // let _ = return + 1; // no paren because '+' cannot begin expr
+ //
+ #[cfg(feature = "full")]
+ next_operator_can_begin_expr: bool,
+
+ // This is the difference between:
+ //
+ // let _ = 1 + return 1; // no parens if rightmost subexpression
+ //
+ // let _ = 1 + (return 1) + 1; // needs parens
+ //
+ #[cfg(feature = "full")]
+ next_operator_can_continue_expr: bool,
+
+ // This is the difference between:
+ //
+ // let _ = x as u8 + T;
+ //
+ // let _ = (x as u8) < T;
+ //
+ // Without parens, the latter would want to parse `u8<T...` as a type.
+ next_operator_can_begin_generics: bool,
+}
+
+impl FixupContext {
+ /// The default amount of fixing is minimal fixing. Fixups should be turned
+ /// on in a targeted fashion where needed.
+ pub const NONE: Self = FixupContext {
+ #[cfg(feature = "full")]
+ previous_operator: Precedence::MIN,
+ #[cfg(feature = "full")]
+ next_operator: Precedence::MIN,
+ #[cfg(feature = "full")]
+ stmt: false,
+ #[cfg(feature = "full")]
+ leftmost_subexpression_in_stmt: false,
+ #[cfg(feature = "full")]
+ match_arm: false,
+ #[cfg(feature = "full")]
+ leftmost_subexpression_in_match_arm: false,
+ #[cfg(feature = "full")]
+ condition: false,
+ #[cfg(feature = "full")]
+ rightmost_subexpression_in_condition: false,
+ #[cfg(feature = "full")]
+ leftmost_subexpression_in_optional_operand: false,
+ #[cfg(feature = "full")]
+ next_operator_can_begin_expr: false,
+ #[cfg(feature = "full")]
+ next_operator_can_continue_expr: false,
+ next_operator_can_begin_generics: false,
+ };
+
+ /// Create the initial fixup for printing an expression in statement
+ /// position.
+ #[cfg(feature = "full")]
+ pub fn new_stmt() -> Self {
+ FixupContext {
+ stmt: true,
+ ..FixupContext::NONE
+ }
+ }
+
+ /// Create the initial fixup for printing an expression as the right-hand
+ /// side of a match arm.
+ #[cfg(feature = "full")]
+ pub fn new_match_arm() -> Self {
+ FixupContext {
+ match_arm: true,
+ ..FixupContext::NONE
+ }
+ }
+
+ /// Create the initial fixup for printing an expression as the "condition"
+ /// of an `if` or `while`. There are a few other positions which are
+ /// grammatically equivalent and also use this, such as the iterator
+ /// expression in `for` and the scrutinee in `match`.
+ #[cfg(feature = "full")]
+ pub fn new_condition() -> Self {
+ FixupContext {
+ condition: true,
+ rightmost_subexpression_in_condition: true,
+ ..FixupContext::NONE
+ }
+ }
+
+ /// Transform this fixup into the one that should apply when printing the
+ /// leftmost subexpression of the current expression.
+ ///
+ /// The leftmost subexpression is any subexpression that has the same first
+ /// token as the current expression, but has a different last token.
+ ///
+ /// For example in `$a + $b` and `$a.method()`, the subexpression `$a` is a
+ /// leftmost subexpression.
+ ///
+ /// Not every expression has a leftmost subexpression. For example neither
+ /// `-$a` nor `[$a]` have one.
+ pub fn leftmost_subexpression_with_operator(
+ self,
+ expr: &Expr,
+ #[cfg(feature = "full")] next_operator_can_begin_expr: bool,
+ next_operator_can_begin_generics: bool,
+ #[cfg(feature = "full")] precedence: Precedence,
+ ) -> (Precedence, Self) {
+ let fixup = FixupContext {
+ #[cfg(feature = "full")]
+ next_operator: precedence,
+ #[cfg(feature = "full")]
+ stmt: false,
+ #[cfg(feature = "full")]
+ leftmost_subexpression_in_stmt: self.stmt || self.leftmost_subexpression_in_stmt,
+ #[cfg(feature = "full")]
+ match_arm: false,
+ #[cfg(feature = "full")]
+ leftmost_subexpression_in_match_arm: self.match_arm
+ || self.leftmost_subexpression_in_match_arm,
+ #[cfg(feature = "full")]
+ rightmost_subexpression_in_condition: false,
+ #[cfg(feature = "full")]
+ next_operator_can_begin_expr,
+ #[cfg(feature = "full")]
+ next_operator_can_continue_expr: true,
+ next_operator_can_begin_generics,
+ ..self
+ };
+
+ (fixup.leftmost_subexpression_precedence(expr), fixup)
+ }
+
+ /// Transform this fixup into the one that should apply when printing a
+ /// leftmost subexpression followed by a `.` or `?` token, which confer
+ /// different statement boundary rules compared to other leftmost
+ /// subexpressions.
+ pub fn leftmost_subexpression_with_dot(self, expr: &Expr) -> (Precedence, Self) {
+ let fixup = FixupContext {
+ #[cfg(feature = "full")]
+ next_operator: Precedence::Unambiguous,
+ #[cfg(feature = "full")]
+ stmt: self.stmt || self.leftmost_subexpression_in_stmt,
+ #[cfg(feature = "full")]
+ leftmost_subexpression_in_stmt: false,
+ #[cfg(feature = "full")]
+ match_arm: self.match_arm || self.leftmost_subexpression_in_match_arm,
+ #[cfg(feature = "full")]
+ leftmost_subexpression_in_match_arm: false,
+ #[cfg(feature = "full")]
+ rightmost_subexpression_in_condition: false,
+ #[cfg(feature = "full")]
+ next_operator_can_begin_expr: false,
+ #[cfg(feature = "full")]
+ next_operator_can_continue_expr: true,
+ next_operator_can_begin_generics: false,
+ ..self
+ };
+
+ (fixup.leftmost_subexpression_precedence(expr), fixup)
+ }
+
+ fn leftmost_subexpression_precedence(self, expr: &Expr) -> Precedence {
+ #[cfg(feature = "full")]
+ if !self.next_operator_can_begin_expr || self.next_operator == Precedence::Range {
+ if let Scan::Bailout = scan_right(expr, self, Precedence::MIN, 0, 0) {
+ if scan_left(expr, self) {
+ return Precedence::Unambiguous;
+ }
+ }
+ }
+
+ self.precedence(expr)
+ }
+
+ /// Transform this fixup into the one that should apply when printing the
+ /// rightmost subexpression of the current expression.
+ ///
+ /// The rightmost subexpression is any subexpression that has a different
+ /// first token than the current expression, but has the same last token.
+ ///
+ /// For example in `$a + $b` and `-$b`, the subexpression `$b` is a
+ /// rightmost subexpression.
+ ///
+ /// Not every expression has a rightmost subexpression. For example neither
+ /// `[$b]` nor `$a.f($b)` have one.
+ pub fn rightmost_subexpression(
+ self,
+ expr: &Expr,
+ #[cfg(feature = "full")] precedence: Precedence,
+ ) -> (Precedence, Self) {
+ let fixup = self.rightmost_subexpression_fixup(
+ #[cfg(feature = "full")]
+ false,
+ #[cfg(feature = "full")]
+ false,
+ #[cfg(feature = "full")]
+ precedence,
+ );
+ (fixup.rightmost_subexpression_precedence(expr), fixup)
+ }
+
+ pub fn rightmost_subexpression_fixup(
+ self,
+ #[cfg(feature = "full")] reset_allow_struct: bool,
+ #[cfg(feature = "full")] optional_operand: bool,
+ #[cfg(feature = "full")] precedence: Precedence,
+ ) -> Self {
+ FixupContext {
+ #[cfg(feature = "full")]
+ previous_operator: precedence,
+ #[cfg(feature = "full")]
+ stmt: false,
+ #[cfg(feature = "full")]
+ leftmost_subexpression_in_stmt: false,
+ #[cfg(feature = "full")]
+ match_arm: false,
+ #[cfg(feature = "full")]
+ leftmost_subexpression_in_match_arm: false,
+ #[cfg(feature = "full")]
+ condition: self.condition && !reset_allow_struct,
+ #[cfg(feature = "full")]
+ leftmost_subexpression_in_optional_operand: self.condition && optional_operand,
+ ..self
+ }
+ }
+
+ pub fn rightmost_subexpression_precedence(self, expr: &Expr) -> Precedence {
+ let default_prec = self.precedence(expr);
+
+ #[cfg(feature = "full")]
+ if match self.previous_operator {
+ Precedence::Assign | Precedence::Let | Precedence::Prefix => {
+ default_prec < self.previous_operator
+ }
+ _ => default_prec <= self.previous_operator,
+ } && match self.next_operator {
+ Precedence::Range | Precedence::Or | Precedence::And => true,
+ _ => !self.next_operator_can_begin_expr,
+ } {
+ if let Scan::Bailout | Scan::Fail = scan_right(expr, self, self.previous_operator, 1, 0)
+ {
+ if scan_left(expr, self) {
+ return Precedence::Prefix;
+ }
+ }
+ }
+
+ default_prec
+ }
+
+ /// Determine whether parentheses are needed around the given expression to
+ /// head off the early termination of a statement or condition.
+ #[cfg(feature = "full")]
+ pub fn parenthesize(self, expr: &Expr) -> bool {
+ (self.leftmost_subexpression_in_stmt && !classify::requires_semi_to_be_stmt(expr))
+ || ((self.stmt || self.leftmost_subexpression_in_stmt) && matches!(expr, Expr::Let(_)))
+ || (self.leftmost_subexpression_in_match_arm
+ && !classify::requires_comma_to_be_match_arm(expr))
+ || (self.condition && matches!(expr, Expr::Struct(_)))
+ || (self.rightmost_subexpression_in_condition
+ && matches!(
+ expr,
+ Expr::Return(ExprReturn { expr: None, .. })
+ | Expr::Yield(ExprYield { expr: None, .. })
+ ))
+ || (self.rightmost_subexpression_in_condition
+ && !self.condition
+ && matches!(
+ expr,
+ Expr::Break(ExprBreak { expr: None, .. })
+ | Expr::Path(_)
+ | Expr::Range(ExprRange { end: None, .. })
+ ))
+ || (self.leftmost_subexpression_in_optional_operand
+ && matches!(expr, Expr::Block(expr) if expr.attrs.is_empty() && expr.label.is_none()))
+ }
+
+ /// Determines the effective precedence of a subexpression. Some expressions
+ /// have higher or lower precedence when adjacent to particular operators.
+ fn precedence(self, expr: &Expr) -> Precedence {
+ #[cfg(feature = "full")]
+ if self.next_operator_can_begin_expr {
+ // Decrease precedence of value-less jumps when followed by an
+ // operator that would otherwise get interpreted as beginning a
+ // value for the jump.
+ if let Expr::Break(ExprBreak { expr: None, .. })
+ | Expr::Return(ExprReturn { expr: None, .. })
+ | Expr::Yield(ExprYield { expr: None, .. }) = expr
+ {
+ return Precedence::Jump;
+ }
+ }
+
+ #[cfg(feature = "full")]
+ if !self.next_operator_can_continue_expr {
+ match expr {
+ // Increase precedence of expressions that extend to the end of
+ // current statement or group.
+ Expr::Break(_)
+ | Expr::Closure(_)
+ | Expr::Let(_)
+ | Expr::Return(_)
+ | Expr::Yield(_) => {
+ return Precedence::Prefix;
+ }
+ Expr::Range(e) if e.start.is_none() => return Precedence::Prefix,
+ _ => {}
+ }
+ }
+
+ if self.next_operator_can_begin_generics {
+ if let Expr::Cast(cast) = expr {
+ if classify::trailing_unparameterized_path(&cast.ty) {
+ return Precedence::MIN;
+ }
+ }
+ }
+
+ Precedence::of(expr)
+ }
+}
+
+impl Copy for FixupContext {}
+
+impl Clone for FixupContext {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+
+#[cfg(feature = "full")]
+enum Scan {
+ Fail,
+ Bailout,
+ Consume,
+}
+
+#[cfg(feature = "full")]
+impl Copy for Scan {}
+
+#[cfg(feature = "full")]
+impl Clone for Scan {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+
+#[cfg(feature = "full")]
+impl PartialEq for Scan {
+ fn eq(&self, other: &Self) -> bool {
+ *self as u8 == *other as u8
+ }
+}
+
+#[cfg(feature = "full")]
+fn scan_left(expr: &Expr, fixup: FixupContext) -> bool {
+ match expr {
+ Expr::Assign(_) => fixup.previous_operator <= Precedence::Assign,
+ Expr::Binary(e) => match Precedence::of_binop(&e.op) {
+ Precedence::Assign => fixup.previous_operator <= Precedence::Assign,
+ binop_prec => fixup.previous_operator < binop_prec,
+ },
+ Expr::Cast(_) => fixup.previous_operator < Precedence::Cast,
+ Expr::Range(e) => e.start.is_none() || fixup.previous_operator < Precedence::Assign,
+ _ => true,
+ }
+}
+
+#[cfg(feature = "full")]
+fn scan_right(
+ expr: &Expr,
+ fixup: FixupContext,
+ precedence: Precedence,
+ fail_offset: u8,
+ bailout_offset: u8,
+) -> Scan {
+ let consume_by_precedence = if match precedence {
+ Precedence::Assign | Precedence::Compare => precedence <= fixup.next_operator,
+ _ => precedence < fixup.next_operator,
+ } || fixup.next_operator == Precedence::MIN
+ {
+ Scan::Consume
+ } else {
+ Scan::Bailout
+ };
+ if fixup.parenthesize(expr) {
+ return consume_by_precedence;
+ }
+ match expr {
+ Expr::Assign(e) if e.attrs.is_empty() => {
+ if match fixup.next_operator {
+ Precedence::Unambiguous => fail_offset >= 2,
+ _ => bailout_offset >= 1,
+ } {
+ return Scan::Consume;
+ }
+ let right_fixup = fixup.rightmost_subexpression_fixup(false, false, Precedence::Assign);
+ let scan = scan_right(
+ &e.right,
+ right_fixup,
+ Precedence::Assign,
+ match fixup.next_operator {
+ Precedence::Unambiguous => fail_offset,
+ _ => 1,
+ },
+ 1,
+ );
+ if let Scan::Bailout | Scan::Consume = scan {
+ Scan::Consume
+ } else if let Precedence::Unambiguous = fixup.next_operator {
+ Scan::Fail
+ } else {
+ Scan::Bailout
+ }
+ }
+ Expr::Binary(e) if e.attrs.is_empty() => {
+ if match fixup.next_operator {
+ Precedence::Unambiguous => {
+ fail_offset >= 2
+ && (consume_by_precedence == Scan::Consume || bailout_offset >= 1)
+ }
+ _ => bailout_offset >= 1,
+ } {
+ return Scan::Consume;
+ }
+ let binop_prec = Precedence::of_binop(&e.op);
+ if binop_prec == Precedence::Compare && fixup.next_operator == Precedence::Compare {
+ return Scan::Consume;
+ }
+ let right_fixup = fixup.rightmost_subexpression_fixup(false, false, binop_prec);
+ let scan = scan_right(
+ &e.right,
+ right_fixup,
+ binop_prec,
+ match fixup.next_operator {
+ Precedence::Unambiguous => fail_offset,
+ _ => 1,
+ },
+ consume_by_precedence as u8 - Scan::Bailout as u8,
+ );
+ match scan {
+ Scan::Fail => {}
+ Scan::Bailout => return consume_by_precedence,
+ Scan::Consume => return Scan::Consume,
+ }
+ let right_needs_group = binop_prec != Precedence::Assign
+ && right_fixup.rightmost_subexpression_precedence(&e.right) <= binop_prec;
+ if right_needs_group {
+ consume_by_precedence
+ } else if let (Scan::Fail, Precedence::Unambiguous) = (scan, fixup.next_operator) {
+ Scan::Fail
+ } else {
+ Scan::Bailout
+ }
+ }
+ Expr::RawAddr(ExprRawAddr { expr, .. })
+ | Expr::Reference(ExprReference { expr, .. })
+ | Expr::Unary(ExprUnary { expr, .. }) => {
+ if match fixup.next_operator {
+ Precedence::Unambiguous => {
+ fail_offset >= 2
+ && (consume_by_precedence == Scan::Consume || bailout_offset >= 1)
+ }
+ _ => bailout_offset >= 1,
+ } {
+ return Scan::Consume;
+ }
+ let right_fixup = fixup.rightmost_subexpression_fixup(false, false, Precedence::Prefix);
+ let scan = scan_right(
+ expr,
+ right_fixup,
+ precedence,
+ match fixup.next_operator {
+ Precedence::Unambiguous => fail_offset,
+ _ => 1,
+ },
+ consume_by_precedence as u8 - Scan::Bailout as u8,
+ );
+ match scan {
+ Scan::Fail => {}
+ Scan::Bailout => return consume_by_precedence,
+ Scan::Consume => return Scan::Consume,
+ }
+ if right_fixup.rightmost_subexpression_precedence(expr) < Precedence::Prefix {
+ consume_by_precedence
+ } else if let (Scan::Fail, Precedence::Unambiguous) = (scan, fixup.next_operator) {
+ Scan::Fail
+ } else {
+ Scan::Bailout
+ }
+ }
+ Expr::Range(e) if e.attrs.is_empty() => match &e.end {
+ Some(end) => {
+ if fail_offset >= 2 {
+ return Scan::Consume;
+ }
+ let right_fixup =
+ fixup.rightmost_subexpression_fixup(false, true, Precedence::Range);
+ let scan = scan_right(
+ end,
+ right_fixup,
+ Precedence::Range,
+ fail_offset,
+ match fixup.next_operator {
+ Precedence::Assign | Precedence::Range => 0,
+ _ => 1,
+ },
+ );
+ if match (scan, fixup.next_operator) {
+ (Scan::Fail, _) => false,
+ (Scan::Bailout, Precedence::Assign | Precedence::Range) => false,
+ (Scan::Bailout | Scan::Consume, _) => true,
+ } {
+ return Scan::Consume;
+ }
+ if right_fixup.rightmost_subexpression_precedence(end) <= Precedence::Range {
+ Scan::Consume
+ } else {
+ Scan::Fail
+ }
+ }
+ None => {
+ if fixup.next_operator_can_begin_expr {
+ Scan::Consume
+ } else {
+ Scan::Fail
+ }
+ }
+ },
+ Expr::Break(e) => match &e.expr {
+ Some(value) => {
+ if bailout_offset >= 1 || e.label.is_none() && classify::expr_leading_label(value) {
+ return Scan::Consume;
+ }
+ let right_fixup = fixup.rightmost_subexpression_fixup(true, true, Precedence::Jump);
+ match scan_right(value, right_fixup, Precedence::Jump, 1, 1) {
+ Scan::Fail => Scan::Bailout,
+ Scan::Bailout | Scan::Consume => Scan::Consume,
+ }
+ }
+ None => match fixup.next_operator {
+ Precedence::Assign if precedence > Precedence::Assign => Scan::Fail,
+ _ => Scan::Consume,
+ },
+ },
+ Expr::Return(ExprReturn { expr, .. }) | Expr::Yield(ExprYield { expr, .. }) => match expr {
+ Some(e) => {
+ if bailout_offset >= 1 {
+ return Scan::Consume;
+ }
+ let right_fixup =
+ fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump);
+ match scan_right(e, right_fixup, Precedence::Jump, 1, 1) {
+ Scan::Fail => Scan::Bailout,
+ Scan::Bailout | Scan::Consume => Scan::Consume,
+ }
+ }
+ None => match fixup.next_operator {
+ Precedence::Assign if precedence > Precedence::Assign => Scan::Fail,
+ _ => Scan::Consume,
+ },
+ },
+ Expr::Closure(e) => {
+ if matches!(e.output, ReturnType::Default)
+ || matches!(&*e.body, Expr::Block(body) if body.attrs.is_empty() && body.label.is_none())
+ {
+ if bailout_offset >= 1 {
+ return Scan::Consume;
+ }
+ let right_fixup =
+ fixup.rightmost_subexpression_fixup(false, false, Precedence::Jump);
+ match scan_right(&e.body, right_fixup, Precedence::Jump, 1, 1) {
+ Scan::Fail => Scan::Bailout,
+ Scan::Bailout | Scan::Consume => Scan::Consume,
+ }
+ } else {
+ Scan::Consume
+ }
+ }
+ Expr::Let(e) => {
+ if bailout_offset >= 1 {
+ return Scan::Consume;
+ }
+ let right_fixup = fixup.rightmost_subexpression_fixup(false, false, Precedence::Let);
+ let scan = scan_right(
+ &e.expr,
+ right_fixup,
+ Precedence::Let,
+ 1,
+ if fixup.next_operator < Precedence::Let {
+ 0
+ } else {
+ 1
+ },
+ );
+ match scan {
+ Scan::Fail | Scan::Bailout if fixup.next_operator < Precedence::Let => {
+ return Scan::Bailout;
+ }
+ Scan::Consume => return Scan::Consume,
+ _ => {}
+ }
+ if right_fixup.rightmost_subexpression_precedence(&e.expr) < Precedence::Let {
+ Scan::Consume
+ } else if let Scan::Fail = scan {
+ Scan::Bailout
+ } else {
+ Scan::Consume
+ }
+ }
+ Expr::Array(_)
+ | Expr::Assign(_)
+ | Expr::Async(_)
+ | Expr::Await(_)
+ | Expr::Binary(_)
+ | Expr::Block(_)
+ | Expr::Call(_)
+ | Expr::Cast(_)
+ | Expr::Const(_)
+ | Expr::Continue(_)
+ | Expr::Field(_)
+ | Expr::ForLoop(_)
+ | Expr::Group(_)
+ | Expr::If(_)
+ | Expr::Index(_)
+ | Expr::Infer(_)
+ | Expr::Lit(_)
+ | Expr::Loop(_)
+ | Expr::Macro(_)
+ | Expr::Match(_)
+ | Expr::MethodCall(_)
+ | Expr::Paren(_)
+ | Expr::Path(_)
+ | Expr::Range(_)
+ | Expr::Repeat(_)
+ | Expr::Struct(_)
+ | Expr::Try(_)
+ | Expr::TryBlock(_)
+ | Expr::Tuple(_)
+ | Expr::Unsafe(_)
+ | Expr::Verbatim(_)
+ | Expr::While(_) => match fixup.next_operator {
+ Precedence::Assign | Precedence::Range if precedence == Precedence::Range => Scan::Fail,
+ _ if precedence == Precedence::Let && fixup.next_operator < Precedence::Let => {
+ Scan::Fail
+ }
+ _ => consume_by_precedence,
+ },
+ }
+}
diff --git a/rust/syn/gen/clone.rs b/rust/syn/gen/clone.rs
new file mode 100644
index 000000000000..be2b698422da
--- /dev/null
+++ b/rust/syn/gen/clone.rs
@@ -0,0 +1,2267 @@
+// This file is @generated by syn-internal-codegen.
+// It is not intended for manual editing.
+
+#![allow(clippy::clone_on_copy, clippy::expl_impl_clone_on_copy)]
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::Abi {
+ fn clone(&self) -> Self {
+ crate::Abi {
+ extern_token: self.extern_token.clone(),
+ name: self.name.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::AngleBracketedGenericArguments {
+ fn clone(&self) -> Self {
+ crate::AngleBracketedGenericArguments {
+ colon2_token: self.colon2_token.clone(),
+ lt_token: self.lt_token.clone(),
+ args: self.args.clone(),
+ gt_token: self.gt_token.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::Arm {
+ fn clone(&self) -> Self {
+ crate::Arm {
+ attrs: self.attrs.clone(),
+ pat: self.pat.clone(),
+ guard: self.guard.clone(),
+ fat_arrow_token: self.fat_arrow_token.clone(),
+ body: self.body.clone(),
+ comma: self.comma.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::AssocConst {
+ fn clone(&self) -> Self {
+ crate::AssocConst {
+ ident: self.ident.clone(),
+ generics: self.generics.clone(),
+ eq_token: self.eq_token.clone(),
+ value: self.value.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::AssocType {
+ fn clone(&self) -> Self {
+ crate::AssocType {
+ ident: self.ident.clone(),
+ generics: self.generics.clone(),
+ eq_token: self.eq_token.clone(),
+ ty: self.ty.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Copy for crate::AttrStyle {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::AttrStyle {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::Attribute {
+ fn clone(&self) -> Self {
+ crate::Attribute {
+ pound_token: self.pound_token.clone(),
+ style: self.style.clone(),
+ bracket_token: self.bracket_token.clone(),
+ meta: self.meta.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::BareFnArg {
+ fn clone(&self) -> Self {
+ crate::BareFnArg {
+ attrs: self.attrs.clone(),
+ name: self.name.clone(),
+ ty: self.ty.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::BareVariadic {
+ fn clone(&self) -> Self {
+ crate::BareVariadic {
+ attrs: self.attrs.clone(),
+ name: self.name.clone(),
+ dots: self.dots.clone(),
+ comma: self.comma.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Copy for crate::BinOp {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::BinOp {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::Block {
+ fn clone(&self) -> Self {
+ crate::Block {
+ brace_token: self.brace_token.clone(),
+ stmts: self.stmts.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::BoundLifetimes {
+ fn clone(&self) -> Self {
+ crate::BoundLifetimes {
+ for_token: self.for_token.clone(),
+ lt_token: self.lt_token.clone(),
+ lifetimes: self.lifetimes.clone(),
+ gt_token: self.gt_token.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::CapturedParam {
+ fn clone(&self) -> Self {
+ match self {
+ crate::CapturedParam::Lifetime(v0) => {
+ crate::CapturedParam::Lifetime(v0.clone())
+ }
+ crate::CapturedParam::Ident(v0) => crate::CapturedParam::Ident(v0.clone()),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ConstParam {
+ fn clone(&self) -> Self {
+ crate::ConstParam {
+ attrs: self.attrs.clone(),
+ const_token: self.const_token.clone(),
+ ident: self.ident.clone(),
+ colon_token: self.colon_token.clone(),
+ ty: self.ty.clone(),
+ eq_token: self.eq_token.clone(),
+ default: self.default.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::Constraint {
+ fn clone(&self) -> Self {
+ crate::Constraint {
+ ident: self.ident.clone(),
+ generics: self.generics.clone(),
+ colon_token: self.colon_token.clone(),
+ bounds: self.bounds.clone(),
+ }
+ }
+}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::Data {
+ fn clone(&self) -> Self {
+ match self {
+ crate::Data::Struct(v0) => crate::Data::Struct(v0.clone()),
+ crate::Data::Enum(v0) => crate::Data::Enum(v0.clone()),
+ crate::Data::Union(v0) => crate::Data::Union(v0.clone()),
+ }
+ }
+}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::DataEnum {
+ fn clone(&self) -> Self {
+ crate::DataEnum {
+ enum_token: self.enum_token.clone(),
+ brace_token: self.brace_token.clone(),
+ variants: self.variants.clone(),
+ }
+ }
+}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::DataStruct {
+ fn clone(&self) -> Self {
+ crate::DataStruct {
+ struct_token: self.struct_token.clone(),
+ fields: self.fields.clone(),
+ semi_token: self.semi_token.clone(),
+ }
+ }
+}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::DataUnion {
+ fn clone(&self) -> Self {
+ crate::DataUnion {
+ union_token: self.union_token.clone(),
+ fields: self.fields.clone(),
+ }
+ }
+}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::DeriveInput {
+ fn clone(&self) -> Self {
+ crate::DeriveInput {
+ attrs: self.attrs.clone(),
+ vis: self.vis.clone(),
+ ident: self.ident.clone(),
+ generics: self.generics.clone(),
+ data: self.data.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::Expr {
+ fn clone(&self) -> Self {
+ match self {
+ #[cfg(feature = "full")]
+ crate::Expr::Array(v0) => crate::Expr::Array(v0.clone()),
+ #[cfg(feature = "full")]
+ crate::Expr::Assign(v0) => crate::Expr::Assign(v0.clone()),
+ #[cfg(feature = "full")]
+ crate::Expr::Async(v0) => crate::Expr::Async(v0.clone()),
+ #[cfg(feature = "full")]
+ crate::Expr::Await(v0) => crate::Expr::Await(v0.clone()),
+ crate::Expr::Binary(v0) => crate::Expr::Binary(v0.clone()),
+ #[cfg(feature = "full")]
+ crate::Expr::Block(v0) => crate::Expr::Block(v0.clone()),
+ #[cfg(feature = "full")]
+ crate::Expr::Break(v0) => crate::Expr::Break(v0.clone()),
+ crate::Expr::Call(v0) => crate::Expr::Call(v0.clone()),
+ crate::Expr::Cast(v0) => crate::Expr::Cast(v0.clone()),
+ #[cfg(feature = "full")]
+ crate::Expr::Closure(v0) => crate::Expr::Closure(v0.clone()),
+ #[cfg(feature = "full")]
+ crate::Expr::Const(v0) => crate::Expr::Const(v0.clone()),
+ #[cfg(feature = "full")]
+ crate::Expr::Continue(v0) => crate::Expr::Continue(v0.clone()),
+ crate::Expr::Field(v0) => crate::Expr::Field(v0.clone()),
+ #[cfg(feature = "full")]
+ crate::Expr::ForLoop(v0) => crate::Expr::ForLoop(v0.clone()),
+ crate::Expr::Group(v0) => crate::Expr::Group(v0.clone()),
+ #[cfg(feature = "full")]
+ crate::Expr::If(v0) => crate::Expr::If(v0.clone()),
+ crate::Expr::Index(v0) => crate::Expr::Index(v0.clone()),
+ #[cfg(feature = "full")]
+ crate::Expr::Infer(v0) => crate::Expr::Infer(v0.clone()),
+ #[cfg(feature = "full")]
+ crate::Expr::Let(v0) => crate::Expr::Let(v0.clone()),
+ crate::Expr::Lit(v0) => crate::Expr::Lit(v0.clone()),
+ #[cfg(feature = "full")]
+ crate::Expr::Loop(v0) => crate::Expr::Loop(v0.clone()),
+ crate::Expr::Macro(v0) => crate::Expr::Macro(v0.clone()),
+ #[cfg(feature = "full")]
+ crate::Expr::Match(v0) => crate::Expr::Match(v0.clone()),
+ crate::Expr::MethodCall(v0) => crate::Expr::MethodCall(v0.clone()),
+ crate::Expr::Paren(v0) => crate::Expr::Paren(v0.clone()),
+ crate::Expr::Path(v0) => crate::Expr::Path(v0.clone()),
+ #[cfg(feature = "full")]
+ crate::Expr::Range(v0) => crate::Expr::Range(v0.clone()),
+ #[cfg(feature = "full")]
+ crate::Expr::RawAddr(v0) => crate::Expr::RawAddr(v0.clone()),
+ crate::Expr::Reference(v0) => crate::Expr::Reference(v0.clone()),
+ #[cfg(feature = "full")]
+ crate::Expr::Repeat(v0) => crate::Expr::Repeat(v0.clone()),
+ #[cfg(feature = "full")]
+ crate::Expr::Return(v0) => crate::Expr::Return(v0.clone()),
+ crate::Expr::Struct(v0) => crate::Expr::Struct(v0.clone()),
+ #[cfg(feature = "full")]
+ crate::Expr::Try(v0) => crate::Expr::Try(v0.clone()),
+ #[cfg(feature = "full")]
+ crate::Expr::TryBlock(v0) => crate::Expr::TryBlock(v0.clone()),
+ crate::Expr::Tuple(v0) => crate::Expr::Tuple(v0.clone()),
+ crate::Expr::Unary(v0) => crate::Expr::Unary(v0.clone()),
+ #[cfg(feature = "full")]
+ crate::Expr::Unsafe(v0) => crate::Expr::Unsafe(v0.clone()),
+ crate::Expr::Verbatim(v0) => crate::Expr::Verbatim(v0.clone()),
+ #[cfg(feature = "full")]
+ crate::Expr::While(v0) => crate::Expr::While(v0.clone()),
+ #[cfg(feature = "full")]
+ crate::Expr::Yield(v0) => crate::Expr::Yield(v0.clone()),
+ #[cfg(not(feature = "full"))]
+ _ => unreachable!(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ExprArray {
+ fn clone(&self) -> Self {
+ crate::ExprArray {
+ attrs: self.attrs.clone(),
+ bracket_token: self.bracket_token.clone(),
+ elems: self.elems.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ExprAssign {
+ fn clone(&self) -> Self {
+ crate::ExprAssign {
+ attrs: self.attrs.clone(),
+ left: self.left.clone(),
+ eq_token: self.eq_token.clone(),
+ right: self.right.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ExprAsync {
+ fn clone(&self) -> Self {
+ crate::ExprAsync {
+ attrs: self.attrs.clone(),
+ async_token: self.async_token.clone(),
+ capture: self.capture.clone(),
+ block: self.block.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ExprAwait {
+ fn clone(&self) -> Self {
+ crate::ExprAwait {
+ attrs: self.attrs.clone(),
+ base: self.base.clone(),
+ dot_token: self.dot_token.clone(),
+ await_token: self.await_token.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ExprBinary {
+ fn clone(&self) -> Self {
+ crate::ExprBinary {
+ attrs: self.attrs.clone(),
+ left: self.left.clone(),
+ op: self.op.clone(),
+ right: self.right.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ExprBlock {
+ fn clone(&self) -> Self {
+ crate::ExprBlock {
+ attrs: self.attrs.clone(),
+ label: self.label.clone(),
+ block: self.block.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ExprBreak {
+ fn clone(&self) -> Self {
+ crate::ExprBreak {
+ attrs: self.attrs.clone(),
+ break_token: self.break_token.clone(),
+ label: self.label.clone(),
+ expr: self.expr.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ExprCall {
+ fn clone(&self) -> Self {
+ crate::ExprCall {
+ attrs: self.attrs.clone(),
+ func: self.func.clone(),
+ paren_token: self.paren_token.clone(),
+ args: self.args.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ExprCast {
+ fn clone(&self) -> Self {
+ crate::ExprCast {
+ attrs: self.attrs.clone(),
+ expr: self.expr.clone(),
+ as_token: self.as_token.clone(),
+ ty: self.ty.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ExprClosure {
+ fn clone(&self) -> Self {
+ crate::ExprClosure {
+ attrs: self.attrs.clone(),
+ lifetimes: self.lifetimes.clone(),
+ constness: self.constness.clone(),
+ movability: self.movability.clone(),
+ asyncness: self.asyncness.clone(),
+ capture: self.capture.clone(),
+ or1_token: self.or1_token.clone(),
+ inputs: self.inputs.clone(),
+ or2_token: self.or2_token.clone(),
+ output: self.output.clone(),
+ body: self.body.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ExprConst {
+ fn clone(&self) -> Self {
+ crate::ExprConst {
+ attrs: self.attrs.clone(),
+ const_token: self.const_token.clone(),
+ block: self.block.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ExprContinue {
+ fn clone(&self) -> Self {
+ crate::ExprContinue {
+ attrs: self.attrs.clone(),
+ continue_token: self.continue_token.clone(),
+ label: self.label.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ExprField {
+ fn clone(&self) -> Self {
+ crate::ExprField {
+ attrs: self.attrs.clone(),
+ base: self.base.clone(),
+ dot_token: self.dot_token.clone(),
+ member: self.member.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ExprForLoop {
+ fn clone(&self) -> Self {
+ crate::ExprForLoop {
+ attrs: self.attrs.clone(),
+ label: self.label.clone(),
+ for_token: self.for_token.clone(),
+ pat: self.pat.clone(),
+ in_token: self.in_token.clone(),
+ expr: self.expr.clone(),
+ body: self.body.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ExprGroup {
+ fn clone(&self) -> Self {
+ crate::ExprGroup {
+ attrs: self.attrs.clone(),
+ group_token: self.group_token.clone(),
+ expr: self.expr.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ExprIf {
+ fn clone(&self) -> Self {
+ crate::ExprIf {
+ attrs: self.attrs.clone(),
+ if_token: self.if_token.clone(),
+ cond: self.cond.clone(),
+ then_branch: self.then_branch.clone(),
+ else_branch: self.else_branch.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ExprIndex {
+ fn clone(&self) -> Self {
+ crate::ExprIndex {
+ attrs: self.attrs.clone(),
+ expr: self.expr.clone(),
+ bracket_token: self.bracket_token.clone(),
+ index: self.index.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ExprInfer {
+ fn clone(&self) -> Self {
+ crate::ExprInfer {
+ attrs: self.attrs.clone(),
+ underscore_token: self.underscore_token.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ExprLet {
+ fn clone(&self) -> Self {
+ crate::ExprLet {
+ attrs: self.attrs.clone(),
+ let_token: self.let_token.clone(),
+ pat: self.pat.clone(),
+ eq_token: self.eq_token.clone(),
+ expr: self.expr.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ExprLit {
+ fn clone(&self) -> Self {
+ crate::ExprLit {
+ attrs: self.attrs.clone(),
+ lit: self.lit.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ExprLoop {
+ fn clone(&self) -> Self {
+ crate::ExprLoop {
+ attrs: self.attrs.clone(),
+ label: self.label.clone(),
+ loop_token: self.loop_token.clone(),
+ body: self.body.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ExprMacro {
+ fn clone(&self) -> Self {
+ crate::ExprMacro {
+ attrs: self.attrs.clone(),
+ mac: self.mac.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ExprMatch {
+ fn clone(&self) -> Self {
+ crate::ExprMatch {
+ attrs: self.attrs.clone(),
+ match_token: self.match_token.clone(),
+ expr: self.expr.clone(),
+ brace_token: self.brace_token.clone(),
+ arms: self.arms.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ExprMethodCall {
+ fn clone(&self) -> Self {
+ crate::ExprMethodCall {
+ attrs: self.attrs.clone(),
+ receiver: self.receiver.clone(),
+ dot_token: self.dot_token.clone(),
+ method: self.method.clone(),
+ turbofish: self.turbofish.clone(),
+ paren_token: self.paren_token.clone(),
+ args: self.args.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ExprParen {
+ fn clone(&self) -> Self {
+ crate::ExprParen {
+ attrs: self.attrs.clone(),
+ paren_token: self.paren_token.clone(),
+ expr: self.expr.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ExprPath {
+ fn clone(&self) -> Self {
+ crate::ExprPath {
+ attrs: self.attrs.clone(),
+ qself: self.qself.clone(),
+ path: self.path.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ExprRange {
+ fn clone(&self) -> Self {
+ crate::ExprRange {
+ attrs: self.attrs.clone(),
+ start: self.start.clone(),
+ limits: self.limits.clone(),
+ end: self.end.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ExprRawAddr {
+ fn clone(&self) -> Self {
+ crate::ExprRawAddr {
+ attrs: self.attrs.clone(),
+ and_token: self.and_token.clone(),
+ raw: self.raw.clone(),
+ mutability: self.mutability.clone(),
+ expr: self.expr.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ExprReference {
+ fn clone(&self) -> Self {
+ crate::ExprReference {
+ attrs: self.attrs.clone(),
+ and_token: self.and_token.clone(),
+ mutability: self.mutability.clone(),
+ expr: self.expr.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ExprRepeat {
+ fn clone(&self) -> Self {
+ crate::ExprRepeat {
+ attrs: self.attrs.clone(),
+ bracket_token: self.bracket_token.clone(),
+ expr: self.expr.clone(),
+ semi_token: self.semi_token.clone(),
+ len: self.len.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ExprReturn {
+ fn clone(&self) -> Self {
+ crate::ExprReturn {
+ attrs: self.attrs.clone(),
+ return_token: self.return_token.clone(),
+ expr: self.expr.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ExprStruct {
+ fn clone(&self) -> Self {
+ crate::ExprStruct {
+ attrs: self.attrs.clone(),
+ qself: self.qself.clone(),
+ path: self.path.clone(),
+ brace_token: self.brace_token.clone(),
+ fields: self.fields.clone(),
+ dot2_token: self.dot2_token.clone(),
+ rest: self.rest.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ExprTry {
+ fn clone(&self) -> Self {
+ crate::ExprTry {
+ attrs: self.attrs.clone(),
+ expr: self.expr.clone(),
+ question_token: self.question_token.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ExprTryBlock {
+ fn clone(&self) -> Self {
+ crate::ExprTryBlock {
+ attrs: self.attrs.clone(),
+ try_token: self.try_token.clone(),
+ block: self.block.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ExprTuple {
+ fn clone(&self) -> Self {
+ crate::ExprTuple {
+ attrs: self.attrs.clone(),
+ paren_token: self.paren_token.clone(),
+ elems: self.elems.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ExprUnary {
+ fn clone(&self) -> Self {
+ crate::ExprUnary {
+ attrs: self.attrs.clone(),
+ op: self.op.clone(),
+ expr: self.expr.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ExprUnsafe {
+ fn clone(&self) -> Self {
+ crate::ExprUnsafe {
+ attrs: self.attrs.clone(),
+ unsafe_token: self.unsafe_token.clone(),
+ block: self.block.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ExprWhile {
+ fn clone(&self) -> Self {
+ crate::ExprWhile {
+ attrs: self.attrs.clone(),
+ label: self.label.clone(),
+ while_token: self.while_token.clone(),
+ cond: self.cond.clone(),
+ body: self.body.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ExprYield {
+ fn clone(&self) -> Self {
+ crate::ExprYield {
+ attrs: self.attrs.clone(),
+ yield_token: self.yield_token.clone(),
+ expr: self.expr.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::Field {
+ fn clone(&self) -> Self {
+ crate::Field {
+ attrs: self.attrs.clone(),
+ vis: self.vis.clone(),
+ mutability: self.mutability.clone(),
+ ident: self.ident.clone(),
+ colon_token: self.colon_token.clone(),
+ ty: self.ty.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::FieldMutability {
+ fn clone(&self) -> Self {
+ match self {
+ crate::FieldMutability::None => crate::FieldMutability::None,
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::FieldPat {
+ fn clone(&self) -> Self {
+ crate::FieldPat {
+ attrs: self.attrs.clone(),
+ member: self.member.clone(),
+ colon_token: self.colon_token.clone(),
+ pat: self.pat.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::FieldValue {
+ fn clone(&self) -> Self {
+ crate::FieldValue {
+ attrs: self.attrs.clone(),
+ member: self.member.clone(),
+ colon_token: self.colon_token.clone(),
+ expr: self.expr.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::Fields {
+ fn clone(&self) -> Self {
+ match self {
+ crate::Fields::Named(v0) => crate::Fields::Named(v0.clone()),
+ crate::Fields::Unnamed(v0) => crate::Fields::Unnamed(v0.clone()),
+ crate::Fields::Unit => crate::Fields::Unit,
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::FieldsNamed {
+ fn clone(&self) -> Self {
+ crate::FieldsNamed {
+ brace_token: self.brace_token.clone(),
+ named: self.named.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::FieldsUnnamed {
+ fn clone(&self) -> Self {
+ crate::FieldsUnnamed {
+ paren_token: self.paren_token.clone(),
+ unnamed: self.unnamed.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::File {
+ fn clone(&self) -> Self {
+ crate::File {
+ shebang: self.shebang.clone(),
+ attrs: self.attrs.clone(),
+ items: self.items.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::FnArg {
+ fn clone(&self) -> Self {
+ match self {
+ crate::FnArg::Receiver(v0) => crate::FnArg::Receiver(v0.clone()),
+ crate::FnArg::Typed(v0) => crate::FnArg::Typed(v0.clone()),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ForeignItem {
+ fn clone(&self) -> Self {
+ match self {
+ crate::ForeignItem::Fn(v0) => crate::ForeignItem::Fn(v0.clone()),
+ crate::ForeignItem::Static(v0) => crate::ForeignItem::Static(v0.clone()),
+ crate::ForeignItem::Type(v0) => crate::ForeignItem::Type(v0.clone()),
+ crate::ForeignItem::Macro(v0) => crate::ForeignItem::Macro(v0.clone()),
+ crate::ForeignItem::Verbatim(v0) => crate::ForeignItem::Verbatim(v0.clone()),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ForeignItemFn {
+ fn clone(&self) -> Self {
+ crate::ForeignItemFn {
+ attrs: self.attrs.clone(),
+ vis: self.vis.clone(),
+ sig: self.sig.clone(),
+ semi_token: self.semi_token.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ForeignItemMacro {
+ fn clone(&self) -> Self {
+ crate::ForeignItemMacro {
+ attrs: self.attrs.clone(),
+ mac: self.mac.clone(),
+ semi_token: self.semi_token.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ForeignItemStatic {
+ fn clone(&self) -> Self {
+ crate::ForeignItemStatic {
+ attrs: self.attrs.clone(),
+ vis: self.vis.clone(),
+ static_token: self.static_token.clone(),
+ mutability: self.mutability.clone(),
+ ident: self.ident.clone(),
+ colon_token: self.colon_token.clone(),
+ ty: self.ty.clone(),
+ semi_token: self.semi_token.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ForeignItemType {
+ fn clone(&self) -> Self {
+ crate::ForeignItemType {
+ attrs: self.attrs.clone(),
+ vis: self.vis.clone(),
+ type_token: self.type_token.clone(),
+ ident: self.ident.clone(),
+ generics: self.generics.clone(),
+ semi_token: self.semi_token.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::GenericArgument {
+ fn clone(&self) -> Self {
+ match self {
+ crate::GenericArgument::Lifetime(v0) => {
+ crate::GenericArgument::Lifetime(v0.clone())
+ }
+ crate::GenericArgument::Type(v0) => crate::GenericArgument::Type(v0.clone()),
+ crate::GenericArgument::Const(v0) => {
+ crate::GenericArgument::Const(v0.clone())
+ }
+ crate::GenericArgument::AssocType(v0) => {
+ crate::GenericArgument::AssocType(v0.clone())
+ }
+ crate::GenericArgument::AssocConst(v0) => {
+ crate::GenericArgument::AssocConst(v0.clone())
+ }
+ crate::GenericArgument::Constraint(v0) => {
+ crate::GenericArgument::Constraint(v0.clone())
+ }
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::GenericParam {
+ fn clone(&self) -> Self {
+ match self {
+ crate::GenericParam::Lifetime(v0) => {
+ crate::GenericParam::Lifetime(v0.clone())
+ }
+ crate::GenericParam::Type(v0) => crate::GenericParam::Type(v0.clone()),
+ crate::GenericParam::Const(v0) => crate::GenericParam::Const(v0.clone()),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::Generics {
+ fn clone(&self) -> Self {
+ crate::Generics {
+ lt_token: self.lt_token.clone(),
+ params: self.params.clone(),
+ gt_token: self.gt_token.clone(),
+ where_clause: self.where_clause.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ImplItem {
+ fn clone(&self) -> Self {
+ match self {
+ crate::ImplItem::Const(v0) => crate::ImplItem::Const(v0.clone()),
+ crate::ImplItem::Fn(v0) => crate::ImplItem::Fn(v0.clone()),
+ crate::ImplItem::Type(v0) => crate::ImplItem::Type(v0.clone()),
+ crate::ImplItem::Macro(v0) => crate::ImplItem::Macro(v0.clone()),
+ crate::ImplItem::Verbatim(v0) => crate::ImplItem::Verbatim(v0.clone()),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ImplItemConst {
+ fn clone(&self) -> Self {
+ crate::ImplItemConst {
+ attrs: self.attrs.clone(),
+ vis: self.vis.clone(),
+ defaultness: self.defaultness.clone(),
+ const_token: self.const_token.clone(),
+ ident: self.ident.clone(),
+ generics: self.generics.clone(),
+ colon_token: self.colon_token.clone(),
+ ty: self.ty.clone(),
+ eq_token: self.eq_token.clone(),
+ expr: self.expr.clone(),
+ semi_token: self.semi_token.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ImplItemFn {
+ fn clone(&self) -> Self {
+ crate::ImplItemFn {
+ attrs: self.attrs.clone(),
+ vis: self.vis.clone(),
+ defaultness: self.defaultness.clone(),
+ sig: self.sig.clone(),
+ block: self.block.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ImplItemMacro {
+ fn clone(&self) -> Self {
+ crate::ImplItemMacro {
+ attrs: self.attrs.clone(),
+ mac: self.mac.clone(),
+ semi_token: self.semi_token.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ImplItemType {
+ fn clone(&self) -> Self {
+ crate::ImplItemType {
+ attrs: self.attrs.clone(),
+ vis: self.vis.clone(),
+ defaultness: self.defaultness.clone(),
+ type_token: self.type_token.clone(),
+ ident: self.ident.clone(),
+ generics: self.generics.clone(),
+ eq_token: self.eq_token.clone(),
+ ty: self.ty.clone(),
+ semi_token: self.semi_token.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ImplRestriction {
+ fn clone(&self) -> Self {
+ match *self {}
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::Index {
+ fn clone(&self) -> Self {
+ crate::Index {
+ index: self.index.clone(),
+ span: self.span.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::Item {
+ fn clone(&self) -> Self {
+ match self {
+ crate::Item::Const(v0) => crate::Item::Const(v0.clone()),
+ crate::Item::Enum(v0) => crate::Item::Enum(v0.clone()),
+ crate::Item::ExternCrate(v0) => crate::Item::ExternCrate(v0.clone()),
+ crate::Item::Fn(v0) => crate::Item::Fn(v0.clone()),
+ crate::Item::ForeignMod(v0) => crate::Item::ForeignMod(v0.clone()),
+ crate::Item::Impl(v0) => crate::Item::Impl(v0.clone()),
+ crate::Item::Macro(v0) => crate::Item::Macro(v0.clone()),
+ crate::Item::Mod(v0) => crate::Item::Mod(v0.clone()),
+ crate::Item::Static(v0) => crate::Item::Static(v0.clone()),
+ crate::Item::Struct(v0) => crate::Item::Struct(v0.clone()),
+ crate::Item::Trait(v0) => crate::Item::Trait(v0.clone()),
+ crate::Item::TraitAlias(v0) => crate::Item::TraitAlias(v0.clone()),
+ crate::Item::Type(v0) => crate::Item::Type(v0.clone()),
+ crate::Item::Union(v0) => crate::Item::Union(v0.clone()),
+ crate::Item::Use(v0) => crate::Item::Use(v0.clone()),
+ crate::Item::Verbatim(v0) => crate::Item::Verbatim(v0.clone()),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ItemConst {
+ fn clone(&self) -> Self {
+ crate::ItemConst {
+ attrs: self.attrs.clone(),
+ vis: self.vis.clone(),
+ const_token: self.const_token.clone(),
+ ident: self.ident.clone(),
+ generics: self.generics.clone(),
+ colon_token: self.colon_token.clone(),
+ ty: self.ty.clone(),
+ eq_token: self.eq_token.clone(),
+ expr: self.expr.clone(),
+ semi_token: self.semi_token.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ItemEnum {
+ fn clone(&self) -> Self {
+ crate::ItemEnum {
+ attrs: self.attrs.clone(),
+ vis: self.vis.clone(),
+ enum_token: self.enum_token.clone(),
+ ident: self.ident.clone(),
+ generics: self.generics.clone(),
+ brace_token: self.brace_token.clone(),
+ variants: self.variants.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ItemExternCrate {
+ fn clone(&self) -> Self {
+ crate::ItemExternCrate {
+ attrs: self.attrs.clone(),
+ vis: self.vis.clone(),
+ extern_token: self.extern_token.clone(),
+ crate_token: self.crate_token.clone(),
+ ident: self.ident.clone(),
+ rename: self.rename.clone(),
+ semi_token: self.semi_token.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ItemFn {
+ fn clone(&self) -> Self {
+ crate::ItemFn {
+ attrs: self.attrs.clone(),
+ vis: self.vis.clone(),
+ sig: self.sig.clone(),
+ block: self.block.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ItemForeignMod {
+ fn clone(&self) -> Self {
+ crate::ItemForeignMod {
+ attrs: self.attrs.clone(),
+ unsafety: self.unsafety.clone(),
+ abi: self.abi.clone(),
+ brace_token: self.brace_token.clone(),
+ items: self.items.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ItemImpl {
+ fn clone(&self) -> Self {
+ crate::ItemImpl {
+ attrs: self.attrs.clone(),
+ defaultness: self.defaultness.clone(),
+ unsafety: self.unsafety.clone(),
+ impl_token: self.impl_token.clone(),
+ generics: self.generics.clone(),
+ trait_: self.trait_.clone(),
+ self_ty: self.self_ty.clone(),
+ brace_token: self.brace_token.clone(),
+ items: self.items.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ItemMacro {
+ fn clone(&self) -> Self {
+ crate::ItemMacro {
+ attrs: self.attrs.clone(),
+ ident: self.ident.clone(),
+ mac: self.mac.clone(),
+ semi_token: self.semi_token.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ItemMod {
+ fn clone(&self) -> Self {
+ crate::ItemMod {
+ attrs: self.attrs.clone(),
+ vis: self.vis.clone(),
+ unsafety: self.unsafety.clone(),
+ mod_token: self.mod_token.clone(),
+ ident: self.ident.clone(),
+ content: self.content.clone(),
+ semi: self.semi.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ItemStatic {
+ fn clone(&self) -> Self {
+ crate::ItemStatic {
+ attrs: self.attrs.clone(),
+ vis: self.vis.clone(),
+ static_token: self.static_token.clone(),
+ mutability: self.mutability.clone(),
+ ident: self.ident.clone(),
+ colon_token: self.colon_token.clone(),
+ ty: self.ty.clone(),
+ eq_token: self.eq_token.clone(),
+ expr: self.expr.clone(),
+ semi_token: self.semi_token.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ItemStruct {
+ fn clone(&self) -> Self {
+ crate::ItemStruct {
+ attrs: self.attrs.clone(),
+ vis: self.vis.clone(),
+ struct_token: self.struct_token.clone(),
+ ident: self.ident.clone(),
+ generics: self.generics.clone(),
+ fields: self.fields.clone(),
+ semi_token: self.semi_token.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ItemTrait {
+ fn clone(&self) -> Self {
+ crate::ItemTrait {
+ attrs: self.attrs.clone(),
+ vis: self.vis.clone(),
+ unsafety: self.unsafety.clone(),
+ auto_token: self.auto_token.clone(),
+ restriction: self.restriction.clone(),
+ trait_token: self.trait_token.clone(),
+ ident: self.ident.clone(),
+ generics: self.generics.clone(),
+ colon_token: self.colon_token.clone(),
+ supertraits: self.supertraits.clone(),
+ brace_token: self.brace_token.clone(),
+ items: self.items.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ItemTraitAlias {
+ fn clone(&self) -> Self {
+ crate::ItemTraitAlias {
+ attrs: self.attrs.clone(),
+ vis: self.vis.clone(),
+ trait_token: self.trait_token.clone(),
+ ident: self.ident.clone(),
+ generics: self.generics.clone(),
+ eq_token: self.eq_token.clone(),
+ bounds: self.bounds.clone(),
+ semi_token: self.semi_token.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ItemType {
+ fn clone(&self) -> Self {
+ crate::ItemType {
+ attrs: self.attrs.clone(),
+ vis: self.vis.clone(),
+ type_token: self.type_token.clone(),
+ ident: self.ident.clone(),
+ generics: self.generics.clone(),
+ eq_token: self.eq_token.clone(),
+ ty: self.ty.clone(),
+ semi_token: self.semi_token.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ItemUnion {
+ fn clone(&self) -> Self {
+ crate::ItemUnion {
+ attrs: self.attrs.clone(),
+ vis: self.vis.clone(),
+ union_token: self.union_token.clone(),
+ ident: self.ident.clone(),
+ generics: self.generics.clone(),
+ fields: self.fields.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ItemUse {
+ fn clone(&self) -> Self {
+ crate::ItemUse {
+ attrs: self.attrs.clone(),
+ vis: self.vis.clone(),
+ use_token: self.use_token.clone(),
+ leading_colon: self.leading_colon.clone(),
+ tree: self.tree.clone(),
+ semi_token: self.semi_token.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::Label {
+ fn clone(&self) -> Self {
+ crate::Label {
+ name: self.name.clone(),
+ colon_token: self.colon_token.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::LifetimeParam {
+ fn clone(&self) -> Self {
+ crate::LifetimeParam {
+ attrs: self.attrs.clone(),
+ lifetime: self.lifetime.clone(),
+ colon_token: self.colon_token.clone(),
+ bounds: self.bounds.clone(),
+ }
+ }
+}
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::Lit {
+ fn clone(&self) -> Self {
+ match self {
+ crate::Lit::Str(v0) => crate::Lit::Str(v0.clone()),
+ crate::Lit::ByteStr(v0) => crate::Lit::ByteStr(v0.clone()),
+ crate::Lit::CStr(v0) => crate::Lit::CStr(v0.clone()),
+ crate::Lit::Byte(v0) => crate::Lit::Byte(v0.clone()),
+ crate::Lit::Char(v0) => crate::Lit::Char(v0.clone()),
+ crate::Lit::Int(v0) => crate::Lit::Int(v0.clone()),
+ crate::Lit::Float(v0) => crate::Lit::Float(v0.clone()),
+ crate::Lit::Bool(v0) => crate::Lit::Bool(v0.clone()),
+ crate::Lit::Verbatim(v0) => crate::Lit::Verbatim(v0.clone()),
+ }
+ }
+}
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::LitBool {
+ fn clone(&self) -> Self {
+ crate::LitBool {
+ value: self.value.clone(),
+ span: self.span.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::Local {
+ fn clone(&self) -> Self {
+ crate::Local {
+ attrs: self.attrs.clone(),
+ let_token: self.let_token.clone(),
+ pat: self.pat.clone(),
+ init: self.init.clone(),
+ semi_token: self.semi_token.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::LocalInit {
+ fn clone(&self) -> Self {
+ crate::LocalInit {
+ eq_token: self.eq_token.clone(),
+ expr: self.expr.clone(),
+ diverge: self.diverge.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::Macro {
+ fn clone(&self) -> Self {
+ crate::Macro {
+ path: self.path.clone(),
+ bang_token: self.bang_token.clone(),
+ delimiter: self.delimiter.clone(),
+ tokens: self.tokens.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::MacroDelimiter {
+ fn clone(&self) -> Self {
+ match self {
+ crate::MacroDelimiter::Paren(v0) => crate::MacroDelimiter::Paren(v0.clone()),
+ crate::MacroDelimiter::Brace(v0) => crate::MacroDelimiter::Brace(v0.clone()),
+ crate::MacroDelimiter::Bracket(v0) => {
+ crate::MacroDelimiter::Bracket(v0.clone())
+ }
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::Member {
+ fn clone(&self) -> Self {
+ match self {
+ crate::Member::Named(v0) => crate::Member::Named(v0.clone()),
+ crate::Member::Unnamed(v0) => crate::Member::Unnamed(v0.clone()),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::Meta {
+ fn clone(&self) -> Self {
+ match self {
+ crate::Meta::Path(v0) => crate::Meta::Path(v0.clone()),
+ crate::Meta::List(v0) => crate::Meta::List(v0.clone()),
+ crate::Meta::NameValue(v0) => crate::Meta::NameValue(v0.clone()),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::MetaList {
+ fn clone(&self) -> Self {
+ crate::MetaList {
+ path: self.path.clone(),
+ delimiter: self.delimiter.clone(),
+ tokens: self.tokens.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::MetaNameValue {
+ fn clone(&self) -> Self {
+ crate::MetaNameValue {
+ path: self.path.clone(),
+ eq_token: self.eq_token.clone(),
+ value: self.value.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ParenthesizedGenericArguments {
+ fn clone(&self) -> Self {
+ crate::ParenthesizedGenericArguments {
+ paren_token: self.paren_token.clone(),
+ inputs: self.inputs.clone(),
+ output: self.output.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::Pat {
+ fn clone(&self) -> Self {
+ match self {
+ crate::Pat::Const(v0) => crate::Pat::Const(v0.clone()),
+ crate::Pat::Ident(v0) => crate::Pat::Ident(v0.clone()),
+ crate::Pat::Lit(v0) => crate::Pat::Lit(v0.clone()),
+ crate::Pat::Macro(v0) => crate::Pat::Macro(v0.clone()),
+ crate::Pat::Or(v0) => crate::Pat::Or(v0.clone()),
+ crate::Pat::Paren(v0) => crate::Pat::Paren(v0.clone()),
+ crate::Pat::Path(v0) => crate::Pat::Path(v0.clone()),
+ crate::Pat::Range(v0) => crate::Pat::Range(v0.clone()),
+ crate::Pat::Reference(v0) => crate::Pat::Reference(v0.clone()),
+ crate::Pat::Rest(v0) => crate::Pat::Rest(v0.clone()),
+ crate::Pat::Slice(v0) => crate::Pat::Slice(v0.clone()),
+ crate::Pat::Struct(v0) => crate::Pat::Struct(v0.clone()),
+ crate::Pat::Tuple(v0) => crate::Pat::Tuple(v0.clone()),
+ crate::Pat::TupleStruct(v0) => crate::Pat::TupleStruct(v0.clone()),
+ crate::Pat::Type(v0) => crate::Pat::Type(v0.clone()),
+ crate::Pat::Verbatim(v0) => crate::Pat::Verbatim(v0.clone()),
+ crate::Pat::Wild(v0) => crate::Pat::Wild(v0.clone()),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::PatIdent {
+ fn clone(&self) -> Self {
+ crate::PatIdent {
+ attrs: self.attrs.clone(),
+ by_ref: self.by_ref.clone(),
+ mutability: self.mutability.clone(),
+ ident: self.ident.clone(),
+ subpat: self.subpat.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::PatOr {
+ fn clone(&self) -> Self {
+ crate::PatOr {
+ attrs: self.attrs.clone(),
+ leading_vert: self.leading_vert.clone(),
+ cases: self.cases.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::PatParen {
+ fn clone(&self) -> Self {
+ crate::PatParen {
+ attrs: self.attrs.clone(),
+ paren_token: self.paren_token.clone(),
+ pat: self.pat.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::PatReference {
+ fn clone(&self) -> Self {
+ crate::PatReference {
+ attrs: self.attrs.clone(),
+ and_token: self.and_token.clone(),
+ mutability: self.mutability.clone(),
+ pat: self.pat.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::PatRest {
+ fn clone(&self) -> Self {
+ crate::PatRest {
+ attrs: self.attrs.clone(),
+ dot2_token: self.dot2_token.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::PatSlice {
+ fn clone(&self) -> Self {
+ crate::PatSlice {
+ attrs: self.attrs.clone(),
+ bracket_token: self.bracket_token.clone(),
+ elems: self.elems.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::PatStruct {
+ fn clone(&self) -> Self {
+ crate::PatStruct {
+ attrs: self.attrs.clone(),
+ qself: self.qself.clone(),
+ path: self.path.clone(),
+ brace_token: self.brace_token.clone(),
+ fields: self.fields.clone(),
+ rest: self.rest.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::PatTuple {
+ fn clone(&self) -> Self {
+ crate::PatTuple {
+ attrs: self.attrs.clone(),
+ paren_token: self.paren_token.clone(),
+ elems: self.elems.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::PatTupleStruct {
+ fn clone(&self) -> Self {
+ crate::PatTupleStruct {
+ attrs: self.attrs.clone(),
+ qself: self.qself.clone(),
+ path: self.path.clone(),
+ paren_token: self.paren_token.clone(),
+ elems: self.elems.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::PatType {
+ fn clone(&self) -> Self {
+ crate::PatType {
+ attrs: self.attrs.clone(),
+ pat: self.pat.clone(),
+ colon_token: self.colon_token.clone(),
+ ty: self.ty.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::PatWild {
+ fn clone(&self) -> Self {
+ crate::PatWild {
+ attrs: self.attrs.clone(),
+ underscore_token: self.underscore_token.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::Path {
+ fn clone(&self) -> Self {
+ crate::Path {
+ leading_colon: self.leading_colon.clone(),
+ segments: self.segments.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::PathArguments {
+ fn clone(&self) -> Self {
+ match self {
+ crate::PathArguments::None => crate::PathArguments::None,
+ crate::PathArguments::AngleBracketed(v0) => {
+ crate::PathArguments::AngleBracketed(v0.clone())
+ }
+ crate::PathArguments::Parenthesized(v0) => {
+ crate::PathArguments::Parenthesized(v0.clone())
+ }
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::PathSegment {
+ fn clone(&self) -> Self {
+ crate::PathSegment {
+ ident: self.ident.clone(),
+ arguments: self.arguments.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::PointerMutability {
+ fn clone(&self) -> Self {
+ match self {
+ crate::PointerMutability::Const(v0) => {
+ crate::PointerMutability::Const(v0.clone())
+ }
+ crate::PointerMutability::Mut(v0) => {
+ crate::PointerMutability::Mut(v0.clone())
+ }
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::PreciseCapture {
+ fn clone(&self) -> Self {
+ crate::PreciseCapture {
+ use_token: self.use_token.clone(),
+ lt_token: self.lt_token.clone(),
+ params: self.params.clone(),
+ gt_token: self.gt_token.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::PredicateLifetime {
+ fn clone(&self) -> Self {
+ crate::PredicateLifetime {
+ lifetime: self.lifetime.clone(),
+ colon_token: self.colon_token.clone(),
+ bounds: self.bounds.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::PredicateType {
+ fn clone(&self) -> Self {
+ crate::PredicateType {
+ lifetimes: self.lifetimes.clone(),
+ bounded_ty: self.bounded_ty.clone(),
+ colon_token: self.colon_token.clone(),
+ bounds: self.bounds.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::QSelf {
+ fn clone(&self) -> Self {
+ crate::QSelf {
+ lt_token: self.lt_token.clone(),
+ ty: self.ty.clone(),
+ position: self.position.clone(),
+ as_token: self.as_token.clone(),
+ gt_token: self.gt_token.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Copy for crate::RangeLimits {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::RangeLimits {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::Receiver {
+ fn clone(&self) -> Self {
+ crate::Receiver {
+ attrs: self.attrs.clone(),
+ reference: self.reference.clone(),
+ mutability: self.mutability.clone(),
+ self_token: self.self_token.clone(),
+ colon_token: self.colon_token.clone(),
+ ty: self.ty.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::ReturnType {
+ fn clone(&self) -> Self {
+ match self {
+ crate::ReturnType::Default => crate::ReturnType::Default,
+ crate::ReturnType::Type(v0, v1) => {
+ crate::ReturnType::Type(v0.clone(), v1.clone())
+ }
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::Signature {
+ fn clone(&self) -> Self {
+ crate::Signature {
+ constness: self.constness.clone(),
+ asyncness: self.asyncness.clone(),
+ unsafety: self.unsafety.clone(),
+ abi: self.abi.clone(),
+ fn_token: self.fn_token.clone(),
+ ident: self.ident.clone(),
+ generics: self.generics.clone(),
+ paren_token: self.paren_token.clone(),
+ inputs: self.inputs.clone(),
+ variadic: self.variadic.clone(),
+ output: self.output.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::StaticMutability {
+ fn clone(&self) -> Self {
+ match self {
+ crate::StaticMutability::Mut(v0) => crate::StaticMutability::Mut(v0.clone()),
+ crate::StaticMutability::None => crate::StaticMutability::None,
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::Stmt {
+ fn clone(&self) -> Self {
+ match self {
+ crate::Stmt::Local(v0) => crate::Stmt::Local(v0.clone()),
+ crate::Stmt::Item(v0) => crate::Stmt::Item(v0.clone()),
+ crate::Stmt::Expr(v0, v1) => crate::Stmt::Expr(v0.clone(), v1.clone()),
+ crate::Stmt::Macro(v0) => crate::Stmt::Macro(v0.clone()),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::StmtMacro {
+ fn clone(&self) -> Self {
+ crate::StmtMacro {
+ attrs: self.attrs.clone(),
+ mac: self.mac.clone(),
+ semi_token: self.semi_token.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::TraitBound {
+ fn clone(&self) -> Self {
+ crate::TraitBound {
+ paren_token: self.paren_token.clone(),
+ modifier: self.modifier.clone(),
+ lifetimes: self.lifetimes.clone(),
+ path: self.path.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Copy for crate::TraitBoundModifier {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::TraitBoundModifier {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::TraitItem {
+ fn clone(&self) -> Self {
+ match self {
+ crate::TraitItem::Const(v0) => crate::TraitItem::Const(v0.clone()),
+ crate::TraitItem::Fn(v0) => crate::TraitItem::Fn(v0.clone()),
+ crate::TraitItem::Type(v0) => crate::TraitItem::Type(v0.clone()),
+ crate::TraitItem::Macro(v0) => crate::TraitItem::Macro(v0.clone()),
+ crate::TraitItem::Verbatim(v0) => crate::TraitItem::Verbatim(v0.clone()),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::TraitItemConst {
+ fn clone(&self) -> Self {
+ crate::TraitItemConst {
+ attrs: self.attrs.clone(),
+ const_token: self.const_token.clone(),
+ ident: self.ident.clone(),
+ generics: self.generics.clone(),
+ colon_token: self.colon_token.clone(),
+ ty: self.ty.clone(),
+ default: self.default.clone(),
+ semi_token: self.semi_token.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::TraitItemFn {
+ fn clone(&self) -> Self {
+ crate::TraitItemFn {
+ attrs: self.attrs.clone(),
+ sig: self.sig.clone(),
+ default: self.default.clone(),
+ semi_token: self.semi_token.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::TraitItemMacro {
+ fn clone(&self) -> Self {
+ crate::TraitItemMacro {
+ attrs: self.attrs.clone(),
+ mac: self.mac.clone(),
+ semi_token: self.semi_token.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::TraitItemType {
+ fn clone(&self) -> Self {
+ crate::TraitItemType {
+ attrs: self.attrs.clone(),
+ type_token: self.type_token.clone(),
+ ident: self.ident.clone(),
+ generics: self.generics.clone(),
+ colon_token: self.colon_token.clone(),
+ bounds: self.bounds.clone(),
+ default: self.default.clone(),
+ semi_token: self.semi_token.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::Type {
+ fn clone(&self) -> Self {
+ match self {
+ crate::Type::Array(v0) => crate::Type::Array(v0.clone()),
+ crate::Type::BareFn(v0) => crate::Type::BareFn(v0.clone()),
+ crate::Type::Group(v0) => crate::Type::Group(v0.clone()),
+ crate::Type::ImplTrait(v0) => crate::Type::ImplTrait(v0.clone()),
+ crate::Type::Infer(v0) => crate::Type::Infer(v0.clone()),
+ crate::Type::Macro(v0) => crate::Type::Macro(v0.clone()),
+ crate::Type::Never(v0) => crate::Type::Never(v0.clone()),
+ crate::Type::Paren(v0) => crate::Type::Paren(v0.clone()),
+ crate::Type::Path(v0) => crate::Type::Path(v0.clone()),
+ crate::Type::Ptr(v0) => crate::Type::Ptr(v0.clone()),
+ crate::Type::Reference(v0) => crate::Type::Reference(v0.clone()),
+ crate::Type::Slice(v0) => crate::Type::Slice(v0.clone()),
+ crate::Type::TraitObject(v0) => crate::Type::TraitObject(v0.clone()),
+ crate::Type::Tuple(v0) => crate::Type::Tuple(v0.clone()),
+ crate::Type::Verbatim(v0) => crate::Type::Verbatim(v0.clone()),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::TypeArray {
+ fn clone(&self) -> Self {
+ crate::TypeArray {
+ bracket_token: self.bracket_token.clone(),
+ elem: self.elem.clone(),
+ semi_token: self.semi_token.clone(),
+ len: self.len.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::TypeBareFn {
+ fn clone(&self) -> Self {
+ crate::TypeBareFn {
+ lifetimes: self.lifetimes.clone(),
+ unsafety: self.unsafety.clone(),
+ abi: self.abi.clone(),
+ fn_token: self.fn_token.clone(),
+ paren_token: self.paren_token.clone(),
+ inputs: self.inputs.clone(),
+ variadic: self.variadic.clone(),
+ output: self.output.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::TypeGroup {
+ fn clone(&self) -> Self {
+ crate::TypeGroup {
+ group_token: self.group_token.clone(),
+ elem: self.elem.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::TypeImplTrait {
+ fn clone(&self) -> Self {
+ crate::TypeImplTrait {
+ impl_token: self.impl_token.clone(),
+ bounds: self.bounds.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::TypeInfer {
+ fn clone(&self) -> Self {
+ crate::TypeInfer {
+ underscore_token: self.underscore_token.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::TypeMacro {
+ fn clone(&self) -> Self {
+ crate::TypeMacro {
+ mac: self.mac.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::TypeNever {
+ fn clone(&self) -> Self {
+ crate::TypeNever {
+ bang_token: self.bang_token.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::TypeParam {
+ fn clone(&self) -> Self {
+ crate::TypeParam {
+ attrs: self.attrs.clone(),
+ ident: self.ident.clone(),
+ colon_token: self.colon_token.clone(),
+ bounds: self.bounds.clone(),
+ eq_token: self.eq_token.clone(),
+ default: self.default.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::TypeParamBound {
+ fn clone(&self) -> Self {
+ match self {
+ crate::TypeParamBound::Trait(v0) => crate::TypeParamBound::Trait(v0.clone()),
+ crate::TypeParamBound::Lifetime(v0) => {
+ crate::TypeParamBound::Lifetime(v0.clone())
+ }
+ #[cfg(feature = "full")]
+ crate::TypeParamBound::PreciseCapture(v0) => {
+ crate::TypeParamBound::PreciseCapture(v0.clone())
+ }
+ crate::TypeParamBound::Verbatim(v0) => {
+ crate::TypeParamBound::Verbatim(v0.clone())
+ }
+ #[cfg(not(feature = "full"))]
+ _ => unreachable!(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::TypeParen {
+ fn clone(&self) -> Self {
+ crate::TypeParen {
+ paren_token: self.paren_token.clone(),
+ elem: self.elem.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::TypePath {
+ fn clone(&self) -> Self {
+ crate::TypePath {
+ qself: self.qself.clone(),
+ path: self.path.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::TypePtr {
+ fn clone(&self) -> Self {
+ crate::TypePtr {
+ star_token: self.star_token.clone(),
+ const_token: self.const_token.clone(),
+ mutability: self.mutability.clone(),
+ elem: self.elem.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::TypeReference {
+ fn clone(&self) -> Self {
+ crate::TypeReference {
+ and_token: self.and_token.clone(),
+ lifetime: self.lifetime.clone(),
+ mutability: self.mutability.clone(),
+ elem: self.elem.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::TypeSlice {
+ fn clone(&self) -> Self {
+ crate::TypeSlice {
+ bracket_token: self.bracket_token.clone(),
+ elem: self.elem.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::TypeTraitObject {
+ fn clone(&self) -> Self {
+ crate::TypeTraitObject {
+ dyn_token: self.dyn_token.clone(),
+ bounds: self.bounds.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::TypeTuple {
+ fn clone(&self) -> Self {
+ crate::TypeTuple {
+ paren_token: self.paren_token.clone(),
+ elems: self.elems.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Copy for crate::UnOp {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::UnOp {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::UseGlob {
+ fn clone(&self) -> Self {
+ crate::UseGlob {
+ star_token: self.star_token.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::UseGroup {
+ fn clone(&self) -> Self {
+ crate::UseGroup {
+ brace_token: self.brace_token.clone(),
+ items: self.items.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::UseName {
+ fn clone(&self) -> Self {
+ crate::UseName {
+ ident: self.ident.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::UsePath {
+ fn clone(&self) -> Self {
+ crate::UsePath {
+ ident: self.ident.clone(),
+ colon2_token: self.colon2_token.clone(),
+ tree: self.tree.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::UseRename {
+ fn clone(&self) -> Self {
+ crate::UseRename {
+ ident: self.ident.clone(),
+ as_token: self.as_token.clone(),
+ rename: self.rename.clone(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::UseTree {
+ fn clone(&self) -> Self {
+ match self {
+ crate::UseTree::Path(v0) => crate::UseTree::Path(v0.clone()),
+ crate::UseTree::Name(v0) => crate::UseTree::Name(v0.clone()),
+ crate::UseTree::Rename(v0) => crate::UseTree::Rename(v0.clone()),
+ crate::UseTree::Glob(v0) => crate::UseTree::Glob(v0.clone()),
+ crate::UseTree::Group(v0) => crate::UseTree::Group(v0.clone()),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::Variadic {
+ fn clone(&self) -> Self {
+ crate::Variadic {
+ attrs: self.attrs.clone(),
+ pat: self.pat.clone(),
+ dots: self.dots.clone(),
+ comma: self.comma.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::Variant {
+ fn clone(&self) -> Self {
+ crate::Variant {
+ attrs: self.attrs.clone(),
+ ident: self.ident.clone(),
+ fields: self.fields.clone(),
+ discriminant: self.discriminant.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::VisRestricted {
+ fn clone(&self) -> Self {
+ crate::VisRestricted {
+ pub_token: self.pub_token.clone(),
+ paren_token: self.paren_token.clone(),
+ in_token: self.in_token.clone(),
+ path: self.path.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::Visibility {
+ fn clone(&self) -> Self {
+ match self {
+ crate::Visibility::Public(v0) => crate::Visibility::Public(v0.clone()),
+ crate::Visibility::Restricted(v0) => {
+ crate::Visibility::Restricted(v0.clone())
+ }
+ crate::Visibility::Inherited => crate::Visibility::Inherited,
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::WhereClause {
+ fn clone(&self) -> Self {
+ crate::WhereClause {
+ where_token: self.where_token.clone(),
+ predicates: self.predicates.clone(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for crate::WherePredicate {
+ fn clone(&self) -> Self {
+ match self {
+ crate::WherePredicate::Lifetime(v0) => {
+ crate::WherePredicate::Lifetime(v0.clone())
+ }
+ crate::WherePredicate::Type(v0) => crate::WherePredicate::Type(v0.clone()),
+ }
+ }
+}
diff --git a/rust/syn/gen/debug.rs b/rust/syn/gen/debug.rs
new file mode 100644
index 000000000000..aa42e32c60ed
--- /dev/null
+++ b/rust/syn/gen/debug.rs
@@ -0,0 +1,3238 @@
+// This file is @generated by syn-internal-codegen.
+// It is not intended for manual editing.
+
+#![allow(unknown_lints, non_local_definitions)]
+use std::fmt::{self, Debug};
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::Abi {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut formatter = formatter.debug_struct("Abi");
+ formatter.field("extern_token", &self.extern_token);
+ formatter.field("name", &self.name);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::AngleBracketedGenericArguments {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "AngleBracketedGenericArguments")
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl crate::AngleBracketedGenericArguments {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("colon2_token", &self.colon2_token);
+ formatter.field("lt_token", &self.lt_token);
+ formatter.field("args", &self.args);
+ formatter.field("gt_token", &self.gt_token);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::Arm {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut formatter = formatter.debug_struct("Arm");
+ formatter.field("attrs", &self.attrs);
+ formatter.field("pat", &self.pat);
+ formatter.field("guard", &self.guard);
+ formatter.field("fat_arrow_token", &self.fat_arrow_token);
+ formatter.field("body", &self.body);
+ formatter.field("comma", &self.comma);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::AssocConst {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut formatter = formatter.debug_struct("AssocConst");
+ formatter.field("ident", &self.ident);
+ formatter.field("generics", &self.generics);
+ formatter.field("eq_token", &self.eq_token);
+ formatter.field("value", &self.value);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::AssocType {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut formatter = formatter.debug_struct("AssocType");
+ formatter.field("ident", &self.ident);
+ formatter.field("generics", &self.generics);
+ formatter.field("eq_token", &self.eq_token);
+ formatter.field("ty", &self.ty);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::AttrStyle {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("AttrStyle::")?;
+ match self {
+ crate::AttrStyle::Outer => formatter.write_str("Outer"),
+ crate::AttrStyle::Inner(v0) => {
+ let mut formatter = formatter.debug_tuple("Inner");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::Attribute {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut formatter = formatter.debug_struct("Attribute");
+ formatter.field("pound_token", &self.pound_token);
+ formatter.field("style", &self.style);
+ formatter.field("bracket_token", &self.bracket_token);
+ formatter.field("meta", &self.meta);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::BareFnArg {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut formatter = formatter.debug_struct("BareFnArg");
+ formatter.field("attrs", &self.attrs);
+ formatter.field("name", &self.name);
+ formatter.field("ty", &self.ty);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::BareVariadic {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut formatter = formatter.debug_struct("BareVariadic");
+ formatter.field("attrs", &self.attrs);
+ formatter.field("name", &self.name);
+ formatter.field("dots", &self.dots);
+ formatter.field("comma", &self.comma);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::BinOp {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("BinOp::")?;
+ match self {
+ crate::BinOp::Add(v0) => {
+ let mut formatter = formatter.debug_tuple("Add");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::BinOp::Sub(v0) => {
+ let mut formatter = formatter.debug_tuple("Sub");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::BinOp::Mul(v0) => {
+ let mut formatter = formatter.debug_tuple("Mul");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::BinOp::Div(v0) => {
+ let mut formatter = formatter.debug_tuple("Div");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::BinOp::Rem(v0) => {
+ let mut formatter = formatter.debug_tuple("Rem");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::BinOp::And(v0) => {
+ let mut formatter = formatter.debug_tuple("And");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::BinOp::Or(v0) => {
+ let mut formatter = formatter.debug_tuple("Or");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::BinOp::BitXor(v0) => {
+ let mut formatter = formatter.debug_tuple("BitXor");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::BinOp::BitAnd(v0) => {
+ let mut formatter = formatter.debug_tuple("BitAnd");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::BinOp::BitOr(v0) => {
+ let mut formatter = formatter.debug_tuple("BitOr");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::BinOp::Shl(v0) => {
+ let mut formatter = formatter.debug_tuple("Shl");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::BinOp::Shr(v0) => {
+ let mut formatter = formatter.debug_tuple("Shr");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::BinOp::Eq(v0) => {
+ let mut formatter = formatter.debug_tuple("Eq");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::BinOp::Lt(v0) => {
+ let mut formatter = formatter.debug_tuple("Lt");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::BinOp::Le(v0) => {
+ let mut formatter = formatter.debug_tuple("Le");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::BinOp::Ne(v0) => {
+ let mut formatter = formatter.debug_tuple("Ne");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::BinOp::Ge(v0) => {
+ let mut formatter = formatter.debug_tuple("Ge");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::BinOp::Gt(v0) => {
+ let mut formatter = formatter.debug_tuple("Gt");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::BinOp::AddAssign(v0) => {
+ let mut formatter = formatter.debug_tuple("AddAssign");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::BinOp::SubAssign(v0) => {
+ let mut formatter = formatter.debug_tuple("SubAssign");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::BinOp::MulAssign(v0) => {
+ let mut formatter = formatter.debug_tuple("MulAssign");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::BinOp::DivAssign(v0) => {
+ let mut formatter = formatter.debug_tuple("DivAssign");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::BinOp::RemAssign(v0) => {
+ let mut formatter = formatter.debug_tuple("RemAssign");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::BinOp::BitXorAssign(v0) => {
+ let mut formatter = formatter.debug_tuple("BitXorAssign");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::BinOp::BitAndAssign(v0) => {
+ let mut formatter = formatter.debug_tuple("BitAndAssign");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::BinOp::BitOrAssign(v0) => {
+ let mut formatter = formatter.debug_tuple("BitOrAssign");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::BinOp::ShlAssign(v0) => {
+ let mut formatter = formatter.debug_tuple("ShlAssign");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::BinOp::ShrAssign(v0) => {
+ let mut formatter = formatter.debug_tuple("ShrAssign");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::Block {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut formatter = formatter.debug_struct("Block");
+ formatter.field("brace_token", &self.brace_token);
+ formatter.field("stmts", &self.stmts);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::BoundLifetimes {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut formatter = formatter.debug_struct("BoundLifetimes");
+ formatter.field("for_token", &self.for_token);
+ formatter.field("lt_token", &self.lt_token);
+ formatter.field("lifetimes", &self.lifetimes);
+ formatter.field("gt_token", &self.gt_token);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::CapturedParam {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("CapturedParam::")?;
+ match self {
+ crate::CapturedParam::Lifetime(v0) => {
+ let mut formatter = formatter.debug_tuple("Lifetime");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::CapturedParam::Ident(v0) => {
+ let mut formatter = formatter.debug_tuple("Ident");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ConstParam {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut formatter = formatter.debug_struct("ConstParam");
+ formatter.field("attrs", &self.attrs);
+ formatter.field("const_token", &self.const_token);
+ formatter.field("ident", &self.ident);
+ formatter.field("colon_token", &self.colon_token);
+ formatter.field("ty", &self.ty);
+ formatter.field("eq_token", &self.eq_token);
+ formatter.field("default", &self.default);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::Constraint {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut formatter = formatter.debug_struct("Constraint");
+ formatter.field("ident", &self.ident);
+ formatter.field("generics", &self.generics);
+ formatter.field("colon_token", &self.colon_token);
+ formatter.field("bounds", &self.bounds);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::Data {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("Data::")?;
+ match self {
+ crate::Data::Struct(v0) => v0.debug(formatter, "Struct"),
+ crate::Data::Enum(v0) => v0.debug(formatter, "Enum"),
+ crate::Data::Union(v0) => v0.debug(formatter, "Union"),
+ }
+ }
+}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::DataEnum {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "DataEnum")
+ }
+}
+#[cfg(feature = "derive")]
+impl crate::DataEnum {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("enum_token", &self.enum_token);
+ formatter.field("brace_token", &self.brace_token);
+ formatter.field("variants", &self.variants);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::DataStruct {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "DataStruct")
+ }
+}
+#[cfg(feature = "derive")]
+impl crate::DataStruct {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("struct_token", &self.struct_token);
+ formatter.field("fields", &self.fields);
+ formatter.field("semi_token", &self.semi_token);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::DataUnion {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "DataUnion")
+ }
+}
+#[cfg(feature = "derive")]
+impl crate::DataUnion {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("union_token", &self.union_token);
+ formatter.field("fields", &self.fields);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::DeriveInput {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut formatter = formatter.debug_struct("DeriveInput");
+ formatter.field("attrs", &self.attrs);
+ formatter.field("vis", &self.vis);
+ formatter.field("ident", &self.ident);
+ formatter.field("generics", &self.generics);
+ formatter.field("data", &self.data);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::Expr {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("Expr::")?;
+ match self {
+ #[cfg(feature = "full")]
+ crate::Expr::Array(v0) => v0.debug(formatter, "Array"),
+ #[cfg(feature = "full")]
+ crate::Expr::Assign(v0) => v0.debug(formatter, "Assign"),
+ #[cfg(feature = "full")]
+ crate::Expr::Async(v0) => v0.debug(formatter, "Async"),
+ #[cfg(feature = "full")]
+ crate::Expr::Await(v0) => v0.debug(formatter, "Await"),
+ crate::Expr::Binary(v0) => v0.debug(formatter, "Binary"),
+ #[cfg(feature = "full")]
+ crate::Expr::Block(v0) => v0.debug(formatter, "Block"),
+ #[cfg(feature = "full")]
+ crate::Expr::Break(v0) => v0.debug(formatter, "Break"),
+ crate::Expr::Call(v0) => v0.debug(formatter, "Call"),
+ crate::Expr::Cast(v0) => v0.debug(formatter, "Cast"),
+ #[cfg(feature = "full")]
+ crate::Expr::Closure(v0) => v0.debug(formatter, "Closure"),
+ #[cfg(feature = "full")]
+ crate::Expr::Const(v0) => v0.debug(formatter, "Const"),
+ #[cfg(feature = "full")]
+ crate::Expr::Continue(v0) => v0.debug(formatter, "Continue"),
+ crate::Expr::Field(v0) => v0.debug(formatter, "Field"),
+ #[cfg(feature = "full")]
+ crate::Expr::ForLoop(v0) => v0.debug(formatter, "ForLoop"),
+ crate::Expr::Group(v0) => v0.debug(formatter, "Group"),
+ #[cfg(feature = "full")]
+ crate::Expr::If(v0) => v0.debug(formatter, "If"),
+ crate::Expr::Index(v0) => v0.debug(formatter, "Index"),
+ #[cfg(feature = "full")]
+ crate::Expr::Infer(v0) => v0.debug(formatter, "Infer"),
+ #[cfg(feature = "full")]
+ crate::Expr::Let(v0) => v0.debug(formatter, "Let"),
+ crate::Expr::Lit(v0) => v0.debug(formatter, "Lit"),
+ #[cfg(feature = "full")]
+ crate::Expr::Loop(v0) => v0.debug(formatter, "Loop"),
+ crate::Expr::Macro(v0) => v0.debug(formatter, "Macro"),
+ #[cfg(feature = "full")]
+ crate::Expr::Match(v0) => v0.debug(formatter, "Match"),
+ crate::Expr::MethodCall(v0) => v0.debug(formatter, "MethodCall"),
+ crate::Expr::Paren(v0) => v0.debug(formatter, "Paren"),
+ crate::Expr::Path(v0) => v0.debug(formatter, "Path"),
+ #[cfg(feature = "full")]
+ crate::Expr::Range(v0) => v0.debug(formatter, "Range"),
+ #[cfg(feature = "full")]
+ crate::Expr::RawAddr(v0) => v0.debug(formatter, "RawAddr"),
+ crate::Expr::Reference(v0) => v0.debug(formatter, "Reference"),
+ #[cfg(feature = "full")]
+ crate::Expr::Repeat(v0) => v0.debug(formatter, "Repeat"),
+ #[cfg(feature = "full")]
+ crate::Expr::Return(v0) => v0.debug(formatter, "Return"),
+ crate::Expr::Struct(v0) => v0.debug(formatter, "Struct"),
+ #[cfg(feature = "full")]
+ crate::Expr::Try(v0) => v0.debug(formatter, "Try"),
+ #[cfg(feature = "full")]
+ crate::Expr::TryBlock(v0) => v0.debug(formatter, "TryBlock"),
+ crate::Expr::Tuple(v0) => v0.debug(formatter, "Tuple"),
+ crate::Expr::Unary(v0) => v0.debug(formatter, "Unary"),
+ #[cfg(feature = "full")]
+ crate::Expr::Unsafe(v0) => v0.debug(formatter, "Unsafe"),
+ crate::Expr::Verbatim(v0) => {
+ let mut formatter = formatter.debug_tuple("Verbatim");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ #[cfg(feature = "full")]
+ crate::Expr::While(v0) => v0.debug(formatter, "While"),
+ #[cfg(feature = "full")]
+ crate::Expr::Yield(v0) => v0.debug(formatter, "Yield"),
+ #[cfg(not(feature = "full"))]
+ _ => unreachable!(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ExprArray {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ExprArray")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ExprArray {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("bracket_token", &self.bracket_token);
+ formatter.field("elems", &self.elems);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ExprAssign {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ExprAssign")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ExprAssign {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("left", &self.left);
+ formatter.field("eq_token", &self.eq_token);
+ formatter.field("right", &self.right);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ExprAsync {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ExprAsync")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ExprAsync {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("async_token", &self.async_token);
+ formatter.field("capture", &self.capture);
+ formatter.field("block", &self.block);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ExprAwait {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ExprAwait")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ExprAwait {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("base", &self.base);
+ formatter.field("dot_token", &self.dot_token);
+ formatter.field("await_token", &self.await_token);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ExprBinary {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ExprBinary")
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl crate::ExprBinary {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("left", &self.left);
+ formatter.field("op", &self.op);
+ formatter.field("right", &self.right);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ExprBlock {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ExprBlock")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ExprBlock {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("label", &self.label);
+ formatter.field("block", &self.block);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ExprBreak {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ExprBreak")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ExprBreak {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("break_token", &self.break_token);
+ formatter.field("label", &self.label);
+ formatter.field("expr", &self.expr);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ExprCall {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ExprCall")
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl crate::ExprCall {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("func", &self.func);
+ formatter.field("paren_token", &self.paren_token);
+ formatter.field("args", &self.args);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ExprCast {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ExprCast")
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl crate::ExprCast {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("expr", &self.expr);
+ formatter.field("as_token", &self.as_token);
+ formatter.field("ty", &self.ty);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ExprClosure {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ExprClosure")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ExprClosure {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("lifetimes", &self.lifetimes);
+ formatter.field("constness", &self.constness);
+ formatter.field("movability", &self.movability);
+ formatter.field("asyncness", &self.asyncness);
+ formatter.field("capture", &self.capture);
+ formatter.field("or1_token", &self.or1_token);
+ formatter.field("inputs", &self.inputs);
+ formatter.field("or2_token", &self.or2_token);
+ formatter.field("output", &self.output);
+ formatter.field("body", &self.body);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ExprConst {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ExprConst")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ExprConst {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("const_token", &self.const_token);
+ formatter.field("block", &self.block);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ExprContinue {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ExprContinue")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ExprContinue {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("continue_token", &self.continue_token);
+ formatter.field("label", &self.label);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ExprField {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ExprField")
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl crate::ExprField {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("base", &self.base);
+ formatter.field("dot_token", &self.dot_token);
+ formatter.field("member", &self.member);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ExprForLoop {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ExprForLoop")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ExprForLoop {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("label", &self.label);
+ formatter.field("for_token", &self.for_token);
+ formatter.field("pat", &self.pat);
+ formatter.field("in_token", &self.in_token);
+ formatter.field("expr", &self.expr);
+ formatter.field("body", &self.body);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ExprGroup {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ExprGroup")
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl crate::ExprGroup {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("group_token", &self.group_token);
+ formatter.field("expr", &self.expr);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ExprIf {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ExprIf")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ExprIf {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("if_token", &self.if_token);
+ formatter.field("cond", &self.cond);
+ formatter.field("then_branch", &self.then_branch);
+ formatter.field("else_branch", &self.else_branch);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ExprIndex {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ExprIndex")
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl crate::ExprIndex {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("expr", &self.expr);
+ formatter.field("bracket_token", &self.bracket_token);
+ formatter.field("index", &self.index);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ExprInfer {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ExprInfer")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ExprInfer {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("underscore_token", &self.underscore_token);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ExprLet {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ExprLet")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ExprLet {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("let_token", &self.let_token);
+ formatter.field("pat", &self.pat);
+ formatter.field("eq_token", &self.eq_token);
+ formatter.field("expr", &self.expr);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ExprLit {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ExprLit")
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl crate::ExprLit {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("lit", &self.lit);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ExprLoop {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ExprLoop")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ExprLoop {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("label", &self.label);
+ formatter.field("loop_token", &self.loop_token);
+ formatter.field("body", &self.body);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ExprMacro {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ExprMacro")
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl crate::ExprMacro {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("mac", &self.mac);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ExprMatch {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ExprMatch")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ExprMatch {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("match_token", &self.match_token);
+ formatter.field("expr", &self.expr);
+ formatter.field("brace_token", &self.brace_token);
+ formatter.field("arms", &self.arms);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ExprMethodCall {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ExprMethodCall")
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl crate::ExprMethodCall {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("receiver", &self.receiver);
+ formatter.field("dot_token", &self.dot_token);
+ formatter.field("method", &self.method);
+ formatter.field("turbofish", &self.turbofish);
+ formatter.field("paren_token", &self.paren_token);
+ formatter.field("args", &self.args);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ExprParen {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ExprParen")
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl crate::ExprParen {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("paren_token", &self.paren_token);
+ formatter.field("expr", &self.expr);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ExprPath {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ExprPath")
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl crate::ExprPath {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("qself", &self.qself);
+ formatter.field("path", &self.path);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ExprRange {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ExprRange")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ExprRange {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("start", &self.start);
+ formatter.field("limits", &self.limits);
+ formatter.field("end", &self.end);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ExprRawAddr {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ExprRawAddr")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ExprRawAddr {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("and_token", &self.and_token);
+ formatter.field("raw", &self.raw);
+ formatter.field("mutability", &self.mutability);
+ formatter.field("expr", &self.expr);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ExprReference {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ExprReference")
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl crate::ExprReference {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("and_token", &self.and_token);
+ formatter.field("mutability", &self.mutability);
+ formatter.field("expr", &self.expr);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ExprRepeat {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ExprRepeat")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ExprRepeat {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("bracket_token", &self.bracket_token);
+ formatter.field("expr", &self.expr);
+ formatter.field("semi_token", &self.semi_token);
+ formatter.field("len", &self.len);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ExprReturn {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ExprReturn")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ExprReturn {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("return_token", &self.return_token);
+ formatter.field("expr", &self.expr);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ExprStruct {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ExprStruct")
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl crate::ExprStruct {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("qself", &self.qself);
+ formatter.field("path", &self.path);
+ formatter.field("brace_token", &self.brace_token);
+ formatter.field("fields", &self.fields);
+ formatter.field("dot2_token", &self.dot2_token);
+ formatter.field("rest", &self.rest);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ExprTry {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ExprTry")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ExprTry {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("expr", &self.expr);
+ formatter.field("question_token", &self.question_token);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ExprTryBlock {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ExprTryBlock")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ExprTryBlock {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("try_token", &self.try_token);
+ formatter.field("block", &self.block);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ExprTuple {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ExprTuple")
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl crate::ExprTuple {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("paren_token", &self.paren_token);
+ formatter.field("elems", &self.elems);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ExprUnary {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ExprUnary")
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl crate::ExprUnary {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("op", &self.op);
+ formatter.field("expr", &self.expr);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ExprUnsafe {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ExprUnsafe")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ExprUnsafe {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("unsafe_token", &self.unsafe_token);
+ formatter.field("block", &self.block);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ExprWhile {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ExprWhile")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ExprWhile {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("label", &self.label);
+ formatter.field("while_token", &self.while_token);
+ formatter.field("cond", &self.cond);
+ formatter.field("body", &self.body);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ExprYield {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ExprYield")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ExprYield {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("yield_token", &self.yield_token);
+ formatter.field("expr", &self.expr);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::Field {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut formatter = formatter.debug_struct("Field");
+ formatter.field("attrs", &self.attrs);
+ formatter.field("vis", &self.vis);
+ formatter.field("mutability", &self.mutability);
+ formatter.field("ident", &self.ident);
+ formatter.field("colon_token", &self.colon_token);
+ formatter.field("ty", &self.ty);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::FieldMutability {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("FieldMutability::")?;
+ match self {
+ crate::FieldMutability::None => formatter.write_str("None"),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::FieldPat {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut formatter = formatter.debug_struct("FieldPat");
+ formatter.field("attrs", &self.attrs);
+ formatter.field("member", &self.member);
+ formatter.field("colon_token", &self.colon_token);
+ formatter.field("pat", &self.pat);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::FieldValue {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut formatter = formatter.debug_struct("FieldValue");
+ formatter.field("attrs", &self.attrs);
+ formatter.field("member", &self.member);
+ formatter.field("colon_token", &self.colon_token);
+ formatter.field("expr", &self.expr);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::Fields {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("Fields::")?;
+ match self {
+ crate::Fields::Named(v0) => v0.debug(formatter, "Named"),
+ crate::Fields::Unnamed(v0) => v0.debug(formatter, "Unnamed"),
+ crate::Fields::Unit => formatter.write_str("Unit"),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::FieldsNamed {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "FieldsNamed")
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl crate::FieldsNamed {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("brace_token", &self.brace_token);
+ formatter.field("named", &self.named);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::FieldsUnnamed {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "FieldsUnnamed")
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl crate::FieldsUnnamed {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("paren_token", &self.paren_token);
+ formatter.field("unnamed", &self.unnamed);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::File {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut formatter = formatter.debug_struct("File");
+ formatter.field("shebang", &self.shebang);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("items", &self.items);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::FnArg {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("FnArg::")?;
+ match self {
+ crate::FnArg::Receiver(v0) => {
+ let mut formatter = formatter.debug_tuple("Receiver");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::FnArg::Typed(v0) => {
+ let mut formatter = formatter.debug_tuple("Typed");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ForeignItem {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("ForeignItem::")?;
+ match self {
+ crate::ForeignItem::Fn(v0) => v0.debug(formatter, "Fn"),
+ crate::ForeignItem::Static(v0) => v0.debug(formatter, "Static"),
+ crate::ForeignItem::Type(v0) => v0.debug(formatter, "Type"),
+ crate::ForeignItem::Macro(v0) => v0.debug(formatter, "Macro"),
+ crate::ForeignItem::Verbatim(v0) => {
+ let mut formatter = formatter.debug_tuple("Verbatim");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ForeignItemFn {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ForeignItemFn")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ForeignItemFn {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("vis", &self.vis);
+ formatter.field("sig", &self.sig);
+ formatter.field("semi_token", &self.semi_token);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ForeignItemMacro {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ForeignItemMacro")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ForeignItemMacro {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("mac", &self.mac);
+ formatter.field("semi_token", &self.semi_token);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ForeignItemStatic {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ForeignItemStatic")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ForeignItemStatic {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("vis", &self.vis);
+ formatter.field("static_token", &self.static_token);
+ formatter.field("mutability", &self.mutability);
+ formatter.field("ident", &self.ident);
+ formatter.field("colon_token", &self.colon_token);
+ formatter.field("ty", &self.ty);
+ formatter.field("semi_token", &self.semi_token);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ForeignItemType {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ForeignItemType")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ForeignItemType {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("vis", &self.vis);
+ formatter.field("type_token", &self.type_token);
+ formatter.field("ident", &self.ident);
+ formatter.field("generics", &self.generics);
+ formatter.field("semi_token", &self.semi_token);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::GenericArgument {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("GenericArgument::")?;
+ match self {
+ crate::GenericArgument::Lifetime(v0) => {
+ let mut formatter = formatter.debug_tuple("Lifetime");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::GenericArgument::Type(v0) => {
+ let mut formatter = formatter.debug_tuple("Type");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::GenericArgument::Const(v0) => {
+ let mut formatter = formatter.debug_tuple("Const");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::GenericArgument::AssocType(v0) => {
+ let mut formatter = formatter.debug_tuple("AssocType");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::GenericArgument::AssocConst(v0) => {
+ let mut formatter = formatter.debug_tuple("AssocConst");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::GenericArgument::Constraint(v0) => {
+ let mut formatter = formatter.debug_tuple("Constraint");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::GenericParam {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("GenericParam::")?;
+ match self {
+ crate::GenericParam::Lifetime(v0) => {
+ let mut formatter = formatter.debug_tuple("Lifetime");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::GenericParam::Type(v0) => {
+ let mut formatter = formatter.debug_tuple("Type");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::GenericParam::Const(v0) => {
+ let mut formatter = formatter.debug_tuple("Const");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::Generics {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut formatter = formatter.debug_struct("Generics");
+ formatter.field("lt_token", &self.lt_token);
+ formatter.field("params", &self.params);
+ formatter.field("gt_token", &self.gt_token);
+ formatter.field("where_clause", &self.where_clause);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ImplItem {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("ImplItem::")?;
+ match self {
+ crate::ImplItem::Const(v0) => v0.debug(formatter, "Const"),
+ crate::ImplItem::Fn(v0) => v0.debug(formatter, "Fn"),
+ crate::ImplItem::Type(v0) => v0.debug(formatter, "Type"),
+ crate::ImplItem::Macro(v0) => v0.debug(formatter, "Macro"),
+ crate::ImplItem::Verbatim(v0) => {
+ let mut formatter = formatter.debug_tuple("Verbatim");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ImplItemConst {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ImplItemConst")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ImplItemConst {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("vis", &self.vis);
+ formatter.field("defaultness", &self.defaultness);
+ formatter.field("const_token", &self.const_token);
+ formatter.field("ident", &self.ident);
+ formatter.field("generics", &self.generics);
+ formatter.field("colon_token", &self.colon_token);
+ formatter.field("ty", &self.ty);
+ formatter.field("eq_token", &self.eq_token);
+ formatter.field("expr", &self.expr);
+ formatter.field("semi_token", &self.semi_token);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ImplItemFn {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ImplItemFn")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ImplItemFn {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("vis", &self.vis);
+ formatter.field("defaultness", &self.defaultness);
+ formatter.field("sig", &self.sig);
+ formatter.field("block", &self.block);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ImplItemMacro {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ImplItemMacro")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ImplItemMacro {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("mac", &self.mac);
+ formatter.field("semi_token", &self.semi_token);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ImplItemType {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ImplItemType")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ImplItemType {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("vis", &self.vis);
+ formatter.field("defaultness", &self.defaultness);
+ formatter.field("type_token", &self.type_token);
+ formatter.field("ident", &self.ident);
+ formatter.field("generics", &self.generics);
+ formatter.field("eq_token", &self.eq_token);
+ formatter.field("ty", &self.ty);
+ formatter.field("semi_token", &self.semi_token);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ImplRestriction {
+ fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result {
+ match *self {}
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::Index {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut formatter = formatter.debug_struct("Index");
+ formatter.field("index", &self.index);
+ formatter.field("span", &self.span);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::Item {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("Item::")?;
+ match self {
+ crate::Item::Const(v0) => v0.debug(formatter, "Const"),
+ crate::Item::Enum(v0) => v0.debug(formatter, "Enum"),
+ crate::Item::ExternCrate(v0) => v0.debug(formatter, "ExternCrate"),
+ crate::Item::Fn(v0) => v0.debug(formatter, "Fn"),
+ crate::Item::ForeignMod(v0) => v0.debug(formatter, "ForeignMod"),
+ crate::Item::Impl(v0) => v0.debug(formatter, "Impl"),
+ crate::Item::Macro(v0) => v0.debug(formatter, "Macro"),
+ crate::Item::Mod(v0) => v0.debug(formatter, "Mod"),
+ crate::Item::Static(v0) => v0.debug(formatter, "Static"),
+ crate::Item::Struct(v0) => v0.debug(formatter, "Struct"),
+ crate::Item::Trait(v0) => v0.debug(formatter, "Trait"),
+ crate::Item::TraitAlias(v0) => v0.debug(formatter, "TraitAlias"),
+ crate::Item::Type(v0) => v0.debug(formatter, "Type"),
+ crate::Item::Union(v0) => v0.debug(formatter, "Union"),
+ crate::Item::Use(v0) => v0.debug(formatter, "Use"),
+ crate::Item::Verbatim(v0) => {
+ let mut formatter = formatter.debug_tuple("Verbatim");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ItemConst {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ItemConst")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ItemConst {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("vis", &self.vis);
+ formatter.field("const_token", &self.const_token);
+ formatter.field("ident", &self.ident);
+ formatter.field("generics", &self.generics);
+ formatter.field("colon_token", &self.colon_token);
+ formatter.field("ty", &self.ty);
+ formatter.field("eq_token", &self.eq_token);
+ formatter.field("expr", &self.expr);
+ formatter.field("semi_token", &self.semi_token);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ItemEnum {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ItemEnum")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ItemEnum {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("vis", &self.vis);
+ formatter.field("enum_token", &self.enum_token);
+ formatter.field("ident", &self.ident);
+ formatter.field("generics", &self.generics);
+ formatter.field("brace_token", &self.brace_token);
+ formatter.field("variants", &self.variants);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ItemExternCrate {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ItemExternCrate")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ItemExternCrate {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("vis", &self.vis);
+ formatter.field("extern_token", &self.extern_token);
+ formatter.field("crate_token", &self.crate_token);
+ formatter.field("ident", &self.ident);
+ formatter.field("rename", &self.rename);
+ formatter.field("semi_token", &self.semi_token);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ItemFn {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ItemFn")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ItemFn {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("vis", &self.vis);
+ formatter.field("sig", &self.sig);
+ formatter.field("block", &self.block);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ItemForeignMod {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ItemForeignMod")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ItemForeignMod {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("unsafety", &self.unsafety);
+ formatter.field("abi", &self.abi);
+ formatter.field("brace_token", &self.brace_token);
+ formatter.field("items", &self.items);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ItemImpl {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ItemImpl")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ItemImpl {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("defaultness", &self.defaultness);
+ formatter.field("unsafety", &self.unsafety);
+ formatter.field("impl_token", &self.impl_token);
+ formatter.field("generics", &self.generics);
+ formatter.field("trait_", &self.trait_);
+ formatter.field("self_ty", &self.self_ty);
+ formatter.field("brace_token", &self.brace_token);
+ formatter.field("items", &self.items);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ItemMacro {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ItemMacro")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ItemMacro {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("ident", &self.ident);
+ formatter.field("mac", &self.mac);
+ formatter.field("semi_token", &self.semi_token);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ItemMod {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ItemMod")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ItemMod {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("vis", &self.vis);
+ formatter.field("unsafety", &self.unsafety);
+ formatter.field("mod_token", &self.mod_token);
+ formatter.field("ident", &self.ident);
+ formatter.field("content", &self.content);
+ formatter.field("semi", &self.semi);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ItemStatic {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ItemStatic")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ItemStatic {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("vis", &self.vis);
+ formatter.field("static_token", &self.static_token);
+ formatter.field("mutability", &self.mutability);
+ formatter.field("ident", &self.ident);
+ formatter.field("colon_token", &self.colon_token);
+ formatter.field("ty", &self.ty);
+ formatter.field("eq_token", &self.eq_token);
+ formatter.field("expr", &self.expr);
+ formatter.field("semi_token", &self.semi_token);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ItemStruct {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ItemStruct")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ItemStruct {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("vis", &self.vis);
+ formatter.field("struct_token", &self.struct_token);
+ formatter.field("ident", &self.ident);
+ formatter.field("generics", &self.generics);
+ formatter.field("fields", &self.fields);
+ formatter.field("semi_token", &self.semi_token);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ItemTrait {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ItemTrait")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ItemTrait {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("vis", &self.vis);
+ formatter.field("unsafety", &self.unsafety);
+ formatter.field("auto_token", &self.auto_token);
+ formatter.field("restriction", &self.restriction);
+ formatter.field("trait_token", &self.trait_token);
+ formatter.field("ident", &self.ident);
+ formatter.field("generics", &self.generics);
+ formatter.field("colon_token", &self.colon_token);
+ formatter.field("supertraits", &self.supertraits);
+ formatter.field("brace_token", &self.brace_token);
+ formatter.field("items", &self.items);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ItemTraitAlias {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ItemTraitAlias")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ItemTraitAlias {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("vis", &self.vis);
+ formatter.field("trait_token", &self.trait_token);
+ formatter.field("ident", &self.ident);
+ formatter.field("generics", &self.generics);
+ formatter.field("eq_token", &self.eq_token);
+ formatter.field("bounds", &self.bounds);
+ formatter.field("semi_token", &self.semi_token);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ItemType {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ItemType")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ItemType {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("vis", &self.vis);
+ formatter.field("type_token", &self.type_token);
+ formatter.field("ident", &self.ident);
+ formatter.field("generics", &self.generics);
+ formatter.field("eq_token", &self.eq_token);
+ formatter.field("ty", &self.ty);
+ formatter.field("semi_token", &self.semi_token);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ItemUnion {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ItemUnion")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ItemUnion {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("vis", &self.vis);
+ formatter.field("union_token", &self.union_token);
+ formatter.field("ident", &self.ident);
+ formatter.field("generics", &self.generics);
+ formatter.field("fields", &self.fields);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ItemUse {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ItemUse")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::ItemUse {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("vis", &self.vis);
+ formatter.field("use_token", &self.use_token);
+ formatter.field("leading_colon", &self.leading_colon);
+ formatter.field("tree", &self.tree);
+ formatter.field("semi_token", &self.semi_token);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::Label {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut formatter = formatter.debug_struct("Label");
+ formatter.field("name", &self.name);
+ formatter.field("colon_token", &self.colon_token);
+ formatter.finish()
+ }
+}
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::Lifetime {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "Lifetime")
+ }
+}
+impl crate::Lifetime {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("apostrophe", &self.apostrophe);
+ formatter.field("ident", &self.ident);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::LifetimeParam {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut formatter = formatter.debug_struct("LifetimeParam");
+ formatter.field("attrs", &self.attrs);
+ formatter.field("lifetime", &self.lifetime);
+ formatter.field("colon_token", &self.colon_token);
+ formatter.field("bounds", &self.bounds);
+ formatter.finish()
+ }
+}
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::Lit {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("Lit::")?;
+ match self {
+ crate::Lit::Str(v0) => v0.debug(formatter, "Str"),
+ crate::Lit::ByteStr(v0) => v0.debug(formatter, "ByteStr"),
+ crate::Lit::CStr(v0) => v0.debug(formatter, "CStr"),
+ crate::Lit::Byte(v0) => v0.debug(formatter, "Byte"),
+ crate::Lit::Char(v0) => v0.debug(formatter, "Char"),
+ crate::Lit::Int(v0) => v0.debug(formatter, "Int"),
+ crate::Lit::Float(v0) => v0.debug(formatter, "Float"),
+ crate::Lit::Bool(v0) => v0.debug(formatter, "Bool"),
+ crate::Lit::Verbatim(v0) => {
+ let mut formatter = formatter.debug_tuple("Verbatim");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::Local {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "Local")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::Local {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("let_token", &self.let_token);
+ formatter.field("pat", &self.pat);
+ formatter.field("init", &self.init);
+ formatter.field("semi_token", &self.semi_token);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::LocalInit {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut formatter = formatter.debug_struct("LocalInit");
+ formatter.field("eq_token", &self.eq_token);
+ formatter.field("expr", &self.expr);
+ formatter.field("diverge", &self.diverge);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::Macro {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut formatter = formatter.debug_struct("Macro");
+ formatter.field("path", &self.path);
+ formatter.field("bang_token", &self.bang_token);
+ formatter.field("delimiter", &self.delimiter);
+ formatter.field("tokens", &self.tokens);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::MacroDelimiter {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("MacroDelimiter::")?;
+ match self {
+ crate::MacroDelimiter::Paren(v0) => {
+ let mut formatter = formatter.debug_tuple("Paren");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::MacroDelimiter::Brace(v0) => {
+ let mut formatter = formatter.debug_tuple("Brace");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::MacroDelimiter::Bracket(v0) => {
+ let mut formatter = formatter.debug_tuple("Bracket");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::Member {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("Member::")?;
+ match self {
+ crate::Member::Named(v0) => {
+ let mut formatter = formatter.debug_tuple("Named");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::Member::Unnamed(v0) => {
+ let mut formatter = formatter.debug_tuple("Unnamed");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::Meta {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("Meta::")?;
+ match self {
+ crate::Meta::Path(v0) => v0.debug(formatter, "Path"),
+ crate::Meta::List(v0) => v0.debug(formatter, "List"),
+ crate::Meta::NameValue(v0) => v0.debug(formatter, "NameValue"),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::MetaList {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "MetaList")
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl crate::MetaList {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("path", &self.path);
+ formatter.field("delimiter", &self.delimiter);
+ formatter.field("tokens", &self.tokens);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::MetaNameValue {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "MetaNameValue")
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl crate::MetaNameValue {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("path", &self.path);
+ formatter.field("eq_token", &self.eq_token);
+ formatter.field("value", &self.value);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ParenthesizedGenericArguments {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "ParenthesizedGenericArguments")
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl crate::ParenthesizedGenericArguments {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("paren_token", &self.paren_token);
+ formatter.field("inputs", &self.inputs);
+ formatter.field("output", &self.output);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::Pat {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("Pat::")?;
+ match self {
+ crate::Pat::Const(v0) => v0.debug(formatter, "Const"),
+ crate::Pat::Ident(v0) => v0.debug(formatter, "Ident"),
+ crate::Pat::Lit(v0) => v0.debug(formatter, "Lit"),
+ crate::Pat::Macro(v0) => v0.debug(formatter, "Macro"),
+ crate::Pat::Or(v0) => v0.debug(formatter, "Or"),
+ crate::Pat::Paren(v0) => v0.debug(formatter, "Paren"),
+ crate::Pat::Path(v0) => v0.debug(formatter, "Path"),
+ crate::Pat::Range(v0) => v0.debug(formatter, "Range"),
+ crate::Pat::Reference(v0) => v0.debug(formatter, "Reference"),
+ crate::Pat::Rest(v0) => v0.debug(formatter, "Rest"),
+ crate::Pat::Slice(v0) => v0.debug(formatter, "Slice"),
+ crate::Pat::Struct(v0) => v0.debug(formatter, "Struct"),
+ crate::Pat::Tuple(v0) => v0.debug(formatter, "Tuple"),
+ crate::Pat::TupleStruct(v0) => v0.debug(formatter, "TupleStruct"),
+ crate::Pat::Type(v0) => v0.debug(formatter, "Type"),
+ crate::Pat::Verbatim(v0) => {
+ let mut formatter = formatter.debug_tuple("Verbatim");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::Pat::Wild(v0) => v0.debug(formatter, "Wild"),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::PatIdent {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "PatIdent")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::PatIdent {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("by_ref", &self.by_ref);
+ formatter.field("mutability", &self.mutability);
+ formatter.field("ident", &self.ident);
+ formatter.field("subpat", &self.subpat);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::PatOr {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "PatOr")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::PatOr {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("leading_vert", &self.leading_vert);
+ formatter.field("cases", &self.cases);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::PatParen {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "PatParen")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::PatParen {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("paren_token", &self.paren_token);
+ formatter.field("pat", &self.pat);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::PatReference {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "PatReference")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::PatReference {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("and_token", &self.and_token);
+ formatter.field("mutability", &self.mutability);
+ formatter.field("pat", &self.pat);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::PatRest {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "PatRest")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::PatRest {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("dot2_token", &self.dot2_token);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::PatSlice {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "PatSlice")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::PatSlice {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("bracket_token", &self.bracket_token);
+ formatter.field("elems", &self.elems);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::PatStruct {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "PatStruct")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::PatStruct {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("qself", &self.qself);
+ formatter.field("path", &self.path);
+ formatter.field("brace_token", &self.brace_token);
+ formatter.field("fields", &self.fields);
+ formatter.field("rest", &self.rest);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::PatTuple {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "PatTuple")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::PatTuple {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("paren_token", &self.paren_token);
+ formatter.field("elems", &self.elems);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::PatTupleStruct {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "PatTupleStruct")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::PatTupleStruct {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("qself", &self.qself);
+ formatter.field("path", &self.path);
+ formatter.field("paren_token", &self.paren_token);
+ formatter.field("elems", &self.elems);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::PatType {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "PatType")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::PatType {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("pat", &self.pat);
+ formatter.field("colon_token", &self.colon_token);
+ formatter.field("ty", &self.ty);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::PatWild {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "PatWild")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::PatWild {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("underscore_token", &self.underscore_token);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::Path {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "Path")
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl crate::Path {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("leading_colon", &self.leading_colon);
+ formatter.field("segments", &self.segments);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::PathArguments {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("PathArguments::")?;
+ match self {
+ crate::PathArguments::None => formatter.write_str("None"),
+ crate::PathArguments::AngleBracketed(v0) => {
+ v0.debug(formatter, "AngleBracketed")
+ }
+ crate::PathArguments::Parenthesized(v0) => {
+ v0.debug(formatter, "Parenthesized")
+ }
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::PathSegment {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut formatter = formatter.debug_struct("PathSegment");
+ formatter.field("ident", &self.ident);
+ formatter.field("arguments", &self.arguments);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::PointerMutability {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("PointerMutability::")?;
+ match self {
+ crate::PointerMutability::Const(v0) => {
+ let mut formatter = formatter.debug_tuple("Const");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::PointerMutability::Mut(v0) => {
+ let mut formatter = formatter.debug_tuple("Mut");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::PreciseCapture {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut formatter = formatter.debug_struct("PreciseCapture");
+ formatter.field("use_token", &self.use_token);
+ formatter.field("lt_token", &self.lt_token);
+ formatter.field("params", &self.params);
+ formatter.field("gt_token", &self.gt_token);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::PredicateLifetime {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut formatter = formatter.debug_struct("PredicateLifetime");
+ formatter.field("lifetime", &self.lifetime);
+ formatter.field("colon_token", &self.colon_token);
+ formatter.field("bounds", &self.bounds);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::PredicateType {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut formatter = formatter.debug_struct("PredicateType");
+ formatter.field("lifetimes", &self.lifetimes);
+ formatter.field("bounded_ty", &self.bounded_ty);
+ formatter.field("colon_token", &self.colon_token);
+ formatter.field("bounds", &self.bounds);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::QSelf {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut formatter = formatter.debug_struct("QSelf");
+ formatter.field("lt_token", &self.lt_token);
+ formatter.field("ty", &self.ty);
+ formatter.field("position", &self.position);
+ formatter.field("as_token", &self.as_token);
+ formatter.field("gt_token", &self.gt_token);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::RangeLimits {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("RangeLimits::")?;
+ match self {
+ crate::RangeLimits::HalfOpen(v0) => {
+ let mut formatter = formatter.debug_tuple("HalfOpen");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::RangeLimits::Closed(v0) => {
+ let mut formatter = formatter.debug_tuple("Closed");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::Receiver {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut formatter = formatter.debug_struct("Receiver");
+ formatter.field("attrs", &self.attrs);
+ formatter.field("reference", &self.reference);
+ formatter.field("mutability", &self.mutability);
+ formatter.field("self_token", &self.self_token);
+ formatter.field("colon_token", &self.colon_token);
+ formatter.field("ty", &self.ty);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::ReturnType {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("ReturnType::")?;
+ match self {
+ crate::ReturnType::Default => formatter.write_str("Default"),
+ crate::ReturnType::Type(v0, v1) => {
+ let mut formatter = formatter.debug_tuple("Type");
+ formatter.field(v0);
+ formatter.field(v1);
+ formatter.finish()
+ }
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::Signature {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut formatter = formatter.debug_struct("Signature");
+ formatter.field("constness", &self.constness);
+ formatter.field("asyncness", &self.asyncness);
+ formatter.field("unsafety", &self.unsafety);
+ formatter.field("abi", &self.abi);
+ formatter.field("fn_token", &self.fn_token);
+ formatter.field("ident", &self.ident);
+ formatter.field("generics", &self.generics);
+ formatter.field("paren_token", &self.paren_token);
+ formatter.field("inputs", &self.inputs);
+ formatter.field("variadic", &self.variadic);
+ formatter.field("output", &self.output);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::StaticMutability {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("StaticMutability::")?;
+ match self {
+ crate::StaticMutability::Mut(v0) => {
+ let mut formatter = formatter.debug_tuple("Mut");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::StaticMutability::None => formatter.write_str("None"),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::Stmt {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("Stmt::")?;
+ match self {
+ crate::Stmt::Local(v0) => v0.debug(formatter, "Local"),
+ crate::Stmt::Item(v0) => {
+ let mut formatter = formatter.debug_tuple("Item");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::Stmt::Expr(v0, v1) => {
+ let mut formatter = formatter.debug_tuple("Expr");
+ formatter.field(v0);
+ formatter.field(v1);
+ formatter.finish()
+ }
+ crate::Stmt::Macro(v0) => v0.debug(formatter, "Macro"),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::StmtMacro {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "StmtMacro")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::StmtMacro {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("mac", &self.mac);
+ formatter.field("semi_token", &self.semi_token);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::TraitBound {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut formatter = formatter.debug_struct("TraitBound");
+ formatter.field("paren_token", &self.paren_token);
+ formatter.field("modifier", &self.modifier);
+ formatter.field("lifetimes", &self.lifetimes);
+ formatter.field("path", &self.path);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::TraitBoundModifier {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("TraitBoundModifier::")?;
+ match self {
+ crate::TraitBoundModifier::None => formatter.write_str("None"),
+ crate::TraitBoundModifier::Maybe(v0) => {
+ let mut formatter = formatter.debug_tuple("Maybe");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::TraitItem {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("TraitItem::")?;
+ match self {
+ crate::TraitItem::Const(v0) => v0.debug(formatter, "Const"),
+ crate::TraitItem::Fn(v0) => v0.debug(formatter, "Fn"),
+ crate::TraitItem::Type(v0) => v0.debug(formatter, "Type"),
+ crate::TraitItem::Macro(v0) => v0.debug(formatter, "Macro"),
+ crate::TraitItem::Verbatim(v0) => {
+ let mut formatter = formatter.debug_tuple("Verbatim");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::TraitItemConst {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "TraitItemConst")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::TraitItemConst {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("const_token", &self.const_token);
+ formatter.field("ident", &self.ident);
+ formatter.field("generics", &self.generics);
+ formatter.field("colon_token", &self.colon_token);
+ formatter.field("ty", &self.ty);
+ formatter.field("default", &self.default);
+ formatter.field("semi_token", &self.semi_token);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::TraitItemFn {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "TraitItemFn")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::TraitItemFn {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("sig", &self.sig);
+ formatter.field("default", &self.default);
+ formatter.field("semi_token", &self.semi_token);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::TraitItemMacro {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "TraitItemMacro")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::TraitItemMacro {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("mac", &self.mac);
+ formatter.field("semi_token", &self.semi_token);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::TraitItemType {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "TraitItemType")
+ }
+}
+#[cfg(feature = "full")]
+impl crate::TraitItemType {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("attrs", &self.attrs);
+ formatter.field("type_token", &self.type_token);
+ formatter.field("ident", &self.ident);
+ formatter.field("generics", &self.generics);
+ formatter.field("colon_token", &self.colon_token);
+ formatter.field("bounds", &self.bounds);
+ formatter.field("default", &self.default);
+ formatter.field("semi_token", &self.semi_token);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::Type {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("Type::")?;
+ match self {
+ crate::Type::Array(v0) => v0.debug(formatter, "Array"),
+ crate::Type::BareFn(v0) => v0.debug(formatter, "BareFn"),
+ crate::Type::Group(v0) => v0.debug(formatter, "Group"),
+ crate::Type::ImplTrait(v0) => v0.debug(formatter, "ImplTrait"),
+ crate::Type::Infer(v0) => v0.debug(formatter, "Infer"),
+ crate::Type::Macro(v0) => v0.debug(formatter, "Macro"),
+ crate::Type::Never(v0) => v0.debug(formatter, "Never"),
+ crate::Type::Paren(v0) => v0.debug(formatter, "Paren"),
+ crate::Type::Path(v0) => v0.debug(formatter, "Path"),
+ crate::Type::Ptr(v0) => v0.debug(formatter, "Ptr"),
+ crate::Type::Reference(v0) => v0.debug(formatter, "Reference"),
+ crate::Type::Slice(v0) => v0.debug(formatter, "Slice"),
+ crate::Type::TraitObject(v0) => v0.debug(formatter, "TraitObject"),
+ crate::Type::Tuple(v0) => v0.debug(formatter, "Tuple"),
+ crate::Type::Verbatim(v0) => {
+ let mut formatter = formatter.debug_tuple("Verbatim");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::TypeArray {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "TypeArray")
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl crate::TypeArray {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("bracket_token", &self.bracket_token);
+ formatter.field("elem", &self.elem);
+ formatter.field("semi_token", &self.semi_token);
+ formatter.field("len", &self.len);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::TypeBareFn {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "TypeBareFn")
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl crate::TypeBareFn {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("lifetimes", &self.lifetimes);
+ formatter.field("unsafety", &self.unsafety);
+ formatter.field("abi", &self.abi);
+ formatter.field("fn_token", &self.fn_token);
+ formatter.field("paren_token", &self.paren_token);
+ formatter.field("inputs", &self.inputs);
+ formatter.field("variadic", &self.variadic);
+ formatter.field("output", &self.output);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::TypeGroup {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "TypeGroup")
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl crate::TypeGroup {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("group_token", &self.group_token);
+ formatter.field("elem", &self.elem);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::TypeImplTrait {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "TypeImplTrait")
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl crate::TypeImplTrait {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("impl_token", &self.impl_token);
+ formatter.field("bounds", &self.bounds);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::TypeInfer {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "TypeInfer")
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl crate::TypeInfer {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("underscore_token", &self.underscore_token);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::TypeMacro {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "TypeMacro")
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl crate::TypeMacro {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("mac", &self.mac);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::TypeNever {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "TypeNever")
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl crate::TypeNever {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("bang_token", &self.bang_token);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::TypeParam {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut formatter = formatter.debug_struct("TypeParam");
+ formatter.field("attrs", &self.attrs);
+ formatter.field("ident", &self.ident);
+ formatter.field("colon_token", &self.colon_token);
+ formatter.field("bounds", &self.bounds);
+ formatter.field("eq_token", &self.eq_token);
+ formatter.field("default", &self.default);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::TypeParamBound {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("TypeParamBound::")?;
+ match self {
+ crate::TypeParamBound::Trait(v0) => {
+ let mut formatter = formatter.debug_tuple("Trait");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::TypeParamBound::Lifetime(v0) => v0.debug(formatter, "Lifetime"),
+ #[cfg(feature = "full")]
+ crate::TypeParamBound::PreciseCapture(v0) => {
+ let mut formatter = formatter.debug_tuple("PreciseCapture");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::TypeParamBound::Verbatim(v0) => {
+ let mut formatter = formatter.debug_tuple("Verbatim");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ #[cfg(not(feature = "full"))]
+ _ => unreachable!(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::TypeParen {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "TypeParen")
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl crate::TypeParen {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("paren_token", &self.paren_token);
+ formatter.field("elem", &self.elem);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::TypePath {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "TypePath")
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl crate::TypePath {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("qself", &self.qself);
+ formatter.field("path", &self.path);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::TypePtr {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "TypePtr")
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl crate::TypePtr {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("star_token", &self.star_token);
+ formatter.field("const_token", &self.const_token);
+ formatter.field("mutability", &self.mutability);
+ formatter.field("elem", &self.elem);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::TypeReference {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "TypeReference")
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl crate::TypeReference {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("and_token", &self.and_token);
+ formatter.field("lifetime", &self.lifetime);
+ formatter.field("mutability", &self.mutability);
+ formatter.field("elem", &self.elem);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::TypeSlice {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "TypeSlice")
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl crate::TypeSlice {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("bracket_token", &self.bracket_token);
+ formatter.field("elem", &self.elem);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::TypeTraitObject {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "TypeTraitObject")
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl crate::TypeTraitObject {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("dyn_token", &self.dyn_token);
+ formatter.field("bounds", &self.bounds);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::TypeTuple {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "TypeTuple")
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl crate::TypeTuple {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("paren_token", &self.paren_token);
+ formatter.field("elems", &self.elems);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::UnOp {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("UnOp::")?;
+ match self {
+ crate::UnOp::Deref(v0) => {
+ let mut formatter = formatter.debug_tuple("Deref");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::UnOp::Not(v0) => {
+ let mut formatter = formatter.debug_tuple("Not");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::UnOp::Neg(v0) => {
+ let mut formatter = formatter.debug_tuple("Neg");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::UseGlob {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut formatter = formatter.debug_struct("UseGlob");
+ formatter.field("star_token", &self.star_token);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::UseGroup {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut formatter = formatter.debug_struct("UseGroup");
+ formatter.field("brace_token", &self.brace_token);
+ formatter.field("items", &self.items);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::UseName {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut formatter = formatter.debug_struct("UseName");
+ formatter.field("ident", &self.ident);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::UsePath {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut formatter = formatter.debug_struct("UsePath");
+ formatter.field("ident", &self.ident);
+ formatter.field("colon2_token", &self.colon2_token);
+ formatter.field("tree", &self.tree);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::UseRename {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut formatter = formatter.debug_struct("UseRename");
+ formatter.field("ident", &self.ident);
+ formatter.field("as_token", &self.as_token);
+ formatter.field("rename", &self.rename);
+ formatter.finish()
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::UseTree {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("UseTree::")?;
+ match self {
+ crate::UseTree::Path(v0) => {
+ let mut formatter = formatter.debug_tuple("Path");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::UseTree::Name(v0) => {
+ let mut formatter = formatter.debug_tuple("Name");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::UseTree::Rename(v0) => {
+ let mut formatter = formatter.debug_tuple("Rename");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::UseTree::Glob(v0) => {
+ let mut formatter = formatter.debug_tuple("Glob");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::UseTree::Group(v0) => {
+ let mut formatter = formatter.debug_tuple("Group");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::Variadic {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut formatter = formatter.debug_struct("Variadic");
+ formatter.field("attrs", &self.attrs);
+ formatter.field("pat", &self.pat);
+ formatter.field("dots", &self.dots);
+ formatter.field("comma", &self.comma);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::Variant {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut formatter = formatter.debug_struct("Variant");
+ formatter.field("attrs", &self.attrs);
+ formatter.field("ident", &self.ident);
+ formatter.field("fields", &self.fields);
+ formatter.field("discriminant", &self.discriminant);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::VisRestricted {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "VisRestricted")
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+impl crate::VisRestricted {
+ fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ let mut formatter = formatter.debug_struct(name);
+ formatter.field("pub_token", &self.pub_token);
+ formatter.field("paren_token", &self.paren_token);
+ formatter.field("in_token", &self.in_token);
+ formatter.field("path", &self.path);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::Visibility {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("Visibility::")?;
+ match self {
+ crate::Visibility::Public(v0) => {
+ let mut formatter = formatter.debug_tuple("Public");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::Visibility::Restricted(v0) => v0.debug(formatter, "Restricted"),
+ crate::Visibility::Inherited => formatter.write_str("Inherited"),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::WhereClause {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut formatter = formatter.debug_struct("WhereClause");
+ formatter.field("where_token", &self.where_token);
+ formatter.field("predicates", &self.predicates);
+ formatter.finish()
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for crate::WherePredicate {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("WherePredicate::")?;
+ match self {
+ crate::WherePredicate::Lifetime(v0) => {
+ let mut formatter = formatter.debug_tuple("Lifetime");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ crate::WherePredicate::Type(v0) => {
+ let mut formatter = formatter.debug_tuple("Type");
+ formatter.field(v0);
+ formatter.finish()
+ }
+ }
+ }
+}
diff --git a/rust/syn/gen/eq.rs b/rust/syn/gen/eq.rs
new file mode 100644
index 000000000000..128e8991eecc
--- /dev/null
+++ b/rust/syn/gen/eq.rs
@@ -0,0 +1,2306 @@
+// This file is @generated by syn-internal-codegen.
+// It is not intended for manual editing.
+
+#[cfg(any(feature = "derive", feature = "full"))]
+use crate::tt::TokenStreamHelper;
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::Abi {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::Abi {
+ fn eq(&self, other: &Self) -> bool {
+ self.name == other.name
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::AngleBracketedGenericArguments {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::AngleBracketedGenericArguments {
+ fn eq(&self, other: &Self) -> bool {
+ self.colon2_token == other.colon2_token && self.args == other.args
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::Arm {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::Arm {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.pat == other.pat && self.guard == other.guard
+ && self.body == other.body && self.comma == other.comma
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::AssocConst {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::AssocConst {
+ fn eq(&self, other: &Self) -> bool {
+ self.ident == other.ident && self.generics == other.generics
+ && self.value == other.value
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::AssocType {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::AssocType {
+ fn eq(&self, other: &Self) -> bool {
+ self.ident == other.ident && self.generics == other.generics
+ && self.ty == other.ty
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::AttrStyle {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::AttrStyle {
+ fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ (crate::AttrStyle::Outer, crate::AttrStyle::Outer) => true,
+ (crate::AttrStyle::Inner(_), crate::AttrStyle::Inner(_)) => true,
+ _ => false,
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::Attribute {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::Attribute {
+ fn eq(&self, other: &Self) -> bool {
+ self.style == other.style && self.meta == other.meta
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::BareFnArg {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::BareFnArg {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.name == other.name && self.ty == other.ty
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::BareVariadic {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::BareVariadic {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.name == other.name && self.comma == other.comma
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::BinOp {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::BinOp {
+ fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ (crate::BinOp::Add(_), crate::BinOp::Add(_)) => true,
+ (crate::BinOp::Sub(_), crate::BinOp::Sub(_)) => true,
+ (crate::BinOp::Mul(_), crate::BinOp::Mul(_)) => true,
+ (crate::BinOp::Div(_), crate::BinOp::Div(_)) => true,
+ (crate::BinOp::Rem(_), crate::BinOp::Rem(_)) => true,
+ (crate::BinOp::And(_), crate::BinOp::And(_)) => true,
+ (crate::BinOp::Or(_), crate::BinOp::Or(_)) => true,
+ (crate::BinOp::BitXor(_), crate::BinOp::BitXor(_)) => true,
+ (crate::BinOp::BitAnd(_), crate::BinOp::BitAnd(_)) => true,
+ (crate::BinOp::BitOr(_), crate::BinOp::BitOr(_)) => true,
+ (crate::BinOp::Shl(_), crate::BinOp::Shl(_)) => true,
+ (crate::BinOp::Shr(_), crate::BinOp::Shr(_)) => true,
+ (crate::BinOp::Eq(_), crate::BinOp::Eq(_)) => true,
+ (crate::BinOp::Lt(_), crate::BinOp::Lt(_)) => true,
+ (crate::BinOp::Le(_), crate::BinOp::Le(_)) => true,
+ (crate::BinOp::Ne(_), crate::BinOp::Ne(_)) => true,
+ (crate::BinOp::Ge(_), crate::BinOp::Ge(_)) => true,
+ (crate::BinOp::Gt(_), crate::BinOp::Gt(_)) => true,
+ (crate::BinOp::AddAssign(_), crate::BinOp::AddAssign(_)) => true,
+ (crate::BinOp::SubAssign(_), crate::BinOp::SubAssign(_)) => true,
+ (crate::BinOp::MulAssign(_), crate::BinOp::MulAssign(_)) => true,
+ (crate::BinOp::DivAssign(_), crate::BinOp::DivAssign(_)) => true,
+ (crate::BinOp::RemAssign(_), crate::BinOp::RemAssign(_)) => true,
+ (crate::BinOp::BitXorAssign(_), crate::BinOp::BitXorAssign(_)) => true,
+ (crate::BinOp::BitAndAssign(_), crate::BinOp::BitAndAssign(_)) => true,
+ (crate::BinOp::BitOrAssign(_), crate::BinOp::BitOrAssign(_)) => true,
+ (crate::BinOp::ShlAssign(_), crate::BinOp::ShlAssign(_)) => true,
+ (crate::BinOp::ShrAssign(_), crate::BinOp::ShrAssign(_)) => true,
+ _ => false,
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::Block {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::Block {
+ fn eq(&self, other: &Self) -> bool {
+ self.stmts == other.stmts
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::BoundLifetimes {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::BoundLifetimes {
+ fn eq(&self, other: &Self) -> bool {
+ self.lifetimes == other.lifetimes
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::CapturedParam {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::CapturedParam {
+ fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ (
+ crate::CapturedParam::Lifetime(self0),
+ crate::CapturedParam::Lifetime(other0),
+ ) => self0 == other0,
+ (crate::CapturedParam::Ident(self0), crate::CapturedParam::Ident(other0)) => {
+ self0 == other0
+ }
+ _ => false,
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ConstParam {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ConstParam {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.ident == other.ident && self.ty == other.ty
+ && self.eq_token == other.eq_token && self.default == other.default
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::Constraint {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::Constraint {
+ fn eq(&self, other: &Self) -> bool {
+ self.ident == other.ident && self.generics == other.generics
+ && self.bounds == other.bounds
+ }
+}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::Data {}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::Data {
+ fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ (crate::Data::Struct(self0), crate::Data::Struct(other0)) => self0 == other0,
+ (crate::Data::Enum(self0), crate::Data::Enum(other0)) => self0 == other0,
+ (crate::Data::Union(self0), crate::Data::Union(other0)) => self0 == other0,
+ _ => false,
+ }
+ }
+}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::DataEnum {}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::DataEnum {
+ fn eq(&self, other: &Self) -> bool {
+ self.variants == other.variants
+ }
+}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::DataStruct {}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::DataStruct {
+ fn eq(&self, other: &Self) -> bool {
+ self.fields == other.fields && self.semi_token == other.semi_token
+ }
+}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::DataUnion {}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::DataUnion {
+ fn eq(&self, other: &Self) -> bool {
+ self.fields == other.fields
+ }
+}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::DeriveInput {}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::DeriveInput {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.vis == other.vis && self.ident == other.ident
+ && self.generics == other.generics && self.data == other.data
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::Expr {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::Expr {
+ fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ #[cfg(feature = "full")]
+ (crate::Expr::Array(self0), crate::Expr::Array(other0)) => self0 == other0,
+ #[cfg(feature = "full")]
+ (crate::Expr::Assign(self0), crate::Expr::Assign(other0)) => self0 == other0,
+ #[cfg(feature = "full")]
+ (crate::Expr::Async(self0), crate::Expr::Async(other0)) => self0 == other0,
+ #[cfg(feature = "full")]
+ (crate::Expr::Await(self0), crate::Expr::Await(other0)) => self0 == other0,
+ (crate::Expr::Binary(self0), crate::Expr::Binary(other0)) => self0 == other0,
+ #[cfg(feature = "full")]
+ (crate::Expr::Block(self0), crate::Expr::Block(other0)) => self0 == other0,
+ #[cfg(feature = "full")]
+ (crate::Expr::Break(self0), crate::Expr::Break(other0)) => self0 == other0,
+ (crate::Expr::Call(self0), crate::Expr::Call(other0)) => self0 == other0,
+ (crate::Expr::Cast(self0), crate::Expr::Cast(other0)) => self0 == other0,
+ #[cfg(feature = "full")]
+ (crate::Expr::Closure(self0), crate::Expr::Closure(other0)) => {
+ self0 == other0
+ }
+ #[cfg(feature = "full")]
+ (crate::Expr::Const(self0), crate::Expr::Const(other0)) => self0 == other0,
+ #[cfg(feature = "full")]
+ (crate::Expr::Continue(self0), crate::Expr::Continue(other0)) => {
+ self0 == other0
+ }
+ (crate::Expr::Field(self0), crate::Expr::Field(other0)) => self0 == other0,
+ #[cfg(feature = "full")]
+ (crate::Expr::ForLoop(self0), crate::Expr::ForLoop(other0)) => {
+ self0 == other0
+ }
+ (crate::Expr::Group(self0), crate::Expr::Group(other0)) => self0 == other0,
+ #[cfg(feature = "full")]
+ (crate::Expr::If(self0), crate::Expr::If(other0)) => self0 == other0,
+ (crate::Expr::Index(self0), crate::Expr::Index(other0)) => self0 == other0,
+ #[cfg(feature = "full")]
+ (crate::Expr::Infer(self0), crate::Expr::Infer(other0)) => self0 == other0,
+ #[cfg(feature = "full")]
+ (crate::Expr::Let(self0), crate::Expr::Let(other0)) => self0 == other0,
+ (crate::Expr::Lit(self0), crate::Expr::Lit(other0)) => self0 == other0,
+ #[cfg(feature = "full")]
+ (crate::Expr::Loop(self0), crate::Expr::Loop(other0)) => self0 == other0,
+ (crate::Expr::Macro(self0), crate::Expr::Macro(other0)) => self0 == other0,
+ #[cfg(feature = "full")]
+ (crate::Expr::Match(self0), crate::Expr::Match(other0)) => self0 == other0,
+ (crate::Expr::MethodCall(self0), crate::Expr::MethodCall(other0)) => {
+ self0 == other0
+ }
+ (crate::Expr::Paren(self0), crate::Expr::Paren(other0)) => self0 == other0,
+ (crate::Expr::Path(self0), crate::Expr::Path(other0)) => self0 == other0,
+ #[cfg(feature = "full")]
+ (crate::Expr::Range(self0), crate::Expr::Range(other0)) => self0 == other0,
+ #[cfg(feature = "full")]
+ (crate::Expr::RawAddr(self0), crate::Expr::RawAddr(other0)) => {
+ self0 == other0
+ }
+ (crate::Expr::Reference(self0), crate::Expr::Reference(other0)) => {
+ self0 == other0
+ }
+ #[cfg(feature = "full")]
+ (crate::Expr::Repeat(self0), crate::Expr::Repeat(other0)) => self0 == other0,
+ #[cfg(feature = "full")]
+ (crate::Expr::Return(self0), crate::Expr::Return(other0)) => self0 == other0,
+ (crate::Expr::Struct(self0), crate::Expr::Struct(other0)) => self0 == other0,
+ #[cfg(feature = "full")]
+ (crate::Expr::Try(self0), crate::Expr::Try(other0)) => self0 == other0,
+ #[cfg(feature = "full")]
+ (crate::Expr::TryBlock(self0), crate::Expr::TryBlock(other0)) => {
+ self0 == other0
+ }
+ (crate::Expr::Tuple(self0), crate::Expr::Tuple(other0)) => self0 == other0,
+ (crate::Expr::Unary(self0), crate::Expr::Unary(other0)) => self0 == other0,
+ #[cfg(feature = "full")]
+ (crate::Expr::Unsafe(self0), crate::Expr::Unsafe(other0)) => self0 == other0,
+ (crate::Expr::Verbatim(self0), crate::Expr::Verbatim(other0)) => {
+ TokenStreamHelper(self0) == TokenStreamHelper(other0)
+ }
+ #[cfg(feature = "full")]
+ (crate::Expr::While(self0), crate::Expr::While(other0)) => self0 == other0,
+ #[cfg(feature = "full")]
+ (crate::Expr::Yield(self0), crate::Expr::Yield(other0)) => self0 == other0,
+ _ => false,
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ExprArray {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ExprArray {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.elems == other.elems
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ExprAssign {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ExprAssign {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.left == other.left && self.right == other.right
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ExprAsync {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ExprAsync {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.capture == other.capture
+ && self.block == other.block
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ExprAwait {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ExprAwait {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.base == other.base
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ExprBinary {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ExprBinary {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.left == other.left && self.op == other.op
+ && self.right == other.right
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ExprBlock {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ExprBlock {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.label == other.label
+ && self.block == other.block
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ExprBreak {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ExprBreak {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.label == other.label && self.expr == other.expr
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ExprCall {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ExprCall {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.func == other.func && self.args == other.args
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ExprCast {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ExprCast {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.expr == other.expr && self.ty == other.ty
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ExprClosure {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ExprClosure {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.lifetimes == other.lifetimes
+ && self.constness == other.constness && self.movability == other.movability
+ && self.asyncness == other.asyncness && self.capture == other.capture
+ && self.inputs == other.inputs && self.output == other.output
+ && self.body == other.body
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ExprConst {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ExprConst {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.block == other.block
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ExprContinue {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ExprContinue {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.label == other.label
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ExprField {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ExprField {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.base == other.base
+ && self.member == other.member
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ExprForLoop {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ExprForLoop {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.label == other.label && self.pat == other.pat
+ && self.expr == other.expr && self.body == other.body
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ExprGroup {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ExprGroup {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.expr == other.expr
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ExprIf {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ExprIf {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.cond == other.cond
+ && self.then_branch == other.then_branch
+ && self.else_branch == other.else_branch
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ExprIndex {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ExprIndex {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.expr == other.expr && self.index == other.index
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ExprInfer {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ExprInfer {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ExprLet {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ExprLet {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.pat == other.pat && self.expr == other.expr
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ExprLit {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ExprLit {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.lit == other.lit
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ExprLoop {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ExprLoop {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.label == other.label && self.body == other.body
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ExprMacro {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ExprMacro {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.mac == other.mac
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ExprMatch {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ExprMatch {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.expr == other.expr && self.arms == other.arms
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ExprMethodCall {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ExprMethodCall {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.receiver == other.receiver
+ && self.method == other.method && self.turbofish == other.turbofish
+ && self.args == other.args
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ExprParen {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ExprParen {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.expr == other.expr
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ExprPath {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ExprPath {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.qself == other.qself && self.path == other.path
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ExprRange {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ExprRange {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.start == other.start
+ && self.limits == other.limits && self.end == other.end
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ExprRawAddr {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ExprRawAddr {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.mutability == other.mutability
+ && self.expr == other.expr
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ExprReference {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ExprReference {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.mutability == other.mutability
+ && self.expr == other.expr
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ExprRepeat {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ExprRepeat {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.expr == other.expr && self.len == other.len
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ExprReturn {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ExprReturn {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.expr == other.expr
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ExprStruct {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ExprStruct {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.qself == other.qself && self.path == other.path
+ && self.fields == other.fields && self.dot2_token == other.dot2_token
+ && self.rest == other.rest
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ExprTry {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ExprTry {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.expr == other.expr
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ExprTryBlock {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ExprTryBlock {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.block == other.block
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ExprTuple {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ExprTuple {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.elems == other.elems
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ExprUnary {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ExprUnary {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.op == other.op && self.expr == other.expr
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ExprUnsafe {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ExprUnsafe {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.block == other.block
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ExprWhile {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ExprWhile {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.label == other.label && self.cond == other.cond
+ && self.body == other.body
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ExprYield {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ExprYield {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.expr == other.expr
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::Field {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::Field {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.vis == other.vis
+ && self.mutability == other.mutability && self.ident == other.ident
+ && self.colon_token == other.colon_token && self.ty == other.ty
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::FieldMutability {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::FieldMutability {
+ fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ (crate::FieldMutability::None, crate::FieldMutability::None) => true,
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::FieldPat {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::FieldPat {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.member == other.member
+ && self.colon_token == other.colon_token && self.pat == other.pat
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::FieldValue {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::FieldValue {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.member == other.member
+ && self.colon_token == other.colon_token && self.expr == other.expr
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::Fields {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::Fields {
+ fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ (crate::Fields::Named(self0), crate::Fields::Named(other0)) => {
+ self0 == other0
+ }
+ (crate::Fields::Unnamed(self0), crate::Fields::Unnamed(other0)) => {
+ self0 == other0
+ }
+ (crate::Fields::Unit, crate::Fields::Unit) => true,
+ _ => false,
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::FieldsNamed {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::FieldsNamed {
+ fn eq(&self, other: &Self) -> bool {
+ self.named == other.named
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::FieldsUnnamed {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::FieldsUnnamed {
+ fn eq(&self, other: &Self) -> bool {
+ self.unnamed == other.unnamed
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::File {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::File {
+ fn eq(&self, other: &Self) -> bool {
+ self.shebang == other.shebang && self.attrs == other.attrs
+ && self.items == other.items
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::FnArg {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::FnArg {
+ fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ (crate::FnArg::Receiver(self0), crate::FnArg::Receiver(other0)) => {
+ self0 == other0
+ }
+ (crate::FnArg::Typed(self0), crate::FnArg::Typed(other0)) => self0 == other0,
+ _ => false,
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ForeignItem {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ForeignItem {
+ fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ (crate::ForeignItem::Fn(self0), crate::ForeignItem::Fn(other0)) => {
+ self0 == other0
+ }
+ (crate::ForeignItem::Static(self0), crate::ForeignItem::Static(other0)) => {
+ self0 == other0
+ }
+ (crate::ForeignItem::Type(self0), crate::ForeignItem::Type(other0)) => {
+ self0 == other0
+ }
+ (crate::ForeignItem::Macro(self0), crate::ForeignItem::Macro(other0)) => {
+ self0 == other0
+ }
+ (
+ crate::ForeignItem::Verbatim(self0),
+ crate::ForeignItem::Verbatim(other0),
+ ) => TokenStreamHelper(self0) == TokenStreamHelper(other0),
+ _ => false,
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ForeignItemFn {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ForeignItemFn {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.vis == other.vis && self.sig == other.sig
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ForeignItemMacro {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ForeignItemMacro {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.mac == other.mac
+ && self.semi_token == other.semi_token
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ForeignItemStatic {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ForeignItemStatic {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.vis == other.vis
+ && self.mutability == other.mutability && self.ident == other.ident
+ && self.ty == other.ty
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ForeignItemType {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ForeignItemType {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.vis == other.vis && self.ident == other.ident
+ && self.generics == other.generics
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::GenericArgument {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::GenericArgument {
+ fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ (
+ crate::GenericArgument::Lifetime(self0),
+ crate::GenericArgument::Lifetime(other0),
+ ) => self0 == other0,
+ (
+ crate::GenericArgument::Type(self0),
+ crate::GenericArgument::Type(other0),
+ ) => self0 == other0,
+ (
+ crate::GenericArgument::Const(self0),
+ crate::GenericArgument::Const(other0),
+ ) => self0 == other0,
+ (
+ crate::GenericArgument::AssocType(self0),
+ crate::GenericArgument::AssocType(other0),
+ ) => self0 == other0,
+ (
+ crate::GenericArgument::AssocConst(self0),
+ crate::GenericArgument::AssocConst(other0),
+ ) => self0 == other0,
+ (
+ crate::GenericArgument::Constraint(self0),
+ crate::GenericArgument::Constraint(other0),
+ ) => self0 == other0,
+ _ => false,
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::GenericParam {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::GenericParam {
+ fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ (
+ crate::GenericParam::Lifetime(self0),
+ crate::GenericParam::Lifetime(other0),
+ ) => self0 == other0,
+ (crate::GenericParam::Type(self0), crate::GenericParam::Type(other0)) => {
+ self0 == other0
+ }
+ (crate::GenericParam::Const(self0), crate::GenericParam::Const(other0)) => {
+ self0 == other0
+ }
+ _ => false,
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::Generics {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::Generics {
+ fn eq(&self, other: &Self) -> bool {
+ self.lt_token == other.lt_token && self.params == other.params
+ && self.gt_token == other.gt_token && self.where_clause == other.where_clause
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ImplItem {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ImplItem {
+ fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ (crate::ImplItem::Const(self0), crate::ImplItem::Const(other0)) => {
+ self0 == other0
+ }
+ (crate::ImplItem::Fn(self0), crate::ImplItem::Fn(other0)) => self0 == other0,
+ (crate::ImplItem::Type(self0), crate::ImplItem::Type(other0)) => {
+ self0 == other0
+ }
+ (crate::ImplItem::Macro(self0), crate::ImplItem::Macro(other0)) => {
+ self0 == other0
+ }
+ (crate::ImplItem::Verbatim(self0), crate::ImplItem::Verbatim(other0)) => {
+ TokenStreamHelper(self0) == TokenStreamHelper(other0)
+ }
+ _ => false,
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ImplItemConst {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ImplItemConst {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.vis == other.vis
+ && self.defaultness == other.defaultness && self.ident == other.ident
+ && self.generics == other.generics && self.ty == other.ty
+ && self.expr == other.expr
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ImplItemFn {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ImplItemFn {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.vis == other.vis
+ && self.defaultness == other.defaultness && self.sig == other.sig
+ && self.block == other.block
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ImplItemMacro {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ImplItemMacro {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.mac == other.mac
+ && self.semi_token == other.semi_token
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ImplItemType {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ImplItemType {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.vis == other.vis
+ && self.defaultness == other.defaultness && self.ident == other.ident
+ && self.generics == other.generics && self.ty == other.ty
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ImplRestriction {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ImplRestriction {
+ fn eq(&self, _other: &Self) -> bool {
+ match *self {}
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::Item {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::Item {
+ fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ (crate::Item::Const(self0), crate::Item::Const(other0)) => self0 == other0,
+ (crate::Item::Enum(self0), crate::Item::Enum(other0)) => self0 == other0,
+ (crate::Item::ExternCrate(self0), crate::Item::ExternCrate(other0)) => {
+ self0 == other0
+ }
+ (crate::Item::Fn(self0), crate::Item::Fn(other0)) => self0 == other0,
+ (crate::Item::ForeignMod(self0), crate::Item::ForeignMod(other0)) => {
+ self0 == other0
+ }
+ (crate::Item::Impl(self0), crate::Item::Impl(other0)) => self0 == other0,
+ (crate::Item::Macro(self0), crate::Item::Macro(other0)) => self0 == other0,
+ (crate::Item::Mod(self0), crate::Item::Mod(other0)) => self0 == other0,
+ (crate::Item::Static(self0), crate::Item::Static(other0)) => self0 == other0,
+ (crate::Item::Struct(self0), crate::Item::Struct(other0)) => self0 == other0,
+ (crate::Item::Trait(self0), crate::Item::Trait(other0)) => self0 == other0,
+ (crate::Item::TraitAlias(self0), crate::Item::TraitAlias(other0)) => {
+ self0 == other0
+ }
+ (crate::Item::Type(self0), crate::Item::Type(other0)) => self0 == other0,
+ (crate::Item::Union(self0), crate::Item::Union(other0)) => self0 == other0,
+ (crate::Item::Use(self0), crate::Item::Use(other0)) => self0 == other0,
+ (crate::Item::Verbatim(self0), crate::Item::Verbatim(other0)) => {
+ TokenStreamHelper(self0) == TokenStreamHelper(other0)
+ }
+ _ => false,
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ItemConst {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ItemConst {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.vis == other.vis && self.ident == other.ident
+ && self.generics == other.generics && self.ty == other.ty
+ && self.expr == other.expr
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ItemEnum {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ItemEnum {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.vis == other.vis && self.ident == other.ident
+ && self.generics == other.generics && self.variants == other.variants
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ItemExternCrate {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ItemExternCrate {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.vis == other.vis && self.ident == other.ident
+ && self.rename == other.rename
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ItemFn {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ItemFn {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.vis == other.vis && self.sig == other.sig
+ && self.block == other.block
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ItemForeignMod {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ItemForeignMod {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.unsafety == other.unsafety
+ && self.abi == other.abi && self.items == other.items
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ItemImpl {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ItemImpl {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.defaultness == other.defaultness
+ && self.unsafety == other.unsafety && self.generics == other.generics
+ && self.trait_ == other.trait_ && self.self_ty == other.self_ty
+ && self.items == other.items
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ItemMacro {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ItemMacro {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.ident == other.ident && self.mac == other.mac
+ && self.semi_token == other.semi_token
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ItemMod {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ItemMod {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.vis == other.vis
+ && self.unsafety == other.unsafety && self.ident == other.ident
+ && self.content == other.content && self.semi == other.semi
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ItemStatic {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ItemStatic {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.vis == other.vis
+ && self.mutability == other.mutability && self.ident == other.ident
+ && self.ty == other.ty && self.expr == other.expr
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ItemStruct {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ItemStruct {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.vis == other.vis && self.ident == other.ident
+ && self.generics == other.generics && self.fields == other.fields
+ && self.semi_token == other.semi_token
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ItemTrait {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ItemTrait {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.vis == other.vis
+ && self.unsafety == other.unsafety && self.auto_token == other.auto_token
+ && self.restriction == other.restriction && self.ident == other.ident
+ && self.generics == other.generics && self.colon_token == other.colon_token
+ && self.supertraits == other.supertraits && self.items == other.items
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ItemTraitAlias {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ItemTraitAlias {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.vis == other.vis && self.ident == other.ident
+ && self.generics == other.generics && self.bounds == other.bounds
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ItemType {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ItemType {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.vis == other.vis && self.ident == other.ident
+ && self.generics == other.generics && self.ty == other.ty
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ItemUnion {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ItemUnion {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.vis == other.vis && self.ident == other.ident
+ && self.generics == other.generics && self.fields == other.fields
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ItemUse {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ItemUse {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.vis == other.vis
+ && self.leading_colon == other.leading_colon && self.tree == other.tree
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::Label {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::Label {
+ fn eq(&self, other: &Self) -> bool {
+ self.name == other.name
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::LifetimeParam {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::LifetimeParam {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.lifetime == other.lifetime
+ && self.colon_token == other.colon_token && self.bounds == other.bounds
+ }
+}
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::Lit {}
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::Lit {
+ fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ (crate::Lit::Str(self0), crate::Lit::Str(other0)) => self0 == other0,
+ (crate::Lit::ByteStr(self0), crate::Lit::ByteStr(other0)) => self0 == other0,
+ (crate::Lit::CStr(self0), crate::Lit::CStr(other0)) => self0 == other0,
+ (crate::Lit::Byte(self0), crate::Lit::Byte(other0)) => self0 == other0,
+ (crate::Lit::Char(self0), crate::Lit::Char(other0)) => self0 == other0,
+ (crate::Lit::Int(self0), crate::Lit::Int(other0)) => self0 == other0,
+ (crate::Lit::Float(self0), crate::Lit::Float(other0)) => self0 == other0,
+ (crate::Lit::Bool(self0), crate::Lit::Bool(other0)) => self0 == other0,
+ (crate::Lit::Verbatim(self0), crate::Lit::Verbatim(other0)) => {
+ self0.to_string() == other0.to_string()
+ }
+ _ => false,
+ }
+ }
+}
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::LitBool {}
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::LitBool {
+ fn eq(&self, other: &Self) -> bool {
+ self.value == other.value
+ }
+}
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::LitByte {}
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::LitByteStr {}
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::LitCStr {}
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::LitChar {}
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::LitFloat {}
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::LitInt {}
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::LitStr {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::Local {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::Local {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.pat == other.pat && self.init == other.init
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::LocalInit {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::LocalInit {
+ fn eq(&self, other: &Self) -> bool {
+ self.expr == other.expr && self.diverge == other.diverge
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::Macro {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::Macro {
+ fn eq(&self, other: &Self) -> bool {
+ self.path == other.path && self.delimiter == other.delimiter
+ && TokenStreamHelper(&self.tokens) == TokenStreamHelper(&other.tokens)
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::MacroDelimiter {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::MacroDelimiter {
+ fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ (crate::MacroDelimiter::Paren(_), crate::MacroDelimiter::Paren(_)) => true,
+ (crate::MacroDelimiter::Brace(_), crate::MacroDelimiter::Brace(_)) => true,
+ (crate::MacroDelimiter::Bracket(_), crate::MacroDelimiter::Bracket(_)) => {
+ true
+ }
+ _ => false,
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::Meta {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::Meta {
+ fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ (crate::Meta::Path(self0), crate::Meta::Path(other0)) => self0 == other0,
+ (crate::Meta::List(self0), crate::Meta::List(other0)) => self0 == other0,
+ (crate::Meta::NameValue(self0), crate::Meta::NameValue(other0)) => {
+ self0 == other0
+ }
+ _ => false,
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::MetaList {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::MetaList {
+ fn eq(&self, other: &Self) -> bool {
+ self.path == other.path && self.delimiter == other.delimiter
+ && TokenStreamHelper(&self.tokens) == TokenStreamHelper(&other.tokens)
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::MetaNameValue {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::MetaNameValue {
+ fn eq(&self, other: &Self) -> bool {
+ self.path == other.path && self.value == other.value
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ParenthesizedGenericArguments {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ParenthesizedGenericArguments {
+ fn eq(&self, other: &Self) -> bool {
+ self.inputs == other.inputs && self.output == other.output
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::Pat {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::Pat {
+ fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ (crate::Pat::Const(self0), crate::Pat::Const(other0)) => self0 == other0,
+ (crate::Pat::Ident(self0), crate::Pat::Ident(other0)) => self0 == other0,
+ (crate::Pat::Lit(self0), crate::Pat::Lit(other0)) => self0 == other0,
+ (crate::Pat::Macro(self0), crate::Pat::Macro(other0)) => self0 == other0,
+ (crate::Pat::Or(self0), crate::Pat::Or(other0)) => self0 == other0,
+ (crate::Pat::Paren(self0), crate::Pat::Paren(other0)) => self0 == other0,
+ (crate::Pat::Path(self0), crate::Pat::Path(other0)) => self0 == other0,
+ (crate::Pat::Range(self0), crate::Pat::Range(other0)) => self0 == other0,
+ (crate::Pat::Reference(self0), crate::Pat::Reference(other0)) => {
+ self0 == other0
+ }
+ (crate::Pat::Rest(self0), crate::Pat::Rest(other0)) => self0 == other0,
+ (crate::Pat::Slice(self0), crate::Pat::Slice(other0)) => self0 == other0,
+ (crate::Pat::Struct(self0), crate::Pat::Struct(other0)) => self0 == other0,
+ (crate::Pat::Tuple(self0), crate::Pat::Tuple(other0)) => self0 == other0,
+ (crate::Pat::TupleStruct(self0), crate::Pat::TupleStruct(other0)) => {
+ self0 == other0
+ }
+ (crate::Pat::Type(self0), crate::Pat::Type(other0)) => self0 == other0,
+ (crate::Pat::Verbatim(self0), crate::Pat::Verbatim(other0)) => {
+ TokenStreamHelper(self0) == TokenStreamHelper(other0)
+ }
+ (crate::Pat::Wild(self0), crate::Pat::Wild(other0)) => self0 == other0,
+ _ => false,
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::PatIdent {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::PatIdent {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.by_ref == other.by_ref
+ && self.mutability == other.mutability && self.ident == other.ident
+ && self.subpat == other.subpat
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::PatOr {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::PatOr {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.leading_vert == other.leading_vert
+ && self.cases == other.cases
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::PatParen {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::PatParen {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.pat == other.pat
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::PatReference {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::PatReference {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.mutability == other.mutability
+ && self.pat == other.pat
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::PatRest {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::PatRest {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::PatSlice {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::PatSlice {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.elems == other.elems
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::PatStruct {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::PatStruct {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.qself == other.qself && self.path == other.path
+ && self.fields == other.fields && self.rest == other.rest
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::PatTuple {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::PatTuple {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.elems == other.elems
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::PatTupleStruct {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::PatTupleStruct {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.qself == other.qself && self.path == other.path
+ && self.elems == other.elems
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::PatType {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::PatType {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.pat == other.pat && self.ty == other.ty
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::PatWild {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::PatWild {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::Path {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::Path {
+ fn eq(&self, other: &Self) -> bool {
+ self.leading_colon == other.leading_colon && self.segments == other.segments
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::PathArguments {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::PathArguments {
+ fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ (crate::PathArguments::None, crate::PathArguments::None) => true,
+ (
+ crate::PathArguments::AngleBracketed(self0),
+ crate::PathArguments::AngleBracketed(other0),
+ ) => self0 == other0,
+ (
+ crate::PathArguments::Parenthesized(self0),
+ crate::PathArguments::Parenthesized(other0),
+ ) => self0 == other0,
+ _ => false,
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::PathSegment {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::PathSegment {
+ fn eq(&self, other: &Self) -> bool {
+ self.ident == other.ident && self.arguments == other.arguments
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::PointerMutability {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::PointerMutability {
+ fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ (crate::PointerMutability::Const(_), crate::PointerMutability::Const(_)) => {
+ true
+ }
+ (crate::PointerMutability::Mut(_), crate::PointerMutability::Mut(_)) => true,
+ _ => false,
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::PreciseCapture {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::PreciseCapture {
+ fn eq(&self, other: &Self) -> bool {
+ self.params == other.params
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::PredicateLifetime {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::PredicateLifetime {
+ fn eq(&self, other: &Self) -> bool {
+ self.lifetime == other.lifetime && self.bounds == other.bounds
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::PredicateType {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::PredicateType {
+ fn eq(&self, other: &Self) -> bool {
+ self.lifetimes == other.lifetimes && self.bounded_ty == other.bounded_ty
+ && self.bounds == other.bounds
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::QSelf {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::QSelf {
+ fn eq(&self, other: &Self) -> bool {
+ self.ty == other.ty && self.position == other.position
+ && self.as_token == other.as_token
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::RangeLimits {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::RangeLimits {
+ fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ (crate::RangeLimits::HalfOpen(_), crate::RangeLimits::HalfOpen(_)) => true,
+ (crate::RangeLimits::Closed(_), crate::RangeLimits::Closed(_)) => true,
+ _ => false,
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::Receiver {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::Receiver {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.reference == other.reference
+ && self.mutability == other.mutability
+ && self.colon_token == other.colon_token && self.ty == other.ty
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::ReturnType {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::ReturnType {
+ fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ (crate::ReturnType::Default, crate::ReturnType::Default) => true,
+ (crate::ReturnType::Type(_, self1), crate::ReturnType::Type(_, other1)) => {
+ self1 == other1
+ }
+ _ => false,
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::Signature {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::Signature {
+ fn eq(&self, other: &Self) -> bool {
+ self.constness == other.constness && self.asyncness == other.asyncness
+ && self.unsafety == other.unsafety && self.abi == other.abi
+ && self.ident == other.ident && self.generics == other.generics
+ && self.inputs == other.inputs && self.variadic == other.variadic
+ && self.output == other.output
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::StaticMutability {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::StaticMutability {
+ fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ (crate::StaticMutability::Mut(_), crate::StaticMutability::Mut(_)) => true,
+ (crate::StaticMutability::None, crate::StaticMutability::None) => true,
+ _ => false,
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::Stmt {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::Stmt {
+ fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ (crate::Stmt::Local(self0), crate::Stmt::Local(other0)) => self0 == other0,
+ (crate::Stmt::Item(self0), crate::Stmt::Item(other0)) => self0 == other0,
+ (crate::Stmt::Expr(self0, self1), crate::Stmt::Expr(other0, other1)) => {
+ self0 == other0 && self1 == other1
+ }
+ (crate::Stmt::Macro(self0), crate::Stmt::Macro(other0)) => self0 == other0,
+ _ => false,
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::StmtMacro {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::StmtMacro {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.mac == other.mac
+ && self.semi_token == other.semi_token
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::TraitBound {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::TraitBound {
+ fn eq(&self, other: &Self) -> bool {
+ self.paren_token == other.paren_token && self.modifier == other.modifier
+ && self.lifetimes == other.lifetimes && self.path == other.path
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::TraitBoundModifier {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::TraitBoundModifier {
+ fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ (crate::TraitBoundModifier::None, crate::TraitBoundModifier::None) => true,
+ (
+ crate::TraitBoundModifier::Maybe(_),
+ crate::TraitBoundModifier::Maybe(_),
+ ) => true,
+ _ => false,
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::TraitItem {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::TraitItem {
+ fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ (crate::TraitItem::Const(self0), crate::TraitItem::Const(other0)) => {
+ self0 == other0
+ }
+ (crate::TraitItem::Fn(self0), crate::TraitItem::Fn(other0)) => {
+ self0 == other0
+ }
+ (crate::TraitItem::Type(self0), crate::TraitItem::Type(other0)) => {
+ self0 == other0
+ }
+ (crate::TraitItem::Macro(self0), crate::TraitItem::Macro(other0)) => {
+ self0 == other0
+ }
+ (crate::TraitItem::Verbatim(self0), crate::TraitItem::Verbatim(other0)) => {
+ TokenStreamHelper(self0) == TokenStreamHelper(other0)
+ }
+ _ => false,
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::TraitItemConst {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::TraitItemConst {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.ident == other.ident
+ && self.generics == other.generics && self.ty == other.ty
+ && self.default == other.default
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::TraitItemFn {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::TraitItemFn {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.sig == other.sig
+ && self.default == other.default && self.semi_token == other.semi_token
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::TraitItemMacro {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::TraitItemMacro {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.mac == other.mac
+ && self.semi_token == other.semi_token
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::TraitItemType {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::TraitItemType {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.ident == other.ident
+ && self.generics == other.generics && self.colon_token == other.colon_token
+ && self.bounds == other.bounds && self.default == other.default
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::Type {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::Type {
+ fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ (crate::Type::Array(self0), crate::Type::Array(other0)) => self0 == other0,
+ (crate::Type::BareFn(self0), crate::Type::BareFn(other0)) => self0 == other0,
+ (crate::Type::Group(self0), crate::Type::Group(other0)) => self0 == other0,
+ (crate::Type::ImplTrait(self0), crate::Type::ImplTrait(other0)) => {
+ self0 == other0
+ }
+ (crate::Type::Infer(self0), crate::Type::Infer(other0)) => self0 == other0,
+ (crate::Type::Macro(self0), crate::Type::Macro(other0)) => self0 == other0,
+ (crate::Type::Never(self0), crate::Type::Never(other0)) => self0 == other0,
+ (crate::Type::Paren(self0), crate::Type::Paren(other0)) => self0 == other0,
+ (crate::Type::Path(self0), crate::Type::Path(other0)) => self0 == other0,
+ (crate::Type::Ptr(self0), crate::Type::Ptr(other0)) => self0 == other0,
+ (crate::Type::Reference(self0), crate::Type::Reference(other0)) => {
+ self0 == other0
+ }
+ (crate::Type::Slice(self0), crate::Type::Slice(other0)) => self0 == other0,
+ (crate::Type::TraitObject(self0), crate::Type::TraitObject(other0)) => {
+ self0 == other0
+ }
+ (crate::Type::Tuple(self0), crate::Type::Tuple(other0)) => self0 == other0,
+ (crate::Type::Verbatim(self0), crate::Type::Verbatim(other0)) => {
+ TokenStreamHelper(self0) == TokenStreamHelper(other0)
+ }
+ _ => false,
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::TypeArray {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::TypeArray {
+ fn eq(&self, other: &Self) -> bool {
+ self.elem == other.elem && self.len == other.len
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::TypeBareFn {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::TypeBareFn {
+ fn eq(&self, other: &Self) -> bool {
+ self.lifetimes == other.lifetimes && self.unsafety == other.unsafety
+ && self.abi == other.abi && self.inputs == other.inputs
+ && self.variadic == other.variadic && self.output == other.output
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::TypeGroup {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::TypeGroup {
+ fn eq(&self, other: &Self) -> bool {
+ self.elem == other.elem
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::TypeImplTrait {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::TypeImplTrait {
+ fn eq(&self, other: &Self) -> bool {
+ self.bounds == other.bounds
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::TypeInfer {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::TypeInfer {
+ fn eq(&self, _other: &Self) -> bool {
+ true
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::TypeMacro {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::TypeMacro {
+ fn eq(&self, other: &Self) -> bool {
+ self.mac == other.mac
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::TypeNever {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::TypeNever {
+ fn eq(&self, _other: &Self) -> bool {
+ true
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::TypeParam {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::TypeParam {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.ident == other.ident
+ && self.colon_token == other.colon_token && self.bounds == other.bounds
+ && self.eq_token == other.eq_token && self.default == other.default
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::TypeParamBound {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::TypeParamBound {
+ fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ (
+ crate::TypeParamBound::Trait(self0),
+ crate::TypeParamBound::Trait(other0),
+ ) => self0 == other0,
+ (
+ crate::TypeParamBound::Lifetime(self0),
+ crate::TypeParamBound::Lifetime(other0),
+ ) => self0 == other0,
+ #[cfg(feature = "full")]
+ (
+ crate::TypeParamBound::PreciseCapture(self0),
+ crate::TypeParamBound::PreciseCapture(other0),
+ ) => self0 == other0,
+ (
+ crate::TypeParamBound::Verbatim(self0),
+ crate::TypeParamBound::Verbatim(other0),
+ ) => TokenStreamHelper(self0) == TokenStreamHelper(other0),
+ _ => false,
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::TypeParen {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::TypeParen {
+ fn eq(&self, other: &Self) -> bool {
+ self.elem == other.elem
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::TypePath {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::TypePath {
+ fn eq(&self, other: &Self) -> bool {
+ self.qself == other.qself && self.path == other.path
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::TypePtr {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::TypePtr {
+ fn eq(&self, other: &Self) -> bool {
+ self.const_token == other.const_token && self.mutability == other.mutability
+ && self.elem == other.elem
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::TypeReference {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::TypeReference {
+ fn eq(&self, other: &Self) -> bool {
+ self.lifetime == other.lifetime && self.mutability == other.mutability
+ && self.elem == other.elem
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::TypeSlice {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::TypeSlice {
+ fn eq(&self, other: &Self) -> bool {
+ self.elem == other.elem
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::TypeTraitObject {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::TypeTraitObject {
+ fn eq(&self, other: &Self) -> bool {
+ self.dyn_token == other.dyn_token && self.bounds == other.bounds
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::TypeTuple {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::TypeTuple {
+ fn eq(&self, other: &Self) -> bool {
+ self.elems == other.elems
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::UnOp {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::UnOp {
+ fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ (crate::UnOp::Deref(_), crate::UnOp::Deref(_)) => true,
+ (crate::UnOp::Not(_), crate::UnOp::Not(_)) => true,
+ (crate::UnOp::Neg(_), crate::UnOp::Neg(_)) => true,
+ _ => false,
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::UseGlob {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::UseGlob {
+ fn eq(&self, _other: &Self) -> bool {
+ true
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::UseGroup {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::UseGroup {
+ fn eq(&self, other: &Self) -> bool {
+ self.items == other.items
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::UseName {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::UseName {
+ fn eq(&self, other: &Self) -> bool {
+ self.ident == other.ident
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::UsePath {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::UsePath {
+ fn eq(&self, other: &Self) -> bool {
+ self.ident == other.ident && self.tree == other.tree
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::UseRename {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::UseRename {
+ fn eq(&self, other: &Self) -> bool {
+ self.ident == other.ident && self.rename == other.rename
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::UseTree {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::UseTree {
+ fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ (crate::UseTree::Path(self0), crate::UseTree::Path(other0)) => {
+ self0 == other0
+ }
+ (crate::UseTree::Name(self0), crate::UseTree::Name(other0)) => {
+ self0 == other0
+ }
+ (crate::UseTree::Rename(self0), crate::UseTree::Rename(other0)) => {
+ self0 == other0
+ }
+ (crate::UseTree::Glob(self0), crate::UseTree::Glob(other0)) => {
+ self0 == other0
+ }
+ (crate::UseTree::Group(self0), crate::UseTree::Group(other0)) => {
+ self0 == other0
+ }
+ _ => false,
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::Variadic {}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::Variadic {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.pat == other.pat && self.comma == other.comma
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::Variant {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::Variant {
+ fn eq(&self, other: &Self) -> bool {
+ self.attrs == other.attrs && self.ident == other.ident
+ && self.fields == other.fields && self.discriminant == other.discriminant
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::VisRestricted {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::VisRestricted {
+ fn eq(&self, other: &Self) -> bool {
+ self.in_token == other.in_token && self.path == other.path
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::Visibility {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::Visibility {
+ fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ (crate::Visibility::Public(_), crate::Visibility::Public(_)) => true,
+ (
+ crate::Visibility::Restricted(self0),
+ crate::Visibility::Restricted(other0),
+ ) => self0 == other0,
+ (crate::Visibility::Inherited, crate::Visibility::Inherited) => true,
+ _ => false,
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::WhereClause {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::WhereClause {
+ fn eq(&self, other: &Self) -> bool {
+ self.predicates == other.predicates
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for crate::WherePredicate {}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for crate::WherePredicate {
+ fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ (
+ crate::WherePredicate::Lifetime(self0),
+ crate::WherePredicate::Lifetime(other0),
+ ) => self0 == other0,
+ (crate::WherePredicate::Type(self0), crate::WherePredicate::Type(other0)) => {
+ self0 == other0
+ }
+ _ => false,
+ }
+ }
+}
diff --git a/rust/syn/gen/fold.rs b/rust/syn/gen/fold.rs
new file mode 100644
index 000000000000..1f0afd31919d
--- /dev/null
+++ b/rust/syn/gen/fold.rs
@@ -0,0 +1,3902 @@
+// This file is @generated by syn-internal-codegen.
+// It is not intended for manual editing.
+
+#![allow(unreachable_code, unused_variables)]
+#![allow(
+ clippy::match_wildcard_for_single_variants,
+ clippy::needless_match,
+ clippy::needless_pass_by_ref_mut,
+)]
+#[cfg(feature = "full")]
+macro_rules! full {
+ ($e:expr) => {
+ $e
+ };
+}
+#[cfg(all(feature = "derive", not(feature = "full")))]
+macro_rules! full {
+ ($e:expr) => {
+ unreachable!()
+ };
+}
+/// Syntax tree traversal to transform the nodes of an owned syntax tree.
+///
+/// See the [module documentation] for details.
+///
+/// [module documentation]: self
+pub trait Fold {
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_abi(&mut self, i: crate::Abi) -> crate::Abi {
+ fold_abi(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_angle_bracketed_generic_arguments(
+ &mut self,
+ i: crate::AngleBracketedGenericArguments,
+ ) -> crate::AngleBracketedGenericArguments {
+ fold_angle_bracketed_generic_arguments(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_arm(&mut self, i: crate::Arm) -> crate::Arm {
+ fold_arm(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_assoc_const(&mut self, i: crate::AssocConst) -> crate::AssocConst {
+ fold_assoc_const(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_assoc_type(&mut self, i: crate::AssocType) -> crate::AssocType {
+ fold_assoc_type(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_attr_style(&mut self, i: crate::AttrStyle) -> crate::AttrStyle {
+ fold_attr_style(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_attribute(&mut self, i: crate::Attribute) -> crate::Attribute {
+ fold_attribute(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_attributes(&mut self, i: Vec<crate::Attribute>) -> Vec<crate::Attribute> {
+ fold_vec(i, self, Self::fold_attribute)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_bare_fn_arg(&mut self, i: crate::BareFnArg) -> crate::BareFnArg {
+ fold_bare_fn_arg(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_bare_variadic(&mut self, i: crate::BareVariadic) -> crate::BareVariadic {
+ fold_bare_variadic(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_bin_op(&mut self, i: crate::BinOp) -> crate::BinOp {
+ fold_bin_op(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_block(&mut self, i: crate::Block) -> crate::Block {
+ fold_block(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_bound_lifetimes(
+ &mut self,
+ i: crate::BoundLifetimes,
+ ) -> crate::BoundLifetimes {
+ fold_bound_lifetimes(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_captured_param(&mut self, i: crate::CapturedParam) -> crate::CapturedParam {
+ fold_captured_param(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_const_param(&mut self, i: crate::ConstParam) -> crate::ConstParam {
+ fold_const_param(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_constraint(&mut self, i: crate::Constraint) -> crate::Constraint {
+ fold_constraint(self, i)
+ }
+ #[cfg(feature = "derive")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
+ fn fold_data(&mut self, i: crate::Data) -> crate::Data {
+ fold_data(self, i)
+ }
+ #[cfg(feature = "derive")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
+ fn fold_data_enum(&mut self, i: crate::DataEnum) -> crate::DataEnum {
+ fold_data_enum(self, i)
+ }
+ #[cfg(feature = "derive")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
+ fn fold_data_struct(&mut self, i: crate::DataStruct) -> crate::DataStruct {
+ fold_data_struct(self, i)
+ }
+ #[cfg(feature = "derive")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
+ fn fold_data_union(&mut self, i: crate::DataUnion) -> crate::DataUnion {
+ fold_data_union(self, i)
+ }
+ #[cfg(feature = "derive")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
+ fn fold_derive_input(&mut self, i: crate::DeriveInput) -> crate::DeriveInput {
+ fold_derive_input(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_expr(&mut self, i: crate::Expr) -> crate::Expr {
+ fold_expr(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_expr_array(&mut self, i: crate::ExprArray) -> crate::ExprArray {
+ fold_expr_array(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_expr_assign(&mut self, i: crate::ExprAssign) -> crate::ExprAssign {
+ fold_expr_assign(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_expr_async(&mut self, i: crate::ExprAsync) -> crate::ExprAsync {
+ fold_expr_async(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_expr_await(&mut self, i: crate::ExprAwait) -> crate::ExprAwait {
+ fold_expr_await(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_expr_binary(&mut self, i: crate::ExprBinary) -> crate::ExprBinary {
+ fold_expr_binary(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_expr_block(&mut self, i: crate::ExprBlock) -> crate::ExprBlock {
+ fold_expr_block(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_expr_break(&mut self, i: crate::ExprBreak) -> crate::ExprBreak {
+ fold_expr_break(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_expr_call(&mut self, i: crate::ExprCall) -> crate::ExprCall {
+ fold_expr_call(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_expr_cast(&mut self, i: crate::ExprCast) -> crate::ExprCast {
+ fold_expr_cast(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_expr_closure(&mut self, i: crate::ExprClosure) -> crate::ExprClosure {
+ fold_expr_closure(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_expr_const(&mut self, i: crate::ExprConst) -> crate::ExprConst {
+ fold_expr_const(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_expr_continue(&mut self, i: crate::ExprContinue) -> crate::ExprContinue {
+ fold_expr_continue(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_expr_field(&mut self, i: crate::ExprField) -> crate::ExprField {
+ fold_expr_field(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_expr_for_loop(&mut self, i: crate::ExprForLoop) -> crate::ExprForLoop {
+ fold_expr_for_loop(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_expr_group(&mut self, i: crate::ExprGroup) -> crate::ExprGroup {
+ fold_expr_group(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_expr_if(&mut self, i: crate::ExprIf) -> crate::ExprIf {
+ fold_expr_if(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_expr_index(&mut self, i: crate::ExprIndex) -> crate::ExprIndex {
+ fold_expr_index(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_expr_infer(&mut self, i: crate::ExprInfer) -> crate::ExprInfer {
+ fold_expr_infer(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_expr_let(&mut self, i: crate::ExprLet) -> crate::ExprLet {
+ fold_expr_let(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_expr_lit(&mut self, i: crate::ExprLit) -> crate::ExprLit {
+ fold_expr_lit(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_expr_loop(&mut self, i: crate::ExprLoop) -> crate::ExprLoop {
+ fold_expr_loop(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_expr_macro(&mut self, i: crate::ExprMacro) -> crate::ExprMacro {
+ fold_expr_macro(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_expr_match(&mut self, i: crate::ExprMatch) -> crate::ExprMatch {
+ fold_expr_match(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_expr_method_call(
+ &mut self,
+ i: crate::ExprMethodCall,
+ ) -> crate::ExprMethodCall {
+ fold_expr_method_call(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_expr_paren(&mut self, i: crate::ExprParen) -> crate::ExprParen {
+ fold_expr_paren(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_expr_path(&mut self, i: crate::ExprPath) -> crate::ExprPath {
+ fold_expr_path(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_expr_range(&mut self, i: crate::ExprRange) -> crate::ExprRange {
+ fold_expr_range(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_expr_raw_addr(&mut self, i: crate::ExprRawAddr) -> crate::ExprRawAddr {
+ fold_expr_raw_addr(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_expr_reference(&mut self, i: crate::ExprReference) -> crate::ExprReference {
+ fold_expr_reference(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_expr_repeat(&mut self, i: crate::ExprRepeat) -> crate::ExprRepeat {
+ fold_expr_repeat(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_expr_return(&mut self, i: crate::ExprReturn) -> crate::ExprReturn {
+ fold_expr_return(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_expr_struct(&mut self, i: crate::ExprStruct) -> crate::ExprStruct {
+ fold_expr_struct(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_expr_try(&mut self, i: crate::ExprTry) -> crate::ExprTry {
+ fold_expr_try(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_expr_try_block(&mut self, i: crate::ExprTryBlock) -> crate::ExprTryBlock {
+ fold_expr_try_block(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_expr_tuple(&mut self, i: crate::ExprTuple) -> crate::ExprTuple {
+ fold_expr_tuple(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_expr_unary(&mut self, i: crate::ExprUnary) -> crate::ExprUnary {
+ fold_expr_unary(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_expr_unsafe(&mut self, i: crate::ExprUnsafe) -> crate::ExprUnsafe {
+ fold_expr_unsafe(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_expr_while(&mut self, i: crate::ExprWhile) -> crate::ExprWhile {
+ fold_expr_while(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_expr_yield(&mut self, i: crate::ExprYield) -> crate::ExprYield {
+ fold_expr_yield(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_field(&mut self, i: crate::Field) -> crate::Field {
+ fold_field(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_field_mutability(
+ &mut self,
+ i: crate::FieldMutability,
+ ) -> crate::FieldMutability {
+ fold_field_mutability(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_field_pat(&mut self, i: crate::FieldPat) -> crate::FieldPat {
+ fold_field_pat(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_field_value(&mut self, i: crate::FieldValue) -> crate::FieldValue {
+ fold_field_value(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_fields(&mut self, i: crate::Fields) -> crate::Fields {
+ fold_fields(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_fields_named(&mut self, i: crate::FieldsNamed) -> crate::FieldsNamed {
+ fold_fields_named(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_fields_unnamed(&mut self, i: crate::FieldsUnnamed) -> crate::FieldsUnnamed {
+ fold_fields_unnamed(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_file(&mut self, i: crate::File) -> crate::File {
+ fold_file(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_fn_arg(&mut self, i: crate::FnArg) -> crate::FnArg {
+ fold_fn_arg(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_foreign_item(&mut self, i: crate::ForeignItem) -> crate::ForeignItem {
+ fold_foreign_item(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_foreign_item_fn(&mut self, i: crate::ForeignItemFn) -> crate::ForeignItemFn {
+ fold_foreign_item_fn(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_foreign_item_macro(
+ &mut self,
+ i: crate::ForeignItemMacro,
+ ) -> crate::ForeignItemMacro {
+ fold_foreign_item_macro(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_foreign_item_static(
+ &mut self,
+ i: crate::ForeignItemStatic,
+ ) -> crate::ForeignItemStatic {
+ fold_foreign_item_static(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_foreign_item_type(
+ &mut self,
+ i: crate::ForeignItemType,
+ ) -> crate::ForeignItemType {
+ fold_foreign_item_type(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_generic_argument(
+ &mut self,
+ i: crate::GenericArgument,
+ ) -> crate::GenericArgument {
+ fold_generic_argument(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_generic_param(&mut self, i: crate::GenericParam) -> crate::GenericParam {
+ fold_generic_param(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_generics(&mut self, i: crate::Generics) -> crate::Generics {
+ fold_generics(self, i)
+ }
+ fn fold_ident(&mut self, i: proc_macro2::Ident) -> proc_macro2::Ident {
+ fold_ident(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_impl_item(&mut self, i: crate::ImplItem) -> crate::ImplItem {
+ fold_impl_item(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_impl_item_const(&mut self, i: crate::ImplItemConst) -> crate::ImplItemConst {
+ fold_impl_item_const(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_impl_item_fn(&mut self, i: crate::ImplItemFn) -> crate::ImplItemFn {
+ fold_impl_item_fn(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_impl_item_macro(&mut self, i: crate::ImplItemMacro) -> crate::ImplItemMacro {
+ fold_impl_item_macro(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_impl_item_type(&mut self, i: crate::ImplItemType) -> crate::ImplItemType {
+ fold_impl_item_type(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_impl_restriction(
+ &mut self,
+ i: crate::ImplRestriction,
+ ) -> crate::ImplRestriction {
+ fold_impl_restriction(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_index(&mut self, i: crate::Index) -> crate::Index {
+ fold_index(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_item(&mut self, i: crate::Item) -> crate::Item {
+ fold_item(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_item_const(&mut self, i: crate::ItemConst) -> crate::ItemConst {
+ fold_item_const(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_item_enum(&mut self, i: crate::ItemEnum) -> crate::ItemEnum {
+ fold_item_enum(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_item_extern_crate(
+ &mut self,
+ i: crate::ItemExternCrate,
+ ) -> crate::ItemExternCrate {
+ fold_item_extern_crate(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_item_fn(&mut self, i: crate::ItemFn) -> crate::ItemFn {
+ fold_item_fn(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_item_foreign_mod(
+ &mut self,
+ i: crate::ItemForeignMod,
+ ) -> crate::ItemForeignMod {
+ fold_item_foreign_mod(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_item_impl(&mut self, i: crate::ItemImpl) -> crate::ItemImpl {
+ fold_item_impl(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_item_macro(&mut self, i: crate::ItemMacro) -> crate::ItemMacro {
+ fold_item_macro(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_item_mod(&mut self, i: crate::ItemMod) -> crate::ItemMod {
+ fold_item_mod(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_item_static(&mut self, i: crate::ItemStatic) -> crate::ItemStatic {
+ fold_item_static(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_item_struct(&mut self, i: crate::ItemStruct) -> crate::ItemStruct {
+ fold_item_struct(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_item_trait(&mut self, i: crate::ItemTrait) -> crate::ItemTrait {
+ fold_item_trait(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_item_trait_alias(
+ &mut self,
+ i: crate::ItemTraitAlias,
+ ) -> crate::ItemTraitAlias {
+ fold_item_trait_alias(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_item_type(&mut self, i: crate::ItemType) -> crate::ItemType {
+ fold_item_type(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_item_union(&mut self, i: crate::ItemUnion) -> crate::ItemUnion {
+ fold_item_union(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_item_use(&mut self, i: crate::ItemUse) -> crate::ItemUse {
+ fold_item_use(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_label(&mut self, i: crate::Label) -> crate::Label {
+ fold_label(self, i)
+ }
+ fn fold_lifetime(&mut self, i: crate::Lifetime) -> crate::Lifetime {
+ fold_lifetime(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_lifetime_param(&mut self, i: crate::LifetimeParam) -> crate::LifetimeParam {
+ fold_lifetime_param(self, i)
+ }
+ fn fold_lit(&mut self, i: crate::Lit) -> crate::Lit {
+ fold_lit(self, i)
+ }
+ fn fold_lit_bool(&mut self, i: crate::LitBool) -> crate::LitBool {
+ fold_lit_bool(self, i)
+ }
+ fn fold_lit_byte(&mut self, i: crate::LitByte) -> crate::LitByte {
+ fold_lit_byte(self, i)
+ }
+ fn fold_lit_byte_str(&mut self, i: crate::LitByteStr) -> crate::LitByteStr {
+ fold_lit_byte_str(self, i)
+ }
+ fn fold_lit_cstr(&mut self, i: crate::LitCStr) -> crate::LitCStr {
+ fold_lit_cstr(self, i)
+ }
+ fn fold_lit_char(&mut self, i: crate::LitChar) -> crate::LitChar {
+ fold_lit_char(self, i)
+ }
+ fn fold_lit_float(&mut self, i: crate::LitFloat) -> crate::LitFloat {
+ fold_lit_float(self, i)
+ }
+ fn fold_lit_int(&mut self, i: crate::LitInt) -> crate::LitInt {
+ fold_lit_int(self, i)
+ }
+ fn fold_lit_str(&mut self, i: crate::LitStr) -> crate::LitStr {
+ fold_lit_str(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_local(&mut self, i: crate::Local) -> crate::Local {
+ fold_local(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_local_init(&mut self, i: crate::LocalInit) -> crate::LocalInit {
+ fold_local_init(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_macro(&mut self, i: crate::Macro) -> crate::Macro {
+ fold_macro(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_macro_delimiter(
+ &mut self,
+ i: crate::MacroDelimiter,
+ ) -> crate::MacroDelimiter {
+ fold_macro_delimiter(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_member(&mut self, i: crate::Member) -> crate::Member {
+ fold_member(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_meta(&mut self, i: crate::Meta) -> crate::Meta {
+ fold_meta(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_meta_list(&mut self, i: crate::MetaList) -> crate::MetaList {
+ fold_meta_list(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_meta_name_value(&mut self, i: crate::MetaNameValue) -> crate::MetaNameValue {
+ fold_meta_name_value(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_parenthesized_generic_arguments(
+ &mut self,
+ i: crate::ParenthesizedGenericArguments,
+ ) -> crate::ParenthesizedGenericArguments {
+ fold_parenthesized_generic_arguments(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_pat(&mut self, i: crate::Pat) -> crate::Pat {
+ fold_pat(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_pat_ident(&mut self, i: crate::PatIdent) -> crate::PatIdent {
+ fold_pat_ident(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_pat_or(&mut self, i: crate::PatOr) -> crate::PatOr {
+ fold_pat_or(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_pat_paren(&mut self, i: crate::PatParen) -> crate::PatParen {
+ fold_pat_paren(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_pat_reference(&mut self, i: crate::PatReference) -> crate::PatReference {
+ fold_pat_reference(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_pat_rest(&mut self, i: crate::PatRest) -> crate::PatRest {
+ fold_pat_rest(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_pat_slice(&mut self, i: crate::PatSlice) -> crate::PatSlice {
+ fold_pat_slice(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_pat_struct(&mut self, i: crate::PatStruct) -> crate::PatStruct {
+ fold_pat_struct(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_pat_tuple(&mut self, i: crate::PatTuple) -> crate::PatTuple {
+ fold_pat_tuple(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_pat_tuple_struct(
+ &mut self,
+ i: crate::PatTupleStruct,
+ ) -> crate::PatTupleStruct {
+ fold_pat_tuple_struct(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_pat_type(&mut self, i: crate::PatType) -> crate::PatType {
+ fold_pat_type(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_pat_wild(&mut self, i: crate::PatWild) -> crate::PatWild {
+ fold_pat_wild(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_path(&mut self, i: crate::Path) -> crate::Path {
+ fold_path(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_path_arguments(&mut self, i: crate::PathArguments) -> crate::PathArguments {
+ fold_path_arguments(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_path_segment(&mut self, i: crate::PathSegment) -> crate::PathSegment {
+ fold_path_segment(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_pointer_mutability(
+ &mut self,
+ i: crate::PointerMutability,
+ ) -> crate::PointerMutability {
+ fold_pointer_mutability(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_precise_capture(
+ &mut self,
+ i: crate::PreciseCapture,
+ ) -> crate::PreciseCapture {
+ fold_precise_capture(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_predicate_lifetime(
+ &mut self,
+ i: crate::PredicateLifetime,
+ ) -> crate::PredicateLifetime {
+ fold_predicate_lifetime(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_predicate_type(&mut self, i: crate::PredicateType) -> crate::PredicateType {
+ fold_predicate_type(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_qself(&mut self, i: crate::QSelf) -> crate::QSelf {
+ fold_qself(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_range_limits(&mut self, i: crate::RangeLimits) -> crate::RangeLimits {
+ fold_range_limits(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_receiver(&mut self, i: crate::Receiver) -> crate::Receiver {
+ fold_receiver(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_return_type(&mut self, i: crate::ReturnType) -> crate::ReturnType {
+ fold_return_type(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_signature(&mut self, i: crate::Signature) -> crate::Signature {
+ fold_signature(self, i)
+ }
+ fn fold_span(&mut self, i: proc_macro2::Span) -> proc_macro2::Span {
+ i
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_static_mutability(
+ &mut self,
+ i: crate::StaticMutability,
+ ) -> crate::StaticMutability {
+ fold_static_mutability(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_stmt(&mut self, i: crate::Stmt) -> crate::Stmt {
+ fold_stmt(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_stmt_macro(&mut self, i: crate::StmtMacro) -> crate::StmtMacro {
+ fold_stmt_macro(self, i)
+ }
+ fn fold_token_stream(
+ &mut self,
+ i: proc_macro2::TokenStream,
+ ) -> proc_macro2::TokenStream {
+ i
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_trait_bound(&mut self, i: crate::TraitBound) -> crate::TraitBound {
+ fold_trait_bound(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_trait_bound_modifier(
+ &mut self,
+ i: crate::TraitBoundModifier,
+ ) -> crate::TraitBoundModifier {
+ fold_trait_bound_modifier(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_trait_item(&mut self, i: crate::TraitItem) -> crate::TraitItem {
+ fold_trait_item(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_trait_item_const(
+ &mut self,
+ i: crate::TraitItemConst,
+ ) -> crate::TraitItemConst {
+ fold_trait_item_const(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_trait_item_fn(&mut self, i: crate::TraitItemFn) -> crate::TraitItemFn {
+ fold_trait_item_fn(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_trait_item_macro(
+ &mut self,
+ i: crate::TraitItemMacro,
+ ) -> crate::TraitItemMacro {
+ fold_trait_item_macro(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_trait_item_type(&mut self, i: crate::TraitItemType) -> crate::TraitItemType {
+ fold_trait_item_type(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_type(&mut self, i: crate::Type) -> crate::Type {
+ fold_type(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_type_array(&mut self, i: crate::TypeArray) -> crate::TypeArray {
+ fold_type_array(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_type_bare_fn(&mut self, i: crate::TypeBareFn) -> crate::TypeBareFn {
+ fold_type_bare_fn(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_type_group(&mut self, i: crate::TypeGroup) -> crate::TypeGroup {
+ fold_type_group(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_type_impl_trait(&mut self, i: crate::TypeImplTrait) -> crate::TypeImplTrait {
+ fold_type_impl_trait(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_type_infer(&mut self, i: crate::TypeInfer) -> crate::TypeInfer {
+ fold_type_infer(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_type_macro(&mut self, i: crate::TypeMacro) -> crate::TypeMacro {
+ fold_type_macro(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_type_never(&mut self, i: crate::TypeNever) -> crate::TypeNever {
+ fold_type_never(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_type_param(&mut self, i: crate::TypeParam) -> crate::TypeParam {
+ fold_type_param(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_type_param_bound(
+ &mut self,
+ i: crate::TypeParamBound,
+ ) -> crate::TypeParamBound {
+ fold_type_param_bound(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_type_paren(&mut self, i: crate::TypeParen) -> crate::TypeParen {
+ fold_type_paren(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_type_path(&mut self, i: crate::TypePath) -> crate::TypePath {
+ fold_type_path(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_type_ptr(&mut self, i: crate::TypePtr) -> crate::TypePtr {
+ fold_type_ptr(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_type_reference(&mut self, i: crate::TypeReference) -> crate::TypeReference {
+ fold_type_reference(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_type_slice(&mut self, i: crate::TypeSlice) -> crate::TypeSlice {
+ fold_type_slice(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_type_trait_object(
+ &mut self,
+ i: crate::TypeTraitObject,
+ ) -> crate::TypeTraitObject {
+ fold_type_trait_object(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_type_tuple(&mut self, i: crate::TypeTuple) -> crate::TypeTuple {
+ fold_type_tuple(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_un_op(&mut self, i: crate::UnOp) -> crate::UnOp {
+ fold_un_op(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_use_glob(&mut self, i: crate::UseGlob) -> crate::UseGlob {
+ fold_use_glob(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_use_group(&mut self, i: crate::UseGroup) -> crate::UseGroup {
+ fold_use_group(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_use_name(&mut self, i: crate::UseName) -> crate::UseName {
+ fold_use_name(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_use_path(&mut self, i: crate::UsePath) -> crate::UsePath {
+ fold_use_path(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_use_rename(&mut self, i: crate::UseRename) -> crate::UseRename {
+ fold_use_rename(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_use_tree(&mut self, i: crate::UseTree) -> crate::UseTree {
+ fold_use_tree(self, i)
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn fold_variadic(&mut self, i: crate::Variadic) -> crate::Variadic {
+ fold_variadic(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_variant(&mut self, i: crate::Variant) -> crate::Variant {
+ fold_variant(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_vis_restricted(&mut self, i: crate::VisRestricted) -> crate::VisRestricted {
+ fold_vis_restricted(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_visibility(&mut self, i: crate::Visibility) -> crate::Visibility {
+ fold_visibility(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_where_clause(&mut self, i: crate::WhereClause) -> crate::WhereClause {
+ fold_where_clause(self, i)
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn fold_where_predicate(
+ &mut self,
+ i: crate::WherePredicate,
+ ) -> crate::WherePredicate {
+ fold_where_predicate(self, i)
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_abi<F>(f: &mut F, node: crate::Abi) -> crate::Abi
+where
+ F: Fold + ?Sized,
+{
+ crate::Abi {
+ extern_token: node.extern_token,
+ name: (node.name).map(|it| f.fold_lit_str(it)),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_angle_bracketed_generic_arguments<F>(
+ f: &mut F,
+ node: crate::AngleBracketedGenericArguments,
+) -> crate::AngleBracketedGenericArguments
+where
+ F: Fold + ?Sized,
+{
+ crate::AngleBracketedGenericArguments {
+ colon2_token: node.colon2_token,
+ lt_token: node.lt_token,
+ args: crate::punctuated::fold(node.args, f, F::fold_generic_argument),
+ gt_token: node.gt_token,
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_arm<F>(f: &mut F, node: crate::Arm) -> crate::Arm
+where
+ F: Fold + ?Sized,
+{
+ crate::Arm {
+ attrs: f.fold_attributes(node.attrs),
+ pat: f.fold_pat(node.pat),
+ guard: (node.guard).map(|it| ((it).0, Box::new(f.fold_expr(*(it).1)))),
+ fat_arrow_token: node.fat_arrow_token,
+ body: Box::new(f.fold_expr(*node.body)),
+ comma: node.comma,
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_assoc_const<F>(f: &mut F, node: crate::AssocConst) -> crate::AssocConst
+where
+ F: Fold + ?Sized,
+{
+ crate::AssocConst {
+ ident: f.fold_ident(node.ident),
+ generics: (node.generics).map(|it| f.fold_angle_bracketed_generic_arguments(it)),
+ eq_token: node.eq_token,
+ value: f.fold_expr(node.value),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_assoc_type<F>(f: &mut F, node: crate::AssocType) -> crate::AssocType
+where
+ F: Fold + ?Sized,
+{
+ crate::AssocType {
+ ident: f.fold_ident(node.ident),
+ generics: (node.generics).map(|it| f.fold_angle_bracketed_generic_arguments(it)),
+ eq_token: node.eq_token,
+ ty: f.fold_type(node.ty),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_attr_style<F>(f: &mut F, node: crate::AttrStyle) -> crate::AttrStyle
+where
+ F: Fold + ?Sized,
+{
+ match node {
+ crate::AttrStyle::Outer => crate::AttrStyle::Outer,
+ crate::AttrStyle::Inner(_binding_0) => crate::AttrStyle::Inner(_binding_0),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_attribute<F>(f: &mut F, node: crate::Attribute) -> crate::Attribute
+where
+ F: Fold + ?Sized,
+{
+ crate::Attribute {
+ pound_token: node.pound_token,
+ style: f.fold_attr_style(node.style),
+ bracket_token: node.bracket_token,
+ meta: f.fold_meta(node.meta),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_bare_fn_arg<F>(f: &mut F, node: crate::BareFnArg) -> crate::BareFnArg
+where
+ F: Fold + ?Sized,
+{
+ crate::BareFnArg {
+ attrs: f.fold_attributes(node.attrs),
+ name: (node.name).map(|it| (f.fold_ident((it).0), (it).1)),
+ ty: f.fold_type(node.ty),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_bare_variadic<F>(f: &mut F, node: crate::BareVariadic) -> crate::BareVariadic
+where
+ F: Fold + ?Sized,
+{
+ crate::BareVariadic {
+ attrs: f.fold_attributes(node.attrs),
+ name: (node.name).map(|it| (f.fold_ident((it).0), (it).1)),
+ dots: node.dots,
+ comma: node.comma,
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_bin_op<F>(f: &mut F, node: crate::BinOp) -> crate::BinOp
+where
+ F: Fold + ?Sized,
+{
+ match node {
+ crate::BinOp::Add(_binding_0) => crate::BinOp::Add(_binding_0),
+ crate::BinOp::Sub(_binding_0) => crate::BinOp::Sub(_binding_0),
+ crate::BinOp::Mul(_binding_0) => crate::BinOp::Mul(_binding_0),
+ crate::BinOp::Div(_binding_0) => crate::BinOp::Div(_binding_0),
+ crate::BinOp::Rem(_binding_0) => crate::BinOp::Rem(_binding_0),
+ crate::BinOp::And(_binding_0) => crate::BinOp::And(_binding_0),
+ crate::BinOp::Or(_binding_0) => crate::BinOp::Or(_binding_0),
+ crate::BinOp::BitXor(_binding_0) => crate::BinOp::BitXor(_binding_0),
+ crate::BinOp::BitAnd(_binding_0) => crate::BinOp::BitAnd(_binding_0),
+ crate::BinOp::BitOr(_binding_0) => crate::BinOp::BitOr(_binding_0),
+ crate::BinOp::Shl(_binding_0) => crate::BinOp::Shl(_binding_0),
+ crate::BinOp::Shr(_binding_0) => crate::BinOp::Shr(_binding_0),
+ crate::BinOp::Eq(_binding_0) => crate::BinOp::Eq(_binding_0),
+ crate::BinOp::Lt(_binding_0) => crate::BinOp::Lt(_binding_0),
+ crate::BinOp::Le(_binding_0) => crate::BinOp::Le(_binding_0),
+ crate::BinOp::Ne(_binding_0) => crate::BinOp::Ne(_binding_0),
+ crate::BinOp::Ge(_binding_0) => crate::BinOp::Ge(_binding_0),
+ crate::BinOp::Gt(_binding_0) => crate::BinOp::Gt(_binding_0),
+ crate::BinOp::AddAssign(_binding_0) => crate::BinOp::AddAssign(_binding_0),
+ crate::BinOp::SubAssign(_binding_0) => crate::BinOp::SubAssign(_binding_0),
+ crate::BinOp::MulAssign(_binding_0) => crate::BinOp::MulAssign(_binding_0),
+ crate::BinOp::DivAssign(_binding_0) => crate::BinOp::DivAssign(_binding_0),
+ crate::BinOp::RemAssign(_binding_0) => crate::BinOp::RemAssign(_binding_0),
+ crate::BinOp::BitXorAssign(_binding_0) => crate::BinOp::BitXorAssign(_binding_0),
+ crate::BinOp::BitAndAssign(_binding_0) => crate::BinOp::BitAndAssign(_binding_0),
+ crate::BinOp::BitOrAssign(_binding_0) => crate::BinOp::BitOrAssign(_binding_0),
+ crate::BinOp::ShlAssign(_binding_0) => crate::BinOp::ShlAssign(_binding_0),
+ crate::BinOp::ShrAssign(_binding_0) => crate::BinOp::ShrAssign(_binding_0),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_block<F>(f: &mut F, node: crate::Block) -> crate::Block
+where
+ F: Fold + ?Sized,
+{
+ crate::Block {
+ brace_token: node.brace_token,
+ stmts: fold_vec(node.stmts, f, F::fold_stmt),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_bound_lifetimes<F>(
+ f: &mut F,
+ node: crate::BoundLifetimes,
+) -> crate::BoundLifetimes
+where
+ F: Fold + ?Sized,
+{
+ crate::BoundLifetimes {
+ for_token: node.for_token,
+ lt_token: node.lt_token,
+ lifetimes: crate::punctuated::fold(node.lifetimes, f, F::fold_generic_param),
+ gt_token: node.gt_token,
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_captured_param<F>(
+ f: &mut F,
+ node: crate::CapturedParam,
+) -> crate::CapturedParam
+where
+ F: Fold + ?Sized,
+{
+ match node {
+ crate::CapturedParam::Lifetime(_binding_0) => {
+ crate::CapturedParam::Lifetime(f.fold_lifetime(_binding_0))
+ }
+ crate::CapturedParam::Ident(_binding_0) => {
+ crate::CapturedParam::Ident(f.fold_ident(_binding_0))
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_const_param<F>(f: &mut F, node: crate::ConstParam) -> crate::ConstParam
+where
+ F: Fold + ?Sized,
+{
+ crate::ConstParam {
+ attrs: f.fold_attributes(node.attrs),
+ const_token: node.const_token,
+ ident: f.fold_ident(node.ident),
+ colon_token: node.colon_token,
+ ty: f.fold_type(node.ty),
+ eq_token: node.eq_token,
+ default: (node.default).map(|it| f.fold_expr(it)),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_constraint<F>(f: &mut F, node: crate::Constraint) -> crate::Constraint
+where
+ F: Fold + ?Sized,
+{
+ crate::Constraint {
+ ident: f.fold_ident(node.ident),
+ generics: (node.generics).map(|it| f.fold_angle_bracketed_generic_arguments(it)),
+ colon_token: node.colon_token,
+ bounds: crate::punctuated::fold(node.bounds, f, F::fold_type_param_bound),
+ }
+}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
+pub fn fold_data<F>(f: &mut F, node: crate::Data) -> crate::Data
+where
+ F: Fold + ?Sized,
+{
+ match node {
+ crate::Data::Struct(_binding_0) => {
+ crate::Data::Struct(f.fold_data_struct(_binding_0))
+ }
+ crate::Data::Enum(_binding_0) => crate::Data::Enum(f.fold_data_enum(_binding_0)),
+ crate::Data::Union(_binding_0) => {
+ crate::Data::Union(f.fold_data_union(_binding_0))
+ }
+ }
+}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
+pub fn fold_data_enum<F>(f: &mut F, node: crate::DataEnum) -> crate::DataEnum
+where
+ F: Fold + ?Sized,
+{
+ crate::DataEnum {
+ enum_token: node.enum_token,
+ brace_token: node.brace_token,
+ variants: crate::punctuated::fold(node.variants, f, F::fold_variant),
+ }
+}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
+pub fn fold_data_struct<F>(f: &mut F, node: crate::DataStruct) -> crate::DataStruct
+where
+ F: Fold + ?Sized,
+{
+ crate::DataStruct {
+ struct_token: node.struct_token,
+ fields: f.fold_fields(node.fields),
+ semi_token: node.semi_token,
+ }
+}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
+pub fn fold_data_union<F>(f: &mut F, node: crate::DataUnion) -> crate::DataUnion
+where
+ F: Fold + ?Sized,
+{
+ crate::DataUnion {
+ union_token: node.union_token,
+ fields: f.fold_fields_named(node.fields),
+ }
+}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
+pub fn fold_derive_input<F>(f: &mut F, node: crate::DeriveInput) -> crate::DeriveInput
+where
+ F: Fold + ?Sized,
+{
+ crate::DeriveInput {
+ attrs: f.fold_attributes(node.attrs),
+ vis: f.fold_visibility(node.vis),
+ ident: f.fold_ident(node.ident),
+ generics: f.fold_generics(node.generics),
+ data: f.fold_data(node.data),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_expr<F>(f: &mut F, node: crate::Expr) -> crate::Expr
+where
+ F: Fold + ?Sized,
+{
+ match node {
+ crate::Expr::Array(_binding_0) => {
+ crate::Expr::Array(full!(f.fold_expr_array(_binding_0)))
+ }
+ crate::Expr::Assign(_binding_0) => {
+ crate::Expr::Assign(full!(f.fold_expr_assign(_binding_0)))
+ }
+ crate::Expr::Async(_binding_0) => {
+ crate::Expr::Async(full!(f.fold_expr_async(_binding_0)))
+ }
+ crate::Expr::Await(_binding_0) => {
+ crate::Expr::Await(full!(f.fold_expr_await(_binding_0)))
+ }
+ crate::Expr::Binary(_binding_0) => {
+ crate::Expr::Binary(f.fold_expr_binary(_binding_0))
+ }
+ crate::Expr::Block(_binding_0) => {
+ crate::Expr::Block(full!(f.fold_expr_block(_binding_0)))
+ }
+ crate::Expr::Break(_binding_0) => {
+ crate::Expr::Break(full!(f.fold_expr_break(_binding_0)))
+ }
+ crate::Expr::Call(_binding_0) => crate::Expr::Call(f.fold_expr_call(_binding_0)),
+ crate::Expr::Cast(_binding_0) => crate::Expr::Cast(f.fold_expr_cast(_binding_0)),
+ crate::Expr::Closure(_binding_0) => {
+ crate::Expr::Closure(full!(f.fold_expr_closure(_binding_0)))
+ }
+ crate::Expr::Const(_binding_0) => {
+ crate::Expr::Const(full!(f.fold_expr_const(_binding_0)))
+ }
+ crate::Expr::Continue(_binding_0) => {
+ crate::Expr::Continue(full!(f.fold_expr_continue(_binding_0)))
+ }
+ crate::Expr::Field(_binding_0) => {
+ crate::Expr::Field(f.fold_expr_field(_binding_0))
+ }
+ crate::Expr::ForLoop(_binding_0) => {
+ crate::Expr::ForLoop(full!(f.fold_expr_for_loop(_binding_0)))
+ }
+ crate::Expr::Group(_binding_0) => {
+ crate::Expr::Group(f.fold_expr_group(_binding_0))
+ }
+ crate::Expr::If(_binding_0) => crate::Expr::If(full!(f.fold_expr_if(_binding_0))),
+ crate::Expr::Index(_binding_0) => {
+ crate::Expr::Index(f.fold_expr_index(_binding_0))
+ }
+ crate::Expr::Infer(_binding_0) => {
+ crate::Expr::Infer(full!(f.fold_expr_infer(_binding_0)))
+ }
+ crate::Expr::Let(_binding_0) => {
+ crate::Expr::Let(full!(f.fold_expr_let(_binding_0)))
+ }
+ crate::Expr::Lit(_binding_0) => crate::Expr::Lit(f.fold_expr_lit(_binding_0)),
+ crate::Expr::Loop(_binding_0) => {
+ crate::Expr::Loop(full!(f.fold_expr_loop(_binding_0)))
+ }
+ crate::Expr::Macro(_binding_0) => {
+ crate::Expr::Macro(f.fold_expr_macro(_binding_0))
+ }
+ crate::Expr::Match(_binding_0) => {
+ crate::Expr::Match(full!(f.fold_expr_match(_binding_0)))
+ }
+ crate::Expr::MethodCall(_binding_0) => {
+ crate::Expr::MethodCall(f.fold_expr_method_call(_binding_0))
+ }
+ crate::Expr::Paren(_binding_0) => {
+ crate::Expr::Paren(f.fold_expr_paren(_binding_0))
+ }
+ crate::Expr::Path(_binding_0) => crate::Expr::Path(f.fold_expr_path(_binding_0)),
+ crate::Expr::Range(_binding_0) => {
+ crate::Expr::Range(full!(f.fold_expr_range(_binding_0)))
+ }
+ crate::Expr::RawAddr(_binding_0) => {
+ crate::Expr::RawAddr(full!(f.fold_expr_raw_addr(_binding_0)))
+ }
+ crate::Expr::Reference(_binding_0) => {
+ crate::Expr::Reference(f.fold_expr_reference(_binding_0))
+ }
+ crate::Expr::Repeat(_binding_0) => {
+ crate::Expr::Repeat(full!(f.fold_expr_repeat(_binding_0)))
+ }
+ crate::Expr::Return(_binding_0) => {
+ crate::Expr::Return(full!(f.fold_expr_return(_binding_0)))
+ }
+ crate::Expr::Struct(_binding_0) => {
+ crate::Expr::Struct(f.fold_expr_struct(_binding_0))
+ }
+ crate::Expr::Try(_binding_0) => {
+ crate::Expr::Try(full!(f.fold_expr_try(_binding_0)))
+ }
+ crate::Expr::TryBlock(_binding_0) => {
+ crate::Expr::TryBlock(full!(f.fold_expr_try_block(_binding_0)))
+ }
+ crate::Expr::Tuple(_binding_0) => {
+ crate::Expr::Tuple(f.fold_expr_tuple(_binding_0))
+ }
+ crate::Expr::Unary(_binding_0) => {
+ crate::Expr::Unary(f.fold_expr_unary(_binding_0))
+ }
+ crate::Expr::Unsafe(_binding_0) => {
+ crate::Expr::Unsafe(full!(f.fold_expr_unsafe(_binding_0)))
+ }
+ crate::Expr::Verbatim(_binding_0) => {
+ crate::Expr::Verbatim(f.fold_token_stream(_binding_0))
+ }
+ crate::Expr::While(_binding_0) => {
+ crate::Expr::While(full!(f.fold_expr_while(_binding_0)))
+ }
+ crate::Expr::Yield(_binding_0) => {
+ crate::Expr::Yield(full!(f.fold_expr_yield(_binding_0)))
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_expr_array<F>(f: &mut F, node: crate::ExprArray) -> crate::ExprArray
+where
+ F: Fold + ?Sized,
+{
+ crate::ExprArray {
+ attrs: f.fold_attributes(node.attrs),
+ bracket_token: node.bracket_token,
+ elems: crate::punctuated::fold(node.elems, f, F::fold_expr),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_expr_assign<F>(f: &mut F, node: crate::ExprAssign) -> crate::ExprAssign
+where
+ F: Fold + ?Sized,
+{
+ crate::ExprAssign {
+ attrs: f.fold_attributes(node.attrs),
+ left: Box::new(f.fold_expr(*node.left)),
+ eq_token: node.eq_token,
+ right: Box::new(f.fold_expr(*node.right)),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_expr_async<F>(f: &mut F, node: crate::ExprAsync) -> crate::ExprAsync
+where
+ F: Fold + ?Sized,
+{
+ crate::ExprAsync {
+ attrs: f.fold_attributes(node.attrs),
+ async_token: node.async_token,
+ capture: node.capture,
+ block: f.fold_block(node.block),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_expr_await<F>(f: &mut F, node: crate::ExprAwait) -> crate::ExprAwait
+where
+ F: Fold + ?Sized,
+{
+ crate::ExprAwait {
+ attrs: f.fold_attributes(node.attrs),
+ base: Box::new(f.fold_expr(*node.base)),
+ dot_token: node.dot_token,
+ await_token: node.await_token,
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_expr_binary<F>(f: &mut F, node: crate::ExprBinary) -> crate::ExprBinary
+where
+ F: Fold + ?Sized,
+{
+ crate::ExprBinary {
+ attrs: f.fold_attributes(node.attrs),
+ left: Box::new(f.fold_expr(*node.left)),
+ op: f.fold_bin_op(node.op),
+ right: Box::new(f.fold_expr(*node.right)),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_expr_block<F>(f: &mut F, node: crate::ExprBlock) -> crate::ExprBlock
+where
+ F: Fold + ?Sized,
+{
+ crate::ExprBlock {
+ attrs: f.fold_attributes(node.attrs),
+ label: (node.label).map(|it| f.fold_label(it)),
+ block: f.fold_block(node.block),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_expr_break<F>(f: &mut F, node: crate::ExprBreak) -> crate::ExprBreak
+where
+ F: Fold + ?Sized,
+{
+ crate::ExprBreak {
+ attrs: f.fold_attributes(node.attrs),
+ break_token: node.break_token,
+ label: (node.label).map(|it| f.fold_lifetime(it)),
+ expr: (node.expr).map(|it| Box::new(f.fold_expr(*it))),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_expr_call<F>(f: &mut F, node: crate::ExprCall) -> crate::ExprCall
+where
+ F: Fold + ?Sized,
+{
+ crate::ExprCall {
+ attrs: f.fold_attributes(node.attrs),
+ func: Box::new(f.fold_expr(*node.func)),
+ paren_token: node.paren_token,
+ args: crate::punctuated::fold(node.args, f, F::fold_expr),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_expr_cast<F>(f: &mut F, node: crate::ExprCast) -> crate::ExprCast
+where
+ F: Fold + ?Sized,
+{
+ crate::ExprCast {
+ attrs: f.fold_attributes(node.attrs),
+ expr: Box::new(f.fold_expr(*node.expr)),
+ as_token: node.as_token,
+ ty: Box::new(f.fold_type(*node.ty)),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_expr_closure<F>(f: &mut F, node: crate::ExprClosure) -> crate::ExprClosure
+where
+ F: Fold + ?Sized,
+{
+ crate::ExprClosure {
+ attrs: f.fold_attributes(node.attrs),
+ lifetimes: (node.lifetimes).map(|it| f.fold_bound_lifetimes(it)),
+ constness: node.constness,
+ movability: node.movability,
+ asyncness: node.asyncness,
+ capture: node.capture,
+ or1_token: node.or1_token,
+ inputs: crate::punctuated::fold(node.inputs, f, F::fold_pat),
+ or2_token: node.or2_token,
+ output: f.fold_return_type(node.output),
+ body: Box::new(f.fold_expr(*node.body)),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_expr_const<F>(f: &mut F, node: crate::ExprConst) -> crate::ExprConst
+where
+ F: Fold + ?Sized,
+{
+ crate::ExprConst {
+ attrs: f.fold_attributes(node.attrs),
+ const_token: node.const_token,
+ block: f.fold_block(node.block),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_expr_continue<F>(f: &mut F, node: crate::ExprContinue) -> crate::ExprContinue
+where
+ F: Fold + ?Sized,
+{
+ crate::ExprContinue {
+ attrs: f.fold_attributes(node.attrs),
+ continue_token: node.continue_token,
+ label: (node.label).map(|it| f.fold_lifetime(it)),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_expr_field<F>(f: &mut F, node: crate::ExprField) -> crate::ExprField
+where
+ F: Fold + ?Sized,
+{
+ crate::ExprField {
+ attrs: f.fold_attributes(node.attrs),
+ base: Box::new(f.fold_expr(*node.base)),
+ dot_token: node.dot_token,
+ member: f.fold_member(node.member),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_expr_for_loop<F>(f: &mut F, node: crate::ExprForLoop) -> crate::ExprForLoop
+where
+ F: Fold + ?Sized,
+{
+ crate::ExprForLoop {
+ attrs: f.fold_attributes(node.attrs),
+ label: (node.label).map(|it| f.fold_label(it)),
+ for_token: node.for_token,
+ pat: Box::new(f.fold_pat(*node.pat)),
+ in_token: node.in_token,
+ expr: Box::new(f.fold_expr(*node.expr)),
+ body: f.fold_block(node.body),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_expr_group<F>(f: &mut F, node: crate::ExprGroup) -> crate::ExprGroup
+where
+ F: Fold + ?Sized,
+{
+ crate::ExprGroup {
+ attrs: f.fold_attributes(node.attrs),
+ group_token: node.group_token,
+ expr: Box::new(f.fold_expr(*node.expr)),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_expr_if<F>(f: &mut F, node: crate::ExprIf) -> crate::ExprIf
+where
+ F: Fold + ?Sized,
+{
+ crate::ExprIf {
+ attrs: f.fold_attributes(node.attrs),
+ if_token: node.if_token,
+ cond: Box::new(f.fold_expr(*node.cond)),
+ then_branch: f.fold_block(node.then_branch),
+ else_branch: (node.else_branch)
+ .map(|it| ((it).0, Box::new(f.fold_expr(*(it).1)))),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_expr_index<F>(f: &mut F, node: crate::ExprIndex) -> crate::ExprIndex
+where
+ F: Fold + ?Sized,
+{
+ crate::ExprIndex {
+ attrs: f.fold_attributes(node.attrs),
+ expr: Box::new(f.fold_expr(*node.expr)),
+ bracket_token: node.bracket_token,
+ index: Box::new(f.fold_expr(*node.index)),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_expr_infer<F>(f: &mut F, node: crate::ExprInfer) -> crate::ExprInfer
+where
+ F: Fold + ?Sized,
+{
+ crate::ExprInfer {
+ attrs: f.fold_attributes(node.attrs),
+ underscore_token: node.underscore_token,
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_expr_let<F>(f: &mut F, node: crate::ExprLet) -> crate::ExprLet
+where
+ F: Fold + ?Sized,
+{
+ crate::ExprLet {
+ attrs: f.fold_attributes(node.attrs),
+ let_token: node.let_token,
+ pat: Box::new(f.fold_pat(*node.pat)),
+ eq_token: node.eq_token,
+ expr: Box::new(f.fold_expr(*node.expr)),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_expr_lit<F>(f: &mut F, node: crate::ExprLit) -> crate::ExprLit
+where
+ F: Fold + ?Sized,
+{
+ crate::ExprLit {
+ attrs: f.fold_attributes(node.attrs),
+ lit: f.fold_lit(node.lit),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_expr_loop<F>(f: &mut F, node: crate::ExprLoop) -> crate::ExprLoop
+where
+ F: Fold + ?Sized,
+{
+ crate::ExprLoop {
+ attrs: f.fold_attributes(node.attrs),
+ label: (node.label).map(|it| f.fold_label(it)),
+ loop_token: node.loop_token,
+ body: f.fold_block(node.body),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_expr_macro<F>(f: &mut F, node: crate::ExprMacro) -> crate::ExprMacro
+where
+ F: Fold + ?Sized,
+{
+ crate::ExprMacro {
+ attrs: f.fold_attributes(node.attrs),
+ mac: f.fold_macro(node.mac),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_expr_match<F>(f: &mut F, node: crate::ExprMatch) -> crate::ExprMatch
+where
+ F: Fold + ?Sized,
+{
+ crate::ExprMatch {
+ attrs: f.fold_attributes(node.attrs),
+ match_token: node.match_token,
+ expr: Box::new(f.fold_expr(*node.expr)),
+ brace_token: node.brace_token,
+ arms: fold_vec(node.arms, f, F::fold_arm),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_expr_method_call<F>(
+ f: &mut F,
+ node: crate::ExprMethodCall,
+) -> crate::ExprMethodCall
+where
+ F: Fold + ?Sized,
+{
+ crate::ExprMethodCall {
+ attrs: f.fold_attributes(node.attrs),
+ receiver: Box::new(f.fold_expr(*node.receiver)),
+ dot_token: node.dot_token,
+ method: f.fold_ident(node.method),
+ turbofish: (node.turbofish)
+ .map(|it| f.fold_angle_bracketed_generic_arguments(it)),
+ paren_token: node.paren_token,
+ args: crate::punctuated::fold(node.args, f, F::fold_expr),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_expr_paren<F>(f: &mut F, node: crate::ExprParen) -> crate::ExprParen
+where
+ F: Fold + ?Sized,
+{
+ crate::ExprParen {
+ attrs: f.fold_attributes(node.attrs),
+ paren_token: node.paren_token,
+ expr: Box::new(f.fold_expr(*node.expr)),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_expr_path<F>(f: &mut F, node: crate::ExprPath) -> crate::ExprPath
+where
+ F: Fold + ?Sized,
+{
+ crate::ExprPath {
+ attrs: f.fold_attributes(node.attrs),
+ qself: (node.qself).map(|it| f.fold_qself(it)),
+ path: f.fold_path(node.path),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_expr_range<F>(f: &mut F, node: crate::ExprRange) -> crate::ExprRange
+where
+ F: Fold + ?Sized,
+{
+ crate::ExprRange {
+ attrs: f.fold_attributes(node.attrs),
+ start: (node.start).map(|it| Box::new(f.fold_expr(*it))),
+ limits: f.fold_range_limits(node.limits),
+ end: (node.end).map(|it| Box::new(f.fold_expr(*it))),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_expr_raw_addr<F>(f: &mut F, node: crate::ExprRawAddr) -> crate::ExprRawAddr
+where
+ F: Fold + ?Sized,
+{
+ crate::ExprRawAddr {
+ attrs: f.fold_attributes(node.attrs),
+ and_token: node.and_token,
+ raw: node.raw,
+ mutability: f.fold_pointer_mutability(node.mutability),
+ expr: Box::new(f.fold_expr(*node.expr)),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_expr_reference<F>(
+ f: &mut F,
+ node: crate::ExprReference,
+) -> crate::ExprReference
+where
+ F: Fold + ?Sized,
+{
+ crate::ExprReference {
+ attrs: f.fold_attributes(node.attrs),
+ and_token: node.and_token,
+ mutability: node.mutability,
+ expr: Box::new(f.fold_expr(*node.expr)),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_expr_repeat<F>(f: &mut F, node: crate::ExprRepeat) -> crate::ExprRepeat
+where
+ F: Fold + ?Sized,
+{
+ crate::ExprRepeat {
+ attrs: f.fold_attributes(node.attrs),
+ bracket_token: node.bracket_token,
+ expr: Box::new(f.fold_expr(*node.expr)),
+ semi_token: node.semi_token,
+ len: Box::new(f.fold_expr(*node.len)),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_expr_return<F>(f: &mut F, node: crate::ExprReturn) -> crate::ExprReturn
+where
+ F: Fold + ?Sized,
+{
+ crate::ExprReturn {
+ attrs: f.fold_attributes(node.attrs),
+ return_token: node.return_token,
+ expr: (node.expr).map(|it| Box::new(f.fold_expr(*it))),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_expr_struct<F>(f: &mut F, node: crate::ExprStruct) -> crate::ExprStruct
+where
+ F: Fold + ?Sized,
+{
+ crate::ExprStruct {
+ attrs: f.fold_attributes(node.attrs),
+ qself: (node.qself).map(|it| f.fold_qself(it)),
+ path: f.fold_path(node.path),
+ brace_token: node.brace_token,
+ fields: crate::punctuated::fold(node.fields, f, F::fold_field_value),
+ dot2_token: node.dot2_token,
+ rest: (node.rest).map(|it| Box::new(f.fold_expr(*it))),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_expr_try<F>(f: &mut F, node: crate::ExprTry) -> crate::ExprTry
+where
+ F: Fold + ?Sized,
+{
+ crate::ExprTry {
+ attrs: f.fold_attributes(node.attrs),
+ expr: Box::new(f.fold_expr(*node.expr)),
+ question_token: node.question_token,
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_expr_try_block<F>(
+ f: &mut F,
+ node: crate::ExprTryBlock,
+) -> crate::ExprTryBlock
+where
+ F: Fold + ?Sized,
+{
+ crate::ExprTryBlock {
+ attrs: f.fold_attributes(node.attrs),
+ try_token: node.try_token,
+ block: f.fold_block(node.block),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_expr_tuple<F>(f: &mut F, node: crate::ExprTuple) -> crate::ExprTuple
+where
+ F: Fold + ?Sized,
+{
+ crate::ExprTuple {
+ attrs: f.fold_attributes(node.attrs),
+ paren_token: node.paren_token,
+ elems: crate::punctuated::fold(node.elems, f, F::fold_expr),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_expr_unary<F>(f: &mut F, node: crate::ExprUnary) -> crate::ExprUnary
+where
+ F: Fold + ?Sized,
+{
+ crate::ExprUnary {
+ attrs: f.fold_attributes(node.attrs),
+ op: f.fold_un_op(node.op),
+ expr: Box::new(f.fold_expr(*node.expr)),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_expr_unsafe<F>(f: &mut F, node: crate::ExprUnsafe) -> crate::ExprUnsafe
+where
+ F: Fold + ?Sized,
+{
+ crate::ExprUnsafe {
+ attrs: f.fold_attributes(node.attrs),
+ unsafe_token: node.unsafe_token,
+ block: f.fold_block(node.block),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_expr_while<F>(f: &mut F, node: crate::ExprWhile) -> crate::ExprWhile
+where
+ F: Fold + ?Sized,
+{
+ crate::ExprWhile {
+ attrs: f.fold_attributes(node.attrs),
+ label: (node.label).map(|it| f.fold_label(it)),
+ while_token: node.while_token,
+ cond: Box::new(f.fold_expr(*node.cond)),
+ body: f.fold_block(node.body),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_expr_yield<F>(f: &mut F, node: crate::ExprYield) -> crate::ExprYield
+where
+ F: Fold + ?Sized,
+{
+ crate::ExprYield {
+ attrs: f.fold_attributes(node.attrs),
+ yield_token: node.yield_token,
+ expr: (node.expr).map(|it| Box::new(f.fold_expr(*it))),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_field<F>(f: &mut F, node: crate::Field) -> crate::Field
+where
+ F: Fold + ?Sized,
+{
+ crate::Field {
+ attrs: f.fold_attributes(node.attrs),
+ vis: f.fold_visibility(node.vis),
+ mutability: f.fold_field_mutability(node.mutability),
+ ident: (node.ident).map(|it| f.fold_ident(it)),
+ colon_token: node.colon_token,
+ ty: f.fold_type(node.ty),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_field_mutability<F>(
+ f: &mut F,
+ node: crate::FieldMutability,
+) -> crate::FieldMutability
+where
+ F: Fold + ?Sized,
+{
+ match node {
+ crate::FieldMutability::None => crate::FieldMutability::None,
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_field_pat<F>(f: &mut F, node: crate::FieldPat) -> crate::FieldPat
+where
+ F: Fold + ?Sized,
+{
+ crate::FieldPat {
+ attrs: f.fold_attributes(node.attrs),
+ member: f.fold_member(node.member),
+ colon_token: node.colon_token,
+ pat: Box::new(f.fold_pat(*node.pat)),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_field_value<F>(f: &mut F, node: crate::FieldValue) -> crate::FieldValue
+where
+ F: Fold + ?Sized,
+{
+ crate::FieldValue {
+ attrs: f.fold_attributes(node.attrs),
+ member: f.fold_member(node.member),
+ colon_token: node.colon_token,
+ expr: f.fold_expr(node.expr),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_fields<F>(f: &mut F, node: crate::Fields) -> crate::Fields
+where
+ F: Fold + ?Sized,
+{
+ match node {
+ crate::Fields::Named(_binding_0) => {
+ crate::Fields::Named(f.fold_fields_named(_binding_0))
+ }
+ crate::Fields::Unnamed(_binding_0) => {
+ crate::Fields::Unnamed(f.fold_fields_unnamed(_binding_0))
+ }
+ crate::Fields::Unit => crate::Fields::Unit,
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_fields_named<F>(f: &mut F, node: crate::FieldsNamed) -> crate::FieldsNamed
+where
+ F: Fold + ?Sized,
+{
+ crate::FieldsNamed {
+ brace_token: node.brace_token,
+ named: crate::punctuated::fold(node.named, f, F::fold_field),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_fields_unnamed<F>(
+ f: &mut F,
+ node: crate::FieldsUnnamed,
+) -> crate::FieldsUnnamed
+where
+ F: Fold + ?Sized,
+{
+ crate::FieldsUnnamed {
+ paren_token: node.paren_token,
+ unnamed: crate::punctuated::fold(node.unnamed, f, F::fold_field),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_file<F>(f: &mut F, node: crate::File) -> crate::File
+where
+ F: Fold + ?Sized,
+{
+ crate::File {
+ shebang: node.shebang,
+ attrs: f.fold_attributes(node.attrs),
+ items: fold_vec(node.items, f, F::fold_item),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_fn_arg<F>(f: &mut F, node: crate::FnArg) -> crate::FnArg
+where
+ F: Fold + ?Sized,
+{
+ match node {
+ crate::FnArg::Receiver(_binding_0) => {
+ crate::FnArg::Receiver(f.fold_receiver(_binding_0))
+ }
+ crate::FnArg::Typed(_binding_0) => {
+ crate::FnArg::Typed(f.fold_pat_type(_binding_0))
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_foreign_item<F>(f: &mut F, node: crate::ForeignItem) -> crate::ForeignItem
+where
+ F: Fold + ?Sized,
+{
+ match node {
+ crate::ForeignItem::Fn(_binding_0) => {
+ crate::ForeignItem::Fn(f.fold_foreign_item_fn(_binding_0))
+ }
+ crate::ForeignItem::Static(_binding_0) => {
+ crate::ForeignItem::Static(f.fold_foreign_item_static(_binding_0))
+ }
+ crate::ForeignItem::Type(_binding_0) => {
+ crate::ForeignItem::Type(f.fold_foreign_item_type(_binding_0))
+ }
+ crate::ForeignItem::Macro(_binding_0) => {
+ crate::ForeignItem::Macro(f.fold_foreign_item_macro(_binding_0))
+ }
+ crate::ForeignItem::Verbatim(_binding_0) => {
+ crate::ForeignItem::Verbatim(f.fold_token_stream(_binding_0))
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_foreign_item_fn<F>(
+ f: &mut F,
+ node: crate::ForeignItemFn,
+) -> crate::ForeignItemFn
+where
+ F: Fold + ?Sized,
+{
+ crate::ForeignItemFn {
+ attrs: f.fold_attributes(node.attrs),
+ vis: f.fold_visibility(node.vis),
+ sig: f.fold_signature(node.sig),
+ semi_token: node.semi_token,
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_foreign_item_macro<F>(
+ f: &mut F,
+ node: crate::ForeignItemMacro,
+) -> crate::ForeignItemMacro
+where
+ F: Fold + ?Sized,
+{
+ crate::ForeignItemMacro {
+ attrs: f.fold_attributes(node.attrs),
+ mac: f.fold_macro(node.mac),
+ semi_token: node.semi_token,
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_foreign_item_static<F>(
+ f: &mut F,
+ node: crate::ForeignItemStatic,
+) -> crate::ForeignItemStatic
+where
+ F: Fold + ?Sized,
+{
+ crate::ForeignItemStatic {
+ attrs: f.fold_attributes(node.attrs),
+ vis: f.fold_visibility(node.vis),
+ static_token: node.static_token,
+ mutability: f.fold_static_mutability(node.mutability),
+ ident: f.fold_ident(node.ident),
+ colon_token: node.colon_token,
+ ty: Box::new(f.fold_type(*node.ty)),
+ semi_token: node.semi_token,
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_foreign_item_type<F>(
+ f: &mut F,
+ node: crate::ForeignItemType,
+) -> crate::ForeignItemType
+where
+ F: Fold + ?Sized,
+{
+ crate::ForeignItemType {
+ attrs: f.fold_attributes(node.attrs),
+ vis: f.fold_visibility(node.vis),
+ type_token: node.type_token,
+ ident: f.fold_ident(node.ident),
+ generics: f.fold_generics(node.generics),
+ semi_token: node.semi_token,
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_generic_argument<F>(
+ f: &mut F,
+ node: crate::GenericArgument,
+) -> crate::GenericArgument
+where
+ F: Fold + ?Sized,
+{
+ match node {
+ crate::GenericArgument::Lifetime(_binding_0) => {
+ crate::GenericArgument::Lifetime(f.fold_lifetime(_binding_0))
+ }
+ crate::GenericArgument::Type(_binding_0) => {
+ crate::GenericArgument::Type(f.fold_type(_binding_0))
+ }
+ crate::GenericArgument::Const(_binding_0) => {
+ crate::GenericArgument::Const(f.fold_expr(_binding_0))
+ }
+ crate::GenericArgument::AssocType(_binding_0) => {
+ crate::GenericArgument::AssocType(f.fold_assoc_type(_binding_0))
+ }
+ crate::GenericArgument::AssocConst(_binding_0) => {
+ crate::GenericArgument::AssocConst(f.fold_assoc_const(_binding_0))
+ }
+ crate::GenericArgument::Constraint(_binding_0) => {
+ crate::GenericArgument::Constraint(f.fold_constraint(_binding_0))
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_generic_param<F>(f: &mut F, node: crate::GenericParam) -> crate::GenericParam
+where
+ F: Fold + ?Sized,
+{
+ match node {
+ crate::GenericParam::Lifetime(_binding_0) => {
+ crate::GenericParam::Lifetime(f.fold_lifetime_param(_binding_0))
+ }
+ crate::GenericParam::Type(_binding_0) => {
+ crate::GenericParam::Type(f.fold_type_param(_binding_0))
+ }
+ crate::GenericParam::Const(_binding_0) => {
+ crate::GenericParam::Const(f.fold_const_param(_binding_0))
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_generics<F>(f: &mut F, node: crate::Generics) -> crate::Generics
+where
+ F: Fold + ?Sized,
+{
+ crate::Generics {
+ lt_token: node.lt_token,
+ params: crate::punctuated::fold(node.params, f, F::fold_generic_param),
+ gt_token: node.gt_token,
+ where_clause: (node.where_clause).map(|it| f.fold_where_clause(it)),
+ }
+}
+pub fn fold_ident<F>(f: &mut F, node: proc_macro2::Ident) -> proc_macro2::Ident
+where
+ F: Fold + ?Sized,
+{
+ let mut node = node;
+ let span = f.fold_span(node.span());
+ node.set_span(span);
+ node
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_impl_item<F>(f: &mut F, node: crate::ImplItem) -> crate::ImplItem
+where
+ F: Fold + ?Sized,
+{
+ match node {
+ crate::ImplItem::Const(_binding_0) => {
+ crate::ImplItem::Const(f.fold_impl_item_const(_binding_0))
+ }
+ crate::ImplItem::Fn(_binding_0) => {
+ crate::ImplItem::Fn(f.fold_impl_item_fn(_binding_0))
+ }
+ crate::ImplItem::Type(_binding_0) => {
+ crate::ImplItem::Type(f.fold_impl_item_type(_binding_0))
+ }
+ crate::ImplItem::Macro(_binding_0) => {
+ crate::ImplItem::Macro(f.fold_impl_item_macro(_binding_0))
+ }
+ crate::ImplItem::Verbatim(_binding_0) => {
+ crate::ImplItem::Verbatim(f.fold_token_stream(_binding_0))
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_impl_item_const<F>(
+ f: &mut F,
+ node: crate::ImplItemConst,
+) -> crate::ImplItemConst
+where
+ F: Fold + ?Sized,
+{
+ crate::ImplItemConst {
+ attrs: f.fold_attributes(node.attrs),
+ vis: f.fold_visibility(node.vis),
+ defaultness: node.defaultness,
+ const_token: node.const_token,
+ ident: f.fold_ident(node.ident),
+ generics: f.fold_generics(node.generics),
+ colon_token: node.colon_token,
+ ty: f.fold_type(node.ty),
+ eq_token: node.eq_token,
+ expr: f.fold_expr(node.expr),
+ semi_token: node.semi_token,
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_impl_item_fn<F>(f: &mut F, node: crate::ImplItemFn) -> crate::ImplItemFn
+where
+ F: Fold + ?Sized,
+{
+ crate::ImplItemFn {
+ attrs: f.fold_attributes(node.attrs),
+ vis: f.fold_visibility(node.vis),
+ defaultness: node.defaultness,
+ sig: f.fold_signature(node.sig),
+ block: f.fold_block(node.block),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_impl_item_macro<F>(
+ f: &mut F,
+ node: crate::ImplItemMacro,
+) -> crate::ImplItemMacro
+where
+ F: Fold + ?Sized,
+{
+ crate::ImplItemMacro {
+ attrs: f.fold_attributes(node.attrs),
+ mac: f.fold_macro(node.mac),
+ semi_token: node.semi_token,
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_impl_item_type<F>(
+ f: &mut F,
+ node: crate::ImplItemType,
+) -> crate::ImplItemType
+where
+ F: Fold + ?Sized,
+{
+ crate::ImplItemType {
+ attrs: f.fold_attributes(node.attrs),
+ vis: f.fold_visibility(node.vis),
+ defaultness: node.defaultness,
+ type_token: node.type_token,
+ ident: f.fold_ident(node.ident),
+ generics: f.fold_generics(node.generics),
+ eq_token: node.eq_token,
+ ty: f.fold_type(node.ty),
+ semi_token: node.semi_token,
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_impl_restriction<F>(
+ f: &mut F,
+ node: crate::ImplRestriction,
+) -> crate::ImplRestriction
+where
+ F: Fold + ?Sized,
+{
+ match node {}
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_index<F>(f: &mut F, node: crate::Index) -> crate::Index
+where
+ F: Fold + ?Sized,
+{
+ crate::Index {
+ index: node.index,
+ span: f.fold_span(node.span),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_item<F>(f: &mut F, node: crate::Item) -> crate::Item
+where
+ F: Fold + ?Sized,
+{
+ match node {
+ crate::Item::Const(_binding_0) => {
+ crate::Item::Const(f.fold_item_const(_binding_0))
+ }
+ crate::Item::Enum(_binding_0) => crate::Item::Enum(f.fold_item_enum(_binding_0)),
+ crate::Item::ExternCrate(_binding_0) => {
+ crate::Item::ExternCrate(f.fold_item_extern_crate(_binding_0))
+ }
+ crate::Item::Fn(_binding_0) => crate::Item::Fn(f.fold_item_fn(_binding_0)),
+ crate::Item::ForeignMod(_binding_0) => {
+ crate::Item::ForeignMod(f.fold_item_foreign_mod(_binding_0))
+ }
+ crate::Item::Impl(_binding_0) => crate::Item::Impl(f.fold_item_impl(_binding_0)),
+ crate::Item::Macro(_binding_0) => {
+ crate::Item::Macro(f.fold_item_macro(_binding_0))
+ }
+ crate::Item::Mod(_binding_0) => crate::Item::Mod(f.fold_item_mod(_binding_0)),
+ crate::Item::Static(_binding_0) => {
+ crate::Item::Static(f.fold_item_static(_binding_0))
+ }
+ crate::Item::Struct(_binding_0) => {
+ crate::Item::Struct(f.fold_item_struct(_binding_0))
+ }
+ crate::Item::Trait(_binding_0) => {
+ crate::Item::Trait(f.fold_item_trait(_binding_0))
+ }
+ crate::Item::TraitAlias(_binding_0) => {
+ crate::Item::TraitAlias(f.fold_item_trait_alias(_binding_0))
+ }
+ crate::Item::Type(_binding_0) => crate::Item::Type(f.fold_item_type(_binding_0)),
+ crate::Item::Union(_binding_0) => {
+ crate::Item::Union(f.fold_item_union(_binding_0))
+ }
+ crate::Item::Use(_binding_0) => crate::Item::Use(f.fold_item_use(_binding_0)),
+ crate::Item::Verbatim(_binding_0) => {
+ crate::Item::Verbatim(f.fold_token_stream(_binding_0))
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_item_const<F>(f: &mut F, node: crate::ItemConst) -> crate::ItemConst
+where
+ F: Fold + ?Sized,
+{
+ crate::ItemConst {
+ attrs: f.fold_attributes(node.attrs),
+ vis: f.fold_visibility(node.vis),
+ const_token: node.const_token,
+ ident: f.fold_ident(node.ident),
+ generics: f.fold_generics(node.generics),
+ colon_token: node.colon_token,
+ ty: Box::new(f.fold_type(*node.ty)),
+ eq_token: node.eq_token,
+ expr: Box::new(f.fold_expr(*node.expr)),
+ semi_token: node.semi_token,
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_item_enum<F>(f: &mut F, node: crate::ItemEnum) -> crate::ItemEnum
+where
+ F: Fold + ?Sized,
+{
+ crate::ItemEnum {
+ attrs: f.fold_attributes(node.attrs),
+ vis: f.fold_visibility(node.vis),
+ enum_token: node.enum_token,
+ ident: f.fold_ident(node.ident),
+ generics: f.fold_generics(node.generics),
+ brace_token: node.brace_token,
+ variants: crate::punctuated::fold(node.variants, f, F::fold_variant),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_item_extern_crate<F>(
+ f: &mut F,
+ node: crate::ItemExternCrate,
+) -> crate::ItemExternCrate
+where
+ F: Fold + ?Sized,
+{
+ crate::ItemExternCrate {
+ attrs: f.fold_attributes(node.attrs),
+ vis: f.fold_visibility(node.vis),
+ extern_token: node.extern_token,
+ crate_token: node.crate_token,
+ ident: f.fold_ident(node.ident),
+ rename: (node.rename).map(|it| ((it).0, f.fold_ident((it).1))),
+ semi_token: node.semi_token,
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_item_fn<F>(f: &mut F, node: crate::ItemFn) -> crate::ItemFn
+where
+ F: Fold + ?Sized,
+{
+ crate::ItemFn {
+ attrs: f.fold_attributes(node.attrs),
+ vis: f.fold_visibility(node.vis),
+ sig: f.fold_signature(node.sig),
+ block: Box::new(f.fold_block(*node.block)),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_item_foreign_mod<F>(
+ f: &mut F,
+ node: crate::ItemForeignMod,
+) -> crate::ItemForeignMod
+where
+ F: Fold + ?Sized,
+{
+ crate::ItemForeignMod {
+ attrs: f.fold_attributes(node.attrs),
+ unsafety: node.unsafety,
+ abi: f.fold_abi(node.abi),
+ brace_token: node.brace_token,
+ items: fold_vec(node.items, f, F::fold_foreign_item),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_item_impl<F>(f: &mut F, node: crate::ItemImpl) -> crate::ItemImpl
+where
+ F: Fold + ?Sized,
+{
+ crate::ItemImpl {
+ attrs: f.fold_attributes(node.attrs),
+ defaultness: node.defaultness,
+ unsafety: node.unsafety,
+ impl_token: node.impl_token,
+ generics: f.fold_generics(node.generics),
+ trait_: (node.trait_).map(|it| ((it).0, f.fold_path((it).1), (it).2)),
+ self_ty: Box::new(f.fold_type(*node.self_ty)),
+ brace_token: node.brace_token,
+ items: fold_vec(node.items, f, F::fold_impl_item),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_item_macro<F>(f: &mut F, node: crate::ItemMacro) -> crate::ItemMacro
+where
+ F: Fold + ?Sized,
+{
+ crate::ItemMacro {
+ attrs: f.fold_attributes(node.attrs),
+ ident: (node.ident).map(|it| f.fold_ident(it)),
+ mac: f.fold_macro(node.mac),
+ semi_token: node.semi_token,
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_item_mod<F>(f: &mut F, node: crate::ItemMod) -> crate::ItemMod
+where
+ F: Fold + ?Sized,
+{
+ crate::ItemMod {
+ attrs: f.fold_attributes(node.attrs),
+ vis: f.fold_visibility(node.vis),
+ unsafety: node.unsafety,
+ mod_token: node.mod_token,
+ ident: f.fold_ident(node.ident),
+ content: (node.content).map(|it| ((it).0, fold_vec((it).1, f, F::fold_item))),
+ semi: node.semi,
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_item_static<F>(f: &mut F, node: crate::ItemStatic) -> crate::ItemStatic
+where
+ F: Fold + ?Sized,
+{
+ crate::ItemStatic {
+ attrs: f.fold_attributes(node.attrs),
+ vis: f.fold_visibility(node.vis),
+ static_token: node.static_token,
+ mutability: f.fold_static_mutability(node.mutability),
+ ident: f.fold_ident(node.ident),
+ colon_token: node.colon_token,
+ ty: Box::new(f.fold_type(*node.ty)),
+ eq_token: node.eq_token,
+ expr: Box::new(f.fold_expr(*node.expr)),
+ semi_token: node.semi_token,
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_item_struct<F>(f: &mut F, node: crate::ItemStruct) -> crate::ItemStruct
+where
+ F: Fold + ?Sized,
+{
+ crate::ItemStruct {
+ attrs: f.fold_attributes(node.attrs),
+ vis: f.fold_visibility(node.vis),
+ struct_token: node.struct_token,
+ ident: f.fold_ident(node.ident),
+ generics: f.fold_generics(node.generics),
+ fields: f.fold_fields(node.fields),
+ semi_token: node.semi_token,
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_item_trait<F>(f: &mut F, node: crate::ItemTrait) -> crate::ItemTrait
+where
+ F: Fold + ?Sized,
+{
+ crate::ItemTrait {
+ attrs: f.fold_attributes(node.attrs),
+ vis: f.fold_visibility(node.vis),
+ unsafety: node.unsafety,
+ auto_token: node.auto_token,
+ restriction: (node.restriction).map(|it| f.fold_impl_restriction(it)),
+ trait_token: node.trait_token,
+ ident: f.fold_ident(node.ident),
+ generics: f.fold_generics(node.generics),
+ colon_token: node.colon_token,
+ supertraits: crate::punctuated::fold(
+ node.supertraits,
+ f,
+ F::fold_type_param_bound,
+ ),
+ brace_token: node.brace_token,
+ items: fold_vec(node.items, f, F::fold_trait_item),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_item_trait_alias<F>(
+ f: &mut F,
+ node: crate::ItemTraitAlias,
+) -> crate::ItemTraitAlias
+where
+ F: Fold + ?Sized,
+{
+ crate::ItemTraitAlias {
+ attrs: f.fold_attributes(node.attrs),
+ vis: f.fold_visibility(node.vis),
+ trait_token: node.trait_token,
+ ident: f.fold_ident(node.ident),
+ generics: f.fold_generics(node.generics),
+ eq_token: node.eq_token,
+ bounds: crate::punctuated::fold(node.bounds, f, F::fold_type_param_bound),
+ semi_token: node.semi_token,
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_item_type<F>(f: &mut F, node: crate::ItemType) -> crate::ItemType
+where
+ F: Fold + ?Sized,
+{
+ crate::ItemType {
+ attrs: f.fold_attributes(node.attrs),
+ vis: f.fold_visibility(node.vis),
+ type_token: node.type_token,
+ ident: f.fold_ident(node.ident),
+ generics: f.fold_generics(node.generics),
+ eq_token: node.eq_token,
+ ty: Box::new(f.fold_type(*node.ty)),
+ semi_token: node.semi_token,
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_item_union<F>(f: &mut F, node: crate::ItemUnion) -> crate::ItemUnion
+where
+ F: Fold + ?Sized,
+{
+ crate::ItemUnion {
+ attrs: f.fold_attributes(node.attrs),
+ vis: f.fold_visibility(node.vis),
+ union_token: node.union_token,
+ ident: f.fold_ident(node.ident),
+ generics: f.fold_generics(node.generics),
+ fields: f.fold_fields_named(node.fields),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_item_use<F>(f: &mut F, node: crate::ItemUse) -> crate::ItemUse
+where
+ F: Fold + ?Sized,
+{
+ crate::ItemUse {
+ attrs: f.fold_attributes(node.attrs),
+ vis: f.fold_visibility(node.vis),
+ use_token: node.use_token,
+ leading_colon: node.leading_colon,
+ tree: f.fold_use_tree(node.tree),
+ semi_token: node.semi_token,
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_label<F>(f: &mut F, node: crate::Label) -> crate::Label
+where
+ F: Fold + ?Sized,
+{
+ crate::Label {
+ name: f.fold_lifetime(node.name),
+ colon_token: node.colon_token,
+ }
+}
+pub fn fold_lifetime<F>(f: &mut F, node: crate::Lifetime) -> crate::Lifetime
+where
+ F: Fold + ?Sized,
+{
+ crate::Lifetime {
+ apostrophe: f.fold_span(node.apostrophe),
+ ident: f.fold_ident(node.ident),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_lifetime_param<F>(
+ f: &mut F,
+ node: crate::LifetimeParam,
+) -> crate::LifetimeParam
+where
+ F: Fold + ?Sized,
+{
+ crate::LifetimeParam {
+ attrs: f.fold_attributes(node.attrs),
+ lifetime: f.fold_lifetime(node.lifetime),
+ colon_token: node.colon_token,
+ bounds: crate::punctuated::fold(node.bounds, f, F::fold_lifetime),
+ }
+}
+pub fn fold_lit<F>(f: &mut F, node: crate::Lit) -> crate::Lit
+where
+ F: Fold + ?Sized,
+{
+ match node {
+ crate::Lit::Str(_binding_0) => crate::Lit::Str(f.fold_lit_str(_binding_0)),
+ crate::Lit::ByteStr(_binding_0) => {
+ crate::Lit::ByteStr(f.fold_lit_byte_str(_binding_0))
+ }
+ crate::Lit::CStr(_binding_0) => crate::Lit::CStr(f.fold_lit_cstr(_binding_0)),
+ crate::Lit::Byte(_binding_0) => crate::Lit::Byte(f.fold_lit_byte(_binding_0)),
+ crate::Lit::Char(_binding_0) => crate::Lit::Char(f.fold_lit_char(_binding_0)),
+ crate::Lit::Int(_binding_0) => crate::Lit::Int(f.fold_lit_int(_binding_0)),
+ crate::Lit::Float(_binding_0) => crate::Lit::Float(f.fold_lit_float(_binding_0)),
+ crate::Lit::Bool(_binding_0) => crate::Lit::Bool(f.fold_lit_bool(_binding_0)),
+ crate::Lit::Verbatim(_binding_0) => crate::Lit::Verbatim(_binding_0),
+ }
+}
+pub fn fold_lit_bool<F>(f: &mut F, node: crate::LitBool) -> crate::LitBool
+where
+ F: Fold + ?Sized,
+{
+ crate::LitBool {
+ value: node.value,
+ span: f.fold_span(node.span),
+ }
+}
+pub fn fold_lit_byte<F>(f: &mut F, node: crate::LitByte) -> crate::LitByte
+where
+ F: Fold + ?Sized,
+{
+ let span = f.fold_span(node.span());
+ let mut node = node;
+ node.set_span(span);
+ node
+}
+pub fn fold_lit_byte_str<F>(f: &mut F, node: crate::LitByteStr) -> crate::LitByteStr
+where
+ F: Fold + ?Sized,
+{
+ let span = f.fold_span(node.span());
+ let mut node = node;
+ node.set_span(span);
+ node
+}
+pub fn fold_lit_cstr<F>(f: &mut F, node: crate::LitCStr) -> crate::LitCStr
+where
+ F: Fold + ?Sized,
+{
+ let span = f.fold_span(node.span());
+ let mut node = node;
+ node.set_span(span);
+ node
+}
+pub fn fold_lit_char<F>(f: &mut F, node: crate::LitChar) -> crate::LitChar
+where
+ F: Fold + ?Sized,
+{
+ let span = f.fold_span(node.span());
+ let mut node = node;
+ node.set_span(span);
+ node
+}
+pub fn fold_lit_float<F>(f: &mut F, node: crate::LitFloat) -> crate::LitFloat
+where
+ F: Fold + ?Sized,
+{
+ let span = f.fold_span(node.span());
+ let mut node = node;
+ node.set_span(span);
+ node
+}
+pub fn fold_lit_int<F>(f: &mut F, node: crate::LitInt) -> crate::LitInt
+where
+ F: Fold + ?Sized,
+{
+ let span = f.fold_span(node.span());
+ let mut node = node;
+ node.set_span(span);
+ node
+}
+pub fn fold_lit_str<F>(f: &mut F, node: crate::LitStr) -> crate::LitStr
+where
+ F: Fold + ?Sized,
+{
+ let span = f.fold_span(node.span());
+ let mut node = node;
+ node.set_span(span);
+ node
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_local<F>(f: &mut F, node: crate::Local) -> crate::Local
+where
+ F: Fold + ?Sized,
+{
+ crate::Local {
+ attrs: f.fold_attributes(node.attrs),
+ let_token: node.let_token,
+ pat: f.fold_pat(node.pat),
+ init: (node.init).map(|it| f.fold_local_init(it)),
+ semi_token: node.semi_token,
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_local_init<F>(f: &mut F, node: crate::LocalInit) -> crate::LocalInit
+where
+ F: Fold + ?Sized,
+{
+ crate::LocalInit {
+ eq_token: node.eq_token,
+ expr: Box::new(f.fold_expr(*node.expr)),
+ diverge: (node.diverge).map(|it| ((it).0, Box::new(f.fold_expr(*(it).1)))),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_macro<F>(f: &mut F, node: crate::Macro) -> crate::Macro
+where
+ F: Fold + ?Sized,
+{
+ crate::Macro {
+ path: f.fold_path(node.path),
+ bang_token: node.bang_token,
+ delimiter: f.fold_macro_delimiter(node.delimiter),
+ tokens: f.fold_token_stream(node.tokens),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_macro_delimiter<F>(
+ f: &mut F,
+ node: crate::MacroDelimiter,
+) -> crate::MacroDelimiter
+where
+ F: Fold + ?Sized,
+{
+ match node {
+ crate::MacroDelimiter::Paren(_binding_0) => {
+ crate::MacroDelimiter::Paren(_binding_0)
+ }
+ crate::MacroDelimiter::Brace(_binding_0) => {
+ crate::MacroDelimiter::Brace(_binding_0)
+ }
+ crate::MacroDelimiter::Bracket(_binding_0) => {
+ crate::MacroDelimiter::Bracket(_binding_0)
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_member<F>(f: &mut F, node: crate::Member) -> crate::Member
+where
+ F: Fold + ?Sized,
+{
+ match node {
+ crate::Member::Named(_binding_0) => {
+ crate::Member::Named(f.fold_ident(_binding_0))
+ }
+ crate::Member::Unnamed(_binding_0) => {
+ crate::Member::Unnamed(f.fold_index(_binding_0))
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_meta<F>(f: &mut F, node: crate::Meta) -> crate::Meta
+where
+ F: Fold + ?Sized,
+{
+ match node {
+ crate::Meta::Path(_binding_0) => crate::Meta::Path(f.fold_path(_binding_0)),
+ crate::Meta::List(_binding_0) => crate::Meta::List(f.fold_meta_list(_binding_0)),
+ crate::Meta::NameValue(_binding_0) => {
+ crate::Meta::NameValue(f.fold_meta_name_value(_binding_0))
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_meta_list<F>(f: &mut F, node: crate::MetaList) -> crate::MetaList
+where
+ F: Fold + ?Sized,
+{
+ crate::MetaList {
+ path: f.fold_path(node.path),
+ delimiter: f.fold_macro_delimiter(node.delimiter),
+ tokens: f.fold_token_stream(node.tokens),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_meta_name_value<F>(
+ f: &mut F,
+ node: crate::MetaNameValue,
+) -> crate::MetaNameValue
+where
+ F: Fold + ?Sized,
+{
+ crate::MetaNameValue {
+ path: f.fold_path(node.path),
+ eq_token: node.eq_token,
+ value: f.fold_expr(node.value),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_parenthesized_generic_arguments<F>(
+ f: &mut F,
+ node: crate::ParenthesizedGenericArguments,
+) -> crate::ParenthesizedGenericArguments
+where
+ F: Fold + ?Sized,
+{
+ crate::ParenthesizedGenericArguments {
+ paren_token: node.paren_token,
+ inputs: crate::punctuated::fold(node.inputs, f, F::fold_type),
+ output: f.fold_return_type(node.output),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_pat<F>(f: &mut F, node: crate::Pat) -> crate::Pat
+where
+ F: Fold + ?Sized,
+{
+ match node {
+ crate::Pat::Const(_binding_0) => crate::Pat::Const(f.fold_expr_const(_binding_0)),
+ crate::Pat::Ident(_binding_0) => crate::Pat::Ident(f.fold_pat_ident(_binding_0)),
+ crate::Pat::Lit(_binding_0) => crate::Pat::Lit(f.fold_expr_lit(_binding_0)),
+ crate::Pat::Macro(_binding_0) => crate::Pat::Macro(f.fold_expr_macro(_binding_0)),
+ crate::Pat::Or(_binding_0) => crate::Pat::Or(f.fold_pat_or(_binding_0)),
+ crate::Pat::Paren(_binding_0) => crate::Pat::Paren(f.fold_pat_paren(_binding_0)),
+ crate::Pat::Path(_binding_0) => crate::Pat::Path(f.fold_expr_path(_binding_0)),
+ crate::Pat::Range(_binding_0) => crate::Pat::Range(f.fold_expr_range(_binding_0)),
+ crate::Pat::Reference(_binding_0) => {
+ crate::Pat::Reference(f.fold_pat_reference(_binding_0))
+ }
+ crate::Pat::Rest(_binding_0) => crate::Pat::Rest(f.fold_pat_rest(_binding_0)),
+ crate::Pat::Slice(_binding_0) => crate::Pat::Slice(f.fold_pat_slice(_binding_0)),
+ crate::Pat::Struct(_binding_0) => {
+ crate::Pat::Struct(f.fold_pat_struct(_binding_0))
+ }
+ crate::Pat::Tuple(_binding_0) => crate::Pat::Tuple(f.fold_pat_tuple(_binding_0)),
+ crate::Pat::TupleStruct(_binding_0) => {
+ crate::Pat::TupleStruct(f.fold_pat_tuple_struct(_binding_0))
+ }
+ crate::Pat::Type(_binding_0) => crate::Pat::Type(f.fold_pat_type(_binding_0)),
+ crate::Pat::Verbatim(_binding_0) => {
+ crate::Pat::Verbatim(f.fold_token_stream(_binding_0))
+ }
+ crate::Pat::Wild(_binding_0) => crate::Pat::Wild(f.fold_pat_wild(_binding_0)),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_pat_ident<F>(f: &mut F, node: crate::PatIdent) -> crate::PatIdent
+where
+ F: Fold + ?Sized,
+{
+ crate::PatIdent {
+ attrs: f.fold_attributes(node.attrs),
+ by_ref: node.by_ref,
+ mutability: node.mutability,
+ ident: f.fold_ident(node.ident),
+ subpat: (node.subpat).map(|it| ((it).0, Box::new(f.fold_pat(*(it).1)))),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_pat_or<F>(f: &mut F, node: crate::PatOr) -> crate::PatOr
+where
+ F: Fold + ?Sized,
+{
+ crate::PatOr {
+ attrs: f.fold_attributes(node.attrs),
+ leading_vert: node.leading_vert,
+ cases: crate::punctuated::fold(node.cases, f, F::fold_pat),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_pat_paren<F>(f: &mut F, node: crate::PatParen) -> crate::PatParen
+where
+ F: Fold + ?Sized,
+{
+ crate::PatParen {
+ attrs: f.fold_attributes(node.attrs),
+ paren_token: node.paren_token,
+ pat: Box::new(f.fold_pat(*node.pat)),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_pat_reference<F>(f: &mut F, node: crate::PatReference) -> crate::PatReference
+where
+ F: Fold + ?Sized,
+{
+ crate::PatReference {
+ attrs: f.fold_attributes(node.attrs),
+ and_token: node.and_token,
+ mutability: node.mutability,
+ pat: Box::new(f.fold_pat(*node.pat)),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_pat_rest<F>(f: &mut F, node: crate::PatRest) -> crate::PatRest
+where
+ F: Fold + ?Sized,
+{
+ crate::PatRest {
+ attrs: f.fold_attributes(node.attrs),
+ dot2_token: node.dot2_token,
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_pat_slice<F>(f: &mut F, node: crate::PatSlice) -> crate::PatSlice
+where
+ F: Fold + ?Sized,
+{
+ crate::PatSlice {
+ attrs: f.fold_attributes(node.attrs),
+ bracket_token: node.bracket_token,
+ elems: crate::punctuated::fold(node.elems, f, F::fold_pat),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_pat_struct<F>(f: &mut F, node: crate::PatStruct) -> crate::PatStruct
+where
+ F: Fold + ?Sized,
+{
+ crate::PatStruct {
+ attrs: f.fold_attributes(node.attrs),
+ qself: (node.qself).map(|it| f.fold_qself(it)),
+ path: f.fold_path(node.path),
+ brace_token: node.brace_token,
+ fields: crate::punctuated::fold(node.fields, f, F::fold_field_pat),
+ rest: (node.rest).map(|it| f.fold_pat_rest(it)),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_pat_tuple<F>(f: &mut F, node: crate::PatTuple) -> crate::PatTuple
+where
+ F: Fold + ?Sized,
+{
+ crate::PatTuple {
+ attrs: f.fold_attributes(node.attrs),
+ paren_token: node.paren_token,
+ elems: crate::punctuated::fold(node.elems, f, F::fold_pat),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_pat_tuple_struct<F>(
+ f: &mut F,
+ node: crate::PatTupleStruct,
+) -> crate::PatTupleStruct
+where
+ F: Fold + ?Sized,
+{
+ crate::PatTupleStruct {
+ attrs: f.fold_attributes(node.attrs),
+ qself: (node.qself).map(|it| f.fold_qself(it)),
+ path: f.fold_path(node.path),
+ paren_token: node.paren_token,
+ elems: crate::punctuated::fold(node.elems, f, F::fold_pat),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_pat_type<F>(f: &mut F, node: crate::PatType) -> crate::PatType
+where
+ F: Fold + ?Sized,
+{
+ crate::PatType {
+ attrs: f.fold_attributes(node.attrs),
+ pat: Box::new(f.fold_pat(*node.pat)),
+ colon_token: node.colon_token,
+ ty: Box::new(f.fold_type(*node.ty)),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_pat_wild<F>(f: &mut F, node: crate::PatWild) -> crate::PatWild
+where
+ F: Fold + ?Sized,
+{
+ crate::PatWild {
+ attrs: f.fold_attributes(node.attrs),
+ underscore_token: node.underscore_token,
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_path<F>(f: &mut F, node: crate::Path) -> crate::Path
+where
+ F: Fold + ?Sized,
+{
+ crate::Path {
+ leading_colon: node.leading_colon,
+ segments: crate::punctuated::fold(node.segments, f, F::fold_path_segment),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_path_arguments<F>(
+ f: &mut F,
+ node: crate::PathArguments,
+) -> crate::PathArguments
+where
+ F: Fold + ?Sized,
+{
+ match node {
+ crate::PathArguments::None => crate::PathArguments::None,
+ crate::PathArguments::AngleBracketed(_binding_0) => {
+ crate::PathArguments::AngleBracketed(
+ f.fold_angle_bracketed_generic_arguments(_binding_0),
+ )
+ }
+ crate::PathArguments::Parenthesized(_binding_0) => {
+ crate::PathArguments::Parenthesized(
+ f.fold_parenthesized_generic_arguments(_binding_0),
+ )
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_path_segment<F>(f: &mut F, node: crate::PathSegment) -> crate::PathSegment
+where
+ F: Fold + ?Sized,
+{
+ crate::PathSegment {
+ ident: f.fold_ident(node.ident),
+ arguments: f.fold_path_arguments(node.arguments),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_pointer_mutability<F>(
+ f: &mut F,
+ node: crate::PointerMutability,
+) -> crate::PointerMutability
+where
+ F: Fold + ?Sized,
+{
+ match node {
+ crate::PointerMutability::Const(_binding_0) => {
+ crate::PointerMutability::Const(_binding_0)
+ }
+ crate::PointerMutability::Mut(_binding_0) => {
+ crate::PointerMutability::Mut(_binding_0)
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_precise_capture<F>(
+ f: &mut F,
+ node: crate::PreciseCapture,
+) -> crate::PreciseCapture
+where
+ F: Fold + ?Sized,
+{
+ crate::PreciseCapture {
+ use_token: node.use_token,
+ lt_token: node.lt_token,
+ params: crate::punctuated::fold(node.params, f, F::fold_captured_param),
+ gt_token: node.gt_token,
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_predicate_lifetime<F>(
+ f: &mut F,
+ node: crate::PredicateLifetime,
+) -> crate::PredicateLifetime
+where
+ F: Fold + ?Sized,
+{
+ crate::PredicateLifetime {
+ lifetime: f.fold_lifetime(node.lifetime),
+ colon_token: node.colon_token,
+ bounds: crate::punctuated::fold(node.bounds, f, F::fold_lifetime),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_predicate_type<F>(
+ f: &mut F,
+ node: crate::PredicateType,
+) -> crate::PredicateType
+where
+ F: Fold + ?Sized,
+{
+ crate::PredicateType {
+ lifetimes: (node.lifetimes).map(|it| f.fold_bound_lifetimes(it)),
+ bounded_ty: f.fold_type(node.bounded_ty),
+ colon_token: node.colon_token,
+ bounds: crate::punctuated::fold(node.bounds, f, F::fold_type_param_bound),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_qself<F>(f: &mut F, node: crate::QSelf) -> crate::QSelf
+where
+ F: Fold + ?Sized,
+{
+ crate::QSelf {
+ lt_token: node.lt_token,
+ ty: Box::new(f.fold_type(*node.ty)),
+ position: node.position,
+ as_token: node.as_token,
+ gt_token: node.gt_token,
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_range_limits<F>(f: &mut F, node: crate::RangeLimits) -> crate::RangeLimits
+where
+ F: Fold + ?Sized,
+{
+ match node {
+ crate::RangeLimits::HalfOpen(_binding_0) => {
+ crate::RangeLimits::HalfOpen(_binding_0)
+ }
+ crate::RangeLimits::Closed(_binding_0) => crate::RangeLimits::Closed(_binding_0),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_receiver<F>(f: &mut F, node: crate::Receiver) -> crate::Receiver
+where
+ F: Fold + ?Sized,
+{
+ crate::Receiver {
+ attrs: f.fold_attributes(node.attrs),
+ reference: (node.reference)
+ .map(|it| ((it).0, ((it).1).map(|it| f.fold_lifetime(it)))),
+ mutability: node.mutability,
+ self_token: node.self_token,
+ colon_token: node.colon_token,
+ ty: Box::new(f.fold_type(*node.ty)),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_return_type<F>(f: &mut F, node: crate::ReturnType) -> crate::ReturnType
+where
+ F: Fold + ?Sized,
+{
+ match node {
+ crate::ReturnType::Default => crate::ReturnType::Default,
+ crate::ReturnType::Type(_binding_0, _binding_1) => {
+ crate::ReturnType::Type(_binding_0, Box::new(f.fold_type(*_binding_1)))
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_signature<F>(f: &mut F, node: crate::Signature) -> crate::Signature
+where
+ F: Fold + ?Sized,
+{
+ crate::Signature {
+ constness: node.constness,
+ asyncness: node.asyncness,
+ unsafety: node.unsafety,
+ abi: (node.abi).map(|it| f.fold_abi(it)),
+ fn_token: node.fn_token,
+ ident: f.fold_ident(node.ident),
+ generics: f.fold_generics(node.generics),
+ paren_token: node.paren_token,
+ inputs: crate::punctuated::fold(node.inputs, f, F::fold_fn_arg),
+ variadic: (node.variadic).map(|it| f.fold_variadic(it)),
+ output: f.fold_return_type(node.output),
+ }
+}
+pub fn fold_span<F>(f: &mut F, node: proc_macro2::Span) -> proc_macro2::Span
+where
+ F: Fold + ?Sized,
+{
+ node
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_static_mutability<F>(
+ f: &mut F,
+ node: crate::StaticMutability,
+) -> crate::StaticMutability
+where
+ F: Fold + ?Sized,
+{
+ match node {
+ crate::StaticMutability::Mut(_binding_0) => {
+ crate::StaticMutability::Mut(_binding_0)
+ }
+ crate::StaticMutability::None => crate::StaticMutability::None,
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_stmt<F>(f: &mut F, node: crate::Stmt) -> crate::Stmt
+where
+ F: Fold + ?Sized,
+{
+ match node {
+ crate::Stmt::Local(_binding_0) => crate::Stmt::Local(f.fold_local(_binding_0)),
+ crate::Stmt::Item(_binding_0) => crate::Stmt::Item(f.fold_item(_binding_0)),
+ crate::Stmt::Expr(_binding_0, _binding_1) => {
+ crate::Stmt::Expr(f.fold_expr(_binding_0), _binding_1)
+ }
+ crate::Stmt::Macro(_binding_0) => {
+ crate::Stmt::Macro(f.fold_stmt_macro(_binding_0))
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_stmt_macro<F>(f: &mut F, node: crate::StmtMacro) -> crate::StmtMacro
+where
+ F: Fold + ?Sized,
+{
+ crate::StmtMacro {
+ attrs: f.fold_attributes(node.attrs),
+ mac: f.fold_macro(node.mac),
+ semi_token: node.semi_token,
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_trait_bound<F>(f: &mut F, node: crate::TraitBound) -> crate::TraitBound
+where
+ F: Fold + ?Sized,
+{
+ crate::TraitBound {
+ paren_token: node.paren_token,
+ modifier: f.fold_trait_bound_modifier(node.modifier),
+ lifetimes: (node.lifetimes).map(|it| f.fold_bound_lifetimes(it)),
+ path: f.fold_path(node.path),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_trait_bound_modifier<F>(
+ f: &mut F,
+ node: crate::TraitBoundModifier,
+) -> crate::TraitBoundModifier
+where
+ F: Fold + ?Sized,
+{
+ match node {
+ crate::TraitBoundModifier::None => crate::TraitBoundModifier::None,
+ crate::TraitBoundModifier::Maybe(_binding_0) => {
+ crate::TraitBoundModifier::Maybe(_binding_0)
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_trait_item<F>(f: &mut F, node: crate::TraitItem) -> crate::TraitItem
+where
+ F: Fold + ?Sized,
+{
+ match node {
+ crate::TraitItem::Const(_binding_0) => {
+ crate::TraitItem::Const(f.fold_trait_item_const(_binding_0))
+ }
+ crate::TraitItem::Fn(_binding_0) => {
+ crate::TraitItem::Fn(f.fold_trait_item_fn(_binding_0))
+ }
+ crate::TraitItem::Type(_binding_0) => {
+ crate::TraitItem::Type(f.fold_trait_item_type(_binding_0))
+ }
+ crate::TraitItem::Macro(_binding_0) => {
+ crate::TraitItem::Macro(f.fold_trait_item_macro(_binding_0))
+ }
+ crate::TraitItem::Verbatim(_binding_0) => {
+ crate::TraitItem::Verbatim(f.fold_token_stream(_binding_0))
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_trait_item_const<F>(
+ f: &mut F,
+ node: crate::TraitItemConst,
+) -> crate::TraitItemConst
+where
+ F: Fold + ?Sized,
+{
+ crate::TraitItemConst {
+ attrs: f.fold_attributes(node.attrs),
+ const_token: node.const_token,
+ ident: f.fold_ident(node.ident),
+ generics: f.fold_generics(node.generics),
+ colon_token: node.colon_token,
+ ty: f.fold_type(node.ty),
+ default: (node.default).map(|it| ((it).0, f.fold_expr((it).1))),
+ semi_token: node.semi_token,
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_trait_item_fn<F>(f: &mut F, node: crate::TraitItemFn) -> crate::TraitItemFn
+where
+ F: Fold + ?Sized,
+{
+ crate::TraitItemFn {
+ attrs: f.fold_attributes(node.attrs),
+ sig: f.fold_signature(node.sig),
+ default: (node.default).map(|it| f.fold_block(it)),
+ semi_token: node.semi_token,
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_trait_item_macro<F>(
+ f: &mut F,
+ node: crate::TraitItemMacro,
+) -> crate::TraitItemMacro
+where
+ F: Fold + ?Sized,
+{
+ crate::TraitItemMacro {
+ attrs: f.fold_attributes(node.attrs),
+ mac: f.fold_macro(node.mac),
+ semi_token: node.semi_token,
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_trait_item_type<F>(
+ f: &mut F,
+ node: crate::TraitItemType,
+) -> crate::TraitItemType
+where
+ F: Fold + ?Sized,
+{
+ crate::TraitItemType {
+ attrs: f.fold_attributes(node.attrs),
+ type_token: node.type_token,
+ ident: f.fold_ident(node.ident),
+ generics: f.fold_generics(node.generics),
+ colon_token: node.colon_token,
+ bounds: crate::punctuated::fold(node.bounds, f, F::fold_type_param_bound),
+ default: (node.default).map(|it| ((it).0, f.fold_type((it).1))),
+ semi_token: node.semi_token,
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_type<F>(f: &mut F, node: crate::Type) -> crate::Type
+where
+ F: Fold + ?Sized,
+{
+ match node {
+ crate::Type::Array(_binding_0) => {
+ crate::Type::Array(f.fold_type_array(_binding_0))
+ }
+ crate::Type::BareFn(_binding_0) => {
+ crate::Type::BareFn(f.fold_type_bare_fn(_binding_0))
+ }
+ crate::Type::Group(_binding_0) => {
+ crate::Type::Group(f.fold_type_group(_binding_0))
+ }
+ crate::Type::ImplTrait(_binding_0) => {
+ crate::Type::ImplTrait(f.fold_type_impl_trait(_binding_0))
+ }
+ crate::Type::Infer(_binding_0) => {
+ crate::Type::Infer(f.fold_type_infer(_binding_0))
+ }
+ crate::Type::Macro(_binding_0) => {
+ crate::Type::Macro(f.fold_type_macro(_binding_0))
+ }
+ crate::Type::Never(_binding_0) => {
+ crate::Type::Never(f.fold_type_never(_binding_0))
+ }
+ crate::Type::Paren(_binding_0) => {
+ crate::Type::Paren(f.fold_type_paren(_binding_0))
+ }
+ crate::Type::Path(_binding_0) => crate::Type::Path(f.fold_type_path(_binding_0)),
+ crate::Type::Ptr(_binding_0) => crate::Type::Ptr(f.fold_type_ptr(_binding_0)),
+ crate::Type::Reference(_binding_0) => {
+ crate::Type::Reference(f.fold_type_reference(_binding_0))
+ }
+ crate::Type::Slice(_binding_0) => {
+ crate::Type::Slice(f.fold_type_slice(_binding_0))
+ }
+ crate::Type::TraitObject(_binding_0) => {
+ crate::Type::TraitObject(f.fold_type_trait_object(_binding_0))
+ }
+ crate::Type::Tuple(_binding_0) => {
+ crate::Type::Tuple(f.fold_type_tuple(_binding_0))
+ }
+ crate::Type::Verbatim(_binding_0) => {
+ crate::Type::Verbatim(f.fold_token_stream(_binding_0))
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_type_array<F>(f: &mut F, node: crate::TypeArray) -> crate::TypeArray
+where
+ F: Fold + ?Sized,
+{
+ crate::TypeArray {
+ bracket_token: node.bracket_token,
+ elem: Box::new(f.fold_type(*node.elem)),
+ semi_token: node.semi_token,
+ len: f.fold_expr(node.len),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_type_bare_fn<F>(f: &mut F, node: crate::TypeBareFn) -> crate::TypeBareFn
+where
+ F: Fold + ?Sized,
+{
+ crate::TypeBareFn {
+ lifetimes: (node.lifetimes).map(|it| f.fold_bound_lifetimes(it)),
+ unsafety: node.unsafety,
+ abi: (node.abi).map(|it| f.fold_abi(it)),
+ fn_token: node.fn_token,
+ paren_token: node.paren_token,
+ inputs: crate::punctuated::fold(node.inputs, f, F::fold_bare_fn_arg),
+ variadic: (node.variadic).map(|it| f.fold_bare_variadic(it)),
+ output: f.fold_return_type(node.output),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_type_group<F>(f: &mut F, node: crate::TypeGroup) -> crate::TypeGroup
+where
+ F: Fold + ?Sized,
+{
+ crate::TypeGroup {
+ group_token: node.group_token,
+ elem: Box::new(f.fold_type(*node.elem)),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_type_impl_trait<F>(
+ f: &mut F,
+ node: crate::TypeImplTrait,
+) -> crate::TypeImplTrait
+where
+ F: Fold + ?Sized,
+{
+ crate::TypeImplTrait {
+ impl_token: node.impl_token,
+ bounds: crate::punctuated::fold(node.bounds, f, F::fold_type_param_bound),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_type_infer<F>(f: &mut F, node: crate::TypeInfer) -> crate::TypeInfer
+where
+ F: Fold + ?Sized,
+{
+ crate::TypeInfer {
+ underscore_token: node.underscore_token,
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_type_macro<F>(f: &mut F, node: crate::TypeMacro) -> crate::TypeMacro
+where
+ F: Fold + ?Sized,
+{
+ crate::TypeMacro {
+ mac: f.fold_macro(node.mac),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_type_never<F>(f: &mut F, node: crate::TypeNever) -> crate::TypeNever
+where
+ F: Fold + ?Sized,
+{
+ crate::TypeNever {
+ bang_token: node.bang_token,
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_type_param<F>(f: &mut F, node: crate::TypeParam) -> crate::TypeParam
+where
+ F: Fold + ?Sized,
+{
+ crate::TypeParam {
+ attrs: f.fold_attributes(node.attrs),
+ ident: f.fold_ident(node.ident),
+ colon_token: node.colon_token,
+ bounds: crate::punctuated::fold(node.bounds, f, F::fold_type_param_bound),
+ eq_token: node.eq_token,
+ default: (node.default).map(|it| f.fold_type(it)),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_type_param_bound<F>(
+ f: &mut F,
+ node: crate::TypeParamBound,
+) -> crate::TypeParamBound
+where
+ F: Fold + ?Sized,
+{
+ match node {
+ crate::TypeParamBound::Trait(_binding_0) => {
+ crate::TypeParamBound::Trait(f.fold_trait_bound(_binding_0))
+ }
+ crate::TypeParamBound::Lifetime(_binding_0) => {
+ crate::TypeParamBound::Lifetime(f.fold_lifetime(_binding_0))
+ }
+ crate::TypeParamBound::PreciseCapture(_binding_0) => {
+ crate::TypeParamBound::PreciseCapture(
+ full!(f.fold_precise_capture(_binding_0)),
+ )
+ }
+ crate::TypeParamBound::Verbatim(_binding_0) => {
+ crate::TypeParamBound::Verbatim(f.fold_token_stream(_binding_0))
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_type_paren<F>(f: &mut F, node: crate::TypeParen) -> crate::TypeParen
+where
+ F: Fold + ?Sized,
+{
+ crate::TypeParen {
+ paren_token: node.paren_token,
+ elem: Box::new(f.fold_type(*node.elem)),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_type_path<F>(f: &mut F, node: crate::TypePath) -> crate::TypePath
+where
+ F: Fold + ?Sized,
+{
+ crate::TypePath {
+ qself: (node.qself).map(|it| f.fold_qself(it)),
+ path: f.fold_path(node.path),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_type_ptr<F>(f: &mut F, node: crate::TypePtr) -> crate::TypePtr
+where
+ F: Fold + ?Sized,
+{
+ crate::TypePtr {
+ star_token: node.star_token,
+ const_token: node.const_token,
+ mutability: node.mutability,
+ elem: Box::new(f.fold_type(*node.elem)),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_type_reference<F>(
+ f: &mut F,
+ node: crate::TypeReference,
+) -> crate::TypeReference
+where
+ F: Fold + ?Sized,
+{
+ crate::TypeReference {
+ and_token: node.and_token,
+ lifetime: (node.lifetime).map(|it| f.fold_lifetime(it)),
+ mutability: node.mutability,
+ elem: Box::new(f.fold_type(*node.elem)),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_type_slice<F>(f: &mut F, node: crate::TypeSlice) -> crate::TypeSlice
+where
+ F: Fold + ?Sized,
+{
+ crate::TypeSlice {
+ bracket_token: node.bracket_token,
+ elem: Box::new(f.fold_type(*node.elem)),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_type_trait_object<F>(
+ f: &mut F,
+ node: crate::TypeTraitObject,
+) -> crate::TypeTraitObject
+where
+ F: Fold + ?Sized,
+{
+ crate::TypeTraitObject {
+ dyn_token: node.dyn_token,
+ bounds: crate::punctuated::fold(node.bounds, f, F::fold_type_param_bound),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_type_tuple<F>(f: &mut F, node: crate::TypeTuple) -> crate::TypeTuple
+where
+ F: Fold + ?Sized,
+{
+ crate::TypeTuple {
+ paren_token: node.paren_token,
+ elems: crate::punctuated::fold(node.elems, f, F::fold_type),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_un_op<F>(f: &mut F, node: crate::UnOp) -> crate::UnOp
+where
+ F: Fold + ?Sized,
+{
+ match node {
+ crate::UnOp::Deref(_binding_0) => crate::UnOp::Deref(_binding_0),
+ crate::UnOp::Not(_binding_0) => crate::UnOp::Not(_binding_0),
+ crate::UnOp::Neg(_binding_0) => crate::UnOp::Neg(_binding_0),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_use_glob<F>(f: &mut F, node: crate::UseGlob) -> crate::UseGlob
+where
+ F: Fold + ?Sized,
+{
+ crate::UseGlob {
+ star_token: node.star_token,
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_use_group<F>(f: &mut F, node: crate::UseGroup) -> crate::UseGroup
+where
+ F: Fold + ?Sized,
+{
+ crate::UseGroup {
+ brace_token: node.brace_token,
+ items: crate::punctuated::fold(node.items, f, F::fold_use_tree),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_use_name<F>(f: &mut F, node: crate::UseName) -> crate::UseName
+where
+ F: Fold + ?Sized,
+{
+ crate::UseName {
+ ident: f.fold_ident(node.ident),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_use_path<F>(f: &mut F, node: crate::UsePath) -> crate::UsePath
+where
+ F: Fold + ?Sized,
+{
+ crate::UsePath {
+ ident: f.fold_ident(node.ident),
+ colon2_token: node.colon2_token,
+ tree: Box::new(f.fold_use_tree(*node.tree)),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_use_rename<F>(f: &mut F, node: crate::UseRename) -> crate::UseRename
+where
+ F: Fold + ?Sized,
+{
+ crate::UseRename {
+ ident: f.fold_ident(node.ident),
+ as_token: node.as_token,
+ rename: f.fold_ident(node.rename),
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_use_tree<F>(f: &mut F, node: crate::UseTree) -> crate::UseTree
+where
+ F: Fold + ?Sized,
+{
+ match node {
+ crate::UseTree::Path(_binding_0) => {
+ crate::UseTree::Path(f.fold_use_path(_binding_0))
+ }
+ crate::UseTree::Name(_binding_0) => {
+ crate::UseTree::Name(f.fold_use_name(_binding_0))
+ }
+ crate::UseTree::Rename(_binding_0) => {
+ crate::UseTree::Rename(f.fold_use_rename(_binding_0))
+ }
+ crate::UseTree::Glob(_binding_0) => {
+ crate::UseTree::Glob(f.fold_use_glob(_binding_0))
+ }
+ crate::UseTree::Group(_binding_0) => {
+ crate::UseTree::Group(f.fold_use_group(_binding_0))
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn fold_variadic<F>(f: &mut F, node: crate::Variadic) -> crate::Variadic
+where
+ F: Fold + ?Sized,
+{
+ crate::Variadic {
+ attrs: f.fold_attributes(node.attrs),
+ pat: (node.pat).map(|it| (Box::new(f.fold_pat(*(it).0)), (it).1)),
+ dots: node.dots,
+ comma: node.comma,
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_variant<F>(f: &mut F, node: crate::Variant) -> crate::Variant
+where
+ F: Fold + ?Sized,
+{
+ crate::Variant {
+ attrs: f.fold_attributes(node.attrs),
+ ident: f.fold_ident(node.ident),
+ fields: f.fold_fields(node.fields),
+ discriminant: (node.discriminant).map(|it| ((it).0, f.fold_expr((it).1))),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_vis_restricted<F>(
+ f: &mut F,
+ node: crate::VisRestricted,
+) -> crate::VisRestricted
+where
+ F: Fold + ?Sized,
+{
+ crate::VisRestricted {
+ pub_token: node.pub_token,
+ paren_token: node.paren_token,
+ in_token: node.in_token,
+ path: Box::new(f.fold_path(*node.path)),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_visibility<F>(f: &mut F, node: crate::Visibility) -> crate::Visibility
+where
+ F: Fold + ?Sized,
+{
+ match node {
+ crate::Visibility::Public(_binding_0) => crate::Visibility::Public(_binding_0),
+ crate::Visibility::Restricted(_binding_0) => {
+ crate::Visibility::Restricted(f.fold_vis_restricted(_binding_0))
+ }
+ crate::Visibility::Inherited => crate::Visibility::Inherited,
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_where_clause<F>(f: &mut F, node: crate::WhereClause) -> crate::WhereClause
+where
+ F: Fold + ?Sized,
+{
+ crate::WhereClause {
+ where_token: node.where_token,
+ predicates: crate::punctuated::fold(node.predicates, f, F::fold_where_predicate),
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn fold_where_predicate<F>(
+ f: &mut F,
+ node: crate::WherePredicate,
+) -> crate::WherePredicate
+where
+ F: Fold + ?Sized,
+{
+ match node {
+ crate::WherePredicate::Lifetime(_binding_0) => {
+ crate::WherePredicate::Lifetime(f.fold_predicate_lifetime(_binding_0))
+ }
+ crate::WherePredicate::Type(_binding_0) => {
+ crate::WherePredicate::Type(f.fold_predicate_type(_binding_0))
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+fn fold_vec<T, V, F>(vec: Vec<T>, fold: &mut V, mut f: F) -> Vec<T>
+where
+ V: ?Sized,
+ F: FnMut(&mut V, T) -> T,
+{
+ vec.into_iter().map(|it| f(fold, it)).collect()
+}
diff --git a/rust/syn/gen/hash.rs b/rust/syn/gen/hash.rs
new file mode 100644
index 000000000000..04f23453a117
--- /dev/null
+++ b/rust/syn/gen/hash.rs
@@ -0,0 +1,2876 @@
+// This file is @generated by syn-internal-codegen.
+// It is not intended for manual editing.
+
+#[cfg(any(feature = "derive", feature = "full"))]
+use crate::tt::TokenStreamHelper;
+use std::hash::{Hash, Hasher};
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::Abi {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.name.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::AngleBracketedGenericArguments {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.colon2_token.hash(state);
+ self.args.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::Arm {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.pat.hash(state);
+ self.guard.hash(state);
+ self.body.hash(state);
+ self.comma.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::AssocConst {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.ident.hash(state);
+ self.generics.hash(state);
+ self.value.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::AssocType {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.ident.hash(state);
+ self.generics.hash(state);
+ self.ty.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::AttrStyle {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ match self {
+ crate::AttrStyle::Outer => {
+ state.write_u8(0u8);
+ }
+ crate::AttrStyle::Inner(_) => {
+ state.write_u8(1u8);
+ }
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::Attribute {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.style.hash(state);
+ self.meta.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::BareFnArg {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.name.hash(state);
+ self.ty.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::BareVariadic {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.name.hash(state);
+ self.comma.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::BinOp {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ match self {
+ crate::BinOp::Add(_) => {
+ state.write_u8(0u8);
+ }
+ crate::BinOp::Sub(_) => {
+ state.write_u8(1u8);
+ }
+ crate::BinOp::Mul(_) => {
+ state.write_u8(2u8);
+ }
+ crate::BinOp::Div(_) => {
+ state.write_u8(3u8);
+ }
+ crate::BinOp::Rem(_) => {
+ state.write_u8(4u8);
+ }
+ crate::BinOp::And(_) => {
+ state.write_u8(5u8);
+ }
+ crate::BinOp::Or(_) => {
+ state.write_u8(6u8);
+ }
+ crate::BinOp::BitXor(_) => {
+ state.write_u8(7u8);
+ }
+ crate::BinOp::BitAnd(_) => {
+ state.write_u8(8u8);
+ }
+ crate::BinOp::BitOr(_) => {
+ state.write_u8(9u8);
+ }
+ crate::BinOp::Shl(_) => {
+ state.write_u8(10u8);
+ }
+ crate::BinOp::Shr(_) => {
+ state.write_u8(11u8);
+ }
+ crate::BinOp::Eq(_) => {
+ state.write_u8(12u8);
+ }
+ crate::BinOp::Lt(_) => {
+ state.write_u8(13u8);
+ }
+ crate::BinOp::Le(_) => {
+ state.write_u8(14u8);
+ }
+ crate::BinOp::Ne(_) => {
+ state.write_u8(15u8);
+ }
+ crate::BinOp::Ge(_) => {
+ state.write_u8(16u8);
+ }
+ crate::BinOp::Gt(_) => {
+ state.write_u8(17u8);
+ }
+ crate::BinOp::AddAssign(_) => {
+ state.write_u8(18u8);
+ }
+ crate::BinOp::SubAssign(_) => {
+ state.write_u8(19u8);
+ }
+ crate::BinOp::MulAssign(_) => {
+ state.write_u8(20u8);
+ }
+ crate::BinOp::DivAssign(_) => {
+ state.write_u8(21u8);
+ }
+ crate::BinOp::RemAssign(_) => {
+ state.write_u8(22u8);
+ }
+ crate::BinOp::BitXorAssign(_) => {
+ state.write_u8(23u8);
+ }
+ crate::BinOp::BitAndAssign(_) => {
+ state.write_u8(24u8);
+ }
+ crate::BinOp::BitOrAssign(_) => {
+ state.write_u8(25u8);
+ }
+ crate::BinOp::ShlAssign(_) => {
+ state.write_u8(26u8);
+ }
+ crate::BinOp::ShrAssign(_) => {
+ state.write_u8(27u8);
+ }
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::Block {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.stmts.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::BoundLifetimes {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.lifetimes.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::CapturedParam {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ match self {
+ crate::CapturedParam::Lifetime(v0) => {
+ state.write_u8(0u8);
+ v0.hash(state);
+ }
+ crate::CapturedParam::Ident(v0) => {
+ state.write_u8(1u8);
+ v0.hash(state);
+ }
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ConstParam {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.ident.hash(state);
+ self.ty.hash(state);
+ self.eq_token.hash(state);
+ self.default.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::Constraint {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.ident.hash(state);
+ self.generics.hash(state);
+ self.bounds.hash(state);
+ }
+}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::Data {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ match self {
+ crate::Data::Struct(v0) => {
+ state.write_u8(0u8);
+ v0.hash(state);
+ }
+ crate::Data::Enum(v0) => {
+ state.write_u8(1u8);
+ v0.hash(state);
+ }
+ crate::Data::Union(v0) => {
+ state.write_u8(2u8);
+ v0.hash(state);
+ }
+ }
+ }
+}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::DataEnum {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.variants.hash(state);
+ }
+}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::DataStruct {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.fields.hash(state);
+ self.semi_token.hash(state);
+ }
+}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::DataUnion {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.fields.hash(state);
+ }
+}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::DeriveInput {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.vis.hash(state);
+ self.ident.hash(state);
+ self.generics.hash(state);
+ self.data.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::Expr {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ match self {
+ #[cfg(feature = "full")]
+ crate::Expr::Array(v0) => {
+ state.write_u8(0u8);
+ v0.hash(state);
+ }
+ #[cfg(feature = "full")]
+ crate::Expr::Assign(v0) => {
+ state.write_u8(1u8);
+ v0.hash(state);
+ }
+ #[cfg(feature = "full")]
+ crate::Expr::Async(v0) => {
+ state.write_u8(2u8);
+ v0.hash(state);
+ }
+ #[cfg(feature = "full")]
+ crate::Expr::Await(v0) => {
+ state.write_u8(3u8);
+ v0.hash(state);
+ }
+ crate::Expr::Binary(v0) => {
+ state.write_u8(4u8);
+ v0.hash(state);
+ }
+ #[cfg(feature = "full")]
+ crate::Expr::Block(v0) => {
+ state.write_u8(5u8);
+ v0.hash(state);
+ }
+ #[cfg(feature = "full")]
+ crate::Expr::Break(v0) => {
+ state.write_u8(6u8);
+ v0.hash(state);
+ }
+ crate::Expr::Call(v0) => {
+ state.write_u8(7u8);
+ v0.hash(state);
+ }
+ crate::Expr::Cast(v0) => {
+ state.write_u8(8u8);
+ v0.hash(state);
+ }
+ #[cfg(feature = "full")]
+ crate::Expr::Closure(v0) => {
+ state.write_u8(9u8);
+ v0.hash(state);
+ }
+ #[cfg(feature = "full")]
+ crate::Expr::Const(v0) => {
+ state.write_u8(10u8);
+ v0.hash(state);
+ }
+ #[cfg(feature = "full")]
+ crate::Expr::Continue(v0) => {
+ state.write_u8(11u8);
+ v0.hash(state);
+ }
+ crate::Expr::Field(v0) => {
+ state.write_u8(12u8);
+ v0.hash(state);
+ }
+ #[cfg(feature = "full")]
+ crate::Expr::ForLoop(v0) => {
+ state.write_u8(13u8);
+ v0.hash(state);
+ }
+ crate::Expr::Group(v0) => {
+ state.write_u8(14u8);
+ v0.hash(state);
+ }
+ #[cfg(feature = "full")]
+ crate::Expr::If(v0) => {
+ state.write_u8(15u8);
+ v0.hash(state);
+ }
+ crate::Expr::Index(v0) => {
+ state.write_u8(16u8);
+ v0.hash(state);
+ }
+ #[cfg(feature = "full")]
+ crate::Expr::Infer(v0) => {
+ state.write_u8(17u8);
+ v0.hash(state);
+ }
+ #[cfg(feature = "full")]
+ crate::Expr::Let(v0) => {
+ state.write_u8(18u8);
+ v0.hash(state);
+ }
+ crate::Expr::Lit(v0) => {
+ state.write_u8(19u8);
+ v0.hash(state);
+ }
+ #[cfg(feature = "full")]
+ crate::Expr::Loop(v0) => {
+ state.write_u8(20u8);
+ v0.hash(state);
+ }
+ crate::Expr::Macro(v0) => {
+ state.write_u8(21u8);
+ v0.hash(state);
+ }
+ #[cfg(feature = "full")]
+ crate::Expr::Match(v0) => {
+ state.write_u8(22u8);
+ v0.hash(state);
+ }
+ crate::Expr::MethodCall(v0) => {
+ state.write_u8(23u8);
+ v0.hash(state);
+ }
+ crate::Expr::Paren(v0) => {
+ state.write_u8(24u8);
+ v0.hash(state);
+ }
+ crate::Expr::Path(v0) => {
+ state.write_u8(25u8);
+ v0.hash(state);
+ }
+ #[cfg(feature = "full")]
+ crate::Expr::Range(v0) => {
+ state.write_u8(26u8);
+ v0.hash(state);
+ }
+ #[cfg(feature = "full")]
+ crate::Expr::RawAddr(v0) => {
+ state.write_u8(27u8);
+ v0.hash(state);
+ }
+ crate::Expr::Reference(v0) => {
+ state.write_u8(28u8);
+ v0.hash(state);
+ }
+ #[cfg(feature = "full")]
+ crate::Expr::Repeat(v0) => {
+ state.write_u8(29u8);
+ v0.hash(state);
+ }
+ #[cfg(feature = "full")]
+ crate::Expr::Return(v0) => {
+ state.write_u8(30u8);
+ v0.hash(state);
+ }
+ crate::Expr::Struct(v0) => {
+ state.write_u8(31u8);
+ v0.hash(state);
+ }
+ #[cfg(feature = "full")]
+ crate::Expr::Try(v0) => {
+ state.write_u8(32u8);
+ v0.hash(state);
+ }
+ #[cfg(feature = "full")]
+ crate::Expr::TryBlock(v0) => {
+ state.write_u8(33u8);
+ v0.hash(state);
+ }
+ crate::Expr::Tuple(v0) => {
+ state.write_u8(34u8);
+ v0.hash(state);
+ }
+ crate::Expr::Unary(v0) => {
+ state.write_u8(35u8);
+ v0.hash(state);
+ }
+ #[cfg(feature = "full")]
+ crate::Expr::Unsafe(v0) => {
+ state.write_u8(36u8);
+ v0.hash(state);
+ }
+ crate::Expr::Verbatim(v0) => {
+ state.write_u8(37u8);
+ TokenStreamHelper(v0).hash(state);
+ }
+ #[cfg(feature = "full")]
+ crate::Expr::While(v0) => {
+ state.write_u8(38u8);
+ v0.hash(state);
+ }
+ #[cfg(feature = "full")]
+ crate::Expr::Yield(v0) => {
+ state.write_u8(39u8);
+ v0.hash(state);
+ }
+ #[cfg(not(feature = "full"))]
+ _ => unreachable!(),
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ExprArray {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.elems.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ExprAssign {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.left.hash(state);
+ self.right.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ExprAsync {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.capture.hash(state);
+ self.block.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ExprAwait {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.base.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ExprBinary {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.left.hash(state);
+ self.op.hash(state);
+ self.right.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ExprBlock {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.label.hash(state);
+ self.block.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ExprBreak {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.label.hash(state);
+ self.expr.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ExprCall {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.func.hash(state);
+ self.args.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ExprCast {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.expr.hash(state);
+ self.ty.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ExprClosure {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.lifetimes.hash(state);
+ self.constness.hash(state);
+ self.movability.hash(state);
+ self.asyncness.hash(state);
+ self.capture.hash(state);
+ self.inputs.hash(state);
+ self.output.hash(state);
+ self.body.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ExprConst {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.block.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ExprContinue {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.label.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ExprField {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.base.hash(state);
+ self.member.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ExprForLoop {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.label.hash(state);
+ self.pat.hash(state);
+ self.expr.hash(state);
+ self.body.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ExprGroup {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.expr.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ExprIf {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.cond.hash(state);
+ self.then_branch.hash(state);
+ self.else_branch.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ExprIndex {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.expr.hash(state);
+ self.index.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ExprInfer {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ExprLet {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.pat.hash(state);
+ self.expr.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ExprLit {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.lit.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ExprLoop {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.label.hash(state);
+ self.body.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ExprMacro {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.mac.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ExprMatch {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.expr.hash(state);
+ self.arms.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ExprMethodCall {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.receiver.hash(state);
+ self.method.hash(state);
+ self.turbofish.hash(state);
+ self.args.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ExprParen {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.expr.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ExprPath {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.qself.hash(state);
+ self.path.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ExprRange {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.start.hash(state);
+ self.limits.hash(state);
+ self.end.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ExprRawAddr {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.mutability.hash(state);
+ self.expr.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ExprReference {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.mutability.hash(state);
+ self.expr.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ExprRepeat {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.expr.hash(state);
+ self.len.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ExprReturn {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.expr.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ExprStruct {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.qself.hash(state);
+ self.path.hash(state);
+ self.fields.hash(state);
+ self.dot2_token.hash(state);
+ self.rest.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ExprTry {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.expr.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ExprTryBlock {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.block.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ExprTuple {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.elems.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ExprUnary {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.op.hash(state);
+ self.expr.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ExprUnsafe {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.block.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ExprWhile {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.label.hash(state);
+ self.cond.hash(state);
+ self.body.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ExprYield {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.expr.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::Field {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.vis.hash(state);
+ self.mutability.hash(state);
+ self.ident.hash(state);
+ self.colon_token.hash(state);
+ self.ty.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::FieldMutability {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ match self {
+ crate::FieldMutability::None => {
+ state.write_u8(0u8);
+ }
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::FieldPat {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.member.hash(state);
+ self.colon_token.hash(state);
+ self.pat.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::FieldValue {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.member.hash(state);
+ self.colon_token.hash(state);
+ self.expr.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::Fields {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ match self {
+ crate::Fields::Named(v0) => {
+ state.write_u8(0u8);
+ v0.hash(state);
+ }
+ crate::Fields::Unnamed(v0) => {
+ state.write_u8(1u8);
+ v0.hash(state);
+ }
+ crate::Fields::Unit => {
+ state.write_u8(2u8);
+ }
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::FieldsNamed {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.named.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::FieldsUnnamed {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.unnamed.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::File {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.shebang.hash(state);
+ self.attrs.hash(state);
+ self.items.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::FnArg {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ match self {
+ crate::FnArg::Receiver(v0) => {
+ state.write_u8(0u8);
+ v0.hash(state);
+ }
+ crate::FnArg::Typed(v0) => {
+ state.write_u8(1u8);
+ v0.hash(state);
+ }
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ForeignItem {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ match self {
+ crate::ForeignItem::Fn(v0) => {
+ state.write_u8(0u8);
+ v0.hash(state);
+ }
+ crate::ForeignItem::Static(v0) => {
+ state.write_u8(1u8);
+ v0.hash(state);
+ }
+ crate::ForeignItem::Type(v0) => {
+ state.write_u8(2u8);
+ v0.hash(state);
+ }
+ crate::ForeignItem::Macro(v0) => {
+ state.write_u8(3u8);
+ v0.hash(state);
+ }
+ crate::ForeignItem::Verbatim(v0) => {
+ state.write_u8(4u8);
+ TokenStreamHelper(v0).hash(state);
+ }
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ForeignItemFn {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.vis.hash(state);
+ self.sig.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ForeignItemMacro {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.mac.hash(state);
+ self.semi_token.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ForeignItemStatic {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.vis.hash(state);
+ self.mutability.hash(state);
+ self.ident.hash(state);
+ self.ty.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ForeignItemType {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.vis.hash(state);
+ self.ident.hash(state);
+ self.generics.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::GenericArgument {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ match self {
+ crate::GenericArgument::Lifetime(v0) => {
+ state.write_u8(0u8);
+ v0.hash(state);
+ }
+ crate::GenericArgument::Type(v0) => {
+ state.write_u8(1u8);
+ v0.hash(state);
+ }
+ crate::GenericArgument::Const(v0) => {
+ state.write_u8(2u8);
+ v0.hash(state);
+ }
+ crate::GenericArgument::AssocType(v0) => {
+ state.write_u8(3u8);
+ v0.hash(state);
+ }
+ crate::GenericArgument::AssocConst(v0) => {
+ state.write_u8(4u8);
+ v0.hash(state);
+ }
+ crate::GenericArgument::Constraint(v0) => {
+ state.write_u8(5u8);
+ v0.hash(state);
+ }
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::GenericParam {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ match self {
+ crate::GenericParam::Lifetime(v0) => {
+ state.write_u8(0u8);
+ v0.hash(state);
+ }
+ crate::GenericParam::Type(v0) => {
+ state.write_u8(1u8);
+ v0.hash(state);
+ }
+ crate::GenericParam::Const(v0) => {
+ state.write_u8(2u8);
+ v0.hash(state);
+ }
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::Generics {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.lt_token.hash(state);
+ self.params.hash(state);
+ self.gt_token.hash(state);
+ self.where_clause.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ImplItem {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ match self {
+ crate::ImplItem::Const(v0) => {
+ state.write_u8(0u8);
+ v0.hash(state);
+ }
+ crate::ImplItem::Fn(v0) => {
+ state.write_u8(1u8);
+ v0.hash(state);
+ }
+ crate::ImplItem::Type(v0) => {
+ state.write_u8(2u8);
+ v0.hash(state);
+ }
+ crate::ImplItem::Macro(v0) => {
+ state.write_u8(3u8);
+ v0.hash(state);
+ }
+ crate::ImplItem::Verbatim(v0) => {
+ state.write_u8(4u8);
+ TokenStreamHelper(v0).hash(state);
+ }
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ImplItemConst {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.vis.hash(state);
+ self.defaultness.hash(state);
+ self.ident.hash(state);
+ self.generics.hash(state);
+ self.ty.hash(state);
+ self.expr.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ImplItemFn {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.vis.hash(state);
+ self.defaultness.hash(state);
+ self.sig.hash(state);
+ self.block.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ImplItemMacro {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.mac.hash(state);
+ self.semi_token.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ImplItemType {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.vis.hash(state);
+ self.defaultness.hash(state);
+ self.ident.hash(state);
+ self.generics.hash(state);
+ self.ty.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ImplRestriction {
+ fn hash<H>(&self, _state: &mut H)
+ where
+ H: Hasher,
+ {
+ match *self {}
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::Item {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ match self {
+ crate::Item::Const(v0) => {
+ state.write_u8(0u8);
+ v0.hash(state);
+ }
+ crate::Item::Enum(v0) => {
+ state.write_u8(1u8);
+ v0.hash(state);
+ }
+ crate::Item::ExternCrate(v0) => {
+ state.write_u8(2u8);
+ v0.hash(state);
+ }
+ crate::Item::Fn(v0) => {
+ state.write_u8(3u8);
+ v0.hash(state);
+ }
+ crate::Item::ForeignMod(v0) => {
+ state.write_u8(4u8);
+ v0.hash(state);
+ }
+ crate::Item::Impl(v0) => {
+ state.write_u8(5u8);
+ v0.hash(state);
+ }
+ crate::Item::Macro(v0) => {
+ state.write_u8(6u8);
+ v0.hash(state);
+ }
+ crate::Item::Mod(v0) => {
+ state.write_u8(7u8);
+ v0.hash(state);
+ }
+ crate::Item::Static(v0) => {
+ state.write_u8(8u8);
+ v0.hash(state);
+ }
+ crate::Item::Struct(v0) => {
+ state.write_u8(9u8);
+ v0.hash(state);
+ }
+ crate::Item::Trait(v0) => {
+ state.write_u8(10u8);
+ v0.hash(state);
+ }
+ crate::Item::TraitAlias(v0) => {
+ state.write_u8(11u8);
+ v0.hash(state);
+ }
+ crate::Item::Type(v0) => {
+ state.write_u8(12u8);
+ v0.hash(state);
+ }
+ crate::Item::Union(v0) => {
+ state.write_u8(13u8);
+ v0.hash(state);
+ }
+ crate::Item::Use(v0) => {
+ state.write_u8(14u8);
+ v0.hash(state);
+ }
+ crate::Item::Verbatim(v0) => {
+ state.write_u8(15u8);
+ TokenStreamHelper(v0).hash(state);
+ }
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ItemConst {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.vis.hash(state);
+ self.ident.hash(state);
+ self.generics.hash(state);
+ self.ty.hash(state);
+ self.expr.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ItemEnum {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.vis.hash(state);
+ self.ident.hash(state);
+ self.generics.hash(state);
+ self.variants.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ItemExternCrate {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.vis.hash(state);
+ self.ident.hash(state);
+ self.rename.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ItemFn {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.vis.hash(state);
+ self.sig.hash(state);
+ self.block.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ItemForeignMod {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.unsafety.hash(state);
+ self.abi.hash(state);
+ self.items.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ItemImpl {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.defaultness.hash(state);
+ self.unsafety.hash(state);
+ self.generics.hash(state);
+ self.trait_.hash(state);
+ self.self_ty.hash(state);
+ self.items.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ItemMacro {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.ident.hash(state);
+ self.mac.hash(state);
+ self.semi_token.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ItemMod {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.vis.hash(state);
+ self.unsafety.hash(state);
+ self.ident.hash(state);
+ self.content.hash(state);
+ self.semi.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ItemStatic {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.vis.hash(state);
+ self.mutability.hash(state);
+ self.ident.hash(state);
+ self.ty.hash(state);
+ self.expr.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ItemStruct {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.vis.hash(state);
+ self.ident.hash(state);
+ self.generics.hash(state);
+ self.fields.hash(state);
+ self.semi_token.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ItemTrait {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.vis.hash(state);
+ self.unsafety.hash(state);
+ self.auto_token.hash(state);
+ self.restriction.hash(state);
+ self.ident.hash(state);
+ self.generics.hash(state);
+ self.colon_token.hash(state);
+ self.supertraits.hash(state);
+ self.items.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ItemTraitAlias {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.vis.hash(state);
+ self.ident.hash(state);
+ self.generics.hash(state);
+ self.bounds.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ItemType {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.vis.hash(state);
+ self.ident.hash(state);
+ self.generics.hash(state);
+ self.ty.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ItemUnion {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.vis.hash(state);
+ self.ident.hash(state);
+ self.generics.hash(state);
+ self.fields.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ItemUse {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.vis.hash(state);
+ self.leading_colon.hash(state);
+ self.tree.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::Label {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.name.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::LifetimeParam {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.lifetime.hash(state);
+ self.colon_token.hash(state);
+ self.bounds.hash(state);
+ }
+}
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::Lit {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ match self {
+ crate::Lit::Str(v0) => {
+ state.write_u8(0u8);
+ v0.hash(state);
+ }
+ crate::Lit::ByteStr(v0) => {
+ state.write_u8(1u8);
+ v0.hash(state);
+ }
+ crate::Lit::CStr(v0) => {
+ state.write_u8(2u8);
+ v0.hash(state);
+ }
+ crate::Lit::Byte(v0) => {
+ state.write_u8(3u8);
+ v0.hash(state);
+ }
+ crate::Lit::Char(v0) => {
+ state.write_u8(4u8);
+ v0.hash(state);
+ }
+ crate::Lit::Int(v0) => {
+ state.write_u8(5u8);
+ v0.hash(state);
+ }
+ crate::Lit::Float(v0) => {
+ state.write_u8(6u8);
+ v0.hash(state);
+ }
+ crate::Lit::Bool(v0) => {
+ state.write_u8(7u8);
+ v0.hash(state);
+ }
+ crate::Lit::Verbatim(v0) => {
+ state.write_u8(8u8);
+ v0.to_string().hash(state);
+ }
+ }
+ }
+}
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::LitBool {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.value.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::Local {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.pat.hash(state);
+ self.init.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::LocalInit {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.expr.hash(state);
+ self.diverge.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::Macro {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.path.hash(state);
+ self.delimiter.hash(state);
+ TokenStreamHelper(&self.tokens).hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::MacroDelimiter {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ match self {
+ crate::MacroDelimiter::Paren(_) => {
+ state.write_u8(0u8);
+ }
+ crate::MacroDelimiter::Brace(_) => {
+ state.write_u8(1u8);
+ }
+ crate::MacroDelimiter::Bracket(_) => {
+ state.write_u8(2u8);
+ }
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::Meta {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ match self {
+ crate::Meta::Path(v0) => {
+ state.write_u8(0u8);
+ v0.hash(state);
+ }
+ crate::Meta::List(v0) => {
+ state.write_u8(1u8);
+ v0.hash(state);
+ }
+ crate::Meta::NameValue(v0) => {
+ state.write_u8(2u8);
+ v0.hash(state);
+ }
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::MetaList {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.path.hash(state);
+ self.delimiter.hash(state);
+ TokenStreamHelper(&self.tokens).hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::MetaNameValue {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.path.hash(state);
+ self.value.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ParenthesizedGenericArguments {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.inputs.hash(state);
+ self.output.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::Pat {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ match self {
+ crate::Pat::Const(v0) => {
+ state.write_u8(0u8);
+ v0.hash(state);
+ }
+ crate::Pat::Ident(v0) => {
+ state.write_u8(1u8);
+ v0.hash(state);
+ }
+ crate::Pat::Lit(v0) => {
+ state.write_u8(2u8);
+ v0.hash(state);
+ }
+ crate::Pat::Macro(v0) => {
+ state.write_u8(3u8);
+ v0.hash(state);
+ }
+ crate::Pat::Or(v0) => {
+ state.write_u8(4u8);
+ v0.hash(state);
+ }
+ crate::Pat::Paren(v0) => {
+ state.write_u8(5u8);
+ v0.hash(state);
+ }
+ crate::Pat::Path(v0) => {
+ state.write_u8(6u8);
+ v0.hash(state);
+ }
+ crate::Pat::Range(v0) => {
+ state.write_u8(7u8);
+ v0.hash(state);
+ }
+ crate::Pat::Reference(v0) => {
+ state.write_u8(8u8);
+ v0.hash(state);
+ }
+ crate::Pat::Rest(v0) => {
+ state.write_u8(9u8);
+ v0.hash(state);
+ }
+ crate::Pat::Slice(v0) => {
+ state.write_u8(10u8);
+ v0.hash(state);
+ }
+ crate::Pat::Struct(v0) => {
+ state.write_u8(11u8);
+ v0.hash(state);
+ }
+ crate::Pat::Tuple(v0) => {
+ state.write_u8(12u8);
+ v0.hash(state);
+ }
+ crate::Pat::TupleStruct(v0) => {
+ state.write_u8(13u8);
+ v0.hash(state);
+ }
+ crate::Pat::Type(v0) => {
+ state.write_u8(14u8);
+ v0.hash(state);
+ }
+ crate::Pat::Verbatim(v0) => {
+ state.write_u8(15u8);
+ TokenStreamHelper(v0).hash(state);
+ }
+ crate::Pat::Wild(v0) => {
+ state.write_u8(16u8);
+ v0.hash(state);
+ }
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::PatIdent {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.by_ref.hash(state);
+ self.mutability.hash(state);
+ self.ident.hash(state);
+ self.subpat.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::PatOr {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.leading_vert.hash(state);
+ self.cases.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::PatParen {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.pat.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::PatReference {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.mutability.hash(state);
+ self.pat.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::PatRest {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::PatSlice {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.elems.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::PatStruct {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.qself.hash(state);
+ self.path.hash(state);
+ self.fields.hash(state);
+ self.rest.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::PatTuple {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.elems.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::PatTupleStruct {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.qself.hash(state);
+ self.path.hash(state);
+ self.elems.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::PatType {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.pat.hash(state);
+ self.ty.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::PatWild {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::Path {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.leading_colon.hash(state);
+ self.segments.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::PathArguments {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ match self {
+ crate::PathArguments::None => {
+ state.write_u8(0u8);
+ }
+ crate::PathArguments::AngleBracketed(v0) => {
+ state.write_u8(1u8);
+ v0.hash(state);
+ }
+ crate::PathArguments::Parenthesized(v0) => {
+ state.write_u8(2u8);
+ v0.hash(state);
+ }
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::PathSegment {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.ident.hash(state);
+ self.arguments.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::PointerMutability {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ match self {
+ crate::PointerMutability::Const(_) => {
+ state.write_u8(0u8);
+ }
+ crate::PointerMutability::Mut(_) => {
+ state.write_u8(1u8);
+ }
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::PreciseCapture {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.params.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::PredicateLifetime {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.lifetime.hash(state);
+ self.bounds.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::PredicateType {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.lifetimes.hash(state);
+ self.bounded_ty.hash(state);
+ self.bounds.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::QSelf {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.ty.hash(state);
+ self.position.hash(state);
+ self.as_token.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::RangeLimits {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ match self {
+ crate::RangeLimits::HalfOpen(_) => {
+ state.write_u8(0u8);
+ }
+ crate::RangeLimits::Closed(_) => {
+ state.write_u8(1u8);
+ }
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::Receiver {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.reference.hash(state);
+ self.mutability.hash(state);
+ self.colon_token.hash(state);
+ self.ty.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::ReturnType {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ match self {
+ crate::ReturnType::Default => {
+ state.write_u8(0u8);
+ }
+ crate::ReturnType::Type(_, v1) => {
+ state.write_u8(1u8);
+ v1.hash(state);
+ }
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::Signature {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.constness.hash(state);
+ self.asyncness.hash(state);
+ self.unsafety.hash(state);
+ self.abi.hash(state);
+ self.ident.hash(state);
+ self.generics.hash(state);
+ self.inputs.hash(state);
+ self.variadic.hash(state);
+ self.output.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::StaticMutability {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ match self {
+ crate::StaticMutability::Mut(_) => {
+ state.write_u8(0u8);
+ }
+ crate::StaticMutability::None => {
+ state.write_u8(1u8);
+ }
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::Stmt {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ match self {
+ crate::Stmt::Local(v0) => {
+ state.write_u8(0u8);
+ v0.hash(state);
+ }
+ crate::Stmt::Item(v0) => {
+ state.write_u8(1u8);
+ v0.hash(state);
+ }
+ crate::Stmt::Expr(v0, v1) => {
+ state.write_u8(2u8);
+ v0.hash(state);
+ v1.hash(state);
+ }
+ crate::Stmt::Macro(v0) => {
+ state.write_u8(3u8);
+ v0.hash(state);
+ }
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::StmtMacro {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.mac.hash(state);
+ self.semi_token.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::TraitBound {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.paren_token.hash(state);
+ self.modifier.hash(state);
+ self.lifetimes.hash(state);
+ self.path.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::TraitBoundModifier {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ match self {
+ crate::TraitBoundModifier::None => {
+ state.write_u8(0u8);
+ }
+ crate::TraitBoundModifier::Maybe(_) => {
+ state.write_u8(1u8);
+ }
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::TraitItem {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ match self {
+ crate::TraitItem::Const(v0) => {
+ state.write_u8(0u8);
+ v0.hash(state);
+ }
+ crate::TraitItem::Fn(v0) => {
+ state.write_u8(1u8);
+ v0.hash(state);
+ }
+ crate::TraitItem::Type(v0) => {
+ state.write_u8(2u8);
+ v0.hash(state);
+ }
+ crate::TraitItem::Macro(v0) => {
+ state.write_u8(3u8);
+ v0.hash(state);
+ }
+ crate::TraitItem::Verbatim(v0) => {
+ state.write_u8(4u8);
+ TokenStreamHelper(v0).hash(state);
+ }
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::TraitItemConst {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.ident.hash(state);
+ self.generics.hash(state);
+ self.ty.hash(state);
+ self.default.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::TraitItemFn {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.sig.hash(state);
+ self.default.hash(state);
+ self.semi_token.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::TraitItemMacro {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.mac.hash(state);
+ self.semi_token.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::TraitItemType {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.ident.hash(state);
+ self.generics.hash(state);
+ self.colon_token.hash(state);
+ self.bounds.hash(state);
+ self.default.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::Type {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ match self {
+ crate::Type::Array(v0) => {
+ state.write_u8(0u8);
+ v0.hash(state);
+ }
+ crate::Type::BareFn(v0) => {
+ state.write_u8(1u8);
+ v0.hash(state);
+ }
+ crate::Type::Group(v0) => {
+ state.write_u8(2u8);
+ v0.hash(state);
+ }
+ crate::Type::ImplTrait(v0) => {
+ state.write_u8(3u8);
+ v0.hash(state);
+ }
+ crate::Type::Infer(v0) => {
+ state.write_u8(4u8);
+ v0.hash(state);
+ }
+ crate::Type::Macro(v0) => {
+ state.write_u8(5u8);
+ v0.hash(state);
+ }
+ crate::Type::Never(v0) => {
+ state.write_u8(6u8);
+ v0.hash(state);
+ }
+ crate::Type::Paren(v0) => {
+ state.write_u8(7u8);
+ v0.hash(state);
+ }
+ crate::Type::Path(v0) => {
+ state.write_u8(8u8);
+ v0.hash(state);
+ }
+ crate::Type::Ptr(v0) => {
+ state.write_u8(9u8);
+ v0.hash(state);
+ }
+ crate::Type::Reference(v0) => {
+ state.write_u8(10u8);
+ v0.hash(state);
+ }
+ crate::Type::Slice(v0) => {
+ state.write_u8(11u8);
+ v0.hash(state);
+ }
+ crate::Type::TraitObject(v0) => {
+ state.write_u8(12u8);
+ v0.hash(state);
+ }
+ crate::Type::Tuple(v0) => {
+ state.write_u8(13u8);
+ v0.hash(state);
+ }
+ crate::Type::Verbatim(v0) => {
+ state.write_u8(14u8);
+ TokenStreamHelper(v0).hash(state);
+ }
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::TypeArray {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.elem.hash(state);
+ self.len.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::TypeBareFn {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.lifetimes.hash(state);
+ self.unsafety.hash(state);
+ self.abi.hash(state);
+ self.inputs.hash(state);
+ self.variadic.hash(state);
+ self.output.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::TypeGroup {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.elem.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::TypeImplTrait {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.bounds.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::TypeInfer {
+ fn hash<H>(&self, _state: &mut H)
+ where
+ H: Hasher,
+ {}
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::TypeMacro {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.mac.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::TypeNever {
+ fn hash<H>(&self, _state: &mut H)
+ where
+ H: Hasher,
+ {}
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::TypeParam {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.ident.hash(state);
+ self.colon_token.hash(state);
+ self.bounds.hash(state);
+ self.eq_token.hash(state);
+ self.default.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::TypeParamBound {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ match self {
+ crate::TypeParamBound::Trait(v0) => {
+ state.write_u8(0u8);
+ v0.hash(state);
+ }
+ crate::TypeParamBound::Lifetime(v0) => {
+ state.write_u8(1u8);
+ v0.hash(state);
+ }
+ #[cfg(feature = "full")]
+ crate::TypeParamBound::PreciseCapture(v0) => {
+ state.write_u8(2u8);
+ v0.hash(state);
+ }
+ crate::TypeParamBound::Verbatim(v0) => {
+ state.write_u8(3u8);
+ TokenStreamHelper(v0).hash(state);
+ }
+ #[cfg(not(feature = "full"))]
+ _ => unreachable!(),
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::TypeParen {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.elem.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::TypePath {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.qself.hash(state);
+ self.path.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::TypePtr {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.const_token.hash(state);
+ self.mutability.hash(state);
+ self.elem.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::TypeReference {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.lifetime.hash(state);
+ self.mutability.hash(state);
+ self.elem.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::TypeSlice {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.elem.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::TypeTraitObject {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.dyn_token.hash(state);
+ self.bounds.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::TypeTuple {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.elems.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::UnOp {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ match self {
+ crate::UnOp::Deref(_) => {
+ state.write_u8(0u8);
+ }
+ crate::UnOp::Not(_) => {
+ state.write_u8(1u8);
+ }
+ crate::UnOp::Neg(_) => {
+ state.write_u8(2u8);
+ }
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::UseGlob {
+ fn hash<H>(&self, _state: &mut H)
+ where
+ H: Hasher,
+ {}
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::UseGroup {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.items.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::UseName {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.ident.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::UsePath {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.ident.hash(state);
+ self.tree.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::UseRename {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.ident.hash(state);
+ self.rename.hash(state);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::UseTree {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ match self {
+ crate::UseTree::Path(v0) => {
+ state.write_u8(0u8);
+ v0.hash(state);
+ }
+ crate::UseTree::Name(v0) => {
+ state.write_u8(1u8);
+ v0.hash(state);
+ }
+ crate::UseTree::Rename(v0) => {
+ state.write_u8(2u8);
+ v0.hash(state);
+ }
+ crate::UseTree::Glob(v0) => {
+ state.write_u8(3u8);
+ v0.hash(state);
+ }
+ crate::UseTree::Group(v0) => {
+ state.write_u8(4u8);
+ v0.hash(state);
+ }
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::Variadic {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.pat.hash(state);
+ self.comma.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::Variant {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.attrs.hash(state);
+ self.ident.hash(state);
+ self.fields.hash(state);
+ self.discriminant.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::VisRestricted {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.in_token.hash(state);
+ self.path.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::Visibility {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ match self {
+ crate::Visibility::Public(_) => {
+ state.write_u8(0u8);
+ }
+ crate::Visibility::Restricted(v0) => {
+ state.write_u8(1u8);
+ v0.hash(state);
+ }
+ crate::Visibility::Inherited => {
+ state.write_u8(2u8);
+ }
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::WhereClause {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.predicates.hash(state);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for crate::WherePredicate {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ match self {
+ crate::WherePredicate::Lifetime(v0) => {
+ state.write_u8(0u8);
+ v0.hash(state);
+ }
+ crate::WherePredicate::Type(v0) => {
+ state.write_u8(1u8);
+ v0.hash(state);
+ }
+ }
+ }
+}
diff --git a/rust/syn/gen/visit.rs b/rust/syn/gen/visit.rs
new file mode 100644
index 000000000000..cd258fcde120
--- /dev/null
+++ b/rust/syn/gen/visit.rs
@@ -0,0 +1,3941 @@
+// This file is @generated by syn-internal-codegen.
+// It is not intended for manual editing.
+
+#![allow(unused_variables)]
+#![allow(clippy::needless_pass_by_ref_mut)]
+#[cfg(any(feature = "full", feature = "derive"))]
+use crate::punctuated::Punctuated;
+#[cfg(feature = "full")]
+macro_rules! full {
+ ($e:expr) => {
+ $e
+ };
+}
+#[cfg(all(feature = "derive", not(feature = "full")))]
+macro_rules! full {
+ ($e:expr) => {
+ unreachable!()
+ };
+}
+macro_rules! skip {
+ ($($tt:tt)*) => {};
+}
+/// Syntax tree traversal to walk a shared borrow of a syntax tree.
+///
+/// See the [module documentation] for details.
+///
+/// [module documentation]: self
+pub trait Visit<'ast> {
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_abi(&mut self, i: &'ast crate::Abi) {
+ visit_abi(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_angle_bracketed_generic_arguments(
+ &mut self,
+ i: &'ast crate::AngleBracketedGenericArguments,
+ ) {
+ visit_angle_bracketed_generic_arguments(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_arm(&mut self, i: &'ast crate::Arm) {
+ visit_arm(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_assoc_const(&mut self, i: &'ast crate::AssocConst) {
+ visit_assoc_const(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_assoc_type(&mut self, i: &'ast crate::AssocType) {
+ visit_assoc_type(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_attr_style(&mut self, i: &'ast crate::AttrStyle) {
+ visit_attr_style(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_attribute(&mut self, i: &'ast crate::Attribute) {
+ visit_attribute(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_bare_fn_arg(&mut self, i: &'ast crate::BareFnArg) {
+ visit_bare_fn_arg(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_bare_variadic(&mut self, i: &'ast crate::BareVariadic) {
+ visit_bare_variadic(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_bin_op(&mut self, i: &'ast crate::BinOp) {
+ visit_bin_op(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_block(&mut self, i: &'ast crate::Block) {
+ visit_block(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_bound_lifetimes(&mut self, i: &'ast crate::BoundLifetimes) {
+ visit_bound_lifetimes(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_captured_param(&mut self, i: &'ast crate::CapturedParam) {
+ visit_captured_param(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_const_param(&mut self, i: &'ast crate::ConstParam) {
+ visit_const_param(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_constraint(&mut self, i: &'ast crate::Constraint) {
+ visit_constraint(self, i);
+ }
+ #[cfg(feature = "derive")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
+ fn visit_data(&mut self, i: &'ast crate::Data) {
+ visit_data(self, i);
+ }
+ #[cfg(feature = "derive")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
+ fn visit_data_enum(&mut self, i: &'ast crate::DataEnum) {
+ visit_data_enum(self, i);
+ }
+ #[cfg(feature = "derive")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
+ fn visit_data_struct(&mut self, i: &'ast crate::DataStruct) {
+ visit_data_struct(self, i);
+ }
+ #[cfg(feature = "derive")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
+ fn visit_data_union(&mut self, i: &'ast crate::DataUnion) {
+ visit_data_union(self, i);
+ }
+ #[cfg(feature = "derive")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
+ fn visit_derive_input(&mut self, i: &'ast crate::DeriveInput) {
+ visit_derive_input(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_expr(&mut self, i: &'ast crate::Expr) {
+ visit_expr(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_array(&mut self, i: &'ast crate::ExprArray) {
+ visit_expr_array(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_assign(&mut self, i: &'ast crate::ExprAssign) {
+ visit_expr_assign(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_async(&mut self, i: &'ast crate::ExprAsync) {
+ visit_expr_async(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_await(&mut self, i: &'ast crate::ExprAwait) {
+ visit_expr_await(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_expr_binary(&mut self, i: &'ast crate::ExprBinary) {
+ visit_expr_binary(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_block(&mut self, i: &'ast crate::ExprBlock) {
+ visit_expr_block(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_break(&mut self, i: &'ast crate::ExprBreak) {
+ visit_expr_break(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_expr_call(&mut self, i: &'ast crate::ExprCall) {
+ visit_expr_call(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_expr_cast(&mut self, i: &'ast crate::ExprCast) {
+ visit_expr_cast(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_closure(&mut self, i: &'ast crate::ExprClosure) {
+ visit_expr_closure(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_const(&mut self, i: &'ast crate::ExprConst) {
+ visit_expr_const(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_continue(&mut self, i: &'ast crate::ExprContinue) {
+ visit_expr_continue(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_expr_field(&mut self, i: &'ast crate::ExprField) {
+ visit_expr_field(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_for_loop(&mut self, i: &'ast crate::ExprForLoop) {
+ visit_expr_for_loop(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_expr_group(&mut self, i: &'ast crate::ExprGroup) {
+ visit_expr_group(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_if(&mut self, i: &'ast crate::ExprIf) {
+ visit_expr_if(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_expr_index(&mut self, i: &'ast crate::ExprIndex) {
+ visit_expr_index(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_infer(&mut self, i: &'ast crate::ExprInfer) {
+ visit_expr_infer(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_let(&mut self, i: &'ast crate::ExprLet) {
+ visit_expr_let(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_expr_lit(&mut self, i: &'ast crate::ExprLit) {
+ visit_expr_lit(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_loop(&mut self, i: &'ast crate::ExprLoop) {
+ visit_expr_loop(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_expr_macro(&mut self, i: &'ast crate::ExprMacro) {
+ visit_expr_macro(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_match(&mut self, i: &'ast crate::ExprMatch) {
+ visit_expr_match(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_expr_method_call(&mut self, i: &'ast crate::ExprMethodCall) {
+ visit_expr_method_call(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_expr_paren(&mut self, i: &'ast crate::ExprParen) {
+ visit_expr_paren(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_expr_path(&mut self, i: &'ast crate::ExprPath) {
+ visit_expr_path(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_range(&mut self, i: &'ast crate::ExprRange) {
+ visit_expr_range(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_raw_addr(&mut self, i: &'ast crate::ExprRawAddr) {
+ visit_expr_raw_addr(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_expr_reference(&mut self, i: &'ast crate::ExprReference) {
+ visit_expr_reference(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_repeat(&mut self, i: &'ast crate::ExprRepeat) {
+ visit_expr_repeat(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_return(&mut self, i: &'ast crate::ExprReturn) {
+ visit_expr_return(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_expr_struct(&mut self, i: &'ast crate::ExprStruct) {
+ visit_expr_struct(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_try(&mut self, i: &'ast crate::ExprTry) {
+ visit_expr_try(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_try_block(&mut self, i: &'ast crate::ExprTryBlock) {
+ visit_expr_try_block(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_expr_tuple(&mut self, i: &'ast crate::ExprTuple) {
+ visit_expr_tuple(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_expr_unary(&mut self, i: &'ast crate::ExprUnary) {
+ visit_expr_unary(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_unsafe(&mut self, i: &'ast crate::ExprUnsafe) {
+ visit_expr_unsafe(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_while(&mut self, i: &'ast crate::ExprWhile) {
+ visit_expr_while(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_yield(&mut self, i: &'ast crate::ExprYield) {
+ visit_expr_yield(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_field(&mut self, i: &'ast crate::Field) {
+ visit_field(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_field_mutability(&mut self, i: &'ast crate::FieldMutability) {
+ visit_field_mutability(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_field_pat(&mut self, i: &'ast crate::FieldPat) {
+ visit_field_pat(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_field_value(&mut self, i: &'ast crate::FieldValue) {
+ visit_field_value(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_fields(&mut self, i: &'ast crate::Fields) {
+ visit_fields(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_fields_named(&mut self, i: &'ast crate::FieldsNamed) {
+ visit_fields_named(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_fields_unnamed(&mut self, i: &'ast crate::FieldsUnnamed) {
+ visit_fields_unnamed(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_file(&mut self, i: &'ast crate::File) {
+ visit_file(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_fn_arg(&mut self, i: &'ast crate::FnArg) {
+ visit_fn_arg(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_foreign_item(&mut self, i: &'ast crate::ForeignItem) {
+ visit_foreign_item(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_foreign_item_fn(&mut self, i: &'ast crate::ForeignItemFn) {
+ visit_foreign_item_fn(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_foreign_item_macro(&mut self, i: &'ast crate::ForeignItemMacro) {
+ visit_foreign_item_macro(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_foreign_item_static(&mut self, i: &'ast crate::ForeignItemStatic) {
+ visit_foreign_item_static(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_foreign_item_type(&mut self, i: &'ast crate::ForeignItemType) {
+ visit_foreign_item_type(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_generic_argument(&mut self, i: &'ast crate::GenericArgument) {
+ visit_generic_argument(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_generic_param(&mut self, i: &'ast crate::GenericParam) {
+ visit_generic_param(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_generics(&mut self, i: &'ast crate::Generics) {
+ visit_generics(self, i);
+ }
+ fn visit_ident(&mut self, i: &'ast proc_macro2::Ident) {
+ visit_ident(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_impl_item(&mut self, i: &'ast crate::ImplItem) {
+ visit_impl_item(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_impl_item_const(&mut self, i: &'ast crate::ImplItemConst) {
+ visit_impl_item_const(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_impl_item_fn(&mut self, i: &'ast crate::ImplItemFn) {
+ visit_impl_item_fn(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_impl_item_macro(&mut self, i: &'ast crate::ImplItemMacro) {
+ visit_impl_item_macro(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_impl_item_type(&mut self, i: &'ast crate::ImplItemType) {
+ visit_impl_item_type(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_impl_restriction(&mut self, i: &'ast crate::ImplRestriction) {
+ visit_impl_restriction(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_index(&mut self, i: &'ast crate::Index) {
+ visit_index(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_item(&mut self, i: &'ast crate::Item) {
+ visit_item(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_item_const(&mut self, i: &'ast crate::ItemConst) {
+ visit_item_const(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_item_enum(&mut self, i: &'ast crate::ItemEnum) {
+ visit_item_enum(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_item_extern_crate(&mut self, i: &'ast crate::ItemExternCrate) {
+ visit_item_extern_crate(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_item_fn(&mut self, i: &'ast crate::ItemFn) {
+ visit_item_fn(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_item_foreign_mod(&mut self, i: &'ast crate::ItemForeignMod) {
+ visit_item_foreign_mod(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_item_impl(&mut self, i: &'ast crate::ItemImpl) {
+ visit_item_impl(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_item_macro(&mut self, i: &'ast crate::ItemMacro) {
+ visit_item_macro(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_item_mod(&mut self, i: &'ast crate::ItemMod) {
+ visit_item_mod(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_item_static(&mut self, i: &'ast crate::ItemStatic) {
+ visit_item_static(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_item_struct(&mut self, i: &'ast crate::ItemStruct) {
+ visit_item_struct(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_item_trait(&mut self, i: &'ast crate::ItemTrait) {
+ visit_item_trait(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_item_trait_alias(&mut self, i: &'ast crate::ItemTraitAlias) {
+ visit_item_trait_alias(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_item_type(&mut self, i: &'ast crate::ItemType) {
+ visit_item_type(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_item_union(&mut self, i: &'ast crate::ItemUnion) {
+ visit_item_union(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_item_use(&mut self, i: &'ast crate::ItemUse) {
+ visit_item_use(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_label(&mut self, i: &'ast crate::Label) {
+ visit_label(self, i);
+ }
+ fn visit_lifetime(&mut self, i: &'ast crate::Lifetime) {
+ visit_lifetime(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_lifetime_param(&mut self, i: &'ast crate::LifetimeParam) {
+ visit_lifetime_param(self, i);
+ }
+ fn visit_lit(&mut self, i: &'ast crate::Lit) {
+ visit_lit(self, i);
+ }
+ fn visit_lit_bool(&mut self, i: &'ast crate::LitBool) {
+ visit_lit_bool(self, i);
+ }
+ fn visit_lit_byte(&mut self, i: &'ast crate::LitByte) {
+ visit_lit_byte(self, i);
+ }
+ fn visit_lit_byte_str(&mut self, i: &'ast crate::LitByteStr) {
+ visit_lit_byte_str(self, i);
+ }
+ fn visit_lit_cstr(&mut self, i: &'ast crate::LitCStr) {
+ visit_lit_cstr(self, i);
+ }
+ fn visit_lit_char(&mut self, i: &'ast crate::LitChar) {
+ visit_lit_char(self, i);
+ }
+ fn visit_lit_float(&mut self, i: &'ast crate::LitFloat) {
+ visit_lit_float(self, i);
+ }
+ fn visit_lit_int(&mut self, i: &'ast crate::LitInt) {
+ visit_lit_int(self, i);
+ }
+ fn visit_lit_str(&mut self, i: &'ast crate::LitStr) {
+ visit_lit_str(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_local(&mut self, i: &'ast crate::Local) {
+ visit_local(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_local_init(&mut self, i: &'ast crate::LocalInit) {
+ visit_local_init(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_macro(&mut self, i: &'ast crate::Macro) {
+ visit_macro(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_macro_delimiter(&mut self, i: &'ast crate::MacroDelimiter) {
+ visit_macro_delimiter(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_member(&mut self, i: &'ast crate::Member) {
+ visit_member(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_meta(&mut self, i: &'ast crate::Meta) {
+ visit_meta(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_meta_list(&mut self, i: &'ast crate::MetaList) {
+ visit_meta_list(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_meta_name_value(&mut self, i: &'ast crate::MetaNameValue) {
+ visit_meta_name_value(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_parenthesized_generic_arguments(
+ &mut self,
+ i: &'ast crate::ParenthesizedGenericArguments,
+ ) {
+ visit_parenthesized_generic_arguments(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_pat(&mut self, i: &'ast crate::Pat) {
+ visit_pat(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_pat_ident(&mut self, i: &'ast crate::PatIdent) {
+ visit_pat_ident(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_pat_or(&mut self, i: &'ast crate::PatOr) {
+ visit_pat_or(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_pat_paren(&mut self, i: &'ast crate::PatParen) {
+ visit_pat_paren(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_pat_reference(&mut self, i: &'ast crate::PatReference) {
+ visit_pat_reference(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_pat_rest(&mut self, i: &'ast crate::PatRest) {
+ visit_pat_rest(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_pat_slice(&mut self, i: &'ast crate::PatSlice) {
+ visit_pat_slice(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_pat_struct(&mut self, i: &'ast crate::PatStruct) {
+ visit_pat_struct(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_pat_tuple(&mut self, i: &'ast crate::PatTuple) {
+ visit_pat_tuple(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_pat_tuple_struct(&mut self, i: &'ast crate::PatTupleStruct) {
+ visit_pat_tuple_struct(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_pat_type(&mut self, i: &'ast crate::PatType) {
+ visit_pat_type(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_pat_wild(&mut self, i: &'ast crate::PatWild) {
+ visit_pat_wild(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_path(&mut self, i: &'ast crate::Path) {
+ visit_path(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_path_arguments(&mut self, i: &'ast crate::PathArguments) {
+ visit_path_arguments(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_path_segment(&mut self, i: &'ast crate::PathSegment) {
+ visit_path_segment(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_pointer_mutability(&mut self, i: &'ast crate::PointerMutability) {
+ visit_pointer_mutability(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_precise_capture(&mut self, i: &'ast crate::PreciseCapture) {
+ visit_precise_capture(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_predicate_lifetime(&mut self, i: &'ast crate::PredicateLifetime) {
+ visit_predicate_lifetime(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_predicate_type(&mut self, i: &'ast crate::PredicateType) {
+ visit_predicate_type(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_qself(&mut self, i: &'ast crate::QSelf) {
+ visit_qself(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_range_limits(&mut self, i: &'ast crate::RangeLimits) {
+ visit_range_limits(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_receiver(&mut self, i: &'ast crate::Receiver) {
+ visit_receiver(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_return_type(&mut self, i: &'ast crate::ReturnType) {
+ visit_return_type(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_signature(&mut self, i: &'ast crate::Signature) {
+ visit_signature(self, i);
+ }
+ fn visit_span(&mut self, i: &proc_macro2::Span) {}
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_static_mutability(&mut self, i: &'ast crate::StaticMutability) {
+ visit_static_mutability(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_stmt(&mut self, i: &'ast crate::Stmt) {
+ visit_stmt(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_stmt_macro(&mut self, i: &'ast crate::StmtMacro) {
+ visit_stmt_macro(self, i);
+ }
+ fn visit_token_stream(&mut self, i: &'ast proc_macro2::TokenStream) {}
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_trait_bound(&mut self, i: &'ast crate::TraitBound) {
+ visit_trait_bound(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_trait_bound_modifier(&mut self, i: &'ast crate::TraitBoundModifier) {
+ visit_trait_bound_modifier(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_trait_item(&mut self, i: &'ast crate::TraitItem) {
+ visit_trait_item(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_trait_item_const(&mut self, i: &'ast crate::TraitItemConst) {
+ visit_trait_item_const(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_trait_item_fn(&mut self, i: &'ast crate::TraitItemFn) {
+ visit_trait_item_fn(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_trait_item_macro(&mut self, i: &'ast crate::TraitItemMacro) {
+ visit_trait_item_macro(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_trait_item_type(&mut self, i: &'ast crate::TraitItemType) {
+ visit_trait_item_type(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_type(&mut self, i: &'ast crate::Type) {
+ visit_type(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_type_array(&mut self, i: &'ast crate::TypeArray) {
+ visit_type_array(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_type_bare_fn(&mut self, i: &'ast crate::TypeBareFn) {
+ visit_type_bare_fn(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_type_group(&mut self, i: &'ast crate::TypeGroup) {
+ visit_type_group(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_type_impl_trait(&mut self, i: &'ast crate::TypeImplTrait) {
+ visit_type_impl_trait(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_type_infer(&mut self, i: &'ast crate::TypeInfer) {
+ visit_type_infer(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_type_macro(&mut self, i: &'ast crate::TypeMacro) {
+ visit_type_macro(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_type_never(&mut self, i: &'ast crate::TypeNever) {
+ visit_type_never(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_type_param(&mut self, i: &'ast crate::TypeParam) {
+ visit_type_param(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_type_param_bound(&mut self, i: &'ast crate::TypeParamBound) {
+ visit_type_param_bound(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_type_paren(&mut self, i: &'ast crate::TypeParen) {
+ visit_type_paren(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_type_path(&mut self, i: &'ast crate::TypePath) {
+ visit_type_path(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_type_ptr(&mut self, i: &'ast crate::TypePtr) {
+ visit_type_ptr(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_type_reference(&mut self, i: &'ast crate::TypeReference) {
+ visit_type_reference(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_type_slice(&mut self, i: &'ast crate::TypeSlice) {
+ visit_type_slice(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_type_trait_object(&mut self, i: &'ast crate::TypeTraitObject) {
+ visit_type_trait_object(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_type_tuple(&mut self, i: &'ast crate::TypeTuple) {
+ visit_type_tuple(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_un_op(&mut self, i: &'ast crate::UnOp) {
+ visit_un_op(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_use_glob(&mut self, i: &'ast crate::UseGlob) {
+ visit_use_glob(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_use_group(&mut self, i: &'ast crate::UseGroup) {
+ visit_use_group(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_use_name(&mut self, i: &'ast crate::UseName) {
+ visit_use_name(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_use_path(&mut self, i: &'ast crate::UsePath) {
+ visit_use_path(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_use_rename(&mut self, i: &'ast crate::UseRename) {
+ visit_use_rename(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_use_tree(&mut self, i: &'ast crate::UseTree) {
+ visit_use_tree(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_variadic(&mut self, i: &'ast crate::Variadic) {
+ visit_variadic(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_variant(&mut self, i: &'ast crate::Variant) {
+ visit_variant(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_vis_restricted(&mut self, i: &'ast crate::VisRestricted) {
+ visit_vis_restricted(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_visibility(&mut self, i: &'ast crate::Visibility) {
+ visit_visibility(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_where_clause(&mut self, i: &'ast crate::WhereClause) {
+ visit_where_clause(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_where_predicate(&mut self, i: &'ast crate::WherePredicate) {
+ visit_where_predicate(self, i);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_abi<'ast, V>(v: &mut V, node: &'ast crate::Abi)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ skip!(node.extern_token);
+ if let Some(it) = &node.name {
+ v.visit_lit_str(it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_angle_bracketed_generic_arguments<'ast, V>(
+ v: &mut V,
+ node: &'ast crate::AngleBracketedGenericArguments,
+)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ skip!(node.colon2_token);
+ skip!(node.lt_token);
+ for el in Punctuated::pairs(&node.args) {
+ let it = el.value();
+ v.visit_generic_argument(it);
+ }
+ skip!(node.gt_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_arm<'ast, V>(v: &mut V, node: &'ast crate::Arm)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_pat(&node.pat);
+ if let Some(it) = &node.guard {
+ skip!((it).0);
+ v.visit_expr(&*(it).1);
+ }
+ skip!(node.fat_arrow_token);
+ v.visit_expr(&*node.body);
+ skip!(node.comma);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_assoc_const<'ast, V>(v: &mut V, node: &'ast crate::AssocConst)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ v.visit_ident(&node.ident);
+ if let Some(it) = &node.generics {
+ v.visit_angle_bracketed_generic_arguments(it);
+ }
+ skip!(node.eq_token);
+ v.visit_expr(&node.value);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_assoc_type<'ast, V>(v: &mut V, node: &'ast crate::AssocType)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ v.visit_ident(&node.ident);
+ if let Some(it) = &node.generics {
+ v.visit_angle_bracketed_generic_arguments(it);
+ }
+ skip!(node.eq_token);
+ v.visit_type(&node.ty);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_attr_style<'ast, V>(v: &mut V, node: &'ast crate::AttrStyle)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ match node {
+ crate::AttrStyle::Outer => {}
+ crate::AttrStyle::Inner(_binding_0) => {
+ skip!(_binding_0);
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_attribute<'ast, V>(v: &mut V, node: &'ast crate::Attribute)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ skip!(node.pound_token);
+ v.visit_attr_style(&node.style);
+ skip!(node.bracket_token);
+ v.visit_meta(&node.meta);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_bare_fn_arg<'ast, V>(v: &mut V, node: &'ast crate::BareFnArg)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ if let Some(it) = &node.name {
+ v.visit_ident(&(it).0);
+ skip!((it).1);
+ }
+ v.visit_type(&node.ty);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_bare_variadic<'ast, V>(v: &mut V, node: &'ast crate::BareVariadic)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ if let Some(it) = &node.name {
+ v.visit_ident(&(it).0);
+ skip!((it).1);
+ }
+ skip!(node.dots);
+ skip!(node.comma);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_bin_op<'ast, V>(v: &mut V, node: &'ast crate::BinOp)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ match node {
+ crate::BinOp::Add(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::Sub(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::Mul(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::Div(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::Rem(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::And(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::Or(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::BitXor(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::BitAnd(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::BitOr(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::Shl(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::Shr(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::Eq(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::Lt(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::Le(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::Ne(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::Ge(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::Gt(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::AddAssign(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::SubAssign(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::MulAssign(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::DivAssign(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::RemAssign(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::BitXorAssign(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::BitAndAssign(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::BitOrAssign(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::ShlAssign(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::ShrAssign(_binding_0) => {
+ skip!(_binding_0);
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_block<'ast, V>(v: &mut V, node: &'ast crate::Block)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ skip!(node.brace_token);
+ for it in &node.stmts {
+ v.visit_stmt(it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_bound_lifetimes<'ast, V>(v: &mut V, node: &'ast crate::BoundLifetimes)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ skip!(node.for_token);
+ skip!(node.lt_token);
+ for el in Punctuated::pairs(&node.lifetimes) {
+ let it = el.value();
+ v.visit_generic_param(it);
+ }
+ skip!(node.gt_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_captured_param<'ast, V>(v: &mut V, node: &'ast crate::CapturedParam)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ match node {
+ crate::CapturedParam::Lifetime(_binding_0) => {
+ v.visit_lifetime(_binding_0);
+ }
+ crate::CapturedParam::Ident(_binding_0) => {
+ v.visit_ident(_binding_0);
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_const_param<'ast, V>(v: &mut V, node: &'ast crate::ConstParam)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ skip!(node.const_token);
+ v.visit_ident(&node.ident);
+ skip!(node.colon_token);
+ v.visit_type(&node.ty);
+ skip!(node.eq_token);
+ if let Some(it) = &node.default {
+ v.visit_expr(it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_constraint<'ast, V>(v: &mut V, node: &'ast crate::Constraint)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ v.visit_ident(&node.ident);
+ if let Some(it) = &node.generics {
+ v.visit_angle_bracketed_generic_arguments(it);
+ }
+ skip!(node.colon_token);
+ for el in Punctuated::pairs(&node.bounds) {
+ let it = el.value();
+ v.visit_type_param_bound(it);
+ }
+}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
+pub fn visit_data<'ast, V>(v: &mut V, node: &'ast crate::Data)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ match node {
+ crate::Data::Struct(_binding_0) => {
+ v.visit_data_struct(_binding_0);
+ }
+ crate::Data::Enum(_binding_0) => {
+ v.visit_data_enum(_binding_0);
+ }
+ crate::Data::Union(_binding_0) => {
+ v.visit_data_union(_binding_0);
+ }
+ }
+}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
+pub fn visit_data_enum<'ast, V>(v: &mut V, node: &'ast crate::DataEnum)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ skip!(node.enum_token);
+ skip!(node.brace_token);
+ for el in Punctuated::pairs(&node.variants) {
+ let it = el.value();
+ v.visit_variant(it);
+ }
+}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
+pub fn visit_data_struct<'ast, V>(v: &mut V, node: &'ast crate::DataStruct)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ skip!(node.struct_token);
+ v.visit_fields(&node.fields);
+ skip!(node.semi_token);
+}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
+pub fn visit_data_union<'ast, V>(v: &mut V, node: &'ast crate::DataUnion)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ skip!(node.union_token);
+ v.visit_fields_named(&node.fields);
+}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
+pub fn visit_derive_input<'ast, V>(v: &mut V, node: &'ast crate::DeriveInput)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_visibility(&node.vis);
+ v.visit_ident(&node.ident);
+ v.visit_generics(&node.generics);
+ v.visit_data(&node.data);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_expr<'ast, V>(v: &mut V, node: &'ast crate::Expr)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ match node {
+ crate::Expr::Array(_binding_0) => {
+ full!(v.visit_expr_array(_binding_0));
+ }
+ crate::Expr::Assign(_binding_0) => {
+ full!(v.visit_expr_assign(_binding_0));
+ }
+ crate::Expr::Async(_binding_0) => {
+ full!(v.visit_expr_async(_binding_0));
+ }
+ crate::Expr::Await(_binding_0) => {
+ full!(v.visit_expr_await(_binding_0));
+ }
+ crate::Expr::Binary(_binding_0) => {
+ v.visit_expr_binary(_binding_0);
+ }
+ crate::Expr::Block(_binding_0) => {
+ full!(v.visit_expr_block(_binding_0));
+ }
+ crate::Expr::Break(_binding_0) => {
+ full!(v.visit_expr_break(_binding_0));
+ }
+ crate::Expr::Call(_binding_0) => {
+ v.visit_expr_call(_binding_0);
+ }
+ crate::Expr::Cast(_binding_0) => {
+ v.visit_expr_cast(_binding_0);
+ }
+ crate::Expr::Closure(_binding_0) => {
+ full!(v.visit_expr_closure(_binding_0));
+ }
+ crate::Expr::Const(_binding_0) => {
+ full!(v.visit_expr_const(_binding_0));
+ }
+ crate::Expr::Continue(_binding_0) => {
+ full!(v.visit_expr_continue(_binding_0));
+ }
+ crate::Expr::Field(_binding_0) => {
+ v.visit_expr_field(_binding_0);
+ }
+ crate::Expr::ForLoop(_binding_0) => {
+ full!(v.visit_expr_for_loop(_binding_0));
+ }
+ crate::Expr::Group(_binding_0) => {
+ v.visit_expr_group(_binding_0);
+ }
+ crate::Expr::If(_binding_0) => {
+ full!(v.visit_expr_if(_binding_0));
+ }
+ crate::Expr::Index(_binding_0) => {
+ v.visit_expr_index(_binding_0);
+ }
+ crate::Expr::Infer(_binding_0) => {
+ full!(v.visit_expr_infer(_binding_0));
+ }
+ crate::Expr::Let(_binding_0) => {
+ full!(v.visit_expr_let(_binding_0));
+ }
+ crate::Expr::Lit(_binding_0) => {
+ v.visit_expr_lit(_binding_0);
+ }
+ crate::Expr::Loop(_binding_0) => {
+ full!(v.visit_expr_loop(_binding_0));
+ }
+ crate::Expr::Macro(_binding_0) => {
+ v.visit_expr_macro(_binding_0);
+ }
+ crate::Expr::Match(_binding_0) => {
+ full!(v.visit_expr_match(_binding_0));
+ }
+ crate::Expr::MethodCall(_binding_0) => {
+ v.visit_expr_method_call(_binding_0);
+ }
+ crate::Expr::Paren(_binding_0) => {
+ v.visit_expr_paren(_binding_0);
+ }
+ crate::Expr::Path(_binding_0) => {
+ v.visit_expr_path(_binding_0);
+ }
+ crate::Expr::Range(_binding_0) => {
+ full!(v.visit_expr_range(_binding_0));
+ }
+ crate::Expr::RawAddr(_binding_0) => {
+ full!(v.visit_expr_raw_addr(_binding_0));
+ }
+ crate::Expr::Reference(_binding_0) => {
+ v.visit_expr_reference(_binding_0);
+ }
+ crate::Expr::Repeat(_binding_0) => {
+ full!(v.visit_expr_repeat(_binding_0));
+ }
+ crate::Expr::Return(_binding_0) => {
+ full!(v.visit_expr_return(_binding_0));
+ }
+ crate::Expr::Struct(_binding_0) => {
+ v.visit_expr_struct(_binding_0);
+ }
+ crate::Expr::Try(_binding_0) => {
+ full!(v.visit_expr_try(_binding_0));
+ }
+ crate::Expr::TryBlock(_binding_0) => {
+ full!(v.visit_expr_try_block(_binding_0));
+ }
+ crate::Expr::Tuple(_binding_0) => {
+ v.visit_expr_tuple(_binding_0);
+ }
+ crate::Expr::Unary(_binding_0) => {
+ v.visit_expr_unary(_binding_0);
+ }
+ crate::Expr::Unsafe(_binding_0) => {
+ full!(v.visit_expr_unsafe(_binding_0));
+ }
+ crate::Expr::Verbatim(_binding_0) => {
+ v.visit_token_stream(_binding_0);
+ }
+ crate::Expr::While(_binding_0) => {
+ full!(v.visit_expr_while(_binding_0));
+ }
+ crate::Expr::Yield(_binding_0) => {
+ full!(v.visit_expr_yield(_binding_0));
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_array<'ast, V>(v: &mut V, node: &'ast crate::ExprArray)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ skip!(node.bracket_token);
+ for el in Punctuated::pairs(&node.elems) {
+ let it = el.value();
+ v.visit_expr(it);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_assign<'ast, V>(v: &mut V, node: &'ast crate::ExprAssign)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_expr(&*node.left);
+ skip!(node.eq_token);
+ v.visit_expr(&*node.right);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_async<'ast, V>(v: &mut V, node: &'ast crate::ExprAsync)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ skip!(node.async_token);
+ skip!(node.capture);
+ v.visit_block(&node.block);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_await<'ast, V>(v: &mut V, node: &'ast crate::ExprAwait)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_expr(&*node.base);
+ skip!(node.dot_token);
+ skip!(node.await_token);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_expr_binary<'ast, V>(v: &mut V, node: &'ast crate::ExprBinary)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_expr(&*node.left);
+ v.visit_bin_op(&node.op);
+ v.visit_expr(&*node.right);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_block<'ast, V>(v: &mut V, node: &'ast crate::ExprBlock)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ if let Some(it) = &node.label {
+ v.visit_label(it);
+ }
+ v.visit_block(&node.block);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_break<'ast, V>(v: &mut V, node: &'ast crate::ExprBreak)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ skip!(node.break_token);
+ if let Some(it) = &node.label {
+ v.visit_lifetime(it);
+ }
+ if let Some(it) = &node.expr {
+ v.visit_expr(&**it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_expr_call<'ast, V>(v: &mut V, node: &'ast crate::ExprCall)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_expr(&*node.func);
+ skip!(node.paren_token);
+ for el in Punctuated::pairs(&node.args) {
+ let it = el.value();
+ v.visit_expr(it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_expr_cast<'ast, V>(v: &mut V, node: &'ast crate::ExprCast)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_expr(&*node.expr);
+ skip!(node.as_token);
+ v.visit_type(&*node.ty);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_closure<'ast, V>(v: &mut V, node: &'ast crate::ExprClosure)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ if let Some(it) = &node.lifetimes {
+ v.visit_bound_lifetimes(it);
+ }
+ skip!(node.constness);
+ skip!(node.movability);
+ skip!(node.asyncness);
+ skip!(node.capture);
+ skip!(node.or1_token);
+ for el in Punctuated::pairs(&node.inputs) {
+ let it = el.value();
+ v.visit_pat(it);
+ }
+ skip!(node.or2_token);
+ v.visit_return_type(&node.output);
+ v.visit_expr(&*node.body);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_const<'ast, V>(v: &mut V, node: &'ast crate::ExprConst)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ skip!(node.const_token);
+ v.visit_block(&node.block);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_continue<'ast, V>(v: &mut V, node: &'ast crate::ExprContinue)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ skip!(node.continue_token);
+ if let Some(it) = &node.label {
+ v.visit_lifetime(it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_expr_field<'ast, V>(v: &mut V, node: &'ast crate::ExprField)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_expr(&*node.base);
+ skip!(node.dot_token);
+ v.visit_member(&node.member);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_for_loop<'ast, V>(v: &mut V, node: &'ast crate::ExprForLoop)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ if let Some(it) = &node.label {
+ v.visit_label(it);
+ }
+ skip!(node.for_token);
+ v.visit_pat(&*node.pat);
+ skip!(node.in_token);
+ v.visit_expr(&*node.expr);
+ v.visit_block(&node.body);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_expr_group<'ast, V>(v: &mut V, node: &'ast crate::ExprGroup)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ skip!(node.group_token);
+ v.visit_expr(&*node.expr);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_if<'ast, V>(v: &mut V, node: &'ast crate::ExprIf)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ skip!(node.if_token);
+ v.visit_expr(&*node.cond);
+ v.visit_block(&node.then_branch);
+ if let Some(it) = &node.else_branch {
+ skip!((it).0);
+ v.visit_expr(&*(it).1);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_expr_index<'ast, V>(v: &mut V, node: &'ast crate::ExprIndex)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_expr(&*node.expr);
+ skip!(node.bracket_token);
+ v.visit_expr(&*node.index);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_infer<'ast, V>(v: &mut V, node: &'ast crate::ExprInfer)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ skip!(node.underscore_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_let<'ast, V>(v: &mut V, node: &'ast crate::ExprLet)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ skip!(node.let_token);
+ v.visit_pat(&*node.pat);
+ skip!(node.eq_token);
+ v.visit_expr(&*node.expr);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_expr_lit<'ast, V>(v: &mut V, node: &'ast crate::ExprLit)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_lit(&node.lit);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_loop<'ast, V>(v: &mut V, node: &'ast crate::ExprLoop)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ if let Some(it) = &node.label {
+ v.visit_label(it);
+ }
+ skip!(node.loop_token);
+ v.visit_block(&node.body);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_expr_macro<'ast, V>(v: &mut V, node: &'ast crate::ExprMacro)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_macro(&node.mac);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_match<'ast, V>(v: &mut V, node: &'ast crate::ExprMatch)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ skip!(node.match_token);
+ v.visit_expr(&*node.expr);
+ skip!(node.brace_token);
+ for it in &node.arms {
+ v.visit_arm(it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_expr_method_call<'ast, V>(v: &mut V, node: &'ast crate::ExprMethodCall)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_expr(&*node.receiver);
+ skip!(node.dot_token);
+ v.visit_ident(&node.method);
+ if let Some(it) = &node.turbofish {
+ v.visit_angle_bracketed_generic_arguments(it);
+ }
+ skip!(node.paren_token);
+ for el in Punctuated::pairs(&node.args) {
+ let it = el.value();
+ v.visit_expr(it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_expr_paren<'ast, V>(v: &mut V, node: &'ast crate::ExprParen)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ skip!(node.paren_token);
+ v.visit_expr(&*node.expr);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_expr_path<'ast, V>(v: &mut V, node: &'ast crate::ExprPath)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ if let Some(it) = &node.qself {
+ v.visit_qself(it);
+ }
+ v.visit_path(&node.path);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_range<'ast, V>(v: &mut V, node: &'ast crate::ExprRange)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ if let Some(it) = &node.start {
+ v.visit_expr(&**it);
+ }
+ v.visit_range_limits(&node.limits);
+ if let Some(it) = &node.end {
+ v.visit_expr(&**it);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_raw_addr<'ast, V>(v: &mut V, node: &'ast crate::ExprRawAddr)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ skip!(node.and_token);
+ skip!(node.raw);
+ v.visit_pointer_mutability(&node.mutability);
+ v.visit_expr(&*node.expr);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_expr_reference<'ast, V>(v: &mut V, node: &'ast crate::ExprReference)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ skip!(node.and_token);
+ skip!(node.mutability);
+ v.visit_expr(&*node.expr);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_repeat<'ast, V>(v: &mut V, node: &'ast crate::ExprRepeat)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ skip!(node.bracket_token);
+ v.visit_expr(&*node.expr);
+ skip!(node.semi_token);
+ v.visit_expr(&*node.len);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_return<'ast, V>(v: &mut V, node: &'ast crate::ExprReturn)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ skip!(node.return_token);
+ if let Some(it) = &node.expr {
+ v.visit_expr(&**it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_expr_struct<'ast, V>(v: &mut V, node: &'ast crate::ExprStruct)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ if let Some(it) = &node.qself {
+ v.visit_qself(it);
+ }
+ v.visit_path(&node.path);
+ skip!(node.brace_token);
+ for el in Punctuated::pairs(&node.fields) {
+ let it = el.value();
+ v.visit_field_value(it);
+ }
+ skip!(node.dot2_token);
+ if let Some(it) = &node.rest {
+ v.visit_expr(&**it);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_try<'ast, V>(v: &mut V, node: &'ast crate::ExprTry)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_expr(&*node.expr);
+ skip!(node.question_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_try_block<'ast, V>(v: &mut V, node: &'ast crate::ExprTryBlock)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ skip!(node.try_token);
+ v.visit_block(&node.block);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_expr_tuple<'ast, V>(v: &mut V, node: &'ast crate::ExprTuple)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ skip!(node.paren_token);
+ for el in Punctuated::pairs(&node.elems) {
+ let it = el.value();
+ v.visit_expr(it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_expr_unary<'ast, V>(v: &mut V, node: &'ast crate::ExprUnary)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_un_op(&node.op);
+ v.visit_expr(&*node.expr);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_unsafe<'ast, V>(v: &mut V, node: &'ast crate::ExprUnsafe)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ skip!(node.unsafe_token);
+ v.visit_block(&node.block);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_while<'ast, V>(v: &mut V, node: &'ast crate::ExprWhile)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ if let Some(it) = &node.label {
+ v.visit_label(it);
+ }
+ skip!(node.while_token);
+ v.visit_expr(&*node.cond);
+ v.visit_block(&node.body);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_yield<'ast, V>(v: &mut V, node: &'ast crate::ExprYield)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ skip!(node.yield_token);
+ if let Some(it) = &node.expr {
+ v.visit_expr(&**it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_field<'ast, V>(v: &mut V, node: &'ast crate::Field)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_visibility(&node.vis);
+ v.visit_field_mutability(&node.mutability);
+ if let Some(it) = &node.ident {
+ v.visit_ident(it);
+ }
+ skip!(node.colon_token);
+ v.visit_type(&node.ty);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_field_mutability<'ast, V>(v: &mut V, node: &'ast crate::FieldMutability)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ match node {
+ crate::FieldMutability::None => {}
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_field_pat<'ast, V>(v: &mut V, node: &'ast crate::FieldPat)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_member(&node.member);
+ skip!(node.colon_token);
+ v.visit_pat(&*node.pat);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_field_value<'ast, V>(v: &mut V, node: &'ast crate::FieldValue)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_member(&node.member);
+ skip!(node.colon_token);
+ v.visit_expr(&node.expr);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_fields<'ast, V>(v: &mut V, node: &'ast crate::Fields)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ match node {
+ crate::Fields::Named(_binding_0) => {
+ v.visit_fields_named(_binding_0);
+ }
+ crate::Fields::Unnamed(_binding_0) => {
+ v.visit_fields_unnamed(_binding_0);
+ }
+ crate::Fields::Unit => {}
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_fields_named<'ast, V>(v: &mut V, node: &'ast crate::FieldsNamed)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ skip!(node.brace_token);
+ for el in Punctuated::pairs(&node.named) {
+ let it = el.value();
+ v.visit_field(it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_fields_unnamed<'ast, V>(v: &mut V, node: &'ast crate::FieldsUnnamed)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ skip!(node.paren_token);
+ for el in Punctuated::pairs(&node.unnamed) {
+ let it = el.value();
+ v.visit_field(it);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_file<'ast, V>(v: &mut V, node: &'ast crate::File)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ skip!(node.shebang);
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ for it in &node.items {
+ v.visit_item(it);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_fn_arg<'ast, V>(v: &mut V, node: &'ast crate::FnArg)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ match node {
+ crate::FnArg::Receiver(_binding_0) => {
+ v.visit_receiver(_binding_0);
+ }
+ crate::FnArg::Typed(_binding_0) => {
+ v.visit_pat_type(_binding_0);
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_foreign_item<'ast, V>(v: &mut V, node: &'ast crate::ForeignItem)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ match node {
+ crate::ForeignItem::Fn(_binding_0) => {
+ v.visit_foreign_item_fn(_binding_0);
+ }
+ crate::ForeignItem::Static(_binding_0) => {
+ v.visit_foreign_item_static(_binding_0);
+ }
+ crate::ForeignItem::Type(_binding_0) => {
+ v.visit_foreign_item_type(_binding_0);
+ }
+ crate::ForeignItem::Macro(_binding_0) => {
+ v.visit_foreign_item_macro(_binding_0);
+ }
+ crate::ForeignItem::Verbatim(_binding_0) => {
+ v.visit_token_stream(_binding_0);
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_foreign_item_fn<'ast, V>(v: &mut V, node: &'ast crate::ForeignItemFn)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_visibility(&node.vis);
+ v.visit_signature(&node.sig);
+ skip!(node.semi_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_foreign_item_macro<'ast, V>(v: &mut V, node: &'ast crate::ForeignItemMacro)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_macro(&node.mac);
+ skip!(node.semi_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_foreign_item_static<'ast, V>(
+ v: &mut V,
+ node: &'ast crate::ForeignItemStatic,
+)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_visibility(&node.vis);
+ skip!(node.static_token);
+ v.visit_static_mutability(&node.mutability);
+ v.visit_ident(&node.ident);
+ skip!(node.colon_token);
+ v.visit_type(&*node.ty);
+ skip!(node.semi_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_foreign_item_type<'ast, V>(v: &mut V, node: &'ast crate::ForeignItemType)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_visibility(&node.vis);
+ skip!(node.type_token);
+ v.visit_ident(&node.ident);
+ v.visit_generics(&node.generics);
+ skip!(node.semi_token);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_generic_argument<'ast, V>(v: &mut V, node: &'ast crate::GenericArgument)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ match node {
+ crate::GenericArgument::Lifetime(_binding_0) => {
+ v.visit_lifetime(_binding_0);
+ }
+ crate::GenericArgument::Type(_binding_0) => {
+ v.visit_type(_binding_0);
+ }
+ crate::GenericArgument::Const(_binding_0) => {
+ v.visit_expr(_binding_0);
+ }
+ crate::GenericArgument::AssocType(_binding_0) => {
+ v.visit_assoc_type(_binding_0);
+ }
+ crate::GenericArgument::AssocConst(_binding_0) => {
+ v.visit_assoc_const(_binding_0);
+ }
+ crate::GenericArgument::Constraint(_binding_0) => {
+ v.visit_constraint(_binding_0);
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_generic_param<'ast, V>(v: &mut V, node: &'ast crate::GenericParam)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ match node {
+ crate::GenericParam::Lifetime(_binding_0) => {
+ v.visit_lifetime_param(_binding_0);
+ }
+ crate::GenericParam::Type(_binding_0) => {
+ v.visit_type_param(_binding_0);
+ }
+ crate::GenericParam::Const(_binding_0) => {
+ v.visit_const_param(_binding_0);
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_generics<'ast, V>(v: &mut V, node: &'ast crate::Generics)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ skip!(node.lt_token);
+ for el in Punctuated::pairs(&node.params) {
+ let it = el.value();
+ v.visit_generic_param(it);
+ }
+ skip!(node.gt_token);
+ if let Some(it) = &node.where_clause {
+ v.visit_where_clause(it);
+ }
+}
+pub fn visit_ident<'ast, V>(v: &mut V, node: &'ast proc_macro2::Ident)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ v.visit_span(&node.span());
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_impl_item<'ast, V>(v: &mut V, node: &'ast crate::ImplItem)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ match node {
+ crate::ImplItem::Const(_binding_0) => {
+ v.visit_impl_item_const(_binding_0);
+ }
+ crate::ImplItem::Fn(_binding_0) => {
+ v.visit_impl_item_fn(_binding_0);
+ }
+ crate::ImplItem::Type(_binding_0) => {
+ v.visit_impl_item_type(_binding_0);
+ }
+ crate::ImplItem::Macro(_binding_0) => {
+ v.visit_impl_item_macro(_binding_0);
+ }
+ crate::ImplItem::Verbatim(_binding_0) => {
+ v.visit_token_stream(_binding_0);
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_impl_item_const<'ast, V>(v: &mut V, node: &'ast crate::ImplItemConst)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_visibility(&node.vis);
+ skip!(node.defaultness);
+ skip!(node.const_token);
+ v.visit_ident(&node.ident);
+ v.visit_generics(&node.generics);
+ skip!(node.colon_token);
+ v.visit_type(&node.ty);
+ skip!(node.eq_token);
+ v.visit_expr(&node.expr);
+ skip!(node.semi_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_impl_item_fn<'ast, V>(v: &mut V, node: &'ast crate::ImplItemFn)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_visibility(&node.vis);
+ skip!(node.defaultness);
+ v.visit_signature(&node.sig);
+ v.visit_block(&node.block);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_impl_item_macro<'ast, V>(v: &mut V, node: &'ast crate::ImplItemMacro)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_macro(&node.mac);
+ skip!(node.semi_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_impl_item_type<'ast, V>(v: &mut V, node: &'ast crate::ImplItemType)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_visibility(&node.vis);
+ skip!(node.defaultness);
+ skip!(node.type_token);
+ v.visit_ident(&node.ident);
+ v.visit_generics(&node.generics);
+ skip!(node.eq_token);
+ v.visit_type(&node.ty);
+ skip!(node.semi_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_impl_restriction<'ast, V>(v: &mut V, node: &'ast crate::ImplRestriction)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ match *node {}
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_index<'ast, V>(v: &mut V, node: &'ast crate::Index)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ skip!(node.index);
+ v.visit_span(&node.span);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_item<'ast, V>(v: &mut V, node: &'ast crate::Item)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ match node {
+ crate::Item::Const(_binding_0) => {
+ v.visit_item_const(_binding_0);
+ }
+ crate::Item::Enum(_binding_0) => {
+ v.visit_item_enum(_binding_0);
+ }
+ crate::Item::ExternCrate(_binding_0) => {
+ v.visit_item_extern_crate(_binding_0);
+ }
+ crate::Item::Fn(_binding_0) => {
+ v.visit_item_fn(_binding_0);
+ }
+ crate::Item::ForeignMod(_binding_0) => {
+ v.visit_item_foreign_mod(_binding_0);
+ }
+ crate::Item::Impl(_binding_0) => {
+ v.visit_item_impl(_binding_0);
+ }
+ crate::Item::Macro(_binding_0) => {
+ v.visit_item_macro(_binding_0);
+ }
+ crate::Item::Mod(_binding_0) => {
+ v.visit_item_mod(_binding_0);
+ }
+ crate::Item::Static(_binding_0) => {
+ v.visit_item_static(_binding_0);
+ }
+ crate::Item::Struct(_binding_0) => {
+ v.visit_item_struct(_binding_0);
+ }
+ crate::Item::Trait(_binding_0) => {
+ v.visit_item_trait(_binding_0);
+ }
+ crate::Item::TraitAlias(_binding_0) => {
+ v.visit_item_trait_alias(_binding_0);
+ }
+ crate::Item::Type(_binding_0) => {
+ v.visit_item_type(_binding_0);
+ }
+ crate::Item::Union(_binding_0) => {
+ v.visit_item_union(_binding_0);
+ }
+ crate::Item::Use(_binding_0) => {
+ v.visit_item_use(_binding_0);
+ }
+ crate::Item::Verbatim(_binding_0) => {
+ v.visit_token_stream(_binding_0);
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_item_const<'ast, V>(v: &mut V, node: &'ast crate::ItemConst)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_visibility(&node.vis);
+ skip!(node.const_token);
+ v.visit_ident(&node.ident);
+ v.visit_generics(&node.generics);
+ skip!(node.colon_token);
+ v.visit_type(&*node.ty);
+ skip!(node.eq_token);
+ v.visit_expr(&*node.expr);
+ skip!(node.semi_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_item_enum<'ast, V>(v: &mut V, node: &'ast crate::ItemEnum)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_visibility(&node.vis);
+ skip!(node.enum_token);
+ v.visit_ident(&node.ident);
+ v.visit_generics(&node.generics);
+ skip!(node.brace_token);
+ for el in Punctuated::pairs(&node.variants) {
+ let it = el.value();
+ v.visit_variant(it);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_item_extern_crate<'ast, V>(v: &mut V, node: &'ast crate::ItemExternCrate)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_visibility(&node.vis);
+ skip!(node.extern_token);
+ skip!(node.crate_token);
+ v.visit_ident(&node.ident);
+ if let Some(it) = &node.rename {
+ skip!((it).0);
+ v.visit_ident(&(it).1);
+ }
+ skip!(node.semi_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_item_fn<'ast, V>(v: &mut V, node: &'ast crate::ItemFn)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_visibility(&node.vis);
+ v.visit_signature(&node.sig);
+ v.visit_block(&*node.block);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_item_foreign_mod<'ast, V>(v: &mut V, node: &'ast crate::ItemForeignMod)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ skip!(node.unsafety);
+ v.visit_abi(&node.abi);
+ skip!(node.brace_token);
+ for it in &node.items {
+ v.visit_foreign_item(it);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_item_impl<'ast, V>(v: &mut V, node: &'ast crate::ItemImpl)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ skip!(node.defaultness);
+ skip!(node.unsafety);
+ skip!(node.impl_token);
+ v.visit_generics(&node.generics);
+ if let Some(it) = &node.trait_ {
+ skip!((it).0);
+ v.visit_path(&(it).1);
+ skip!((it).2);
+ }
+ v.visit_type(&*node.self_ty);
+ skip!(node.brace_token);
+ for it in &node.items {
+ v.visit_impl_item(it);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_item_macro<'ast, V>(v: &mut V, node: &'ast crate::ItemMacro)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ if let Some(it) = &node.ident {
+ v.visit_ident(it);
+ }
+ v.visit_macro(&node.mac);
+ skip!(node.semi_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_item_mod<'ast, V>(v: &mut V, node: &'ast crate::ItemMod)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_visibility(&node.vis);
+ skip!(node.unsafety);
+ skip!(node.mod_token);
+ v.visit_ident(&node.ident);
+ if let Some(it) = &node.content {
+ skip!((it).0);
+ for it in &(it).1 {
+ v.visit_item(it);
+ }
+ }
+ skip!(node.semi);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_item_static<'ast, V>(v: &mut V, node: &'ast crate::ItemStatic)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_visibility(&node.vis);
+ skip!(node.static_token);
+ v.visit_static_mutability(&node.mutability);
+ v.visit_ident(&node.ident);
+ skip!(node.colon_token);
+ v.visit_type(&*node.ty);
+ skip!(node.eq_token);
+ v.visit_expr(&*node.expr);
+ skip!(node.semi_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_item_struct<'ast, V>(v: &mut V, node: &'ast crate::ItemStruct)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_visibility(&node.vis);
+ skip!(node.struct_token);
+ v.visit_ident(&node.ident);
+ v.visit_generics(&node.generics);
+ v.visit_fields(&node.fields);
+ skip!(node.semi_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_item_trait<'ast, V>(v: &mut V, node: &'ast crate::ItemTrait)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_visibility(&node.vis);
+ skip!(node.unsafety);
+ skip!(node.auto_token);
+ if let Some(it) = &node.restriction {
+ v.visit_impl_restriction(it);
+ }
+ skip!(node.trait_token);
+ v.visit_ident(&node.ident);
+ v.visit_generics(&node.generics);
+ skip!(node.colon_token);
+ for el in Punctuated::pairs(&node.supertraits) {
+ let it = el.value();
+ v.visit_type_param_bound(it);
+ }
+ skip!(node.brace_token);
+ for it in &node.items {
+ v.visit_trait_item(it);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_item_trait_alias<'ast, V>(v: &mut V, node: &'ast crate::ItemTraitAlias)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_visibility(&node.vis);
+ skip!(node.trait_token);
+ v.visit_ident(&node.ident);
+ v.visit_generics(&node.generics);
+ skip!(node.eq_token);
+ for el in Punctuated::pairs(&node.bounds) {
+ let it = el.value();
+ v.visit_type_param_bound(it);
+ }
+ skip!(node.semi_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_item_type<'ast, V>(v: &mut V, node: &'ast crate::ItemType)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_visibility(&node.vis);
+ skip!(node.type_token);
+ v.visit_ident(&node.ident);
+ v.visit_generics(&node.generics);
+ skip!(node.eq_token);
+ v.visit_type(&*node.ty);
+ skip!(node.semi_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_item_union<'ast, V>(v: &mut V, node: &'ast crate::ItemUnion)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_visibility(&node.vis);
+ skip!(node.union_token);
+ v.visit_ident(&node.ident);
+ v.visit_generics(&node.generics);
+ v.visit_fields_named(&node.fields);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_item_use<'ast, V>(v: &mut V, node: &'ast crate::ItemUse)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_visibility(&node.vis);
+ skip!(node.use_token);
+ skip!(node.leading_colon);
+ v.visit_use_tree(&node.tree);
+ skip!(node.semi_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_label<'ast, V>(v: &mut V, node: &'ast crate::Label)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ v.visit_lifetime(&node.name);
+ skip!(node.colon_token);
+}
+pub fn visit_lifetime<'ast, V>(v: &mut V, node: &'ast crate::Lifetime)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ v.visit_span(&node.apostrophe);
+ v.visit_ident(&node.ident);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_lifetime_param<'ast, V>(v: &mut V, node: &'ast crate::LifetimeParam)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_lifetime(&node.lifetime);
+ skip!(node.colon_token);
+ for el in Punctuated::pairs(&node.bounds) {
+ let it = el.value();
+ v.visit_lifetime(it);
+ }
+}
+pub fn visit_lit<'ast, V>(v: &mut V, node: &'ast crate::Lit)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ match node {
+ crate::Lit::Str(_binding_0) => {
+ v.visit_lit_str(_binding_0);
+ }
+ crate::Lit::ByteStr(_binding_0) => {
+ v.visit_lit_byte_str(_binding_0);
+ }
+ crate::Lit::CStr(_binding_0) => {
+ v.visit_lit_cstr(_binding_0);
+ }
+ crate::Lit::Byte(_binding_0) => {
+ v.visit_lit_byte(_binding_0);
+ }
+ crate::Lit::Char(_binding_0) => {
+ v.visit_lit_char(_binding_0);
+ }
+ crate::Lit::Int(_binding_0) => {
+ v.visit_lit_int(_binding_0);
+ }
+ crate::Lit::Float(_binding_0) => {
+ v.visit_lit_float(_binding_0);
+ }
+ crate::Lit::Bool(_binding_0) => {
+ v.visit_lit_bool(_binding_0);
+ }
+ crate::Lit::Verbatim(_binding_0) => {
+ skip!(_binding_0);
+ }
+ }
+}
+pub fn visit_lit_bool<'ast, V>(v: &mut V, node: &'ast crate::LitBool)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ skip!(node.value);
+ v.visit_span(&node.span);
+}
+pub fn visit_lit_byte<'ast, V>(v: &mut V, node: &'ast crate::LitByte)
+where
+ V: Visit<'ast> + ?Sized,
+{}
+pub fn visit_lit_byte_str<'ast, V>(v: &mut V, node: &'ast crate::LitByteStr)
+where
+ V: Visit<'ast> + ?Sized,
+{}
+pub fn visit_lit_cstr<'ast, V>(v: &mut V, node: &'ast crate::LitCStr)
+where
+ V: Visit<'ast> + ?Sized,
+{}
+pub fn visit_lit_char<'ast, V>(v: &mut V, node: &'ast crate::LitChar)
+where
+ V: Visit<'ast> + ?Sized,
+{}
+pub fn visit_lit_float<'ast, V>(v: &mut V, node: &'ast crate::LitFloat)
+where
+ V: Visit<'ast> + ?Sized,
+{}
+pub fn visit_lit_int<'ast, V>(v: &mut V, node: &'ast crate::LitInt)
+where
+ V: Visit<'ast> + ?Sized,
+{}
+pub fn visit_lit_str<'ast, V>(v: &mut V, node: &'ast crate::LitStr)
+where
+ V: Visit<'ast> + ?Sized,
+{}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_local<'ast, V>(v: &mut V, node: &'ast crate::Local)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ skip!(node.let_token);
+ v.visit_pat(&node.pat);
+ if let Some(it) = &node.init {
+ v.visit_local_init(it);
+ }
+ skip!(node.semi_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_local_init<'ast, V>(v: &mut V, node: &'ast crate::LocalInit)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ skip!(node.eq_token);
+ v.visit_expr(&*node.expr);
+ if let Some(it) = &node.diverge {
+ skip!((it).0);
+ v.visit_expr(&*(it).1);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_macro<'ast, V>(v: &mut V, node: &'ast crate::Macro)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ v.visit_path(&node.path);
+ skip!(node.bang_token);
+ v.visit_macro_delimiter(&node.delimiter);
+ v.visit_token_stream(&node.tokens);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_macro_delimiter<'ast, V>(v: &mut V, node: &'ast crate::MacroDelimiter)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ match node {
+ crate::MacroDelimiter::Paren(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::MacroDelimiter::Brace(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::MacroDelimiter::Bracket(_binding_0) => {
+ skip!(_binding_0);
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_member<'ast, V>(v: &mut V, node: &'ast crate::Member)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ match node {
+ crate::Member::Named(_binding_0) => {
+ v.visit_ident(_binding_0);
+ }
+ crate::Member::Unnamed(_binding_0) => {
+ v.visit_index(_binding_0);
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_meta<'ast, V>(v: &mut V, node: &'ast crate::Meta)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ match node {
+ crate::Meta::Path(_binding_0) => {
+ v.visit_path(_binding_0);
+ }
+ crate::Meta::List(_binding_0) => {
+ v.visit_meta_list(_binding_0);
+ }
+ crate::Meta::NameValue(_binding_0) => {
+ v.visit_meta_name_value(_binding_0);
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_meta_list<'ast, V>(v: &mut V, node: &'ast crate::MetaList)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ v.visit_path(&node.path);
+ v.visit_macro_delimiter(&node.delimiter);
+ v.visit_token_stream(&node.tokens);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_meta_name_value<'ast, V>(v: &mut V, node: &'ast crate::MetaNameValue)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ v.visit_path(&node.path);
+ skip!(node.eq_token);
+ v.visit_expr(&node.value);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_parenthesized_generic_arguments<'ast, V>(
+ v: &mut V,
+ node: &'ast crate::ParenthesizedGenericArguments,
+)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ skip!(node.paren_token);
+ for el in Punctuated::pairs(&node.inputs) {
+ let it = el.value();
+ v.visit_type(it);
+ }
+ v.visit_return_type(&node.output);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_pat<'ast, V>(v: &mut V, node: &'ast crate::Pat)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ match node {
+ crate::Pat::Const(_binding_0) => {
+ v.visit_expr_const(_binding_0);
+ }
+ crate::Pat::Ident(_binding_0) => {
+ v.visit_pat_ident(_binding_0);
+ }
+ crate::Pat::Lit(_binding_0) => {
+ v.visit_expr_lit(_binding_0);
+ }
+ crate::Pat::Macro(_binding_0) => {
+ v.visit_expr_macro(_binding_0);
+ }
+ crate::Pat::Or(_binding_0) => {
+ v.visit_pat_or(_binding_0);
+ }
+ crate::Pat::Paren(_binding_0) => {
+ v.visit_pat_paren(_binding_0);
+ }
+ crate::Pat::Path(_binding_0) => {
+ v.visit_expr_path(_binding_0);
+ }
+ crate::Pat::Range(_binding_0) => {
+ v.visit_expr_range(_binding_0);
+ }
+ crate::Pat::Reference(_binding_0) => {
+ v.visit_pat_reference(_binding_0);
+ }
+ crate::Pat::Rest(_binding_0) => {
+ v.visit_pat_rest(_binding_0);
+ }
+ crate::Pat::Slice(_binding_0) => {
+ v.visit_pat_slice(_binding_0);
+ }
+ crate::Pat::Struct(_binding_0) => {
+ v.visit_pat_struct(_binding_0);
+ }
+ crate::Pat::Tuple(_binding_0) => {
+ v.visit_pat_tuple(_binding_0);
+ }
+ crate::Pat::TupleStruct(_binding_0) => {
+ v.visit_pat_tuple_struct(_binding_0);
+ }
+ crate::Pat::Type(_binding_0) => {
+ v.visit_pat_type(_binding_0);
+ }
+ crate::Pat::Verbatim(_binding_0) => {
+ v.visit_token_stream(_binding_0);
+ }
+ crate::Pat::Wild(_binding_0) => {
+ v.visit_pat_wild(_binding_0);
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_pat_ident<'ast, V>(v: &mut V, node: &'ast crate::PatIdent)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ skip!(node.by_ref);
+ skip!(node.mutability);
+ v.visit_ident(&node.ident);
+ if let Some(it) = &node.subpat {
+ skip!((it).0);
+ v.visit_pat(&*(it).1);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_pat_or<'ast, V>(v: &mut V, node: &'ast crate::PatOr)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ skip!(node.leading_vert);
+ for el in Punctuated::pairs(&node.cases) {
+ let it = el.value();
+ v.visit_pat(it);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_pat_paren<'ast, V>(v: &mut V, node: &'ast crate::PatParen)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ skip!(node.paren_token);
+ v.visit_pat(&*node.pat);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_pat_reference<'ast, V>(v: &mut V, node: &'ast crate::PatReference)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ skip!(node.and_token);
+ skip!(node.mutability);
+ v.visit_pat(&*node.pat);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_pat_rest<'ast, V>(v: &mut V, node: &'ast crate::PatRest)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ skip!(node.dot2_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_pat_slice<'ast, V>(v: &mut V, node: &'ast crate::PatSlice)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ skip!(node.bracket_token);
+ for el in Punctuated::pairs(&node.elems) {
+ let it = el.value();
+ v.visit_pat(it);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_pat_struct<'ast, V>(v: &mut V, node: &'ast crate::PatStruct)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ if let Some(it) = &node.qself {
+ v.visit_qself(it);
+ }
+ v.visit_path(&node.path);
+ skip!(node.brace_token);
+ for el in Punctuated::pairs(&node.fields) {
+ let it = el.value();
+ v.visit_field_pat(it);
+ }
+ if let Some(it) = &node.rest {
+ v.visit_pat_rest(it);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_pat_tuple<'ast, V>(v: &mut V, node: &'ast crate::PatTuple)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ skip!(node.paren_token);
+ for el in Punctuated::pairs(&node.elems) {
+ let it = el.value();
+ v.visit_pat(it);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_pat_tuple_struct<'ast, V>(v: &mut V, node: &'ast crate::PatTupleStruct)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ if let Some(it) = &node.qself {
+ v.visit_qself(it);
+ }
+ v.visit_path(&node.path);
+ skip!(node.paren_token);
+ for el in Punctuated::pairs(&node.elems) {
+ let it = el.value();
+ v.visit_pat(it);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_pat_type<'ast, V>(v: &mut V, node: &'ast crate::PatType)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_pat(&*node.pat);
+ skip!(node.colon_token);
+ v.visit_type(&*node.ty);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_pat_wild<'ast, V>(v: &mut V, node: &'ast crate::PatWild)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ skip!(node.underscore_token);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_path<'ast, V>(v: &mut V, node: &'ast crate::Path)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ skip!(node.leading_colon);
+ for el in Punctuated::pairs(&node.segments) {
+ let it = el.value();
+ v.visit_path_segment(it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_path_arguments<'ast, V>(v: &mut V, node: &'ast crate::PathArguments)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ match node {
+ crate::PathArguments::None => {}
+ crate::PathArguments::AngleBracketed(_binding_0) => {
+ v.visit_angle_bracketed_generic_arguments(_binding_0);
+ }
+ crate::PathArguments::Parenthesized(_binding_0) => {
+ v.visit_parenthesized_generic_arguments(_binding_0);
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_path_segment<'ast, V>(v: &mut V, node: &'ast crate::PathSegment)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ v.visit_ident(&node.ident);
+ v.visit_path_arguments(&node.arguments);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_pointer_mutability<'ast, V>(v: &mut V, node: &'ast crate::PointerMutability)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ match node {
+ crate::PointerMutability::Const(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::PointerMutability::Mut(_binding_0) => {
+ skip!(_binding_0);
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_precise_capture<'ast, V>(v: &mut V, node: &'ast crate::PreciseCapture)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ skip!(node.use_token);
+ skip!(node.lt_token);
+ for el in Punctuated::pairs(&node.params) {
+ let it = el.value();
+ v.visit_captured_param(it);
+ }
+ skip!(node.gt_token);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_predicate_lifetime<'ast, V>(v: &mut V, node: &'ast crate::PredicateLifetime)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ v.visit_lifetime(&node.lifetime);
+ skip!(node.colon_token);
+ for el in Punctuated::pairs(&node.bounds) {
+ let it = el.value();
+ v.visit_lifetime(it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_predicate_type<'ast, V>(v: &mut V, node: &'ast crate::PredicateType)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ if let Some(it) = &node.lifetimes {
+ v.visit_bound_lifetimes(it);
+ }
+ v.visit_type(&node.bounded_ty);
+ skip!(node.colon_token);
+ for el in Punctuated::pairs(&node.bounds) {
+ let it = el.value();
+ v.visit_type_param_bound(it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_qself<'ast, V>(v: &mut V, node: &'ast crate::QSelf)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ skip!(node.lt_token);
+ v.visit_type(&*node.ty);
+ skip!(node.position);
+ skip!(node.as_token);
+ skip!(node.gt_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_range_limits<'ast, V>(v: &mut V, node: &'ast crate::RangeLimits)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ match node {
+ crate::RangeLimits::HalfOpen(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::RangeLimits::Closed(_binding_0) => {
+ skip!(_binding_0);
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_receiver<'ast, V>(v: &mut V, node: &'ast crate::Receiver)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ if let Some(it) = &node.reference {
+ skip!((it).0);
+ if let Some(it) = &(it).1 {
+ v.visit_lifetime(it);
+ }
+ }
+ skip!(node.mutability);
+ skip!(node.self_token);
+ skip!(node.colon_token);
+ v.visit_type(&*node.ty);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_return_type<'ast, V>(v: &mut V, node: &'ast crate::ReturnType)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ match node {
+ crate::ReturnType::Default => {}
+ crate::ReturnType::Type(_binding_0, _binding_1) => {
+ skip!(_binding_0);
+ v.visit_type(&**_binding_1);
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_signature<'ast, V>(v: &mut V, node: &'ast crate::Signature)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ skip!(node.constness);
+ skip!(node.asyncness);
+ skip!(node.unsafety);
+ if let Some(it) = &node.abi {
+ v.visit_abi(it);
+ }
+ skip!(node.fn_token);
+ v.visit_ident(&node.ident);
+ v.visit_generics(&node.generics);
+ skip!(node.paren_token);
+ for el in Punctuated::pairs(&node.inputs) {
+ let it = el.value();
+ v.visit_fn_arg(it);
+ }
+ if let Some(it) = &node.variadic {
+ v.visit_variadic(it);
+ }
+ v.visit_return_type(&node.output);
+}
+pub fn visit_span<'ast, V>(v: &mut V, node: &proc_macro2::Span)
+where
+ V: Visit<'ast> + ?Sized,
+{}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_static_mutability<'ast, V>(v: &mut V, node: &'ast crate::StaticMutability)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ match node {
+ crate::StaticMutability::Mut(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::StaticMutability::None => {}
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_stmt<'ast, V>(v: &mut V, node: &'ast crate::Stmt)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ match node {
+ crate::Stmt::Local(_binding_0) => {
+ v.visit_local(_binding_0);
+ }
+ crate::Stmt::Item(_binding_0) => {
+ v.visit_item(_binding_0);
+ }
+ crate::Stmt::Expr(_binding_0, _binding_1) => {
+ v.visit_expr(_binding_0);
+ skip!(_binding_1);
+ }
+ crate::Stmt::Macro(_binding_0) => {
+ v.visit_stmt_macro(_binding_0);
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_stmt_macro<'ast, V>(v: &mut V, node: &'ast crate::StmtMacro)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_macro(&node.mac);
+ skip!(node.semi_token);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_trait_bound<'ast, V>(v: &mut V, node: &'ast crate::TraitBound)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ skip!(node.paren_token);
+ v.visit_trait_bound_modifier(&node.modifier);
+ if let Some(it) = &node.lifetimes {
+ v.visit_bound_lifetimes(it);
+ }
+ v.visit_path(&node.path);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_trait_bound_modifier<'ast, V>(
+ v: &mut V,
+ node: &'ast crate::TraitBoundModifier,
+)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ match node {
+ crate::TraitBoundModifier::None => {}
+ crate::TraitBoundModifier::Maybe(_binding_0) => {
+ skip!(_binding_0);
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_trait_item<'ast, V>(v: &mut V, node: &'ast crate::TraitItem)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ match node {
+ crate::TraitItem::Const(_binding_0) => {
+ v.visit_trait_item_const(_binding_0);
+ }
+ crate::TraitItem::Fn(_binding_0) => {
+ v.visit_trait_item_fn(_binding_0);
+ }
+ crate::TraitItem::Type(_binding_0) => {
+ v.visit_trait_item_type(_binding_0);
+ }
+ crate::TraitItem::Macro(_binding_0) => {
+ v.visit_trait_item_macro(_binding_0);
+ }
+ crate::TraitItem::Verbatim(_binding_0) => {
+ v.visit_token_stream(_binding_0);
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_trait_item_const<'ast, V>(v: &mut V, node: &'ast crate::TraitItemConst)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ skip!(node.const_token);
+ v.visit_ident(&node.ident);
+ v.visit_generics(&node.generics);
+ skip!(node.colon_token);
+ v.visit_type(&node.ty);
+ if let Some(it) = &node.default {
+ skip!((it).0);
+ v.visit_expr(&(it).1);
+ }
+ skip!(node.semi_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_trait_item_fn<'ast, V>(v: &mut V, node: &'ast crate::TraitItemFn)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_signature(&node.sig);
+ if let Some(it) = &node.default {
+ v.visit_block(it);
+ }
+ skip!(node.semi_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_trait_item_macro<'ast, V>(v: &mut V, node: &'ast crate::TraitItemMacro)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_macro(&node.mac);
+ skip!(node.semi_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_trait_item_type<'ast, V>(v: &mut V, node: &'ast crate::TraitItemType)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ skip!(node.type_token);
+ v.visit_ident(&node.ident);
+ v.visit_generics(&node.generics);
+ skip!(node.colon_token);
+ for el in Punctuated::pairs(&node.bounds) {
+ let it = el.value();
+ v.visit_type_param_bound(it);
+ }
+ if let Some(it) = &node.default {
+ skip!((it).0);
+ v.visit_type(&(it).1);
+ }
+ skip!(node.semi_token);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_type<'ast, V>(v: &mut V, node: &'ast crate::Type)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ match node {
+ crate::Type::Array(_binding_0) => {
+ v.visit_type_array(_binding_0);
+ }
+ crate::Type::BareFn(_binding_0) => {
+ v.visit_type_bare_fn(_binding_0);
+ }
+ crate::Type::Group(_binding_0) => {
+ v.visit_type_group(_binding_0);
+ }
+ crate::Type::ImplTrait(_binding_0) => {
+ v.visit_type_impl_trait(_binding_0);
+ }
+ crate::Type::Infer(_binding_0) => {
+ v.visit_type_infer(_binding_0);
+ }
+ crate::Type::Macro(_binding_0) => {
+ v.visit_type_macro(_binding_0);
+ }
+ crate::Type::Never(_binding_0) => {
+ v.visit_type_never(_binding_0);
+ }
+ crate::Type::Paren(_binding_0) => {
+ v.visit_type_paren(_binding_0);
+ }
+ crate::Type::Path(_binding_0) => {
+ v.visit_type_path(_binding_0);
+ }
+ crate::Type::Ptr(_binding_0) => {
+ v.visit_type_ptr(_binding_0);
+ }
+ crate::Type::Reference(_binding_0) => {
+ v.visit_type_reference(_binding_0);
+ }
+ crate::Type::Slice(_binding_0) => {
+ v.visit_type_slice(_binding_0);
+ }
+ crate::Type::TraitObject(_binding_0) => {
+ v.visit_type_trait_object(_binding_0);
+ }
+ crate::Type::Tuple(_binding_0) => {
+ v.visit_type_tuple(_binding_0);
+ }
+ crate::Type::Verbatim(_binding_0) => {
+ v.visit_token_stream(_binding_0);
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_type_array<'ast, V>(v: &mut V, node: &'ast crate::TypeArray)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ skip!(node.bracket_token);
+ v.visit_type(&*node.elem);
+ skip!(node.semi_token);
+ v.visit_expr(&node.len);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_type_bare_fn<'ast, V>(v: &mut V, node: &'ast crate::TypeBareFn)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ if let Some(it) = &node.lifetimes {
+ v.visit_bound_lifetimes(it);
+ }
+ skip!(node.unsafety);
+ if let Some(it) = &node.abi {
+ v.visit_abi(it);
+ }
+ skip!(node.fn_token);
+ skip!(node.paren_token);
+ for el in Punctuated::pairs(&node.inputs) {
+ let it = el.value();
+ v.visit_bare_fn_arg(it);
+ }
+ if let Some(it) = &node.variadic {
+ v.visit_bare_variadic(it);
+ }
+ v.visit_return_type(&node.output);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_type_group<'ast, V>(v: &mut V, node: &'ast crate::TypeGroup)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ skip!(node.group_token);
+ v.visit_type(&*node.elem);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_type_impl_trait<'ast, V>(v: &mut V, node: &'ast crate::TypeImplTrait)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ skip!(node.impl_token);
+ for el in Punctuated::pairs(&node.bounds) {
+ let it = el.value();
+ v.visit_type_param_bound(it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_type_infer<'ast, V>(v: &mut V, node: &'ast crate::TypeInfer)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ skip!(node.underscore_token);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_type_macro<'ast, V>(v: &mut V, node: &'ast crate::TypeMacro)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ v.visit_macro(&node.mac);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_type_never<'ast, V>(v: &mut V, node: &'ast crate::TypeNever)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ skip!(node.bang_token);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_type_param<'ast, V>(v: &mut V, node: &'ast crate::TypeParam)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_ident(&node.ident);
+ skip!(node.colon_token);
+ for el in Punctuated::pairs(&node.bounds) {
+ let it = el.value();
+ v.visit_type_param_bound(it);
+ }
+ skip!(node.eq_token);
+ if let Some(it) = &node.default {
+ v.visit_type(it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_type_param_bound<'ast, V>(v: &mut V, node: &'ast crate::TypeParamBound)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ match node {
+ crate::TypeParamBound::Trait(_binding_0) => {
+ v.visit_trait_bound(_binding_0);
+ }
+ crate::TypeParamBound::Lifetime(_binding_0) => {
+ v.visit_lifetime(_binding_0);
+ }
+ crate::TypeParamBound::PreciseCapture(_binding_0) => {
+ full!(v.visit_precise_capture(_binding_0));
+ }
+ crate::TypeParamBound::Verbatim(_binding_0) => {
+ v.visit_token_stream(_binding_0);
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_type_paren<'ast, V>(v: &mut V, node: &'ast crate::TypeParen)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ skip!(node.paren_token);
+ v.visit_type(&*node.elem);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_type_path<'ast, V>(v: &mut V, node: &'ast crate::TypePath)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ if let Some(it) = &node.qself {
+ v.visit_qself(it);
+ }
+ v.visit_path(&node.path);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_type_ptr<'ast, V>(v: &mut V, node: &'ast crate::TypePtr)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ skip!(node.star_token);
+ skip!(node.const_token);
+ skip!(node.mutability);
+ v.visit_type(&*node.elem);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_type_reference<'ast, V>(v: &mut V, node: &'ast crate::TypeReference)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ skip!(node.and_token);
+ if let Some(it) = &node.lifetime {
+ v.visit_lifetime(it);
+ }
+ skip!(node.mutability);
+ v.visit_type(&*node.elem);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_type_slice<'ast, V>(v: &mut V, node: &'ast crate::TypeSlice)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ skip!(node.bracket_token);
+ v.visit_type(&*node.elem);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_type_trait_object<'ast, V>(v: &mut V, node: &'ast crate::TypeTraitObject)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ skip!(node.dyn_token);
+ for el in Punctuated::pairs(&node.bounds) {
+ let it = el.value();
+ v.visit_type_param_bound(it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_type_tuple<'ast, V>(v: &mut V, node: &'ast crate::TypeTuple)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ skip!(node.paren_token);
+ for el in Punctuated::pairs(&node.elems) {
+ let it = el.value();
+ v.visit_type(it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_un_op<'ast, V>(v: &mut V, node: &'ast crate::UnOp)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ match node {
+ crate::UnOp::Deref(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::UnOp::Not(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::UnOp::Neg(_binding_0) => {
+ skip!(_binding_0);
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_use_glob<'ast, V>(v: &mut V, node: &'ast crate::UseGlob)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ skip!(node.star_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_use_group<'ast, V>(v: &mut V, node: &'ast crate::UseGroup)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ skip!(node.brace_token);
+ for el in Punctuated::pairs(&node.items) {
+ let it = el.value();
+ v.visit_use_tree(it);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_use_name<'ast, V>(v: &mut V, node: &'ast crate::UseName)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ v.visit_ident(&node.ident);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_use_path<'ast, V>(v: &mut V, node: &'ast crate::UsePath)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ v.visit_ident(&node.ident);
+ skip!(node.colon2_token);
+ v.visit_use_tree(&*node.tree);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_use_rename<'ast, V>(v: &mut V, node: &'ast crate::UseRename)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ v.visit_ident(&node.ident);
+ skip!(node.as_token);
+ v.visit_ident(&node.rename);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_use_tree<'ast, V>(v: &mut V, node: &'ast crate::UseTree)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ match node {
+ crate::UseTree::Path(_binding_0) => {
+ v.visit_use_path(_binding_0);
+ }
+ crate::UseTree::Name(_binding_0) => {
+ v.visit_use_name(_binding_0);
+ }
+ crate::UseTree::Rename(_binding_0) => {
+ v.visit_use_rename(_binding_0);
+ }
+ crate::UseTree::Glob(_binding_0) => {
+ v.visit_use_glob(_binding_0);
+ }
+ crate::UseTree::Group(_binding_0) => {
+ v.visit_use_group(_binding_0);
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_variadic<'ast, V>(v: &mut V, node: &'ast crate::Variadic)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ if let Some(it) = &node.pat {
+ v.visit_pat(&*(it).0);
+ skip!((it).1);
+ }
+ skip!(node.dots);
+ skip!(node.comma);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_variant<'ast, V>(v: &mut V, node: &'ast crate::Variant)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ for it in &node.attrs {
+ v.visit_attribute(it);
+ }
+ v.visit_ident(&node.ident);
+ v.visit_fields(&node.fields);
+ if let Some(it) = &node.discriminant {
+ skip!((it).0);
+ v.visit_expr(&(it).1);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_vis_restricted<'ast, V>(v: &mut V, node: &'ast crate::VisRestricted)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ skip!(node.pub_token);
+ skip!(node.paren_token);
+ skip!(node.in_token);
+ v.visit_path(&*node.path);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_visibility<'ast, V>(v: &mut V, node: &'ast crate::Visibility)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ match node {
+ crate::Visibility::Public(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::Visibility::Restricted(_binding_0) => {
+ v.visit_vis_restricted(_binding_0);
+ }
+ crate::Visibility::Inherited => {}
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_where_clause<'ast, V>(v: &mut V, node: &'ast crate::WhereClause)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ skip!(node.where_token);
+ for el in Punctuated::pairs(&node.predicates) {
+ let it = el.value();
+ v.visit_where_predicate(it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_where_predicate<'ast, V>(v: &mut V, node: &'ast crate::WherePredicate)
+where
+ V: Visit<'ast> + ?Sized,
+{
+ match node {
+ crate::WherePredicate::Lifetime(_binding_0) => {
+ v.visit_predicate_lifetime(_binding_0);
+ }
+ crate::WherePredicate::Type(_binding_0) => {
+ v.visit_predicate_type(_binding_0);
+ }
+ }
+}
diff --git a/rust/syn/gen/visit_mut.rs b/rust/syn/gen/visit_mut.rs
new file mode 100644
index 000000000000..2bbd6895db75
--- /dev/null
+++ b/rust/syn/gen/visit_mut.rs
@@ -0,0 +1,3759 @@
+// This file is @generated by syn-internal-codegen.
+// It is not intended for manual editing.
+
+#![allow(unused_variables)]
+#![allow(clippy::needless_pass_by_ref_mut)]
+#[cfg(any(feature = "full", feature = "derive"))]
+use crate::punctuated::Punctuated;
+#[cfg(feature = "full")]
+macro_rules! full {
+ ($e:expr) => {
+ $e
+ };
+}
+#[cfg(all(feature = "derive", not(feature = "full")))]
+macro_rules! full {
+ ($e:expr) => {
+ unreachable!()
+ };
+}
+macro_rules! skip {
+ ($($tt:tt)*) => {};
+}
+/// Syntax tree traversal to mutate an exclusive borrow of a syntax tree in
+/// place.
+///
+/// See the [module documentation] for details.
+///
+/// [module documentation]: self
+pub trait VisitMut {
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_abi_mut(&mut self, i: &mut crate::Abi) {
+ visit_abi_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_angle_bracketed_generic_arguments_mut(
+ &mut self,
+ i: &mut crate::AngleBracketedGenericArguments,
+ ) {
+ visit_angle_bracketed_generic_arguments_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_arm_mut(&mut self, i: &mut crate::Arm) {
+ visit_arm_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_assoc_const_mut(&mut self, i: &mut crate::AssocConst) {
+ visit_assoc_const_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_assoc_type_mut(&mut self, i: &mut crate::AssocType) {
+ visit_assoc_type_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_attr_style_mut(&mut self, i: &mut crate::AttrStyle) {
+ visit_attr_style_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_attribute_mut(&mut self, i: &mut crate::Attribute) {
+ visit_attribute_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_attributes_mut(&mut self, i: &mut Vec<crate::Attribute>) {
+ for attr in i {
+ self.visit_attribute_mut(attr);
+ }
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_bare_fn_arg_mut(&mut self, i: &mut crate::BareFnArg) {
+ visit_bare_fn_arg_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_bare_variadic_mut(&mut self, i: &mut crate::BareVariadic) {
+ visit_bare_variadic_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_bin_op_mut(&mut self, i: &mut crate::BinOp) {
+ visit_bin_op_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_block_mut(&mut self, i: &mut crate::Block) {
+ visit_block_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_bound_lifetimes_mut(&mut self, i: &mut crate::BoundLifetimes) {
+ visit_bound_lifetimes_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_captured_param_mut(&mut self, i: &mut crate::CapturedParam) {
+ visit_captured_param_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_const_param_mut(&mut self, i: &mut crate::ConstParam) {
+ visit_const_param_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_constraint_mut(&mut self, i: &mut crate::Constraint) {
+ visit_constraint_mut(self, i);
+ }
+ #[cfg(feature = "derive")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
+ fn visit_data_mut(&mut self, i: &mut crate::Data) {
+ visit_data_mut(self, i);
+ }
+ #[cfg(feature = "derive")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
+ fn visit_data_enum_mut(&mut self, i: &mut crate::DataEnum) {
+ visit_data_enum_mut(self, i);
+ }
+ #[cfg(feature = "derive")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
+ fn visit_data_struct_mut(&mut self, i: &mut crate::DataStruct) {
+ visit_data_struct_mut(self, i);
+ }
+ #[cfg(feature = "derive")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
+ fn visit_data_union_mut(&mut self, i: &mut crate::DataUnion) {
+ visit_data_union_mut(self, i);
+ }
+ #[cfg(feature = "derive")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
+ fn visit_derive_input_mut(&mut self, i: &mut crate::DeriveInput) {
+ visit_derive_input_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_expr_mut(&mut self, i: &mut crate::Expr) {
+ visit_expr_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_array_mut(&mut self, i: &mut crate::ExprArray) {
+ visit_expr_array_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_assign_mut(&mut self, i: &mut crate::ExprAssign) {
+ visit_expr_assign_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_async_mut(&mut self, i: &mut crate::ExprAsync) {
+ visit_expr_async_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_await_mut(&mut self, i: &mut crate::ExprAwait) {
+ visit_expr_await_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_expr_binary_mut(&mut self, i: &mut crate::ExprBinary) {
+ visit_expr_binary_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_block_mut(&mut self, i: &mut crate::ExprBlock) {
+ visit_expr_block_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_break_mut(&mut self, i: &mut crate::ExprBreak) {
+ visit_expr_break_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_expr_call_mut(&mut self, i: &mut crate::ExprCall) {
+ visit_expr_call_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_expr_cast_mut(&mut self, i: &mut crate::ExprCast) {
+ visit_expr_cast_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_closure_mut(&mut self, i: &mut crate::ExprClosure) {
+ visit_expr_closure_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_const_mut(&mut self, i: &mut crate::ExprConst) {
+ visit_expr_const_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_continue_mut(&mut self, i: &mut crate::ExprContinue) {
+ visit_expr_continue_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_expr_field_mut(&mut self, i: &mut crate::ExprField) {
+ visit_expr_field_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_for_loop_mut(&mut self, i: &mut crate::ExprForLoop) {
+ visit_expr_for_loop_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_expr_group_mut(&mut self, i: &mut crate::ExprGroup) {
+ visit_expr_group_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_if_mut(&mut self, i: &mut crate::ExprIf) {
+ visit_expr_if_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_expr_index_mut(&mut self, i: &mut crate::ExprIndex) {
+ visit_expr_index_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_infer_mut(&mut self, i: &mut crate::ExprInfer) {
+ visit_expr_infer_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_let_mut(&mut self, i: &mut crate::ExprLet) {
+ visit_expr_let_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_expr_lit_mut(&mut self, i: &mut crate::ExprLit) {
+ visit_expr_lit_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_loop_mut(&mut self, i: &mut crate::ExprLoop) {
+ visit_expr_loop_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_expr_macro_mut(&mut self, i: &mut crate::ExprMacro) {
+ visit_expr_macro_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_match_mut(&mut self, i: &mut crate::ExprMatch) {
+ visit_expr_match_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_expr_method_call_mut(&mut self, i: &mut crate::ExprMethodCall) {
+ visit_expr_method_call_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_expr_paren_mut(&mut self, i: &mut crate::ExprParen) {
+ visit_expr_paren_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_expr_path_mut(&mut self, i: &mut crate::ExprPath) {
+ visit_expr_path_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_range_mut(&mut self, i: &mut crate::ExprRange) {
+ visit_expr_range_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_raw_addr_mut(&mut self, i: &mut crate::ExprRawAddr) {
+ visit_expr_raw_addr_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_expr_reference_mut(&mut self, i: &mut crate::ExprReference) {
+ visit_expr_reference_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_repeat_mut(&mut self, i: &mut crate::ExprRepeat) {
+ visit_expr_repeat_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_return_mut(&mut self, i: &mut crate::ExprReturn) {
+ visit_expr_return_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_expr_struct_mut(&mut self, i: &mut crate::ExprStruct) {
+ visit_expr_struct_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_try_mut(&mut self, i: &mut crate::ExprTry) {
+ visit_expr_try_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_try_block_mut(&mut self, i: &mut crate::ExprTryBlock) {
+ visit_expr_try_block_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_expr_tuple_mut(&mut self, i: &mut crate::ExprTuple) {
+ visit_expr_tuple_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_expr_unary_mut(&mut self, i: &mut crate::ExprUnary) {
+ visit_expr_unary_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_unsafe_mut(&mut self, i: &mut crate::ExprUnsafe) {
+ visit_expr_unsafe_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_while_mut(&mut self, i: &mut crate::ExprWhile) {
+ visit_expr_while_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_expr_yield_mut(&mut self, i: &mut crate::ExprYield) {
+ visit_expr_yield_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_field_mut(&mut self, i: &mut crate::Field) {
+ visit_field_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_field_mutability_mut(&mut self, i: &mut crate::FieldMutability) {
+ visit_field_mutability_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_field_pat_mut(&mut self, i: &mut crate::FieldPat) {
+ visit_field_pat_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_field_value_mut(&mut self, i: &mut crate::FieldValue) {
+ visit_field_value_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_fields_mut(&mut self, i: &mut crate::Fields) {
+ visit_fields_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_fields_named_mut(&mut self, i: &mut crate::FieldsNamed) {
+ visit_fields_named_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_fields_unnamed_mut(&mut self, i: &mut crate::FieldsUnnamed) {
+ visit_fields_unnamed_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_file_mut(&mut self, i: &mut crate::File) {
+ visit_file_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_fn_arg_mut(&mut self, i: &mut crate::FnArg) {
+ visit_fn_arg_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_foreign_item_mut(&mut self, i: &mut crate::ForeignItem) {
+ visit_foreign_item_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_foreign_item_fn_mut(&mut self, i: &mut crate::ForeignItemFn) {
+ visit_foreign_item_fn_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_foreign_item_macro_mut(&mut self, i: &mut crate::ForeignItemMacro) {
+ visit_foreign_item_macro_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_foreign_item_static_mut(&mut self, i: &mut crate::ForeignItemStatic) {
+ visit_foreign_item_static_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_foreign_item_type_mut(&mut self, i: &mut crate::ForeignItemType) {
+ visit_foreign_item_type_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_generic_argument_mut(&mut self, i: &mut crate::GenericArgument) {
+ visit_generic_argument_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_generic_param_mut(&mut self, i: &mut crate::GenericParam) {
+ visit_generic_param_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_generics_mut(&mut self, i: &mut crate::Generics) {
+ visit_generics_mut(self, i);
+ }
+ fn visit_ident_mut(&mut self, i: &mut proc_macro2::Ident) {
+ visit_ident_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_impl_item_mut(&mut self, i: &mut crate::ImplItem) {
+ visit_impl_item_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_impl_item_const_mut(&mut self, i: &mut crate::ImplItemConst) {
+ visit_impl_item_const_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_impl_item_fn_mut(&mut self, i: &mut crate::ImplItemFn) {
+ visit_impl_item_fn_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_impl_item_macro_mut(&mut self, i: &mut crate::ImplItemMacro) {
+ visit_impl_item_macro_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_impl_item_type_mut(&mut self, i: &mut crate::ImplItemType) {
+ visit_impl_item_type_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_impl_restriction_mut(&mut self, i: &mut crate::ImplRestriction) {
+ visit_impl_restriction_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_index_mut(&mut self, i: &mut crate::Index) {
+ visit_index_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_item_mut(&mut self, i: &mut crate::Item) {
+ visit_item_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_item_const_mut(&mut self, i: &mut crate::ItemConst) {
+ visit_item_const_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_item_enum_mut(&mut self, i: &mut crate::ItemEnum) {
+ visit_item_enum_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_item_extern_crate_mut(&mut self, i: &mut crate::ItemExternCrate) {
+ visit_item_extern_crate_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_item_fn_mut(&mut self, i: &mut crate::ItemFn) {
+ visit_item_fn_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_item_foreign_mod_mut(&mut self, i: &mut crate::ItemForeignMod) {
+ visit_item_foreign_mod_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_item_impl_mut(&mut self, i: &mut crate::ItemImpl) {
+ visit_item_impl_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_item_macro_mut(&mut self, i: &mut crate::ItemMacro) {
+ visit_item_macro_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_item_mod_mut(&mut self, i: &mut crate::ItemMod) {
+ visit_item_mod_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_item_static_mut(&mut self, i: &mut crate::ItemStatic) {
+ visit_item_static_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_item_struct_mut(&mut self, i: &mut crate::ItemStruct) {
+ visit_item_struct_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_item_trait_mut(&mut self, i: &mut crate::ItemTrait) {
+ visit_item_trait_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_item_trait_alias_mut(&mut self, i: &mut crate::ItemTraitAlias) {
+ visit_item_trait_alias_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_item_type_mut(&mut self, i: &mut crate::ItemType) {
+ visit_item_type_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_item_union_mut(&mut self, i: &mut crate::ItemUnion) {
+ visit_item_union_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_item_use_mut(&mut self, i: &mut crate::ItemUse) {
+ visit_item_use_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_label_mut(&mut self, i: &mut crate::Label) {
+ visit_label_mut(self, i);
+ }
+ fn visit_lifetime_mut(&mut self, i: &mut crate::Lifetime) {
+ visit_lifetime_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_lifetime_param_mut(&mut self, i: &mut crate::LifetimeParam) {
+ visit_lifetime_param_mut(self, i);
+ }
+ fn visit_lit_mut(&mut self, i: &mut crate::Lit) {
+ visit_lit_mut(self, i);
+ }
+ fn visit_lit_bool_mut(&mut self, i: &mut crate::LitBool) {
+ visit_lit_bool_mut(self, i);
+ }
+ fn visit_lit_byte_mut(&mut self, i: &mut crate::LitByte) {
+ visit_lit_byte_mut(self, i);
+ }
+ fn visit_lit_byte_str_mut(&mut self, i: &mut crate::LitByteStr) {
+ visit_lit_byte_str_mut(self, i);
+ }
+ fn visit_lit_cstr_mut(&mut self, i: &mut crate::LitCStr) {
+ visit_lit_cstr_mut(self, i);
+ }
+ fn visit_lit_char_mut(&mut self, i: &mut crate::LitChar) {
+ visit_lit_char_mut(self, i);
+ }
+ fn visit_lit_float_mut(&mut self, i: &mut crate::LitFloat) {
+ visit_lit_float_mut(self, i);
+ }
+ fn visit_lit_int_mut(&mut self, i: &mut crate::LitInt) {
+ visit_lit_int_mut(self, i);
+ }
+ fn visit_lit_str_mut(&mut self, i: &mut crate::LitStr) {
+ visit_lit_str_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_local_mut(&mut self, i: &mut crate::Local) {
+ visit_local_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_local_init_mut(&mut self, i: &mut crate::LocalInit) {
+ visit_local_init_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_macro_mut(&mut self, i: &mut crate::Macro) {
+ visit_macro_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_macro_delimiter_mut(&mut self, i: &mut crate::MacroDelimiter) {
+ visit_macro_delimiter_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_member_mut(&mut self, i: &mut crate::Member) {
+ visit_member_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_meta_mut(&mut self, i: &mut crate::Meta) {
+ visit_meta_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_meta_list_mut(&mut self, i: &mut crate::MetaList) {
+ visit_meta_list_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_meta_name_value_mut(&mut self, i: &mut crate::MetaNameValue) {
+ visit_meta_name_value_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_parenthesized_generic_arguments_mut(
+ &mut self,
+ i: &mut crate::ParenthesizedGenericArguments,
+ ) {
+ visit_parenthesized_generic_arguments_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_pat_mut(&mut self, i: &mut crate::Pat) {
+ visit_pat_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_pat_ident_mut(&mut self, i: &mut crate::PatIdent) {
+ visit_pat_ident_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_pat_or_mut(&mut self, i: &mut crate::PatOr) {
+ visit_pat_or_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_pat_paren_mut(&mut self, i: &mut crate::PatParen) {
+ visit_pat_paren_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_pat_reference_mut(&mut self, i: &mut crate::PatReference) {
+ visit_pat_reference_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_pat_rest_mut(&mut self, i: &mut crate::PatRest) {
+ visit_pat_rest_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_pat_slice_mut(&mut self, i: &mut crate::PatSlice) {
+ visit_pat_slice_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_pat_struct_mut(&mut self, i: &mut crate::PatStruct) {
+ visit_pat_struct_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_pat_tuple_mut(&mut self, i: &mut crate::PatTuple) {
+ visit_pat_tuple_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_pat_tuple_struct_mut(&mut self, i: &mut crate::PatTupleStruct) {
+ visit_pat_tuple_struct_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_pat_type_mut(&mut self, i: &mut crate::PatType) {
+ visit_pat_type_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_pat_wild_mut(&mut self, i: &mut crate::PatWild) {
+ visit_pat_wild_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_path_mut(&mut self, i: &mut crate::Path) {
+ visit_path_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_path_arguments_mut(&mut self, i: &mut crate::PathArguments) {
+ visit_path_arguments_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_path_segment_mut(&mut self, i: &mut crate::PathSegment) {
+ visit_path_segment_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_pointer_mutability_mut(&mut self, i: &mut crate::PointerMutability) {
+ visit_pointer_mutability_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_precise_capture_mut(&mut self, i: &mut crate::PreciseCapture) {
+ visit_precise_capture_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_predicate_lifetime_mut(&mut self, i: &mut crate::PredicateLifetime) {
+ visit_predicate_lifetime_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_predicate_type_mut(&mut self, i: &mut crate::PredicateType) {
+ visit_predicate_type_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_qself_mut(&mut self, i: &mut crate::QSelf) {
+ visit_qself_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_range_limits_mut(&mut self, i: &mut crate::RangeLimits) {
+ visit_range_limits_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_receiver_mut(&mut self, i: &mut crate::Receiver) {
+ visit_receiver_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_return_type_mut(&mut self, i: &mut crate::ReturnType) {
+ visit_return_type_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_signature_mut(&mut self, i: &mut crate::Signature) {
+ visit_signature_mut(self, i);
+ }
+ fn visit_span_mut(&mut self, i: &mut proc_macro2::Span) {}
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_static_mutability_mut(&mut self, i: &mut crate::StaticMutability) {
+ visit_static_mutability_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_stmt_mut(&mut self, i: &mut crate::Stmt) {
+ visit_stmt_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_stmt_macro_mut(&mut self, i: &mut crate::StmtMacro) {
+ visit_stmt_macro_mut(self, i);
+ }
+ fn visit_token_stream_mut(&mut self, i: &mut proc_macro2::TokenStream) {}
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_trait_bound_mut(&mut self, i: &mut crate::TraitBound) {
+ visit_trait_bound_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_trait_bound_modifier_mut(&mut self, i: &mut crate::TraitBoundModifier) {
+ visit_trait_bound_modifier_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_trait_item_mut(&mut self, i: &mut crate::TraitItem) {
+ visit_trait_item_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_trait_item_const_mut(&mut self, i: &mut crate::TraitItemConst) {
+ visit_trait_item_const_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_trait_item_fn_mut(&mut self, i: &mut crate::TraitItemFn) {
+ visit_trait_item_fn_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_trait_item_macro_mut(&mut self, i: &mut crate::TraitItemMacro) {
+ visit_trait_item_macro_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_trait_item_type_mut(&mut self, i: &mut crate::TraitItemType) {
+ visit_trait_item_type_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_type_mut(&mut self, i: &mut crate::Type) {
+ visit_type_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_type_array_mut(&mut self, i: &mut crate::TypeArray) {
+ visit_type_array_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_type_bare_fn_mut(&mut self, i: &mut crate::TypeBareFn) {
+ visit_type_bare_fn_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_type_group_mut(&mut self, i: &mut crate::TypeGroup) {
+ visit_type_group_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_type_impl_trait_mut(&mut self, i: &mut crate::TypeImplTrait) {
+ visit_type_impl_trait_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_type_infer_mut(&mut self, i: &mut crate::TypeInfer) {
+ visit_type_infer_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_type_macro_mut(&mut self, i: &mut crate::TypeMacro) {
+ visit_type_macro_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_type_never_mut(&mut self, i: &mut crate::TypeNever) {
+ visit_type_never_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_type_param_mut(&mut self, i: &mut crate::TypeParam) {
+ visit_type_param_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_type_param_bound_mut(&mut self, i: &mut crate::TypeParamBound) {
+ visit_type_param_bound_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_type_paren_mut(&mut self, i: &mut crate::TypeParen) {
+ visit_type_paren_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_type_path_mut(&mut self, i: &mut crate::TypePath) {
+ visit_type_path_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_type_ptr_mut(&mut self, i: &mut crate::TypePtr) {
+ visit_type_ptr_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_type_reference_mut(&mut self, i: &mut crate::TypeReference) {
+ visit_type_reference_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_type_slice_mut(&mut self, i: &mut crate::TypeSlice) {
+ visit_type_slice_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_type_trait_object_mut(&mut self, i: &mut crate::TypeTraitObject) {
+ visit_type_trait_object_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_type_tuple_mut(&mut self, i: &mut crate::TypeTuple) {
+ visit_type_tuple_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_un_op_mut(&mut self, i: &mut crate::UnOp) {
+ visit_un_op_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_use_glob_mut(&mut self, i: &mut crate::UseGlob) {
+ visit_use_glob_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_use_group_mut(&mut self, i: &mut crate::UseGroup) {
+ visit_use_group_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_use_name_mut(&mut self, i: &mut crate::UseName) {
+ visit_use_name_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_use_path_mut(&mut self, i: &mut crate::UsePath) {
+ visit_use_path_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_use_rename_mut(&mut self, i: &mut crate::UseRename) {
+ visit_use_rename_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_use_tree_mut(&mut self, i: &mut crate::UseTree) {
+ visit_use_tree_mut(self, i);
+ }
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ fn visit_variadic_mut(&mut self, i: &mut crate::Variadic) {
+ visit_variadic_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_variant_mut(&mut self, i: &mut crate::Variant) {
+ visit_variant_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_vis_restricted_mut(&mut self, i: &mut crate::VisRestricted) {
+ visit_vis_restricted_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_visibility_mut(&mut self, i: &mut crate::Visibility) {
+ visit_visibility_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_where_clause_mut(&mut self, i: &mut crate::WhereClause) {
+ visit_where_clause_mut(self, i);
+ }
+ #[cfg(any(feature = "derive", feature = "full"))]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+ fn visit_where_predicate_mut(&mut self, i: &mut crate::WherePredicate) {
+ visit_where_predicate_mut(self, i);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_abi_mut<V>(v: &mut V, node: &mut crate::Abi)
+where
+ V: VisitMut + ?Sized,
+{
+ skip!(node.extern_token);
+ if let Some(it) = &mut node.name {
+ v.visit_lit_str_mut(it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_angle_bracketed_generic_arguments_mut<V>(
+ v: &mut V,
+ node: &mut crate::AngleBracketedGenericArguments,
+)
+where
+ V: VisitMut + ?Sized,
+{
+ skip!(node.colon2_token);
+ skip!(node.lt_token);
+ for mut el in Punctuated::pairs_mut(&mut node.args) {
+ let it = el.value_mut();
+ v.visit_generic_argument_mut(it);
+ }
+ skip!(node.gt_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_arm_mut<V>(v: &mut V, node: &mut crate::Arm)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_pat_mut(&mut node.pat);
+ if let Some(it) = &mut node.guard {
+ skip!((it).0);
+ v.visit_expr_mut(&mut *(it).1);
+ }
+ skip!(node.fat_arrow_token);
+ v.visit_expr_mut(&mut *node.body);
+ skip!(node.comma);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_assoc_const_mut<V>(v: &mut V, node: &mut crate::AssocConst)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_ident_mut(&mut node.ident);
+ if let Some(it) = &mut node.generics {
+ v.visit_angle_bracketed_generic_arguments_mut(it);
+ }
+ skip!(node.eq_token);
+ v.visit_expr_mut(&mut node.value);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_assoc_type_mut<V>(v: &mut V, node: &mut crate::AssocType)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_ident_mut(&mut node.ident);
+ if let Some(it) = &mut node.generics {
+ v.visit_angle_bracketed_generic_arguments_mut(it);
+ }
+ skip!(node.eq_token);
+ v.visit_type_mut(&mut node.ty);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_attr_style_mut<V>(v: &mut V, node: &mut crate::AttrStyle)
+where
+ V: VisitMut + ?Sized,
+{
+ match node {
+ crate::AttrStyle::Outer => {}
+ crate::AttrStyle::Inner(_binding_0) => {
+ skip!(_binding_0);
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_attribute_mut<V>(v: &mut V, node: &mut crate::Attribute)
+where
+ V: VisitMut + ?Sized,
+{
+ skip!(node.pound_token);
+ v.visit_attr_style_mut(&mut node.style);
+ skip!(node.bracket_token);
+ v.visit_meta_mut(&mut node.meta);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_bare_fn_arg_mut<V>(v: &mut V, node: &mut crate::BareFnArg)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ if let Some(it) = &mut node.name {
+ v.visit_ident_mut(&mut (it).0);
+ skip!((it).1);
+ }
+ v.visit_type_mut(&mut node.ty);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_bare_variadic_mut<V>(v: &mut V, node: &mut crate::BareVariadic)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ if let Some(it) = &mut node.name {
+ v.visit_ident_mut(&mut (it).0);
+ skip!((it).1);
+ }
+ skip!(node.dots);
+ skip!(node.comma);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_bin_op_mut<V>(v: &mut V, node: &mut crate::BinOp)
+where
+ V: VisitMut + ?Sized,
+{
+ match node {
+ crate::BinOp::Add(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::Sub(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::Mul(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::Div(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::Rem(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::And(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::Or(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::BitXor(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::BitAnd(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::BitOr(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::Shl(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::Shr(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::Eq(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::Lt(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::Le(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::Ne(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::Ge(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::Gt(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::AddAssign(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::SubAssign(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::MulAssign(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::DivAssign(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::RemAssign(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::BitXorAssign(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::BitAndAssign(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::BitOrAssign(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::ShlAssign(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::BinOp::ShrAssign(_binding_0) => {
+ skip!(_binding_0);
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_block_mut<V>(v: &mut V, node: &mut crate::Block)
+where
+ V: VisitMut + ?Sized,
+{
+ skip!(node.brace_token);
+ for it in &mut node.stmts {
+ v.visit_stmt_mut(it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_bound_lifetimes_mut<V>(v: &mut V, node: &mut crate::BoundLifetimes)
+where
+ V: VisitMut + ?Sized,
+{
+ skip!(node.for_token);
+ skip!(node.lt_token);
+ for mut el in Punctuated::pairs_mut(&mut node.lifetimes) {
+ let it = el.value_mut();
+ v.visit_generic_param_mut(it);
+ }
+ skip!(node.gt_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_captured_param_mut<V>(v: &mut V, node: &mut crate::CapturedParam)
+where
+ V: VisitMut + ?Sized,
+{
+ match node {
+ crate::CapturedParam::Lifetime(_binding_0) => {
+ v.visit_lifetime_mut(_binding_0);
+ }
+ crate::CapturedParam::Ident(_binding_0) => {
+ v.visit_ident_mut(_binding_0);
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_const_param_mut<V>(v: &mut V, node: &mut crate::ConstParam)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ skip!(node.const_token);
+ v.visit_ident_mut(&mut node.ident);
+ skip!(node.colon_token);
+ v.visit_type_mut(&mut node.ty);
+ skip!(node.eq_token);
+ if let Some(it) = &mut node.default {
+ v.visit_expr_mut(it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_constraint_mut<V>(v: &mut V, node: &mut crate::Constraint)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_ident_mut(&mut node.ident);
+ if let Some(it) = &mut node.generics {
+ v.visit_angle_bracketed_generic_arguments_mut(it);
+ }
+ skip!(node.colon_token);
+ for mut el in Punctuated::pairs_mut(&mut node.bounds) {
+ let it = el.value_mut();
+ v.visit_type_param_bound_mut(it);
+ }
+}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
+pub fn visit_data_mut<V>(v: &mut V, node: &mut crate::Data)
+where
+ V: VisitMut + ?Sized,
+{
+ match node {
+ crate::Data::Struct(_binding_0) => {
+ v.visit_data_struct_mut(_binding_0);
+ }
+ crate::Data::Enum(_binding_0) => {
+ v.visit_data_enum_mut(_binding_0);
+ }
+ crate::Data::Union(_binding_0) => {
+ v.visit_data_union_mut(_binding_0);
+ }
+ }
+}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
+pub fn visit_data_enum_mut<V>(v: &mut V, node: &mut crate::DataEnum)
+where
+ V: VisitMut + ?Sized,
+{
+ skip!(node.enum_token);
+ skip!(node.brace_token);
+ for mut el in Punctuated::pairs_mut(&mut node.variants) {
+ let it = el.value_mut();
+ v.visit_variant_mut(it);
+ }
+}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
+pub fn visit_data_struct_mut<V>(v: &mut V, node: &mut crate::DataStruct)
+where
+ V: VisitMut + ?Sized,
+{
+ skip!(node.struct_token);
+ v.visit_fields_mut(&mut node.fields);
+ skip!(node.semi_token);
+}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
+pub fn visit_data_union_mut<V>(v: &mut V, node: &mut crate::DataUnion)
+where
+ V: VisitMut + ?Sized,
+{
+ skip!(node.union_token);
+ v.visit_fields_named_mut(&mut node.fields);
+}
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
+pub fn visit_derive_input_mut<V>(v: &mut V, node: &mut crate::DeriveInput)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_visibility_mut(&mut node.vis);
+ v.visit_ident_mut(&mut node.ident);
+ v.visit_generics_mut(&mut node.generics);
+ v.visit_data_mut(&mut node.data);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_expr_mut<V>(v: &mut V, node: &mut crate::Expr)
+where
+ V: VisitMut + ?Sized,
+{
+ match node {
+ crate::Expr::Array(_binding_0) => {
+ full!(v.visit_expr_array_mut(_binding_0));
+ }
+ crate::Expr::Assign(_binding_0) => {
+ full!(v.visit_expr_assign_mut(_binding_0));
+ }
+ crate::Expr::Async(_binding_0) => {
+ full!(v.visit_expr_async_mut(_binding_0));
+ }
+ crate::Expr::Await(_binding_0) => {
+ full!(v.visit_expr_await_mut(_binding_0));
+ }
+ crate::Expr::Binary(_binding_0) => {
+ v.visit_expr_binary_mut(_binding_0);
+ }
+ crate::Expr::Block(_binding_0) => {
+ full!(v.visit_expr_block_mut(_binding_0));
+ }
+ crate::Expr::Break(_binding_0) => {
+ full!(v.visit_expr_break_mut(_binding_0));
+ }
+ crate::Expr::Call(_binding_0) => {
+ v.visit_expr_call_mut(_binding_0);
+ }
+ crate::Expr::Cast(_binding_0) => {
+ v.visit_expr_cast_mut(_binding_0);
+ }
+ crate::Expr::Closure(_binding_0) => {
+ full!(v.visit_expr_closure_mut(_binding_0));
+ }
+ crate::Expr::Const(_binding_0) => {
+ full!(v.visit_expr_const_mut(_binding_0));
+ }
+ crate::Expr::Continue(_binding_0) => {
+ full!(v.visit_expr_continue_mut(_binding_0));
+ }
+ crate::Expr::Field(_binding_0) => {
+ v.visit_expr_field_mut(_binding_0);
+ }
+ crate::Expr::ForLoop(_binding_0) => {
+ full!(v.visit_expr_for_loop_mut(_binding_0));
+ }
+ crate::Expr::Group(_binding_0) => {
+ v.visit_expr_group_mut(_binding_0);
+ }
+ crate::Expr::If(_binding_0) => {
+ full!(v.visit_expr_if_mut(_binding_0));
+ }
+ crate::Expr::Index(_binding_0) => {
+ v.visit_expr_index_mut(_binding_0);
+ }
+ crate::Expr::Infer(_binding_0) => {
+ full!(v.visit_expr_infer_mut(_binding_0));
+ }
+ crate::Expr::Let(_binding_0) => {
+ full!(v.visit_expr_let_mut(_binding_0));
+ }
+ crate::Expr::Lit(_binding_0) => {
+ v.visit_expr_lit_mut(_binding_0);
+ }
+ crate::Expr::Loop(_binding_0) => {
+ full!(v.visit_expr_loop_mut(_binding_0));
+ }
+ crate::Expr::Macro(_binding_0) => {
+ v.visit_expr_macro_mut(_binding_0);
+ }
+ crate::Expr::Match(_binding_0) => {
+ full!(v.visit_expr_match_mut(_binding_0));
+ }
+ crate::Expr::MethodCall(_binding_0) => {
+ v.visit_expr_method_call_mut(_binding_0);
+ }
+ crate::Expr::Paren(_binding_0) => {
+ v.visit_expr_paren_mut(_binding_0);
+ }
+ crate::Expr::Path(_binding_0) => {
+ v.visit_expr_path_mut(_binding_0);
+ }
+ crate::Expr::Range(_binding_0) => {
+ full!(v.visit_expr_range_mut(_binding_0));
+ }
+ crate::Expr::RawAddr(_binding_0) => {
+ full!(v.visit_expr_raw_addr_mut(_binding_0));
+ }
+ crate::Expr::Reference(_binding_0) => {
+ v.visit_expr_reference_mut(_binding_0);
+ }
+ crate::Expr::Repeat(_binding_0) => {
+ full!(v.visit_expr_repeat_mut(_binding_0));
+ }
+ crate::Expr::Return(_binding_0) => {
+ full!(v.visit_expr_return_mut(_binding_0));
+ }
+ crate::Expr::Struct(_binding_0) => {
+ v.visit_expr_struct_mut(_binding_0);
+ }
+ crate::Expr::Try(_binding_0) => {
+ full!(v.visit_expr_try_mut(_binding_0));
+ }
+ crate::Expr::TryBlock(_binding_0) => {
+ full!(v.visit_expr_try_block_mut(_binding_0));
+ }
+ crate::Expr::Tuple(_binding_0) => {
+ v.visit_expr_tuple_mut(_binding_0);
+ }
+ crate::Expr::Unary(_binding_0) => {
+ v.visit_expr_unary_mut(_binding_0);
+ }
+ crate::Expr::Unsafe(_binding_0) => {
+ full!(v.visit_expr_unsafe_mut(_binding_0));
+ }
+ crate::Expr::Verbatim(_binding_0) => {
+ v.visit_token_stream_mut(_binding_0);
+ }
+ crate::Expr::While(_binding_0) => {
+ full!(v.visit_expr_while_mut(_binding_0));
+ }
+ crate::Expr::Yield(_binding_0) => {
+ full!(v.visit_expr_yield_mut(_binding_0));
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_array_mut<V>(v: &mut V, node: &mut crate::ExprArray)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ skip!(node.bracket_token);
+ for mut el in Punctuated::pairs_mut(&mut node.elems) {
+ let it = el.value_mut();
+ v.visit_expr_mut(it);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_assign_mut<V>(v: &mut V, node: &mut crate::ExprAssign)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_expr_mut(&mut *node.left);
+ skip!(node.eq_token);
+ v.visit_expr_mut(&mut *node.right);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_async_mut<V>(v: &mut V, node: &mut crate::ExprAsync)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ skip!(node.async_token);
+ skip!(node.capture);
+ v.visit_block_mut(&mut node.block);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_await_mut<V>(v: &mut V, node: &mut crate::ExprAwait)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_expr_mut(&mut *node.base);
+ skip!(node.dot_token);
+ skip!(node.await_token);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_expr_binary_mut<V>(v: &mut V, node: &mut crate::ExprBinary)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_expr_mut(&mut *node.left);
+ v.visit_bin_op_mut(&mut node.op);
+ v.visit_expr_mut(&mut *node.right);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_block_mut<V>(v: &mut V, node: &mut crate::ExprBlock)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ if let Some(it) = &mut node.label {
+ v.visit_label_mut(it);
+ }
+ v.visit_block_mut(&mut node.block);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_break_mut<V>(v: &mut V, node: &mut crate::ExprBreak)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ skip!(node.break_token);
+ if let Some(it) = &mut node.label {
+ v.visit_lifetime_mut(it);
+ }
+ if let Some(it) = &mut node.expr {
+ v.visit_expr_mut(&mut **it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_expr_call_mut<V>(v: &mut V, node: &mut crate::ExprCall)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_expr_mut(&mut *node.func);
+ skip!(node.paren_token);
+ for mut el in Punctuated::pairs_mut(&mut node.args) {
+ let it = el.value_mut();
+ v.visit_expr_mut(it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_expr_cast_mut<V>(v: &mut V, node: &mut crate::ExprCast)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_expr_mut(&mut *node.expr);
+ skip!(node.as_token);
+ v.visit_type_mut(&mut *node.ty);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_closure_mut<V>(v: &mut V, node: &mut crate::ExprClosure)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ if let Some(it) = &mut node.lifetimes {
+ v.visit_bound_lifetimes_mut(it);
+ }
+ skip!(node.constness);
+ skip!(node.movability);
+ skip!(node.asyncness);
+ skip!(node.capture);
+ skip!(node.or1_token);
+ for mut el in Punctuated::pairs_mut(&mut node.inputs) {
+ let it = el.value_mut();
+ v.visit_pat_mut(it);
+ }
+ skip!(node.or2_token);
+ v.visit_return_type_mut(&mut node.output);
+ v.visit_expr_mut(&mut *node.body);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_const_mut<V>(v: &mut V, node: &mut crate::ExprConst)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ skip!(node.const_token);
+ v.visit_block_mut(&mut node.block);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_continue_mut<V>(v: &mut V, node: &mut crate::ExprContinue)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ skip!(node.continue_token);
+ if let Some(it) = &mut node.label {
+ v.visit_lifetime_mut(it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_expr_field_mut<V>(v: &mut V, node: &mut crate::ExprField)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_expr_mut(&mut *node.base);
+ skip!(node.dot_token);
+ v.visit_member_mut(&mut node.member);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_for_loop_mut<V>(v: &mut V, node: &mut crate::ExprForLoop)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ if let Some(it) = &mut node.label {
+ v.visit_label_mut(it);
+ }
+ skip!(node.for_token);
+ v.visit_pat_mut(&mut *node.pat);
+ skip!(node.in_token);
+ v.visit_expr_mut(&mut *node.expr);
+ v.visit_block_mut(&mut node.body);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_expr_group_mut<V>(v: &mut V, node: &mut crate::ExprGroup)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ skip!(node.group_token);
+ v.visit_expr_mut(&mut *node.expr);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_if_mut<V>(v: &mut V, node: &mut crate::ExprIf)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ skip!(node.if_token);
+ v.visit_expr_mut(&mut *node.cond);
+ v.visit_block_mut(&mut node.then_branch);
+ if let Some(it) = &mut node.else_branch {
+ skip!((it).0);
+ v.visit_expr_mut(&mut *(it).1);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_expr_index_mut<V>(v: &mut V, node: &mut crate::ExprIndex)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_expr_mut(&mut *node.expr);
+ skip!(node.bracket_token);
+ v.visit_expr_mut(&mut *node.index);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_infer_mut<V>(v: &mut V, node: &mut crate::ExprInfer)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ skip!(node.underscore_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_let_mut<V>(v: &mut V, node: &mut crate::ExprLet)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ skip!(node.let_token);
+ v.visit_pat_mut(&mut *node.pat);
+ skip!(node.eq_token);
+ v.visit_expr_mut(&mut *node.expr);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_expr_lit_mut<V>(v: &mut V, node: &mut crate::ExprLit)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_lit_mut(&mut node.lit);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_loop_mut<V>(v: &mut V, node: &mut crate::ExprLoop)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ if let Some(it) = &mut node.label {
+ v.visit_label_mut(it);
+ }
+ skip!(node.loop_token);
+ v.visit_block_mut(&mut node.body);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_expr_macro_mut<V>(v: &mut V, node: &mut crate::ExprMacro)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_macro_mut(&mut node.mac);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_match_mut<V>(v: &mut V, node: &mut crate::ExprMatch)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ skip!(node.match_token);
+ v.visit_expr_mut(&mut *node.expr);
+ skip!(node.brace_token);
+ for it in &mut node.arms {
+ v.visit_arm_mut(it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_expr_method_call_mut<V>(v: &mut V, node: &mut crate::ExprMethodCall)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_expr_mut(&mut *node.receiver);
+ skip!(node.dot_token);
+ v.visit_ident_mut(&mut node.method);
+ if let Some(it) = &mut node.turbofish {
+ v.visit_angle_bracketed_generic_arguments_mut(it);
+ }
+ skip!(node.paren_token);
+ for mut el in Punctuated::pairs_mut(&mut node.args) {
+ let it = el.value_mut();
+ v.visit_expr_mut(it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_expr_paren_mut<V>(v: &mut V, node: &mut crate::ExprParen)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ skip!(node.paren_token);
+ v.visit_expr_mut(&mut *node.expr);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_expr_path_mut<V>(v: &mut V, node: &mut crate::ExprPath)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ if let Some(it) = &mut node.qself {
+ v.visit_qself_mut(it);
+ }
+ v.visit_path_mut(&mut node.path);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_range_mut<V>(v: &mut V, node: &mut crate::ExprRange)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ if let Some(it) = &mut node.start {
+ v.visit_expr_mut(&mut **it);
+ }
+ v.visit_range_limits_mut(&mut node.limits);
+ if let Some(it) = &mut node.end {
+ v.visit_expr_mut(&mut **it);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_raw_addr_mut<V>(v: &mut V, node: &mut crate::ExprRawAddr)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ skip!(node.and_token);
+ skip!(node.raw);
+ v.visit_pointer_mutability_mut(&mut node.mutability);
+ v.visit_expr_mut(&mut *node.expr);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_expr_reference_mut<V>(v: &mut V, node: &mut crate::ExprReference)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ skip!(node.and_token);
+ skip!(node.mutability);
+ v.visit_expr_mut(&mut *node.expr);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_repeat_mut<V>(v: &mut V, node: &mut crate::ExprRepeat)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ skip!(node.bracket_token);
+ v.visit_expr_mut(&mut *node.expr);
+ skip!(node.semi_token);
+ v.visit_expr_mut(&mut *node.len);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_return_mut<V>(v: &mut V, node: &mut crate::ExprReturn)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ skip!(node.return_token);
+ if let Some(it) = &mut node.expr {
+ v.visit_expr_mut(&mut **it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_expr_struct_mut<V>(v: &mut V, node: &mut crate::ExprStruct)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ if let Some(it) = &mut node.qself {
+ v.visit_qself_mut(it);
+ }
+ v.visit_path_mut(&mut node.path);
+ skip!(node.brace_token);
+ for mut el in Punctuated::pairs_mut(&mut node.fields) {
+ let it = el.value_mut();
+ v.visit_field_value_mut(it);
+ }
+ skip!(node.dot2_token);
+ if let Some(it) = &mut node.rest {
+ v.visit_expr_mut(&mut **it);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_try_mut<V>(v: &mut V, node: &mut crate::ExprTry)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_expr_mut(&mut *node.expr);
+ skip!(node.question_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_try_block_mut<V>(v: &mut V, node: &mut crate::ExprTryBlock)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ skip!(node.try_token);
+ v.visit_block_mut(&mut node.block);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_expr_tuple_mut<V>(v: &mut V, node: &mut crate::ExprTuple)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ skip!(node.paren_token);
+ for mut el in Punctuated::pairs_mut(&mut node.elems) {
+ let it = el.value_mut();
+ v.visit_expr_mut(it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_expr_unary_mut<V>(v: &mut V, node: &mut crate::ExprUnary)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_un_op_mut(&mut node.op);
+ v.visit_expr_mut(&mut *node.expr);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_unsafe_mut<V>(v: &mut V, node: &mut crate::ExprUnsafe)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ skip!(node.unsafe_token);
+ v.visit_block_mut(&mut node.block);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_while_mut<V>(v: &mut V, node: &mut crate::ExprWhile)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ if let Some(it) = &mut node.label {
+ v.visit_label_mut(it);
+ }
+ skip!(node.while_token);
+ v.visit_expr_mut(&mut *node.cond);
+ v.visit_block_mut(&mut node.body);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_expr_yield_mut<V>(v: &mut V, node: &mut crate::ExprYield)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ skip!(node.yield_token);
+ if let Some(it) = &mut node.expr {
+ v.visit_expr_mut(&mut **it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_field_mut<V>(v: &mut V, node: &mut crate::Field)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_visibility_mut(&mut node.vis);
+ v.visit_field_mutability_mut(&mut node.mutability);
+ if let Some(it) = &mut node.ident {
+ v.visit_ident_mut(it);
+ }
+ skip!(node.colon_token);
+ v.visit_type_mut(&mut node.ty);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_field_mutability_mut<V>(v: &mut V, node: &mut crate::FieldMutability)
+where
+ V: VisitMut + ?Sized,
+{
+ match node {
+ crate::FieldMutability::None => {}
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_field_pat_mut<V>(v: &mut V, node: &mut crate::FieldPat)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_member_mut(&mut node.member);
+ skip!(node.colon_token);
+ v.visit_pat_mut(&mut *node.pat);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_field_value_mut<V>(v: &mut V, node: &mut crate::FieldValue)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_member_mut(&mut node.member);
+ skip!(node.colon_token);
+ v.visit_expr_mut(&mut node.expr);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_fields_mut<V>(v: &mut V, node: &mut crate::Fields)
+where
+ V: VisitMut + ?Sized,
+{
+ match node {
+ crate::Fields::Named(_binding_0) => {
+ v.visit_fields_named_mut(_binding_0);
+ }
+ crate::Fields::Unnamed(_binding_0) => {
+ v.visit_fields_unnamed_mut(_binding_0);
+ }
+ crate::Fields::Unit => {}
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_fields_named_mut<V>(v: &mut V, node: &mut crate::FieldsNamed)
+where
+ V: VisitMut + ?Sized,
+{
+ skip!(node.brace_token);
+ for mut el in Punctuated::pairs_mut(&mut node.named) {
+ let it = el.value_mut();
+ v.visit_field_mut(it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_fields_unnamed_mut<V>(v: &mut V, node: &mut crate::FieldsUnnamed)
+where
+ V: VisitMut + ?Sized,
+{
+ skip!(node.paren_token);
+ for mut el in Punctuated::pairs_mut(&mut node.unnamed) {
+ let it = el.value_mut();
+ v.visit_field_mut(it);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_file_mut<V>(v: &mut V, node: &mut crate::File)
+where
+ V: VisitMut + ?Sized,
+{
+ skip!(node.shebang);
+ v.visit_attributes_mut(&mut node.attrs);
+ for it in &mut node.items {
+ v.visit_item_mut(it);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_fn_arg_mut<V>(v: &mut V, node: &mut crate::FnArg)
+where
+ V: VisitMut + ?Sized,
+{
+ match node {
+ crate::FnArg::Receiver(_binding_0) => {
+ v.visit_receiver_mut(_binding_0);
+ }
+ crate::FnArg::Typed(_binding_0) => {
+ v.visit_pat_type_mut(_binding_0);
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_foreign_item_mut<V>(v: &mut V, node: &mut crate::ForeignItem)
+where
+ V: VisitMut + ?Sized,
+{
+ match node {
+ crate::ForeignItem::Fn(_binding_0) => {
+ v.visit_foreign_item_fn_mut(_binding_0);
+ }
+ crate::ForeignItem::Static(_binding_0) => {
+ v.visit_foreign_item_static_mut(_binding_0);
+ }
+ crate::ForeignItem::Type(_binding_0) => {
+ v.visit_foreign_item_type_mut(_binding_0);
+ }
+ crate::ForeignItem::Macro(_binding_0) => {
+ v.visit_foreign_item_macro_mut(_binding_0);
+ }
+ crate::ForeignItem::Verbatim(_binding_0) => {
+ v.visit_token_stream_mut(_binding_0);
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_foreign_item_fn_mut<V>(v: &mut V, node: &mut crate::ForeignItemFn)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_visibility_mut(&mut node.vis);
+ v.visit_signature_mut(&mut node.sig);
+ skip!(node.semi_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_foreign_item_macro_mut<V>(v: &mut V, node: &mut crate::ForeignItemMacro)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_macro_mut(&mut node.mac);
+ skip!(node.semi_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_foreign_item_static_mut<V>(v: &mut V, node: &mut crate::ForeignItemStatic)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_visibility_mut(&mut node.vis);
+ skip!(node.static_token);
+ v.visit_static_mutability_mut(&mut node.mutability);
+ v.visit_ident_mut(&mut node.ident);
+ skip!(node.colon_token);
+ v.visit_type_mut(&mut *node.ty);
+ skip!(node.semi_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_foreign_item_type_mut<V>(v: &mut V, node: &mut crate::ForeignItemType)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_visibility_mut(&mut node.vis);
+ skip!(node.type_token);
+ v.visit_ident_mut(&mut node.ident);
+ v.visit_generics_mut(&mut node.generics);
+ skip!(node.semi_token);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_generic_argument_mut<V>(v: &mut V, node: &mut crate::GenericArgument)
+where
+ V: VisitMut + ?Sized,
+{
+ match node {
+ crate::GenericArgument::Lifetime(_binding_0) => {
+ v.visit_lifetime_mut(_binding_0);
+ }
+ crate::GenericArgument::Type(_binding_0) => {
+ v.visit_type_mut(_binding_0);
+ }
+ crate::GenericArgument::Const(_binding_0) => {
+ v.visit_expr_mut(_binding_0);
+ }
+ crate::GenericArgument::AssocType(_binding_0) => {
+ v.visit_assoc_type_mut(_binding_0);
+ }
+ crate::GenericArgument::AssocConst(_binding_0) => {
+ v.visit_assoc_const_mut(_binding_0);
+ }
+ crate::GenericArgument::Constraint(_binding_0) => {
+ v.visit_constraint_mut(_binding_0);
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_generic_param_mut<V>(v: &mut V, node: &mut crate::GenericParam)
+where
+ V: VisitMut + ?Sized,
+{
+ match node {
+ crate::GenericParam::Lifetime(_binding_0) => {
+ v.visit_lifetime_param_mut(_binding_0);
+ }
+ crate::GenericParam::Type(_binding_0) => {
+ v.visit_type_param_mut(_binding_0);
+ }
+ crate::GenericParam::Const(_binding_0) => {
+ v.visit_const_param_mut(_binding_0);
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_generics_mut<V>(v: &mut V, node: &mut crate::Generics)
+where
+ V: VisitMut + ?Sized,
+{
+ skip!(node.lt_token);
+ for mut el in Punctuated::pairs_mut(&mut node.params) {
+ let it = el.value_mut();
+ v.visit_generic_param_mut(it);
+ }
+ skip!(node.gt_token);
+ if let Some(it) = &mut node.where_clause {
+ v.visit_where_clause_mut(it);
+ }
+}
+pub fn visit_ident_mut<V>(v: &mut V, node: &mut proc_macro2::Ident)
+where
+ V: VisitMut + ?Sized,
+{
+ let mut span = node.span();
+ v.visit_span_mut(&mut span);
+ node.set_span(span);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_impl_item_mut<V>(v: &mut V, node: &mut crate::ImplItem)
+where
+ V: VisitMut + ?Sized,
+{
+ match node {
+ crate::ImplItem::Const(_binding_0) => {
+ v.visit_impl_item_const_mut(_binding_0);
+ }
+ crate::ImplItem::Fn(_binding_0) => {
+ v.visit_impl_item_fn_mut(_binding_0);
+ }
+ crate::ImplItem::Type(_binding_0) => {
+ v.visit_impl_item_type_mut(_binding_0);
+ }
+ crate::ImplItem::Macro(_binding_0) => {
+ v.visit_impl_item_macro_mut(_binding_0);
+ }
+ crate::ImplItem::Verbatim(_binding_0) => {
+ v.visit_token_stream_mut(_binding_0);
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_impl_item_const_mut<V>(v: &mut V, node: &mut crate::ImplItemConst)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_visibility_mut(&mut node.vis);
+ skip!(node.defaultness);
+ skip!(node.const_token);
+ v.visit_ident_mut(&mut node.ident);
+ v.visit_generics_mut(&mut node.generics);
+ skip!(node.colon_token);
+ v.visit_type_mut(&mut node.ty);
+ skip!(node.eq_token);
+ v.visit_expr_mut(&mut node.expr);
+ skip!(node.semi_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_impl_item_fn_mut<V>(v: &mut V, node: &mut crate::ImplItemFn)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_visibility_mut(&mut node.vis);
+ skip!(node.defaultness);
+ v.visit_signature_mut(&mut node.sig);
+ v.visit_block_mut(&mut node.block);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_impl_item_macro_mut<V>(v: &mut V, node: &mut crate::ImplItemMacro)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_macro_mut(&mut node.mac);
+ skip!(node.semi_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_impl_item_type_mut<V>(v: &mut V, node: &mut crate::ImplItemType)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_visibility_mut(&mut node.vis);
+ skip!(node.defaultness);
+ skip!(node.type_token);
+ v.visit_ident_mut(&mut node.ident);
+ v.visit_generics_mut(&mut node.generics);
+ skip!(node.eq_token);
+ v.visit_type_mut(&mut node.ty);
+ skip!(node.semi_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_impl_restriction_mut<V>(v: &mut V, node: &mut crate::ImplRestriction)
+where
+ V: VisitMut + ?Sized,
+{
+ match *node {}
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_index_mut<V>(v: &mut V, node: &mut crate::Index)
+where
+ V: VisitMut + ?Sized,
+{
+ skip!(node.index);
+ v.visit_span_mut(&mut node.span);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_item_mut<V>(v: &mut V, node: &mut crate::Item)
+where
+ V: VisitMut + ?Sized,
+{
+ match node {
+ crate::Item::Const(_binding_0) => {
+ v.visit_item_const_mut(_binding_0);
+ }
+ crate::Item::Enum(_binding_0) => {
+ v.visit_item_enum_mut(_binding_0);
+ }
+ crate::Item::ExternCrate(_binding_0) => {
+ v.visit_item_extern_crate_mut(_binding_0);
+ }
+ crate::Item::Fn(_binding_0) => {
+ v.visit_item_fn_mut(_binding_0);
+ }
+ crate::Item::ForeignMod(_binding_0) => {
+ v.visit_item_foreign_mod_mut(_binding_0);
+ }
+ crate::Item::Impl(_binding_0) => {
+ v.visit_item_impl_mut(_binding_0);
+ }
+ crate::Item::Macro(_binding_0) => {
+ v.visit_item_macro_mut(_binding_0);
+ }
+ crate::Item::Mod(_binding_0) => {
+ v.visit_item_mod_mut(_binding_0);
+ }
+ crate::Item::Static(_binding_0) => {
+ v.visit_item_static_mut(_binding_0);
+ }
+ crate::Item::Struct(_binding_0) => {
+ v.visit_item_struct_mut(_binding_0);
+ }
+ crate::Item::Trait(_binding_0) => {
+ v.visit_item_trait_mut(_binding_0);
+ }
+ crate::Item::TraitAlias(_binding_0) => {
+ v.visit_item_trait_alias_mut(_binding_0);
+ }
+ crate::Item::Type(_binding_0) => {
+ v.visit_item_type_mut(_binding_0);
+ }
+ crate::Item::Union(_binding_0) => {
+ v.visit_item_union_mut(_binding_0);
+ }
+ crate::Item::Use(_binding_0) => {
+ v.visit_item_use_mut(_binding_0);
+ }
+ crate::Item::Verbatim(_binding_0) => {
+ v.visit_token_stream_mut(_binding_0);
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_item_const_mut<V>(v: &mut V, node: &mut crate::ItemConst)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_visibility_mut(&mut node.vis);
+ skip!(node.const_token);
+ v.visit_ident_mut(&mut node.ident);
+ v.visit_generics_mut(&mut node.generics);
+ skip!(node.colon_token);
+ v.visit_type_mut(&mut *node.ty);
+ skip!(node.eq_token);
+ v.visit_expr_mut(&mut *node.expr);
+ skip!(node.semi_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_item_enum_mut<V>(v: &mut V, node: &mut crate::ItemEnum)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_visibility_mut(&mut node.vis);
+ skip!(node.enum_token);
+ v.visit_ident_mut(&mut node.ident);
+ v.visit_generics_mut(&mut node.generics);
+ skip!(node.brace_token);
+ for mut el in Punctuated::pairs_mut(&mut node.variants) {
+ let it = el.value_mut();
+ v.visit_variant_mut(it);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_item_extern_crate_mut<V>(v: &mut V, node: &mut crate::ItemExternCrate)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_visibility_mut(&mut node.vis);
+ skip!(node.extern_token);
+ skip!(node.crate_token);
+ v.visit_ident_mut(&mut node.ident);
+ if let Some(it) = &mut node.rename {
+ skip!((it).0);
+ v.visit_ident_mut(&mut (it).1);
+ }
+ skip!(node.semi_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_item_fn_mut<V>(v: &mut V, node: &mut crate::ItemFn)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_visibility_mut(&mut node.vis);
+ v.visit_signature_mut(&mut node.sig);
+ v.visit_block_mut(&mut *node.block);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_item_foreign_mod_mut<V>(v: &mut V, node: &mut crate::ItemForeignMod)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ skip!(node.unsafety);
+ v.visit_abi_mut(&mut node.abi);
+ skip!(node.brace_token);
+ for it in &mut node.items {
+ v.visit_foreign_item_mut(it);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_item_impl_mut<V>(v: &mut V, node: &mut crate::ItemImpl)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ skip!(node.defaultness);
+ skip!(node.unsafety);
+ skip!(node.impl_token);
+ v.visit_generics_mut(&mut node.generics);
+ if let Some(it) = &mut node.trait_ {
+ skip!((it).0);
+ v.visit_path_mut(&mut (it).1);
+ skip!((it).2);
+ }
+ v.visit_type_mut(&mut *node.self_ty);
+ skip!(node.brace_token);
+ for it in &mut node.items {
+ v.visit_impl_item_mut(it);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_item_macro_mut<V>(v: &mut V, node: &mut crate::ItemMacro)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ if let Some(it) = &mut node.ident {
+ v.visit_ident_mut(it);
+ }
+ v.visit_macro_mut(&mut node.mac);
+ skip!(node.semi_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_item_mod_mut<V>(v: &mut V, node: &mut crate::ItemMod)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_visibility_mut(&mut node.vis);
+ skip!(node.unsafety);
+ skip!(node.mod_token);
+ v.visit_ident_mut(&mut node.ident);
+ if let Some(it) = &mut node.content {
+ skip!((it).0);
+ for it in &mut (it).1 {
+ v.visit_item_mut(it);
+ }
+ }
+ skip!(node.semi);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_item_static_mut<V>(v: &mut V, node: &mut crate::ItemStatic)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_visibility_mut(&mut node.vis);
+ skip!(node.static_token);
+ v.visit_static_mutability_mut(&mut node.mutability);
+ v.visit_ident_mut(&mut node.ident);
+ skip!(node.colon_token);
+ v.visit_type_mut(&mut *node.ty);
+ skip!(node.eq_token);
+ v.visit_expr_mut(&mut *node.expr);
+ skip!(node.semi_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_item_struct_mut<V>(v: &mut V, node: &mut crate::ItemStruct)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_visibility_mut(&mut node.vis);
+ skip!(node.struct_token);
+ v.visit_ident_mut(&mut node.ident);
+ v.visit_generics_mut(&mut node.generics);
+ v.visit_fields_mut(&mut node.fields);
+ skip!(node.semi_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_item_trait_mut<V>(v: &mut V, node: &mut crate::ItemTrait)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_visibility_mut(&mut node.vis);
+ skip!(node.unsafety);
+ skip!(node.auto_token);
+ if let Some(it) = &mut node.restriction {
+ v.visit_impl_restriction_mut(it);
+ }
+ skip!(node.trait_token);
+ v.visit_ident_mut(&mut node.ident);
+ v.visit_generics_mut(&mut node.generics);
+ skip!(node.colon_token);
+ for mut el in Punctuated::pairs_mut(&mut node.supertraits) {
+ let it = el.value_mut();
+ v.visit_type_param_bound_mut(it);
+ }
+ skip!(node.brace_token);
+ for it in &mut node.items {
+ v.visit_trait_item_mut(it);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_item_trait_alias_mut<V>(v: &mut V, node: &mut crate::ItemTraitAlias)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_visibility_mut(&mut node.vis);
+ skip!(node.trait_token);
+ v.visit_ident_mut(&mut node.ident);
+ v.visit_generics_mut(&mut node.generics);
+ skip!(node.eq_token);
+ for mut el in Punctuated::pairs_mut(&mut node.bounds) {
+ let it = el.value_mut();
+ v.visit_type_param_bound_mut(it);
+ }
+ skip!(node.semi_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_item_type_mut<V>(v: &mut V, node: &mut crate::ItemType)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_visibility_mut(&mut node.vis);
+ skip!(node.type_token);
+ v.visit_ident_mut(&mut node.ident);
+ v.visit_generics_mut(&mut node.generics);
+ skip!(node.eq_token);
+ v.visit_type_mut(&mut *node.ty);
+ skip!(node.semi_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_item_union_mut<V>(v: &mut V, node: &mut crate::ItemUnion)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_visibility_mut(&mut node.vis);
+ skip!(node.union_token);
+ v.visit_ident_mut(&mut node.ident);
+ v.visit_generics_mut(&mut node.generics);
+ v.visit_fields_named_mut(&mut node.fields);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_item_use_mut<V>(v: &mut V, node: &mut crate::ItemUse)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_visibility_mut(&mut node.vis);
+ skip!(node.use_token);
+ skip!(node.leading_colon);
+ v.visit_use_tree_mut(&mut node.tree);
+ skip!(node.semi_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_label_mut<V>(v: &mut V, node: &mut crate::Label)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_lifetime_mut(&mut node.name);
+ skip!(node.colon_token);
+}
+pub fn visit_lifetime_mut<V>(v: &mut V, node: &mut crate::Lifetime)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_span_mut(&mut node.apostrophe);
+ v.visit_ident_mut(&mut node.ident);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_lifetime_param_mut<V>(v: &mut V, node: &mut crate::LifetimeParam)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_lifetime_mut(&mut node.lifetime);
+ skip!(node.colon_token);
+ for mut el in Punctuated::pairs_mut(&mut node.bounds) {
+ let it = el.value_mut();
+ v.visit_lifetime_mut(it);
+ }
+}
+pub fn visit_lit_mut<V>(v: &mut V, node: &mut crate::Lit)
+where
+ V: VisitMut + ?Sized,
+{
+ match node {
+ crate::Lit::Str(_binding_0) => {
+ v.visit_lit_str_mut(_binding_0);
+ }
+ crate::Lit::ByteStr(_binding_0) => {
+ v.visit_lit_byte_str_mut(_binding_0);
+ }
+ crate::Lit::CStr(_binding_0) => {
+ v.visit_lit_cstr_mut(_binding_0);
+ }
+ crate::Lit::Byte(_binding_0) => {
+ v.visit_lit_byte_mut(_binding_0);
+ }
+ crate::Lit::Char(_binding_0) => {
+ v.visit_lit_char_mut(_binding_0);
+ }
+ crate::Lit::Int(_binding_0) => {
+ v.visit_lit_int_mut(_binding_0);
+ }
+ crate::Lit::Float(_binding_0) => {
+ v.visit_lit_float_mut(_binding_0);
+ }
+ crate::Lit::Bool(_binding_0) => {
+ v.visit_lit_bool_mut(_binding_0);
+ }
+ crate::Lit::Verbatim(_binding_0) => {
+ skip!(_binding_0);
+ }
+ }
+}
+pub fn visit_lit_bool_mut<V>(v: &mut V, node: &mut crate::LitBool)
+where
+ V: VisitMut + ?Sized,
+{
+ skip!(node.value);
+ v.visit_span_mut(&mut node.span);
+}
+pub fn visit_lit_byte_mut<V>(v: &mut V, node: &mut crate::LitByte)
+where
+ V: VisitMut + ?Sized,
+{}
+pub fn visit_lit_byte_str_mut<V>(v: &mut V, node: &mut crate::LitByteStr)
+where
+ V: VisitMut + ?Sized,
+{}
+pub fn visit_lit_cstr_mut<V>(v: &mut V, node: &mut crate::LitCStr)
+where
+ V: VisitMut + ?Sized,
+{}
+pub fn visit_lit_char_mut<V>(v: &mut V, node: &mut crate::LitChar)
+where
+ V: VisitMut + ?Sized,
+{}
+pub fn visit_lit_float_mut<V>(v: &mut V, node: &mut crate::LitFloat)
+where
+ V: VisitMut + ?Sized,
+{}
+pub fn visit_lit_int_mut<V>(v: &mut V, node: &mut crate::LitInt)
+where
+ V: VisitMut + ?Sized,
+{}
+pub fn visit_lit_str_mut<V>(v: &mut V, node: &mut crate::LitStr)
+where
+ V: VisitMut + ?Sized,
+{}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_local_mut<V>(v: &mut V, node: &mut crate::Local)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ skip!(node.let_token);
+ v.visit_pat_mut(&mut node.pat);
+ if let Some(it) = &mut node.init {
+ v.visit_local_init_mut(it);
+ }
+ skip!(node.semi_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_local_init_mut<V>(v: &mut V, node: &mut crate::LocalInit)
+where
+ V: VisitMut + ?Sized,
+{
+ skip!(node.eq_token);
+ v.visit_expr_mut(&mut *node.expr);
+ if let Some(it) = &mut node.diverge {
+ skip!((it).0);
+ v.visit_expr_mut(&mut *(it).1);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_macro_mut<V>(v: &mut V, node: &mut crate::Macro)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_path_mut(&mut node.path);
+ skip!(node.bang_token);
+ v.visit_macro_delimiter_mut(&mut node.delimiter);
+ v.visit_token_stream_mut(&mut node.tokens);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_macro_delimiter_mut<V>(v: &mut V, node: &mut crate::MacroDelimiter)
+where
+ V: VisitMut + ?Sized,
+{
+ match node {
+ crate::MacroDelimiter::Paren(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::MacroDelimiter::Brace(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::MacroDelimiter::Bracket(_binding_0) => {
+ skip!(_binding_0);
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_member_mut<V>(v: &mut V, node: &mut crate::Member)
+where
+ V: VisitMut + ?Sized,
+{
+ match node {
+ crate::Member::Named(_binding_0) => {
+ v.visit_ident_mut(_binding_0);
+ }
+ crate::Member::Unnamed(_binding_0) => {
+ v.visit_index_mut(_binding_0);
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_meta_mut<V>(v: &mut V, node: &mut crate::Meta)
+where
+ V: VisitMut + ?Sized,
+{
+ match node {
+ crate::Meta::Path(_binding_0) => {
+ v.visit_path_mut(_binding_0);
+ }
+ crate::Meta::List(_binding_0) => {
+ v.visit_meta_list_mut(_binding_0);
+ }
+ crate::Meta::NameValue(_binding_0) => {
+ v.visit_meta_name_value_mut(_binding_0);
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_meta_list_mut<V>(v: &mut V, node: &mut crate::MetaList)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_path_mut(&mut node.path);
+ v.visit_macro_delimiter_mut(&mut node.delimiter);
+ v.visit_token_stream_mut(&mut node.tokens);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_meta_name_value_mut<V>(v: &mut V, node: &mut crate::MetaNameValue)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_path_mut(&mut node.path);
+ skip!(node.eq_token);
+ v.visit_expr_mut(&mut node.value);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_parenthesized_generic_arguments_mut<V>(
+ v: &mut V,
+ node: &mut crate::ParenthesizedGenericArguments,
+)
+where
+ V: VisitMut + ?Sized,
+{
+ skip!(node.paren_token);
+ for mut el in Punctuated::pairs_mut(&mut node.inputs) {
+ let it = el.value_mut();
+ v.visit_type_mut(it);
+ }
+ v.visit_return_type_mut(&mut node.output);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_pat_mut<V>(v: &mut V, node: &mut crate::Pat)
+where
+ V: VisitMut + ?Sized,
+{
+ match node {
+ crate::Pat::Const(_binding_0) => {
+ v.visit_expr_const_mut(_binding_0);
+ }
+ crate::Pat::Ident(_binding_0) => {
+ v.visit_pat_ident_mut(_binding_0);
+ }
+ crate::Pat::Lit(_binding_0) => {
+ v.visit_expr_lit_mut(_binding_0);
+ }
+ crate::Pat::Macro(_binding_0) => {
+ v.visit_expr_macro_mut(_binding_0);
+ }
+ crate::Pat::Or(_binding_0) => {
+ v.visit_pat_or_mut(_binding_0);
+ }
+ crate::Pat::Paren(_binding_0) => {
+ v.visit_pat_paren_mut(_binding_0);
+ }
+ crate::Pat::Path(_binding_0) => {
+ v.visit_expr_path_mut(_binding_0);
+ }
+ crate::Pat::Range(_binding_0) => {
+ v.visit_expr_range_mut(_binding_0);
+ }
+ crate::Pat::Reference(_binding_0) => {
+ v.visit_pat_reference_mut(_binding_0);
+ }
+ crate::Pat::Rest(_binding_0) => {
+ v.visit_pat_rest_mut(_binding_0);
+ }
+ crate::Pat::Slice(_binding_0) => {
+ v.visit_pat_slice_mut(_binding_0);
+ }
+ crate::Pat::Struct(_binding_0) => {
+ v.visit_pat_struct_mut(_binding_0);
+ }
+ crate::Pat::Tuple(_binding_0) => {
+ v.visit_pat_tuple_mut(_binding_0);
+ }
+ crate::Pat::TupleStruct(_binding_0) => {
+ v.visit_pat_tuple_struct_mut(_binding_0);
+ }
+ crate::Pat::Type(_binding_0) => {
+ v.visit_pat_type_mut(_binding_0);
+ }
+ crate::Pat::Verbatim(_binding_0) => {
+ v.visit_token_stream_mut(_binding_0);
+ }
+ crate::Pat::Wild(_binding_0) => {
+ v.visit_pat_wild_mut(_binding_0);
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_pat_ident_mut<V>(v: &mut V, node: &mut crate::PatIdent)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ skip!(node.by_ref);
+ skip!(node.mutability);
+ v.visit_ident_mut(&mut node.ident);
+ if let Some(it) = &mut node.subpat {
+ skip!((it).0);
+ v.visit_pat_mut(&mut *(it).1);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_pat_or_mut<V>(v: &mut V, node: &mut crate::PatOr)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ skip!(node.leading_vert);
+ for mut el in Punctuated::pairs_mut(&mut node.cases) {
+ let it = el.value_mut();
+ v.visit_pat_mut(it);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_pat_paren_mut<V>(v: &mut V, node: &mut crate::PatParen)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ skip!(node.paren_token);
+ v.visit_pat_mut(&mut *node.pat);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_pat_reference_mut<V>(v: &mut V, node: &mut crate::PatReference)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ skip!(node.and_token);
+ skip!(node.mutability);
+ v.visit_pat_mut(&mut *node.pat);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_pat_rest_mut<V>(v: &mut V, node: &mut crate::PatRest)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ skip!(node.dot2_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_pat_slice_mut<V>(v: &mut V, node: &mut crate::PatSlice)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ skip!(node.bracket_token);
+ for mut el in Punctuated::pairs_mut(&mut node.elems) {
+ let it = el.value_mut();
+ v.visit_pat_mut(it);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_pat_struct_mut<V>(v: &mut V, node: &mut crate::PatStruct)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ if let Some(it) = &mut node.qself {
+ v.visit_qself_mut(it);
+ }
+ v.visit_path_mut(&mut node.path);
+ skip!(node.brace_token);
+ for mut el in Punctuated::pairs_mut(&mut node.fields) {
+ let it = el.value_mut();
+ v.visit_field_pat_mut(it);
+ }
+ if let Some(it) = &mut node.rest {
+ v.visit_pat_rest_mut(it);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_pat_tuple_mut<V>(v: &mut V, node: &mut crate::PatTuple)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ skip!(node.paren_token);
+ for mut el in Punctuated::pairs_mut(&mut node.elems) {
+ let it = el.value_mut();
+ v.visit_pat_mut(it);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_pat_tuple_struct_mut<V>(v: &mut V, node: &mut crate::PatTupleStruct)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ if let Some(it) = &mut node.qself {
+ v.visit_qself_mut(it);
+ }
+ v.visit_path_mut(&mut node.path);
+ skip!(node.paren_token);
+ for mut el in Punctuated::pairs_mut(&mut node.elems) {
+ let it = el.value_mut();
+ v.visit_pat_mut(it);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_pat_type_mut<V>(v: &mut V, node: &mut crate::PatType)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_pat_mut(&mut *node.pat);
+ skip!(node.colon_token);
+ v.visit_type_mut(&mut *node.ty);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_pat_wild_mut<V>(v: &mut V, node: &mut crate::PatWild)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ skip!(node.underscore_token);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_path_mut<V>(v: &mut V, node: &mut crate::Path)
+where
+ V: VisitMut + ?Sized,
+{
+ skip!(node.leading_colon);
+ for mut el in Punctuated::pairs_mut(&mut node.segments) {
+ let it = el.value_mut();
+ v.visit_path_segment_mut(it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_path_arguments_mut<V>(v: &mut V, node: &mut crate::PathArguments)
+where
+ V: VisitMut + ?Sized,
+{
+ match node {
+ crate::PathArguments::None => {}
+ crate::PathArguments::AngleBracketed(_binding_0) => {
+ v.visit_angle_bracketed_generic_arguments_mut(_binding_0);
+ }
+ crate::PathArguments::Parenthesized(_binding_0) => {
+ v.visit_parenthesized_generic_arguments_mut(_binding_0);
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_path_segment_mut<V>(v: &mut V, node: &mut crate::PathSegment)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_ident_mut(&mut node.ident);
+ v.visit_path_arguments_mut(&mut node.arguments);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_pointer_mutability_mut<V>(v: &mut V, node: &mut crate::PointerMutability)
+where
+ V: VisitMut + ?Sized,
+{
+ match node {
+ crate::PointerMutability::Const(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::PointerMutability::Mut(_binding_0) => {
+ skip!(_binding_0);
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_precise_capture_mut<V>(v: &mut V, node: &mut crate::PreciseCapture)
+where
+ V: VisitMut + ?Sized,
+{
+ skip!(node.use_token);
+ skip!(node.lt_token);
+ for mut el in Punctuated::pairs_mut(&mut node.params) {
+ let it = el.value_mut();
+ v.visit_captured_param_mut(it);
+ }
+ skip!(node.gt_token);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_predicate_lifetime_mut<V>(v: &mut V, node: &mut crate::PredicateLifetime)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_lifetime_mut(&mut node.lifetime);
+ skip!(node.colon_token);
+ for mut el in Punctuated::pairs_mut(&mut node.bounds) {
+ let it = el.value_mut();
+ v.visit_lifetime_mut(it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_predicate_type_mut<V>(v: &mut V, node: &mut crate::PredicateType)
+where
+ V: VisitMut + ?Sized,
+{
+ if let Some(it) = &mut node.lifetimes {
+ v.visit_bound_lifetimes_mut(it);
+ }
+ v.visit_type_mut(&mut node.bounded_ty);
+ skip!(node.colon_token);
+ for mut el in Punctuated::pairs_mut(&mut node.bounds) {
+ let it = el.value_mut();
+ v.visit_type_param_bound_mut(it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_qself_mut<V>(v: &mut V, node: &mut crate::QSelf)
+where
+ V: VisitMut + ?Sized,
+{
+ skip!(node.lt_token);
+ v.visit_type_mut(&mut *node.ty);
+ skip!(node.position);
+ skip!(node.as_token);
+ skip!(node.gt_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_range_limits_mut<V>(v: &mut V, node: &mut crate::RangeLimits)
+where
+ V: VisitMut + ?Sized,
+{
+ match node {
+ crate::RangeLimits::HalfOpen(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::RangeLimits::Closed(_binding_0) => {
+ skip!(_binding_0);
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_receiver_mut<V>(v: &mut V, node: &mut crate::Receiver)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ if let Some(it) = &mut node.reference {
+ skip!((it).0);
+ if let Some(it) = &mut (it).1 {
+ v.visit_lifetime_mut(it);
+ }
+ }
+ skip!(node.mutability);
+ skip!(node.self_token);
+ skip!(node.colon_token);
+ v.visit_type_mut(&mut *node.ty);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_return_type_mut<V>(v: &mut V, node: &mut crate::ReturnType)
+where
+ V: VisitMut + ?Sized,
+{
+ match node {
+ crate::ReturnType::Default => {}
+ crate::ReturnType::Type(_binding_0, _binding_1) => {
+ skip!(_binding_0);
+ v.visit_type_mut(&mut **_binding_1);
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_signature_mut<V>(v: &mut V, node: &mut crate::Signature)
+where
+ V: VisitMut + ?Sized,
+{
+ skip!(node.constness);
+ skip!(node.asyncness);
+ skip!(node.unsafety);
+ if let Some(it) = &mut node.abi {
+ v.visit_abi_mut(it);
+ }
+ skip!(node.fn_token);
+ v.visit_ident_mut(&mut node.ident);
+ v.visit_generics_mut(&mut node.generics);
+ skip!(node.paren_token);
+ for mut el in Punctuated::pairs_mut(&mut node.inputs) {
+ let it = el.value_mut();
+ v.visit_fn_arg_mut(it);
+ }
+ if let Some(it) = &mut node.variadic {
+ v.visit_variadic_mut(it);
+ }
+ v.visit_return_type_mut(&mut node.output);
+}
+pub fn visit_span_mut<V>(v: &mut V, node: &mut proc_macro2::Span)
+where
+ V: VisitMut + ?Sized,
+{}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_static_mutability_mut<V>(v: &mut V, node: &mut crate::StaticMutability)
+where
+ V: VisitMut + ?Sized,
+{
+ match node {
+ crate::StaticMutability::Mut(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::StaticMutability::None => {}
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_stmt_mut<V>(v: &mut V, node: &mut crate::Stmt)
+where
+ V: VisitMut + ?Sized,
+{
+ match node {
+ crate::Stmt::Local(_binding_0) => {
+ v.visit_local_mut(_binding_0);
+ }
+ crate::Stmt::Item(_binding_0) => {
+ v.visit_item_mut(_binding_0);
+ }
+ crate::Stmt::Expr(_binding_0, _binding_1) => {
+ v.visit_expr_mut(_binding_0);
+ skip!(_binding_1);
+ }
+ crate::Stmt::Macro(_binding_0) => {
+ v.visit_stmt_macro_mut(_binding_0);
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_stmt_macro_mut<V>(v: &mut V, node: &mut crate::StmtMacro)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_macro_mut(&mut node.mac);
+ skip!(node.semi_token);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_trait_bound_mut<V>(v: &mut V, node: &mut crate::TraitBound)
+where
+ V: VisitMut + ?Sized,
+{
+ skip!(node.paren_token);
+ v.visit_trait_bound_modifier_mut(&mut node.modifier);
+ if let Some(it) = &mut node.lifetimes {
+ v.visit_bound_lifetimes_mut(it);
+ }
+ v.visit_path_mut(&mut node.path);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_trait_bound_modifier_mut<V>(v: &mut V, node: &mut crate::TraitBoundModifier)
+where
+ V: VisitMut + ?Sized,
+{
+ match node {
+ crate::TraitBoundModifier::None => {}
+ crate::TraitBoundModifier::Maybe(_binding_0) => {
+ skip!(_binding_0);
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_trait_item_mut<V>(v: &mut V, node: &mut crate::TraitItem)
+where
+ V: VisitMut + ?Sized,
+{
+ match node {
+ crate::TraitItem::Const(_binding_0) => {
+ v.visit_trait_item_const_mut(_binding_0);
+ }
+ crate::TraitItem::Fn(_binding_0) => {
+ v.visit_trait_item_fn_mut(_binding_0);
+ }
+ crate::TraitItem::Type(_binding_0) => {
+ v.visit_trait_item_type_mut(_binding_0);
+ }
+ crate::TraitItem::Macro(_binding_0) => {
+ v.visit_trait_item_macro_mut(_binding_0);
+ }
+ crate::TraitItem::Verbatim(_binding_0) => {
+ v.visit_token_stream_mut(_binding_0);
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_trait_item_const_mut<V>(v: &mut V, node: &mut crate::TraitItemConst)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ skip!(node.const_token);
+ v.visit_ident_mut(&mut node.ident);
+ v.visit_generics_mut(&mut node.generics);
+ skip!(node.colon_token);
+ v.visit_type_mut(&mut node.ty);
+ if let Some(it) = &mut node.default {
+ skip!((it).0);
+ v.visit_expr_mut(&mut (it).1);
+ }
+ skip!(node.semi_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_trait_item_fn_mut<V>(v: &mut V, node: &mut crate::TraitItemFn)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_signature_mut(&mut node.sig);
+ if let Some(it) = &mut node.default {
+ v.visit_block_mut(it);
+ }
+ skip!(node.semi_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_trait_item_macro_mut<V>(v: &mut V, node: &mut crate::TraitItemMacro)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_macro_mut(&mut node.mac);
+ skip!(node.semi_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_trait_item_type_mut<V>(v: &mut V, node: &mut crate::TraitItemType)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ skip!(node.type_token);
+ v.visit_ident_mut(&mut node.ident);
+ v.visit_generics_mut(&mut node.generics);
+ skip!(node.colon_token);
+ for mut el in Punctuated::pairs_mut(&mut node.bounds) {
+ let it = el.value_mut();
+ v.visit_type_param_bound_mut(it);
+ }
+ if let Some(it) = &mut node.default {
+ skip!((it).0);
+ v.visit_type_mut(&mut (it).1);
+ }
+ skip!(node.semi_token);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_type_mut<V>(v: &mut V, node: &mut crate::Type)
+where
+ V: VisitMut + ?Sized,
+{
+ match node {
+ crate::Type::Array(_binding_0) => {
+ v.visit_type_array_mut(_binding_0);
+ }
+ crate::Type::BareFn(_binding_0) => {
+ v.visit_type_bare_fn_mut(_binding_0);
+ }
+ crate::Type::Group(_binding_0) => {
+ v.visit_type_group_mut(_binding_0);
+ }
+ crate::Type::ImplTrait(_binding_0) => {
+ v.visit_type_impl_trait_mut(_binding_0);
+ }
+ crate::Type::Infer(_binding_0) => {
+ v.visit_type_infer_mut(_binding_0);
+ }
+ crate::Type::Macro(_binding_0) => {
+ v.visit_type_macro_mut(_binding_0);
+ }
+ crate::Type::Never(_binding_0) => {
+ v.visit_type_never_mut(_binding_0);
+ }
+ crate::Type::Paren(_binding_0) => {
+ v.visit_type_paren_mut(_binding_0);
+ }
+ crate::Type::Path(_binding_0) => {
+ v.visit_type_path_mut(_binding_0);
+ }
+ crate::Type::Ptr(_binding_0) => {
+ v.visit_type_ptr_mut(_binding_0);
+ }
+ crate::Type::Reference(_binding_0) => {
+ v.visit_type_reference_mut(_binding_0);
+ }
+ crate::Type::Slice(_binding_0) => {
+ v.visit_type_slice_mut(_binding_0);
+ }
+ crate::Type::TraitObject(_binding_0) => {
+ v.visit_type_trait_object_mut(_binding_0);
+ }
+ crate::Type::Tuple(_binding_0) => {
+ v.visit_type_tuple_mut(_binding_0);
+ }
+ crate::Type::Verbatim(_binding_0) => {
+ v.visit_token_stream_mut(_binding_0);
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_type_array_mut<V>(v: &mut V, node: &mut crate::TypeArray)
+where
+ V: VisitMut + ?Sized,
+{
+ skip!(node.bracket_token);
+ v.visit_type_mut(&mut *node.elem);
+ skip!(node.semi_token);
+ v.visit_expr_mut(&mut node.len);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_type_bare_fn_mut<V>(v: &mut V, node: &mut crate::TypeBareFn)
+where
+ V: VisitMut + ?Sized,
+{
+ if let Some(it) = &mut node.lifetimes {
+ v.visit_bound_lifetimes_mut(it);
+ }
+ skip!(node.unsafety);
+ if let Some(it) = &mut node.abi {
+ v.visit_abi_mut(it);
+ }
+ skip!(node.fn_token);
+ skip!(node.paren_token);
+ for mut el in Punctuated::pairs_mut(&mut node.inputs) {
+ let it = el.value_mut();
+ v.visit_bare_fn_arg_mut(it);
+ }
+ if let Some(it) = &mut node.variadic {
+ v.visit_bare_variadic_mut(it);
+ }
+ v.visit_return_type_mut(&mut node.output);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_type_group_mut<V>(v: &mut V, node: &mut crate::TypeGroup)
+where
+ V: VisitMut + ?Sized,
+{
+ skip!(node.group_token);
+ v.visit_type_mut(&mut *node.elem);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_type_impl_trait_mut<V>(v: &mut V, node: &mut crate::TypeImplTrait)
+where
+ V: VisitMut + ?Sized,
+{
+ skip!(node.impl_token);
+ for mut el in Punctuated::pairs_mut(&mut node.bounds) {
+ let it = el.value_mut();
+ v.visit_type_param_bound_mut(it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_type_infer_mut<V>(v: &mut V, node: &mut crate::TypeInfer)
+where
+ V: VisitMut + ?Sized,
+{
+ skip!(node.underscore_token);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_type_macro_mut<V>(v: &mut V, node: &mut crate::TypeMacro)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_macro_mut(&mut node.mac);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_type_never_mut<V>(v: &mut V, node: &mut crate::TypeNever)
+where
+ V: VisitMut + ?Sized,
+{
+ skip!(node.bang_token);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_type_param_mut<V>(v: &mut V, node: &mut crate::TypeParam)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_ident_mut(&mut node.ident);
+ skip!(node.colon_token);
+ for mut el in Punctuated::pairs_mut(&mut node.bounds) {
+ let it = el.value_mut();
+ v.visit_type_param_bound_mut(it);
+ }
+ skip!(node.eq_token);
+ if let Some(it) = &mut node.default {
+ v.visit_type_mut(it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_type_param_bound_mut<V>(v: &mut V, node: &mut crate::TypeParamBound)
+where
+ V: VisitMut + ?Sized,
+{
+ match node {
+ crate::TypeParamBound::Trait(_binding_0) => {
+ v.visit_trait_bound_mut(_binding_0);
+ }
+ crate::TypeParamBound::Lifetime(_binding_0) => {
+ v.visit_lifetime_mut(_binding_0);
+ }
+ crate::TypeParamBound::PreciseCapture(_binding_0) => {
+ full!(v.visit_precise_capture_mut(_binding_0));
+ }
+ crate::TypeParamBound::Verbatim(_binding_0) => {
+ v.visit_token_stream_mut(_binding_0);
+ }
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_type_paren_mut<V>(v: &mut V, node: &mut crate::TypeParen)
+where
+ V: VisitMut + ?Sized,
+{
+ skip!(node.paren_token);
+ v.visit_type_mut(&mut *node.elem);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_type_path_mut<V>(v: &mut V, node: &mut crate::TypePath)
+where
+ V: VisitMut + ?Sized,
+{
+ if let Some(it) = &mut node.qself {
+ v.visit_qself_mut(it);
+ }
+ v.visit_path_mut(&mut node.path);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_type_ptr_mut<V>(v: &mut V, node: &mut crate::TypePtr)
+where
+ V: VisitMut + ?Sized,
+{
+ skip!(node.star_token);
+ skip!(node.const_token);
+ skip!(node.mutability);
+ v.visit_type_mut(&mut *node.elem);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_type_reference_mut<V>(v: &mut V, node: &mut crate::TypeReference)
+where
+ V: VisitMut + ?Sized,
+{
+ skip!(node.and_token);
+ if let Some(it) = &mut node.lifetime {
+ v.visit_lifetime_mut(it);
+ }
+ skip!(node.mutability);
+ v.visit_type_mut(&mut *node.elem);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_type_slice_mut<V>(v: &mut V, node: &mut crate::TypeSlice)
+where
+ V: VisitMut + ?Sized,
+{
+ skip!(node.bracket_token);
+ v.visit_type_mut(&mut *node.elem);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_type_trait_object_mut<V>(v: &mut V, node: &mut crate::TypeTraitObject)
+where
+ V: VisitMut + ?Sized,
+{
+ skip!(node.dyn_token);
+ for mut el in Punctuated::pairs_mut(&mut node.bounds) {
+ let it = el.value_mut();
+ v.visit_type_param_bound_mut(it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_type_tuple_mut<V>(v: &mut V, node: &mut crate::TypeTuple)
+where
+ V: VisitMut + ?Sized,
+{
+ skip!(node.paren_token);
+ for mut el in Punctuated::pairs_mut(&mut node.elems) {
+ let it = el.value_mut();
+ v.visit_type_mut(it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_un_op_mut<V>(v: &mut V, node: &mut crate::UnOp)
+where
+ V: VisitMut + ?Sized,
+{
+ match node {
+ crate::UnOp::Deref(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::UnOp::Not(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::UnOp::Neg(_binding_0) => {
+ skip!(_binding_0);
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_use_glob_mut<V>(v: &mut V, node: &mut crate::UseGlob)
+where
+ V: VisitMut + ?Sized,
+{
+ skip!(node.star_token);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_use_group_mut<V>(v: &mut V, node: &mut crate::UseGroup)
+where
+ V: VisitMut + ?Sized,
+{
+ skip!(node.brace_token);
+ for mut el in Punctuated::pairs_mut(&mut node.items) {
+ let it = el.value_mut();
+ v.visit_use_tree_mut(it);
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_use_name_mut<V>(v: &mut V, node: &mut crate::UseName)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_ident_mut(&mut node.ident);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_use_path_mut<V>(v: &mut V, node: &mut crate::UsePath)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_ident_mut(&mut node.ident);
+ skip!(node.colon2_token);
+ v.visit_use_tree_mut(&mut *node.tree);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_use_rename_mut<V>(v: &mut V, node: &mut crate::UseRename)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_ident_mut(&mut node.ident);
+ skip!(node.as_token);
+ v.visit_ident_mut(&mut node.rename);
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_use_tree_mut<V>(v: &mut V, node: &mut crate::UseTree)
+where
+ V: VisitMut + ?Sized,
+{
+ match node {
+ crate::UseTree::Path(_binding_0) => {
+ v.visit_use_path_mut(_binding_0);
+ }
+ crate::UseTree::Name(_binding_0) => {
+ v.visit_use_name_mut(_binding_0);
+ }
+ crate::UseTree::Rename(_binding_0) => {
+ v.visit_use_rename_mut(_binding_0);
+ }
+ crate::UseTree::Glob(_binding_0) => {
+ v.visit_use_glob_mut(_binding_0);
+ }
+ crate::UseTree::Group(_binding_0) => {
+ v.visit_use_group_mut(_binding_0);
+ }
+ }
+}
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub fn visit_variadic_mut<V>(v: &mut V, node: &mut crate::Variadic)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ if let Some(it) = &mut node.pat {
+ v.visit_pat_mut(&mut *(it).0);
+ skip!((it).1);
+ }
+ skip!(node.dots);
+ skip!(node.comma);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_variant_mut<V>(v: &mut V, node: &mut crate::Variant)
+where
+ V: VisitMut + ?Sized,
+{
+ v.visit_attributes_mut(&mut node.attrs);
+ v.visit_ident_mut(&mut node.ident);
+ v.visit_fields_mut(&mut node.fields);
+ if let Some(it) = &mut node.discriminant {
+ skip!((it).0);
+ v.visit_expr_mut(&mut (it).1);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_vis_restricted_mut<V>(v: &mut V, node: &mut crate::VisRestricted)
+where
+ V: VisitMut + ?Sized,
+{
+ skip!(node.pub_token);
+ skip!(node.paren_token);
+ skip!(node.in_token);
+ v.visit_path_mut(&mut *node.path);
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_visibility_mut<V>(v: &mut V, node: &mut crate::Visibility)
+where
+ V: VisitMut + ?Sized,
+{
+ match node {
+ crate::Visibility::Public(_binding_0) => {
+ skip!(_binding_0);
+ }
+ crate::Visibility::Restricted(_binding_0) => {
+ v.visit_vis_restricted_mut(_binding_0);
+ }
+ crate::Visibility::Inherited => {}
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_where_clause_mut<V>(v: &mut V, node: &mut crate::WhereClause)
+where
+ V: VisitMut + ?Sized,
+{
+ skip!(node.where_token);
+ for mut el in Punctuated::pairs_mut(&mut node.predicates) {
+ let it = el.value_mut();
+ v.visit_where_predicate_mut(it);
+ }
+}
+#[cfg(any(feature = "derive", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))]
+pub fn visit_where_predicate_mut<V>(v: &mut V, node: &mut crate::WherePredicate)
+where
+ V: VisitMut + ?Sized,
+{
+ match node {
+ crate::WherePredicate::Lifetime(_binding_0) => {
+ v.visit_predicate_lifetime_mut(_binding_0);
+ }
+ crate::WherePredicate::Type(_binding_0) => {
+ v.visit_predicate_type_mut(_binding_0);
+ }
+ }
+}
diff --git a/rust/syn/generics.rs b/rust/syn/generics.rs
new file mode 100644
index 000000000000..0c77193da043
--- /dev/null
+++ b/rust/syn/generics.rs
@@ -0,0 +1,1477 @@
+use crate::attr::Attribute;
+use crate::expr::Expr;
+use crate::ident::Ident;
+use crate::lifetime::Lifetime;
+use crate::path::Path;
+use crate::punctuated::{Iter, IterMut, Punctuated};
+use crate::token;
+use crate::ty::Type;
+use proc_macro2::TokenStream;
+#[cfg(all(feature = "printing", feature = "extra-traits"))]
+use std::fmt::{self, Debug};
+#[cfg(all(feature = "printing", feature = "extra-traits"))]
+use std::hash::{Hash, Hasher};
+
+ast_struct! {
+ /// Lifetimes and type parameters attached to a declaration of a function,
+ /// enum, trait, etc.
+ ///
+ /// This struct represents two distinct optional syntactic elements,
+ /// [generic parameters] and [where clause]. In some locations of the
+ /// grammar, there may be other tokens in between these two things.
+ ///
+ /// [generic parameters]: https://doc.rust-lang.org/stable/reference/items/generics.html#generic-parameters
+ /// [where clause]: https://doc.rust-lang.org/stable/reference/items/generics.html#where-clauses
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct Generics {
+ pub lt_token: Option<Token![<]>,
+ pub params: Punctuated<GenericParam, Token![,]>,
+ pub gt_token: Option<Token![>]>,
+ pub where_clause: Option<WhereClause>,
+ }
+}
+
+ast_enum_of_structs! {
+ /// A generic type parameter, lifetime, or const generic: `T: Into<String>`,
+ /// `'a: 'b`, `const LEN: usize`.
+ ///
+ /// # 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 GenericParam {
+ /// A lifetime parameter: `'a: 'b + 'c + 'd`.
+ Lifetime(LifetimeParam),
+
+ /// A generic type parameter: `T: Into<String>`.
+ Type(TypeParam),
+
+ /// A const generic parameter: `const LENGTH: usize`.
+ Const(ConstParam),
+ }
+}
+
+ast_struct! {
+ /// A lifetime definition: `'a: 'b + 'c + 'd`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct LifetimeParam {
+ pub attrs: Vec<Attribute>,
+ pub lifetime: Lifetime,
+ pub colon_token: Option<Token![:]>,
+ pub bounds: Punctuated<Lifetime, Token![+]>,
+ }
+}
+
+ast_struct! {
+ /// A generic type parameter: `T: Into<String>`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct TypeParam {
+ pub attrs: Vec<Attribute>,
+ pub ident: Ident,
+ pub colon_token: Option<Token![:]>,
+ pub bounds: Punctuated<TypeParamBound, Token![+]>,
+ pub eq_token: Option<Token![=]>,
+ pub default: Option<Type>,
+ }
+}
+
+ast_struct! {
+ /// A const generic parameter: `const LENGTH: usize`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct ConstParam {
+ pub attrs: Vec<Attribute>,
+ pub const_token: Token![const],
+ pub ident: Ident,
+ pub colon_token: Token![:],
+ pub ty: Type,
+ pub eq_token: Option<Token![=]>,
+ pub default: Option<Expr>,
+ }
+}
+
+impl Default for Generics {
+ fn default() -> Self {
+ Generics {
+ lt_token: None,
+ params: Punctuated::new(),
+ gt_token: None,
+ where_clause: None,
+ }
+ }
+}
+
+impl Generics {
+ return_impl_trait! {
+ /// Iterator over the lifetime parameters in `self.params`.
+ pub fn lifetimes(&self) -> impl Iterator<Item = &LifetimeParam> [Lifetimes] {
+ Lifetimes(self.params.iter())
+ }
+ }
+
+ return_impl_trait! {
+ /// Iterator over the lifetime parameters in `self.params`.
+ pub fn lifetimes_mut(&mut self) -> impl Iterator<Item = &mut LifetimeParam> [LifetimesMut] {
+ LifetimesMut(self.params.iter_mut())
+ }
+ }
+
+ return_impl_trait! {
+ /// Iterator over the type parameters in `self.params`.
+ pub fn type_params(&self) -> impl Iterator<Item = &TypeParam> [TypeParams] {
+ TypeParams(self.params.iter())
+ }
+ }
+
+ return_impl_trait! {
+ /// Iterator over the type parameters in `self.params`.
+ pub fn type_params_mut(&mut self) -> impl Iterator<Item = &mut TypeParam> [TypeParamsMut] {
+ TypeParamsMut(self.params.iter_mut())
+ }
+ }
+
+ return_impl_trait! {
+ /// Iterator over the constant parameters in `self.params`.
+ pub fn const_params(&self) -> impl Iterator<Item = &ConstParam> [ConstParams] {
+ ConstParams(self.params.iter())
+ }
+ }
+
+ return_impl_trait! {
+ /// Iterator over the constant parameters in `self.params`.
+ pub fn const_params_mut(&mut self) -> impl Iterator<Item = &mut ConstParam> [ConstParamsMut] {
+ ConstParamsMut(self.params.iter_mut())
+ }
+ }
+
+ /// Initializes an empty `where`-clause if there is not one present already.
+ pub fn make_where_clause(&mut self) -> &mut WhereClause {
+ self.where_clause.get_or_insert_with(|| WhereClause {
+ where_token: <Token![where]>::default(),
+ predicates: Punctuated::new(),
+ })
+ }
+
+ /// Split a type's generics into the pieces required for impl'ing a trait
+ /// for that type.
+ ///
+ /// ```
+ /// # use proc_macro2::{Span, Ident};
+ /// # use quote::quote;
+ /// #
+ /// # let generics: syn::Generics = Default::default();
+ /// # let name = Ident::new("MyType", Span::call_site());
+ /// #
+ /// let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+ /// quote! {
+ /// impl #impl_generics MyTrait for #name #ty_generics #where_clause {
+ /// // ...
+ /// }
+ /// }
+ /// # ;
+ /// ```
+ #[cfg(feature = "printing")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ pub fn split_for_impl(&self) -> (ImplGenerics, TypeGenerics, Option<&WhereClause>) {
+ (
+ ImplGenerics(self),
+ TypeGenerics(self),
+ self.where_clause.as_ref(),
+ )
+ }
+}
+
+pub struct Lifetimes<'a>(Iter<'a, GenericParam>);
+
+impl<'a> Iterator for Lifetimes<'a> {
+ type Item = &'a LifetimeParam;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ if let GenericParam::Lifetime(lifetime) = self.0.next()? {
+ Some(lifetime)
+ } else {
+ self.next()
+ }
+ }
+}
+
+pub struct LifetimesMut<'a>(IterMut<'a, GenericParam>);
+
+impl<'a> Iterator for LifetimesMut<'a> {
+ type Item = &'a mut LifetimeParam;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ if let GenericParam::Lifetime(lifetime) = self.0.next()? {
+ Some(lifetime)
+ } else {
+ self.next()
+ }
+ }
+}
+
+pub struct TypeParams<'a>(Iter<'a, GenericParam>);
+
+impl<'a> Iterator for TypeParams<'a> {
+ type Item = &'a TypeParam;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ if let GenericParam::Type(type_param) = self.0.next()? {
+ Some(type_param)
+ } else {
+ self.next()
+ }
+ }
+}
+
+pub struct TypeParamsMut<'a>(IterMut<'a, GenericParam>);
+
+impl<'a> Iterator for TypeParamsMut<'a> {
+ type Item = &'a mut TypeParam;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ if let GenericParam::Type(type_param) = self.0.next()? {
+ Some(type_param)
+ } else {
+ self.next()
+ }
+ }
+}
+
+pub struct ConstParams<'a>(Iter<'a, GenericParam>);
+
+impl<'a> Iterator for ConstParams<'a> {
+ type Item = &'a ConstParam;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ if let GenericParam::Const(const_param) = self.0.next()? {
+ Some(const_param)
+ } else {
+ self.next()
+ }
+ }
+}
+
+pub struct ConstParamsMut<'a>(IterMut<'a, GenericParam>);
+
+impl<'a> Iterator for ConstParamsMut<'a> {
+ type Item = &'a mut ConstParam;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ if let GenericParam::Const(const_param) = self.0.next()? {
+ Some(const_param)
+ } else {
+ self.next()
+ }
+ }
+}
+
+/// Returned by `Generics::split_for_impl`.
+#[cfg(feature = "printing")]
+#[cfg_attr(
+ docsrs,
+ doc(cfg(all(any(feature = "full", feature = "derive"), feature = "printing")))
+)]
+pub struct ImplGenerics<'a>(&'a Generics);
+
+/// Returned by `Generics::split_for_impl`.
+#[cfg(feature = "printing")]
+#[cfg_attr(
+ docsrs,
+ doc(cfg(all(any(feature = "full", feature = "derive"), feature = "printing")))
+)]
+pub struct TypeGenerics<'a>(&'a Generics);
+
+/// Returned by `TypeGenerics::as_turbofish`.
+#[cfg(feature = "printing")]
+#[cfg_attr(
+ docsrs,
+ doc(cfg(all(any(feature = "full", feature = "derive"), feature = "printing")))
+)]
+pub struct Turbofish<'a>(&'a Generics);
+
+#[cfg(feature = "printing")]
+macro_rules! generics_wrapper_impls {
+ ($ty:ident) => {
+ #[cfg(feature = "clone-impls")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+ impl<'a> Clone for $ty<'a> {
+ fn clone(&self) -> Self {
+ $ty(self.0)
+ }
+ }
+
+ #[cfg(feature = "extra-traits")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+ impl<'a> Debug for $ty<'a> {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter
+ .debug_tuple(stringify!($ty))
+ .field(self.0)
+ .finish()
+ }
+ }
+
+ #[cfg(feature = "extra-traits")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+ impl<'a> Eq for $ty<'a> {}
+
+ #[cfg(feature = "extra-traits")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+ impl<'a> PartialEq for $ty<'a> {
+ fn eq(&self, other: &Self) -> bool {
+ self.0 == other.0
+ }
+ }
+
+ #[cfg(feature = "extra-traits")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+ impl<'a> Hash for $ty<'a> {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ self.0.hash(state);
+ }
+ }
+ };
+}
+
+#[cfg(feature = "printing")]
+generics_wrapper_impls!(ImplGenerics);
+#[cfg(feature = "printing")]
+generics_wrapper_impls!(TypeGenerics);
+#[cfg(feature = "printing")]
+generics_wrapper_impls!(Turbofish);
+
+#[cfg(feature = "printing")]
+impl<'a> TypeGenerics<'a> {
+ /// Turn a type's generics like `<X, Y>` into a turbofish like `::<X, Y>`.
+ pub fn as_turbofish(&self) -> Turbofish<'a> {
+ Turbofish(self.0)
+ }
+}
+
+ast_struct! {
+ /// A set of bound lifetimes: `for<'a, 'b, 'c>`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct BoundLifetimes {
+ pub for_token: Token![for],
+ pub lt_token: Token![<],
+ pub lifetimes: Punctuated<GenericParam, Token![,]>,
+ pub gt_token: Token![>],
+ }
+}
+
+impl Default for BoundLifetimes {
+ fn default() -> Self {
+ BoundLifetimes {
+ for_token: Default::default(),
+ lt_token: Default::default(),
+ lifetimes: Punctuated::new(),
+ gt_token: Default::default(),
+ }
+ }
+}
+
+impl LifetimeParam {
+ pub fn new(lifetime: Lifetime) -> Self {
+ LifetimeParam {
+ attrs: Vec::new(),
+ lifetime,
+ colon_token: None,
+ bounds: Punctuated::new(),
+ }
+ }
+}
+
+impl From<Ident> for TypeParam {
+ fn from(ident: Ident) -> Self {
+ TypeParam {
+ attrs: vec![],
+ ident,
+ colon_token: None,
+ bounds: Punctuated::new(),
+ eq_token: None,
+ default: None,
+ }
+ }
+}
+
+ast_enum_of_structs! {
+ /// A trait or lifetime used as a bound on a type parameter.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ #[non_exhaustive]
+ pub enum TypeParamBound {
+ Trait(TraitBound),
+ Lifetime(Lifetime),
+ PreciseCapture(PreciseCapture),
+ Verbatim(TokenStream),
+ }
+}
+
+ast_struct! {
+ /// A trait used as a bound on a type parameter.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct TraitBound {
+ pub paren_token: Option<token::Paren>,
+ pub modifier: TraitBoundModifier,
+ /// The `for<'a>` in `for<'a> Foo<&'a T>`
+ pub lifetimes: Option<BoundLifetimes>,
+ /// The `Foo<&'a T>` in `for<'a> Foo<&'a T>`
+ pub path: Path,
+ }
+}
+
+ast_enum! {
+ /// A modifier on a trait bound, currently only used for the `?` in
+ /// `?Sized`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub enum TraitBoundModifier {
+ None,
+ Maybe(Token![?]),
+ }
+}
+
+ast_struct! {
+ /// Precise capturing bound: the 'use<…>' in `impl Trait +
+ /// use<'a, T>`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct PreciseCapture #full {
+ pub use_token: Token![use],
+ pub lt_token: Token![<],
+ pub params: Punctuated<CapturedParam, Token![,]>,
+ pub gt_token: Token![>],
+ }
+}
+
+#[cfg(feature = "full")]
+ast_enum! {
+ /// Single parameter in a precise capturing bound.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ #[non_exhaustive]
+ pub enum CapturedParam {
+ /// A lifetime parameter in precise capturing bound: `fn f<'a>() -> impl
+ /// Trait + use<'a>`.
+ Lifetime(Lifetime),
+ /// A type parameter or const generic parameter in precise capturing
+ /// bound: `fn f<T>() -> impl Trait + use<T>` or `fn f<const K: T>() ->
+ /// impl Trait + use<K>`.
+ Ident(Ident),
+ }
+}
+
+ast_struct! {
+ /// A `where` clause in a definition: `where T: Deserialize<'de>, D:
+ /// 'static`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct WhereClause {
+ pub where_token: Token![where],
+ pub predicates: Punctuated<WherePredicate, Token![,]>,
+ }
+}
+
+ast_enum_of_structs! {
+ /// A single predicate in a `where` clause: `T: Deserialize<'de>`.
+ ///
+ /// # 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"))))]
+ #[non_exhaustive]
+ pub enum WherePredicate {
+ /// A lifetime predicate in a `where` clause: `'a: 'b + 'c`.
+ Lifetime(PredicateLifetime),
+
+ /// A type predicate in a `where` clause: `for<'c> Foo<'c>: Trait<'c>`.
+ Type(PredicateType),
+ }
+}
+
+ast_struct! {
+ /// A lifetime predicate in a `where` clause: `'a: 'b + 'c`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct PredicateLifetime {
+ pub lifetime: Lifetime,
+ pub colon_token: Token![:],
+ pub bounds: Punctuated<Lifetime, Token![+]>,
+ }
+}
+
+ast_struct! {
+ /// A type predicate in a `where` clause: `for<'c> Foo<'c>: Trait<'c>`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct PredicateType {
+ /// Any lifetimes from a `for` binding
+ pub lifetimes: Option<BoundLifetimes>,
+ /// The type being bounded
+ pub bounded_ty: Type,
+ pub colon_token: Token![:],
+ /// Trait and lifetime bounds (`Clone+Send+'static`)
+ pub bounds: Punctuated<TypeParamBound, Token![+]>,
+ }
+}
+
+#[cfg(feature = "parsing")]
+pub(crate) mod parsing {
+ use crate::attr::Attribute;
+ #[cfg(feature = "full")]
+ use crate::error;
+ use crate::error::{Error, Result};
+ use crate::ext::IdentExt as _;
+ use crate::generics::{
+ BoundLifetimes, ConstParam, GenericParam, Generics, LifetimeParam, PredicateLifetime,
+ PredicateType, TraitBound, TraitBoundModifier, TypeParam, TypeParamBound, WhereClause,
+ WherePredicate,
+ };
+ #[cfg(feature = "full")]
+ use crate::generics::{CapturedParam, PreciseCapture};
+ use crate::ident::Ident;
+ use crate::lifetime::Lifetime;
+ use crate::parse::{Parse, ParseStream};
+ use crate::path::{self, ParenthesizedGenericArguments, Path, PathArguments};
+ use crate::punctuated::Punctuated;
+ use crate::token;
+ use crate::ty::Type;
+ use crate::verbatim;
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for Generics {
+ fn parse(input: ParseStream) -> Result<Self> {
+ if !input.peek(Token![<]) {
+ return Ok(Generics::default());
+ }
+
+ let lt_token: Token![<] = input.parse()?;
+
+ let mut params = Punctuated::new();
+ loop {
+ if input.peek(Token![>]) {
+ break;
+ }
+
+ let attrs = input.call(Attribute::parse_outer)?;
+ let lookahead = input.lookahead1();
+ if lookahead.peek(Lifetime) {
+ params.push_value(GenericParam::Lifetime(LifetimeParam {
+ attrs,
+ ..input.parse()?
+ }));
+ } else if lookahead.peek(Ident) {
+ params.push_value(GenericParam::Type(TypeParam {
+ attrs,
+ ..input.parse()?
+ }));
+ } else if lookahead.peek(Token![const]) {
+ params.push_value(GenericParam::Const(ConstParam {
+ attrs,
+ ..input.parse()?
+ }));
+ } else if input.peek(Token![_]) {
+ params.push_value(GenericParam::Type(TypeParam {
+ attrs,
+ ident: input.call(Ident::parse_any)?,
+ colon_token: None,
+ bounds: Punctuated::new(),
+ eq_token: None,
+ default: None,
+ }));
+ } else {
+ return Err(lookahead.error());
+ }
+
+ if input.peek(Token![>]) {
+ break;
+ }
+ let punct = input.parse()?;
+ params.push_punct(punct);
+ }
+
+ let gt_token: Token![>] = input.parse()?;
+
+ Ok(Generics {
+ lt_token: Some(lt_token),
+ params,
+ gt_token: Some(gt_token),
+ where_clause: None,
+ })
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for GenericParam {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let attrs = input.call(Attribute::parse_outer)?;
+
+ let lookahead = input.lookahead1();
+ if lookahead.peek(Ident) {
+ Ok(GenericParam::Type(TypeParam {
+ attrs,
+ ..input.parse()?
+ }))
+ } else if lookahead.peek(Lifetime) {
+ Ok(GenericParam::Lifetime(LifetimeParam {
+ attrs,
+ ..input.parse()?
+ }))
+ } else if lookahead.peek(Token![const]) {
+ Ok(GenericParam::Const(ConstParam {
+ attrs,
+ ..input.parse()?
+ }))
+ } else {
+ Err(lookahead.error())
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for LifetimeParam {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let has_colon;
+ Ok(LifetimeParam {
+ attrs: input.call(Attribute::parse_outer)?,
+ lifetime: input.parse()?,
+ colon_token: {
+ if input.peek(Token![:]) {
+ has_colon = true;
+ Some(input.parse()?)
+ } else {
+ has_colon = false;
+ None
+ }
+ },
+ bounds: {
+ let mut bounds = Punctuated::new();
+ if has_colon {
+ loop {
+ if input.peek(Token![,]) || input.peek(Token![>]) {
+ break;
+ }
+ let value = input.parse()?;
+ bounds.push_value(value);
+ if !input.peek(Token![+]) {
+ break;
+ }
+ let punct = input.parse()?;
+ bounds.push_punct(punct);
+ }
+ }
+ bounds
+ },
+ })
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for BoundLifetimes {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Ok(BoundLifetimes {
+ for_token: input.parse()?,
+ lt_token: input.parse()?,
+ lifetimes: {
+ let mut lifetimes = Punctuated::new();
+ while !input.peek(Token![>]) {
+ lifetimes.push_value(input.parse()?);
+ if input.peek(Token![>]) {
+ break;
+ }
+ lifetimes.push_punct(input.parse()?);
+ }
+ lifetimes
+ },
+ gt_token: input.parse()?,
+ })
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for Option<BoundLifetimes> {
+ fn parse(input: ParseStream) -> Result<Self> {
+ if input.peek(Token![for]) {
+ input.parse().map(Some)
+ } else {
+ Ok(None)
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for TypeParam {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let attrs = input.call(Attribute::parse_outer)?;
+ let ident: Ident = input.parse()?;
+ let colon_token: Option<Token![:]> = input.parse()?;
+
+ let mut bounds = Punctuated::new();
+ if colon_token.is_some() {
+ loop {
+ if input.peek(Token![,]) || input.peek(Token![>]) || input.peek(Token![=]) {
+ break;
+ }
+ bounds.push_value({
+ let allow_precise_capture = false;
+ let allow_const = true;
+ TypeParamBound::parse_single(input, allow_precise_capture, allow_const)?
+ });
+ if !input.peek(Token![+]) {
+ break;
+ }
+ let punct: Token![+] = input.parse()?;
+ bounds.push_punct(punct);
+ }
+ }
+
+ let eq_token: Option<Token![=]> = input.parse()?;
+ let default = if eq_token.is_some() {
+ Some(input.parse::<Type>()?)
+ } else {
+ None
+ };
+
+ Ok(TypeParam {
+ attrs,
+ ident,
+ colon_token,
+ bounds,
+ eq_token,
+ default,
+ })
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for TypeParamBound {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let allow_precise_capture = true;
+ let allow_const = true;
+ Self::parse_single(input, allow_precise_capture, allow_const)
+ }
+ }
+
+ impl TypeParamBound {
+ pub(crate) fn parse_single(
+ input: ParseStream,
+ #[cfg_attr(not(feature = "full"), allow(unused_variables))] allow_precise_capture: bool,
+ allow_const: bool,
+ ) -> Result<Self> {
+ if input.peek(Lifetime) {
+ return input.parse().map(TypeParamBound::Lifetime);
+ }
+
+ #[cfg(feature = "full")]
+ {
+ if input.peek(Token![use]) {
+ let precise_capture: PreciseCapture = input.parse()?;
+ return if allow_precise_capture {
+ Ok(TypeParamBound::PreciseCapture(precise_capture))
+ } else {
+ let msg = "`use<...>` precise capturing syntax is not allowed here";
+ Err(error::new2(
+ precise_capture.use_token.span,
+ precise_capture.gt_token.span,
+ msg,
+ ))
+ };
+ }
+ }
+
+ let begin = input.fork();
+
+ let content;
+ let (paren_token, content) = if input.peek(token::Paren) {
+ (Some(parenthesized!(content in input)), &content)
+ } else {
+ (None, input)
+ };
+
+ if let Some(mut bound) = TraitBound::do_parse(content, allow_const)? {
+ bound.paren_token = paren_token;
+ Ok(TypeParamBound::Trait(bound))
+ } else {
+ Ok(TypeParamBound::Verbatim(verbatim::between(&begin, input)))
+ }
+ }
+
+ pub(crate) fn parse_multiple(
+ input: ParseStream,
+ allow_plus: bool,
+ allow_precise_capture: bool,
+ allow_const: bool,
+ ) -> Result<Punctuated<Self, Token![+]>> {
+ let mut bounds = Punctuated::new();
+ loop {
+ let bound = Self::parse_single(input, allow_precise_capture, allow_const)?;
+ bounds.push_value(bound);
+ if !(allow_plus && input.peek(Token![+])) {
+ break;
+ }
+ bounds.push_punct(input.parse()?);
+ if !(input.peek(Ident::peek_any)
+ || input.peek(Token![::])
+ || input.peek(Token![?])
+ || input.peek(Lifetime)
+ || input.peek(token::Paren)
+ || (allow_const && (input.peek(token::Bracket) || input.peek(Token![const]))))
+ {
+ break;
+ }
+ }
+ Ok(bounds)
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for TraitBound {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let allow_const = false;
+ Self::do_parse(input, allow_const).map(Option::unwrap)
+ }
+ }
+
+ impl TraitBound {
+ fn do_parse(input: ParseStream, allow_const: bool) -> Result<Option<Self>> {
+ let mut lifetimes: Option<BoundLifetimes> = input.parse()?;
+
+ let is_conditionally_const = cfg!(feature = "full") && input.peek(token::Bracket);
+ let is_unconditionally_const = cfg!(feature = "full") && input.peek(Token![const]);
+ if is_conditionally_const {
+ let conditionally_const;
+ let bracket_token = bracketed!(conditionally_const in input);
+ conditionally_const.parse::<Token![const]>()?;
+ if !allow_const {
+ let msg = "`[const]` is not allowed here";
+ return Err(Error::new(bracket_token.span.join(), msg));
+ }
+ } else if is_unconditionally_const {
+ let const_token: Token![const] = input.parse()?;
+ if !allow_const {
+ let msg = "`const` is not allowed here";
+ return Err(Error::new(const_token.span, msg));
+ }
+ }
+
+ let modifier: TraitBoundModifier = input.parse()?;
+ if lifetimes.is_none() && matches!(modifier, TraitBoundModifier::Maybe(_)) {
+ lifetimes = input.parse()?;
+ }
+
+ let mut path: Path = input.parse()?;
+ if path.segments.last().unwrap().arguments.is_empty()
+ && (input.peek(token::Paren) || input.peek(Token![::]) && input.peek3(token::Paren))
+ {
+ input.parse::<Option<Token![::]>>()?;
+ let args: ParenthesizedGenericArguments = input.parse()?;
+ let parenthesized = PathArguments::Parenthesized(args);
+ path.segments.last_mut().unwrap().arguments = parenthesized;
+ }
+
+ if lifetimes.is_some() {
+ match modifier {
+ TraitBoundModifier::None => {}
+ TraitBoundModifier::Maybe(maybe) => {
+ let msg = "`for<...>` binder not allowed with `?` trait polarity modifier";
+ return Err(Error::new(maybe.span, msg));
+ }
+ }
+ }
+
+ if is_conditionally_const || is_unconditionally_const {
+ Ok(None)
+ } else {
+ Ok(Some(TraitBound {
+ paren_token: None,
+ modifier,
+ lifetimes,
+ path,
+ }))
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for TraitBoundModifier {
+ fn parse(input: ParseStream) -> Result<Self> {
+ if input.peek(Token![?]) {
+ input.parse().map(TraitBoundModifier::Maybe)
+ } else {
+ Ok(TraitBoundModifier::None)
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ConstParam {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let mut default = None;
+ Ok(ConstParam {
+ attrs: input.call(Attribute::parse_outer)?,
+ const_token: input.parse()?,
+ ident: input.parse()?,
+ colon_token: input.parse()?,
+ ty: input.parse()?,
+ eq_token: {
+ if input.peek(Token![=]) {
+ let eq_token = input.parse()?;
+ default = Some(path::parsing::const_argument(input)?);
+ Some(eq_token)
+ } else {
+ None
+ }
+ },
+ default,
+ })
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for WhereClause {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let where_token: Token![where] = input.parse()?;
+
+ if choose_generics_over_qpath(input) {
+ return Err(input
+ .error("generic parameters on `where` clauses are reserved for future use"));
+ }
+
+ Ok(WhereClause {
+ where_token,
+ predicates: {
+ let mut predicates = Punctuated::new();
+ loop {
+ if input.is_empty()
+ || input.peek(token::Brace)
+ || input.peek(Token![,])
+ || input.peek(Token![;])
+ || input.peek(Token![:]) && !input.peek(Token![::])
+ || input.peek(Token![=])
+ {
+ break;
+ }
+ let value = input.parse()?;
+ predicates.push_value(value);
+ if !input.peek(Token![,]) {
+ break;
+ }
+ let punct = input.parse()?;
+ predicates.push_punct(punct);
+ }
+ predicates
+ },
+ })
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for Option<WhereClause> {
+ fn parse(input: ParseStream) -> Result<Self> {
+ if input.peek(Token![where]) {
+ input.parse().map(Some)
+ } else {
+ Ok(None)
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for WherePredicate {
+ fn parse(input: ParseStream) -> Result<Self> {
+ if input.peek(Lifetime) && input.peek2(Token![:]) {
+ Ok(WherePredicate::Lifetime(PredicateLifetime {
+ lifetime: input.parse()?,
+ colon_token: input.parse()?,
+ bounds: {
+ let mut bounds = Punctuated::new();
+ loop {
+ if input.is_empty()
+ || input.peek(token::Brace)
+ || input.peek(Token![,])
+ || input.peek(Token![;])
+ || input.peek(Token![:])
+ || input.peek(Token![=])
+ {
+ break;
+ }
+ let value = input.parse()?;
+ bounds.push_value(value);
+ if !input.peek(Token![+]) {
+ break;
+ }
+ let punct = input.parse()?;
+ bounds.push_punct(punct);
+ }
+ bounds
+ },
+ }))
+ } else {
+ Ok(WherePredicate::Type(PredicateType {
+ lifetimes: input.parse()?,
+ bounded_ty: input.parse()?,
+ colon_token: input.parse()?,
+ bounds: {
+ let mut bounds = Punctuated::new();
+ loop {
+ if input.is_empty()
+ || input.peek(token::Brace)
+ || input.peek(Token![,])
+ || input.peek(Token![;])
+ || input.peek(Token![:]) && !input.peek(Token![::])
+ || input.peek(Token![=])
+ {
+ break;
+ }
+ bounds.push_value({
+ let allow_precise_capture = false;
+ let allow_const = true;
+ TypeParamBound::parse_single(
+ input,
+ allow_precise_capture,
+ allow_const,
+ )?
+ });
+ if !input.peek(Token![+]) {
+ break;
+ }
+ let punct = input.parse()?;
+ bounds.push_punct(punct);
+ }
+ bounds
+ },
+ }))
+ }
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for PreciseCapture {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let use_token: Token![use] = input.parse()?;
+ let lt_token: Token![<] = input.parse()?;
+ let mut params = Punctuated::new();
+ loop {
+ let lookahead = input.lookahead1();
+ params.push_value(
+ if lookahead.peek(Lifetime) || lookahead.peek(Ident) || input.peek(Token![Self])
+ {
+ input.parse::<CapturedParam>()?
+ } else if lookahead.peek(Token![>]) {
+ break;
+ } else {
+ return Err(lookahead.error());
+ },
+ );
+ let lookahead = input.lookahead1();
+ params.push_punct(if lookahead.peek(Token![,]) {
+ input.parse::<Token![,]>()?
+ } else if lookahead.peek(Token![>]) {
+ break;
+ } else {
+ return Err(lookahead.error());
+ });
+ }
+ let gt_token: Token![>] = input.parse()?;
+ Ok(PreciseCapture {
+ use_token,
+ lt_token,
+ params,
+ gt_token,
+ })
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for CapturedParam {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let lookahead = input.lookahead1();
+ if lookahead.peek(Lifetime) {
+ input.parse().map(CapturedParam::Lifetime)
+ } else if lookahead.peek(Ident) || input.peek(Token![Self]) {
+ input.call(Ident::parse_any).map(CapturedParam::Ident)
+ } else {
+ Err(lookahead.error())
+ }
+ }
+ }
+
+ pub(crate) fn choose_generics_over_qpath(input: ParseStream) -> bool {
+ // Rust syntax has an ambiguity between generic parameters and qualified
+ // paths. In `impl <T> :: Thing<T, U> {}` this may either be a generic
+ // inherent impl `impl<T> ::Thing<T, U>` or a non-generic inherent impl
+ // for an associated type `impl <T>::Thing<T, U>`.
+ //
+ // After `<` the following continuations can only begin generics, not a
+ // qualified path:
+ //
+ // `<` `>` - empty generic parameters
+ // `<` `#` - generic parameters with attribute
+ // `<` LIFETIME `>` - single lifetime parameter
+ // `<` (LIFETIME|IDENT) `,` - first generic parameter in a list
+ // `<` (LIFETIME|IDENT) `:` - generic parameter with bounds
+ // `<` (LIFETIME|IDENT) `=` - generic parameter with a default
+ // `<` const - generic const parameter
+ //
+ // The only truly ambiguous case is:
+ //
+ // `<` IDENT `>` `::` IDENT ...
+ //
+ // which we disambiguate in favor of generics because this is almost
+ // always the expected one in the context of real-world code.
+ input.peek(Token![<])
+ && (input.peek2(Token![>])
+ || input.peek2(Token![#])
+ || (input.peek2(Lifetime) || input.peek2(Ident))
+ && (input.peek3(Token![>])
+ || input.peek3(Token![,])
+ || input.peek3(Token![:]) && !input.peek3(Token![::])
+ || input.peek3(Token![=]))
+ || input.peek2(Token![const]))
+ }
+
+ #[cfg(feature = "full")]
+ pub(crate) fn choose_generics_over_qpath_after_keyword(input: ParseStream) -> bool {
+ let input = input.fork();
+ input.call(Ident::parse_any).unwrap(); // `impl` or `for` or `where`
+ choose_generics_over_qpath(&input)
+ }
+}
+
+#[cfg(feature = "printing")]
+pub(crate) mod printing {
+ use crate::attr::FilterAttrs;
+ #[cfg(feature = "full")]
+ use crate::expr;
+ use crate::expr::Expr;
+ #[cfg(feature = "full")]
+ use crate::fixup::FixupContext;
+ use crate::generics::{
+ BoundLifetimes, ConstParam, GenericParam, Generics, ImplGenerics, LifetimeParam,
+ PredicateLifetime, PredicateType, TraitBound, TraitBoundModifier, Turbofish, TypeGenerics,
+ TypeParam, WhereClause,
+ };
+ #[cfg(feature = "full")]
+ use crate::generics::{CapturedParam, PreciseCapture};
+ use crate::print::TokensOrDefault;
+ use crate::token;
+ use proc_macro2::TokenStream;
+ use quote::{ToTokens, TokenStreamExt};
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for Generics {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ if self.params.is_empty() {
+ return;
+ }
+
+ TokensOrDefault(&self.lt_token).to_tokens(tokens);
+
+ // Print lifetimes before types and consts, regardless of their
+ // order in self.params.
+ let mut trailing_or_empty = true;
+ for param in self.params.pairs() {
+ if let GenericParam::Lifetime(_) = **param.value() {
+ param.to_tokens(tokens);
+ trailing_or_empty = param.punct().is_some();
+ }
+ }
+ for param in self.params.pairs() {
+ match param.value() {
+ GenericParam::Type(_) | GenericParam::Const(_) => {
+ if !trailing_or_empty {
+ <Token![,]>::default().to_tokens(tokens);
+ trailing_or_empty = true;
+ }
+ param.to_tokens(tokens);
+ }
+ GenericParam::Lifetime(_) => {}
+ }
+ }
+
+ TokensOrDefault(&self.gt_token).to_tokens(tokens);
+ }
+ }
+
+ impl<'a> ToTokens for ImplGenerics<'a> {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ if self.0.params.is_empty() {
+ return;
+ }
+
+ TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
+
+ // Print lifetimes before types and consts, regardless of their
+ // order in self.params.
+ let mut trailing_or_empty = true;
+ for param in self.0.params.pairs() {
+ if let GenericParam::Lifetime(_) = **param.value() {
+ param.to_tokens(tokens);
+ trailing_or_empty = param.punct().is_some();
+ }
+ }
+ for param in self.0.params.pairs() {
+ if let GenericParam::Lifetime(_) = **param.value() {
+ continue;
+ }
+ if !trailing_or_empty {
+ <Token![,]>::default().to_tokens(tokens);
+ trailing_or_empty = true;
+ }
+ match param.value() {
+ GenericParam::Lifetime(_) => unreachable!(),
+ GenericParam::Type(param) => {
+ // Leave off the type parameter defaults
+ tokens.append_all(param.attrs.outer());
+ param.ident.to_tokens(tokens);
+ if !param.bounds.is_empty() {
+ TokensOrDefault(¶m.colon_token).to_tokens(tokens);
+ param.bounds.to_tokens(tokens);
+ }
+ }
+ GenericParam::Const(param) => {
+ // Leave off the const parameter defaults
+ tokens.append_all(param.attrs.outer());
+ param.const_token.to_tokens(tokens);
+ param.ident.to_tokens(tokens);
+ param.colon_token.to_tokens(tokens);
+ param.ty.to_tokens(tokens);
+ }
+ }
+ param.punct().to_tokens(tokens);
+ }
+
+ TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
+ }
+ }
+
+ impl<'a> ToTokens for TypeGenerics<'a> {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ if self.0.params.is_empty() {
+ return;
+ }
+
+ TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
+
+ // Print lifetimes before types and consts, regardless of their
+ // order in self.params.
+ let mut trailing_or_empty = true;
+ for param in self.0.params.pairs() {
+ if let GenericParam::Lifetime(def) = *param.value() {
+ // Leave off the lifetime bounds and attributes
+ def.lifetime.to_tokens(tokens);
+ param.punct().to_tokens(tokens);
+ trailing_or_empty = param.punct().is_some();
+ }
+ }
+ for param in self.0.params.pairs() {
+ if let GenericParam::Lifetime(_) = **param.value() {
+ continue;
+ }
+ if !trailing_or_empty {
+ <Token![,]>::default().to_tokens(tokens);
+ trailing_or_empty = true;
+ }
+ match param.value() {
+ GenericParam::Lifetime(_) => unreachable!(),
+ GenericParam::Type(param) => {
+ // Leave off the type parameter defaults
+ param.ident.to_tokens(tokens);
+ }
+ GenericParam::Const(param) => {
+ // Leave off the const parameter defaults
+ param.ident.to_tokens(tokens);
+ }
+ }
+ param.punct().to_tokens(tokens);
+ }
+
+ TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
+ }
+ }
+
+ impl<'a> ToTokens for Turbofish<'a> {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ if !self.0.params.is_empty() {
+ <Token![::]>::default().to_tokens(tokens);
+ TypeGenerics(self.0).to_tokens(tokens);
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for BoundLifetimes {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.for_token.to_tokens(tokens);
+ self.lt_token.to_tokens(tokens);
+ self.lifetimes.to_tokens(tokens);
+ self.gt_token.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for LifetimeParam {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.lifetime.to_tokens(tokens);
+ if !self.bounds.is_empty() {
+ TokensOrDefault(&self.colon_token).to_tokens(tokens);
+ self.bounds.to_tokens(tokens);
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for TypeParam {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.ident.to_tokens(tokens);
+ if !self.bounds.is_empty() {
+ TokensOrDefault(&self.colon_token).to_tokens(tokens);
+ self.bounds.to_tokens(tokens);
+ }
+ if let Some(default) = &self.default {
+ TokensOrDefault(&self.eq_token).to_tokens(tokens);
+ default.to_tokens(tokens);
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for TraitBound {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ let to_tokens = |tokens: &mut TokenStream| {
+ self.modifier.to_tokens(tokens);
+ self.lifetimes.to_tokens(tokens);
+ self.path.to_tokens(tokens);
+ };
+ match &self.paren_token {
+ Some(paren) => paren.surround(tokens, to_tokens),
+ None => to_tokens(tokens),
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for TraitBoundModifier {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ match self {
+ TraitBoundModifier::None => {}
+ TraitBoundModifier::Maybe(t) => t.to_tokens(tokens),
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ConstParam {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.const_token.to_tokens(tokens);
+ self.ident.to_tokens(tokens);
+ self.colon_token.to_tokens(tokens);
+ self.ty.to_tokens(tokens);
+ if let Some(default) = &self.default {
+ TokensOrDefault(&self.eq_token).to_tokens(tokens);
+ print_const_argument(default, tokens);
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for WhereClause {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ if !self.predicates.is_empty() {
+ self.where_token.to_tokens(tokens);
+ self.predicates.to_tokens(tokens);
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for PredicateLifetime {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.lifetime.to_tokens(tokens);
+ self.colon_token.to_tokens(tokens);
+ self.bounds.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for PredicateType {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.lifetimes.to_tokens(tokens);
+ self.bounded_ty.to_tokens(tokens);
+ self.colon_token.to_tokens(tokens);
+ self.bounds.to_tokens(tokens);
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for PreciseCapture {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.use_token.to_tokens(tokens);
+ self.lt_token.to_tokens(tokens);
+
+ // Print lifetimes before types and consts, regardless of their
+ // order in self.params.
+ let mut trailing_or_empty = true;
+ for param in self.params.pairs() {
+ if let CapturedParam::Lifetime(_) = **param.value() {
+ param.to_tokens(tokens);
+ trailing_or_empty = param.punct().is_some();
+ }
+ }
+ for param in self.params.pairs() {
+ if let CapturedParam::Ident(_) = **param.value() {
+ if !trailing_or_empty {
+ <Token![,]>::default().to_tokens(tokens);
+ trailing_or_empty = true;
+ }
+ param.to_tokens(tokens);
+ }
+ }
+
+ self.gt_token.to_tokens(tokens);
+ }
+ }
+
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for CapturedParam {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ match self {
+ CapturedParam::Lifetime(lifetime) => lifetime.to_tokens(tokens),
+ CapturedParam::Ident(ident) => ident.to_tokens(tokens),
+ }
+ }
+ }
+
+ pub(crate) fn print_const_argument(expr: &Expr, tokens: &mut TokenStream) {
+ match expr {
+ Expr::Lit(expr) => expr.to_tokens(tokens),
+
+ Expr::Path(expr)
+ if expr.attrs.is_empty()
+ && expr.qself.is_none()
+ && expr.path.get_ident().is_some() =>
+ {
+ expr.to_tokens(tokens);
+ }
+
+ #[cfg(feature = "full")]
+ Expr::Block(expr) => expr.to_tokens(tokens),
+
+ #[cfg(not(feature = "full"))]
+ Expr::Verbatim(expr) => expr.to_tokens(tokens),
+
+ // ERROR CORRECTION: Add braces to make sure that the
+ // generated code is valid.
+ _ => token::Brace::default().surround(tokens, |tokens| {
+ #[cfg(feature = "full")]
+ expr::printing::print_expr(expr, tokens, FixupContext::new_stmt());
+
+ #[cfg(not(feature = "full"))]
+ expr.to_tokens(tokens);
+ }),
+ }
+ }
+}
diff --git a/rust/syn/group.rs b/rust/syn/group.rs
new file mode 100644
index 000000000000..1534ae995dd5
--- /dev/null
+++ b/rust/syn/group.rs
@@ -0,0 +1,291 @@
+use crate::error::Result;
+use crate::parse::ParseBuffer;
+use crate::token;
+use proc_macro2::extra::DelimSpan;
+use proc_macro2::Delimiter;
+
+// Not public API.
+#[doc(hidden)]
+pub struct Parens<'a> {
+ #[doc(hidden)]
+ pub token: token::Paren,
+ #[doc(hidden)]
+ pub content: ParseBuffer<'a>,
+}
+
+// Not public API.
+#[doc(hidden)]
+pub struct Braces<'a> {
+ #[doc(hidden)]
+ pub token: token::Brace,
+ #[doc(hidden)]
+ pub content: ParseBuffer<'a>,
+}
+
+// Not public API.
+#[doc(hidden)]
+pub struct Brackets<'a> {
+ #[doc(hidden)]
+ pub token: token::Bracket,
+ #[doc(hidden)]
+ pub content: ParseBuffer<'a>,
+}
+
+// Not public API.
+#[cfg(any(feature = "full", feature = "derive"))]
+#[doc(hidden)]
+pub struct Group<'a> {
+ #[doc(hidden)]
+ pub token: token::Group,
+ #[doc(hidden)]
+ pub content: ParseBuffer<'a>,
+}
+
+// Not public API.
+#[doc(hidden)]
+pub fn parse_parens<'a>(input: &ParseBuffer<'a>) -> Result<Parens<'a>> {
+ parse_delimited(input, Delimiter::Parenthesis).map(|(span, content)| Parens {
+ token: token::Paren(span),
+ content,
+ })
+}
+
+// Not public API.
+#[doc(hidden)]
+pub fn parse_braces<'a>(input: &ParseBuffer<'a>) -> Result<Braces<'a>> {
+ parse_delimited(input, Delimiter::Brace).map(|(span, content)| Braces {
+ token: token::Brace(span),
+ content,
+ })
+}
+
+// Not public API.
+#[doc(hidden)]
+pub fn parse_brackets<'a>(input: &ParseBuffer<'a>) -> Result<Brackets<'a>> {
+ parse_delimited(input, Delimiter::Bracket).map(|(span, content)| Brackets {
+ token: token::Bracket(span),
+ content,
+ })
+}
+
+#[cfg(any(feature = "full", feature = "derive"))]
+pub(crate) fn parse_group<'a>(input: &ParseBuffer<'a>) -> Result<Group<'a>> {
+ parse_delimited(input, Delimiter::None).map(|(span, content)| Group {
+ token: token::Group(span.join()),
+ content,
+ })
+}
+
+fn parse_delimited<'a>(
+ input: &ParseBuffer<'a>,
+ delimiter: Delimiter,
+) -> Result<(DelimSpan, ParseBuffer<'a>)> {
+ input.step(|cursor| {
+ if let Some((content, span, rest)) = cursor.group(delimiter) {
+ let scope = span.close();
+ let nested = crate::parse::advance_step_cursor(cursor, content);
+ let unexpected = crate::parse::get_unexpected(input);
+ let content = crate::parse::new_parse_buffer(scope, nested, unexpected);
+ Ok(((span, content), rest))
+ } else {
+ let message = match delimiter {
+ Delimiter::Parenthesis => "expected parentheses",
+ Delimiter::Brace => "expected curly braces",
+ Delimiter::Bracket => "expected square brackets",
+ Delimiter::None => "expected invisible group",
+ };
+ Err(cursor.error(message))
+ }
+ })
+}
+
+/// Parse a set of parentheses and expose their content to subsequent parsers.
+///
+/// # Example
+///
+/// ```
+/// # use quote::quote;
+/// #
+/// use syn::{parenthesized, token, Ident, Result, Token, Type};
+/// use syn::parse::{Parse, ParseStream};
+/// use syn::punctuated::Punctuated;
+///
+/// // Parse a simplified tuple struct syntax like:
+/// //
+/// // struct S(A, B);
+/// struct TupleStruct {
+/// struct_token: Token![struct],
+/// ident: Ident,
+/// paren_token: token::Paren,
+/// fields: Punctuated<Type, Token![,]>,
+/// semi_token: Token![;],
+/// }
+///
+/// impl Parse for TupleStruct {
+/// fn parse(input: ParseStream) -> Result<Self> {
+/// let content;
+/// Ok(TupleStruct {
+/// struct_token: input.parse()?,
+/// ident: input.parse()?,
+/// paren_token: parenthesized!(content in input),
+/// fields: content.parse_terminated(Type::parse, Token![,])?,
+/// semi_token: input.parse()?,
+/// })
+/// }
+/// }
+/// #
+/// # fn main() {
+/// # let input = quote! {
+/// # struct S(A, B);
+/// # };
+/// # syn::parse2::<TupleStruct>(input).unwrap();
+/// # }
+/// ```
+#[macro_export]
+#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+macro_rules! parenthesized {
+ ($content:ident in $cursor:expr) => {
+ match $crate::__private::parse_parens(&$cursor) {
+ $crate::__private::Ok(parens) => {
+ $content = parens.content;
+ parens.token
+ }
+ $crate::__private::Err(error) => {
+ return $crate::__private::Err(error);
+ }
+ }
+ };
+}
+
+/// Parse a set of curly braces and expose their content to subsequent parsers.
+///
+/// # Example
+///
+/// ```
+/// # use quote::quote;
+/// #
+/// use syn::{braced, token, Ident, Result, Token, Type};
+/// use syn::parse::{Parse, ParseStream};
+/// use syn::punctuated::Punctuated;
+///
+/// // Parse a simplified struct syntax like:
+/// //
+/// // struct S {
+/// // a: A,
+/// // b: B,
+/// // }
+/// struct Struct {
+/// struct_token: Token![struct],
+/// ident: Ident,
+/// brace_token: token::Brace,
+/// fields: Punctuated<Field, Token![,]>,
+/// }
+///
+/// struct Field {
+/// name: Ident,
+/// colon_token: Token![:],
+/// ty: Type,
+/// }
+///
+/// impl Parse for Struct {
+/// fn parse(input: ParseStream) -> Result<Self> {
+/// let content;
+/// Ok(Struct {
+/// struct_token: input.parse()?,
+/// ident: input.parse()?,
+/// brace_token: braced!(content in input),
+/// fields: content.parse_terminated(Field::parse, Token![,])?,
+/// })
+/// }
+/// }
+///
+/// impl Parse for Field {
+/// fn parse(input: ParseStream) -> Result<Self> {
+/// Ok(Field {
+/// name: input.parse()?,
+/// colon_token: input.parse()?,
+/// ty: input.parse()?,
+/// })
+/// }
+/// }
+/// #
+/// # fn main() {
+/// # let input = quote! {
+/// # struct S {
+/// # a: A,
+/// # b: B,
+/// # }
+/// # };
+/// # syn::parse2::<Struct>(input).unwrap();
+/// # }
+/// ```
+#[macro_export]
+#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+macro_rules! braced {
+ ($content:ident in $cursor:expr) => {
+ match $crate::__private::parse_braces(&$cursor) {
+ $crate::__private::Ok(braces) => {
+ $content = braces.content;
+ braces.token
+ }
+ $crate::__private::Err(error) => {
+ return $crate::__private::Err(error);
+ }
+ }
+ };
+}
+
+/// Parse a set of square brackets and expose their content to subsequent
+/// parsers.
+///
+/// # Example
+///
+/// ```
+/// # use quote::quote;
+/// #
+/// use proc_macro2::TokenStream;
+/// use syn::{bracketed, token, Result, Token};
+/// use syn::parse::{Parse, ParseStream};
+///
+/// // Parse an outer attribute like:
+/// //
+/// // #[repr(C, packed)]
+/// struct OuterAttribute {
+/// pound_token: Token![#],
+/// bracket_token: token::Bracket,
+/// content: TokenStream,
+/// }
+///
+/// impl Parse for OuterAttribute {
+/// fn parse(input: ParseStream) -> Result<Self> {
+/// let content;
+/// Ok(OuterAttribute {
+/// pound_token: input.parse()?,
+/// bracket_token: bracketed!(content in input),
+/// content: content.parse()?,
+/// })
+/// }
+/// }
+/// #
+/// # fn main() {
+/// # let input = quote! {
+/// # #[repr(C, packed)]
+/// # };
+/// # syn::parse2::<OuterAttribute>(input).unwrap();
+/// # }
+/// ```
+#[macro_export]
+#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+macro_rules! bracketed {
+ ($content:ident in $cursor:expr) => {
+ match $crate::__private::parse_brackets(&$cursor) {
+ $crate::__private::Ok(brackets) => {
+ $content = brackets.content;
+ brackets.token
+ }
+ $crate::__private::Err(error) => {
+ return $crate::__private::Err(error);
+ }
+ }
+ };
+}
diff --git a/rust/syn/ident.rs b/rust/syn/ident.rs
new file mode 100644
index 000000000000..8a8e8a50d9b0
--- /dev/null
+++ b/rust/syn/ident.rs
@@ -0,0 +1,108 @@
+#[cfg(feature = "parsing")]
+use crate::lookahead;
+
+pub use proc_macro2::Ident;
+
+#[cfg(feature = "parsing")]
+pub_if_not_doc! {
+ #[doc(hidden)]
+ #[allow(non_snake_case)]
+ pub fn Ident(marker: lookahead::TokenMarker) -> Ident {
+ match marker {}
+ }
+}
+
+macro_rules! ident_from_token {
+ ($token:ident) => {
+ impl From<Token![$token]> for Ident {
+ fn from(token: Token![$token]) -> Ident {
+ Ident::new(stringify!($token), token.span)
+ }
+ }
+ };
+}
+
+ident_from_token!(self);
+ident_from_token!(Self);
+ident_from_token!(super);
+ident_from_token!(crate);
+ident_from_token!(extern);
+
+impl From<Token![_]> for Ident {
+ fn from(token: Token![_]) -> Ident {
+ Ident::new("_", token.span)
+ }
+}
+
+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)) {
+ return false;
+ }
+ for ch in chars {
+ if !unicode_ident::is_xid_continue(ch) {
+ return false;
+ }
+ }
+ true
+}
+
+#[cfg(feature = "parsing")]
+mod parsing {
+ use crate::buffer::Cursor;
+ use crate::error::Result;
+ use crate::parse::{Parse, ParseStream};
+ use crate::token::Token;
+ use proc_macro2::Ident;
+
+ fn accept_as_ident(ident: &Ident) -> bool {
+ match ident.to_string().as_str() {
+ "_" |
+ // Based on https://doc.rust-lang.org/1.65.0/reference/keywords.html
+ "abstract" | "as" | "async" | "await" | "become" | "box" | "break" |
+ "const" | "continue" | "crate" | "do" | "dyn" | "else" | "enum" |
+ "extern" | "false" | "final" | "fn" | "for" | "if" | "impl" | "in" |
+ "let" | "loop" | "macro" | "match" | "mod" | "move" | "mut" |
+ "override" | "priv" | "pub" | "ref" | "return" | "Self" | "self" |
+ "static" | "struct" | "super" | "trait" | "true" | "try" | "type" |
+ "typeof" | "unsafe" | "unsized" | "use" | "virtual" | "where" |
+ "while" | "yield" => false,
+ _ => true,
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for Ident {
+ fn parse(input: ParseStream) -> Result<Self> {
+ input.step(|cursor| {
+ if let Some((ident, rest)) = cursor.ident() {
+ if accept_as_ident(&ident) {
+ Ok((ident, rest))
+ } else {
+ Err(cursor.error(format_args!(
+ "expected identifier, found keyword `{}`",
+ ident,
+ )))
+ }
+ } else {
+ Err(cursor.error("expected identifier"))
+ }
+ })
+ }
+ }
+
+ impl Token for Ident {
+ fn peek(cursor: Cursor) -> bool {
+ if let Some((ident, _rest)) = cursor.ident() {
+ accept_as_ident(&ident)
+ } else {
+ false
+ }
+ }
+
+ fn display() -> &'static str {
+ "identifier"
+ }
+ }
+}
diff --git a/rust/syn/item.rs b/rust/syn/item.rs
new file mode 100644
index 000000000000..1716f5137afb
--- /dev/null
+++ b/rust/syn/item.rs
@@ -0,0 +1,3490 @@
+use crate::attr::Attribute;
+use crate::data::{Fields, FieldsNamed, Variant};
+use crate::derive::{Data, DataEnum, DataStruct, DataUnion, DeriveInput};
+use crate::expr::Expr;
+use crate::generics::{Generics, TypeParamBound};
+use crate::ident::Ident;
+use crate::lifetime::Lifetime;
+use crate::mac::Macro;
+use crate::pat::{Pat, PatType};
+use crate::path::Path;
+use crate::punctuated::Punctuated;
+use crate::restriction::Visibility;
+use crate::stmt::Block;
+use crate::token;
+use crate::ty::{Abi, ReturnType, Type};
+use proc_macro2::TokenStream;
+#[cfg(feature = "parsing")]
+use std::mem;
+
+ast_enum_of_structs! {
+ /// Things that can appear directly inside of a module or scope.
+ ///
+ /// # Syntax tree enum
+ ///
+ /// This type is a [syntax tree enum].
+ ///
+ /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ #[non_exhaustive]
+ pub enum Item {
+ /// A constant item: `const MAX: u16 = 65535`.
+ Const(ItemConst),
+
+ /// An enum definition: `enum Foo<A, B> { A(A), B(B) }`.
+ Enum(ItemEnum),
+
+ /// An `extern crate` item: `extern crate serde`.
+ ExternCrate(ItemExternCrate),
+
+ /// A free-standing function: `fn process(n: usize) -> Result<()> { ...
+ /// }`.
+ Fn(ItemFn),
+
+ /// A block of foreign items: `extern "C" { ... }`.
+ ForeignMod(ItemForeignMod),
+
+ /// An impl block providing trait or associated items: `impl<A> Trait
+ /// for Data<A> { ... }`.
+ Impl(ItemImpl),
+
+ /// A macro invocation, which includes `macro_rules!` definitions.
+ Macro(ItemMacro),
+
+ /// A module or module declaration: `mod m` or `mod m { ... }`.
+ Mod(ItemMod),
+
+ /// A static item: `static BIKE: Shed = Shed(42)`.
+ Static(ItemStatic),
+
+ /// A struct definition: `struct Foo<A> { x: A }`.
+ Struct(ItemStruct),
+
+ /// A trait definition: `pub trait Iterator { ... }`.
+ Trait(ItemTrait),
+
+ /// A trait alias: `pub trait SharableIterator = Iterator + Sync`.
+ TraitAlias(ItemTraitAlias),
+
+ /// A type alias: `type Result<T> = std::result::Result<T, MyError>`.
+ Type(ItemType),
+
+ /// A union definition: `union Foo<A, B> { x: A, y: B }`.
+ Union(ItemUnion),
+
+ /// A use declaration: `use std::collections::HashMap`.
+ Use(ItemUse),
+
+ /// Tokens forming an item not interpreted by Syn.
+ Verbatim(TokenStream),
+
+ // For testing exhaustiveness in downstream code, use the following idiom:
+ //
+ // match item {
+ // #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))]
+ //
+ // Item::Const(item) => {...}
+ // Item::Enum(item) => {...}
+ // ...
+ // Item::Verbatim(item) => {...}
+ //
+ // _ => { /* some sane fallback */ }
+ // }
+ //
+ // This way we fail your tests but don't break your library when adding
+ // a variant. You will be notified by a test failure when a variant is
+ // added, so that you can add code to handle it, but your library will
+ // continue to compile and work for downstream users in the interim.
+ }
+}
+
+ast_struct! {
+ /// A constant item: `const MAX: u16 = 65535`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ItemConst {
+ pub attrs: Vec<Attribute>,
+ pub vis: Visibility,
+ pub const_token: Token![const],
+ pub ident: Ident,
+ pub generics: Generics,
+ pub colon_token: Token![:],
+ pub ty: Box<Type>,
+ pub eq_token: Token![=],
+ pub expr: Box<Expr>,
+ pub semi_token: Token![;],
+ }
+}
+
+ast_struct! {
+ /// An enum definition: `enum Foo<A, B> { A(A), B(B) }`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ItemEnum {
+ pub attrs: Vec<Attribute>,
+ pub vis: Visibility,
+ pub enum_token: Token![enum],
+ pub ident: Ident,
+ pub generics: Generics,
+ pub brace_token: token::Brace,
+ pub variants: Punctuated<Variant, Token![,]>,
+ }
+}
+
+ast_struct! {
+ /// An `extern crate` item: `extern crate serde`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ItemExternCrate {
+ pub attrs: Vec<Attribute>,
+ pub vis: Visibility,
+ pub extern_token: Token![extern],
+ pub crate_token: Token![crate],
+ pub ident: Ident,
+ pub rename: Option<(Token![as], Ident)>,
+ pub semi_token: Token![;],
+ }
+}
+
+ast_struct! {
+ /// A free-standing function: `fn process(n: usize) -> Result<()> { ... }`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ItemFn {
+ pub attrs: Vec<Attribute>,
+ pub vis: Visibility,
+ pub sig: Signature,
+ pub block: Box<Block>,
+ }
+}
+
+ast_struct! {
+ /// A block of foreign items: `extern "C" { ... }`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ItemForeignMod {
+ pub attrs: Vec<Attribute>,
+ pub unsafety: Option<Token![unsafe]>,
+ pub abi: Abi,
+ pub brace_token: token::Brace,
+ pub items: Vec<ForeignItem>,
+ }
+}
+
+ast_struct! {
+ /// An impl block providing trait or associated items: `impl<A> Trait
+ /// for Data<A> { ... }`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ItemImpl {
+ pub attrs: Vec<Attribute>,
+ pub defaultness: Option<Token![default]>,
+ pub unsafety: Option<Token![unsafe]>,
+ pub impl_token: Token![impl],
+ pub generics: Generics,
+ /// Trait this impl implements.
+ pub trait_: Option<(Option<Token![!]>, Path, Token![for])>,
+ /// The Self type of the impl.
+ pub self_ty: Box<Type>,
+ pub brace_token: token::Brace,
+ pub items: Vec<ImplItem>,
+ }
+}
+
+ast_struct! {
+ /// A macro invocation, which includes `macro_rules!` definitions.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ItemMacro {
+ pub attrs: Vec<Attribute>,
+ /// The `example` in `macro_rules! example { ... }`.
+ pub ident: Option<Ident>,
+ pub mac: Macro,
+ pub semi_token: Option<Token![;]>,
+ }
+}
+
+ast_struct! {
+ /// A module or module declaration: `mod m` or `mod m { ... }`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ItemMod {
+ pub attrs: Vec<Attribute>,
+ pub vis: Visibility,
+ pub unsafety: Option<Token![unsafe]>,
+ pub mod_token: Token![mod],
+ pub ident: Ident,
+ pub content: Option<(token::Brace, Vec<Item>)>,
+ pub semi: Option<Token![;]>,
+ }
+}
+
+ast_struct! {
+ /// A static item: `static BIKE: Shed = Shed(42)`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ItemStatic {
+ pub attrs: Vec<Attribute>,
+ pub vis: Visibility,
+ pub static_token: Token![static],
+ pub mutability: StaticMutability,
+ pub ident: Ident,
+ pub colon_token: Token![:],
+ pub ty: Box<Type>,
+ pub eq_token: Token![=],
+ pub expr: Box<Expr>,
+ pub semi_token: Token![;],
+ }
+}
+
+ast_struct! {
+ /// A struct definition: `struct Foo<A> { x: A }`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ItemStruct {
+ pub attrs: Vec<Attribute>,
+ pub vis: Visibility,
+ pub struct_token: Token![struct],
+ pub ident: Ident,
+ pub generics: Generics,
+ pub fields: Fields,
+ pub semi_token: Option<Token![;]>,
+ }
+}
+
+ast_struct! {
+ /// A trait definition: `pub trait Iterator { ... }`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ItemTrait {
+ pub attrs: Vec<Attribute>,
+ pub vis: Visibility,
+ pub unsafety: Option<Token![unsafe]>,
+ pub auto_token: Option<Token![auto]>,
+ pub restriction: Option<ImplRestriction>,
+ pub trait_token: Token![trait],
+ pub ident: Ident,
+ pub generics: Generics,
+ pub colon_token: Option<Token![:]>,
+ pub supertraits: Punctuated<TypeParamBound, Token![+]>,
+ pub brace_token: token::Brace,
+ pub items: Vec<TraitItem>,
+ }
+}
+
+ast_struct! {
+ /// A trait alias: `pub trait SharableIterator = Iterator + Sync`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ItemTraitAlias {
+ pub attrs: Vec<Attribute>,
+ pub vis: Visibility,
+ pub trait_token: Token![trait],
+ pub ident: Ident,
+ pub generics: Generics,
+ pub eq_token: Token![=],
+ pub bounds: Punctuated<TypeParamBound, Token![+]>,
+ pub semi_token: Token![;],
+ }
+}
+
+ast_struct! {
+ /// A type alias: `type Result<T> = std::result::Result<T, MyError>`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ItemType {
+ pub attrs: Vec<Attribute>,
+ pub vis: Visibility,
+ pub type_token: Token![type],
+ pub ident: Ident,
+ pub generics: Generics,
+ pub eq_token: Token![=],
+ pub ty: Box<Type>,
+ pub semi_token: Token![;],
+ }
+}
+
+ast_struct! {
+ /// A union definition: `union Foo<A, B> { x: A, y: B }`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ItemUnion {
+ pub attrs: Vec<Attribute>,
+ pub vis: Visibility,
+ pub union_token: Token![union],
+ pub ident: Ident,
+ pub generics: Generics,
+ pub fields: FieldsNamed,
+ }
+}
+
+ast_struct! {
+ /// A use declaration: `use std::collections::HashMap`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ItemUse {
+ pub attrs: Vec<Attribute>,
+ pub vis: Visibility,
+ pub use_token: Token![use],
+ pub leading_colon: Option<Token![::]>,
+ pub tree: UseTree,
+ pub semi_token: Token![;],
+ }
+}
+
+impl Item {
+ #[cfg(feature = "parsing")]
+ pub(crate) fn replace_attrs(&mut self, new: Vec<Attribute>) -> Vec<Attribute> {
+ match self {
+ Item::Const(ItemConst { attrs, .. })
+ | Item::Enum(ItemEnum { attrs, .. })
+ | Item::ExternCrate(ItemExternCrate { attrs, .. })
+ | Item::Fn(ItemFn { attrs, .. })
+ | Item::ForeignMod(ItemForeignMod { attrs, .. })
+ | Item::Impl(ItemImpl { attrs, .. })
+ | Item::Macro(ItemMacro { attrs, .. })
+ | Item::Mod(ItemMod { attrs, .. })
+ | Item::Static(ItemStatic { attrs, .. })
+ | Item::Struct(ItemStruct { attrs, .. })
+ | Item::Trait(ItemTrait { attrs, .. })
+ | Item::TraitAlias(ItemTraitAlias { attrs, .. })
+ | Item::Type(ItemType { attrs, .. })
+ | Item::Union(ItemUnion { attrs, .. })
+ | Item::Use(ItemUse { attrs, .. }) => mem::replace(attrs, new),
+ Item::Verbatim(_) => Vec::new(),
+ }
+ }
+}
+
+impl From<DeriveInput> for Item {
+ fn from(input: DeriveInput) -> Item {
+ match input.data {
+ Data::Struct(data) => Item::Struct(ItemStruct {
+ attrs: input.attrs,
+ vis: input.vis,
+ struct_token: data.struct_token,
+ ident: input.ident,
+ generics: input.generics,
+ fields: data.fields,
+ semi_token: data.semi_token,
+ }),
+ Data::Enum(data) => Item::Enum(ItemEnum {
+ attrs: input.attrs,
+ vis: input.vis,
+ enum_token: data.enum_token,
+ ident: input.ident,
+ generics: input.generics,
+ brace_token: data.brace_token,
+ variants: data.variants,
+ }),
+ Data::Union(data) => Item::Union(ItemUnion {
+ attrs: input.attrs,
+ vis: input.vis,
+ union_token: data.union_token,
+ ident: input.ident,
+ generics: input.generics,
+ fields: data.fields,
+ }),
+ }
+ }
+}
+
+impl From<ItemStruct> for DeriveInput {
+ fn from(input: ItemStruct) -> DeriveInput {
+ DeriveInput {
+ attrs: input.attrs,
+ vis: input.vis,
+ ident: input.ident,
+ generics: input.generics,
+ data: Data::Struct(DataStruct {
+ struct_token: input.struct_token,
+ fields: input.fields,
+ semi_token: input.semi_token,
+ }),
+ }
+ }
+}
+
+impl From<ItemEnum> for DeriveInput {
+ fn from(input: ItemEnum) -> DeriveInput {
+ DeriveInput {
+ attrs: input.attrs,
+ vis: input.vis,
+ ident: input.ident,
+ generics: input.generics,
+ data: Data::Enum(DataEnum {
+ enum_token: input.enum_token,
+ brace_token: input.brace_token,
+ variants: input.variants,
+ }),
+ }
+ }
+}
+
+impl From<ItemUnion> for DeriveInput {
+ fn from(input: ItemUnion) -> DeriveInput {
+ DeriveInput {
+ attrs: input.attrs,
+ vis: input.vis,
+ ident: input.ident,
+ generics: input.generics,
+ data: Data::Union(DataUnion {
+ union_token: input.union_token,
+ fields: input.fields,
+ }),
+ }
+ }
+}
+
+ast_enum_of_structs! {
+ /// A suffix of an import tree in a `use` item: `Type as Renamed` or `*`.
+ ///
+ /// # Syntax tree enum
+ ///
+ /// This type is a [syntax tree enum].
+ ///
+ /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub enum UseTree {
+ /// A path prefix of imports in a `use` item: `std::...`.
+ Path(UsePath),
+
+ /// An identifier imported by a `use` item: `HashMap`.
+ Name(UseName),
+
+ /// An renamed identifier imported by a `use` item: `HashMap as Map`.
+ Rename(UseRename),
+
+ /// A glob import in a `use` item: `*`.
+ Glob(UseGlob),
+
+ /// A braced group of imports in a `use` item: `{A, B, C}`.
+ Group(UseGroup),
+ }
+}
+
+ast_struct! {
+ /// A path prefix of imports in a `use` item: `std::...`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct UsePath {
+ pub ident: Ident,
+ pub colon2_token: Token![::],
+ pub tree: Box<UseTree>,
+ }
+}
+
+ast_struct! {
+ /// An identifier imported by a `use` item: `HashMap`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct UseName {
+ pub ident: Ident,
+ }
+}
+
+ast_struct! {
+ /// An renamed identifier imported by a `use` item: `HashMap as Map`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct UseRename {
+ pub ident: Ident,
+ pub as_token: Token![as],
+ pub rename: Ident,
+ }
+}
+
+ast_struct! {
+ /// A glob import in a `use` item: `*`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct UseGlob {
+ pub star_token: Token![*],
+ }
+}
+
+ast_struct! {
+ /// A braced group of imports in a `use` item: `{A, B, C}`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct UseGroup {
+ pub brace_token: token::Brace,
+ pub items: Punctuated<UseTree, Token![,]>,
+ }
+}
+
+ast_enum_of_structs! {
+ /// An item within an `extern` block.
+ ///
+ /// # Syntax tree enum
+ ///
+ /// This type is a [syntax tree enum].
+ ///
+ /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ #[non_exhaustive]
+ pub enum ForeignItem {
+ /// A foreign function in an `extern` block.
+ Fn(ForeignItemFn),
+
+ /// A foreign static item in an `extern` block: `static ext: u8`.
+ Static(ForeignItemStatic),
+
+ /// A foreign type in an `extern` block: `type void`.
+ Type(ForeignItemType),
+
+ /// A macro invocation within an extern block.
+ Macro(ForeignItemMacro),
+
+ /// Tokens in an `extern` block not interpreted by Syn.
+ Verbatim(TokenStream),
+
+ // For testing exhaustiveness in downstream code, use the following idiom:
+ //
+ // match item {
+ // #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))]
+ //
+ // ForeignItem::Fn(item) => {...}
+ // ForeignItem::Static(item) => {...}
+ // ...
+ // ForeignItem::Verbatim(item) => {...}
+ //
+ // _ => { /* some sane fallback */ }
+ // }
+ //
+ // This way we fail your tests but don't break your library when adding
+ // a variant. You will be notified by a test failure when a variant is
+ // added, so that you can add code to handle it, but your library will
+ // continue to compile and work for downstream users in the interim.
+ }
+}
+
+ast_struct! {
+ /// A foreign function in an `extern` block.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ForeignItemFn {
+ pub attrs: Vec<Attribute>,
+ pub vis: Visibility,
+ pub sig: Signature,
+ pub semi_token: Token![;],
+ }
+}
+
+ast_struct! {
+ /// A foreign static item in an `extern` block: `static ext: u8`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ForeignItemStatic {
+ pub attrs: Vec<Attribute>,
+ pub vis: Visibility,
+ pub static_token: Token![static],
+ pub mutability: StaticMutability,
+ pub ident: Ident,
+ pub colon_token: Token![:],
+ pub ty: Box<Type>,
+ pub semi_token: Token![;],
+ }
+}
+
+ast_struct! {
+ /// A foreign type in an `extern` block: `type void`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ForeignItemType {
+ pub attrs: Vec<Attribute>,
+ pub vis: Visibility,
+ pub type_token: Token![type],
+ pub ident: Ident,
+ pub generics: Generics,
+ pub semi_token: Token![;],
+ }
+}
+
+ast_struct! {
+ /// A macro invocation within an extern block.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ForeignItemMacro {
+ pub attrs: Vec<Attribute>,
+ pub mac: Macro,
+ pub semi_token: Option<Token![;]>,
+ }
+}
+
+ast_enum_of_structs! {
+ /// An item declaration within the definition of a trait.
+ ///
+ /// # Syntax tree enum
+ ///
+ /// This type is a [syntax tree enum].
+ ///
+ /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ #[non_exhaustive]
+ pub enum TraitItem {
+ /// An associated constant within the definition of a trait.
+ Const(TraitItemConst),
+
+ /// An associated function within the definition of a trait.
+ Fn(TraitItemFn),
+
+ /// An associated type within the definition of a trait.
+ Type(TraitItemType),
+
+ /// A macro invocation within the definition of a trait.
+ Macro(TraitItemMacro),
+
+ /// Tokens within the definition of a trait not interpreted by Syn.
+ Verbatim(TokenStream),
+
+ // For testing exhaustiveness in downstream code, use the following idiom:
+ //
+ // match item {
+ // #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))]
+ //
+ // TraitItem::Const(item) => {...}
+ // TraitItem::Fn(item) => {...}
+ // ...
+ // TraitItem::Verbatim(item) => {...}
+ //
+ // _ => { /* some sane fallback */ }
+ // }
+ //
+ // This way we fail your tests but don't break your library when adding
+ // a variant. You will be notified by a test failure when a variant is
+ // added, so that you can add code to handle it, but your library will
+ // continue to compile and work for downstream users in the interim.
+ }
+}
+
+ast_struct! {
+ /// An associated constant within the definition of a trait.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct TraitItemConst {
+ pub attrs: Vec<Attribute>,
+ pub const_token: Token![const],
+ pub ident: Ident,
+ pub generics: Generics,
+ pub colon_token: Token![:],
+ pub ty: Type,
+ pub default: Option<(Token![=], Expr)>,
+ pub semi_token: Token![;],
+ }
+}
+
+ast_struct! {
+ /// An associated function within the definition of a trait.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct TraitItemFn {
+ pub attrs: Vec<Attribute>,
+ pub sig: Signature,
+ pub default: Option<Block>,
+ pub semi_token: Option<Token![;]>,
+ }
+}
+
+ast_struct! {
+ /// An associated type within the definition of a trait.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct TraitItemType {
+ pub attrs: Vec<Attribute>,
+ pub type_token: Token![type],
+ pub ident: Ident,
+ pub generics: Generics,
+ pub colon_token: Option<Token![:]>,
+ pub bounds: Punctuated<TypeParamBound, Token![+]>,
+ pub default: Option<(Token![=], Type)>,
+ pub semi_token: Token![;],
+ }
+}
+
+ast_struct! {
+ /// A macro invocation within the definition of a trait.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct TraitItemMacro {
+ pub attrs: Vec<Attribute>,
+ pub mac: Macro,
+ pub semi_token: Option<Token![;]>,
+ }
+}
+
+ast_enum_of_structs! {
+ /// An item within an impl block.
+ ///
+ /// # Syntax tree enum
+ ///
+ /// This type is a [syntax tree enum].
+ ///
+ /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ #[non_exhaustive]
+ pub enum ImplItem {
+ /// An associated constant within an impl block.
+ Const(ImplItemConst),
+
+ /// An associated function within an impl block.
+ Fn(ImplItemFn),
+
+ /// An associated type within an impl block.
+ Type(ImplItemType),
+
+ /// A macro invocation within an impl block.
+ Macro(ImplItemMacro),
+
+ /// Tokens within an impl block not interpreted by Syn.
+ Verbatim(TokenStream),
+
+ // For testing exhaustiveness in downstream code, use the following idiom:
+ //
+ // match item {
+ // #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))]
+ //
+ // ImplItem::Const(item) => {...}
+ // ImplItem::Fn(item) => {...}
+ // ...
+ // ImplItem::Verbatim(item) => {...}
+ //
+ // _ => { /* some sane fallback */ }
+ // }
+ //
+ // This way we fail your tests but don't break your library when adding
+ // a variant. You will be notified by a test failure when a variant is
+ // added, so that you can add code to handle it, but your library will
+ // continue to compile and work for downstream users in the interim.
+ }
+}
+
+ast_struct! {
+ /// An associated constant within an impl block.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ImplItemConst {
+ pub attrs: Vec<Attribute>,
+ pub vis: Visibility,
+ pub defaultness: Option<Token![default]>,
+ pub const_token: Token![const],
+ pub ident: Ident,
+ pub generics: Generics,
+ pub colon_token: Token![:],
+ pub ty: Type,
+ pub eq_token: Token![=],
+ pub expr: Expr,
+ pub semi_token: Token![;],
+ }
+}
+
+ast_struct! {
+ /// An associated function within an impl block.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ImplItemFn {
+ pub attrs: Vec<Attribute>,
+ pub vis: Visibility,
+ pub defaultness: Option<Token![default]>,
+ pub sig: Signature,
+ pub block: Block,
+ }
+}
+
+ast_struct! {
+ /// An associated type within an impl block.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ImplItemType {
+ pub attrs: Vec<Attribute>,
+ pub vis: Visibility,
+ pub defaultness: Option<Token![default]>,
+ pub type_token: Token![type],
+ pub ident: Ident,
+ pub generics: Generics,
+ pub eq_token: Token![=],
+ pub ty: Type,
+ pub semi_token: Token![;],
+ }
+}
+
+ast_struct! {
+ /// A macro invocation within an impl block.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct ImplItemMacro {
+ pub attrs: Vec<Attribute>,
+ pub mac: Macro,
+ pub semi_token: Option<Token![;]>,
+ }
+}
+
+ast_struct! {
+ /// A function signature in a trait or implementation: `unsafe fn
+ /// initialize(&self)`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct Signature {
+ pub constness: Option<Token![const]>,
+ pub asyncness: Option<Token![async]>,
+ pub unsafety: Option<Token![unsafe]>,
+ pub abi: Option<Abi>,
+ pub fn_token: Token![fn],
+ pub ident: Ident,
+ pub generics: Generics,
+ pub paren_token: token::Paren,
+ pub inputs: Punctuated<FnArg, Token![,]>,
+ pub variadic: Option<Variadic>,
+ pub output: ReturnType,
+ }
+}
+
+impl Signature {
+ /// A method's `self` receiver, such as `&self` or `self: Box<Self>`.
+ pub fn receiver(&self) -> Option<&Receiver> {
+ let arg = self.inputs.first()?;
+ match arg {
+ FnArg::Receiver(receiver) => Some(receiver),
+ FnArg::Typed(_) => None,
+ }
+ }
+}
+
+ast_enum_of_structs! {
+ /// An argument in a function signature: the `n: usize` in `fn f(n: usize)`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub enum FnArg {
+ /// The `self` argument of an associated method.
+ Receiver(Receiver),
+
+ /// A function argument accepted by pattern and type.
+ Typed(PatType),
+ }
+}
+
+ast_struct! {
+ /// The `self` argument of an associated method.
+ ///
+ /// If `colon_token` is present, the receiver is written with an explicit
+ /// type such as `self: Box<Self>`. If `colon_token` is absent, the receiver
+ /// is written in shorthand such as `self` or `&self` or `&mut self`. In the
+ /// shorthand case, the type in `ty` is reconstructed as one of `Self`,
+ /// `&Self`, or `&mut Self`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct Receiver {
+ pub attrs: Vec<Attribute>,
+ pub reference: Option<(Token![&], Option<Lifetime>)>,
+ pub mutability: Option<Token![mut]>,
+ pub self_token: Token![self],
+ pub colon_token: Option<Token![:]>,
+ pub ty: Box<Type>,
+ }
+}
+
+impl Receiver {
+ pub fn lifetime(&self) -> Option<&Lifetime> {
+ self.reference.as_ref()?.1.as_ref()
+ }
+}
+
+ast_struct! {
+ /// The variadic argument of a foreign function.
+ ///
+ /// ```rust
+ /// # struct c_char;
+ /// # struct c_int;
+ /// #
+ /// extern "C" {
+ /// fn printf(format: *const c_char, ...) -> c_int;
+ /// // ^^^
+ /// }
+ /// ```
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct Variadic {
+ pub attrs: Vec<Attribute>,
+ pub pat: Option<(Box<Pat>, Token![:])>,
+ pub dots: Token![...],
+ pub comma: Option<Token![,]>,
+ }
+}
+
+ast_enum! {
+ /// The mutability of an `Item::Static` or `ForeignItem::Static`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ #[non_exhaustive]
+ pub enum StaticMutability {
+ Mut(Token![mut]),
+ None,
+ }
+}
+
+ast_enum! {
+ /// Unused, but reserved for RFC 3323 restrictions.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ #[non_exhaustive]
+ pub enum ImplRestriction {}
+
+
+ // TODO: https://rust-lang.github.io/rfcs/3323-restrictions.html
+ //
+ // pub struct ImplRestriction {
+ // pub impl_token: Token![impl],
+ // pub paren_token: token::Paren,
+ // pub in_token: Option<Token![in]>,
+ // pub path: Box<Path>,
+ // }
+}
+
+#[cfg(feature = "parsing")]
+pub(crate) mod parsing {
+ use crate::attr::{self, Attribute};
+ use crate::derive;
+ use crate::error::{Error, Result};
+ use crate::expr::Expr;
+ use crate::ext::IdentExt as _;
+ use crate::generics::{self, Generics, TypeParamBound};
+ use crate::ident::Ident;
+ use crate::item::{
+ FnArg, ForeignItem, ForeignItemFn, ForeignItemMacro, ForeignItemStatic, ForeignItemType,
+ ImplItem, ImplItemConst, ImplItemFn, ImplItemMacro, ImplItemType, Item, ItemConst,
+ ItemEnum, ItemExternCrate, ItemFn, ItemForeignMod, ItemImpl, ItemMacro, ItemMod,
+ ItemStatic, ItemStruct, ItemTrait, ItemTraitAlias, ItemType, ItemUnion, ItemUse, Receiver,
+ Signature, StaticMutability, TraitItem, TraitItemConst, TraitItemFn, TraitItemMacro,
+ TraitItemType, UseGlob, UseGroup, UseName, UsePath, UseRename, UseTree, Variadic,
+ };
+ use crate::lifetime::Lifetime;
+ use crate::lit::LitStr;
+ use crate::mac::{self, Macro};
+ use crate::parse::discouraged::Speculative as _;
+ use crate::parse::{Parse, ParseBuffer, ParseStream};
+ use crate::pat::{Pat, PatType, PatWild};
+ use crate::path::Path;
+ use crate::punctuated::Punctuated;
+ use crate::restriction::Visibility;
+ use crate::stmt::Block;
+ use crate::token;
+ use crate::ty::{Abi, ReturnType, Type, TypePath, TypeReference};
+ use crate::verbatim;
+ use proc_macro2::TokenStream;
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for Item {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let begin = input.fork();
+ let attrs = input.call(Attribute::parse_outer)?;
+ parse_rest_of_item(begin, attrs, input)
+ }
+ }
+
+ pub(crate) fn parse_rest_of_item(
+ begin: ParseBuffer,
+ mut attrs: Vec<Attribute>,
+ input: ParseStream,
+ ) -> Result<Item> {
+ let ahead = input.fork();
+ let vis: Visibility = ahead.parse()?;
+
+ let lookahead = ahead.lookahead1();
+ let allow_safe = false;
+ let mut item = if lookahead.peek(Token![fn]) || peek_signature(&ahead, allow_safe) {
+ let vis: Visibility = input.parse()?;
+ let sig: Signature = input.parse()?;
+ if input.peek(Token![;]) {
+ input.parse::<Token![;]>()?;
+ Ok(Item::Verbatim(verbatim::between(&begin, input)))
+ } else {
+ parse_rest_of_fn(input, Vec::new(), vis, sig).map(Item::Fn)
+ }
+ } else if lookahead.peek(Token![extern]) {
+ ahead.parse::<Token![extern]>()?;
+ let lookahead = ahead.lookahead1();
+ if lookahead.peek(Token![crate]) {
+ input.parse().map(Item::ExternCrate)
+ } else if lookahead.peek(token::Brace) {
+ input.parse().map(Item::ForeignMod)
+ } else if lookahead.peek(LitStr) {
+ ahead.parse::<LitStr>()?;
+ let lookahead = ahead.lookahead1();
+ if lookahead.peek(token::Brace) {
+ input.parse().map(Item::ForeignMod)
+ } else {
+ Err(lookahead.error())
+ }
+ } else {
+ Err(lookahead.error())
+ }
+ } else if lookahead.peek(Token![use]) {
+ let allow_crate_root_in_path = true;
+ match parse_item_use(input, allow_crate_root_in_path)? {
+ Some(item_use) => Ok(Item::Use(item_use)),
+ None => Ok(Item::Verbatim(verbatim::between(&begin, input))),
+ }
+ } else if lookahead.peek(Token![static]) {
+ let vis = input.parse()?;
+ let static_token = input.parse()?;
+ let mutability = input.parse()?;
+ let ident = input.parse()?;
+ if input.peek(Token![=]) {
+ input.parse::<Token![=]>()?;
+ input.parse::<Expr>()?;
+ input.parse::<Token![;]>()?;
+ Ok(Item::Verbatim(verbatim::between(&begin, input)))
+ } else {
+ let colon_token = input.parse()?;
+ let ty = input.parse()?;
+ if input.peek(Token![;]) {
+ input.parse::<Token![;]>()?;
+ Ok(Item::Verbatim(verbatim::between(&begin, input)))
+ } else {
+ Ok(Item::Static(ItemStatic {
+ attrs: Vec::new(),
+ vis,
+ static_token,
+ mutability,
+ ident,
+ colon_token,
+ ty,
+ eq_token: input.parse()?,
+ expr: input.parse()?,
+ semi_token: input.parse()?,
+ }))
+ }
+ }
+ } else if lookahead.peek(Token![const]) {
+ let vis = input.parse()?;
+ let const_token: Token![const] = input.parse()?;
+ let lookahead = input.lookahead1();
+ let ident = if lookahead.peek(Ident) || lookahead.peek(Token![_]) {
+ input.call(Ident::parse_any)?
+ } else {
+ return Err(lookahead.error());
+ };
+ let mut generics: Generics = input.parse()?;
+ let colon_token = input.parse()?;
+ let ty = input.parse()?;
+ let value = if let Some(eq_token) = input.parse::<Option<Token![=]>>()? {
+ let expr: Expr = input.parse()?;
+ Some((eq_token, expr))
+ } else {
+ None
+ };
+ generics.where_clause = input.parse()?;
+ let semi_token: Token![;] = input.parse()?;
+ match value {
+ Some((eq_token, expr))
+ if generics.lt_token.is_none() && generics.where_clause.is_none() =>
+ {
+ Ok(Item::Const(ItemConst {
+ attrs: Vec::new(),
+ vis,
+ const_token,
+ ident,
+ generics,
+ colon_token,
+ ty,
+ eq_token,
+ expr: Box::new(expr),
+ semi_token,
+ }))
+ }
+ _ => Ok(Item::Verbatim(verbatim::between(&begin, input))),
+ }
+ } else if lookahead.peek(Token![unsafe]) {
+ ahead.parse::<Token![unsafe]>()?;
+ let lookahead = ahead.lookahead1();
+ if lookahead.peek(Token![trait])
+ || lookahead.peek(Token![auto]) && ahead.peek2(Token![trait])
+ {
+ input.parse().map(Item::Trait)
+ } else if lookahead.peek(Token![impl]) {
+ let allow_verbatim_impl = true;
+ if let Some(item) = parse_impl(input, allow_verbatim_impl)? {
+ Ok(Item::Impl(item))
+ } else {
+ Ok(Item::Verbatim(verbatim::between(&begin, input)))
+ }
+ } else if lookahead.peek(Token![extern]) {
+ input.parse().map(Item::ForeignMod)
+ } else if lookahead.peek(Token![mod]) {
+ input.parse().map(Item::Mod)
+ } else {
+ Err(lookahead.error())
+ }
+ } else if lookahead.peek(Token![mod]) {
+ input.parse().map(Item::Mod)
+ } else if lookahead.peek(Token![type]) {
+ parse_item_type(begin, input)
+ } else if lookahead.peek(Token![struct]) {
+ input.parse().map(Item::Struct)
+ } else if lookahead.peek(Token![enum]) {
+ input.parse().map(Item::Enum)
+ } else if lookahead.peek(Token![union]) && ahead.peek2(Ident) {
+ input.parse().map(Item::Union)
+ } else if lookahead.peek(Token![trait]) {
+ input.call(parse_trait_or_trait_alias)
+ } else if lookahead.peek(Token![auto]) && ahead.peek2(Token![trait]) {
+ input.parse().map(Item::Trait)
+ } else if lookahead.peek(Token![impl])
+ || lookahead.peek(Token![default]) && !ahead.peek2(Token![!])
+ {
+ let allow_verbatim_impl = true;
+ if let Some(item) = parse_impl(input, allow_verbatim_impl)? {
+ Ok(Item::Impl(item))
+ } else {
+ Ok(Item::Verbatim(verbatim::between(&begin, input)))
+ }
+ } else if lookahead.peek(Token![macro]) {
+ input.advance_to(&ahead);
+ parse_macro2(begin, vis, input)
+ } else if vis.is_inherited()
+ && (lookahead.peek(Ident)
+ || lookahead.peek(Token![self])
+ || lookahead.peek(Token![super])
+ || lookahead.peek(Token![crate])
+ || lookahead.peek(Token![::]))
+ {
+ input.parse().map(Item::Macro)
+ } else {
+ Err(lookahead.error())
+ }?;
+
+ attrs.extend(item.replace_attrs(Vec::new()));
+ item.replace_attrs(attrs);
+ Ok(item)
+ }
+
+ struct FlexibleItemType {
+ vis: Visibility,
+ defaultness: Option<Token![default]>,
+ type_token: Token![type],
+ ident: Ident,
+ generics: Generics,
+ colon_token: Option<Token![:]>,
+ bounds: Punctuated<TypeParamBound, Token![+]>,
+ ty: Option<(Token![=], Type)>,
+ semi_token: Token![;],
+ }
+
+ enum TypeDefaultness {
+ Optional,
+ Disallowed,
+ }
+
+ enum WhereClauseLocation {
+ // type Ty<T> where T: 'static = T;
+ BeforeEq,
+ // type Ty<T> = T where T: 'static;
+ AfterEq,
+ // TODO: goes away once the migration period on rust-lang/rust#89122 is over
+ Both,
+ }
+
+ impl FlexibleItemType {
+ fn parse(
+ input: ParseStream,
+ allow_defaultness: TypeDefaultness,
+ where_clause_location: WhereClauseLocation,
+ ) -> Result<Self> {
+ let vis: Visibility = input.parse()?;
+ let defaultness: Option<Token![default]> = match allow_defaultness {
+ TypeDefaultness::Optional => input.parse()?,
+ TypeDefaultness::Disallowed => None,
+ };
+ let type_token: Token![type] = input.parse()?;
+ let ident: Ident = input.parse()?;
+ let mut generics: Generics = input.parse()?;
+ let (colon_token, bounds) = Self::parse_optional_bounds(input)?;
+
+ match where_clause_location {
+ WhereClauseLocation::BeforeEq | WhereClauseLocation::Both => {
+ generics.where_clause = input.parse()?;
+ }
+ WhereClauseLocation::AfterEq => {}
+ }
+
+ let ty = Self::parse_optional_definition(input)?;
+
+ match where_clause_location {
+ WhereClauseLocation::AfterEq | WhereClauseLocation::Both
+ if generics.where_clause.is_none() =>
+ {
+ generics.where_clause = input.parse()?;
+ }
+ _ => {}
+ }
+
+ let semi_token: Token![;] = input.parse()?;
+
+ Ok(FlexibleItemType {
+ vis,
+ defaultness,
+ type_token,
+ ident,
+ generics,
+ colon_token,
+ bounds,
+ ty,
+ semi_token,
+ })
+ }
+
+ fn parse_optional_bounds(
+ input: ParseStream,
+ ) -> Result<(Option<Token![:]>, Punctuated<TypeParamBound, Token![+]>)> {
+ let colon_token: Option<Token![:]> = input.parse()?;
+
+ let mut bounds = Punctuated::new();
+ if colon_token.is_some() {
+ loop {
+ if input.peek(Token![where]) || input.peek(Token![=]) || input.peek(Token![;]) {
+ break;
+ }
+ bounds.push_value({
+ let allow_precise_capture = false;
+ let allow_const = true;
+ TypeParamBound::parse_single(input, allow_precise_capture, allow_const)?
+ });
+ if input.peek(Token![where]) || input.peek(Token![=]) || input.peek(Token![;]) {
+ break;
+ }
+ bounds.push_punct(input.parse::<Token![+]>()?);
+ }
+ }
+
+ Ok((colon_token, bounds))
+ }
+
+ fn parse_optional_definition(input: ParseStream) -> Result<Option<(Token![=], Type)>> {
+ let eq_token: Option<Token![=]> = input.parse()?;
+ if let Some(eq_token) = eq_token {
+ let definition: Type = input.parse()?;
+ Ok(Some((eq_token, definition)))
+ } else {
+ Ok(None)
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ItemMacro {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let attrs = input.call(Attribute::parse_outer)?;
+ let path = input.call(Path::parse_mod_style)?;
+ let bang_token: Token![!] = input.parse()?;
+ let ident: Option<Ident> = if input.peek(Token![try]) {
+ input.call(Ident::parse_any).map(Some)
+ } else {
+ input.parse()
+ }?;
+ let (delimiter, tokens) = input.call(mac::parse_delimiter)?;
+ let semi_token: Option<Token![;]> = if !delimiter.is_brace() {
+ Some(input.parse()?)
+ } else {
+ None
+ };
+ Ok(ItemMacro {
+ attrs,
+ ident,
+ mac: Macro {
+ path,
+ bang_token,
+ delimiter,
+ tokens,
+ },
+ semi_token,
+ })
+ }
+ }
+
+ fn parse_macro2(begin: ParseBuffer, _vis: Visibility, input: ParseStream) -> Result<Item> {
+ input.parse::<Token![macro]>()?;
+ input.parse::<Ident>()?;
+
+ let mut lookahead = input.lookahead1();
+ if lookahead.peek(token::Paren) {
+ let paren_content;
+ parenthesized!(paren_content in input);
+ paren_content.parse::<TokenStream>()?;
+ lookahead = input.lookahead1();
+ }
+
+ if lookahead.peek(token::Brace) {
+ let brace_content;
+ braced!(brace_content in input);
+ brace_content.parse::<TokenStream>()?;
+ } else {
+ return Err(lookahead.error());
+ }
+
+ Ok(Item::Verbatim(verbatim::between(&begin, input)))
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ItemExternCrate {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Ok(ItemExternCrate {
+ attrs: input.call(Attribute::parse_outer)?,
+ vis: input.parse()?,
+ extern_token: input.parse()?,
+ crate_token: input.parse()?,
+ ident: {
+ if input.peek(Token![self]) {
+ input.call(Ident::parse_any)?
+ } else {
+ input.parse()?
+ }
+ },
+ rename: {
+ if input.peek(Token![as]) {
+ let as_token: Token![as] = input.parse()?;
+ let rename: Ident = if input.peek(Token![_]) {
+ Ident::from(input.parse::<Token![_]>()?)
+ } else {
+ input.parse()?
+ };
+ Some((as_token, rename))
+ } else {
+ None
+ }
+ },
+ semi_token: input.parse()?,
+ })
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ItemUse {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let allow_crate_root_in_path = false;
+ parse_item_use(input, allow_crate_root_in_path).map(Option::unwrap)
+ }
+ }
+
+ fn parse_item_use(
+ input: ParseStream,
+ allow_crate_root_in_path: bool,
+ ) -> Result<Option<ItemUse>> {
+ let attrs = input.call(Attribute::parse_outer)?;
+ let vis: Visibility = input.parse()?;
+ let use_token: Token![use] = input.parse()?;
+ let leading_colon: Option<Token![::]> = input.parse()?;
+ let tree = parse_use_tree(input, allow_crate_root_in_path && leading_colon.is_none())?;
+ let semi_token: Token![;] = input.parse()?;
+
+ let tree = match tree {
+ Some(tree) => tree,
+ None => return Ok(None),
+ };
+
+ Ok(Some(ItemUse {
+ attrs,
+ vis,
+ use_token,
+ leading_colon,
+ tree,
+ semi_token,
+ }))
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for UseTree {
+ fn parse(input: ParseStream) -> Result<UseTree> {
+ let allow_crate_root_in_path = false;
+ parse_use_tree(input, allow_crate_root_in_path).map(Option::unwrap)
+ }
+ }
+
+ fn parse_use_tree(
+ input: ParseStream,
+ allow_crate_root_in_path: bool,
+ ) -> Result<Option<UseTree>> {
+ let lookahead = input.lookahead1();
+ if lookahead.peek(Ident)
+ || lookahead.peek(Token![self])
+ || lookahead.peek(Token![super])
+ || lookahead.peek(Token![crate])
+ || lookahead.peek(Token![try])
+ {
+ let ident = input.call(Ident::parse_any)?;
+ if input.peek(Token![::]) {
+ Ok(Some(UseTree::Path(UsePath {
+ ident,
+ colon2_token: input.parse()?,
+ tree: Box::new(input.parse()?),
+ })))
+ } else if input.peek(Token![as]) {
+ Ok(Some(UseTree::Rename(UseRename {
+ ident,
+ as_token: input.parse()?,
+ rename: {
+ if input.peek(Ident) {
+ input.parse()?
+ } else if input.peek(Token![_]) {
+ Ident::from(input.parse::<Token![_]>()?)
+ } else {
+ return Err(input.error("expected identifier or underscore"));
+ }
+ },
+ })))
+ } else {
+ Ok(Some(UseTree::Name(UseName { ident })))
+ }
+ } else if lookahead.peek(Token![*]) {
+ Ok(Some(UseTree::Glob(UseGlob {
+ star_token: input.parse()?,
+ })))
+ } else if lookahead.peek(token::Brace) {
+ let content;
+ let brace_token = braced!(content in input);
+ let mut items = Punctuated::new();
+ let mut has_any_crate_root_in_path = false;
+ loop {
+ if content.is_empty() {
+ break;
+ }
+ let this_tree_starts_with_crate_root =
+ allow_crate_root_in_path && content.parse::<Option<Token![::]>>()?.is_some();
+ has_any_crate_root_in_path |= this_tree_starts_with_crate_root;
+ match parse_use_tree(
+ &content,
+ allow_crate_root_in_path && !this_tree_starts_with_crate_root,
+ )? {
+ Some(tree) if !has_any_crate_root_in_path => items.push_value(tree),
+ _ => has_any_crate_root_in_path = true,
+ }
+ if content.is_empty() {
+ break;
+ }
+ let comma: Token![,] = content.parse()?;
+ if !has_any_crate_root_in_path {
+ items.push_punct(comma);
+ }
+ }
+ if has_any_crate_root_in_path {
+ Ok(None)
+ } else {
+ Ok(Some(UseTree::Group(UseGroup { brace_token, items })))
+ }
+ } else {
+ Err(lookahead.error())
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ItemStatic {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Ok(ItemStatic {
+ attrs: input.call(Attribute::parse_outer)?,
+ vis: input.parse()?,
+ static_token: input.parse()?,
+ mutability: input.parse()?,
+ ident: input.parse()?,
+ colon_token: input.parse()?,
+ ty: input.parse()?,
+ eq_token: input.parse()?,
+ expr: input.parse()?,
+ semi_token: input.parse()?,
+ })
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ItemConst {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let attrs = input.call(Attribute::parse_outer)?;
+ let vis: Visibility = input.parse()?;
+ let const_token: Token![const] = input.parse()?;
+
+ let lookahead = input.lookahead1();
+ let ident = if lookahead.peek(Ident) || lookahead.peek(Token![_]) {
+ input.call(Ident::parse_any)?
+ } else {
+ return Err(lookahead.error());
+ };
+
+ let colon_token: Token![:] = input.parse()?;
+ let ty: Type = input.parse()?;
+ let eq_token: Token![=] = input.parse()?;
+ let expr: Expr = input.parse()?;
+ let semi_token: Token![;] = input.parse()?;
+
+ Ok(ItemConst {
+ attrs,
+ vis,
+ const_token,
+ ident,
+ generics: Generics::default(),
+ colon_token,
+ ty: Box::new(ty),
+ eq_token,
+ expr: Box::new(expr),
+ semi_token,
+ })
+ }
+ }
+
+ fn peek_signature(input: ParseStream, allow_safe: bool) -> bool {
+ let fork = input.fork();
+ fork.parse::<Option<Token![const]>>().is_ok()
+ && fork.parse::<Option<Token![async]>>().is_ok()
+ && ((allow_safe
+ && token::parsing::peek_keyword(fork.cursor(), "safe")
+ && token::parsing::keyword(&fork, "safe").is_ok())
+ || fork.parse::<Option<Token![unsafe]>>().is_ok())
+ && fork.parse::<Option<Abi>>().is_ok()
+ && fork.peek(Token![fn])
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for Signature {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let allow_safe = false;
+ parse_signature(input, allow_safe).map(Option::unwrap)
+ }
+ }
+
+ fn parse_signature(input: ParseStream, allow_safe: bool) -> Result<Option<Signature>> {
+ let constness: Option<Token![const]> = input.parse()?;
+ let asyncness: Option<Token![async]> = input.parse()?;
+ let unsafety: Option<Token![unsafe]> = input.parse()?;
+ let safe = allow_safe
+ && unsafety.is_none()
+ && token::parsing::peek_keyword(input.cursor(), "safe");
+ if safe {
+ token::parsing::keyword(input, "safe")?;
+ }
+ let abi: Option<Abi> = input.parse()?;
+ let fn_token: Token![fn] = input.parse()?;
+ let ident: Ident = input.parse()?;
+ let mut generics: Generics = input.parse()?;
+
+ let content;
+ let paren_token = parenthesized!(content in input);
+ let (inputs, variadic) = parse_fn_args(&content)?;
+
+ let output: ReturnType = input.parse()?;
+ generics.where_clause = input.parse()?;
+
+ Ok(if safe {
+ None
+ } else {
+ Some(Signature {
+ constness,
+ asyncness,
+ unsafety,
+ abi,
+ fn_token,
+ ident,
+ generics,
+ paren_token,
+ inputs,
+ variadic,
+ output,
+ })
+ })
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ItemFn {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let outer_attrs = input.call(Attribute::parse_outer)?;
+ let vis: Visibility = input.parse()?;
+ let sig: Signature = input.parse()?;
+ parse_rest_of_fn(input, outer_attrs, vis, sig)
+ }
+ }
+
+ fn parse_rest_of_fn(
+ input: ParseStream,
+ mut attrs: Vec<Attribute>,
+ vis: Visibility,
+ sig: Signature,
+ ) -> Result<ItemFn> {
+ let content;
+ let brace_token = braced!(content in input);
+ attr::parsing::parse_inner(&content, &mut attrs)?;
+ let stmts = content.call(Block::parse_within)?;
+
+ Ok(ItemFn {
+ attrs,
+ vis,
+ sig,
+ block: Box::new(Block { brace_token, stmts }),
+ })
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for FnArg {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let allow_variadic = false;
+ let attrs = input.call(Attribute::parse_outer)?;
+ match parse_fn_arg_or_variadic(input, attrs, allow_variadic)? {
+ FnArgOrVariadic::FnArg(arg) => Ok(arg),
+ FnArgOrVariadic::Variadic(_) => unreachable!(),
+ }
+ }
+ }
+
+ enum FnArgOrVariadic {
+ FnArg(FnArg),
+ Variadic(Variadic),
+ }
+
+ fn parse_fn_arg_or_variadic(
+ input: ParseStream,
+ attrs: Vec<Attribute>,
+ allow_variadic: bool,
+ ) -> Result<FnArgOrVariadic> {
+ let ahead = input.fork();
+ if let Ok(mut receiver) = ahead.parse::<Receiver>() {
+ input.advance_to(&ahead);
+ receiver.attrs = attrs;
+ return Ok(FnArgOrVariadic::FnArg(FnArg::Receiver(receiver)));
+ }
+
+ // Hack to parse pre-2018 syntax in
+ // test/ui/rfc-2565-param-attrs/param-attrs-pretty.rs
+ // because the rest of the test case is valuable.
+ if input.peek(Ident) && input.peek2(Token![<]) {
+ let span = input.span();
+ return Ok(FnArgOrVariadic::FnArg(FnArg::Typed(PatType {
+ attrs,
+ pat: Box::new(Pat::Wild(PatWild {
+ attrs: Vec::new(),
+ underscore_token: Token,
+ })),
+ colon_token: Token,
+ ty: input.parse()?,
+ })));
+ }
+
+ let pat = Box::new(Pat::parse_single(input)?);
+ let colon_token: Token![:] = input.parse()?;
+
+ if allow_variadic {
+ if let Some(dots) = input.parse::<Option<Token![...]>>()? {
+ return Ok(FnArgOrVariadic::Variadic(Variadic {
+ attrs,
+ pat: Some((pat, colon_token)),
+ dots,
+ comma: None,
+ }));
+ }
+ }
+
+ Ok(FnArgOrVariadic::FnArg(FnArg::Typed(PatType {
+ attrs,
+ pat,
+ colon_token,
+ ty: input.parse()?,
+ })))
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for Receiver {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let reference = if input.peek(Token![&]) {
+ let ampersand: Token![&] = input.parse()?;
+ let lifetime: Option<Lifetime> = input.parse()?;
+ Some((ampersand, lifetime))
+ } else {
+ None
+ };
+ let mutability: Option<Token![mut]> = input.parse()?;
+ let self_token: Token![self] = input.parse()?;
+ let colon_token: Option<Token![:]> = if reference.is_some() {
+ None
+ } else {
+ input.parse()?
+ };
+ let ty: Type = if colon_token.is_some() {
+ input.parse()?
+ } else {
+ let mut ty = Type::Path(TypePath {
+ qself: None,
+ path: Path::from(Ident::new("Self", self_token.span)),
+ });
+ if let Some((ampersand, lifetime)) = reference.as_ref() {
+ ty = Type::Reference(TypeReference {
+ and_token: Token,
+ lifetime: lifetime.clone(),
+ mutability: mutability.as_ref().map(|m| Token),
+ elem: Box::new(ty),
+ });
+ }
+ ty
+ };
+ Ok(Receiver {
+ attrs: Vec::new(),
+ reference,
+ mutability,
+ self_token,
+ colon_token,
+ ty: Box::new(ty),
+ })
+ }
+ }
+
+ fn parse_fn_args(
+ input: ParseStream,
+ ) -> Result<(Punctuated<FnArg, Token![,]>, Option<Variadic>)> {
+ let mut args = Punctuated::new();
+ let mut variadic = None;
+ let mut has_receiver = false;
+
+ while !input.is_empty() {
+ let attrs = input.call(Attribute::parse_outer)?;
+
+ if let Some(dots) = input.parse::<Option<Token![...]>>()? {
+ variadic = Some(Variadic {
+ attrs,
+ pat: None,
+ dots,
+ comma: if input.is_empty() {
+ None
+ } else {
+ Some(input.parse()?)
+ },
+ });
+ break;
+ }
+
+ let allow_variadic = true;
+ let arg = match parse_fn_arg_or_variadic(input, attrs, allow_variadic)? {
+ FnArgOrVariadic::FnArg(arg) => arg,
+ FnArgOrVariadic::Variadic(arg) => {
+ variadic = Some(Variadic {
+ comma: if input.is_empty() {
+ None
+ } else {
+ Some(input.parse()?)
+ },
+ ..arg
+ });
+ break;
+ }
+ };
+
+ match &arg {
+ FnArg::Receiver(receiver) if has_receiver => {
+ return Err(Error::new(
+ receiver.self_token.span,
+ "unexpected second method receiver",
+ ));
+ }
+ FnArg::Receiver(receiver) if !args.is_empty() => {
+ return Err(Error::new(
+ receiver.self_token.span,
+ "unexpected method receiver",
+ ));
+ }
+ FnArg::Receiver(_) => has_receiver = true,
+ FnArg::Typed(_) => {}
+ }
+ args.push_value(arg);
+
+ if input.is_empty() {
+ break;
+ }
+
+ let comma: Token![,] = input.parse()?;
+ args.push_punct(comma);
+ }
+
+ Ok((args, variadic))
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ItemMod {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let mut attrs = input.call(Attribute::parse_outer)?;
+ let vis: Visibility = input.parse()?;
+ let unsafety: Option<Token![unsafe]> = input.parse()?;
+ let mod_token: Token![mod] = input.parse()?;
+ let ident: Ident = if input.peek(Token![try]) {
+ input.call(Ident::parse_any)
+ } else {
+ input.parse()
+ }?;
+
+ let lookahead = input.lookahead1();
+ if lookahead.peek(Token![;]) {
+ Ok(ItemMod {
+ attrs,
+ vis,
+ unsafety,
+ mod_token,
+ ident,
+ content: None,
+ semi: Some(input.parse()?),
+ })
+ } else if lookahead.peek(token::Brace) {
+ let content;
+ let brace_token = braced!(content in input);
+ attr::parsing::parse_inner(&content, &mut attrs)?;
+
+ let mut items = Vec::new();
+ while !content.is_empty() {
+ items.push(content.parse()?);
+ }
+
+ Ok(ItemMod {
+ attrs,
+ vis,
+ unsafety,
+ mod_token,
+ ident,
+ content: Some((brace_token, items)),
+ semi: None,
+ })
+ } else {
+ Err(lookahead.error())
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ItemForeignMod {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let mut attrs = input.call(Attribute::parse_outer)?;
+ let unsafety: Option<Token![unsafe]> = input.parse()?;
+ let abi: Abi = input.parse()?;
+
+ let content;
+ let brace_token = braced!(content in input);
+ attr::parsing::parse_inner(&content, &mut attrs)?;
+ let mut items = Vec::new();
+ while !content.is_empty() {
+ items.push(content.parse()?);
+ }
+
+ Ok(ItemForeignMod {
+ attrs,
+ unsafety,
+ abi,
+ brace_token,
+ items,
+ })
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ForeignItem {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let begin = input.fork();
+ let mut attrs = input.call(Attribute::parse_outer)?;
+ let ahead = input.fork();
+ let vis: Visibility = ahead.parse()?;
+
+ let lookahead = ahead.lookahead1();
+ let allow_safe = true;
+ let mut item = if lookahead.peek(Token![fn]) || peek_signature(&ahead, allow_safe) {
+ let vis: Visibility = input.parse()?;
+ let sig = parse_signature(input, allow_safe)?;
+ let has_safe = sig.is_none();
+ let has_body = input.peek(token::Brace);
+ let semi_token: Option<Token![;]> = if has_body {
+ let content;
+ braced!(content in input);
+ content.call(Attribute::parse_inner)?;
+ content.call(Block::parse_within)?;
+ None
+ } else {
+ Some(input.parse()?)
+ };
+ if has_safe || has_body {
+ Ok(ForeignItem::Verbatim(verbatim::between(&begin, input)))
+ } else {
+ Ok(ForeignItem::Fn(ForeignItemFn {
+ attrs: Vec::new(),
+ vis,
+ sig: sig.unwrap(),
+ semi_token: semi_token.unwrap(),
+ }))
+ }
+ } else if lookahead.peek(Token![static])
+ || ((ahead.peek(Token![unsafe])
+ || token::parsing::peek_keyword(ahead.cursor(), "safe"))
+ && ahead.peek2(Token![static]))
+ {
+ let vis = input.parse()?;
+ let unsafety: Option<Token![unsafe]> = input.parse()?;
+ let safe =
+ unsafety.is_none() && token::parsing::peek_keyword(input.cursor(), "safe");
+ if safe {
+ token::parsing::keyword(input, "safe")?;
+ }
+ let static_token = input.parse()?;
+ let mutability = input.parse()?;
+ let ident = input.parse()?;
+ let colon_token = input.parse()?;
+ let ty = input.parse()?;
+ let has_value = input.peek(Token![=]);
+ if has_value {
+ input.parse::<Token![=]>()?;
+ input.parse::<Expr>()?;
+ }
+ let semi_token: Token![;] = input.parse()?;
+ if unsafety.is_some() || safe || has_value {
+ Ok(ForeignItem::Verbatim(verbatim::between(&begin, input)))
+ } else {
+ Ok(ForeignItem::Static(ForeignItemStatic {
+ attrs: Vec::new(),
+ vis,
+ static_token,
+ mutability,
+ ident,
+ colon_token,
+ ty,
+ semi_token,
+ }))
+ }
+ } else if lookahead.peek(Token![type]) {
+ parse_foreign_item_type(begin, input)
+ } else if vis.is_inherited()
+ && (lookahead.peek(Ident)
+ || lookahead.peek(Token![self])
+ || lookahead.peek(Token![super])
+ || lookahead.peek(Token![crate])
+ || lookahead.peek(Token![::]))
+ {
+ input.parse().map(ForeignItem::Macro)
+ } else {
+ Err(lookahead.error())
+ }?;
+
+ let item_attrs = match &mut item {
+ ForeignItem::Fn(item) => &mut item.attrs,
+ ForeignItem::Static(item) => &mut item.attrs,
+ ForeignItem::Type(item) => &mut item.attrs,
+ ForeignItem::Macro(item) => &mut item.attrs,
+ ForeignItem::Verbatim(_) => return Ok(item),
+ };
+ attrs.append(item_attrs);
+ *item_attrs = attrs;
+
+ Ok(item)
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ForeignItemFn {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let attrs = input.call(Attribute::parse_outer)?;
+ let vis: Visibility = input.parse()?;
+ let sig: Signature = input.parse()?;
+ let semi_token: Token![;] = input.parse()?;
+ Ok(ForeignItemFn {
+ attrs,
+ vis,
+ sig,
+ semi_token,
+ })
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ForeignItemStatic {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Ok(ForeignItemStatic {
+ attrs: input.call(Attribute::parse_outer)?,
+ vis: input.parse()?,
+ static_token: input.parse()?,
+ mutability: input.parse()?,
+ ident: input.parse()?,
+ colon_token: input.parse()?,
+ ty: input.parse()?,
+ semi_token: input.parse()?,
+ })
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ForeignItemType {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Ok(ForeignItemType {
+ attrs: input.call(Attribute::parse_outer)?,
+ vis: input.parse()?,
+ type_token: input.parse()?,
+ ident: input.parse()?,
+ generics: {
+ let mut generics: Generics = input.parse()?;
+ generics.where_clause = input.parse()?;
+ generics
+ },
+ semi_token: input.parse()?,
+ })
+ }
+ }
+
+ fn parse_foreign_item_type(begin: ParseBuffer, input: ParseStream) -> Result<ForeignItem> {
+ let FlexibleItemType {
+ vis,
+ defaultness: _,
+ type_token,
+ ident,
+ generics,
+ colon_token,
+ bounds: _,
+ ty,
+ semi_token,
+ } = FlexibleItemType::parse(
+ input,
+ TypeDefaultness::Disallowed,
+ WhereClauseLocation::Both,
+ )?;
+
+ if colon_token.is_some() || ty.is_some() {
+ Ok(ForeignItem::Verbatim(verbatim::between(&begin, input)))
+ } else {
+ Ok(ForeignItem::Type(ForeignItemType {
+ attrs: Vec::new(),
+ vis,
+ type_token,
+ ident,
+ generics,
+ semi_token,
+ }))
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ForeignItemMacro {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let attrs = input.call(Attribute::parse_outer)?;
+ let mac: Macro = input.parse()?;
+ let semi_token: Option<Token![;]> = if mac.delimiter.is_brace() {
+ None
+ } else {
+ Some(input.parse()?)
+ };
+ Ok(ForeignItemMacro {
+ attrs,
+ mac,
+ semi_token,
+ })
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ItemType {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Ok(ItemType {
+ attrs: input.call(Attribute::parse_outer)?,
+ vis: input.parse()?,
+ type_token: input.parse()?,
+ ident: input.parse()?,
+ generics: {
+ let mut generics: Generics = input.parse()?;
+ generics.where_clause = input.parse()?;
+ generics
+ },
+ eq_token: input.parse()?,
+ ty: input.parse()?,
+ semi_token: input.parse()?,
+ })
+ }
+ }
+
+ fn parse_item_type(begin: ParseBuffer, input: ParseStream) -> Result<Item> {
+ let FlexibleItemType {
+ vis,
+ defaultness: _,
+ type_token,
+ ident,
+ generics,
+ colon_token,
+ bounds: _,
+ ty,
+ semi_token,
+ } = FlexibleItemType::parse(
+ input,
+ TypeDefaultness::Disallowed,
+ WhereClauseLocation::BeforeEq,
+ )?;
+
+ let (eq_token, ty) = match ty {
+ Some(ty) if colon_token.is_none() => ty,
+ _ => return Ok(Item::Verbatim(verbatim::between(&begin, input))),
+ };
+
+ Ok(Item::Type(ItemType {
+ attrs: Vec::new(),
+ vis,
+ type_token,
+ ident,
+ generics,
+ eq_token,
+ ty: Box::new(ty),
+ semi_token,
+ }))
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ItemStruct {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let attrs = input.call(Attribute::parse_outer)?;
+ let vis = input.parse::<Visibility>()?;
+ let struct_token = input.parse::<Token![struct]>()?;
+ let ident = input.parse::<Ident>()?;
+ let generics = input.parse::<Generics>()?;
+ let (where_clause, fields, semi_token) = derive::parsing::data_struct(input)?;
+ Ok(ItemStruct {
+ attrs,
+ vis,
+ struct_token,
+ ident,
+ generics: Generics {
+ where_clause,
+ ..generics
+ },
+ fields,
+ semi_token,
+ })
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ItemEnum {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let attrs = input.call(Attribute::parse_outer)?;
+ let vis = input.parse::<Visibility>()?;
+ let enum_token = input.parse::<Token![enum]>()?;
+ let ident = input.parse::<Ident>()?;
+ let generics = input.parse::<Generics>()?;
+ let (where_clause, brace_token, variants) = derive::parsing::data_enum(input)?;
+ Ok(ItemEnum {
+ attrs,
+ vis,
+ enum_token,
+ ident,
+ generics: Generics {
+ where_clause,
+ ..generics
+ },
+ brace_token,
+ variants,
+ })
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ItemUnion {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let attrs = input.call(Attribute::parse_outer)?;
+ let vis = input.parse::<Visibility>()?;
+ let union_token = input.parse::<Token![union]>()?;
+ let ident = input.parse::<Ident>()?;
+ let generics = input.parse::<Generics>()?;
+ let (where_clause, fields) = derive::parsing::data_union(input)?;
+ Ok(ItemUnion {
+ attrs,
+ vis,
+ union_token,
+ ident,
+ generics: Generics {
+ where_clause,
+ ..generics
+ },
+ fields,
+ })
+ }
+ }
+
+ fn parse_trait_or_trait_alias(input: ParseStream) -> Result<Item> {
+ let (attrs, vis, trait_token, ident, generics) = parse_start_of_trait_alias(input)?;
+ let lookahead = input.lookahead1();
+ if lookahead.peek(token::Brace)
+ || lookahead.peek(Token![:])
+ || lookahead.peek(Token![where])
+ {
+ let unsafety = None;
+ let auto_token = None;
+ parse_rest_of_trait(
+ input,
+ attrs,
+ vis,
+ unsafety,
+ auto_token,
+ trait_token,
+ ident,
+ generics,
+ )
+ .map(Item::Trait)
+ } else if lookahead.peek(Token![=]) {
+ parse_rest_of_trait_alias(input, attrs, vis, trait_token, ident, generics)
+ .map(Item::TraitAlias)
+ } else {
+ Err(lookahead.error())
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ItemTrait {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let outer_attrs = input.call(Attribute::parse_outer)?;
+ let vis: Visibility = input.parse()?;
+ let unsafety: Option<Token![unsafe]> = input.parse()?;
+ let auto_token: Option<Token![auto]> = input.parse()?;
+ let trait_token: Token![trait] = input.parse()?;
+ let ident: Ident = input.parse()?;
+ let generics: Generics = input.parse()?;
+ parse_rest_of_trait(
+ input,
+ outer_attrs,
+ vis,
+ unsafety,
+ auto_token,
+ trait_token,
+ ident,
+ generics,
+ )
+ }
+ }
+
+ fn parse_rest_of_trait(
+ input: ParseStream,
+ mut attrs: Vec<Attribute>,
+ vis: Visibility,
+ unsafety: Option<Token![unsafe]>,
+ auto_token: Option<Token![auto]>,
+ trait_token: Token![trait],
+ ident: Ident,
+ mut generics: Generics,
+ ) -> Result<ItemTrait> {
+ let colon_token: Option<Token![:]> = input.parse()?;
+
+ let mut supertraits = Punctuated::new();
+ if colon_token.is_some() {
+ loop {
+ if input.peek(Token![where]) || input.peek(token::Brace) {
+ break;
+ }
+ supertraits.push_value({
+ let allow_precise_capture = false;
+ let allow_const = true;
+ TypeParamBound::parse_single(input, allow_precise_capture, allow_const)?
+ });
+ if input.peek(Token![where]) || input.peek(token::Brace) {
+ break;
+ }
+ supertraits.push_punct(input.parse()?);
+ }
+ }
+
+ generics.where_clause = input.parse()?;
+
+ let content;
+ let brace_token = braced!(content in input);
+ attr::parsing::parse_inner(&content, &mut attrs)?;
+ let mut items = Vec::new();
+ while !content.is_empty() {
+ items.push(content.parse()?);
+ }
+
+ Ok(ItemTrait {
+ attrs,
+ vis,
+ unsafety,
+ auto_token,
+ restriction: None,
+ trait_token,
+ ident,
+ generics,
+ colon_token,
+ supertraits,
+ brace_token,
+ items,
+ })
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ItemTraitAlias {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let (attrs, vis, trait_token, ident, generics) = parse_start_of_trait_alias(input)?;
+ parse_rest_of_trait_alias(input, attrs, vis, trait_token, ident, generics)
+ }
+ }
+
+ fn parse_start_of_trait_alias(
+ input: ParseStream,
+ ) -> Result<(Vec<Attribute>, Visibility, Token![trait], Ident, Generics)> {
+ let attrs = input.call(Attribute::parse_outer)?;
+ let vis: Visibility = input.parse()?;
+ let trait_token: Token![trait] = input.parse()?;
+ let ident: Ident = input.parse()?;
+ let generics: Generics = input.parse()?;
+ Ok((attrs, vis, trait_token, ident, generics))
+ }
+
+ fn parse_rest_of_trait_alias(
+ input: ParseStream,
+ attrs: Vec<Attribute>,
+ vis: Visibility,
+ trait_token: Token![trait],
+ ident: Ident,
+ mut generics: Generics,
+ ) -> Result<ItemTraitAlias> {
+ let eq_token: Token![=] = input.parse()?;
+
+ let mut bounds = Punctuated::new();
+ loop {
+ if input.peek(Token![where]) || input.peek(Token![;]) {
+ break;
+ }
+ bounds.push_value({
+ let allow_precise_capture = false;
+ let allow_const = false;
+ TypeParamBound::parse_single(input, allow_precise_capture, allow_const)?
+ });
+ if input.peek(Token![where]) || input.peek(Token![;]) {
+ break;
+ }
+ bounds.push_punct(input.parse()?);
+ }
+
+ generics.where_clause = input.parse()?;
+ let semi_token: Token![;] = input.parse()?;
+
+ Ok(ItemTraitAlias {
+ attrs,
+ vis,
+ trait_token,
+ ident,
+ generics,
+ eq_token,
+ bounds,
+ semi_token,
+ })
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for TraitItem {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let begin = input.fork();
+ let mut attrs = input.call(Attribute::parse_outer)?;
+ let vis: Visibility = input.parse()?;
+ let defaultness: Option<Token![default]> = input.parse()?;
+ let ahead = input.fork();
+
+ let lookahead = ahead.lookahead1();
+ let allow_safe = false;
+ let mut item = if lookahead.peek(Token![fn]) || peek_signature(&ahead, allow_safe) {
+ input.parse().map(TraitItem::Fn)
+ } else if lookahead.peek(Token![const]) {
+ let const_token: Token![const] = ahead.parse()?;
+ let lookahead = ahead.lookahead1();
+ if lookahead.peek(Ident) || lookahead.peek(Token![_]) {
+ input.advance_to(&ahead);
+ let ident = input.call(Ident::parse_any)?;
+ let mut generics: Generics = input.parse()?;
+ let colon_token: Token![:] = input.parse()?;
+ let ty: Type = input.parse()?;
+ let default = if let Some(eq_token) = input.parse::<Option<Token![=]>>()? {
+ let expr: Expr = input.parse()?;
+ Some((eq_token, expr))
+ } else {
+ None
+ };
+ generics.where_clause = input.parse()?;
+ let semi_token: Token![;] = input.parse()?;
+ if generics.lt_token.is_none() && generics.where_clause.is_none() {
+ Ok(TraitItem::Const(TraitItemConst {
+ attrs: Vec::new(),
+ const_token,
+ ident,
+ generics,
+ colon_token,
+ ty,
+ default,
+ semi_token,
+ }))
+ } else {
+ return Ok(TraitItem::Verbatim(verbatim::between(&begin, input)));
+ }
+ } else if lookahead.peek(Token![async])
+ || lookahead.peek(Token![unsafe])
+ || lookahead.peek(Token![extern])
+ || lookahead.peek(Token![fn])
+ {
+ input.parse().map(TraitItem::Fn)
+ } else {
+ Err(lookahead.error())
+ }
+ } else if lookahead.peek(Token![type]) {
+ parse_trait_item_type(begin.fork(), input)
+ } else if vis.is_inherited()
+ && defaultness.is_none()
+ && (lookahead.peek(Ident)
+ || lookahead.peek(Token![self])
+ || lookahead.peek(Token![super])
+ || lookahead.peek(Token![crate])
+ || lookahead.peek(Token![::]))
+ {
+ input.parse().map(TraitItem::Macro)
+ } else {
+ Err(lookahead.error())
+ }?;
+
+ match (vis, defaultness) {
+ (Visibility::Inherited, None) => {}
+ _ => return Ok(TraitItem::Verbatim(verbatim::between(&begin, input))),
+ }
+
+ let item_attrs = match &mut item {
+ TraitItem::Const(item) => &mut item.attrs,
+ TraitItem::Fn(item) => &mut item.attrs,
+ TraitItem::Type(item) => &mut item.attrs,
+ TraitItem::Macro(item) => &mut item.attrs,
+ TraitItem::Verbatim(_) => unreachable!(),
+ };
+ attrs.append(item_attrs);
+ *item_attrs = attrs;
+ Ok(item)
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for TraitItemConst {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let attrs = input.call(Attribute::parse_outer)?;
+ let const_token: Token![const] = input.parse()?;
+
+ let lookahead = input.lookahead1();
+ let ident = if lookahead.peek(Ident) || lookahead.peek(Token![_]) {
+ input.call(Ident::parse_any)?
+ } else {
+ return Err(lookahead.error());
+ };
+
+ let colon_token: Token![:] = input.parse()?;
+ let ty: Type = input.parse()?;
+ let default = if input.peek(Token![=]) {
+ let eq_token: Token![=] = input.parse()?;
+ let default: Expr = input.parse()?;
+ Some((eq_token, default))
+ } else {
+ None
+ };
+ let semi_token: Token![;] = input.parse()?;
+
+ Ok(TraitItemConst {
+ attrs,
+ const_token,
+ ident,
+ generics: Generics::default(),
+ colon_token,
+ ty,
+ default,
+ semi_token,
+ })
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for TraitItemFn {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let mut attrs = input.call(Attribute::parse_outer)?;
+ let sig: Signature = input.parse()?;
+
+ let lookahead = input.lookahead1();
+ let (brace_token, stmts, semi_token) = if lookahead.peek(token::Brace) {
+ let content;
+ let brace_token = braced!(content in input);
+ attr::parsing::parse_inner(&content, &mut attrs)?;
+ let stmts = content.call(Block::parse_within)?;
+ (Some(brace_token), stmts, None)
+ } else if lookahead.peek(Token![;]) {
+ let semi_token: Token![;] = input.parse()?;
+ (None, Vec::new(), Some(semi_token))
+ } else {
+ return Err(lookahead.error());
+ };
+
+ Ok(TraitItemFn {
+ attrs,
+ sig,
+ default: brace_token.map(|brace_token| Block { brace_token, stmts }),
+ semi_token,
+ })
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for TraitItemType {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let attrs = input.call(Attribute::parse_outer)?;
+ let type_token: Token![type] = input.parse()?;
+ let ident: Ident = input.parse()?;
+ let mut generics: Generics = input.parse()?;
+ let (colon_token, bounds) = FlexibleItemType::parse_optional_bounds(input)?;
+ let default = FlexibleItemType::parse_optional_definition(input)?;
+ generics.where_clause = input.parse()?;
+ let semi_token: Token![;] = input.parse()?;
+ Ok(TraitItemType {
+ attrs,
+ type_token,
+ ident,
+ generics,
+ colon_token,
+ bounds,
+ default,
+ semi_token,
+ })
+ }
+ }
+
+ fn parse_trait_item_type(begin: ParseBuffer, input: ParseStream) -> Result<TraitItem> {
+ let FlexibleItemType {
+ vis,
+ defaultness: _,
+ type_token,
+ ident,
+ generics,
+ colon_token,
+ bounds,
+ ty,
+ semi_token,
+ } = FlexibleItemType::parse(
+ input,
+ TypeDefaultness::Disallowed,
+ WhereClauseLocation::AfterEq,
+ )?;
+
+ if vis.is_some() {
+ Ok(TraitItem::Verbatim(verbatim::between(&begin, input)))
+ } else {
+ Ok(TraitItem::Type(TraitItemType {
+ attrs: Vec::new(),
+ type_token,
+ ident,
+ generics,
+ colon_token,
+ bounds,
+ default: ty,
+ semi_token,
+ }))
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for TraitItemMacro {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let attrs = input.call(Attribute::parse_outer)?;
+ let mac: Macro = input.parse()?;
+ let semi_token: Option<Token![;]> = if mac.delimiter.is_brace() {
+ None
+ } else {
+ Some(input.parse()?)
+ };
+ Ok(TraitItemMacro {
+ attrs,
+ mac,
+ semi_token,
+ })
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ItemImpl {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let allow_verbatim_impl = false;
+ parse_impl(input, allow_verbatim_impl).map(Option::unwrap)
+ }
+ }
+
+ fn parse_impl(input: ParseStream, allow_verbatim_impl: bool) -> Result<Option<ItemImpl>> {
+ let mut attrs = input.call(Attribute::parse_outer)?;
+ let has_visibility = allow_verbatim_impl && input.parse::<Visibility>()?.is_some();
+ let defaultness: Option<Token![default]> = input.parse()?;
+ let unsafety: Option<Token![unsafe]> = input.parse()?;
+ let impl_token: Token![impl] = input.parse()?;
+
+ let has_generics = generics::parsing::choose_generics_over_qpath(input);
+ let mut generics: Generics = if has_generics {
+ input.parse()?
+ } else {
+ Generics::default()
+ };
+
+ let is_const_impl = allow_verbatim_impl
+ && (input.peek(Token![const]) || input.peek(Token![?]) && input.peek2(Token![const]));
+ if is_const_impl {
+ input.parse::<Option<Token![?]>>()?;
+ input.parse::<Token![const]>()?;
+ }
+
+ let polarity = if input.peek(Token![!]) && !input.peek2(token::Brace) {
+ Some(input.parse::<Token![!]>()?)
+ } else {
+ None
+ };
+
+ #[cfg(not(feature = "printing"))]
+ let first_ty_span = input.span();
+ let mut first_ty: Type = input.parse()?;
+ let self_ty: Type;
+ let trait_;
+
+ let is_impl_for = input.peek(Token![for]);
+ if is_impl_for {
+ let for_token: Token![for] = input.parse()?;
+ let mut first_ty_ref = &first_ty;
+ while let Type::Group(ty) = first_ty_ref {
+ first_ty_ref = &ty.elem;
+ }
+ if let Type::Path(TypePath { qself: None, .. }) = first_ty_ref {
+ while let Type::Group(ty) = first_ty {
+ first_ty = *ty.elem;
+ }
+ if let Type::Path(TypePath { qself: None, path }) = first_ty {
+ trait_ = Some((polarity, path, for_token));
+ } else {
+ unreachable!();
+ }
+ } else if !allow_verbatim_impl {
+ #[cfg(feature = "printing")]
+ return Err(Error::new_spanned(first_ty_ref, "expected trait path"));
+ #[cfg(not(feature = "printing"))]
+ return Err(Error::new(first_ty_span, "expected trait path"));
+ } else {
+ trait_ = None;
+ }
+ self_ty = input.parse()?;
+ } else if let Some(polarity) = polarity {
+ return Err(Error::new(
+ polarity.span,
+ "inherent impls cannot be negative",
+ ));
+ } else {
+ trait_ = None;
+ self_ty = first_ty;
+ }
+
+ generics.where_clause = input.parse()?;
+
+ let content;
+ let brace_token = braced!(content in input);
+ attr::parsing::parse_inner(&content, &mut attrs)?;
+
+ let mut items = Vec::new();
+ while !content.is_empty() {
+ items.push(content.parse()?);
+ }
+
+ if has_visibility || is_const_impl || is_impl_for && trait_.is_none() {
+ Ok(None)
+ } else {
+ Ok(Some(ItemImpl {
+ attrs,
+ defaultness,
+ unsafety,
+ impl_token,
+ generics,
+ trait_,
+ self_ty: Box::new(self_ty),
+ brace_token,
+ items,
+ }))
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ImplItem {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let begin = input.fork();
+ let mut attrs = input.call(Attribute::parse_outer)?;
+ let ahead = input.fork();
+ let vis: Visibility = ahead.parse()?;
+
+ let mut lookahead = ahead.lookahead1();
+ let defaultness = if lookahead.peek(Token![default]) && !ahead.peek2(Token![!]) {
+ let defaultness: Token![default] = ahead.parse()?;
+ lookahead = ahead.lookahead1();
+ Some(defaultness)
+ } else {
+ None
+ };
+
+ let allow_safe = false;
+ let mut item = if lookahead.peek(Token![fn]) || peek_signature(&ahead, allow_safe) {
+ let allow_omitted_body = true;
+ if let Some(item) = parse_impl_item_fn(input, allow_omitted_body)? {
+ Ok(ImplItem::Fn(item))
+ } else {
+ Ok(ImplItem::Verbatim(verbatim::between(&begin, input)))
+ }
+ } else if lookahead.peek(Token![const]) {
+ input.advance_to(&ahead);
+ let const_token: Token![const] = input.parse()?;
+ let lookahead = input.lookahead1();
+ let ident = if lookahead.peek(Ident) || lookahead.peek(Token![_]) {
+ input.call(Ident::parse_any)?
+ } else {
+ return Err(lookahead.error());
+ };
+ let mut generics: Generics = input.parse()?;
+ let colon_token: Token![:] = input.parse()?;
+ let ty: Type = input.parse()?;
+ let value = if let Some(eq_token) = input.parse::<Option<Token![=]>>()? {
+ let expr: Expr = input.parse()?;
+ Some((eq_token, expr))
+ } else {
+ None
+ };
+ generics.where_clause = input.parse()?;
+ let semi_token: Token![;] = input.parse()?;
+ return match value {
+ Some((eq_token, expr))
+ if generics.lt_token.is_none() && generics.where_clause.is_none() =>
+ {
+ Ok(ImplItem::Const(ImplItemConst {
+ attrs,
+ vis,
+ defaultness,
+ const_token,
+ ident,
+ generics,
+ colon_token,
+ ty,
+ eq_token,
+ expr,
+ semi_token,
+ }))
+ }
+ _ => Ok(ImplItem::Verbatim(verbatim::between(&begin, input))),
+ };
+ } else if lookahead.peek(Token![type]) {
+ parse_impl_item_type(begin, input)
+ } else if vis.is_inherited()
+ && defaultness.is_none()
+ && (lookahead.peek(Ident)
+ || lookahead.peek(Token![self])
+ || lookahead.peek(Token![super])
+ || lookahead.peek(Token![crate])
+ || lookahead.peek(Token![::]))
+ {
+ input.parse().map(ImplItem::Macro)
+ } else {
+ Err(lookahead.error())
+ }?;
+
+ {
+ let item_attrs = match &mut item {
+ ImplItem::Const(item) => &mut item.attrs,
+ ImplItem::Fn(item) => &mut item.attrs,
+ ImplItem::Type(item) => &mut item.attrs,
+ ImplItem::Macro(item) => &mut item.attrs,
+ ImplItem::Verbatim(_) => return Ok(item),
+ };
+ attrs.append(item_attrs);
+ *item_attrs = attrs;
+ }
+
+ Ok(item)
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ImplItemConst {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let attrs = input.call(Attribute::parse_outer)?;
+ let vis: Visibility = input.parse()?;
+ let defaultness: Option<Token![default]> = input.parse()?;
+ let const_token: Token![const] = input.parse()?;
+
+ let lookahead = input.lookahead1();
+ let ident = if lookahead.peek(Ident) || lookahead.peek(Token![_]) {
+ input.call(Ident::parse_any)?
+ } else {
+ return Err(lookahead.error());
+ };
+
+ let colon_token: Token![:] = input.parse()?;
+ let ty: Type = input.parse()?;
+ let eq_token: Token![=] = input.parse()?;
+ let expr: Expr = input.parse()?;
+ let semi_token: Token![;] = input.parse()?;
+
+ Ok(ImplItemConst {
+ attrs,
+ vis,
+ defaultness,
+ const_token,
+ ident,
+ generics: Generics::default(),
+ colon_token,
+ ty,
+ eq_token,
+ expr,
+ semi_token,
+ })
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ImplItemFn {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let allow_omitted_body = false;
+ parse_impl_item_fn(input, allow_omitted_body).map(Option::unwrap)
+ }
+ }
+
+ fn parse_impl_item_fn(
+ input: ParseStream,
+ allow_omitted_body: bool,
+ ) -> Result<Option<ImplItemFn>> {
+ let mut attrs = input.call(Attribute::parse_outer)?;
+ let vis: Visibility = input.parse()?;
+ let defaultness: Option<Token![default]> = input.parse()?;
+ let sig: Signature = input.parse()?;
+
+ // Accept functions without a body in an impl block because rustc's
+ // *parser* does not reject them (the compilation error is emitted later
+ // than parsing) and it can be useful for macro DSLs.
+ if allow_omitted_body && input.parse::<Option<Token![;]>>()?.is_some() {
+ return Ok(None);
+ }
+
+ let content;
+ let brace_token = braced!(content in input);
+ attrs.extend(content.call(Attribute::parse_inner)?);
+ let block = Block {
+ brace_token,
+ stmts: content.call(Block::parse_within)?,
+ };
+
+ Ok(Some(ImplItemFn {
+ attrs,
+ vis,
+ defaultness,
+ sig,
+ block,
+ }))
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ImplItemType {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let attrs = input.call(Attribute::parse_outer)?;
+ let vis: Visibility = input.parse()?;
+ let defaultness: Option<Token![default]> = input.parse()?;
+ let type_token: Token![type] = input.parse()?;
+ let ident: Ident = input.parse()?;
+ let mut generics: Generics = input.parse()?;
+ let eq_token: Token![=] = input.parse()?;
+ let ty: Type = input.parse()?;
+ generics.where_clause = input.parse()?;
+ let semi_token: Token![;] = input.parse()?;
+ Ok(ImplItemType {
+ attrs,
+ vis,
+ defaultness,
+ type_token,
+ ident,
+ generics,
+ eq_token,
+ ty,
+ semi_token,
+ })
+ }
+ }
+
+ fn parse_impl_item_type(begin: ParseBuffer, input: ParseStream) -> Result<ImplItem> {
+ let FlexibleItemType {
+ vis,
+ defaultness,
+ type_token,
+ ident,
+ generics,
+ colon_token,
+ bounds: _,
+ ty,
+ semi_token,
+ } = FlexibleItemType::parse(
+ input,
+ TypeDefaultness::Optional,
+ WhereClauseLocation::AfterEq,
+ )?;
+
+ let (eq_token, ty) = match ty {
+ Some(ty) if colon_token.is_none() => ty,
+ _ => return Ok(ImplItem::Verbatim(verbatim::between(&begin, input))),
+ };
+
+ Ok(ImplItem::Type(ImplItemType {
+ attrs: Vec::new(),
+ vis,
+ defaultness,
+ type_token,
+ ident,
+ generics,
+ eq_token,
+ ty,
+ semi_token,
+ }))
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ImplItemMacro {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let attrs = input.call(Attribute::parse_outer)?;
+ let mac: Macro = input.parse()?;
+ let semi_token: Option<Token![;]> = if mac.delimiter.is_brace() {
+ None
+ } else {
+ Some(input.parse()?)
+ };
+ Ok(ImplItemMacro {
+ attrs,
+ mac,
+ semi_token,
+ })
+ }
+ }
+
+ impl Visibility {
+ fn is_inherited(&self) -> bool {
+ match self {
+ Visibility::Inherited => true,
+ _ => false,
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for StaticMutability {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let mut_token: Option<Token![mut]> = input.parse()?;
+ Ok(mut_token.map_or(StaticMutability::None, StaticMutability::Mut))
+ }
+ }
+}
+
+#[cfg(feature = "printing")]
+mod printing {
+ use crate::attr::FilterAttrs;
+ use crate::data::Fields;
+ use crate::item::{
+ ForeignItemFn, ForeignItemMacro, ForeignItemStatic, ForeignItemType, ImplItemConst,
+ ImplItemFn, ImplItemMacro, ImplItemType, ItemConst, ItemEnum, ItemExternCrate, ItemFn,
+ ItemForeignMod, ItemImpl, ItemMacro, ItemMod, ItemStatic, ItemStruct, ItemTrait,
+ ItemTraitAlias, ItemType, ItemUnion, ItemUse, Receiver, Signature, StaticMutability,
+ TraitItemConst, TraitItemFn, TraitItemMacro, TraitItemType, UseGlob, UseGroup, UseName,
+ UsePath, UseRename, Variadic,
+ };
+ use crate::mac::MacroDelimiter;
+ use crate::path;
+ use crate::path::printing::PathStyle;
+ use crate::print::TokensOrDefault;
+ use crate::ty::Type;
+ use proc_macro2::TokenStream;
+ use quote::{ToTokens, TokenStreamExt};
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ItemExternCrate {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.vis.to_tokens(tokens);
+ self.extern_token.to_tokens(tokens);
+ self.crate_token.to_tokens(tokens);
+ self.ident.to_tokens(tokens);
+ if let Some((as_token, rename)) = &self.rename {
+ as_token.to_tokens(tokens);
+ rename.to_tokens(tokens);
+ }
+ self.semi_token.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ItemUse {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.vis.to_tokens(tokens);
+ self.use_token.to_tokens(tokens);
+ self.leading_colon.to_tokens(tokens);
+ self.tree.to_tokens(tokens);
+ self.semi_token.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ItemStatic {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.vis.to_tokens(tokens);
+ self.static_token.to_tokens(tokens);
+ self.mutability.to_tokens(tokens);
+ self.ident.to_tokens(tokens);
+ self.colon_token.to_tokens(tokens);
+ self.ty.to_tokens(tokens);
+ self.eq_token.to_tokens(tokens);
+ self.expr.to_tokens(tokens);
+ self.semi_token.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ItemConst {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.vis.to_tokens(tokens);
+ self.const_token.to_tokens(tokens);
+ self.ident.to_tokens(tokens);
+ self.colon_token.to_tokens(tokens);
+ self.ty.to_tokens(tokens);
+ self.eq_token.to_tokens(tokens);
+ self.expr.to_tokens(tokens);
+ self.semi_token.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ItemFn {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.vis.to_tokens(tokens);
+ self.sig.to_tokens(tokens);
+ self.block.brace_token.surround(tokens, |tokens| {
+ tokens.append_all(self.attrs.inner());
+ tokens.append_all(&self.block.stmts);
+ });
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ItemMod {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.vis.to_tokens(tokens);
+ self.unsafety.to_tokens(tokens);
+ self.mod_token.to_tokens(tokens);
+ self.ident.to_tokens(tokens);
+ if let Some((brace, items)) = &self.content {
+ brace.surround(tokens, |tokens| {
+ tokens.append_all(self.attrs.inner());
+ tokens.append_all(items);
+ });
+ } else {
+ TokensOrDefault(&self.semi).to_tokens(tokens);
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ItemForeignMod {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.unsafety.to_tokens(tokens);
+ self.abi.to_tokens(tokens);
+ self.brace_token.surround(tokens, |tokens| {
+ tokens.append_all(self.attrs.inner());
+ tokens.append_all(&self.items);
+ });
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ItemType {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.vis.to_tokens(tokens);
+ self.type_token.to_tokens(tokens);
+ self.ident.to_tokens(tokens);
+ self.generics.to_tokens(tokens);
+ self.generics.where_clause.to_tokens(tokens);
+ self.eq_token.to_tokens(tokens);
+ self.ty.to_tokens(tokens);
+ self.semi_token.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ItemEnum {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.vis.to_tokens(tokens);
+ self.enum_token.to_tokens(tokens);
+ self.ident.to_tokens(tokens);
+ self.generics.to_tokens(tokens);
+ self.generics.where_clause.to_tokens(tokens);
+ self.brace_token.surround(tokens, |tokens| {
+ self.variants.to_tokens(tokens);
+ });
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ItemStruct {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.vis.to_tokens(tokens);
+ self.struct_token.to_tokens(tokens);
+ self.ident.to_tokens(tokens);
+ self.generics.to_tokens(tokens);
+ match &self.fields {
+ Fields::Named(fields) => {
+ self.generics.where_clause.to_tokens(tokens);
+ fields.to_tokens(tokens);
+ }
+ Fields::Unnamed(fields) => {
+ fields.to_tokens(tokens);
+ self.generics.where_clause.to_tokens(tokens);
+ TokensOrDefault(&self.semi_token).to_tokens(tokens);
+ }
+ Fields::Unit => {
+ self.generics.where_clause.to_tokens(tokens);
+ TokensOrDefault(&self.semi_token).to_tokens(tokens);
+ }
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ItemUnion {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.vis.to_tokens(tokens);
+ self.union_token.to_tokens(tokens);
+ self.ident.to_tokens(tokens);
+ self.generics.to_tokens(tokens);
+ self.generics.where_clause.to_tokens(tokens);
+ self.fields.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ItemTrait {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.vis.to_tokens(tokens);
+ self.unsafety.to_tokens(tokens);
+ self.auto_token.to_tokens(tokens);
+ self.trait_token.to_tokens(tokens);
+ self.ident.to_tokens(tokens);
+ self.generics.to_tokens(tokens);
+ if !self.supertraits.is_empty() {
+ TokensOrDefault(&self.colon_token).to_tokens(tokens);
+ self.supertraits.to_tokens(tokens);
+ }
+ self.generics.where_clause.to_tokens(tokens);
+ self.brace_token.surround(tokens, |tokens| {
+ tokens.append_all(self.attrs.inner());
+ tokens.append_all(&self.items);
+ });
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ItemTraitAlias {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.vis.to_tokens(tokens);
+ self.trait_token.to_tokens(tokens);
+ self.ident.to_tokens(tokens);
+ self.generics.to_tokens(tokens);
+ self.eq_token.to_tokens(tokens);
+ self.bounds.to_tokens(tokens);
+ self.generics.where_clause.to_tokens(tokens);
+ self.semi_token.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ItemImpl {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.defaultness.to_tokens(tokens);
+ self.unsafety.to_tokens(tokens);
+ self.impl_token.to_tokens(tokens);
+ self.generics.to_tokens(tokens);
+ if let Some((polarity, path, for_token)) = &self.trait_ {
+ polarity.to_tokens(tokens);
+ path.to_tokens(tokens);
+ for_token.to_tokens(tokens);
+ }
+ self.self_ty.to_tokens(tokens);
+ self.generics.where_clause.to_tokens(tokens);
+ self.brace_token.surround(tokens, |tokens| {
+ tokens.append_all(self.attrs.inner());
+ tokens.append_all(&self.items);
+ });
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ItemMacro {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ path::printing::print_path(tokens, &self.mac.path, PathStyle::Mod);
+ self.mac.bang_token.to_tokens(tokens);
+ self.ident.to_tokens(tokens);
+ match &self.mac.delimiter {
+ MacroDelimiter::Paren(paren) => {
+ paren.surround(tokens, |tokens| self.mac.tokens.to_tokens(tokens));
+ }
+ MacroDelimiter::Brace(brace) => {
+ brace.surround(tokens, |tokens| self.mac.tokens.to_tokens(tokens));
+ }
+ MacroDelimiter::Bracket(bracket) => {
+ bracket.surround(tokens, |tokens| self.mac.tokens.to_tokens(tokens));
+ }
+ }
+ self.semi_token.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for UsePath {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.ident.to_tokens(tokens);
+ self.colon2_token.to_tokens(tokens);
+ self.tree.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for UseName {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.ident.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for UseRename {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.ident.to_tokens(tokens);
+ self.as_token.to_tokens(tokens);
+ self.rename.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for UseGlob {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.star_token.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for UseGroup {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.brace_token.surround(tokens, |tokens| {
+ self.items.to_tokens(tokens);
+ });
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for TraitItemConst {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.const_token.to_tokens(tokens);
+ self.ident.to_tokens(tokens);
+ self.colon_token.to_tokens(tokens);
+ self.ty.to_tokens(tokens);
+ if let Some((eq_token, default)) = &self.default {
+ eq_token.to_tokens(tokens);
+ default.to_tokens(tokens);
+ }
+ self.semi_token.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for TraitItemFn {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.sig.to_tokens(tokens);
+ match &self.default {
+ Some(block) => {
+ block.brace_token.surround(tokens, |tokens| {
+ tokens.append_all(self.attrs.inner());
+ tokens.append_all(&block.stmts);
+ });
+ }
+ None => {
+ TokensOrDefault(&self.semi_token).to_tokens(tokens);
+ }
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for TraitItemType {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.type_token.to_tokens(tokens);
+ self.ident.to_tokens(tokens);
+ self.generics.to_tokens(tokens);
+ if !self.bounds.is_empty() {
+ TokensOrDefault(&self.colon_token).to_tokens(tokens);
+ self.bounds.to_tokens(tokens);
+ }
+ if let Some((eq_token, default)) = &self.default {
+ eq_token.to_tokens(tokens);
+ default.to_tokens(tokens);
+ }
+ self.generics.where_clause.to_tokens(tokens);
+ self.semi_token.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for TraitItemMacro {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.mac.to_tokens(tokens);
+ self.semi_token.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ImplItemConst {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.vis.to_tokens(tokens);
+ self.defaultness.to_tokens(tokens);
+ self.const_token.to_tokens(tokens);
+ self.ident.to_tokens(tokens);
+ self.colon_token.to_tokens(tokens);
+ self.ty.to_tokens(tokens);
+ self.eq_token.to_tokens(tokens);
+ self.expr.to_tokens(tokens);
+ self.semi_token.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ImplItemFn {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.vis.to_tokens(tokens);
+ self.defaultness.to_tokens(tokens);
+ self.sig.to_tokens(tokens);
+ self.block.brace_token.surround(tokens, |tokens| {
+ tokens.append_all(self.attrs.inner());
+ tokens.append_all(&self.block.stmts);
+ });
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ImplItemType {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.vis.to_tokens(tokens);
+ self.defaultness.to_tokens(tokens);
+ self.type_token.to_tokens(tokens);
+ self.ident.to_tokens(tokens);
+ self.generics.to_tokens(tokens);
+ self.eq_token.to_tokens(tokens);
+ self.ty.to_tokens(tokens);
+ self.generics.where_clause.to_tokens(tokens);
+ self.semi_token.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ImplItemMacro {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.mac.to_tokens(tokens);
+ self.semi_token.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ForeignItemFn {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.vis.to_tokens(tokens);
+ self.sig.to_tokens(tokens);
+ self.semi_token.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ForeignItemStatic {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.vis.to_tokens(tokens);
+ self.static_token.to_tokens(tokens);
+ self.mutability.to_tokens(tokens);
+ self.ident.to_tokens(tokens);
+ self.colon_token.to_tokens(tokens);
+ self.ty.to_tokens(tokens);
+ self.semi_token.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ForeignItemType {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.vis.to_tokens(tokens);
+ self.type_token.to_tokens(tokens);
+ self.ident.to_tokens(tokens);
+ self.generics.to_tokens(tokens);
+ self.generics.where_clause.to_tokens(tokens);
+ self.semi_token.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ForeignItemMacro {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.mac.to_tokens(tokens);
+ self.semi_token.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for Signature {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.constness.to_tokens(tokens);
+ self.asyncness.to_tokens(tokens);
+ self.unsafety.to_tokens(tokens);
+ self.abi.to_tokens(tokens);
+ self.fn_token.to_tokens(tokens);
+ self.ident.to_tokens(tokens);
+ self.generics.to_tokens(tokens);
+ self.paren_token.surround(tokens, |tokens| {
+ self.inputs.to_tokens(tokens);
+ if let Some(variadic) = &self.variadic {
+ if !self.inputs.empty_or_trailing() {
+ <Token![,]>::default().to_tokens(tokens);
+ }
+ variadic.to_tokens(tokens);
+ }
+ });
+ self.output.to_tokens(tokens);
+ self.generics.where_clause.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for Receiver {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ if let Some((ampersand, lifetime)) = &self.reference {
+ ampersand.to_tokens(tokens);
+ lifetime.to_tokens(tokens);
+ }
+ self.mutability.to_tokens(tokens);
+ self.self_token.to_tokens(tokens);
+ if let Some(colon_token) = &self.colon_token {
+ colon_token.to_tokens(tokens);
+ self.ty.to_tokens(tokens);
+ } else {
+ let consistent = match (&self.reference, &self.mutability, &*self.ty) {
+ (Some(_), mutability, Type::Reference(ty)) => {
+ mutability.is_some() == ty.mutability.is_some()
+ && match &*ty.elem {
+ Type::Path(ty) => ty.qself.is_none() && ty.path.is_ident("Self"),
+ _ => false,
+ }
+ }
+ (None, _, Type::Path(ty)) => ty.qself.is_none() && ty.path.is_ident("Self"),
+ _ => false,
+ };
+ if !consistent {
+ <Token![:]>::default().to_tokens(tokens);
+ self.ty.to_tokens(tokens);
+ }
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for Variadic {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ if let Some((pat, colon)) = &self.pat {
+ pat.to_tokens(tokens);
+ colon.to_tokens(tokens);
+ }
+ self.dots.to_tokens(tokens);
+ self.comma.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for StaticMutability {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ match self {
+ StaticMutability::None => {}
+ StaticMutability::Mut(mut_token) => mut_token.to_tokens(tokens),
+ }
+ }
+ }
+}
diff --git a/rust/syn/lib.rs b/rust/syn/lib.rs
new file mode 100644
index 000000000000..79dc9e7c3324
--- /dev/null
+++ b/rust/syn/lib.rs
@@ -0,0 +1,1011 @@
+//! [![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
+//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
+//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs
+//!
+//! <br>
+//!
+//! 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.
+//!
+//! - **Data structures** — Syn provides a complete syntax tree that can
+//! represent any valid Rust source code. The syntax tree is rooted at
+//! [`syn::File`] which represents a full source file, but there are other
+//! entry points that may be useful to procedural macros including
+//! [`syn::Item`], [`syn::Expr`] and [`syn::Type`].
+//!
+//! - **Derives** — Of particular interest to derive macros is
+//! [`syn::DeriveInput`] which is any of the three legal input items to a
+//! derive macro. An example below shows using this type in a library that can
+//! derive implementations of a user-defined trait.
+//!
+//! - **Parsing** — Parsing in Syn is built around [parser functions] with the
+//! signature `fn(ParseStream) -> Result<T>`. Every syntax tree node defined
+//! by Syn is individually parsable and may be used as a building block for
+//! custom syntaxes, or you may dream up your own brand new syntax without
+//! involving any of our syntax tree types.
+//!
+//! - **Location information** — Every token parsed by Syn is associated with a
+//! `Span` that tracks line and column information back to the source of that
+//! token. These spans allow a procedural macro to display detailed error
+//! messages pointing to all the right places in the user's code. There is an
+//! example of this below.
+//!
+//! - **Feature flags** — Functionality is aggressively feature gated so your
+//! procedural macros enable only what they need, and do not pay in compile
+//! time for all the rest.
+//!
+//! [`syn::File`]: File
+//! [`syn::Item`]: Item
+//! [`syn::Expr`]: Expr
+//! [`syn::Type`]: Type
+//! [`syn::DeriveInput`]: DeriveInput
+//! [parser functions]: mod@parse
+//!
+//! <br>
+//!
+//! # Example of a derive macro
+//!
+//! The canonical derive macro using Syn looks like this. We write an ordinary
+//! Rust function tagged with a `proc_macro_derive` attribute and the name of
+//! the trait we are deriving. Any time that derive appears in the user's code,
+//! the Rust compiler passes their data structure as tokens into our macro. We
+//! get to execute arbitrary Rust code to figure out what to do with those
+//! tokens, then hand some tokens back to the compiler to compile into the
+//! user's crate.
+//!
+//! [`TokenStream`]: proc_macro::TokenStream
+//!
+//! ```toml
+//! [dependencies]
+//! syn = "2.0"
+//! quote = "1.0"
+//!
+//! [lib]
+//! proc-macro = true
+//! ```
+//!
+//! ```
+//! # extern crate proc_macro;
+//! #
+//! use proc_macro::TokenStream;
+//! use quote::quote;
+//! use syn::{parse_macro_input, DeriveInput};
+//!
+//! # const IGNORE_TOKENS: &str = stringify! {
+//! #[proc_macro_derive(MyMacro)]
+//! # };
+//! pub fn my_macro(input: TokenStream) -> TokenStream {
+//! // Parse the input tokens into a syntax tree
+//! let input = parse_macro_input!(input as DeriveInput);
+//!
+//! // Build the output, possibly using quasi-quotation
+//! let expanded = quote! {
+//! // ...
+//! };
+//!
+//! // Hand the output tokens back to the compiler
+//! TokenStream::from(expanded)
+//! }
+//! ```
+//!
+//! The [`heapsize`] example directory shows a complete working implementation
+//! of a derive macro. The example derives a `HeapSize` trait which computes an
+//! estimate of the amount of heap memory owned by a value.
+//!
+//! [`heapsize`]: https://github.com/dtolnay/syn/tree/master/examples/heapsize
+//!
+//! ```
+//! pub trait HeapSize {
+//! /// Total number of bytes of heap memory owned by `self`.
+//! fn heap_size_of_children(&self) -> usize;
+//! }
+//! ```
+//!
+//! The derive macro allows users to write `#[derive(HeapSize)]` on data
+//! structures in their program.
+//!
+//! ```
+//! # const IGNORE_TOKENS: &str = stringify! {
+//! #[derive(HeapSize)]
+//! # };
+//! struct Demo<'a, T: ?Sized> {
+//! a: Box<T>,
+//! b: u8,
+//! c: &'a str,
+//! d: String,
+//! }
+//! ```
+//!
+//! <p><br></p>
+//!
+//! # Spans and error reporting
+//!
+//! The token-based procedural macro API provides great control over where the
+//! compiler's error messages are displayed in user code. Consider the error the
+//! user sees if one of their field types does not implement `HeapSize`.
+//!
+//! ```
+//! # const IGNORE_TOKENS: &str = stringify! {
+//! #[derive(HeapSize)]
+//! # };
+//! struct Broken {
+//! ok: String,
+//! bad: std::thread::Thread,
+//! }
+//! ```
+//!
+//! By tracking span information all the way through the expansion of a
+//! procedural macro as shown in the `heapsize` example, token-based macros in
+//! Syn are able to trigger errors that directly pinpoint the source of the
+//! problem.
+//!
+//! ```text
+//! error[E0277]: the trait bound `std::thread::Thread: HeapSize` is not satisfied
+//! --> src/main.rs:7:5
+//! |
+//! 7 | bad: std::thread::Thread,
+//! | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HeapSize` is not implemented for `Thread`
+//! ```
+//!
+//! <br>
+//!
+//! # Parsing a custom syntax
+//!
+//! The [`lazy-static`] example directory shows the implementation of a
+//! `functionlike!(...)` procedural macro in which the input tokens are parsed
+//! using Syn's parsing API.
+//!
+//! [`lazy-static`]: https://github.com/dtolnay/syn/tree/master/examples/lazy-static
+//!
+//! The example reimplements the popular `lazy_static` crate from crates.io as a
+//! procedural macro.
+//!
+//! ```
+//! # macro_rules! lazy_static {
+//! # ($($tt:tt)*) => {}
+//! # }
+//! #
+//! lazy_static! {
+//! static ref USERNAME: Regex = Regex::new("^[a-z0-9_-]{3,16}$").unwrap();
+//! }
+//! ```
+//!
+//! The implementation shows how to trigger custom warnings and error messages
+//! on the macro input.
+//!
+//! ```text
+//! warning: come on, pick a more creative name
+//! --> src/main.rs:10:16
+//! |
+//! 10 | static ref FOO: String = "lazy_static".to_owned();
+//! | ^^^
+//! ```
+//!
+//! <br>
+//!
+//! # Testing
+//!
+//! When testing macros, we often care not just that the macro can be used
+//! successfully but also that when the macro is provided with invalid input it
+//! produces maximally helpful error messages. Consider using the [`trybuild`]
+//! crate to write tests for errors that are emitted by your macro or errors
+//! detected by the Rust compiler in the expanded code following misuse of the
+//! macro. Such tests help avoid regressions from later refactors that
+//! mistakenly make an error no longer trigger or be less helpful than it used
+//! to be.
+//!
+//! [`trybuild`]: https://github.com/dtolnay/trybuild
+//!
+//! <br>
+//!
+//! # Debugging
+//!
+//! When developing a procedural macro it can be helpful to look at what the
+//! generated code looks like. Use `cargo rustc -- -Zunstable-options
+//! --pretty=expanded` or the [`cargo expand`] subcommand.
+//!
+//! [`cargo expand`]: https://github.com/dtolnay/cargo-expand
+//!
+//! To show the expanded code for some crate that uses your procedural macro,
+//! run `cargo expand` from that crate. To show the expanded code for one of
+//! your own test cases, run `cargo expand --test the_test_case` where the last
+//! argument is the name of the test file without the `.rs` extension.
+//!
+//! This write-up by Brandon W Maister discusses debugging in more detail:
+//! [Debugging Rust's new Custom Derive system][debugging].
+//!
+//! [debugging]: https://quodlibetor.github.io/posts/debugging-rusts-new-custom-derive-system/
+//!
+//! <br>
+//!
+//! # Optional features
+//!
+//! Syn puts a lot of functionality behind optional features in order to
+//! optimize compile time for the most common use cases. The following features
+//! are available.
+//!
+//! - **`derive`** *(enabled by default)* — Data structures for representing the
+//! possible input to a derive macro, including structs and enums and types.
+//! - **`full`** — Data structures for representing the syntax tree of all valid
+//! Rust source code, including items and expressions.
+//! - **`parsing`** *(enabled by default)* — Ability to parse input tokens into
+//! a syntax tree node of a chosen type.
+//! - **`printing`** *(enabled by default)* — Ability to print a syntax tree
+//! node as tokens of Rust source code.
+//! - **`visit`** — Trait for traversing a syntax tree.
+//! - **`visit-mut`** — Trait for traversing and mutating in place a syntax
+//! tree.
+//! - **`fold`** — Trait for transforming an owned syntax tree.
+//! - **`clone-impls`** *(enabled by default)* — Clone impls for all syntax tree
+//! types.
+//! - **`extra-traits`** — Debug, Eq, PartialEq, Hash impls for all syntax tree
+//! types.
+//! - **`proc-macro`** *(enabled by default)* — Runtime dependency on the
+//! dynamic library libproc_macro from rustc toolchain.
+
+// Syn types in rustdoc of other crates get linked to here.
+#![doc(html_root_url = "https://docs.rs/syn/2.0.106")]
+#![cfg_attr(docsrs, feature(doc_cfg))]
+#![deny(unsafe_op_in_unsafe_fn)]
+#![allow(non_camel_case_types)]
+#![cfg_attr(not(check_cfg), allow(unexpected_cfgs))]
+#![allow(
+ clippy::bool_to_int_with_if,
+ clippy::cast_lossless,
+ clippy::cast_possible_truncation,
+ clippy::cast_possible_wrap,
+ clippy::cast_ptr_alignment,
+ clippy::default_trait_access,
+ clippy::derivable_impls,
+ clippy::diverging_sub_expression,
+ clippy::doc_markdown,
+ clippy::elidable_lifetime_names,
+ clippy::enum_glob_use,
+ clippy::expl_impl_clone_on_copy,
+ clippy::explicit_auto_deref,
+ clippy::fn_params_excessive_bools,
+ clippy::if_not_else,
+ clippy::inherent_to_string,
+ clippy::into_iter_without_iter,
+ clippy::items_after_statements,
+ clippy::large_enum_variant,
+ clippy::let_underscore_untyped, // https://github.com/rust-lang/rust-clippy/issues/10410
+ clippy::manual_assert,
+ clippy::manual_let_else,
+ clippy::manual_map,
+ clippy::match_like_matches_macro,
+ clippy::match_same_arms,
+ clippy::match_wildcard_for_single_variants, // clippy bug: https://github.com/rust-lang/rust-clippy/issues/6984
+ clippy::missing_errors_doc,
+ clippy::missing_panics_doc,
+ clippy::module_name_repetitions,
+ clippy::must_use_candidate,
+ clippy::needless_doctest_main,
+ clippy::needless_lifetimes,
+ clippy::needless_pass_by_value,
+ clippy::needless_update,
+ clippy::never_loop,
+ clippy::range_plus_one,
+ clippy::redundant_else,
+ clippy::ref_option,
+ clippy::return_self_not_must_use,
+ clippy::similar_names,
+ clippy::single_match_else,
+ clippy::struct_excessive_bools,
+ clippy::too_many_arguments,
+ clippy::too_many_lines,
+ clippy::trivially_copy_pass_by_ref,
+ clippy::unconditional_recursion, // https://github.com/rust-lang/rust-clippy/issues/12133
+ clippy::uninhabited_references,
+ clippy::uninlined_format_args,
+ clippy::unnecessary_box_returns,
+ clippy::unnecessary_unwrap,
+ clippy::used_underscore_binding,
+ clippy::wildcard_imports,
+)]
+#![allow(unknown_lints, mismatched_lifetime_syntaxes)]
+
+extern crate self as syn;
+
+#[cfg(feature = "proc-macro")]
+extern crate proc_macro;
+
+#[macro_use]
+mod macros;
+
+#[cfg(feature = "parsing")]
+#[macro_use]
+mod group;
+
+#[macro_use]
+pub mod token;
+
+#[cfg(any(feature = "full", feature = "derive"))]
+mod attr;
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+pub use crate::attr::{AttrStyle, Attribute, Meta, MetaList, MetaNameValue};
+
+mod bigint;
+
+#[cfg(feature = "parsing")]
+#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+pub mod buffer;
+
+#[cfg(any(
+ all(feature = "parsing", feature = "full"),
+ all(feature = "printing", any(feature = "full", feature = "derive")),
+))]
+mod classify;
+
+mod custom_keyword;
+
+mod custom_punctuation;
+
+#[cfg(any(feature = "full", feature = "derive"))]
+mod data;
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+pub use crate::data::{Field, Fields, FieldsNamed, FieldsUnnamed, Variant};
+
+#[cfg(any(feature = "full", feature = "derive"))]
+mod derive;
+#[cfg(feature = "derive")]
+#[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
+pub use crate::derive::{Data, DataEnum, DataStruct, DataUnion, DeriveInput};
+
+mod drops;
+
+mod error;
+pub use crate::error::{Error, Result};
+
+#[cfg(any(feature = "full", feature = "derive"))]
+mod expr;
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub use crate::expr::{Arm, Label, PointerMutability, RangeLimits};
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+pub use crate::expr::{
+ Expr, ExprBinary, ExprCall, ExprCast, ExprField, ExprIndex, ExprLit, ExprMacro, ExprMethodCall,
+ ExprParen, ExprPath, ExprReference, ExprStruct, ExprUnary, FieldValue, Index, Member,
+};
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub use crate::expr::{
+ ExprArray, ExprAssign, ExprAsync, ExprAwait, ExprBlock, ExprBreak, ExprClosure, ExprConst,
+ ExprContinue, ExprForLoop, ExprGroup, ExprIf, ExprInfer, ExprLet, ExprLoop, ExprMatch,
+ ExprRange, ExprRawAddr, ExprRepeat, ExprReturn, ExprTry, ExprTryBlock, ExprTuple, ExprUnsafe,
+ ExprWhile, ExprYield,
+};
+
+#[cfg(feature = "parsing")]
+#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+pub mod ext;
+
+#[cfg(feature = "full")]
+mod file;
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub use crate::file::File;
+
+#[cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))]
+mod fixup;
+
+#[cfg(any(feature = "full", feature = "derive"))]
+mod generics;
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+pub use crate::generics::{
+ BoundLifetimes, ConstParam, GenericParam, Generics, LifetimeParam, PredicateLifetime,
+ PredicateType, TraitBound, TraitBoundModifier, TypeParam, TypeParamBound, WhereClause,
+ WherePredicate,
+};
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub use crate::generics::{CapturedParam, PreciseCapture};
+#[cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))]
+#[cfg_attr(
+ docsrs,
+ doc(cfg(all(any(feature = "full", feature = "derive"), feature = "printing")))
+)]
+pub use crate::generics::{ImplGenerics, Turbofish, TypeGenerics};
+
+mod ident;
+#[doc(inline)]
+pub use crate::ident::Ident;
+
+#[cfg(feature = "full")]
+mod item;
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub use crate::item::{
+ FnArg, ForeignItem, ForeignItemFn, ForeignItemMacro, ForeignItemStatic, ForeignItemType,
+ ImplItem, ImplItemConst, ImplItemFn, ImplItemMacro, ImplItemType, ImplRestriction, Item,
+ ItemConst, ItemEnum, ItemExternCrate, ItemFn, ItemForeignMod, ItemImpl, ItemMacro, ItemMod,
+ ItemStatic, ItemStruct, ItemTrait, ItemTraitAlias, ItemType, ItemUnion, ItemUse, Receiver,
+ Signature, StaticMutability, TraitItem, TraitItemConst, TraitItemFn, TraitItemMacro,
+ TraitItemType, UseGlob, UseGroup, UseName, UsePath, UseRename, UseTree, Variadic,
+};
+
+mod lifetime;
+#[doc(inline)]
+pub use crate::lifetime::Lifetime;
+
+mod lit;
+#[doc(hidden)] // https://github.com/dtolnay/syn/issues/1566
+pub use crate::lit::StrStyle;
+#[doc(inline)]
+pub use crate::lit::{
+ Lit, LitBool, LitByte, LitByteStr, LitCStr, LitChar, LitFloat, LitInt, LitStr,
+};
+
+#[cfg(feature = "parsing")]
+mod lookahead;
+
+#[cfg(any(feature = "full", feature = "derive"))]
+mod mac;
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+pub use crate::mac::{Macro, MacroDelimiter};
+
+#[cfg(all(feature = "parsing", any(feature = "full", feature = "derive")))]
+#[cfg_attr(
+ docsrs,
+ doc(cfg(all(feature = "parsing", any(feature = "full", feature = "derive"))))
+)]
+pub mod meta;
+
+#[cfg(any(feature = "full", feature = "derive"))]
+mod op;
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+pub use crate::op::{BinOp, UnOp};
+
+#[cfg(feature = "parsing")]
+#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+pub mod parse;
+
+#[cfg(all(feature = "parsing", feature = "proc-macro"))]
+mod parse_macro_input;
+
+#[cfg(all(feature = "parsing", feature = "printing"))]
+mod parse_quote;
+
+#[cfg(feature = "full")]
+mod pat;
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub use crate::pat::{
+ FieldPat, Pat, PatConst, PatIdent, PatLit, PatMacro, PatOr, PatParen, PatPath, PatRange,
+ PatReference, PatRest, PatSlice, PatStruct, PatTuple, PatTupleStruct, PatType, PatWild,
+};
+
+#[cfg(any(feature = "full", feature = "derive"))]
+mod path;
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+pub use crate::path::{
+ AngleBracketedGenericArguments, AssocConst, AssocType, Constraint, GenericArgument,
+ ParenthesizedGenericArguments, Path, PathArguments, PathSegment, QSelf,
+};
+
+#[cfg(all(
+ any(feature = "full", feature = "derive"),
+ any(feature = "parsing", feature = "printing")
+))]
+mod precedence;
+
+#[cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))]
+mod print;
+
+pub mod punctuated;
+
+#[cfg(any(feature = "full", feature = "derive"))]
+mod restriction;
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+pub use crate::restriction::{FieldMutability, VisRestricted, Visibility};
+
+mod sealed;
+
+#[cfg(all(feature = "parsing", feature = "derive", not(feature = "full")))]
+mod scan_expr;
+
+mod span;
+
+#[cfg(all(feature = "parsing", feature = "printing"))]
+#[cfg_attr(docsrs, doc(cfg(all(feature = "parsing", feature = "printing"))))]
+pub mod spanned;
+
+#[cfg(feature = "full")]
+mod stmt;
+#[cfg(feature = "full")]
+#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+pub use crate::stmt::{Block, Local, LocalInit, Stmt, StmtMacro};
+
+mod thread;
+
+#[cfg(all(any(feature = "full", feature = "derive"), feature = "extra-traits"))]
+mod tt;
+
+#[cfg(any(feature = "full", feature = "derive"))]
+mod ty;
+#[cfg(any(feature = "full", feature = "derive"))]
+#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+pub use crate::ty::{
+ Abi, BareFnArg, BareVariadic, ReturnType, Type, TypeArray, TypeBareFn, TypeGroup,
+ TypeImplTrait, TypeInfer, TypeMacro, TypeNever, TypeParen, TypePath, TypePtr, TypeReference,
+ TypeSlice, TypeTraitObject, TypeTuple,
+};
+
+#[cfg(all(any(feature = "full", feature = "derive"), feature = "parsing"))]
+mod verbatim;
+
+#[cfg(all(feature = "parsing", feature = "full"))]
+mod whitespace;
+
+#[rustfmt::skip] // https://github.com/rust-lang/rustfmt/issues/6176
+mod gen {
+ /// Syntax tree traversal to transform the nodes of an owned syntax tree.
+ ///
+ /// Each method of the [`Fold`] trait is a hook that can be overridden to
+ /// customize the behavior when transforming the corresponding type of node.
+ /// By default, every method recursively visits the substructure of the
+ /// input by invoking the right visitor method of each of its fields.
+ ///
+ /// [`Fold`]: fold::Fold
+ ///
+ /// ```
+ /// # use syn::{Attribute, BinOp, Expr, ExprBinary};
+ /// #
+ /// pub trait Fold {
+ /// /* ... */
+ ///
+ /// fn fold_expr_binary(&mut self, node: ExprBinary) -> ExprBinary {
+ /// fold_expr_binary(self, node)
+ /// }
+ ///
+ /// /* ... */
+ /// # fn fold_attribute(&mut self, node: Attribute) -> Attribute;
+ /// # fn fold_expr(&mut self, node: Expr) -> Expr;
+ /// # fn fold_bin_op(&mut self, node: BinOp) -> BinOp;
+ /// }
+ ///
+ /// pub fn fold_expr_binary<V>(v: &mut V, node: ExprBinary) -> ExprBinary
+ /// where
+ /// V: Fold + ?Sized,
+ /// {
+ /// ExprBinary {
+ /// attrs: node
+ /// .attrs
+ /// .into_iter()
+ /// .map(|attr| v.fold_attribute(attr))
+ /// .collect(),
+ /// left: Box::new(v.fold_expr(*node.left)),
+ /// op: v.fold_bin_op(node.op),
+ /// right: Box::new(v.fold_expr(*node.right)),
+ /// }
+ /// }
+ ///
+ /// /* ... */
+ /// ```
+ ///
+ /// <br>
+ ///
+ /// # Example
+ ///
+ /// This fold inserts parentheses to fully parenthesizes any expression.
+ ///
+ /// ```
+ /// // [dependencies]
+ /// // quote = "1.0"
+ /// // syn = { version = "2.0", features = ["fold", "full"] }
+ ///
+ /// use quote::quote;
+ /// use syn::fold::{fold_expr, Fold};
+ /// use syn::{token, Expr, ExprParen};
+ ///
+ /// struct ParenthesizeEveryExpr;
+ ///
+ /// impl Fold for ParenthesizeEveryExpr {
+ /// fn fold_expr(&mut self, expr: Expr) -> Expr {
+ /// Expr::Paren(ExprParen {
+ /// attrs: Vec::new(),
+ /// expr: Box::new(fold_expr(self, expr)),
+ /// paren_token: token::Paren::default(),
+ /// })
+ /// }
+ /// }
+ ///
+ /// fn main() {
+ /// let code = quote! { a() + b(1) * c.d };
+ /// let expr: Expr = syn::parse2(code).unwrap();
+ /// let parenthesized = ParenthesizeEveryExpr.fold_expr(expr);
+ /// println!("{}", quote!(#parenthesized));
+ ///
+ /// // Output: (((a)()) + (((b)((1))) * ((c).d)))
+ /// }
+ /// ```
+ #[cfg(feature = "fold")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "fold")))]
+ #[rustfmt::skip]
+ pub mod fold;
+
+ /// Syntax tree traversal to walk a shared borrow of a syntax tree.
+ ///
+ /// Each method of the [`Visit`] trait is a hook that can be overridden to
+ /// customize the behavior when visiting the corresponding type of node. By
+ /// default, every method recursively visits the substructure of the input
+ /// by invoking the right visitor method of each of its fields.
+ ///
+ /// [`Visit`]: visit::Visit
+ ///
+ /// ```
+ /// # use syn::{Attribute, BinOp, Expr, ExprBinary};
+ /// #
+ /// pub trait Visit<'ast> {
+ /// /* ... */
+ ///
+ /// fn visit_expr_binary(&mut self, node: &'ast ExprBinary) {
+ /// visit_expr_binary(self, node);
+ /// }
+ ///
+ /// /* ... */
+ /// # fn visit_attribute(&mut self, node: &'ast Attribute);
+ /// # fn visit_expr(&mut self, node: &'ast Expr);
+ /// # fn visit_bin_op(&mut self, node: &'ast BinOp);
+ /// }
+ ///
+ /// pub fn visit_expr_binary<'ast, V>(v: &mut V, node: &'ast ExprBinary)
+ /// where
+ /// V: Visit<'ast> + ?Sized,
+ /// {
+ /// for attr in &node.attrs {
+ /// v.visit_attribute(attr);
+ /// }
+ /// v.visit_expr(&*node.left);
+ /// v.visit_bin_op(&node.op);
+ /// v.visit_expr(&*node.right);
+ /// }
+ ///
+ /// /* ... */
+ /// ```
+ ///
+ /// <br>
+ ///
+ /// # Example
+ ///
+ /// This visitor will print the name of every freestanding function in the
+ /// syntax tree, including nested functions.
+ ///
+ /// ```
+ /// // [dependencies]
+ /// // quote = "1.0"
+ /// // syn = { version = "2.0", features = ["full", "visit"] }
+ ///
+ /// use quote::quote;
+ /// use syn::visit::{self, Visit};
+ /// use syn::{File, ItemFn};
+ ///
+ /// struct FnVisitor;
+ ///
+ /// impl<'ast> Visit<'ast> for FnVisitor {
+ /// fn visit_item_fn(&mut self, node: &'ast ItemFn) {
+ /// println!("Function with name={}", node.sig.ident);
+ ///
+ /// // Delegate to the default impl to visit any nested functions.
+ /// visit::visit_item_fn(self, node);
+ /// }
+ /// }
+ ///
+ /// fn main() {
+ /// let code = quote! {
+ /// pub fn f() {
+ /// fn g() {}
+ /// }
+ /// };
+ ///
+ /// let syntax_tree: File = syn::parse2(code).unwrap();
+ /// FnVisitor.visit_file(&syntax_tree);
+ /// }
+ /// ```
+ ///
+ /// The `'ast` lifetime on the input references means that the syntax tree
+ /// outlives the complete recursive visit call, so the visitor is allowed to
+ /// hold on to references into the syntax tree.
+ ///
+ /// ```
+ /// use quote::quote;
+ /// use syn::visit::{self, Visit};
+ /// use syn::{File, ItemFn};
+ ///
+ /// struct FnVisitor<'ast> {
+ /// functions: Vec<&'ast ItemFn>,
+ /// }
+ ///
+ /// impl<'ast> Visit<'ast> for FnVisitor<'ast> {
+ /// fn visit_item_fn(&mut self, node: &'ast ItemFn) {
+ /// self.functions.push(node);
+ /// visit::visit_item_fn(self, node);
+ /// }
+ /// }
+ ///
+ /// fn main() {
+ /// let code = quote! {
+ /// pub fn f() {
+ /// fn g() {}
+ /// }
+ /// };
+ ///
+ /// let syntax_tree: File = syn::parse2(code).unwrap();
+ /// let mut visitor = FnVisitor { functions: Vec::new() };
+ /// visitor.visit_file(&syntax_tree);
+ /// for f in visitor.functions {
+ /// println!("Function with name={}", f.sig.ident);
+ /// }
+ /// }
+ /// ```
+ #[cfg(feature = "visit")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "visit")))]
+ #[rustfmt::skip]
+ pub mod visit;
+
+ /// Syntax tree traversal to mutate an exclusive borrow of a syntax tree in
+ /// place.
+ ///
+ /// Each method of the [`VisitMut`] trait is a hook that can be overridden
+ /// to customize the behavior when mutating the corresponding type of node.
+ /// By default, every method recursively visits the substructure of the
+ /// input by invoking the right visitor method of each of its fields.
+ ///
+ /// [`VisitMut`]: visit_mut::VisitMut
+ ///
+ /// ```
+ /// # use syn::{Attribute, BinOp, Expr, ExprBinary};
+ /// #
+ /// pub trait VisitMut {
+ /// /* ... */
+ ///
+ /// fn visit_expr_binary_mut(&mut self, node: &mut ExprBinary) {
+ /// visit_expr_binary_mut(self, node);
+ /// }
+ ///
+ /// /* ... */
+ /// # fn visit_attribute_mut(&mut self, node: &mut Attribute);
+ /// # fn visit_expr_mut(&mut self, node: &mut Expr);
+ /// # fn visit_bin_op_mut(&mut self, node: &mut BinOp);
+ /// }
+ ///
+ /// pub fn visit_expr_binary_mut<V>(v: &mut V, node: &mut ExprBinary)
+ /// where
+ /// V: VisitMut + ?Sized,
+ /// {
+ /// for attr in &mut node.attrs {
+ /// v.visit_attribute_mut(attr);
+ /// }
+ /// v.visit_expr_mut(&mut *node.left);
+ /// v.visit_bin_op_mut(&mut node.op);
+ /// v.visit_expr_mut(&mut *node.right);
+ /// }
+ ///
+ /// /* ... */
+ /// ```
+ ///
+ /// <br>
+ ///
+ /// # Example
+ ///
+ /// This mut visitor replace occurrences of u256 suffixed integer literals
+ /// like `999u256` with a macro invocation `bigint::u256!(999)`.
+ ///
+ /// ```
+ /// // [dependencies]
+ /// // quote = "1.0"
+ /// // syn = { version = "2.0", features = ["full", "visit-mut"] }
+ ///
+ /// use quote::quote;
+ /// use syn::visit_mut::{self, VisitMut};
+ /// use syn::{parse_quote, Expr, File, Lit, LitInt};
+ ///
+ /// struct BigintReplace;
+ ///
+ /// impl VisitMut for BigintReplace {
+ /// fn visit_expr_mut(&mut self, node: &mut Expr) {
+ /// if let Expr::Lit(expr) = &node {
+ /// if let Lit::Int(int) = &expr.lit {
+ /// if int.suffix() == "u256" {
+ /// let digits = int.base10_digits();
+ /// let unsuffixed: LitInt = syn::parse_str(digits).unwrap();
+ /// *node = parse_quote!(bigint::u256!(#unsuffixed));
+ /// return;
+ /// }
+ /// }
+ /// }
+ ///
+ /// // Delegate to the default impl to visit nested expressions.
+ /// visit_mut::visit_expr_mut(self, node);
+ /// }
+ /// }
+ ///
+ /// fn main() {
+ /// let code = quote! {
+ /// fn main() {
+ /// let _ = 999u256;
+ /// }
+ /// };
+ ///
+ /// let mut syntax_tree: File = syn::parse2(code).unwrap();
+ /// BigintReplace.visit_file_mut(&mut syntax_tree);
+ /// println!("{}", quote!(#syntax_tree));
+ /// }
+ /// ```
+ #[cfg(feature = "visit-mut")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "visit-mut")))]
+ #[rustfmt::skip]
+ pub mod visit_mut;
+
+ #[cfg(feature = "clone-impls")]
+ #[rustfmt::skip]
+ mod clone;
+
+ #[cfg(feature = "extra-traits")]
+ #[rustfmt::skip]
+ mod debug;
+
+ #[cfg(feature = "extra-traits")]
+ #[rustfmt::skip]
+ mod eq;
+
+ #[cfg(feature = "extra-traits")]
+ #[rustfmt::skip]
+ mod hash;
+}
+
+#[cfg(feature = "fold")]
+#[cfg_attr(docsrs, doc(cfg(feature = "fold")))]
+pub use crate::gen::fold;
+
+#[cfg(feature = "visit")]
+#[cfg_attr(docsrs, doc(cfg(feature = "visit")))]
+pub use crate::gen::visit;
+
+#[cfg(feature = "visit-mut")]
+#[cfg_attr(docsrs, doc(cfg(feature = "visit-mut")))]
+pub use crate::gen::visit_mut;
+
+// Not public API.
+#[doc(hidden)]
+#[path = "export.rs"]
+pub mod __private;
+
+/// Parse tokens of source code into the chosen syntax tree node.
+///
+/// This is preferred over parsing a string because tokens are able to preserve
+/// information about where in the user's code they were originally written (the
+/// "span" of the token), possibly allowing the compiler to produce better error
+/// messages.
+///
+/// This function parses a `proc_macro::TokenStream` which is the type used for
+/// interop with the compiler in a procedural macro. To parse a
+/// `proc_macro2::TokenStream`, use [`syn::parse2`] instead.
+///
+/// [`syn::parse2`]: parse2
+///
+/// This function enforces that the input is fully parsed. If there are any
+/// unparsed tokens at the end of the stream, an error is returned.
+#[cfg(all(feature = "parsing", feature = "proc-macro"))]
+#[cfg_attr(docsrs, doc(cfg(all(feature = "parsing", feature = "proc-macro"))))]
+pub fn parse<T: parse::Parse>(tokens: proc_macro::TokenStream) -> Result<T> {
+ parse::Parser::parse(T::parse, tokens)
+}
+
+/// Parse a proc-macro2 token stream into the chosen syntax tree node.
+///
+/// This function parses a `proc_macro2::TokenStream` which is commonly useful
+/// when the input comes from a node of the Syn syntax tree, for example the
+/// body tokens of a [`Macro`] node. When in a procedural macro parsing the
+/// `proc_macro::TokenStream` provided by the compiler, use [`syn::parse`]
+/// instead.
+///
+/// [`syn::parse`]: parse()
+///
+/// This function enforces that the input is fully parsed. If there are any
+/// unparsed tokens at the end of the stream, an error is returned.
+#[cfg(feature = "parsing")]
+#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+pub fn parse2<T: parse::Parse>(tokens: proc_macro2::TokenStream) -> Result<T> {
+ parse::Parser::parse2(T::parse, tokens)
+}
+
+/// Parse a string of Rust code into the chosen syntax tree node.
+///
+/// This function enforces that the input is fully parsed. If there are any
+/// unparsed tokens at the end of the stream, an error is returned.
+///
+/// # Hygiene
+///
+/// Every span in the resulting syntax tree will be set to resolve at the macro
+/// call site.
+///
+/// # Examples
+///
+/// ```
+/// use syn::{Expr, Result};
+///
+/// fn run() -> Result<()> {
+/// let code = "assert_eq!(u8::max_value(), 255)";
+/// let expr = syn::parse_str::<Expr>(code)?;
+/// println!("{:#?}", expr);
+/// Ok(())
+/// }
+/// #
+/// # run().unwrap();
+/// ```
+#[cfg(feature = "parsing")]
+#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+pub fn parse_str<T: parse::Parse>(s: &str) -> Result<T> {
+ parse::Parser::parse_str(T::parse, s)
+}
+
+/// Parse the content of a file of Rust code.
+///
+/// This is different from `syn::parse_str::<File>(content)` in two ways:
+///
+/// - It discards a leading byte order mark `\u{FEFF}` if the file has one.
+/// - It preserves the shebang line of the file, such as `#!/usr/bin/env rustx`.
+///
+/// If present, either of these would be an error using `from_str`.
+///
+/// # Examples
+///
+/// ```no_run
+/// use std::error::Error;
+/// use std::fs;
+/// use std::io::Read;
+///
+/// fn run() -> Result<(), Box<dyn Error>> {
+/// let content = fs::read_to_string("path/to/code.rs")?;
+/// let ast = syn::parse_file(&content)?;
+/// if let Some(shebang) = ast.shebang {
+/// println!("{}", shebang);
+/// }
+/// println!("{} items", ast.items.len());
+///
+/// Ok(())
+/// }
+/// #
+/// # run().unwrap();
+/// ```
+#[cfg(all(feature = "parsing", feature = "full"))]
+#[cfg_attr(docsrs, doc(cfg(all(feature = "parsing", feature = "full"))))]
+pub fn parse_file(mut content: &str) -> Result<File> {
+ // Strip the BOM if it is present
+ const BOM: &str = "\u{feff}";
+ if content.starts_with(BOM) {
+ content = &content[BOM.len()..];
+ }
+
+ let mut shebang = None;
+ if content.starts_with("#!") {
+ let rest = whitespace::skip(&content[2..]);
+ if !rest.starts_with('[') {
+ if let Some(idx) = content.find('\n') {
+ shebang = Some(content[..idx].to_string());
+ content = &content[idx..];
+ } else {
+ shebang = Some(content.to_string());
+ content = "";
+ }
+ }
+ }
+
+ let mut file: File = parse_str(content)?;
+ file.shebang = shebang;
+ Ok(file)
+}
diff --git a/rust/syn/lifetime.rs b/rust/syn/lifetime.rs
new file mode 100644
index 000000000000..cc189d1ac91f
--- /dev/null
+++ b/rust/syn/lifetime.rs
@@ -0,0 +1,156 @@
+#[cfg(feature = "parsing")]
+use crate::lookahead;
+use proc_macro2::{Ident, Span};
+use std::cmp::Ordering;
+use std::fmt::{self, Display};
+use std::hash::{Hash, Hasher};
+
+/// A Rust lifetime: `'a`.
+///
+/// Lifetime names must conform to the following rules:
+///
+/// - Must start with an apostrophe.
+/// - Must not consist of just an apostrophe: `'`.
+/// - Character after the apostrophe must be `_` or a Unicode code point with
+/// the XID_Start property.
+/// - All following characters must be Unicode code points with the XID_Continue
+/// property.
+pub struct Lifetime {
+ pub apostrophe: Span,
+ pub ident: Ident,
+}
+
+impl Lifetime {
+ /// # Panics
+ ///
+ /// Panics if the lifetime does not conform to the bulleted rules above.
+ ///
+ /// # Invocation
+ ///
+ /// ```
+ /// # use proc_macro2::Span;
+ /// # use syn::Lifetime;
+ /// #
+ /// # fn f() -> Lifetime {
+ /// Lifetime::new("'a", Span::call_site())
+ /// # }
+ /// ```
+ pub fn new(symbol: &str, span: Span) -> Self {
+ if !symbol.starts_with('\'') {
+ panic!(
+ "lifetime name must start with apostrophe as in \"'a\", got {:?}",
+ symbol
+ );
+ }
+
+ if symbol == "'" {
+ panic!("lifetime name must not be empty");
+ }
+
+ if !crate::ident::xid_ok(&symbol[1..]) {
+ panic!("{:?} is not a valid lifetime name", symbol);
+ }
+
+ Lifetime {
+ apostrophe: span,
+ ident: Ident::new(&symbol[1..], span),
+ }
+ }
+
+ pub fn span(&self) -> Span {
+ self.apostrophe
+ .join(self.ident.span())
+ .unwrap_or(self.apostrophe)
+ }
+
+ pub fn set_span(&mut self, span: Span) {
+ self.apostrophe = span;
+ self.ident.set_span(span);
+ }
+}
+
+impl Display for Lifetime {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ "'".fmt(formatter)?;
+ self.ident.fmt(formatter)
+ }
+}
+
+impl Clone for Lifetime {
+ fn clone(&self) -> Self {
+ Lifetime {
+ apostrophe: self.apostrophe,
+ ident: self.ident.clone(),
+ }
+ }
+}
+
+impl PartialEq for Lifetime {
+ fn eq(&self, other: &Lifetime) -> bool {
+ self.ident.eq(&other.ident)
+ }
+}
+
+impl Eq for Lifetime {}
+
+impl PartialOrd for Lifetime {
+ fn partial_cmp(&self, other: &Lifetime) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
+impl Ord for Lifetime {
+ fn cmp(&self, other: &Lifetime) -> Ordering {
+ self.ident.cmp(&other.ident)
+ }
+}
+
+impl Hash for Lifetime {
+ fn hash<H: Hasher>(&self, h: &mut H) {
+ self.ident.hash(h);
+ }
+}
+
+#[cfg(feature = "parsing")]
+pub_if_not_doc! {
+ #[doc(hidden)]
+ #[allow(non_snake_case)]
+ pub fn Lifetime(marker: lookahead::TokenMarker) -> Lifetime {
+ match marker {}
+ }
+}
+
+#[cfg(feature = "parsing")]
+pub(crate) mod parsing {
+ use crate::error::Result;
+ use crate::lifetime::Lifetime;
+ use crate::parse::{Parse, ParseStream};
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for Lifetime {
+ fn parse(input: ParseStream) -> Result<Self> {
+ input.step(|cursor| {
+ cursor
+ .lifetime()
+ .ok_or_else(|| cursor.error("expected lifetime"))
+ })
+ }
+ }
+}
+
+#[cfg(feature = "printing")]
+mod printing {
+ use crate::lifetime::Lifetime;
+ use proc_macro2::{Punct, Spacing, TokenStream};
+ use quote::{ToTokens, TokenStreamExt};
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for Lifetime {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ let mut apostrophe = Punct::new('\'', Spacing::Joint);
+ apostrophe.set_span(self.apostrophe);
+ tokens.append(apostrophe);
+ self.ident.to_tokens(tokens);
+ }
+ }
+}
diff --git a/rust/syn/lit.rs b/rust/syn/lit.rs
new file mode 100644
index 000000000000..45c26d56fed3
--- /dev/null
+++ b/rust/syn/lit.rs
@@ -0,0 +1,1860 @@
+#[cfg(feature = "parsing")]
+use crate::lookahead;
+#[cfg(feature = "parsing")]
+use crate::parse::{Parse, Parser};
+use crate::{Error, Result};
+use proc_macro2::{Ident, Literal, Span};
+#[cfg(feature = "parsing")]
+use proc_macro2::{TokenStream, TokenTree};
+use std::ffi::{CStr, CString};
+use std::fmt::{self, Display};
+#[cfg(feature = "extra-traits")]
+use std::hash::{Hash, Hasher};
+use std::str::{self, FromStr};
+
+ast_enum_of_structs! {
+ /// A Rust literal such as a string or integer or boolean.
+ ///
+ /// # Syntax tree enum
+ ///
+ /// This type is a [syntax tree enum].
+ ///
+ /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums
+ #[non_exhaustive]
+ pub enum Lit {
+ /// A UTF-8 string literal: `"foo"`.
+ Str(LitStr),
+
+ /// A byte string literal: `b"foo"`.
+ ByteStr(LitByteStr),
+
+ /// A nul-terminated C-string literal: `c"foo"`.
+ CStr(LitCStr),
+
+ /// A byte literal: `b'f'`.
+ Byte(LitByte),
+
+ /// A character literal: `'a'`.
+ Char(LitChar),
+
+ /// An integer literal: `1` or `1u16`.
+ Int(LitInt),
+
+ /// A floating point literal: `1f64` or `1.0e10f64`.
+ ///
+ /// Must be finite. May not be infinite or NaN.
+ Float(LitFloat),
+
+ /// A boolean literal: `true` or `false`.
+ Bool(LitBool),
+
+ /// A raw token literal not interpreted by Syn.
+ Verbatim(Literal),
+ }
+}
+
+ast_struct! {
+ /// A UTF-8 string literal: `"foo"`.
+ pub struct LitStr {
+ repr: Box<LitRepr>,
+ }
+}
+
+ast_struct! {
+ /// A byte string literal: `b"foo"`.
+ pub struct LitByteStr {
+ repr: Box<LitRepr>,
+ }
+}
+
+ast_struct! {
+ /// A nul-terminated C-string literal: `c"foo"`.
+ pub struct LitCStr {
+ repr: Box<LitRepr>,
+ }
+}
+
+ast_struct! {
+ /// A byte literal: `b'f'`.
+ pub struct LitByte {
+ repr: Box<LitRepr>,
+ }
+}
+
+ast_struct! {
+ /// A character literal: `'a'`.
+ pub struct LitChar {
+ repr: Box<LitRepr>,
+ }
+}
+
+struct LitRepr {
+ token: Literal,
+ suffix: Box<str>,
+}
+
+ast_struct! {
+ /// An integer literal: `1` or `1u16`.
+ pub struct LitInt {
+ repr: Box<LitIntRepr>,
+ }
+}
+
+struct LitIntRepr {
+ token: Literal,
+ digits: Box<str>,
+ suffix: Box<str>,
+}
+
+ast_struct! {
+ /// A floating point literal: `1f64` or `1.0e10f64`.
+ ///
+ /// Must be finite. May not be infinite or NaN.
+ pub struct LitFloat {
+ repr: Box<LitFloatRepr>,
+ }
+}
+
+struct LitFloatRepr {
+ token: Literal,
+ digits: Box<str>,
+ suffix: Box<str>,
+}
+
+ast_struct! {
+ /// A boolean literal: `true` or `false`.
+ pub struct LitBool {
+ pub value: bool,
+ pub span: Span,
+ }
+}
+
+impl LitStr {
+ pub fn new(value: &str, span: Span) -> Self {
+ let mut token = Literal::string(value);
+ token.set_span(span);
+ LitStr {
+ repr: Box::new(LitRepr {
+ token,
+ suffix: Box::<str>::default(),
+ }),
+ }
+ }
+
+ pub fn value(&self) -> String {
+ let repr = self.repr.token.to_string();
+ let (value, _suffix) = value::parse_lit_str(&repr);
+ String::from(value)
+ }
+
+ /// Parse a syntax tree node from the content of this string literal.
+ ///
+ /// All spans in the syntax tree will point to the span of this `LitStr`.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use syn::{Attribute, Error, Expr, Lit, Meta, Path, Result};
+ ///
+ /// // Parses the path from an attribute that looks like:
+ /// //
+ /// // #[path = "a::b::c"]
+ /// //
+ /// // or returns `None` if the input is some other attribute.
+ /// fn get_path(attr: &Attribute) -> Result<Option<Path>> {
+ /// if !attr.path().is_ident("path") {
+ /// return Ok(None);
+ /// }
+ ///
+ /// if let Meta::NameValue(meta) = &attr.meta {
+ /// if let Expr::Lit(expr) = &meta.value {
+ /// if let Lit::Str(lit_str) = &expr.lit {
+ /// return lit_str.parse().map(Some);
+ /// }
+ /// }
+ /// }
+ ///
+ /// let message = "expected #[path = \"...\"]";
+ /// Err(Error::new_spanned(attr, message))
+ /// }
+ /// ```
+ #[cfg(feature = "parsing")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ pub fn parse<T: Parse>(&self) -> Result<T> {
+ self.parse_with(T::parse)
+ }
+
+ /// Invoke parser on the content of this string literal.
+ ///
+ /// All spans in the syntax tree will point to the span of this `LitStr`.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// # use proc_macro2::Span;
+ /// # use syn::{LitStr, Result};
+ /// #
+ /// # fn main() -> Result<()> {
+ /// # let lit_str = LitStr::new("a::b::c", Span::call_site());
+ /// #
+ /// # const IGNORE: &str = stringify! {
+ /// let lit_str: LitStr = /* ... */;
+ /// # };
+ ///
+ /// // Parse a string literal like "a::b::c" into a Path, not allowing
+ /// // generic arguments on any of the path segments.
+ /// let basic_path = lit_str.parse_with(syn::Path::parse_mod_style)?;
+ /// #
+ /// # Ok(())
+ /// # }
+ /// ```
+ #[cfg(feature = "parsing")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ pub fn parse_with<F: Parser>(&self, parser: F) -> Result<F::Output> {
+ use proc_macro2::Group;
+
+ // Token stream with every span replaced by the given one.
+ fn respan_token_stream(stream: TokenStream, span: Span) -> TokenStream {
+ stream
+ .into_iter()
+ .map(|token| respan_token_tree(token, span))
+ .collect()
+ }
+
+ // Token tree with every span replaced by the given one.
+ fn respan_token_tree(mut token: TokenTree, span: Span) -> TokenTree {
+ match &mut token {
+ TokenTree::Group(g) => {
+ let stream = respan_token_stream(g.stream(), span);
+ *g = Group::new(g.delimiter(), stream);
+ g.set_span(span);
+ }
+ other => other.set_span(span),
+ }
+ token
+ }
+
+ // Parse string literal into a token stream with every span equal to the
+ // original literal's span.
+ let span = self.span();
+ let mut tokens = TokenStream::from_str(&self.value())?;
+ tokens = respan_token_stream(tokens, span);
+
+ let result = crate::parse::parse_scoped(parser, span, tokens)?;
+
+ let suffix = self.suffix();
+ if !suffix.is_empty() {
+ return Err(Error::new(
+ self.span(),
+ format!("unexpected suffix `{}` on string literal", suffix),
+ ));
+ }
+
+ Ok(result)
+ }
+
+ pub fn span(&self) -> Span {
+ self.repr.token.span()
+ }
+
+ pub fn set_span(&mut self, span: Span) {
+ self.repr.token.set_span(span);
+ }
+
+ pub fn suffix(&self) -> &str {
+ &self.repr.suffix
+ }
+
+ pub fn token(&self) -> Literal {
+ self.repr.token.clone()
+ }
+}
+
+impl LitByteStr {
+ pub fn new(value: &[u8], span: Span) -> Self {
+ let mut token = Literal::byte_string(value);
+ token.set_span(span);
+ LitByteStr {
+ repr: Box::new(LitRepr {
+ token,
+ suffix: Box::<str>::default(),
+ }),
+ }
+ }
+
+ pub fn value(&self) -> Vec<u8> {
+ let repr = self.repr.token.to_string();
+ let (value, _suffix) = value::parse_lit_byte_str(&repr);
+ value
+ }
+
+ pub fn span(&self) -> Span {
+ self.repr.token.span()
+ }
+
+ pub fn set_span(&mut self, span: Span) {
+ self.repr.token.set_span(span);
+ }
+
+ pub fn suffix(&self) -> &str {
+ &self.repr.suffix
+ }
+
+ pub fn token(&self) -> Literal {
+ self.repr.token.clone()
+ }
+}
+
+impl LitCStr {
+ pub fn new(value: &CStr, span: Span) -> Self {
+ let mut token = Literal::c_string(value);
+ token.set_span(span);
+ LitCStr {
+ repr: Box::new(LitRepr {
+ token,
+ suffix: Box::<str>::default(),
+ }),
+ }
+ }
+
+ pub fn value(&self) -> CString {
+ let repr = self.repr.token.to_string();
+ let (value, _suffix) = value::parse_lit_c_str(&repr);
+ value
+ }
+
+ pub fn span(&self) -> Span {
+ self.repr.token.span()
+ }
+
+ pub fn set_span(&mut self, span: Span) {
+ self.repr.token.set_span(span);
+ }
+
+ pub fn suffix(&self) -> &str {
+ &self.repr.suffix
+ }
+
+ pub fn token(&self) -> Literal {
+ self.repr.token.clone()
+ }
+}
+
+impl LitByte {
+ pub fn new(value: u8, span: Span) -> Self {
+ let mut token = Literal::u8_suffixed(value);
+ token.set_span(span);
+ LitByte {
+ repr: Box::new(LitRepr {
+ token,
+ suffix: Box::<str>::default(),
+ }),
+ }
+ }
+
+ pub fn value(&self) -> u8 {
+ let repr = self.repr.token.to_string();
+ let (value, _suffix) = value::parse_lit_byte(&repr);
+ value
+ }
+
+ pub fn span(&self) -> Span {
+ self.repr.token.span()
+ }
+
+ pub fn set_span(&mut self, span: Span) {
+ self.repr.token.set_span(span);
+ }
+
+ pub fn suffix(&self) -> &str {
+ &self.repr.suffix
+ }
+
+ pub fn token(&self) -> Literal {
+ self.repr.token.clone()
+ }
+}
+
+impl LitChar {
+ pub fn new(value: char, span: Span) -> Self {
+ let mut token = Literal::character(value);
+ token.set_span(span);
+ LitChar {
+ repr: Box::new(LitRepr {
+ token,
+ suffix: Box::<str>::default(),
+ }),
+ }
+ }
+
+ pub fn value(&self) -> char {
+ let repr = self.repr.token.to_string();
+ let (value, _suffix) = value::parse_lit_char(&repr);
+ value
+ }
+
+ pub fn span(&self) -> Span {
+ self.repr.token.span()
+ }
+
+ pub fn set_span(&mut self, span: Span) {
+ self.repr.token.set_span(span);
+ }
+
+ pub fn suffix(&self) -> &str {
+ &self.repr.suffix
+ }
+
+ pub fn token(&self) -> Literal {
+ self.repr.token.clone()
+ }
+}
+
+impl LitInt {
+ pub fn new(repr: &str, span: Span) -> Self {
+ let (digits, suffix) = match value::parse_lit_int(repr) {
+ Some(parse) => parse,
+ None => panic!("not an integer literal: `{}`", repr),
+ };
+
+ let mut token: Literal = repr.parse().unwrap();
+ token.set_span(span);
+ LitInt {
+ repr: Box::new(LitIntRepr {
+ token,
+ digits,
+ suffix,
+ }),
+ }
+ }
+
+ pub fn base10_digits(&self) -> &str {
+ &self.repr.digits
+ }
+
+ /// Parses the literal into a selected number type.
+ ///
+ /// This is equivalent to `lit.base10_digits().parse()` except that the
+ /// resulting errors will be correctly spanned to point to the literal token
+ /// in the macro input.
+ ///
+ /// ```
+ /// use syn::LitInt;
+ /// use syn::parse::{Parse, ParseStream, Result};
+ ///
+ /// struct Port {
+ /// value: u16,
+ /// }
+ ///
+ /// impl Parse for Port {
+ /// fn parse(input: ParseStream) -> Result<Self> {
+ /// let lit: LitInt = input.parse()?;
+ /// let value = lit.base10_parse::<u16>()?;
+ /// Ok(Port { value })
+ /// }
+ /// }
+ /// ```
+ pub fn base10_parse<N>(&self) -> Result<N>
+ where
+ N: FromStr,
+ N::Err: Display,
+ {
+ self.base10_digits()
+ .parse()
+ .map_err(|err| Error::new(self.span(), err))
+ }
+
+ pub fn suffix(&self) -> &str {
+ &self.repr.suffix
+ }
+
+ pub fn span(&self) -> Span {
+ self.repr.token.span()
+ }
+
+ pub fn set_span(&mut self, span: Span) {
+ self.repr.token.set_span(span);
+ }
+
+ pub fn token(&self) -> Literal {
+ self.repr.token.clone()
+ }
+}
+
+impl From<Literal> for LitInt {
+ fn from(token: Literal) -> Self {
+ let repr = token.to_string();
+ if let Some((digits, suffix)) = value::parse_lit_int(&repr) {
+ LitInt {
+ repr: Box::new(LitIntRepr {
+ token,
+ digits,
+ suffix,
+ }),
+ }
+ } else {
+ panic!("not an integer literal: `{}`", repr);
+ }
+ }
+}
+
+impl Display for LitInt {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.repr.token.fmt(formatter)
+ }
+}
+
+impl LitFloat {
+ pub fn new(repr: &str, span: Span) -> Self {
+ let (digits, suffix) = match value::parse_lit_float(repr) {
+ Some(parse) => parse,
+ None => panic!("not a float literal: `{}`", repr),
+ };
+
+ let mut token: Literal = repr.parse().unwrap();
+ token.set_span(span);
+ LitFloat {
+ repr: Box::new(LitFloatRepr {
+ token,
+ digits,
+ suffix,
+ }),
+ }
+ }
+
+ pub fn base10_digits(&self) -> &str {
+ &self.repr.digits
+ }
+
+ pub fn base10_parse<N>(&self) -> Result<N>
+ where
+ N: FromStr,
+ N::Err: Display,
+ {
+ self.base10_digits()
+ .parse()
+ .map_err(|err| Error::new(self.span(), err))
+ }
+
+ pub fn suffix(&self) -> &str {
+ &self.repr.suffix
+ }
+
+ pub fn span(&self) -> Span {
+ self.repr.token.span()
+ }
+
+ pub fn set_span(&mut self, span: Span) {
+ self.repr.token.set_span(span);
+ }
+
+ pub fn token(&self) -> Literal {
+ self.repr.token.clone()
+ }
+}
+
+impl From<Literal> for LitFloat {
+ fn from(token: Literal) -> Self {
+ let repr = token.to_string();
+ if let Some((digits, suffix)) = value::parse_lit_float(&repr) {
+ LitFloat {
+ repr: Box::new(LitFloatRepr {
+ token,
+ digits,
+ suffix,
+ }),
+ }
+ } else {
+ panic!("not a float literal: `{}`", repr);
+ }
+ }
+}
+
+impl Display for LitFloat {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.repr.token.fmt(formatter)
+ }
+}
+
+impl LitBool {
+ pub fn new(value: bool, span: Span) -> Self {
+ LitBool { value, span }
+ }
+
+ pub fn value(&self) -> bool {
+ self.value
+ }
+
+ pub fn span(&self) -> Span {
+ self.span
+ }
+
+ pub fn set_span(&mut self, span: Span) {
+ self.span = span;
+ }
+
+ pub fn token(&self) -> Ident {
+ let s = if self.value { "true" } else { "false" };
+ Ident::new(s, self.span)
+ }
+}
+
+#[cfg(feature = "extra-traits")]
+mod debug_impls {
+ use crate::lit::{LitBool, LitByte, LitByteStr, LitCStr, LitChar, LitFloat, LitInt, LitStr};
+ use std::fmt::{self, Debug};
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+ impl Debug for LitStr {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "LitStr")
+ }
+ }
+
+ impl LitStr {
+ pub(crate) fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ formatter
+ .debug_struct(name)
+ .field("token", &format_args!("{}", self.repr.token))
+ .finish()
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+ impl Debug for LitByteStr {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "LitByteStr")
+ }
+ }
+
+ impl LitByteStr {
+ pub(crate) fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ formatter
+ .debug_struct(name)
+ .field("token", &format_args!("{}", self.repr.token))
+ .finish()
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+ impl Debug for LitCStr {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "LitCStr")
+ }
+ }
+
+ impl LitCStr {
+ pub(crate) fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ formatter
+ .debug_struct(name)
+ .field("token", &format_args!("{}", self.repr.token))
+ .finish()
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+ impl Debug for LitByte {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "LitByte")
+ }
+ }
+
+ impl LitByte {
+ pub(crate) fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ formatter
+ .debug_struct(name)
+ .field("token", &format_args!("{}", self.repr.token))
+ .finish()
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+ impl Debug for LitChar {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "LitChar")
+ }
+ }
+
+ impl LitChar {
+ pub(crate) fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ formatter
+ .debug_struct(name)
+ .field("token", &format_args!("{}", self.repr.token))
+ .finish()
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+ impl Debug for LitInt {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "LitInt")
+ }
+ }
+
+ impl LitInt {
+ pub(crate) fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ formatter
+ .debug_struct(name)
+ .field("token", &format_args!("{}", self.repr.token))
+ .finish()
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+ impl Debug for LitFloat {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "LitFloat")
+ }
+ }
+
+ impl LitFloat {
+ pub(crate) fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ formatter
+ .debug_struct(name)
+ .field("token", &format_args!("{}", self.repr.token))
+ .finish()
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+ impl Debug for LitBool {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.debug(formatter, "LitBool")
+ }
+ }
+
+ impl LitBool {
+ pub(crate) fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result {
+ formatter
+ .debug_struct(name)
+ .field("value", &self.value)
+ .finish()
+ }
+ }
+}
+
+#[cfg(feature = "clone-impls")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for LitRepr {
+ fn clone(&self) -> Self {
+ LitRepr {
+ token: self.token.clone(),
+ suffix: self.suffix.clone(),
+ }
+ }
+}
+
+#[cfg(feature = "clone-impls")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for LitIntRepr {
+ fn clone(&self) -> Self {
+ LitIntRepr {
+ token: self.token.clone(),
+ digits: self.digits.clone(),
+ suffix: self.suffix.clone(),
+ }
+ }
+}
+
+#[cfg(feature = "clone-impls")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for LitFloatRepr {
+ fn clone(&self) -> Self {
+ LitFloatRepr {
+ token: self.token.clone(),
+ digits: self.digits.clone(),
+ suffix: self.suffix.clone(),
+ }
+ }
+}
+
+macro_rules! lit_extra_traits {
+ ($ty:ident) => {
+ #[cfg(feature = "clone-impls")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+ impl Clone for $ty {
+ fn clone(&self) -> Self {
+ $ty {
+ repr: self.repr.clone(),
+ }
+ }
+ }
+
+ #[cfg(feature = "extra-traits")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+ impl PartialEq for $ty {
+ fn eq(&self, other: &Self) -> bool {
+ self.repr.token.to_string() == other.repr.token.to_string()
+ }
+ }
+
+ #[cfg(feature = "extra-traits")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+ impl Hash for $ty {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.repr.token.to_string().hash(state);
+ }
+ }
+
+ #[cfg(feature = "parsing")]
+ pub_if_not_doc! {
+ #[doc(hidden)]
+ #[allow(non_snake_case)]
+ pub fn $ty(marker: lookahead::TokenMarker) -> $ty {
+ match marker {}
+ }
+ }
+ };
+}
+
+lit_extra_traits!(LitStr);
+lit_extra_traits!(LitByteStr);
+lit_extra_traits!(LitCStr);
+lit_extra_traits!(LitByte);
+lit_extra_traits!(LitChar);
+lit_extra_traits!(LitInt);
+lit_extra_traits!(LitFloat);
+
+#[cfg(feature = "parsing")]
+pub_if_not_doc! {
+ #[doc(hidden)]
+ #[allow(non_snake_case)]
+ pub fn LitBool(marker: lookahead::TokenMarker) -> LitBool {
+ match marker {}
+ }
+}
+
+/// The style of a string literal, either plain quoted or a raw string like
+/// `r##"data"##`.
+#[doc(hidden)] // https://github.com/dtolnay/syn/issues/1566
+pub enum StrStyle {
+ /// An ordinary string like `"data"`.
+ Cooked,
+ /// A raw string like `r##"data"##`.
+ ///
+ /// The unsigned integer is the number of `#` symbols used.
+ Raw(usize),
+}
+
+#[cfg(feature = "parsing")]
+pub_if_not_doc! {
+ #[doc(hidden)]
+ #[allow(non_snake_case)]
+ pub fn Lit(marker: lookahead::TokenMarker) -> Lit {
+ match marker {}
+ }
+}
+
+#[cfg(feature = "parsing")]
+pub(crate) mod parsing {
+ use crate::buffer::Cursor;
+ use crate::error::Result;
+ use crate::lit::{
+ value, Lit, LitBool, LitByte, LitByteStr, LitCStr, LitChar, LitFloat, LitFloatRepr, LitInt,
+ LitIntRepr, LitStr,
+ };
+ use crate::parse::{Parse, ParseStream, Unexpected};
+ use crate::token::{self, Token};
+ use proc_macro2::{Literal, Punct, Span};
+ use std::cell::Cell;
+ use std::rc::Rc;
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for Lit {
+ fn parse(input: ParseStream) -> Result<Self> {
+ input.step(|cursor| {
+ if let Some((lit, rest)) = cursor.literal() {
+ return Ok((Lit::new(lit), rest));
+ }
+
+ if let Some((ident, rest)) = cursor.ident() {
+ let value = ident == "true";
+ if value || ident == "false" {
+ let lit_bool = LitBool {
+ value,
+ span: ident.span(),
+ };
+ return Ok((Lit::Bool(lit_bool), rest));
+ }
+ }
+
+ if let Some((punct, rest)) = cursor.punct() {
+ if punct.as_char() == '-' {
+ if let Some((lit, rest)) = parse_negative_lit(punct, rest) {
+ return Ok((lit, rest));
+ }
+ }
+ }
+
+ Err(cursor.error("expected literal"))
+ })
+ }
+ }
+
+ fn parse_negative_lit(neg: Punct, cursor: Cursor) -> Option<(Lit, Cursor)> {
+ let (lit, rest) = cursor.literal()?;
+
+ let mut span = neg.span();
+ span = span.join(lit.span()).unwrap_or(span);
+
+ let mut repr = lit.to_string();
+ repr.insert(0, '-');
+
+ if let Some((digits, suffix)) = value::parse_lit_int(&repr) {
+ let mut token: Literal = repr.parse().unwrap();
+ token.set_span(span);
+ return Some((
+ Lit::Int(LitInt {
+ repr: Box::new(LitIntRepr {
+ token,
+ digits,
+ suffix,
+ }),
+ }),
+ rest,
+ ));
+ }
+
+ let (digits, suffix) = value::parse_lit_float(&repr)?;
+ let mut token: Literal = repr.parse().unwrap();
+ token.set_span(span);
+ Some((
+ Lit::Float(LitFloat {
+ repr: Box::new(LitFloatRepr {
+ token,
+ digits,
+ suffix,
+ }),
+ }),
+ rest,
+ ))
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for LitStr {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let head = input.fork();
+ match input.parse() {
+ Ok(Lit::Str(lit)) => Ok(lit),
+ _ => Err(head.error("expected string literal")),
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for LitByteStr {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let head = input.fork();
+ match input.parse() {
+ Ok(Lit::ByteStr(lit)) => Ok(lit),
+ _ => Err(head.error("expected byte string literal")),
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for LitCStr {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let head = input.fork();
+ match input.parse() {
+ Ok(Lit::CStr(lit)) => Ok(lit),
+ _ => Err(head.error("expected C string literal")),
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for LitByte {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let head = input.fork();
+ match input.parse() {
+ Ok(Lit::Byte(lit)) => Ok(lit),
+ _ => Err(head.error("expected byte literal")),
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for LitChar {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let head = input.fork();
+ match input.parse() {
+ Ok(Lit::Char(lit)) => Ok(lit),
+ _ => Err(head.error("expected character literal")),
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for LitInt {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let head = input.fork();
+ match input.parse() {
+ Ok(Lit::Int(lit)) => Ok(lit),
+ _ => Err(head.error("expected integer literal")),
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for LitFloat {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let head = input.fork();
+ match input.parse() {
+ Ok(Lit::Float(lit)) => Ok(lit),
+ _ => Err(head.error("expected floating point literal")),
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for LitBool {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let head = input.fork();
+ match input.parse() {
+ Ok(Lit::Bool(lit)) => Ok(lit),
+ _ => Err(head.error("expected boolean literal")),
+ }
+ }
+ }
+
+ fn peek_impl(cursor: Cursor, peek: fn(ParseStream) -> bool) -> bool {
+ let scope = Span::call_site();
+ let unexpected = Rc::new(Cell::new(Unexpected::None));
+ let buffer = crate::parse::new_parse_buffer(scope, cursor, unexpected);
+ peek(&buffer)
+ }
+
+ macro_rules! impl_token {
+ ($display:literal $name:ty) => {
+ impl Token for $name {
+ fn peek(cursor: Cursor) -> bool {
+ fn peek(input: ParseStream) -> bool {
+ <$name as Parse>::parse(input).is_ok()
+ }
+ peek_impl(cursor, peek)
+ }
+
+ fn display() -> &'static str {
+ $display
+ }
+ }
+
+ impl token::private::Sealed for $name {}
+ };
+ }
+
+ impl_token!("literal" Lit);
+ impl_token!("string literal" LitStr);
+ impl_token!("byte string literal" LitByteStr);
+ impl_token!("C-string literal" LitCStr);
+ impl_token!("byte literal" LitByte);
+ impl_token!("character literal" LitChar);
+ impl_token!("integer literal" LitInt);
+ impl_token!("floating point literal" LitFloat);
+ impl_token!("boolean literal" LitBool);
+}
+
+#[cfg(feature = "printing")]
+mod printing {
+ use crate::lit::{LitBool, LitByte, LitByteStr, LitCStr, LitChar, LitFloat, LitInt, LitStr};
+ use proc_macro2::TokenStream;
+ use quote::{ToTokens, TokenStreamExt};
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for LitStr {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.repr.token.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for LitByteStr {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.repr.token.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for LitCStr {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.repr.token.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for LitByte {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.repr.token.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for LitChar {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.repr.token.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for LitInt {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.repr.token.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for LitFloat {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.repr.token.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for LitBool {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append(self.token());
+ }
+ }
+}
+
+mod value {
+ use crate::bigint::BigInt;
+ use crate::lit::{
+ Lit, LitBool, LitByte, LitByteStr, LitCStr, LitChar, LitFloat, LitFloatRepr, LitInt,
+ LitIntRepr, LitRepr, LitStr,
+ };
+ use proc_macro2::{Literal, Span};
+ use std::ascii;
+ use std::char;
+ use std::ffi::CString;
+ use std::ops::{Index, RangeFrom};
+
+ impl Lit {
+ /// Interpret a Syn literal from a proc-macro2 literal.
+ pub fn new(token: Literal) -> Self {
+ let repr = token.to_string();
+
+ match byte(&repr, 0) {
+ // "...", r"...", r#"..."#
+ b'"' | b'r' => {
+ let (_, suffix) = parse_lit_str(&repr);
+ return Lit::Str(LitStr {
+ repr: Box::new(LitRepr { token, suffix }),
+ });
+ }
+ b'b' => match byte(&repr, 1) {
+ // b"...", br"...", br#"...#"
+ b'"' | b'r' => {
+ let (_, suffix) = parse_lit_byte_str(&repr);
+ return Lit::ByteStr(LitByteStr {
+ repr: Box::new(LitRepr { token, suffix }),
+ });
+ }
+ // b'...'
+ b'\'' => {
+ let (_, suffix) = parse_lit_byte(&repr);
+ return Lit::Byte(LitByte {
+ repr: Box::new(LitRepr { token, suffix }),
+ });
+ }
+ _ => {}
+ },
+ // c"...", cr"...", cr#"..."#
+ b'c' => {
+ let (_, suffix) = parse_lit_c_str(&repr);
+ return Lit::CStr(LitCStr {
+ repr: Box::new(LitRepr { token, suffix }),
+ });
+ }
+ // '...'
+ b'\'' => {
+ let (_, suffix) = parse_lit_char(&repr);
+ return Lit::Char(LitChar {
+ repr: Box::new(LitRepr { token, suffix }),
+ });
+ }
+ b'0'..=b'9' | b'-' => {
+ // 0, 123, 0xFF, 0o77, 0b11
+ if let Some((digits, suffix)) = parse_lit_int(&repr) {
+ return Lit::Int(LitInt {
+ repr: Box::new(LitIntRepr {
+ token,
+ digits,
+ suffix,
+ }),
+ });
+ }
+ // 1.0, 1e-1, 1e+1
+ if let Some((digits, suffix)) = parse_lit_float(&repr) {
+ return Lit::Float(LitFloat {
+ repr: Box::new(LitFloatRepr {
+ token,
+ digits,
+ suffix,
+ }),
+ });
+ }
+ }
+ // true, false
+ b't' | b'f' => {
+ if repr == "true" || repr == "false" {
+ return Lit::Bool(LitBool {
+ value: repr == "true",
+ span: token.span(),
+ });
+ }
+ }
+ b'(' if repr == "(/*ERROR*/)" => return Lit::Verbatim(token),
+ _ => {}
+ }
+
+ panic!("unrecognized literal: `{}`", repr);
+ }
+
+ pub fn suffix(&self) -> &str {
+ match self {
+ Lit::Str(lit) => lit.suffix(),
+ Lit::ByteStr(lit) => lit.suffix(),
+ Lit::CStr(lit) => lit.suffix(),
+ Lit::Byte(lit) => lit.suffix(),
+ Lit::Char(lit) => lit.suffix(),
+ Lit::Int(lit) => lit.suffix(),
+ Lit::Float(lit) => lit.suffix(),
+ Lit::Bool(_) | Lit::Verbatim(_) => "",
+ }
+ }
+
+ pub fn span(&self) -> Span {
+ match self {
+ Lit::Str(lit) => lit.span(),
+ Lit::ByteStr(lit) => lit.span(),
+ Lit::CStr(lit) => lit.span(),
+ Lit::Byte(lit) => lit.span(),
+ Lit::Char(lit) => lit.span(),
+ Lit::Int(lit) => lit.span(),
+ Lit::Float(lit) => lit.span(),
+ Lit::Bool(lit) => lit.span,
+ Lit::Verbatim(lit) => lit.span(),
+ }
+ }
+
+ pub fn set_span(&mut self, span: Span) {
+ match self {
+ Lit::Str(lit) => lit.set_span(span),
+ Lit::ByteStr(lit) => lit.set_span(span),
+ Lit::CStr(lit) => lit.set_span(span),
+ Lit::Byte(lit) => lit.set_span(span),
+ Lit::Char(lit) => lit.set_span(span),
+ Lit::Int(lit) => lit.set_span(span),
+ Lit::Float(lit) => lit.set_span(span),
+ Lit::Bool(lit) => lit.span = span,
+ Lit::Verbatim(lit) => lit.set_span(span),
+ }
+ }
+ }
+
+ /// Get the byte at offset idx, or a default of `b'\0'` if we're looking
+ /// past the end of the input buffer.
+ pub(crate) fn byte<S: AsRef<[u8]> + ?Sized>(s: &S, idx: usize) -> u8 {
+ let s = s.as_ref();
+ if idx < s.len() {
+ s[idx]
+ } else {
+ 0
+ }
+ }
+
+ fn next_chr(s: &str) -> char {
+ s.chars().next().unwrap_or('\0')
+ }
+
+ // Returns (content, suffix).
+ pub(crate) fn parse_lit_str(s: &str) -> (Box<str>, Box<str>) {
+ match byte(s, 0) {
+ b'"' => parse_lit_str_cooked(s),
+ b'r' => parse_lit_str_raw(s),
+ _ => unreachable!(),
+ }
+ }
+
+ fn parse_lit_str_cooked(mut s: &str) -> (Box<str>, Box<str>) {
+ assert_eq!(byte(s, 0), b'"');
+ s = &s[1..];
+
+ let mut content = String::new();
+ 'outer: loop {
+ let ch = match byte(s, 0) {
+ b'"' => break,
+ b'\\' => {
+ let b = byte(s, 1);
+ s = &s[2..];
+ match b {
+ b'x' => {
+ let (byte, rest) = backslash_x(s);
+ s = rest;
+ assert!(byte <= 0x7F, "invalid \\x byte in string literal");
+ char::from_u32(u32::from(byte)).unwrap()
+ }
+ b'u' => {
+ let (ch, rest) = backslash_u(s);
+ s = rest;
+ ch
+ }
+ b'n' => '\n',
+ b'r' => '\r',
+ b't' => '\t',
+ b'\\' => '\\',
+ b'0' => '\0',
+ b'\'' => '\'',
+ b'"' => '"',
+ b'\r' | b'\n' => loop {
+ let b = byte(s, 0);
+ match b {
+ b' ' | b'\t' | b'\n' | b'\r' => s = &s[1..],
+ _ => continue 'outer,
+ }
+ },
+ b => panic!(
+ "unexpected byte '{}' after \\ character in string literal",
+ ascii::escape_default(b),
+ ),
+ }
+ }
+ b'\r' => {
+ assert_eq!(byte(s, 1), b'\n', "bare CR not allowed in string");
+ s = &s[2..];
+ '\n'
+ }
+ _ => {
+ let ch = next_chr(s);
+ s = &s[ch.len_utf8()..];
+ ch
+ }
+ };
+ content.push(ch);
+ }
+
+ assert!(s.starts_with('"'));
+ let content = content.into_boxed_str();
+ let suffix = s[1..].to_owned().into_boxed_str();
+ (content, suffix)
+ }
+
+ fn parse_lit_str_raw(mut s: &str) -> (Box<str>, Box<str>) {
+ assert_eq!(byte(s, 0), b'r');
+ s = &s[1..];
+
+ let mut pounds = 0;
+ while byte(s, pounds) == b'#' {
+ pounds += 1;
+ }
+ assert_eq!(byte(s, pounds), b'"');
+ let close = s.rfind('"').unwrap();
+ for end in s[close + 1..close + 1 + pounds].bytes() {
+ assert_eq!(end, b'#');
+ }
+
+ let content = s[pounds + 1..close].to_owned().into_boxed_str();
+ let suffix = s[close + 1 + pounds..].to_owned().into_boxed_str();
+ (content, suffix)
+ }
+
+ // Returns (content, suffix).
+ pub(crate) fn parse_lit_byte_str(s: &str) -> (Vec<u8>, Box<str>) {
+ assert_eq!(byte(s, 0), b'b');
+ match byte(s, 1) {
+ b'"' => parse_lit_byte_str_cooked(s),
+ b'r' => parse_lit_byte_str_raw(s),
+ _ => unreachable!(),
+ }
+ }
+
+ fn parse_lit_byte_str_cooked(mut s: &str) -> (Vec<u8>, Box<str>) {
+ assert_eq!(byte(s, 0), b'b');
+ assert_eq!(byte(s, 1), b'"');
+ s = &s[2..];
+
+ // We're going to want to have slices which don't respect codepoint boundaries.
+ let mut v = s.as_bytes();
+
+ let mut out = Vec::new();
+ 'outer: loop {
+ let byte = match byte(v, 0) {
+ b'"' => break,
+ b'\\' => {
+ let b = byte(v, 1);
+ v = &v[2..];
+ match b {
+ b'x' => {
+ let (b, rest) = backslash_x(v);
+ v = rest;
+ b
+ }
+ b'n' => b'\n',
+ b'r' => b'\r',
+ b't' => b'\t',
+ b'\\' => b'\\',
+ b'0' => b'\0',
+ b'\'' => b'\'',
+ b'"' => b'"',
+ b'\r' | b'\n' => loop {
+ let byte = byte(v, 0);
+ if matches!(byte, b' ' | b'\t' | b'\n' | b'\r') {
+ v = &v[1..];
+ } else {
+ continue 'outer;
+ }
+ },
+ b => panic!(
+ "unexpected byte '{}' after \\ character in byte-string literal",
+ ascii::escape_default(b),
+ ),
+ }
+ }
+ b'\r' => {
+ assert_eq!(byte(v, 1), b'\n', "bare CR not allowed in string");
+ v = &v[2..];
+ b'\n'
+ }
+ b => {
+ v = &v[1..];
+ b
+ }
+ };
+ out.push(byte);
+ }
+
+ assert_eq!(byte(v, 0), b'"');
+ let suffix = s[s.len() - v.len() + 1..].to_owned().into_boxed_str();
+ (out, suffix)
+ }
+
+ fn parse_lit_byte_str_raw(s: &str) -> (Vec<u8>, Box<str>) {
+ assert_eq!(byte(s, 0), b'b');
+ let (value, suffix) = parse_lit_str_raw(&s[1..]);
+ (String::from(value).into_bytes(), suffix)
+ }
+
+ // Returns (content, suffix).
+ pub(crate) fn parse_lit_c_str(s: &str) -> (CString, Box<str>) {
+ assert_eq!(byte(s, 0), b'c');
+ match byte(s, 1) {
+ b'"' => parse_lit_c_str_cooked(s),
+ b'r' => parse_lit_c_str_raw(s),
+ _ => unreachable!(),
+ }
+ }
+
+ fn parse_lit_c_str_cooked(mut s: &str) -> (CString, Box<str>) {
+ assert_eq!(byte(s, 0), b'c');
+ assert_eq!(byte(s, 1), b'"');
+ s = &s[2..];
+
+ // We're going to want to have slices which don't respect codepoint boundaries.
+ let mut v = s.as_bytes();
+
+ let mut out = Vec::new();
+ 'outer: loop {
+ let byte = match byte(v, 0) {
+ b'"' => break,
+ b'\\' => {
+ let b = byte(v, 1);
+ v = &v[2..];
+ match b {
+ b'x' => {
+ let (b, rest) = backslash_x(v);
+ assert!(b != 0, "\\x00 is not allowed in C-string literal");
+ v = rest;
+ b
+ }
+ b'u' => {
+ let (ch, rest) = backslash_u(v);
+ assert!(ch != '\0', "\\u{{0}} is not allowed in C-string literal");
+ v = rest;
+ out.extend_from_slice(ch.encode_utf8(&mut [0u8; 4]).as_bytes());
+ continue 'outer;
+ }
+ b'n' => b'\n',
+ b'r' => b'\r',
+ b't' => b'\t',
+ b'\\' => b'\\',
+ b'\'' => b'\'',
+ b'"' => b'"',
+ b'\r' | b'\n' => loop {
+ let byte = byte(v, 0);
+ if matches!(byte, b' ' | b'\t' | b'\n' | b'\r') {
+ v = &v[1..];
+ } else {
+ continue 'outer;
+ }
+ },
+ b => panic!(
+ "unexpected byte '{}' after \\ character in byte literal",
+ ascii::escape_default(b),
+ ),
+ }
+ }
+ b'\r' => {
+ assert_eq!(byte(v, 1), b'\n', "bare CR not allowed in string");
+ v = &v[2..];
+ b'\n'
+ }
+ b => {
+ v = &v[1..];
+ b
+ }
+ };
+ out.push(byte);
+ }
+
+ assert_eq!(byte(v, 0), b'"');
+ let suffix = s[s.len() - v.len() + 1..].to_owned().into_boxed_str();
+ (CString::new(out).unwrap(), suffix)
+ }
+
+ fn parse_lit_c_str_raw(s: &str) -> (CString, Box<str>) {
+ assert_eq!(byte(s, 0), b'c');
+ let (value, suffix) = parse_lit_str_raw(&s[1..]);
+ (CString::new(String::from(value)).unwrap(), suffix)
+ }
+
+ // Returns (value, suffix).
+ pub(crate) fn parse_lit_byte(s: &str) -> (u8, Box<str>) {
+ assert_eq!(byte(s, 0), b'b');
+ assert_eq!(byte(s, 1), b'\'');
+
+ // We're going to want to have slices which don't respect codepoint boundaries.
+ let mut v = &s.as_bytes()[2..];
+
+ let b = match byte(v, 0) {
+ b'\\' => {
+ let b = byte(v, 1);
+ v = &v[2..];
+ match b {
+ b'x' => {
+ let (b, rest) = backslash_x(v);
+ v = rest;
+ b
+ }
+ b'n' => b'\n',
+ b'r' => b'\r',
+ b't' => b'\t',
+ b'\\' => b'\\',
+ b'0' => b'\0',
+ b'\'' => b'\'',
+ b'"' => b'"',
+ b => panic!(
+ "unexpected byte '{}' after \\ character in byte literal",
+ ascii::escape_default(b),
+ ),
+ }
+ }
+ b => {
+ v = &v[1..];
+ b
+ }
+ };
+
+ assert_eq!(byte(v, 0), b'\'');
+ let suffix = s[s.len() - v.len() + 1..].to_owned().into_boxed_str();
+ (b, suffix)
+ }
+
+ // Returns (value, suffix).
+ pub(crate) fn parse_lit_char(mut s: &str) -> (char, Box<str>) {
+ assert_eq!(byte(s, 0), b'\'');
+ s = &s[1..];
+
+ let ch = match byte(s, 0) {
+ b'\\' => {
+ let b = byte(s, 1);
+ s = &s[2..];
+ match b {
+ b'x' => {
+ let (byte, rest) = backslash_x(s);
+ s = rest;
+ assert!(byte <= 0x7F, "invalid \\x byte in character literal");
+ char::from_u32(u32::from(byte)).unwrap()
+ }
+ b'u' => {
+ let (ch, rest) = backslash_u(s);
+ s = rest;
+ ch
+ }
+ b'n' => '\n',
+ b'r' => '\r',
+ b't' => '\t',
+ b'\\' => '\\',
+ b'0' => '\0',
+ b'\'' => '\'',
+ b'"' => '"',
+ b => panic!(
+ "unexpected byte '{}' after \\ character in character literal",
+ ascii::escape_default(b),
+ ),
+ }
+ }
+ _ => {
+ let ch = next_chr(s);
+ s = &s[ch.len_utf8()..];
+ ch
+ }
+ };
+ assert_eq!(byte(s, 0), b'\'');
+ let suffix = s[1..].to_owned().into_boxed_str();
+ (ch, suffix)
+ }
+
+ fn backslash_x<S>(s: &S) -> (u8, &S)
+ where
+ S: Index<RangeFrom<usize>, Output = S> + AsRef<[u8]> + ?Sized,
+ {
+ let mut ch = 0;
+ let b0 = byte(s, 0);
+ let b1 = byte(s, 1);
+ ch += 0x10
+ * match b0 {
+ b'0'..=b'9' => b0 - b'0',
+ b'a'..=b'f' => 10 + (b0 - b'a'),
+ b'A'..=b'F' => 10 + (b0 - b'A'),
+ _ => panic!("unexpected non-hex character after \\x"),
+ };
+ ch += match b1 {
+ b'0'..=b'9' => b1 - b'0',
+ b'a'..=b'f' => 10 + (b1 - b'a'),
+ b'A'..=b'F' => 10 + (b1 - b'A'),
+ _ => panic!("unexpected non-hex character after \\x"),
+ };
+ (ch, &s[2..])
+ }
+
+ fn backslash_u<S>(mut s: &S) -> (char, &S)
+ where
+ S: Index<RangeFrom<usize>, Output = S> + AsRef<[u8]> + ?Sized,
+ {
+ if byte(s, 0) != b'{' {
+ panic!("{}", "expected { after \\u");
+ }
+ s = &s[1..];
+
+ let mut ch = 0;
+ let mut digits = 0;
+ loop {
+ let b = byte(s, 0);
+ let digit = match b {
+ b'0'..=b'9' => b - b'0',
+ b'a'..=b'f' => 10 + b - b'a',
+ b'A'..=b'F' => 10 + b - b'A',
+ b'_' if digits > 0 => {
+ s = &s[1..];
+ continue;
+ }
+ b'}' if digits == 0 => panic!("invalid empty unicode escape"),
+ b'}' => break,
+ _ => panic!("unexpected non-hex character after \\u"),
+ };
+ if digits == 6 {
+ panic!("overlong unicode escape (must have at most 6 hex digits)");
+ }
+ ch *= 0x10;
+ ch += u32::from(digit);
+ digits += 1;
+ s = &s[1..];
+ }
+ assert!(byte(s, 0) == b'}');
+ s = &s[1..];
+
+ if let Some(ch) = char::from_u32(ch) {
+ (ch, s)
+ } else {
+ panic!("character code {:x} is not a valid unicode character", ch);
+ }
+ }
+
+ // Returns base 10 digits and suffix.
+ pub(crate) fn parse_lit_int(mut s: &str) -> Option<(Box<str>, Box<str>)> {
+ let negative = byte(s, 0) == b'-';
+ if negative {
+ s = &s[1..];
+ }
+
+ let base = match (byte(s, 0), byte(s, 1)) {
+ (b'0', b'x') => {
+ s = &s[2..];
+ 16
+ }
+ (b'0', b'o') => {
+ s = &s[2..];
+ 8
+ }
+ (b'0', b'b') => {
+ s = &s[2..];
+ 2
+ }
+ (b'0'..=b'9', _) => 10,
+ _ => return None,
+ };
+
+ let mut value = BigInt::new();
+ let mut has_digit = false;
+ 'outer: loop {
+ let b = byte(s, 0);
+ let digit = match b {
+ b'0'..=b'9' => b - b'0',
+ b'a'..=b'f' if base > 10 => b - b'a' + 10,
+ b'A'..=b'F' if base > 10 => b - b'A' + 10,
+ b'_' => {
+ s = &s[1..];
+ continue;
+ }
+ // If looking at a floating point literal, we don't want to
+ // consider it an integer.
+ b'.' if base == 10 => return None,
+ b'e' | b'E' if base == 10 => {
+ let mut has_exp = false;
+ for (i, b) in s[1..].bytes().enumerate() {
+ match b {
+ b'_' => {}
+ b'-' | b'+' => return None,
+ b'0'..=b'9' => has_exp = true,
+ _ => {
+ let suffix = &s[1 + i..];
+ if has_exp && crate::ident::xid_ok(suffix) {
+ return None;
+ } else {
+ break 'outer;
+ }
+ }
+ }
+ }
+ if has_exp {
+ return None;
+ } else {
+ break;
+ }
+ }
+ _ => break,
+ };
+
+ if digit >= base {
+ return None;
+ }
+
+ has_digit = true;
+ value *= base;
+ value += digit;
+ s = &s[1..];
+ }
+
+ if !has_digit {
+ return None;
+ }
+
+ let suffix = s;
+ if suffix.is_empty() || crate::ident::xid_ok(suffix) {
+ let mut repr = value.to_string();
+ if negative {
+ repr.insert(0, '-');
+ }
+ Some((repr.into_boxed_str(), suffix.to_owned().into_boxed_str()))
+ } else {
+ None
+ }
+ }
+
+ // Returns base 10 digits and suffix.
+ pub(crate) fn parse_lit_float(input: &str) -> Option<(Box<str>, Box<str>)> {
+ // Rust's floating point literals are very similar to the ones parsed by
+ // the standard library, except that rust's literals can contain
+ // ignorable underscores. Let's remove those underscores.
+
+ let mut bytes = input.to_owned().into_bytes();
+
+ let start = (*bytes.first()? == b'-') as usize;
+ match bytes.get(start)? {
+ b'0'..=b'9' => {}
+ _ => return None,
+ }
+
+ let mut read = start;
+ let mut write = start;
+ let mut has_dot = false;
+ let mut has_e = false;
+ let mut has_sign = false;
+ let mut has_exponent = false;
+ while read < bytes.len() {
+ match bytes[read] {
+ b'_' => {
+ // Don't increase write
+ read += 1;
+ continue;
+ }
+ b'0'..=b'9' => {
+ if has_e {
+ has_exponent = true;
+ }
+ bytes[write] = bytes[read];
+ }
+ b'.' => {
+ if has_e || has_dot {
+ return None;
+ }
+ has_dot = true;
+ bytes[write] = b'.';
+ }
+ b'e' | b'E' => {
+ match bytes[read + 1..]
+ .iter()
+ .find(|b| **b != b'_')
+ .unwrap_or(&b'\0')
+ {
+ b'-' | b'+' | b'0'..=b'9' => {}
+ _ => break,
+ }
+ if has_e {
+ if has_exponent {
+ break;
+ } else {
+ return None;
+ }
+ }
+ has_e = true;
+ bytes[write] = b'e';
+ }
+ b'-' | b'+' => {
+ if has_sign || has_exponent || !has_e {
+ return None;
+ }
+ has_sign = true;
+ if bytes[read] == b'-' {
+ bytes[write] = bytes[read];
+ } else {
+ // Omit '+'
+ read += 1;
+ continue;
+ }
+ }
+ _ => break,
+ }
+ read += 1;
+ write += 1;
+ }
+
+ if has_e && !has_exponent {
+ return None;
+ }
+
+ let mut digits = String::from_utf8(bytes).unwrap();
+ let suffix = digits.split_off(read);
+ digits.truncate(write);
+ if suffix.is_empty() || crate::ident::xid_ok(&suffix) {
+ Some((digits.into_boxed_str(), suffix.into_boxed_str()))
+ } else {
+ None
+ }
+ }
+}
diff --git a/rust/syn/lookahead.rs b/rust/syn/lookahead.rs
new file mode 100644
index 000000000000..da13ffc47a7a
--- /dev/null
+++ b/rust/syn/lookahead.rs
@@ -0,0 +1,332 @@
+use crate::buffer::Cursor;
+use crate::error::{self, Error};
+use crate::sealed::lookahead::Sealed;
+use crate::span::IntoSpans;
+use crate::token::{CustomToken, Token};
+use proc_macro2::{Delimiter, Span};
+use std::cell::RefCell;
+
+/// Support for checking the next token in a stream to decide how to parse.
+///
+/// An important advantage over [`ParseStream::peek`] is that here we
+/// automatically construct an appropriate error message based on the token
+/// alternatives that get peeked. If you are producing your own error message,
+/// go ahead and use `ParseStream::peek` instead.
+///
+/// Use [`ParseStream::lookahead1`] to construct this object.
+///
+/// [`ParseStream::peek`]: crate::parse::ParseBuffer::peek
+/// [`ParseStream::lookahead1`]: crate::parse::ParseBuffer::lookahead1
+///
+/// Consuming tokens from the source stream after constructing a lookahead
+/// object does not also advance the lookahead object.
+///
+/// # Example
+///
+/// ```
+/// use syn::{ConstParam, Ident, Lifetime, LifetimeParam, Result, Token, TypeParam};
+/// use syn::parse::{Parse, ParseStream};
+///
+/// // A generic parameter, a single one of the comma-separated elements inside
+/// // angle brackets in:
+/// //
+/// // fn f<T: Clone, 'a, 'b: 'a, const N: usize>() { ... }
+/// //
+/// // On invalid input, lookahead gives us a reasonable error message.
+/// //
+/// // error: expected one of: identifier, lifetime, `const`
+/// // |
+/// // 5 | fn f<!Sized>() {}
+/// // | ^
+/// enum GenericParam {
+/// Type(TypeParam),
+/// Lifetime(LifetimeParam),
+/// Const(ConstParam),
+/// }
+///
+/// impl Parse for GenericParam {
+/// fn parse(input: ParseStream) -> Result<Self> {
+/// let lookahead = input.lookahead1();
+/// if lookahead.peek(Ident) {
+/// input.parse().map(GenericParam::Type)
+/// } else if lookahead.peek(Lifetime) {
+/// input.parse().map(GenericParam::Lifetime)
+/// } else if lookahead.peek(Token![const]) {
+/// input.parse().map(GenericParam::Const)
+/// } else {
+/// Err(lookahead.error())
+/// }
+/// }
+/// }
+/// ```
+pub struct Lookahead1<'a> {
+ scope: Span,
+ cursor: Cursor<'a>,
+ comparisons: RefCell<Vec<&'static str>>,
+}
+
+pub(crate) fn new(scope: Span, cursor: Cursor) -> Lookahead1 {
+ Lookahead1 {
+ scope,
+ cursor,
+ comparisons: RefCell::new(Vec::new()),
+ }
+}
+
+fn peek_impl(
+ lookahead: &Lookahead1,
+ peek: fn(Cursor) -> bool,
+ display: fn() -> &'static str,
+) -> bool {
+ if peek(lookahead.cursor) {
+ return true;
+ }
+ lookahead.comparisons.borrow_mut().push(display());
+ false
+}
+
+impl<'a> Lookahead1<'a> {
+ /// Looks at the next token in the parse stream to determine whether it
+ /// matches the requested type of token.
+ ///
+ /// # Syntax
+ ///
+ /// Note that this method does not use turbofish syntax. Pass the peek type
+ /// inside of parentheses.
+ ///
+ /// - `input.peek(Token![struct])`
+ /// - `input.peek(Token![==])`
+ /// - `input.peek(Ident)` *(does not accept keywords)*
+ /// - `input.peek(Ident::peek_any)`
+ /// - `input.peek(Lifetime)`
+ /// - `input.peek(token::Brace)`
+ pub fn peek<T: Peek>(&self, token: T) -> bool {
+ let _ = token;
+ peek_impl(self, T::Token::peek, T::Token::display)
+ }
+
+ /// Triggers an error at the current position of the parse stream.
+ ///
+ /// The error message will identify all of the expected token types that
+ /// have been peeked against this lookahead instance.
+ pub fn error(self) -> Error {
+ let mut comparisons = self.comparisons.into_inner();
+ comparisons.retain_mut(|display| {
+ if *display == "`)`" {
+ *display = match self.cursor.scope_delimiter() {
+ Delimiter::Parenthesis => "`)`",
+ Delimiter::Brace => "`}`",
+ Delimiter::Bracket => "`]`",
+ Delimiter::None => return false,
+ }
+ }
+ true
+ });
+ match comparisons.len() {
+ 0 => {
+ if self.cursor.eof() {
+ Error::new(self.scope, "unexpected end of input")
+ } else {
+ Error::new(self.cursor.span(), "unexpected token")
+ }
+ }
+ 1 => {
+ let message = format!("expected {}", comparisons[0]);
+ error::new_at(self.scope, self.cursor, message)
+ }
+ 2 => {
+ let message = format!("expected {} or {}", comparisons[0], comparisons[1]);
+ error::new_at(self.scope, self.cursor, message)
+ }
+ _ => {
+ let join = comparisons.join(", ");
+ let message = format!("expected one of: {}", join);
+ error::new_at(self.scope, self.cursor, message)
+ }
+ }
+ }
+}
+
+/// Types that can be parsed by looking at just one token.
+///
+/// Use [`ParseStream::peek`] to peek one of these types in a parse stream
+/// without consuming it from the stream.
+///
+/// This trait is sealed and cannot be implemented for types outside of Syn.
+///
+/// [`ParseStream::peek`]: crate::parse::ParseBuffer::peek
+pub trait Peek: Sealed {
+ // Not public API.
+ #[doc(hidden)]
+ type Token: Token;
+}
+
+/// Pseudo-token used for peeking the end of a parse stream.
+///
+/// This type is only useful as an argument to one of the following functions:
+///
+/// - [`ParseStream::peek`][crate::parse::ParseBuffer::peek]
+/// - [`ParseStream::peek2`][crate::parse::ParseBuffer::peek2]
+/// - [`ParseStream::peek3`][crate::parse::ParseBuffer::peek3]
+/// - [`Lookahead1::peek`]
+///
+/// The peek will return `true` if there are no remaining tokens after that
+/// point in the parse stream.
+///
+/// # Example
+///
+/// Suppose we are parsing attributes containing core::fmt inspired formatting
+/// arguments:
+///
+/// - `#[fmt("simple example")]`
+/// - `#[fmt("interpolation e{}ample", self.x)]`
+/// - `#[fmt("interpolation e{x}ample")]`
+///
+/// and we want to recognize the cases where no interpolation occurs so that
+/// more efficient code can be generated.
+///
+/// The following implementation uses `input.peek(Token![,]) &&
+/// input.peek2(End)` to recognize the case of a trailing comma without
+/// consuming the comma from the parse stream, because if it isn't a trailing
+/// comma, that same comma needs to be parsed as part of `args`.
+///
+/// ```
+/// use proc_macro2::TokenStream;
+/// use quote::quote;
+/// use syn::parse::{End, Parse, ParseStream, Result};
+/// use syn::{parse_quote, Attribute, LitStr, Token};
+///
+/// struct FormatArgs {
+/// template: LitStr, // "...{}..."
+/// args: TokenStream, // , self.x
+/// }
+///
+/// impl Parse for FormatArgs {
+/// fn parse(input: ParseStream) -> Result<Self> {
+/// let template: LitStr = input.parse()?;
+///
+/// let args = if input.is_empty()
+/// || input.peek(Token![,]) && input.peek2(End)
+/// {
+/// input.parse::<Option<Token![,]>>()?;
+/// TokenStream::new()
+/// } else {
+/// input.parse()?
+/// };
+///
+/// Ok(FormatArgs {
+/// template,
+/// args,
+/// })
+/// }
+/// }
+///
+/// fn main() -> Result<()> {
+/// let attrs: Vec<Attribute> = parse_quote! {
+/// #[fmt("simple example")]
+/// #[fmt("interpolation e{}ample", self.x)]
+/// #[fmt("interpolation e{x}ample")]
+/// };
+///
+/// for attr in &attrs {
+/// let FormatArgs { template, args } = attr.parse_args()?;
+/// let requires_fmt_machinery =
+/// !args.is_empty() || template.value().contains(['{', '}']);
+/// let out = if requires_fmt_machinery {
+/// quote! {
+/// ::core::write!(__formatter, #template #args)
+/// }
+/// } else {
+/// quote! {
+/// __formatter.write_str(#template)
+/// }
+/// };
+/// println!("{}", out);
+/// }
+/// Ok(())
+/// }
+/// ```
+///
+/// Implementing this parsing logic without `peek2(End)` is more clumsy because
+/// we'd need a parse stream actually advanced past the comma before being able
+/// to find out whether there is anything after it. It would look something
+/// like:
+///
+/// ```
+/// # use proc_macro2::TokenStream;
+/// # use syn::parse::{ParseStream, Result};
+/// # use syn::Token;
+/// #
+/// # fn parse(input: ParseStream) -> Result<()> {
+/// use syn::parse::discouraged::Speculative as _;
+///
+/// let ahead = input.fork();
+/// ahead.parse::<Option<Token![,]>>()?;
+/// let args = if ahead.is_empty() {
+/// input.advance_to(&ahead);
+/// TokenStream::new()
+/// } else {
+/// input.parse()?
+/// };
+/// # Ok(())
+/// # }
+/// ```
+///
+/// or:
+///
+/// ```
+/// # use proc_macro2::TokenStream;
+/// # use syn::parse::{ParseStream, Result};
+/// # use syn::Token;
+/// #
+/// # fn parse(input: ParseStream) -> Result<()> {
+/// use quote::ToTokens as _;
+///
+/// let comma: Option<Token![,]> = input.parse()?;
+/// let mut args = TokenStream::new();
+/// if !input.is_empty() {
+/// comma.to_tokens(&mut args);
+/// input.parse::<TokenStream>()?.to_tokens(&mut args);
+/// }
+/// # Ok(())
+/// # }
+/// ```
+pub struct End;
+
+impl Copy for End {}
+
+impl Clone for End {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+
+impl Peek for End {
+ type Token = Self;
+}
+
+impl CustomToken for End {
+ fn peek(cursor: Cursor) -> bool {
+ cursor.eof()
+ }
+
+ fn display() -> &'static str {
+ "`)`" // Lookahead1 error message will fill in the expected close delimiter
+ }
+}
+
+impl<F: Copy + FnOnce(TokenMarker) -> T, T: Token> Peek for F {
+ type Token = T;
+}
+
+pub enum TokenMarker {}
+
+impl<S> IntoSpans<S> for TokenMarker {
+ fn into_spans(self) -> S {
+ match self {}
+ }
+}
+
+impl<F: Copy + FnOnce(TokenMarker) -> T, T: Token> Sealed for F {}
+
+impl Sealed for End {}
diff --git a/rust/syn/mac.rs b/rust/syn/mac.rs
new file mode 100644
index 000000000000..15107801cfee
--- /dev/null
+++ b/rust/syn/mac.rs
@@ -0,0 +1,225 @@
+#[cfg(feature = "parsing")]
+use crate::error::Result;
+#[cfg(feature = "parsing")]
+use crate::parse::{Parse, ParseStream, Parser};
+use crate::path::Path;
+use crate::token::{Brace, Bracket, Paren};
+use proc_macro2::extra::DelimSpan;
+#[cfg(feature = "parsing")]
+use proc_macro2::Delimiter;
+use proc_macro2::TokenStream;
+#[cfg(feature = "parsing")]
+use proc_macro2::TokenTree;
+
+ast_struct! {
+ /// A macro invocation: `println!("{}", mac)`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct Macro {
+ pub path: Path,
+ pub bang_token: Token![!],
+ pub delimiter: MacroDelimiter,
+ pub tokens: TokenStream,
+ }
+}
+
+ast_enum! {
+ /// A grouping token that surrounds a macro body: `m!(...)` or `m!{...}` or `m![...]`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub enum MacroDelimiter {
+ Paren(Paren),
+ Brace(Brace),
+ Bracket(Bracket),
+ }
+}
+
+impl MacroDelimiter {
+ pub fn span(&self) -> &DelimSpan {
+ match self {
+ MacroDelimiter::Paren(token) => &token.span,
+ MacroDelimiter::Brace(token) => &token.span,
+ MacroDelimiter::Bracket(token) => &token.span,
+ }
+ }
+
+ #[cfg(all(feature = "full", any(feature = "parsing", feature = "printing")))]
+ pub(crate) fn is_brace(&self) -> bool {
+ match self {
+ MacroDelimiter::Brace(_) => true,
+ MacroDelimiter::Paren(_) | MacroDelimiter::Bracket(_) => false,
+ }
+ }
+}
+
+impl Macro {
+ /// Parse the tokens within the macro invocation's delimiters into a syntax
+ /// tree.
+ ///
+ /// This is equivalent to `syn::parse2::<T>(mac.tokens)` except that it
+ /// produces a more useful span when `tokens` is empty.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use syn::{parse_quote, Expr, ExprLit, Ident, Lit, LitStr, Macro, Token};
+ /// use syn::ext::IdentExt;
+ /// use syn::parse::{Error, Parse, ParseStream, Result};
+ /// use syn::punctuated::Punctuated;
+ ///
+ /// // The arguments expected by libcore's format_args macro, and as a
+ /// // result most other formatting and printing macros like println.
+ /// //
+ /// // println!("{} is {number:.prec$}", "x", prec=5, number=0.01)
+ /// struct FormatArgs {
+ /// format_string: Expr,
+ /// positional_args: Vec<Expr>,
+ /// named_args: Vec<(Ident, Expr)>,
+ /// }
+ ///
+ /// impl Parse for FormatArgs {
+ /// fn parse(input: ParseStream) -> Result<Self> {
+ /// let format_string: Expr;
+ /// let mut positional_args = Vec::new();
+ /// let mut named_args = Vec::new();
+ ///
+ /// format_string = input.parse()?;
+ /// while !input.is_empty() {
+ /// input.parse::<Token![,]>()?;
+ /// if input.is_empty() {
+ /// break;
+ /// }
+ /// if input.peek(Ident::peek_any) && input.peek2(Token![=]) {
+ /// while !input.is_empty() {
+ /// let name: Ident = input.call(Ident::parse_any)?;
+ /// input.parse::<Token![=]>()?;
+ /// let value: Expr = input.parse()?;
+ /// named_args.push((name, value));
+ /// if input.is_empty() {
+ /// break;
+ /// }
+ /// input.parse::<Token![,]>()?;
+ /// }
+ /// break;
+ /// }
+ /// positional_args.push(input.parse()?);
+ /// }
+ ///
+ /// Ok(FormatArgs {
+ /// format_string,
+ /// positional_args,
+ /// named_args,
+ /// })
+ /// }
+ /// }
+ ///
+ /// // Extract the first argument, the format string literal, from an
+ /// // invocation of a formatting or printing macro.
+ /// fn get_format_string(m: &Macro) -> Result<LitStr> {
+ /// let args: FormatArgs = m.parse_body()?;
+ /// match args.format_string {
+ /// Expr::Lit(ExprLit { lit: Lit::Str(lit), .. }) => Ok(lit),
+ /// other => {
+ /// // First argument was not a string literal expression.
+ /// // Maybe something like: println!(concat!(...), ...)
+ /// Err(Error::new_spanned(other, "format string must be a string literal"))
+ /// }
+ /// }
+ /// }
+ ///
+ /// fn main() {
+ /// let invocation = parse_quote! {
+ /// println!("{:?}", Instant::now())
+ /// };
+ /// let lit = get_format_string(&invocation).unwrap();
+ /// assert_eq!(lit.value(), "{:?}");
+ /// }
+ /// ```
+ #[cfg(feature = "parsing")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ pub fn parse_body<T: Parse>(&self) -> Result<T> {
+ self.parse_body_with(T::parse)
+ }
+
+ /// Parse the tokens within the macro invocation's delimiters using the
+ /// given parser.
+ #[cfg(feature = "parsing")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ pub fn parse_body_with<F: Parser>(&self, parser: F) -> Result<F::Output> {
+ let scope = self.delimiter.span().close();
+ crate::parse::parse_scoped(parser, scope, self.tokens.clone())
+ }
+}
+
+#[cfg(feature = "parsing")]
+pub(crate) fn parse_delimiter(input: ParseStream) -> Result<(MacroDelimiter, TokenStream)> {
+ input.step(|cursor| {
+ if let Some((TokenTree::Group(g), rest)) = cursor.token_tree() {
+ let span = g.delim_span();
+ let delimiter = match g.delimiter() {
+ Delimiter::Parenthesis => MacroDelimiter::Paren(Paren(span)),
+ Delimiter::Brace => MacroDelimiter::Brace(Brace(span)),
+ Delimiter::Bracket => MacroDelimiter::Bracket(Bracket(span)),
+ Delimiter::None => {
+ return Err(cursor.error("expected delimiter"));
+ }
+ };
+ Ok(((delimiter, g.stream()), rest))
+ } else {
+ Err(cursor.error("expected delimiter"))
+ }
+ })
+}
+
+#[cfg(feature = "parsing")]
+pub(crate) mod parsing {
+ use crate::error::Result;
+ use crate::mac::{parse_delimiter, Macro};
+ use crate::parse::{Parse, ParseStream};
+ use crate::path::Path;
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for Macro {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let tokens;
+ Ok(Macro {
+ path: input.call(Path::parse_mod_style)?,
+ bang_token: input.parse()?,
+ delimiter: {
+ let (delimiter, content) = parse_delimiter(input)?;
+ tokens = content;
+ delimiter
+ },
+ tokens,
+ })
+ }
+ }
+}
+
+#[cfg(feature = "printing")]
+mod printing {
+ use crate::mac::{Macro, MacroDelimiter};
+ use crate::path;
+ use crate::path::printing::PathStyle;
+ use crate::token;
+ use proc_macro2::{Delimiter, TokenStream};
+ use quote::ToTokens;
+
+ impl MacroDelimiter {
+ pub(crate) fn surround(&self, tokens: &mut TokenStream, inner: TokenStream) {
+ let (delim, span) = match self {
+ MacroDelimiter::Paren(paren) => (Delimiter::Parenthesis, paren.span),
+ MacroDelimiter::Brace(brace) => (Delimiter::Brace, brace.span),
+ MacroDelimiter::Bracket(bracket) => (Delimiter::Bracket, bracket.span),
+ };
+ token::printing::delim(delim, span.join(), tokens, inner);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for Macro {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ path::printing::print_path(tokens, &self.path, PathStyle::Mod);
+ self.bang_token.to_tokens(tokens);
+ self.delimiter.surround(tokens, self.tokens.clone());
+ }
+ }
+}
diff --git a/rust/syn/macros.rs b/rust/syn/macros.rs
new file mode 100644
index 000000000000..167f2cf260a7
--- /dev/null
+++ b/rust/syn/macros.rs
@@ -0,0 +1,182 @@
+#[cfg_attr(
+ not(any(feature = "full", feature = "derive")),
+ allow(unknown_lints, unused_macro_rules)
+)]
+macro_rules! ast_struct {
+ (
+ $(#[$attr:meta])*
+ $pub:ident $struct:ident $name:ident #full $body:tt
+ ) => {
+ check_keyword_matches!(pub $pub);
+ check_keyword_matches!(struct $struct);
+
+ #[cfg(feature = "full")]
+ $(#[$attr])* $pub $struct $name $body
+
+ #[cfg(not(feature = "full"))]
+ $(#[$attr])* $pub $struct $name {
+ _noconstruct: ::std::marker::PhantomData<::proc_macro2::Span>,
+ }
+
+ #[cfg(all(not(feature = "full"), feature = "printing"))]
+ impl ::quote::ToTokens for $name {
+ fn to_tokens(&self, _: &mut ::proc_macro2::TokenStream) {
+ unreachable!()
+ }
+ }
+ };
+
+ (
+ $(#[$attr:meta])*
+ $pub:ident $struct:ident $name:ident $body:tt
+ ) => {
+ check_keyword_matches!(pub $pub);
+ check_keyword_matches!(struct $struct);
+
+ $(#[$attr])* $pub $struct $name $body
+ };
+}
+
+#[cfg(any(feature = "full", feature = "derive"))]
+macro_rules! ast_enum {
+ (
+ $(#[$enum_attr:meta])*
+ $pub:ident $enum:ident $name:ident $body:tt
+ ) => {
+ check_keyword_matches!(pub $pub);
+ check_keyword_matches!(enum $enum);
+
+ $(#[$enum_attr])* $pub $enum $name $body
+ };
+}
+
+macro_rules! ast_enum_of_structs {
+ (
+ $(#[$enum_attr:meta])*
+ $pub:ident $enum:ident $name:ident $body:tt
+ ) => {
+ check_keyword_matches!(pub $pub);
+ check_keyword_matches!(enum $enum);
+
+ $(#[$enum_attr])* $pub $enum $name $body
+
+ ast_enum_of_structs_impl!($name $body);
+
+ #[cfg(feature = "printing")]
+ generate_to_tokens!(() tokens $name $body);
+ };
+}
+
+macro_rules! ast_enum_of_structs_impl {
+ (
+ $name:ident {
+ $(
+ $(#[cfg $cfg_attr:tt])*
+ $(#[doc $($doc_attr:tt)*])*
+ $variant:ident $( ($member:ident) )*,
+ )*
+ }
+ ) => {
+ $($(
+ ast_enum_from_struct!($name::$variant, $member);
+ )*)*
+ };
+}
+
+macro_rules! ast_enum_from_struct {
+ // No From<TokenStream> for verbatim variants.
+ ($name:ident::Verbatim, $member:ident) => {};
+
+ ($name:ident::$variant:ident, $member:ident) => {
+ impl From<$member> for $name {
+ fn from(e: $member) -> $name {
+ $name::$variant(e)
+ }
+ }
+ };
+}
+
+#[cfg(feature = "printing")]
+macro_rules! generate_to_tokens {
+ (
+ ($($arms:tt)*) $tokens:ident $name:ident {
+ $(#[cfg $cfg_attr:tt])*
+ $(#[doc $($doc_attr:tt)*])*
+ $variant:ident,
+ $($next:tt)*
+ }
+ ) => {
+ generate_to_tokens!(
+ ($($arms)* $(#[cfg $cfg_attr])* $name::$variant => {})
+ $tokens $name { $($next)* }
+ );
+ };
+
+ (
+ ($($arms:tt)*) $tokens:ident $name:ident {
+ $(#[cfg $cfg_attr:tt])*
+ $(#[doc $($doc_attr:tt)*])*
+ $variant:ident($member:ident),
+ $($next:tt)*
+ }
+ ) => {
+ generate_to_tokens!(
+ ($($arms)* $(#[cfg $cfg_attr])* $name::$variant(_e) => _e.to_tokens($tokens),)
+ $tokens $name { $($next)* }
+ );
+ };
+
+ (($($arms:tt)*) $tokens:ident $name:ident {}) => {
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ::quote::ToTokens for $name {
+ fn to_tokens(&self, $tokens: &mut ::proc_macro2::TokenStream) {
+ match self {
+ $($arms)*
+ }
+ }
+ }
+ };
+}
+
+// Rustdoc bug: does not respect the doc(hidden) on some items.
+#[cfg(all(doc, feature = "parsing"))]
+macro_rules! pub_if_not_doc {
+ ($(#[$m:meta])* $pub:ident $($item:tt)*) => {
+ check_keyword_matches!(pub $pub);
+
+ $(#[$m])*
+ $pub(crate) $($item)*
+ };
+}
+
+#[cfg(all(not(doc), feature = "parsing"))]
+macro_rules! pub_if_not_doc {
+ ($(#[$m:meta])* $pub:ident $($item:tt)*) => {
+ check_keyword_matches!(pub $pub);
+
+ $(#[$m])*
+ $pub $($item)*
+ };
+}
+
+macro_rules! check_keyword_matches {
+ (enum enum) => {};
+ (pub pub) => {};
+ (struct struct) => {};
+}
+
+#[cfg(any(feature = "full", feature = "derive"))]
+macro_rules! return_impl_trait {
+ (
+ $(#[$attr:meta])*
+ $vis:vis fn $name:ident $args:tt -> $impl_trait:ty [$concrete:ty] $body:block
+ ) => {
+ #[cfg(not(docsrs))]
+ $(#[$attr])*
+ $vis fn $name $args -> $concrete $body
+
+ #[cfg(docsrs)]
+ $(#[$attr])*
+ $vis fn $name $args -> $impl_trait $body
+ };
+}
diff --git a/rust/syn/meta.rs b/rust/syn/meta.rs
new file mode 100644
index 000000000000..ffeeb2629f4f
--- /dev/null
+++ b/rust/syn/meta.rs
@@ -0,0 +1,427 @@
+//! Facility for interpreting structured content inside of an `Attribute`.
+
+use crate::error::{Error, Result};
+use crate::ext::IdentExt as _;
+use crate::lit::Lit;
+use crate::parse::{ParseStream, Parser};
+use crate::path::{Path, PathSegment};
+use crate::punctuated::Punctuated;
+use proc_macro2::Ident;
+use std::fmt::Display;
+
+/// Make a parser that is usable with `parse_macro_input!` in a
+/// `#[proc_macro_attribute]` macro.
+///
+/// *Warning:* When parsing attribute args **other than** the
+/// `proc_macro::TokenStream` input of a `proc_macro_attribute`, you do **not**
+/// need this function. In several cases your callers will get worse error
+/// messages if you use this function, because the surrounding delimiter's span
+/// is concealed from attribute macros by rustc. Use
+/// [`Attribute::parse_nested_meta`] instead.
+///
+/// [`Attribute::parse_nested_meta`]: crate::Attribute::parse_nested_meta
+///
+/// # Example
+///
+/// This example implements an attribute macro whose invocations look like this:
+///
+/// ```
+/// # const IGNORE: &str = stringify! {
+/// #[tea(kind = "EarlGrey", hot)]
+/// struct Picard {...}
+/// # };
+/// ```
+///
+/// The "parameters" supported by the attribute are:
+///
+/// - `kind = "..."`
+/// - `hot`
+/// - `with(sugar, milk, ...)`, a comma-separated list of ingredients
+///
+/// ```
+/// # extern crate proc_macro;
+/// #
+/// use proc_macro::TokenStream;
+/// use syn::{parse_macro_input, LitStr, Path};
+///
+/// # const IGNORE: &str = stringify! {
+/// #[proc_macro_attribute]
+/// # };
+/// pub fn tea(args: TokenStream, input: TokenStream) -> TokenStream {
+/// let mut kind: Option<LitStr> = None;
+/// let mut hot: bool = false;
+/// let mut with: Vec<Path> = Vec::new();
+/// let tea_parser = syn::meta::parser(|meta| {
+/// if meta.path.is_ident("kind") {
+/// kind = Some(meta.value()?.parse()?);
+/// Ok(())
+/// } else if meta.path.is_ident("hot") {
+/// hot = true;
+/// Ok(())
+/// } else if meta.path.is_ident("with") {
+/// meta.parse_nested_meta(|meta| {
+/// with.push(meta.path);
+/// Ok(())
+/// })
+/// } else {
+/// Err(meta.error("unsupported tea property"))
+/// }
+/// });
+///
+/// parse_macro_input!(args with tea_parser);
+/// eprintln!("kind={kind:?} hot={hot} with={with:?}");
+///
+/// /* ... */
+/// # TokenStream::new()
+/// }
+/// ```
+///
+/// The `syn::meta` library will take care of dealing with the commas including
+/// trailing commas, and producing sensible error messages on unexpected input.
+///
+/// ```console
+/// error: expected `,`
+/// --> src/main.rs:3:37
+/// |
+/// 3 | #[tea(kind = "EarlGrey", with(sugar = "lol", milk))]
+/// | ^
+/// ```
+///
+/// # Example
+///
+/// Same as above but we factor out most of the logic into a separate function.
+///
+/// ```
+/// # extern crate proc_macro;
+/// #
+/// use proc_macro::TokenStream;
+/// use syn::meta::ParseNestedMeta;
+/// use syn::parse::{Parser, Result};
+/// use syn::{parse_macro_input, LitStr, Path};
+///
+/// # const IGNORE: &str = stringify! {
+/// #[proc_macro_attribute]
+/// # };
+/// pub fn tea(args: TokenStream, input: TokenStream) -> TokenStream {
+/// let mut attrs = TeaAttributes::default();
+/// let tea_parser = syn::meta::parser(|meta| attrs.parse(meta));
+/// parse_macro_input!(args with tea_parser);
+///
+/// /* ... */
+/// # TokenStream::new()
+/// }
+///
+/// #[derive(Default)]
+/// struct TeaAttributes {
+/// kind: Option<LitStr>,
+/// hot: bool,
+/// with: Vec<Path>,
+/// }
+///
+/// impl TeaAttributes {
+/// fn parse(&mut self, meta: ParseNestedMeta) -> Result<()> {
+/// if meta.path.is_ident("kind") {
+/// self.kind = Some(meta.value()?.parse()?);
+/// Ok(())
+/// } else /* just like in last example */
+/// # { unimplemented!() }
+///
+/// }
+/// }
+/// ```
+pub fn parser(logic: impl FnMut(ParseNestedMeta) -> Result<()>) -> impl Parser<Output = ()> {
+ |input: ParseStream| {
+ if input.is_empty() {
+ Ok(())
+ } else {
+ parse_nested_meta(input, logic)
+ }
+ }
+}
+
+/// Context for parsing a single property in the conventional syntax for
+/// structured attributes.
+///
+/// # Examples
+///
+/// Refer to usage examples on the following two entry-points:
+///
+/// - [`Attribute::parse_nested_meta`] if you have an entire `Attribute` to
+/// parse. Always use this if possible. Generally this is able to produce
+/// better error messages because `Attribute` holds span information for all
+/// of the delimiters therein.
+///
+/// - [`syn::meta::parser`] if you are implementing a `proc_macro_attribute`
+/// macro and parsing the arguments to the attribute macro, i.e. the ones
+/// written in the same attribute that dispatched the macro invocation. Rustc
+/// does not pass span information for the surrounding delimiters into the
+/// attribute macro invocation in this situation, so error messages might be
+/// less precise.
+///
+/// [`Attribute::parse_nested_meta`]: crate::Attribute::parse_nested_meta
+/// [`syn::meta::parser`]: crate::meta::parser
+#[non_exhaustive]
+pub struct ParseNestedMeta<'a> {
+ pub path: Path,
+ pub input: ParseStream<'a>,
+}
+
+impl<'a> ParseNestedMeta<'a> {
+ /// Used when parsing `key = "value"` syntax.
+ ///
+ /// All it does is advance `meta.input` past the `=` sign in the input. You
+ /// could accomplish the same effect by writing
+ /// `meta.parse::<Token![=]>()?`, so at most it is a minor convenience to
+ /// use `meta.value()?`.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use syn::{parse_quote, Attribute, LitStr};
+ ///
+ /// let attr: Attribute = parse_quote! {
+ /// #[tea(kind = "EarlGrey")]
+ /// };
+ /// // conceptually:
+ /// if attr.path().is_ident("tea") { // this parses the `tea`
+ /// attr.parse_nested_meta(|meta| { // this parses the `(`
+ /// if meta.path.is_ident("kind") { // this parses the `kind`
+ /// let value = meta.value()?; // this parses the `=`
+ /// let s: LitStr = value.parse()?; // this parses `"EarlGrey"`
+ /// if s.value() == "EarlGrey" {
+ /// // ...
+ /// }
+ /// Ok(())
+ /// } else {
+ /// Err(meta.error("unsupported attribute"))
+ /// }
+ /// })?;
+ /// }
+ /// # anyhow::Ok(())
+ /// ```
+ pub fn value(&self) -> Result<ParseStream<'a>> {
+ self.input.parse::<Token![=]>()?;
+ Ok(self.input)
+ }
+
+ /// Used when parsing `list(...)` syntax **if** the content inside the
+ /// nested parentheses is also expected to conform to Rust's structured
+ /// attribute convention.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use syn::{parse_quote, Attribute};
+ ///
+ /// let attr: Attribute = parse_quote! {
+ /// #[tea(with(sugar, milk))]
+ /// };
+ ///
+ /// if attr.path().is_ident("tea") {
+ /// attr.parse_nested_meta(|meta| {
+ /// if meta.path.is_ident("with") {
+ /// meta.parse_nested_meta(|meta| { // <---
+ /// if meta.path.is_ident("sugar") {
+ /// // Here we can go even deeper if needed.
+ /// Ok(())
+ /// } else if meta.path.is_ident("milk") {
+ /// Ok(())
+ /// } else {
+ /// Err(meta.error("unsupported ingredient"))
+ /// }
+ /// })
+ /// } else {
+ /// Err(meta.error("unsupported tea property"))
+ /// }
+ /// })?;
+ /// }
+ /// # anyhow::Ok(())
+ /// ```
+ ///
+ /// # Counterexample
+ ///
+ /// If you don't need `parse_nested_meta`'s help in parsing the content
+ /// written within the nested parentheses, keep in mind that you can always
+ /// just parse it yourself from the exposed ParseStream. Rust syntax permits
+ /// arbitrary tokens within those parentheses so for the crazier stuff,
+ /// `parse_nested_meta` is not what you want.
+ ///
+ /// ```
+ /// use syn::{parenthesized, parse_quote, Attribute, LitInt};
+ ///
+ /// let attr: Attribute = parse_quote! {
+ /// #[repr(align(32))]
+ /// };
+ ///
+ /// let mut align: Option<LitInt> = None;
+ /// if attr.path().is_ident("repr") {
+ /// attr.parse_nested_meta(|meta| {
+ /// if meta.path.is_ident("align") {
+ /// let content;
+ /// parenthesized!(content in meta.input);
+ /// align = Some(content.parse()?);
+ /// Ok(())
+ /// } else {
+ /// Err(meta.error("unsupported repr"))
+ /// }
+ /// })?;
+ /// }
+ /// # anyhow::Ok(())
+ /// ```
+ pub fn parse_nested_meta(
+ &self,
+ logic: impl FnMut(ParseNestedMeta) -> Result<()>,
+ ) -> Result<()> {
+ let content;
+ parenthesized!(content in self.input);
+ parse_nested_meta(&content, logic)
+ }
+
+ /// Report that the attribute's content did not conform to expectations.
+ ///
+ /// The span of the resulting error will cover `meta.path` *and* everything
+ /// that has been parsed so far since it.
+ ///
+ /// There are 2 ways you might call this. First, if `meta.path` is not
+ /// something you recognize:
+ ///
+ /// ```
+ /// # use syn::Attribute;
+ /// #
+ /// # fn example(attr: &Attribute) -> syn::Result<()> {
+ /// attr.parse_nested_meta(|meta| {
+ /// if meta.path.is_ident("kind") {
+ /// // ...
+ /// Ok(())
+ /// } else {
+ /// Err(meta.error("unsupported tea property"))
+ /// }
+ /// })?;
+ /// # Ok(())
+ /// # }
+ /// ```
+ ///
+ /// In this case, it behaves exactly like
+ /// `syn::Error::new_spanned(&meta.path, "message...")`.
+ ///
+ /// ```console
+ /// error: unsupported tea property
+ /// --> src/main.rs:3:26
+ /// |
+ /// 3 | #[tea(kind = "EarlGrey", wat = "foo")]
+ /// | ^^^
+ /// ```
+ ///
+ /// More usefully, the second place is if you've already parsed a value but
+ /// have decided not to accept the value:
+ ///
+ /// ```
+ /// # use syn::Attribute;
+ /// #
+ /// # fn example(attr: &Attribute) -> syn::Result<()> {
+ /// use syn::Expr;
+ ///
+ /// attr.parse_nested_meta(|meta| {
+ /// if meta.path.is_ident("kind") {
+ /// let expr: Expr = meta.value()?.parse()?;
+ /// match expr {
+ /// Expr::Lit(expr) => /* ... */
+ /// # unimplemented!(),
+ /// Expr::Path(expr) => /* ... */
+ /// # unimplemented!(),
+ /// Expr::Macro(expr) => /* ... */
+ /// # unimplemented!(),
+ /// _ => Err(meta.error("tea kind must be a string literal, path, or macro")),
+ /// }
+ /// } else /* as above */
+ /// # { unimplemented!() }
+ ///
+ /// })?;
+ /// # Ok(())
+ /// # }
+ /// ```
+ ///
+ /// ```console
+ /// error: tea kind must be a string literal, path, or macro
+ /// --> src/main.rs:3:7
+ /// |
+ /// 3 | #[tea(kind = async { replicator.await })]
+ /// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ /// ```
+ ///
+ /// Often you may want to use `syn::Error::new_spanned` even in this
+ /// situation. In the above code, that would be:
+ ///
+ /// ```
+ /// # use syn::{Error, Expr};
+ /// #
+ /// # fn example(expr: Expr) -> syn::Result<()> {
+ /// match expr {
+ /// Expr::Lit(expr) => /* ... */
+ /// # unimplemented!(),
+ /// Expr::Path(expr) => /* ... */
+ /// # unimplemented!(),
+ /// Expr::Macro(expr) => /* ... */
+ /// # unimplemented!(),
+ /// _ => Err(Error::new_spanned(expr, "unsupported expression type for `kind`")),
+ /// }
+ /// # }
+ /// ```
+ ///
+ /// ```console
+ /// error: unsupported expression type for `kind`
+ /// --> src/main.rs:3:14
+ /// |
+ /// 3 | #[tea(kind = async { replicator.await })]
+ /// | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ /// ```
+ pub fn error(&self, msg: impl Display) -> Error {
+ let start_span = self.path.segments[0].ident.span();
+ let end_span = self.input.cursor().prev_span();
+ crate::error::new2(start_span, end_span, msg)
+ }
+}
+
+pub(crate) fn parse_nested_meta(
+ input: ParseStream,
+ mut logic: impl FnMut(ParseNestedMeta) -> Result<()>,
+) -> Result<()> {
+ loop {
+ let path = input.call(parse_meta_path)?;
+ logic(ParseNestedMeta { path, input })?;
+ if input.is_empty() {
+ return Ok(());
+ }
+ input.parse::<Token![,]>()?;
+ if input.is_empty() {
+ return Ok(());
+ }
+ }
+}
+
+// Like Path::parse_mod_style, but accepts keywords in the path.
+fn parse_meta_path(input: ParseStream) -> Result<Path> {
+ Ok(Path {
+ leading_colon: input.parse()?,
+ segments: {
+ let mut segments = Punctuated::new();
+ if input.peek(Ident::peek_any) {
+ let ident = Ident::parse_any(input)?;
+ segments.push_value(PathSegment::from(ident));
+ } else if input.is_empty() {
+ return Err(input.error("expected nested attribute"));
+ } else if input.peek(Lit) {
+ return Err(input.error("unexpected literal in nested attribute, expected ident"));
+ } else {
+ return Err(input.error("unexpected token in nested attribute, expected ident"));
+ }
+ while input.peek(Token![::]) {
+ let punct = input.parse()?;
+ segments.push_punct(punct);
+ let ident = Ident::parse_any(input)?;
+ segments.push_value(PathSegment::from(ident));
+ }
+ segments
+ },
+ })
+}
diff --git a/rust/syn/op.rs b/rust/syn/op.rs
new file mode 100644
index 000000000000..575d9faa1273
--- /dev/null
+++ b/rust/syn/op.rs
@@ -0,0 +1,219 @@
+ast_enum! {
+ /// A binary operator: `+`, `+=`, `&`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ #[non_exhaustive]
+ pub enum BinOp {
+ /// The `+` operator (addition)
+ Add(Token![+]),
+ /// The `-` operator (subtraction)
+ Sub(Token![-]),
+ /// The `*` operator (multiplication)
+ Mul(Token![*]),
+ /// The `/` operator (division)
+ Div(Token![/]),
+ /// The `%` operator (modulus)
+ Rem(Token![%]),
+ /// The `&&` operator (logical and)
+ And(Token![&&]),
+ /// The `||` operator (logical or)
+ Or(Token![||]),
+ /// The `^` operator (bitwise xor)
+ BitXor(Token![^]),
+ /// The `&` operator (bitwise and)
+ BitAnd(Token![&]),
+ /// The `|` operator (bitwise or)
+ BitOr(Token![|]),
+ /// The `<<` operator (shift left)
+ Shl(Token![<<]),
+ /// The `>>` operator (shift right)
+ Shr(Token![>>]),
+ /// The `==` operator (equality)
+ Eq(Token![==]),
+ /// The `<` operator (less than)
+ Lt(Token![<]),
+ /// The `<=` operator (less than or equal to)
+ Le(Token![<=]),
+ /// The `!=` operator (not equal to)
+ Ne(Token![!=]),
+ /// The `>=` operator (greater than or equal to)
+ Ge(Token![>=]),
+ /// The `>` operator (greater than)
+ Gt(Token![>]),
+ /// The `+=` operator
+ AddAssign(Token![+=]),
+ /// The `-=` operator
+ SubAssign(Token![-=]),
+ /// The `*=` operator
+ MulAssign(Token![*=]),
+ /// The `/=` operator
+ DivAssign(Token![/=]),
+ /// The `%=` operator
+ RemAssign(Token![%=]),
+ /// The `^=` operator
+ BitXorAssign(Token![^=]),
+ /// The `&=` operator
+ BitAndAssign(Token![&=]),
+ /// The `|=` operator
+ BitOrAssign(Token![|=]),
+ /// The `<<=` operator
+ ShlAssign(Token![<<=]),
+ /// The `>>=` operator
+ ShrAssign(Token![>>=]),
+ }
+}
+
+ast_enum! {
+ /// A unary operator: `*`, `!`, `-`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ #[non_exhaustive]
+ pub enum UnOp {
+ /// The `*` operator for dereferencing
+ Deref(Token![*]),
+ /// The `!` operator for logical inversion
+ Not(Token![!]),
+ /// The `-` operator for negation
+ Neg(Token![-]),
+ }
+}
+
+#[cfg(feature = "parsing")]
+pub(crate) mod parsing {
+ use crate::error::Result;
+ use crate::op::{BinOp, UnOp};
+ use crate::parse::{Parse, ParseStream};
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for BinOp {
+ fn parse(input: ParseStream) -> Result<Self> {
+ if input.peek(Token![+=]) {
+ input.parse().map(BinOp::AddAssign)
+ } else if input.peek(Token![-=]) {
+ input.parse().map(BinOp::SubAssign)
+ } else if input.peek(Token![*=]) {
+ input.parse().map(BinOp::MulAssign)
+ } else if input.peek(Token![/=]) {
+ input.parse().map(BinOp::DivAssign)
+ } else if input.peek(Token![%=]) {
+ input.parse().map(BinOp::RemAssign)
+ } else if input.peek(Token![^=]) {
+ input.parse().map(BinOp::BitXorAssign)
+ } else if input.peek(Token![&=]) {
+ input.parse().map(BinOp::BitAndAssign)
+ } else if input.peek(Token![|=]) {
+ input.parse().map(BinOp::BitOrAssign)
+ } else if input.peek(Token![<<=]) {
+ input.parse().map(BinOp::ShlAssign)
+ } else if input.peek(Token![>>=]) {
+ input.parse().map(BinOp::ShrAssign)
+ } else if input.peek(Token![&&]) {
+ input.parse().map(BinOp::And)
+ } else if input.peek(Token![||]) {
+ input.parse().map(BinOp::Or)
+ } else if input.peek(Token![<<]) {
+ input.parse().map(BinOp::Shl)
+ } else if input.peek(Token![>>]) {
+ input.parse().map(BinOp::Shr)
+ } else if input.peek(Token![==]) {
+ input.parse().map(BinOp::Eq)
+ } else if input.peek(Token![<=]) {
+ input.parse().map(BinOp::Le)
+ } else if input.peek(Token![!=]) {
+ input.parse().map(BinOp::Ne)
+ } else if input.peek(Token![>=]) {
+ input.parse().map(BinOp::Ge)
+ } else if input.peek(Token![+]) {
+ input.parse().map(BinOp::Add)
+ } else if input.peek(Token![-]) {
+ input.parse().map(BinOp::Sub)
+ } else if input.peek(Token![*]) {
+ input.parse().map(BinOp::Mul)
+ } else if input.peek(Token![/]) {
+ input.parse().map(BinOp::Div)
+ } else if input.peek(Token![%]) {
+ input.parse().map(BinOp::Rem)
+ } else if input.peek(Token![^]) {
+ input.parse().map(BinOp::BitXor)
+ } else if input.peek(Token![&]) {
+ input.parse().map(BinOp::BitAnd)
+ } else if input.peek(Token![|]) {
+ input.parse().map(BinOp::BitOr)
+ } else if input.peek(Token![<]) {
+ input.parse().map(BinOp::Lt)
+ } else if input.peek(Token![>]) {
+ input.parse().map(BinOp::Gt)
+ } else {
+ Err(input.error("expected binary operator"))
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for UnOp {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let lookahead = input.lookahead1();
+ if lookahead.peek(Token![*]) {
+ input.parse().map(UnOp::Deref)
+ } else if lookahead.peek(Token![!]) {
+ input.parse().map(UnOp::Not)
+ } else if lookahead.peek(Token![-]) {
+ input.parse().map(UnOp::Neg)
+ } else {
+ Err(lookahead.error())
+ }
+ }
+ }
+}
+
+#[cfg(feature = "printing")]
+mod printing {
+ use crate::op::{BinOp, UnOp};
+ use proc_macro2::TokenStream;
+ use quote::ToTokens;
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for BinOp {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ match self {
+ BinOp::Add(t) => t.to_tokens(tokens),
+ BinOp::Sub(t) => t.to_tokens(tokens),
+ BinOp::Mul(t) => t.to_tokens(tokens),
+ BinOp::Div(t) => t.to_tokens(tokens),
+ BinOp::Rem(t) => t.to_tokens(tokens),
+ BinOp::And(t) => t.to_tokens(tokens),
+ BinOp::Or(t) => t.to_tokens(tokens),
+ BinOp::BitXor(t) => t.to_tokens(tokens),
+ BinOp::BitAnd(t) => t.to_tokens(tokens),
+ BinOp::BitOr(t) => t.to_tokens(tokens),
+ BinOp::Shl(t) => t.to_tokens(tokens),
+ BinOp::Shr(t) => t.to_tokens(tokens),
+ BinOp::Eq(t) => t.to_tokens(tokens),
+ BinOp::Lt(t) => t.to_tokens(tokens),
+ BinOp::Le(t) => t.to_tokens(tokens),
+ BinOp::Ne(t) => t.to_tokens(tokens),
+ BinOp::Ge(t) => t.to_tokens(tokens),
+ BinOp::Gt(t) => t.to_tokens(tokens),
+ BinOp::AddAssign(t) => t.to_tokens(tokens),
+ BinOp::SubAssign(t) => t.to_tokens(tokens),
+ BinOp::MulAssign(t) => t.to_tokens(tokens),
+ BinOp::DivAssign(t) => t.to_tokens(tokens),
+ BinOp::RemAssign(t) => t.to_tokens(tokens),
+ BinOp::BitXorAssign(t) => t.to_tokens(tokens),
+ BinOp::BitAndAssign(t) => t.to_tokens(tokens),
+ BinOp::BitOrAssign(t) => t.to_tokens(tokens),
+ BinOp::ShlAssign(t) => t.to_tokens(tokens),
+ BinOp::ShrAssign(t) => t.to_tokens(tokens),
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for UnOp {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ match self {
+ UnOp::Deref(t) => t.to_tokens(tokens),
+ UnOp::Not(t) => t.to_tokens(tokens),
+ UnOp::Neg(t) => t.to_tokens(tokens),
+ }
+ }
+ }
+}
diff --git a/rust/syn/parse.rs b/rust/syn/parse.rs
new file mode 100644
index 000000000000..57531005ac4e
--- /dev/null
+++ b/rust/syn/parse.rs
@@ -0,0 +1,1419 @@
+//! 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`]
+//! and produce a [`Result<T>`] where `T` is some syntax tree node. Underlying
+//! these parser functions is a lower level mechanism built around the
+//! [`Cursor`] type. `Cursor` is a cheaply copyable cursor over a range of
+//! tokens in a token stream.
+//!
+//! [`Result<T>`]: Result
+//! [`Cursor`]: crate::buffer::Cursor
+//!
+//! # Example
+//!
+//! Here is a snippet of parsing code to get a feel for the style of the
+//! library. We define data structures for a subset of Rust syntax including
+//! enums (not shown) and structs, then provide implementations of the [`Parse`]
+//! trait to parse these syntax tree data structures from a token stream.
+//!
+//! Once `Parse` impls have been defined, they can be called conveniently from a
+//! procedural macro through [`parse_macro_input!`] as shown at the bottom of
+//! the snippet. If the caller provides syntactically invalid input to the
+//! procedural macro, they will receive a helpful compiler error message
+//! pointing out the exact token that triggered the failure to parse.
+//!
+//! [`parse_macro_input!`]: crate::parse_macro_input!
+//!
+//! ```
+//! # extern crate proc_macro;
+//! #
+//! use proc_macro::TokenStream;
+//! use syn::{braced, parse_macro_input, token, Field, Ident, Result, Token};
+//! use syn::parse::{Parse, ParseStream};
+//! use syn::punctuated::Punctuated;
+//!
+//! enum Item {
+//! Struct(ItemStruct),
+//! Enum(ItemEnum),
+//! }
+//!
+//! struct ItemStruct {
+//! struct_token: Token![struct],
+//! ident: Ident,
+//! brace_token: token::Brace,
+//! fields: Punctuated<Field, Token![,]>,
+//! }
+//! #
+//! # enum ItemEnum {}
+//!
+//! impl Parse for Item {
+//! fn parse(input: ParseStream) -> Result<Self> {
+//! let lookahead = input.lookahead1();
+//! if lookahead.peek(Token![struct]) {
+//! input.parse().map(Item::Struct)
+//! } else if lookahead.peek(Token![enum]) {
+//! input.parse().map(Item::Enum)
+//! } else {
+//! Err(lookahead.error())
+//! }
+//! }
+//! }
+//!
+//! impl Parse for ItemStruct {
+//! fn parse(input: ParseStream) -> Result<Self> {
+//! let content;
+//! Ok(ItemStruct {
+//! struct_token: input.parse()?,
+//! ident: input.parse()?,
+//! brace_token: braced!(content in input),
+//! fields: content.parse_terminated(Field::parse_named, Token![,])?,
+//! })
+//! }
+//! }
+//! #
+//! # impl Parse for ItemEnum {
+//! # fn parse(input: ParseStream) -> Result<Self> {
+//! # unimplemented!()
+//! # }
+//! # }
+//!
+//! # const IGNORE: &str = stringify! {
+//! #[proc_macro]
+//! # };
+//! pub fn my_macro(tokens: TokenStream) -> TokenStream {
+//! let input = parse_macro_input!(tokens as Item);
+//!
+//! /* ... */
+//! # TokenStream::new()
+//! }
+//! ```
+//!
+//! # The `syn::parse*` functions
+//!
+//! The [`syn::parse`], [`syn::parse2`], and [`syn::parse_str`] functions serve
+//! as an entry point for parsing syntax tree nodes that can be parsed in an
+//! obvious default way. These functions can return any syntax tree node that
+//! implements the [`Parse`] trait, which includes most types in Syn.
+//!
+//! [`syn::parse`]: crate::parse()
+//! [`syn::parse2`]: crate::parse2()
+//! [`syn::parse_str`]: crate::parse_str()
+//!
+//! ```
+//! use syn::Type;
+//!
+//! # fn run_parser() -> syn::Result<()> {
+//! let t: Type = syn::parse_str("std::collections::HashMap<String, Value>")?;
+//! # Ok(())
+//! # }
+//! #
+//! # run_parser().unwrap();
+//! ```
+//!
+//! The [`parse_quote!`] macro also uses this approach.
+//!
+//! [`parse_quote!`]: crate::parse_quote!
+//!
+//! # The `Parser` trait
+//!
+//! Some types can be parsed in several ways depending on context. For example
+//! an [`Attribute`] can be either "outer" like `#[...]` or "inner" like
+//! `#![...]` and parsing the wrong one would be a bug. Similarly [`Punctuated`]
+//! may or may not allow trailing punctuation, and parsing it the wrong way
+//! would either reject valid input or accept invalid input.
+//!
+//! [`Attribute`]: crate::Attribute
+//! [`Punctuated`]: crate::punctuated
+//!
+//! The `Parse` trait is not implemented in these cases because there is no good
+//! behavior to consider the default.
+//!
+//! ```compile_fail
+//! # extern crate proc_macro;
+//! #
+//! # use syn::punctuated::Punctuated;
+//! # use syn::{PathSegment, Result, Token};
+//! #
+//! # fn f(tokens: proc_macro::TokenStream) -> Result<()> {
+//! #
+//! // Can't parse `Punctuated` without knowing whether trailing punctuation
+//! // should be allowed in this context.
+//! let path: Punctuated<PathSegment, Token![::]> = syn::parse(tokens)?;
+//! #
+//! # Ok(())
+//! # }
+//! ```
+//!
+//! In these cases the types provide a choice of parser functions rather than a
+//! single `Parse` implementation, and those parser functions can be invoked
+//! through the [`Parser`] trait.
+//!
+//!
+//! ```
+//! # extern crate proc_macro;
+//! #
+//! use proc_macro::TokenStream;
+//! use syn::parse::Parser;
+//! use syn::punctuated::Punctuated;
+//! use syn::{Attribute, Expr, PathSegment, Result, Token};
+//!
+//! fn call_some_parser_methods(input: TokenStream) -> Result<()> {
+//! // Parse a nonempty sequence of path segments separated by `::` punctuation
+//! // with no trailing punctuation.
+//! let tokens = input.clone();
+//! let parser = Punctuated::<PathSegment, Token![::]>::parse_separated_nonempty;
+//! let _path = parser.parse(tokens)?;
+//!
+//! // Parse a possibly empty sequence of expressions terminated by commas with
+//! // an optional trailing punctuation.
+//! let tokens = input.clone();
+//! let parser = Punctuated::<Expr, Token![,]>::parse_terminated;
+//! let _args = parser.parse(tokens)?;
+//!
+//! // Parse zero or more outer attributes but not inner attributes.
+//! let tokens = input.clone();
+//! let parser = Attribute::parse_outer;
+//! let _attrs = parser.parse(tokens)?;
+//!
+//! Ok(())
+//! }
+//! ```
+
+#[path = "discouraged.rs"]
+pub mod discouraged;
+
+use crate::buffer::{Cursor, TokenBuffer};
+use crate::error;
+use crate::lookahead;
+use crate::punctuated::Punctuated;
+use crate::token::Token;
+use proc_macro2::{Delimiter, Group, Literal, Punct, Span, TokenStream, TokenTree};
+#[cfg(feature = "printing")]
+use quote::ToTokens;
+use std::cell::Cell;
+use std::fmt::{self, Debug, Display};
+#[cfg(feature = "extra-traits")]
+use std::hash::{Hash, Hasher};
+use std::marker::PhantomData;
+use std::mem;
+use std::ops::Deref;
+use std::panic::{RefUnwindSafe, UnwindSafe};
+use std::rc::Rc;
+use std::str::FromStr;
+
+pub use crate::error::{Error, Result};
+pub use crate::lookahead::{End, Lookahead1, Peek};
+
+/// Parsing interface implemented by all types that can be parsed in a default
+/// way from a token stream.
+///
+/// Refer to the [module documentation] for details about implementing and using
+/// the `Parse` trait.
+///
+/// [module documentation]: self
+pub trait Parse: Sized {
+ fn parse(input: ParseStream) -> Result<Self>;
+}
+
+/// Input to a Syn parser function.
+///
+/// See the methods of this type under the documentation of [`ParseBuffer`]. For
+/// an overview of parsing in Syn, refer to the [module documentation].
+///
+/// [module documentation]: self
+pub type ParseStream<'a> = &'a ParseBuffer<'a>;
+
+/// Cursor position within a buffered token stream.
+///
+/// This type is more commonly used through the type alias [`ParseStream`] which
+/// is an alias for `&ParseBuffer`.
+///
+/// `ParseStream` is the input type for all parser functions in Syn. They have
+/// the signature `fn(ParseStream) -> Result<T>`.
+///
+/// ## Calling a parser function
+///
+/// There is no public way to construct a `ParseBuffer`. Instead, if you are
+/// looking to invoke a parser function that requires `ParseStream` as input,
+/// you will need to go through one of the public parsing entry points.
+///
+/// - The [`parse_macro_input!`] macro if parsing input of a procedural macro;
+/// - One of [the `syn::parse*` functions][syn-parse]; or
+/// - A method of the [`Parser`] trait.
+///
+/// [`parse_macro_input!`]: crate::parse_macro_input!
+/// [syn-parse]: self#the-synparse-functions
+pub struct ParseBuffer<'a> {
+ scope: Span,
+ // Instead of Cell<Cursor<'a>> so that ParseBuffer<'a> is covariant in 'a.
+ // The rest of the code in this module needs to be careful that only a
+ // cursor derived from this `cell` is ever assigned to this `cell`.
+ //
+ // Cell<Cursor<'a>> cannot be covariant in 'a because then we could take a
+ // ParseBuffer<'a>, upcast to ParseBuffer<'short> for some lifetime shorter
+ // than 'a, and then assign a Cursor<'short> into the Cell.
+ //
+ // By extension, it would not be safe to expose an API that accepts a
+ // Cursor<'a> and trusts that it lives as long as the cursor currently in
+ // the cell.
+ cell: Cell<Cursor<'static>>,
+ marker: PhantomData<Cursor<'a>>,
+ unexpected: Cell<Option<Rc<Cell<Unexpected>>>>,
+}
+
+impl<'a> Drop for ParseBuffer<'a> {
+ fn drop(&mut self) {
+ if let Some((unexpected_span, delimiter)) = span_of_unexpected_ignoring_nones(self.cursor())
+ {
+ let (inner, old_span) = inner_unexpected(self);
+ if old_span.is_none() {
+ inner.set(Unexpected::Some(unexpected_span, delimiter));
+ }
+ }
+ }
+}
+
+impl<'a> Display for ParseBuffer<'a> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ Display::fmt(&self.cursor().token_stream(), f)
+ }
+}
+
+impl<'a> Debug for ParseBuffer<'a> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ Debug::fmt(&self.cursor().token_stream(), f)
+ }
+}
+
+impl<'a> UnwindSafe for ParseBuffer<'a> {}
+impl<'a> RefUnwindSafe for ParseBuffer<'a> {}
+
+/// Cursor state associated with speculative parsing.
+///
+/// This type is the input of the closure provided to [`ParseStream::step`].
+///
+/// [`ParseStream::step`]: ParseBuffer::step
+///
+/// # Example
+///
+/// ```
+/// use proc_macro2::TokenTree;
+/// use syn::Result;
+/// use syn::parse::ParseStream;
+///
+/// // This function advances the stream past the next occurrence of `@`. If
+/// // no `@` is present in the stream, the stream position is unchanged and
+/// // an error is returned.
+/// fn skip_past_next_at(input: ParseStream) -> Result<()> {
+/// input.step(|cursor| {
+/// let mut rest = *cursor;
+/// while let Some((tt, next)) = rest.token_tree() {
+/// match &tt {
+/// TokenTree::Punct(punct) if punct.as_char() == '@' => {
+/// return Ok(((), next));
+/// }
+/// _ => rest = next,
+/// }
+/// }
+/// Err(cursor.error("no `@` was found after this point"))
+/// })
+/// }
+/// #
+/// # fn remainder_after_skipping_past_next_at(
+/// # input: ParseStream,
+/// # ) -> Result<proc_macro2::TokenStream> {
+/// # skip_past_next_at(input)?;
+/// # input.parse()
+/// # }
+/// #
+/// # use syn::parse::Parser;
+/// # let remainder = remainder_after_skipping_past_next_at
+/// # .parse_str("a @ b c")
+/// # .unwrap();
+/// # assert_eq!(remainder.to_string(), "b c");
+/// ```
+pub struct StepCursor<'c, 'a> {
+ scope: Span,
+ // This field is covariant in 'c.
+ cursor: Cursor<'c>,
+ // This field is contravariant in 'c. Together these make StepCursor
+ // invariant in 'c. Also covariant in 'a. The user cannot cast 'c to a
+ // different lifetime but can upcast into a StepCursor with a shorter
+ // lifetime 'a.
+ //
+ // As long as we only ever construct a StepCursor for which 'c outlives 'a,
+ // this means if ever a StepCursor<'c, 'a> exists we are guaranteed that 'c
+ // outlives 'a.
+ marker: PhantomData<fn(Cursor<'c>) -> Cursor<'a>>,
+}
+
+impl<'c, 'a> Deref for StepCursor<'c, 'a> {
+ type Target = Cursor<'c>;
+
+ fn deref(&self) -> &Self::Target {
+ &self.cursor
+ }
+}
+
+impl<'c, 'a> Copy for StepCursor<'c, 'a> {}
+
+impl<'c, 'a> Clone for StepCursor<'c, 'a> {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+
+impl<'c, 'a> StepCursor<'c, 'a> {
+ /// Triggers an error at the current position of the parse stream.
+ ///
+ /// The `ParseStream::step` invocation will return this same error without
+ /// advancing the stream state.
+ pub fn error<T: Display>(self, message: T) -> Error {
+ error::new_at(self.scope, self.cursor, message)
+ }
+}
+
+pub(crate) fn advance_step_cursor<'c, 'a>(proof: StepCursor<'c, 'a>, to: Cursor<'c>) -> Cursor<'a> {
+ // Refer to the comments within the StepCursor definition. We use the
+ // fact that a StepCursor<'c, 'a> exists as proof that 'c outlives 'a.
+ // Cursor is covariant in its lifetime parameter so we can cast a
+ // Cursor<'c> to one with the shorter lifetime Cursor<'a>.
+ let _ = proof;
+ unsafe { mem::transmute::<Cursor<'c>, Cursor<'a>>(to) }
+}
+
+pub(crate) fn new_parse_buffer(
+ scope: Span,
+ cursor: Cursor,
+ unexpected: Rc<Cell<Unexpected>>,
+) -> ParseBuffer {
+ ParseBuffer {
+ scope,
+ // See comment on `cell` in the struct definition.
+ cell: Cell::new(unsafe { mem::transmute::<Cursor, Cursor<'static>>(cursor) }),
+ marker: PhantomData,
+ unexpected: Cell::new(Some(unexpected)),
+ }
+}
+
+pub(crate) enum Unexpected {
+ None,
+ Some(Span, Delimiter),
+ Chain(Rc<Cell<Unexpected>>),
+}
+
+impl Default for Unexpected {
+ fn default() -> Self {
+ Unexpected::None
+ }
+}
+
+impl Clone for Unexpected {
+ fn clone(&self) -> Self {
+ match self {
+ Unexpected::None => Unexpected::None,
+ Unexpected::Some(span, delimiter) => Unexpected::Some(*span, *delimiter),
+ Unexpected::Chain(next) => Unexpected::Chain(next.clone()),
+ }
+ }
+}
+
+// We call this on Cell<Unexpected> and Cell<Option<T>> where temporarily
+// swapping in a None is cheap.
+fn cell_clone<T: Default + Clone>(cell: &Cell<T>) -> T {
+ let prev = cell.take();
+ let ret = prev.clone();
+ cell.set(prev);
+ ret
+}
+
+fn inner_unexpected(buffer: &ParseBuffer) -> (Rc<Cell<Unexpected>>, Option<(Span, Delimiter)>) {
+ let mut unexpected = get_unexpected(buffer);
+ loop {
+ match cell_clone(&unexpected) {
+ Unexpected::None => return (unexpected, None),
+ Unexpected::Some(span, delimiter) => return (unexpected, Some((span, delimiter))),
+ Unexpected::Chain(next) => unexpected = next,
+ }
+ }
+}
+
+pub(crate) fn get_unexpected(buffer: &ParseBuffer) -> Rc<Cell<Unexpected>> {
+ cell_clone(&buffer.unexpected).unwrap()
+}
+
+fn span_of_unexpected_ignoring_nones(mut cursor: Cursor) -> Option<(Span, Delimiter)> {
+ if cursor.eof() {
+ return None;
+ }
+ while let Some((inner, _span, rest)) = cursor.group(Delimiter::None) {
+ if let Some(unexpected) = span_of_unexpected_ignoring_nones(inner) {
+ return Some(unexpected);
+ }
+ cursor = rest;
+ }
+ if cursor.eof() {
+ None
+ } else {
+ Some((cursor.span(), cursor.scope_delimiter()))
+ }
+}
+
+impl<'a> ParseBuffer<'a> {
+ /// Parses a syntax tree node of type `T`, advancing the position of our
+ /// parse stream past it.
+ pub fn parse<T: Parse>(&self) -> Result<T> {
+ T::parse(self)
+ }
+
+ /// Calls the given parser function to parse a syntax tree node of type `T`
+ /// from this stream.
+ ///
+ /// # Example
+ ///
+ /// The parser below invokes [`Attribute::parse_outer`] to parse a vector of
+ /// zero or more outer attributes.
+ ///
+ /// [`Attribute::parse_outer`]: crate::Attribute::parse_outer
+ ///
+ /// ```
+ /// 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()?,
+ /// })
+ /// }
+ /// }
+ /// ```
+ pub fn call<T>(&'a self, function: fn(ParseStream<'a>) -> Result<T>) -> Result<T> {
+ function(self)
+ }
+
+ /// Looks at the next token in the parse stream to determine whether it
+ /// matches the requested type of token.
+ ///
+ /// Does not advance the position of the parse stream.
+ ///
+ /// # Syntax
+ ///
+ /// Note that this method does not use turbofish syntax. Pass the peek type
+ /// inside of parentheses.
+ ///
+ /// - `input.peek(Token![struct])`
+ /// - `input.peek(Token![==])`
+ /// - `input.peek(syn::Ident)` *(does not accept keywords)*
+ /// - `input.peek(syn::Ident::peek_any)`
+ /// - `input.peek(Lifetime)`
+ /// - `input.peek(token::Brace)`
+ ///
+ /// # Example
+ ///
+ /// In this example we finish parsing the list of supertraits when the next
+ /// token in the input is either `where` or an opening curly brace.
+ ///
+ /// ```
+ /// use syn::{braced, token, Generics, Ident, Result, Token, TypeParamBound};
+ /// use syn::parse::{Parse, ParseStream};
+ /// use syn::punctuated::Punctuated;
+ ///
+ /// // Parses a trait definition containing no associated items.
+ /// //
+ /// // trait Marker<'de, T>: A + B<'de> where Box<T>: Clone {}
+ /// struct MarkerTrait {
+ /// trait_token: Token![trait],
+ /// ident: Ident,
+ /// generics: Generics,
+ /// colon_token: Option<Token![:]>,
+ /// supertraits: Punctuated<TypeParamBound, Token![+]>,
+ /// brace_token: token::Brace,
+ /// }
+ ///
+ /// impl Parse for MarkerTrait {
+ /// fn parse(input: ParseStream) -> Result<Self> {
+ /// let trait_token: Token![trait] = input.parse()?;
+ /// let ident: Ident = input.parse()?;
+ /// let mut generics: Generics = input.parse()?;
+ /// let colon_token: Option<Token![:]> = input.parse()?;
+ ///
+ /// let mut supertraits = Punctuated::new();
+ /// if colon_token.is_some() {
+ /// loop {
+ /// supertraits.push_value(input.parse()?);
+ /// if input.peek(Token![where]) || input.peek(token::Brace) {
+ /// break;
+ /// }
+ /// supertraits.push_punct(input.parse()?);
+ /// }
+ /// }
+ ///
+ /// generics.where_clause = input.parse()?;
+ /// let content;
+ /// let empty_brace_token = braced!(content in input);
+ ///
+ /// Ok(MarkerTrait {
+ /// trait_token,
+ /// ident,
+ /// generics,
+ /// colon_token,
+ /// supertraits,
+ /// brace_token: empty_brace_token,
+ /// })
+ /// }
+ /// }
+ /// ```
+ pub fn peek<T: Peek>(&self, token: T) -> bool {
+ let _ = token;
+ T::Token::peek(self.cursor())
+ }
+
+ /// Looks at the second-next token in the parse stream.
+ ///
+ /// This is commonly useful as a way to implement contextual keywords.
+ ///
+ /// # Example
+ ///
+ /// This example needs to use `peek2` because the symbol `union` is not a
+ /// keyword in Rust. We can't use just `peek` and decide to parse a union if
+ /// the very next token is `union`, because someone is free to write a `mod
+ /// union` and a macro invocation that looks like `union::some_macro! { ...
+ /// }`. In other words `union` is a contextual keyword.
+ ///
+ /// ```
+ /// use syn::{Ident, ItemUnion, Macro, Result, Token};
+ /// use syn::parse::{Parse, ParseStream};
+ ///
+ /// // Parses either a union or a macro invocation.
+ /// enum UnionOrMacro {
+ /// // union MaybeUninit<T> { uninit: (), value: T }
+ /// Union(ItemUnion),
+ /// // lazy_static! { ... }
+ /// Macro(Macro),
+ /// }
+ ///
+ /// impl Parse for UnionOrMacro {
+ /// fn parse(input: ParseStream) -> Result<Self> {
+ /// if input.peek(Token![union]) && input.peek2(Ident) {
+ /// input.parse().map(UnionOrMacro::Union)
+ /// } else {
+ /// input.parse().map(UnionOrMacro::Macro)
+ /// }
+ /// }
+ /// }
+ /// ```
+ pub fn peek2<T: Peek>(&self, token: T) -> bool {
+ fn peek2(buffer: &ParseBuffer, peek: fn(Cursor) -> bool) -> bool {
+ buffer.cursor().skip().map_or(false, peek)
+ }
+
+ let _ = token;
+ peek2(self, T::Token::peek)
+ }
+
+ /// Looks at the third-next token in the parse stream.
+ pub fn peek3<T: Peek>(&self, token: T) -> bool {
+ fn peek3(buffer: &ParseBuffer, peek: fn(Cursor) -> bool) -> bool {
+ buffer
+ .cursor()
+ .skip()
+ .and_then(Cursor::skip)
+ .map_or(false, peek)
+ }
+
+ let _ = token;
+ peek3(self, T::Token::peek)
+ }
+
+ /// Parses zero or more occurrences of `T` separated by punctuation of type
+ /// `P`, with optional trailing punctuation.
+ ///
+ /// Parsing continues until the end of this parse stream. The entire content
+ /// of this parse stream must consist of `T` and `P`.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// # use quote::quote;
+ /// #
+ /// use syn::{parenthesized, token, Ident, Result, Token, Type};
+ /// use syn::parse::{Parse, ParseStream};
+ /// use syn::punctuated::Punctuated;
+ ///
+ /// // Parse a simplified tuple struct syntax like:
+ /// //
+ /// // struct S(A, B);
+ /// struct TupleStruct {
+ /// struct_token: Token![struct],
+ /// ident: Ident,
+ /// paren_token: token::Paren,
+ /// fields: Punctuated<Type, Token![,]>,
+ /// semi_token: Token![;],
+ /// }
+ ///
+ /// impl Parse for TupleStruct {
+ /// fn parse(input: ParseStream) -> Result<Self> {
+ /// let content;
+ /// Ok(TupleStruct {
+ /// struct_token: input.parse()?,
+ /// ident: input.parse()?,
+ /// paren_token: parenthesized!(content in input),
+ /// fields: content.parse_terminated(Type::parse, Token![,])?,
+ /// semi_token: input.parse()?,
+ /// })
+ /// }
+ /// }
+ /// #
+ /// # let input = quote! {
+ /// # struct S(A, B);
+ /// # };
+ /// # syn::parse2::<TupleStruct>(input).unwrap();
+ /// ```
+ ///
+ /// # See also
+ ///
+ /// If your separator is anything more complicated than an invocation of the
+ /// `Token!` macro, this method won't be applicable and you can instead
+ /// directly use `Punctuated`'s parser functions: [`parse_terminated`],
+ /// [`parse_separated_nonempty`] etc.
+ ///
+ /// [`parse_terminated`]: Punctuated::parse_terminated
+ /// [`parse_separated_nonempty`]: Punctuated::parse_separated_nonempty
+ ///
+ /// ```
+ /// use syn::{custom_keyword, Expr, Result, Token};
+ /// use syn::parse::{Parse, ParseStream};
+ /// use syn::punctuated::Punctuated;
+ ///
+ /// mod kw {
+ /// syn::custom_keyword!(fin);
+ /// }
+ ///
+ /// struct Fin(kw::fin, Token![;]);
+ ///
+ /// impl Parse for Fin {
+ /// fn parse(input: ParseStream) -> Result<Self> {
+ /// Ok(Self(input.parse()?, input.parse()?))
+ /// }
+ /// }
+ ///
+ /// struct Thing {
+ /// steps: Punctuated<Expr, Fin>,
+ /// }
+ ///
+ /// impl Parse for Thing {
+ /// fn parse(input: ParseStream) -> Result<Self> {
+ /// # if true {
+ /// Ok(Thing {
+ /// steps: Punctuated::parse_terminated(input)?,
+ /// })
+ /// # } else {
+ /// // or equivalently, this means the same thing:
+ /// # Ok(Thing {
+ /// steps: input.call(Punctuated::parse_terminated)?,
+ /// # })
+ /// # }
+ /// }
+ /// }
+ /// ```
+ pub fn parse_terminated<T, P>(
+ &'a self,
+ parser: fn(ParseStream<'a>) -> Result<T>,
+ separator: P,
+ ) -> Result<Punctuated<T, P::Token>>
+ where
+ P: Peek,
+ P::Token: Parse,
+ {
+ let _ = separator;
+ Punctuated::parse_terminated_with(self, parser)
+ }
+
+ /// Returns whether there are no more tokens remaining to be parsed from
+ /// this stream.
+ ///
+ /// This method returns true upon reaching the end of the content within a
+ /// set of delimiters, as well as at the end of the tokens provided to the
+ /// outermost parsing entry point.
+ ///
+ /// This is equivalent to
+ /// <code>.<a href="#method.peek">peek</a>(<a href="struct.End.html">syn::parse::End</a>)</code>.
+ /// Use `.peek2(End)` or `.peek3(End)` to look for the end of a parse stream
+ /// further ahead than the current position.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use syn::{braced, token, Ident, Item, Result, Token};
+ /// use syn::parse::{Parse, ParseStream};
+ ///
+ /// // Parses a Rust `mod m { ... }` containing zero or more items.
+ /// struct Mod {
+ /// mod_token: Token![mod],
+ /// name: Ident,
+ /// brace_token: token::Brace,
+ /// items: Vec<Item>,
+ /// }
+ ///
+ /// impl Parse for Mod {
+ /// fn parse(input: ParseStream) -> Result<Self> {
+ /// let content;
+ /// Ok(Mod {
+ /// mod_token: input.parse()?,
+ /// name: input.parse()?,
+ /// brace_token: braced!(content in input),
+ /// items: {
+ /// let mut items = Vec::new();
+ /// while !content.is_empty() {
+ /// items.push(content.parse()?);
+ /// }
+ /// items
+ /// },
+ /// })
+ /// }
+ /// }
+ /// ```
+ pub fn is_empty(&self) -> bool {
+ self.cursor().eof()
+ }
+
+ /// Constructs a helper for peeking at the next token in this stream and
+ /// building an error message if it is not one of a set of expected tokens.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use syn::{ConstParam, Ident, Lifetime, LifetimeParam, Result, Token, TypeParam};
+ /// use syn::parse::{Parse, ParseStream};
+ ///
+ /// // A generic parameter, a single one of the comma-separated elements inside
+ /// // angle brackets in:
+ /// //
+ /// // fn f<T: Clone, 'a, 'b: 'a, const N: usize>() { ... }
+ /// //
+ /// // On invalid input, lookahead gives us a reasonable error message.
+ /// //
+ /// // error: expected one of: identifier, lifetime, `const`
+ /// // |
+ /// // 5 | fn f<!Sized>() {}
+ /// // | ^
+ /// enum GenericParam {
+ /// Type(TypeParam),
+ /// Lifetime(LifetimeParam),
+ /// Const(ConstParam),
+ /// }
+ ///
+ /// impl Parse for GenericParam {
+ /// fn parse(input: ParseStream) -> Result<Self> {
+ /// let lookahead = input.lookahead1();
+ /// if lookahead.peek(Ident) {
+ /// input.parse().map(GenericParam::Type)
+ /// } else if lookahead.peek(Lifetime) {
+ /// input.parse().map(GenericParam::Lifetime)
+ /// } else if lookahead.peek(Token![const]) {
+ /// input.parse().map(GenericParam::Const)
+ /// } else {
+ /// Err(lookahead.error())
+ /// }
+ /// }
+ /// }
+ /// ```
+ pub fn lookahead1(&self) -> Lookahead1<'a> {
+ lookahead::new(self.scope, self.cursor())
+ }
+
+ /// Forks a parse stream so that parsing tokens out of either the original
+ /// or the fork does not advance the position of the other.
+ ///
+ /// # Performance
+ ///
+ /// Forking a parse stream is a cheap fixed amount of work and does not
+ /// involve copying token buffers. Where you might hit performance problems
+ /// is if your macro ends up parsing a large amount of content more than
+ /// once.
+ ///
+ /// ```
+ /// # use syn::{Expr, Result};
+ /// # use syn::parse::ParseStream;
+ /// #
+ /// # fn bad(input: ParseStream) -> Result<Expr> {
+ /// // Do not do this.
+ /// if input.fork().parse::<Expr>().is_ok() {
+ /// return input.parse::<Expr>();
+ /// }
+ /// # unimplemented!()
+ /// # }
+ /// ```
+ ///
+ /// As a rule, avoid parsing an unbounded amount of tokens out of a forked
+ /// parse stream. Only use a fork when the amount of work performed against
+ /// the fork is small and bounded.
+ ///
+ /// When complex speculative parsing against the forked stream is
+ /// unavoidable, use [`parse::discouraged::Speculative`] to advance the
+ /// original stream once the fork's parse is determined to have been
+ /// successful.
+ ///
+ /// For a lower level way to perform speculative parsing at the token level,
+ /// consider using [`ParseStream::step`] instead.
+ ///
+ /// [`parse::discouraged::Speculative`]: discouraged::Speculative
+ /// [`ParseStream::step`]: ParseBuffer::step
+ ///
+ /// # Example
+ ///
+ /// The parse implementation shown here parses possibly restricted `pub`
+ /// visibilities.
+ ///
+ /// - `pub`
+ /// - `pub(crate)`
+ /// - `pub(self)`
+ /// - `pub(super)`
+ /// - `pub(in some::path)`
+ ///
+ /// To handle the case of visibilities inside of tuple structs, the parser
+ /// needs to distinguish parentheses that specify visibility restrictions
+ /// from parentheses that form part of a tuple type.
+ ///
+ /// ```
+ /// # struct A;
+ /// # struct B;
+ /// # struct C;
+ /// #
+ /// struct S(pub(crate) A, pub (B, C));
+ /// ```
+ ///
+ /// In this example input the first tuple struct element of `S` has
+ /// `pub(crate)` visibility while the second tuple struct element has `pub`
+ /// visibility; the parentheses around `(B, C)` are part of the type rather
+ /// than part of a visibility restriction.
+ ///
+ /// The parser uses a forked parse stream to check the first token inside of
+ /// parentheses after the `pub` keyword. This is a small bounded amount of
+ /// work performed against the forked parse stream.
+ ///
+ /// ```
+ /// use syn::{parenthesized, token, Ident, Path, Result, Token};
+ /// use syn::ext::IdentExt;
+ /// use syn::parse::{Parse, ParseStream};
+ ///
+ /// struct PubVisibility {
+ /// pub_token: Token![pub],
+ /// restricted: Option<Restricted>,
+ /// }
+ ///
+ /// struct Restricted {
+ /// paren_token: token::Paren,
+ /// in_token: Option<Token![in]>,
+ /// path: Path,
+ /// }
+ ///
+ /// impl Parse for PubVisibility {
+ /// fn parse(input: ParseStream) -> Result<Self> {
+ /// let pub_token: Token![pub] = input.parse()?;
+ ///
+ /// if input.peek(token::Paren) {
+ /// let ahead = input.fork();
+ /// let mut content;
+ /// parenthesized!(content in ahead);
+ ///
+ /// if content.peek(Token![crate])
+ /// || content.peek(Token![self])
+ /// || content.peek(Token![super])
+ /// {
+ /// return Ok(PubVisibility {
+ /// pub_token,
+ /// restricted: Some(Restricted {
+ /// paren_token: parenthesized!(content in input),
+ /// in_token: None,
+ /// path: Path::from(content.call(Ident::parse_any)?),
+ /// }),
+ /// });
+ /// } else if content.peek(Token![in]) {
+ /// return Ok(PubVisibility {
+ /// pub_token,
+ /// restricted: Some(Restricted {
+ /// paren_token: parenthesized!(content in input),
+ /// in_token: Some(content.parse()?),
+ /// path: content.call(Path::parse_mod_style)?,
+ /// }),
+ /// });
+ /// }
+ /// }
+ ///
+ /// Ok(PubVisibility {
+ /// pub_token,
+ /// restricted: None,
+ /// })
+ /// }
+ /// }
+ /// ```
+ pub fn fork(&self) -> Self {
+ ParseBuffer {
+ scope: self.scope,
+ cell: self.cell.clone(),
+ marker: PhantomData,
+ // Not the parent's unexpected. Nothing cares whether the clone
+ // parses all the way unless we `advance_to`.
+ unexpected: Cell::new(Some(Rc::new(Cell::new(Unexpected::None)))),
+ }
+ }
+
+ /// Triggers an error at the current position of the parse stream.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use syn::{Expr, Result, Token};
+ /// use syn::parse::{Parse, ParseStream};
+ ///
+ /// // Some kind of loop: `while` or `for` or `loop`.
+ /// struct Loop {
+ /// expr: Expr,
+ /// }
+ ///
+ /// impl Parse for Loop {
+ /// fn parse(input: ParseStream) -> Result<Self> {
+ /// if input.peek(Token![while])
+ /// || input.peek(Token![for])
+ /// || input.peek(Token![loop])
+ /// {
+ /// Ok(Loop {
+ /// expr: input.parse()?,
+ /// })
+ /// } else {
+ /// Err(input.error("expected some kind of loop"))
+ /// }
+ /// }
+ /// }
+ /// ```
+ pub fn error<T: Display>(&self, message: T) -> Error {
+ error::new_at(self.scope, self.cursor(), message)
+ }
+
+ /// Speculatively parses tokens from this parse stream, advancing the
+ /// position of this stream only if parsing succeeds.
+ ///
+ /// This is a powerful low-level API used for defining the `Parse` impls of
+ /// the basic built-in token types. It is not something that will be used
+ /// widely outside of the Syn codebase.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use proc_macro2::TokenTree;
+ /// use syn::Result;
+ /// use syn::parse::ParseStream;
+ ///
+ /// // This function advances the stream past the next occurrence of `@`. If
+ /// // no `@` is present in the stream, the stream position is unchanged and
+ /// // an error is returned.
+ /// fn skip_past_next_at(input: ParseStream) -> Result<()> {
+ /// input.step(|cursor| {
+ /// let mut rest = *cursor;
+ /// while let Some((tt, next)) = rest.token_tree() {
+ /// match &tt {
+ /// TokenTree::Punct(punct) if punct.as_char() == '@' => {
+ /// return Ok(((), next));
+ /// }
+ /// _ => rest = next,
+ /// }
+ /// }
+ /// Err(cursor.error("no `@` was found after this point"))
+ /// })
+ /// }
+ /// #
+ /// # fn remainder_after_skipping_past_next_at(
+ /// # input: ParseStream,
+ /// # ) -> Result<proc_macro2::TokenStream> {
+ /// # skip_past_next_at(input)?;
+ /// # input.parse()
+ /// # }
+ /// #
+ /// # use syn::parse::Parser;
+ /// # let remainder = remainder_after_skipping_past_next_at
+ /// # .parse_str("a @ b c")
+ /// # .unwrap();
+ /// # assert_eq!(remainder.to_string(), "b c");
+ /// ```
+ pub fn step<F, R>(&self, function: F) -> Result<R>
+ where
+ F: for<'c> FnOnce(StepCursor<'c, 'a>) -> Result<(R, Cursor<'c>)>,
+ {
+ // Since the user's function is required to work for any 'c, we know
+ // that the Cursor<'c> they return is either derived from the input
+ // StepCursor<'c, 'a> or from a Cursor<'static>.
+ //
+ // It would not be legal to write this function without the invariant
+ // lifetime 'c in StepCursor<'c, 'a>. If this function were written only
+ // in terms of 'a, the user could take our ParseBuffer<'a>, upcast it to
+ // a ParseBuffer<'short> which some shorter lifetime than 'a, invoke
+ // `step` on their ParseBuffer<'short> with a closure that returns
+ // Cursor<'short>, and we would wrongly write that Cursor<'short> into
+ // the Cell intended to hold Cursor<'a>.
+ //
+ // In some cases it may be necessary for R to contain a Cursor<'a>.
+ // Within Syn we solve this using `advance_step_cursor` which uses the
+ // existence of a StepCursor<'c, 'a> as proof that it is safe to cast
+ // from Cursor<'c> to Cursor<'a>. If needed outside of Syn, it would be
+ // safe to expose that API as a method on StepCursor.
+ let (node, rest) = function(StepCursor {
+ scope: self.scope,
+ cursor: self.cell.get(),
+ marker: PhantomData,
+ })?;
+ self.cell.set(rest);
+ Ok(node)
+ }
+
+ /// Returns the `Span` of the next token in the parse stream, or
+ /// `Span::call_site()` if this parse stream has completely exhausted its
+ /// input `TokenStream`.
+ pub fn span(&self) -> Span {
+ let cursor = self.cursor();
+ if cursor.eof() {
+ self.scope
+ } else {
+ crate::buffer::open_span_of_group(cursor)
+ }
+ }
+
+ /// Provides low-level access to the token representation underlying this
+ /// parse stream.
+ ///
+ /// Cursors are immutable so no operations you perform against the cursor
+ /// will affect the state of this parse stream.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use proc_macro2::TokenStream;
+ /// use syn::buffer::Cursor;
+ /// use syn::parse::{ParseStream, Result};
+ ///
+ /// // Run a parser that returns T, but get its output as TokenStream instead of T.
+ /// // This works without T needing to implement ToTokens.
+ /// fn recognize_token_stream<T>(
+ /// recognizer: fn(ParseStream) -> Result<T>,
+ /// ) -> impl Fn(ParseStream) -> Result<TokenStream> {
+ /// move |input| {
+ /// let begin = input.cursor();
+ /// recognizer(input)?;
+ /// let end = input.cursor();
+ /// Ok(tokens_between(begin, end))
+ /// }
+ /// }
+ ///
+ /// // Collect tokens between two cursors as a TokenStream.
+ /// fn tokens_between(begin: Cursor, end: Cursor) -> TokenStream {
+ /// assert!(begin <= end);
+ ///
+ /// let mut cursor = begin;
+ /// let mut tokens = TokenStream::new();
+ /// while cursor < end {
+ /// let (token, next) = cursor.token_tree().unwrap();
+ /// tokens.extend(std::iter::once(token));
+ /// cursor = next;
+ /// }
+ /// tokens
+ /// }
+ ///
+ /// fn main() {
+ /// use quote::quote;
+ /// use syn::parse::{Parse, Parser};
+ /// use syn::Token;
+ ///
+ /// // Parse syn::Type as a TokenStream, surrounded by angle brackets.
+ /// fn example(input: ParseStream) -> Result<TokenStream> {
+ /// let _langle: Token![<] = input.parse()?;
+ /// let ty = recognize_token_stream(syn::Type::parse)(input)?;
+ /// let _rangle: Token![>] = input.parse()?;
+ /// Ok(ty)
+ /// }
+ ///
+ /// let tokens = quote! { <fn() -> u8> };
+ /// println!("{}", example.parse2(tokens).unwrap());
+ /// }
+ /// ```
+ pub fn cursor(&self) -> Cursor<'a> {
+ self.cell.get()
+ }
+
+ fn check_unexpected(&self) -> Result<()> {
+ match inner_unexpected(self).1 {
+ Some((span, delimiter)) => Err(err_unexpected_token(span, delimiter)),
+ None => Ok(()),
+ }
+ }
+}
+
+#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+impl<T: Parse> Parse for Box<T> {
+ fn parse(input: ParseStream) -> Result<Self> {
+ input.parse().map(Box::new)
+ }
+}
+
+#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+impl<T: Parse + Token> Parse for Option<T> {
+ fn parse(input: ParseStream) -> Result<Self> {
+ if T::peek(input.cursor()) {
+ Ok(Some(input.parse()?))
+ } else {
+ Ok(None)
+ }
+ }
+}
+
+#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+impl Parse for TokenStream {
+ fn parse(input: ParseStream) -> Result<Self> {
+ input.step(|cursor| Ok((cursor.token_stream(), Cursor::empty())))
+ }
+}
+
+#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+impl Parse for TokenTree {
+ fn parse(input: ParseStream) -> Result<Self> {
+ input.step(|cursor| match cursor.token_tree() {
+ Some((tt, rest)) => Ok((tt, rest)),
+ None => Err(cursor.error("expected token tree")),
+ })
+ }
+}
+
+#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+impl Parse for Group {
+ fn parse(input: ParseStream) -> Result<Self> {
+ input.step(|cursor| {
+ if let Some((group, rest)) = cursor.any_group_token() {
+ if group.delimiter() != Delimiter::None {
+ return Ok((group, rest));
+ }
+ }
+ Err(cursor.error("expected group token"))
+ })
+ }
+}
+
+#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+impl Parse for Punct {
+ fn parse(input: ParseStream) -> Result<Self> {
+ input.step(|cursor| match cursor.punct() {
+ Some((punct, rest)) => Ok((punct, rest)),
+ None => Err(cursor.error("expected punctuation token")),
+ })
+ }
+}
+
+#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+impl Parse for Literal {
+ fn parse(input: ParseStream) -> Result<Self> {
+ input.step(|cursor| match cursor.literal() {
+ Some((literal, rest)) => Ok((literal, rest)),
+ None => Err(cursor.error("expected literal token")),
+ })
+ }
+}
+
+/// Parser that can parse Rust tokens into a particular syntax tree node.
+///
+/// Refer to the [module documentation] for details about parsing in Syn.
+///
+/// [module documentation]: self
+pub trait Parser: Sized {
+ type Output;
+
+ /// Parse a proc-macro2 token stream into the chosen syntax tree node.
+ ///
+ /// This function enforces that the input is fully parsed. If there are any
+ /// unparsed tokens at the end of the stream, an error is returned.
+ fn parse2(self, tokens: TokenStream) -> Result<Self::Output>;
+
+ /// Parse tokens of source code into the chosen syntax tree node.
+ ///
+ /// This function enforces that the input is fully parsed. If there are any
+ /// unparsed tokens at the end of the stream, an error is returned.
+ #[cfg(feature = "proc-macro")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "proc-macro")))]
+ fn parse(self, tokens: proc_macro::TokenStream) -> Result<Self::Output> {
+ self.parse2(proc_macro2::TokenStream::from(tokens))
+ }
+
+ /// Parse a string of Rust code into the chosen syntax tree node.
+ ///
+ /// This function enforces that the input is fully parsed. If there are any
+ /// unparsed tokens at the end of the string, an error is returned.
+ ///
+ /// # Hygiene
+ ///
+ /// Every span in the resulting syntax tree will be set to resolve at the
+ /// macro call site.
+ fn parse_str(self, s: &str) -> Result<Self::Output> {
+ self.parse2(proc_macro2::TokenStream::from_str(s)?)
+ }
+
+ // Not public API.
+ #[doc(hidden)]
+ fn __parse_scoped(self, scope: Span, tokens: TokenStream) -> Result<Self::Output> {
+ let _ = scope;
+ self.parse2(tokens)
+ }
+}
+
+fn tokens_to_parse_buffer(tokens: &TokenBuffer) -> ParseBuffer {
+ let scope = Span::call_site();
+ let cursor = tokens.begin();
+ let unexpected = Rc::new(Cell::new(Unexpected::None));
+ new_parse_buffer(scope, cursor, unexpected)
+}
+
+impl<F, T> Parser for F
+where
+ F: FnOnce(ParseStream) -> Result<T>,
+{
+ type Output = T;
+
+ fn parse2(self, tokens: TokenStream) -> Result<T> {
+ let buf = TokenBuffer::new2(tokens);
+ let state = tokens_to_parse_buffer(&buf);
+ let node = self(&state)?;
+ state.check_unexpected()?;
+ if let Some((unexpected_span, delimiter)) =
+ span_of_unexpected_ignoring_nones(state.cursor())
+ {
+ Err(err_unexpected_token(unexpected_span, delimiter))
+ } else {
+ Ok(node)
+ }
+ }
+
+ fn __parse_scoped(self, scope: Span, tokens: TokenStream) -> Result<Self::Output> {
+ let buf = TokenBuffer::new2(tokens);
+ let cursor = buf.begin();
+ let unexpected = Rc::new(Cell::new(Unexpected::None));
+ let state = new_parse_buffer(scope, cursor, unexpected);
+ let node = self(&state)?;
+ state.check_unexpected()?;
+ if let Some((unexpected_span, delimiter)) =
+ span_of_unexpected_ignoring_nones(state.cursor())
+ {
+ Err(err_unexpected_token(unexpected_span, delimiter))
+ } else {
+ Ok(node)
+ }
+ }
+}
+
+pub(crate) fn parse_scoped<F: Parser>(f: F, scope: Span, tokens: TokenStream) -> Result<F::Output> {
+ f.__parse_scoped(scope, tokens)
+}
+
+fn err_unexpected_token(span: Span, delimiter: Delimiter) -> Error {
+ let msg = match delimiter {
+ Delimiter::Parenthesis => "unexpected token, expected `)`",
+ Delimiter::Brace => "unexpected token, expected `}`",
+ Delimiter::Bracket => "unexpected token, expected `]`",
+ Delimiter::None => "unexpected token",
+ };
+ Error::new(span, msg)
+}
+
+/// An empty syntax tree node that consumes no tokens when parsed.
+///
+/// This is useful for attribute macros that want to ensure they are not
+/// provided any attribute args.
+///
+/// ```
+/// # extern crate proc_macro;
+/// #
+/// use proc_macro::TokenStream;
+/// use syn::parse_macro_input;
+/// use syn::parse::Nothing;
+///
+/// # const IGNORE: &str = stringify! {
+/// #[proc_macro_attribute]
+/// # };
+/// pub fn my_attr(args: TokenStream, input: TokenStream) -> TokenStream {
+/// parse_macro_input!(args as Nothing);
+///
+/// /* ... */
+/// # TokenStream::new()
+/// }
+/// ```
+///
+/// ```text
+/// error: unexpected token
+/// --> src/main.rs:3:19
+/// |
+/// 3 | #[my_attr(asdf)]
+/// | ^^^^
+/// ```
+pub struct Nothing;
+
+impl Parse for Nothing {
+ fn parse(_input: ParseStream) -> Result<Self> {
+ Ok(Nothing)
+ }
+}
+
+#[cfg(feature = "printing")]
+#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+impl ToTokens for Nothing {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ let _ = tokens;
+ }
+}
+
+#[cfg(feature = "clone-impls")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for Nothing {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+
+#[cfg(feature = "clone-impls")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Copy for Nothing {}
+
+#[cfg(feature = "extra-traits")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for Nothing {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.write_str("Nothing")
+ }
+}
+
+#[cfg(feature = "extra-traits")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Eq for Nothing {}
+
+#[cfg(feature = "extra-traits")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for Nothing {
+ fn eq(&self, _other: &Self) -> bool {
+ true
+ }
+}
+
+#[cfg(feature = "extra-traits")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for Nothing {
+ fn hash<H: Hasher>(&self, _state: &mut H) {}
+}
diff --git a/rust/syn/parse_macro_input.rs b/rust/syn/parse_macro_input.rs
new file mode 100644
index 000000000000..f0660aedd7df
--- /dev/null
+++ b/rust/syn/parse_macro_input.rs
@@ -0,0 +1,128 @@
+/// Parse the input TokenStream of a macro, triggering a compile error if the
+/// tokens fail to parse.
+///
+/// Refer to the [`parse` module] documentation for more details about parsing
+/// in Syn.
+///
+/// [`parse` module]: mod@crate::parse
+///
+/// <br>
+///
+/// # Intended usage
+///
+/// This macro must be called from a function that returns
+/// `proc_macro::TokenStream`. Usually this will be your proc macro entry point,
+/// the function that has the #\[proc_macro\] / #\[proc_macro_derive\] /
+/// #\[proc_macro_attribute\] attribute.
+///
+/// ```
+/// # extern crate proc_macro;
+/// #
+/// use proc_macro::TokenStream;
+/// use syn::{parse_macro_input, Result};
+/// use syn::parse::{Parse, ParseStream};
+///
+/// struct MyMacroInput {
+/// /* ... */
+/// }
+///
+/// impl Parse for MyMacroInput {
+/// fn parse(input: ParseStream) -> Result<Self> {
+/// /* ... */
+/// # Ok(MyMacroInput {})
+/// }
+/// }
+///
+/// # const IGNORE: &str = stringify! {
+/// #[proc_macro]
+/// # };
+/// pub fn my_macro(tokens: TokenStream) -> TokenStream {
+/// let input = parse_macro_input!(tokens as MyMacroInput);
+///
+/// /* ... */
+/// # TokenStream::new()
+/// }
+/// ```
+///
+/// <br>
+///
+/// # Usage with Parser
+///
+/// This macro can also be used with the [`Parser` trait] for types that have
+/// multiple ways that they can be parsed.
+///
+/// [`Parser` trait]: crate::parse::Parser
+///
+/// ```
+/// # extern crate proc_macro;
+/// #
+/// # use proc_macro::TokenStream;
+/// # use syn::{parse_macro_input, Result};
+/// # use syn::parse::ParseStream;
+/// #
+/// # struct MyMacroInput {}
+/// #
+/// impl MyMacroInput {
+/// fn parse_alternate(input: ParseStream) -> Result<Self> {
+/// /* ... */
+/// # Ok(MyMacroInput {})
+/// }
+/// }
+///
+/// # const IGNORE: &str = stringify! {
+/// #[proc_macro]
+/// # };
+/// pub fn my_macro(tokens: TokenStream) -> TokenStream {
+/// let input = parse_macro_input!(tokens with MyMacroInput::parse_alternate);
+///
+/// /* ... */
+/// # TokenStream::new()
+/// }
+/// ```
+///
+/// <br>
+///
+/// # Expansion
+///
+/// `parse_macro_input!($variable as $Type)` expands to something like:
+///
+/// ```no_run
+/// # extern crate proc_macro;
+/// #
+/// # macro_rules! doc_test {
+/// # ($variable:ident as $Type:ty) => {
+/// match syn::parse::<$Type>($variable) {
+/// Ok(syntax_tree) => syntax_tree,
+/// Err(err) => return proc_macro::TokenStream::from(err.to_compile_error()),
+/// }
+/// # };
+/// # }
+/// #
+/// # fn test(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
+/// # let _ = doc_test!(input as syn::Ident);
+/// # proc_macro::TokenStream::new()
+/// # }
+/// ```
+#[macro_export]
+#[cfg_attr(docsrs, doc(cfg(all(feature = "parsing", feature = "proc-macro"))))]
+macro_rules! parse_macro_input {
+ ($tokenstream:ident as $ty:ty) => {
+ match $crate::parse::<$ty>($tokenstream) {
+ $crate::__private::Ok(data) => data,
+ $crate::__private::Err(err) => {
+ return $crate::__private::TokenStream::from(err.to_compile_error());
+ }
+ }
+ };
+ ($tokenstream:ident with $parser:path) => {
+ match $crate::parse::Parser::parse($parser, $tokenstream) {
+ $crate::__private::Ok(data) => data,
+ $crate::__private::Err(err) => {
+ return $crate::__private::TokenStream::from(err.to_compile_error());
+ }
+ }
+ };
+ ($tokenstream:ident) => {
+ $crate::parse_macro_input!($tokenstream as _)
+ };
+}
diff --git a/rust/syn/parse_quote.rs b/rust/syn/parse_quote.rs
new file mode 100644
index 000000000000..2db20597c436
--- /dev/null
+++ b/rust/syn/parse_quote.rs
@@ -0,0 +1,240 @@
+/// Quasi-quotation macro that accepts input like the [`quote!`] macro but uses
+/// type inference to figure out a return type for those tokens.
+///
+/// [`quote!`]: https://docs.rs/quote/1.0/quote/index.html
+///
+/// The return type can be any syntax tree node that implements the [`Parse`]
+/// trait.
+///
+/// [`Parse`]: crate::parse::Parse
+///
+/// ```
+/// use quote::quote;
+/// use syn::{parse_quote, Stmt};
+///
+/// fn main() {
+/// let name = quote!(v);
+/// let ty = quote!(u8);
+///
+/// let stmt: Stmt = parse_quote! {
+/// let #name: #ty = Default::default();
+/// };
+///
+/// println!("{:#?}", stmt);
+/// }
+/// ```
+///
+/// *This macro is available only if Syn is built with both the `"parsing"` and
+/// `"printing"` features.*
+///
+/// # Example
+///
+/// The following helper function adds a bound `T: HeapSize` to every type
+/// parameter `T` in the input generics.
+///
+/// ```
+/// use syn::{parse_quote, Generics, GenericParam};
+///
+/// // Add a bound `T: HeapSize` to every type parameter T.
+/// fn add_trait_bounds(mut generics: Generics) -> Generics {
+/// for param in &mut generics.params {
+/// if let GenericParam::Type(type_param) = param {
+/// type_param.bounds.push(parse_quote!(HeapSize));
+/// }
+/// }
+/// generics
+/// }
+/// ```
+///
+/// # Special cases
+///
+/// This macro can parse the following additional types as a special case even
+/// though they do not implement the `Parse` trait.
+///
+/// - [`Attribute`] — parses one attribute, allowing either outer like `#[...]`
+/// or inner like `#![...]`
+/// - [`Vec<Attribute>`] — parses multiple attributes, including mixed kinds in
+/// any order
+/// - [`Punctuated<T, P>`] — parses zero or more `T` separated by punctuation
+/// `P` with optional trailing punctuation
+/// - [`Vec<Arm>`] — parses arms separated by optional commas according to the
+/// same grammar as the inside of a `match` expression
+/// - [`Vec<Stmt>`] — parses the same as `Block::parse_within`
+/// - [`Pat`], [`Box<Pat>`] — parses the same as
+/// `Pat::parse_multi_with_leading_vert`
+/// - [`Field`] — parses a named or unnamed struct field
+///
+/// [`Vec<Attribute>`]: Attribute
+/// [`Vec<Arm>`]: Arm
+/// [`Vec<Stmt>`]: Block::parse_within
+/// [`Pat`]: Pat::parse_multi_with_leading_vert
+/// [`Box<Pat>`]: Pat::parse_multi_with_leading_vert
+///
+/// # Panics
+///
+/// Panics if the tokens fail to parse as the expected syntax tree type. The
+/// caller is responsible for ensuring that the input tokens are syntactically
+/// valid.
+#[cfg_attr(docsrs, doc(cfg(all(feature = "parsing", feature = "printing"))))]
+#[macro_export]
+macro_rules! parse_quote {
+ ($($tt:tt)*) => {
+ $crate::__private::parse_quote($crate::__private::quote::quote!($($tt)*))
+ };
+}
+
+/// This macro is [`parse_quote!`] + [`quote_spanned!`][quote::quote_spanned].
+///
+/// Please refer to each of their documentation.
+///
+/// # Example
+///
+/// ```
+/// use quote::{quote, quote_spanned};
+/// use syn::spanned::Spanned;
+/// use syn::{parse_quote_spanned, ReturnType, Signature};
+///
+/// // Changes `fn()` to `fn() -> Pin<Box<dyn Future<Output = ()>>>`,
+/// // and `fn() -> T` to `fn() -> Pin<Box<dyn Future<Output = T>>>`,
+/// // without introducing any call_site() spans.
+/// fn make_ret_pinned_future(sig: &mut Signature) {
+/// let ret = match &sig.output {
+/// ReturnType::Default => quote_spanned!(sig.paren_token.span=> ()),
+/// ReturnType::Type(_, ret) => quote!(#ret),
+/// };
+/// sig.output = parse_quote_spanned! {ret.span()=>
+/// -> ::std::pin::Pin<::std::boxed::Box<dyn ::std::future::Future<Output = #ret>>>
+/// };
+/// }
+/// ```
+#[cfg_attr(docsrs, doc(cfg(all(feature = "parsing", feature = "printing"))))]
+#[macro_export]
+macro_rules! parse_quote_spanned {
+ ($span:expr=> $($tt:tt)*) => {
+ $crate::__private::parse_quote($crate::__private::quote::quote_spanned!($span=> $($tt)*))
+ };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Can parse any type that implements Parse.
+
+use crate::error::Result;
+use crate::parse::{Parse, ParseStream, Parser};
+use proc_macro2::TokenStream;
+
+// Not public API.
+#[doc(hidden)]
+#[track_caller]
+pub fn parse<T: ParseQuote>(token_stream: TokenStream) -> T {
+ let parser = T::parse;
+ match parser.parse2(token_stream) {
+ Ok(t) => t,
+ Err(err) => panic!("{}", err),
+ }
+}
+
+#[doc(hidden)]
+pub trait ParseQuote: Sized {
+ fn parse(input: ParseStream) -> Result<Self>;
+}
+
+impl<T: Parse> ParseQuote for T {
+ fn parse(input: ParseStream) -> Result<Self> {
+ <T as Parse>::parse(input)
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Any other types that we want `parse_quote!` to be able to parse.
+
+use crate::punctuated::Punctuated;
+#[cfg(any(feature = "full", feature = "derive"))]
+use crate::{attr, Attribute, Field, FieldMutability, Ident, Type, Visibility};
+#[cfg(feature = "full")]
+use crate::{Arm, Block, Pat, Stmt};
+
+#[cfg(any(feature = "full", feature = "derive"))]
+impl ParseQuote for Attribute {
+ fn parse(input: ParseStream) -> Result<Self> {
+ if input.peek(Token![#]) && input.peek2(Token![!]) {
+ attr::parsing::single_parse_inner(input)
+ } else {
+ attr::parsing::single_parse_outer(input)
+ }
+ }
+}
+
+#[cfg(any(feature = "full", feature = "derive"))]
+impl ParseQuote for Vec<Attribute> {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let mut attrs = Vec::new();
+ while !input.is_empty() {
+ attrs.push(ParseQuote::parse(input)?);
+ }
+ Ok(attrs)
+ }
+}
+
+#[cfg(any(feature = "full", feature = "derive"))]
+impl ParseQuote for Field {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let attrs = input.call(Attribute::parse_outer)?;
+ let vis: Visibility = input.parse()?;
+
+ let ident: Option<Ident>;
+ let colon_token: Option<Token![:]>;
+ let is_named = input.peek(Ident) && input.peek2(Token![:]) && !input.peek2(Token![::]);
+ if is_named {
+ ident = Some(input.parse()?);
+ colon_token = Some(input.parse()?);
+ } else {
+ ident = None;
+ colon_token = None;
+ }
+
+ let ty: Type = input.parse()?;
+
+ Ok(Field {
+ attrs,
+ vis,
+ mutability: FieldMutability::None,
+ ident,
+ colon_token,
+ ty,
+ })
+ }
+}
+
+#[cfg(feature = "full")]
+impl ParseQuote for Pat {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Pat::parse_multi_with_leading_vert(input)
+ }
+}
+
+#[cfg(feature = "full")]
+impl ParseQuote for Box<Pat> {
+ fn parse(input: ParseStream) -> Result<Self> {
+ <Pat as ParseQuote>::parse(input).map(Box::new)
+ }
+}
+
+impl<T: Parse, P: Parse> ParseQuote for Punctuated<T, P> {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Self::parse_terminated(input)
+ }
+}
+
+#[cfg(feature = "full")]
+impl ParseQuote for Vec<Stmt> {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Block::parse_within(input)
+ }
+}
+
+#[cfg(feature = "full")]
+impl ParseQuote for Vec<Arm> {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Arm::parse_multiple(input)
+ }
+}
diff --git a/rust/syn/pat.rs b/rust/syn/pat.rs
new file mode 100644
index 000000000000..81a2f183f6b9
--- /dev/null
+++ b/rust/syn/pat.rs
@@ -0,0 +1,955 @@
+use crate::attr::Attribute;
+use crate::expr::Member;
+use crate::ident::Ident;
+use crate::path::{Path, QSelf};
+use crate::punctuated::Punctuated;
+use crate::token;
+use crate::ty::Type;
+use proc_macro2::TokenStream;
+
+pub use crate::expr::{
+ ExprConst as PatConst, ExprLit as PatLit, ExprMacro as PatMacro, ExprPath as PatPath,
+ ExprRange as PatRange,
+};
+
+ast_enum_of_structs! {
+ /// A pattern in a local binding, function signature, match expression, or
+ /// various other places.
+ ///
+ /// # Syntax tree enum
+ ///
+ /// This type is a [syntax tree enum].
+ ///
+ /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ #[non_exhaustive]
+ pub enum Pat {
+ /// A const block: `const { ... }`.
+ Const(PatConst),
+
+ /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`.
+ Ident(PatIdent),
+
+ /// A literal pattern: `0`.
+ Lit(PatLit),
+
+ /// A macro in pattern position.
+ Macro(PatMacro),
+
+ /// A pattern that matches any one of a set of cases.
+ Or(PatOr),
+
+ /// A parenthesized pattern: `(A | B)`.
+ Paren(PatParen),
+
+ /// A path pattern like `Color::Red`, optionally qualified with a
+ /// self-type.
+ ///
+ /// Unqualified path patterns can legally refer to variants, structs,
+ /// constants or associated constants. Qualified path patterns like
+ /// `<A>::B::C` and `<A as Trait>::B::C` can only legally refer to
+ /// associated constants.
+ Path(PatPath),
+
+ /// A range pattern: `1..=2`.
+ Range(PatRange),
+
+ /// A reference pattern: `&mut var`.
+ Reference(PatReference),
+
+ /// The dots in a tuple or slice pattern: `[0, 1, ..]`.
+ Rest(PatRest),
+
+ /// A dynamically sized slice pattern: `[a, b, ref i @ .., y, z]`.
+ Slice(PatSlice),
+
+ /// A struct or struct variant pattern: `Variant { x, y, .. }`.
+ Struct(PatStruct),
+
+ /// A tuple pattern: `(a, b)`.
+ Tuple(PatTuple),
+
+ /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`.
+ TupleStruct(PatTupleStruct),
+
+ /// A type ascription pattern: `foo: f64`.
+ Type(PatType),
+
+ /// Tokens in pattern position not interpreted by Syn.
+ Verbatim(TokenStream),
+
+ /// A pattern that matches any value: `_`.
+ Wild(PatWild),
+
+ // For testing exhaustiveness in downstream code, use the following idiom:
+ //
+ // match pat {
+ // #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))]
+ //
+ // Pat::Box(pat) => {...}
+ // Pat::Ident(pat) => {...}
+ // ...
+ // Pat::Wild(pat) => {...}
+ //
+ // _ => { /* some sane fallback */ }
+ // }
+ //
+ // This way we fail your tests but don't break your library when adding
+ // a variant. You will be notified by a test failure when a variant is
+ // added, so that you can add code to handle it, but your library will
+ // continue to compile and work for downstream users in the interim.
+ }
+}
+
+ast_struct! {
+ /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`.
+ ///
+ /// It may also be a unit struct or struct variant (e.g. `None`), or a
+ /// constant; these cannot be distinguished syntactically.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct PatIdent {
+ pub attrs: Vec<Attribute>,
+ pub by_ref: Option<Token![ref]>,
+ pub mutability: Option<Token![mut]>,
+ pub ident: Ident,
+ pub subpat: Option<(Token![@], Box<Pat>)>,
+ }
+}
+
+ast_struct! {
+ /// A pattern that matches any one of a set of cases.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct PatOr {
+ pub attrs: Vec<Attribute>,
+ pub leading_vert: Option<Token![|]>,
+ pub cases: Punctuated<Pat, Token![|]>,
+ }
+}
+
+ast_struct! {
+ /// A parenthesized pattern: `(A | B)`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct PatParen {
+ pub attrs: Vec<Attribute>,
+ pub paren_token: token::Paren,
+ pub pat: Box<Pat>,
+ }
+}
+
+ast_struct! {
+ /// A reference pattern: `&mut var`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct PatReference {
+ pub attrs: Vec<Attribute>,
+ pub and_token: Token![&],
+ pub mutability: Option<Token![mut]>,
+ pub pat: Box<Pat>,
+ }
+}
+
+ast_struct! {
+ /// The dots in a tuple or slice pattern: `[0, 1, ..]`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct PatRest {
+ pub attrs: Vec<Attribute>,
+ pub dot2_token: Token![..],
+ }
+}
+
+ast_struct! {
+ /// A dynamically sized slice pattern: `[a, b, ref i @ .., y, z]`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct PatSlice {
+ pub attrs: Vec<Attribute>,
+ pub bracket_token: token::Bracket,
+ pub elems: Punctuated<Pat, Token![,]>,
+ }
+}
+
+ast_struct! {
+ /// A struct or struct variant pattern: `Variant { x, y, .. }`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct PatStruct {
+ pub attrs: Vec<Attribute>,
+ pub qself: Option<QSelf>,
+ pub path: Path,
+ pub brace_token: token::Brace,
+ pub fields: Punctuated<FieldPat, Token![,]>,
+ pub rest: Option<PatRest>,
+ }
+}
+
+ast_struct! {
+ /// A tuple pattern: `(a, b)`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct PatTuple {
+ pub attrs: Vec<Attribute>,
+ pub paren_token: token::Paren,
+ pub elems: Punctuated<Pat, Token![,]>,
+ }
+}
+
+ast_struct! {
+ /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct PatTupleStruct {
+ pub attrs: Vec<Attribute>,
+ pub qself: Option<QSelf>,
+ pub path: Path,
+ pub paren_token: token::Paren,
+ pub elems: Punctuated<Pat, Token![,]>,
+ }
+}
+
+ast_struct! {
+ /// A type ascription pattern: `foo: f64`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct PatType {
+ pub attrs: Vec<Attribute>,
+ pub pat: Box<Pat>,
+ pub colon_token: Token![:],
+ pub ty: Box<Type>,
+ }
+}
+
+ast_struct! {
+ /// A pattern that matches any value: `_`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct PatWild {
+ pub attrs: Vec<Attribute>,
+ pub underscore_token: Token![_],
+ }
+}
+
+ast_struct! {
+ /// A single field in a struct pattern.
+ ///
+ /// Patterns like the fields of Foo `{ x, ref y, ref mut z }` are treated
+ /// the same as `x: x, y: ref y, z: ref mut z` but there is no colon token.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct FieldPat {
+ pub attrs: Vec<Attribute>,
+ pub member: Member,
+ pub colon_token: Option<Token![:]>,
+ pub pat: Box<Pat>,
+ }
+}
+
+#[cfg(feature = "parsing")]
+pub(crate) mod parsing {
+ use crate::attr::Attribute;
+ use crate::error::{self, Result};
+ use crate::expr::{
+ Expr, ExprConst, ExprLit, ExprMacro, ExprPath, ExprRange, Member, RangeLimits,
+ };
+ use crate::ext::IdentExt as _;
+ use crate::ident::Ident;
+ use crate::lit::Lit;
+ use crate::mac::{self, Macro};
+ use crate::parse::{Parse, ParseBuffer, ParseStream};
+ use crate::pat::{
+ FieldPat, Pat, PatIdent, PatOr, PatParen, PatReference, PatRest, PatSlice, PatStruct,
+ PatTuple, PatTupleStruct, PatType, PatWild,
+ };
+ use crate::path::{self, Path, QSelf};
+ use crate::punctuated::Punctuated;
+ use crate::stmt::Block;
+ use crate::token;
+ use crate::verbatim;
+ use proc_macro2::TokenStream;
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Pat {
+ /// Parse a pattern that does _not_ involve `|` at the top level.
+ ///
+ /// This parser matches the behavior of the `$:pat_param` macro_rules
+ /// matcher, and on editions prior to Rust 2021, the behavior of
+ /// `$:pat`.
+ ///
+ /// In Rust syntax, some examples of where this syntax would occur are
+ /// in the argument pattern of functions and closures. Patterns using
+ /// `|` are not allowed to occur in these positions.
+ ///
+ /// ```compile_fail
+ /// fn f(Some(_) | None: Option<T>) {
+ /// let _ = |Some(_) | None: Option<T>| {};
+ /// // ^^^^^^^^^^^^^^^^^^^^^^^^^??? :(
+ /// }
+ /// ```
+ ///
+ /// ```console
+ /// error: top-level or-patterns are not allowed in function parameters
+ /// --> src/main.rs:1:6
+ /// |
+ /// 1 | fn f(Some(_) | None: Option<T>) {
+ /// | ^^^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(Some(_) | None)`
+ /// ```
+ pub fn parse_single(input: ParseStream) -> Result<Self> {
+ let begin = input.fork();
+ let lookahead = input.lookahead1();
+ if lookahead.peek(Ident)
+ && (input.peek2(Token![::])
+ || input.peek2(Token![!])
+ || input.peek2(token::Brace)
+ || input.peek2(token::Paren)
+ || input.peek2(Token![..]))
+ || input.peek(Token![self]) && input.peek2(Token![::])
+ || lookahead.peek(Token![::])
+ || lookahead.peek(Token![<])
+ || input.peek(Token![Self])
+ || input.peek(Token![super])
+ || input.peek(Token![crate])
+ {
+ pat_path_or_macro_or_struct_or_range(input)
+ } else if lookahead.peek(Token![_]) {
+ input.call(pat_wild).map(Pat::Wild)
+ } else if input.peek(Token![box]) {
+ pat_box(begin, input)
+ } else if input.peek(Token![-]) || lookahead.peek(Lit) || lookahead.peek(Token![const])
+ {
+ pat_lit_or_range(input)
+ } else if lookahead.peek(Token![ref])
+ || lookahead.peek(Token![mut])
+ || input.peek(Token![self])
+ || input.peek(Ident)
+ {
+ input.call(pat_ident).map(Pat::Ident)
+ } else if lookahead.peek(Token![&]) {
+ input.call(pat_reference).map(Pat::Reference)
+ } else if lookahead.peek(token::Paren) {
+ input.call(pat_paren_or_tuple)
+ } else if lookahead.peek(token::Bracket) {
+ input.call(pat_slice).map(Pat::Slice)
+ } else if lookahead.peek(Token![..]) && !input.peek(Token![...]) {
+ pat_range_half_open(input)
+ } else if lookahead.peek(Token![const]) {
+ input.call(pat_const).map(Pat::Verbatim)
+ } else {
+ Err(lookahead.error())
+ }
+ }
+
+ /// Parse a pattern, possibly involving `|`, but not a leading `|`.
+ pub fn parse_multi(input: ParseStream) -> Result<Self> {
+ multi_pat_impl(input, None)
+ }
+
+ /// Parse a pattern, possibly involving `|`, possibly including a
+ /// leading `|`.
+ ///
+ /// This parser matches the behavior of the Rust 2021 edition's `$:pat`
+ /// macro_rules matcher.
+ ///
+ /// In Rust syntax, an example of where this syntax would occur is in
+ /// the pattern of a `match` arm, where the language permits an optional
+ /// leading `|`, although it is not idiomatic to write one there in
+ /// handwritten code.
+ ///
+ /// ```
+ /// # let wat = None;
+ /// match wat {
+ /// | None | Some(false) => {}
+ /// | Some(true) => {}
+ /// }
+ /// ```
+ ///
+ /// The compiler accepts it only to facilitate some situations in
+ /// macro-generated code where a macro author might need to write:
+ ///
+ /// ```
+ /// # macro_rules! doc {
+ /// # ($value:expr, ($($conditions1:pat),*), ($($conditions2:pat),*), $then:expr) => {
+ /// match $value {
+ /// $(| $conditions1)* $(| $conditions2)* => $then
+ /// }
+ /// # };
+ /// # }
+ /// #
+ /// # doc!(true, (true), (false), {});
+ /// # doc!(true, (), (true, false), {});
+ /// # doc!(true, (true, false), (), {});
+ /// ```
+ ///
+ /// Expressing the same thing correctly in the case that either one (but
+ /// not both) of `$conditions1` and `$conditions2` might be empty,
+ /// without leading `|`, is complex.
+ ///
+ /// Use [`Pat::parse_multi`] instead if you are not intending to support
+ /// macro-generated macro input.
+ pub fn parse_multi_with_leading_vert(input: ParseStream) -> Result<Self> {
+ let leading_vert: Option<Token![|]> = input.parse()?;
+ multi_pat_impl(input, leading_vert)
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for PatType {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Ok(PatType {
+ attrs: Vec::new(),
+ pat: Box::new(Pat::parse_single(input)?),
+ colon_token: input.parse()?,
+ ty: input.parse()?,
+ })
+ }
+ }
+
+ fn multi_pat_impl(input: ParseStream, leading_vert: Option<Token![|]>) -> Result<Pat> {
+ let mut pat = Pat::parse_single(input)?;
+ if leading_vert.is_some()
+ || input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=])
+ {
+ let mut cases = Punctuated::new();
+ cases.push_value(pat);
+ while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
+ let punct = input.parse()?;
+ cases.push_punct(punct);
+ let pat = Pat::parse_single(input)?;
+ cases.push_value(pat);
+ }
+ pat = Pat::Or(PatOr {
+ attrs: Vec::new(),
+ leading_vert,
+ cases,
+ });
+ }
+ Ok(pat)
+ }
+
+ fn pat_path_or_macro_or_struct_or_range(input: ParseStream) -> Result<Pat> {
+ let expr_style = true;
+ let (qself, path) = path::parsing::qpath(input, expr_style)?;
+
+ if qself.is_none()
+ && input.peek(Token![!])
+ && !input.peek(Token![!=])
+ && path.is_mod_style()
+ {
+ let bang_token: Token![!] = input.parse()?;
+ let (delimiter, tokens) = mac::parse_delimiter(input)?;
+ return Ok(Pat::Macro(ExprMacro {
+ attrs: Vec::new(),
+ mac: Macro {
+ path,
+ bang_token,
+ delimiter,
+ tokens,
+ },
+ }));
+ }
+
+ if input.peek(token::Brace) {
+ pat_struct(input, qself, path).map(Pat::Struct)
+ } else if input.peek(token::Paren) {
+ pat_tuple_struct(input, qself, path).map(Pat::TupleStruct)
+ } else if input.peek(Token![..]) {
+ pat_range(input, qself, path)
+ } else {
+ Ok(Pat::Path(ExprPath {
+ attrs: Vec::new(),
+ qself,
+ path,
+ }))
+ }
+ }
+
+ fn pat_wild(input: ParseStream) -> Result<PatWild> {
+ Ok(PatWild {
+ attrs: Vec::new(),
+ underscore_token: input.parse()?,
+ })
+ }
+
+ fn pat_box(begin: ParseBuffer, input: ParseStream) -> Result<Pat> {
+ input.parse::<Token![box]>()?;
+ Pat::parse_single(input)?;
+ Ok(Pat::Verbatim(verbatim::between(&begin, input)))
+ }
+
+ fn pat_ident(input: ParseStream) -> Result<PatIdent> {
+ Ok(PatIdent {
+ attrs: Vec::new(),
+ by_ref: input.parse()?,
+ mutability: input.parse()?,
+ ident: {
+ if input.peek(Token![self]) {
+ input.call(Ident::parse_any)?
+ } else {
+ input.parse()?
+ }
+ },
+ subpat: {
+ if input.peek(Token![@]) {
+ let at_token: Token![@] = input.parse()?;
+ let subpat = Pat::parse_single(input)?;
+ Some((at_token, Box::new(subpat)))
+ } else {
+ None
+ }
+ },
+ })
+ }
+
+ fn pat_tuple_struct(
+ input: ParseStream,
+ qself: Option<QSelf>,
+ path: Path,
+ ) -> Result<PatTupleStruct> {
+ let content;
+ let paren_token = parenthesized!(content in input);
+
+ let mut elems = Punctuated::new();
+ while !content.is_empty() {
+ let value = Pat::parse_multi_with_leading_vert(&content)?;
+ elems.push_value(value);
+ if content.is_empty() {
+ break;
+ }
+ let punct = content.parse()?;
+ elems.push_punct(punct);
+ }
+
+ Ok(PatTupleStruct {
+ attrs: Vec::new(),
+ qself,
+ path,
+ paren_token,
+ elems,
+ })
+ }
+
+ fn pat_struct(input: ParseStream, qself: Option<QSelf>, path: Path) -> Result<PatStruct> {
+ let content;
+ let brace_token = braced!(content in input);
+
+ let mut fields = Punctuated::new();
+ let mut rest = None;
+ while !content.is_empty() {
+ let attrs = content.call(Attribute::parse_outer)?;
+ if content.peek(Token![..]) {
+ rest = Some(PatRest {
+ attrs,
+ dot2_token: content.parse()?,
+ });
+ break;
+ }
+ let mut value = content.call(field_pat)?;
+ value.attrs = attrs;
+ fields.push_value(value);
+ if content.is_empty() {
+ break;
+ }
+ let punct: Token![,] = content.parse()?;
+ fields.push_punct(punct);
+ }
+
+ Ok(PatStruct {
+ attrs: Vec::new(),
+ qself,
+ path,
+ brace_token,
+ fields,
+ rest,
+ })
+ }
+
+ fn field_pat(input: ParseStream) -> Result<FieldPat> {
+ let begin = input.fork();
+ let boxed: Option<Token![box]> = input.parse()?;
+ let by_ref: Option<Token![ref]> = input.parse()?;
+ let mutability: Option<Token![mut]> = input.parse()?;
+
+ let member = if boxed.is_some() || by_ref.is_some() || mutability.is_some() {
+ input.parse().map(Member::Named)
+ } else {
+ input.parse()
+ }?;
+
+ if boxed.is_none() && by_ref.is_none() && mutability.is_none() && input.peek(Token![:])
+ || !member.is_named()
+ {
+ return Ok(FieldPat {
+ attrs: Vec::new(),
+ member,
+ colon_token: Some(input.parse()?),
+ pat: Box::new(Pat::parse_multi_with_leading_vert(input)?),
+ });
+ }
+
+ let ident = match member {
+ Member::Named(ident) => ident,
+ Member::Unnamed(_) => unreachable!(),
+ };
+
+ let pat = if boxed.is_some() {
+ Pat::Verbatim(verbatim::between(&begin, input))
+ } else {
+ Pat::Ident(PatIdent {
+ attrs: Vec::new(),
+ by_ref,
+ mutability,
+ ident: ident.clone(),
+ subpat: None,
+ })
+ };
+
+ Ok(FieldPat {
+ attrs: Vec::new(),
+ member: Member::Named(ident),
+ colon_token: None,
+ pat: Box::new(pat),
+ })
+ }
+
+ fn pat_range(input: ParseStream, qself: Option<QSelf>, path: Path) -> Result<Pat> {
+ let limits = RangeLimits::parse_obsolete(input)?;
+ let end = input.call(pat_range_bound)?;
+ if let (RangeLimits::Closed(_), None) = (&limits, &end) {
+ return Err(input.error("expected range upper bound"));
+ }
+ Ok(Pat::Range(ExprRange {
+ attrs: Vec::new(),
+ start: Some(Box::new(Expr::Path(ExprPath {
+ attrs: Vec::new(),
+ qself,
+ path,
+ }))),
+ limits,
+ end: end.map(PatRangeBound::into_expr),
+ }))
+ }
+
+ fn pat_range_half_open(input: ParseStream) -> Result<Pat> {
+ let limits: RangeLimits = input.parse()?;
+ let end = input.call(pat_range_bound)?;
+ if end.is_some() {
+ Ok(Pat::Range(ExprRange {
+ attrs: Vec::new(),
+ start: None,
+ limits,
+ end: end.map(PatRangeBound::into_expr),
+ }))
+ } else {
+ match limits {
+ RangeLimits::HalfOpen(dot2_token) => Ok(Pat::Rest(PatRest {
+ attrs: Vec::new(),
+ dot2_token,
+ })),
+ RangeLimits::Closed(_) => Err(input.error("expected range upper bound")),
+ }
+ }
+ }
+
+ fn pat_paren_or_tuple(input: ParseStream) -> Result<Pat> {
+ let content;
+ let paren_token = parenthesized!(content in input);
+
+ let mut elems = Punctuated::new();
+ while !content.is_empty() {
+ let value = Pat::parse_multi_with_leading_vert(&content)?;
+ if content.is_empty() {
+ if elems.is_empty() && !matches!(value, Pat::Rest(_)) {
+ return Ok(Pat::Paren(PatParen {
+ attrs: Vec::new(),
+ paren_token,
+ pat: Box::new(value),
+ }));
+ }
+ elems.push_value(value);
+ break;
+ }
+ elems.push_value(value);
+ let punct = content.parse()?;
+ elems.push_punct(punct);
+ }
+
+ Ok(Pat::Tuple(PatTuple {
+ attrs: Vec::new(),
+ paren_token,
+ elems,
+ }))
+ }
+
+ fn pat_reference(input: ParseStream) -> Result<PatReference> {
+ Ok(PatReference {
+ attrs: Vec::new(),
+ and_token: input.parse()?,
+ mutability: input.parse()?,
+ pat: Box::new(Pat::parse_single(input)?),
+ })
+ }
+
+ fn pat_lit_or_range(input: ParseStream) -> Result<Pat> {
+ let start = input.call(pat_range_bound)?.unwrap();
+ if input.peek(Token![..]) {
+ let limits = RangeLimits::parse_obsolete(input)?;
+ let end = input.call(pat_range_bound)?;
+ if let (RangeLimits::Closed(_), None) = (&limits, &end) {
+ return Err(input.error("expected range upper bound"));
+ }
+ Ok(Pat::Range(ExprRange {
+ attrs: Vec::new(),
+ start: Some(start.into_expr()),
+ limits,
+ end: end.map(PatRangeBound::into_expr),
+ }))
+ } else {
+ Ok(start.into_pat())
+ }
+ }
+
+ // Patterns that can appear on either side of a range pattern.
+ enum PatRangeBound {
+ Const(ExprConst),
+ Lit(ExprLit),
+ Path(ExprPath),
+ }
+
+ impl PatRangeBound {
+ fn into_expr(self) -> Box<Expr> {
+ Box::new(match self {
+ PatRangeBound::Const(pat) => Expr::Const(pat),
+ PatRangeBound::Lit(pat) => Expr::Lit(pat),
+ PatRangeBound::Path(pat) => Expr::Path(pat),
+ })
+ }
+
+ fn into_pat(self) -> Pat {
+ match self {
+ PatRangeBound::Const(pat) => Pat::Const(pat),
+ PatRangeBound::Lit(pat) => Pat::Lit(pat),
+ PatRangeBound::Path(pat) => Pat::Path(pat),
+ }
+ }
+ }
+
+ fn pat_range_bound(input: ParseStream) -> Result<Option<PatRangeBound>> {
+ if input.is_empty()
+ || input.peek(Token![|])
+ || input.peek(Token![=])
+ || input.peek(Token![:]) && !input.peek(Token![::])
+ || input.peek(Token![,])
+ || input.peek(Token![;])
+ || input.peek(Token![if])
+ {
+ return Ok(None);
+ }
+
+ let lookahead = input.lookahead1();
+ let expr = if lookahead.peek(Lit) {
+ PatRangeBound::Lit(input.parse()?)
+ } else if lookahead.peek(Ident)
+ || lookahead.peek(Token![::])
+ || lookahead.peek(Token![<])
+ || lookahead.peek(Token![self])
+ || lookahead.peek(Token![Self])
+ || lookahead.peek(Token![super])
+ || lookahead.peek(Token![crate])
+ {
+ PatRangeBound::Path(input.parse()?)
+ } else if lookahead.peek(Token![const]) {
+ PatRangeBound::Const(input.parse()?)
+ } else {
+ return Err(lookahead.error());
+ };
+
+ Ok(Some(expr))
+ }
+
+ fn pat_slice(input: ParseStream) -> Result<PatSlice> {
+ let content;
+ let bracket_token = bracketed!(content in input);
+
+ let mut elems = Punctuated::new();
+ while !content.is_empty() {
+ let value = Pat::parse_multi_with_leading_vert(&content)?;
+ match value {
+ Pat::Range(pat) if pat.start.is_none() || pat.end.is_none() => {
+ let (start, end) = match pat.limits {
+ RangeLimits::HalfOpen(dot_dot) => (dot_dot.spans[0], dot_dot.spans[1]),
+ RangeLimits::Closed(dot_dot_eq) => {
+ (dot_dot_eq.spans[0], dot_dot_eq.spans[2])
+ }
+ };
+ let msg = "range pattern is not allowed unparenthesized inside slice pattern";
+ return Err(error::new2(start, end, msg));
+ }
+ _ => {}
+ }
+ elems.push_value(value);
+ if content.is_empty() {
+ break;
+ }
+ let punct = content.parse()?;
+ elems.push_punct(punct);
+ }
+
+ Ok(PatSlice {
+ attrs: Vec::new(),
+ bracket_token,
+ elems,
+ })
+ }
+
+ fn pat_const(input: ParseStream) -> Result<TokenStream> {
+ let begin = input.fork();
+ input.parse::<Token![const]>()?;
+
+ let content;
+ braced!(content in input);
+ content.call(Attribute::parse_inner)?;
+ content.call(Block::parse_within)?;
+
+ Ok(verbatim::between(&begin, input))
+ }
+}
+
+#[cfg(feature = "printing")]
+mod printing {
+ use crate::attr::FilterAttrs;
+ use crate::pat::{
+ FieldPat, Pat, PatIdent, PatOr, PatParen, PatReference, PatRest, PatSlice, PatStruct,
+ PatTuple, PatTupleStruct, PatType, PatWild,
+ };
+ use crate::path;
+ use crate::path::printing::PathStyle;
+ use proc_macro2::TokenStream;
+ use quote::{ToTokens, TokenStreamExt};
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for PatIdent {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.by_ref.to_tokens(tokens);
+ self.mutability.to_tokens(tokens);
+ self.ident.to_tokens(tokens);
+ if let Some((at_token, subpat)) = &self.subpat {
+ at_token.to_tokens(tokens);
+ subpat.to_tokens(tokens);
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for PatOr {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.leading_vert.to_tokens(tokens);
+ self.cases.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for PatParen {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.paren_token.surround(tokens, |tokens| {
+ self.pat.to_tokens(tokens);
+ });
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for PatReference {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.and_token.to_tokens(tokens);
+ self.mutability.to_tokens(tokens);
+ self.pat.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for PatRest {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.dot2_token.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for PatSlice {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.bracket_token.surround(tokens, |tokens| {
+ self.elems.to_tokens(tokens);
+ });
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for PatStruct {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
+ self.brace_token.surround(tokens, |tokens| {
+ self.fields.to_tokens(tokens);
+ // NOTE: We need a comma before the dot2 token if it is present.
+ if !self.fields.empty_or_trailing() && self.rest.is_some() {
+ <Token![,]>::default().to_tokens(tokens);
+ }
+ self.rest.to_tokens(tokens);
+ });
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for PatTuple {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.paren_token.surround(tokens, |tokens| {
+ self.elems.to_tokens(tokens);
+ // If there is only one element, a trailing comma is needed to
+ // distinguish PatTuple from PatParen, unless this is `(..)`
+ // which is a tuple pattern even without comma.
+ if self.elems.len() == 1
+ && !self.elems.trailing_punct()
+ && !matches!(self.elems[0], Pat::Rest { .. })
+ {
+ <Token![,]>::default().to_tokens(tokens);
+ }
+ });
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for PatTupleStruct {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
+ self.paren_token.surround(tokens, |tokens| {
+ self.elems.to_tokens(tokens);
+ });
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for PatType {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.pat.to_tokens(tokens);
+ self.colon_token.to_tokens(tokens);
+ self.ty.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for PatWild {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.underscore_token.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for FieldPat {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ if let Some(colon_token) = &self.colon_token {
+ self.member.to_tokens(tokens);
+ colon_token.to_tokens(tokens);
+ }
+ self.pat.to_tokens(tokens);
+ }
+ }
+}
diff --git a/rust/syn/path.rs b/rust/syn/path.rs
new file mode 100644
index 000000000000..d2fcb9bc5d28
--- /dev/null
+++ b/rust/syn/path.rs
@@ -0,0 +1,966 @@
+#[cfg(feature = "parsing")]
+use crate::error::Result;
+use crate::expr::Expr;
+use crate::generics::TypeParamBound;
+use crate::ident::Ident;
+use crate::lifetime::Lifetime;
+use crate::punctuated::Punctuated;
+use crate::token;
+use crate::ty::{ReturnType, Type};
+
+ast_struct! {
+ /// A path at which a named item is exported (e.g. `std::collections::HashMap`).
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct Path {
+ pub leading_colon: Option<Token![::]>,
+ pub segments: Punctuated<PathSegment, Token![::]>,
+ }
+}
+
+impl<T> From<T> for Path
+where
+ T: Into<PathSegment>,
+{
+ fn from(segment: T) -> Self {
+ let mut path = Path {
+ leading_colon: None,
+ segments: Punctuated::new(),
+ };
+ path.segments.push_value(segment.into());
+ path
+ }
+}
+
+impl Path {
+ /// Determines whether this is a path of length 1 equal to the given
+ /// ident.
+ ///
+ /// For them to compare equal, it must be the case that:
+ ///
+ /// - the path has no leading colon,
+ /// - the number of path segments is 1,
+ /// - the first path segment has no angle bracketed or parenthesized
+ /// path arguments, and
+ /// - the ident of the first path segment is equal to the given one.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use proc_macro2::TokenStream;
+ /// use syn::{Attribute, Error, Meta, Result};
+ ///
+ /// fn get_serde_meta_item(attr: &Attribute) -> Result<Option<&TokenStream>> {
+ /// if attr.path().is_ident("serde") {
+ /// match &attr.meta {
+ /// Meta::List(meta) => Ok(Some(&meta.tokens)),
+ /// bad => Err(Error::new_spanned(bad, "unrecognized attribute")),
+ /// }
+ /// } else {
+ /// Ok(None)
+ /// }
+ /// }
+ /// ```
+ pub fn is_ident<I>(&self, ident: &I) -> bool
+ where
+ I: ?Sized,
+ Ident: PartialEq<I>,
+ {
+ match self.get_ident() {
+ Some(id) => id == ident,
+ None => false,
+ }
+ }
+
+ /// If this path consists of a single ident, returns the ident.
+ ///
+ /// A path is considered an ident if:
+ ///
+ /// - the path has no leading colon,
+ /// - the number of path segments is 1, and
+ /// - the first path segment has no angle bracketed or parenthesized
+ /// path arguments.
+ pub fn get_ident(&self) -> Option<&Ident> {
+ if self.leading_colon.is_none()
+ && self.segments.len() == 1
+ && self.segments[0].arguments.is_none()
+ {
+ Some(&self.segments[0].ident)
+ } else {
+ None
+ }
+ }
+
+ /// An error if this path is not a single ident, as defined in `get_ident`.
+ #[cfg(feature = "parsing")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ pub fn require_ident(&self) -> Result<&Ident> {
+ self.get_ident().ok_or_else(|| {
+ crate::error::new2(
+ self.segments.first().unwrap().ident.span(),
+ self.segments.last().unwrap().ident.span(),
+ "expected this path to be an identifier",
+ )
+ })
+ }
+}
+
+ast_struct! {
+ /// A segment of a path together with any path arguments on that segment.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct PathSegment {
+ pub ident: Ident,
+ pub arguments: PathArguments,
+ }
+}
+
+impl<T> From<T> for PathSegment
+where
+ T: Into<Ident>,
+{
+ fn from(ident: T) -> Self {
+ PathSegment {
+ ident: ident.into(),
+ arguments: PathArguments::None,
+ }
+ }
+}
+
+ast_enum! {
+ /// Angle bracketed or parenthesized arguments of a path segment.
+ ///
+ /// ## Angle bracketed
+ ///
+ /// The `<'a, T>` in `std::slice::iter<'a, T>`.
+ ///
+ /// ## Parenthesized
+ ///
+ /// The `(A, B) -> C` in `Fn(A, B) -> C`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub enum PathArguments {
+ None,
+ /// The `<'a, T>` in `std::slice::iter<'a, T>`.
+ AngleBracketed(AngleBracketedGenericArguments),
+ /// The `(A, B) -> C` in `Fn(A, B) -> C`.
+ Parenthesized(ParenthesizedGenericArguments),
+ }
+}
+
+impl Default for PathArguments {
+ fn default() -> Self {
+ PathArguments::None
+ }
+}
+
+impl PathArguments {
+ pub fn is_empty(&self) -> bool {
+ match self {
+ PathArguments::None => true,
+ PathArguments::AngleBracketed(bracketed) => bracketed.args.is_empty(),
+ PathArguments::Parenthesized(_) => false,
+ }
+ }
+
+ pub fn is_none(&self) -> bool {
+ match self {
+ PathArguments::None => true,
+ PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => false,
+ }
+ }
+}
+
+ast_enum! {
+ /// An individual generic argument, like `'a`, `T`, or `Item = T`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ #[non_exhaustive]
+ pub enum GenericArgument {
+ /// A lifetime argument.
+ Lifetime(Lifetime),
+ /// A type argument.
+ Type(Type),
+ /// A const expression. Must be inside of a block.
+ ///
+ /// NOTE: Identity expressions are represented as Type arguments, as
+ /// they are indistinguishable syntactically.
+ Const(Expr),
+ /// A binding (equality constraint) on an associated type: the `Item =
+ /// u8` in `Iterator<Item = u8>`.
+ AssocType(AssocType),
+ /// An equality constraint on an associated constant: the `PANIC =
+ /// false` in `Trait<PANIC = false>`.
+ AssocConst(AssocConst),
+ /// An associated type bound: `Iterator<Item: Display>`.
+ Constraint(Constraint),
+ }
+}
+
+ast_struct! {
+ /// Angle bracketed arguments of a path segment: the `<K, V>` in `HashMap<K,
+ /// V>`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct AngleBracketedGenericArguments {
+ pub colon2_token: Option<Token![::]>,
+ pub lt_token: Token![<],
+ pub args: Punctuated<GenericArgument, Token![,]>,
+ pub gt_token: Token![>],
+ }
+}
+
+ast_struct! {
+ /// A binding (equality constraint) on an associated type: the `Item = u8`
+ /// in `Iterator<Item = u8>`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct AssocType {
+ pub ident: Ident,
+ pub generics: Option<AngleBracketedGenericArguments>,
+ pub eq_token: Token![=],
+ pub ty: Type,
+ }
+}
+
+ast_struct! {
+ /// An equality constraint on an associated constant: the `PANIC = false` in
+ /// `Trait<PANIC = false>`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct AssocConst {
+ pub ident: Ident,
+ pub generics: Option<AngleBracketedGenericArguments>,
+ pub eq_token: Token![=],
+ pub value: Expr,
+ }
+}
+
+ast_struct! {
+ /// An associated type bound: `Iterator<Item: Display>`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct Constraint {
+ pub ident: Ident,
+ pub generics: Option<AngleBracketedGenericArguments>,
+ pub colon_token: Token![:],
+ pub bounds: Punctuated<TypeParamBound, Token![+]>,
+ }
+}
+
+ast_struct! {
+ /// Arguments of a function path segment: the `(A, B) -> C` in `Fn(A,B) ->
+ /// C`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct ParenthesizedGenericArguments {
+ pub paren_token: token::Paren,
+ /// `(A, B)`
+ pub inputs: Punctuated<Type, Token![,]>,
+ /// `C`
+ pub output: ReturnType,
+ }
+}
+
+ast_struct! {
+ /// The explicit Self type in a qualified path: the `T` in `<T as
+ /// Display>::fmt`.
+ ///
+ /// The actual path, including the trait and the associated item, is stored
+ /// separately. The `position` field represents the index of the associated
+ /// item qualified with this Self type.
+ ///
+ /// ```text
+ /// <Vec<T> as a::b::Trait>::AssociatedItem
+ /// ^~~~~~ ~~~~~~~~~~~~~~^
+ /// ty position = 3
+ ///
+ /// <Vec<T>>::AssociatedItem
+ /// ^~~~~~ ^
+ /// ty position = 0
+ /// ```
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct QSelf {
+ pub lt_token: Token![<],
+ pub ty: Box<Type>,
+ pub position: usize,
+ pub as_token: Option<Token![as]>,
+ pub gt_token: Token![>],
+ }
+}
+
+#[cfg(feature = "parsing")]
+pub(crate) mod parsing {
+ use crate::error::Result;
+ #[cfg(feature = "full")]
+ use crate::expr::ExprBlock;
+ use crate::expr::{Expr, ExprPath};
+ use crate::ext::IdentExt as _;
+ #[cfg(feature = "full")]
+ use crate::generics::TypeParamBound;
+ use crate::ident::Ident;
+ use crate::lifetime::Lifetime;
+ use crate::lit::Lit;
+ use crate::parse::{Parse, ParseStream};
+ #[cfg(feature = "full")]
+ use crate::path::Constraint;
+ use crate::path::{
+ AngleBracketedGenericArguments, AssocConst, AssocType, GenericArgument,
+ ParenthesizedGenericArguments, Path, PathArguments, PathSegment, QSelf,
+ };
+ use crate::punctuated::Punctuated;
+ use crate::token;
+ use crate::ty::{ReturnType, Type};
+ #[cfg(not(feature = "full"))]
+ use crate::verbatim;
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for Path {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Self::parse_helper(input, false)
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for GenericArgument {
+ fn parse(input: ParseStream) -> Result<Self> {
+ if input.peek(Lifetime) && !input.peek2(Token![+]) {
+ return Ok(GenericArgument::Lifetime(input.parse()?));
+ }
+
+ if input.peek(Lit) || input.peek(token::Brace) {
+ return const_argument(input).map(GenericArgument::Const);
+ }
+
+ let mut argument: Type = input.parse()?;
+
+ match argument {
+ Type::Path(mut ty)
+ if ty.qself.is_none()
+ && ty.path.leading_colon.is_none()
+ && ty.path.segments.len() == 1
+ && match &ty.path.segments[0].arguments {
+ PathArguments::None | PathArguments::AngleBracketed(_) => true,
+ PathArguments::Parenthesized(_) => false,
+ } =>
+ {
+ if let Some(eq_token) = input.parse::<Option<Token![=]>>()? {
+ let segment = ty.path.segments.pop().unwrap().into_value();
+ let ident = segment.ident;
+ let generics = match segment.arguments {
+ PathArguments::None => None,
+ PathArguments::AngleBracketed(arguments) => Some(arguments),
+ PathArguments::Parenthesized(_) => unreachable!(),
+ };
+ return if input.peek(Lit) || input.peek(token::Brace) {
+ Ok(GenericArgument::AssocConst(AssocConst {
+ ident,
+ generics,
+ eq_token,
+ value: const_argument(input)?,
+ }))
+ } else {
+ Ok(GenericArgument::AssocType(AssocType {
+ ident,
+ generics,
+ eq_token,
+ ty: input.parse()?,
+ }))
+ };
+ }
+
+ #[cfg(feature = "full")]
+ if let Some(colon_token) = input.parse::<Option<Token![:]>>()? {
+ let segment = ty.path.segments.pop().unwrap().into_value();
+ return Ok(GenericArgument::Constraint(Constraint {
+ ident: segment.ident,
+ generics: match segment.arguments {
+ PathArguments::None => None,
+ PathArguments::AngleBracketed(arguments) => Some(arguments),
+ PathArguments::Parenthesized(_) => unreachable!(),
+ },
+ colon_token,
+ bounds: {
+ let mut bounds = Punctuated::new();
+ loop {
+ if input.peek(Token![,]) || input.peek(Token![>]) {
+ break;
+ }
+ bounds.push_value({
+ let allow_precise_capture = false;
+ let allow_const = true;
+ TypeParamBound::parse_single(
+ input,
+ allow_precise_capture,
+ allow_const,
+ )?
+ });
+ if !input.peek(Token![+]) {
+ break;
+ }
+ let punct: Token![+] = input.parse()?;
+ bounds.push_punct(punct);
+ }
+ bounds
+ },
+ }));
+ }
+
+ argument = Type::Path(ty);
+ }
+ _ => {}
+ }
+
+ Ok(GenericArgument::Type(argument))
+ }
+ }
+
+ pub(crate) fn const_argument(input: ParseStream) -> Result<Expr> {
+ let lookahead = input.lookahead1();
+
+ if input.peek(Lit) {
+ let lit = input.parse()?;
+ return Ok(Expr::Lit(lit));
+ }
+
+ if input.peek(Ident) {
+ let ident: Ident = input.parse()?;
+ return Ok(Expr::Path(ExprPath {
+ attrs: Vec::new(),
+ qself: None,
+ path: Path::from(ident),
+ }));
+ }
+
+ if input.peek(token::Brace) {
+ #[cfg(feature = "full")]
+ {
+ let block: ExprBlock = input.parse()?;
+ return Ok(Expr::Block(block));
+ }
+
+ #[cfg(not(feature = "full"))]
+ {
+ let begin = input.fork();
+ let content;
+ braced!(content in input);
+ content.parse::<Expr>()?;
+ let verbatim = verbatim::between(&begin, input);
+ return Ok(Expr::Verbatim(verbatim));
+ }
+ }
+
+ Err(lookahead.error())
+ }
+
+ impl AngleBracketedGenericArguments {
+ /// Parse `::<…>` with mandatory leading `::`.
+ ///
+ /// The ordinary [`Parse`] impl for `AngleBracketedGenericArguments`
+ /// parses optional leading `::`.
+ #[cfg(feature = "full")]
+ #[cfg_attr(docsrs, doc(cfg(all(feature = "parsing", feature = "full"))))]
+ pub fn parse_turbofish(input: ParseStream) -> Result<Self> {
+ let colon2_token: Token![::] = input.parse()?;
+ Self::do_parse(Some(colon2_token), input)
+ }
+
+ pub(crate) fn do_parse(
+ colon2_token: Option<Token![::]>,
+ input: ParseStream,
+ ) -> Result<Self> {
+ Ok(AngleBracketedGenericArguments {
+ colon2_token,
+ lt_token: input.parse()?,
+ args: {
+ let mut args = Punctuated::new();
+ loop {
+ if input.peek(Token![>]) {
+ break;
+ }
+ let value: GenericArgument = input.parse()?;
+ args.push_value(value);
+ if input.peek(Token![>]) {
+ break;
+ }
+ let punct: Token![,] = input.parse()?;
+ args.push_punct(punct);
+ }
+ args
+ },
+ gt_token: input.parse()?,
+ })
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for AngleBracketedGenericArguments {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let colon2_token: Option<Token![::]> = input.parse()?;
+ Self::do_parse(colon2_token, input)
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ParenthesizedGenericArguments {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let content;
+ Ok(ParenthesizedGenericArguments {
+ paren_token: parenthesized!(content in input),
+ inputs: content.parse_terminated(Type::parse, Token![,])?,
+ output: input.call(ReturnType::without_plus)?,
+ })
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for PathSegment {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Self::parse_helper(input, false)
+ }
+ }
+
+ impl PathSegment {
+ fn parse_helper(input: ParseStream, expr_style: bool) -> Result<Self> {
+ if input.peek(Token![super])
+ || input.peek(Token![self])
+ || input.peek(Token![crate])
+ || cfg!(feature = "full") && input.peek(Token![try])
+ {
+ let ident = input.call(Ident::parse_any)?;
+ return Ok(PathSegment::from(ident));
+ }
+
+ let ident = if input.peek(Token![Self]) {
+ input.call(Ident::parse_any)?
+ } else {
+ input.parse()?
+ };
+
+ if !expr_style
+ && input.peek(Token![<])
+ && !input.peek(Token![<=])
+ && !input.peek(Token![<<=])
+ || input.peek(Token![::]) && input.peek3(Token![<])
+ {
+ Ok(PathSegment {
+ ident,
+ arguments: PathArguments::AngleBracketed(input.parse()?),
+ })
+ } else {
+ Ok(PathSegment::from(ident))
+ }
+ }
+ }
+
+ impl Path {
+ /// Parse a `Path` containing no path arguments on any of its segments.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use syn::{Path, Result, Token};
+ /// use syn::parse::{Parse, ParseStream};
+ ///
+ /// // A simplified single `use` statement like:
+ /// //
+ /// // use std::collections::HashMap;
+ /// //
+ /// // Note that generic parameters are not allowed in a `use` statement
+ /// // so the following must not be accepted.
+ /// //
+ /// // use a::<b>::c;
+ /// struct SingleUse {
+ /// use_token: Token![use],
+ /// path: Path,
+ /// }
+ ///
+ /// impl Parse for SingleUse {
+ /// fn parse(input: ParseStream) -> Result<Self> {
+ /// Ok(SingleUse {
+ /// use_token: input.parse()?,
+ /// path: input.call(Path::parse_mod_style)?,
+ /// })
+ /// }
+ /// }
+ /// ```
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ pub fn parse_mod_style(input: ParseStream) -> Result<Self> {
+ Ok(Path {
+ leading_colon: input.parse()?,
+ segments: {
+ let mut segments = Punctuated::new();
+ loop {
+ if !input.peek(Ident)
+ && !input.peek(Token![super])
+ && !input.peek(Token![self])
+ && !input.peek(Token![Self])
+ && !input.peek(Token![crate])
+ {
+ break;
+ }
+ let ident = Ident::parse_any(input)?;
+ segments.push_value(PathSegment::from(ident));
+ if !input.peek(Token![::]) {
+ break;
+ }
+ let punct = input.parse()?;
+ segments.push_punct(punct);
+ }
+ if segments.is_empty() {
+ return Err(input.parse::<Ident>().unwrap_err());
+ } else if segments.trailing_punct() {
+ return Err(input.error("expected path segment after `::`"));
+ }
+ segments
+ },
+ })
+ }
+
+ pub(crate) fn parse_helper(input: ParseStream, expr_style: bool) -> Result<Self> {
+ let mut path = Path {
+ leading_colon: input.parse()?,
+ segments: {
+ let mut segments = Punctuated::new();
+ let value = PathSegment::parse_helper(input, expr_style)?;
+ segments.push_value(value);
+ segments
+ },
+ };
+ Path::parse_rest(input, &mut path, expr_style)?;
+ Ok(path)
+ }
+
+ pub(crate) fn parse_rest(
+ input: ParseStream,
+ path: &mut Self,
+ expr_style: bool,
+ ) -> Result<()> {
+ while input.peek(Token![::]) && !input.peek3(token::Paren) {
+ let punct: Token![::] = input.parse()?;
+ path.segments.push_punct(punct);
+ let value = PathSegment::parse_helper(input, expr_style)?;
+ path.segments.push_value(value);
+ }
+ Ok(())
+ }
+
+ pub(crate) fn is_mod_style(&self) -> bool {
+ self.segments
+ .iter()
+ .all(|segment| segment.arguments.is_none())
+ }
+ }
+
+ pub(crate) fn qpath(input: ParseStream, expr_style: bool) -> Result<(Option<QSelf>, Path)> {
+ if input.peek(Token![<]) {
+ let lt_token: Token![<] = input.parse()?;
+ let this: Type = input.parse()?;
+ let path = if input.peek(Token![as]) {
+ let as_token: Token![as] = input.parse()?;
+ let path: Path = input.parse()?;
+ Some((as_token, path))
+ } else {
+ None
+ };
+ let gt_token: Token![>] = input.parse()?;
+ let colon2_token: Token![::] = input.parse()?;
+ let mut rest = Punctuated::new();
+ loop {
+ let path = PathSegment::parse_helper(input, expr_style)?;
+ rest.push_value(path);
+ if !input.peek(Token![::]) {
+ break;
+ }
+ let punct: Token![::] = input.parse()?;
+ rest.push_punct(punct);
+ }
+ let (position, as_token, path) = match path {
+ Some((as_token, mut path)) => {
+ let pos = path.segments.len();
+ path.segments.push_punct(colon2_token);
+ path.segments.extend(rest.into_pairs());
+ (pos, Some(as_token), path)
+ }
+ None => {
+ let path = Path {
+ leading_colon: Some(colon2_token),
+ segments: rest,
+ };
+ (0, None, path)
+ }
+ };
+ let qself = QSelf {
+ lt_token,
+ ty: Box::new(this),
+ position,
+ as_token,
+ gt_token,
+ };
+ Ok((Some(qself), path))
+ } else {
+ let path = Path::parse_helper(input, expr_style)?;
+ Ok((None, path))
+ }
+ }
+}
+
+#[cfg(feature = "printing")]
+pub(crate) mod printing {
+ use crate::generics;
+ use crate::path::{
+ AngleBracketedGenericArguments, AssocConst, AssocType, Constraint, GenericArgument,
+ ParenthesizedGenericArguments, Path, PathArguments, PathSegment, QSelf,
+ };
+ use crate::print::TokensOrDefault;
+ #[cfg(feature = "parsing")]
+ use crate::spanned::Spanned;
+ #[cfg(feature = "parsing")]
+ use proc_macro2::Span;
+ use proc_macro2::TokenStream;
+ use quote::ToTokens;
+ use std::cmp;
+
+ pub(crate) enum PathStyle {
+ Expr,
+ Mod,
+ AsWritten,
+ }
+
+ impl Copy for PathStyle {}
+
+ impl Clone for PathStyle {
+ fn clone(&self) -> Self {
+ *self
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for Path {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ print_path(tokens, self, PathStyle::AsWritten);
+ }
+ }
+
+ pub(crate) fn print_path(tokens: &mut TokenStream, path: &Path, style: PathStyle) {
+ path.leading_colon.to_tokens(tokens);
+ for segment in path.segments.pairs() {
+ print_path_segment(tokens, segment.value(), style);
+ segment.punct().to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for PathSegment {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ print_path_segment(tokens, self, PathStyle::AsWritten);
+ }
+ }
+
+ fn print_path_segment(tokens: &mut TokenStream, segment: &PathSegment, style: PathStyle) {
+ segment.ident.to_tokens(tokens);
+ print_path_arguments(tokens, &segment.arguments, style);
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for PathArguments {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ print_path_arguments(tokens, self, PathStyle::AsWritten);
+ }
+ }
+
+ fn print_path_arguments(tokens: &mut TokenStream, arguments: &PathArguments, style: PathStyle) {
+ match arguments {
+ PathArguments::None => {}
+ PathArguments::AngleBracketed(arguments) => {
+ print_angle_bracketed_generic_arguments(tokens, arguments, style);
+ }
+ PathArguments::Parenthesized(arguments) => {
+ print_parenthesized_generic_arguments(tokens, arguments, style);
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for GenericArgument {
+ #[allow(clippy::match_same_arms)]
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ match self {
+ GenericArgument::Lifetime(lt) => lt.to_tokens(tokens),
+ GenericArgument::Type(ty) => ty.to_tokens(tokens),
+ GenericArgument::Const(expr) => {
+ generics::printing::print_const_argument(expr, tokens);
+ }
+ GenericArgument::AssocType(assoc) => assoc.to_tokens(tokens),
+ GenericArgument::AssocConst(assoc) => assoc.to_tokens(tokens),
+ GenericArgument::Constraint(constraint) => constraint.to_tokens(tokens),
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for AngleBracketedGenericArguments {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ print_angle_bracketed_generic_arguments(tokens, self, PathStyle::AsWritten);
+ }
+ }
+
+ pub(crate) fn print_angle_bracketed_generic_arguments(
+ tokens: &mut TokenStream,
+ arguments: &AngleBracketedGenericArguments,
+ style: PathStyle,
+ ) {
+ if let PathStyle::Mod = style {
+ return;
+ }
+
+ conditionally_print_turbofish(tokens, &arguments.colon2_token, style);
+ arguments.lt_token.to_tokens(tokens);
+
+ // Print lifetimes before types/consts/bindings, regardless of their
+ // order in args.
+ let mut trailing_or_empty = true;
+ for param in arguments.args.pairs() {
+ match param.value() {
+ GenericArgument::Lifetime(_) => {
+ param.to_tokens(tokens);
+ trailing_or_empty = param.punct().is_some();
+ }
+ GenericArgument::Type(_)
+ | GenericArgument::Const(_)
+ | GenericArgument::AssocType(_)
+ | GenericArgument::AssocConst(_)
+ | GenericArgument::Constraint(_) => {}
+ }
+ }
+ for param in arguments.args.pairs() {
+ match param.value() {
+ GenericArgument::Type(_)
+ | GenericArgument::Const(_)
+ | GenericArgument::AssocType(_)
+ | GenericArgument::AssocConst(_)
+ | GenericArgument::Constraint(_) => {
+ if !trailing_or_empty {
+ <Token![,]>::default().to_tokens(tokens);
+ }
+ param.to_tokens(tokens);
+ trailing_or_empty = param.punct().is_some();
+ }
+ GenericArgument::Lifetime(_) => {}
+ }
+ }
+
+ arguments.gt_token.to_tokens(tokens);
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for AssocType {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.ident.to_tokens(tokens);
+ self.generics.to_tokens(tokens);
+ self.eq_token.to_tokens(tokens);
+ self.ty.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for AssocConst {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.ident.to_tokens(tokens);
+ self.generics.to_tokens(tokens);
+ self.eq_token.to_tokens(tokens);
+ generics::printing::print_const_argument(&self.value, tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for Constraint {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.ident.to_tokens(tokens);
+ self.generics.to_tokens(tokens);
+ self.colon_token.to_tokens(tokens);
+ self.bounds.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ParenthesizedGenericArguments {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ print_parenthesized_generic_arguments(tokens, self, PathStyle::AsWritten);
+ }
+ }
+
+ fn print_parenthesized_generic_arguments(
+ tokens: &mut TokenStream,
+ arguments: &ParenthesizedGenericArguments,
+ style: PathStyle,
+ ) {
+ if let PathStyle::Mod = style {
+ return;
+ }
+
+ conditionally_print_turbofish(tokens, &None, style);
+ arguments.paren_token.surround(tokens, |tokens| {
+ arguments.inputs.to_tokens(tokens);
+ });
+ arguments.output.to_tokens(tokens);
+ }
+
+ pub(crate) fn print_qpath(
+ tokens: &mut TokenStream,
+ qself: &Option<QSelf>,
+ path: &Path,
+ style: PathStyle,
+ ) {
+ let qself = match qself {
+ Some(qself) => qself,
+ None => {
+ print_path(tokens, path, style);
+ return;
+ }
+ };
+ qself.lt_token.to_tokens(tokens);
+ qself.ty.to_tokens(tokens);
+
+ let pos = cmp::min(qself.position, path.segments.len());
+ let mut segments = path.segments.pairs();
+ if pos > 0 {
+ TokensOrDefault(&qself.as_token).to_tokens(tokens);
+ path.leading_colon.to_tokens(tokens);
+ for (i, segment) in segments.by_ref().take(pos).enumerate() {
+ print_path_segment(tokens, segment.value(), PathStyle::AsWritten);
+ if i + 1 == pos {
+ qself.gt_token.to_tokens(tokens);
+ }
+ segment.punct().to_tokens(tokens);
+ }
+ } else {
+ qself.gt_token.to_tokens(tokens);
+ path.leading_colon.to_tokens(tokens);
+ }
+ for segment in segments {
+ print_path_segment(tokens, segment.value(), style);
+ segment.punct().to_tokens(tokens);
+ }
+ }
+
+ fn conditionally_print_turbofish(
+ tokens: &mut TokenStream,
+ colon2_token: &Option<Token![::]>,
+ style: PathStyle,
+ ) {
+ match style {
+ PathStyle::Expr => TokensOrDefault(colon2_token).to_tokens(tokens),
+ PathStyle::Mod => unreachable!(),
+ PathStyle::AsWritten => colon2_token.to_tokens(tokens),
+ }
+ }
+
+ #[cfg(feature = "parsing")]
+ #[cfg_attr(docsrs, doc(cfg(all(feature = "parsing", feature = "printing"))))]
+ impl Spanned for QSelf {
+ fn span(&self) -> Span {
+ struct QSelfDelimiters<'a>(&'a QSelf);
+
+ impl<'a> ToTokens for QSelfDelimiters<'a> {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.0.lt_token.to_tokens(tokens);
+ self.0.gt_token.to_tokens(tokens);
+ }
+ }
+
+ QSelfDelimiters(self).span()
+ }
+ }
+}
diff --git a/rust/syn/precedence.rs b/rust/syn/precedence.rs
new file mode 100644
index 000000000000..1891bfc202fd
--- /dev/null
+++ b/rust/syn/precedence.rs
@@ -0,0 +1,210 @@
+#[cfg(all(feature = "printing", feature = "full"))]
+use crate::attr::{AttrStyle, Attribute};
+#[cfg(feature = "printing")]
+use crate::expr::Expr;
+#[cfg(all(feature = "printing", feature = "full"))]
+use crate::expr::{
+ ExprArray, ExprAsync, ExprAwait, ExprBlock, ExprBreak, ExprCall, ExprConst, ExprContinue,
+ ExprField, ExprForLoop, ExprGroup, ExprIf, ExprIndex, ExprInfer, ExprLit, ExprLoop, ExprMacro,
+ ExprMatch, ExprMethodCall, ExprParen, ExprPath, ExprRepeat, ExprReturn, ExprStruct, ExprTry,
+ ExprTryBlock, ExprTuple, ExprUnsafe, ExprWhile, ExprYield,
+};
+use crate::op::BinOp;
+#[cfg(all(feature = "printing", feature = "full"))]
+use crate::ty::ReturnType;
+use std::cmp::Ordering;
+
+// Reference: https://doc.rust-lang.org/reference/expressions.html#expression-precedence
+pub(crate) enum Precedence {
+ // return, break, closures
+ Jump,
+ // = += -= *= /= %= &= |= ^= <<= >>=
+ Assign,
+ // .. ..=
+ Range,
+ // ||
+ Or,
+ // &&
+ And,
+ // let
+ #[cfg(feature = "printing")]
+ Let,
+ // == != < > <= >=
+ Compare,
+ // |
+ BitOr,
+ // ^
+ BitXor,
+ // &
+ BitAnd,
+ // << >>
+ Shift,
+ // + -
+ Sum,
+ // * / %
+ Product,
+ // as
+ Cast,
+ // unary - * ! & &mut
+ #[cfg(feature = "printing")]
+ Prefix,
+ // paths, loops, function calls, array indexing, field expressions, method calls
+ #[cfg(feature = "printing")]
+ Unambiguous,
+}
+
+impl Precedence {
+ pub(crate) const MIN: Self = Precedence::Jump;
+
+ pub(crate) fn of_binop(op: &BinOp) -> Self {
+ match op {
+ BinOp::Add(_) | BinOp::Sub(_) => Precedence::Sum,
+ BinOp::Mul(_) | BinOp::Div(_) | BinOp::Rem(_) => Precedence::Product,
+ BinOp::And(_) => Precedence::And,
+ BinOp::Or(_) => Precedence::Or,
+ BinOp::BitXor(_) => Precedence::BitXor,
+ BinOp::BitAnd(_) => Precedence::BitAnd,
+ BinOp::BitOr(_) => Precedence::BitOr,
+ BinOp::Shl(_) | BinOp::Shr(_) => Precedence::Shift,
+
+ BinOp::Eq(_)
+ | BinOp::Lt(_)
+ | BinOp::Le(_)
+ | BinOp::Ne(_)
+ | BinOp::Ge(_)
+ | BinOp::Gt(_) => Precedence::Compare,
+
+ BinOp::AddAssign(_)
+ | BinOp::SubAssign(_)
+ | BinOp::MulAssign(_)
+ | BinOp::DivAssign(_)
+ | BinOp::RemAssign(_)
+ | BinOp::BitXorAssign(_)
+ | BinOp::BitAndAssign(_)
+ | BinOp::BitOrAssign(_)
+ | BinOp::ShlAssign(_)
+ | BinOp::ShrAssign(_) => Precedence::Assign,
+ }
+ }
+
+ #[cfg(feature = "printing")]
+ pub(crate) fn of(e: &Expr) -> Self {
+ #[cfg(feature = "full")]
+ fn prefix_attrs(attrs: &[Attribute]) -> Precedence {
+ for attr in attrs {
+ if let AttrStyle::Outer = attr.style {
+ return Precedence::Prefix;
+ }
+ }
+ Precedence::Unambiguous
+ }
+
+ match e {
+ #[cfg(feature = "full")]
+ Expr::Closure(e) => match e.output {
+ ReturnType::Default => Precedence::Jump,
+ ReturnType::Type(..) => prefix_attrs(&e.attrs),
+ },
+
+ #[cfg(feature = "full")]
+ Expr::Break(ExprBreak { expr, .. })
+ | Expr::Return(ExprReturn { expr, .. })
+ | Expr::Yield(ExprYield { expr, .. }) => match expr {
+ Some(_) => Precedence::Jump,
+ None => Precedence::Unambiguous,
+ },
+
+ Expr::Assign(_) => Precedence::Assign,
+ Expr::Range(_) => Precedence::Range,
+ Expr::Binary(e) => Precedence::of_binop(&e.op),
+ Expr::Let(_) => Precedence::Let,
+ Expr::Cast(_) => Precedence::Cast,
+ Expr::RawAddr(_) | Expr::Reference(_) | Expr::Unary(_) => Precedence::Prefix,
+
+ #[cfg(feature = "full")]
+ Expr::Array(ExprArray { attrs, .. })
+ | Expr::Async(ExprAsync { attrs, .. })
+ | Expr::Await(ExprAwait { attrs, .. })
+ | Expr::Block(ExprBlock { attrs, .. })
+ | Expr::Call(ExprCall { attrs, .. })
+ | Expr::Const(ExprConst { attrs, .. })
+ | Expr::Continue(ExprContinue { attrs, .. })
+ | Expr::Field(ExprField { attrs, .. })
+ | Expr::ForLoop(ExprForLoop { attrs, .. })
+ | Expr::Group(ExprGroup { attrs, .. })
+ | Expr::If(ExprIf { attrs, .. })
+ | Expr::Index(ExprIndex { attrs, .. })
+ | Expr::Infer(ExprInfer { attrs, .. })
+ | Expr::Lit(ExprLit { attrs, .. })
+ | Expr::Loop(ExprLoop { attrs, .. })
+ | Expr::Macro(ExprMacro { attrs, .. })
+ | Expr::Match(ExprMatch { attrs, .. })
+ | Expr::MethodCall(ExprMethodCall { attrs, .. })
+ | Expr::Paren(ExprParen { attrs, .. })
+ | Expr::Path(ExprPath { attrs, .. })
+ | Expr::Repeat(ExprRepeat { attrs, .. })
+ | Expr::Struct(ExprStruct { attrs, .. })
+ | Expr::Try(ExprTry { attrs, .. })
+ | Expr::TryBlock(ExprTryBlock { attrs, .. })
+ | Expr::Tuple(ExprTuple { attrs, .. })
+ | Expr::Unsafe(ExprUnsafe { attrs, .. })
+ | Expr::While(ExprWhile { attrs, .. }) => prefix_attrs(attrs),
+
+ #[cfg(not(feature = "full"))]
+ Expr::Array(_)
+ | Expr::Async(_)
+ | Expr::Await(_)
+ | Expr::Block(_)
+ | Expr::Call(_)
+ | Expr::Const(_)
+ | Expr::Continue(_)
+ | Expr::Field(_)
+ | Expr::ForLoop(_)
+ | Expr::Group(_)
+ | Expr::If(_)
+ | Expr::Index(_)
+ | Expr::Infer(_)
+ | Expr::Lit(_)
+ | Expr::Loop(_)
+ | Expr::Macro(_)
+ | Expr::Match(_)
+ | Expr::MethodCall(_)
+ | Expr::Paren(_)
+ | Expr::Path(_)
+ | Expr::Repeat(_)
+ | Expr::Struct(_)
+ | Expr::Try(_)
+ | Expr::TryBlock(_)
+ | Expr::Tuple(_)
+ | Expr::Unsafe(_)
+ | Expr::While(_) => Precedence::Unambiguous,
+
+ Expr::Verbatim(_) => Precedence::Unambiguous,
+
+ #[cfg(not(feature = "full"))]
+ Expr::Break(_) | Expr::Closure(_) | Expr::Return(_) | Expr::Yield(_) => unreachable!(),
+ }
+ }
+}
+
+impl Copy for Precedence {}
+
+impl Clone for Precedence {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+
+impl PartialEq for Precedence {
+ fn eq(&self, other: &Self) -> bool {
+ *self as u8 == *other as u8
+ }
+}
+
+impl PartialOrd for Precedence {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ let this = *self as u8;
+ let other = *other as u8;
+ Some(this.cmp(&other))
+ }
+}
diff --git a/rust/syn/print.rs b/rust/syn/print.rs
new file mode 100644
index 000000000000..07409932677b
--- /dev/null
+++ b/rust/syn/print.rs
@@ -0,0 +1,16 @@
+use proc_macro2::TokenStream;
+use quote::ToTokens;
+
+pub(crate) struct TokensOrDefault<'a, T: 'a>(pub &'a Option<T>);
+
+impl<'a, T> ToTokens for TokensOrDefault<'a, T>
+where
+ T: ToTokens + Default,
+{
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ match self.0 {
+ Some(t) => t.to_tokens(tokens),
+ None => T::default().to_tokens(tokens),
+ }
+ }
+}
diff --git a/rust/syn/punctuated.rs b/rust/syn/punctuated.rs
new file mode 100644
index 000000000000..ebaaa94f9a26
--- /dev/null
+++ b/rust/syn/punctuated.rs
@@ -0,0 +1,1155 @@
+//! A punctuated sequence of syntax tree nodes separated by punctuation.
+//!
+//! Lots of things in Rust are punctuated sequences.
+//!
+//! - The fields of a struct are `Punctuated<Field, Token![,]>`.
+//! - The segments of a path are `Punctuated<PathSegment, Token![::]>`.
+//! - The bounds on a generic parameter are `Punctuated<TypeParamBound,
+//! Token![+]>`.
+//! - The arguments to a function call are `Punctuated<Expr, Token![,]>`.
+//!
+//! This module provides a common representation for these punctuated sequences
+//! in the form of the [`Punctuated<T, P>`] type. We store a vector of pairs of
+//! syntax tree node + punctuation, where every node in the sequence is followed
+//! by punctuation except for possibly the final one.
+//!
+//! [`Punctuated<T, P>`]: Punctuated
+//!
+//! ```text
+//! a_function_call(arg1, arg2, arg3);
+//! ~~~~^ ~~~~^ ~~~~
+//! ```
+
+use crate::drops::{NoDrop, TrivialDrop};
+#[cfg(feature = "parsing")]
+use crate::error::Result;
+#[cfg(feature = "parsing")]
+use crate::parse::{Parse, ParseStream};
+#[cfg(feature = "parsing")]
+use crate::token::Token;
+#[cfg(feature = "extra-traits")]
+use std::fmt::{self, Debug};
+#[cfg(feature = "extra-traits")]
+use std::hash::{Hash, Hasher};
+#[cfg(any(feature = "full", feature = "derive"))]
+use std::iter;
+use std::ops::{Index, IndexMut};
+use std::option;
+use std::slice;
+use std::vec;
+
+/// **A punctuated sequence of syntax tree nodes of type `T` separated by
+/// punctuation of type `P`.**
+///
+/// Refer to the [module documentation] for details about punctuated sequences.
+///
+/// [module documentation]: self
+pub struct Punctuated<T, P> {
+ inner: Vec<(T, P)>,
+ last: Option<Box<T>>,
+}
+
+impl<T, P> Punctuated<T, P> {
+ /// Creates an empty punctuated sequence.
+ pub const fn new() -> Self {
+ Punctuated {
+ inner: Vec::new(),
+ last: None,
+ }
+ }
+
+ /// Determines whether this punctuated sequence is empty, meaning it
+ /// contains no syntax tree nodes or punctuation.
+ pub fn is_empty(&self) -> bool {
+ self.inner.len() == 0 && self.last.is_none()
+ }
+
+ /// Returns the number of syntax tree nodes in this punctuated sequence.
+ ///
+ /// This is the number of nodes of type `T`, not counting the punctuation of
+ /// type `P`.
+ pub fn len(&self) -> usize {
+ self.inner.len() + if self.last.is_some() { 1 } else { 0 }
+ }
+
+ /// Borrows the first element in this sequence.
+ pub fn first(&self) -> Option<&T> {
+ self.iter().next()
+ }
+
+ /// Mutably borrows the first element in this sequence.
+ pub fn first_mut(&mut self) -> Option<&mut T> {
+ self.iter_mut().next()
+ }
+
+ /// Borrows the last element in this sequence.
+ pub fn last(&self) -> Option<&T> {
+ self.iter().next_back()
+ }
+
+ /// Mutably borrows the last element in this sequence.
+ pub fn last_mut(&mut self) -> Option<&mut T> {
+ self.iter_mut().next_back()
+ }
+
+ /// Borrows the element at the given index.
+ pub fn get(&self, index: usize) -> Option<&T> {
+ if let Some((value, _punct)) = self.inner.get(index) {
+ Some(value)
+ } else if index == self.inner.len() {
+ self.last.as_deref()
+ } else {
+ None
+ }
+ }
+
+ /// Mutably borrows the element at the given index.
+ pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
+ let inner_len = self.inner.len();
+ if let Some((value, _punct)) = self.inner.get_mut(index) {
+ Some(value)
+ } else if index == inner_len {
+ self.last.as_deref_mut()
+ } else {
+ None
+ }
+ }
+
+ /// Returns an iterator over borrowed syntax tree nodes of type `&T`.
+ pub fn iter(&self) -> Iter<T> {
+ Iter {
+ inner: Box::new(NoDrop::new(PrivateIter {
+ inner: self.inner.iter(),
+ last: self.last.as_ref().map(Box::as_ref).into_iter(),
+ })),
+ }
+ }
+
+ /// Returns an iterator over mutably borrowed syntax tree nodes of type
+ /// `&mut T`.
+ pub fn iter_mut(&mut self) -> IterMut<T> {
+ IterMut {
+ inner: Box::new(NoDrop::new(PrivateIterMut {
+ inner: self.inner.iter_mut(),
+ last: self.last.as_mut().map(Box::as_mut).into_iter(),
+ })),
+ }
+ }
+
+ /// Returns an iterator over the contents of this sequence as borrowed
+ /// punctuated pairs.
+ pub fn pairs(&self) -> Pairs<T, P> {
+ Pairs {
+ inner: self.inner.iter(),
+ last: self.last.as_ref().map(Box::as_ref).into_iter(),
+ }
+ }
+
+ /// Returns an iterator over the contents of this sequence as mutably
+ /// borrowed punctuated pairs.
+ pub fn pairs_mut(&mut self) -> PairsMut<T, P> {
+ PairsMut {
+ inner: self.inner.iter_mut(),
+ last: self.last.as_mut().map(Box::as_mut).into_iter(),
+ }
+ }
+
+ /// Returns an iterator over the contents of this sequence as owned
+ /// punctuated pairs.
+ pub fn into_pairs(self) -> IntoPairs<T, P> {
+ IntoPairs {
+ inner: self.inner.into_iter(),
+ last: self.last.map(|t| *t).into_iter(),
+ }
+ }
+
+ /// Appends a syntax tree node onto the end of this punctuated sequence. The
+ /// sequence must already have a trailing punctuation, or be empty.
+ ///
+ /// Use [`push`] instead if the punctuated sequence may or may not already
+ /// have trailing punctuation.
+ ///
+ /// [`push`]: Punctuated::push
+ ///
+ /// # Panics
+ ///
+ /// Panics if the sequence is nonempty and does not already have a trailing
+ /// punctuation.
+ pub fn push_value(&mut self, value: T) {
+ assert!(
+ self.empty_or_trailing(),
+ "Punctuated::push_value: cannot push value if Punctuated is missing trailing punctuation",
+ );
+
+ self.last = Some(Box::new(value));
+ }
+
+ /// Appends a trailing punctuation onto the end of this punctuated sequence.
+ /// The sequence must be non-empty and must not already have trailing
+ /// punctuation.
+ ///
+ /// # Panics
+ ///
+ /// Panics if the sequence is empty or already has a trailing punctuation.
+ pub fn push_punct(&mut self, punctuation: P) {
+ assert!(
+ self.last.is_some(),
+ "Punctuated::push_punct: cannot push punctuation if Punctuated is empty or already has trailing punctuation",
+ );
+
+ let last = self.last.take().unwrap();
+ self.inner.push((*last, punctuation));
+ }
+
+ /// Removes the last punctuated pair from this sequence, or `None` if the
+ /// sequence is empty.
+ pub fn pop(&mut self) -> Option<Pair<T, P>> {
+ if self.last.is_some() {
+ self.last.take().map(|t| Pair::End(*t))
+ } else {
+ self.inner.pop().map(|(t, p)| Pair::Punctuated(t, p))
+ }
+ }
+
+ /// Removes the trailing punctuation from this punctuated sequence, or
+ /// `None` if there isn't any.
+ pub fn pop_punct(&mut self) -> Option<P> {
+ if self.last.is_some() {
+ None
+ } else {
+ let (t, p) = self.inner.pop()?;
+ self.last = Some(Box::new(t));
+ Some(p)
+ }
+ }
+
+ /// Determines whether this punctuated sequence ends with a trailing
+ /// punctuation.
+ pub fn trailing_punct(&self) -> bool {
+ self.last.is_none() && !self.is_empty()
+ }
+
+ /// Returns true if either this `Punctuated` is empty, or it has a trailing
+ /// punctuation.
+ ///
+ /// Equivalent to `punctuated.is_empty() || punctuated.trailing_punct()`.
+ pub fn empty_or_trailing(&self) -> bool {
+ self.last.is_none()
+ }
+
+ /// Appends a syntax tree node onto the end of this punctuated sequence.
+ ///
+ /// If there is not a trailing punctuation in this sequence when this method
+ /// is called, the default value of punctuation type `P` is inserted before
+ /// the given value of type `T`.
+ pub fn push(&mut self, value: T)
+ where
+ P: Default,
+ {
+ if !self.empty_or_trailing() {
+ self.push_punct(Default::default());
+ }
+ self.push_value(value);
+ }
+
+ /// Inserts an element at position `index`.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `index` is greater than the number of elements previously in
+ /// this punctuated sequence.
+ pub fn insert(&mut self, index: usize, value: T)
+ where
+ P: Default,
+ {
+ assert!(
+ index <= self.len(),
+ "Punctuated::insert: index out of range",
+ );
+
+ if index == self.len() {
+ self.push(value);
+ } else {
+ self.inner.insert(index, (value, Default::default()));
+ }
+ }
+
+ /// Clears the sequence of all values and punctuation, making it empty.
+ pub fn clear(&mut self) {
+ self.inner.clear();
+ self.last = None;
+ }
+
+ /// Parses zero or more occurrences of `T` separated by punctuation of type
+ /// `P`, with optional trailing punctuation.
+ ///
+ /// Parsing continues until the end of this parse stream. The entire content
+ /// of this parse stream must consist of `T` and `P`.
+ #[cfg(feature = "parsing")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ pub fn parse_terminated(input: ParseStream) -> Result<Self>
+ where
+ T: Parse,
+ P: Parse,
+ {
+ Self::parse_terminated_with(input, T::parse)
+ }
+
+ /// Parses zero or more occurrences of `T` using the given parse function,
+ /// separated by punctuation of type `P`, with optional trailing
+ /// punctuation.
+ ///
+ /// Like [`parse_terminated`], the entire content of this stream is expected
+ /// to be parsed.
+ ///
+ /// [`parse_terminated`]: Punctuated::parse_terminated
+ #[cfg(feature = "parsing")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ pub fn parse_terminated_with<'a>(
+ input: ParseStream<'a>,
+ parser: fn(ParseStream<'a>) -> Result<T>,
+ ) -> Result<Self>
+ where
+ P: Parse,
+ {
+ let mut punctuated = Punctuated::new();
+
+ loop {
+ if input.is_empty() {
+ break;
+ }
+ let value = parser(input)?;
+ punctuated.push_value(value);
+ if input.is_empty() {
+ break;
+ }
+ let punct = input.parse()?;
+ punctuated.push_punct(punct);
+ }
+
+ Ok(punctuated)
+ }
+
+ /// Parses one or more occurrences of `T` separated by punctuation of type
+ /// `P`, not accepting trailing punctuation.
+ ///
+ /// Parsing continues as long as punctuation `P` is present at the head of
+ /// the stream. This method returns upon parsing a `T` and observing that it
+ /// is not followed by a `P`, even if there are remaining tokens in the
+ /// stream.
+ #[cfg(feature = "parsing")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ pub fn parse_separated_nonempty(input: ParseStream) -> Result<Self>
+ where
+ T: Parse,
+ P: Token + Parse,
+ {
+ Self::parse_separated_nonempty_with(input, T::parse)
+ }
+
+ /// Parses one or more occurrences of `T` using the given parse function,
+ /// separated by punctuation of type `P`, not accepting trailing
+ /// punctuation.
+ ///
+ /// Like [`parse_separated_nonempty`], may complete early without parsing
+ /// the entire content of this stream.
+ ///
+ /// [`parse_separated_nonempty`]: Punctuated::parse_separated_nonempty
+ #[cfg(feature = "parsing")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ pub fn parse_separated_nonempty_with<'a>(
+ input: ParseStream<'a>,
+ parser: fn(ParseStream<'a>) -> Result<T>,
+ ) -> Result<Self>
+ where
+ P: Token + Parse,
+ {
+ let mut punctuated = Punctuated::new();
+
+ loop {
+ let value = parser(input)?;
+ punctuated.push_value(value);
+ if !P::peek(input.cursor()) {
+ break;
+ }
+ let punct = input.parse()?;
+ punctuated.push_punct(punct);
+ }
+
+ Ok(punctuated)
+ }
+}
+
+#[cfg(feature = "clone-impls")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl<T, P> Clone for Punctuated<T, P>
+where
+ T: Clone,
+ P: Clone,
+{
+ fn clone(&self) -> Self {
+ Punctuated {
+ inner: self.inner.clone(),
+ last: self.last.clone(),
+ }
+ }
+
+ fn clone_from(&mut self, other: &Self) {
+ self.inner.clone_from(&other.inner);
+ self.last.clone_from(&other.last);
+ }
+}
+
+#[cfg(feature = "extra-traits")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl<T, P> Eq for Punctuated<T, P>
+where
+ T: Eq,
+ P: Eq,
+{
+}
+
+#[cfg(feature = "extra-traits")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl<T, P> PartialEq for Punctuated<T, P>
+where
+ T: PartialEq,
+ P: PartialEq,
+{
+ fn eq(&self, other: &Self) -> bool {
+ let Punctuated { inner, last } = self;
+ *inner == other.inner && *last == other.last
+ }
+}
+
+#[cfg(feature = "extra-traits")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl<T, P> Hash for Punctuated<T, P>
+where
+ T: Hash,
+ P: Hash,
+{
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ let Punctuated { inner, last } = self;
+ inner.hash(state);
+ last.hash(state);
+ }
+}
+
+#[cfg(feature = "extra-traits")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl<T: Debug, P: Debug> Debug for Punctuated<T, P> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let mut list = f.debug_list();
+ for (t, p) in &self.inner {
+ list.entry(t);
+ list.entry(p);
+ }
+ if let Some(last) = &self.last {
+ list.entry(last);
+ }
+ list.finish()
+ }
+}
+
+impl<T, P> FromIterator<T> for Punctuated<T, P>
+where
+ P: Default,
+{
+ fn from_iter<I: IntoIterator<Item = T>>(i: I) -> Self {
+ let mut ret = Punctuated::new();
+ ret.extend(i);
+ ret
+ }
+}
+
+impl<T, P> Extend<T> for Punctuated<T, P>
+where
+ P: Default,
+{
+ fn extend<I: IntoIterator<Item = T>>(&mut self, i: I) {
+ for value in i {
+ self.push(value);
+ }
+ }
+}
+
+impl<T, P> FromIterator<Pair<T, P>> for Punctuated<T, P> {
+ fn from_iter<I: IntoIterator<Item = Pair<T, P>>>(i: I) -> Self {
+ let mut ret = Punctuated::new();
+ do_extend(&mut ret, i.into_iter());
+ ret
+ }
+}
+
+impl<T, P> Extend<Pair<T, P>> for Punctuated<T, P>
+where
+ P: Default,
+{
+ fn extend<I: IntoIterator<Item = Pair<T, P>>>(&mut self, i: I) {
+ if !self.empty_or_trailing() {
+ self.push_punct(P::default());
+ }
+ do_extend(self, i.into_iter());
+ }
+}
+
+fn do_extend<T, P, I>(punctuated: &mut Punctuated<T, P>, i: I)
+where
+ I: Iterator<Item = Pair<T, P>>,
+{
+ let mut nomore = false;
+ for pair in i {
+ if nomore {
+ panic!("punctuated extended with items after a Pair::End");
+ }
+ match pair {
+ Pair::Punctuated(a, b) => punctuated.inner.push((a, b)),
+ Pair::End(a) => {
+ punctuated.last = Some(Box::new(a));
+ nomore = true;
+ }
+ }
+ }
+}
+
+impl<T, P> IntoIterator for Punctuated<T, P> {
+ type Item = T;
+ type IntoIter = IntoIter<T>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ let mut elements = Vec::with_capacity(self.len());
+ elements.extend(self.inner.into_iter().map(|pair| pair.0));
+ elements.extend(self.last.map(|t| *t));
+
+ IntoIter {
+ inner: elements.into_iter(),
+ }
+ }
+}
+
+impl<'a, T, P> IntoIterator for &'a Punctuated<T, P> {
+ type Item = &'a T;
+ type IntoIter = Iter<'a, T>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ Punctuated::iter(self)
+ }
+}
+
+impl<'a, T, P> IntoIterator for &'a mut Punctuated<T, P> {
+ type Item = &'a mut T;
+ type IntoIter = IterMut<'a, T>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ Punctuated::iter_mut(self)
+ }
+}
+
+impl<T, P> Default for Punctuated<T, P> {
+ fn default() -> Self {
+ Punctuated::new()
+ }
+}
+
+/// An iterator over borrowed pairs of type `Pair<&T, &P>`.
+///
+/// Refer to the [module documentation] for details about punctuated sequences.
+///
+/// [module documentation]: self
+pub struct Pairs<'a, T: 'a, P: 'a> {
+ inner: slice::Iter<'a, (T, P)>,
+ last: option::IntoIter<&'a T>,
+}
+
+impl<'a, T, P> Iterator for Pairs<'a, T, P> {
+ type Item = Pair<&'a T, &'a P>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.inner
+ .next()
+ .map(|(t, p)| Pair::Punctuated(t, p))
+ .or_else(|| self.last.next().map(Pair::End))
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (self.len(), Some(self.len()))
+ }
+}
+
+impl<'a, T, P> DoubleEndedIterator for Pairs<'a, T, P> {
+ fn next_back(&mut self) -> Option<Self::Item> {
+ self.last
+ .next()
+ .map(Pair::End)
+ .or_else(|| self.inner.next_back().map(|(t, p)| Pair::Punctuated(t, p)))
+ }
+}
+
+impl<'a, T, P> ExactSizeIterator for Pairs<'a, T, P> {
+ fn len(&self) -> usize {
+ self.inner.len() + self.last.len()
+ }
+}
+
+// No Clone bound on T or P.
+impl<'a, T, P> Clone for Pairs<'a, T, P> {
+ fn clone(&self) -> Self {
+ Pairs {
+ inner: self.inner.clone(),
+ last: self.last.clone(),
+ }
+ }
+}
+
+/// An iterator over mutably borrowed pairs of type `Pair<&mut T, &mut P>`.
+///
+/// Refer to the [module documentation] for details about punctuated sequences.
+///
+/// [module documentation]: self
+pub struct PairsMut<'a, T: 'a, P: 'a> {
+ inner: slice::IterMut<'a, (T, P)>,
+ last: option::IntoIter<&'a mut T>,
+}
+
+impl<'a, T, P> Iterator for PairsMut<'a, T, P> {
+ type Item = Pair<&'a mut T, &'a mut P>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.inner
+ .next()
+ .map(|(t, p)| Pair::Punctuated(t, p))
+ .or_else(|| self.last.next().map(Pair::End))
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (self.len(), Some(self.len()))
+ }
+}
+
+impl<'a, T, P> DoubleEndedIterator for PairsMut<'a, T, P> {
+ fn next_back(&mut self) -> Option<Self::Item> {
+ self.last
+ .next()
+ .map(Pair::End)
+ .or_else(|| self.inner.next_back().map(|(t, p)| Pair::Punctuated(t, p)))
+ }
+}
+
+impl<'a, T, P> ExactSizeIterator for PairsMut<'a, T, P> {
+ fn len(&self) -> usize {
+ self.inner.len() + self.last.len()
+ }
+}
+
+/// An iterator over owned pairs of type `Pair<T, P>`.
+///
+/// Refer to the [module documentation] for details about punctuated sequences.
+///
+/// [module documentation]: self
+pub struct IntoPairs<T, P> {
+ inner: vec::IntoIter<(T, P)>,
+ last: option::IntoIter<T>,
+}
+
+impl<T, P> Iterator for IntoPairs<T, P> {
+ type Item = Pair<T, P>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.inner
+ .next()
+ .map(|(t, p)| Pair::Punctuated(t, p))
+ .or_else(|| self.last.next().map(Pair::End))
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (self.len(), Some(self.len()))
+ }
+}
+
+impl<T, P> DoubleEndedIterator for IntoPairs<T, P> {
+ fn next_back(&mut self) -> Option<Self::Item> {
+ self.last
+ .next()
+ .map(Pair::End)
+ .or_else(|| self.inner.next_back().map(|(t, p)| Pair::Punctuated(t, p)))
+ }
+}
+
+impl<T, P> ExactSizeIterator for IntoPairs<T, P> {
+ fn len(&self) -> usize {
+ self.inner.len() + self.last.len()
+ }
+}
+
+impl<T, P> Clone for IntoPairs<T, P>
+where
+ T: Clone,
+ P: Clone,
+{
+ fn clone(&self) -> Self {
+ IntoPairs {
+ inner: self.inner.clone(),
+ last: self.last.clone(),
+ }
+ }
+}
+
+/// An iterator over owned values of type `T`.
+///
+/// Refer to the [module documentation] for details about punctuated sequences.
+///
+/// [module documentation]: self
+pub struct IntoIter<T> {
+ inner: vec::IntoIter<T>,
+}
+
+impl<T> Iterator for IntoIter<T> {
+ type Item = T;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.inner.next()
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (self.len(), Some(self.len()))
+ }
+}
+
+impl<T> DoubleEndedIterator for IntoIter<T> {
+ fn next_back(&mut self) -> Option<Self::Item> {
+ self.inner.next_back()
+ }
+}
+
+impl<T> ExactSizeIterator for IntoIter<T> {
+ fn len(&self) -> usize {
+ self.inner.len()
+ }
+}
+
+impl<T> Clone for IntoIter<T>
+where
+ T: Clone,
+{
+ fn clone(&self) -> Self {
+ IntoIter {
+ inner: self.inner.clone(),
+ }
+ }
+}
+
+/// An iterator over borrowed values of type `&T`.
+///
+/// Refer to the [module documentation] for details about punctuated sequences.
+///
+/// [module documentation]: self
+pub struct Iter<'a, T: 'a> {
+ inner: Box<NoDrop<dyn IterTrait<'a, T> + 'a>>,
+}
+
+trait IterTrait<'a, T: 'a>: Iterator<Item = &'a T> + DoubleEndedIterator + ExactSizeIterator {
+ fn clone_box(&self) -> Box<NoDrop<dyn IterTrait<'a, T> + 'a>>;
+}
+
+struct PrivateIter<'a, T: 'a, P: 'a> {
+ inner: slice::Iter<'a, (T, P)>,
+ last: option::IntoIter<&'a T>,
+}
+
+impl<'a, T, P> TrivialDrop for PrivateIter<'a, T, P>
+where
+ slice::Iter<'a, (T, P)>: TrivialDrop,
+ option::IntoIter<&'a T>: TrivialDrop,
+{
+}
+
+#[cfg(any(feature = "full", feature = "derive"))]
+pub(crate) fn empty_punctuated_iter<'a, T>() -> Iter<'a, T> {
+ Iter {
+ inner: Box::new(NoDrop::new(iter::empty())),
+ }
+}
+
+// No Clone bound on T.
+impl<'a, T> Clone for Iter<'a, T> {
+ fn clone(&self) -> Self {
+ Iter {
+ inner: self.inner.clone_box(),
+ }
+ }
+}
+
+impl<'a, T> Iterator for Iter<'a, T> {
+ type Item = &'a T;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.inner.next()
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (self.len(), Some(self.len()))
+ }
+}
+
+impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
+ fn next_back(&mut self) -> Option<Self::Item> {
+ self.inner.next_back()
+ }
+}
+
+impl<'a, T> ExactSizeIterator for Iter<'a, T> {
+ fn len(&self) -> usize {
+ self.inner.len()
+ }
+}
+
+impl<'a, T, P> Iterator for PrivateIter<'a, T, P> {
+ type Item = &'a T;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.inner
+ .next()
+ .map(|pair| &pair.0)
+ .or_else(|| self.last.next())
+ }
+}
+
+impl<'a, T, P> DoubleEndedIterator for PrivateIter<'a, T, P> {
+ fn next_back(&mut self) -> Option<Self::Item> {
+ self.last
+ .next()
+ .or_else(|| self.inner.next_back().map(|pair| &pair.0))
+ }
+}
+
+impl<'a, T, P> ExactSizeIterator for PrivateIter<'a, T, P> {
+ fn len(&self) -> usize {
+ self.inner.len() + self.last.len()
+ }
+}
+
+// No Clone bound on T or P.
+impl<'a, T, P> Clone for PrivateIter<'a, T, P> {
+ fn clone(&self) -> Self {
+ PrivateIter {
+ inner: self.inner.clone(),
+ last: self.last.clone(),
+ }
+ }
+}
+
+impl<'a, T, I> IterTrait<'a, T> for I
+where
+ T: 'a,
+ I: DoubleEndedIterator<Item = &'a T>
+ + ExactSizeIterator<Item = &'a T>
+ + Clone
+ + TrivialDrop
+ + 'a,
+{
+ fn clone_box(&self) -> Box<NoDrop<dyn IterTrait<'a, T> + 'a>> {
+ Box::new(NoDrop::new(self.clone()))
+ }
+}
+
+/// An iterator over mutably borrowed values of type `&mut T`.
+///
+/// Refer to the [module documentation] for details about punctuated sequences.
+///
+/// [module documentation]: self
+pub struct IterMut<'a, T: 'a> {
+ inner: Box<NoDrop<dyn IterMutTrait<'a, T, Item = &'a mut T> + 'a>>,
+}
+
+trait IterMutTrait<'a, T: 'a>:
+ DoubleEndedIterator<Item = &'a mut T> + ExactSizeIterator<Item = &'a mut T>
+{
+}
+
+struct PrivateIterMut<'a, T: 'a, P: 'a> {
+ inner: slice::IterMut<'a, (T, P)>,
+ last: option::IntoIter<&'a mut T>,
+}
+
+impl<'a, T, P> TrivialDrop for PrivateIterMut<'a, T, P>
+where
+ slice::IterMut<'a, (T, P)>: TrivialDrop,
+ option::IntoIter<&'a mut T>: TrivialDrop,
+{
+}
+
+#[cfg(any(feature = "full", feature = "derive"))]
+pub(crate) fn empty_punctuated_iter_mut<'a, T>() -> IterMut<'a, T> {
+ IterMut {
+ inner: Box::new(NoDrop::new(iter::empty())),
+ }
+}
+
+impl<'a, T> Iterator for IterMut<'a, T> {
+ type Item = &'a mut T;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.inner.next()
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (self.len(), Some(self.len()))
+ }
+}
+
+impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
+ fn next_back(&mut self) -> Option<Self::Item> {
+ self.inner.next_back()
+ }
+}
+
+impl<'a, T> ExactSizeIterator for IterMut<'a, T> {
+ fn len(&self) -> usize {
+ self.inner.len()
+ }
+}
+
+impl<'a, T, P> Iterator for PrivateIterMut<'a, T, P> {
+ type Item = &'a mut T;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.inner
+ .next()
+ .map(|pair| &mut pair.0)
+ .or_else(|| self.last.next())
+ }
+}
+
+impl<'a, T, P> DoubleEndedIterator for PrivateIterMut<'a, T, P> {
+ fn next_back(&mut self) -> Option<Self::Item> {
+ self.last
+ .next()
+ .or_else(|| self.inner.next_back().map(|pair| &mut pair.0))
+ }
+}
+
+impl<'a, T, P> ExactSizeIterator for PrivateIterMut<'a, T, P> {
+ fn len(&self) -> usize {
+ self.inner.len() + self.last.len()
+ }
+}
+
+impl<'a, T, I> IterMutTrait<'a, T> for I
+where
+ T: 'a,
+ I: DoubleEndedIterator<Item = &'a mut T> + ExactSizeIterator<Item = &'a mut T> + 'a,
+{
+}
+
+/// A single syntax tree node of type `T` followed by its trailing punctuation
+/// of type `P` if any.
+///
+/// Refer to the [module documentation] for details about punctuated sequences.
+///
+/// [module documentation]: self
+pub enum Pair<T, P> {
+ Punctuated(T, P),
+ End(T),
+}
+
+impl<T, P> Pair<T, P> {
+ /// Extracts the syntax tree node from this punctuated pair, discarding the
+ /// following punctuation.
+ pub fn into_value(self) -> T {
+ match self {
+ Pair::Punctuated(t, _) | Pair::End(t) => t,
+ }
+ }
+
+ /// Borrows the syntax tree node from this punctuated pair.
+ pub fn value(&self) -> &T {
+ match self {
+ Pair::Punctuated(t, _) | Pair::End(t) => t,
+ }
+ }
+
+ /// Mutably borrows the syntax tree node from this punctuated pair.
+ pub fn value_mut(&mut self) -> &mut T {
+ match self {
+ Pair::Punctuated(t, _) | Pair::End(t) => t,
+ }
+ }
+
+ /// Borrows the punctuation from this punctuated pair, unless this pair is
+ /// the final one and there is no trailing punctuation.
+ pub fn punct(&self) -> Option<&P> {
+ match self {
+ Pair::Punctuated(_, p) => Some(p),
+ Pair::End(_) => None,
+ }
+ }
+
+ /// Mutably borrows the punctuation from this punctuated pair, unless the
+ /// pair is the final one and there is no trailing punctuation.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// # use proc_macro2::Span;
+ /// # use syn::punctuated::Punctuated;
+ /// # use syn::{parse_quote, Token, TypeParamBound};
+ /// #
+ /// # let mut punctuated = Punctuated::<TypeParamBound, Token![+]>::new();
+ /// # let span = Span::call_site();
+ /// #
+ /// punctuated.insert(0, parse_quote!('lifetime));
+ /// if let Some(punct) = punctuated.pairs_mut().next().unwrap().punct_mut() {
+ /// punct.span = span;
+ /// }
+ /// ```
+ pub fn punct_mut(&mut self) -> Option<&mut P> {
+ match self {
+ Pair::Punctuated(_, p) => Some(p),
+ Pair::End(_) => None,
+ }
+ }
+
+ /// Creates a punctuated pair out of a syntax tree node and an optional
+ /// following punctuation.
+ pub fn new(t: T, p: Option<P>) -> Self {
+ match p {
+ Some(p) => Pair::Punctuated(t, p),
+ None => Pair::End(t),
+ }
+ }
+
+ /// Produces this punctuated pair as a tuple of syntax tree node and
+ /// optional following punctuation.
+ pub fn into_tuple(self) -> (T, Option<P>) {
+ match self {
+ Pair::Punctuated(t, p) => (t, Some(p)),
+ Pair::End(t) => (t, None),
+ }
+ }
+}
+
+#[cfg(feature = "clone-impls")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl<T, P> Pair<&T, &P> {
+ pub fn cloned(self) -> Pair<T, P>
+ where
+ T: Clone,
+ P: Clone,
+ {
+ match self {
+ Pair::Punctuated(t, p) => Pair::Punctuated(t.clone(), p.clone()),
+ Pair::End(t) => Pair::End(t.clone()),
+ }
+ }
+}
+
+#[cfg(feature = "clone-impls")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl<T, P> Clone for Pair<T, P>
+where
+ T: Clone,
+ P: Clone,
+{
+ fn clone(&self) -> Self {
+ match self {
+ Pair::Punctuated(t, p) => Pair::Punctuated(t.clone(), p.clone()),
+ Pair::End(t) => Pair::End(t.clone()),
+ }
+ }
+}
+
+#[cfg(feature = "clone-impls")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl<T, P> Copy for Pair<T, P>
+where
+ T: Copy,
+ P: Copy,
+{
+}
+
+impl<T, P> Index<usize> for Punctuated<T, P> {
+ type Output = T;
+
+ fn index(&self, index: usize) -> &Self::Output {
+ if index == self.len() - 1 {
+ match &self.last {
+ Some(t) => t,
+ None => &self.inner[index].0,
+ }
+ } else {
+ &self.inner[index].0
+ }
+ }
+}
+
+impl<T, P> IndexMut<usize> for Punctuated<T, P> {
+ fn index_mut(&mut self, index: usize) -> &mut Self::Output {
+ if index == self.len() - 1 {
+ match &mut self.last {
+ Some(t) => t,
+ None => &mut self.inner[index].0,
+ }
+ } else {
+ &mut self.inner[index].0
+ }
+ }
+}
+
+#[cfg(all(feature = "fold", any(feature = "full", feature = "derive")))]
+pub(crate) fn fold<T, P, V, F>(
+ punctuated: Punctuated<T, P>,
+ fold: &mut V,
+ mut f: F,
+) -> Punctuated<T, P>
+where
+ V: ?Sized,
+ F: FnMut(&mut V, T) -> T,
+{
+ Punctuated {
+ inner: punctuated
+ .inner
+ .into_iter()
+ .map(|(t, p)| (f(fold, t), p))
+ .collect(),
+ last: match punctuated.last {
+ Some(t) => Some(Box::new(f(fold, *t))),
+ None => None,
+ },
+ }
+}
+
+#[cfg(feature = "printing")]
+mod printing {
+ use crate::punctuated::{Pair, Punctuated};
+ use proc_macro2::TokenStream;
+ use quote::{ToTokens, TokenStreamExt};
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl<T, P> ToTokens for Punctuated<T, P>
+ where
+ T: ToTokens,
+ P: ToTokens,
+ {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.pairs());
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl<T, P> ToTokens for Pair<T, P>
+ where
+ T: ToTokens,
+ P: ToTokens,
+ {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ match self {
+ Pair::Punctuated(a, b) => {
+ a.to_tokens(tokens);
+ b.to_tokens(tokens);
+ }
+ Pair::End(a) => a.to_tokens(tokens),
+ }
+ }
+ }
+}
diff --git a/rust/syn/restriction.rs b/rust/syn/restriction.rs
new file mode 100644
index 000000000000..6e6758f3cd73
--- /dev/null
+++ b/rust/syn/restriction.rs
@@ -0,0 +1,178 @@
+use crate::path::Path;
+use crate::token;
+
+ast_enum! {
+ /// The visibility level of an item: inherited or `pub` or
+ /// `pub(restricted)`.
+ ///
+ /// # 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 Visibility {
+ /// A public visibility level: `pub`.
+ Public(Token![pub]),
+
+ /// A visibility level restricted to some path: `pub(self)` or
+ /// `pub(super)` or `pub(crate)` or `pub(in some::module)`.
+ Restricted(VisRestricted),
+
+ /// An inherited visibility, which usually means private.
+ Inherited,
+ }
+}
+
+ast_struct! {
+ /// A visibility level restricted to some path: `pub(self)` or
+ /// `pub(super)` or `pub(crate)` or `pub(in some::module)`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct VisRestricted {
+ pub pub_token: Token![pub],
+ pub paren_token: token::Paren,
+ pub in_token: Option<Token![in]>,
+ pub path: Box<Path>,
+ }
+}
+
+ast_enum! {
+ /// Unused, but reserved for RFC 3323 restrictions.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ #[non_exhaustive]
+ pub enum FieldMutability {
+ None,
+
+ // TODO: https://rust-lang.github.io/rfcs/3323-restrictions.html
+ //
+ // FieldMutability::Restricted(MutRestricted)
+ //
+ // pub struct MutRestricted {
+ // pub mut_token: Token![mut],
+ // pub paren_token: token::Paren,
+ // pub in_token: Option<Token![in]>,
+ // pub path: Box<Path>,
+ // }
+ }
+}
+
+#[cfg(feature = "parsing")]
+pub(crate) mod parsing {
+ use crate::error::Result;
+ use crate::ext::IdentExt as _;
+ use crate::ident::Ident;
+ use crate::parse::discouraged::Speculative as _;
+ use crate::parse::{Parse, ParseStream};
+ use crate::path::Path;
+ use crate::restriction::{VisRestricted, Visibility};
+ use crate::token;
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for Visibility {
+ fn parse(input: ParseStream) -> Result<Self> {
+ // Recognize an empty None-delimited group, as produced by a $:vis
+ // matcher that matched no tokens.
+ if input.peek(token::Group) {
+ let ahead = input.fork();
+ let group = crate::group::parse_group(&ahead)?;
+ if group.content.is_empty() {
+ input.advance_to(&ahead);
+ return Ok(Visibility::Inherited);
+ }
+ }
+
+ if input.peek(Token![pub]) {
+ Self::parse_pub(input)
+ } else {
+ Ok(Visibility::Inherited)
+ }
+ }
+ }
+
+ impl Visibility {
+ fn parse_pub(input: ParseStream) -> Result<Self> {
+ let pub_token = input.parse::<Token![pub]>()?;
+
+ if input.peek(token::Paren) {
+ let ahead = input.fork();
+
+ let content;
+ let paren_token = parenthesized!(content in ahead);
+ if content.peek(Token![crate])
+ || content.peek(Token![self])
+ || content.peek(Token![super])
+ {
+ let path = content.call(Ident::parse_any)?;
+
+ // Ensure there are no additional tokens within `content`.
+ // Without explicitly checking, we may misinterpret a tuple
+ // field as a restricted visibility, causing a parse error.
+ // e.g. `pub (crate::A, crate::B)` (Issue #720).
+ if content.is_empty() {
+ input.advance_to(&ahead);
+ return Ok(Visibility::Restricted(VisRestricted {
+ pub_token,
+ paren_token,
+ in_token: None,
+ path: Box::new(Path::from(path)),
+ }));
+ }
+ } else if content.peek(Token![in]) {
+ let in_token: Token![in] = content.parse()?;
+ let path = content.call(Path::parse_mod_style)?;
+
+ input.advance_to(&ahead);
+ return Ok(Visibility::Restricted(VisRestricted {
+ pub_token,
+ paren_token,
+ in_token: Some(in_token),
+ path: Box::new(path),
+ }));
+ }
+ }
+
+ Ok(Visibility::Public(pub_token))
+ }
+
+ #[cfg(feature = "full")]
+ pub(crate) fn is_some(&self) -> bool {
+ match self {
+ Visibility::Inherited => false,
+ _ => true,
+ }
+ }
+ }
+}
+
+#[cfg(feature = "printing")]
+mod printing {
+ use crate::path;
+ use crate::path::printing::PathStyle;
+ use crate::restriction::{VisRestricted, Visibility};
+ use proc_macro2::TokenStream;
+ use quote::ToTokens;
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for Visibility {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ match self {
+ Visibility::Public(pub_token) => pub_token.to_tokens(tokens),
+ Visibility::Restricted(vis_restricted) => vis_restricted.to_tokens(tokens),
+ Visibility::Inherited => {}
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for VisRestricted {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.pub_token.to_tokens(tokens);
+ self.paren_token.surround(tokens, |tokens| {
+ // TODO: If we have a path which is not "self" or "super" or
+ // "crate", automatically add the "in" token.
+ self.in_token.to_tokens(tokens);
+ path::printing::print_path(tokens, &self.path, PathStyle::Mod);
+ });
+ }
+ }
+}
diff --git a/rust/syn/scan_expr.rs b/rust/syn/scan_expr.rs
new file mode 100644
index 000000000000..3d88cf06acea
--- /dev/null
+++ b/rust/syn/scan_expr.rs
@@ -0,0 +1,265 @@
+use self::{Action::*, Input::*};
+use proc_macro2::{Delimiter, Ident, Spacing, TokenTree};
+use syn::parse::{ParseStream, Result};
+use syn::{AngleBracketedGenericArguments, BinOp, Expr, ExprPath, Lifetime, Lit, Token, Type};
+
+enum Input {
+ Keyword(&'static str),
+ Punct(&'static str),
+ ConsumeAny,
+ ConsumeBinOp,
+ ConsumeBrace,
+ ConsumeDelimiter,
+ ConsumeIdent,
+ ConsumeLifetime,
+ ConsumeLiteral,
+ ConsumeNestedBrace,
+ ExpectPath,
+ ExpectTurbofish,
+ ExpectType,
+ CanBeginExpr,
+ Otherwise,
+ Empty,
+}
+
+enum Action {
+ SetState(&'static [(Input, Action)]),
+ IncDepth,
+ DecDepth,
+ Finish,
+}
+
+static INIT: [(Input, Action); 28] = [
+ (ConsumeDelimiter, SetState(&POSTFIX)),
+ (Keyword("async"), SetState(&ASYNC)),
+ (Keyword("break"), SetState(&BREAK_LABEL)),
+ (Keyword("const"), SetState(&CONST)),
+ (Keyword("continue"), SetState(&CONTINUE)),
+ (Keyword("for"), SetState(&FOR)),
+ (Keyword("if"), IncDepth),
+ (Keyword("let"), SetState(&PATTERN)),
+ (Keyword("loop"), SetState(&BLOCK)),
+ (Keyword("match"), IncDepth),
+ (Keyword("move"), SetState(&CLOSURE)),
+ (Keyword("return"), SetState(&RETURN)),
+ (Keyword("static"), SetState(&CLOSURE)),
+ (Keyword("unsafe"), SetState(&BLOCK)),
+ (Keyword("while"), IncDepth),
+ (Keyword("yield"), SetState(&RETURN)),
+ (Keyword("_"), SetState(&POSTFIX)),
+ (Punct("!"), SetState(&INIT)),
+ (Punct("#"), SetState(&[(ConsumeDelimiter, SetState(&INIT))])),
+ (Punct("&"), SetState(&REFERENCE)),
+ (Punct("*"), SetState(&INIT)),
+ (Punct("-"), SetState(&INIT)),
+ (Punct("..="), SetState(&INIT)),
+ (Punct(".."), SetState(&RANGE)),
+ (Punct("|"), SetState(&CLOSURE_ARGS)),
+ (ConsumeLifetime, SetState(&[(Punct(":"), SetState(&INIT))])),
+ (ConsumeLiteral, SetState(&POSTFIX)),
+ (ExpectPath, SetState(&PATH)),
+];
+
+static POSTFIX: [(Input, Action); 10] = [
+ (Keyword("as"), SetState(&[(ExpectType, SetState(&POSTFIX))])),
+ (Punct("..="), SetState(&INIT)),
+ (Punct(".."), SetState(&RANGE)),
+ (Punct("."), SetState(&DOT)),
+ (Punct("?"), SetState(&POSTFIX)),
+ (ConsumeBinOp, SetState(&INIT)),
+ (Punct("="), SetState(&INIT)),
+ (ConsumeNestedBrace, SetState(&IF_THEN)),
+ (ConsumeDelimiter, SetState(&POSTFIX)),
+ (Empty, Finish),
+];
+
+static ASYNC: [(Input, Action); 3] = [
+ (Keyword("move"), SetState(&ASYNC)),
+ (Punct("|"), SetState(&CLOSURE_ARGS)),
+ (ConsumeBrace, SetState(&POSTFIX)),
+];
+
+static BLOCK: [(Input, Action); 1] = [(ConsumeBrace, SetState(&POSTFIX))];
+
+static BREAK_LABEL: [(Input, Action); 2] = [
+ (ConsumeLifetime, SetState(&BREAK_VALUE)),
+ (Otherwise, SetState(&BREAK_VALUE)),
+];
+
+static BREAK_VALUE: [(Input, Action); 3] = [
+ (ConsumeNestedBrace, SetState(&IF_THEN)),
+ (CanBeginExpr, SetState(&INIT)),
+ (Otherwise, SetState(&POSTFIX)),
+];
+
+static CLOSURE: [(Input, Action); 7] = [
+ (Keyword("async"), SetState(&CLOSURE)),
+ (Keyword("move"), SetState(&CLOSURE)),
+ (Punct(","), SetState(&CLOSURE)),
+ (Punct(">"), SetState(&CLOSURE)),
+ (Punct("|"), SetState(&CLOSURE_ARGS)),
+ (ConsumeLifetime, SetState(&CLOSURE)),
+ (ConsumeIdent, SetState(&CLOSURE)),
+];
+
+static CLOSURE_ARGS: [(Input, Action); 2] = [
+ (Punct("|"), SetState(&CLOSURE_RET)),
+ (ConsumeAny, SetState(&CLOSURE_ARGS)),
+];
+
+static CLOSURE_RET: [(Input, Action); 2] = [
+ (Punct("->"), SetState(&[(ExpectType, SetState(&BLOCK))])),
+ (Otherwise, SetState(&INIT)),
+];
+
+static CONST: [(Input, Action); 2] = [
+ (Punct("|"), SetState(&CLOSURE_ARGS)),
+ (ConsumeBrace, SetState(&POSTFIX)),
+];
+
+static CONTINUE: [(Input, Action); 2] = [
+ (ConsumeLifetime, SetState(&POSTFIX)),
+ (Otherwise, SetState(&POSTFIX)),
+];
+
+static DOT: [(Input, Action); 3] = [
+ (Keyword("await"), SetState(&POSTFIX)),
+ (ConsumeIdent, SetState(&METHOD)),
+ (ConsumeLiteral, SetState(&POSTFIX)),
+];
+
+static FOR: [(Input, Action); 2] = [
+ (Punct("<"), SetState(&CLOSURE)),
+ (Otherwise, SetState(&PATTERN)),
+];
+
+static IF_ELSE: [(Input, Action); 2] = [(Keyword("if"), SetState(&INIT)), (ConsumeBrace, DecDepth)];
+static IF_THEN: [(Input, Action); 2] =
+ [(Keyword("else"), SetState(&IF_ELSE)), (Otherwise, DecDepth)];
+
+static METHOD: [(Input, Action); 1] = [(ExpectTurbofish, SetState(&POSTFIX))];
+
+static PATH: [(Input, Action); 4] = [
+ (Punct("!="), SetState(&INIT)),
+ (Punct("!"), SetState(&INIT)),
+ (ConsumeNestedBrace, SetState(&IF_THEN)),
+ (Otherwise, SetState(&POSTFIX)),
+];
+
+static PATTERN: [(Input, Action); 15] = [
+ (ConsumeDelimiter, SetState(&PATTERN)),
+ (Keyword("box"), SetState(&PATTERN)),
+ (Keyword("in"), IncDepth),
+ (Keyword("mut"), SetState(&PATTERN)),
+ (Keyword("ref"), SetState(&PATTERN)),
+ (Keyword("_"), SetState(&PATTERN)),
+ (Punct("!"), SetState(&PATTERN)),
+ (Punct("&"), SetState(&PATTERN)),
+ (Punct("..="), SetState(&PATTERN)),
+ (Punct(".."), SetState(&PATTERN)),
+ (Punct("="), SetState(&INIT)),
+ (Punct("@"), SetState(&PATTERN)),
+ (Punct("|"), SetState(&PATTERN)),
+ (ConsumeLiteral, SetState(&PATTERN)),
+ (ExpectPath, SetState(&PATTERN)),
+];
+
+static RANGE: [(Input, Action); 6] = [
+ (Punct("..="), SetState(&INIT)),
+ (Punct(".."), SetState(&RANGE)),
+ (Punct("."), SetState(&DOT)),
+ (ConsumeNestedBrace, SetState(&IF_THEN)),
+ (Empty, Finish),
+ (Otherwise, SetState(&INIT)),
+];
+
+static RAW: [(Input, Action); 3] = [
+ (Keyword("const"), SetState(&INIT)),
+ (Keyword("mut"), SetState(&INIT)),
+ (Otherwise, SetState(&POSTFIX)),
+];
+
+static REFERENCE: [(Input, Action); 3] = [
+ (Keyword("mut"), SetState(&INIT)),
+ (Keyword("raw"), SetState(&RAW)),
+ (Otherwise, SetState(&INIT)),
+];
+
+static RETURN: [(Input, Action); 2] = [
+ (CanBeginExpr, SetState(&INIT)),
+ (Otherwise, SetState(&POSTFIX)),
+];
+
+pub(crate) fn scan_expr(input: ParseStream) -> Result<()> {
+ let mut state = INIT.as_slice();
+ let mut depth = 0usize;
+ 'table: loop {
+ for rule in state {
+ if match rule.0 {
+ Input::Keyword(expected) => input.step(|cursor| match cursor.ident() {
+ Some((ident, rest)) if ident == expected => Ok((true, rest)),
+ _ => Ok((false, *cursor)),
+ })?,
+ Input::Punct(expected) => input.step(|cursor| {
+ let begin = *cursor;
+ let mut cursor = begin;
+ for (i, ch) in expected.chars().enumerate() {
+ match cursor.punct() {
+ Some((punct, _)) if punct.as_char() != ch => break,
+ Some((_, rest)) if i == expected.len() - 1 => {
+ return Ok((true, rest));
+ }
+ Some((punct, rest)) if punct.spacing() == Spacing::Joint => {
+ cursor = rest;
+ }
+ _ => break,
+ }
+ }
+ Ok((false, begin))
+ })?,
+ Input::ConsumeAny => input.parse::<Option<TokenTree>>()?.is_some(),
+ Input::ConsumeBinOp => input.parse::<BinOp>().is_ok(),
+ Input::ConsumeBrace | Input::ConsumeNestedBrace => {
+ (matches!(rule.0, Input::ConsumeBrace) || depth > 0)
+ && input.step(|cursor| match cursor.group(Delimiter::Brace) {
+ Some((_inside, _span, rest)) => Ok((true, rest)),
+ None => Ok((false, *cursor)),
+ })?
+ }
+ Input::ConsumeDelimiter => input.step(|cursor| match cursor.any_group() {
+ Some((_inside, _delimiter, _span, rest)) => Ok((true, rest)),
+ None => Ok((false, *cursor)),
+ })?,
+ Input::ConsumeIdent => input.parse::<Option<Ident>>()?.is_some(),
+ Input::ConsumeLifetime => input.parse::<Option<Lifetime>>()?.is_some(),
+ Input::ConsumeLiteral => input.parse::<Option<Lit>>()?.is_some(),
+ Input::ExpectPath => {
+ input.parse::<ExprPath>()?;
+ true
+ }
+ Input::ExpectTurbofish => {
+ if input.peek(Token![::]) {
+ input.parse::<AngleBracketedGenericArguments>()?;
+ }
+ true
+ }
+ Input::ExpectType => {
+ Type::without_plus(input)?;
+ true
+ }
+ Input::CanBeginExpr => Expr::peek(input),
+ Input::Otherwise => true,
+ Input::Empty => input.is_empty() || input.peek(Token![,]),
+ } {
+ state = match rule.1 {
+ Action::SetState(next) => next,
+ Action::IncDepth => (depth += 1, &INIT).1,
+ Action::DecDepth => (depth -= 1, &POSTFIX).1,
+ Action::Finish => return if depth == 0 { Ok(()) } else { break },
+ };
+ continue 'table;
+ }
+ }
+ return Err(input.error("unsupported expression"));
+ }
+}
diff --git a/rust/syn/sealed.rs b/rust/syn/sealed.rs
new file mode 100644
index 000000000000..dc804742d12d
--- /dev/null
+++ b/rust/syn/sealed.rs
@@ -0,0 +1,4 @@
+#[cfg(feature = "parsing")]
+pub(crate) mod lookahead {
+ pub trait Sealed: Copy {}
+}
diff --git a/rust/syn/span.rs b/rust/syn/span.rs
new file mode 100644
index 000000000000..eb2779479aaa
--- /dev/null
+++ b/rust/syn/span.rs
@@ -0,0 +1,63 @@
+use proc_macro2::extra::DelimSpan;
+use proc_macro2::{Delimiter, Group, Span, TokenStream};
+
+#[doc(hidden)]
+pub trait IntoSpans<S> {
+ fn into_spans(self) -> S;
+}
+
+impl IntoSpans<Span> for Span {
+ fn into_spans(self) -> Span {
+ self
+ }
+}
+
+impl IntoSpans<[Span; 1]> for Span {
+ fn into_spans(self) -> [Span; 1] {
+ [self]
+ }
+}
+
+impl IntoSpans<[Span; 2]> for Span {
+ fn into_spans(self) -> [Span; 2] {
+ [self, self]
+ }
+}
+
+impl IntoSpans<[Span; 3]> for Span {
+ fn into_spans(self) -> [Span; 3] {
+ [self, self, self]
+ }
+}
+
+impl IntoSpans<[Span; 1]> for [Span; 1] {
+ fn into_spans(self) -> [Span; 1] {
+ self
+ }
+}
+
+impl IntoSpans<[Span; 2]> for [Span; 2] {
+ fn into_spans(self) -> [Span; 2] {
+ self
+ }
+}
+
+impl IntoSpans<[Span; 3]> for [Span; 3] {
+ fn into_spans(self) -> [Span; 3] {
+ self
+ }
+}
+
+impl IntoSpans<DelimSpan> for Span {
+ fn into_spans(self) -> DelimSpan {
+ let mut group = Group::new(Delimiter::None, TokenStream::new());
+ group.set_span(self);
+ group.delim_span()
+ }
+}
+
+impl IntoSpans<DelimSpan> for DelimSpan {
+ fn into_spans(self) -> DelimSpan {
+ self
+ }
+}
diff --git a/rust/syn/spanned.rs b/rust/syn/spanned.rs
new file mode 100644
index 000000000000..17b69e9f5b28
--- /dev/null
+++ b/rust/syn/spanned.rs
@@ -0,0 +1,118 @@
+//! A trait that can provide the `Span` of the complete contents of a syntax
+//! tree node.
+//!
+//! <br>
+//!
+//! # Example
+//!
+//! Suppose in a procedural macro we have a [`Type`] that we want to assert
+//! implements the [`Sync`] trait. Maybe this is the type of one of the fields
+//! of a struct for which we are deriving a trait implementation, and we need to
+//! be able to pass a reference to one of those fields across threads.
+//!
+//! [`Type`]: crate::Type
+//! [`Sync`]: std::marker::Sync
+//!
+//! If the field type does *not* implement `Sync` as required, we want the
+//! compiler to report an error pointing out exactly which type it was.
+//!
+//! The following macro code takes a variable `ty` of type `Type` and produces a
+//! static assertion that `Sync` is implemented for that type.
+//!
+//! ```
+//! # extern crate proc_macro;
+//! #
+//! use proc_macro::TokenStream;
+//! use proc_macro2::Span;
+//! use quote::quote_spanned;
+//! use syn::Type;
+//! use syn::spanned::Spanned;
+//!
+//! # const IGNORE_TOKENS: &str = stringify! {
+//! #[proc_macro_derive(MyMacro)]
+//! # };
+//! pub fn my_macro(input: TokenStream) -> TokenStream {
+//! # let ty = get_a_type();
+//! /* ... */
+//!
+//! let assert_sync = quote_spanned! {ty.span()=>
+//! struct _AssertSync where #ty: Sync;
+//! };
+//!
+//! /* ... */
+//! # input
+//! }
+//! #
+//! # fn get_a_type() -> Type {
+//! # unimplemented!()
+//! # }
+//! ```
+//!
+//! By inserting this `assert_sync` fragment into the output code generated by
+//! our macro, the user's code will fail to compile if `ty` does not implement
+//! `Sync`. The errors they would see look like the following.
+//!
+//! ```text
+//! error[E0277]: the trait bound `*const i32: std::marker::Sync` is not satisfied
+//! --> src/main.rs:10:21
+//! |
+//! 10 | bad_field: *const i32,
+//! | ^^^^^^^^^^ `*const i32` cannot be shared between threads safely
+//! ```
+//!
+//! In this technique, using the `Type`'s span for the error message makes the
+//! error appear in the correct place underlining the right type.
+//!
+//! <br>
+//!
+//! # Limitations
+//!
+//! The underlying [`proc_macro::Span::join`] method is nightly-only. When
+//! called from within a procedural macro in a nightly compiler, `Spanned` will
+//! use `join` to produce the intended span. When not using a nightly compiler,
+//! only the span of the *first token* of the syntax tree node is returned.
+//!
+//! In the common case of wanting to use the joined span as the span of a
+//! `syn::Error`, consider instead using [`syn::Error::new_spanned`] which is
+//! able to span the error correctly under the complete syntax tree node without
+//! needing the unstable `join`.
+//!
+//! [`syn::Error::new_spanned`]: crate::Error::new_spanned
+
+use proc_macro2::Span;
+use quote::spanned::Spanned as ToTokens;
+
+/// A trait that can provide the `Span` of the complete contents of a syntax
+/// tree node.
+///
+/// This trait is automatically implemented for all types that implement
+/// [`ToTokens`] from the `quote` crate, as well as for `Span` itself.
+///
+/// [`ToTokens`]: quote::ToTokens
+///
+/// See the [module documentation] for an example.
+///
+/// [module documentation]: self
+pub trait Spanned: private::Sealed {
+ /// Returns a `Span` covering the complete contents of this syntax tree
+ /// node, or [`Span::call_site()`] if this node is empty.
+ ///
+ /// [`Span::call_site()`]: proc_macro2::Span::call_site
+ fn span(&self) -> Span;
+}
+
+impl<T: ?Sized + ToTokens> Spanned for T {
+ fn span(&self) -> Span {
+ self.__span()
+ }
+}
+
+mod private {
+ use crate::spanned::ToTokens;
+
+ pub trait Sealed {}
+ impl<T: ?Sized + ToTokens> Sealed for T {}
+
+ #[cfg(any(feature = "full", feature = "derive"))]
+ impl Sealed for crate::QSelf {}
+}
diff --git a/rust/syn/stmt.rs b/rust/syn/stmt.rs
new file mode 100644
index 000000000000..8ea0077f63df
--- /dev/null
+++ b/rust/syn/stmt.rs
@@ -0,0 +1,484 @@
+use crate::attr::Attribute;
+use crate::expr::Expr;
+use crate::item::Item;
+use crate::mac::Macro;
+use crate::pat::Pat;
+use crate::token;
+
+ast_struct! {
+ /// A braced block containing Rust statements.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct Block {
+ pub brace_token: token::Brace,
+ /// Statements in a block
+ pub stmts: Vec<Stmt>,
+ }
+}
+
+ast_enum! {
+ /// A statement, usually ending in a semicolon.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub enum Stmt {
+ /// A local (let) binding.
+ Local(Local),
+
+ /// An item definition.
+ Item(Item),
+
+ /// Expression, with or without trailing semicolon.
+ Expr(Expr, Option<Token![;]>),
+
+ /// A macro invocation in statement position.
+ ///
+ /// Syntactically it's ambiguous which other kind of statement this
+ /// macro would expand to. It can be any of local variable (`let`),
+ /// item, or expression.
+ Macro(StmtMacro),
+ }
+}
+
+ast_struct! {
+ /// A local `let` binding: `let x: u64 = s.parse()?;`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct Local {
+ pub attrs: Vec<Attribute>,
+ pub let_token: Token![let],
+ pub pat: Pat,
+ pub init: Option<LocalInit>,
+ pub semi_token: Token![;],
+ }
+}
+
+ast_struct! {
+ /// The expression assigned in a local `let` binding, including optional
+ /// diverging `else` block.
+ ///
+ /// `LocalInit` represents `= s.parse()?` in `let x: u64 = s.parse()?` and
+ /// `= r else { return }` in `let Ok(x) = r else { return }`.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct LocalInit {
+ pub eq_token: Token![=],
+ pub expr: Box<Expr>,
+ pub diverge: Option<(Token![else], Box<Expr>)>,
+ }
+}
+
+ast_struct! {
+ /// A macro invocation in statement position.
+ ///
+ /// Syntactically it's ambiguous which other kind of statement this macro
+ /// would expand to. It can be any of local variable (`let`), item, or
+ /// expression.
+ #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
+ pub struct StmtMacro {
+ pub attrs: Vec<Attribute>,
+ pub mac: Macro,
+ pub semi_token: Option<Token![;]>,
+ }
+}
+
+#[cfg(feature = "parsing")]
+pub(crate) mod parsing {
+ use crate::attr::Attribute;
+ use crate::classify;
+ use crate::error::Result;
+ use crate::expr::{Expr, ExprBlock, ExprMacro};
+ use crate::ident::Ident;
+ use crate::item;
+ use crate::mac::{self, Macro};
+ use crate::parse::discouraged::Speculative as _;
+ use crate::parse::{Parse, ParseStream};
+ use crate::pat::{Pat, PatType};
+ use crate::path::Path;
+ use crate::stmt::{Block, Local, LocalInit, Stmt, StmtMacro};
+ use crate::token;
+ use crate::ty::Type;
+ use proc_macro2::TokenStream;
+
+ struct AllowNoSemi(bool);
+
+ impl Block {
+ /// Parse the body of a block as zero or more statements, possibly
+ /// including one trailing expression.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use syn::{braced, token, Attribute, Block, Ident, Result, Stmt, Token};
+ /// use syn::parse::{Parse, ParseStream};
+ ///
+ /// // Parse a function with no generics or parameter list.
+ /// //
+ /// // fn playground {
+ /// // let mut x = 1;
+ /// // x += 1;
+ /// // println!("{}", x);
+ /// // }
+ /// struct MiniFunction {
+ /// attrs: Vec<Attribute>,
+ /// fn_token: Token![fn],
+ /// name: Ident,
+ /// brace_token: token::Brace,
+ /// stmts: Vec<Stmt>,
+ /// }
+ ///
+ /// impl Parse for MiniFunction {
+ /// fn parse(input: ParseStream) -> Result<Self> {
+ /// let outer_attrs = input.call(Attribute::parse_outer)?;
+ /// let fn_token: Token![fn] = input.parse()?;
+ /// let name: Ident = input.parse()?;
+ ///
+ /// let content;
+ /// let brace_token = braced!(content in input);
+ /// let inner_attrs = content.call(Attribute::parse_inner)?;
+ /// let stmts = content.call(Block::parse_within)?;
+ ///
+ /// Ok(MiniFunction {
+ /// attrs: {
+ /// let mut attrs = outer_attrs;
+ /// attrs.extend(inner_attrs);
+ /// attrs
+ /// },
+ /// fn_token,
+ /// name,
+ /// brace_token,
+ /// stmts,
+ /// })
+ /// }
+ /// }
+ /// ```
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ pub fn parse_within(input: ParseStream) -> Result<Vec<Stmt>> {
+ let mut stmts = Vec::new();
+ loop {
+ while let semi @ Some(_) = input.parse()? {
+ stmts.push(Stmt::Expr(Expr::Verbatim(TokenStream::new()), semi));
+ }
+ if input.is_empty() {
+ break;
+ }
+ let stmt = parse_stmt(input, AllowNoSemi(true))?;
+ let requires_semicolon = match &stmt {
+ Stmt::Expr(stmt, None) => classify::requires_semi_to_be_stmt(stmt),
+ Stmt::Macro(stmt) => {
+ stmt.semi_token.is_none() && !stmt.mac.delimiter.is_brace()
+ }
+ Stmt::Local(_) | Stmt::Item(_) | Stmt::Expr(_, Some(_)) => false,
+ };
+ stmts.push(stmt);
+ if input.is_empty() {
+ break;
+ } else if requires_semicolon {
+ return Err(input.error("unexpected token, expected `;`"));
+ }
+ }
+ Ok(stmts)
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for Block {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let content;
+ Ok(Block {
+ brace_token: braced!(content in input),
+ stmts: content.call(Block::parse_within)?,
+ })
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for Stmt {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let allow_nosemi = AllowNoSemi(false);
+ parse_stmt(input, allow_nosemi)
+ }
+ }
+
+ fn parse_stmt(input: ParseStream, allow_nosemi: AllowNoSemi) -> Result<Stmt> {
+ let begin = input.fork();
+ let attrs = input.call(Attribute::parse_outer)?;
+
+ // brace-style macros; paren and bracket macros get parsed as
+ // expression statements.
+ let ahead = input.fork();
+ let mut is_item_macro = false;
+ if let Ok(path) = ahead.call(Path::parse_mod_style) {
+ if ahead.peek(Token![!]) {
+ if ahead.peek2(Ident) || ahead.peek2(Token![try]) {
+ is_item_macro = true;
+ } else if ahead.peek2(token::Brace)
+ && !(ahead.peek3(Token![.]) && !ahead.peek3(Token![..])
+ || ahead.peek3(Token![?]))
+ {
+ input.advance_to(&ahead);
+ return stmt_mac(input, attrs, path).map(Stmt::Macro);
+ }
+ }
+ }
+
+ if input.peek(Token![let]) && !input.peek(token::Group) {
+ stmt_local(input, attrs).map(Stmt::Local)
+ } else if input.peek(Token![pub])
+ || input.peek(Token![crate]) && !input.peek2(Token![::])
+ || input.peek(Token![extern])
+ || input.peek(Token![use])
+ || input.peek(Token![static])
+ && (input.peek2(Token![mut])
+ || input.peek2(Ident)
+ && !(input.peek2(Token![async])
+ && (input.peek3(Token![move]) || input.peek3(Token![|]))))
+ || input.peek(Token![const])
+ && !(input.peek2(token::Brace)
+ || input.peek2(Token![static])
+ || input.peek2(Token![async])
+ && !(input.peek3(Token![unsafe])
+ || input.peek3(Token![extern])
+ || input.peek3(Token![fn]))
+ || input.peek2(Token![move])
+ || input.peek2(Token![|]))
+ || input.peek(Token![unsafe]) && !input.peek2(token::Brace)
+ || input.peek(Token![async])
+ && (input.peek2(Token![unsafe])
+ || input.peek2(Token![extern])
+ || input.peek2(Token![fn]))
+ || input.peek(Token![fn])
+ || input.peek(Token![mod])
+ || input.peek(Token![type])
+ || input.peek(Token![struct])
+ || input.peek(Token![enum])
+ || input.peek(Token![union]) && input.peek2(Ident)
+ || input.peek(Token![auto]) && input.peek2(Token![trait])
+ || input.peek(Token![trait])
+ || input.peek(Token![default])
+ && (input.peek2(Token![unsafe]) || input.peek2(Token![impl]))
+ || input.peek(Token![impl])
+ || input.peek(Token![macro])
+ || is_item_macro
+ {
+ let item = item::parsing::parse_rest_of_item(begin, attrs, input)?;
+ Ok(Stmt::Item(item))
+ } else {
+ stmt_expr(input, allow_nosemi, attrs)
+ }
+ }
+
+ fn stmt_mac(input: ParseStream, attrs: Vec<Attribute>, path: Path) -> Result<StmtMacro> {
+ let bang_token: Token![!] = input.parse()?;
+ let (delimiter, tokens) = mac::parse_delimiter(input)?;
+ let semi_token: Option<Token![;]> = input.parse()?;
+
+ Ok(StmtMacro {
+ attrs,
+ mac: Macro {
+ path,
+ bang_token,
+ delimiter,
+ tokens,
+ },
+ semi_token,
+ })
+ }
+
+ fn stmt_local(input: ParseStream, attrs: Vec<Attribute>) -> Result<Local> {
+ let let_token: Token![let] = input.parse()?;
+
+ let mut pat = Pat::parse_single(input)?;
+ if input.peek(Token![:]) {
+ let colon_token: Token![:] = input.parse()?;
+ let ty: Type = input.parse()?;
+ pat = Pat::Type(PatType {
+ attrs: Vec::new(),
+ pat: Box::new(pat),
+ colon_token,
+ ty: Box::new(ty),
+ });
+ }
+
+ let init = if let Some(eq_token) = input.parse()? {
+ let eq_token: Token![=] = eq_token;
+ let expr: Expr = input.parse()?;
+
+ let diverge = if !classify::expr_trailing_brace(&expr) && input.peek(Token![else]) {
+ let else_token: Token![else] = input.parse()?;
+ let diverge = ExprBlock {
+ attrs: Vec::new(),
+ label: None,
+ block: input.parse()?,
+ };
+ Some((else_token, Box::new(Expr::Block(diverge))))
+ } else {
+ None
+ };
+
+ Some(LocalInit {
+ eq_token,
+ expr: Box::new(expr),
+ diverge,
+ })
+ } else {
+ None
+ };
+
+ let semi_token: Token![;] = input.parse()?;
+
+ Ok(Local {
+ attrs,
+ let_token,
+ pat,
+ init,
+ semi_token,
+ })
+ }
+
+ fn stmt_expr(
+ input: ParseStream,
+ allow_nosemi: AllowNoSemi,
+ mut attrs: Vec<Attribute>,
+ ) -> Result<Stmt> {
+ let mut e = Expr::parse_with_earlier_boundary_rule(input)?;
+
+ let mut attr_target = &mut e;
+ loop {
+ attr_target = match attr_target {
+ Expr::Assign(e) => &mut e.left,
+ Expr::Binary(e) => &mut e.left,
+ Expr::Cast(e) => &mut e.expr,
+ Expr::Array(_)
+ | Expr::Async(_)
+ | Expr::Await(_)
+ | Expr::Block(_)
+ | Expr::Break(_)
+ | Expr::Call(_)
+ | Expr::Closure(_)
+ | Expr::Const(_)
+ | Expr::Continue(_)
+ | Expr::Field(_)
+ | Expr::ForLoop(_)
+ | Expr::Group(_)
+ | Expr::If(_)
+ | Expr::Index(_)
+ | Expr::Infer(_)
+ | Expr::Let(_)
+ | Expr::Lit(_)
+ | Expr::Loop(_)
+ | Expr::Macro(_)
+ | Expr::Match(_)
+ | Expr::MethodCall(_)
+ | Expr::Paren(_)
+ | Expr::Path(_)
+ | Expr::Range(_)
+ | Expr::RawAddr(_)
+ | Expr::Reference(_)
+ | Expr::Repeat(_)
+ | Expr::Return(_)
+ | Expr::Struct(_)
+ | Expr::Try(_)
+ | Expr::TryBlock(_)
+ | Expr::Tuple(_)
+ | Expr::Unary(_)
+ | Expr::Unsafe(_)
+ | Expr::While(_)
+ | Expr::Yield(_)
+ | Expr::Verbatim(_) => break,
+ };
+ }
+ attrs.extend(attr_target.replace_attrs(Vec::new()));
+ attr_target.replace_attrs(attrs);
+
+ let semi_token: Option<Token![;]> = input.parse()?;
+
+ match e {
+ Expr::Macro(ExprMacro { attrs, mac })
+ if semi_token.is_some() || mac.delimiter.is_brace() =>
+ {
+ return Ok(Stmt::Macro(StmtMacro {
+ attrs,
+ mac,
+ semi_token,
+ }));
+ }
+ _ => {}
+ }
+
+ if semi_token.is_some() {
+ Ok(Stmt::Expr(e, semi_token))
+ } else if allow_nosemi.0 || !classify::requires_semi_to_be_stmt(&e) {
+ Ok(Stmt::Expr(e, None))
+ } else {
+ Err(input.error("expected semicolon"))
+ }
+ }
+}
+
+#[cfg(feature = "printing")]
+pub(crate) mod printing {
+ use crate::classify;
+ use crate::expr::{self, Expr};
+ use crate::fixup::FixupContext;
+ use crate::stmt::{Block, Local, Stmt, StmtMacro};
+ use crate::token;
+ use proc_macro2::TokenStream;
+ use quote::{ToTokens, TokenStreamExt};
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for Block {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.brace_token.surround(tokens, |tokens| {
+ tokens.append_all(&self.stmts);
+ });
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for Stmt {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ match self {
+ Stmt::Local(local) => local.to_tokens(tokens),
+ Stmt::Item(item) => item.to_tokens(tokens),
+ Stmt::Expr(expr, semi) => {
+ expr::printing::print_expr(expr, tokens, FixupContext::new_stmt());
+ semi.to_tokens(tokens);
+ }
+ Stmt::Macro(mac) => mac.to_tokens(tokens),
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for Local {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ expr::printing::outer_attrs_to_tokens(&self.attrs, tokens);
+ self.let_token.to_tokens(tokens);
+ self.pat.to_tokens(tokens);
+ if let Some(init) = &self.init {
+ init.eq_token.to_tokens(tokens);
+ expr::printing::print_subexpression(
+ &init.expr,
+ init.diverge.is_some() && classify::expr_trailing_brace(&init.expr),
+ tokens,
+ FixupContext::NONE,
+ );
+ if let Some((else_token, diverge)) = &init.diverge {
+ else_token.to_tokens(tokens);
+ match &**diverge {
+ Expr::Block(diverge) => diverge.to_tokens(tokens),
+ _ => token::Brace::default().surround(tokens, |tokens| {
+ expr::printing::print_expr(diverge, tokens, FixupContext::new_stmt());
+ }),
+ }
+ }
+ }
+ self.semi_token.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for StmtMacro {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ expr::printing::outer_attrs_to_tokens(&self.attrs, tokens);
+ self.mac.to_tokens(tokens);
+ self.semi_token.to_tokens(tokens);
+ }
+ }
+}
diff --git a/rust/syn/thread.rs b/rust/syn/thread.rs
new file mode 100644
index 000000000000..b33d248afc60
--- /dev/null
+++ b/rust/syn/thread.rs
@@ -0,0 +1,60 @@
+use std::fmt::{self, Debug};
+use std::thread::{self, ThreadId};
+
+/// ThreadBound is a Sync-maker and Send-maker that allows accessing a value
+/// of type T only from the original thread on which the ThreadBound was
+/// constructed.
+pub(crate) struct ThreadBound<T> {
+ value: T,
+ thread_id: ThreadId,
+}
+
+unsafe impl<T> Sync for ThreadBound<T> {}
+
+// Send bound requires Copy, as otherwise Drop could run in the wrong place.
+//
+// Today Copy and Drop are mutually exclusive so `T: Copy` implies `T: !Drop`.
+// This impl needs to be revisited if that restriction is relaxed in the future.
+unsafe impl<T: Copy> Send for ThreadBound<T> {}
+
+impl<T> ThreadBound<T> {
+ pub(crate) fn new(value: T) -> Self {
+ ThreadBound {
+ value,
+ thread_id: thread::current().id(),
+ }
+ }
+
+ pub(crate) fn get(&self) -> Option<&T> {
+ if thread::current().id() == self.thread_id {
+ Some(&self.value)
+ } else {
+ None
+ }
+ }
+}
+
+impl<T: Debug> Debug for ThreadBound<T> {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ match self.get() {
+ Some(value) => Debug::fmt(value, formatter),
+ None => formatter.write_str("unknown"),
+ }
+ }
+}
+
+// Copy the bytes of T, even if the currently running thread is the "wrong"
+// thread. This is fine as long as the original thread is not simultaneously
+// mutating this value via interior mutability, which would be a data race.
+//
+// Currently `T: Copy` is sufficient to guarantee that T contains no interior
+// mutability, because _all_ interior mutability in Rust is built on
+// std::cell::UnsafeCell, which has no Copy impl. This impl needs to be
+// revisited if that restriction is relaxed in the future.
+impl<T: Copy> Copy for ThreadBound<T> {}
+
+impl<T: Copy> Clone for ThreadBound<T> {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
diff --git a/rust/syn/token.rs b/rust/syn/token.rs
new file mode 100644
index 000000000000..752c188883cb
--- /dev/null
+++ b/rust/syn/token.rs
@@ -0,0 +1,1096 @@
+//! Tokens representing Rust punctuation, keywords, and delimiters.
+//!
+//! The type names in this module can be difficult to keep straight, so we
+//! prefer to use the [`Token!`] macro instead. This is a type-macro that
+//! expands to the token type of the given token.
+//!
+//! [`Token!`]: crate::Token
+//!
+//! # Example
+//!
+//! The [`ItemStatic`] syntax tree node is defined like this.
+//!
+//! [`ItemStatic`]: crate::ItemStatic
+//!
+//! ```
+//! # use syn::{Attribute, Expr, Ident, Token, Type, Visibility};
+//! #
+//! pub struct ItemStatic {
+//! pub attrs: Vec<Attribute>,
+//! pub vis: Visibility,
+//! pub static_token: Token![static],
+//! pub mutability: Option<Token![mut]>,
+//! pub ident: Ident,
+//! pub colon_token: Token![:],
+//! pub ty: Box<Type>,
+//! pub eq_token: Token![=],
+//! pub expr: Box<Expr>,
+//! pub semi_token: Token![;],
+//! }
+//! ```
+//!
+//! # Parsing
+//!
+//! Keywords and punctuation can be parsed through the [`ParseStream::parse`]
+//! method. Delimiter tokens are parsed using the [`parenthesized!`],
+//! [`bracketed!`] and [`braced!`] macros.
+//!
+//! [`ParseStream::parse`]: crate::parse::ParseBuffer::parse()
+//! [`parenthesized!`]: crate::parenthesized!
+//! [`bracketed!`]: crate::bracketed!
+//! [`braced!`]: crate::braced!
+//!
+//! ```
+//! use syn::{Attribute, Result};
+//! use syn::parse::{Parse, ParseStream};
+//! #
+//! # enum ItemStatic {}
+//!
+//! // Parse the ItemStatic struct shown above.
+//! impl Parse for ItemStatic {
+//! fn parse(input: ParseStream) -> Result<Self> {
+//! # use syn::ItemStatic;
+//! # fn parse(input: ParseStream) -> Result<ItemStatic> {
+//! Ok(ItemStatic {
+//! attrs: input.call(Attribute::parse_outer)?,
+//! vis: input.parse()?,
+//! static_token: input.parse()?,
+//! mutability: input.parse()?,
+//! ident: input.parse()?,
+//! colon_token: input.parse()?,
+//! ty: input.parse()?,
+//! eq_token: input.parse()?,
+//! expr: input.parse()?,
+//! semi_token: input.parse()?,
+//! })
+//! # }
+//! # unimplemented!()
+//! }
+//! }
+//! ```
+//!
+//! # Other operations
+//!
+//! Every keyword and punctuation token supports the following operations.
+//!
+//! - [Peeking] — `input.peek(Token![...])`
+//!
+//! - [Parsing] — `input.parse::<Token![...]>()?`
+//!
+//! - [Printing] — `quote!( ... #the_token ... )`
+//!
+//! - Construction from a [`Span`] — `let the_token = Token`
+//!
+//! - Field access to its span — `let sp = the_token.span`
+//!
+//! [Peeking]: crate::parse::ParseBuffer::peek()
+//! [Parsing]: crate::parse::ParseBuffer::parse()
+//! [Printing]: https://docs.rs/quote/1.0/quote/trait.ToTokens.html
+//! [`Span`]: https://docs.rs/proc-macro2/1.0/proc_macro2/struct.Span.html
+
+#[cfg(feature = "parsing")]
+pub(crate) use self::private::CustomToken;
+use self::private::WithSpan;
+#[cfg(feature = "parsing")]
+use crate::buffer::Cursor;
+#[cfg(feature = "parsing")]
+use crate::error::Result;
+#[cfg(feature = "parsing")]
+use crate::lifetime::Lifetime;
+#[cfg(feature = "parsing")]
+use crate::parse::{Parse, ParseStream};
+use crate::span::IntoSpans;
+use proc_macro2::extra::DelimSpan;
+use proc_macro2::Span;
+#[cfg(feature = "printing")]
+use proc_macro2::TokenStream;
+#[cfg(any(feature = "parsing", feature = "printing"))]
+use proc_macro2::{Delimiter, Ident};
+#[cfg(feature = "parsing")]
+use proc_macro2::{Literal, Punct, TokenTree};
+#[cfg(feature = "printing")]
+use quote::{ToTokens, TokenStreamExt};
+#[cfg(feature = "extra-traits")]
+use std::cmp;
+#[cfg(feature = "extra-traits")]
+use std::fmt::{self, Debug};
+#[cfg(feature = "extra-traits")]
+use std::hash::{Hash, Hasher};
+use std::ops::{Deref, DerefMut};
+
+/// Marker trait for types that represent single tokens.
+///
+/// This trait is sealed and cannot be implemented for types outside of Syn.
+#[cfg(feature = "parsing")]
+pub trait Token: private::Sealed {
+ // Not public API.
+ #[doc(hidden)]
+ fn peek(cursor: Cursor) -> bool;
+
+ // Not public API.
+ #[doc(hidden)]
+ fn display() -> &'static str;
+}
+
+pub(crate) mod private {
+ #[cfg(feature = "parsing")]
+ use crate::buffer::Cursor;
+ use proc_macro2::Span;
+
+ #[cfg(feature = "parsing")]
+ pub trait Sealed {}
+
+ /// Support writing `token.span` rather than `token.spans[0]` on tokens that
+ /// hold a single span.
+ #[repr(transparent)]
+ #[allow(unknown_lints, repr_transparent_external_private_fields)] // False positive: https://github.com/rust-lang/rust/issues/78586#issuecomment-1722680482
+ pub struct WithSpan {
+ pub span: Span,
+ }
+
+ // Not public API.
+ #[doc(hidden)]
+ #[cfg(feature = "parsing")]
+ pub trait CustomToken {
+ fn peek(cursor: Cursor) -> bool;
+ fn display() -> &'static str;
+ }
+}
+
+#[cfg(feature = "parsing")]
+impl private::Sealed for Ident {}
+
+macro_rules! impl_low_level_token {
+ ($display:literal $($path:ident)::+ $get:ident) => {
+ #[cfg(feature = "parsing")]
+ impl Token for $($path)::+ {
+ fn peek(cursor: Cursor) -> bool {
+ cursor.$get().is_some()
+ }
+
+ fn display() -> &'static str {
+ $display
+ }
+ }
+
+ #[cfg(feature = "parsing")]
+ impl private::Sealed for $($path)::+ {}
+ };
+}
+
+impl_low_level_token!("punctuation token" Punct punct);
+impl_low_level_token!("literal" Literal literal);
+impl_low_level_token!("token" TokenTree token_tree);
+impl_low_level_token!("group token" proc_macro2::Group any_group);
+impl_low_level_token!("lifetime" Lifetime lifetime);
+
+#[cfg(feature = "parsing")]
+impl<T: CustomToken> private::Sealed for T {}
+
+#[cfg(feature = "parsing")]
+impl<T: CustomToken> Token for T {
+ fn peek(cursor: Cursor) -> bool {
+ <Self as CustomToken>::peek(cursor)
+ }
+
+ fn display() -> &'static str {
+ <Self as CustomToken>::display()
+ }
+}
+
+macro_rules! define_keywords {
+ ($($token:literal pub struct $name:ident)*) => {
+ $(
+ #[doc = concat!('`', $token, '`')]
+ ///
+ /// Don't try to remember the name of this type — use the
+ /// [`Token!`] macro instead.
+ ///
+ /// [`Token!`]: crate::token
+ pub struct $name {
+ pub span: Span,
+ }
+
+ #[doc(hidden)]
+ #[allow(non_snake_case)]
+ pub fn $name<S: IntoSpans<Span>>(span: S) -> $name {
+ $name {
+ span: span.into_spans(),
+ }
+ }
+
+ impl std::default::Default for $name {
+ fn default() -> Self {
+ $name {
+ span: Span::call_site(),
+ }
+ }
+ }
+
+ #[cfg(feature = "clone-impls")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+ impl Copy for $name {}
+
+ #[cfg(feature = "clone-impls")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+ impl Clone for $name {
+ fn clone(&self) -> Self {
+ *self
+ }
+ }
+
+ #[cfg(feature = "extra-traits")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+ impl Debug for $name {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.write_str(stringify!($name))
+ }
+ }
+
+ #[cfg(feature = "extra-traits")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+ impl cmp::Eq for $name {}
+
+ #[cfg(feature = "extra-traits")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+ impl PartialEq for $name {
+ fn eq(&self, _other: &$name) -> bool {
+ true
+ }
+ }
+
+ #[cfg(feature = "extra-traits")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+ impl Hash for $name {
+ fn hash<H: Hasher>(&self, _state: &mut H) {}
+ }
+
+ #[cfg(feature = "printing")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for $name {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ printing::keyword($token, self.span, tokens);
+ }
+ }
+
+ #[cfg(feature = "parsing")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for $name {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Ok($name {
+ span: parsing::keyword(input, $token)?,
+ })
+ }
+ }
+
+ #[cfg(feature = "parsing")]
+ impl Token for $name {
+ fn peek(cursor: Cursor) -> bool {
+ parsing::peek_keyword(cursor, $token)
+ }
+
+ fn display() -> &'static str {
+ concat!("`", $token, "`")
+ }
+ }
+
+ #[cfg(feature = "parsing")]
+ impl private::Sealed for $name {}
+ )*
+ };
+}
+
+macro_rules! impl_deref_if_len_is_1 {
+ ($name:ident/1) => {
+ impl Deref for $name {
+ type Target = WithSpan;
+
+ fn deref(&self) -> &Self::Target {
+ unsafe { &*(self as *const Self).cast::<WithSpan>() }
+ }
+ }
+
+ impl DerefMut for $name {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ unsafe { &mut *(self as *mut Self).cast::<WithSpan>() }
+ }
+ }
+ };
+
+ ($name:ident/$len:literal) => {};
+}
+
+macro_rules! define_punctuation_structs {
+ ($($token:literal pub struct $name:ident/$len:tt #[doc = $usage:literal])*) => {
+ $(
+ #[cfg_attr(not(doc), repr(transparent))]
+ #[allow(unknown_lints, repr_transparent_external_private_fields)] // False positive: https://github.com/rust-lang/rust/issues/78586#issuecomment-1722680482
+ #[doc = concat!('`', $token, '`')]
+ ///
+ /// Usage:
+ #[doc = concat!($usage, '.')]
+ ///
+ /// Don't try to remember the name of this type — use the
+ /// [`Token!`] macro instead.
+ ///
+ /// [`Token!`]: crate::token
+ pub struct $name {
+ pub spans: [Span; $len],
+ }
+
+ #[doc(hidden)]
+ #[allow(non_snake_case)]
+ pub fn $name<S: IntoSpans<[Span; $len]>>(spans: S) -> $name {
+ $name {
+ spans: spans.into_spans(),
+ }
+ }
+
+ impl std::default::Default for $name {
+ fn default() -> Self {
+ $name {
+ spans: [Span::call_site(); $len],
+ }
+ }
+ }
+
+ #[cfg(feature = "clone-impls")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+ impl Copy for $name {}
+
+ #[cfg(feature = "clone-impls")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+ impl Clone for $name {
+ fn clone(&self) -> Self {
+ *self
+ }
+ }
+
+ #[cfg(feature = "extra-traits")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+ impl Debug for $name {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.write_str(stringify!($name))
+ }
+ }
+
+ #[cfg(feature = "extra-traits")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+ impl cmp::Eq for $name {}
+
+ #[cfg(feature = "extra-traits")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+ impl PartialEq for $name {
+ fn eq(&self, _other: &$name) -> bool {
+ true
+ }
+ }
+
+ #[cfg(feature = "extra-traits")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+ impl Hash for $name {
+ fn hash<H: Hasher>(&self, _state: &mut H) {}
+ }
+
+ impl_deref_if_len_is_1!($name/$len);
+ )*
+ };
+}
+
+macro_rules! define_punctuation {
+ ($($token:literal pub struct $name:ident/$len:tt #[doc = $usage:literal])*) => {
+ $(
+ define_punctuation_structs! {
+ $token pub struct $name/$len #[doc = $usage]
+ }
+
+ #[cfg(feature = "printing")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for $name {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ printing::punct($token, &self.spans, tokens);
+ }
+ }
+
+ #[cfg(feature = "parsing")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for $name {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Ok($name {
+ spans: parsing::punct(input, $token)?,
+ })
+ }
+ }
+
+ #[cfg(feature = "parsing")]
+ impl Token for $name {
+ fn peek(cursor: Cursor) -> bool {
+ parsing::peek_punct(cursor, $token)
+ }
+
+ fn display() -> &'static str {
+ concat!("`", $token, "`")
+ }
+ }
+
+ #[cfg(feature = "parsing")]
+ impl private::Sealed for $name {}
+ )*
+ };
+}
+
+macro_rules! define_delimiters {
+ ($($delim:ident pub struct $name:ident #[$doc:meta])*) => {
+ $(
+ #[$doc]
+ pub struct $name {
+ pub span: DelimSpan,
+ }
+
+ #[doc(hidden)]
+ #[allow(non_snake_case)]
+ pub fn $name<S: IntoSpans<DelimSpan>>(span: S) -> $name {
+ $name {
+ span: span.into_spans(),
+ }
+ }
+
+ impl std::default::Default for $name {
+ fn default() -> Self {
+ $name(Span::call_site())
+ }
+ }
+
+ #[cfg(feature = "clone-impls")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+ impl Copy for $name {}
+
+ #[cfg(feature = "clone-impls")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+ impl Clone for $name {
+ fn clone(&self) -> Self {
+ *self
+ }
+ }
+
+ #[cfg(feature = "extra-traits")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+ impl Debug for $name {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.write_str(stringify!($name))
+ }
+ }
+
+ #[cfg(feature = "extra-traits")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+ impl cmp::Eq for $name {}
+
+ #[cfg(feature = "extra-traits")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+ impl PartialEq for $name {
+ fn eq(&self, _other: &$name) -> bool {
+ true
+ }
+ }
+
+ #[cfg(feature = "extra-traits")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+ impl Hash for $name {
+ fn hash<H: Hasher>(&self, _state: &mut H) {}
+ }
+
+ impl $name {
+ #[cfg(feature = "printing")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ pub fn surround<F>(&self, tokens: &mut TokenStream, f: F)
+ where
+ F: FnOnce(&mut TokenStream),
+ {
+ let mut inner = TokenStream::new();
+ f(&mut inner);
+ printing::delim(Delimiter::$delim, self.span.join(), tokens, inner);
+ }
+ }
+
+ #[cfg(feature = "parsing")]
+ impl private::Sealed for $name {}
+ )*
+ };
+}
+
+define_punctuation_structs! {
+ "_" pub struct Underscore/1 /// wildcard patterns, inferred types, unnamed items in constants, extern crates, use declarations, and destructuring assignment
+}
+
+#[cfg(feature = "printing")]
+#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+impl ToTokens for Underscore {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append(Ident::new("_", self.span));
+ }
+}
+
+#[cfg(feature = "parsing")]
+#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+impl Parse for Underscore {
+ fn parse(input: ParseStream) -> Result<Self> {
+ input.step(|cursor| {
+ if let Some((ident, rest)) = cursor.ident() {
+ if ident == "_" {
+ return Ok((Underscore(ident.span()), rest));
+ }
+ }
+ if let Some((punct, rest)) = cursor.punct() {
+ if punct.as_char() == '_' {
+ return Ok((Underscore(punct.span()), rest));
+ }
+ }
+ Err(cursor.error("expected `_`"))
+ })
+ }
+}
+
+#[cfg(feature = "parsing")]
+impl Token for Underscore {
+ fn peek(cursor: Cursor) -> bool {
+ if let Some((ident, _rest)) = cursor.ident() {
+ return ident == "_";
+ }
+ if let Some((punct, _rest)) = cursor.punct() {
+ return punct.as_char() == '_';
+ }
+ false
+ }
+
+ fn display() -> &'static str {
+ "`_`"
+ }
+}
+
+#[cfg(feature = "parsing")]
+impl private::Sealed for Underscore {}
+
+/// None-delimited group
+pub struct Group {
+ pub span: Span,
+}
+
+#[doc(hidden)]
+#[allow(non_snake_case)]
+pub fn Group<S: IntoSpans<Span>>(span: S) -> Group {
+ Group {
+ span: span.into_spans(),
+ }
+}
+
+impl std::default::Default for Group {
+ fn default() -> Self {
+ Group {
+ span: Span::call_site(),
+ }
+ }
+}
+
+#[cfg(feature = "clone-impls")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Copy for Group {}
+
+#[cfg(feature = "clone-impls")]
+#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
+impl Clone for Group {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+
+#[cfg(feature = "extra-traits")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Debug for Group {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.write_str("Group")
+ }
+}
+
+#[cfg(feature = "extra-traits")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl cmp::Eq for Group {}
+
+#[cfg(feature = "extra-traits")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl PartialEq for Group {
+ fn eq(&self, _other: &Group) -> bool {
+ true
+ }
+}
+
+#[cfg(feature = "extra-traits")]
+#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
+impl Hash for Group {
+ fn hash<H: Hasher>(&self, _state: &mut H) {}
+}
+
+impl Group {
+ #[cfg(feature = "printing")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ pub fn surround<F>(&self, tokens: &mut TokenStream, f: F)
+ where
+ F: FnOnce(&mut TokenStream),
+ {
+ let mut inner = TokenStream::new();
+ f(&mut inner);
+ printing::delim(Delimiter::None, self.span, tokens, inner);
+ }
+}
+
+#[cfg(feature = "parsing")]
+impl private::Sealed for Group {}
+
+#[cfg(feature = "parsing")]
+impl Token for Paren {
+ fn peek(cursor: Cursor) -> bool {
+ cursor.group(Delimiter::Parenthesis).is_some()
+ }
+
+ fn display() -> &'static str {
+ "parentheses"
+ }
+}
+
+#[cfg(feature = "parsing")]
+impl Token for Brace {
+ fn peek(cursor: Cursor) -> bool {
+ cursor.group(Delimiter::Brace).is_some()
+ }
+
+ fn display() -> &'static str {
+ "curly braces"
+ }
+}
+
+#[cfg(feature = "parsing")]
+impl Token for Bracket {
+ fn peek(cursor: Cursor) -> bool {
+ cursor.group(Delimiter::Bracket).is_some()
+ }
+
+ fn display() -> &'static str {
+ "square brackets"
+ }
+}
+
+#[cfg(feature = "parsing")]
+impl Token for Group {
+ fn peek(cursor: Cursor) -> bool {
+ cursor.group(Delimiter::None).is_some()
+ }
+
+ fn display() -> &'static str {
+ "invisible group"
+ }
+}
+
+define_keywords! {
+ "abstract" pub struct Abstract
+ "as" pub struct As
+ "async" pub struct Async
+ "auto" pub struct Auto
+ "await" pub struct Await
+ "become" pub struct Become
+ "box" pub struct Box
+ "break" pub struct Break
+ "const" pub struct Const
+ "continue" pub struct Continue
+ "crate" pub struct Crate
+ "default" pub struct Default
+ "do" pub struct Do
+ "dyn" pub struct Dyn
+ "else" pub struct Else
+ "enum" pub struct Enum
+ "extern" pub struct Extern
+ "final" pub struct Final
+ "fn" pub struct Fn
+ "for" pub struct For
+ "if" pub struct If
+ "impl" pub struct Impl
+ "in" pub struct In
+ "let" pub struct Let
+ "loop" pub struct Loop
+ "macro" pub struct Macro
+ "match" pub struct Match
+ "mod" pub struct Mod
+ "move" pub struct Move
+ "mut" pub struct Mut
+ "override" pub struct Override
+ "priv" pub struct Priv
+ "pub" pub struct Pub
+ "raw" pub struct Raw
+ "ref" pub struct Ref
+ "return" pub struct Return
+ "Self" pub struct SelfType
+ "self" pub struct SelfValue
+ "static" pub struct Static
+ "struct" pub struct Struct
+ "super" pub struct Super
+ "trait" pub struct Trait
+ "try" pub struct Try
+ "type" pub struct Type
+ "typeof" pub struct Typeof
+ "union" pub struct Union
+ "unsafe" pub struct Unsafe
+ "unsized" pub struct Unsized
+ "use" pub struct Use
+ "virtual" pub struct Virtual
+ "where" pub struct Where
+ "while" pub struct While
+ "yield" pub struct Yield
+}
+
+define_punctuation! {
+ "&" pub struct And/1 /// bitwise and logical AND, borrow, references, reference patterns
+ "&&" pub struct AndAnd/2 /// lazy AND, borrow, references, reference patterns
+ "&=" pub struct AndEq/2 /// bitwise AND assignment
+ "@" pub struct At/1 /// subpattern binding
+ "^" pub struct Caret/1 /// bitwise and logical XOR
+ "^=" pub struct CaretEq/2 /// bitwise XOR assignment
+ ":" pub struct Colon/1 /// various separators
+ "," pub struct Comma/1 /// various separators
+ "$" pub struct Dollar/1 /// macros
+ "." pub struct Dot/1 /// field access, tuple index
+ ".." pub struct DotDot/2 /// range, struct expressions, patterns, range patterns
+ "..." pub struct DotDotDot/3 /// variadic functions, range patterns
+ "..=" pub struct DotDotEq/3 /// inclusive range, range patterns
+ "=" pub struct Eq/1 /// assignment, attributes, various type definitions
+ "==" pub struct EqEq/2 /// equal
+ "=>" pub struct FatArrow/2 /// match arms, macros
+ ">=" pub struct Ge/2 /// greater than or equal to, generics
+ ">" pub struct Gt/1 /// greater than, generics, paths
+ "<-" pub struct LArrow/2 /// unused
+ "<=" pub struct Le/2 /// less than or equal to
+ "<" pub struct Lt/1 /// less than, generics, paths
+ "-" pub struct Minus/1 /// subtraction, negation
+ "-=" pub struct MinusEq/2 /// subtraction assignment
+ "!=" pub struct Ne/2 /// not equal
+ "!" pub struct Not/1 /// bitwise and logical NOT, macro calls, inner attributes, never type, negative impls
+ "|" pub struct Or/1 /// bitwise and logical OR, closures, patterns in match, if let, and while let
+ "|=" pub struct OrEq/2 /// bitwise OR assignment
+ "||" pub struct OrOr/2 /// lazy OR, closures
+ "::" pub struct PathSep/2 /// path separator
+ "%" pub struct Percent/1 /// remainder
+ "%=" pub struct PercentEq/2 /// remainder assignment
+ "+" pub struct Plus/1 /// addition, trait bounds, macro Kleene matcher
+ "+=" pub struct PlusEq/2 /// addition assignment
+ "#" pub struct Pound/1 /// attributes
+ "?" pub struct Question/1 /// question mark operator, questionably sized, macro Kleene matcher
+ "->" pub struct RArrow/2 /// function return type, closure return type, function pointer type
+ ";" pub struct Semi/1 /// terminator for various items and statements, array types
+ "<<" pub struct Shl/2 /// shift left, nested generics
+ "<<=" pub struct ShlEq/3 /// shift left assignment
+ ">>" pub struct Shr/2 /// shift right, nested generics
+ ">>=" pub struct ShrEq/3 /// shift right assignment, nested generics
+ "/" pub struct Slash/1 /// division
+ "/=" pub struct SlashEq/2 /// division assignment
+ "*" pub struct Star/1 /// multiplication, dereference, raw pointers, macro Kleene matcher, use wildcards
+ "*=" pub struct StarEq/2 /// multiplication assignment
+ "~" pub struct Tilde/1 /// unused since before Rust 1.0
+}
+
+define_delimiters! {
+ Brace pub struct Brace /// `{`…`}`
+ Bracket pub struct Bracket /// `[`…`]`
+ Parenthesis pub struct Paren /// `(`…`)`
+}
+
+/// A type-macro that expands to the name of the Rust type representation of a
+/// given token.
+///
+/// As a type, `Token!` is commonly used in the type of struct fields, the type
+/// of a `let` statement, or in turbofish for a `parse` function.
+///
+/// ```
+/// use syn::{Ident, Token};
+/// use syn::parse::{Parse, ParseStream, Result};
+///
+/// // `struct Foo;`
+/// pub struct UnitStruct {
+/// struct_token: Token![struct],
+/// ident: Ident,
+/// semi_token: Token![;],
+/// }
+///
+/// impl Parse for UnitStruct {
+/// fn parse(input: ParseStream) -> Result<Self> {
+/// let struct_token: Token![struct] = input.parse()?;
+/// let ident: Ident = input.parse()?;
+/// let semi_token = input.parse::<Token![;]>()?;
+/// Ok(UnitStruct { struct_token, ident, semi_token })
+/// }
+/// }
+/// ```
+///
+/// As an expression, `Token!` is used for peeking tokens or instantiating
+/// tokens from a span.
+///
+/// ```
+/// # use syn::{Ident, Token};
+/// # use syn::parse::{Parse, ParseStream, Result};
+/// #
+/// # struct UnitStruct {
+/// # struct_token: Token![struct],
+/// # ident: Ident,
+/// # semi_token: Token![;],
+/// # }
+/// #
+/// # impl Parse for UnitStruct {
+/// # fn parse(input: ParseStream) -> Result<Self> {
+/// # unimplemented!()
+/// # }
+/// # }
+/// #
+/// fn make_unit_struct(name: Ident) -> UnitStruct {
+/// let span = name.span();
+/// UnitStruct {
+/// struct_token: Token,
+/// ident: name,
+/// semi_token: Token,
+/// }
+/// }
+///
+/// # fn parse(input: ParseStream) -> Result<()> {
+/// if input.peek(Token![struct]) {
+/// let unit_struct: UnitStruct = input.parse()?;
+/// /* ... */
+/// }
+/// # Ok(())
+/// # }
+/// ```
+///
+/// See the [token module] documentation for details and examples.
+///
+/// [token module]: crate::token
+#[macro_export]
+macro_rules! Token {
+ [abstract] => { $crate::token::Abstract };
+ [as] => { $crate::token::As };
+ [async] => { $crate::token::Async };
+ [auto] => { $crate::token::Auto };
+ [await] => { $crate::token::Await };
+ [become] => { $crate::token::Become };
+ [box] => { $crate::token::Box };
+ [break] => { $crate::token::Break };
+ [const] => { $crate::token::Const };
+ [continue] => { $crate::token::Continue };
+ [crate] => { $crate::token::Crate };
+ [default] => { $crate::token::Default };
+ [do] => { $crate::token::Do };
+ [dyn] => { $crate::token::Dyn };
+ [else] => { $crate::token::Else };
+ [enum] => { $crate::token::Enum };
+ [extern] => { $crate::token::Extern };
+ [final] => { $crate::token::Final };
+ [fn] => { $crate::token::Fn };
+ [for] => { $crate::token::For };
+ [if] => { $crate::token::If };
+ [impl] => { $crate::token::Impl };
+ [in] => { $crate::token::In };
+ [let] => { $crate::token::Let };
+ [loop] => { $crate::token::Loop };
+ [macro] => { $crate::token::Macro };
+ [match] => { $crate::token::Match };
+ [mod] => { $crate::token::Mod };
+ [move] => { $crate::token::Move };
+ [mut] => { $crate::token::Mut };
+ [override] => { $crate::token::Override };
+ [priv] => { $crate::token::Priv };
+ [pub] => { $crate::token::Pub };
+ [raw] => { $crate::token::Raw };
+ [ref] => { $crate::token::Ref };
+ [return] => { $crate::token::Return };
+ [Self] => { $crate::token::SelfType };
+ [self] => { $crate::token::SelfValue };
+ [static] => { $crate::token::Static };
+ [struct] => { $crate::token::Struct };
+ [super] => { $crate::token::Super };
+ [trait] => { $crate::token::Trait };
+ [try] => { $crate::token::Try };
+ [type] => { $crate::token::Type };
+ [typeof] => { $crate::token::Typeof };
+ [union] => { $crate::token::Union };
+ [unsafe] => { $crate::token::Unsafe };
+ [unsized] => { $crate::token::Unsized };
+ [use] => { $crate::token::Use };
+ [virtual] => { $crate::token::Virtual };
+ [where] => { $crate::token::Where };
+ [while] => { $crate::token::While };
+ [yield] => { $crate::token::Yield };
+ [&] => { $crate::token::And };
+ [&&] => { $crate::token::AndAnd };
+ [&=] => { $crate::token::AndEq };
+ [@] => { $crate::token::At };
+ [^] => { $crate::token::Caret };
+ [^=] => { $crate::token::CaretEq };
+ [:] => { $crate::token::Colon };
+ [,] => { $crate::token::Comma };
+ [$] => { $crate::token::Dollar };
+ [.] => { $crate::token::Dot };
+ [..] => { $crate::token::DotDot };
+ [...] => { $crate::token::DotDotDot };
+ [..=] => { $crate::token::DotDotEq };
+ [=] => { $crate::token::Eq };
+ [==] => { $crate::token::EqEq };
+ [=>] => { $crate::token::FatArrow };
+ [>=] => { $crate::token::Ge };
+ [>] => { $crate::token::Gt };
+ [<-] => { $crate::token::LArrow };
+ [<=] => { $crate::token::Le };
+ [<] => { $crate::token::Lt };
+ [-] => { $crate::token::Minus };
+ [-=] => { $crate::token::MinusEq };
+ [!=] => { $crate::token::Ne };
+ [!] => { $crate::token::Not };
+ [|] => { $crate::token::Or };
+ [|=] => { $crate::token::OrEq };
+ [||] => { $crate::token::OrOr };
+ [::] => { $crate::token::PathSep };
+ [%] => { $crate::token::Percent };
+ [%=] => { $crate::token::PercentEq };
+ [+] => { $crate::token::Plus };
+ [+=] => { $crate::token::PlusEq };
+ [#] => { $crate::token::Pound };
+ [?] => { $crate::token::Question };
+ [->] => { $crate::token::RArrow };
+ [;] => { $crate::token::Semi };
+ [<<] => { $crate::token::Shl };
+ [<<=] => { $crate::token::ShlEq };
+ [>>] => { $crate::token::Shr };
+ [>>=] => { $crate::token::ShrEq };
+ [/] => { $crate::token::Slash };
+ [/=] => { $crate::token::SlashEq };
+ [*] => { $crate::token::Star };
+ [*=] => { $crate::token::StarEq };
+ [~] => { $crate::token::Tilde };
+ [_] => { $crate::token::Underscore };
+}
+
+// Not public API.
+#[doc(hidden)]
+#[cfg(feature = "parsing")]
+pub(crate) mod parsing {
+ use crate::buffer::Cursor;
+ use crate::error::{Error, Result};
+ use crate::parse::ParseStream;
+ use proc_macro2::{Spacing, Span};
+
+ pub(crate) fn keyword(input: ParseStream, token: &str) -> Result<Span> {
+ input.step(|cursor| {
+ if let Some((ident, rest)) = cursor.ident() {
+ if ident == token {
+ return Ok((ident.span(), rest));
+ }
+ }
+ Err(cursor.error(format!("expected `{}`", token)))
+ })
+ }
+
+ pub(crate) fn peek_keyword(cursor: Cursor, token: &str) -> bool {
+ if let Some((ident, _rest)) = cursor.ident() {
+ ident == token
+ } else {
+ false
+ }
+ }
+
+ #[doc(hidden)]
+ pub fn punct<const N: usize>(input: ParseStream, token: &str) -> Result<[Span; N]> {
+ let mut spans = [input.span(); N];
+ punct_helper(input, token, &mut spans)?;
+ Ok(spans)
+ }
+
+ fn punct_helper(input: ParseStream, token: &str, spans: &mut [Span]) -> Result<()> {
+ input.step(|cursor| {
+ let mut cursor = *cursor;
+ assert_eq!(token.len(), spans.len());
+
+ for (i, ch) in token.chars().enumerate() {
+ match cursor.punct() {
+ Some((punct, rest)) => {
+ spans[i] = punct.span();
+ if punct.as_char() != ch {
+ break;
+ } else if i == token.len() - 1 {
+ return Ok(((), rest));
+ } else if punct.spacing() != Spacing::Joint {
+ break;
+ }
+ cursor = rest;
+ }
+ None => break,
+ }
+ }
+
+ Err(Error::new(spans[0], format!("expected `{}`", token)))
+ })
+ }
+
+ #[doc(hidden)]
+ pub fn peek_punct(mut cursor: Cursor, token: &str) -> bool {
+ for (i, ch) in token.chars().enumerate() {
+ match cursor.punct() {
+ Some((punct, rest)) => {
+ if punct.as_char() != ch {
+ break;
+ } else if i == token.len() - 1 {
+ return true;
+ } else if punct.spacing() != Spacing::Joint {
+ break;
+ }
+ cursor = rest;
+ }
+ None => break,
+ }
+ }
+ false
+ }
+}
+
+// Not public API.
+#[doc(hidden)]
+#[cfg(feature = "printing")]
+pub(crate) mod printing {
+ use proc_macro2::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream};
+ use quote::TokenStreamExt;
+
+ #[doc(hidden)]
+ pub fn punct(s: &str, spans: &[Span], tokens: &mut TokenStream) {
+ assert_eq!(s.len(), spans.len());
+
+ let mut chars = s.chars();
+ let mut spans = spans.iter();
+ let ch = chars.next_back().unwrap();
+ let span = spans.next_back().unwrap();
+ for (ch, span) in chars.zip(spans) {
+ let mut op = Punct::new(ch, Spacing::Joint);
+ op.set_span(*span);
+ tokens.append(op);
+ }
+
+ let mut op = Punct::new(ch, Spacing::Alone);
+ op.set_span(*span);
+ tokens.append(op);
+ }
+
+ pub(crate) fn keyword(s: &str, span: Span, tokens: &mut TokenStream) {
+ tokens.append(Ident::new(s, span));
+ }
+
+ pub(crate) fn delim(
+ delim: Delimiter,
+ span: Span,
+ tokens: &mut TokenStream,
+ inner: TokenStream,
+ ) {
+ let mut g = Group::new(delim, inner);
+ g.set_span(span);
+ tokens.append(g);
+ }
+}
diff --git a/rust/syn/tt.rs b/rust/syn/tt.rs
new file mode 100644
index 000000000000..7d5d6a1ac326
--- /dev/null
+++ b/rust/syn/tt.rs
@@ -0,0 +1,107 @@
+use proc_macro2::{Delimiter, TokenStream, TokenTree};
+use std::hash::{Hash, Hasher};
+
+pub(crate) struct TokenTreeHelper<'a>(pub &'a TokenTree);
+
+impl<'a> PartialEq for TokenTreeHelper<'a> {
+ fn eq(&self, other: &Self) -> bool {
+ use proc_macro2::Spacing;
+
+ match (self.0, other.0) {
+ (TokenTree::Group(g1), TokenTree::Group(g2)) => {
+ match (g1.delimiter(), g2.delimiter()) {
+ (Delimiter::Parenthesis, Delimiter::Parenthesis)
+ | (Delimiter::Brace, Delimiter::Brace)
+ | (Delimiter::Bracket, Delimiter::Bracket)
+ | (Delimiter::None, Delimiter::None) => {}
+ _ => return false,
+ }
+
+ let s1 = g1.stream().into_iter();
+ let mut s2 = g2.stream().into_iter();
+
+ for item1 in s1 {
+ let item2 = match s2.next() {
+ Some(item) => item,
+ None => return false,
+ };
+ if TokenTreeHelper(&item1) != TokenTreeHelper(&item2) {
+ return false;
+ }
+ }
+ s2.next().is_none()
+ }
+ (TokenTree::Punct(o1), TokenTree::Punct(o2)) => {
+ o1.as_char() == o2.as_char()
+ && match (o1.spacing(), o2.spacing()) {
+ (Spacing::Alone, Spacing::Alone) | (Spacing::Joint, Spacing::Joint) => true,
+ _ => false,
+ }
+ }
+ (TokenTree::Literal(l1), TokenTree::Literal(l2)) => l1.to_string() == l2.to_string(),
+ (TokenTree::Ident(s1), TokenTree::Ident(s2)) => s1 == s2,
+ _ => false,
+ }
+ }
+}
+
+impl<'a> Hash for TokenTreeHelper<'a> {
+ fn hash<H: Hasher>(&self, h: &mut H) {
+ use proc_macro2::Spacing;
+
+ match self.0 {
+ TokenTree::Group(g) => {
+ 0u8.hash(h);
+ match g.delimiter() {
+ Delimiter::Parenthesis => 0u8.hash(h),
+ Delimiter::Brace => 1u8.hash(h),
+ Delimiter::Bracket => 2u8.hash(h),
+ Delimiter::None => 3u8.hash(h),
+ }
+
+ for item in g.stream() {
+ TokenTreeHelper(&item).hash(h);
+ }
+ 0xFFu8.hash(h); // terminator w/ a variant we don't normally hash
+ }
+ TokenTree::Punct(op) => {
+ 1u8.hash(h);
+ op.as_char().hash(h);
+ match op.spacing() {
+ Spacing::Alone => 0u8.hash(h),
+ Spacing::Joint => 1u8.hash(h),
+ }
+ }
+ TokenTree::Literal(lit) => (2u8, lit.to_string()).hash(h),
+ TokenTree::Ident(word) => (3u8, word).hash(h),
+ }
+ }
+}
+
+pub(crate) struct TokenStreamHelper<'a>(pub &'a TokenStream);
+
+impl<'a> PartialEq for TokenStreamHelper<'a> {
+ fn eq(&self, other: &Self) -> bool {
+ let left = self.0.clone().into_iter().collect::<Vec<_>>();
+ let right = other.0.clone().into_iter().collect::<Vec<_>>();
+ if left.len() != right.len() {
+ return false;
+ }
+ for (a, b) in left.into_iter().zip(right) {
+ if TokenTreeHelper(&a) != TokenTreeHelper(&b) {
+ return false;
+ }
+ }
+ true
+ }
+}
+
+impl<'a> Hash for TokenStreamHelper<'a> {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ let tts = self.0.clone().into_iter().collect::<Vec<_>>();
+ tts.len().hash(state);
+ for tt in tts {
+ TokenTreeHelper(&tt).hash(state);
+ }
+ }
+}
diff --git a/rust/syn/ty.rs b/rust/syn/ty.rs
new file mode 100644
index 000000000000..c093f5877b3c
--- /dev/null
+++ b/rust/syn/ty.rs
@@ -0,0 +1,1271 @@
+use crate::attr::Attribute;
+use crate::expr::Expr;
+use crate::generics::{BoundLifetimes, TypeParamBound};
+use crate::ident::Ident;
+use crate::lifetime::Lifetime;
+use crate::lit::LitStr;
+use crate::mac::Macro;
+use crate::path::{Path, QSelf};
+use crate::punctuated::Punctuated;
+use crate::token;
+use proc_macro2::TokenStream;
+
+ast_enum_of_structs! {
+ /// The possible types that a Rust value could have.
+ ///
+ /// # 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"))))]
+ #[non_exhaustive]
+ pub enum Type {
+ /// A fixed size array type: `[T; n]`.
+ Array(TypeArray),
+
+ /// A bare function type: `fn(usize) -> bool`.
+ BareFn(TypeBareFn),
+
+ /// A type contained within invisible delimiters.
+ Group(TypeGroup),
+
+ /// An `impl Bound1 + Bound2 + Bound3` type where `Bound` is a trait or
+ /// a lifetime.
+ ImplTrait(TypeImplTrait),
+
+ /// Indication that a type should be inferred by the compiler: `_`.
+ Infer(TypeInfer),
+
+ /// A macro in the type position.
+ Macro(TypeMacro),
+
+ /// The never type: `!`.
+ Never(TypeNever),
+
+ /// A parenthesized type equivalent to the inner type.
+ Paren(TypeParen),
+
+ /// A path like `std::slice::Iter`, optionally qualified with a
+ /// self-type as in `<Vec<T> as SomeTrait>::Associated`.
+ Path(TypePath),
+
+ /// A raw pointer type: `*const T` or `*mut T`.
+ Ptr(TypePtr),
+
+ /// A reference type: `&'a T` or `&'a mut T`.
+ Reference(TypeReference),
+
+ /// A dynamically sized slice type: `[T]`.
+ Slice(TypeSlice),
+
+ /// A trait object type `dyn Bound1 + Bound2 + Bound3` where `Bound` is a
+ /// trait or a lifetime.
+ TraitObject(TypeTraitObject),
+
+ /// A tuple type: `(A, B, C, String)`.
+ Tuple(TypeTuple),
+
+ /// Tokens in type position not interpreted by Syn.
+ Verbatim(TokenStream),
+
+ // For testing exhaustiveness in downstream code, use the following idiom:
+ //
+ // match ty {
+ // #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))]
+ //
+ // Type::Array(ty) => {...}
+ // Type::BareFn(ty) => {...}
+ // ...
+ // Type::Verbatim(ty) => {...}
+ //
+ // _ => { /* some sane fallback */ }
+ // }
+ //
+ // This way we fail your tests but don't break your library when adding
+ // a variant. You will be notified by a test failure when a variant is
+ // added, so that you can add code to handle it, but your library will
+ // continue to compile and work for downstream users in the interim.
+ }
+}
+
+ast_struct! {
+ /// A fixed size array type: `[T; n]`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct TypeArray {
+ pub bracket_token: token::Bracket,
+ pub elem: Box<Type>,
+ pub semi_token: Token![;],
+ pub len: Expr,
+ }
+}
+
+ast_struct! {
+ /// A bare function type: `fn(usize) -> bool`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct TypeBareFn {
+ pub lifetimes: Option<BoundLifetimes>,
+ pub unsafety: Option<Token![unsafe]>,
+ pub abi: Option<Abi>,
+ pub fn_token: Token![fn],
+ pub paren_token: token::Paren,
+ pub inputs: Punctuated<BareFnArg, Token![,]>,
+ pub variadic: Option<BareVariadic>,
+ pub output: ReturnType,
+ }
+}
+
+ast_struct! {
+ /// A type contained within invisible delimiters.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct TypeGroup {
+ pub group_token: token::Group,
+ pub elem: Box<Type>,
+ }
+}
+
+ast_struct! {
+ /// An `impl Bound1 + Bound2 + Bound3` type where `Bound` is a trait or
+ /// a lifetime.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct TypeImplTrait {
+ pub impl_token: Token![impl],
+ pub bounds: Punctuated<TypeParamBound, Token![+]>,
+ }
+}
+
+ast_struct! {
+ /// Indication that a type should be inferred by the compiler: `_`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct TypeInfer {
+ pub underscore_token: Token![_],
+ }
+}
+
+ast_struct! {
+ /// A macro in the type position.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct TypeMacro {
+ pub mac: Macro,
+ }
+}
+
+ast_struct! {
+ /// The never type: `!`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct TypeNever {
+ pub bang_token: Token![!],
+ }
+}
+
+ast_struct! {
+ /// A parenthesized type equivalent to the inner type.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct TypeParen {
+ pub paren_token: token::Paren,
+ pub elem: Box<Type>,
+ }
+}
+
+ast_struct! {
+ /// A path like `std::slice::Iter`, optionally qualified with a
+ /// self-type as in `<Vec<T> as SomeTrait>::Associated`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct TypePath {
+ pub qself: Option<QSelf>,
+ pub path: Path,
+ }
+}
+
+ast_struct! {
+ /// A raw pointer type: `*const T` or `*mut T`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct TypePtr {
+ pub star_token: Token![*],
+ pub const_token: Option<Token![const]>,
+ pub mutability: Option<Token![mut]>,
+ pub elem: Box<Type>,
+ }
+}
+
+ast_struct! {
+ /// A reference type: `&'a T` or `&'a mut T`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct TypeReference {
+ pub and_token: Token![&],
+ pub lifetime: Option<Lifetime>,
+ pub mutability: Option<Token![mut]>,
+ pub elem: Box<Type>,
+ }
+}
+
+ast_struct! {
+ /// A dynamically sized slice type: `[T]`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct TypeSlice {
+ pub bracket_token: token::Bracket,
+ pub elem: Box<Type>,
+ }
+}
+
+ast_struct! {
+ /// A trait object type `dyn Bound1 + Bound2 + Bound3` where `Bound` is a
+ /// trait or a lifetime.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct TypeTraitObject {
+ pub dyn_token: Option<Token![dyn]>,
+ pub bounds: Punctuated<TypeParamBound, Token![+]>,
+ }
+}
+
+ast_struct! {
+ /// A tuple type: `(A, B, C, String)`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct TypeTuple {
+ pub paren_token: token::Paren,
+ pub elems: Punctuated<Type, Token![,]>,
+ }
+}
+
+ast_struct! {
+ /// The binary interface of a function: `extern "C"`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct Abi {
+ pub extern_token: Token![extern],
+ pub name: Option<LitStr>,
+ }
+}
+
+ast_struct! {
+ /// An argument in a function type: the `usize` in `fn(usize) -> bool`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct BareFnArg {
+ pub attrs: Vec<Attribute>,
+ pub name: Option<(Ident, Token![:])>,
+ pub ty: Type,
+ }
+}
+
+ast_struct! {
+ /// The variadic argument of a function pointer like `fn(usize, ...)`.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub struct BareVariadic {
+ pub attrs: Vec<Attribute>,
+ pub name: Option<(Ident, Token![:])>,
+ pub dots: Token![...],
+ pub comma: Option<Token![,]>,
+ }
+}
+
+ast_enum! {
+ /// Return type of a function signature.
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
+ pub enum ReturnType {
+ /// Return type is not specified.
+ ///
+ /// Functions default to `()` and closures default to type inference.
+ Default,
+ /// A particular type is returned.
+ Type(Token![->], Box<Type>),
+ }
+}
+
+#[cfg(feature = "parsing")]
+pub(crate) mod parsing {
+ use crate::attr::Attribute;
+ use crate::error::{self, Result};
+ use crate::ext::IdentExt as _;
+ use crate::generics::{BoundLifetimes, TraitBound, TraitBoundModifier, TypeParamBound};
+ use crate::ident::Ident;
+ use crate::lifetime::Lifetime;
+ use crate::mac::{self, Macro};
+ use crate::parse::{Parse, ParseStream};
+ use crate::path;
+ use crate::path::{Path, PathArguments, QSelf};
+ use crate::punctuated::Punctuated;
+ use crate::token;
+ use crate::ty::{
+ Abi, BareFnArg, BareVariadic, ReturnType, Type, TypeArray, TypeBareFn, TypeGroup,
+ TypeImplTrait, TypeInfer, TypeMacro, TypeNever, TypeParen, TypePath, TypePtr,
+ TypeReference, TypeSlice, TypeTraitObject, TypeTuple,
+ };
+ use crate::verbatim;
+ use proc_macro2::Span;
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for Type {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let allow_plus = true;
+ let allow_group_generic = true;
+ ambig_ty(input, allow_plus, allow_group_generic)
+ }
+ }
+
+ impl Type {
+ /// In some positions, types may not contain the `+` character, to
+ /// disambiguate them. For example in the expression `1 as T`, T may not
+ /// contain a `+` character.
+ ///
+ /// This parser does not allow a `+`, while the default parser does.
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ pub fn without_plus(input: ParseStream) -> Result<Self> {
+ let allow_plus = false;
+ let allow_group_generic = true;
+ ambig_ty(input, allow_plus, allow_group_generic)
+ }
+ }
+
+ pub(crate) fn ambig_ty(
+ input: ParseStream,
+ allow_plus: bool,
+ allow_group_generic: bool,
+ ) -> Result<Type> {
+ let begin = input.fork();
+
+ if input.peek(token::Group) {
+ let mut group: TypeGroup = input.parse()?;
+ if input.peek(Token![::]) && input.peek3(Ident::peek_any) {
+ if let Type::Path(mut ty) = *group.elem {
+ Path::parse_rest(input, &mut ty.path, false)?;
+ return Ok(Type::Path(ty));
+ } else {
+ return Ok(Type::Path(TypePath {
+ qself: Some(QSelf {
+ lt_token: Token,
+ position: 0,
+ as_token: None,
+ gt_token: Token,
+ ty: group.elem,
+ }),
+ path: Path::parse_helper(input, false)?,
+ }));
+ }
+ } else if input.peek(Token![<]) && allow_group_generic
+ || input.peek(Token![::]) && input.peek3(Token![<])
+ {
+ if let Type::Path(mut ty) = *group.elem {
+ let arguments = &mut ty.path.segments.last_mut().unwrap().arguments;
+ if arguments.is_none() {
+ *arguments = PathArguments::AngleBracketed(input.parse()?);
+ Path::parse_rest(input, &mut ty.path, false)?;
+ return Ok(Type::Path(ty));
+ } else {
+ group.elem = Box::new(Type::Path(ty));
+ }
+ }
+ }
+ return Ok(Type::Group(group));
+ }
+
+ let mut lifetimes = None::<BoundLifetimes>;
+ let mut lookahead = input.lookahead1();
+ if lookahead.peek(Token![for]) {
+ lifetimes = input.parse()?;
+ lookahead = input.lookahead1();
+ if !lookahead.peek(Ident)
+ && !lookahead.peek(Token![fn])
+ && !lookahead.peek(Token![unsafe])
+ && !lookahead.peek(Token![extern])
+ && !lookahead.peek(Token![super])
+ && !lookahead.peek(Token![self])
+ && !lookahead.peek(Token![Self])
+ && !lookahead.peek(Token![crate])
+ || input.peek(Token![dyn])
+ {
+ return Err(lookahead.error());
+ }
+ }
+
+ if lookahead.peek(token::Paren) {
+ let content;
+ let paren_token = parenthesized!(content in input);
+ if content.is_empty() {
+ return Ok(Type::Tuple(TypeTuple {
+ paren_token,
+ elems: Punctuated::new(),
+ }));
+ }
+ if content.peek(Lifetime) {
+ return Ok(Type::Paren(TypeParen {
+ paren_token,
+ elem: Box::new(Type::TraitObject(content.parse()?)),
+ }));
+ }
+ if content.peek(Token![?]) {
+ return Ok(Type::TraitObject(TypeTraitObject {
+ dyn_token: None,
+ bounds: {
+ let mut bounds = Punctuated::new();
+ bounds.push_value(TypeParamBound::Trait(TraitBound {
+ paren_token: Some(paren_token),
+ ..content.parse()?
+ }));
+ while let Some(plus) = input.parse()? {
+ bounds.push_punct(plus);
+ bounds.push_value({
+ let allow_precise_capture = false;
+ let allow_const = false;
+ TypeParamBound::parse_single(
+ input,
+ allow_precise_capture,
+ allow_const,
+ )?
+ });
+ }
+ bounds
+ },
+ }));
+ }
+ let mut first: Type = content.parse()?;
+ if content.peek(Token![,]) {
+ return Ok(Type::Tuple(TypeTuple {
+ paren_token,
+ elems: {
+ let mut elems = Punctuated::new();
+ elems.push_value(first);
+ elems.push_punct(content.parse()?);
+ while !content.is_empty() {
+ elems.push_value(content.parse()?);
+ if content.is_empty() {
+ break;
+ }
+ elems.push_punct(content.parse()?);
+ }
+ elems
+ },
+ }));
+ }
+ if allow_plus && input.peek(Token![+]) {
+ loop {
+ let first = match first {
+ Type::Path(TypePath { qself: None, path }) => {
+ TypeParamBound::Trait(TraitBound {
+ paren_token: Some(paren_token),
+ modifier: TraitBoundModifier::None,
+ lifetimes: None,
+ path,
+ })
+ }
+ Type::TraitObject(TypeTraitObject {
+ dyn_token: None,
+ bounds,
+ }) => {
+ if bounds.len() > 1 || bounds.trailing_punct() {
+ first = Type::TraitObject(TypeTraitObject {
+ dyn_token: None,
+ bounds,
+ });
+ break;
+ }
+ match bounds.into_iter().next().unwrap() {
+ TypeParamBound::Trait(trait_bound) => {
+ TypeParamBound::Trait(TraitBound {
+ paren_token: Some(paren_token),
+ ..trait_bound
+ })
+ }
+ other @ (TypeParamBound::Lifetime(_)
+ | TypeParamBound::PreciseCapture(_)
+ | TypeParamBound::Verbatim(_)) => other,
+ }
+ }
+ _ => break,
+ };
+ return Ok(Type::TraitObject(TypeTraitObject {
+ dyn_token: None,
+ bounds: {
+ let mut bounds = Punctuated::new();
+ bounds.push_value(first);
+ while let Some(plus) = input.parse()? {
+ bounds.push_punct(plus);
+ bounds.push_value({
+ let allow_precise_capture = false;
+ let allow_const = false;
+ TypeParamBound::parse_single(
+ input,
+ allow_precise_capture,
+ allow_const,
+ )?
+ });
+ }
+ bounds
+ },
+ }));
+ }
+ }
+ Ok(Type::Paren(TypeParen {
+ paren_token,
+ elem: Box::new(first),
+ }))
+ } else if lookahead.peek(Token![fn])
+ || lookahead.peek(Token![unsafe])
+ || lookahead.peek(Token![extern])
+ {
+ let mut bare_fn: TypeBareFn = input.parse()?;
+ bare_fn.lifetimes = lifetimes;
+ Ok(Type::BareFn(bare_fn))
+ } else if lookahead.peek(Ident)
+ || input.peek(Token![super])
+ || input.peek(Token![self])
+ || input.peek(Token![Self])
+ || input.peek(Token![crate])
+ || lookahead.peek(Token![::])
+ || lookahead.peek(Token![<])
+ {
+ let ty: TypePath = input.parse()?;
+ if ty.qself.is_some() {
+ return Ok(Type::Path(ty));
+ }
+
+ if input.peek(Token![!]) && !input.peek(Token![!=]) && ty.path.is_mod_style() {
+ let bang_token: Token![!] = input.parse()?;
+ let (delimiter, tokens) = mac::parse_delimiter(input)?;
+ return Ok(Type::Macro(TypeMacro {
+ mac: Macro {
+ path: ty.path,
+ bang_token,
+ delimiter,
+ tokens,
+ },
+ }));
+ }
+
+ if lifetimes.is_some() || allow_plus && input.peek(Token![+]) {
+ let mut bounds = Punctuated::new();
+ bounds.push_value(TypeParamBound::Trait(TraitBound {
+ paren_token: None,
+ modifier: TraitBoundModifier::None,
+ lifetimes,
+ path: ty.path,
+ }));
+ if allow_plus {
+ while input.peek(Token![+]) {
+ bounds.push_punct(input.parse()?);
+ if !(input.peek(Ident::peek_any)
+ || input.peek(Token![::])
+ || input.peek(Token![?])
+ || input.peek(Lifetime)
+ || input.peek(token::Paren))
+ {
+ break;
+ }
+ bounds.push_value({
+ let allow_precise_capture = false;
+ let allow_const = false;
+ TypeParamBound::parse_single(input, allow_precise_capture, allow_const)?
+ });
+ }
+ }
+ return Ok(Type::TraitObject(TypeTraitObject {
+ dyn_token: None,
+ bounds,
+ }));
+ }
+
+ Ok(Type::Path(ty))
+ } else if lookahead.peek(Token![dyn]) {
+ let dyn_token: Token![dyn] = input.parse()?;
+ let dyn_span = dyn_token.span;
+ let star_token: Option<Token![*]> = input.parse()?;
+ let bounds = TypeTraitObject::parse_bounds(dyn_span, input, allow_plus)?;
+ Ok(if star_token.is_some() {
+ Type::Verbatim(verbatim::between(&begin, input))
+ } else {
+ Type::TraitObject(TypeTraitObject {
+ dyn_token: Some(dyn_token),
+ bounds,
+ })
+ })
+ } else if lookahead.peek(token::Bracket) {
+ let content;
+ let bracket_token = bracketed!(content in input);
+ let elem: Type = content.parse()?;
+ if content.peek(Token![;]) {
+ Ok(Type::Array(TypeArray {
+ bracket_token,
+ elem: Box::new(elem),
+ semi_token: content.parse()?,
+ len: content.parse()?,
+ }))
+ } else {
+ Ok(Type::Slice(TypeSlice {
+ bracket_token,
+ elem: Box::new(elem),
+ }))
+ }
+ } else if lookahead.peek(Token![*]) {
+ input.parse().map(Type::Ptr)
+ } else if lookahead.peek(Token![&]) {
+ input.parse().map(Type::Reference)
+ } else if lookahead.peek(Token![!]) && !input.peek(Token![=]) {
+ input.parse().map(Type::Never)
+ } else if lookahead.peek(Token![impl]) {
+ TypeImplTrait::parse(input, allow_plus).map(Type::ImplTrait)
+ } else if lookahead.peek(Token![_]) {
+ input.parse().map(Type::Infer)
+ } else if lookahead.peek(Lifetime) {
+ input.parse().map(Type::TraitObject)
+ } else {
+ Err(lookahead.error())
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for TypeSlice {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let content;
+ Ok(TypeSlice {
+ bracket_token: bracketed!(content in input),
+ elem: content.parse()?,
+ })
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for TypeArray {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let content;
+ Ok(TypeArray {
+ bracket_token: bracketed!(content in input),
+ elem: content.parse()?,
+ semi_token: content.parse()?,
+ len: content.parse()?,
+ })
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for TypePtr {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let star_token: Token![*] = input.parse()?;
+
+ let lookahead = input.lookahead1();
+ let (const_token, mutability) = if lookahead.peek(Token![const]) {
+ (Some(input.parse()?), None)
+ } else if lookahead.peek(Token![mut]) {
+ (None, Some(input.parse()?))
+ } else {
+ return Err(lookahead.error());
+ };
+
+ Ok(TypePtr {
+ star_token,
+ const_token,
+ mutability,
+ elem: Box::new(input.call(Type::without_plus)?),
+ })
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for TypeReference {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Ok(TypeReference {
+ and_token: input.parse()?,
+ lifetime: input.parse()?,
+ mutability: input.parse()?,
+ // & binds tighter than +, so we don't allow + here.
+ elem: Box::new(input.call(Type::without_plus)?),
+ })
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for TypeBareFn {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let args;
+ let mut variadic = None;
+
+ Ok(TypeBareFn {
+ lifetimes: input.parse()?,
+ unsafety: input.parse()?,
+ abi: input.parse()?,
+ fn_token: input.parse()?,
+ paren_token: parenthesized!(args in input),
+ inputs: {
+ let mut inputs = Punctuated::new();
+
+ while !args.is_empty() {
+ let attrs = args.call(Attribute::parse_outer)?;
+
+ if inputs.empty_or_trailing()
+ && (args.peek(Token![...])
+ || (args.peek(Ident) || args.peek(Token![_]))
+ && args.peek2(Token![:])
+ && args.peek3(Token![...]))
+ {
+ variadic = Some(parse_bare_variadic(&args, attrs)?);
+ break;
+ }
+
+ let allow_self = inputs.is_empty();
+ let arg = parse_bare_fn_arg(&args, allow_self)?;
+ inputs.push_value(BareFnArg { attrs, ..arg });
+ if args.is_empty() {
+ break;
+ }
+
+ let comma = args.parse()?;
+ inputs.push_punct(comma);
+ }
+
+ inputs
+ },
+ variadic,
+ output: input.call(ReturnType::without_plus)?,
+ })
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for TypeNever {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Ok(TypeNever {
+ bang_token: input.parse()?,
+ })
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for TypeInfer {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Ok(TypeInfer {
+ underscore_token: input.parse()?,
+ })
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for TypeTuple {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let content;
+ let paren_token = parenthesized!(content in input);
+
+ if content.is_empty() {
+ return Ok(TypeTuple {
+ paren_token,
+ elems: Punctuated::new(),
+ });
+ }
+
+ let first: Type = content.parse()?;
+ Ok(TypeTuple {
+ paren_token,
+ elems: {
+ let mut elems = Punctuated::new();
+ elems.push_value(first);
+ elems.push_punct(content.parse()?);
+ while !content.is_empty() {
+ elems.push_value(content.parse()?);
+ if content.is_empty() {
+ break;
+ }
+ elems.push_punct(content.parse()?);
+ }
+ elems
+ },
+ })
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for TypeMacro {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Ok(TypeMacro {
+ mac: input.parse()?,
+ })
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for TypePath {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let expr_style = false;
+ let (qself, path) = path::parsing::qpath(input, expr_style)?;
+ Ok(TypePath { qself, path })
+ }
+ }
+
+ impl ReturnType {
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ pub fn without_plus(input: ParseStream) -> Result<Self> {
+ let allow_plus = false;
+ Self::parse(input, allow_plus)
+ }
+
+ pub(crate) fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> {
+ if input.peek(Token![->]) {
+ let arrow = input.parse()?;
+ let allow_group_generic = true;
+ let ty = ambig_ty(input, allow_plus, allow_group_generic)?;
+ Ok(ReturnType::Type(arrow, Box::new(ty)))
+ } else {
+ Ok(ReturnType::Default)
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for ReturnType {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let allow_plus = true;
+ Self::parse(input, allow_plus)
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for TypeTraitObject {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let allow_plus = true;
+ Self::parse(input, allow_plus)
+ }
+ }
+
+ impl TypeTraitObject {
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ pub fn without_plus(input: ParseStream) -> Result<Self> {
+ let allow_plus = false;
+ Self::parse(input, allow_plus)
+ }
+
+ // Only allow multiple trait references if allow_plus is true.
+ pub(crate) fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> {
+ let dyn_token: Option<Token![dyn]> = input.parse()?;
+ let dyn_span = match &dyn_token {
+ Some(token) => token.span,
+ None => input.span(),
+ };
+ let bounds = Self::parse_bounds(dyn_span, input, allow_plus)?;
+ Ok(TypeTraitObject { dyn_token, bounds })
+ }
+
+ fn parse_bounds(
+ dyn_span: Span,
+ input: ParseStream,
+ allow_plus: bool,
+ ) -> Result<Punctuated<TypeParamBound, Token![+]>> {
+ let allow_precise_capture = false;
+ let allow_const = false;
+ let bounds = TypeParamBound::parse_multiple(
+ input,
+ allow_plus,
+ allow_precise_capture,
+ allow_const,
+ )?;
+ let mut last_lifetime_span = None;
+ let mut at_least_one_trait = false;
+ for bound in &bounds {
+ match bound {
+ TypeParamBound::Trait(_) => {
+ at_least_one_trait = true;
+ break;
+ }
+ TypeParamBound::Lifetime(lifetime) => {
+ last_lifetime_span = Some(lifetime.ident.span());
+ }
+ TypeParamBound::PreciseCapture(_) | TypeParamBound::Verbatim(_) => {
+ unreachable!()
+ }
+ }
+ }
+ // Just lifetimes like `'a + 'b` is not a TraitObject.
+ if !at_least_one_trait {
+ let msg = "at least one trait is required for an object type";
+ return Err(error::new2(dyn_span, last_lifetime_span.unwrap(), msg));
+ }
+ Ok(bounds)
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for TypeImplTrait {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let allow_plus = true;
+ Self::parse(input, allow_plus)
+ }
+ }
+
+ impl TypeImplTrait {
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ pub fn without_plus(input: ParseStream) -> Result<Self> {
+ let allow_plus = false;
+ Self::parse(input, allow_plus)
+ }
+
+ pub(crate) fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> {
+ let impl_token: Token![impl] = input.parse()?;
+ let allow_precise_capture = true;
+ let allow_const = true;
+ let bounds = TypeParamBound::parse_multiple(
+ input,
+ allow_plus,
+ allow_precise_capture,
+ allow_const,
+ )?;
+ let mut last_nontrait_span = None;
+ let mut at_least_one_trait = false;
+ for bound in &bounds {
+ match bound {
+ TypeParamBound::Trait(_) => {
+ at_least_one_trait = true;
+ break;
+ }
+ TypeParamBound::Lifetime(lifetime) => {
+ last_nontrait_span = Some(lifetime.ident.span());
+ }
+ TypeParamBound::PreciseCapture(precise_capture) => {
+ #[cfg(feature = "full")]
+ {
+ last_nontrait_span = Some(precise_capture.gt_token.span);
+ }
+ #[cfg(not(feature = "full"))]
+ {
+ _ = precise_capture;
+ unreachable!();
+ }
+ }
+ TypeParamBound::Verbatim(_) => {
+ // `[const] Trait`
+ at_least_one_trait = true;
+ break;
+ }
+ }
+ }
+ if !at_least_one_trait {
+ let msg = "at least one trait must be specified";
+ return Err(error::new2(
+ impl_token.span,
+ last_nontrait_span.unwrap(),
+ msg,
+ ));
+ }
+ Ok(TypeImplTrait { impl_token, bounds })
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for TypeGroup {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let group = crate::group::parse_group(input)?;
+ Ok(TypeGroup {
+ group_token: group.token,
+ elem: group.content.parse()?,
+ })
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for TypeParen {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let allow_plus = false;
+ Self::parse(input, allow_plus)
+ }
+ }
+
+ impl TypeParen {
+ fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> {
+ let content;
+ Ok(TypeParen {
+ paren_token: parenthesized!(content in input),
+ elem: Box::new({
+ let allow_group_generic = true;
+ ambig_ty(&content, allow_plus, allow_group_generic)?
+ }),
+ })
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for BareFnArg {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let allow_self = false;
+ parse_bare_fn_arg(input, allow_self)
+ }
+ }
+
+ fn parse_bare_fn_arg(input: ParseStream, allow_self: bool) -> Result<BareFnArg> {
+ let attrs = input.call(Attribute::parse_outer)?;
+
+ let begin = input.fork();
+
+ let has_mut_self = allow_self && input.peek(Token![mut]) && input.peek2(Token![self]);
+ if has_mut_self {
+ input.parse::<Token![mut]>()?;
+ }
+
+ let mut has_self = false;
+ let mut name = if (input.peek(Ident) || input.peek(Token![_]) || {
+ has_self = allow_self && input.peek(Token![self]);
+ has_self
+ }) && input.peek2(Token![:])
+ && !input.peek2(Token![::])
+ {
+ let name = input.call(Ident::parse_any)?;
+ let colon: Token![:] = input.parse()?;
+ Some((name, colon))
+ } else {
+ has_self = false;
+ None
+ };
+
+ let ty = if allow_self && !has_self && input.peek(Token![mut]) && input.peek2(Token![self])
+ {
+ input.parse::<Token![mut]>()?;
+ input.parse::<Token![self]>()?;
+ None
+ } else if has_mut_self && name.is_none() {
+ input.parse::<Token![self]>()?;
+ None
+ } else {
+ Some(input.parse()?)
+ };
+
+ let ty = match ty {
+ Some(ty) if !has_mut_self => ty,
+ _ => {
+ name = None;
+ Type::Verbatim(verbatim::between(&begin, input))
+ }
+ };
+
+ Ok(BareFnArg { attrs, name, ty })
+ }
+
+ fn parse_bare_variadic(input: ParseStream, attrs: Vec<Attribute>) -> Result<BareVariadic> {
+ Ok(BareVariadic {
+ attrs,
+ name: if input.peek(Ident) || input.peek(Token![_]) {
+ let name = input.call(Ident::parse_any)?;
+ let colon: Token![:] = input.parse()?;
+ Some((name, colon))
+ } else {
+ None
+ },
+ dots: input.parse()?,
+ comma: input.parse()?,
+ })
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for Abi {
+ fn parse(input: ParseStream) -> Result<Self> {
+ Ok(Abi {
+ extern_token: input.parse()?,
+ name: input.parse()?,
+ })
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
+ impl Parse for Option<Abi> {
+ fn parse(input: ParseStream) -> Result<Self> {
+ if input.peek(Token![extern]) {
+ input.parse().map(Some)
+ } else {
+ Ok(None)
+ }
+ }
+ }
+}
+
+#[cfg(feature = "printing")]
+mod printing {
+ use crate::attr::FilterAttrs;
+ use crate::path;
+ use crate::path::printing::PathStyle;
+ use crate::print::TokensOrDefault;
+ use crate::ty::{
+ Abi, BareFnArg, BareVariadic, ReturnType, TypeArray, TypeBareFn, TypeGroup, TypeImplTrait,
+ TypeInfer, TypeMacro, TypeNever, TypeParen, TypePath, TypePtr, TypeReference, TypeSlice,
+ TypeTraitObject, TypeTuple,
+ };
+ use proc_macro2::TokenStream;
+ use quote::{ToTokens, TokenStreamExt};
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for TypeSlice {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.bracket_token.surround(tokens, |tokens| {
+ self.elem.to_tokens(tokens);
+ });
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for TypeArray {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.bracket_token.surround(tokens, |tokens| {
+ self.elem.to_tokens(tokens);
+ self.semi_token.to_tokens(tokens);
+ self.len.to_tokens(tokens);
+ });
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for TypePtr {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.star_token.to_tokens(tokens);
+ match &self.mutability {
+ Some(tok) => tok.to_tokens(tokens),
+ None => {
+ TokensOrDefault(&self.const_token).to_tokens(tokens);
+ }
+ }
+ self.elem.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for TypeReference {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.and_token.to_tokens(tokens);
+ self.lifetime.to_tokens(tokens);
+ self.mutability.to_tokens(tokens);
+ self.elem.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for TypeBareFn {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.lifetimes.to_tokens(tokens);
+ self.unsafety.to_tokens(tokens);
+ self.abi.to_tokens(tokens);
+ self.fn_token.to_tokens(tokens);
+ self.paren_token.surround(tokens, |tokens| {
+ self.inputs.to_tokens(tokens);
+ if let Some(variadic) = &self.variadic {
+ if !self.inputs.empty_or_trailing() {
+ let span = variadic.dots.spans[0];
+ Token.to_tokens(tokens);
+ }
+ variadic.to_tokens(tokens);
+ }
+ });
+ self.output.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for TypeNever {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.bang_token.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for TypeTuple {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.paren_token.surround(tokens, |tokens| {
+ self.elems.to_tokens(tokens);
+ // If we only have one argument, we need a trailing comma to
+ // distinguish TypeTuple from TypeParen.
+ if self.elems.len() == 1 && !self.elems.trailing_punct() {
+ <Token![,]>::default().to_tokens(tokens);
+ }
+ });
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for TypePath {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::AsWritten);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for TypeTraitObject {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.dyn_token.to_tokens(tokens);
+ self.bounds.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for TypeImplTrait {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.impl_token.to_tokens(tokens);
+ self.bounds.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for TypeGroup {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.group_token.surround(tokens, |tokens| {
+ self.elem.to_tokens(tokens);
+ });
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for TypeParen {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.paren_token.surround(tokens, |tokens| {
+ self.elem.to_tokens(tokens);
+ });
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for TypeInfer {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.underscore_token.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for TypeMacro {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.mac.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for ReturnType {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ match self {
+ ReturnType::Default => {}
+ ReturnType::Type(arrow, ty) => {
+ arrow.to_tokens(tokens);
+ ty.to_tokens(tokens);
+ }
+ }
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for BareFnArg {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ if let Some((name, colon)) = &self.name {
+ name.to_tokens(tokens);
+ colon.to_tokens(tokens);
+ }
+ self.ty.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for BareVariadic {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ if let Some((name, colon)) = &self.name {
+ name.to_tokens(tokens);
+ colon.to_tokens(tokens);
+ }
+ self.dots.to_tokens(tokens);
+ self.comma.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
+ impl ToTokens for Abi {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ self.extern_token.to_tokens(tokens);
+ self.name.to_tokens(tokens);
+ }
+ }
+}
diff --git a/rust/syn/verbatim.rs b/rust/syn/verbatim.rs
new file mode 100644
index 000000000000..54dc1cfa0d82
--- /dev/null
+++ b/rust/syn/verbatim.rs
@@ -0,0 +1,33 @@
+use crate::parse::ParseStream;
+use proc_macro2::{Delimiter, TokenStream};
+use std::cmp::Ordering;
+use std::iter;
+
+pub(crate) fn between<'a>(begin: ParseStream<'a>, end: ParseStream<'a>) -> TokenStream {
+ let end = end.cursor();
+ let mut cursor = begin.cursor();
+ assert!(crate::buffer::same_buffer(end, cursor));
+
+ let mut tokens = TokenStream::new();
+ while cursor != end {
+ let (tt, next) = cursor.token_tree().unwrap();
+
+ if crate::buffer::cmp_assuming_same_buffer(end, next) == Ordering::Less {
+ // A syntax node can cross the boundary of a None-delimited group
+ // due to such groups being transparent to the parser in most cases.
+ // Any time this occurs the group is known to be semantically
+ // irrelevant. https://github.com/dtolnay/syn/issues/1235
+ if let Some((inside, _span, after)) = cursor.group(Delimiter::None) {
+ assert!(next == after);
+ cursor = inside;
+ continue;
+ } else {
+ panic!("verbatim end must not be inside a delimited group");
+ }
+ }
+
+ tokens.extend(iter::once(tt));
+ cursor = next;
+ }
+ tokens
+}
diff --git a/rust/syn/whitespace.rs b/rust/syn/whitespace.rs
new file mode 100644
index 000000000000..a50b5069a68b
--- /dev/null
+++ b/rust/syn/whitespace.rs
@@ -0,0 +1,65 @@
+pub(crate) fn skip(mut s: &str) -> &str {
+ 'skip: while !s.is_empty() {
+ let byte = s.as_bytes()[0];
+ if byte == b'/' {
+ if s.starts_with("//")
+ && (!s.starts_with("///") || s.starts_with("////"))
+ && !s.starts_with("//!")
+ {
+ if let Some(i) = s.find('\n') {
+ s = &s[i + 1..];
+ continue;
+ } else {
+ return "";
+ }
+ } else if s.starts_with("/**/") {
+ s = &s[4..];
+ continue;
+ } else if s.starts_with("/*")
+ && (!s.starts_with("/**") || s.starts_with("/***"))
+ && !s.starts_with("/*!")
+ {
+ let mut depth = 0;
+ let bytes = s.as_bytes();
+ let mut i = 0;
+ let upper = bytes.len() - 1;
+ while i < upper {
+ if bytes[i] == b'/' && bytes[i + 1] == b'*' {
+ depth += 1;
+ i += 1; // eat '*'
+ } else if bytes[i] == b'*' && bytes[i + 1] == b'/' {
+ depth -= 1;
+ if depth == 0 {
+ s = &s[i + 2..];
+ continue 'skip;
+ }
+ i += 1; // eat '/'
+ }
+ i += 1;
+ }
+ return s;
+ }
+ }
+ match byte {
+ b' ' | 0x09..=0x0D => {
+ s = &s[1..];
+ continue;
+ }
+ b if b <= 0x7F => {}
+ _ => {
+ let ch = s.chars().next().unwrap();
+ if is_whitespace(ch) {
+ s = &s[ch.len_utf8()..];
+ continue;
+ }
+ }
+ }
+ return s;
+ }
+ s
+}
+
+fn is_whitespace(ch: char) -> bool {
+ // Rust treats left-to-right mark and right-to-left mark as whitespace
+ ch.is_whitespace() || ch == '\u{200e}' || ch == '\u{200f}'
+}
--
2.51.2
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH 15/18] rust: syn: add SPDX License Identifiers
2025-11-10 9:50 [PATCH 00/18] `syn` support Miguel Ojeda
` (13 preceding siblings ...)
2025-11-10 9:50 ` [PATCH 14/18] rust: syn: import crate Miguel Ojeda
@ 2025-11-10 9:50 ` Miguel Ojeda
2025-11-10 9:50 ` [PATCH 16/18] rust: syn: remove `unicode-ident` dependency Miguel Ojeda
` (4 subsequent siblings)
19 siblings, 0 replies; 57+ messages in thread
From: Miguel Ojeda @ 2025-11-10 9:50 UTC (permalink / raw)
To: Miguel Ojeda, Alex Gaynor, Nathan Chancellor, Nicolas Schier
Cc: Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
rust-for-linux, linux-kbuild, linux-kernel, patches
Originally, 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.
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
---
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(+)
diff --git a/rust/syn/attr.rs b/rust/syn/attr.rs
index 2bdf96ee7fa9..020b31f9de22 100644
--- a/rust/syn/attr.rs
+++ b/rust/syn/attr.rs
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
#[cfg(feature = "parsing")]
use crate::error::Error;
#[cfg(feature = "parsing")]
diff --git a/rust/syn/bigint.rs b/rust/syn/bigint.rs
index 66aaa9372540..d706f9f515e9 100644
--- a/rust/syn/bigint.rs
+++ b/rust/syn/bigint.rs
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
use std::ops::{AddAssign, MulAssign};
// For implementing base10_digits() accessor on LitInt.
diff --git a/rust/syn/buffer.rs b/rust/syn/buffer.rs
index 7b6a504eeb7c..406f70db323c 100644
--- a/rust/syn/buffer.rs
+++ b/rust/syn/buffer.rs
@@ -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.
diff --git a/rust/syn/classify.rs b/rust/syn/classify.rs
index 8eab19dbc37c..92a975bfe4aa 100644
--- a/rust/syn/classify.rs
+++ b/rust/syn/classify.rs
@@ -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"))]
diff --git a/rust/syn/custom_keyword.rs b/rust/syn/custom_keyword.rs
index cc4f632c981a..ff2c415f1aab 100644
--- a/rust/syn/custom_keyword.rs
+++ b/rust/syn/custom_keyword.rs
@@ -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.
///
diff --git a/rust/syn/custom_punctuation.rs b/rust/syn/custom_punctuation.rs
index eef5f5458459..d37c0e9c3a1e 100644
--- a/rust/syn/custom_punctuation.rs
+++ b/rust/syn/custom_punctuation.rs
@@ -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.
///
diff --git a/rust/syn/data.rs b/rust/syn/data.rs
index 96db2a0b7c6f..c32c1366c1db 100644
--- a/rust/syn/data.rs
+++ b/rust/syn/data.rs
@@ -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;
diff --git a/rust/syn/derive.rs b/rust/syn/derive.rs
index 3443ecfc05cb..27fd9f12c88c 100644
--- a/rust/syn/derive.rs
+++ b/rust/syn/derive.rs
@@ -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;
diff --git a/rust/syn/discouraged.rs b/rust/syn/discouraged.rs
index c8d6bfe89a14..2acd631ece84 100644
--- a/rust/syn/discouraged.rs
+++ b/rust/syn/discouraged.rs
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
//! Extensions to the parsing API with niche applicability.
use crate::buffer::Cursor;
diff --git a/rust/syn/drops.rs b/rust/syn/drops.rs
index c54308f02c13..2c4ae333dad8 100644
--- a/rust/syn/drops.rs
+++ b/rust/syn/drops.rs
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
use std::iter;
use std::mem::ManuallyDrop;
use std::ops::{Deref, DerefMut};
diff --git a/rust/syn/error.rs b/rust/syn/error.rs
index 63310543a3b4..6fa0faf7f4e4 100644
--- a/rust/syn/error.rs
+++ b/rust/syn/error.rs
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
#[cfg(feature = "parsing")]
use crate::buffer::Cursor;
use crate::thread::ThreadBound;
diff --git a/rust/syn/export.rs b/rust/syn/export.rs
index b9ea5c747b75..05dad324ba51 100644
--- a/rust/syn/export.rs
+++ b/rust/syn/export.rs
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
#[doc(hidden)]
pub use std::clone::Clone;
#[doc(hidden)]
diff --git a/rust/syn/expr.rs b/rust/syn/expr.rs
index 1e49d9a6633e..deb918436604 100644
--- a/rust/syn/expr.rs
+++ b/rust/syn/expr.rs
@@ -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;
diff --git a/rust/syn/ext.rs b/rust/syn/ext.rs
index 5cd79e863a9d..a9be9af42787 100644
--- a/rust/syn/ext.rs
+++ b/rust/syn/ext.rs
@@ -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;
diff --git a/rust/syn/file.rs b/rust/syn/file.rs
index 8956d82eee93..ce2d2680ca9a 100644
--- a/rust/syn/file.rs
+++ b/rust/syn/file.rs
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
use crate::attr::Attribute;
use crate::item::Item;
diff --git a/rust/syn/fixup.rs b/rust/syn/fixup.rs
index 6d2c3092d548..79b6d7618bb7 100644
--- a/rust/syn/fixup.rs
+++ b/rust/syn/fixup.rs
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
use crate::classify;
use crate::expr::Expr;
#[cfg(feature = "full")]
diff --git a/rust/syn/gen/clone.rs b/rust/syn/gen/clone.rs
index be2b698422da..dfb53182e378 100644
--- a/rust/syn/gen/clone.rs
+++ b/rust/syn/gen/clone.rs
@@ -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.
diff --git a/rust/syn/gen/debug.rs b/rust/syn/gen/debug.rs
index aa42e32c60ed..d594e57fcf21 100644
--- a/rust/syn/gen/debug.rs
+++ b/rust/syn/gen/debug.rs
@@ -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.
diff --git a/rust/syn/gen/eq.rs b/rust/syn/gen/eq.rs
index 128e8991eecc..79e9691b8c67 100644
--- a/rust/syn/gen/eq.rs
+++ b/rust/syn/gen/eq.rs
@@ -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.
diff --git a/rust/syn/gen/fold.rs b/rust/syn/gen/fold.rs
index 1f0afd31919d..0643a72f87ca 100644
--- a/rust/syn/gen/fold.rs
+++ b/rust/syn/gen/fold.rs
@@ -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.
diff --git a/rust/syn/gen/hash.rs b/rust/syn/gen/hash.rs
index 04f23453a117..fae2197a5610 100644
--- a/rust/syn/gen/hash.rs
+++ b/rust/syn/gen/hash.rs
@@ -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.
diff --git a/rust/syn/gen/visit.rs b/rust/syn/gen/visit.rs
index cd258fcde120..a82293c053d6 100644
--- a/rust/syn/gen/visit.rs
+++ b/rust/syn/gen/visit.rs
@@ -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.
diff --git a/rust/syn/gen/visit_mut.rs b/rust/syn/gen/visit_mut.rs
index 2bbd6895db75..08e134b43a92 100644
--- a/rust/syn/gen/visit_mut.rs
+++ b/rust/syn/gen/visit_mut.rs
@@ -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.
diff --git a/rust/syn/generics.rs b/rust/syn/generics.rs
index 0c77193da043..9f8df8a155e1 100644
--- a/rust/syn/generics.rs
+++ b/rust/syn/generics.rs
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
use crate::attr::Attribute;
use crate::expr::Expr;
use crate::ident::Ident;
diff --git a/rust/syn/group.rs b/rust/syn/group.rs
index 1534ae995dd5..57586c58fd92 100644
--- a/rust/syn/group.rs
+++ b/rust/syn/group.rs
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
use crate::error::Result;
use crate::parse::ParseBuffer;
use crate::token;
diff --git a/rust/syn/ident.rs b/rust/syn/ident.rs
index 8a8e8a50d9b0..2c4b56505bec 100644
--- a/rust/syn/ident.rs
+++ b/rust/syn/ident.rs
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
#[cfg(feature = "parsing")]
use crate::lookahead;
diff --git a/rust/syn/item.rs b/rust/syn/item.rs
index 1716f5137afb..1ab10cf218a6 100644
--- a/rust/syn/item.rs
+++ b/rust/syn/item.rs
@@ -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};
diff --git a/rust/syn/lib.rs b/rust/syn/lib.rs
index 79dc9e7c3324..b0006fd30b08 100644
--- a/rust/syn/lib.rs
+++ b/rust/syn/lib.rs
@@ -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
diff --git a/rust/syn/lifetime.rs b/rust/syn/lifetime.rs
index cc189d1ac91f..24bec7fe969d 100644
--- a/rust/syn/lifetime.rs
+++ b/rust/syn/lifetime.rs
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
#[cfg(feature = "parsing")]
use crate::lookahead;
use proc_macro2::{Ident, Span};
diff --git a/rust/syn/lit.rs b/rust/syn/lit.rs
index 45c26d56fed3..1d2d8bdccfb1 100644
--- a/rust/syn/lit.rs
+++ b/rust/syn/lit.rs
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
#[cfg(feature = "parsing")]
use crate::lookahead;
#[cfg(feature = "parsing")]
diff --git a/rust/syn/lookahead.rs b/rust/syn/lookahead.rs
index da13ffc47a7a..a7994cb6ae88 100644
--- a/rust/syn/lookahead.rs
+++ b/rust/syn/lookahead.rs
@@ -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;
diff --git a/rust/syn/mac.rs b/rust/syn/mac.rs
index 15107801cfee..ce4b022b4d14 100644
--- a/rust/syn/mac.rs
+++ b/rust/syn/mac.rs
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
#[cfg(feature = "parsing")]
use crate::error::Result;
#[cfg(feature = "parsing")]
diff --git a/rust/syn/macros.rs b/rust/syn/macros.rs
index 167f2cf260a7..8676f6492a9c 100644
--- a/rust/syn/macros.rs
+++ b/rust/syn/macros.rs
@@ -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)
diff --git a/rust/syn/meta.rs b/rust/syn/meta.rs
index ffeeb2629f4f..2dd138e6dd55 100644
--- a/rust/syn/meta.rs
+++ b/rust/syn/meta.rs
@@ -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};
diff --git a/rust/syn/op.rs b/rust/syn/op.rs
index 575d9faa1273..73dada3fae2d 100644
--- a/rust/syn/op.rs
+++ b/rust/syn/op.rs
@@ -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"))))]
diff --git a/rust/syn/parse.rs b/rust/syn/parse.rs
index 57531005ac4e..c6f6c0eece02 100644
--- a/rust/syn/parse.rs
+++ b/rust/syn/parse.rs
@@ -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`]
diff --git a/rust/syn/parse_macro_input.rs b/rust/syn/parse_macro_input.rs
index f0660aedd7df..2f977754d41c 100644
--- a/rust/syn/parse_macro_input.rs
+++ b/rust/syn/parse_macro_input.rs
@@ -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.
///
diff --git a/rust/syn/parse_quote.rs b/rust/syn/parse_quote.rs
index 2db20597c436..7cc7b9b8fd75 100644
--- a/rust/syn/parse_quote.rs
+++ b/rust/syn/parse_quote.rs
@@ -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.
///
diff --git a/rust/syn/pat.rs b/rust/syn/pat.rs
index 81a2f183f6b9..46edd63d5ed8 100644
--- a/rust/syn/pat.rs
+++ b/rust/syn/pat.rs
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
use crate::attr::Attribute;
use crate::expr::Member;
use crate::ident::Ident;
diff --git a/rust/syn/path.rs b/rust/syn/path.rs
index d2fcb9bc5d28..f2453bea4a3c 100644
--- a/rust/syn/path.rs
+++ b/rust/syn/path.rs
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
#[cfg(feature = "parsing")]
use crate::error::Result;
use crate::expr::Expr;
diff --git a/rust/syn/precedence.rs b/rust/syn/precedence.rs
index 1891bfc202fd..cc4dba24a433 100644
--- a/rust/syn/precedence.rs
+++ b/rust/syn/precedence.rs
@@ -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")]
diff --git a/rust/syn/print.rs b/rust/syn/print.rs
index 07409932677b..d73262cda060 100644
--- a/rust/syn/print.rs
+++ b/rust/syn/print.rs
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
use proc_macro2::TokenStream;
use quote::ToTokens;
diff --git a/rust/syn/punctuated.rs b/rust/syn/punctuated.rs
index ebaaa94f9a26..f79152940db6 100644
--- a/rust/syn/punctuated.rs
+++ b/rust/syn/punctuated.rs
@@ -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.
diff --git a/rust/syn/restriction.rs b/rust/syn/restriction.rs
index 6e6758f3cd73..b844f64c3a73 100644
--- a/rust/syn/restriction.rs
+++ b/rust/syn/restriction.rs
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
use crate::path::Path;
use crate::token;
diff --git a/rust/syn/scan_expr.rs b/rust/syn/scan_expr.rs
index 3d88cf06acea..a5fd1ddc1501 100644
--- a/rust/syn/scan_expr.rs
+++ b/rust/syn/scan_expr.rs
@@ -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};
diff --git a/rust/syn/sealed.rs b/rust/syn/sealed.rs
index dc804742d12d..541df9623755 100644
--- a/rust/syn/sealed.rs
+++ b/rust/syn/sealed.rs
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
#[cfg(feature = "parsing")]
pub(crate) mod lookahead {
pub trait Sealed: Copy {}
diff --git a/rust/syn/span.rs b/rust/syn/span.rs
index eb2779479aaa..e6d55b3ccd03 100644
--- a/rust/syn/span.rs
+++ b/rust/syn/span.rs
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
use proc_macro2::extra::DelimSpan;
use proc_macro2::{Delimiter, Group, Span, TokenStream};
diff --git a/rust/syn/spanned.rs b/rust/syn/spanned.rs
index 17b69e9f5b28..fcc93699f742 100644
--- a/rust/syn/spanned.rs
+++ b/rust/syn/spanned.rs
@@ -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.
//!
diff --git a/rust/syn/stmt.rs b/rust/syn/stmt.rs
index 8ea0077f63df..029171a98dca 100644
--- a/rust/syn/stmt.rs
+++ b/rust/syn/stmt.rs
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
use crate::attr::Attribute;
use crate::expr::Expr;
use crate::item::Item;
diff --git a/rust/syn/thread.rs b/rust/syn/thread.rs
index b33d248afc60..4165a173d9e1 100644
--- a/rust/syn/thread.rs
+++ b/rust/syn/thread.rs
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
use std::fmt::{self, Debug};
use std::thread::{self, ThreadId};
diff --git a/rust/syn/token.rs b/rust/syn/token.rs
index 752c188883cb..18345cc5831a 100644
--- a/rust/syn/token.rs
+++ b/rust/syn/token.rs
@@ -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
diff --git a/rust/syn/tt.rs b/rust/syn/tt.rs
index 7d5d6a1ac326..fc7adec3da90 100644
--- a/rust/syn/tt.rs
+++ b/rust/syn/tt.rs
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
use proc_macro2::{Delimiter, TokenStream, TokenTree};
use std::hash::{Hash, Hasher};
diff --git a/rust/syn/ty.rs b/rust/syn/ty.rs
index c093f5877b3c..ae660d2d2e74 100644
--- a/rust/syn/ty.rs
+++ b/rust/syn/ty.rs
@@ -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};
diff --git a/rust/syn/verbatim.rs b/rust/syn/verbatim.rs
index 54dc1cfa0d82..97bc08f70afe 100644
--- a/rust/syn/verbatim.rs
+++ b/rust/syn/verbatim.rs
@@ -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;
diff --git a/rust/syn/whitespace.rs b/rust/syn/whitespace.rs
index a50b5069a68b..b7319bd7af18 100644
--- a/rust/syn/whitespace.rs
+++ b/rust/syn/whitespace.rs
@@ -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];
--
2.51.2
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH 16/18] rust: syn: remove `unicode-ident` dependency
2025-11-10 9:50 [PATCH 00/18] `syn` support Miguel Ojeda
` (14 preceding siblings ...)
2025-11-10 9:50 ` [PATCH 15/18] rust: syn: add SPDX License Identifiers Miguel Ojeda
@ 2025-11-10 9:50 ` Miguel Ojeda
2025-11-10 11:47 ` Alice Ryhl
2025-11-10 9:50 ` [PATCH 17/18] rust: syn: add `README.md` Miguel Ojeda
` (3 subsequent siblings)
19 siblings, 1 reply; 57+ messages in thread
From: Miguel Ojeda @ 2025-11-10 9:50 UTC (permalink / raw)
To: Miguel Ojeda, Alex Gaynor, Nathan Chancellor, Nicolas Schier
Cc: Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
rust-for-linux, linux-kbuild, linux-kernel, patches
The `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.
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
---
rust/syn/ident.rs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/rust/syn/ident.rs b/rust/syn/ident.rs
index 2c4b56505bec..03ccebf9c022 100644
--- a/rust/syn/ident.rs
+++ b/rust/syn/ident.rs
@@ -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 ch in chars {
- if !unicode_ident::is_xid_continue(ch) {
+ if !(ch == '_' || ch.is_ascii_alphanumeric()) {
return false;
}
}
--
2.51.2
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH 17/18] rust: syn: add `README.md`
2025-11-10 9:50 [PATCH 00/18] `syn` support Miguel Ojeda
` (15 preceding siblings ...)
2025-11-10 9:50 ` [PATCH 16/18] rust: syn: remove `unicode-ident` dependency Miguel Ojeda
@ 2025-11-10 9:50 ` Miguel Ojeda
2025-11-10 11:47 ` Alice Ryhl
2025-11-10 9:50 ` [PATCH 18/18] rust: syn: enable support in kbuild Miguel Ojeda
` (2 subsequent siblings)
19 siblings, 1 reply; 57+ messages in thread
From: Miguel Ojeda @ 2025-11-10 9:50 UTC (permalink / raw)
To: Miguel Ojeda, Alex Gaynor, Nathan Chancellor, Nicolas Schier
Cc: Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
rust-for-linux, linux-kbuild, linux-kernel, patches
Originally, 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.
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
---
rust/syn/README.md | 13 +++++++++++++
1 file changed, 13 insertions(+)
create mode 100644 rust/syn/README.md
diff --git a/rust/syn/README.md b/rust/syn/README.md
new file mode 100644
index 000000000000..d3e3981da2fe
--- /dev/null
+++ b/rust/syn/README.md
@@ -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
--
2.51.2
^ permalink raw reply related [flat|nested] 57+ messages in thread
* [PATCH 18/18] rust: syn: enable support in kbuild
2025-11-10 9:50 [PATCH 00/18] `syn` support Miguel Ojeda
` (16 preceding siblings ...)
2025-11-10 9:50 ` [PATCH 17/18] rust: syn: add `README.md` Miguel Ojeda
@ 2025-11-10 9:50 ` Miguel Ojeda
2025-11-10 11:49 ` Alice Ryhl
2025-11-10 19:43 ` John Hubbard
2025-11-10 13:59 ` [PATCH 00/18] `syn` support Gary Guo
2025-11-10 15:59 ` Jonathan Corbet
19 siblings, 2 replies; 57+ messages in thread
From: Miguel Ojeda @ 2025-11-10 9:50 UTC (permalink / raw)
To: Miguel Ojeda, Alex Gaynor, Nathan Chancellor, Nicolas Schier
Cc: Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
rust-for-linux, linux-kbuild, linux-kernel, patches
With all the new files in place and ready from the new crate, enable
the support for it in the build system.
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
---
Makefile | 1 +
rust/Makefile | 39 +++++++++++++++++++++++++++----
scripts/generate_rust_analyzer.py | 7 ++++++
3 files changed, 43 insertions(+), 4 deletions(-)
diff --git a/Makefile b/Makefile
index f1b38b7fed1e..5364b3ad3600 100644
--- a/Makefile
+++ b/Makefile
@@ -1833,6 +1833,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)
diff --git a/rust/Makefile b/rust/Makefile
index 801a8cbf3bdd..984aec608c27 100644
--- a/rust/Makefile
+++ b/rust/Makefile
@@ -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)
@@ -164,11 +180,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
@@ -240,6 +261,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
@@ -497,19 +522,24 @@ $(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_hostlibrary)
+$(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_hostlibrary)
+
quiet_cmd_rustc_procmacro = $(RUSTC_OR_CLIPPY_QUIET) P $@
cmd_rustc_procmacro = \
$(RUSTC_OR_CLIPPY) $(rust_common_flags) $(rustc_target_flags) \
-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 $<
# 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
@@ -534,6 +564,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
diff --git a/scripts/generate_rust_analyzer.py b/scripts/generate_rust_analyzer.py
index 4faf153ed2ee..5b6f7b8d6918 100755
--- a/scripts/generate_rust_analyzer.py
+++ b/scripts/generate_rust_analyzer.py
@@ -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",
--
2.51.2
^ permalink raw reply related [flat|nested] 57+ messages in thread
* Re: [PATCH 02/18] rust: kbuild: introduce `core-flags` and `core-skip_flags`
2025-11-10 9:50 ` [PATCH 02/18] rust: kbuild: introduce `core-flags` and `core-skip_flags` Miguel Ojeda
@ 2025-11-10 10:19 ` Miguel Ojeda
2025-11-10 11:50 ` Alice Ryhl
2025-11-10 10:27 ` Alice Ryhl
2025-11-10 19:18 ` John Hubbard
2 siblings, 1 reply; 57+ messages in thread
From: Miguel Ojeda @ 2025-11-10 10:19 UTC (permalink / raw)
To: Miguel Ojeda
Cc: Alex Gaynor, Nathan Chancellor, Nicolas Schier, Boqun Feng,
Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Alice Ryhl, Trevor Gross, Danilo Krummrich, rust-for-linux,
linux-kbuild, linux-kernel, patches
On Mon, Nov 10, 2025 at 10:51 AM Miguel Ojeda <ojeda@kernel.org> wrote:
>
> Thus do so here for `core`, which simplifies a bit the `Makefile`
> (including the next commit) and makes it more consistent.
We may want to eventually use `--cap-lints=allow` here too, but the
skip flags here were already feeling a bit more than needed for the
series.
Cheers,
Miguel
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 01/18] rust: condvar: avoid `pub` in example
2025-11-10 9:50 ` [PATCH 01/18] rust: condvar: avoid `pub` in example Miguel Ojeda
@ 2025-11-10 10:24 ` Alice Ryhl
2025-11-10 11:10 ` Miguel Ojeda
0 siblings, 1 reply; 57+ messages in thread
From: Alice Ryhl @ 2025-11-10 10:24 UTC (permalink / raw)
To: Miguel Ojeda
Cc: Alex Gaynor, Nathan Chancellor, Nicolas Schier, Boqun Feng,
Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, rust-for-linux, linux-kbuild,
linux-kernel, patches
On Mon, Nov 10, 2025 at 10:50:06AM +0100, Miguel Ojeda wrote:
> The future move of pin-init to `syn` uncovers the following unreachable
> public item in an example:
>
> error: unreachable `pub` item
> --> rust/doctests_kernel_generated.rs:14683:1
> |
> 14683 | pub struct Example {
> | ---^^^^^^^^^^^^^^^
> | |
> | help: consider restricting its visibility: `pub(crate)`
> |
> = help: or consider exporting it for use by other crates
> = note: `-D unreachable-pub` implied by `-D warnings`
> = help: to override `-D warnings` add `#[allow(unreachable_pub)]`
>
> There is no real downside of keeping the example as-is until the
> `syn`-based pin-init is introduced, so there is no need to treat it as
> a fix nor to backport it. However, we still need to change it before
> introducing the new pin-init.
>
> Thus do so.
>
> Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
The unreachable_pub warning normally does not trigger for documentation
tests since using `pub` in documentation tests is not wrong. So this
sounds like a bug in our doc-test setup.
Regardless, I don't mind changing it here for now.
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 14/18] rust: syn: import crate
2025-11-10 9:50 ` [PATCH 14/18] rust: syn: import crate Miguel Ojeda
@ 2025-11-10 10:26 ` Miguel Ojeda
0 siblings, 0 replies; 57+ messages in thread
From: Miguel Ojeda @ 2025-11-10 10:26 UTC (permalink / raw)
To: Miguel Ojeda
Cc: Alex Gaynor, Nathan Chancellor, Nicolas Schier, Boqun Feng,
Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Alice Ryhl, Trevor Gross, Danilo Krummrich, rust-for-linux,
linux-kbuild, linux-kernel, patches
On Mon, Nov 10, 2025 at 10:52 AM Miguel Ojeda <ojeda@kernel.org> wrote:
>
> This is a subset of the Rust `syn` crate, version 2.0.106 (released
> 2025-08-16), licensed under "Apache-2.0 OR MIT", from:
In case someone is wondering: I didn't use the very latest since it
was quite new (even if the diff was fairly small).
Same for `quote`.
Cheers,
Miguel
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 02/18] rust: kbuild: introduce `core-flags` and `core-skip_flags`
2025-11-10 9:50 ` [PATCH 02/18] rust: kbuild: introduce `core-flags` and `core-skip_flags` Miguel Ojeda
2025-11-10 10:19 ` Miguel Ojeda
@ 2025-11-10 10:27 ` Alice Ryhl
2025-11-10 19:18 ` John Hubbard
2 siblings, 0 replies; 57+ messages in thread
From: Alice Ryhl @ 2025-11-10 10:27 UTC (permalink / raw)
To: Miguel Ojeda
Cc: Alex Gaynor, Nathan Chancellor, Nicolas Schier, Boqun Feng,
Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, rust-for-linux, linux-kbuild,
linux-kernel, patches
On Mon, Nov 10, 2025 at 10:50:07AM +0100, Miguel Ojeda wrote:
> 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.
>
> Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 03/18] rust: kbuild: simplify `--cfg` handling
2025-11-10 9:50 ` [PATCH 03/18] rust: kbuild: simplify `--cfg` handling Miguel Ojeda
@ 2025-11-10 10:33 ` Alice Ryhl
0 siblings, 0 replies; 57+ messages in thread
From: Alice Ryhl @ 2025-11-10 10:33 UTC (permalink / raw)
To: Miguel Ojeda
Cc: Alex Gaynor, Nathan Chancellor, Nicolas Schier, Boqun Feng,
Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, rust-for-linux, linux-kbuild,
linux-kernel, patches
On Mon, Nov 10, 2025 at 10:50:08AM +0100, Miguel Ojeda wrote:
> We need to handle `cfg`s 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`.
>
> Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
For anyone else reviewing this, here is the relevant part of the
makefile that calls generate_rust_analyzer:
rust-analyzer:
$(Q)MAKEFLAGS= $(srctree)/scripts/generate_rust_analyzer.py \
--cfgs='core=$(core-cfgs)' $(core-edition) \
$(realpath $(srctree)) $(realpath $(objtree)) \
$(rustc_sysroot) $(RUST_LIB_SRC) $(if $(KBUILD_EXTMOD),$(srcroot)) \
> rust-project.json
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 04/18] rust: kbuild: add host library support
2025-11-10 9:50 ` [PATCH 04/18] rust: kbuild: add host library support Miguel Ojeda
@ 2025-11-10 10:43 ` Alice Ryhl
2025-11-10 11:17 ` Miguel Ojeda
0 siblings, 1 reply; 57+ messages in thread
From: Alice Ryhl @ 2025-11-10 10:43 UTC (permalink / raw)
To: Miguel Ojeda
Cc: Alex Gaynor, Nathan Chancellor, Nicolas Schier, Boqun Feng,
Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, rust-for-linux, linux-kbuild,
linux-kernel, patches
On Mon, Nov 10, 2025 at 10:50:09AM +0100, Miguel Ojeda wrote:
> Add the a host library rule that produces `.rlib` files to be used by the
> `macros` crate.
>
> Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
We currently have two kinds of build rules:
* cmd_host-rust used for host binaries such as generate_rust_target
* cmd_rustc_procmacro used for proc macros
This is a library for the second case, not the first case, so it may
make more sense to name this rule procmacrolibrary?
Note that HOSTRUSTFLAGS is passed to only the first category, but this
naming makes it sound like it should be passed to this new build rule,
but I don't think it should be since it is not passed to proc macros.
Alice
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 07/18] rust: proc-macro2: remove `unicode_ident` dependency
2025-11-10 9:50 ` [PATCH 07/18] rust: proc-macro2: remove `unicode_ident` dependency Miguel Ojeda
@ 2025-11-10 10:50 ` Alice Ryhl
0 siblings, 0 replies; 57+ messages in thread
From: Alice Ryhl @ 2025-11-10 10:50 UTC (permalink / raw)
To: Miguel Ojeda
Cc: Alex Gaynor, Nathan Chancellor, Nicolas Schier, Boqun Feng,
Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, rust-for-linux, linux-kbuild,
linux-kernel, patches
On Mon, Nov 10, 2025 at 10:50:12AM +0100, Miguel Ojeda wrote:
> The `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.
>
> Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
Verified that these match exactly for ascii characters.
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 08/18] rust: proc-macro2: add `README.md`
2025-11-10 9:50 ` [PATCH 08/18] rust: proc-macro2: add `README.md` Miguel Ojeda
@ 2025-11-10 10:52 ` Alice Ryhl
0 siblings, 0 replies; 57+ messages in thread
From: Alice Ryhl @ 2025-11-10 10:52 UTC (permalink / raw)
To: Miguel Ojeda
Cc: Alex Gaynor, Nathan Chancellor, Nicolas Schier, Boqun Feng,
Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, rust-for-linux, linux-kbuild,
linux-kernel, patches
On Mon, Nov 10, 2025 at 10:50:13AM +0100, Miguel Ojeda wrote:
> Originally, 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.
>
> Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
> ---
> rust/proc-macro2/README.md | 13 +++++++++++++
> 1 file changed, 13 insertions(+)
> create mode 100644 rust/proc-macro2/README.md
>
> diff --git a/rust/proc-macro2/README.md b/rust/proc-macro2/README.md
> new file mode 100644
> index 000000000000..af044fee4f59
> --- /dev/null
> +++ b/rust/proc-macro2/README.md
> @@ -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
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 01/18] rust: condvar: avoid `pub` in example
2025-11-10 10:24 ` Alice Ryhl
@ 2025-11-10 11:10 ` Miguel Ojeda
0 siblings, 0 replies; 57+ messages in thread
From: Miguel Ojeda @ 2025-11-10 11:10 UTC (permalink / raw)
To: Alice Ryhl
Cc: Miguel Ojeda, Alex Gaynor, Nathan Chancellor, Nicolas Schier,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Trevor Gross, Danilo Krummrich, rust-for-linux,
linux-kbuild, linux-kernel, patches
On Mon, Nov 10, 2025 at 11:24 AM Alice Ryhl <aliceryhl@google.com> wrote:
>
> The unreachable_pub warning normally does not trigger for documentation
> tests since using `pub` in documentation tests is not wrong. So this
> sounds like a bug in our doc-test setup.
Yeah, we can allow the warning for doctests, that is easy.
In any case, this was needed for the future pin-init, not the current
one, so I should have probably removed it (we had a bigger branch with
the new pin-init).
Cheers,
Miguel
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 04/18] rust: kbuild: add host library support
2025-11-10 10:43 ` Alice Ryhl
@ 2025-11-10 11:17 ` Miguel Ojeda
0 siblings, 0 replies; 57+ messages in thread
From: Miguel Ojeda @ 2025-11-10 11:17 UTC (permalink / raw)
To: Alice Ryhl
Cc: Miguel Ojeda, Alex Gaynor, Nathan Chancellor, Nicolas Schier,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Trevor Gross, Danilo Krummrich, rust-for-linux,
linux-kbuild, linux-kernel, patches
On Mon, Nov 10, 2025 at 11:43 AM Alice Ryhl <aliceryhl@google.com> wrote:
>
> This is a library for the second case, not the first case, so it may
> make more sense to name this rule procmacrolibrary?
Making it more concrete sounds good to me. We can always rename later
if we find some other use.
Cheers,
Miguel
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 09/18] rust: proc-macro2: enable support in kbuild
2025-11-10 9:50 ` [PATCH 09/18] rust: proc-macro2: enable support in kbuild Miguel Ojeda
@ 2025-11-10 11:38 ` Alice Ryhl
2025-11-10 13:10 ` Gary Guo
2025-11-10 19:34 ` John Hubbard
1 sibling, 1 reply; 57+ messages in thread
From: Alice Ryhl @ 2025-11-10 11:38 UTC (permalink / raw)
To: Miguel Ojeda
Cc: Alex Gaynor, Nathan Chancellor, Nicolas Schier, Boqun Feng,
Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, rust-for-linux, linux-kbuild,
linux-kernel, patches
On Mon, Nov 10, 2025 at 10:50:14AM +0100, Miguel Ojeda wrote:
> With 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.
>
> Link: https://github.com/rust-lang/rust/pull/123431 [1]
> Link: https://github.com/rust-lang/rust/pull/112711 [2]
> Link: https://github.com/rust-lang/rust/pull/119651 [3]
> Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
> ---
> Makefile | 3 +++
> rust/Makefile | 32 +++++++++++++++++++++++++++++--
> scripts/generate_rust_analyzer.py | 7 +++++++
> 3 files changed, 40 insertions(+), 2 deletions(-)
>
> diff --git a/Makefile b/Makefile
> index fb4389aa5d5f..6ff887523eee 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -1830,6 +1830,9 @@ 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)
>
> diff --git a/rust/Makefile b/rust/Makefile
> index 9eea6563ef35..a614a23023cb 100644
> --- a/rust/Makefile
> +++ b/rust/Makefile
> @@ -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))
> +
I don't understand this. We enable the features even on 1.79, but we
only pass the proc_macro_span_file, proc_macro_span_location cfgs on
1.88 and above?
We add the appropriate feature(_) invocations on older compilers, so
should we not support those things on those compilers?
Alice
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 13/18] rust: quote: enable support in kbuild
2025-11-10 9:50 ` [PATCH 13/18] rust: quote: enable support in kbuild Miguel Ojeda
@ 2025-11-10 11:44 ` Alice Ryhl
2025-11-10 13:13 ` Gary Guo
0 siblings, 1 reply; 57+ messages in thread
From: Alice Ryhl @ 2025-11-10 11:44 UTC (permalink / raw)
To: Miguel Ojeda
Cc: Alex Gaynor, Nathan Chancellor, Nicolas Schier, Boqun Feng,
Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, rust-for-linux, linux-kbuild,
linux-kernel, patches
On Mon, Nov 10, 2025 at 10:50:18AM +0100, Miguel Ojeda wrote:
> With all the new files in place and ready from the new crate, enable
> the support for it in the build system.
>
> Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
> diff --git a/rust/Makefile b/rust/Makefile
> index a614a23023cb..801a8cbf3bdd 100644
> --- a/rust/Makefile
> +++ b/rust/Makefile
> @@ -199,8 +218,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 \
This change seems unrelated?
Alice
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 16/18] rust: syn: remove `unicode-ident` dependency
2025-11-10 9:50 ` [PATCH 16/18] rust: syn: remove `unicode-ident` dependency Miguel Ojeda
@ 2025-11-10 11:47 ` Alice Ryhl
0 siblings, 0 replies; 57+ messages in thread
From: Alice Ryhl @ 2025-11-10 11:47 UTC (permalink / raw)
To: Miguel Ojeda
Cc: Alex Gaynor, Nathan Chancellor, Nicolas Schier, Boqun Feng,
Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, rust-for-linux, linux-kbuild,
linux-kernel, patches
On Mon, Nov 10, 2025 at 10:50:21AM +0100, Miguel Ojeda wrote:
> The `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.
>
> Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 17/18] rust: syn: add `README.md`
2025-11-10 9:50 ` [PATCH 17/18] rust: syn: add `README.md` Miguel Ojeda
@ 2025-11-10 11:47 ` Alice Ryhl
0 siblings, 0 replies; 57+ messages in thread
From: Alice Ryhl @ 2025-11-10 11:47 UTC (permalink / raw)
To: Miguel Ojeda
Cc: Alex Gaynor, Nathan Chancellor, Nicolas Schier, Boqun Feng,
Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, rust-for-linux, linux-kbuild,
linux-kernel, patches
On Mon, Nov 10, 2025 at 10:50:22AM +0100, Miguel Ojeda wrote:
> Originally, 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.
>
> Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
> ---
> rust/syn/README.md | 13 +++++++++++++
> 1 file changed, 13 insertions(+)
> create mode 100644 rust/syn/README.md
>
> diff --git a/rust/syn/README.md b/rust/syn/README.md
> new file mode 100644
> index 000000000000..d3e3981da2fe
> --- /dev/null
> +++ b/rust/syn/README.md
> @@ -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
> --
> 2.51.2
>
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 18/18] rust: syn: enable support in kbuild
2025-11-10 9:50 ` [PATCH 18/18] rust: syn: enable support in kbuild Miguel Ojeda
@ 2025-11-10 11:49 ` Alice Ryhl
2025-11-10 13:38 ` Miguel Ojeda
2025-11-10 19:43 ` John Hubbard
1 sibling, 1 reply; 57+ messages in thread
From: Alice Ryhl @ 2025-11-10 11:49 UTC (permalink / raw)
To: Miguel Ojeda
Cc: Alex Gaynor, Nathan Chancellor, Nicolas Schier, Boqun Feng,
Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, rust-for-linux, linux-kbuild,
linux-kernel, patches
On Mon, Nov 10, 2025 at 10:50:23AM +0100, Miguel Ojeda wrote:
> With all the new files in place and ready from the new crate, enable
> the support for it in the build system.
>
> Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
> quiet_cmd_rustc_procmacro = $(RUSTC_OR_CLIPPY_QUIET) P $@
> cmd_rustc_procmacro = \
> $(RUSTC_OR_CLIPPY) $(rust_common_flags) $(rustc_target_flags) \
> -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 $<
This change seems unrelated?
Alice
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 02/18] rust: kbuild: introduce `core-flags` and `core-skip_flags`
2025-11-10 10:19 ` Miguel Ojeda
@ 2025-11-10 11:50 ` Alice Ryhl
0 siblings, 0 replies; 57+ messages in thread
From: Alice Ryhl @ 2025-11-10 11:50 UTC (permalink / raw)
To: Miguel Ojeda
Cc: Miguel Ojeda, Alex Gaynor, Nathan Chancellor, Nicolas Schier,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Trevor Gross, Danilo Krummrich, rust-for-linux,
linux-kbuild, linux-kernel, patches
On Mon, Nov 10, 2025 at 11:19:19AM +0100, Miguel Ojeda wrote:
> On Mon, Nov 10, 2025 at 10:51 AM Miguel Ojeda <ojeda@kernel.org> wrote:
> >
> > Thus do so here for `core`, which simplifies a bit the `Makefile`
> > (including the next commit) and makes it more consistent.
>
> We may want to eventually use `--cap-lints=allow` here too, but the
> skip flags here were already feeling a bit more than needed for the
> series.
Using cap-lints allow for core sgtm.
Alice
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 09/18] rust: proc-macro2: enable support in kbuild
2025-11-10 11:38 ` Alice Ryhl
@ 2025-11-10 13:10 ` Gary Guo
2025-11-10 13:28 ` Miguel Ojeda
0 siblings, 1 reply; 57+ messages in thread
From: Gary Guo @ 2025-11-10 13:10 UTC (permalink / raw)
To: Alice Ryhl
Cc: Miguel Ojeda, Alex Gaynor, Nathan Chancellor, Nicolas Schier,
Boqun Feng, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, rust-for-linux, linux-kbuild,
linux-kernel, patches
On Mon, 10 Nov 2025 11:38:04 +0000
Alice Ryhl <aliceryhl@google.com> wrote:
> On Mon, Nov 10, 2025 at 10:50:14AM +0100, Miguel Ojeda wrote:
> > With 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.
> >
> > Link: https://github.com/rust-lang/rust/pull/123431 [1]
> > Link: https://github.com/rust-lang/rust/pull/112711 [2]
> > Link: https://github.com/rust-lang/rust/pull/119651 [3]
> > Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
> > ---
> > Makefile | 3 +++
> > rust/Makefile | 32 +++++++++++++++++++++++++++++--
> > scripts/generate_rust_analyzer.py | 7 +++++++
> > 3 files changed, 40 insertions(+), 2 deletions(-)
> >
> > diff --git a/Makefile b/Makefile
> > index fb4389aa5d5f..6ff887523eee 100644
> > --- a/Makefile
> > +++ b/Makefile
> > @@ -1830,6 +1830,9 @@ 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)
> >
> > diff --git a/rust/Makefile b/rust/Makefile
> > index 9eea6563ef35..a614a23023cb 100644
> > --- a/rust/Makefile
> > +++ b/rust/Makefile
> > @@ -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))
> > +
>
> I don't understand this. We enable the features even on 1.79, but we
> only pass the proc_macro_span_file, proc_macro_span_location cfgs on
> 1.88 and above?
>
> We add the appropriate feature(_) invocations on older compilers, so
> should we not support those things on those compilers?
>
> Alice
For 1.79- it switches to any polyfill for byte_character and
c_str_literals using cfg no_literal_byte_character and
no_literal_c_string. These feature gates are stablised already so I
think turning on features on makes sense for this scenario.
For 1.88+, `Span::file`, `Span::line` etc are stable so proc-macro2 can
stop using polyfills. These APIs are not gated under specific feature
gates before stablising however. They were gated under the generic
`proc_macro_span` feature gate and only renamed to
`proc_macro_span_location` during stabilisation. So in this case
there's no already-stable feature flags to turn on. (proc_macro_span
feature would make these APIs usable in 1.79, but that's a
still-unstable feature flag in all versions of rustc).
So I think the implementation here is sensible. I believe Miguel's
patch is also pretty much replicating the logic in proc-macro2's
build.rs.
Best,
Gary
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 13/18] rust: quote: enable support in kbuild
2025-11-10 11:44 ` Alice Ryhl
@ 2025-11-10 13:13 ` Gary Guo
2025-11-10 13:22 ` Miguel Ojeda
0 siblings, 1 reply; 57+ messages in thread
From: Gary Guo @ 2025-11-10 13:13 UTC (permalink / raw)
To: Alice Ryhl
Cc: Miguel Ojeda, Alex Gaynor, Nathan Chancellor, Nicolas Schier,
Boqun Feng, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, rust-for-linux, linux-kbuild,
linux-kernel, patches
On Mon, 10 Nov 2025 11:44:03 +0000
Alice Ryhl <aliceryhl@google.com> wrote:
> On Mon, Nov 10, 2025 at 10:50:18AM +0100, Miguel Ojeda wrote:
> > With all the new files in place and ready from the new crate, enable
> > the support for it in the build system.
> >
> > Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
>
> > diff --git a/rust/Makefile b/rust/Makefile
> > index a614a23023cb..801a8cbf3bdd 100644
> > --- a/rust/Makefile
> > +++ b/rust/Makefile
> > @@ -199,8 +218,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 \
>
> This change seems unrelated?
>
> Alice
This is to be able to skip over edition flags for `quote` when building
the rusttestlib?
Best,
Gary
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 13/18] rust: quote: enable support in kbuild
2025-11-10 13:13 ` Gary Guo
@ 2025-11-10 13:22 ` Miguel Ojeda
2025-11-10 13:35 ` Alice Ryhl
0 siblings, 1 reply; 57+ messages in thread
From: Miguel Ojeda @ 2025-11-10 13:22 UTC (permalink / raw)
To: Gary Guo
Cc: Alice Ryhl, Miguel Ojeda, Alex Gaynor, Nathan Chancellor,
Nicolas Schier, Boqun Feng, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Trevor Gross, Danilo Krummrich, rust-for-linux,
linux-kbuild, linux-kernel, patches
On Mon, Nov 10, 2025 at 2:13 PM Gary Guo <gary@garyguo.net> wrote:
>
> This is to be able to skip over edition flags for `quote` when building
> the rusttestlib?
Yes, it is needed to support skipping the flags, which isn't needed
until this patch.
It can be done earlier separately since it doesn't hurt -- a simpler
option is just to mention it here in the log.
Cheers,
Miguel
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 09/18] rust: proc-macro2: enable support in kbuild
2025-11-10 13:10 ` Gary Guo
@ 2025-11-10 13:28 ` Miguel Ojeda
2025-11-10 13:34 ` Alice Ryhl
0 siblings, 1 reply; 57+ messages in thread
From: Miguel Ojeda @ 2025-11-10 13:28 UTC (permalink / raw)
To: Gary Guo
Cc: Alice Ryhl, Miguel Ojeda, Alex Gaynor, Nathan Chancellor,
Nicolas Schier, Boqun Feng, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Trevor Gross, Danilo Krummrich, rust-for-linux,
linux-kbuild, linux-kernel, patches
On Mon, Nov 10, 2025 at 2:10 PM Gary Guo <gary@garyguo.net> wrote:
>
> So I think the implementation here is sensible. I believe Miguel's
> patch is also pretty much replicating the logic in proc-macro2's
> build.rs.
Exactly, I was essentially following what upstream does for stable compilers.
(More generally, even if a feature may work, if upstream doesn't
usually test "older nightlies", then I wonder if we should enable such
combinations/setups anyway, unless we need them for a particular
reason).
Cheers,
Miguel
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 09/18] rust: proc-macro2: enable support in kbuild
2025-11-10 13:28 ` Miguel Ojeda
@ 2025-11-10 13:34 ` Alice Ryhl
0 siblings, 0 replies; 57+ messages in thread
From: Alice Ryhl @ 2025-11-10 13:34 UTC (permalink / raw)
To: Miguel Ojeda
Cc: Gary Guo, Miguel Ojeda, Alex Gaynor, Nathan Chancellor,
Nicolas Schier, Boqun Feng, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Trevor Gross, Danilo Krummrich, rust-for-linux,
linux-kbuild, linux-kernel, patches
On Mon, Nov 10, 2025 at 02:28:06PM +0100, Miguel Ojeda wrote:
> On Mon, Nov 10, 2025 at 2:10 PM Gary Guo <gary@garyguo.net> wrote:
> >
> > So I think the implementation here is sensible. I believe Miguel's
> > patch is also pretty much replicating the logic in proc-macro2's
> > build.rs.
>
> Exactly, I was essentially following what upstream does for stable compilers.
>
> (More generally, even if a feature may work, if upstream doesn't
> usually test "older nightlies", then I wonder if we should enable such
> combinations/setups anyway, unless we need them for a particular
> reason).
If these features change the public API exposed by proc-macro2, then it
seems better to always disable it to prevent situations where you
accidentally wrote code that does not work on our minimum rustc version.
(Of course, this is a polyfill and no API is changed, then that's a
different situation and then this LGTM.)
Alice
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 13/18] rust: quote: enable support in kbuild
2025-11-10 13:22 ` Miguel Ojeda
@ 2025-11-10 13:35 ` Alice Ryhl
0 siblings, 0 replies; 57+ messages in thread
From: Alice Ryhl @ 2025-11-10 13:35 UTC (permalink / raw)
To: Miguel Ojeda
Cc: Gary Guo, Miguel Ojeda, Alex Gaynor, Nathan Chancellor,
Nicolas Schier, Boqun Feng, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Trevor Gross, Danilo Krummrich, rust-for-linux,
linux-kbuild, linux-kernel, patches
On Mon, Nov 10, 2025 at 02:22:53PM +0100, Miguel Ojeda wrote:
> On Mon, Nov 10, 2025 at 2:13 PM Gary Guo <gary@garyguo.net> wrote:
> >
> > This is to be able to skip over edition flags for `quote` when building
> > the rusttestlib?
>
> Yes, it is needed to support skipping the flags, which isn't needed
> until this patch.
>
> It can be done earlier separately since it doesn't hurt -- a simpler
> option is just to mention it here in the log.
With that mentioned:
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 18/18] rust: syn: enable support in kbuild
2025-11-10 11:49 ` Alice Ryhl
@ 2025-11-10 13:38 ` Miguel Ojeda
2025-11-10 13:42 ` Alice Ryhl
0 siblings, 1 reply; 57+ messages in thread
From: Miguel Ojeda @ 2025-11-10 13:38 UTC (permalink / raw)
To: Alice Ryhl
Cc: Miguel Ojeda, Alex Gaynor, Nathan Chancellor, Nicolas Schier,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Trevor Gross, Danilo Krummrich, rust-for-linux,
linux-kbuild, linux-kernel, patches
On Mon, Nov 10, 2025 at 12:49 PM Alice Ryhl <aliceryhl@google.com> wrote:
>
> This change seems unrelated?
It is needed to actually use them in proc macros, e.g. to build the
new `pin-init`. We could move it to that patch series, but then it
means it is harder to use this series (e.g. someone was waiting to
port other macros).
I can put it in a final patch or perhaps just mention it in the log,
similar to the `quote` one.
Cheers,
Miguel
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 18/18] rust: syn: enable support in kbuild
2025-11-10 13:38 ` Miguel Ojeda
@ 2025-11-10 13:42 ` Alice Ryhl
0 siblings, 0 replies; 57+ messages in thread
From: Alice Ryhl @ 2025-11-10 13:42 UTC (permalink / raw)
To: Miguel Ojeda
Cc: Miguel Ojeda, Alex Gaynor, Nathan Chancellor, Nicolas Schier,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Trevor Gross, Danilo Krummrich, rust-for-linux,
linux-kbuild, linux-kernel, patches
On Mon, Nov 10, 2025 at 02:38:58PM +0100, Miguel Ojeda wrote:
> On Mon, Nov 10, 2025 at 12:49 PM Alice Ryhl <aliceryhl@google.com> wrote:
> >
> > This change seems unrelated?
>
> It is needed to actually use them in proc macros, e.g. to build the
> new `pin-init`. We could move it to that patch series, but then it
> means it is harder to use this series (e.g. someone was waiting to
> port other macros).
>
> I can put it in a final patch or perhaps just mention it in the log,
> similar to the `quote` one.
With that mentioned in the commit message:
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 00/18] `syn` support
2025-11-10 9:50 [PATCH 00/18] `syn` support Miguel Ojeda
` (17 preceding siblings ...)
2025-11-10 9:50 ` [PATCH 18/18] rust: syn: enable support in kbuild Miguel Ojeda
@ 2025-11-10 13:59 ` Gary Guo
2025-11-10 14:20 ` Miguel Ojeda
2025-11-21 4:37 ` Jesung Yang
2025-11-10 15:59 ` Jonathan Corbet
19 siblings, 2 replies; 57+ messages in thread
From: Gary Guo @ 2025-11-10 13:59 UTC (permalink / raw)
To: Miguel Ojeda
Cc: Alex Gaynor, Nathan Chancellor, Nicolas Schier, Boqun Feng,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, Danilo Krummrich, rust-for-linux, linux-kbuild,
linux-kernel, patches
On Mon, 10 Nov 2025 10:50:05 +0100
Miguel Ojeda <ojeda@kernel.org> wrote:
> This patch series introduces support for `syn` (and its dependencies).
> Having such support allows to greatly simplify writing complex macros
> such as `pin-init`.
>
> 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.
>
> 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.
>
> This has been a long time coming -- the first iterations of this, from
> 2022 and 2023 (with `serde` too), 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.
>
> I will be updating the webpage as well with the result of this:
>
> https://rust-for-linux.com/third-party-crates
>
> Please give it a test -- thanks!
Hi Miguel,
Thank you for creating this. I have been wanting to use `syn` even
before RfL was merged into mainline :)
I've gone through all commits and they all look good to me (I've also
verified the "import crate" patches against the source). So
Reviewed-by: Gary Guo <gary@garyguo.net>
I can build with these patches and I've verified that libmacros can
indeed reference types within `syn`, so also
Tested-by: Gary Guo <gary@garyguo.net>
Best,
Gary
>
> Miguel Ojeda (18):
> rust: condvar: avoid `pub` in example
> rust: kbuild: introduce `core-flags` and `core-skip_flags`
> rust: kbuild: simplify `--cfg` handling
> rust: kbuild: add host library support
> 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
>
> .gitignore | 1 +
> Makefile | 5 +
> rust/Makefile | 134 +-
> rust/kernel/sync/condvar.rs | 2 +-
> 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 | 23 +-
> 83 files changed, 57895 insertions(+), 13 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
>
> --
> 2.51.2
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 00/18] `syn` support
2025-11-10 13:59 ` [PATCH 00/18] `syn` support Gary Guo
@ 2025-11-10 14:20 ` Miguel Ojeda
2025-11-21 4:37 ` Jesung Yang
1 sibling, 0 replies; 57+ messages in thread
From: Miguel Ojeda @ 2025-11-10 14:20 UTC (permalink / raw)
To: Gary Guo
Cc: Miguel Ojeda, Alex Gaynor, Nathan Chancellor, Nicolas Schier,
Boqun Feng, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Alice Ryhl, Trevor Gross, Danilo Krummrich, rust-for-linux,
linux-kbuild, linux-kernel, patches
On Mon, Nov 10, 2025 at 2:59 PM Gary Guo <gary@garyguo.net> wrote:
>
> Thank you for creating this. I have been wanting to use `syn` even
> before RfL was merged into mainline :)
Indeed, you were definitely one of the biggest proponents of `syn`
since the beginning! I could have mentioned a bit more of the older
history in the cover letter, sorry.
In a sense, this cover letter could have had a
Supported-by/Wanted-by/...: Gary & Benno et al. Actually, I may just
add that :) And/or perhaps something about the history in the actual
commit messages or use the cover letter in a merge.
Thanks a lot for the very quick reviews and tests!
Cheers,
Miguel
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 00/18] `syn` support
2025-11-10 9:50 [PATCH 00/18] `syn` support Miguel Ojeda
` (18 preceding siblings ...)
2025-11-10 13:59 ` [PATCH 00/18] `syn` support Gary Guo
@ 2025-11-10 15:59 ` Jonathan Corbet
2025-11-10 16:27 ` Miguel Ojeda
19 siblings, 1 reply; 57+ messages in thread
From: Jonathan Corbet @ 2025-11-10 15:59 UTC (permalink / raw)
To: Miguel Ojeda, Miguel Ojeda, Alex Gaynor, Nathan Chancellor,
Nicolas Schier
Cc: Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
rust-for-linux, linux-kbuild, linux-kernel, patches
Miguel Ojeda <ojeda@kernel.org> writes:
> This patch series introduces support for `syn` (and its dependencies).
> Having such support allows to greatly simplify writing complex macros
> such as `pin-init`.
Just in case I'm not the only ignorant person who didn't immediately
know what "syn" is and why we might want 57,000 lines of it in the
kernel... :)
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
https://docs.rs/syn/latest/syn/
Thanks,
jon
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 00/18] `syn` support
2025-11-10 15:59 ` Jonathan Corbet
@ 2025-11-10 16:27 ` Miguel Ojeda
2025-11-10 17:04 ` Benno Lossin
0 siblings, 1 reply; 57+ messages in thread
From: Miguel Ojeda @ 2025-11-10 16:27 UTC (permalink / raw)
To: Jonathan Corbet
Cc: Miguel Ojeda, Alex Gaynor, Nathan Chancellor, Nicolas Schier,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
rust-for-linux, linux-kbuild, linux-kernel, patches
On Mon, Nov 10, 2025 at 4:59 PM Jonathan Corbet <corbet@lwn.net> wrote:
>
> Just in case I'm not the only ignorant person who didn't immediately
> know what "syn" is and why we might want 57,000 lines of it in the
> kernel... :)
Thanks -- I will add something like that.
It has been such a long and recurrent topic in our discussions that I
guess I was writing from inside the Rust for Linux's bubble.
Just to give a bit more context, it is the most downloaded Rust crate
(according to crates.io). It (or something like it) is essentially a
necessity for writing complex macros without too much pain.
Cheers,
Miguel
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 00/18] `syn` support
2025-11-10 16:27 ` Miguel Ojeda
@ 2025-11-10 17:04 ` Benno Lossin
0 siblings, 0 replies; 57+ messages in thread
From: Benno Lossin @ 2025-11-10 17:04 UTC (permalink / raw)
To: Miguel Ojeda, Jonathan Corbet
Cc: Miguel Ojeda, Alex Gaynor, Nathan Chancellor, Nicolas Schier,
Boqun Feng, Gary Guo, Björn Roy Baron, Andreas Hindborg,
Alice Ryhl, Trevor Gross, Danilo Krummrich, rust-for-linux,
linux-kbuild, linux-kernel, patches
On Mon Nov 10, 2025 at 5:27 PM CET, Miguel Ojeda wrote:
> On Mon, Nov 10, 2025 at 4:59 PM Jonathan Corbet <corbet@lwn.net> wrote:
>>
>> Just in case I'm not the only ignorant person who didn't immediately
>> know what "syn" is and why we might want 57,000 lines of it in the
>> kernel... :)
>
> Thanks -- I will add something like that.
>
> It has been such a long and recurrent topic in our discussions that I
> guess I was writing from inside the Rust for Linux's bubble.
>
> Just to give a bit more context, it is the most downloaded Rust crate
> (according to crates.io). It (or something like it) is essentially a
> necessity for writing complex macros without too much pain.
It also is used by the Rust compiler itself for some proc-macros of
their own.
Cheers,
Benno
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 02/18] rust: kbuild: introduce `core-flags` and `core-skip_flags`
2025-11-10 9:50 ` [PATCH 02/18] rust: kbuild: introduce `core-flags` and `core-skip_flags` Miguel Ojeda
2025-11-10 10:19 ` Miguel Ojeda
2025-11-10 10:27 ` Alice Ryhl
@ 2025-11-10 19:18 ` John Hubbard
2025-11-12 11:13 ` Miguel Ojeda
2 siblings, 1 reply; 57+ messages in thread
From: John Hubbard @ 2025-11-10 19:18 UTC (permalink / raw)
To: Miguel Ojeda, Alex Gaynor, Nathan Chancellor, Nicolas Schier
Cc: Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
rust-for-linux, linux-kbuild, linux-kernel, patches
On 11/10/25 1:50 AM, Miguel Ojeda wrote:
> 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.
>
> Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
> ---
> rust/Makefile | 19 ++++++++++++++-----
> 1 file changed, 14 insertions(+), 5 deletions(-)
>
> diff --git a/rust/Makefile b/rust/Makefile
> index 3e545c1a0ff4..a001aae0da9d 100644
> --- a/rust/Makefile
> +++ b/rust/Makefile
> @@ -60,11 +60,20 @@ rustdoc_test_quiet=--test-args -q
> rustdoc_test_kernel_quiet=>/dev/null
> endif
>
> -core-cfgs = \
> +core-cfgs := \
I agree that switching to ":=" for this kind of Makefile variable
is a good move. However, it should be mentioned in the commit log
so that it doesn't look like it was accidentally introduced.
thanks,
--
John Hubbard
> --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)
> @@ -125,8 +134,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)
>
> @@ -508,9 +517,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)
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 09/18] rust: proc-macro2: enable support in kbuild
2025-11-10 9:50 ` [PATCH 09/18] rust: proc-macro2: enable support in kbuild Miguel Ojeda
2025-11-10 11:38 ` Alice Ryhl
@ 2025-11-10 19:34 ` John Hubbard
2025-11-12 11:14 ` Miguel Ojeda
1 sibling, 1 reply; 57+ messages in thread
From: John Hubbard @ 2025-11-10 19:34 UTC (permalink / raw)
To: Miguel Ojeda, Alex Gaynor, Nathan Chancellor, Nicolas Schier
Cc: Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
rust-for-linux, linux-kbuild, linux-kernel, patches
On 11/10/25 1:50 AM, Miguel Ojeda wrote:
> With 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.
>
> Link: https://github.com/rust-lang/rust/pull/123431 [1]
> Link: https://github.com/rust-lang/rust/pull/112711 [2]
> Link: https://github.com/rust-lang/rust/pull/119651 [3]
> Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
> ---
> Makefile | 3 +++
> rust/Makefile | 32 +++++++++++++++++++++++++++++--
> scripts/generate_rust_analyzer.py | 7 +++++++
> 3 files changed, 40 insertions(+), 2 deletions(-)
>
> diff --git a/Makefile b/Makefile
> index fb4389aa5d5f..6ff887523eee 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -1830,6 +1830,9 @@ PHONY += rustfmt rustfmtcheck
>
> rustfmt:
> $(Q)find $(srctree) $(RCS_FIND_IGNORE) \
> + \( \
> + -path $(srctree)/rust/proc-macro2 \
> + \) -prune -o \
Looks good. But for future code and commit log readers, should
we leave a small comment, to explain that this was vendored in,
and therefore excluded from "make rustfmt"?
An alternative approach might be to create a "vendored" subdir,
to make it clear which parts of the Rust for Linux code are
special in that way.
thanks,
--
John Hubbard
> -type f -a -name '*.rs' -a ! -name '*generated*' -print \
> | xargs $(RUSTFMT) $(rustfmt_flags)
>
> diff --git a/rust/Makefile b/rust/Makefile
> index 9eea6563ef35..a614a23023cb 100644
> --- a/rust/Makefile
> +++ b/rust/Makefile
> @@ -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)
> @@ -128,10 +141,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
> @@ -194,6 +212,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
> @@ -440,6 +462,11 @@ quiet_cmd_rustc_hostlibrary = $(RUSTC_OR_CLIPPY_QUIET) H $@
> 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_hostlibrary)
> +
> quiet_cmd_rustc_procmacro = $(RUSTC_OR_CLIPPY_QUIET) P $@
> cmd_rustc_procmacro = \
> $(RUSTC_OR_CLIPPY) $(rust_common_flags) $(rustc_target_flags) \
> @@ -451,7 +478,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
> @@ -474,6 +501,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
> diff --git a/scripts/generate_rust_analyzer.py b/scripts/generate_rust_analyzer.py
> index dedca470adc1..00c6b7cc94b7 100755
> --- a/scripts/generate_rust_analyzer.py
> +++ b/scripts/generate_rust_analyzer.py
> @@ -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",
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 18/18] rust: syn: enable support in kbuild
2025-11-10 9:50 ` [PATCH 18/18] rust: syn: enable support in kbuild Miguel Ojeda
2025-11-10 11:49 ` Alice Ryhl
@ 2025-11-10 19:43 ` John Hubbard
1 sibling, 0 replies; 57+ messages in thread
From: John Hubbard @ 2025-11-10 19:43 UTC (permalink / raw)
To: Miguel Ojeda, Alex Gaynor, Nathan Chancellor, Nicolas Schier
Cc: Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
rust-for-linux, linux-kbuild, linux-kernel, patches
On 11/10/25 1:50 AM, Miguel Ojeda wrote:
> With all the new files in place and ready from the new crate, enable
> the support for it in the build system.
>
> Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
> ---
> Makefile | 1 +
> rust/Makefile | 39 +++++++++++++++++++++++++++----
> scripts/generate_rust_analyzer.py | 7 ++++++
> 3 files changed, 43 insertions(+), 4 deletions(-)
>
> diff --git a/Makefile b/Makefile
> index f1b38b7fed1e..5364b3ad3600 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -1833,6 +1833,7 @@ rustfmt:
> \( \
> -path $(srctree)/rust/proc-macro2 \
> -o -path $(srctree)/rust/quote \
> + -o -path $(srctree)/rust/syn \
At this point, a "vendored" subdirectory for these three items is
starting to sound even better, from a self-documenting point of
view, yes?
thanks,
--
John Hubbard
> \) -prune -o \
> -type f -a -name '*.rs' -a ! -name '*generated*' -print \
> | xargs $(RUSTFMT) $(rustfmt_flags)
> diff --git a/rust/Makefile b/rust/Makefile
> index 801a8cbf3bdd..984aec608c27 100644
> --- a/rust/Makefile
> +++ b/rust/Makefile
> @@ -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)
> @@ -164,11 +180,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
> @@ -240,6 +261,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
> @@ -497,19 +522,24 @@ $(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_hostlibrary)
>
> +$(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_hostlibrary)
> +
> quiet_cmd_rustc_procmacro = $(RUSTC_OR_CLIPPY_QUIET) P $@
> cmd_rustc_procmacro = \
> $(RUSTC_OR_CLIPPY) $(rust_common_flags) $(rustc_target_flags) \
> -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 $<
>
> # 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
> @@ -534,6 +564,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
> diff --git a/scripts/generate_rust_analyzer.py b/scripts/generate_rust_analyzer.py
> index 4faf153ed2ee..5b6f7b8d6918 100755
> --- a/scripts/generate_rust_analyzer.py
> +++ b/scripts/generate_rust_analyzer.py
> @@ -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",
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 02/18] rust: kbuild: introduce `core-flags` and `core-skip_flags`
2025-11-10 19:18 ` John Hubbard
@ 2025-11-12 11:13 ` Miguel Ojeda
0 siblings, 0 replies; 57+ messages in thread
From: Miguel Ojeda @ 2025-11-12 11:13 UTC (permalink / raw)
To: John Hubbard
Cc: Miguel Ojeda, Alex Gaynor, Nathan Chancellor, Nicolas Schier,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
rust-for-linux, linux-kbuild, linux-kernel, patches
On Mon, Nov 10, 2025 at 8:18 PM John Hubbard <jhubbard@nvidia.com> wrote:
>
> I agree that switching to ":=" for this kind of Makefile variable
> is a good move. However, it should be mentioned in the commit log
> so that it doesn't look like it was accidentally introduced.
It was meant to make it consistent with the upcoming additions since
this commit is essentially about that, i.e. it was not intended as a
drive-by cleanup (which I usually oppose), if that makes sense.
I will clarify in the log.
Thanks for taking a look!
Cheers,
Miguel
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 09/18] rust: proc-macro2: enable support in kbuild
2025-11-10 19:34 ` John Hubbard
@ 2025-11-12 11:14 ` Miguel Ojeda
0 siblings, 0 replies; 57+ messages in thread
From: Miguel Ojeda @ 2025-11-12 11:14 UTC (permalink / raw)
To: John Hubbard
Cc: Miguel Ojeda, Alex Gaynor, Nathan Chancellor, Nicolas Schier,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
rust-for-linux, linux-kbuild, linux-kernel, patches
On Mon, Nov 10, 2025 at 8:34 PM John Hubbard <jhubbard@nvidia.com> wrote:
>
> Looks good. But for future code and commit log readers, should
> we leave a small comment, to explain that this was vendored in,
> and therefore excluded from "make rustfmt"?
>
> An alternative approach might be to create a "vendored" subdir,
> to make it clear which parts of the Rust for Linux code are
> special in that way.
Sure, that can help, I will add it.
The subdir makes sense, although it makes it into a different level
than the other crates and I don't see it done with a folder in other
cases either. Hmm... I will think about it.
Thanks for taking a look!
Cheers,
Miguel
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 00/18] `syn` support
2025-11-10 13:59 ` [PATCH 00/18] `syn` support Gary Guo
2025-11-10 14:20 ` Miguel Ojeda
@ 2025-11-21 4:37 ` Jesung Yang
2025-11-21 5:36 ` Miguel Ojeda
1 sibling, 1 reply; 57+ messages in thread
From: Jesung Yang @ 2025-11-21 4:37 UTC (permalink / raw)
To: gary, ojeda
Cc: a.hindborg, alex.gaynor, aliceryhl, bjorn3_gh, boqun.feng, dakr,
linux-kbuild, linux-kernel, lossin, nathan, nicolas, patches,
rust-for-linux, tmgross
Gary Guo <gary@garyguo.net> wrote:
> I can build with these patches and I've verified that libmacros can
> indeed reference types within `syn`, so also
Hi,
I've been trying to apply this patch on the current rust-next HEAD
494de8f67b1e ("rust: sync: replace kernel::c_str! with C-Strings") and
test it, since I need this series for my future patch revision.
Unfortunately, when I make the following change:
diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs
index 793f712dbf7c..084633b517be 100644
--- a/rust/macros/lib.rs
+++ b/rust/macros/lib.rs
@@ -444,3 +444,14 @@ pub fn paste(input: TokenStream) -> TokenStream {
pub fn kunit_tests(attr: TokenStream, ts: TokenStream) -> TokenStream {
kunit::kunit_tests(attr, ts)
}
+
+use syn::{
+ parse_macro_input,
+ DeriveInput, //
+};
+
+#[proc_macro_attribute]
+pub fn dummy(input: TokenStream) -> TokenStream {
+ let input = parse_macro_input!(input as DeriveInput);
+ todo!()
+}
It fails to compile:
error[E0432]: unresolved import `syn`
--> rust/macros/lib.rs:448:5
|
448 | use syn::{
| ^^^ use of unresolved module or unlinked crate `syn`
|
= help: you might be missing a crate named `syn`
error: aborting due to 1 previous error
It appears that the vendored crates are indeed compiled; I can see some
build artifacts like `rust/libsyn.rlib`, `libquote.rlib`, etc.
For reference, here's the sequence of commands I ran to compile the
kernel:
make LLVM=1 ARCH=arm64 rustavailable
make LLVM=1 ARCH=arm64 defconfig
scripts/config --enable CONFIG_RUST
scripts/config --enable CONFIG_SAMPLES
scripts/config --enable CONFIG_SAMPLES_RUST
scripts/config --module CONFIG_SAMPLE_RUST_MINIMAL
scripts/config --enable CONFIG_KUNIT
scripts/config --enable CONFIG_RUST_KERNEL_DOCTESTS
make LLVM=1 ARCH=arm64 olddefconfig
make LLVM=1 ARCH=arm64 CLIPPY=1 -j8
I'd appreciate any guidance on steps I might be missing. Thanks in
advance!
Best Regards,
Jesung
^ permalink raw reply [flat|nested] 57+ messages in thread
* Re: [PATCH 00/18] `syn` support
2025-11-21 4:37 ` Jesung Yang
@ 2025-11-21 5:36 ` Miguel Ojeda
2025-11-21 9:08 ` Jesung Yang
0 siblings, 1 reply; 57+ messages in thread
From: Miguel Ojeda @ 2025-11-21 5:36 UTC (permalink / raw)
To: y.j3ms.n
Cc: a.hindborg, alex.gaynor, aliceryhl, bjorn3_gh, boqun.feng, dakr,
gary, linux-kbuild, linux-kernel, lossin, nathan, nicolas, ojeda,
patches, rust-for-linux, tmgross
On Fri, 21 Nov 2025 04:37:47 +0000 Jesung Yang <y.j3ms.n@gmail.com> wrote:
>
> I'd appreciate any guidance on steps I might be missing. Thanks in
> advance!
For using (all of) them from `macros`, you would need [1].
Maybe I should just put it on top of this series for convenience.
Cheers,
Miguel
diff --git a/rust/Makefile b/rust/Makefile
index 984aec608c27..640e51129be0 100644
--- a/rust/Makefile
+++ b/rust/Makefile
@@ -187,7 +187,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)
@@ -265,9 +265,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 \
@@ -348,7 +350,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
@@ -538,6 +541,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)
^ permalink raw reply related [flat|nested] 57+ messages in thread
* Re: [PATCH 00/18] `syn` support
2025-11-21 5:36 ` Miguel Ojeda
@ 2025-11-21 9:08 ` Jesung Yang
2025-11-23 12:50 ` Miguel Ojeda
0 siblings, 1 reply; 57+ messages in thread
From: Jesung Yang @ 2025-11-21 9:08 UTC (permalink / raw)
To: Miguel Ojeda
Cc: a.hindborg, alex.gaynor, aliceryhl, bjorn3_gh, boqun.feng, dakr,
gary, linux-kbuild, linux-kernel, lossin, nathan, nicolas,
patches, rust-for-linux, tmgross
On Fri, Nov 21, 2025 at 2:36 PM Miguel Ojeda <ojeda@kernel.org> wrote:
> For using (all of) them from `macros`, you would need [1].
Now everything compiles. Thanks!
By the way, I needed to make a small change to
`generate_rust_analyzer.py` for rust-analyzer to correctly reference
symbols from the vendored crates:
diff --git a/scripts/generate_rust_analyzer.py
b/scripts/generate_rust_analyzer.py
index 5b6f7b8d6918..147d0cc94068 100755
--- a/scripts/generate_rust_analyzer.py
+++ b/scripts/generate_rust_analyzer.py
@@ -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,
)
This might already be covered somewhere else, but I'm bringing it up
just in case.
Best Regards,
Jesung
^ permalink raw reply related [flat|nested] 57+ messages in thread
* Re: [PATCH 00/18] `syn` support
2025-11-21 9:08 ` Jesung Yang
@ 2025-11-23 12:50 ` Miguel Ojeda
0 siblings, 0 replies; 57+ messages in thread
From: Miguel Ojeda @ 2025-11-23 12:50 UTC (permalink / raw)
To: Jesung Yang
Cc: Miguel Ojeda, a.hindborg, alex.gaynor, aliceryhl, bjorn3_gh,
boqun.feng, dakr, gary, linux-kbuild, linux-kernel, lossin,
nathan, nicolas, patches, rust-for-linux, tmgross
On Fri, Nov 21, 2025 at 10:08 AM Jesung Yang <y.j3ms.n@gmail.com> wrote:
>
> Now everything compiles. Thanks!
Great and thanks for testing! Do you mind if I add a:
Tested-by: Jesung Yang <y.j3ms.n@gmail.com>
?
> By the way, I needed to make a small change to
> `generate_rust_analyzer.py` for rust-analyzer to correctly reference
> symbols from the vendored crates:
>
> This might already be covered somewhere else, but I'm bringing it up
> just in case.
Definitely, it should be included.
Cheers,
Miguel
^ permalink raw reply [flat|nested] 57+ messages in thread
end of thread, other threads:[~2025-11-23 12:51 UTC | newest]
Thread overview: 57+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-10 9:50 [PATCH 00/18] `syn` support Miguel Ojeda
2025-11-10 9:50 ` [PATCH 01/18] rust: condvar: avoid `pub` in example Miguel Ojeda
2025-11-10 10:24 ` Alice Ryhl
2025-11-10 11:10 ` Miguel Ojeda
2025-11-10 9:50 ` [PATCH 02/18] rust: kbuild: introduce `core-flags` and `core-skip_flags` Miguel Ojeda
2025-11-10 10:19 ` Miguel Ojeda
2025-11-10 11:50 ` Alice Ryhl
2025-11-10 10:27 ` Alice Ryhl
2025-11-10 19:18 ` John Hubbard
2025-11-12 11:13 ` Miguel Ojeda
2025-11-10 9:50 ` [PATCH 03/18] rust: kbuild: simplify `--cfg` handling Miguel Ojeda
2025-11-10 10:33 ` Alice Ryhl
2025-11-10 9:50 ` [PATCH 04/18] rust: kbuild: add host library support Miguel Ojeda
2025-11-10 10:43 ` Alice Ryhl
2025-11-10 11:17 ` Miguel Ojeda
2025-11-10 9:50 ` [PATCH 05/18] rust: proc-macro2: import crate Miguel Ojeda
2025-11-10 9:50 ` [PATCH 06/18] rust: proc-macro2: add SPDX License Identifiers Miguel Ojeda
2025-11-10 9:50 ` [PATCH 07/18] rust: proc-macro2: remove `unicode_ident` dependency Miguel Ojeda
2025-11-10 10:50 ` Alice Ryhl
2025-11-10 9:50 ` [PATCH 08/18] rust: proc-macro2: add `README.md` Miguel Ojeda
2025-11-10 10:52 ` Alice Ryhl
2025-11-10 9:50 ` [PATCH 09/18] rust: proc-macro2: enable support in kbuild Miguel Ojeda
2025-11-10 11:38 ` Alice Ryhl
2025-11-10 13:10 ` Gary Guo
2025-11-10 13:28 ` Miguel Ojeda
2025-11-10 13:34 ` Alice Ryhl
2025-11-10 19:34 ` John Hubbard
2025-11-12 11:14 ` Miguel Ojeda
2025-11-10 9:50 ` [PATCH 10/18] rust: quote: import crate Miguel Ojeda
2025-11-10 9:50 ` [PATCH 11/18] rust: quote: add SPDX License Identifiers Miguel Ojeda
2025-11-10 9:50 ` [PATCH 12/18] rust: quote: add `README.md` Miguel Ojeda
2025-11-10 9:50 ` [PATCH 13/18] rust: quote: enable support in kbuild Miguel Ojeda
2025-11-10 11:44 ` Alice Ryhl
2025-11-10 13:13 ` Gary Guo
2025-11-10 13:22 ` Miguel Ojeda
2025-11-10 13:35 ` Alice Ryhl
2025-11-10 9:50 ` [PATCH 14/18] rust: syn: import crate Miguel Ojeda
2025-11-10 10:26 ` Miguel Ojeda
2025-11-10 9:50 ` [PATCH 15/18] rust: syn: add SPDX License Identifiers Miguel Ojeda
2025-11-10 9:50 ` [PATCH 16/18] rust: syn: remove `unicode-ident` dependency Miguel Ojeda
2025-11-10 11:47 ` Alice Ryhl
2025-11-10 9:50 ` [PATCH 17/18] rust: syn: add `README.md` Miguel Ojeda
2025-11-10 11:47 ` Alice Ryhl
2025-11-10 9:50 ` [PATCH 18/18] rust: syn: enable support in kbuild Miguel Ojeda
2025-11-10 11:49 ` Alice Ryhl
2025-11-10 13:38 ` Miguel Ojeda
2025-11-10 13:42 ` Alice Ryhl
2025-11-10 19:43 ` John Hubbard
2025-11-10 13:59 ` [PATCH 00/18] `syn` support Gary Guo
2025-11-10 14:20 ` Miguel Ojeda
2025-11-21 4:37 ` Jesung Yang
2025-11-21 5:36 ` Miguel Ojeda
2025-11-21 9:08 ` Jesung Yang
2025-11-23 12:50 ` Miguel Ojeda
2025-11-10 15:59 ` Jonathan Corbet
2025-11-10 16:27 ` Miguel Ojeda
2025-11-10 17:04 ` Benno Lossin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).