From 4281c2c3d5b6fe4ef4c6cf659c20da42209f2289 Mon Sep 17 00:00:00 2001 From: DianQK Date: Wed, 19 Jun 2024 21:20:38 +0800 Subject: [PATCH 01/23] patch `rust-lld` and `ld.lld` on NixOS --- src/bootstrap/bootstrap.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 9861121aac0a..7e47b373ff9d 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -617,6 +617,9 @@ class RustBuild(object): self.fix_bin_or_dylib("{}/bin/rustdoc".format(bin_root)) self.fix_bin_or_dylib("{}/libexec/rust-analyzer-proc-macro-srv".format(bin_root)) lib_dir = "{}/lib".format(bin_root) + rustlib_bin_dir = "{}/rustlib/{}/bin".format(lib_dir, self.build) + self.fix_bin_or_dylib("{}/rust-lld".format(rustlib_bin_dir)) + self.fix_bin_or_dylib("{}/gcc-ld/ld.lld".format(rustlib_bin_dir)) for lib in os.listdir(lib_dir): # .so is not necessarily the suffix, there can be version numbers afterwards. if ".so" in lib: @@ -731,12 +734,9 @@ class RustBuild(object): patchelf = "{}/bin/patchelf".format(nix_deps_dir) rpath_entries = [ - # Relative default, all binary and dynamic libraries we ship - # appear to have this (even when `../lib` is redundant). - "$ORIGIN/../lib", os.path.join(os.path.realpath(nix_deps_dir), "lib") ] - patchelf_args = ["--set-rpath", ":".join(rpath_entries)] + patchelf_args = ["--add-rpath", ":".join(rpath_entries)] if ".so" not in fname: # Finally, set the correct .interp for binaries with open("{}/nix-support/dynamic-linker".format(nix_deps_dir)) as dynamic_linker: From 80e43c128cf24f143a1bf58ffa972e78633cf8e9 Mon Sep 17 00:00:00 2001 From: DianQK Date: Wed, 19 Jun 2024 21:32:18 +0800 Subject: [PATCH 02/23] patch an ELF file using `--add-rpath` --- src/bootstrap/src/core/download.rs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index 2b11b8c3d4f2..fd077ab2d7c7 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -173,15 +173,10 @@ impl Config { } let mut patchelf = Command::new(nix_deps_dir.join("bin/patchelf")); - let rpath_entries = { - // ORIGIN is a relative default, all binary and dynamic libraries we ship - // appear to have this (even when `../lib` is redundant). - // NOTE: there are only two paths here, delimited by a `:` - let mut entries = OsString::from("$ORIGIN/../lib:"); - entries.push(t!(fs::canonicalize(nix_deps_dir)).join("lib")); - entries - }; - patchelf.args(&[OsString::from("--set-rpath"), rpath_entries]); + patchelf.args(&[ + OsString::from("--add-rpath"), + OsString::from(t!(fs::canonicalize(nix_deps_dir)).join("lib")), + ]); if !path_is_dylib(fname) { // Finally, set the correct .interp for binaries let dynamic_linker_path = nix_deps_dir.join("nix-support/dynamic-linker"); From 08fa5f0460c8b9a0fd5aeed0aa78a7864edf5aff Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Thu, 20 Jun 2024 11:06:32 +0300 Subject: [PATCH 03/23] bootstrap-rustdoc: use current stage if download-rustc enabled When using download-rustc, using stage 1 rustdoc results in the wrong librustc_driver being used. ```sh $ ./build/host/stage1/bin/rustdoc --version ./build/host/stage1/bin/rustdoc: error while loading shared libraries: librustc_driver-7ff02ed05016d515.so: cannot open shared object file: No such file or directory ``` This change fixes that by not cutting the stage if download-rustc is enabled. Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/tool.rs | 23 +++++++++++----------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index 613484788b60..abda29b790ef 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -476,24 +476,23 @@ impl Step for Rustdoc { return builder.initial_rustc.with_file_name(exe("rustdoc", target_compiler.host)); } let target = target_compiler.host; - // Similar to `compile::Assemble`, build with the previous stage's compiler. Otherwise - // we'd have stageN/bin/rustc and stageN/bin/rustdoc be effectively different stage - // compilers, which isn't what we want. Rustdoc should be linked in the same way as the - // rustc compiler it's paired with, so it must be built with the previous stage compiler. - let build_compiler = builder.compiler(target_compiler.stage - 1, builder.config.build); + + let build_compiler = if builder.download_rustc() && target_compiler.stage == 1 { + // We already have the stage 1 compiler, we don't need to cut the stage. + builder.compiler(target_compiler.stage, builder.config.build) + } else { + // Similar to `compile::Assemble`, build with the previous stage's compiler. Otherwise + // we'd have stageN/bin/rustc and stageN/bin/rustdoc be effectively different stage + // compilers, which isn't what we want. Rustdoc should be linked in the same way as the + // rustc compiler it's paired with, so it must be built with the previous stage compiler. + builder.compiler(target_compiler.stage - 1, builder.config.build) + }; // When using `download-rustc` and a stage0 build_compiler, copying rustc doesn't actually // build stage0 libstd (because the libstd in sysroot has the wrong ABI). Explicitly build // it. builder.ensure(compile::Std::new(build_compiler, target_compiler.host)); builder.ensure(compile::Rustc::new(build_compiler, target_compiler.host)); - // NOTE: this implies that `download-rustc` is pretty useless when compiling with the stage0 - // compiler, since you do just as much work. - if !builder.config.dry_run() && builder.download_rustc() && build_compiler.stage == 0 { - println!( - "WARNING: `download-rustc` does nothing when building stage1 tools; consider using `--stage 2` instead" - ); - } // The presence of `target_compiler` ensures that the necessary libraries (codegen backends, // compiler libraries, ...) are built. Rustdoc does not require the presence of any From aa30dd444b00248065d9c286527bf9168c9cfb4b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 15 May 2024 15:23:49 +1000 Subject: [PATCH 04/23] Fix a typo in a comment. --- compiler/rustc_ast/src/tokenstream.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index 3d46415507de..b4ddbe20689e 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -224,7 +224,7 @@ impl AttrTokenStream { // Inner attributes are only supported on extern blocks, functions, // impls, and modules. All of these have their inner attributes // placed at the beginning of the rightmost outermost braced group: - // e.g. fn foo() { #![my_attr} } + // e.g. fn foo() { #![my_attr] } // // Therefore, we can insert them back into the right location // without needing to do any extra position tracking. From 572ae3b22743018ea909b5f8d8a33d3d83392322 Mon Sep 17 00:00:00 2001 From: John Paul Adrian Glaubitz Date: Mon, 24 Jun 2024 16:33:24 +0200 Subject: [PATCH 05/23] rustc_data_structures: Use portable AtomicU64 on 32-bit SPARC While at it, order the list of architectures alphabetically. --- compiler/rustc_data_structures/Cargo.toml | 2 +- compiler/rustc_data_structures/src/marker.rs | 6 +++--- compiler/rustc_data_structures/src/sync.rs | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml index ff0a94f8e9b2..f525510030b4 100644 --- a/compiler/rustc_data_structures/Cargo.toml +++ b/compiler/rustc_data_structures/Cargo.toml @@ -50,7 +50,7 @@ libc = "0.2" memmap2 = "0.2.1" # tidy-alphabetical-end -[target.'cfg(any(target_arch = "powerpc", target_arch = "mips"))'.dependencies] +[target.'cfg(any(target_arch = "mips", target_arch = "powerpc", target_arch = "sparc"))'.dependencies] portable-atomic = "1.5.1" [features] diff --git a/compiler/rustc_data_structures/src/marker.rs b/compiler/rustc_data_structures/src/marker.rs index a9ccfbed4116..32fad0de1aa3 100644 --- a/compiler/rustc_data_structures/src/marker.rs +++ b/compiler/rustc_data_structures/src/marker.rs @@ -147,14 +147,14 @@ cfg_match! { [crate::owned_slice::OwnedSlice] ); - // PowerPC and MIPS platforms with 32-bit pointers do not + // MIPS, PowerPC and SPARC platforms with 32-bit pointers do not // have AtomicU64 type. - #[cfg(not(any(target_arch = "powerpc", target_arch = "mips")))] + #[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc", target_arch = "sparc")))] already_sync!( [std::sync::atomic::AtomicU64] ); - #[cfg(any(target_arch = "powerpc", target_arch = "mips"))] + #[cfg(any(target_arch = "mips", target_arch = "powerpc", target_arch = "sparc"))] already_sync!( [portable_atomic::AtomicU64] ); diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs index ecb85db33f70..5ae79ca988f1 100644 --- a/compiler/rustc_data_structures/src/sync.rs +++ b/compiler/rustc_data_structures/src/sync.rs @@ -270,12 +270,12 @@ cfg_match! { pub use std::sync::atomic::{AtomicBool, AtomicUsize, AtomicU32}; - // PowerPC and MIPS platforms with 32-bit pointers do not + // MIPS, PowerPC and SPARC platforms with 32-bit pointers do not // have AtomicU64 type. - #[cfg(not(any(target_arch = "powerpc", target_arch = "mips")))] + #[cfg(not(any(target_arch = "mips", target_arch = "powerpc", target_arch = "sparc")))] pub use std::sync::atomic::AtomicU64; - #[cfg(any(target_arch = "powerpc", target_arch = "mips"))] + #[cfg(any(target_arch = "mips", target_arch = "powerpc", target_arch = "sparc"))] pub use portable_atomic::AtomicU64; pub use std::sync::Arc as Lrc; From dc8ac3ec91716678aa4dfa9e8df1dceacdf3464f Mon Sep 17 00:00:00 2001 From: John Paul Adrian Glaubitz Date: Mon, 24 Jun 2024 16:36:38 +0200 Subject: [PATCH 06/23] rustc_llvm: Link against libatomic on 32-bit SPARC While at it, order the list of architectures alphabetically. --- compiler/rustc_llvm/build.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs index cdaabb036c2a..3aa852c83045 100644 --- a/compiler/rustc_llvm/build.rs +++ b/compiler/rustc_llvm/build.rs @@ -235,6 +235,7 @@ fn main() { || target.starts_with("mips-") || target.starts_with("mipsel-") || target.starts_with("powerpc-") + || target.starts_with("sparc-") { // 32-bit targets need to link libatomic. println!("cargo:rustc-link-lib=atomic"); From 8f7175c199472486756ab4432addc416e548e6d6 Mon Sep 17 00:00:00 2001 From: John Paul Adrian Glaubitz Date: Mon, 24 Jun 2024 16:41:35 +0200 Subject: [PATCH 07/23] bootstrap: Link against libatomic on 32-bit SPARC While at it, order the list of architectures alphabetically. --- src/bootstrap/src/core/build_steps/llvm.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index 8b379d3be5c0..8e6795b11bd2 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -407,18 +407,21 @@ impl Step for Llvm { cfg.define("LLVM_LINK_LLVM_DYLIB", "ON"); } - if (target.starts_with("riscv") || target.starts_with("csky")) + if (target.starts_with("csky") + || target.starts_with("riscv") + || target.starts_with("sparc-")) && !target.contains("freebsd") && !target.contains("openbsd") && !target.contains("netbsd") { - // RISC-V and CSKY GCC erroneously requires linking against + // CSKY and RISC-V GCC erroneously requires linking against // `libatomic` when using 1-byte and 2-byte C++ // atomics but the LLVM build system check cannot // detect this. Therefore it is set manually here. // Some BSD uses Clang as its system compiler and // provides no libatomic in its base system so does - // not want this. + // not want this. 32-bit SPARC requires linking against + // libatomic as well. ldflags.exe.push(" -latomic"); ldflags.shared.push(" -latomic"); } From a194f42d21cac273b9d2d44d70d02f7c7aef1304 Mon Sep 17 00:00:00 2001 From: John Paul Adrian Glaubitz Date: Mon, 24 Jun 2024 16:46:53 +0200 Subject: [PATCH 08/23] rustc_target: Rewrite sparc_unknown_linux_gnu spec to use TargetOptions --- .../spec/targets/sparc_unknown_linux_gnu.rs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs index c10f9d82d463..6fa50a28c370 100644 --- a/compiler/rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs @@ -1,13 +1,7 @@ use crate::abi::Endian; -use crate::spec::{base, Cc, LinkerFlavor, Lld, Target}; +use crate::spec::{base, Cc, LinkerFlavor, Lld, Target, TargetOptions}; pub fn target() -> Target { - let mut base = base::linux_gnu::opts(); - base.endian = Endian::Big; - base.cpu = "v9".into(); - base.max_atomic_width = Some(32); - base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-mv8plus"]); - Target { llvm_target: "sparc-unknown-linux-gnu".into(), metadata: crate::spec::TargetMetadata { @@ -19,6 +13,15 @@ pub fn target() -> Target { pointer_width: 32, data_layout: "E-m:e-p:32:32-i64:64-f128:64-n32-S64".into(), arch: "sparc".into(), - options: base, + options: TargetOptions { + cpu: "v9".into(), + endian: Endian::Big, + late_link_args: TargetOptions::link_args( + LinkerFlavor::Gnu(Cc::Yes, Lld::No), + &["-mv8plus"], + ), + max_atomic_width: Some(32), + ..base::linux_gnu::opts() + }, } } From e57bbb37798ca9e3a4c3a043312b0ed30f9cfd87 Mon Sep 17 00:00:00 2001 From: John Paul Adrian Glaubitz Date: Mon, 24 Jun 2024 16:48:12 +0200 Subject: [PATCH 09/23] rustc_target: Build sparc_unknown_linux_gnu with -mcpu=v9 and -m32 The previously -mv8plus parameter is supported by GCC only, so let's use something that the SPARC backend in LLVM supports as well. --- .../rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs index 6fa50a28c370..5cee06e4936c 100644 --- a/compiler/rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs @@ -18,7 +18,7 @@ pub fn target() -> Target { endian: Endian::Big, late_link_args: TargetOptions::link_args( LinkerFlavor::Gnu(Cc::Yes, Lld::No), - &["-mv8plus"], + &["-mcpu=v9", "-m32"], ), max_atomic_width: Some(32), ..base::linux_gnu::opts() From bca5cd3a9dccc166e936b21eb86e6a58d3f4b84e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 25 Jun 2024 14:14:58 +1000 Subject: [PATCH 10/23] Extend `tests/ui/macros/nonterminal-matching.rs`. To involve `macro_rules!` macros, and also a mix of fragment specifiers, some of which feature the forwaring limitation and some of which don't. --- tests/ui/macros/nonterminal-matching.rs | 30 +++++++ tests/ui/macros/nonterminal-matching.stderr | 90 ++++++++++++++++++++- 2 files changed, 119 insertions(+), 1 deletion(-) diff --git a/tests/ui/macros/nonterminal-matching.rs b/tests/ui/macros/nonterminal-matching.rs index 84fffe44d6a5..5f0d6b2f90ee 100644 --- a/tests/ui/macros/nonterminal-matching.rs +++ b/tests/ui/macros/nonterminal-matching.rs @@ -23,4 +23,34 @@ simple_nonterminal!(a, 'a, (x, y, z)); // OK complex_nonterminal!(enum E {}); +// `ident`, `lifetime`, and `tt` all work. Other fragments do not. See +// https://doc.rust-lang.org/nightly/reference/macros-by-example.html#forwarding-a-matched-fragment +macro_rules! foo { + (ident $x:ident) => { bar!(ident $x); }; + (lifetime $x:lifetime) => { bar!(lifetime $x); }; + (tt $x:tt) => { bar!(tt $x); }; + (expr $x:expr) => { bar!(expr $x); }; //~ ERROR: no rules expected the token `3` + (literal $x:literal) => { bar!(literal $x); }; //~ ERROR: no rules expected the token `4` + (path $x:path) => { bar!(path $x); }; //~ ERROR: no rules expected the token `a::b::c` + (stmt $x:stmt) => { bar!(stmt $x); }; //~ ERROR: no rules expected the token `let abc = 0` +} + +macro_rules! bar { + (ident abc) => {}; + (lifetime 'abc) => {}; + (tt 2) => {}; + (expr 3) => {}; + (literal 4) => {}; + (path a::b::c) => {}; + (stmt let abc = 0) => {}; +} + +foo!(ident abc); +foo!(lifetime 'abc); +foo!(tt 2); +foo!(expr 3); +foo!(literal 4); +foo!(path a::b::c); +foo!(stmt let abc = 0); + fn main() {} diff --git a/tests/ui/macros/nonterminal-matching.stderr b/tests/ui/macros/nonterminal-matching.stderr index d19141145fa1..3ee88b5f52ef 100644 --- a/tests/ui/macros/nonterminal-matching.stderr +++ b/tests/ui/macros/nonterminal-matching.stderr @@ -23,5 +23,93 @@ LL | complex_nonterminal!(enum E {}); = help: try using `:tt` instead in the macro definition = note: this error originates in the macro `complex_nonterminal` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 1 previous error +error: no rules expected the token `3` + --> $DIR/nonterminal-matching.rs:32:35 + | +LL | (expr $x:expr) => { bar!(expr $x); }; + | ^^ no rules expected this token in macro call +... +LL | macro_rules! bar { + | ---------------- when calling this macro +... +LL | foo!(expr 3); + | ------------ in this macro invocation + | +note: while trying to match `3` + --> $DIR/nonterminal-matching.rs:42:11 + | +LL | (expr 3) => {}; + | ^ + = note: captured metavariables except for `:tt`, `:ident` and `:lifetime` cannot be compared to other tokens + = note: see for more information + = help: try using `:tt` instead in the macro definition + = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: no rules expected the token `4` + --> $DIR/nonterminal-matching.rs:33:44 + | +LL | (literal $x:literal) => { bar!(literal $x); }; + | ^^ no rules expected this token in macro call +... +LL | macro_rules! bar { + | ---------------- when calling this macro +... +LL | foo!(literal 4); + | --------------- in this macro invocation + | +note: while trying to match `4` + --> $DIR/nonterminal-matching.rs:43:14 + | +LL | (literal 4) => {}; + | ^ + = note: captured metavariables except for `:tt`, `:ident` and `:lifetime` cannot be compared to other tokens + = note: see for more information + = help: try using `:tt` instead in the macro definition + = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: no rules expected the token `a::b::c` + --> $DIR/nonterminal-matching.rs:34:35 + | +LL | (path $x:path) => { bar!(path $x); }; + | ^^ no rules expected this token in macro call +... +LL | macro_rules! bar { + | ---------------- when calling this macro +... +LL | foo!(path a::b::c); + | ------------------ in this macro invocation + | +note: while trying to match `a` + --> $DIR/nonterminal-matching.rs:44:11 + | +LL | (path a::b::c) => {}; + | ^ + = note: captured metavariables except for `:tt`, `:ident` and `:lifetime` cannot be compared to other tokens + = note: see for more information + = help: try using `:tt` instead in the macro definition + = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: no rules expected the token `let abc = 0` + --> $DIR/nonterminal-matching.rs:35:35 + | +LL | (stmt $x:stmt) => { bar!(stmt $x); }; + | ^^ no rules expected this token in macro call +... +LL | macro_rules! bar { + | ---------------- when calling this macro +... +LL | foo!(stmt let abc = 0); + | ---------------------- in this macro invocation + | +note: while trying to match `let` + --> $DIR/nonterminal-matching.rs:45:11 + | +LL | (stmt let abc = 0) => {}; + | ^^^ + = note: captured metavariables except for `:tt`, `:ident` and `:lifetime` cannot be compared to other tokens + = note: see for more information + = help: try using `:tt` instead in the macro definition + = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 5 previous errors From 2e4d547d4a862aafd9b9b8382a1bbcde1a4c0d32 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 15 May 2024 09:29:11 +1000 Subject: [PATCH 11/23] Extra panic cases. Just some extra sanity checking, making explicit some values not possible in code working with token trees -- we shouldn't be seeing explicit delimiter tokens, because they should be represented as `TokenTree::Delimited`. --- compiler/rustc_ast/src/attr/mod.rs | 9 ++++++++- compiler/rustc_expand/src/config.rs | 6 ++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 676a2377c3b3..593c78df3cdb 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -327,7 +327,8 @@ impl MetaItem { I: Iterator, { // FIXME: Share code with `parse_path`. - let path = match tokens.next().map(|tt| TokenTree::uninterpolate(tt)).as_deref() { + let tt = tokens.next().map(|tt| TokenTree::uninterpolate(tt)); + let path = match tt.as_deref() { Some(&TokenTree::Token( Token { kind: ref kind @ (token::Ident(..) | token::PathSep), span }, _, @@ -368,6 +369,12 @@ impl MetaItem { token::Nonterminal::NtPath(path) => (**path).clone(), _ => return None, }, + Some(TokenTree::Token( + Token { kind: token::OpenDelim(_) | token::CloseDelim(_), .. }, + _, + )) => { + panic!("Should be `AttrTokenTree::Delimited`, not delim tokens: {:?}", tt); + } _ => return None, }; let list_closing_paren_pos = tokens.peek().map(|tt| tt.span().hi()); diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index badfa6d3aa32..56cbb54fcecf 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -214,6 +214,12 @@ impl<'a> StripUnconfigured<'a> { ) => { panic!("Nonterminal should have been flattened: {:?}", tree); } + AttrTokenTree::Token( + Token { kind: TokenKind::OpenDelim(_) | TokenKind::CloseDelim(_), .. }, + _, + ) => { + panic!("Should be `AttrTokenTree::Delimited`, not delim tokens: {:?}", tree); + } AttrTokenTree::Token(token, spacing) => { Some(AttrTokenTree::Token(token, spacing)).into_iter() } From 9828e960ab4cccc9526fd6cc61df430588bd0487 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sun, 23 Jun 2024 16:12:39 +1000 Subject: [PATCH 12/23] Remove `__rust_force_expr`. This was added (with a different name) to improve an error message. It is no longer needed -- removing it changes the error message, but overall I think the new message is no worse: - the mention of `#` in the first line is a little worse, - but the extra context makes it very clear what the problem is, perhaps even clearer than the old message, - and the removal of the note about the `expr` fragment (an internal detail of `__rust_force_expr`) is an improvement. Overall I think the error is quite clear and still far better than the old message that prompted #61933, which didn't even mention patterns. The motivation for this is #124141, which will cause pasted metavariables to be tokenized and reparsed instead of the AST node being cached. This change in behaviour occasionally has a non-zero perf cost, and `__rust_force_expr` causes the tokenize/reparse step to occur twice. Removing `__rust_force_expr` greatly reduces the extra overhead for the `deep-vector` benchmark. --- library/alloc/src/macros.rs | 18 ++++-------------- tests/ui/macros/vec-macro-in-pattern.rs | 2 +- tests/ui/macros/vec-macro-in-pattern.stderr | 7 +++++-- 3 files changed, 10 insertions(+), 17 deletions(-) diff --git a/library/alloc/src/macros.rs b/library/alloc/src/macros.rs index 0f767df6063a..d5ca5c4ed27a 100644 --- a/library/alloc/src/macros.rs +++ b/library/alloc/src/macros.rs @@ -41,18 +41,18 @@ #[allow_internal_unstable(rustc_attrs, liballoc_internals)] macro_rules! vec { () => ( - $crate::__rust_force_expr!($crate::vec::Vec::new()) + $crate::vec::Vec::new() ); ($elem:expr; $n:expr) => ( - $crate::__rust_force_expr!($crate::vec::from_elem($elem, $n)) + $crate::vec::from_elem($elem, $n) ); ($($x:expr),+ $(,)?) => ( - $crate::__rust_force_expr!(<[_]>::into_vec( + <[_]>::into_vec( // This rustc_box is not required, but it produces a dramatic improvement in compile // time when constructing arrays with many elements. #[rustc_box] $crate::boxed::Box::new([$($x),+]) - )) + ) ); } @@ -126,13 +126,3 @@ macro_rules! format { res }} } - -/// Force AST node to an expression to improve diagnostics in pattern position. -#[doc(hidden)] -#[macro_export] -#[unstable(feature = "liballoc_internals", issue = "none", reason = "implementation detail")] -macro_rules! __rust_force_expr { - ($e:expr) => { - $e - }; -} diff --git a/tests/ui/macros/vec-macro-in-pattern.rs b/tests/ui/macros/vec-macro-in-pattern.rs index ce4298b8bb33..26d7d4280fad 100644 --- a/tests/ui/macros/vec-macro-in-pattern.rs +++ b/tests/ui/macros/vec-macro-in-pattern.rs @@ -4,7 +4,7 @@ fn main() { match Some(vec![42]) { - Some(vec![43]) => {} //~ ERROR arbitrary expressions aren't allowed in patterns + Some(vec![43]) => {} //~ ERROR expected pattern, found `#` _ => {} } } diff --git a/tests/ui/macros/vec-macro-in-pattern.stderr b/tests/ui/macros/vec-macro-in-pattern.stderr index 1a446b8c3edb..f32a2cf8e435 100644 --- a/tests/ui/macros/vec-macro-in-pattern.stderr +++ b/tests/ui/macros/vec-macro-in-pattern.stderr @@ -1,10 +1,13 @@ -error: arbitrary expressions aren't allowed in patterns +error: expected pattern, found `#` --> $DIR/vec-macro-in-pattern.rs:7:14 | LL | Some(vec![43]) => {} | ^^^^^^^^ + | | + | expected pattern + | in this macro invocation + | this macro call doesn't expand to a pattern | - = note: the `expr` fragment specifier forces the metavariable's content to be an expression = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error From 379b7614627b3a917a5f459388f95c4fb55c39ad Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 17 Jun 2024 14:44:55 +1000 Subject: [PATCH 13/23] Inline and remove `maybe_whole_expr!`. And remove the `NtPath` and `NtBlock` cases in `parse_literal_maybe_minus`, because they are unnecessary. --- compiler/rustc_parse/src/parser/expr.rs | 73 ++++++++++++++----------- 1 file changed, 41 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 9fad954addad..e0c70884feea 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -39,36 +39,6 @@ use rustc_span::{BytePos, ErrorGuaranteed, Pos, Span}; use thin_vec::{thin_vec, ThinVec}; use tracing::instrument; -/// Possibly accepts an `token::Interpolated` expression (a pre-parsed expression -/// dropped into the token stream, which happens while parsing the result of -/// macro expansion). Placement of these is not as complex as I feared it would -/// be. The important thing is to make sure that lookahead doesn't balk at -/// `token::Interpolated` tokens. -macro_rules! maybe_whole_expr { - ($p:expr) => { - if let token::Interpolated(nt) = &$p.token.kind { - match &**nt { - token::NtExpr(e) | token::NtLiteral(e) => { - let e = e.clone(); - $p.bump(); - return Ok(e); - } - token::NtPath(path) => { - let path = (**path).clone(); - $p.bump(); - return Ok($p.mk_expr($p.prev_token.span, ExprKind::Path(None, path))); - } - token::NtBlock(block) => { - let block = block.clone(); - $p.bump(); - return Ok($p.mk_expr($p.prev_token.span, ExprKind::Block(block, None))); - } - _ => {} - }; - } - }; -} - #[derive(Debug)] pub(super) enum LhsExpr { // Already parsed just the outer attributes. @@ -1421,7 +1391,27 @@ impl<'a> Parser<'a> { /// correctly if called from `parse_dot_or_call_expr()`. fn parse_expr_bottom(&mut self) -> PResult<'a, P> { maybe_recover_from_interpolated_ty_qpath!(self, true); - maybe_whole_expr!(self); + + if let token::Interpolated(nt) = &self.token.kind { + match &**nt { + token::NtExpr(e) | token::NtLiteral(e) => { + let e = e.clone(); + self.bump(); + return Ok(e); + } + token::NtPath(path) => { + let path = (**path).clone(); + self.bump(); + return Ok(self.mk_expr(self.prev_token.span, ExprKind::Path(None, path))); + } + token::NtBlock(block) => { + let block = block.clone(); + self.bump(); + return Ok(self.mk_expr(self.prev_token.span, ExprKind::Block(block, None))); + } + _ => {} + }; + } // Outer attributes are already parsed and will be // added to the return value after the fact. @@ -2190,7 +2180,26 @@ impl<'a> Parser<'a> { /// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`). /// Keep this in sync with `Token::can_begin_literal_maybe_minus`. pub fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P> { - maybe_whole_expr!(self); + if let token::Interpolated(nt) = &self.token.kind { + match &**nt { + // FIXME(nnethercote) The `NtExpr` case should only match if + // `e` is an `ExprKind::Lit` or an `ExprKind::Unary` containing + // an `UnOp::Neg` and an `ExprKind::Lit`, like how + // `can_begin_literal_maybe_minus` works. But this method has + // been over-accepting for a long time, and to make that change + // here requires also changing some `parse_literal_maybe_minus` + // call sites to accept additional expression kinds. E.g. + // `ExprKind::Path` must be accepted when parsing range + // patterns. That requires some care. So for now, we continue + // being less strict here than we should be. + token::NtExpr(e) | token::NtLiteral(e) => { + let e = e.clone(); + self.bump(); + return Ok(e); + } + _ => {} + }; + } let lo = self.token.span; let minus_present = self.eat(&token::BinOp(token::Minus)); From 457fda1701e191d9ff439d9d01ee650e6bbefee6 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 20 Jun 2024 10:49:40 +1000 Subject: [PATCH 14/23] coverage: Detach `#[coverage(..)]` from codegen attribute handling --- .../rustc_codegen_ssa/src/codegen_attrs.rs | 17 ------------ .../src/middle/codegen_fn_attrs.rs | 5 +--- compiler/rustc_middle/src/query/mod.rs | 8 ++++++ .../rustc_mir_transform/src/coverage/query.rs | 27 ++++++++++++++++++- 4 files changed, 35 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index fb71cdaa8ff2..d224695d1f28 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -124,22 +124,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { .emit(); } } - sym::coverage => { - let inner = attr.meta_item_list(); - match inner.as_deref() { - Some([item]) if item.has_name(sym::off) => { - codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE; - } - Some([item]) if item.has_name(sym::on) => { - // Allow #[coverage(on)] for being explicit, maybe also in future to enable - // coverage on a smaller scope within an excluded larger scope. - } - Some(_) | None => { - tcx.dcx() - .span_delayed_bug(attr.span, "unexpected value of coverage attribute"); - } - } - } sym::rustc_std_internal_symbol => { codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL } @@ -584,7 +568,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { } if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) { - codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE; codegen_fn_attrs.inline = InlineAttr::Never; } diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index 3fa5054baed1..c8f0d0795a3c 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -87,10 +87,7 @@ bitflags::bitflags! { /// #[cmse_nonsecure_entry]: with a TrustZone-M extension, declare a /// function as an entry function from Non-Secure code. const CMSE_NONSECURE_ENTRY = 1 << 13; - /// `#[coverage(off)]`: indicates that the function should be ignored by - /// the MIR `InstrumentCoverage` pass and not added to the coverage map - /// during codegen. - const NO_COVERAGE = 1 << 14; + // (Bit 14 was used for `#[coverage(off)]`, but is now unused.) /// `#[used(linker)]`: /// indicates that neither LLVM nor the linker will eliminate this function. const USED_LINKER = 1 << 15; diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index c5afecffb07a..320e21e85da0 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -572,6 +572,14 @@ rustc_queries! { separate_provide_extern } + /// Checks for `#[coverage(off)]` or `#[coverage(on)]`. + /// + /// Returns `false` if `#[coverage(off)]` was found, or `true` if + /// either `#[coverage(on)]` or no coverage attribute was found. + query coverage_attr_on(key: LocalDefId) -> bool { + desc { |tcx| "checking for `#[coverage(..)]` on `{}`", tcx.def_path_str(key) } + } + /// Summarizes coverage IDs inserted by the `InstrumentCoverage` MIR pass /// (for compiler option `-Cinstrument-coverage`), after MIR optimizations /// have had a chance to potentially remove some of them. diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs index 25744009be8b..14dcb7ef424a 100644 --- a/compiler/rustc_mir_transform/src/coverage/query.rs +++ b/compiler/rustc_mir_transform/src/coverage/query.rs @@ -6,11 +6,13 @@ use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::util::Providers; use rustc_span::def_id::LocalDefId; +use rustc_span::sym; /// Registers query/hook implementations related to coverage. pub(crate) fn provide(providers: &mut Providers) { providers.hooks.is_eligible_for_coverage = |TyCtxtAt { tcx, .. }, def_id| is_eligible_for_coverage(tcx, def_id); + providers.queries.coverage_attr_on = coverage_attr_on; providers.queries.coverage_ids_info = coverage_ids_info; } @@ -38,7 +40,12 @@ fn is_eligible_for_coverage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { return false; } - if tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::NO_COVERAGE) { + if tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::NAKED) { + trace!("InstrumentCoverage skipped for {def_id:?} (`#[naked]`)"); + return false; + } + + if !tcx.coverage_attr_on(def_id) { trace!("InstrumentCoverage skipped for {def_id:?} (`#[coverage(off)]`)"); return false; } @@ -46,6 +53,24 @@ fn is_eligible_for_coverage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { true } +/// Query implementation for `coverage_attr_on`. +fn coverage_attr_on(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { + if let Some(attr) = tcx.get_attr(def_id, sym::coverage) { + match attr.meta_item_list().as_deref() { + Some([item]) if item.has_name(sym::off) => return false, + Some([item]) if item.has_name(sym::on) => return true, + Some(_) | None => { + // Other possibilities should have been rejected by `rustc_parse::validate_attr`. + tcx.dcx().span_bug(attr.span, "unexpected value of coverage attribute"); + } + } + } + + // We didn't see an explicit coverage attribute, so + // allow coverage instrumentation by default. + true +} + /// Query implementation for `coverage_ids_info`. fn coverage_ids_info<'tcx>( tcx: TyCtxt<'tcx>, From 3262611cc5db7ce83dee4268fb1901311b24e5fc Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 22 Jun 2024 16:34:24 +1000 Subject: [PATCH 15/23] coverage: Apply `#[coverage(..)]` recursively to nested functions --- compiler/rustc_middle/src/query/mod.rs | 3 +- .../rustc_mir_transform/src/coverage/query.rs | 12 ++- tests/coverage/attr/nested.cov-map | 82 ------------------- tests/coverage/attr/nested.coverage | 74 ++++++++--------- tests/coverage/attr/off-on-sandwich.cov-map | 8 -- tests/coverage/attr/off-on-sandwich.coverage | 10 +-- tests/coverage/no_cov_crate.cov-map | 13 --- tests/coverage/no_cov_crate.coverage | 14 ++-- 8 files changed, 60 insertions(+), 156 deletions(-) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 320e21e85da0..230a44bcf245 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -572,7 +572,8 @@ rustc_queries! { separate_provide_extern } - /// Checks for `#[coverage(off)]` or `#[coverage(on)]`. + /// Checks for the nearest `#[coverage(off)]` or `#[coverage(on)]` on + /// this def and any enclosing defs, up to the crate root. /// /// Returns `false` if `#[coverage(off)]` was found, or `true` if /// either `#[coverage(on)]` or no coverage attribute was found. diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs index 14dcb7ef424a..1fce2abbbbf7 100644 --- a/compiler/rustc_mir_transform/src/coverage/query.rs +++ b/compiler/rustc_mir_transform/src/coverage/query.rs @@ -55,6 +55,7 @@ fn is_eligible_for_coverage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { /// Query implementation for `coverage_attr_on`. fn coverage_attr_on(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { + // Check for annotations directly on this def. if let Some(attr) = tcx.get_attr(def_id, sym::coverage) { match attr.meta_item_list().as_deref() { Some([item]) if item.has_name(sym::off) => return false, @@ -66,9 +67,14 @@ fn coverage_attr_on(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { } } - // We didn't see an explicit coverage attribute, so - // allow coverage instrumentation by default. - true + match tcx.opt_local_parent(def_id) { + // Check the parent def (and so on recursively) until we find an + // enclosing attribute or reach the crate root. + Some(parent) => tcx.coverage_attr_on(parent), + // We reached the crate root without seeing a coverage attribute, so + // allow coverage instrumentation by default. + None => true, + } } /// Query implementation for `coverage_ids_info`. diff --git a/tests/coverage/attr/nested.cov-map b/tests/coverage/attr/nested.cov-map index a613bb7f8cdf..0f2d5542f753 100644 --- a/tests/coverage/attr/nested.cov-map +++ b/tests/coverage/attr/nested.cov-map @@ -1,35 +1,3 @@ -Function name: <<::trait_method::MyMiddle as nested::MyTrait>::trait_method::MyInner as nested::MyTrait>::trait_method (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 39, 15, 02, 16] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 57, 21) to (start + 2, 22) - -Function name: <<::outer_method::MyMiddle>::middle_method::MyInner>::inner_method (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 23, 15, 02, 16] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 35, 21) to (start + 2, 22) - -Function name: <::trait_method::MyMiddle as nested::MyTrait>::trait_method (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 36, 0d, 08, 0e] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 54, 13) to (start + 8, 14) - -Function name: <::outer_method::MyMiddle>::middle_method (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 20, 0d, 08, 0e] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 32, 13) to (start + 8, 14) - Function name: nested::closure_expr Raw bytes (14): 0x[01, 01, 00, 02, 01, 44, 01, 01, 0f, 01, 0b, 05, 01, 02] Number of files: 1 @@ -39,23 +7,6 @@ Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 68, 1) to (start + 1, 15) - Code(Counter(0)) at (prev + 11, 5) to (start + 1, 2) -Function name: nested::closure_expr::{closure#0}::{closure#0} (unused) -Raw bytes (14): 0x[01, 01, 00, 02, 00, 47, 1a, 01, 17, 00, 04, 0d, 01, 0a] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 0 -Number of file 0 mappings: 2 -- Code(Zero) at (prev + 71, 26) to (start + 1, 23) -- Code(Zero) at (prev + 4, 13) to (start + 1, 10) - -Function name: nested::closure_expr::{closure#0}::{closure#0}::{closure#0} (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 48, 1d, 02, 0e] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 72, 29) to (start + 2, 14) - Function name: nested::closure_tail Raw bytes (14): 0x[01, 01, 00, 02, 01, 53, 01, 01, 0f, 01, 11, 05, 01, 02] Number of files: 1 @@ -65,36 +16,3 @@ Number of file 0 mappings: 2 - Code(Counter(0)) at (prev + 83, 1) to (start + 1, 15) - Code(Counter(0)) at (prev + 17, 5) to (start + 1, 2) -Function name: nested::closure_tail::{closure#0}::{closure#0} (unused) -Raw bytes (14): 0x[01, 01, 00, 02, 00, 58, 14, 01, 1f, 00, 06, 15, 01, 12] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 0 -Number of file 0 mappings: 2 -- Code(Zero) at (prev + 88, 20) to (start + 1, 31) -- Code(Zero) at (prev + 6, 21) to (start + 1, 18) - -Function name: nested::closure_tail::{closure#0}::{closure#0}::{closure#0} (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 5a, 1c, 02, 1a] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 90, 28) to (start + 2, 26) - -Function name: nested::outer_fn::middle_fn (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 11, 05, 05, 06] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 17, 5) to (start + 5, 6) - -Function name: nested::outer_fn::middle_fn::inner_fn (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 12, 09, 02, 0a] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 18, 9) to (start + 2, 10) - diff --git a/tests/coverage/attr/nested.coverage b/tests/coverage/attr/nested.coverage index 13129572aec7..bdd117b7dfaf 100644 --- a/tests/coverage/attr/nested.coverage +++ b/tests/coverage/attr/nested.coverage @@ -14,12 +14,12 @@ LL| | LL| |#[coverage(off)] LL| |fn outer_fn() { - LL| 0| fn middle_fn() { - LL| 0| fn inner_fn() { - LL| 0| do_stuff(); - LL| 0| } - LL| 0| do_stuff(); - LL| 0| } + LL| | fn middle_fn() { + LL| | fn inner_fn() { + LL| | do_stuff(); + LL| | } + LL| | do_stuff(); + LL| | } LL| | do_stuff(); LL| |} LL| | @@ -29,15 +29,15 @@ LL| | fn outer_method(&self) { LL| | struct MyMiddle; LL| | impl MyMiddle { - LL| 0| fn middle_method(&self) { - LL| 0| struct MyInner; - LL| 0| impl MyInner { - LL| 0| fn inner_method(&self) { - LL| 0| do_stuff(); - LL| 0| } - LL| 0| } - LL| 0| do_stuff(); - LL| 0| } + LL| | fn middle_method(&self) { + LL| | struct MyInner; + LL| | impl MyInner { + LL| | fn inner_method(&self) { + LL| | do_stuff(); + LL| | } + LL| | } + LL| | do_stuff(); + LL| | } LL| | } LL| | do_stuff(); LL| | } @@ -51,15 +51,15 @@ LL| | fn trait_method(&self) { LL| | struct MyMiddle; LL| | impl MyTrait for MyMiddle { - LL| 0| fn trait_method(&self) { - LL| 0| struct MyInner; - LL| 0| impl MyTrait for MyInner { - LL| 0| fn trait_method(&self) { - LL| 0| do_stuff(); - LL| 0| } - LL| 0| } - LL| 0| do_stuff(); - LL| 0| } + LL| | fn trait_method(&self) { + LL| | struct MyInner; + LL| | impl MyTrait for MyInner { + LL| | fn trait_method(&self) { + LL| | do_stuff(); + LL| | } + LL| | } + LL| | do_stuff(); + LL| | } LL| | } LL| | do_stuff(); LL| | } @@ -68,12 +68,12 @@ LL| 1|fn closure_expr() { LL| 1| let _outer = #[coverage(off)] LL| | || { - LL| 0| let _middle = || { - LL| 0| let _inner = || { - LL| 0| do_stuff(); - LL| 0| }; - LL| 0| do_stuff(); - LL| 0| }; + LL| | let _middle = || { + LL| | let _inner = || { + LL| | do_stuff(); + LL| | }; + LL| | do_stuff(); + LL| | }; LL| | do_stuff(); LL| | }; LL| 1| do_stuff(); @@ -85,14 +85,14 @@ LL| | #[coverage(off)] LL| | || { LL| | let _middle = { - LL| 0| || { - LL| 0| let _inner = { - LL| 0| || { - LL| 0| do_stuff(); - LL| 0| } + LL| | || { + LL| | let _inner = { + LL| | || { + LL| | do_stuff(); + LL| | } LL| | }; - LL| 0| do_stuff(); - LL| 0| } + LL| | do_stuff(); + LL| | } LL| | }; LL| | do_stuff(); LL| | } diff --git a/tests/coverage/attr/off-on-sandwich.cov-map b/tests/coverage/attr/off-on-sandwich.cov-map index 72b96420cb56..ed77d7d17e6a 100644 --- a/tests/coverage/attr/off-on-sandwich.cov-map +++ b/tests/coverage/attr/off-on-sandwich.cov-map @@ -6,14 +6,6 @@ Number of expressions: 0 Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 20, 5) to (start + 7, 6) -Function name: off_on_sandwich::sparse_a::sparse_b -Raw bytes (9): 0x[01, 01, 00, 01, 01, 22, 05, 10, 06] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 34, 5) to (start + 16, 6) - Function name: off_on_sandwich::sparse_a::sparse_b::sparse_c Raw bytes (9): 0x[01, 01, 00, 01, 01, 26, 09, 0b, 0a] Number of files: 1 diff --git a/tests/coverage/attr/off-on-sandwich.coverage b/tests/coverage/attr/off-on-sandwich.coverage index e831b0e926e3..58c128b83424 100644 --- a/tests/coverage/attr/off-on-sandwich.coverage +++ b/tests/coverage/attr/off-on-sandwich.coverage @@ -31,10 +31,10 @@ LL| |fn sparse_a() { LL| | sparse_b(); LL| | sparse_b(); - LL| 2| fn sparse_b() { - LL| 2| sparse_c(); - LL| 2| sparse_c(); - LL| 2| #[coverage(on)] + LL| | fn sparse_b() { + LL| | sparse_c(); + LL| | sparse_c(); + LL| | #[coverage(on)] LL| 4| fn sparse_c() { LL| 4| sparse_d(); LL| 4| sparse_d(); @@ -47,7 +47,7 @@ LL| 8| } LL| 8| } LL| 4| } - LL| 2| } + LL| | } LL| |} LL| | LL| |#[coverage(off)] diff --git a/tests/coverage/no_cov_crate.cov-map b/tests/coverage/no_cov_crate.cov-map index e623f6480b90..281efb6d00d9 100644 --- a/tests/coverage/no_cov_crate.cov-map +++ b/tests/coverage/no_cov_crate.cov-map @@ -59,16 +59,3 @@ Number of file 0 mappings: 4 = (c0 - c1) - Code(Counter(0)) at (prev + 3, 9) to (start + 0, 10) -Function name: no_cov_crate::nested_fns::outer_not_covered::inner -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 26, 09, 01, 17, 05, 01, 18, 02, 0e, 02, 02, 14, 02, 0e, 01, 03, 09, 00, 0a] -Number of files: 1 -- file 0 => global file 1 -Number of expressions: 1 -- expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 38, 9) to (start + 1, 23) -- Code(Counter(1)) at (prev + 1, 24) to (start + 2, 14) -- Code(Expression(0, Sub)) at (prev + 2, 20) to (start + 2, 14) - = (c0 - c1) -- Code(Counter(0)) at (prev + 3, 9) to (start + 0, 10) - diff --git a/tests/coverage/no_cov_crate.coverage b/tests/coverage/no_cov_crate.coverage index f5a0322bf3ee..29ad1f979cf8 100644 --- a/tests/coverage/no_cov_crate.coverage +++ b/tests/coverage/no_cov_crate.coverage @@ -35,13 +35,13 @@ LL| |mod nested_fns { LL| | #[coverage(off)] LL| | pub fn outer_not_covered(is_true: bool) { - LL| 1| fn inner(is_true: bool) { - LL| 1| if is_true { - LL| 1| println!("called and covered"); - LL| 1| } else { - LL| 0| println!("absolutely not covered"); - LL| 0| } - LL| 1| } + LL| | fn inner(is_true: bool) { + LL| | if is_true { + LL| | println!("called and covered"); + LL| | } else { + LL| | println!("absolutely not covered"); + LL| | } + LL| | } LL| | println!("called but not covered"); LL| | inner(is_true); LL| | } From 7f37f8af5f067e0f4f8d14adb7d76f013e3c4118 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 21 Jun 2024 21:59:02 +1000 Subject: [PATCH 16/23] coverage: Allow `#[coverage(..)]` on `impl` and `mod` These attributes apply to all enclosed functions/methods/closures, unless explicitly overridden by another coverage attribute. --- compiler/rustc_passes/src/check_attr.rs | 9 ++- tests/coverage/attr/impl.cov-map | 24 +++++++ tests/coverage/attr/impl.coverage | 42 +++++++++++ tests/coverage/attr/impl.rs | 41 +++++++++++ tests/coverage/attr/module.cov-map | 24 +++++++ tests/coverage/attr/module.coverage | 38 ++++++++++ tests/coverage/attr/module.rs | 37 ++++++++++ tests/ui/coverage-attr/name-value.rs | 4 -- tests/ui/coverage-attr/name-value.stderr | 87 +++++------------------ tests/ui/coverage-attr/no-coverage.rs | 4 +- tests/ui/coverage-attr/no-coverage.stderr | 22 +----- tests/ui/coverage-attr/word-only.rs | 4 -- tests/ui/coverage-attr/word-only.stderr | 87 +++++------------------ 13 files changed, 253 insertions(+), 170 deletions(-) create mode 100644 tests/coverage/attr/impl.cov-map create mode 100644 tests/coverage/attr/impl.coverage create mode 100644 tests/coverage/attr/impl.rs create mode 100644 tests/coverage/attr/module.cov-map create mode 100644 tests/coverage/attr/module.coverage create mode 100644 tests/coverage/attr/module.rs diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index d33f12a973fd..5f8e4a8b7a76 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -369,13 +369,16 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - /// Checks that `#[coverage(..)]` is applied to a function or closure. + /// Checks that `#[coverage(..)]` is applied to a function/closure/method, + /// or to an impl block or module. fn check_coverage(&self, attr: &Attribute, span: Span, target: Target) -> bool { match target { - // #[coverage(..)] on function is fine Target::Fn | Target::Closure - | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true, + | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) + | Target::Impl + | Target::Mod => true, + _ => { self.dcx().emit_err(errors::CoverageNotFnOrClosure { attr_span: attr.span, diff --git a/tests/coverage/attr/impl.cov-map b/tests/coverage/attr/impl.cov-map new file mode 100644 index 000000000000..9b0deed8b64c --- /dev/null +++ b/tests/coverage/attr/impl.cov-map @@ -0,0 +1,24 @@ +Function name: ::off_on (unused) +Raw bytes (9): 0x[01, 01, 00, 01, 00, 0e, 05, 00, 13] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Zero) at (prev + 14, 5) to (start + 0, 19) + +Function name: ::on_inherit (unused) +Raw bytes (9): 0x[01, 01, 00, 01, 00, 16, 05, 00, 17] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Zero) at (prev + 22, 5) to (start + 0, 23) + +Function name: ::on_on (unused) +Raw bytes (9): 0x[01, 01, 00, 01, 00, 19, 05, 00, 12] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Zero) at (prev + 25, 5) to (start + 0, 18) + diff --git a/tests/coverage/attr/impl.coverage b/tests/coverage/attr/impl.coverage new file mode 100644 index 000000000000..560429fb5fe5 --- /dev/null +++ b/tests/coverage/attr/impl.coverage @@ -0,0 +1,42 @@ + LL| |#![feature(coverage_attribute)] + LL| |//@ edition: 2021 + LL| | + LL| |// Checks that `#[coverage(..)]` can be applied to impl and impl-trait blocks, + LL| |// and is inherited by any enclosed functions. + LL| | + LL| |struct MyStruct; + LL| | + LL| |#[coverage(off)] + LL| |impl MyStruct { + LL| | fn off_inherit() {} + LL| | + LL| | #[coverage(on)] + LL| 0| fn off_on() {} + LL| | + LL| | #[coverage(off)] + LL| | fn off_off() {} + LL| |} + LL| | + LL| |#[coverage(on)] + LL| |impl MyStruct { + LL| 0| fn on_inherit() {} + LL| | + LL| | #[coverage(on)] + LL| 0| fn on_on() {} + LL| | + LL| | #[coverage(off)] + LL| | fn on_off() {} + LL| |} + LL| | + LL| |trait MyTrait { + LL| | fn method(); + LL| |} + LL| | + LL| |#[coverage(off)] + LL| |impl MyTrait for MyStruct { + LL| | fn method() {} + LL| |} + LL| | + LL| |#[coverage(off)] + LL| |fn main() {} + diff --git a/tests/coverage/attr/impl.rs b/tests/coverage/attr/impl.rs new file mode 100644 index 000000000000..d4d784a3502b --- /dev/null +++ b/tests/coverage/attr/impl.rs @@ -0,0 +1,41 @@ +#![feature(coverage_attribute)] +//@ edition: 2021 + +// Checks that `#[coverage(..)]` can be applied to impl and impl-trait blocks, +// and is inherited by any enclosed functions. + +struct MyStruct; + +#[coverage(off)] +impl MyStruct { + fn off_inherit() {} + + #[coverage(on)] + fn off_on() {} + + #[coverage(off)] + fn off_off() {} +} + +#[coverage(on)] +impl MyStruct { + fn on_inherit() {} + + #[coverage(on)] + fn on_on() {} + + #[coverage(off)] + fn on_off() {} +} + +trait MyTrait { + fn method(); +} + +#[coverage(off)] +impl MyTrait for MyStruct { + fn method() {} +} + +#[coverage(off)] +fn main() {} diff --git a/tests/coverage/attr/module.cov-map b/tests/coverage/attr/module.cov-map new file mode 100644 index 000000000000..34898eb4ca81 --- /dev/null +++ b/tests/coverage/attr/module.cov-map @@ -0,0 +1,24 @@ +Function name: module::off::on (unused) +Raw bytes (9): 0x[01, 01, 00, 01, 00, 0c, 05, 00, 0f] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Zero) at (prev + 12, 5) to (start + 0, 15) + +Function name: module::on::inherit (unused) +Raw bytes (9): 0x[01, 01, 00, 01, 00, 14, 05, 00, 14] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Zero) at (prev + 20, 5) to (start + 0, 20) + +Function name: module::on::on (unused) +Raw bytes (9): 0x[01, 01, 00, 01, 00, 17, 05, 00, 0f] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Zero) at (prev + 23, 5) to (start + 0, 15) + diff --git a/tests/coverage/attr/module.coverage b/tests/coverage/attr/module.coverage new file mode 100644 index 000000000000..c1b9f0e35c0b --- /dev/null +++ b/tests/coverage/attr/module.coverage @@ -0,0 +1,38 @@ + LL| |#![feature(coverage_attribute)] + LL| |//@ edition: 2021 + LL| | + LL| |// Checks that `#[coverage(..)]` can be applied to modules, and is inherited + LL| |// by any enclosed functions. + LL| | + LL| |#[coverage(off)] + LL| |mod off { + LL| | fn inherit() {} + LL| | + LL| | #[coverage(on)] + LL| 0| fn on() {} + LL| | + LL| | #[coverage(off)] + LL| | fn off() {} + LL| |} + LL| | + LL| |#[coverage(on)] + LL| |mod on { + LL| 0| fn inherit() {} + LL| | + LL| | #[coverage(on)] + LL| 0| fn on() {} + LL| | + LL| | #[coverage(off)] + LL| | fn off() {} + LL| |} + LL| | + LL| |#[coverage(off)] + LL| |mod nested_a { + LL| | mod nested_b { + LL| | fn inner() {} + LL| | } + LL| |} + LL| | + LL| |#[coverage(off)] + LL| |fn main() {} + diff --git a/tests/coverage/attr/module.rs b/tests/coverage/attr/module.rs new file mode 100644 index 000000000000..4bfb1e7729b7 --- /dev/null +++ b/tests/coverage/attr/module.rs @@ -0,0 +1,37 @@ +#![feature(coverage_attribute)] +//@ edition: 2021 + +// Checks that `#[coverage(..)]` can be applied to modules, and is inherited +// by any enclosed functions. + +#[coverage(off)] +mod off { + fn inherit() {} + + #[coverage(on)] + fn on() {} + + #[coverage(off)] + fn off() {} +} + +#[coverage(on)] +mod on { + fn inherit() {} + + #[coverage(on)] + fn on() {} + + #[coverage(off)] + fn off() {} +} + +#[coverage(off)] +mod nested_a { + mod nested_b { + fn inner() {} + } +} + +#[coverage(off)] +fn main() {} diff --git a/tests/ui/coverage-attr/name-value.rs b/tests/ui/coverage-attr/name-value.rs index cfd78a03e438..24a0feb0710f 100644 --- a/tests/ui/coverage-attr/name-value.rs +++ b/tests/ui/coverage-attr/name-value.rs @@ -10,13 +10,11 @@ #[coverage = "off"] //~^ ERROR malformed `coverage` attribute input -//~| ERROR attribute should be applied to a function definition or closure mod my_mod {} mod my_mod_inner { #![coverage = "off"] //~^ ERROR malformed `coverage` attribute input - //~| ERROR attribute should be applied to a function definition or closure } #[coverage = "off"] @@ -26,7 +24,6 @@ struct MyStruct; #[coverage = "off"] //~^ ERROR malformed `coverage` attribute input -//~| ERROR attribute should be applied to a function definition or closure impl MyStruct { #[coverage = "off"] //~^ ERROR malformed `coverage` attribute input @@ -51,7 +48,6 @@ trait MyTrait { #[coverage = "off"] //~^ ERROR malformed `coverage` attribute input -//~| ERROR attribute should be applied to a function definition or closure impl MyTrait for MyStruct { #[coverage = "off"] //~^ ERROR malformed `coverage` attribute input diff --git a/tests/ui/coverage-attr/name-value.stderr b/tests/ui/coverage-attr/name-value.stderr index caac687c94d0..986467dda698 100644 --- a/tests/ui/coverage-attr/name-value.stderr +++ b/tests/ui/coverage-attr/name-value.stderr @@ -12,7 +12,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/name-value.rs:17:5 + --> $DIR/name-value.rs:16:5 | LL | #![coverage = "off"] | ^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | #![coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/name-value.rs:22:1 + --> $DIR/name-value.rs:20:1 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ @@ -38,7 +38,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/name-value.rs:31:5 + --> $DIR/name-value.rs:28:5 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ @@ -51,7 +51,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/name-value.rs:27:1 + --> $DIR/name-value.rs:25:1 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ @@ -64,7 +64,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/name-value.rs:41:5 + --> $DIR/name-value.rs:38:5 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ @@ -77,7 +77,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/name-value.rs:46:5 + --> $DIR/name-value.rs:43:5 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ @@ -90,7 +90,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/name-value.rs:37:1 + --> $DIR/name-value.rs:34:1 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ @@ -103,7 +103,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/name-value.rs:56:5 + --> $DIR/name-value.rs:52:5 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ @@ -116,7 +116,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/name-value.rs:61:5 + --> $DIR/name-value.rs:57:5 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ @@ -129,7 +129,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/name-value.rs:52:1 + --> $DIR/name-value.rs:49:1 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ @@ -142,7 +142,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/name-value.rs:67:1 + --> $DIR/name-value.rs:63:1 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ @@ -155,27 +155,7 @@ LL | #[coverage(on)] | error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/name-value.rs:11:1 - | -LL | #[coverage = "off"] - | ^^^^^^^^^^^^^^^^^^^ -... -LL | mod my_mod {} - | ------------- not a function or closure - -error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/name-value.rs:17:5 - | -LL | / mod my_mod_inner { -LL | | #![coverage = "off"] - | | ^^^^^^^^^^^^^^^^^^^^ -LL | | -LL | | -LL | | } - | |_- not a function or closure - -error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/name-value.rs:22:1 + --> $DIR/name-value.rs:20:1 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ @@ -184,21 +164,7 @@ LL | struct MyStruct; | ---------------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/name-value.rs:27:1 - | -LL | #[coverage = "off"] - | ^^^^^^^^^^^^^^^^^^^ -... -LL | / impl MyStruct { -LL | | #[coverage = "off"] -LL | | -LL | | -LL | | const X: u32 = 7; -LL | | } - | |_- not a function or closure - -error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/name-value.rs:37:1 + --> $DIR/name-value.rs:34:1 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ @@ -213,22 +179,7 @@ LL | | } | |_- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/name-value.rs:52:1 - | -LL | #[coverage = "off"] - | ^^^^^^^^^^^^^^^^^^^ -... -LL | / impl MyTrait for MyStruct { -LL | | #[coverage = "off"] -LL | | -LL | | -... | -LL | | type T = (); -LL | | } - | |_- not a function or closure - -error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/name-value.rs:41:5 + --> $DIR/name-value.rs:38:5 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ @@ -237,7 +188,7 @@ LL | const X: u32; | ------------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/name-value.rs:46:5 + --> $DIR/name-value.rs:43:5 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ @@ -246,7 +197,7 @@ LL | type T; | ------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/name-value.rs:31:5 + --> $DIR/name-value.rs:28:5 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ @@ -255,7 +206,7 @@ LL | const X: u32 = 7; | ----------------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/name-value.rs:56:5 + --> $DIR/name-value.rs:52:5 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ @@ -264,7 +215,7 @@ LL | const X: u32 = 8; | ----------------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/name-value.rs:61:5 + --> $DIR/name-value.rs:57:5 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ @@ -272,6 +223,6 @@ LL | #[coverage = "off"] LL | type T = (); | ------------ not a function or closure -error: aborting due to 23 previous errors +error: aborting due to 19 previous errors For more information about this error, try `rustc --explain E0788`. diff --git a/tests/ui/coverage-attr/no-coverage.rs b/tests/ui/coverage-attr/no-coverage.rs index 5290fccca610..9545b0b55cf2 100644 --- a/tests/ui/coverage-attr/no-coverage.rs +++ b/tests/ui/coverage-attr/no-coverage.rs @@ -2,7 +2,7 @@ #![feature(coverage_attribute)] #![feature(impl_trait_in_assoc_type)] #![warn(unused_attributes)] -#![coverage(off)] //~ ERROR attribute should be applied to a function definition or closure +#![coverage(off)] #[coverage(off)] //~ ERROR attribute should be applied to a function definition or closure trait Trait { @@ -15,7 +15,7 @@ trait Trait { type U; } -#[coverage(off)] //~ ERROR attribute should be applied to a function definition or closure +#[coverage(off)] impl Trait for () { const X: u32 = 0; diff --git a/tests/ui/coverage-attr/no-coverage.stderr b/tests/ui/coverage-attr/no-coverage.stderr index c5e3b0922cb4..3897d295940e 100644 --- a/tests/ui/coverage-attr/no-coverage.stderr +++ b/tests/ui/coverage-attr/no-coverage.stderr @@ -11,20 +11,6 @@ LL | | type U; LL | | } | |_- not a function or closure -error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/no-coverage.rs:18:1 - | -LL | #[coverage(off)] - | ^^^^^^^^^^^^^^^^ -LL | / impl Trait for () { -LL | | const X: u32 = 0; -LL | | -LL | | #[coverage(off)] -... | -LL | | type U = impl Trait; -LL | | } - | |_- not a function or closure - error[E0788]: attribute should be applied to a function definition or closure --> $DIR/no-coverage.rs:39:5 | @@ -97,12 +83,6 @@ LL | #[coverage(off)] LL | type T; | ------- not a function or closure -error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/no-coverage.rs:5:1 - | -LL | #![coverage(off)] - | ^^^^^^^^^^^^^^^^^ not a function or closure - error: unconstrained opaque type --> $DIR/no-coverage.rs:26:14 | @@ -111,6 +91,6 @@ LL | type U = impl Trait; | = note: `U` must be used in combination with a concrete type within the same impl -error: aborting due to 13 previous errors +error: aborting due to 11 previous errors For more information about this error, try `rustc --explain E0788`. diff --git a/tests/ui/coverage-attr/word-only.rs b/tests/ui/coverage-attr/word-only.rs index 0a61d1e709f5..ea12e7b19eef 100644 --- a/tests/ui/coverage-attr/word-only.rs +++ b/tests/ui/coverage-attr/word-only.rs @@ -10,13 +10,11 @@ #[coverage] //~^ ERROR malformed `coverage` attribute input -//~| ERROR attribute should be applied to a function definition or closure mod my_mod {} mod my_mod_inner { #![coverage] //~^ ERROR malformed `coverage` attribute input - //~| ERROR attribute should be applied to a function definition or closure } #[coverage] @@ -26,7 +24,6 @@ struct MyStruct; #[coverage] //~^ ERROR malformed `coverage` attribute input -//~| ERROR attribute should be applied to a function definition or closure impl MyStruct { #[coverage] //~^ ERROR malformed `coverage` attribute input @@ -51,7 +48,6 @@ trait MyTrait { #[coverage] //~^ ERROR malformed `coverage` attribute input -//~| ERROR attribute should be applied to a function definition or closure impl MyTrait for MyStruct { #[coverage] //~^ ERROR malformed `coverage` attribute input diff --git a/tests/ui/coverage-attr/word-only.stderr b/tests/ui/coverage-attr/word-only.stderr index 18b5fed74847..1ce149724c6f 100644 --- a/tests/ui/coverage-attr/word-only.stderr +++ b/tests/ui/coverage-attr/word-only.stderr @@ -12,7 +12,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/word-only.rs:17:5 + --> $DIR/word-only.rs:16:5 | LL | #![coverage] | ^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | #![coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/word-only.rs:22:1 + --> $DIR/word-only.rs:20:1 | LL | #[coverage] | ^^^^^^^^^^^ @@ -38,7 +38,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/word-only.rs:31:5 + --> $DIR/word-only.rs:28:5 | LL | #[coverage] | ^^^^^^^^^^^ @@ -51,7 +51,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/word-only.rs:27:1 + --> $DIR/word-only.rs:25:1 | LL | #[coverage] | ^^^^^^^^^^^ @@ -64,7 +64,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/word-only.rs:41:5 + --> $DIR/word-only.rs:38:5 | LL | #[coverage] | ^^^^^^^^^^^ @@ -77,7 +77,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/word-only.rs:46:5 + --> $DIR/word-only.rs:43:5 | LL | #[coverage] | ^^^^^^^^^^^ @@ -90,7 +90,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/word-only.rs:37:1 + --> $DIR/word-only.rs:34:1 | LL | #[coverage] | ^^^^^^^^^^^ @@ -103,7 +103,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/word-only.rs:56:5 + --> $DIR/word-only.rs:52:5 | LL | #[coverage] | ^^^^^^^^^^^ @@ -116,7 +116,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/word-only.rs:61:5 + --> $DIR/word-only.rs:57:5 | LL | #[coverage] | ^^^^^^^^^^^ @@ -129,7 +129,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/word-only.rs:52:1 + --> $DIR/word-only.rs:49:1 | LL | #[coverage] | ^^^^^^^^^^^ @@ -142,7 +142,7 @@ LL | #[coverage(on)] | error: malformed `coverage` attribute input - --> $DIR/word-only.rs:67:1 + --> $DIR/word-only.rs:63:1 | LL | #[coverage] | ^^^^^^^^^^^ @@ -155,27 +155,7 @@ LL | #[coverage(on)] | error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/word-only.rs:11:1 - | -LL | #[coverage] - | ^^^^^^^^^^^ -... -LL | mod my_mod {} - | ------------- not a function or closure - -error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/word-only.rs:17:5 - | -LL | / mod my_mod_inner { -LL | | #![coverage] - | | ^^^^^^^^^^^^ -LL | | -LL | | -LL | | } - | |_- not a function or closure - -error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/word-only.rs:22:1 + --> $DIR/word-only.rs:20:1 | LL | #[coverage] | ^^^^^^^^^^^ @@ -184,21 +164,7 @@ LL | struct MyStruct; | ---------------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/word-only.rs:27:1 - | -LL | #[coverage] - | ^^^^^^^^^^^ -... -LL | / impl MyStruct { -LL | | #[coverage] -LL | | -LL | | -LL | | const X: u32 = 7; -LL | | } - | |_- not a function or closure - -error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/word-only.rs:37:1 + --> $DIR/word-only.rs:34:1 | LL | #[coverage] | ^^^^^^^^^^^ @@ -213,22 +179,7 @@ LL | | } | |_- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/word-only.rs:52:1 - | -LL | #[coverage] - | ^^^^^^^^^^^ -... -LL | / impl MyTrait for MyStruct { -LL | | #[coverage] -LL | | -LL | | -... | -LL | | type T = (); -LL | | } - | |_- not a function or closure - -error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/word-only.rs:41:5 + --> $DIR/word-only.rs:38:5 | LL | #[coverage] | ^^^^^^^^^^^ @@ -237,7 +188,7 @@ LL | const X: u32; | ------------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/word-only.rs:46:5 + --> $DIR/word-only.rs:43:5 | LL | #[coverage] | ^^^^^^^^^^^ @@ -246,7 +197,7 @@ LL | type T; | ------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/word-only.rs:31:5 + --> $DIR/word-only.rs:28:5 | LL | #[coverage] | ^^^^^^^^^^^ @@ -255,7 +206,7 @@ LL | const X: u32 = 7; | ----------------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/word-only.rs:56:5 + --> $DIR/word-only.rs:52:5 | LL | #[coverage] | ^^^^^^^^^^^ @@ -264,7 +215,7 @@ LL | const X: u32 = 8; | ----------------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/word-only.rs:61:5 + --> $DIR/word-only.rs:57:5 | LL | #[coverage] | ^^^^^^^^^^^ @@ -272,6 +223,6 @@ LL | #[coverage] LL | type T = (); | ------------ not a function or closure -error: aborting due to 23 previous errors +error: aborting due to 19 previous errors For more information about this error, try `rustc --explain E0788`. From e5167fe7bd52a8eaebbf01d0b1469785306f4a96 Mon Sep 17 00:00:00 2001 From: ash <97464181+Borgerr@users.noreply.github.com> Date: Tue, 25 Jun 2024 23:58:43 -0600 Subject: [PATCH 17/23] set self.is_known_utf8 to false in extend_from_slice --- library/std/src/sys_common/wtf8.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys_common/wtf8.rs b/library/std/src/sys_common/wtf8.rs index 708f62f476e7..117a3e23044e 100644 --- a/library/std/src/sys_common/wtf8.rs +++ b/library/std/src/sys_common/wtf8.rs @@ -480,7 +480,7 @@ impl Wtf8Buf { #[inline] pub(crate) fn extend_from_slice(&mut self, other: &[u8]) { self.bytes.extend_from_slice(other); - self.is_known_utf8 = self.is_known_utf8 || self.next_surrogate(0).is_none(); + self.is_known_utf8 = false; } } From 5aac24909c321dd4bb8d90380f9b2dd9f0162c68 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 25 Jun 2024 22:29:37 -0700 Subject: [PATCH 18/23] std: test a variety of ways to extend a Wtf8Buf --- library/std/src/sys_common/wtf8/tests.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/library/std/src/sys_common/wtf8/tests.rs b/library/std/src/sys_common/wtf8/tests.rs index 6a1cc41a8fb0..b57c99a8452a 100644 --- a/library/std/src/sys_common/wtf8/tests.rs +++ b/library/std/src/sys_common/wtf8/tests.rs @@ -725,3 +725,27 @@ fn wtf8_utf8_boundary_between_surrogates() { string.push(CodePoint::from_u32(0xD800).unwrap()); check_utf8_boundary(&string, 3); } + +#[test] +fn wobbled_wtf8_plus_bytes_isnt_utf8() { + let mut string: Wtf8Buf = unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80").to_owned() }; + assert!(!string.is_known_utf8); + string.extend_from_slice(b"some utf-8"); + assert!(!string.is_known_utf8); +} + +#[test] +fn wobbled_wtf8_plus_str_isnt_utf8() { + let mut string: Wtf8Buf = unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80").to_owned() }; + assert!(!string.is_known_utf8); + string.push_str("some utf-8"); + assert!(!string.is_known_utf8); +} + +#[test] +fn unwobbly_wtf8_plus_utf8_is_utf8() { + let mut string: Wtf8Buf = Wtf8Buf::from_str("hello world"); + assert!(string.is_known_utf8); + string.push_str("some utf-8"); + assert!(string.is_known_utf8); +} From 518b74ec5d97317af70d3fdbc41eac903622a6b9 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 21 Jun 2024 04:09:38 -0400 Subject: [PATCH 19/23] Remove `f16` and `f128` ICE paths from smir --- compiler/rustc_smir/src/rustc_internal/internal.rs | 2 ++ compiler/rustc_smir/src/rustc_smir/convert/ty.rs | 4 ++-- compiler/stable_mir/src/ty.rs | 2 ++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs index c9c1570a29a8..7b5abcf45130 100644 --- a/compiler/rustc_smir/src/rustc_internal/internal.rs +++ b/compiler/rustc_smir/src/rustc_internal/internal.rs @@ -188,8 +188,10 @@ impl RustcInternal for FloatTy { fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> { match self { + FloatTy::F16 => rustc_ty::FloatTy::F16, FloatTy::F32 => rustc_ty::FloatTy::F32, FloatTy::F64 => rustc_ty::FloatTy::F64, + FloatTy::F128 => rustc_ty::FloatTy::F128, } } } diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index 9cd841bba109..74c3fcc9b9ea 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -304,10 +304,10 @@ impl<'tcx> Stable<'tcx> for ty::FloatTy { fn stable(&self, _: &mut Tables<'_>) -> Self::T { match self { - ty::FloatTy::F16 => unimplemented!("f16_f128"), + ty::FloatTy::F16 => FloatTy::F16, ty::FloatTy::F32 => FloatTy::F32, ty::FloatTy::F64 => FloatTy::F64, - ty::FloatTy::F128 => unimplemented!("f16_f128"), + ty::FloatTy::F128 => FloatTy::F128, } } } diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs index 8c120a96e75b..01e4f1d1f33b 100644 --- a/compiler/stable_mir/src/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -608,8 +608,10 @@ impl UintTy { #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum FloatTy { + F16, F32, F64, + F128, } #[derive(Clone, Copy, Debug, PartialEq, Eq)] From ba3f6812c177dde51ec4164413868311d89047f1 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 26 Jun 2024 15:25:57 +0300 Subject: [PATCH 20/23] ast: Standardize visiting order Id, attributes, inner nodes in source order if possible, tokens, span. Also always use exhaustive matching in visiting infra, and visit some missing nodes. --- compiler/rustc_ast/src/mut_visit.rs | 206 ++++++------- compiler/rustc_ast/src/visit.rs | 438 ++++++++++++++++------------ tests/ui/stats/hir-stats.stderr | 62 ++-- 3 files changed, 389 insertions(+), 317 deletions(-) diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index ed8bf58eb23e..a81c335aa23b 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -402,10 +402,10 @@ fn visit_attr_args(args: &mut AttrArgs, vis: &mut T) { AttrArgs::Empty => {} AttrArgs::Delimited(args) => visit_delim_args(args, vis), AttrArgs::Eq(eq_span, AttrArgsEq::Ast(expr)) => { - vis.visit_span(eq_span); vis.visit_expr(expr); + vis.visit_span(eq_span); } - AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => { + AttrArgs::Eq(_eq_span, AttrArgsEq::Hir(lit)) => { unreachable!("in literal form when visiting mac args eq: {:?}", lit) } } @@ -414,13 +414,13 @@ fn visit_attr_args(args: &mut AttrArgs, vis: &mut T) { // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. fn visit_delim_args(args: &mut DelimArgs, vis: &mut T) { let DelimArgs { dspan, delim: _, tokens } = args; - visit_delim_span(dspan, vis); visit_tts(tokens, vis); + visit_delim_span(dspan, vis); } -pub fn visit_delim_span(dspan: &mut DelimSpan, vis: &mut T) { - vis.visit_span(&mut dspan.open); - vis.visit_span(&mut dspan.close); +pub fn visit_delim_span(DelimSpan { open, close }: &mut DelimSpan, vis: &mut T) { + vis.visit_span(open); + vis.visit_span(close); } pub fn noop_flat_map_pat_field( @@ -441,11 +441,12 @@ fn noop_visit_use_tree(use_tree: &mut UseTree, vis: &mut T) { vis.visit_path(prefix); match kind { UseTreeKind::Simple(rename) => visit_opt(rename, |rename| vis.visit_ident(rename)), - UseTreeKind::Nested { items, .. } => { + UseTreeKind::Nested { items, span } => { for (tree, id) in items { vis.visit_id(id); vis.visit_use_tree(tree); } + vis.visit_span(span); } UseTreeKind::Glob => {} } @@ -486,12 +487,9 @@ pub fn noop_visit_ty(ty: &mut P, vis: &mut T) { let Ty { id, kind, span, tokens } = ty.deref_mut(); vis.visit_id(id); match kind { - TyKind::Infer - | TyKind::ImplicitSelf - | TyKind::Err(_) - | TyKind::Dummy - | TyKind::Never - | TyKind::CVarArgs => {} + TyKind::Err(_guar) => {} + TyKind::Infer | TyKind::ImplicitSelf | TyKind::Dummy | TyKind::Never | TyKind::CVarArgs => { + } TyKind::Slice(ty) => vis.visit_ty(ty), TyKind::Ptr(mt) => vis.visit_mt(mt), TyKind::Ref(lt, mt) => { @@ -533,8 +531,8 @@ pub fn noop_visit_ty(ty: &mut P, vis: &mut T) { fields.flat_map_in_place(|field| vis.flat_map_field_def(field)); } } - vis.visit_span(span); visit_lazy_tts(tokens, vis); + vis.visit_span(span); } fn noop_visit_foreign_mod(foreign_mod: &mut ForeignMod, vis: &mut T) { @@ -550,8 +548,8 @@ pub fn noop_flat_map_variant( let Variant { ident, vis, attrs, id, data, disr_expr, span, is_placeholder: _ } = &mut variant; visitor.visit_id(id); visit_attrs(attrs, visitor); - visitor.visit_ident(ident); visitor.visit_vis(vis); + visitor.visit_ident(ident); visitor.visit_variant_data(data); visit_opt(disr_expr, |disr_expr| visitor.visit_anon_const(disr_expr)); visitor.visit_span(span); @@ -563,13 +561,13 @@ fn noop_visit_ident(Ident { name: _, span }: &mut Ident, vis: &mu } fn noop_visit_path(Path { segments, span, tokens }: &mut Path, vis: &mut T) { - vis.visit_span(span); for PathSegment { ident, id, args } in segments { vis.visit_id(id); vis.visit_ident(ident); visit_opt(args, |args| vis.visit_generic_args(args)); } visit_lazy_tts(tokens, vis); + vis.visit_span(span); } fn noop_visit_qself(qself: &mut Option>, vis: &mut T) { @@ -611,10 +609,11 @@ fn noop_visit_parenthesized_parameter_data( args: &mut ParenthesizedArgs, vis: &mut T, ) { - let ParenthesizedArgs { inputs, output, span, .. } = args; + let ParenthesizedArgs { inputs, output, span, inputs_span } = args; visit_thin_vec(inputs, |input| vis.visit_ty(input)); noop_visit_fn_ret_ty(output, vis); vis.visit_span(span); + vis.visit_span(inputs_span); } fn noop_visit_local(local: &mut P, vis: &mut T) { @@ -633,9 +632,9 @@ fn noop_visit_local(local: &mut P, vis: &mut T) { vis.visit_block(els); } } - vis.visit_span(span); - visit_opt(colon_sp, |sp| vis.visit_span(sp)); visit_lazy_tts(tokens, vis); + visit_opt(colon_sp, |sp| vis.visit_span(sp)); + vis.visit_span(span); } fn noop_visit_attribute(attr: &mut Attribute, vis: &mut T) { @@ -651,7 +650,7 @@ fn noop_visit_attribute(attr: &mut Attribute, vis: &mut T) { visit_lazy_tts(tokens, vis); visit_lazy_tts(attr_tokens, vis); } - AttrKind::DocComment(..) => {} + AttrKind::DocComment(_kind, _sym) => {} } vis.visit_span(span); } @@ -689,34 +688,24 @@ pub fn noop_flat_map_param(mut param: Param, vis: &mut T) -> Smal vis.visit_id(id); visit_attrs(attrs, vis); vis.visit_pat(pat); - vis.visit_span(span); vis.visit_ty(ty); + vis.visit_span(span); smallvec![param] } // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. fn visit_attr_tt(tt: &mut AttrTokenTree, vis: &mut T) { match tt { - AttrTokenTree::Token(token, _) => { + AttrTokenTree::Token(token, _spacing) => { visit_token(token, vis); } - AttrTokenTree::Delimited(DelimSpan { open, close }, _spacing, _delim, tts) => { - vis.visit_span(open); - vis.visit_span(close); + AttrTokenTree::Delimited(dspan, _spacing, _delim, tts) => { visit_attr_tts(tts, vis); + visit_delim_span(dspan, vis); } - AttrTokenTree::Attributes(data) => { - for attr in &mut *data.attrs { - match &mut attr.kind { - AttrKind::Normal(normal) => { - visit_lazy_tts(&mut normal.tokens, vis); - } - AttrKind::DocComment(..) => { - vis.visit_span(&mut attr.span); - } - } - } - visit_lazy_tts_opt_mut(Some(&mut data.tokens), vis); + AttrTokenTree::Attributes(AttributesData { attrs, tokens }) => { + visit_attrs(attrs, vis); + visit_lazy_tts_opt_mut(Some(tokens), vis); } } } @@ -724,13 +713,12 @@ fn visit_attr_tt(tt: &mut AttrTokenTree, vis: &mut T) { // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. fn visit_tt(tt: &mut TokenTree, vis: &mut T) { match tt { - TokenTree::Token(token, _) => { + TokenTree::Token(token, _spacing) => { visit_token(token, vis); } - TokenTree::Delimited(DelimSpan { open, close }, _spacing, _delim, tts) => { - vis.visit_span(open); - vis.visit_span(close); + TokenTree::Delimited(dspan, _spacing, _delim, tts) => { visit_tts(tts, vis); + visit_delim_span(dspan, vis); } } } @@ -771,7 +759,7 @@ fn visit_lazy_tts(lazy_tts: &mut Option, vis pub fn visit_token(t: &mut Token, vis: &mut T) { let Token { kind, span } = t; match kind { - token::Ident(name, _) | token::Lifetime(name) => { + token::Ident(name, _ /*raw*/) | token::Lifetime(name) => { let mut ident = Ident::new(*name, *span); vis.visit_ident(&mut ident); *name = ident.name; @@ -918,10 +906,11 @@ fn noop_visit_param_bound(pb: &mut GenericBound, vis: &mut T) { match pb { GenericBound::Trait(ty, _modifier) => vis.visit_poly_trait_ref(ty), GenericBound::Outlives(lifetime) => noop_visit_lifetime(lifetime, vis), - GenericBound::Use(args, _) => { + GenericBound::Use(args, span) => { for arg in args { vis.visit_precise_capturing_arg(arg); } + vis.visit_span(span); } } } @@ -946,9 +935,6 @@ pub fn noop_flat_map_generic_param( vis.visit_id(id); visit_attrs(attrs, vis); vis.visit_ident(ident); - if let Some(colon_span) = colon_span { - vis.visit_span(colon_span); - } visit_vec(bounds, |bound| noop_visit_param_bound(bound, vis)); match kind { GenericParamKind::Lifetime => {} @@ -960,6 +946,9 @@ pub fn noop_flat_map_generic_param( visit_opt(default, |default| vis.visit_anon_const(default)); } } + if let Some(colon_span) = colon_span { + vis.visit_span(colon_span); + } smallvec![param] } @@ -979,6 +968,14 @@ fn noop_visit_generics(generics: &mut Generics, vis: &mut T) { vis.visit_span(span); } +fn noop_visit_ty_alias_where_clauses(tawcs: &mut TyAliasWhereClauses, vis: &mut T) { + let TyAliasWhereClauses { before, after, split: _ } = tawcs; + let TyAliasWhereClause { has_where_token: _, span: span_before } = before; + let TyAliasWhereClause { has_where_token: _, span: span_after } = after; + vis.visit_span(span_before); + vis.visit_span(span_after); +} + fn noop_visit_where_clause(wc: &mut WhereClause, vis: &mut T) { let WhereClause { has_where_token: _, predicates, span } = wc; visit_thin_vec(predicates, |predicate| vis.visit_where_predicate(predicate)); @@ -989,29 +986,29 @@ fn noop_visit_where_predicate(pred: &mut WherePredicate, vis: &mu match pred { WherePredicate::BoundPredicate(bp) => { let WhereBoundPredicate { span, bound_generic_params, bounded_ty, bounds } = bp; - vis.visit_span(span); bound_generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param)); vis.visit_ty(bounded_ty); visit_vec(bounds, |bound| vis.visit_param_bound(bound)); + vis.visit_span(span); } WherePredicate::RegionPredicate(rp) => { let WhereRegionPredicate { span, lifetime, bounds } = rp; - vis.visit_span(span); noop_visit_lifetime(lifetime, vis); visit_vec(bounds, |bound| noop_visit_param_bound(bound, vis)); + vis.visit_span(span); } WherePredicate::EqPredicate(ep) => { let WhereEqPredicate { span, lhs_ty, rhs_ty } = ep; - vis.visit_span(span); vis.visit_ty(lhs_ty); vis.visit_ty(rhs_ty); + vis.visit_span(span); } } } fn noop_visit_variant_data(vdata: &mut VariantData, vis: &mut T) { match vdata { - VariantData::Struct { fields, .. } => { + VariantData::Struct { fields, recovered: _ } => { fields.flat_map_in_place(|field| vis.flat_map_field_def(field)); } VariantData::Tuple(fields, id) => { @@ -1041,10 +1038,10 @@ pub fn noop_flat_map_field_def( let FieldDef { span, ident, vis, id, ty, attrs, is_placeholder: _ } = &mut fd; visitor.visit_id(id); visit_attrs(attrs, visitor); - visitor.visit_span(span); - visit_opt(ident, |ident| visitor.visit_ident(ident)); visitor.visit_vis(vis); + visit_opt(ident, |ident| visitor.visit_ident(ident)); visitor.visit_ty(ty); + visitor.visit_span(span); smallvec![fd] } @@ -1069,8 +1066,8 @@ pub fn noop_visit_block(block: &mut P, vis: &mut T) { let Block { id, stmts, rules: _, span, tokens, could_be_bare_literal: _ } = block.deref_mut(); vis.visit_id(id); stmts.flat_map_in_place(|stmt| vis.flat_map_stmt(stmt)); - vis.visit_span(span); visit_lazy_tts(tokens, vis); + vis.visit_span(span); } pub fn noop_visit_item_kind(kind: &mut impl NoopVisitItemKind, vis: &mut impl MutVisitor) { @@ -1091,45 +1088,37 @@ impl NoopVisitItemKind for ItemKind { } ItemKind::Fn(box Fn { defaultness, generics, sig, body }) => { visit_defaultness(defaultness, vis); - visit_fn_sig(sig, vis); vis.visit_generics(generics); + visit_fn_sig(sig, vis); visit_opt(body, |body| vis.visit_block(body)); } ItemKind::Mod(safety, mod_kind) => { visit_safety(safety, vis); match mod_kind { ModKind::Loaded(items, _inline, ModSpans { inner_span, inject_use_span }) => { + items.flat_map_in_place(|item| vis.flat_map_item(item)); vis.visit_span(inner_span); vis.visit_span(inject_use_span); - items.flat_map_in_place(|item| vis.flat_map_item(item)); } ModKind::Unloaded => {} } } ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm), ItemKind::GlobalAsm(asm) => vis.visit_inline_asm(asm), - ItemKind::TyAlias(box TyAlias { - defaultness, - generics, - where_clauses, - bounds, - ty, - .. - }) => { + ItemKind::TyAlias(box TyAlias { defaultness, generics, where_clauses, bounds, ty }) => { visit_defaultness(defaultness, vis); vis.visit_generics(generics); - vis.visit_span(&mut where_clauses.before.span); - vis.visit_span(&mut where_clauses.after.span); visit_bounds(bounds, vis); visit_opt(ty, |ty| vis.visit_ty(ty)); + noop_visit_ty_alias_where_clauses(where_clauses, vis); } ItemKind::Enum(EnumDef { variants }, generics) => { - variants.flat_map_in_place(|variant| vis.flat_map_variant(variant)); vis.visit_generics(generics); + variants.flat_map_in_place(|variant| vis.flat_map_variant(variant)); } ItemKind::Struct(variant_data, generics) | ItemKind::Union(variant_data, generics) => { - vis.visit_variant_data(variant_data); vis.visit_generics(generics); + vis.visit_variant_data(variant_data); } ItemKind::Impl(box Impl { defaultness, @@ -1217,14 +1206,12 @@ impl NoopVisitItemKind for AssocItemKind { where_clauses, bounds, ty, - .. }) => { visit_defaultness(defaultness, visitor); visitor.visit_generics(generics); - visitor.visit_span(&mut where_clauses.before.span); - visitor.visit_span(&mut where_clauses.after.span); visit_bounds(bounds, visitor); visit_opt(ty, |ty| visitor.visit_ty(ty)); + noop_visit_ty_alias_where_clauses(where_clauses, visitor); } AssocItemKind::MacCall(mac) => visitor.visit_mac_call(mac), AssocItemKind::Delegation(box Delegation { @@ -1302,8 +1289,8 @@ pub fn noop_flat_map_item( visitor.visit_vis(vis); visitor.visit_ident(ident); kind.noop_visit(visitor); - visitor.visit_span(span); visit_lazy_tts(tokens, visitor); + visitor.visit_span(span); smallvec![item] } @@ -1326,14 +1313,12 @@ impl NoopVisitItemKind for ForeignItemKind { where_clauses, bounds, ty, - .. }) => { visit_defaultness(defaultness, visitor); visitor.visit_generics(generics); - visitor.visit_span(&mut where_clauses.before.span); - visitor.visit_span(&mut where_clauses.after.span); visit_bounds(bounds, visitor); visit_opt(ty, |ty| visitor.visit_ty(ty)); + noop_visit_ty_alias_where_clauses(where_clauses, visitor); } ForeignItemKind::MacCall(mac) => visitor.visit_mac_call(mac), } @@ -1344,7 +1329,8 @@ pub fn noop_visit_pat(pat: &mut P, vis: &mut T) { let Pat { id, kind, span, tokens } = pat.deref_mut(); vis.visit_id(id); match kind { - PatKind::Wild | PatKind::Rest | PatKind::Never | PatKind::Err(_) => {} + PatKind::Err(_guar) => {} + PatKind::Wild | PatKind::Rest | PatKind::Never => {} PatKind::Ident(_binding_mode, ident, sub) => { vis.visit_ident(ident); visit_opt(sub, |sub| vis.visit_pat(sub)); @@ -1378,8 +1364,8 @@ pub fn noop_visit_pat(pat: &mut P, vis: &mut T) { PatKind::Paren(inner) => vis.visit_pat(inner), PatKind::MacCall(mac) => vis.visit_mac_call(mac), } - vis.visit_span(span); visit_lazy_tts(tokens, vis); + vis.visit_span(span); } fn noop_visit_anon_const(AnonConst { id, value }: &mut AnonConst, vis: &mut T) { @@ -1388,13 +1374,22 @@ fn noop_visit_anon_const(AnonConst { id, value }: &mut AnonConst, } fn noop_visit_inline_asm(asm: &mut InlineAsm, vis: &mut T) { - for (op, _) in &mut asm.operands { + // FIXME: Visit spans inside all this currently ignored stuff. + let InlineAsm { + template: _, + template_strs: _, + operands, + clobber_abis: _, + options: _, + line_spans: _, + } = asm; + for (op, span) in operands { match op { - InlineAsmOperand::In { expr, .. } - | InlineAsmOperand::Out { expr: Some(expr), .. } - | InlineAsmOperand::InOut { expr, .. } => vis.visit_expr(expr), - InlineAsmOperand::Out { expr: None, .. } => {} - InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => { + InlineAsmOperand::In { expr, reg: _ } + | InlineAsmOperand::Out { expr: Some(expr), reg: _, late: _ } + | InlineAsmOperand::InOut { expr, reg: _, late: _ } => vis.visit_expr(expr), + InlineAsmOperand::Out { expr: None, reg: _, late: _ } => {} + InlineAsmOperand::SplitInOut { in_expr, out_expr, reg: _, late: _ } => { vis.visit_expr(in_expr); if let Some(out_expr) = out_expr { vis.visit_expr(out_expr); @@ -1404,6 +1399,7 @@ fn noop_visit_inline_asm(asm: &mut InlineAsm, vis: &mut T) { InlineAsmOperand::Sym { sym } => vis.visit_inline_asm_sym(sym), InlineAsmOperand::Label { block } => vis.visit_block(block), } + vis.visit_span(span); } } @@ -1417,12 +1413,18 @@ fn noop_visit_inline_asm_sym( } fn noop_visit_format_args(fmt: &mut FormatArgs, vis: &mut T) { - for arg in fmt.arguments.all_args_mut() { - if let FormatArgumentKind::Named(name) = &mut arg.kind { - vis.visit_ident(name); + // FIXME: visit the template exhaustively. + let FormatArgs { span, template: _, arguments } = fmt; + for FormatArgument { kind, expr } in arguments.all_args_mut() { + match kind { + FormatArgumentKind::Named(ident) | FormatArgumentKind::Captured(ident) => { + vis.visit_ident(ident) + } + FormatArgumentKind::Normal => {} } - vis.visit_expr(&mut arg.expr); + vis.visit_expr(expr); } + vis.visit_span(span); } pub fn noop_visit_expr( @@ -1451,10 +1453,10 @@ pub fn noop_visit_expr( args: call_args, span, }) => { + vis.visit_method_receiver_expr(receiver); vis.visit_id(id); vis.visit_ident(ident); visit_opt(seg_args, |args| vis.visit_generic_args(args)); - vis.visit_method_receiver_expr(receiver); visit_thin_exprs(call_args, vis); vis.visit_span(span); } @@ -1471,10 +1473,11 @@ pub fn noop_visit_expr( vis.visit_expr(expr); vis.visit_ty(ty); } - ExprKind::AddrOf(_, _, ohs) => vis.visit_expr(ohs), - ExprKind::Let(pat, scrutinee, _, _) => { + ExprKind::AddrOf(_kind, _mut, ohs) => vis.visit_expr(ohs), + ExprKind::Let(pat, scrutinee, span, _recovered) => { vis.visit_pat(pat); vis.visit_expr(scrutinee); + vis.visit_span(span); } ExprKind::If(cond, tr, fl) => { vis.visit_expr(cond); @@ -1482,19 +1485,19 @@ pub fn noop_visit_expr( visit_opt(fl, |fl| ensure_sufficient_stack(|| vis.visit_expr(fl))); } ExprKind::While(cond, body, label) => { + visit_opt(label, |label| vis.visit_label(label)); vis.visit_expr(cond); vis.visit_block(body); - visit_opt(label, |label| vis.visit_label(label)); } ExprKind::ForLoop { pat, iter, body, label, kind: _ } => { + visit_opt(label, |label| vis.visit_label(label)); vis.visit_pat(pat); vis.visit_expr(iter); vis.visit_block(body); - visit_opt(label, |label| vis.visit_label(label)); } ExprKind::Loop(body, label, span) => { - vis.visit_block(body); visit_opt(label, |label| vis.visit_label(label)); + vis.visit_block(body); vis.visit_span(span); } ExprKind::Match(expr, arms, _kind) => { @@ -1522,10 +1525,10 @@ pub fn noop_visit_expr( vis.visit_span(fn_arg_span); } ExprKind::Block(blk, label) => { - vis.visit_block(blk); visit_opt(label, |label| vis.visit_label(label)); + vis.visit_block(blk); } - ExprKind::Gen(_capture_by, body, _) => { + ExprKind::Gen(_capture_by, body, _kind) => { vis.visit_block(body); } ExprKind::Await(expr, await_kw_span) => { @@ -1601,10 +1604,13 @@ pub fn noop_visit_expr( } ExprKind::Try(expr) => vis.visit_expr(expr), ExprKind::TryBlock(body) => vis.visit_block(body), - ExprKind::Lit(_) | ExprKind::IncludedBytes(..) | ExprKind::Err(_) | ExprKind::Dummy => {} + ExprKind::Lit(_token) => {} + ExprKind::IncludedBytes(_bytes) => {} + ExprKind::Err(_guar) => {} + ExprKind::Dummy => {} } - vis.visit_span(span); visit_lazy_tts(tokens, vis); + vis.visit_span(span); } pub fn noop_filter_map_expr(mut e: P, vis: &mut T) -> Option> { @@ -1619,7 +1625,6 @@ pub fn noop_flat_map_stmt( vis: &mut T, ) -> SmallVec<[Stmt; 1]> { vis.visit_id(&mut id); - vis.visit_span(&mut span); let stmts: SmallVec<_> = noop_flat_map_stmt_kind(kind, vis) .into_iter() .map(|kind| Stmt { id, kind, span }) @@ -1630,6 +1635,7 @@ pub fn noop_flat_map_stmt( the visitor should implement custom statement visiting" ); } + vis.visit_span(&mut span); stmts } @@ -1654,14 +1660,16 @@ fn noop_flat_map_stmt_kind(kind: StmtKind, vis: &mut T) -> SmallV } fn noop_visit_vis(visibility: &mut Visibility, vis: &mut T) { - match &mut visibility.kind { + let Visibility { kind, span, tokens } = visibility; + match kind { VisibilityKind::Public | VisibilityKind::Inherited => {} VisibilityKind::Restricted { path, id, shorthand: _ } => { vis.visit_id(id); vis.visit_path(path); } } - vis.visit_span(&mut visibility.span); + visit_lazy_tts(tokens, vis); + vis.visit_span(span); } fn noop_visit_capture_by(capture_by: &mut CaptureBy, vis: &mut T) { diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index e2ef0542bf9c..0f3c30048ce4 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -14,6 +14,7 @@ //! those that are created by the expansion of a macro. use crate::ast::*; +use crate::ptr::P; use rustc_span::symbol::Ident; use rustc_span::Span; @@ -298,40 +299,45 @@ pub trait Visitor<'ast>: Sized { } pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) -> V::Result { - walk_list!(visitor, visit_attribute, &krate.attrs); - walk_list!(visitor, visit_item, &krate.items); + let Crate { attrs, items, spans: _, id: _, is_placeholder: _ } = krate; + walk_list!(visitor, visit_attribute, attrs); + walk_list!(visitor, visit_item, items); V::Result::output() } pub fn walk_local<'a, V: Visitor<'a>>(visitor: &mut V, local: &'a Local) -> V::Result { - walk_list!(visitor, visit_attribute, &local.attrs); - try_visit!(visitor.visit_pat(&local.pat)); - visit_opt!(visitor, visit_ty, &local.ty); - if let Some((init, els)) = local.kind.init_else_opt() { + let Local { id: _, pat, ty, kind, span: _, colon_sp: _, attrs, tokens: _ } = local; + walk_list!(visitor, visit_attribute, attrs); + try_visit!(visitor.visit_pat(pat)); + visit_opt!(visitor, visit_ty, ty); + if let Some((init, els)) = kind.init_else_opt() { try_visit!(visitor.visit_expr(init)); visit_opt!(visitor, visit_block, els); } V::Result::output() } -pub fn walk_label<'a, V: Visitor<'a>>(visitor: &mut V, label: &'a Label) -> V::Result { - visitor.visit_ident(label.ident) +pub fn walk_label<'a, V: Visitor<'a>>(visitor: &mut V, Label { ident }: &'a Label) -> V::Result { + visitor.visit_ident(*ident) } pub fn walk_lifetime<'a, V: Visitor<'a>>(visitor: &mut V, lifetime: &'a Lifetime) -> V::Result { - visitor.visit_ident(lifetime.ident) + let Lifetime { id: _, ident } = lifetime; + visitor.visit_ident(*ident) } pub fn walk_poly_trait_ref<'a, V>(visitor: &mut V, trait_ref: &'a PolyTraitRef) -> V::Result where V: Visitor<'a>, { - walk_list!(visitor, visit_generic_param, &trait_ref.bound_generic_params); - visitor.visit_trait_ref(&trait_ref.trait_ref) + let PolyTraitRef { bound_generic_params, trait_ref, span: _ } = trait_ref; + walk_list!(visitor, visit_generic_param, bound_generic_params); + visitor.visit_trait_ref(trait_ref) } pub fn walk_trait_ref<'a, V: Visitor<'a>>(visitor: &mut V, trait_ref: &'a TraitRef) -> V::Result { - visitor.visit_path(&trait_ref.path, trait_ref.ref_id) + let TraitRef { path, ref_id } = trait_ref; + visitor.visit_path(path, *ref_id) } impl WalkItemKind for ItemKind { @@ -341,9 +347,10 @@ impl WalkItemKind for ItemKind { _ctxt: AssocCtxt, visitor: &mut V, ) -> V::Result { + let Item { id, span, vis, ident, .. } = item; match self { - ItemKind::ExternCrate(_) => {} - ItemKind::Use(use_tree) => try_visit!(visitor.visit_use_tree(use_tree, item.id, false)), + ItemKind::ExternCrate(_rename) => {} + ItemKind::Use(use_tree) => try_visit!(visitor.visit_use_tree(use_tree, *id, false)), ItemKind::Static(box StaticItem { ty, safety: _, mutability: _, expr }) => { try_visit!(visitor.visit_ty(ty)); visit_opt!(visitor, visit_expr, expr); @@ -354,9 +361,8 @@ impl WalkItemKind for ItemKind { visit_opt!(visitor, visit_expr, expr); } ItemKind::Fn(box Fn { defaultness: _, generics, sig, body }) => { - let kind = - FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, generics, body.as_deref()); - try_visit!(visitor.visit_fn(kind, item.span, item.id)); + let kind = FnKind::Fn(FnCtxt::Free, *ident, sig, vis, generics, body.as_deref()); + try_visit!(visitor.visit_fn(kind, *span, *id)); } ItemKind::Mod(_unsafety, mod_kind) => match mod_kind { ModKind::Loaded(items, _inline, _inner_span) => { @@ -364,11 +370,17 @@ impl WalkItemKind for ItemKind { } ModKind::Unloaded => {} }, - ItemKind::ForeignMod(foreign_module) => { - walk_list!(visitor, visit_foreign_item, &foreign_module.items); + ItemKind::ForeignMod(ForeignMod { safety: _, abi: _, items }) => { + walk_list!(visitor, visit_foreign_item, items); } ItemKind::GlobalAsm(asm) => try_visit!(visitor.visit_inline_asm(asm)), - ItemKind::TyAlias(box TyAlias { generics, bounds, ty, .. }) => { + ItemKind::TyAlias(box TyAlias { + generics, + bounds, + ty, + defaultness: _, + where_clauses: _, + }) => { try_visit!(visitor.visit_generics(generics)); walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); visit_opt!(visitor, visit_ty, ty); @@ -407,7 +419,7 @@ impl WalkItemKind for ItemKind { walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); } ItemKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)), - ItemKind::MacroDef(ts) => try_visit!(visitor.visit_mac_def(ts, item.id)), + ItemKind::MacroDef(ts) => try_visit!(visitor.visit_mac_def(ts, *id)), ItemKind::Delegation(box Delegation { id, qself, @@ -416,18 +428,14 @@ impl WalkItemKind for ItemKind { body, from_glob: _, }) => { - if let Some(qself) = qself { - try_visit!(visitor.visit_ty(&qself.ty)); - } + try_visit!(walk_qself(visitor, qself)); try_visit!(visitor.visit_path(path, *id)); visit_opt!(visitor, visit_ident, *rename); visit_opt!(visitor, visit_block, body); } ItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => { - if let Some(qself) = qself { - try_visit!(visitor.visit_ty(&qself.ty)); - } - try_visit!(visitor.visit_path(prefix, item.id)); + try_visit!(walk_qself(visitor, qself)); + try_visit!(visitor.visit_path(prefix, *id)); if let Some(suffixes) = suffixes { for (ident, rename) in suffixes { visitor.visit_ident(*ident); @@ -452,9 +460,9 @@ pub fn walk_item<'a, V: Visitor<'a>>( pub fn walk_enum_def<'a, V: Visitor<'a>>( visitor: &mut V, - enum_definition: &'a EnumDef, + EnumDef { variants }: &'a EnumDef, ) -> V::Result { - walk_list!(visitor, visit_variant, &enum_definition.variants); + walk_list!(visitor, visit_variant, variants); V::Result::output() } @@ -462,48 +470,52 @@ pub fn walk_variant<'a, V: Visitor<'a>>(visitor: &mut V, variant: &'a Variant) - where V: Visitor<'a>, { - walk_list!(visitor, visit_attribute, &variant.attrs); - try_visit!(visitor.visit_ident(variant.ident)); - try_visit!(visitor.visit_vis(&variant.vis)); - try_visit!(visitor.visit_variant_data(&variant.data)); - visit_opt!(visitor, visit_variant_discr, &variant.disr_expr); + let Variant { attrs, id: _, span: _, vis, ident, data, disr_expr, is_placeholder: _ } = variant; + walk_list!(visitor, visit_attribute, attrs); + try_visit!(visitor.visit_vis(vis)); + try_visit!(visitor.visit_ident(*ident)); + try_visit!(visitor.visit_variant_data(data)); + visit_opt!(visitor, visit_variant_discr, disr_expr); V::Result::output() } pub fn walk_expr_field<'a, V: Visitor<'a>>(visitor: &mut V, f: &'a ExprField) -> V::Result { - walk_list!(visitor, visit_attribute, &f.attrs); - try_visit!(visitor.visit_expr(&f.expr)); - try_visit!(visitor.visit_ident(f.ident)); + let ExprField { attrs, id: _, span: _, ident, expr, is_shorthand: _, is_placeholder: _ } = f; + walk_list!(visitor, visit_attribute, attrs); + try_visit!(visitor.visit_ident(*ident)); + try_visit!(visitor.visit_expr(expr)); V::Result::output() } pub fn walk_pat_field<'a, V: Visitor<'a>>(visitor: &mut V, fp: &'a PatField) -> V::Result { - walk_list!(visitor, visit_attribute, &fp.attrs); - try_visit!(visitor.visit_ident(fp.ident)); - try_visit!(visitor.visit_pat(&fp.pat)); + let PatField { ident, pat, is_shorthand: _, attrs, id: _, span: _, is_placeholder: _ } = fp; + walk_list!(visitor, visit_attribute, attrs); + try_visit!(visitor.visit_ident(*ident)); + try_visit!(visitor.visit_pat(pat)); V::Result::output() } pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) -> V::Result { - match &typ.kind { + let Ty { id, kind, span: _, tokens: _ } = typ; + match kind { TyKind::Slice(ty) | TyKind::Paren(ty) => try_visit!(visitor.visit_ty(ty)), - TyKind::Ptr(mutable_type) => try_visit!(visitor.visit_ty(&mutable_type.ty)), - TyKind::Ref(opt_lifetime, mutable_type) => { + TyKind::Ptr(MutTy { ty, mutbl: _ }) => try_visit!(visitor.visit_ty(ty)), + TyKind::Ref(opt_lifetime, MutTy { ty, mutbl: _ }) => { visit_opt!(visitor, visit_lifetime, opt_lifetime, LifetimeCtxt::Ref); - try_visit!(visitor.visit_ty(&mutable_type.ty)); + try_visit!(visitor.visit_ty(ty)); } TyKind::Tup(tuple_element_types) => { walk_list!(visitor, visit_ty, tuple_element_types); } TyKind::BareFn(function_declaration) => { - walk_list!(visitor, visit_generic_param, &function_declaration.generic_params); - try_visit!(walk_fn_decl(visitor, &function_declaration.decl)); + let BareFnTy { safety: _, ext: _, generic_params, decl, decl_span: _ } = + &**function_declaration; + walk_list!(visitor, visit_generic_param, generic_params); + try_visit!(walk_fn_decl(visitor, decl)); } TyKind::Path(maybe_qself, path) => { - if let Some(qself) = maybe_qself { - try_visit!(visitor.visit_ty(&qself.ty)); - } - try_visit!(visitor.visit_path(path, typ.id)); + try_visit!(walk_qself(visitor, maybe_qself)); + try_visit!(visitor.visit_path(path, *id)); } TyKind::Pat(ty, pat) => { try_visit!(visitor.visit_ty(ty)); @@ -513,25 +525,35 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) -> V::Result { try_visit!(visitor.visit_ty(ty)); try_visit!(visitor.visit_anon_const(length)); } - TyKind::TraitObject(bounds, ..) => { + TyKind::TraitObject(bounds, _syntax) => { walk_list!(visitor, visit_param_bound, bounds, BoundKind::TraitObject); } - TyKind::ImplTrait(_, bounds) => { + TyKind::ImplTrait(_id, bounds) => { walk_list!(visitor, visit_param_bound, bounds, BoundKind::Impl); } TyKind::Typeof(expression) => try_visit!(visitor.visit_anon_const(expression)), - TyKind::Infer | TyKind::ImplicitSelf | TyKind::Dummy | TyKind::Err(_) => {} + TyKind::Infer | TyKind::ImplicitSelf | TyKind::Dummy => {} + TyKind::Err(_guar) => {} TyKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)), TyKind::Never | TyKind::CVarArgs => {} - TyKind::AnonStruct(_, ref fields) | TyKind::AnonUnion(_, ref fields) => { + TyKind::AnonStruct(_id, ref fields) | TyKind::AnonUnion(_id, ref fields) => { walk_list!(visitor, visit_field_def, fields); } } V::Result::output() } +fn walk_qself<'a, V: Visitor<'a>>(visitor: &mut V, qself: &'a Option>) -> V::Result { + if let Some(qself) = qself { + let QSelf { ty, path_span: _, position: _ } = &**qself; + try_visit!(visitor.visit_ty(ty)); + } + V::Result::output() +} + pub fn walk_path<'a, V: Visitor<'a>>(visitor: &mut V, path: &'a Path) -> V::Result { - walk_list!(visitor, visit_path_segment, &path.segments); + let Path { span: _, segments, tokens: _ } = path; + walk_list!(visitor, visit_path_segment, segments); V::Result::output() } @@ -540,14 +562,15 @@ pub fn walk_use_tree<'a, V: Visitor<'a>>( use_tree: &'a UseTree, id: NodeId, ) -> V::Result { - try_visit!(visitor.visit_path(&use_tree.prefix, id)); - match use_tree.kind { + let UseTree { prefix, kind, span: _ } = use_tree; + try_visit!(visitor.visit_path(prefix, id)); + match kind { UseTreeKind::Simple(rename) => { // The extra IDs are handled during AST lowering. - visit_opt!(visitor, visit_ident, rename); + visit_opt!(visitor, visit_ident, *rename); } UseTreeKind::Glob => {} - UseTreeKind::Nested { ref items, .. } => { + UseTreeKind::Nested { ref items, span: _ } => { for &(ref nested_tree, nested_id) in items { try_visit!(visitor.visit_use_tree(nested_tree, nested_id, true)); } @@ -560,8 +583,9 @@ pub fn walk_path_segment<'a, V: Visitor<'a>>( visitor: &mut V, segment: &'a PathSegment, ) -> V::Result { - try_visit!(visitor.visit_ident(segment.ident)); - visit_opt!(visitor, visit_generic_args, &segment.args); + let PathSegment { ident, id: _, args } = segment; + try_visit!(visitor.visit_ident(*ident)); + visit_opt!(visitor, visit_generic_args, args); V::Result::output() } @@ -570,8 +594,8 @@ where V: Visitor<'a>, { match generic_args { - GenericArgs::AngleBracketed(data) => { - for arg in &data.args { + GenericArgs::AngleBracketed(AngleBracketedArgs { span: _, args }) => { + for arg in args { match arg { AngleBracketedArg::Arg(a) => try_visit!(visitor.visit_generic_arg(a)), AngleBracketedArg::Constraint(c) => { @@ -581,8 +605,9 @@ where } } GenericArgs::Parenthesized(data) => { - walk_list!(visitor, visit_ty, &data.inputs); - try_visit!(visitor.visit_fn_ret_ty(&data.output)); + let ParenthesizedArgs { span: _, inputs, inputs_span: _, output } = data; + walk_list!(visitor, visit_ty, inputs); + try_visit!(visitor.visit_fn_ret_ty(output)); } } V::Result::output() @@ -603,9 +628,10 @@ pub fn walk_assoc_item_constraint<'a, V: Visitor<'a>>( visitor: &mut V, constraint: &'a AssocItemConstraint, ) -> V::Result { - try_visit!(visitor.visit_ident(constraint.ident)); - visit_opt!(visitor, visit_generic_args, &constraint.gen_args); - match &constraint.kind { + let AssocItemConstraint { id: _, ident, gen_args, kind, span: _ } = constraint; + try_visit!(visitor.visit_ident(*ident)); + visit_opt!(visitor, visit_generic_args, gen_args); + match kind { AssocItemConstraintKind::Equality { term } => match term { Term::Ty(ty) => try_visit!(visitor.visit_ty(ty)), Term::Const(c) => try_visit!(visitor.visit_anon_const(c)), @@ -618,43 +644,39 @@ pub fn walk_assoc_item_constraint<'a, V: Visitor<'a>>( } pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) -> V::Result { - match &pattern.kind { + let Pat { id, kind, span: _, tokens: _ } = pattern; + match kind { PatKind::TupleStruct(opt_qself, path, elems) => { - if let Some(qself) = opt_qself { - try_visit!(visitor.visit_ty(&qself.ty)); - } - try_visit!(visitor.visit_path(path, pattern.id)); + try_visit!(walk_qself(visitor, opt_qself)); + try_visit!(visitor.visit_path(path, *id)); walk_list!(visitor, visit_pat, elems); } PatKind::Path(opt_qself, path) => { - if let Some(qself) = opt_qself { - try_visit!(visitor.visit_ty(&qself.ty)); - } - try_visit!(visitor.visit_path(path, pattern.id)) + try_visit!(walk_qself(visitor, opt_qself)); + try_visit!(visitor.visit_path(path, *id)) } - PatKind::Struct(opt_qself, path, fields, _) => { - if let Some(qself) = opt_qself { - try_visit!(visitor.visit_ty(&qself.ty)); - } - try_visit!(visitor.visit_path(path, pattern.id)); + PatKind::Struct(opt_qself, path, fields, _rest) => { + try_visit!(walk_qself(visitor, opt_qself)); + try_visit!(visitor.visit_path(path, *id)); walk_list!(visitor, visit_pat_field, fields); } - PatKind::Box(subpattern) - | PatKind::Deref(subpattern) - | PatKind::Ref(subpattern, _) - | PatKind::Paren(subpattern) => { + PatKind::Box(subpattern) | PatKind::Deref(subpattern) | PatKind::Paren(subpattern) => { try_visit!(visitor.visit_pat(subpattern)); } - PatKind::Ident(_, ident, optional_subpattern) => { + PatKind::Ref(subpattern, _ /*mutbl*/) => { + try_visit!(visitor.visit_pat(subpattern)); + } + PatKind::Ident(_bmode, ident, optional_subpattern) => { try_visit!(visitor.visit_ident(*ident)); visit_opt!(visitor, visit_pat, optional_subpattern); } PatKind::Lit(expression) => try_visit!(visitor.visit_expr(expression)), - PatKind::Range(lower_bound, upper_bound, _) => { + PatKind::Range(lower_bound, upper_bound, _end) => { visit_opt!(visitor, visit_expr, lower_bound); visit_opt!(visitor, visit_expr, upper_bound); } - PatKind::Wild | PatKind::Rest | PatKind::Never | PatKind::Err(_) => {} + PatKind::Wild | PatKind::Rest | PatKind::Never => {} + PatKind::Err(_guar) => {} PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => { walk_list!(visitor, visit_pat, elems); } @@ -680,7 +702,13 @@ impl WalkItemKind for ForeignItemKind { let kind = FnKind::Fn(FnCtxt::Foreign, ident, sig, vis, generics, body.as_deref()); try_visit!(visitor.visit_fn(kind, span, id)); } - ForeignItemKind::TyAlias(box TyAlias { generics, bounds, ty, .. }) => { + ForeignItemKind::TyAlias(box TyAlias { + generics, + bounds, + ty, + defaultness: _, + where_clauses: _, + }) => { try_visit!(visitor.visit_generics(generics)); walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); visit_opt!(visitor, visit_ty, ty); @@ -697,7 +725,7 @@ pub fn walk_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a GenericB match bound { GenericBound::Trait(typ, _modifier) => visitor.visit_poly_trait_ref(typ), GenericBound::Outlives(lifetime) => visitor.visit_lifetime(lifetime, LifetimeCtxt::Bound), - GenericBound::Use(args, _) => { + GenericBound::Use(args, _span) => { walk_list!(visitor, visit_precise_capturing_arg, args); V::Result::output() } @@ -722,13 +750,15 @@ pub fn walk_generic_param<'a, V: Visitor<'a>>( visitor: &mut V, param: &'a GenericParam, ) -> V::Result { - walk_list!(visitor, visit_attribute, ¶m.attrs); - try_visit!(visitor.visit_ident(param.ident)); - walk_list!(visitor, visit_param_bound, ¶m.bounds, BoundKind::Bound); - match ¶m.kind { + let GenericParam { id: _, ident, attrs, bounds, is_placeholder: _, kind, colon_span: _ } = + param; + walk_list!(visitor, visit_attribute, attrs); + try_visit!(visitor.visit_ident(*ident)); + walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); + match kind { GenericParamKind::Lifetime => (), GenericParamKind::Type { default } => visit_opt!(visitor, visit_ty, default), - GenericParamKind::Const { ty, default, .. } => { + GenericParamKind::Const { ty, default, kw_span: _ } => { try_visit!(visitor.visit_ty(ty)); visit_opt!(visitor, visit_anon_const, default); } @@ -737,8 +767,10 @@ pub fn walk_generic_param<'a, V: Visitor<'a>>( } pub fn walk_generics<'a, V: Visitor<'a>>(visitor: &mut V, generics: &'a Generics) -> V::Result { - walk_list!(visitor, visit_generic_param, &generics.params); - walk_list!(visitor, visit_where_predicate, &generics.where_clause.predicates); + let Generics { params, where_clause, span: _ } = generics; + let WhereClause { has_where_token: _, predicates, span: _ } = where_clause; + walk_list!(visitor, visit_generic_param, params); + walk_list!(visitor, visit_where_predicate, predicates); V::Result::output() } @@ -764,17 +796,17 @@ pub fn walk_where_predicate<'a, V: Visitor<'a>>( bounded_ty, bounds, bound_generic_params, - .. + span: _, }) => { + walk_list!(visitor, visit_generic_param, bound_generic_params); try_visit!(visitor.visit_ty(bounded_ty)); walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); - walk_list!(visitor, visit_generic_param, bound_generic_params); } - WherePredicate::RegionPredicate(WhereRegionPredicate { lifetime, bounds, .. }) => { + WherePredicate::RegionPredicate(WhereRegionPredicate { lifetime, bounds, span: _ }) => { try_visit!(visitor.visit_lifetime(lifetime, LifetimeCtxt::Bound)); walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); } - WherePredicate::EqPredicate(WhereEqPredicate { lhs_ty, rhs_ty, .. }) => { + WherePredicate::EqPredicate(WhereEqPredicate { lhs_ty, rhs_ty, span: _ }) => { try_visit!(visitor.visit_ty(lhs_ty)); try_visit!(visitor.visit_ty(rhs_ty)); } @@ -783,26 +815,28 @@ pub fn walk_where_predicate<'a, V: Visitor<'a>>( } pub fn walk_fn_ret_ty<'a, V: Visitor<'a>>(visitor: &mut V, ret_ty: &'a FnRetTy) -> V::Result { - if let FnRetTy::Ty(output_ty) = ret_ty { - try_visit!(visitor.visit_ty(output_ty)); + match ret_ty { + FnRetTy::Default(_span) => {} + FnRetTy::Ty(output_ty) => try_visit!(visitor.visit_ty(output_ty)), } V::Result::output() } pub fn walk_fn_decl<'a, V: Visitor<'a>>( visitor: &mut V, - function_declaration: &'a FnDecl, + FnDecl { inputs, output }: &'a FnDecl, ) -> V::Result { - walk_list!(visitor, visit_param, &function_declaration.inputs); - visitor.visit_fn_ret_ty(&function_declaration.output) + walk_list!(visitor, visit_param, inputs); + visitor.visit_fn_ret_ty(output) } pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Result { match kind { - FnKind::Fn(_, _, sig, _, generics, body) => { + FnKind::Fn(_ctxt, _ident, FnSig { header, decl, span: _ }, _vis, generics, body) => { + // Identifier and visibility are visited as a part of the item. + try_visit!(visitor.visit_fn_header(header)); try_visit!(visitor.visit_generics(generics)); - try_visit!(visitor.visit_fn_header(&sig.header)); - try_visit!(walk_fn_decl(visitor, &sig.decl)); + try_visit!(walk_fn_decl(visitor, decl)); visit_opt!(visitor, visit_block, body); } FnKind::Closure(binder, decl, body) => { @@ -833,7 +867,13 @@ impl WalkItemKind for AssocItemKind { FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, vis, generics, body.as_deref()); try_visit!(visitor.visit_fn(kind, span, id)); } - AssocItemKind::Type(box TyAlias { generics, bounds, ty, .. }) => { + AssocItemKind::Type(box TyAlias { + generics, + bounds, + ty, + defaultness: _, + where_clauses: _, + }) => { try_visit!(visitor.visit_generics(generics)); walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); visit_opt!(visitor, visit_ty, ty); @@ -849,18 +889,14 @@ impl WalkItemKind for AssocItemKind { body, from_glob: _, }) => { - if let Some(qself) = qself { - try_visit!(visitor.visit_ty(&qself.ty)); - } + try_visit!(walk_qself(visitor, qself)); try_visit!(visitor.visit_path(path, *id)); visit_opt!(visitor, visit_ident, *rename); visit_opt!(visitor, visit_block, body); } AssocItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => { - if let Some(qself) = qself { - try_visit!(visitor.visit_ty(&qself.ty)); - } - try_visit!(visitor.visit_path(prefix, item.id)); + try_visit!(walk_qself(visitor, qself)); + try_visit!(visitor.visit_path(prefix, id)); if let Some(suffixes) = suffixes { for (ident, rename) in suffixes { visitor.visit_ident(*ident); @@ -898,20 +934,23 @@ pub fn walk_struct_def<'a, V: Visitor<'a>>( } pub fn walk_field_def<'a, V: Visitor<'a>>(visitor: &mut V, field: &'a FieldDef) -> V::Result { - walk_list!(visitor, visit_attribute, &field.attrs); - try_visit!(visitor.visit_vis(&field.vis)); - visit_opt!(visitor, visit_ident, field.ident); - try_visit!(visitor.visit_ty(&field.ty)); + let FieldDef { attrs, id: _, span: _, vis, ident, ty, is_placeholder: _ } = field; + walk_list!(visitor, visit_attribute, attrs); + try_visit!(visitor.visit_vis(vis)); + visit_opt!(visitor, visit_ident, *ident); + try_visit!(visitor.visit_ty(ty)); V::Result::output() } pub fn walk_block<'a, V: Visitor<'a>>(visitor: &mut V, block: &'a Block) -> V::Result { - walk_list!(visitor, visit_stmt, &block.stmts); + let Block { stmts, id: _, rules: _, span: _, tokens: _, could_be_bare_literal: _ } = block; + walk_list!(visitor, visit_stmt, stmts); V::Result::output() } pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) -> V::Result { - match &statement.kind { + let Stmt { id: _, kind, span: _ } = statement; + match kind { StmtKind::Let(local) => try_visit!(visitor.visit_local(local)), StmtKind::Item(item) => try_visit!(visitor.visit_item(item)), StmtKind::Expr(expr) | StmtKind::Semi(expr) => try_visit!(visitor.visit_expr(expr)), @@ -926,25 +965,37 @@ pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) -> V: } pub fn walk_mac<'a, V: Visitor<'a>>(visitor: &mut V, mac: &'a MacCall) -> V::Result { - visitor.visit_path(&mac.path, DUMMY_NODE_ID) + let MacCall { path, args: _ } = mac; + visitor.visit_path(path, DUMMY_NODE_ID) } pub fn walk_anon_const<'a, V: Visitor<'a>>(visitor: &mut V, constant: &'a AnonConst) -> V::Result { - visitor.visit_expr(&constant.value) + let AnonConst { id: _, value } = constant; + visitor.visit_expr(value) } pub fn walk_inline_asm<'a, V: Visitor<'a>>(visitor: &mut V, asm: &'a InlineAsm) -> V::Result { - for (op, _) in &asm.operands { + let InlineAsm { + template: _, + template_strs: _, + operands, + clobber_abis: _, + options: _, + line_spans: _, + } = asm; + for (op, _span) in operands { match op { - InlineAsmOperand::In { expr, .. } - | InlineAsmOperand::Out { expr: Some(expr), .. } - | InlineAsmOperand::InOut { expr, .. } => try_visit!(visitor.visit_expr(expr)), - InlineAsmOperand::Out { expr: None, .. } => {} - InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => { + InlineAsmOperand::In { expr, reg: _ } + | InlineAsmOperand::Out { expr: Some(expr), reg: _, late: _ } + | InlineAsmOperand::InOut { expr, reg: _, late: _ } => { + try_visit!(visitor.visit_expr(expr)) + } + InlineAsmOperand::Out { expr: None, reg: _, late: _ } => {} + InlineAsmOperand::SplitInOut { in_expr, out_expr, reg: _, late: _ } => { try_visit!(visitor.visit_expr(in_expr)); visit_opt!(visitor, visit_expr, out_expr); } - InlineAsmOperand::Const { anon_const, .. } => { + InlineAsmOperand::Const { anon_const } => { try_visit!(visitor.visit_anon_const(anon_const)) } InlineAsmOperand::Sym { sym } => try_visit!(visitor.visit_inline_asm_sym(sym)), @@ -956,28 +1007,30 @@ pub fn walk_inline_asm<'a, V: Visitor<'a>>(visitor: &mut V, asm: &'a InlineAsm) pub fn walk_inline_asm_sym<'a, V: Visitor<'a>>( visitor: &mut V, - sym: &'a InlineAsmSym, + InlineAsmSym { id, qself, path }: &'a InlineAsmSym, ) -> V::Result { - if let Some(qself) = &sym.qself { - try_visit!(visitor.visit_ty(&qself.ty)); - } - visitor.visit_path(&sym.path, sym.id) + try_visit!(walk_qself(visitor, qself)); + visitor.visit_path(path, *id) } pub fn walk_format_args<'a, V: Visitor<'a>>(visitor: &mut V, fmt: &'a FormatArgs) -> V::Result { - for arg in fmt.arguments.all_args() { - if let FormatArgumentKind::Named(name) = arg.kind { - try_visit!(visitor.visit_ident(name)); + let FormatArgs { span: _, template: _, arguments } = fmt; + for FormatArgument { kind, expr } in arguments.all_args() { + match kind { + FormatArgumentKind::Named(ident) | FormatArgumentKind::Captured(ident) => { + try_visit!(visitor.visit_ident(*ident)) + } + FormatArgumentKind::Normal => {} } - try_visit!(visitor.visit_expr(&arg.expr)); + try_visit!(visitor.visit_expr(expr)); } V::Result::output() } pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V::Result { - walk_list!(visitor, visit_attribute, &expression.attrs); - - match &expression.kind { + let Expr { id, kind, span, attrs, tokens: _ } = expression; + walk_list!(visitor, visit_attribute, attrs); + match kind { ExprKind::Array(subexpressions) => { walk_list!(visitor, visit_expr, subexpressions); } @@ -987,12 +1040,11 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V try_visit!(visitor.visit_anon_const(count)); } ExprKind::Struct(se) => { - if let Some(qself) = &se.qself { - try_visit!(visitor.visit_ty(&qself.ty)); - } - try_visit!(visitor.visit_path(&se.path, expression.id)); - walk_list!(visitor, visit_expr_field, &se.fields); - match &se.rest { + let StructExpr { qself, path, fields, rest } = &**se; + try_visit!(walk_qself(visitor, qself)); + try_visit!(visitor.visit_path(path, *id)); + walk_list!(visitor, visit_expr_field, fields); + match rest { StructRest::Base(expr) => try_visit!(visitor.visit_expr(expr)), StructRest::Rest(_span) => {} StructRest::None => {} @@ -1006,22 +1058,25 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V walk_list!(visitor, visit_expr, arguments); } ExprKind::MethodCall(box MethodCall { seg, receiver, args, span: _ }) => { - try_visit!(visitor.visit_path_segment(seg)); try_visit!(visitor.visit_expr(receiver)); + try_visit!(visitor.visit_path_segment(seg)); walk_list!(visitor, visit_expr, args); } - ExprKind::Binary(_, left_expression, right_expression) => { + ExprKind::Binary(_op, left_expression, right_expression) => { try_visit!(visitor.visit_expr(left_expression)); try_visit!(visitor.visit_expr(right_expression)); } - ExprKind::AddrOf(_, _, subexpression) | ExprKind::Unary(_, subexpression) => { + ExprKind::AddrOf(_kind, _mutbl, subexpression) => { + try_visit!(visitor.visit_expr(subexpression)); + } + ExprKind::Unary(_op, subexpression) => { try_visit!(visitor.visit_expr(subexpression)); } ExprKind::Cast(subexpression, typ) | ExprKind::Type(subexpression, typ) => { try_visit!(visitor.visit_expr(subexpression)); try_visit!(visitor.visit_ty(typ)); } - ExprKind::Let(pat, expr, _, _) => { + ExprKind::Let(pat, expr, _span, _recovered) => { try_visit!(visitor.visit_pat(pat)); try_visit!(visitor.visit_expr(expr)); } @@ -1041,7 +1096,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V try_visit!(visitor.visit_expr(iter)); try_visit!(visitor.visit_block(body)); } - ExprKind::Loop(block, opt_label, _) => { + ExprKind::Loop(block, opt_label, _span) => { visit_opt!(visitor, visit_label, opt_label); try_visit!(visitor.visit_block(block)); } @@ -1061,23 +1116,19 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V fn_arg_span: _, }) => { try_visit!(visitor.visit_capture_by(capture_clause)); - try_visit!(visitor.visit_fn( - FnKind::Closure(binder, fn_decl, body), - expression.span, - expression.id - )) + try_visit!(visitor.visit_fn(FnKind::Closure(binder, fn_decl, body), *span, *id)) } ExprKind::Block(block, opt_label) => { visit_opt!(visitor, visit_label, opt_label); try_visit!(visitor.visit_block(block)); } - ExprKind::Gen(_, body, _) => try_visit!(visitor.visit_block(body)), - ExprKind::Await(expr, _) => try_visit!(visitor.visit_expr(expr)), - ExprKind::Assign(lhs, rhs, _) => { + ExprKind::Gen(_capt, body, _kind) => try_visit!(visitor.visit_block(body)), + ExprKind::Await(expr, _span) => try_visit!(visitor.visit_expr(expr)), + ExprKind::Assign(lhs, rhs, _span) => { try_visit!(visitor.visit_expr(lhs)); try_visit!(visitor.visit_expr(rhs)); } - ExprKind::AssignOp(_, left_expression, right_expression) => { + ExprKind::AssignOp(_op, left_expression, right_expression) => { try_visit!(visitor.visit_expr(left_expression)); try_visit!(visitor.visit_expr(right_expression)); } @@ -1085,20 +1136,18 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V try_visit!(visitor.visit_expr(subexpression)); try_visit!(visitor.visit_ident(*ident)); } - ExprKind::Index(main_expression, index_expression, _) => { + ExprKind::Index(main_expression, index_expression, _span) => { try_visit!(visitor.visit_expr(main_expression)); try_visit!(visitor.visit_expr(index_expression)); } - ExprKind::Range(start, end, _) => { + ExprKind::Range(start, end, _limit) => { visit_opt!(visitor, visit_expr, start); visit_opt!(visitor, visit_expr, end); } ExprKind::Underscore => {} ExprKind::Path(maybe_qself, path) => { - if let Some(qself) = maybe_qself { - try_visit!(visitor.visit_ty(&qself.ty)); - } - try_visit!(visitor.visit_path(path, expression.id)); + try_visit!(walk_qself(visitor, maybe_qself)); + try_visit!(visitor.visit_path(path, *id)); } ExprKind::Break(opt_label, opt_expr) => { visit_opt!(visitor, visit_label, opt_label); @@ -1127,38 +1176,53 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V } ExprKind::Try(subexpression) => try_visit!(visitor.visit_expr(subexpression)), ExprKind::TryBlock(body) => try_visit!(visitor.visit_block(body)), - ExprKind::Lit(_) | ExprKind::IncludedBytes(..) | ExprKind::Err(_) | ExprKind::Dummy => {} + ExprKind::Lit(_token) => {} + ExprKind::IncludedBytes(_bytes) => {} + ExprKind::Err(_guar) => {} + ExprKind::Dummy => {} } visitor.visit_expr_post(expression) } pub fn walk_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a Param) -> V::Result { - walk_list!(visitor, visit_attribute, ¶m.attrs); - try_visit!(visitor.visit_pat(¶m.pat)); - try_visit!(visitor.visit_ty(¶m.ty)); + let Param { attrs, ty, pat, id: _, span: _, is_placeholder: _ } = param; + walk_list!(visitor, visit_attribute, attrs); + try_visit!(visitor.visit_pat(pat)); + try_visit!(visitor.visit_ty(ty)); V::Result::output() } pub fn walk_arm<'a, V: Visitor<'a>>(visitor: &mut V, arm: &'a Arm) -> V::Result { - walk_list!(visitor, visit_attribute, &arm.attrs); - try_visit!(visitor.visit_pat(&arm.pat)); - visit_opt!(visitor, visit_expr, &arm.guard); - visit_opt!(visitor, visit_expr, &arm.body); + let Arm { attrs, pat, guard, body, span: _, id: _, is_placeholder: _ } = arm; + walk_list!(visitor, visit_attribute, attrs); + try_visit!(visitor.visit_pat(pat)); + visit_opt!(visitor, visit_expr, guard); + visit_opt!(visitor, visit_expr, body); V::Result::output() } pub fn walk_vis<'a, V: Visitor<'a>>(visitor: &mut V, vis: &'a Visibility) -> V::Result { - if let VisibilityKind::Restricted { ref path, id, shorthand: _ } = vis.kind { - try_visit!(visitor.visit_path(path, id)); + let Visibility { kind, span: _, tokens: _ } = vis; + match kind { + VisibilityKind::Restricted { path, id, shorthand: _ } => { + try_visit!(visitor.visit_path(path, *id)); + } + VisibilityKind::Public | VisibilityKind::Inherited => {} } V::Result::output() } pub fn walk_attribute<'a, V: Visitor<'a>>(visitor: &mut V, attr: &'a Attribute) -> V::Result { - match &attr.kind { - AttrKind::Normal(normal) => try_visit!(walk_attr_args(visitor, &normal.item.args)), - AttrKind::DocComment(..) => {} + let Attribute { kind, id: _, style: _, span: _ } = attr; + match kind { + AttrKind::Normal(normal) => { + let NormalAttr { item, tokens: _ } = &**normal; + let AttrItem { unsafety: _, path, args, tokens: _ } = item; + try_visit!(visitor.visit_path(path, DUMMY_NODE_ID)); + try_visit!(walk_attr_args(visitor, args)); + } + AttrKind::DocComment(_kind, _sym) => {} } V::Result::output() } @@ -1166,9 +1230,9 @@ pub fn walk_attribute<'a, V: Visitor<'a>>(visitor: &mut V, attr: &'a Attribute) pub fn walk_attr_args<'a, V: Visitor<'a>>(visitor: &mut V, args: &'a AttrArgs) -> V::Result { match args { AttrArgs::Empty => {} - AttrArgs::Delimited(_) => {} + AttrArgs::Delimited(_args) => {} AttrArgs::Eq(_eq_span, AttrArgsEq::Ast(expr)) => try_visit!(visitor.visit_expr(expr)), - AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => { + AttrArgs::Eq(_eq_span, AttrArgsEq::Hir(lit)) => { unreachable!("in literal form when walking mac args eq: {:?}", lit) } } diff --git a/tests/ui/stats/hir-stats.stderr b/tests/ui/stats/hir-stats.stderr index a3d0d47d4075..a7a612a8a9ea 100644 --- a/tests/ui/stats/hir-stats.stderr +++ b/tests/ui/stats/hir-stats.stderr @@ -13,13 +13,13 @@ ast-stats-1 - DocComment 32 ( 0.5%) 1 ast-stats-1 Local 80 ( 1.2%) 1 80 ast-stats-1 ForeignItem 88 ( 1.3%) 1 88 ast-stats-1 - Fn 88 ( 1.3%) 1 -ast-stats-1 Arm 96 ( 1.5%) 2 48 +ast-stats-1 Arm 96 ( 1.4%) 2 48 ast-stats-1 FnDecl 120 ( 1.8%) 5 24 ast-stats-1 FieldDef 160 ( 2.4%) 2 80 ast-stats-1 Stmt 160 ( 2.4%) 5 32 ast-stats-1 - Let 32 ( 0.5%) 1 ast-stats-1 - MacCall 32 ( 0.5%) 1 -ast-stats-1 - Expr 96 ( 1.5%) 3 +ast-stats-1 - Expr 96 ( 1.4%) 3 ast-stats-1 Param 160 ( 2.4%) 4 40 ast-stats-1 Block 192 ( 2.9%) 6 32 ast-stats-1 Variant 208 ( 3.1%) 2 104 @@ -28,7 +28,7 @@ ast-stats-1 - Trait 352 ( 5.3%) 4 ast-stats-1 AssocItem 352 ( 5.3%) 4 88 ast-stats-1 - Type 176 ( 2.7%) 2 ast-stats-1 - Fn 176 ( 2.7%) 2 -ast-stats-1 GenericParam 480 ( 7.3%) 5 96 +ast-stats-1 GenericParam 480 ( 7.2%) 5 96 ast-stats-1 Pat 504 ( 7.6%) 7 72 ast-stats-1 - Struct 72 ( 1.1%) 1 ast-stats-1 - Wild 72 ( 1.1%) 1 @@ -39,28 +39,28 @@ ast-stats-1 - Match 72 ( 1.1%) 1 ast-stats-1 - Struct 72 ( 1.1%) 1 ast-stats-1 - Lit 144 ( 2.2%) 2 ast-stats-1 - Block 216 ( 3.3%) 3 -ast-stats-1 PathSegment 720 (10.9%) 30 24 +ast-stats-1 PathSegment 744 (11.2%) 31 24 ast-stats-1 Ty 896 (13.5%) 14 64 ast-stats-1 - Ptr 64 ( 1.0%) 1 ast-stats-1 - Ref 64 ( 1.0%) 1 ast-stats-1 - ImplicitSelf 128 ( 1.9%) 2 -ast-stats-1 - Path 640 ( 9.7%) 10 -ast-stats-1 Item 1_224 (18.5%) 9 136 -ast-stats-1 - Trait 136 ( 2.1%) 1 -ast-stats-1 - Enum 136 ( 2.1%) 1 -ast-stats-1 - ForeignMod 136 ( 2.1%) 1 -ast-stats-1 - Impl 136 ( 2.1%) 1 +ast-stats-1 - Path 640 ( 9.6%) 10 +ast-stats-1 Item 1_224 (18.4%) 9 136 +ast-stats-1 - Trait 136 ( 2.0%) 1 +ast-stats-1 - Enum 136 ( 2.0%) 1 +ast-stats-1 - ForeignMod 136 ( 2.0%) 1 +ast-stats-1 - Impl 136 ( 2.0%) 1 ast-stats-1 - Fn 272 ( 4.1%) 2 -ast-stats-1 - Use 408 ( 6.2%) 3 +ast-stats-1 - Use 408 ( 6.1%) 3 ast-stats-1 ---------------------------------------------------------------- -ast-stats-1 Total 6_616 +ast-stats-1 Total 6_640 ast-stats-1 ast-stats-2 POST EXPANSION AST STATS ast-stats-2 Name Accumulated Size Count Item Size ast-stats-2 ---------------------------------------------------------------- -ast-stats-2 GenericArgs 40 ( 0.6%) 1 40 -ast-stats-2 - AngleBracketed 40 ( 0.6%) 1 -ast-stats-2 Crate 40 ( 0.6%) 1 40 +ast-stats-2 GenericArgs 40 ( 0.5%) 1 40 +ast-stats-2 - AngleBracketed 40 ( 0.5%) 1 +ast-stats-2 Crate 40 ( 0.5%) 1 40 ast-stats-2 ExprField 48 ( 0.7%) 1 48 ast-stats-2 WherePredicate 56 ( 0.8%) 1 56 ast-stats-2 - BoundPredicate 56 ( 0.8%) 1 @@ -68,8 +68,8 @@ ast-stats-2 Local 80 ( 1.1%) 1 80 ast-stats-2 ForeignItem 88 ( 1.2%) 1 88 ast-stats-2 - Fn 88 ( 1.2%) 1 ast-stats-2 Arm 96 ( 1.3%) 2 48 -ast-stats-2 InlineAsm 120 ( 1.7%) 1 120 -ast-stats-2 FnDecl 120 ( 1.7%) 5 24 +ast-stats-2 InlineAsm 120 ( 1.6%) 1 120 +ast-stats-2 FnDecl 120 ( 1.6%) 5 24 ast-stats-2 Attribute 128 ( 1.8%) 4 32 ast-stats-2 - DocComment 32 ( 0.4%) 1 ast-stats-2 - Normal 96 ( 1.3%) 3 @@ -79,41 +79,41 @@ ast-stats-2 - Let 32 ( 0.4%) 1 ast-stats-2 - Semi 32 ( 0.4%) 1 ast-stats-2 - Expr 96 ( 1.3%) 3 ast-stats-2 Param 160 ( 2.2%) 4 40 -ast-stats-2 Block 192 ( 2.7%) 6 32 +ast-stats-2 Block 192 ( 2.6%) 6 32 ast-stats-2 Variant 208 ( 2.9%) 2 104 -ast-stats-2 GenericBound 352 ( 4.9%) 4 88 -ast-stats-2 - Trait 352 ( 4.9%) 4 -ast-stats-2 AssocItem 352 ( 4.9%) 4 88 +ast-stats-2 GenericBound 352 ( 4.8%) 4 88 +ast-stats-2 - Trait 352 ( 4.8%) 4 +ast-stats-2 AssocItem 352 ( 4.8%) 4 88 ast-stats-2 - Type 176 ( 2.4%) 2 ast-stats-2 - Fn 176 ( 2.4%) 2 -ast-stats-2 GenericParam 480 ( 6.7%) 5 96 -ast-stats-2 Pat 504 ( 7.0%) 7 72 +ast-stats-2 GenericParam 480 ( 6.6%) 5 96 +ast-stats-2 Pat 504 ( 6.9%) 7 72 ast-stats-2 - Struct 72 ( 1.0%) 1 ast-stats-2 - Wild 72 ( 1.0%) 1 -ast-stats-2 - Ident 360 ( 5.0%) 5 -ast-stats-2 Expr 648 ( 9.0%) 9 72 +ast-stats-2 - Ident 360 ( 4.9%) 5 +ast-stats-2 Expr 648 ( 8.9%) 9 72 ast-stats-2 - Path 72 ( 1.0%) 1 ast-stats-2 - Match 72 ( 1.0%) 1 ast-stats-2 - Struct 72 ( 1.0%) 1 ast-stats-2 - InlineAsm 72 ( 1.0%) 1 ast-stats-2 - Lit 144 ( 2.0%) 2 ast-stats-2 - Block 216 ( 3.0%) 3 -ast-stats-2 PathSegment 792 (11.0%) 33 24 -ast-stats-2 Ty 896 (12.4%) 14 64 +ast-stats-2 PathSegment 864 (11.9%) 36 24 +ast-stats-2 Ty 896 (12.3%) 14 64 ast-stats-2 - Ptr 64 ( 0.9%) 1 ast-stats-2 - Ref 64 ( 0.9%) 1 ast-stats-2 - ImplicitSelf 128 ( 1.8%) 2 -ast-stats-2 - Path 640 ( 8.9%) 10 -ast-stats-2 Item 1_496 (20.7%) 11 136 +ast-stats-2 - Path 640 ( 8.8%) 10 +ast-stats-2 Item 1_496 (20.5%) 11 136 ast-stats-2 - Trait 136 ( 1.9%) 1 ast-stats-2 - Enum 136 ( 1.9%) 1 ast-stats-2 - ExternCrate 136 ( 1.9%) 1 ast-stats-2 - ForeignMod 136 ( 1.9%) 1 ast-stats-2 - Impl 136 ( 1.9%) 1 -ast-stats-2 - Fn 272 ( 3.8%) 2 +ast-stats-2 - Fn 272 ( 3.7%) 2 ast-stats-2 - Use 544 ( 7.5%) 4 ast-stats-2 ---------------------------------------------------------------- -ast-stats-2 Total 7_216 +ast-stats-2 Total 7_288 ast-stats-2 hir-stats HIR STATS hir-stats Name Accumulated Size Count Item Size From 789ee88bd015fde4257464d0120ab57b0d744e0b Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 27 Jun 2024 14:56:57 -0400 Subject: [PATCH 21/23] Tighten spans for async blocks --- compiler/rustc_ast/src/ast.rs | 5 +- compiler/rustc_ast/src/mut_visit.rs | 3 +- compiler/rustc_ast/src/visit.rs | 2 +- compiler/rustc_ast_lowering/src/expr.rs | 7 ++- compiler/rustc_ast_lowering/src/item.rs | 16 +++--- .../rustc_ast_pretty/src/pprust/state/expr.rs | 2 +- .../src/assert/context.rs | 2 +- compiler/rustc_parse/src/parser/expr.rs | 5 +- compiler/rustc_resolve/src/def_collector.rs | 2 +- .../src/suspicious_operation_groupings.rs | 2 +- .../clippy/clippy_utils/src/ast_utils.rs | 2 +- src/tools/rustfmt/src/expr.rs | 2 +- ...block-control-flow-static-semantics.stderr | 26 +++++----- ...async-borrowck-escaping-block-error.stderr | 10 ++-- .../async-closures/wrong-fn-kind.stderr | 24 ++++----- .../ui/async-await/async-is-unwindsafe.stderr | 25 +++++----- tests/ui/async-await/coroutine-desc.stderr | 4 +- .../async-await/coroutine-not-future.stderr | 4 +- .../issue-67252-unnamed-future.stderr | 2 +- tests/ui/async-await/issue-68112.stderr | 15 ++---- .../issue-70935-complex-spans.stderr | 20 +++----- ...sue-74072-lifetime-name-annotations.stderr | 14 +++--- tests/ui/async-await/issue-86507.stderr | 2 +- .../issues/issue-78938-async-block.stderr | 10 ++-- .../async-closure-gate.afn.stderr | 4 +- .../async-closure-gate.nofeat.stderr | 4 +- .../async-await/try-on-option-in-async.stderr | 12 ++--- .../cloning-in-async-block-121547.stderr | 18 +++---- ...break-inside-coroutine-issue-124495.stderr | 50 ++++++++----------- tests/ui/coroutine/clone-impl-async.stderr | 24 ++++----- tests/ui/coroutine/gen_block_is_coro.stderr | 12 ++--- .../coroutine/gen_block_is_no_future.stderr | 6 +-- tests/ui/coroutine/gen_block_move.stderr | 13 ++--- .../issue-90014-tait.stderr | 2 +- tests/ui/impl-trait/issue-55872-3.stderr | 4 +- .../ui/impl-trait/issues/issue-78722-2.stderr | 4 +- tests/ui/impl-trait/issues/issue-78722.stderr | 2 +- .../ui/impl-trait/nested-return-type4.stderr | 2 +- .../mismatch-sugg-for-shorthand-field.stderr | 4 +- .../pattern/non-structural-match-types.stderr | 2 +- .../expected-boxed-future-isnt-pinned.stderr | 2 +- tests/ui/traits/next-solver/async.fail.stderr | 2 +- .../indirect-recursion-issue-112047.stderr | 4 +- 43 files changed, 173 insertions(+), 204 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 4a3ce0e0c306..f5e79c04d784 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1454,7 +1454,10 @@ pub enum ExprKind { Block(P, Option