From f693910dcd0fe82ade55b666dc93f2fcfb3e31f9 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Sun, 28 Jul 2024 22:11:09 +0300 Subject: [PATCH 001/189] Partially stabilize `io_error_more` --- library/std/src/io/error.rs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index 8de27367a3f21..f3da35e1d0d93 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -226,10 +226,10 @@ pub enum ErrorKind { #[stable(feature = "rust1", since = "1.0.0")] ConnectionReset, /// The remote host is not reachable. - #[unstable(feature = "io_error_more", issue = "86442")] + #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] HostUnreachable, /// The network containing the remote host is not reachable. - #[unstable(feature = "io_error_more", issue = "86442")] + #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] NetworkUnreachable, /// The connection was aborted (terminated) by the remote server. #[stable(feature = "rust1", since = "1.0.0")] @@ -246,7 +246,7 @@ pub enum ErrorKind { #[stable(feature = "rust1", since = "1.0.0")] AddrNotAvailable, /// The system's networking is down. - #[unstable(feature = "io_error_more", issue = "86442")] + #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] NetworkDown, /// The operation failed because a pipe was closed. #[stable(feature = "rust1", since = "1.0.0")] @@ -262,18 +262,18 @@ pub enum ErrorKind { /// /// For example, a filesystem path was specified where one of the intermediate directory /// components was, in fact, a plain file. - #[unstable(feature = "io_error_more", issue = "86442")] + #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] NotADirectory, /// The filesystem object is, unexpectedly, a directory. /// /// A directory was specified when a non-directory was expected. - #[unstable(feature = "io_error_more", issue = "86442")] + #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] IsADirectory, /// A non-empty directory was specified where an empty directory was expected. - #[unstable(feature = "io_error_more", issue = "86442")] + #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] DirectoryNotEmpty, /// The filesystem or storage medium is read-only, but a write operation was attempted. - #[unstable(feature = "io_error_more", issue = "86442")] + #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] ReadOnlyFilesystem, /// Loop in the filesystem or IO subsystem; often, too many levels of symbolic links. /// @@ -288,7 +288,7 @@ pub enum ErrorKind { /// /// With some network filesystems, notably NFS, an open file (or directory) can be invalidated /// by problems with the network or server. - #[unstable(feature = "io_error_more", issue = "86442")] + #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] StaleNetworkFileHandle, /// A parameter was incorrect. #[stable(feature = "rust1", since = "1.0.0")] @@ -322,13 +322,13 @@ pub enum ErrorKind { /// The underlying storage (typically, a filesystem) is full. /// /// This does not include out of quota errors. - #[unstable(feature = "io_error_more", issue = "86442")] + #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] StorageFull, /// Seek on unseekable file. /// /// Seeking was attempted on an open file handle which is not suitable for seeking - for /// example, on Unix, a named pipe opened with `File::open`. - #[unstable(feature = "io_error_more", issue = "86442")] + #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] NotSeekable, /// Filesystem quota was exceeded. #[unstable(feature = "io_error_more", issue = "86442")] @@ -338,22 +338,22 @@ pub enum ErrorKind { /// This might arise from a hard limit of the underlying filesystem or file access API, or from /// an administratively imposed resource limitation. Simple disk full, and out of quota, have /// their own errors. - #[unstable(feature = "io_error_more", issue = "86442")] + #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] FileTooLarge, /// Resource is busy. - #[unstable(feature = "io_error_more", issue = "86442")] + #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] ResourceBusy, /// Executable file is busy. /// /// An attempt was made to write to a file which is also in use as a running program. (Not all /// operating systems detect this situation.) - #[unstable(feature = "io_error_more", issue = "86442")] + #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] ExecutableFileBusy, /// Deadlock (avoided). /// /// A file locking operation would result in deadlock. This situation is typically detected, if /// at all, on a best-effort basis. - #[unstable(feature = "io_error_more", issue = "86442")] + #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] Deadlock, /// Cross-device or cross-filesystem (hard) link or rename. #[unstable(feature = "io_error_more", issue = "86442")] @@ -361,7 +361,7 @@ pub enum ErrorKind { /// Too many (hard) links to the same filesystem object. /// /// The filesystem does not support making so many hardlinks to the same file. - #[unstable(feature = "io_error_more", issue = "86442")] + #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] TooManyLinks, /// A filename was invalid. /// @@ -372,7 +372,7 @@ pub enum ErrorKind { /// /// When trying to run an external program, a system or process limit on the size of the /// arguments would have been exceeded. - #[unstable(feature = "io_error_more", issue = "86442")] + #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] ArgumentListTooLong, /// This operation was interrupted. /// From 2dbc976f5d1e49343cba31c0b3a529c2f4d3d271 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 10 Aug 2024 19:23:03 +0000 Subject: [PATCH 002/189] Distribute rustc_codegen_cranelift for Windows --- compiler/rustc_codegen_cranelift/Readme.md | 2 +- src/bootstrap/src/core/build_steps/dist.rs | 15 +++------------ src/ci/github-actions/jobs.yml | 4 ++++ 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/Readme.md b/compiler/rustc_codegen_cranelift/Readme.md index 6766e2f844d6d..18a840f8a50e0 100644 --- a/compiler/rustc_codegen_cranelift/Readme.md +++ b/compiler/rustc_codegen_cranelift/Readme.md @@ -70,7 +70,7 @@ For more docs on how to build and test see [build_system/usage.txt](build_system |AIX|❌[^xcoff]|N/A|N/A|❌[^xcoff]| |Other unixes|❓|❓|❓|❓| |macOS|✅|✅|N/A|N/A| -|Windows|✅[^no-rustup]|❌|N/A|N/A| +|Windows|✅|❌|N/A|N/A| ✅: Fully supported and tested ❓: Maybe supported, not tested diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 43306eab1b144..9edbb130905aa 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -1361,18 +1361,9 @@ impl Step for CodegenBackend { return None; } - if self.backend == "cranelift" { - if !target_supports_cranelift_backend(self.compiler.host) { - builder.info("target not supported by rustc_codegen_cranelift. skipping"); - return None; - } - - if self.compiler.host.is_windows() { - builder.info( - "dist currently disabled for windows by rustc_codegen_cranelift. skipping", - ); - return None; - } + if self.backend == "cranelift" && !target_supports_cranelift_backend(self.compiler.host) { + builder.info("target not supported by rustc_codegen_cranelift. skipping"); + return None; } let compiler = self.compiler; diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 638f14ad53fef..dfbc95cfa7954 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -416,6 +416,7 @@ auto: --set rust.codegen-units=1 SCRIPT: python x.py build --set rust.debug=true opt-dist && PGO_HOST=x86_64-pc-windows-msvc ./build/x86_64-pc-windows-msvc/stage0-tools-bin/opt-dist windows-ci -- python x.py dist bootstrap --include-default-paths DIST_REQUIRE_ALL_TOOLS: 1 + CODEGEN_BACKENDS: llvm,cranelift <<: *job-windows-8c - image: dist-i686-msvc @@ -428,6 +429,7 @@ auto: --enable-profiler SCRIPT: python x.py dist bootstrap --include-default-paths DIST_REQUIRE_ALL_TOOLS: 1 + CODEGEN_BACKENDS: llvm,cranelift <<: *job-windows-8c - image: dist-aarch64-msvc @@ -452,6 +454,7 @@ auto: NO_DOWNLOAD_CI_LLVM: 1 SCRIPT: python x.py dist bootstrap --include-default-paths DIST_REQUIRE_ALL_TOOLS: 1 + CODEGEN_BACKENDS: llvm,cranelift <<: *job-windows-8c - image: dist-x86_64-mingw @@ -464,6 +467,7 @@ auto: # incompatible with LLVM downloads today). NO_DOWNLOAD_CI_LLVM: 1 DIST_REQUIRE_ALL_TOOLS: 1 + CODEGEN_BACKENDS: llvm,cranelift <<: *job-windows-8c - image: dist-x86_64-msvc-alt From 893413de5b3e574cee9e2e2cc36524a485b9ea83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sat, 24 Aug 2024 10:55:31 +0200 Subject: [PATCH 003/189] Add a run-make test for checking that certain `rustc_` crates build on stable --- .../src/external_deps/cargo.rs | 7 ++++ .../run-make-support/src/external_deps/mod.rs | 1 + .../src/external_deps/rustc.rs | 7 ++-- src/tools/run-make-support/src/lib.rs | 4 ++- .../run-make/rustc-crates-on-stable/rmake.rs | 35 +++++++++++++++++++ 5 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 src/tools/run-make-support/src/external_deps/cargo.rs create mode 100644 tests/run-make/rustc-crates-on-stable/rmake.rs diff --git a/src/tools/run-make-support/src/external_deps/cargo.rs b/src/tools/run-make-support/src/external_deps/cargo.rs new file mode 100644 index 0000000000000..b0e045dc80bf8 --- /dev/null +++ b/src/tools/run-make-support/src/external_deps/cargo.rs @@ -0,0 +1,7 @@ +use crate::command::Command; +use crate::env_var; + +/// Returns a command that can be used to invoke Cargo. +pub fn cargo() -> Command { + Command::new(env_var("BOOTSTRAP_CARGO")) +} diff --git a/src/tools/run-make-support/src/external_deps/mod.rs b/src/tools/run-make-support/src/external_deps/mod.rs index f7c84724d0e07..80c34a9070fcc 100644 --- a/src/tools/run-make-support/src/external_deps/mod.rs +++ b/src/tools/run-make-support/src/external_deps/mod.rs @@ -2,6 +2,7 @@ //! such as `cc` or `python`. pub mod c_build; +pub mod cargo; pub mod cc; pub mod clang; pub mod htmldocck; diff --git a/src/tools/run-make-support/src/external_deps/rustc.rs b/src/tools/run-make-support/src/external_deps/rustc.rs index cece58d29566c..e20d87165144a 100644 --- a/src/tools/run-make-support/src/external_deps/rustc.rs +++ b/src/tools/run-make-support/src/external_deps/rustc.rs @@ -36,10 +36,13 @@ pub struct Rustc { crate::macros::impl_common_helpers!(Rustc); +pub fn rustc_path() -> String { + env_var("RUSTC") +} + #[track_caller] fn setup_common() -> Command { - let rustc = env_var("RUSTC"); - let mut cmd = Command::new(rustc); + let mut cmd = Command::new(rustc_path()); set_host_rpath(&mut cmd); cmd } diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index 989d00d4c2f97..efe744d6ba4a7 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -48,6 +48,7 @@ pub use external_deps::{c_build, cc, clang, htmldocck, llvm, python, rustc, rust // These rely on external dependencies. pub use cc::{cc, cxx, extra_c_flags, extra_cxx_flags, Cc}; pub use c_build::{build_native_dynamic_lib, build_native_static_lib, build_native_static_lib_optimized, build_native_static_lib_cxx}; +pub use cargo::cargo; pub use clang::{clang, Clang}; pub use htmldocck::htmldocck; pub use llvm::{ @@ -56,7 +57,7 @@ pub use llvm::{ LlvmProfdata, LlvmReadobj, }; pub use python::python_command; -pub use rustc::{aux_build, bare_rustc, rustc, Rustc}; +pub use rustc::{aux_build, bare_rustc, rustc, rustc_path, Rustc}; pub use rustdoc::{bare_rustdoc, rustdoc, Rustdoc}; /// [`diff`][mod@diff] is implemented in terms of the [similar] library. @@ -96,3 +97,4 @@ pub use assertion_helpers::{ pub use string::{ count_regex_matches_in_files_with_extension, invalid_utf8_contains, invalid_utf8_not_contains, }; +use crate::external_deps::cargo; diff --git a/tests/run-make/rustc-crates-on-stable/rmake.rs b/tests/run-make/rustc-crates-on-stable/rmake.rs new file mode 100644 index 0000000000000..67461788ee4b6 --- /dev/null +++ b/tests/run-make/rustc-crates-on-stable/rmake.rs @@ -0,0 +1,35 @@ +//! Checks if selected rustc crates can be compiled on the stable channel (or a "simulation" of it). +//! These crates are designed to be used by downstream users. + +use run_make_support::{cargo, rustc_path, source_root}; + +fn main() { + // Use the stage0 beta cargo for the compilation (it shouldn't really matter which cargo we use) + let cargo = cargo() + // This is required to allow using nightly cargo features (public-dependency) with beta + // cargo + .env("RUSTC_BOOTSTRAP", "1") + .env("RUSTC", rustc_path()) + .arg("build") + .arg("--manifest-path") + .arg(source_root().join("Cargo.toml")) + .args(&[ + "--config", + r#"workspace.exclude=["library/core"]"#, + // We want to disallow all nightly features, to simulate a stable build + // public-dependency needs to be enabled for cargo to work + "-Zallow-features=public-dependency", + // Avoid depending on transitive rustc crates + "--no-default-features", + // Check that these crates can be compiled on "stable" + "-p", + "rustc_type_ir", + "-p", + "rustc_next_trait_solver", + "-p", + "rustc_pattern_analysis", + "-p", + "rustc_lexer", + ]) + .run(); +} From 7957140f3ef7fbbaf9696d8fbbced1ebe6128c5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Sat, 24 Aug 2024 20:34:46 +0000 Subject: [PATCH 004/189] inhibit proc-macro2 nightly detection --- tests/run-make/rustc-crates-on-stable/rmake.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/run-make/rustc-crates-on-stable/rmake.rs b/tests/run-make/rustc-crates-on-stable/rmake.rs index 67461788ee4b6..503b0c6ead445 100644 --- a/tests/run-make/rustc-crates-on-stable/rmake.rs +++ b/tests/run-make/rustc-crates-on-stable/rmake.rs @@ -9,6 +9,7 @@ fn main() { // This is required to allow using nightly cargo features (public-dependency) with beta // cargo .env("RUSTC_BOOTSTRAP", "1") + .env("RUSTC_STAGE", "0") // Ensure `proc-macro2`'s nightly detection is disabled .env("RUSTC", rustc_path()) .arg("build") .arg("--manifest-path") From d9794a9af63b5cf59bf9a7bfa65191a6d2a1e122 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Sat, 24 Aug 2024 21:16:54 +0000 Subject: [PATCH 005/189] run test in tmp dir and emit artifacts there otherwise the test would build in the source root's `target` folder --- .../run-make/rustc-crates-on-stable/rmake.rs | 67 ++++++++++--------- 1 file changed, 37 insertions(+), 30 deletions(-) diff --git a/tests/run-make/rustc-crates-on-stable/rmake.rs b/tests/run-make/rustc-crates-on-stable/rmake.rs index 503b0c6ead445..66f0b2c812625 100644 --- a/tests/run-make/rustc-crates-on-stable/rmake.rs +++ b/tests/run-make/rustc-crates-on-stable/rmake.rs @@ -1,36 +1,43 @@ //! Checks if selected rustc crates can be compiled on the stable channel (or a "simulation" of it). //! These crates are designed to be used by downstream users. -use run_make_support::{cargo, rustc_path, source_root}; +use run_make_support::{cargo, run_in_tmpdir, rustc_path, source_root}; fn main() { - // Use the stage0 beta cargo for the compilation (it shouldn't really matter which cargo we use) - let cargo = cargo() - // This is required to allow using nightly cargo features (public-dependency) with beta - // cargo - .env("RUSTC_BOOTSTRAP", "1") - .env("RUSTC_STAGE", "0") // Ensure `proc-macro2`'s nightly detection is disabled - .env("RUSTC", rustc_path()) - .arg("build") - .arg("--manifest-path") - .arg(source_root().join("Cargo.toml")) - .args(&[ - "--config", - r#"workspace.exclude=["library/core"]"#, - // We want to disallow all nightly features, to simulate a stable build - // public-dependency needs to be enabled for cargo to work - "-Zallow-features=public-dependency", - // Avoid depending on transitive rustc crates - "--no-default-features", - // Check that these crates can be compiled on "stable" - "-p", - "rustc_type_ir", - "-p", - "rustc_next_trait_solver", - "-p", - "rustc_pattern_analysis", - "-p", - "rustc_lexer", - ]) - .run(); + run_in_tmpdir(|| { + // Use the stage0 beta cargo for the compilation (it shouldn't really matter which cargo we + // use) + let cargo = cargo() + // This is required to allow using nightly cargo features (public-dependency) with beta + // cargo + .env("RUSTC_BOOTSTRAP", "1") + .env("RUSTC_STAGE", "0") // Ensure `proc-macro2`'s nightly detection is disabled + .env("RUSTC", rustc_path()) + .arg("build") + .arg("--manifest-path") + .arg(source_root().join("Cargo.toml")) + .args(&[ + "--config", + r#"workspace.exclude=["library/core"]"#, + // We want to disallow all nightly features, to simulate a stable build + // public-dependency needs to be enabled for cargo to work + "-Zallow-features=public-dependency", + // Avoid depending on transitive rustc crates + "--no-default-features", + // Emit artifacts in this temporary directory, not in the source_root's `target` + // folder + "--target-dir", + ".", + // Check that these crates can be compiled on "stable" + "-p", + "rustc_type_ir", + "-p", + "rustc_next_trait_solver", + "-p", + "rustc_pattern_analysis", + "-p", + "rustc_lexer", + ]) + .run(); + }); } From 2190c288e2455bce98dde643267ce53fd3412edb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Sun, 25 Aug 2024 10:53:28 +0000 Subject: [PATCH 006/189] remove use of RUSTC_BOOTSTRAP and cargo nightly features --- tests/run-make/rustc-crates-on-stable/rmake.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/tests/run-make/rustc-crates-on-stable/rmake.rs b/tests/run-make/rustc-crates-on-stable/rmake.rs index 66f0b2c812625..513c128828725 100644 --- a/tests/run-make/rustc-crates-on-stable/rmake.rs +++ b/tests/run-make/rustc-crates-on-stable/rmake.rs @@ -8,20 +8,17 @@ fn main() { // Use the stage0 beta cargo for the compilation (it shouldn't really matter which cargo we // use) let cargo = cargo() - // This is required to allow using nightly cargo features (public-dependency) with beta - // cargo - .env("RUSTC_BOOTSTRAP", "1") - .env("RUSTC_STAGE", "0") // Ensure `proc-macro2`'s nightly detection is disabled + // Ensure `proc-macro2`'s nightly detection is disabled + .env("RUSTC_STAGE", "0") .env("RUSTC", rustc_path()) + // We want to disallow all nightly features to simulate a stable build + .env("RUSTFLAGS", "-Zallow-features=") .arg("build") .arg("--manifest-path") .arg(source_root().join("Cargo.toml")) .args(&[ "--config", r#"workspace.exclude=["library/core"]"#, - // We want to disallow all nightly features, to simulate a stable build - // public-dependency needs to be enabled for cargo to work - "-Zallow-features=public-dependency", // Avoid depending on transitive rustc crates "--no-default-features", // Emit artifacts in this temporary directory, not in the source_root's `target` From 057703593c9744619787f1fe93b01059247ebb2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Sun, 25 Aug 2024 10:59:38 +0000 Subject: [PATCH 007/189] separate the crates to test from the test setup it'll be easier to see and update the list: the other cmd args can just be ignored --- tests/run-make/rustc-crates-on-stable/rmake.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/run-make/rustc-crates-on-stable/rmake.rs b/tests/run-make/rustc-crates-on-stable/rmake.rs index 513c128828725..48b8551ecef7c 100644 --- a/tests/run-make/rustc-crates-on-stable/rmake.rs +++ b/tests/run-make/rustc-crates-on-stable/rmake.rs @@ -25,7 +25,9 @@ fn main() { // folder "--target-dir", ".", - // Check that these crates can be compiled on "stable" + ]) + // Check that these crates can be compiled on "stable" + .args(&[ "-p", "rustc_type_ir", "-p", From f1df0c5fdc8fce70a36bbe283c7165223056d16a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Sun, 25 Aug 2024 22:33:18 +0000 Subject: [PATCH 008/189] remove unneeded type ascription --- compiler/rustc_type_ir/src/elaborate.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_type_ir/src/elaborate.rs b/compiler/rustc_type_ir/src/elaborate.rs index 433c444e701cc..f30419c801f18 100644 --- a/compiler/rustc_type_ir/src/elaborate.rs +++ b/compiler/rustc_type_ir/src/elaborate.rs @@ -237,7 +237,7 @@ pub fn supertrait_def_ids( cx: I, trait_def_id: I::DefId, ) -> impl Iterator { - let mut set: HashSet = HashSet::default(); + let mut set = HashSet::default(); let mut stack = vec![trait_def_id]; set.insert(trait_def_id); From 736ab66c62ad23b880299e1f997ff1e4d7a9ceef Mon Sep 17 00:00:00 2001 From: Wafarm Date: Mon, 19 Aug 2024 11:37:11 +0800 Subject: [PATCH 009/189] Don't suggest adding return type for closures with default return type --- compiler/rustc_hir_typeck/src/_match.rs | 2 +- compiler/rustc_hir_typeck/src/coercion.rs | 4 +- compiler/rustc_hir_typeck/src/expr.rs | 2 +- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 39 +++++---------- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 2 +- .../src/fn_ctxt/suggestions.rs | 49 ++++++++++++++----- .../add_semicolon_non_block_closure.rs | 1 - .../add_semicolon_non_block_closure.stderr | 4 -- .../try-operator-dont-suggest-semicolon.rs | 1 - ...try-operator-dont-suggest-semicolon.stderr | 17 ++----- tests/ui/typeck/issue-81943.stderr | 26 +++++----- 11 files changed, 74 insertions(+), 73 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index 7427fb147166f..573c8d4d7119a 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -388,7 +388,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { // check that the `if` expr without `else` is the fn body's expr if expr.span == sp { - return self.get_fn_decl(hir_id).map(|(_, fn_decl, _)| { + return self.get_fn_decl(hir_id).map(|(_, fn_decl)| { let (ty, span) = match fn_decl.output { hir::FnRetTy::DefaultReturn(span) => ("()".to_string(), span), hir::FnRetTy::Return(ty) => (ty_to_string(&self.tcx, ty), ty.span), diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index dabc5a8939783..8e5d8cba5bef0 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -1859,10 +1859,10 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { }; // If this is due to an explicit `return`, suggest adding a return type. - if let Some((fn_id, fn_decl, can_suggest)) = fcx.get_fn_decl(block_or_return_id) + if let Some((fn_id, fn_decl)) = fcx.get_fn_decl(block_or_return_id) && !due_to_block { - fcx.suggest_missing_return_type(&mut err, fn_decl, expected, found, can_suggest, fn_id); + fcx.suggest_missing_return_type(&mut err, fn_decl, expected, found, fn_id); } // If this is due to a block, then maybe we forgot a `return`/`break`. diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index dd33b947b0d06..d70c3f6a0d843 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -773,7 +773,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.ret_coercion_span.set(Some(expr.span)); } let cause = self.cause(expr.span, ObligationCauseCode::ReturnNoExpression); - if let Some((_, fn_decl, _)) = self.get_fn_decl(expr.hir_id) { + if let Some((_, fn_decl)) = self.get_fn_decl(expr.hir_id) { coercion.coerce_forced_unit( self, &cause, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 2d205d1ede9cd..1c4a6fc22f797 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -31,7 +31,7 @@ use rustc_middle::{bug, span_bug}; use rustc_session::lint; use rustc_span::def_id::LocalDefId; use rustc_span::hygiene::DesugaringKind; -use rustc_span::symbol::{kw, sym}; +use rustc_span::symbol::kw; use rustc_span::Span; use rustc_target::abi::FieldIdx; use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded; @@ -895,38 +895,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) } - /// Given a `HirId`, return the `HirId` of the enclosing function, its `FnDecl`, and whether a - /// suggestion can be made, `None` otherwise. + /// Given a `HirId`, return the `HirId` of the enclosing function and its `FnDecl`. pub(crate) fn get_fn_decl( &self, blk_id: HirId, - ) -> Option<(LocalDefId, &'tcx hir::FnDecl<'tcx>, bool)> { + ) -> Option<(LocalDefId, &'tcx hir::FnDecl<'tcx>)> { // Get enclosing Fn, if it is a function or a trait method, unless there's a `loop` or // `while` before reaching it, as block tail returns are not available in them. self.tcx.hir().get_fn_id_for_return_block(blk_id).and_then(|item_id| { match self.tcx.hir_node(item_id) { Node::Item(&hir::Item { - ident, - kind: hir::ItemKind::Fn(ref sig, ..), - owner_id, - .. - }) => { - // This is less than ideal, it will not suggest a return type span on any - // method called `main`, regardless of whether it is actually the entry point, - // but it will still present it as the reason for the expected type. - Some((owner_id.def_id, sig.decl, ident.name != sym::main)) - } + kind: hir::ItemKind::Fn(ref sig, ..), owner_id, .. + }) => Some((owner_id.def_id, sig.decl)), Node::TraitItem(&hir::TraitItem { kind: hir::TraitItemKind::Fn(ref sig, ..), owner_id, .. - }) => Some((owner_id.def_id, sig.decl, true)), - // FIXME: Suggestable if this is not a trait implementation + }) => Some((owner_id.def_id, sig.decl)), Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(ref sig, ..), owner_id, .. - }) => Some((owner_id.def_id, sig.decl, false)), + }) => Some((owner_id.def_id, sig.decl)), Node::Expr(&hir::Expr { hir_id, kind: hir::ExprKind::Closure(&hir::Closure { def_id, kind, fn_decl, .. }), @@ -937,33 +927,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // FIXME(async_closures): Implement this. return None; } - hir::ClosureKind::Closure => Some((def_id, fn_decl, true)), + hir::ClosureKind::Closure => Some((def_id, fn_decl)), hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( _, hir::CoroutineSource::Fn, )) => { - let (ident, sig, owner_id) = match self.tcx.parent_hir_node(hir_id) { + let (sig, owner_id) = match self.tcx.parent_hir_node(hir_id) { Node::Item(&hir::Item { - ident, kind: hir::ItemKind::Fn(ref sig, ..), owner_id, .. - }) => (ident, sig, owner_id), + }) => (sig, owner_id), Node::TraitItem(&hir::TraitItem { - ident, kind: hir::TraitItemKind::Fn(ref sig, ..), owner_id, .. - }) => (ident, sig, owner_id), + }) => (sig, owner_id), Node::ImplItem(&hir::ImplItem { - ident, kind: hir::ImplItemKind::Fn(ref sig, ..), owner_id, .. - }) => (ident, sig, owner_id), + }) => (sig, owner_id), _ => return None, }; - Some((owner_id.def_id, sig.decl, ident.name != sym::main)) + Some((owner_id.def_id, sig.decl)) } _ => None, } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 5333982c42029..2a1c3b0300482 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1841,7 +1841,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // that highlight errors inline. let mut sp = blk.span; let mut fn_span = None; - if let Some((fn_def_id, decl, _)) = self.get_fn_decl(blk.hir_id) { + if let Some((fn_def_id, decl)) = self.get_fn_decl(blk.hir_id) { let ret_sp = decl.output.span(); if let Some(block_sp) = self.parent_item_span(blk.hir_id) { // HACK: on some cases (`ui/liveness/liveness-issue-2163.rs`) the diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 031aa6159d2bc..8b63a6df8af00 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -78,9 +78,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // `break` type mismatches provide better context for tail `loop` expressions. return false; } - if let Some((fn_id, fn_decl, can_suggest)) = self.get_fn_decl(blk_id) { + if let Some((fn_id, fn_decl)) = self.get_fn_decl(blk_id) { pointing_at_return_type = - self.suggest_missing_return_type(err, fn_decl, expected, found, can_suggest, fn_id); + self.suggest_missing_return_type(err, fn_decl, expected, found, fn_id); self.suggest_missing_break_or_return_expr( err, expr, fn_decl, expected, found, blk_id, fn_id, ); @@ -812,7 +812,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn_decl: &hir::FnDecl<'tcx>, expected: Ty<'tcx>, found: Ty<'tcx>, - can_suggest: bool, fn_id: LocalDefId, ) -> bool { // Can't suggest `->` on a block-like coroutine @@ -825,28 +824,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let found = self.resolve_numeric_literals_with_default(self.resolve_vars_if_possible(found)); // Only suggest changing the return type for methods that - // haven't set a return type at all (and aren't `fn main()` or an impl). + // haven't set a return type at all (and aren't `fn main()`, impl or closure). match &fn_decl.output { - &hir::FnRetTy::DefaultReturn(span) if expected.is_unit() && !can_suggest => { - // `fn main()` must return `()`, do not suggest changing return type - err.subdiagnostic(errors::ExpectedReturnTypeLabel::Unit { span }); - return true; - } + // For closure with default returns, don't suggest adding return type + &hir::FnRetTy::DefaultReturn(_) if self.tcx.is_closure_like(fn_id.to_def_id()) => {} &hir::FnRetTy::DefaultReturn(span) if expected.is_unit() => { - if let Some(found) = found.make_suggestable(self.tcx, false, None) { + if !self.can_add_return_type(fn_id) { + err.subdiagnostic(errors::ExpectedReturnTypeLabel::Unit { span }); + } else if let Some(found) = found.make_suggestable(self.tcx, false, None) { err.subdiagnostic(errors::AddReturnTypeSuggestion::Add { span, found: found.to_string(), }); - return true; } else if let Some(sugg) = suggest_impl_trait(self, self.param_env, found) { err.subdiagnostic(errors::AddReturnTypeSuggestion::Add { span, found: sugg }); - return true; } else { // FIXME: if `found` could be `impl Iterator` we should suggest that. err.subdiagnostic(errors::AddReturnTypeSuggestion::MissingHere { span }); - return true; } + + return true; } hir::FnRetTy::Return(hir_ty) => { if let hir::TyKind::OpaqueDef(item_id, ..) = hir_ty.kind @@ -904,6 +901,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { false } + /// Checks whether we can add a return type to a function. + /// Assumes given function doesn't have a explicit return type. + fn can_add_return_type(&self, fn_id: LocalDefId) -> bool { + match self.tcx.hir_node_by_def_id(fn_id) { + Node::Item(&hir::Item { ident, .. }) => { + // This is less than ideal, it will not suggest a return type span on any + // method called `main`, regardless of whether it is actually the entry point, + // but it will still present it as the reason for the expected type. + ident.name != sym::main + } + Node::ImplItem(item) => { + // If it doesn't impl a trait, we can add a return type + let Node::Item(&hir::Item { + kind: hir::ItemKind::Impl(&hir::Impl { of_trait, .. }), + .. + }) = self.tcx.parent_hir_node(item.hir_id()) + else { + unreachable!(); + }; + + of_trait.is_none() + } + _ => true, + } + } + fn try_note_caller_chooses_ty_for_ty_param( &self, diag: &mut Diag<'_>, diff --git a/tests/ui/closures/add_semicolon_non_block_closure.rs b/tests/ui/closures/add_semicolon_non_block_closure.rs index 62c5e343cd345..3ae91be60c5a0 100644 --- a/tests/ui/closures/add_semicolon_non_block_closure.rs +++ b/tests/ui/closures/add_semicolon_non_block_closure.rs @@ -8,5 +8,4 @@ fn main() { foo(|| bar()) //~^ ERROR mismatched types [E0308] //~| HELP consider using a semicolon here - //~| HELP try adding a return type } diff --git a/tests/ui/closures/add_semicolon_non_block_closure.stderr b/tests/ui/closures/add_semicolon_non_block_closure.stderr index 7883db8f98ec5..3dd8f12d55f32 100644 --- a/tests/ui/closures/add_semicolon_non_block_closure.stderr +++ b/tests/ui/closures/add_semicolon_non_block_closure.stderr @@ -8,10 +8,6 @@ help: consider using a semicolon here | LL | foo(|| { bar(); }) | + +++ -help: try adding a return type - | -LL | foo(|| -> i32 bar()) - | ++++++ error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/try-operator-dont-suggest-semicolon.rs b/tests/ui/suggestions/try-operator-dont-suggest-semicolon.rs index 35a06d396f2bb..f882a159f9834 100644 --- a/tests/ui/suggestions/try-operator-dont-suggest-semicolon.rs +++ b/tests/ui/suggestions/try-operator-dont-suggest-semicolon.rs @@ -3,7 +3,6 @@ fn main() -> Result<(), ()> { a(|| { - //~^ HELP: try adding a return type b() //~^ ERROR: mismatched types [E0308] //~| NOTE: expected `()`, found `i32` diff --git a/tests/ui/suggestions/try-operator-dont-suggest-semicolon.stderr b/tests/ui/suggestions/try-operator-dont-suggest-semicolon.stderr index 5506456afe9ca..939285498fb69 100644 --- a/tests/ui/suggestions/try-operator-dont-suggest-semicolon.stderr +++ b/tests/ui/suggestions/try-operator-dont-suggest-semicolon.stderr @@ -1,20 +1,13 @@ error[E0308]: mismatched types - --> $DIR/try-operator-dont-suggest-semicolon.rs:7:9 + --> $DIR/try-operator-dont-suggest-semicolon.rs:6:9 | LL | b() - | ^^^ expected `()`, found `i32` - | -help: consider using a semicolon here - | -LL | b(); - | + -help: try adding a return type - | -LL | a(|| -> i32 { - | ++++++ + | ^^^- help: consider using a semicolon here: `;` + | | + | expected `()`, found `i32` error[E0308]: mismatched types - --> $DIR/try-operator-dont-suggest-semicolon.rs:17:9 + --> $DIR/try-operator-dont-suggest-semicolon.rs:16:9 | LL | / if true { LL | | diff --git a/tests/ui/typeck/issue-81943.stderr b/tests/ui/typeck/issue-81943.stderr index f8da9ef0d180f..041ff10752cf0 100644 --- a/tests/ui/typeck/issue-81943.stderr +++ b/tests/ui/typeck/issue-81943.stderr @@ -2,9 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-81943.rs:7:9 | LL | f(|x| lib::d!(x)); - | -^^^^^^^^^^ expected `()`, found `i32` - | | - | help: try adding a return type: `-> i32` + | ^^^^^^^^^^ expected `()`, found `i32` | = note: this error originates in the macro `lib::d` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -12,22 +10,28 @@ error[E0308]: mismatched types --> $DIR/issue-81943.rs:8:28 | LL | f(|x| match x { tmp => { g(tmp) } }); - | ^^^^^^ expected `()`, found `i32` + | -------------------^^^^^^---- + | | | + | | expected `()`, found `i32` + | expected this to be `()` | help: consider using a semicolon here | LL | f(|x| match x { tmp => { g(tmp); } }); | + -help: try adding a return type +help: consider using a semicolon here | -LL | f(|x| -> i32 match x { tmp => { g(tmp) } }); - | ++++++ +LL | f(|x| match x { tmp => { g(tmp) } };); + | + error[E0308]: mismatched types --> $DIR/issue-81943.rs:10:38 | LL | ($e:expr) => { match $e { x => { g(x) } } } - | ^^^^ expected `()`, found `i32` + | ------------------^^^^---- + | | | + | | expected `()`, found `i32` + | expected this to be `()` LL | } LL | f(|x| d!(x)); | ----- in this macro invocation @@ -37,10 +41,10 @@ help: consider using a semicolon here | LL | ($e:expr) => { match $e { x => { g(x); } } } | + -help: try adding a return type +help: consider using a semicolon here | -LL | f(|x| -> i32 d!(x)); - | ++++++ +LL | ($e:expr) => { match $e { x => { g(x) } }; } + | + error: aborting due to 3 previous errors From 2ddcbca0e626cc3856349deeed17814ba6c272d6 Mon Sep 17 00:00:00 2001 From: tunawasabi <77270077+tunawasabi@users.noreply.github.com> Date: Sun, 25 Aug 2024 04:24:27 +0900 Subject: [PATCH 010/189] Suggest the struct variant pattern syntax on usage of unit variant pattern for a struct variant --- compiler/rustc_hir_typeck/src/lib.rs | 32 ++++++++++++++++++- .../ui/empty/empty-struct-braces-pat-1.stderr | 10 ++++++ .../ui/empty/empty-struct-braces-pat-3.stderr | 20 ++++++++++++ tests/ui/issues/issue-63983.stderr | 5 +++ .../recover/recover-from-bad-variant.stderr | 5 +++ tests/ui/suggestions/issue-84700.stderr | 5 +++ ...t-variant-form-through-alias-caught.stderr | 10 ++++++ 7 files changed, 86 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 9ec101196a43f..0a4df619c20f3 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -45,7 +45,7 @@ pub use coercion::can_coerce; use fn_ctxt::FnCtxt; use rustc_data_structures::unord::UnordSet; use rustc_errors::codes::*; -use rustc_errors::{struct_span_code_err, Applicability, ErrorGuaranteed}; +use rustc_errors::{pluralize, struct_span_code_err, Applicability, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::Visitor; @@ -421,6 +421,36 @@ fn report_unexpected_variant_res( err.multipart_suggestion_verbose(descr, suggestion, Applicability::MaybeIncorrect); err } + Res::Def(DefKind::Variant, _) if expr.is_none() => { + err.span_label(span, format!("not a {expected}")); + + let fields = &tcx.expect_variant_res(res).fields.raw; + let span = qpath.span().shrink_to_hi().to(span.shrink_to_hi()); + let (msg, sugg) = if fields.is_empty() { + ("use the struct variant pattern syntax".to_string(), " {}".to_string()) + } else { + let msg = format!( + "the struct variant's field{s} {are} being ignored", + s = pluralize!(fields.len()), + are = pluralize!("is", fields.len()) + ); + let fields = fields + .iter() + .map(|field| format!("{}: _", field.name.to_ident_string())) + .collect::>() + .join(", "); + let sugg = format!(" {{ {} }}", fields); + (msg, sugg) + }; + + err.span_suggestion_verbose( + qpath.span().shrink_to_hi().to(span.shrink_to_hi()), + msg, + sugg, + Applicability::HasPlaceholders, + ); + err + } _ => err.with_span_label(span, format!("not a {expected}")), } .emit() diff --git a/tests/ui/empty/empty-struct-braces-pat-1.stderr b/tests/ui/empty/empty-struct-braces-pat-1.stderr index 14e09fc27a06d..c16fbc7de2b29 100644 --- a/tests/ui/empty/empty-struct-braces-pat-1.stderr +++ b/tests/ui/empty/empty-struct-braces-pat-1.stderr @@ -3,12 +3,22 @@ error[E0533]: expected unit struct, unit variant or constant, found struct varia | LL | E::Empty3 => () | ^^^^^^^^^ not a unit struct, unit variant or constant + | +help: use the struct variant pattern syntax + | +LL | E::Empty3 {} => () + | ++ error[E0533]: expected unit struct, unit variant or constant, found struct variant `XE::XEmpty3` --> $DIR/empty-struct-braces-pat-1.rs:31:9 | LL | XE::XEmpty3 => () | ^^^^^^^^^^^ not a unit struct, unit variant or constant + | +help: use the struct variant pattern syntax + | +LL | XE::XEmpty3 {} => () + | ++ error: aborting due to 2 previous errors diff --git a/tests/ui/empty/empty-struct-braces-pat-3.stderr b/tests/ui/empty/empty-struct-braces-pat-3.stderr index 00c8b12e6f984..b2ab7113347ff 100644 --- a/tests/ui/empty/empty-struct-braces-pat-3.stderr +++ b/tests/ui/empty/empty-struct-braces-pat-3.stderr @@ -3,24 +3,44 @@ error[E0164]: expected tuple struct or tuple variant, found struct variant `E::E | LL | E::Empty3() => () | ^^^^^^^^^^^ not a tuple struct or tuple variant + | +help: use the struct variant pattern syntax + | +LL | E::Empty3 {} => () + | ~~ error[E0164]: expected tuple struct or tuple variant, found struct variant `XE::XEmpty3` --> $DIR/empty-struct-braces-pat-3.rs:21:9 | LL | XE::XEmpty3() => () | ^^^^^^^^^^^^^ not a tuple struct or tuple variant + | +help: use the struct variant pattern syntax + | +LL | XE::XEmpty3 {} => () + | ~~ error[E0164]: expected tuple struct or tuple variant, found struct variant `E::Empty3` --> $DIR/empty-struct-braces-pat-3.rs:25:9 | LL | E::Empty3(..) => () | ^^^^^^^^^^^^^ not a tuple struct or tuple variant + | +help: use the struct variant pattern syntax + | +LL | E::Empty3 {} => () + | ~~ error[E0164]: expected tuple struct or tuple variant, found struct variant `XE::XEmpty3` --> $DIR/empty-struct-braces-pat-3.rs:29:9 | LL | XE::XEmpty3(..) => () | ^^^^^^^^^^^^^^^ not a tuple struct or tuple variant + | +help: use the struct variant pattern syntax + | +LL | XE::XEmpty3 {} => () + | ~~ error: aborting due to 4 previous errors diff --git a/tests/ui/issues/issue-63983.stderr b/tests/ui/issues/issue-63983.stderr index f90c81116264a..3539732451ce2 100644 --- a/tests/ui/issues/issue-63983.stderr +++ b/tests/ui/issues/issue-63983.stderr @@ -12,6 +12,11 @@ error[E0533]: expected unit struct, unit variant or constant, found struct varia | LL | MyEnum::Struct => "", | ^^^^^^^^^^^^^^ not a unit struct, unit variant or constant + | +help: the struct variant's field is being ignored + | +LL | MyEnum::Struct { s: _ } => "", + | ++++++++ error: aborting due to 2 previous errors diff --git a/tests/ui/parser/recover/recover-from-bad-variant.stderr b/tests/ui/parser/recover/recover-from-bad-variant.stderr index 04968bbdf999d..0339f86951543 100644 --- a/tests/ui/parser/recover/recover-from-bad-variant.stderr +++ b/tests/ui/parser/recover/recover-from-bad-variant.stderr @@ -19,6 +19,11 @@ error[E0164]: expected tuple struct or tuple variant, found struct variant `Enum | LL | Enum::Foo(a, b) => {} | ^^^^^^^^^^^^^^^ not a tuple struct or tuple variant + | +help: the struct variant's fields are being ignored + | +LL | Enum::Foo { a: _, b: _ } => {} + | ~~~~~~~~~~~~~~ error[E0769]: tuple variant `Enum::Bar` written as struct variant --> $DIR/recover-from-bad-variant.rs:12:9 diff --git a/tests/ui/suggestions/issue-84700.stderr b/tests/ui/suggestions/issue-84700.stderr index ac9f5ab0b0cbb..d07055826606d 100644 --- a/tests/ui/suggestions/issue-84700.stderr +++ b/tests/ui/suggestions/issue-84700.stderr @@ -12,6 +12,11 @@ error[E0164]: expected tuple struct or tuple variant, found struct variant `Farm | LL | FarmAnimal::Chicken(_) => "cluck, cluck!".to_string(), | ^^^^^^^^^^^^^^^^^^^^^^ not a tuple struct or tuple variant + | +help: the struct variant's field is being ignored + | +LL | FarmAnimal::Chicken { num_eggs: _ } => "cluck, cluck!".to_string(), + | ~~~~~~~~~~~~~~~ error: aborting due to 2 previous errors diff --git a/tests/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr b/tests/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr index c21c59397c79e..714b4fd7d25f6 100644 --- a/tests/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr +++ b/tests/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr @@ -14,12 +14,22 @@ error[E0533]: expected unit struct, unit variant or constant, found struct varia | LL | let Alias::Braced = panic!(); | ^^^^^^^^^^^^^ not a unit struct, unit variant or constant + | +help: use the struct variant pattern syntax + | +LL | let Alias::Braced {} = panic!(); + | ++ error[E0164]: expected tuple struct or tuple variant, found struct variant `Alias::Braced` --> $DIR/incorrect-variant-form-through-alias-caught.rs:12:9 | LL | let Alias::Braced(..) = panic!(); | ^^^^^^^^^^^^^^^^^ not a tuple struct or tuple variant + | +help: use the struct variant pattern syntax + | +LL | let Alias::Braced {} = panic!(); + | ~~ error[E0618]: expected function, found enum variant `Alias::Unit` --> $DIR/incorrect-variant-form-through-alias-caught.rs:15:5 From 3a693f247b81b4538ff1e634d4cfffa30d0a3cfc Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Sun, 1 Sep 2024 04:55:50 +0000 Subject: [PATCH 011/189] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index c33d9ad86149b..5a435a9f55bd3 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -0d634185dfddefe09047881175f35c65d68dcff1 +43eaa5c6246057b1675f42631967ad500eaf47d5 From b71297f670299f54118de07b2e63af309a80b198 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Sun, 1 Sep 2024 05:04:43 +0000 Subject: [PATCH 012/189] fmt --- src/tools/miri/src/alloc_addresses/mod.rs | 24 ++++++++++++++----- src/tools/miri/src/concurrency/thread.rs | 9 +++++-- src/tools/miri/src/machine.rs | 6 ++--- src/tools/miri/src/shims/native_lib.rs | 7 ++++-- .../tests/native-lib/pass/ptr_read_access.rs | 12 ++++------ 5 files changed, 37 insertions(+), 21 deletions(-) diff --git a/src/tools/miri/src/alloc_addresses/mod.rs b/src/tools/miri/src/alloc_addresses/mod.rs index 76c68add8cdc9..cb3929959f697 100644 --- a/src/tools/miri/src/alloc_addresses/mod.rs +++ b/src/tools/miri/src/alloc_addresses/mod.rs @@ -185,8 +185,11 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { panic!("Miri ran out of memory: cannot create allocation of {size:?} bytes") }); let ptr = prepared_bytes.as_ptr(); - // Store prepared allocation space to be picked up for use later. - global_state.prepared_alloc_bytes.try_insert(alloc_id, prepared_bytes).unwrap(); + // Store prepared allocation space to be picked up for use later. + global_state + .prepared_alloc_bytes + .try_insert(alloc_id, prepared_bytes) + .unwrap(); ptr } else { ecx.get_alloc_bytes_unchecked_raw(alloc_id)? @@ -196,16 +199,19 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { } AllocKind::Function | AllocKind::VTable => { // Allocate some dummy memory to get a unique address for this function/vtable. - let alloc_bytes = MiriAllocBytes::from_bytes(&[0u8; 1], Align::from_bytes(1).unwrap()); + let alloc_bytes = MiriAllocBytes::from_bytes( + &[0u8; 1], + Align::from_bytes(1).unwrap(), + ); // We don't need to expose these bytes as nobody is allowed to access them. let addr = alloc_bytes.as_ptr().addr().try_into().unwrap(); // Leak the underlying memory to ensure it remains unique. std::mem::forget(alloc_bytes); addr } - AllocKind::Dead => unreachable!() + AllocKind::Dead => unreachable!(), } - } else if let Some((reuse_addr, clock)) = global_state.reuse.take_addr( + } else if let Some((reuse_addr, clock)) = global_state.reuse.take_addr( &mut *rng, size, align, @@ -359,7 +365,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // This returns some prepared `MiriAllocBytes`, either because `addr_from_alloc_id` reserved // memory space in the past, or by doing the pre-allocation right upon being called. - fn get_global_alloc_bytes(&self, id: AllocId, kind: MemoryKind, bytes: &[u8], align: Align) -> InterpResult<'tcx, MiriAllocBytes> { + fn get_global_alloc_bytes( + &self, + id: AllocId, + kind: MemoryKind, + bytes: &[u8], + align: Align, + ) -> InterpResult<'tcx, MiriAllocBytes> { let ecx = self.eval_context_ref(); Ok(if ecx.machine.native_lib.is_some() { // In native lib mode, MiriAllocBytes for global allocations are handled via `prepared_alloc_bytes`. diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs index 79f292f696599..306245a843bf4 100644 --- a/src/tools/miri/src/concurrency/thread.rs +++ b/src/tools/miri/src/concurrency/thread.rs @@ -888,8 +888,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } let alloc = this.ctfe_query(|tcx| tcx.eval_static_initializer(def_id))?; // We make a full copy of this allocation. - let mut alloc = - alloc.inner().adjust_from_tcx(&this.tcx, |bytes, align| Ok(MiriAllocBytes::from_bytes(std::borrow::Cow::Borrowed(bytes), align)), |ptr| this.global_root_pointer(ptr))?; + let mut alloc = alloc.inner().adjust_from_tcx( + &this.tcx, + |bytes, align| { + Ok(MiriAllocBytes::from_bytes(std::borrow::Cow::Borrowed(bytes), align)) + }, + |ptr| this.global_root_pointer(ptr), + )?; // This allocation will be deallocated when the thread dies, so it is not in read-only memory. alloc.mutability = Mutability::Mut; // Create a fresh allocation with this content. diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 66c6966d1a6c3..331edf9c7ea31 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -1277,12 +1277,12 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { ) -> InterpResult<'tcx, Cow<'b, Allocation>> { let kind = Self::GLOBAL_KIND.unwrap().into(); - let alloc = alloc.adjust_from_tcx(&ecx.tcx, + let alloc = alloc.adjust_from_tcx( + &ecx.tcx, |bytes, align| ecx.get_global_alloc_bytes(id, kind, bytes, align), |ptr| ecx.global_root_pointer(ptr), )?; - let extra = - Self::init_alloc_extra(ecx, id, kind, alloc.size(), alloc.align)?; + let extra = Self::init_alloc_extra(ecx, id, kind, alloc.size(), alloc.align)?; Ok(Cow::Owned(alloc.with_extra(extra))) } diff --git a/src/tools/miri/src/shims/native_lib.rs b/src/tools/miri/src/shims/native_lib.rs index 25d96fbd7331f..e4998c37f3fe6 100644 --- a/src/tools/miri/src/shims/native_lib.rs +++ b/src/tools/miri/src/shims/native_lib.rs @@ -240,13 +240,16 @@ fn imm_to_carg<'tcx>(v: ImmTy<'tcx>, cx: &impl HasDataLayout) -> InterpResult<'t ty::RawPtr(_, mutability) => { // Arbitrary mutable pointer accesses are not currently supported in Miri. if mutability.is_mut() { - throw_unsup_format!("unsupported mutable pointer type for native call: {}", v.layout.ty); + throw_unsup_format!( + "unsupported mutable pointer type for native call: {}", + v.layout.ty + ); } else { let s = v.to_scalar().to_pointer(cx)?.addr(); // This relies on the `expose_provenance` in `addr_from_alloc_id`. CArg::RawPtr(std::ptr::with_exposed_provenance_mut(s.bytes_usize())) } - }, + } _ => throw_unsup_format!("unsupported argument type for native call: {}", v.layout.ty), }) } diff --git a/src/tools/miri/tests/native-lib/pass/ptr_read_access.rs b/src/tools/miri/tests/native-lib/pass/ptr_read_access.rs index d8e6209839e2a..77a73deddedb8 100644 --- a/src/tools/miri/tests/native-lib/pass/ptr_read_access.rs +++ b/src/tools/miri/tests/native-lib/pass/ptr_read_access.rs @@ -26,7 +26,7 @@ fn test_pointer() { fn test_simple() { #[repr(C)] struct Simple { - field: i32 + field: i32, } extern "C" { @@ -41,7 +41,7 @@ fn test_simple() { // Test function that dereferences nested struct pointers and accesses fields. fn test_nested() { use std::ptr::NonNull; - + #[derive(Debug, PartialEq, Eq)] #[repr(C)] struct Nested { @@ -62,7 +62,6 @@ fn test_nested() { // Test function that dereferences static struct pointers and accesses fields. fn test_static() { - #[repr(C)] struct Static { value: i32, @@ -72,11 +71,8 @@ fn test_static() { extern "C" { fn access_static(n_ptr: *const Static) -> i32; } - - static STATIC: Static = Static { - value: 9001, - recurse: &STATIC, - }; + + static STATIC: Static = Static { value: 9001, recurse: &STATIC }; assert_eq!(unsafe { access_static(&STATIC) }, 9001); } From 53451c2b76169532d5398614c5778c7bc4f68985 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 1 Sep 2024 11:10:13 +0200 Subject: [PATCH 013/189] move addr_from_alloc_id logic into its own function --- src/tools/miri/src/alloc_addresses/mod.rs | 211 +++++++++++----------- 1 file changed, 106 insertions(+), 105 deletions(-) diff --git a/src/tools/miri/src/alloc_addresses/mod.rs b/src/tools/miri/src/alloc_addresses/mod.rs index cb3929959f697..c19a962e6523e 100644 --- a/src/tools/miri/src/alloc_addresses/mod.rs +++ b/src/tools/miri/src/alloc_addresses/mod.rs @@ -5,7 +5,6 @@ mod reuse_pool; use std::cell::RefCell; use std::cmp::max; -use std::collections::hash_map::Entry; use rand::Rng; @@ -151,6 +150,95 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { } } + fn addr_from_alloc_id_uncached( + &self, + global_state: &mut GlobalStateInner, + alloc_id: AllocId, + memory_kind: MemoryKind, + ) -> InterpResult<'tcx, u64> { + let ecx = self.eval_context_ref(); + let mut rng = ecx.machine.rng.borrow_mut(); + let (size, align, kind) = ecx.get_alloc_info(alloc_id); + // This is either called immediately after allocation (and then cached), or when + // adjusting `tcx` pointers (which never get freed). So assert that we are looking + // at a live allocation. This also ensures that we never re-assign an address to an + // allocation that previously had an address, but then was freed and the address + // information was removed. + assert!(!matches!(kind, AllocKind::Dead)); + + // This allocation does not have a base address yet, pick or reuse one. + if ecx.machine.native_lib.is_some() { + // In native lib mode, we use the "real" address of the bytes for this allocation. + // This ensures the interpreted program and native code have the same view of memory. + let base_ptr = match kind { + AllocKind::LiveData => { + if ecx.tcx.try_get_global_alloc(alloc_id).is_some() { + // For new global allocations, we always pre-allocate the memory to be able use the machine address directly. + let prepared_bytes = MiriAllocBytes::zeroed(size, align) + .unwrap_or_else(|| { + panic!("Miri ran out of memory: cannot create allocation of {size:?} bytes") + }); + let ptr = prepared_bytes.as_ptr(); + // Store prepared allocation space to be picked up for use later. + global_state + .prepared_alloc_bytes + .try_insert(alloc_id, prepared_bytes) + .unwrap(); + ptr + } else { + ecx.get_alloc_bytes_unchecked_raw(alloc_id)? + } + } + AllocKind::Function | AllocKind::VTable => { + // Allocate some dummy memory to get a unique address for this function/vtable. + let alloc_bytes = + MiriAllocBytes::from_bytes(&[0u8; 1], Align::from_bytes(1).unwrap()); + let ptr = alloc_bytes.as_ptr(); + // Leak the underlying memory to ensure it remains unique. + std::mem::forget(alloc_bytes); + ptr + } + AllocKind::Dead => unreachable!(), + }; + // Ensure this pointer's provenance is exposed, so that it can be used by FFI code. + return Ok(base_ptr.expose_provenance().try_into().unwrap()); + } + // We are not in native lib mode, so we control the addresses ourselves. + if let Some((reuse_addr, clock)) = + global_state.reuse.take_addr(&mut *rng, size, align, memory_kind, ecx.active_thread()) + { + if let Some(clock) = clock { + ecx.acquire_clock(&clock); + } + Ok(reuse_addr) + } else { + // We have to pick a fresh address. + // Leave some space to the previous allocation, to give it some chance to be less aligned. + // We ensure that `(global_state.next_base_addr + slack) % 16` is uniformly distributed. + let slack = rng.gen_range(0..16); + // From next_base_addr + slack, round up to adjust for alignment. + let base_addr = global_state + .next_base_addr + .checked_add(slack) + .ok_or_else(|| err_exhaust!(AddressSpaceFull))?; + let base_addr = align_addr(base_addr, align.bytes()); + + // Remember next base address. If this allocation is zero-sized, leave a gap of at + // least 1 to avoid two allocations having the same base address. (The logic in + // `alloc_id_from_addr` assumes unique addresses, and different function/vtable pointers + // need to be distinguishable!) + global_state.next_base_addr = base_addr + .checked_add(max(size.bytes(), 1)) + .ok_or_else(|| err_exhaust!(AddressSpaceFull))?; + // Even if `Size` didn't overflow, we might still have filled up the address space. + if global_state.next_base_addr > ecx.target_usize_max() { + throw_exhaust!(AddressSpaceFull); + } + + Ok(base_addr) + } + } + fn addr_from_alloc_id( &self, alloc_id: AllocId, @@ -160,104 +248,16 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { let mut global_state = ecx.machine.alloc_addresses.borrow_mut(); let global_state = &mut *global_state; - Ok(match global_state.base_addr.entry(alloc_id) { - Entry::Occupied(entry) => *entry.get(), - Entry::Vacant(entry) => { - let mut rng = ecx.machine.rng.borrow_mut(); - let (size, align, kind) = ecx.get_alloc_info(alloc_id); - // This is either called immediately after allocation (and then cached), or when - // adjusting `tcx` pointers (which never get freed). So assert that we are looking - // at a live allocation. This also ensures that we never re-assign an address to an - // allocation that previously had an address, but then was freed and the address - // information was removed. - assert!(!matches!(kind, AllocKind::Dead)); - - // This allocation does not have a base address yet, pick or reuse one. - let base_addr = if ecx.machine.native_lib.is_some() { - // In native lib mode, we use the "real" address of the bytes for this allocation. - // This ensures the interpreted program and native code have the same view of memory. - match kind { - AllocKind::LiveData => { - let ptr = if ecx.tcx.try_get_global_alloc(alloc_id).is_some() { - // For new global allocations, we always pre-allocate the memory to be able use the machine address directly. - let prepared_bytes = MiriAllocBytes::zeroed(size, align) - .unwrap_or_else(|| { - panic!("Miri ran out of memory: cannot create allocation of {size:?} bytes") - }); - let ptr = prepared_bytes.as_ptr(); - // Store prepared allocation space to be picked up for use later. - global_state - .prepared_alloc_bytes - .try_insert(alloc_id, prepared_bytes) - .unwrap(); - ptr - } else { - ecx.get_alloc_bytes_unchecked_raw(alloc_id)? - }; - // Ensure this pointer's provenance is exposed, so that it can be used by FFI code. - ptr.expose_provenance().try_into().unwrap() - } - AllocKind::Function | AllocKind::VTable => { - // Allocate some dummy memory to get a unique address for this function/vtable. - let alloc_bytes = MiriAllocBytes::from_bytes( - &[0u8; 1], - Align::from_bytes(1).unwrap(), - ); - // We don't need to expose these bytes as nobody is allowed to access them. - let addr = alloc_bytes.as_ptr().addr().try_into().unwrap(); - // Leak the underlying memory to ensure it remains unique. - std::mem::forget(alloc_bytes); - addr - } - AllocKind::Dead => unreachable!(), - } - } else if let Some((reuse_addr, clock)) = global_state.reuse.take_addr( - &mut *rng, - size, - align, - memory_kind, - ecx.active_thread(), - ) { - if let Some(clock) = clock { - ecx.acquire_clock(&clock); - } - reuse_addr - } else { - // We have to pick a fresh address. - // Leave some space to the previous allocation, to give it some chance to be less aligned. - // We ensure that `(global_state.next_base_addr + slack) % 16` is uniformly distributed. - let slack = rng.gen_range(0..16); - // From next_base_addr + slack, round up to adjust for alignment. - let base_addr = global_state - .next_base_addr - .checked_add(slack) - .ok_or_else(|| err_exhaust!(AddressSpaceFull))?; - let base_addr = align_addr(base_addr, align.bytes()); - - // Remember next base address. If this allocation is zero-sized, leave a gap - // of at least 1 to avoid two allocations having the same base address. - // (The logic in `alloc_id_from_addr` assumes unique addresses, and different - // function/vtable pointers need to be distinguishable!) - global_state.next_base_addr = base_addr - .checked_add(max(size.bytes(), 1)) - .ok_or_else(|| err_exhaust!(AddressSpaceFull))?; - // Even if `Size` didn't overflow, we might still have filled up the address space. - if global_state.next_base_addr > ecx.target_usize_max() { - throw_exhaust!(AddressSpaceFull); - } - - base_addr - }; - trace!( - "Assigning base address {:#x} to allocation {:?} (size: {}, align: {})", - base_addr, - alloc_id, - size.bytes(), - align.bytes(), - ); + match global_state.base_addr.get(&alloc_id) { + Some(&addr) => Ok(addr), + None => { + // First time we're looking for the absolute address of this allocation. + let base_addr = + self.addr_from_alloc_id_uncached(global_state, alloc_id, memory_kind)?; + trace!("Assigning base address {:#x} to allocation {:?}", base_addr, alloc_id); // Store address in cache. - entry.insert(base_addr); + global_state.base_addr.try_insert(alloc_id, base_addr).unwrap(); // Also maintain the opposite mapping in `int_to_ptr_map`, ensuring we keep it sorted. // We have a fast-path for the common case that this address is bigger than all previous ones. @@ -275,9 +275,9 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { }; global_state.int_to_ptr_map.insert(pos, (base_addr, alloc_id)); - base_addr + Ok(base_addr) } - }) + } } } @@ -373,14 +373,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { align: Align, ) -> InterpResult<'tcx, MiriAllocBytes> { let ecx = self.eval_context_ref(); - Ok(if ecx.machine.native_lib.is_some() { + if ecx.machine.native_lib.is_some() { // In native lib mode, MiriAllocBytes for global allocations are handled via `prepared_alloc_bytes`. - // This additional call ensures that some `MiriAllocBytes` are always prepared. + // This additional call ensures that some `MiriAllocBytes` are always prepared, just in case + // this function gets called before the first time `addr_from_alloc_id` gets called. ecx.addr_from_alloc_id(id, kind)?; - let mut global_state = ecx.machine.alloc_addresses.borrow_mut(); // The memory we need here will have already been allocated during an earlier call to // `addr_from_alloc_id` for this allocation. So don't create a new `MiriAllocBytes` here, instead // fetch the previously prepared bytes from `prepared_alloc_bytes`. + let mut global_state = ecx.machine.alloc_addresses.borrow_mut(); let mut prepared_alloc_bytes = global_state .prepared_alloc_bytes .remove(&id) @@ -390,10 +391,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { assert_eq!(prepared_alloc_bytes.len(), bytes.len()); // Copy allocation contents into prepared memory. prepared_alloc_bytes.copy_from_slice(bytes); - prepared_alloc_bytes + Ok(prepared_alloc_bytes) } else { - MiriAllocBytes::from_bytes(std::borrow::Cow::Borrowed(&*bytes), align) - }) + Ok(MiriAllocBytes::from_bytes(std::borrow::Cow::Borrowed(bytes), align)) + } } /// When a pointer is used for a memory access, this computes where in which allocation the From 4ee58db2f10d370f8e7ccc4b1409440342f01c3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Sun, 25 Aug 2024 13:33:50 +0200 Subject: [PATCH 014/189] Upgrade CI's mingw-w64 toolchain --- src/ci/scripts/install-mingw.sh | 4 ++-- tests/debuginfo/by-value-non-immediate-argument.rs | 1 + tests/debuginfo/method-on-enum.rs | 2 ++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/ci/scripts/install-mingw.sh b/src/ci/scripts/install-mingw.sh index 31aa3785bc369..91eab2e7a0816 100755 --- a/src/ci/scripts/install-mingw.sh +++ b/src/ci/scripts/install-mingw.sh @@ -6,8 +6,8 @@ IFS=$'\n\t' source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" -MINGW_ARCHIVE_32="i686-12.2.0-release-posix-dwarf-rt_v10-rev0.7z" -MINGW_ARCHIVE_64="x86_64-12.2.0-release-posix-seh-rt_v10-rev0.7z" +MINGW_ARCHIVE_32="i686-14.1.0-release-posix-dwarf-msvcrt-rt_v12-rev0.7z" +MINGW_ARCHIVE_64="x86_64-14.1.0-release-posix-seh-msvcrt-rt_v12-rev0.7z" if isWindows && isKnownToBeMingwBuild; then case "${CI_JOB_NAME}" in diff --git a/tests/debuginfo/by-value-non-immediate-argument.rs b/tests/debuginfo/by-value-non-immediate-argument.rs index f0a39a45195a1..192f6efe7db6c 100644 --- a/tests/debuginfo/by-value-non-immediate-argument.rs +++ b/tests/debuginfo/by-value-non-immediate-argument.rs @@ -1,6 +1,7 @@ //@ min-lldb-version: 1800 //@ min-gdb-version: 13.0 //@ compile-flags:-g +//@ ignore-windows-gnu: #128973 // === GDB TESTS =================================================================================== diff --git a/tests/debuginfo/method-on-enum.rs b/tests/debuginfo/method-on-enum.rs index a570144450d70..754b4a2dc26c5 100644 --- a/tests/debuginfo/method-on-enum.rs +++ b/tests/debuginfo/method-on-enum.rs @@ -3,6 +3,8 @@ //@ compile-flags:-g +//@ ignore-windows-gnu: #128973 + // === GDB TESTS =================================================================================== // gdb-command:run From f2696ab4d3095bb6ad6197e55855ebdf00f50b80 Mon Sep 17 00:00:00 2001 From: schvv31n Date: Mon, 5 Aug 2024 00:44:35 +0100 Subject: [PATCH 015/189] rustdoc: normalise type/field names in rustdoc-json-types/jsondoclint --- src/librustdoc/json/conversions.rs | 102 +++++++++--------- src/librustdoc/json/mod.rs | 4 +- src/rustdoc-json-types/lib.rs | 86 ++++++++------- src/rustdoc-json-types/tests.rs | 4 +- src/tools/jsondoclint/src/item_kind.rs | 22 ++-- src/tools/jsondoclint/src/validator.rs | 49 ++++----- tests/rustdoc-json/assoc_items.rs | 8 +- tests/rustdoc-json/blanket_impls.rs | 4 +- tests/rustdoc-json/enums/kind.rs | 4 +- .../rustdoc-json/enums/struct_field_hidden.rs | 2 +- tests/rustdoc-json/enums/use_glob.rs | 6 +- tests/rustdoc-json/enums/use_variant.rs | 4 +- .../rustdoc-json/enums/use_variant_foreign.rs | 2 +- tests/rustdoc-json/fn_pointer/generics.rs | 8 +- tests/rustdoc-json/fn_pointer/qualifiers.rs | 12 +-- tests/rustdoc-json/fns/async_return.rs | 24 ++--- tests/rustdoc-json/fns/extern_c_variadic.rs | 4 +- tests/rustdoc-json/fns/generic_args.rs | 22 ++-- tests/rustdoc-json/fns/generic_returns.rs | 6 +- tests/rustdoc-json/fns/generics.rs | 12 +-- tests/rustdoc-json/fns/pattern_arg.rs | 4 +- tests/rustdoc-json/fns/qualifiers.rs | 36 +++---- tests/rustdoc-json/fns/return_type_alias.rs | 2 +- .../generic-associated-types/gats.rs | 16 +-- tests/rustdoc-json/glob_import.rs | 2 +- .../rustdoc-json/impl-trait-in-assoc-type.rs | 10 +- .../impl-trait-precise-capturing.rs | 6 +- tests/rustdoc-json/impls/auto.rs | 2 +- tests/rustdoc-json/impls/foreign_for_local.rs | 2 +- .../rustdoc-json/impls/import_from_private.rs | 4 +- tests/rustdoc-json/impls/local_for_foreign.rs | 2 +- tests/rustdoc-json/lifetime/longest.rs | 24 ++--- tests/rustdoc-json/lifetime/outlives.rs | 10 +- tests/rustdoc-json/methods/qualifiers.rs | 36 +++---- tests/rustdoc-json/nested.rs | 10 +- tests/rustdoc-json/non_lifetime_binders.rs | 2 +- .../rustdoc-json/primitives/use_primitive.rs | 4 +- .../reexport/extern_crate_glob.rs | 4 +- tests/rustdoc-json/reexport/glob_collision.rs | 8 +- tests/rustdoc-json/reexport/glob_empty_mod.rs | 2 +- tests/rustdoc-json/reexport/glob_extern.rs | 6 +- tests/rustdoc-json/reexport/glob_private.rs | 4 +- .../rustdoc-json/reexport/in_root_and_mod.rs | 4 +- .../reexport/in_root_and_mod_pub.rs | 4 +- .../rustdoc-json/reexport/mod_not_included.rs | 2 +- .../reexport/private_twice_one_inline.rs | 6 +- .../reexport/private_two_names.rs | 8 +- .../reexport/reexport_of_hidden.rs | 2 +- tests/rustdoc-json/reexport/rename_private.rs | 2 +- tests/rustdoc-json/reexport/rename_public.rs | 4 +- .../reexport/same_name_different_types.rs | 8 +- .../same_type_reexported_more_than_once.rs | 4 +- tests/rustdoc-json/reexport/simple_private.rs | 6 +- tests/rustdoc-json/reexport/simple_public.rs | 2 +- tests/rustdoc-json/return_private.rs | 2 +- tests/rustdoc-json/structs/plain_all_pub.rs | 2 +- .../rustdoc-json/structs/plain_doc_hidden.rs | 2 +- tests/rustdoc-json/structs/plain_empty.rs | 2 +- tests/rustdoc-json/structs/plain_pub_priv.rs | 2 +- tests/rustdoc-json/structs/with_generics.rs | 2 +- tests/rustdoc-json/structs/with_primitives.rs | 2 +- tests/rustdoc-json/trait_alias.rs | 4 +- tests/rustdoc-json/traits/self.rs | 30 +++--- tests/rustdoc-json/traits/trait_alias.rs | 4 +- tests/rustdoc-json/type/dyn.rs | 4 +- tests/rustdoc-json/type/extern.rs | 2 +- tests/rustdoc-json/type/fn_lifetime.rs | 12 +-- tests/rustdoc-json/type/generic_default.rs | 2 +- tests/rustdoc-json/type/hrtb.rs | 8 +- .../type/inherent_associated_type.rs | 8 +- .../type/inherent_associated_type_bound.rs | 16 +-- .../inherent_associated_type_projections.rs | 12 +-- tests/rustdoc-json/type_alias.rs | 4 +- tests/rustdoc-json/unions/union.rs | 4 +- 74 files changed, 382 insertions(+), 375 deletions(-) diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index b97d710c007ce..59e4b072a12d2 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -156,7 +156,7 @@ impl FromWithTcx for GenericArgs { match args { AngleBracketed { args, constraints } => GenericArgs::AngleBracketed { args: args.into_vec().into_tcx(tcx), - bindings: constraints.into_tcx(tcx), + constraints: constraints.into_tcx(tcx), }, Parenthesized { inputs, output } => GenericArgs::Parenthesized { inputs: inputs.into_vec().into_tcx(tcx), @@ -198,9 +198,9 @@ impl FromWithTcx for Constant { } } -impl FromWithTcx for TypeBinding { +impl FromWithTcx for AssocItemConstraint { fn from_tcx(constraint: clean::AssocItemConstraint, tcx: TyCtxt<'_>) -> Self { - TypeBinding { + AssocItemConstraint { name: constraint.assoc.name.to_string(), args: constraint.assoc.args.into_tcx(tcx), binding: constraint.kind.into_tcx(tcx), @@ -208,12 +208,12 @@ impl FromWithTcx for TypeBinding { } } -impl FromWithTcx for TypeBindingKind { +impl FromWithTcx for AssocItemConstraintKind { fn from_tcx(kind: clean::AssocItemConstraintKind, tcx: TyCtxt<'_>) -> Self { use clean::AssocItemConstraintKind::*; match kind { - Equality { term } => TypeBindingKind::Equality(term.into_tcx(tcx)), - Bound { bounds } => TypeBindingKind::Constraint(bounds.into_tcx(tcx)), + Equality { term } => AssocItemConstraintKind::Equality(term.into_tcx(tcx)), + Bound { bounds } => AssocItemConstraintKind::Constraint(bounds.into_tcx(tcx)), } } } @@ -314,7 +314,7 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum { ModuleItem(m) => { ItemEnum::Module(Module { is_crate, items: ids(m.items, tcx), is_stripped: false }) } - ImportItem(i) => ItemEnum::Import(i.into_tcx(tcx)), + ImportItem(i) => ItemEnum::Use(i.into_tcx(tcx)), StructItem(s) => ItemEnum::Struct(s.into_tcx(tcx)), UnionItem(u) => ItemEnum::Union(u.into_tcx(tcx)), StructFieldItem(f) => ItemEnum::StructField(f.into_tcx(tcx)), @@ -331,7 +331,7 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum { ImplItem(i) => ItemEnum::Impl((*i).into_tcx(tcx)), StaticItem(s) => ItemEnum::Static(s.into_tcx(tcx)), ForeignStaticItem(s, _) => ItemEnum::Static(s.into_tcx(tcx)), - ForeignTypeItem => ItemEnum::ForeignType, + ForeignTypeItem => ItemEnum::ExternType, TypeAliasItem(t) => ItemEnum::TypeAlias(t.into_tcx(tcx)), // FIXME(generic_const_items): Add support for generic free consts ConstantItem(ci) => { @@ -347,21 +347,19 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum { } // FIXME(generic_const_items): Add support for generic associated consts. TyAssocConstItem(_generics, ty) => { - ItemEnum::AssocConst { type_: (*ty).into_tcx(tcx), default: None } + ItemEnum::AssocConst { type_: (*ty).into_tcx(tcx), value: None } } // FIXME(generic_const_items): Add support for generic associated consts. AssocConstItem(ci) => { - ItemEnum::AssocConst { type_: ci.type_.into_tcx(tcx), default: Some(ci.kind.expr(tcx)) } + ItemEnum::AssocConst { type_: ci.type_.into_tcx(tcx), value: Some(ci.kind.expr(tcx)) } + } + TyAssocTypeItem(g, b) => { + ItemEnum::AssocType { generics: g.into_tcx(tcx), bounds: b.into_tcx(tcx), type_: None } } - TyAssocTypeItem(g, b) => ItemEnum::AssocType { - generics: g.into_tcx(tcx), - bounds: b.into_tcx(tcx), - default: None, - }, AssocTypeItem(t, b) => ItemEnum::AssocType { generics: t.generics.into_tcx(tcx), bounds: b.into_tcx(tcx), - default: Some(t.item_type.unwrap_or(t.type_).into_tcx(tcx)), + type_: Some(t.item_type.unwrap_or(t.type_).into_tcx(tcx)), }, // `convert_item` early returns `None` for stripped items and keywords. KeywordItem => unreachable!(), @@ -385,7 +383,7 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum { impl FromWithTcx for Struct { fn from_tcx(struct_: clean::Struct, tcx: TyCtxt<'_>) -> Self { - let fields_stripped = struct_.has_stripped_entries(); + let has_stripped_fields = struct_.has_stripped_entries(); let clean::Struct { ctor_kind, generics, fields } = struct_; let kind = match ctor_kind { @@ -394,7 +392,7 @@ impl FromWithTcx for Struct { assert!(fields.is_empty()); StructKind::Unit } - None => StructKind::Plain { fields: ids(fields, tcx), fields_stripped }, + None => StructKind::Plain { fields: ids(fields, tcx), has_stripped_fields }, }; Struct { @@ -407,22 +405,22 @@ impl FromWithTcx for Struct { impl FromWithTcx for Union { fn from_tcx(union_: clean::Union, tcx: TyCtxt<'_>) -> Self { - let fields_stripped = union_.has_stripped_entries(); + let has_stripped_fields = union_.has_stripped_entries(); let clean::Union { generics, fields } = union_; Union { generics: generics.into_tcx(tcx), - fields_stripped, + has_stripped_fields, fields: ids(fields, tcx), impls: Vec::new(), // Added in JsonRenderer::item } } } -pub(crate) fn from_fn_header(header: &rustc_hir::FnHeader) -> Header { - Header { - async_: header.is_async(), - const_: header.is_const(), - unsafe_: header.is_unsafe(), +pub(crate) fn from_fn_header(header: &rustc_hir::FnHeader) -> FunctionHeader { + FunctionHeader { + is_async: header.is_async(), + is_const: header.is_const(), + is_unsafe: header.is_unsafe(), abi: convert_abi(header.abi), } } @@ -474,7 +472,7 @@ impl FromWithTcx for GenericParamDefKind { Type { bounds, default, synthetic } => GenericParamDefKind::Type { bounds: bounds.into_tcx(tcx), default: default.map(|x| (*x).into_tcx(tcx)), - synthetic, + is_synthetic: synthetic, }, Const { ty, default, synthetic: _ } => GenericParamDefKind::Const { type_: (*ty).into_tcx(tcx), @@ -508,7 +506,7 @@ impl FromWithTcx for WherePredicate { .map(|bound| bound.into_tcx(tcx)) .collect(), default: default.map(|ty| (*ty).into_tcx(tcx)), - synthetic, + is_synthetic: synthetic, } } clean::GenericParamDefKind::Const { ty, default, synthetic: _ } => { @@ -602,12 +600,12 @@ impl FromWithTcx for Type { ImplTrait(g) => Type::ImplTrait(g.into_tcx(tcx)), Infer => Type::Infer, RawPointer(mutability, type_) => Type::RawPointer { - mutable: mutability == ast::Mutability::Mut, + is_mutable: mutability == ast::Mutability::Mut, type_: Box::new((*type_).into_tcx(tcx)), }, BorrowedRef { lifetime, mutability, type_ } => Type::BorrowedRef { lifetime: lifetime.map(convert_lifetime), - mutable: mutability == ast::Mutability::Mut, + is_mutable: mutability == ast::Mutability::Mut, type_: Box::new((*type_).into_tcx(tcx)), }, QPath(box clean::QPathData { assoc, self_type, trait_, .. }) => Type::QualifiedPath { @@ -643,29 +641,29 @@ impl FromWithTcx for FunctionPointer { fn from_tcx(bare_decl: clean::BareFunctionDecl, tcx: TyCtxt<'_>) -> Self { let clean::BareFunctionDecl { safety, generic_params, decl, abi } = bare_decl; FunctionPointer { - header: Header { - unsafe_: matches!(safety, rustc_hir::Safety::Unsafe), - const_: false, - async_: false, + header: FunctionHeader { + is_unsafe: matches!(safety, rustc_hir::Safety::Unsafe), + is_const: false, + is_async: false, abi: convert_abi(abi), }, generic_params: generic_params.into_tcx(tcx), - decl: decl.into_tcx(tcx), + sig: decl.into_tcx(tcx), } } } -impl FromWithTcx for FnDecl { +impl FromWithTcx for FunctionSignature { fn from_tcx(decl: clean::FnDecl, tcx: TyCtxt<'_>) -> Self { let clean::FnDecl { inputs, output, c_variadic } = decl; - FnDecl { + FunctionSignature { inputs: inputs .values .into_iter() .map(|arg| (arg.name.to_string(), arg.type_.into_tcx(tcx))) .collect(), output: if output.is_unit() { None } else { Some(output.into_tcx(tcx)) }, - c_variadic, + is_c_variadic: c_variadic, } } } @@ -702,12 +700,12 @@ impl FromWithTcx for Impl { let provided_trait_methods = impl_.provided_trait_methods(tcx); let clean::Impl { safety, generics, trait_, for_, items, polarity, kind } = impl_; // FIXME: use something like ImplKind in JSON? - let (synthetic, blanket_impl) = match kind { + let (is_synthetic, blanket_impl) = match kind { clean::ImplKind::Normal | clean::ImplKind::FakeVariadic => (false, None), clean::ImplKind::Auto => (true, None), clean::ImplKind::Blanket(ty) => (false, Some(*ty)), }; - let negative_polarity = match polarity { + let is_negative = match polarity { ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => false, ty::ImplPolarity::Negative => true, }; @@ -721,8 +719,8 @@ impl FromWithTcx for Impl { trait_: trait_.map(|path| path.into_tcx(tcx)), for_: for_.into_tcx(tcx), items: ids(items, tcx), - negative: negative_polarity, - synthetic, + is_negative, + is_synthetic, blanket_impl: blanket_impl.map(|x| x.into_tcx(tcx)), } } @@ -736,7 +734,7 @@ pub(crate) fn from_function( ) -> Function { let clean::Function { decl, generics } = *function; Function { - decl: decl.into_tcx(tcx), + sig: decl.into_tcx(tcx), generics: generics.into_tcx(tcx), header: from_fn_header(&header), has_body, @@ -745,11 +743,11 @@ pub(crate) fn from_function( impl FromWithTcx for Enum { fn from_tcx(enum_: clean::Enum, tcx: TyCtxt<'_>) -> Self { - let variants_stripped = enum_.has_stripped_entries(); + let has_stripped_variants = enum_.has_stripped_entries(); let clean::Enum { variants, generics } = enum_; Enum { generics: generics.into_tcx(tcx), - variants_stripped, + has_stripped_variants, variants: ids(variants, tcx), impls: Vec::new(), // Added in JsonRenderer::item } @@ -766,7 +764,7 @@ impl FromWithTcx for Variant { CLike => VariantKind::Plain, Tuple(fields) => VariantKind::Tuple(ids_keeping_stripped(fields, tcx)), Struct(s) => VariantKind::Struct { - fields_stripped: s.has_stripped_entries(), + has_stripped_fields: s.has_stripped_entries(), fields: ids(s.fields, tcx), }, }; @@ -787,21 +785,21 @@ impl FromWithTcx for Discriminant { } } -impl FromWithTcx for Import { +impl FromWithTcx for Use { fn from_tcx(import: clean::Import, tcx: TyCtxt<'_>) -> Self { use clean::ImportKind::*; - let (name, glob) = match import.kind { + let (name, is_glob) = match import.kind { Simple(s) => (s.to_string(), false), Glob => ( import.source.path.last_opt().unwrap_or_else(|| Symbol::intern("*")).to_string(), true, ), }; - Import { + Use { source: import.source.path.whole_name(), name, id: import.source.did.map(ItemId::from).map(|i| id_from_item_default(i, tcx)), - glob, + is_glob, } } } @@ -835,7 +833,7 @@ impl FromWithTcx for Static { fn from_tcx(stat: clean::Static, tcx: TyCtxt<'_>) -> Self { Static { type_: (*stat.type_).into_tcx(tcx), - mutable: stat.mutability == ast::Mutability::Mut, + is_mutable: stat.mutability == ast::Mutability::Mut, expr: stat .expr .map(|e| rendered_const(tcx, tcx.hir().body(e), tcx.hir().body_owner_def_id(e))) @@ -856,7 +854,7 @@ impl FromWithTcx for ItemKind { match kind { Module => ItemKind::Module, ExternCrate => ItemKind::ExternCrate, - Import => ItemKind::Import, + Import => ItemKind::Use, Struct => ItemKind::Struct, Union => ItemKind::Union, Enum => ItemKind::Enum, @@ -872,7 +870,7 @@ impl FromWithTcx for ItemKind { Primitive => ItemKind::Primitive, AssocConst => ItemKind::AssocConst, AssocType => ItemKind::AssocType, - ForeignType => ItemKind::ForeignType, + ForeignType => ItemKind::ExternType, Keyword => ItemKind::Keyword, TraitAlias => ItemKind::TraitAlias, ProcAttribute => ItemKind::ProcAttribute, diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index 1b2d61a763797..03a012864efd3 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -197,7 +197,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { types::ItemEnum::Function(_) | types::ItemEnum::Module(_) - | types::ItemEnum::Import(_) + | types::ItemEnum::Use(_) | types::ItemEnum::AssocConst { .. } | types::ItemEnum::AssocType { .. } => true, types::ItemEnum::ExternCrate { .. } @@ -208,7 +208,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { | types::ItemEnum::TypeAlias(_) | types::ItemEnum::Constant { .. } | types::ItemEnum::Static(_) - | types::ItemEnum::ForeignType + | types::ItemEnum::ExternType | types::ItemEnum::Macro(_) | types::ItemEnum::ProcMacro(_) => false, }; diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index 40a90c1a56504..ef21779b09931 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -13,7 +13,7 @@ use serde::{Deserialize, Serialize}; /// This integer is incremented with every breaking change to the API, /// and is returned along with the JSON blob as [`Crate::format_version`]. /// Consuming code should assert that this value matches the format version(s) that it supports. -pub const FORMAT_VERSION: u32 = 33; +pub const FORMAT_VERSION: u32 = 34; /// The root of the emitted JSON blob. /// @@ -194,7 +194,7 @@ pub enum GenericArgs { /// ``` args: Vec, /// Associated type or constant bindings (e.g. `Item=i32` or `Item: Clone`) for this type. - bindings: Vec, + constraints: Vec, }, /// `Fn(A, B) -> C` Parenthesized { @@ -258,19 +258,19 @@ pub struct Constant { /// ^^^^^^^^^^ ^^^^^^^^^^^^^^^ /// ``` #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct TypeBinding { +pub struct AssocItemConstraint { /// The name of the associated type/constant. pub name: String, /// Arguments provided to the associated type/constant. pub args: GenericArgs, /// The kind of bound applied to the associated type/constant. - pub binding: TypeBindingKind, + pub binding: AssocItemConstraintKind, } /// The way in which an associate type/constant is bound. #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] -pub enum TypeBindingKind { +pub enum AssocItemConstraintKind { /// The required value/type is specified exactly. e.g. /// ```text /// Iterator @@ -311,7 +311,7 @@ pub enum ItemKind { /// A crate imported via the `extern crate` syntax. ExternCrate, /// An import of 1 or more items into scope, using the `use` keyword. - Import, + Use, /// A `struct` declaration. Struct, /// A field of a struct. @@ -341,7 +341,7 @@ pub enum ItemKind { /// `type`s from an `extern` block. /// /// See [the tracking issue](https://github.com/rust-lang/rust/issues/43467) - ForeignType, + ExternType, /// A macro declaration. /// /// Corresponds to either `ItemEnum::Macro(_)` @@ -386,7 +386,7 @@ pub enum ItemEnum { rename: Option, }, /// An import of 1 or more items into scope, using the `use` keyword. - Import(Import), + Use(Use), /// A `union` declaration. Union(Union), @@ -429,7 +429,7 @@ pub enum ItemEnum { /// `type`s from an `extern` block. /// /// See [the tracking issue](https://github.com/rust-lang/rust/issues/43467) - ForeignType, + ExternType, /// A macro_rules! declarative macro. Contains a single string with the source /// representation of the macro with the patterns stripped. @@ -447,12 +447,19 @@ pub enum ItemEnum { /// The type of the constant. #[serde(rename = "type")] type_: Type, - /// The stringified expression for the default value, if provided, e.g. + /// Inside a trait declaration, this is the default value for the associated constant, + /// if provided. + /// Inside an `impl` block, this is the value assigned to the associated constant, + /// and will always be present. + /// + /// The representation is implementation-defined and not guaranteed to be representative of + /// either the resulting value or of the source code. + /// /// ```rust /// const X: usize = 640 * 1024; /// // ^^^^^^^^^^ /// ``` - default: Option, + value: Option, }, /// An associated type of a trait or a type. AssocType { @@ -467,12 +474,16 @@ pub enum ItemEnum { /// } /// ``` bounds: Vec, - /// The default for this type, if provided, e.g. + /// Inside a trait declaration, this is the default for the associated type, if provided. + /// Inside an impl block, this is the type assigned to the associated type, and will always + /// be present. + /// /// ```rust /// type X = usize; /// // ^^^^^ /// ``` - default: Option, + #[serde(rename = "type")] + type_: Option, }, } @@ -497,7 +508,7 @@ pub struct Union { /// The generic parameters and where clauses on this union. pub generics: Generics, /// Whether any fields have been removed from the result, due to being private or hidden. - pub fields_stripped: bool, + pub has_stripped_fields: bool, /// The list of fields in the union. /// /// All of the corresponding [`Item`]s are of kind [`ItemEnum::StructField`]. @@ -554,7 +565,7 @@ pub enum StructKind { /// All of the corresponding [`Item`]s are of kind [`ItemEnum::StructField`]. fields: Vec, /// Whether any fields have been removed from the result, due to being private or hidden. - fields_stripped: bool, + has_stripped_fields: bool, }, } @@ -564,7 +575,7 @@ pub struct Enum { /// Information about the type parameters and `where` clauses of the enum. pub generics: Generics, /// Whether any variants have been removed from the result, due to being private or hidden. - pub variants_stripped: bool, + pub has_stripped_variants: bool, /// The list of variants in the enum. /// /// All of the corresponding [`Item`]s are of kind [`ItemEnum::Variant`] @@ -621,7 +632,7 @@ pub enum VariantKind { /// All of the corresponding [`Item`]s are of kind [`ItemEnum::Variant`]. fields: Vec, /// Whether any variants have been removed from the result, due to being private or hidden. - fields_stripped: bool, + has_stripped_fields: bool, }, } @@ -645,16 +656,13 @@ pub struct Discriminant { /// A set of fundamental properties of a function. #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct Header { +pub struct FunctionHeader { /// Is this function marked as `const`? - #[serde(rename = "const")] - pub const_: bool, + pub is_const: bool, /// Is this function unsafe? - #[serde(rename = "unsafe")] - pub unsafe_: bool, + pub is_unsafe: bool, /// Is this function async? - #[serde(rename = "async")] - pub async_: bool, + pub is_async: bool, /// The ABI used by the function. pub abi: Abi, } @@ -697,11 +705,11 @@ pub enum Abi { #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Function { /// Information about the function signature, or declaration. - pub decl: FnDecl, + pub sig: FunctionSignature, /// Information about the function’s type parameters and `where` clauses. pub generics: Generics, /// Information about core properties of the function, e.g. whether it's `const`, its ABI, etc. - pub header: Header, + pub header: FunctionHeader, /// Whether the function has a body, i.e. an implementation. pub has_body: bool, } @@ -784,7 +792,7 @@ pub enum GenericParamDefKind { /// In this example, the generic parameter named `impl Trait` (and which /// is bound by `Trait`) is synthetic, because it was not originally in /// the Rust source text. - synthetic: bool, + is_synthetic: bool, }, /// Denotes a constant parameter. @@ -894,7 +902,7 @@ pub enum TraitBoundModifier { } /// Either a type or a constant, usually stored as the right-hand side of an equation in places like -/// [`TypeBinding`] +/// [`AssocItemConstraint`] #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum Term { @@ -963,7 +971,7 @@ pub enum Type { /// A raw pointer type, e.g. `*mut u32`, `*const u8`, etc. RawPointer { /// This is `true` for `*mut _` and `false` for `*const _`. - mutable: bool, + is_mutable: bool, /// The type of the pointee. #[serde(rename = "type")] type_: Box, @@ -973,7 +981,7 @@ pub enum Type { /// The name of the lifetime of the reference, if provided. lifetime: Option, /// This is `true` for `&mut i32` and `false` for `&i32` - mutable: bool, + is_mutable: bool, /// The type of the pointee, e.g. the `i32` in `&'a mut i32` #[serde(rename = "type")] type_: Box, @@ -1036,7 +1044,7 @@ pub struct Path { #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct FunctionPointer { /// The signature of the function. - pub decl: FnDecl, + pub sig: FunctionSignature, /// Used for Higher-Rank Trait Bounds (HRTBs) /// /// ```ignore (incomplete expression) @@ -1045,12 +1053,12 @@ pub struct FunctionPointer { /// ``` pub generic_params: Vec, /// The core properties of the function, such as the ABI it conforms to, whether it's unsafe, etc. - pub header: Header, + pub header: FunctionHeader, } /// The signature of a function. #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct FnDecl { +pub struct FunctionSignature { /// List of argument names and their type. /// /// Note that not all names will be valid identifiers, as some of @@ -1063,7 +1071,7 @@ pub struct FnDecl { /// ```ignore (incomplete code) /// fn printf(fmt: &str, ...); /// ``` - pub c_variadic: bool, + pub is_c_variadic: bool, } /// A `trait` declaration. @@ -1127,10 +1135,10 @@ pub struct Impl { /// The list of associated items contained in this impl block. pub items: Vec, /// Whether this is a negative impl (e.g. `!Sized` or `!Send`). - pub negative: bool, + pub is_negative: bool, /// Whether this is an impl that’s implied by the compiler /// (for autotraits, e.g. `Send` or `Sync`). - pub synthetic: bool, + pub is_synthetic: bool, // FIXME: document this pub blanket_impl: Option, } @@ -1138,7 +1146,7 @@ pub struct Impl { /// A `use` statement. #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] -pub struct Import { +pub struct Use { /// The full path being imported. pub source: String, /// May be different from the last segment of `source` when renaming imports: @@ -1150,7 +1158,7 @@ pub struct Import { /// ``` pub id: Option, /// Whether this statement is a wildcard `use`, e.g. `use source::*;` - pub glob: bool, + pub is_glob: bool, } /// A procedural macro. @@ -1205,7 +1213,7 @@ pub struct Static { #[serde(rename = "type")] pub type_: Type, /// This is `true` for mutable statics, declared as `static mut X: T = f();` - pub mutable: bool, + pub is_mutable: bool, /// The stringified expression for the initial value. /// /// It's not guaranteed that it'll match the actual source code for the initial value. diff --git a/src/rustdoc-json-types/tests.rs b/src/rustdoc-json-types/tests.rs index 1126d5f786f4d..b9363fcf1b714 100644 --- a/src/rustdoc-json-types/tests.rs +++ b/src/rustdoc-json-types/tests.rs @@ -4,7 +4,7 @@ use super::*; fn test_struct_info_roundtrip() { let s = ItemEnum::Struct(Struct { generics: Generics { params: vec![], where_predicates: vec![] }, - kind: StructKind::Plain { fields: vec![], fields_stripped: false }, + kind: StructKind::Plain { fields: vec![], has_stripped_fields: false }, impls: vec![], }); @@ -23,7 +23,7 @@ fn test_struct_info_roundtrip() { fn test_union_info_roundtrip() { let u = ItemEnum::Union(Union { generics: Generics { params: vec![], where_predicates: vec![] }, - fields_stripped: false, + has_stripped_fields: false, fields: vec![], impls: vec![], }); diff --git a/src/tools/jsondoclint/src/item_kind.rs b/src/tools/jsondoclint/src/item_kind.rs index 7d6ec475badd4..51146831efa40 100644 --- a/src/tools/jsondoclint/src/item_kind.rs +++ b/src/tools/jsondoclint/src/item_kind.rs @@ -5,7 +5,7 @@ use rustdoc_json_types::{Item, ItemEnum, ItemKind, ItemSummary}; pub(crate) enum Kind { Module, ExternCrate, - Import, + Use, Struct, StructField, Union, @@ -18,7 +18,7 @@ pub(crate) enum Kind { TraitAlias, Impl, Static, - ForeignType, + ExternType, Macro, ProcAttribute, ProcDerive, @@ -36,7 +36,7 @@ impl Kind { match self { Module => true, ExternCrate => true, - Import => true, + Use => true, Union => true, Struct => true, Enum => true, @@ -50,7 +50,7 @@ impl Kind { Macro => true, ProcMacro => true, Primitive => true, - ForeignType => true, + ExternType => true, // FIXME(adotinthevoid): I'm not sure if these are correct Keyword => false, @@ -69,7 +69,7 @@ impl Kind { pub fn can_appear_in_import(self) -> bool { match self { Kind::Variant => true, - Kind::Import => false, + Kind::Use => false, other => other.can_appear_in_mod(), } } @@ -90,7 +90,7 @@ impl Kind { Kind::Module => false, Kind::ExternCrate => false, - Kind::Import => false, + Kind::Use => false, Kind::Struct => false, Kind::StructField => false, Kind::Union => false, @@ -102,7 +102,7 @@ impl Kind { Kind::TraitAlias => false, Kind::Impl => false, Kind::Static => false, - Kind::ForeignType => false, + Kind::ExternType => false, Kind::Macro => false, Kind::ProcAttribute => false, Kind::ProcDerive => false, @@ -135,7 +135,7 @@ impl Kind { use Kind::*; match i.inner { ItemEnum::Module(_) => Module, - ItemEnum::Import(_) => Import, + ItemEnum::Use(_) => Use, ItemEnum::Union(_) => Union, ItemEnum::Struct(_) => Struct, ItemEnum::StructField(_) => StructField, @@ -151,7 +151,7 @@ impl Kind { ItemEnum::Macro(_) => Macro, ItemEnum::ProcMacro(_) => ProcMacro, ItemEnum::Primitive(_) => Primitive, - ItemEnum::ForeignType => ForeignType, + ItemEnum::ExternType => ExternType, ItemEnum::ExternCrate { .. } => ExternCrate, ItemEnum::AssocConst { .. } => AssocConst, ItemEnum::AssocType { .. } => AssocType, @@ -166,10 +166,10 @@ impl Kind { ItemKind::Constant => Constant, ItemKind::Enum => Enum, ItemKind::ExternCrate => ExternCrate, - ItemKind::ForeignType => ForeignType, + ItemKind::ExternType => ExternType, ItemKind::Function => Function, ItemKind::Impl => Impl, - ItemKind::Import => Import, + ItemKind::Use => Use, ItemKind::Keyword => Keyword, ItemKind::Macro => Macro, ItemKind::Module => Module, diff --git a/src/tools/jsondoclint/src/validator.rs b/src/tools/jsondoclint/src/validator.rs index 0ffb96bef29ba..10ab62cb24aa8 100644 --- a/src/tools/jsondoclint/src/validator.rs +++ b/src/tools/jsondoclint/src/validator.rs @@ -2,10 +2,11 @@ use std::collections::HashSet; use std::hash::Hash; use rustdoc_json_types::{ - Constant, Crate, DynTrait, Enum, FnDecl, Function, FunctionPointer, GenericArg, GenericArgs, - GenericBound, GenericParamDef, Generics, Id, Impl, Import, ItemEnum, ItemSummary, Module, Path, - Primitive, ProcMacro, Static, Struct, StructKind, Term, Trait, TraitAlias, Type, TypeAlias, - TypeBinding, TypeBindingKind, Union, Variant, VariantKind, WherePredicate, + AssocItemConstraint, AssocItemConstraintKind, Constant, Crate, DynTrait, Enum, Function, + FunctionPointer, FunctionSignature, GenericArg, GenericArgs, GenericBound, GenericParamDef, + Generics, Id, Impl, ItemEnum, ItemSummary, Module, Path, Primitive, ProcMacro, Static, Struct, + StructKind, Term, Trait, TraitAlias, Type, TypeAlias, Union, Use, Variant, VariantKind, + WherePredicate, }; use serde_json::Value; @@ -90,7 +91,7 @@ impl<'a> Validator<'a> { item.links.values().for_each(|id| self.add_any_id(id)); match &item.inner { - ItemEnum::Import(x) => self.check_import(x), + ItemEnum::Use(x) => self.check_use(x), ItemEnum::Union(x) => self.check_union(x), ItemEnum::Struct(x) => self.check_struct(x), ItemEnum::StructField(x) => self.check_struct_field(x), @@ -106,18 +107,18 @@ impl<'a> Validator<'a> { self.check_constant(const_); } ItemEnum::Static(x) => self.check_static(x), - ItemEnum::ForeignType => {} // nop + ItemEnum::ExternType => {} // nop ItemEnum::Macro(x) => self.check_macro(x), ItemEnum::ProcMacro(x) => self.check_proc_macro(x), ItemEnum::Primitive(x) => self.check_primitive_type(x), ItemEnum::Module(x) => self.check_module(x, id), // FIXME: Why don't these have their own structs? ItemEnum::ExternCrate { .. } => {} - ItemEnum::AssocConst { type_, default: _ } => self.check_type(type_), - ItemEnum::AssocType { generics, bounds, default } => { + ItemEnum::AssocConst { type_, value: _ } => self.check_type(type_), + ItemEnum::AssocType { generics, bounds, type_ } => { self.check_generics(generics); bounds.iter().for_each(|b| self.check_generic_bound(b)); - if let Some(ty) = default { + if let Some(ty) = type_ { self.check_type(ty); } } @@ -133,8 +134,8 @@ impl<'a> Validator<'a> { module.items.iter().for_each(|i| self.add_mod_item_id(i)); } - fn check_import(&mut self, x: &'a Import) { - if x.glob { + fn check_use(&mut self, x: &'a Use) { + if x.is_glob { self.add_glob_import_item_id(x.id.as_ref().unwrap()); } else if let Some(id) = &x.id { self.add_import_item_id(id); @@ -152,7 +153,7 @@ impl<'a> Validator<'a> { match &x.kind { StructKind::Unit => {} StructKind::Tuple(fields) => fields.iter().flatten().for_each(|f| self.add_field_id(f)), - StructKind::Plain { fields, fields_stripped: _ } => { + StructKind::Plain { fields, has_stripped_fields: _ } => { fields.iter().for_each(|f| self.add_field_id(f)) } } @@ -187,7 +188,7 @@ impl<'a> Validator<'a> { match kind { VariantKind::Plain => {} VariantKind::Tuple(tys) => tys.iter().flatten().for_each(|t| self.add_field_id(t)), - VariantKind::Struct { fields, fields_stripped: _ } => { + VariantKind::Struct { fields, has_stripped_fields: _ } => { fields.iter().for_each(|f| self.add_field_id(f)) } } @@ -195,7 +196,7 @@ impl<'a> Validator<'a> { fn check_function(&mut self, x: &'a Function) { self.check_generics(&x.generics); - self.check_fn_decl(&x.decl); + self.check_function_signature(&x.sig); } fn check_trait(&mut self, x: &'a Trait, id: &Id) { @@ -267,8 +268,8 @@ impl<'a> Validator<'a> { Type::Array { type_, len: _ } => self.check_type(&**type_), Type::ImplTrait(bounds) => bounds.iter().for_each(|b| self.check_generic_bound(b)), Type::Infer => {} - Type::RawPointer { mutable: _, type_ } => self.check_type(&**type_), - Type::BorrowedRef { lifetime: _, mutable: _, type_ } => self.check_type(&**type_), + Type::RawPointer { is_mutable: _, type_ } => self.check_type(&**type_), + Type::BorrowedRef { lifetime: _, is_mutable: _, type_ } => self.check_type(&**type_), Type::QualifiedPath { name: _, args, self_type, trait_ } => { self.check_generic_args(&**args); self.check_type(&**self_type); @@ -279,7 +280,7 @@ impl<'a> Validator<'a> { } } - fn check_fn_decl(&mut self, x: &'a FnDecl) { + fn check_function_signature(&mut self, x: &'a FunctionSignature) { x.inputs.iter().for_each(|(_name, ty)| self.check_type(ty)); if let Some(output) = &x.output { self.check_type(output); @@ -309,9 +310,9 @@ impl<'a> Validator<'a> { fn check_generic_args(&mut self, x: &'a GenericArgs) { match x { - GenericArgs::AngleBracketed { args, bindings } => { + GenericArgs::AngleBracketed { args, constraints } => { args.iter().for_each(|arg| self.check_generic_arg(arg)); - bindings.iter().for_each(|bind| self.check_type_binding(bind)); + constraints.iter().for_each(|bind| self.check_assoc_item_constraint(bind)); } GenericArgs::Parenthesized { inputs, output } => { inputs.iter().for_each(|ty| self.check_type(ty)); @@ -325,7 +326,7 @@ impl<'a> Validator<'a> { fn check_generic_param_def(&mut self, gpd: &'a GenericParamDef) { match &gpd.kind { rustdoc_json_types::GenericParamDefKind::Lifetime { outlives: _ } => {} - rustdoc_json_types::GenericParamDefKind::Type { bounds, default, synthetic: _ } => { + rustdoc_json_types::GenericParamDefKind::Type { bounds, default, is_synthetic: _ } => { bounds.iter().for_each(|b| self.check_generic_bound(b)); if let Some(ty) = default { self.check_type(ty); @@ -346,11 +347,11 @@ impl<'a> Validator<'a> { } } - fn check_type_binding(&mut self, bind: &'a TypeBinding) { + fn check_assoc_item_constraint(&mut self, bind: &'a AssocItemConstraint) { self.check_generic_args(&bind.args); match &bind.binding { - TypeBindingKind::Equality(term) => self.check_term(term), - TypeBindingKind::Constraint(bounds) => { + AssocItemConstraintKind::Equality(term) => self.check_term(term), + AssocItemConstraintKind::Constraint(bounds) => { bounds.iter().for_each(|b| self.check_generic_bound(b)) } } @@ -388,7 +389,7 @@ impl<'a> Validator<'a> { } fn check_function_pointer(&mut self, fp: &'a FunctionPointer) { - self.check_fn_decl(&fp.decl); + self.check_function_signature(&fp.sig); fp.generic_params.iter().for_each(|gpd| self.check_generic_param_def(gpd)); } diff --git a/tests/rustdoc-json/assoc_items.rs b/tests/rustdoc-json/assoc_items.rs index 7fd0fe2b89878..f315f37966d0b 100644 --- a/tests/rustdoc-json/assoc_items.rs +++ b/tests/rustdoc-json/assoc_items.rs @@ -9,12 +9,12 @@ impl Simple { pub trait EasyToImpl { //@ has "$.index[*][?(@.docs=='ToDeclare trait')].inner.assoc_type" - //@ is "$.index[*][?(@.docs=='ToDeclare trait')].inner.assoc_type.default" null + //@ is "$.index[*][?(@.docs=='ToDeclare trait')].inner.assoc_type.type" null //@ is "$.index[*][?(@.docs=='ToDeclare trait')].inner.assoc_type.bounds" [] /// ToDeclare trait type ToDeclare; //@ has "$.index[*][?(@.docs=='AN_ATTRIBUTE trait')].inner.assoc_const" - //@ is "$.index[*][?(@.docs=='AN_ATTRIBUTE trait')].inner.assoc_const.default" null + //@ is "$.index[*][?(@.docs=='AN_ATTRIBUTE trait')].inner.assoc_const.value" null //@ is "$.index[*][?(@.docs=='AN_ATTRIBUTE trait')].inner.assoc_const.type.primitive" '"usize"' /// AN_ATTRIBUTE trait const AN_ATTRIBUTE: usize; @@ -22,13 +22,13 @@ pub trait EasyToImpl { impl EasyToImpl for Simple { //@ has "$.index[*][?(@.docs=='ToDeclare impl')].inner.assoc_type" - //@ is "$.index[*][?(@.docs=='ToDeclare impl')].inner.assoc_type.default.primitive" \"usize\" + //@ is "$.index[*][?(@.docs=='ToDeclare impl')].inner.assoc_type.type.primitive" \"usize\" /// ToDeclare impl type ToDeclare = usize; //@ has "$.index[*][?(@.docs=='AN_ATTRIBUTE impl')].inner.assoc_const" //@ is "$.index[*][?(@.docs=='AN_ATTRIBUTE impl')].inner.assoc_const.type.primitive" \"usize\" - //@ is "$.index[*][?(@.docs=='AN_ATTRIBUTE impl')].inner.assoc_const.default" \"12\" + //@ is "$.index[*][?(@.docs=='AN_ATTRIBUTE impl')].inner.assoc_const.value" \"12\" /// AN_ATTRIBUTE impl const AN_ATTRIBUTE: usize = 12; } diff --git a/tests/rustdoc-json/blanket_impls.rs b/tests/rustdoc-json/blanket_impls.rs index bc2c98dcbb7ca..f2acabbe37254 100644 --- a/tests/rustdoc-json/blanket_impls.rs +++ b/tests/rustdoc-json/blanket_impls.rs @@ -3,6 +3,6 @@ #![no_std] //@ has "$.index[*][?(@.name=='Error')].inner.assoc_type" -//@ has "$.index[*][?(@.name=='Error')].inner.assoc_type.default.resolved_path" -//@ has "$.index[*][?(@.name=='Error')].inner.assoc_type.default.resolved_path.name" \"Infallible\" +//@ has "$.index[*][?(@.name=='Error')].inner.assoc_type.type.resolved_path" +//@ has "$.index[*][?(@.name=='Error')].inner.assoc_type.type.resolved_path.name" \"Infallible\" pub struct ForBlanketTryFromImpl; diff --git a/tests/rustdoc-json/enums/kind.rs b/tests/rustdoc-json/enums/kind.rs index ef3d9363d647a..2e0fb3101a31f 100644 --- a/tests/rustdoc-json/enums/kind.rs +++ b/tests/rustdoc-json/enums/kind.rs @@ -5,7 +5,7 @@ pub enum Foo { //@ is "$.index[*][?(@.name=='Unit')].inner.variant.kind" '"plain"' Unit, //@ set Named = "$.index[*][?(@.name=='Named')].id" - //@ is "$.index[*][?(@.name=='Named')].inner.variant.kind.struct" '{"fields": [], "fields_stripped": false}' + //@ is "$.index[*][?(@.name=='Named')].inner.variant.kind.struct" '{"fields": [], "has_stripped_fields": false}' Named {}, //@ set Tuple = "$.index[*][?(@.name=='Tuple')].id" //@ is "$.index[*][?(@.name=='Tuple')].inner.variant.kind.tuple" [] @@ -13,7 +13,7 @@ pub enum Foo { //@ set NamedField = "$.index[*][?(@.name=='NamedField')].id" //@ set x = "$.index[*][?(@.name=='x' && @.inner.struct_field)].id" //@ is "$.index[*][?(@.name=='NamedField')].inner.variant.kind.struct.fields[*]" $x - //@ is "$.index[*][?(@.name=='NamedField')].inner.variant.kind.struct.fields_stripped" false + //@ is "$.index[*][?(@.name=='NamedField')].inner.variant.kind.struct.has_stripped_fields" false NamedField { x: i32 }, //@ set TupleField = "$.index[*][?(@.name=='TupleField')].id" //@ set tup_field = "$.index[*][?(@.name=='0' && @.inner.struct_field)].id" diff --git a/tests/rustdoc-json/enums/struct_field_hidden.rs b/tests/rustdoc-json/enums/struct_field_hidden.rs index b724f9abb71b1..2184f58b1da80 100644 --- a/tests/rustdoc-json/enums/struct_field_hidden.rs +++ b/tests/rustdoc-json/enums/struct_field_hidden.rs @@ -9,7 +9,7 @@ pub enum Foo { //@ set y = "$.index[*][?(@.name=='y')].id" y: i32, }, - //@ is "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.fields_stripped" true + //@ is "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.has_stripped_fields" true //@ is "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.fields[0]" $b //@ is "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.fields[1]" $y //@ count "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.fields[*]" 2 diff --git a/tests/rustdoc-json/enums/use_glob.rs b/tests/rustdoc-json/enums/use_glob.rs index 61766d2a62982..2631b43da8e0e 100644 --- a/tests/rustdoc-json/enums/use_glob.rs +++ b/tests/rustdoc-json/enums/use_glob.rs @@ -7,9 +7,9 @@ pub enum Color { Blue, } -//@ set use_Color = "$.index[*][?(@.inner.import)].id" -//@ is "$.index[*][?(@.inner.import)].inner.import.id" $Color -//@ is "$.index[*][?(@.inner.import)].inner.import.glob" true +//@ set use_Color = "$.index[*][?(@.inner.use)].id" +//@ is "$.index[*][?(@.inner.use)].inner.use.id" $Color +//@ is "$.index[*][?(@.inner.use)].inner.use.is_glob" true pub use Color::*; //@ ismany "$.index[*][?(@.name == 'use_glob')].inner.module.items[*]" $Color $use_Color diff --git a/tests/rustdoc-json/enums/use_variant.rs b/tests/rustdoc-json/enums/use_variant.rs index 9010d61649396..6d3322e0ba9a1 100644 --- a/tests/rustdoc-json/enums/use_variant.rs +++ b/tests/rustdoc-json/enums/use_variant.rs @@ -5,8 +5,8 @@ pub enum AlwaysNone { } //@ is "$.index[*][?(@.name == 'AlwaysNone')].inner.enum.variants[*]" $None -//@ set use_None = "$.index[*][?(@.inner.import)].id" -//@ is "$.index[*][?(@.inner.import)].inner.import.id" $None +//@ set use_None = "$.index[*][?(@.inner.use)].id" +//@ is "$.index[*][?(@.inner.use)].inner.use.id" $None pub use AlwaysNone::None; //@ ismany "$.index[*][?(@.name == 'use_variant')].inner.module.items[*]" $AlwaysNone $use_None diff --git a/tests/rustdoc-json/enums/use_variant_foreign.rs b/tests/rustdoc-json/enums/use_variant_foreign.rs index 0f3f16ff83576..a9ad61b9fe35e 100644 --- a/tests/rustdoc-json/enums/use_variant_foreign.rs +++ b/tests/rustdoc-json/enums/use_variant_foreign.rs @@ -2,7 +2,7 @@ extern crate color; -//@ has "$.index[*].inner.import[?(@.name == 'Red')]" +//@ has "$.index[*].inner.use[?(@.name == 'Red')]" pub use color::Color::Red; //@ !has "$.index[*][?(@.name == 'Red')]" diff --git a/tests/rustdoc-json/fn_pointer/generics.rs b/tests/rustdoc-json/fn_pointer/generics.rs index 9f5d23ae421eb..7d64e490a2220 100644 --- a/tests/rustdoc-json/fn_pointer/generics.rs +++ b/tests/rustdoc-json/fn_pointer/generics.rs @@ -1,9 +1,9 @@ // ignore-tidy-linelength -//@ count "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.decl.inputs[*]" 1 -//@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.decl.inputs[0][0]" '"val"' -//@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.decl.inputs[0][1].borrowed_ref.lifetime" \"\'c\" -//@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.decl.output.primitive" \"i32\" +//@ count "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.sig.inputs[*]" 1 +//@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.sig.inputs[0][0]" '"val"' +//@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.sig.inputs[0][1].borrowed_ref.lifetime" \"\'c\" +//@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.sig.output.primitive" \"i32\" //@ count "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.generic_params[*]" 1 //@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.generic_params[0].name" \"\'c\" //@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }' diff --git a/tests/rustdoc-json/fn_pointer/qualifiers.rs b/tests/rustdoc-json/fn_pointer/qualifiers.rs index 9c0e6c0ccf1e6..6f03cf58522e4 100644 --- a/tests/rustdoc-json/fn_pointer/qualifiers.rs +++ b/tests/rustdoc-json/fn_pointer/qualifiers.rs @@ -1,11 +1,11 @@ // ignore-tidy-linelength -//@ is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.unsafe" false -//@ is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.const" false -//@ is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.async" false +//@ is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.is_unsafe" false +//@ is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.is_const" false +//@ is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.is_async" false pub type FnPointer = fn(); -//@ is "$.index[*][?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.unsafe" true -//@ is "$.index[*][?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.const" false -//@ is "$.index[*][?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.async" false +//@ is "$.index[*][?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.is_unsafe" true +//@ is "$.index[*][?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.is_const" false +//@ is "$.index[*][?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.is_async" false pub type UnsafePointer = unsafe fn(); diff --git a/tests/rustdoc-json/fns/async_return.rs b/tests/rustdoc-json/fns/async_return.rs index e029c72df212f..18a8a586e76d9 100644 --- a/tests/rustdoc-json/fns/async_return.rs +++ b/tests/rustdoc-json/fns/async_return.rs @@ -5,30 +5,30 @@ use std::future::Future; -//@ is "$.index[*][?(@.name=='get_int')].inner.function.decl.output.primitive" \"i32\" -//@ is "$.index[*][?(@.name=='get_int')].inner.function.header.async" false +//@ is "$.index[*][?(@.name=='get_int')].inner.function.sig.output.primitive" \"i32\" +//@ is "$.index[*][?(@.name=='get_int')].inner.function.header.is_async" false pub fn get_int() -> i32 { 42 } -//@ is "$.index[*][?(@.name=='get_int_async')].inner.function.decl.output.primitive" \"i32\" -//@ is "$.index[*][?(@.name=='get_int_async')].inner.function.header.async" true +//@ is "$.index[*][?(@.name=='get_int_async')].inner.function.sig.output.primitive" \"i32\" +//@ is "$.index[*][?(@.name=='get_int_async')].inner.function.header.is_async" true pub async fn get_int_async() -> i32 { 42 } -//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.decl.output.impl_trait[0].trait_bound.trait.name" '"Future"' -//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.decl.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].name" '"Output"' -//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.decl.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].binding.equality.type.primitive" \"i32\" -//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.header.async" false +//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.sig.output.impl_trait[0].trait_bound.trait.name" '"Future"' +//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].name" '"Output"' +//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].binding.equality.type.primitive" \"i32\" +//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.header.is_async" false pub fn get_int_future() -> impl Future { async { 42 } } -//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.decl.output.impl_trait[0].trait_bound.trait.name" '"Future"' -//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.decl.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].name" '"Output"' -//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.decl.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].binding.equality.type.primitive" \"i32\" -//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.header.async" true +//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.sig.output.impl_trait[0].trait_bound.trait.name" '"Future"' +//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].name" '"Output"' +//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].binding.equality.type.primitive" \"i32\" +//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.header.is_async" true pub async fn get_int_future_async() -> impl Future { async { 42 } } diff --git a/tests/rustdoc-json/fns/extern_c_variadic.rs b/tests/rustdoc-json/fns/extern_c_variadic.rs index defe66345e83c..8e9085640e041 100644 --- a/tests/rustdoc-json/fns/extern_c_variadic.rs +++ b/tests/rustdoc-json/fns/extern_c_variadic.rs @@ -1,6 +1,6 @@ extern "C" { - //@ is "$.index[*][?(@.name == 'not_variadic')].inner.function.decl.c_variadic" false + //@ is "$.index[*][?(@.name == 'not_variadic')].inner.function.sig.is_c_variadic" false pub fn not_variadic(_: i32); - //@ is "$.index[*][?(@.name == 'variadic')].inner.function.decl.c_variadic" true + //@ is "$.index[*][?(@.name == 'variadic')].inner.function.sig.is_c_variadic" true pub fn variadic(_: i32, ...); } diff --git a/tests/rustdoc-json/fns/generic_args.rs b/tests/rustdoc-json/fns/generic_args.rs index 75c5fcbb01f6c..b5412446ab42a 100644 --- a/tests/rustdoc-json/fns/generic_args.rs +++ b/tests/rustdoc-json/fns/generic_args.rs @@ -12,27 +12,27 @@ pub trait GenericFoo<'a> {} //@ is "$.index[*][?(@.name=='generics')].inner.function.generics.params[0].kind.type.default" 'null' //@ count "$.index[*][?(@.name=='generics')].inner.function.generics.params[0].kind.type.bounds[*]" 1 //@ is "$.index[*][?(@.name=='generics')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" '$foo' -//@ count "$.index[*][?(@.name=='generics')].inner.function.decl.inputs[*]" 1 -//@ is "$.index[*][?(@.name=='generics')].inner.function.decl.inputs[0][0]" '"f"' -//@ is "$.index[*][?(@.name=='generics')].inner.function.decl.inputs[0][1].generic" '"F"' +//@ count "$.index[*][?(@.name=='generics')].inner.function.sig.inputs[*]" 1 +//@ is "$.index[*][?(@.name=='generics')].inner.function.sig.inputs[0][0]" '"f"' +//@ is "$.index[*][?(@.name=='generics')].inner.function.sig.inputs[0][1].generic" '"F"' pub fn generics(f: F) {} //@ is "$.index[*][?(@.name=='impl_trait')].inner.function.generics.where_predicates" "[]" //@ count "$.index[*][?(@.name=='impl_trait')].inner.function.generics.params[*]" 1 //@ is "$.index[*][?(@.name=='impl_trait')].inner.function.generics.params[0].name" '"impl Foo"' //@ is "$.index[*][?(@.name=='impl_trait')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $foo -//@ count "$.index[*][?(@.name=='impl_trait')].inner.function.decl.inputs[*]" 1 -//@ is "$.index[*][?(@.name=='impl_trait')].inner.function.decl.inputs[0][0]" '"f"' -//@ count "$.index[*][?(@.name=='impl_trait')].inner.function.decl.inputs[0][1].impl_trait[*]" 1 -//@ is "$.index[*][?(@.name=='impl_trait')].inner.function.decl.inputs[0][1].impl_trait[0].trait_bound.trait.id" $foo +//@ count "$.index[*][?(@.name=='impl_trait')].inner.function.sig.inputs[*]" 1 +//@ is "$.index[*][?(@.name=='impl_trait')].inner.function.sig.inputs[0][0]" '"f"' +//@ count "$.index[*][?(@.name=='impl_trait')].inner.function.sig.inputs[0][1].impl_trait[*]" 1 +//@ is "$.index[*][?(@.name=='impl_trait')].inner.function.sig.inputs[0][1].impl_trait[0].trait_bound.trait.id" $foo pub fn impl_trait(f: impl Foo) {} //@ count "$.index[*][?(@.name=='where_clase')].inner.function.generics.params[*]" 3 //@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.params[0].name" '"F"' -//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.params[0].kind" '{"type": {"bounds": [], "default": null, "synthetic": false}}' -//@ count "$.index[*][?(@.name=='where_clase')].inner.function.decl.inputs[*]" 3 -//@ is "$.index[*][?(@.name=='where_clase')].inner.function.decl.inputs[0][0]" '"f"' -//@ is "$.index[*][?(@.name=='where_clase')].inner.function.decl.inputs[0][1].generic" '"F"' +//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.params[0].kind" '{"type": {"bounds": [], "default": null, "is_synthetic": false}}' +//@ count "$.index[*][?(@.name=='where_clase')].inner.function.sig.inputs[*]" 3 +//@ is "$.index[*][?(@.name=='where_clase')].inner.function.sig.inputs[0][0]" '"f"' +//@ is "$.index[*][?(@.name=='where_clase')].inner.function.sig.inputs[0][1].generic" '"F"' //@ count "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[*]" 3 //@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[0].bound_predicate.type.generic" \"F\" diff --git a/tests/rustdoc-json/fns/generic_returns.rs b/tests/rustdoc-json/fns/generic_returns.rs index 07dc691b933f5..2f23801fc3f8f 100644 --- a/tests/rustdoc-json/fns/generic_returns.rs +++ b/tests/rustdoc-json/fns/generic_returns.rs @@ -5,9 +5,9 @@ //@ set foo = "$.index[*][?(@.name=='Foo')].id" pub trait Foo {} -//@ is "$.index[*][?(@.name=='get_foo')].inner.function.decl.inputs" [] -//@ count "$.index[*][?(@.name=='get_foo')].inner.function.decl.output.impl_trait[*]" 1 -//@ is "$.index[*][?(@.name=='get_foo')].inner.function.decl.output.impl_trait[0].trait_bound.trait.id" $foo +//@ is "$.index[*][?(@.name=='get_foo')].inner.function.sig.inputs" [] +//@ count "$.index[*][?(@.name=='get_foo')].inner.function.sig.output.impl_trait[*]" 1 +//@ is "$.index[*][?(@.name=='get_foo')].inner.function.sig.output.impl_trait[0].trait_bound.trait.id" $foo pub fn get_foo() -> impl Foo { Fooer {} } diff --git a/tests/rustdoc-json/fns/generics.rs b/tests/rustdoc-json/fns/generics.rs index 43fc7279ded57..f2064fd1e93df 100644 --- a/tests/rustdoc-json/fns/generics.rs +++ b/tests/rustdoc-json/fns/generics.rs @@ -6,17 +6,17 @@ pub trait Wham {} //@ is "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.where_predicates" [] //@ count "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[*]" 1 //@ is "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[0].name" '"T"' -//@ is "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[0].kind.type.synthetic" false +//@ is "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[0].kind.type.is_synthetic" false //@ is "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $wham_id -//@ is "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.decl.inputs" '[["w", {"generic": "T"}]]' +//@ is "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.sig.inputs" '[["w", {"generic": "T"}]]' pub fn one_generic_param_fn(w: T) {} //@ is "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.where_predicates" [] //@ count "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[*]" 1 //@ is "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[0].name" '"impl Wham"' -//@ is "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[0].kind.type.synthetic" true +//@ is "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[0].kind.type.is_synthetic" true //@ is "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $wham_id -//@ count "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.decl.inputs[*]" 1 -//@ is "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.decl.inputs[0][0]" '"w"' -//@ is "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.decl.inputs[0][1].impl_trait[0].trait_bound.trait.id" $wham_id +//@ count "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.sig.inputs[*]" 1 +//@ is "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.sig.inputs[0][0]" '"w"' +//@ is "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.sig.inputs[0][1].impl_trait[0].trait_bound.trait.id" $wham_id pub fn one_synthetic_generic_param_fn(w: impl Wham) {} diff --git a/tests/rustdoc-json/fns/pattern_arg.rs b/tests/rustdoc-json/fns/pattern_arg.rs index 3fa423bcefd27..d2a00f47438e2 100644 --- a/tests/rustdoc-json/fns/pattern_arg.rs +++ b/tests/rustdoc-json/fns/pattern_arg.rs @@ -1,7 +1,7 @@ -//@ is "$.index[*][?(@.name=='fst')].inner.function.decl.inputs[0][0]" '"(x, _)"' +//@ is "$.index[*][?(@.name=='fst')].inner.function.sig.inputs[0][0]" '"(x, _)"' pub fn fst((x, _): (X, Y)) -> X { x } -//@ is "$.index[*][?(@.name=='drop_int')].inner.function.decl.inputs[0][0]" '"_"' +//@ is "$.index[*][?(@.name=='drop_int')].inner.function.sig.inputs[0][0]" '"_"' pub fn drop_int(_: i32) {} diff --git a/tests/rustdoc-json/fns/qualifiers.rs b/tests/rustdoc-json/fns/qualifiers.rs index beb1b4ccd10c5..67e49f0780ae1 100644 --- a/tests/rustdoc-json/fns/qualifiers.rs +++ b/tests/rustdoc-json/fns/qualifiers.rs @@ -1,33 +1,33 @@ //@ edition:2018 -//@ is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.async" false -//@ is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.const" false -//@ is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.unsafe" false +//@ is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.is_async" false +//@ is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.is_const" false +//@ is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.is_unsafe" false pub fn nothing_fn() {} -//@ is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.async" false -//@ is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.const" false -//@ is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.unsafe" true +//@ is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.is_async" false +//@ is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.is_const" false +//@ is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.is_unsafe" true pub unsafe fn unsafe_fn() {} -//@ is "$.index[*][?(@.name=='const_fn')].inner.function.header.async" false -//@ is "$.index[*][?(@.name=='const_fn')].inner.function.header.const" true -//@ is "$.index[*][?(@.name=='const_fn')].inner.function.header.unsafe" false +//@ is "$.index[*][?(@.name=='const_fn')].inner.function.header.is_async" false +//@ is "$.index[*][?(@.name=='const_fn')].inner.function.header.is_const" true +//@ is "$.index[*][?(@.name=='const_fn')].inner.function.header.is_unsafe" false pub const fn const_fn() {} -//@ is "$.index[*][?(@.name=='async_fn')].inner.function.header.async" true -//@ is "$.index[*][?(@.name=='async_fn')].inner.function.header.const" false -//@ is "$.index[*][?(@.name=='async_fn')].inner.function.header.unsafe" false +//@ is "$.index[*][?(@.name=='async_fn')].inner.function.header.is_async" true +//@ is "$.index[*][?(@.name=='async_fn')].inner.function.header.is_const" false +//@ is "$.index[*][?(@.name=='async_fn')].inner.function.header.is_unsafe" false pub async fn async_fn() {} -//@ is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.async" true -//@ is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.const" false -//@ is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.unsafe" true +//@ is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.is_async" true +//@ is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.is_const" false +//@ is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.is_unsafe" true pub async unsafe fn async_unsafe_fn() {} -//@ is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.async" false -//@ is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.const" true -//@ is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.unsafe" true +//@ is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.is_async" false +//@ is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.is_const" true +//@ is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.is_unsafe" true pub const unsafe fn const_unsafe_fn() {} // It's impossible for a function to be both const and async, so no test for that diff --git a/tests/rustdoc-json/fns/return_type_alias.rs b/tests/rustdoc-json/fns/return_type_alias.rs index 67bc46a874064..d60c4b6825894 100644 --- a/tests/rustdoc-json/fns/return_type_alias.rs +++ b/tests/rustdoc-json/fns/return_type_alias.rs @@ -3,7 +3,7 @@ ///@ set foo = "$.index[*][?(@.name=='Foo')].id" pub type Foo = i32; -//@ is "$.index[*][?(@.name=='demo')].inner.function.decl.output.resolved_path.id" $foo +//@ is "$.index[*][?(@.name=='demo')].inner.function.sig.output.resolved_path.id" $foo pub fn demo() -> Foo { 42 } diff --git a/tests/rustdoc-json/generic-associated-types/gats.rs b/tests/rustdoc-json/generic-associated-types/gats.rs index 8a38230bb5d22..fdf605e928715 100644 --- a/tests/rustdoc-json/generic-associated-types/gats.rs +++ b/tests/rustdoc-json/generic-associated-types/gats.rs @@ -13,10 +13,10 @@ pub trait LendingIterator { where Self: 'a; - //@ count "$.index[*][?(@.name=='lending_next')].inner.function.decl.output.qualified_path.args.angle_bracketed.args[*]" 1 - //@ count "$.index[*][?(@.name=='lending_next')].inner.function.decl.output.qualified_path.args.angle_bracketed.bindings[*]" 0 - //@ is "$.index[*][?(@.name=='lending_next')].inner.function.decl.output.qualified_path.self_type.generic" \"Self\" - //@ is "$.index[*][?(@.name=='lending_next')].inner.function.decl.output.qualified_path.name" \"LendingItem\" + //@ count "$.index[*][?(@.name=='lending_next')].inner.function.sig.output.qualified_path.args.angle_bracketed.args[*]" 1 + //@ count "$.index[*][?(@.name=='lending_next')].inner.function.sig.output.qualified_path.args.angle_bracketed.bindings[*]" 0 + //@ is "$.index[*][?(@.name=='lending_next')].inner.function.sig.output.qualified_path.self_type.generic" \"Self\" + //@ is "$.index[*][?(@.name=='lending_next')].inner.function.sig.output.qualified_path.name" \"LendingItem\" fn lending_next<'a>(&'a self) -> Self::LendingItem<'a>; } @@ -26,9 +26,9 @@ pub trait Iterator { //@ count "$.index[*][?(@.name=='Item')].inner.assoc_type.bounds[*]" 1 type Item: Display; - //@ count "$.index[*][?(@.name=='next')].inner.function.decl.output.qualified_path.args.angle_bracketed.args[*]" 0 - //@ count "$.index[*][?(@.name=='next')].inner.function.decl.output.qualified_path.args.angle_bracketed.bindings[*]" 0 - //@ is "$.index[*][?(@.name=='next')].inner.function.decl.output.qualified_path.self_type.generic" \"Self\" - //@ is "$.index[*][?(@.name=='next')].inner.function.decl.output.qualified_path.name" \"Item\" + //@ count "$.index[*][?(@.name=='next')].inner.function.sig.output.qualified_path.args.angle_bracketed.args[*]" 0 + //@ count "$.index[*][?(@.name=='next')].inner.function.sig.output.qualified_path.args.angle_bracketed.bindings[*]" 0 + //@ is "$.index[*][?(@.name=='next')].inner.function.sig.output.qualified_path.self_type.generic" \"Self\" + //@ is "$.index[*][?(@.name=='next')].inner.function.sig.output.qualified_path.name" \"Item\" fn next<'a>(&'a self) -> Self::Item; } diff --git a/tests/rustdoc-json/glob_import.rs b/tests/rustdoc-json/glob_import.rs index a67a99a37cbc7..b63e5dadd9e74 100644 --- a/tests/rustdoc-json/glob_import.rs +++ b/tests/rustdoc-json/glob_import.rs @@ -3,7 +3,7 @@ #![no_std] //@ has "$.index[*][?(@.name=='glob')]" -//@ has "$.index[*][?(@.inner.import)].inner.import.name" \"*\" +//@ has "$.index[*][?(@.inner.use)].inner.use.name" \"*\" mod m1 { pub fn f() {} diff --git a/tests/rustdoc-json/impl-trait-in-assoc-type.rs b/tests/rustdoc-json/impl-trait-in-assoc-type.rs index f02e38ca393de..907a0f6c603e0 100644 --- a/tests/rustdoc-json/impl-trait-in-assoc-type.rs +++ b/tests/rustdoc-json/impl-trait-in-assoc-type.rs @@ -9,11 +9,11 @@ impl IntoIterator for AlwaysTrue { /// type Item type Item = bool; - //@ count '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.default.impl_trait[*]' 1 - //@ is '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.default.impl_trait[0].trait_bound.trait.name' '"Iterator"' - //@ count '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.default.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[*]' 1 - //@ is '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.default.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].name' '"Item"' - //@ is '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.default.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].binding.equality.type.primitive' '"bool"' + //@ count '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[*]' 1 + //@ is '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.name' '"Iterator"' + //@ count '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[*]' 1 + //@ is '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].name' '"Item"' + //@ is '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].binding.equality.type.primitive' '"bool"' //@ set IntoIter = '$.index[*][?(@.docs=="type IntoIter")].id' /// type IntoIter diff --git a/tests/rustdoc-json/impl-trait-precise-capturing.rs b/tests/rustdoc-json/impl-trait-precise-capturing.rs index 0c116a1029019..52252560e6fda 100644 --- a/tests/rustdoc-json/impl-trait-precise-capturing.rs +++ b/tests/rustdoc-json/impl-trait-precise-capturing.rs @@ -1,4 +1,4 @@ -//@ is "$.index[*][?(@.name=='hello')].inner.function.decl.output.impl_trait[1].use[0]" \"\'a\" -//@ is "$.index[*][?(@.name=='hello')].inner.function.decl.output.impl_trait[1].use[1]" \"T\" -//@ is "$.index[*][?(@.name=='hello')].inner.function.decl.output.impl_trait[1].use[2]" \"N\" +//@ is "$.index[*][?(@.name=='hello')].inner.function.sig.output.impl_trait[1].use[0]" \"\'a\" +//@ is "$.index[*][?(@.name=='hello')].inner.function.sig.output.impl_trait[1].use[1]" \"T\" +//@ is "$.index[*][?(@.name=='hello')].inner.function.sig.output.impl_trait[1].use[2]" \"N\" pub fn hello<'a, T, const N: usize>() -> impl Sized + use<'a, T, N> {} diff --git a/tests/rustdoc-json/impls/auto.rs b/tests/rustdoc-json/impls/auto.rs index 84a1e6ed7d564..e14c935b23b87 100644 --- a/tests/rustdoc-json/impls/auto.rs +++ b/tests/rustdoc-json/impls/auto.rs @@ -18,5 +18,5 @@ impl Foo { //@ is "$.index[*][?(@.docs=='has span')].span.begin" "[13, 0]" //@ is "$.index[*][?(@.docs=='has span')].span.end" "[15, 1]" // FIXME: this doesn't work due to https://github.com/freestrings/jsonpath/issues/91 -// is "$.index[*][?(@.inner.impl.synthetic==true)].span" null +// is "$.index[*][?(@.inner.impl.is_synthetic==true)].span" null pub struct Foo; diff --git a/tests/rustdoc-json/impls/foreign_for_local.rs b/tests/rustdoc-json/impls/foreign_for_local.rs index 20690f26851be..1347f954cade8 100644 --- a/tests/rustdoc-json/impls/foreign_for_local.rs +++ b/tests/rustdoc-json/impls/foreign_for_local.rs @@ -3,7 +3,7 @@ extern crate foreign_trait; /// ForeignTrait id hack pub use foreign_trait::ForeignTrait as _; -//@ set ForeignTrait = "$.index[*][?(@.docs=='ForeignTrait id hack')].inner.import.id" +//@ set ForeignTrait = "$.index[*][?(@.docs=='ForeignTrait id hack')].inner.use.id" pub struct LocalStruct; //@ set LocalStruct = "$.index[*][?(@.name=='LocalStruct')].id" diff --git a/tests/rustdoc-json/impls/import_from_private.rs b/tests/rustdoc-json/impls/import_from_private.rs index e386252e83b51..32b9abb0717cc 100644 --- a/tests/rustdoc-json/impls/import_from_private.rs +++ b/tests/rustdoc-json/impls/import_from_private.rs @@ -11,10 +11,10 @@ mod bar { } } -//@ set import = "$.index[*][?(@.inner.import)].id" +//@ set import = "$.index[*][?(@.inner.use)].id" pub use bar::Baz; //@ is "$.index[*].inner.module.items[*]" $import -//@ is "$.index[*].inner.import.id" $baz +//@ is "$.index[*].inner.use.id" $baz //@ has "$.index[*][?(@.name == 'Baz')].inner.struct.impls[*]" $impl //@ is "$.index[*][?(@.docs=='impl')].inner.impl.items[*]" $doit diff --git a/tests/rustdoc-json/impls/local_for_foreign.rs b/tests/rustdoc-json/impls/local_for_foreign.rs index bd49269104fb7..cd89c47534881 100644 --- a/tests/rustdoc-json/impls/local_for_foreign.rs +++ b/tests/rustdoc-json/impls/local_for_foreign.rs @@ -3,7 +3,7 @@ extern crate foreign_struct; /// ForeignStruct id hack pub use foreign_struct::ForeignStruct as _; -//@ set ForeignStruct = "$.index[*][?(@.docs=='ForeignStruct id hack')].inner.import.id" +//@ set ForeignStruct = "$.index[*][?(@.docs=='ForeignStruct id hack')].inner.use.id" pub trait LocalTrait {} //@ set LocalTrait = "$.index[*][?(@.name=='LocalTrait')].id" diff --git a/tests/rustdoc-json/lifetime/longest.rs b/tests/rustdoc-json/lifetime/longest.rs index 39f791d2b0935..8ac60be0fefdb 100644 --- a/tests/rustdoc-json/lifetime/longest.rs +++ b/tests/rustdoc-json/lifetime/longest.rs @@ -6,21 +6,21 @@ //@ count "$.index[*][?(@.name=='longest')].inner.function.generics.params[*]" 1 //@ is "$.index[*][?(@.name=='longest')].inner.function.generics.where_predicates" [] -//@ count "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[*]" 2 -//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[0][0]" '"l"' -//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[1][0]" '"r"' +//@ count "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[*]" 2 +//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[0][0]" '"l"' +//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[1][0]" '"r"' -//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[0][1].borrowed_ref.lifetime" \"\'a\" -//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[0][1].borrowed_ref.mutable" false -//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[0][1].borrowed_ref.type.primitive" \"str\" +//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[0][1].borrowed_ref.lifetime" \"\'a\" +//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable" false +//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[0][1].borrowed_ref.type.primitive" \"str\" -//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[1][1].borrowed_ref.lifetime" \"\'a\" -//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[1][1].borrowed_ref.mutable" false -//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[1][1].borrowed_ref.type.primitive" \"str\" +//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[1][1].borrowed_ref.lifetime" \"\'a\" +//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[1][1].borrowed_ref.is_mutable" false +//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[1][1].borrowed_ref.type.primitive" \"str\" -//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.output.borrowed_ref.lifetime" \"\'a\" -//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.output.borrowed_ref.mutable" false -//@ is "$.index[*][?(@.name=='longest')].inner.function.decl.output.borrowed_ref.type.primitive" \"str\" +//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.output.borrowed_ref.lifetime" \"\'a\" +//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.output.borrowed_ref.is_mutable" false +//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.output.borrowed_ref.type.primitive" \"str\" pub fn longest<'a>(l: &'a str, r: &'a str) -> &'a str { if l.len() > r.len() { l } else { r } diff --git a/tests/rustdoc-json/lifetime/outlives.rs b/tests/rustdoc-json/lifetime/outlives.rs index c98555d5737ad..99d14296f9998 100644 --- a/tests/rustdoc-json/lifetime/outlives.rs +++ b/tests/rustdoc-json/lifetime/outlives.rs @@ -10,9 +10,9 @@ //@ is "$.index[*][?(@.name=='foo')].inner.function.generics.params[2].kind.type.default" null //@ count "$.index[*][?(@.name=='foo')].inner.function.generics.params[2].kind.type.bounds[*]" 1 //@ is "$.index[*][?(@.name=='foo')].inner.function.generics.params[2].kind.type.bounds[0].outlives" \"\'b\" -//@ is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.lifetime" \"\'a\" -//@ is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.mutable" false -//@ is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.type.borrowed_ref.lifetime" \"\'b\" -//@ is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.type.borrowed_ref.mutable" false -//@ is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.type.borrowed_ref.type.generic" \"T\" +//@ is "$.index[*][?(@.name=='foo')].inner.function.sig.inputs[0][1].borrowed_ref.lifetime" \"\'a\" +//@ is "$.index[*][?(@.name=='foo')].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable" false +//@ is "$.index[*][?(@.name=='foo')].inner.function.sig.inputs[0][1].borrowed_ref.type.borrowed_ref.lifetime" \"\'b\" +//@ is "$.index[*][?(@.name=='foo')].inner.function.sig.inputs[0][1].borrowed_ref.type.borrowed_ref.is_mutable" false +//@ is "$.index[*][?(@.name=='foo')].inner.function.sig.inputs[0][1].borrowed_ref.type.borrowed_ref.type.generic" \"T\" pub fn foo<'a, 'b: 'a, T: 'b>(_: &'a &'b T) {} diff --git a/tests/rustdoc-json/methods/qualifiers.rs b/tests/rustdoc-json/methods/qualifiers.rs index 8de8cfd4c15d3..ba7c2e60936b3 100644 --- a/tests/rustdoc-json/methods/qualifiers.rs +++ b/tests/rustdoc-json/methods/qualifiers.rs @@ -3,34 +3,34 @@ pub struct Foo; impl Foo { - //@ is "$.index[*][?(@.name=='const_meth')].inner.function.header.async" false - //@ is "$.index[*][?(@.name=='const_meth')].inner.function.header.const" true - //@ is "$.index[*][?(@.name=='const_meth')].inner.function.header.unsafe" false + //@ is "$.index[*][?(@.name=='const_meth')].inner.function.header.is_async" false + //@ is "$.index[*][?(@.name=='const_meth')].inner.function.header.is_const" true + //@ is "$.index[*][?(@.name=='const_meth')].inner.function.header.is_unsafe" false pub const fn const_meth() {} - //@ is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.async" false - //@ is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.const" false - //@ is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.unsafe" false + //@ is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.is_async" false + //@ is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.is_const" false + //@ is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.is_unsafe" false pub fn nothing_meth() {} - //@ is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.async" false - //@ is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.const" false - //@ is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.unsafe" true + //@ is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.is_async" false + //@ is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.is_const" false + //@ is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.is_unsafe" true pub unsafe fn unsafe_meth() {} - //@ is "$.index[*][?(@.name=='async_meth')].inner.function.header.async" true - //@ is "$.index[*][?(@.name=='async_meth')].inner.function.header.const" false - //@ is "$.index[*][?(@.name=='async_meth')].inner.function.header.unsafe" false + //@ is "$.index[*][?(@.name=='async_meth')].inner.function.header.is_async" true + //@ is "$.index[*][?(@.name=='async_meth')].inner.function.header.is_const" false + //@ is "$.index[*][?(@.name=='async_meth')].inner.function.header.is_unsafe" false pub async fn async_meth() {} - //@ is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.async" true - //@ is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.const" false - //@ is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.unsafe" true + //@ is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.is_async" true + //@ is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.is_const" false + //@ is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.is_unsafe" true pub async unsafe fn async_unsafe_meth() {} - //@ is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.async" false - //@ is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.const" true - //@ is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.unsafe" true + //@ is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.is_async" false + //@ is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.is_const" true + //@ is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.is_unsafe" true pub const unsafe fn const_unsafe_meth() {} // It's impossible for a method to be both const and async, so no test for that diff --git a/tests/rustdoc-json/nested.rs b/tests/rustdoc-json/nested.rs index ae2d9fe0ac55b..10ec2831c212c 100644 --- a/tests/rustdoc-json/nested.rs +++ b/tests/rustdoc-json/nested.rs @@ -22,11 +22,11 @@ pub mod l1 { //@ ismany "$.index[*][?(@.name=='l3')].inner.module.items[*]" $l4_id pub struct L4; } - //@ is "$.index[*][?(@.inner.import)].inner.import.glob" false - //@ is "$.index[*][?(@.inner.import)].inner.import.source" '"l3::L4"' - //@ is "$.index[*][?(@.inner.import)].inner.import.glob" false - //@ is "$.index[*][?(@.inner.import)].inner.import.id" $l4_id - //@ set l4_use_id = "$.index[*][?(@.inner.import)].id" + //@ is "$.index[*][?(@.inner.use)].inner.use.is_glob" false + //@ is "$.index[*][?(@.inner.use)].inner.use.source" '"l3::L4"' + //@ is "$.index[*][?(@.inner.use)].inner.use.is_glob" false + //@ is "$.index[*][?(@.inner.use)].inner.use.id" $l4_id + //@ set l4_use_id = "$.index[*][?(@.inner.use)].id" pub use l3::L4; } //@ ismany "$.index[*][?(@.name=='l1')].inner.module.items[*]" $l3_id $l4_use_id diff --git a/tests/rustdoc-json/non_lifetime_binders.rs b/tests/rustdoc-json/non_lifetime_binders.rs index 06f6e10aa85c2..8443141fecd50 100644 --- a/tests/rustdoc-json/non_lifetime_binders.rs +++ b/tests/rustdoc-json/non_lifetime_binders.rs @@ -11,7 +11,7 @@ pub struct Wrapper(std::marker::PhantomData); //@ is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[0].name" \"\'a\" //@ is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }' //@ is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[1].name" \"T\" -//@ is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[1].kind" '{ "type": { "bounds": [], "default": null, "synthetic": false } }' +//@ is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[1].kind" '{ "type": { "bounds": [], "default": null, "is_synthetic": false } }' pub fn foo() where for<'a, T> &'a Wrapper: Trait, diff --git a/tests/rustdoc-json/primitives/use_primitive.rs b/tests/rustdoc-json/primitives/use_primitive.rs index 27394a688c4b5..d4cdef84de845 100644 --- a/tests/rustdoc-json/primitives/use_primitive.rs +++ b/tests/rustdoc-json/primitives/use_primitive.rs @@ -13,7 +13,7 @@ mod usize {} //@ !is "$.index[*][?(@.name=='checked_add')]" $local_crate_id //@ !has "$.index[*][?(@.name=='is_ascii_uppercase')]" -//@ is "$.index[*].inner.import[?(@.name=='my_i32')].id" null +//@ is "$.index[*].inner.use[?(@.name=='my_i32')].id" null pub use i32 as my_i32; -//@ is "$.index[*].inner.import[?(@.name=='u32')].id" null +//@ is "$.index[*].inner.use[?(@.name=='u32')].id" null pub use u32; diff --git a/tests/rustdoc-json/reexport/extern_crate_glob.rs b/tests/rustdoc-json/reexport/extern_crate_glob.rs index a0b4cb8ab2cdc..dfe6e7a03b153 100644 --- a/tests/rustdoc-json/reexport/extern_crate_glob.rs +++ b/tests/rustdoc-json/reexport/extern_crate_glob.rs @@ -6,6 +6,6 @@ extern crate enum_with_discriminant; pub use enum_with_discriminant::*; //@ !has '$.index[*][?(@.docs == "Should not be inlined")]' -//@ is '$.index[*][?(@.inner.import)].inner.import.name' \"enum_with_discriminant\" -//@ set use = '$.index[*][?(@.inner.import)].id' +//@ is '$.index[*][?(@.inner.use)].inner.use.name' \"enum_with_discriminant\" +//@ set use = '$.index[*][?(@.inner.use)].id' //@ is '$.index[*][?(@.name == "extern_crate_glob")].inner.module.items[*]' $use diff --git a/tests/rustdoc-json/reexport/glob_collision.rs b/tests/rustdoc-json/reexport/glob_collision.rs index 3a034afab65f1..8142c35f4c712 100644 --- a/tests/rustdoc-json/reexport/glob_collision.rs +++ b/tests/rustdoc-json/reexport/glob_collision.rs @@ -14,13 +14,13 @@ mod m2 { } //@ set m1_use = "$.index[*][?(@.docs=='m1 re-export')].id" -//@ is "$.index[*].inner.import[?(@.name=='m1')].id" $m1 -//@ is "$.index[*].inner.import[?(@.name=='m1')].glob" true +//@ is "$.index[*].inner.use[?(@.name=='m1')].id" $m1 +//@ is "$.index[*].inner.use[?(@.name=='m1')].is_glob" true /// m1 re-export pub use m1::*; //@ set m2_use = "$.index[*][?(@.docs=='m2 re-export')].id" -//@ is "$.index[*].inner.import[?(@.name=='m2')].id" $m2 -//@ is "$.index[*].inner.import[?(@.name=='m2')].glob" true +//@ is "$.index[*].inner.use[?(@.name=='m2')].id" $m2 +//@ is "$.index[*].inner.use[?(@.name=='m2')].is_glob" true /// m2 re-export pub use m2::*; diff --git a/tests/rustdoc-json/reexport/glob_empty_mod.rs b/tests/rustdoc-json/reexport/glob_empty_mod.rs index 326df5fdb6198..ee1779407f404 100644 --- a/tests/rustdoc-json/reexport/glob_empty_mod.rs +++ b/tests/rustdoc-json/reexport/glob_empty_mod.rs @@ -4,5 +4,5 @@ //@ set m1 = "$.index[*][?(@.name=='m1')].id" mod m1 {} -//@ is "$.index[*][?(@.inner.import)].inner.import.id" $m1 +//@ is "$.index[*][?(@.inner.use)].inner.use.id" $m1 pub use m1::*; diff --git a/tests/rustdoc-json/reexport/glob_extern.rs b/tests/rustdoc-json/reexport/glob_extern.rs index ff5d986d377f4..98be47739413e 100644 --- a/tests/rustdoc-json/reexport/glob_extern.rs +++ b/tests/rustdoc-json/reexport/glob_extern.rs @@ -12,8 +12,8 @@ mod mod1 { //@ set mod1_id = "$.index[*][?(@.name=='mod1')].id" } -//@ is "$.index[*][?(@.inner.import)].inner.import.glob" true -//@ is "$.index[*][?(@.inner.import)].inner.import.id" $mod1_id -//@ set use_id = "$.index[*][?(@.inner.import)].id" +//@ is "$.index[*][?(@.inner.use)].inner.use.is_glob" true +//@ is "$.index[*][?(@.inner.use)].inner.use.id" $mod1_id +//@ set use_id = "$.index[*][?(@.inner.use)].id" //@ ismany "$.index[*][?(@.name=='glob_extern')].inner.module.items[*]" $use_id pub use mod1::*; diff --git a/tests/rustdoc-json/reexport/glob_private.rs b/tests/rustdoc-json/reexport/glob_private.rs index 0a88910759206..2084ffc356e2a 100644 --- a/tests/rustdoc-json/reexport/glob_private.rs +++ b/tests/rustdoc-json/reexport/glob_private.rs @@ -12,7 +12,7 @@ mod mod1 { } //@ set mod2_use_id = "$.index[*][?(@.docs=='Mod2 re-export')].id" - //@ is "$.index[*][?(@.docs=='Mod2 re-export')].inner.import.name" \"mod2\" + //@ is "$.index[*][?(@.docs=='Mod2 re-export')].inner.use.name" \"mod2\" /// Mod2 re-export pub use self::mod2::*; @@ -23,7 +23,7 @@ mod mod1 { } //@ set mod1_use_id = "$.index[*][?(@.docs=='Mod1 re-export')].id" -//@ is "$.index[*][?(@.docs=='Mod1 re-export')].inner.import.name" \"mod1\" +//@ is "$.index[*][?(@.docs=='Mod1 re-export')].inner.use.name" \"mod1\" /// Mod1 re-export pub use mod1::*; diff --git a/tests/rustdoc-json/reexport/in_root_and_mod.rs b/tests/rustdoc-json/reexport/in_root_and_mod.rs index f94e416c00f58..a1d2080c06887 100644 --- a/tests/rustdoc-json/reexport/in_root_and_mod.rs +++ b/tests/rustdoc-json/reexport/in_root_and_mod.rs @@ -4,10 +4,10 @@ mod foo { pub struct Foo; } -//@ has "$.index[*].inner[?(@.import.source=='foo::Foo')]" +//@ has "$.index[*].inner[?(@.use.source=='foo::Foo')]" pub use foo::Foo; pub mod bar { - //@ has "$.index[*].inner[?(@.import.source=='crate::foo::Foo')]" + //@ has "$.index[*].inner[?(@.use.source=='crate::foo::Foo')]" pub use crate::foo::Foo; } diff --git a/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs b/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs index 13dee32354224..7d26d2a970d4a 100644 --- a/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs +++ b/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs @@ -5,14 +5,14 @@ pub mod foo { } //@ set root_import_id = "$.index[*][?(@.docs=='Outer re-export')].id" -//@ is "$.index[*].inner[?(@.import.source=='foo::Bar')].import.id" $bar_id +//@ is "$.index[*].inner[?(@.use.source=='foo::Bar')].use.id" $bar_id //@ has "$.index[*][?(@.name=='in_root_and_mod_pub')].inner.module.items[*]" $root_import_id /// Outer re-export pub use foo::Bar; pub mod baz { //@ set baz_import_id = "$.index[*][?(@.docs=='Inner re-export')].id" - //@ is "$.index[*].inner[?(@.import.source=='crate::foo::Bar')].import.id" $bar_id + //@ is "$.index[*].inner[?(@.use.source=='crate::foo::Bar')].use.id" $bar_id //@ ismany "$.index[*][?(@.name=='baz')].inner.module.items[*]" $baz_import_id /// Inner re-export pub use crate::foo::Bar; diff --git a/tests/rustdoc-json/reexport/mod_not_included.rs b/tests/rustdoc-json/reexport/mod_not_included.rs index 7e0c0118e8462..d0ce95749f1b4 100644 --- a/tests/rustdoc-json/reexport/mod_not_included.rs +++ b/tests/rustdoc-json/reexport/mod_not_included.rs @@ -7,5 +7,5 @@ mod m1 { pub use m1::x; //@ has "$.index[*][?(@.name=='x' && @.inner.function)]" -//@ has "$.index[*].inner[?(@.import.name=='x')].import.source" '"m1::x"' +//@ has "$.index[*].inner[?(@.use.name=='x')].use.source" '"m1::x"' //@ !has "$.index[*][?(@.name=='m1')]" diff --git a/tests/rustdoc-json/reexport/private_twice_one_inline.rs b/tests/rustdoc-json/reexport/private_twice_one_inline.rs index be66ad522da86..87b97e65c0ac2 100644 --- a/tests/rustdoc-json/reexport/private_twice_one_inline.rs +++ b/tests/rustdoc-json/reexport/private_twice_one_inline.rs @@ -7,18 +7,18 @@ extern crate pub_struct as foo; #[doc(inline)] //@ set crate_use_id = "$.index[*][?(@.docs=='Hack A')].id" -//@ set foo_id = "$.index[*][?(@.docs=='Hack A')].inner.import.id" +//@ set foo_id = "$.index[*][?(@.docs=='Hack A')].inner.use.id" /// Hack A pub use foo::Foo; //@ set bar_id = "$.index[*][?(@.name=='bar')].id" pub mod bar { - //@ is "$.index[*][?(@.docs=='Hack B')].inner.import.id" $foo_id + //@ is "$.index[*][?(@.docs=='Hack B')].inner.use.id" $foo_id //@ set bar_use_id = "$.index[*][?(@.docs=='Hack B')].id" //@ ismany "$.index[*][?(@.name=='bar')].inner.module.items[*]" $bar_use_id /// Hack B pub use foo::Foo; } -//@ ismany "$.index[*][?(@.inner.import)].id" $crate_use_id $bar_use_id +//@ ismany "$.index[*][?(@.inner.use)].id" $crate_use_id $bar_use_id //@ ismany "$.index[*][?(@.name=='private_twice_one_inline')].inner.module.items[*]" $bar_id $crate_use_id diff --git a/tests/rustdoc-json/reexport/private_two_names.rs b/tests/rustdoc-json/reexport/private_two_names.rs index 1e5466dba5e4e..1ed54f15fdc36 100644 --- a/tests/rustdoc-json/reexport/private_two_names.rs +++ b/tests/rustdoc-json/reexport/private_two_names.rs @@ -9,13 +9,13 @@ mod style { pub struct Color; } -//@ is "$.index[*][?(@.docs=='First re-export')].inner.import.id" $color_struct_id -//@ is "$.index[*][?(@.docs=='First re-export')].inner.import.name" \"Color\" +//@ is "$.index[*][?(@.docs=='First re-export')].inner.use.id" $color_struct_id +//@ is "$.index[*][?(@.docs=='First re-export')].inner.use.name" \"Color\" //@ set color_export_id = "$.index[*][?(@.docs=='First re-export')].id" /// First re-export pub use style::Color; -//@ is "$.index[*][?(@.docs=='Second re-export')].inner.import.id" $color_struct_id -//@ is "$.index[*][?(@.docs=='Second re-export')].inner.import.name" \"Colour\" +//@ is "$.index[*][?(@.docs=='Second re-export')].inner.use.id" $color_struct_id +//@ is "$.index[*][?(@.docs=='Second re-export')].inner.use.name" \"Colour\" //@ set colour_export_id = "$.index[*][?(@.docs=='Second re-export')].id" /// Second re-export pub use style::Color as Colour; diff --git a/tests/rustdoc-json/reexport/reexport_of_hidden.rs b/tests/rustdoc-json/reexport/reexport_of_hidden.rs index 07ce1f5c20a1b..80f171da888e3 100644 --- a/tests/rustdoc-json/reexport/reexport_of_hidden.rs +++ b/tests/rustdoc-json/reexport/reexport_of_hidden.rs @@ -1,6 +1,6 @@ //@ compile-flags: --document-hidden-items -//@ has "$.index[*].inner[?(@.import.name=='UsedHidden')]" +//@ has "$.index[*].inner[?(@.use.name=='UsedHidden')]" //@ has "$.index[*][?(@.name=='Hidden')]" pub mod submodule { #[doc(hidden)] diff --git a/tests/rustdoc-json/reexport/rename_private.rs b/tests/rustdoc-json/reexport/rename_private.rs index 3335d18e27b1f..3f13f305d6448 100644 --- a/tests/rustdoc-json/reexport/rename_private.rs +++ b/tests/rustdoc-json/reexport/rename_private.rs @@ -6,5 +6,5 @@ mod inner { pub struct Public; } -//@ is "$.index[*][?(@.inner.import)].inner.import.name" \"NewName\" +//@ is "$.index[*][?(@.inner.use)].inner.use.name" \"NewName\" pub use inner::Public as NewName; diff --git a/tests/rustdoc-json/reexport/rename_public.rs b/tests/rustdoc-json/reexport/rename_public.rs index e534f458f9378..81c003a51c4af 100644 --- a/tests/rustdoc-json/reexport/rename_public.rs +++ b/tests/rustdoc-json/reexport/rename_public.rs @@ -7,8 +7,8 @@ pub mod inner { pub struct Public; } //@ set import_id = "$.index[*][?(@.docs=='Re-export')].id" -//@ !has "$.index[*].inner[?(@.import.name=='Public')]" -//@ is "$.index[*].inner[?(@.import.name=='NewName')].import.source" \"inner::Public\" +//@ !has "$.index[*].inner[?(@.use.name=='Public')]" +//@ is "$.index[*].inner[?(@.use.name=='NewName')].use.source" \"inner::Public\" /// Re-export pub use inner::Public as NewName; diff --git a/tests/rustdoc-json/reexport/same_name_different_types.rs b/tests/rustdoc-json/reexport/same_name_different_types.rs index b0a06d4ecfab5..e9bc4a5ac406d 100644 --- a/tests/rustdoc-json/reexport/same_name_different_types.rs +++ b/tests/rustdoc-json/reexport/same_name_different_types.rs @@ -13,10 +13,10 @@ pub mod nested { pub fn Foo() {} } -//@ ismany "$.index[*].inner[?(@.import.name == 'Foo')].import.id" $foo_fn $foo_struct -//@ ismany "$.index[*].inner[?(@.import.name == 'Bar')].import.id" $foo_fn $foo_struct +//@ ismany "$.index[*].inner[?(@.use.name == 'Foo')].use.id" $foo_fn $foo_struct +//@ ismany "$.index[*].inner[?(@.use.name == 'Bar')].use.id" $foo_fn $foo_struct -//@ count "$.index[*].inner[?(@.import.name == 'Foo')]" 2 +//@ count "$.index[*].inner[?(@.use.name == 'Foo')]" 2 pub use nested::Foo; -//@ count "$.index[*].inner[?(@.import.name == 'Bar')]" 2 +//@ count "$.index[*].inner[?(@.use.name == 'Bar')]" 2 pub use Foo as Bar; diff --git a/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs b/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs index c533b9ba7709c..27e2827d08ddb 100644 --- a/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs +++ b/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs @@ -10,11 +10,11 @@ mod inner { } //@ set export_id = "$.index[*][?(@.docs=='First re-export')].id" -//@ is "$.index[*].inner[?(@.import.name=='Trait')].import.id" $trait_id +//@ is "$.index[*].inner[?(@.use.name=='Trait')].use.id" $trait_id /// First re-export pub use inner::Trait; //@ set reexport_id = "$.index[*][?(@.docs=='Second re-export')].id" -//@ is "$.index[*].inner[?(@.import.name=='Reexport')].import.id" $trait_id +//@ is "$.index[*].inner[?(@.use.name=='Reexport')].use.id" $trait_id /// Second re-export pub use inner::Trait as Reexport; diff --git a/tests/rustdoc-json/reexport/simple_private.rs b/tests/rustdoc-json/reexport/simple_private.rs index 9af0157818b4f..8a936f5da1b9e 100644 --- a/tests/rustdoc-json/reexport/simple_private.rs +++ b/tests/rustdoc-json/reexport/simple_private.rs @@ -6,9 +6,9 @@ mod inner { pub struct Public; } -//@ is "$.index[*][?(@.inner.import)].inner.import.name" \"Public\" -//@ is "$.index[*][?(@.inner.import)].inner.import.id" $pub_id -//@ set use_id = "$.index[*][?(@.inner.import)].id" +//@ is "$.index[*][?(@.inner.use)].inner.use.name" \"Public\" +//@ is "$.index[*][?(@.inner.use)].inner.use.id" $pub_id +//@ set use_id = "$.index[*][?(@.inner.use)].id" pub use inner::Public; //@ ismany "$.index[*][?(@.name=='simple_private')].inner.module.items[*]" $use_id diff --git a/tests/rustdoc-json/reexport/simple_public.rs b/tests/rustdoc-json/reexport/simple_public.rs index d7b44b2f9877f..e5a8dc7d2ad00 100644 --- a/tests/rustdoc-json/reexport/simple_public.rs +++ b/tests/rustdoc-json/reexport/simple_public.rs @@ -9,7 +9,7 @@ pub mod inner { } //@ set import_id = "$.index[*][?(@.docs=='Outer')].id" -//@ is "$.index[*][?(@.docs=='Outer')].inner.import.source" \"inner::Public\" +//@ is "$.index[*][?(@.docs=='Outer')].inner.use.source" \"inner::Public\" /// Outer pub use inner::Public; diff --git a/tests/rustdoc-json/return_private.rs b/tests/rustdoc-json/return_private.rs index 4a1922e15e5fe..0b341e2bda7d2 100644 --- a/tests/rustdoc-json/return_private.rs +++ b/tests/rustdoc-json/return_private.rs @@ -6,7 +6,7 @@ mod secret { } //@ has "$.index[*][?(@.name=='get_secret')].inner.function" -//@ is "$.index[*][?(@.name=='get_secret')].inner.function.decl.output.resolved_path.name" \"secret::Secret\" +//@ is "$.index[*][?(@.name=='get_secret')].inner.function.sig.output.resolved_path.name" \"secret::Secret\" pub fn get_secret() -> secret::Secret { secret::Secret } diff --git a/tests/rustdoc-json/structs/plain_all_pub.rs b/tests/rustdoc-json/structs/plain_all_pub.rs index aa53b59726a9d..67d2a4a7a8cf8 100644 --- a/tests/rustdoc-json/structs/plain_all_pub.rs +++ b/tests/rustdoc-json/structs/plain_all_pub.rs @@ -8,4 +8,4 @@ pub struct Demo { //@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[0]" $x //@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[1]" $y //@ count "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[*]" 2 -//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields_stripped" false +//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.has_stripped_fields" false diff --git a/tests/rustdoc-json/structs/plain_doc_hidden.rs b/tests/rustdoc-json/structs/plain_doc_hidden.rs index 39f9367cb935f..4573adc73fa1f 100644 --- a/tests/rustdoc-json/structs/plain_doc_hidden.rs +++ b/tests/rustdoc-json/structs/plain_doc_hidden.rs @@ -8,4 +8,4 @@ pub struct Demo { //@ !has "$.index[*][?(@.name=='y')].id" //@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[0]" $x //@ count "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[*]" 1 -//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields_stripped" true +//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.has_stripped_fields" true diff --git a/tests/rustdoc-json/structs/plain_empty.rs b/tests/rustdoc-json/structs/plain_empty.rs index 00b4b05ebddd1..30013021abef2 100644 --- a/tests/rustdoc-json/structs/plain_empty.rs +++ b/tests/rustdoc-json/structs/plain_empty.rs @@ -1,5 +1,5 @@ //@ is "$.index[*][?(@.name=='PlainEmpty')].visibility" \"public\" //@ has "$.index[*][?(@.name=='PlainEmpty')].inner.struct" -//@ is "$.index[*][?(@.name=='PlainEmpty')].inner.struct.kind.plain.fields_stripped" false +//@ is "$.index[*][?(@.name=='PlainEmpty')].inner.struct.kind.plain.has_stripped_fields" false //@ is "$.index[*][?(@.name=='PlainEmpty')].inner.struct.kind.plain.fields" [] pub struct PlainEmpty {} diff --git a/tests/rustdoc-json/structs/plain_pub_priv.rs b/tests/rustdoc-json/structs/plain_pub_priv.rs index f9ab8714f81a6..91079a30d42ea 100644 --- a/tests/rustdoc-json/structs/plain_pub_priv.rs +++ b/tests/rustdoc-json/structs/plain_pub_priv.rs @@ -6,4 +6,4 @@ pub struct Demo { //@ set x = "$.index[*][?(@.name=='x')].id" //@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[0]" $x //@ count "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[*]" 1 -//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields_stripped" true +//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.has_stripped_fields" true diff --git a/tests/rustdoc-json/structs/with_generics.rs b/tests/rustdoc-json/structs/with_generics.rs index 6e13dae9ebffb..3e7f175a5a1a5 100644 --- a/tests/rustdoc-json/structs/with_generics.rs +++ b/tests/rustdoc-json/structs/with_generics.rs @@ -6,7 +6,7 @@ use std::collections::HashMap; //@ is "$.index[*][?(@.name=='WithGenerics')].inner.struct.generics.params[0].kind.type.bounds" [] //@ is "$.index[*][?(@.name=='WithGenerics')].inner.struct.generics.params[1].name" \"U\" //@ is "$.index[*][?(@.name=='WithGenerics')].inner.struct.generics.params[1].kind.type.bounds" [] -//@ is "$.index[*][?(@.name=='WithGenerics')].inner.struct.kind.plain.fields_stripped" true +//@ is "$.index[*][?(@.name=='WithGenerics')].inner.struct.kind.plain.has_stripped_fields" true //@ is "$.index[*][?(@.name=='WithGenerics')].inner.struct.kind.plain.fields" [] pub struct WithGenerics { stuff: Vec, diff --git a/tests/rustdoc-json/structs/with_primitives.rs b/tests/rustdoc-json/structs/with_primitives.rs index 2ca11b50608f8..7202ab9af9c28 100644 --- a/tests/rustdoc-json/structs/with_primitives.rs +++ b/tests/rustdoc-json/structs/with_primitives.rs @@ -4,7 +4,7 @@ //@ has "$.index[*][?(@.name=='WithPrimitives')].inner.struct" //@ is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.generics.params[0].name" \"\'a\" //@ is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.generics.params[0].kind.lifetime.outlives" [] -//@ is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.kind.plain.fields_stripped" true +//@ is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.kind.plain.has_stripped_fields" true //@ is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.kind.plain.fields" [] pub struct WithPrimitives<'a> { num: u32, diff --git a/tests/rustdoc-json/trait_alias.rs b/tests/rustdoc-json/trait_alias.rs index ca9e5edfdf7e0..3ae5fad8accd7 100644 --- a/tests/rustdoc-json/trait_alias.rs +++ b/tests/rustdoc-json/trait_alias.rs @@ -7,12 +7,12 @@ //@ is "$.index[*][?(@.name=='StrLike')].span.filename" $FILE pub trait StrLike = AsRef; -//@ is "$.index[*][?(@.name=='f')].inner.function.decl.output.impl_trait[0].trait_bound.trait.id" $StrLike +//@ is "$.index[*][?(@.name=='f')].inner.function.sig.output.impl_trait[0].trait_bound.trait.id" $StrLike pub fn f() -> impl StrLike { "heya" } -//@ !is "$.index[*][?(@.name=='g')].inner.function.decl.output.impl_trait[0].trait_bound.trait.id" $StrLike +//@ !is "$.index[*][?(@.name=='g')].inner.function.sig.output.impl_trait[0].trait_bound.trait.id" $StrLike pub fn g() -> impl AsRef { "heya" } diff --git a/tests/rustdoc-json/traits/self.rs b/tests/rustdoc-json/traits/self.rs index c7d952ae567d4..060bc37f2d5ea 100644 --- a/tests/rustdoc-json/traits/self.rs +++ b/tests/rustdoc-json/traits/self.rs @@ -9,29 +9,29 @@ pub struct Foo; // Each assertion matches 3 times, and should be the same each time. impl Foo { - //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.decl.inputs[0][0]' '"self"' '"self"' '"self"' - //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.decl.inputs[0][1].borrowed_ref.type.generic' '"Self"' '"Self"' '"Self"' - //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.decl.inputs[0][1].borrowed_ref.lifetime' null null null - //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.decl.inputs[0][1].borrowed_ref.mutable' false false false + //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.sig.inputs[0][0]' '"self"' '"self"' '"self"' + //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.sig.inputs[0][1].borrowed_ref.type.generic' '"Self"' '"Self"' '"Self"' + //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.sig.inputs[0][1].borrowed_ref.lifetime' null null null + //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable' false false false pub fn by_ref(&self) {} - //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.decl.inputs[0][0]' '"self"' '"self"' '"self"' - //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.decl.inputs[0][1].borrowed_ref.type.generic' '"Self"' '"Self"' '"Self"' - //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.decl.inputs[0][1].borrowed_ref.lifetime' null null null - //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.decl.inputs[0][1].borrowed_ref.mutable' true true true + //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.sig.inputs[0][0]' '"self"' '"self"' '"self"' + //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.sig.inputs[0][1].borrowed_ref.type.generic' '"Self"' '"Self"' '"Self"' + //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.sig.inputs[0][1].borrowed_ref.lifetime' null null null + //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable' true true true pub fn by_exclusive_ref(&mut self) {} - //@ ismany '$.index[*][?(@.name=="by_value")].inner.function.decl.inputs[0][0]' '"self"' '"self"' '"self"' - //@ ismany '$.index[*][?(@.name=="by_value")].inner.function.decl.inputs[0][1].generic' '"Self"' '"Self"' '"Self"' + //@ ismany '$.index[*][?(@.name=="by_value")].inner.function.sig.inputs[0][0]' '"self"' '"self"' '"self"' + //@ ismany '$.index[*][?(@.name=="by_value")].inner.function.sig.inputs[0][1].generic' '"Self"' '"Self"' '"Self"' pub fn by_value(self) {} - //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.decl.inputs[0][0]' '"self"' '"self"' '"self"' - //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.decl.inputs[0][1].borrowed_ref.type.generic' '"Self"' '"Self"' '"Self"' - //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.decl.inputs[0][1].borrowed_ref.lifetime' \"\'a\" \"\'a\" \"\'a\" - //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.decl.inputs[0][1].borrowed_ref.mutable' false false false + //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.sig.inputs[0][0]' '"self"' '"self"' '"self"' + //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.sig.inputs[0][1].borrowed_ref.type.generic' '"Self"' '"Self"' '"Self"' + //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.sig.inputs[0][1].borrowed_ref.lifetime' \"\'a\" \"\'a\" \"\'a\" + //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable' false false false pub fn with_lifetime<'a>(&'a self) {} - //@ ismany '$.index[*][?(@.name=="build")].inner.function.decl.output.generic' '"Self"' '"Self"' '"Self"' + //@ ismany '$.index[*][?(@.name=="build")].inner.function.sig.output.generic' '"Self"' '"Self"' '"Self"' pub fn build() -> Self { Self } diff --git a/tests/rustdoc-json/traits/trait_alias.rs b/tests/rustdoc-json/traits/trait_alias.rs index a1ab039692bed..17c83ddc353ce 100644 --- a/tests/rustdoc-json/traits/trait_alias.rs +++ b/tests/rustdoc-json/traits/trait_alias.rs @@ -19,8 +19,8 @@ pub struct Struct; impl Orig for Struct {} -//@ has "$.index[*][?(@.name=='takes_alias')].inner.function.decl.inputs[0][1].impl_trait" -//@ is "$.index[*][?(@.name=='takes_alias')].inner.function.decl.inputs[0][1].impl_trait[0].trait_bound.trait.id" $Alias +//@ has "$.index[*][?(@.name=='takes_alias')].inner.function.sig.inputs[0][1].impl_trait" +//@ is "$.index[*][?(@.name=='takes_alias')].inner.function.sig.inputs[0][1].impl_trait[0].trait_bound.trait.id" $Alias //@ is "$.index[*][?(@.name=='takes_alias')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $Alias pub fn takes_alias(_: impl Alias) {} // FIXME: Should the trait be mentioned in both the decl and generics? diff --git a/tests/rustdoc-json/type/dyn.rs b/tests/rustdoc-json/type/dyn.rs index 86ea1c2b5f220..97c8689a7c80a 100644 --- a/tests/rustdoc-json/type/dyn.rs +++ b/tests/rustdoc-json/type/dyn.rs @@ -11,7 +11,7 @@ use std::fmt::Debug; //@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.generics" '{"params": [], "where_predicates": []}' //@ has "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path" //@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.name" \"Box\" -//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.bindings" [] +//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.constraints" [] //@ count "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args" 1 //@ has "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait" //@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.lifetime" \"\'static\" @@ -28,7 +28,7 @@ pub type SyncIntGen = Box i32 + Send + Sync + 'static>; //@ has "$.index[*][?(@.name=='RefFn')].inner.type_alias" //@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.generics" '{"params": [{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"}],"where_predicates": []}' //@ has "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref" -//@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.mutable" 'false' +//@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.is_mutable" 'false' //@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.lifetime" "\"'a\"" //@ has "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait" //@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.lifetime" null diff --git a/tests/rustdoc-json/type/extern.rs b/tests/rustdoc-json/type/extern.rs index fda5d5ab970e0..97e1c3760ee5f 100644 --- a/tests/rustdoc-json/type/extern.rs +++ b/tests/rustdoc-json/type/extern.rs @@ -6,4 +6,4 @@ extern "C" { } //@ is "$.index[*][?(@.docs=='No inner information')].name" '"Foo"' -//@ is "$.index[*][?(@.docs=='No inner information')].inner" \"foreign_type\" +//@ is "$.index[*][?(@.docs=='No inner information')].inner" \"extern_type\" diff --git a/tests/rustdoc-json/type/fn_lifetime.rs b/tests/rustdoc-json/type/fn_lifetime.rs index 2893b37319ffb..7fa12dad54e9b 100644 --- a/tests/rustdoc-json/type/fn_lifetime.rs +++ b/tests/rustdoc-json/type/fn_lifetime.rs @@ -7,9 +7,9 @@ //@ count "$.index[*][?(@.name=='GenericFn')].inner.type_alias.generics.params[*].kind.lifetime.outlives[*]" 0 //@ count "$.index[*][?(@.name=='GenericFn')].inner.type_alias.generics.where_predicates[*]" 0 //@ count "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.generic_params[*]" 0 -//@ count "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.decl.inputs[*]" 1 -//@ is "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.decl.inputs[*][1].borrowed_ref.lifetime" \"\'a\" -//@ is "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.decl.output.borrowed_ref.lifetime" \"\'a\" +//@ count "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.sig.inputs[*]" 1 +//@ is "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.sig.inputs[*][1].borrowed_ref.lifetime" \"\'a\" +//@ is "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.sig.output.borrowed_ref.lifetime" \"\'a\" pub type GenericFn<'a> = fn(&'a i32) -> &'a i32; @@ -20,7 +20,7 @@ pub type GenericFn<'a> = fn(&'a i32) -> &'a i32; //@ is "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.generic_params[*].name" \"\'a\" //@ has "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.generic_params[*].kind.lifetime" //@ count "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.generic_params[*].kind.lifetime.outlives[*]" 0 -//@ count "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.decl.inputs[*]" 1 -//@ is "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.decl.inputs[*][1].borrowed_ref.lifetime" \"\'a\" -//@ is "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.decl.output.borrowed_ref.lifetime" \"\'a\" +//@ count "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.sig.inputs[*]" 1 +//@ is "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.sig.inputs[*][1].borrowed_ref.lifetime" \"\'a\" +//@ is "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.sig.output.borrowed_ref.lifetime" \"\'a\" pub type ForAll = for<'a> fn(&'a i32) -> &'a i32; diff --git a/tests/rustdoc-json/type/generic_default.rs b/tests/rustdoc-json/type/generic_default.rs index 306376354cef2..c1a05805014a9 100644 --- a/tests/rustdoc-json/type/generic_default.rs +++ b/tests/rustdoc-json/type/generic_default.rs @@ -25,7 +25,7 @@ pub struct MyError {} //@ has "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path" //@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.id" $result //@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.name" \"Result\" -//@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.bindings" [] +//@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.constraints" [] //@ has "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.generic" //@ has "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[1].type.generic" //@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.generic" \"T\" diff --git a/tests/rustdoc-json/type/hrtb.rs b/tests/rustdoc-json/type/hrtb.rs index a28b2fddf469b..825720e9198b6 100644 --- a/tests/rustdoc-json/type/hrtb.rs +++ b/tests/rustdoc-json/type/hrtb.rs @@ -12,10 +12,10 @@ where //@ is "$.index[*][?(@.name=='dynfn')].inner.function.generics" '{"params": [], "where_predicates": []}' //@ is "$.index[*][?(@.name=='dynfn')].inner.function.generics" '{"params": [], "where_predicates": []}' -//@ is "$.index[*][?(@.name=='dynfn')].inner.function.decl.inputs[0][1].borrowed_ref.type.dyn_trait.lifetime" null -//@ count "$.index[*][?(@.name=='dynfn')].inner.function.decl.inputs[0][1].borrowed_ref.type.dyn_trait.traits[*]" 1 -//@ is "$.index[*][?(@.name=='dynfn')].inner.function.decl.inputs[0][1].borrowed_ref.type.dyn_trait.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"},{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]' -//@ is "$.index[*][?(@.name=='dynfn')].inner.function.decl.inputs[0][1].borrowed_ref.type.dyn_trait.traits[0].trait.name" '"Fn"' +//@ is "$.index[*][?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.lifetime" null +//@ count "$.index[*][?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.traits[*]" 1 +//@ is "$.index[*][?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"},{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]' +//@ is "$.index[*][?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.traits[0].trait.name" '"Fn"' pub fn dynfn(f: &dyn for<'a, 'b> Fn(&'a i32, &'b i32)) { let zero = 0; f(&zero, &zero); diff --git a/tests/rustdoc-json/type/inherent_associated_type.rs b/tests/rustdoc-json/type/inherent_associated_type.rs index 386c7c80d7fa9..b8ce11fc6e196 100644 --- a/tests/rustdoc-json/type/inherent_associated_type.rs +++ b/tests/rustdoc-json/type/inherent_associated_type.rs @@ -10,9 +10,9 @@ pub struct Owner; pub fn create() -> Owner::Metadata { OwnerMetadata } -//@ is '$.index[*][?(@.name=="create")].inner.function.decl.output.qualified_path.name' '"Metadata"' -//@ is '$.index[*][?(@.name=="create")].inner.function.decl.output.qualified_path.trait' null -//@ is '$.index[*][?(@.name=="create")].inner.function.decl.output.qualified_path.self_type.resolved_path.id' $Owner +//@ is '$.index[*][?(@.name=="create")].inner.function.sig.output.qualified_path.name' '"Metadata"' +//@ is '$.index[*][?(@.name=="create")].inner.function.sig.output.qualified_path.trait' null +//@ is '$.index[*][?(@.name=="create")].inner.function.sig.output.qualified_path.self_type.resolved_path.id' $Owner /// impl impl Owner { @@ -21,4 +21,4 @@ impl Owner { } //@ set iat = '$.index[*][?(@.docs=="iat")].id' //@ is '$.index[*][?(@.docs=="impl")].inner.impl.items[*]' $iat -//@ is '$.index[*][?(@.docs=="iat")].inner.assoc_type.default.resolved_path.id' $OwnerMetadata +//@ is '$.index[*][?(@.docs=="iat")].inner.assoc_type.type.resolved_path.id' $OwnerMetadata diff --git a/tests/rustdoc-json/type/inherent_associated_type_bound.rs b/tests/rustdoc-json/type/inherent_associated_type_bound.rs index 45fe19bf4673d..d0a88b1970fe3 100644 --- a/tests/rustdoc-json/type/inherent_associated_type_bound.rs +++ b/tests/rustdoc-json/type/inherent_associated_type_bound.rs @@ -5,14 +5,14 @@ //@ set Carrier = '$.index[*][?(@.name=="Carrier")].id' pub struct Carrier<'a>(&'a ()); -//@ count "$.index[*][?(@.name=='user')].inner.function.decl.inputs[*]" 1 -//@ is "$.index[*][?(@.name=='user')].inner.function.decl.inputs[0][0]" '"_"' -//@ is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.generic_params[*].name' \""'b"\" -//@ is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.self_type.resolved_path.id' $Carrier -//@ is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].lifetime' \""'b"\" -//@ is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.name' '"Focus"' -//@ is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.trait' null -//@ is '$.index[*][?(@.name=="user")].inner.function.decl.inputs[0][1].function_pointer.decl.inputs[0][1].qualified_path.args.angle_bracketed.args[0].type.primitive' '"i32"' +//@ count "$.index[*][?(@.name=='user')].inner.function.sig.inputs[*]" 1 +//@ is "$.index[*][?(@.name=='user')].inner.function.sig.inputs[0][0]" '"_"' +//@ is '$.index[*][?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.generic_params[*].name' \""'b"\" +//@ is '$.index[*][?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.inputs[0][1].qualified_path.self_type.resolved_path.id' $Carrier +//@ is '$.index[*][?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.inputs[0][1].qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].lifetime' \""'b"\" +//@ is '$.index[*][?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.inputs[0][1].qualified_path.name' '"Focus"' +//@ is '$.index[*][?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.inputs[0][1].qualified_path.trait' null +//@ is '$.index[*][?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.inputs[0][1].qualified_path.args.angle_bracketed.args[0].type.primitive' '"i32"' pub fn user(_: for<'b> fn(Carrier<'b>::Focus)) {} impl<'a> Carrier<'a> { diff --git a/tests/rustdoc-json/type/inherent_associated_type_projections.rs b/tests/rustdoc-json/type/inherent_associated_type_projections.rs index 9b827a9841951..e73e86d5817fe 100644 --- a/tests/rustdoc-json/type/inherent_associated_type_projections.rs +++ b/tests/rustdoc-json/type/inherent_associated_type_projections.rs @@ -5,12 +5,12 @@ //@ set Parametrized = '$.index[*][?(@.name=="Parametrized")].id' pub struct Parametrized(T); -//@ count "$.index[*][?(@.name=='test')].inner.function.decl.inputs[*]" 1 -//@ is "$.index[*][?(@.name=='test')].inner.function.decl.inputs[0][0]" '"_"' -//@ is '$.index[*][?(@.name=="test")].inner.function.decl.inputs[0][1].qualified_path.self_type.resolved_path.id' $Parametrized -//@ is '$.index[*][?(@.name=="test")].inner.function.decl.inputs[0][1].qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].type.primitive' \"i32\" -//@ is '$.index[*][?(@.name=="test")].inner.function.decl.inputs[0][1].qualified_path.name' '"Proj"' -//@ is '$.index[*][?(@.name=="test")].inner.function.decl.inputs[0][1].qualified_path.trait' null +//@ count "$.index[*][?(@.name=='test')].inner.function.sig.inputs[*]" 1 +//@ is "$.index[*][?(@.name=='test')].inner.function.sig.inputs[0][0]" '"_"' +//@ is '$.index[*][?(@.name=="test")].inner.function.sig.inputs[0][1].qualified_path.self_type.resolved_path.id' $Parametrized +//@ is '$.index[*][?(@.name=="test")].inner.function.sig.inputs[0][1].qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].type.primitive' \"i32\" +//@ is '$.index[*][?(@.name=="test")].inner.function.sig.inputs[0][1].qualified_path.name' '"Proj"' +//@ is '$.index[*][?(@.name=="test")].inner.function.sig.inputs[0][1].qualified_path.trait' null pub fn test(_: Parametrized::Proj) {} /// param_bool diff --git a/tests/rustdoc-json/type_alias.rs b/tests/rustdoc-json/type_alias.rs index ecf35c5987ab5..2f2b4c42d441d 100644 --- a/tests/rustdoc-json/type_alias.rs +++ b/tests/rustdoc-json/type_alias.rs @@ -4,12 +4,12 @@ //@ is "$.index[*][?(@.name=='IntVec')].span.filename" $FILE pub type IntVec = Vec; -//@ is "$.index[*][?(@.name=='f')].inner.function.decl.output.resolved_path.id" $IntVec +//@ is "$.index[*][?(@.name=='f')].inner.function.sig.output.resolved_path.id" $IntVec pub fn f() -> IntVec { vec![0; 32] } -//@ !is "$.index[*][?(@.name=='g')].inner.function.decl.output.resolved_path.id" $IntVec +//@ !is "$.index[*][?(@.name=='g')].inner.function.sig.output.resolved_path.id" $IntVec pub fn g() -> Vec { vec![0; 32] } diff --git a/tests/rustdoc-json/unions/union.rs b/tests/rustdoc-json/unions/union.rs index 4a97b5d4fb8f0..7f135a72dec63 100644 --- a/tests/rustdoc-json/unions/union.rs +++ b/tests/rustdoc-json/unions/union.rs @@ -7,8 +7,8 @@ pub union Union { float: f32, } -//@ has "$.index[*][?(@.name=='make_int_union')].inner.function.decl.output.resolved_path" -//@ is "$.index[*][?(@.name=='make_int_union')].inner.function.decl.output.resolved_path.id" $Union +//@ has "$.index[*][?(@.name=='make_int_union')].inner.function.sig.output.resolved_path" +//@ is "$.index[*][?(@.name=='make_int_union')].inner.function.sig.output.resolved_path.id" $Union pub fn make_int_union(int: i32) -> Union { Union { int } } From 6c09243724aae85f3109a12913347d8affb1939b Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Mon, 2 Sep 2024 05:04:59 +0000 Subject: [PATCH 016/189] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 5a435a9f55bd3..4f14caf0e56c3 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -43eaa5c6246057b1675f42631967ad500eaf47d5 +e71f9529121ca8f687e4b725e3c9adc3f1ebab4d From 747f68091aa1c53ed4229b26a315ccd0ca2e267f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 2 Sep 2024 13:59:12 +1000 Subject: [PATCH 017/189] Use sysroot crates maximally in `rustc_codegen_gcc`. This shrinks `compiler/rustc_codegen_gcc/Cargo.lock` quite a bit. The only remaining dependencies in `compiler/rustc_codegen_gcc/Cargo.lock` are `gccjit`, `lang_tester`, and `boml`, all of which aren't used in any other compiler crates. The commit also reorders and adds comments to the `extern crate` items so they match those in miri. --- compiler/rustc_codegen_gcc/Cargo.lock | 176 -------------------------- compiler/rustc_codegen_gcc/Cargo.toml | 10 -- compiler/rustc_codegen_gcc/src/lib.rs | 10 +- 3 files changed, 8 insertions(+), 188 deletions(-) diff --git a/compiler/rustc_codegen_gcc/Cargo.lock b/compiler/rustc_codegen_gcc/Cargo.lock index 915229f7e7eef..0eb264f99eb08 100644 --- a/compiler/rustc_codegen_gcc/Cargo.lock +++ b/compiler/rustc_codegen_gcc/Cargo.lock @@ -11,63 +11,12 @@ dependencies = [ "memchr", ] -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" - [[package]] name = "boml" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85fdb93f04c73bff54305fa437ffea5449c41edcaadfe882f35836206b166ac5" -[[package]] -name = "cc" -version = "1.0.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "errno" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" -dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys", -] - -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "fastrand" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" - [[package]] name = "fm" version = "0.2.2" @@ -132,12 +81,6 @@ version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" -[[package]] -name = "linux-raw-sys" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" - [[package]] name = "memchr" version = "2.5.0" @@ -154,24 +97,6 @@ dependencies = [ "libc", ] -[[package]] -name = "object" -version = "0.30.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03b4680b86d9cfafba8fc491dc9b6df26b68cf40e9e6cd73909194759a63c385" -dependencies = [ - "memchr", -] - -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "regex" version = "1.8.4" @@ -196,22 +121,6 @@ dependencies = [ "boml", "gccjit", "lang_tester", - "object", - "smallvec", - "tempfile", -] - -[[package]] -name = "rustix" -version = "0.38.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ed4fa021d81c8392ce04db050a3da9a60299050b7ae1cf482d862b54a7218f" -dependencies = [ - "bitflags 2.4.0", - "errno", - "libc", - "linux-raw-sys", - "windows-sys", ] [[package]] @@ -223,25 +132,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "smallvec" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" - -[[package]] -name = "tempfile" -version = "3.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc02fddf48964c42031a0b3fe0428320ecf3a73c401040fc0096f97794310651" -dependencies = [ - "cfg-if", - "fastrand", - "redox_syscall", - "rustix", - "windows-sys", -] - [[package]] name = "termcolor" version = "1.2.0" @@ -315,69 +205,3 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.48.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" diff --git a/compiler/rustc_codegen_gcc/Cargo.toml b/compiler/rustc_codegen_gcc/Cargo.toml index 5caca63f63480..44fb5eef04a57 100644 --- a/compiler/rustc_codegen_gcc/Cargo.toml +++ b/compiler/rustc_codegen_gcc/Cargo.toml @@ -23,21 +23,11 @@ default = ["master"] [dependencies] gccjit = "2.1" - # Local copy. #gccjit = { path = "../gccjit.rs" } -object = { version = "0.30.1", default-features = false, features = [ - "std", - "read", -] } -smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } -# TODO(antoyo): make tempfile optional. -tempfile = "3.7.1" - [dev-dependencies] lang_tester = "0.8.0" -tempfile = "3.1.0" boml = "0.3.1" [profile.dev] diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index 94f016234f921..4de671ac4a062 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -24,6 +24,14 @@ #![deny(clippy::pattern_type_mismatch)] #![allow(clippy::needless_lifetimes)] +// Some "regular" crates we want to share with rustc +extern crate object; +extern crate smallvec; +extern crate tempfile; +#[macro_use] +extern crate tracing; + +// The rustc crates we need extern crate rustc_apfloat; extern crate rustc_ast; extern crate rustc_attr; @@ -42,8 +50,6 @@ extern crate rustc_middle; extern crate rustc_session; extern crate rustc_span; extern crate rustc_target; -#[macro_use] -extern crate tracing; // This prevents duplicating functions and statics that are already part of the host rustc process. #[allow(unused_extern_crates)] From a178559a03a11b5f6e716045e1b486ca29b2d543 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Mon, 2 Sep 2024 08:37:55 +0000 Subject: [PATCH 018/189] address review comments --- .../run-make/rustc-crates-on-stable/rmake.rs | 66 +++++++++---------- 1 file changed, 30 insertions(+), 36 deletions(-) diff --git a/tests/run-make/rustc-crates-on-stable/rmake.rs b/tests/run-make/rustc-crates-on-stable/rmake.rs index 48b8551ecef7c..81cc775c91997 100644 --- a/tests/run-make/rustc-crates-on-stable/rmake.rs +++ b/tests/run-make/rustc-crates-on-stable/rmake.rs @@ -1,42 +1,36 @@ //! Checks if selected rustc crates can be compiled on the stable channel (or a "simulation" of it). //! These crates are designed to be used by downstream users. -use run_make_support::{cargo, run_in_tmpdir, rustc_path, source_root}; +use run_make_support::{cargo, rustc_path, source_root}; fn main() { - run_in_tmpdir(|| { - // Use the stage0 beta cargo for the compilation (it shouldn't really matter which cargo we - // use) - let cargo = cargo() - // Ensure `proc-macro2`'s nightly detection is disabled - .env("RUSTC_STAGE", "0") - .env("RUSTC", rustc_path()) - // We want to disallow all nightly features to simulate a stable build - .env("RUSTFLAGS", "-Zallow-features=") - .arg("build") - .arg("--manifest-path") - .arg(source_root().join("Cargo.toml")) - .args(&[ - "--config", - r#"workspace.exclude=["library/core"]"#, - // Avoid depending on transitive rustc crates - "--no-default-features", - // Emit artifacts in this temporary directory, not in the source_root's `target` - // folder - "--target-dir", - ".", - ]) - // Check that these crates can be compiled on "stable" - .args(&[ - "-p", - "rustc_type_ir", - "-p", - "rustc_next_trait_solver", - "-p", - "rustc_pattern_analysis", - "-p", - "rustc_lexer", - ]) - .run(); - }); + // Use the stage0 beta cargo for the compilation (it shouldn't really matter which cargo we use) + cargo() + // Ensure `proc-macro2`'s nightly detection is disabled + .env("RUSTC_STAGE", "0") + .env("RUSTC", rustc_path()) + // We want to disallow all nightly features to simulate a stable build + .env("RUSTFLAGS", "-Zallow-features=") + .arg("build") + .arg("--manifest-path") + .arg(source_root().join("Cargo.toml")) + .args(&[ + // Avoid depending on transitive rustc crates + "--no-default-features", + // Emit artifacts in this temporary directory, not in the source_root's `target` folder + "--target-dir", + "target", + ]) + // Check that these crates can be compiled on "stable" + .args(&[ + "-p", + "rustc_type_ir", + "-p", + "rustc_next_trait_solver", + "-p", + "rustc_pattern_analysis", + "-p", + "rustc_lexer", + ]) + .run(); } From de96082152a4ecae3273381db9b571ceefa51e83 Mon Sep 17 00:00:00 2001 From: Jesse Rusak Date: Sun, 1 Sep 2024 16:13:58 -0400 Subject: [PATCH 019/189] Enable native libraries on macOS Fixes #3595 by using -fvisibility=hidden and the visibility attribute supported by both gcc and clang rather than the previous gcc-only mechanism for symbol hiding. Also brings over cfg changes from #3594 which enable native-lib functionality on all unixes. --- src/tools/miri/Cargo.toml | 2 -- src/tools/miri/README.md | 2 +- src/tools/miri/src/machine.rs | 10 +++++----- src/tools/miri/src/shims/foreign_items.rs | 2 +- src/tools/miri/src/shims/mod.rs | 2 +- .../native-lib/fail/function_not_in_so.rs | 4 +++- .../tests/native-lib/fail/private_function.rs | 15 ++++++++++++++ .../native-lib/fail/private_function.stderr | 15 ++++++++++++++ .../miri/tests/native-lib/native-lib.map | 20 ------------------- .../tests/native-lib/pass/ptr_read_access.rs | 4 +++- .../tests/native-lib/pass/scalar_arguments.rs | 4 +++- .../miri/tests/native-lib/ptr_read_access.c | 11 ++++++---- .../miri/tests/native-lib/scalar_arguments.c | 20 +++++++++++++------ src/tools/miri/tests/ui.rs | 19 +++++++++--------- 14 files changed, 78 insertions(+), 52 deletions(-) create mode 100644 src/tools/miri/tests/native-lib/fail/private_function.rs create mode 100644 src/tools/miri/tests/native-lib/fail/private_function.stderr delete mode 100644 src/tools/miri/tests/native-lib/native-lib.map diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml index 4b7f3483ff7db..d8cfa5b886dad 100644 --- a/src/tools/miri/Cargo.toml +++ b/src/tools/miri/Cargo.toml @@ -37,8 +37,6 @@ features = ['unprefixed_malloc_on_supported_platforms'] [target.'cfg(unix)'.dependencies] libc = "0.2" - -[target.'cfg(target_os = "linux")'.dependencies] libffi = "3.2.0" libloading = "0.8" diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md index 5821adb96ce29..dbb0e8a2925b3 100644 --- a/src/tools/miri/README.md +++ b/src/tools/miri/README.md @@ -383,7 +383,7 @@ to Miri failing to detect cases of undefined behavior in a program. file descriptors will be mixed up. This is **work in progress**; currently, only integer arguments and return values are supported (and no, pointer/integer casts to work around this limitation will not work; - they will fail horribly). It also only works on Linux hosts for now. + they will fail horribly). It also only works on Unix hosts for now. * `-Zmiri-measureme=` enables `measureme` profiling for the interpreted program. This can be used to find which parts of your program are executing slowly under Miri. The profile is written out to a file inside a directory called ``, and can be processed diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 331edf9c7ea31..2cd57e72871ba 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -535,9 +535,9 @@ pub struct MiriMachine<'tcx> { pub(crate) basic_block_count: u64, /// Handle of the optional shared object file for native functions. - #[cfg(target_os = "linux")] + #[cfg(unix)] pub native_lib: Option<(libloading::Library, std::path::PathBuf)>, - #[cfg(not(target_os = "linux"))] + #[cfg(not(unix))] pub native_lib: Option, /// Run a garbage collector for BorTags every N basic blocks. @@ -678,7 +678,7 @@ impl<'tcx> MiriMachine<'tcx> { report_progress: config.report_progress, basic_block_count: 0, clock: Clock::new(config.isolated_op == IsolatedOp::Allow), - #[cfg(target_os = "linux")] + #[cfg(unix)] native_lib: config.native_lib.as_ref().map(|lib_file_path| { let target_triple = layout_cx.tcx.sess.opts.target_triple.triple(); // Check if host target == the session target. @@ -700,9 +700,9 @@ impl<'tcx> MiriMachine<'tcx> { lib_file_path.clone(), ) }), - #[cfg(not(target_os = "linux"))] + #[cfg(not(unix))] native_lib: config.native_lib.as_ref().map(|_| { - panic!("loading external .so files is only supported on Linux") + panic!("calling functions from native libraries via FFI is only supported on Unix") }), gc_interval: config.gc_interval, since_gc: 0, diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index d40dbdba80f1e..1b45bc22038b1 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -226,7 +226,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { let this = self.eval_context_mut(); // First deal with any external C functions in linked .so file. - #[cfg(target_os = "linux")] + #[cfg(unix)] if this.machine.native_lib.as_ref().is_some() { use crate::shims::native_lib::EvalContextExt as _; // An Ok(false) here means that the function being called was not exported diff --git a/src/tools/miri/src/shims/mod.rs b/src/tools/miri/src/shims/mod.rs index 7d5349f26b127..618cf8cf200c1 100644 --- a/src/tools/miri/src/shims/mod.rs +++ b/src/tools/miri/src/shims/mod.rs @@ -2,7 +2,7 @@ mod alloc; mod backtrace; -#[cfg(target_os = "linux")] +#[cfg(unix)] mod native_lib; mod unix; mod wasi; diff --git a/src/tools/miri/tests/native-lib/fail/function_not_in_so.rs b/src/tools/miri/tests/native-lib/fail/function_not_in_so.rs index 3540c75b73a12..c532d05224537 100644 --- a/src/tools/miri/tests/native-lib/fail/function_not_in_so.rs +++ b/src/tools/miri/tests/native-lib/fail/function_not_in_so.rs @@ -1,4 +1,6 @@ -//@only-target-linux +// Only works on Unix targets +//@ignore-target-windows +//@ignore-target-wasm //@only-on-host //@normalize-stderr-test: "OS `.*`" -> "$$OS" diff --git a/src/tools/miri/tests/native-lib/fail/private_function.rs b/src/tools/miri/tests/native-lib/fail/private_function.rs new file mode 100644 index 0000000000000..3c6fda741dd70 --- /dev/null +++ b/src/tools/miri/tests/native-lib/fail/private_function.rs @@ -0,0 +1,15 @@ +// Only works on Unix targets +//@ignore-target-windows +//@ignore-target-wasm +//@only-on-host +//@normalize-stderr-test: "OS `.*`" -> "$$OS" + +extern "C" { + fn not_exported(); +} + +fn main() { + unsafe { + not_exported(); //~ ERROR: unsupported operation: can't call foreign function `not_exported` + } +} diff --git a/src/tools/miri/tests/native-lib/fail/private_function.stderr b/src/tools/miri/tests/native-lib/fail/private_function.stderr new file mode 100644 index 0000000000000..e27a501ebb9d8 --- /dev/null +++ b/src/tools/miri/tests/native-lib/fail/private_function.stderr @@ -0,0 +1,15 @@ +error: unsupported operation: can't call foreign function `not_exported` on $OS + --> $DIR/private_function.rs:LL:CC + | +LL | not_exported(); + | ^^^^^^^^^^^^^^ can't call foreign function `not_exported` on $OS + | + = help: if this is a basic API commonly used on this target, please report an issue with Miri + = help: however, note that Miri does not aim to support every FFI function out there; for instance, we will not support APIs for things such as GUIs, scripting languages, or databases + = note: BACKTRACE: + = note: inside `main` at $DIR/private_function.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/native-lib/native-lib.map b/src/tools/miri/tests/native-lib/native-lib.map deleted file mode 100644 index 7e3bd19622af3..0000000000000 --- a/src/tools/miri/tests/native-lib/native-lib.map +++ /dev/null @@ -1,20 +0,0 @@ -CODEABI_1.0 { - # Define which symbols to export. - global: - # scalar_arguments.c - add_one_int; - printer; - test_stack_spill; - get_unsigned_int; - add_int16; - add_short_to_long; - - # ptr_read_access.c - print_pointer; - access_simple; - access_nested; - access_static; - - # The rest remains private. - local: *; -}; diff --git a/src/tools/miri/tests/native-lib/pass/ptr_read_access.rs b/src/tools/miri/tests/native-lib/pass/ptr_read_access.rs index 77a73deddedb8..2990dfa89756c 100644 --- a/src/tools/miri/tests/native-lib/pass/ptr_read_access.rs +++ b/src/tools/miri/tests/native-lib/pass/ptr_read_access.rs @@ -1,4 +1,6 @@ -//@only-target-linux +// Only works on Unix targets +//@ignore-target-windows +//@ignore-target-wasm //@only-on-host fn main() { diff --git a/src/tools/miri/tests/native-lib/pass/scalar_arguments.rs b/src/tools/miri/tests/native-lib/pass/scalar_arguments.rs index 1e1d0b11e99ff..378baa7ce98de 100644 --- a/src/tools/miri/tests/native-lib/pass/scalar_arguments.rs +++ b/src/tools/miri/tests/native-lib/pass/scalar_arguments.rs @@ -1,4 +1,6 @@ -//@only-target-linux +// Only works on Unix targets +//@ignore-target-windows +//@ignore-target-wasm //@only-on-host extern "C" { diff --git a/src/tools/miri/tests/native-lib/ptr_read_access.c b/src/tools/miri/tests/native-lib/ptr_read_access.c index 03b9189e2e86d..540845d53a744 100644 --- a/src/tools/miri/tests/native-lib/ptr_read_access.c +++ b/src/tools/miri/tests/native-lib/ptr_read_access.c @@ -1,8 +1,11 @@ #include +// See comments in build_native_lib() +#define EXPORT __attribute__((visibility("default"))) + /* Test: test_pointer */ -void print_pointer(const int *ptr) { +EXPORT void print_pointer(const int *ptr) { printf("printing pointer dereference from C: %d\n", *ptr); } @@ -12,7 +15,7 @@ typedef struct Simple { int field; } Simple; -int access_simple(const Simple *s_ptr) { +EXPORT int access_simple(const Simple *s_ptr) { return s_ptr->field; } @@ -24,7 +27,7 @@ typedef struct Nested { } Nested; // Returns the innermost/last value of a Nested pointer chain. -int access_nested(const Nested *n_ptr) { +EXPORT int access_nested(const Nested *n_ptr) { // Edge case: `n_ptr == NULL` (i.e. first Nested is None). if (!n_ptr) { return 0; } @@ -42,6 +45,6 @@ typedef struct Static { struct Static *recurse; } Static; -int access_static(const Static *s_ptr) { +EXPORT int access_static(const Static *s_ptr) { return s_ptr->recurse->recurse->value; } diff --git a/src/tools/miri/tests/native-lib/scalar_arguments.c b/src/tools/miri/tests/native-lib/scalar_arguments.c index 68714f1743b6e..6da730a498724 100644 --- a/src/tools/miri/tests/native-lib/scalar_arguments.c +++ b/src/tools/miri/tests/native-lib/scalar_arguments.c @@ -1,27 +1,35 @@ #include -int add_one_int(int x) { +// See comments in build_native_lib() +#define EXPORT __attribute__((visibility("default"))) + +EXPORT int add_one_int(int x) { return 2 + x; } -void printer() { +EXPORT void printer(void) { printf("printing from C\n"); } // function with many arguments, to test functionality when some args are stored // on the stack -int test_stack_spill(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l) { +EXPORT int test_stack_spill(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l) { return a+b+c+d+e+f+g+h+i+j+k+l; } -unsigned int get_unsigned_int() { +EXPORT unsigned int get_unsigned_int(void) { return -10; } -short add_int16(short x) { +EXPORT short add_int16(short x) { return x + 3; } -long add_short_to_long(short x, long y) { +EXPORT long add_short_to_long(short x, long y) { return x + y; } + +// To test that functions not marked with EXPORT cannot be called by Miri. +int not_exported(void) { + return 0; +} diff --git a/src/tools/miri/tests/ui.rs b/src/tools/miri/tests/ui.rs index c510ef95c30e8..e62394bc499f1 100644 --- a/src/tools/miri/tests/ui.rs +++ b/src/tools/miri/tests/ui.rs @@ -36,20 +36,21 @@ fn build_native_lib() -> PathBuf { // Create the directory if it does not already exist. std::fs::create_dir_all(&so_target_dir) .expect("Failed to create directory for shared object file"); - let so_file_path = so_target_dir.join("native-lib.so"); + // We use a platform-neutral file extension to avoid having to hard-code alternatives. + let native_lib_path = so_target_dir.join("native-lib.module"); let cc_output = Command::new(cc) .args([ "-shared", + "-fPIC", + // We hide all symbols by default and export just the ones we need + // This is to future-proof against a more complex shared object which eg defines its own malloc + // (but we wouldn't want miri to call that, as it would if it was exported). + "-fvisibility=hidden", "-o", - so_file_path.to_str().unwrap(), + native_lib_path.to_str().unwrap(), // FIXME: Automate gathering of all relevant C source files in the directory. "tests/native-lib/scalar_arguments.c", "tests/native-lib/ptr_read_access.c", - // Only add the functions specified in libcode.version to the shared object file. - // This is to avoid automatically adding `malloc`, etc. - // Source: https://anadoxin.org/blog/control-over-symbol-exports-in-gcc.html/ - "-fPIC", - "-Wl,--version-script=tests/native-lib/native-lib.map", // Ensure we notice serious problems in the C code. "-Wall", "-Wextra", @@ -64,7 +65,7 @@ fn build_native_lib() -> PathBuf { String::from_utf8_lossy(&cc_output.stderr), ); } - so_file_path + native_lib_path } /// Does *not* set any args or env vars, since it is shared between the test runner and @@ -300,7 +301,7 @@ fn main() -> Result<()> { WithDependencies, tmpdir.path(), )?; - if cfg!(target_os = "linux") { + if cfg!(unix) { ui(Mode::Pass, "tests/native-lib/pass", &target, WithoutDependencies, tmpdir.path())?; ui( Mode::Fail { require_patterns: true, rustfix: RustfixMode::Disabled }, From d4b246bb117d451e34f1692fa34f9574b3d169e4 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 4 Sep 2024 16:39:23 -0700 Subject: [PATCH 020/189] rustdoc: unify the short-circuit on all lints This is a bit of an experiment to see if it improves perf. --- src/librustdoc/passes/lint.rs | 33 ++- src/librustdoc/passes/lint/bare_urls.rs | 68 +++-- .../passes/lint/check_code_block_syntax.rs | 6 +- src/librustdoc/passes/lint/html_tags.rs | 248 +++++++++--------- .../passes/lint/redundant_explicit_links.rs | 7 +- .../passes/lint/unescaped_backticks.rs | 12 +- .../passes/lint/unportable_markdown.rs | 12 +- 7 files changed, 184 insertions(+), 202 deletions(-) diff --git a/src/librustdoc/passes/lint.rs b/src/librustdoc/passes/lint.rs index bc804a340bf2c..4da5d8f0e0663 100644 --- a/src/librustdoc/passes/lint.rs +++ b/src/librustdoc/passes/lint.rs @@ -27,12 +27,33 @@ pub(crate) fn run_lints(krate: Crate, cx: &mut DocContext<'_>) -> Crate { impl<'a, 'tcx> DocVisitor for Linter<'a, 'tcx> { fn visit_item(&mut self, item: &Item) { - bare_urls::visit_item(self.cx, item); - check_code_block_syntax::visit_item(self.cx, item); - html_tags::visit_item(self.cx, item); - unescaped_backticks::visit_item(self.cx, item); - redundant_explicit_links::visit_item(self.cx, item); - unportable_markdown::visit_item(self.cx, item); + let Some(hir_id) = DocContext::as_local_hir_id(self.cx.tcx, item.item_id) else { + // If non-local, no need to check anything. + return; + }; + let dox = item.doc_value(); + if !dox.is_empty() { + let may_have_link = dox.contains(&[':', '['][..]); + let may_have_block_comment_or_html = dox.contains(&['<', '>']); + // ~~~rust + // // This is a real, supported commonmark syntax for block code + // ~~~ + let may_have_code = dox.contains(&['~', '`', '\t'][..]) || dox.contains(" "); + if may_have_link { + bare_urls::visit_item(self.cx, item, hir_id, &dox); + redundant_explicit_links::visit_item(self.cx, item, hir_id); + } + if may_have_code { + check_code_block_syntax::visit_item(self.cx, item, &dox); + unescaped_backticks::visit_item(self.cx, item, hir_id, &dox); + } + if may_have_block_comment_or_html { + html_tags::visit_item(self.cx, item, hir_id, &dox); + unportable_markdown::visit_item(self.cx, item, hir_id, &dox); + } else if may_have_link { + unportable_markdown::visit_item(self.cx, item, hir_id, &dox); + } + } self.visit_item_recur(item) } diff --git a/src/librustdoc/passes/lint/bare_urls.rs b/src/librustdoc/passes/lint/bare_urls.rs index 22051dd954db3..bac0e07f1c108 100644 --- a/src/librustdoc/passes/lint/bare_urls.rs +++ b/src/librustdoc/passes/lint/bare_urls.rs @@ -8,6 +8,7 @@ use std::sync::LazyLock; use pulldown_cmark::{Event, Parser, Tag}; use regex::Regex; use rustc_errors::Applicability; +use rustc_hir::HirId; use rustc_resolve::rustdoc::source_span_for_markdown_range; use tracing::trace; @@ -15,50 +16,43 @@ use crate::clean::*; use crate::core::DocContext; use crate::html::markdown::main_body_opts; -pub(super) fn visit_item(cx: &DocContext<'_>, item: &Item) { - let Some(hir_id) = DocContext::as_local_hir_id(cx.tcx, item.item_id) else { - // If non-local, no need to check anything. - return; +pub(super) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: &str) { + let report_diag = |cx: &DocContext<'_>, msg: &'static str, range: Range| { + let sp = source_span_for_markdown_range(cx.tcx, &dox, &range, &item.attrs.doc_strings) + .unwrap_or_else(|| item.attr_span(cx.tcx)); + cx.tcx.node_span_lint(crate::lint::BARE_URLS, hir_id, sp, |lint| { + lint.primary_message(msg) + .note("bare URLs are not automatically turned into clickable links") + .multipart_suggestion( + "use an automatic link instead", + vec![ + (sp.shrink_to_lo(), "<".to_string()), + (sp.shrink_to_hi(), ">".to_string()), + ], + Applicability::MachineApplicable, + ); + }); }; - let dox = item.doc_value(); - if !dox.is_empty() { - let report_diag = |cx: &DocContext<'_>, msg: &'static str, range: Range| { - let sp = source_span_for_markdown_range(cx.tcx, &dox, &range, &item.attrs.doc_strings) - .unwrap_or_else(|| item.attr_span(cx.tcx)); - cx.tcx.node_span_lint(crate::lint::BARE_URLS, hir_id, sp, |lint| { - lint.primary_message(msg) - .note("bare URLs are not automatically turned into clickable links") - .multipart_suggestion( - "use an automatic link instead", - vec![ - (sp.shrink_to_lo(), "<".to_string()), - (sp.shrink_to_hi(), ">".to_string()), - ], - Applicability::MachineApplicable, - ); - }); - }; - let mut p = Parser::new_ext(&dox, main_body_opts()).into_offset_iter(); + let mut p = Parser::new_ext(&dox, main_body_opts()).into_offset_iter(); - while let Some((event, range)) = p.next() { - match event { - Event::Text(s) => find_raw_urls(cx, &s, range, &report_diag), - // We don't want to check the text inside code blocks or links. - Event::Start(tag @ (Tag::CodeBlock(_) | Tag::Link { .. })) => { - while let Some((event, _)) = p.next() { - match event { - Event::End(end) - if mem::discriminant(&end) == mem::discriminant(&tag.to_end()) => - { - break; - } - _ => {} + while let Some((event, range)) = p.next() { + match event { + Event::Text(s) => find_raw_urls(cx, &s, range, &report_diag), + // We don't want to check the text inside code blocks or links. + Event::Start(tag @ (Tag::CodeBlock(_) | Tag::Link { .. })) => { + while let Some((event, _)) = p.next() { + match event { + Event::End(end) + if mem::discriminant(&end) == mem::discriminant(&tag.to_end()) => + { + break; } + _ => {} } } - _ => {} } + _ => {} } } } diff --git a/src/librustdoc/passes/lint/check_code_block_syntax.rs b/src/librustdoc/passes/lint/check_code_block_syntax.rs index 977c095333641..1b2431a629b94 100644 --- a/src/librustdoc/passes/lint/check_code_block_syntax.rs +++ b/src/librustdoc/passes/lint/check_code_block_syntax.rs @@ -15,10 +15,8 @@ use crate::clean; use crate::core::DocContext; use crate::html::markdown::{self, RustCodeBlock}; -pub(crate) fn visit_item(cx: &DocContext<'_>, item: &clean::Item) { - if let Some(def_id) = item.item_id.as_local_def_id() - && let Some(dox) = &item.opt_doc_value() - { +pub(crate) fn visit_item(cx: &DocContext<'_>, item: &clean::Item, dox: &str) { + if let Some(def_id) = item.item_id.as_local_def_id() { let sp = item.attr_span(cx.tcx); let extra = crate::html::markdown::ExtraInfo::new(cx.tcx, def_id, sp); for code_block in markdown::rust_code_blocks(dox, &extra) { diff --git a/src/librustdoc/passes/lint/html_tags.rs b/src/librustdoc/passes/lint/html_tags.rs index 6f9e9d36a5c57..223174838ade0 100644 --- a/src/librustdoc/passes/lint/html_tags.rs +++ b/src/librustdoc/passes/lint/html_tags.rs @@ -5,159 +5,149 @@ use std::ops::Range; use std::str::CharIndices; use pulldown_cmark::{BrokenLink, Event, LinkType, Parser, Tag, TagEnd}; +use rustc_hir::HirId; use rustc_resolve::rustdoc::source_span_for_markdown_range; use crate::clean::*; use crate::core::DocContext; use crate::html::markdown::main_body_opts; -pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) { +pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: &str) { let tcx = cx.tcx; - let Some(hir_id) = DocContext::as_local_hir_id(tcx, item.item_id) - // If non-local, no need to check anything. - else { - return; - }; - let dox = item.doc_value(); - if !dox.is_empty() { - let report_diag = |msg: String, range: &Range, is_open_tag: bool| { - let sp = match source_span_for_markdown_range(tcx, &dox, range, &item.attrs.doc_strings) - { - Some(sp) => sp, - None => item.attr_span(tcx), - }; - tcx.node_span_lint(crate::lint::INVALID_HTML_TAGS, hir_id, sp, |lint| { - use rustc_lint_defs::Applicability; + let report_diag = |msg: String, range: &Range, is_open_tag: bool| { + let sp = match source_span_for_markdown_range(tcx, &dox, range, &item.attrs.doc_strings) { + Some(sp) => sp, + None => item.attr_span(tcx), + }; + tcx.node_span_lint(crate::lint::INVALID_HTML_TAGS, hir_id, sp, |lint| { + use rustc_lint_defs::Applicability; - lint.primary_message(msg); + lint.primary_message(msg); - // If a tag looks like ``, it might actually be a generic. - // We don't try to detect stuff `` because that's not valid HTML, - // and we don't try to detect stuff `` because that's not valid Rust. - let mut generics_end = range.end; - if let Some(Some(mut generics_start)) = (is_open_tag - && dox[..generics_end].ends_with('>')) - .then(|| extract_path_backwards(&dox, range.start)) + // If a tag looks like ``, it might actually be a generic. + // We don't try to detect stuff `` because that's not valid HTML, + // and we don't try to detect stuff `` because that's not valid Rust. + let mut generics_end = range.end; + if let Some(Some(mut generics_start)) = (is_open_tag + && dox[..generics_end].ends_with('>')) + .then(|| extract_path_backwards(&dox, range.start)) + { + while generics_start != 0 + && generics_end < dox.len() + && dox.as_bytes()[generics_start - 1] == b'<' + && dox.as_bytes()[generics_end] == b'>' { - while generics_start != 0 - && generics_end < dox.len() - && dox.as_bytes()[generics_start - 1] == b'<' - && dox.as_bytes()[generics_end] == b'>' - { - generics_end += 1; - generics_start -= 1; - if let Some(new_start) = extract_path_backwards(&dox, generics_start) { - generics_start = new_start; - } - if let Some(new_end) = extract_path_forward(&dox, generics_end) { - generics_end = new_end; - } + generics_end += 1; + generics_start -= 1; + if let Some(new_start) = extract_path_backwards(&dox, generics_start) { + generics_start = new_start; } if let Some(new_end) = extract_path_forward(&dox, generics_end) { generics_end = new_end; } - let generics_sp = match source_span_for_markdown_range( - tcx, - &dox, - &(generics_start..generics_end), - &item.attrs.doc_strings, - ) { - Some(sp) => sp, - None => item.attr_span(tcx), - }; - // Sometimes, we only extract part of a path. For example, consider this: - // - // <[u32] as IntoIter>::Item - // ^^^^^ unclosed HTML tag `u32` - // - // We don't have any code for parsing fully-qualified trait paths. - // In theory, we could add it, but doing it correctly would require - // parsing the entire path grammar, which is problematic because of - // overlap between the path grammar and Markdown. - // - // The example above shows that ambiguity. Is `[u32]` intended to be an - // intra-doc link to the u32 primitive, or is it intended to be a slice? - // - // If the below conditional were removed, we would suggest this, which is - // not what the user probably wants. - // - // <[u32] as `IntoIter`>::Item - // - // We know that the user actually wants to wrap the whole thing in a code - // block, but the only reason we know that is because `u32` does not, in - // fact, implement IntoIter. If the example looks like this: - // - // <[Vec] as IntoIter::Item - // - // The ideal fix would be significantly different. - if (generics_start > 0 && dox.as_bytes()[generics_start - 1] == b'<') - || (generics_end < dox.len() && dox.as_bytes()[generics_end] == b'>') - { - return; - } - // multipart form is chosen here because ``Vec`` would be confusing. - lint.multipart_suggestion( - "try marking as source code", - vec![ - (generics_sp.shrink_to_lo(), String::from("`")), - (generics_sp.shrink_to_hi(), String::from("`")), - ], - Applicability::MaybeIncorrect, - ); } - }); - }; + if let Some(new_end) = extract_path_forward(&dox, generics_end) { + generics_end = new_end; + } + let generics_sp = match source_span_for_markdown_range( + tcx, + &dox, + &(generics_start..generics_end), + &item.attrs.doc_strings, + ) { + Some(sp) => sp, + None => item.attr_span(tcx), + }; + // Sometimes, we only extract part of a path. For example, consider this: + // + // <[u32] as IntoIter>::Item + // ^^^^^ unclosed HTML tag `u32` + // + // We don't have any code for parsing fully-qualified trait paths. + // In theory, we could add it, but doing it correctly would require + // parsing the entire path grammar, which is problematic because of + // overlap between the path grammar and Markdown. + // + // The example above shows that ambiguity. Is `[u32]` intended to be an + // intra-doc link to the u32 primitive, or is it intended to be a slice? + // + // If the below conditional were removed, we would suggest this, which is + // not what the user probably wants. + // + // <[u32] as `IntoIter`>::Item + // + // We know that the user actually wants to wrap the whole thing in a code + // block, but the only reason we know that is because `u32` does not, in + // fact, implement IntoIter. If the example looks like this: + // + // <[Vec] as IntoIter::Item + // + // The ideal fix would be significantly different. + if (generics_start > 0 && dox.as_bytes()[generics_start - 1] == b'<') + || (generics_end < dox.len() && dox.as_bytes()[generics_end] == b'>') + { + return; + } + // multipart form is chosen here because ``Vec`` would be confusing. + lint.multipart_suggestion( + "try marking as source code", + vec![ + (generics_sp.shrink_to_lo(), String::from("`")), + (generics_sp.shrink_to_hi(), String::from("`")), + ], + Applicability::MaybeIncorrect, + ); + } + }); + }; - let mut tags = Vec::new(); - let mut is_in_comment = None; - let mut in_code_block = false; + let mut tags = Vec::new(); + let mut is_in_comment = None; + let mut in_code_block = false; - let link_names = item.link_names(&cx.cache); + let link_names = item.link_names(&cx.cache); - let mut replacer = |broken_link: BrokenLink<'_>| { - if let Some(link) = - link_names.iter().find(|link| *link.original_text == *broken_link.reference) - { - Some((link.href.as_str().into(), link.new_text.to_string().into())) - } else if matches!( - &broken_link.link_type, - LinkType::Reference | LinkType::ReferenceUnknown - ) { - // If the link is shaped [like][this], suppress any broken HTML in the [this] part. - // The `broken_intra_doc_links` will report typos in there anyway. - Some(( - broken_link.reference.to_string().into(), - broken_link.reference.to_string().into(), - )) - } else { - None - } - }; + let mut replacer = |broken_link: BrokenLink<'_>| { + if let Some(link) = + link_names.iter().find(|link| *link.original_text == *broken_link.reference) + { + Some((link.href.as_str().into(), link.new_text.to_string().into())) + } else if matches!(&broken_link.link_type, LinkType::Reference | LinkType::ReferenceUnknown) + { + // If the link is shaped [like][this], suppress any broken HTML in the [this] part. + // The `broken_intra_doc_links` will report typos in there anyway. + Some(( + broken_link.reference.to_string().into(), + broken_link.reference.to_string().into(), + )) + } else { + None + } + }; - let p = Parser::new_with_broken_link_callback(&dox, main_body_opts(), Some(&mut replacer)) - .into_offset_iter(); + let p = Parser::new_with_broken_link_callback(&dox, main_body_opts(), Some(&mut replacer)) + .into_offset_iter(); - for (event, range) in p { - match event { - Event::Start(Tag::CodeBlock(_)) => in_code_block = true, - Event::Html(text) | Event::InlineHtml(text) if !in_code_block => { - extract_tags(&mut tags, &text, range, &mut is_in_comment, &report_diag) - } - Event::End(TagEnd::CodeBlock) => in_code_block = false, - _ => {} + for (event, range) in p { + match event { + Event::Start(Tag::CodeBlock(_)) => in_code_block = true, + Event::Html(text) | Event::InlineHtml(text) if !in_code_block => { + extract_tags(&mut tags, &text, range, &mut is_in_comment, &report_diag) } + Event::End(TagEnd::CodeBlock) => in_code_block = false, + _ => {} } + } - for (tag, range) in tags.iter().filter(|(t, _)| { - let t = t.to_lowercase(); - !ALLOWED_UNCLOSED.contains(&t.as_str()) - }) { - report_diag(format!("unclosed HTML tag `{tag}`"), range, true); - } + for (tag, range) in tags.iter().filter(|(t, _)| { + let t = t.to_lowercase(); + !ALLOWED_UNCLOSED.contains(&t.as_str()) + }) { + report_diag(format!("unclosed HTML tag `{tag}`"), range, true); + } - if let Some(range) = is_in_comment { - report_diag("Unclosed HTML comment".to_string(), &range, false); - } + if let Some(range) = is_in_comment { + report_diag("Unclosed HTML comment".to_string(), &range, false); } } diff --git a/src/librustdoc/passes/lint/redundant_explicit_links.rs b/src/librustdoc/passes/lint/redundant_explicit_links.rs index 0a90c039dfbcb..9c37e11349a32 100644 --- a/src/librustdoc/passes/lint/redundant_explicit_links.rs +++ b/src/librustdoc/passes/lint/redundant_explicit_links.rs @@ -24,12 +24,7 @@ struct LinkData { display_link: String, } -pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) { - let Some(hir_id) = DocContext::as_local_hir_id(cx.tcx, item.item_id) else { - // If non-local, no need to check anything. - return; - }; - +pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId) { let hunks = prepare_to_doc_link_resolution(&item.attrs.doc_strings); for (item_id, doc) in hunks { if let Some(item_id) = item_id.or(item.def_id()) diff --git a/src/librustdoc/passes/lint/unescaped_backticks.rs b/src/librustdoc/passes/lint/unescaped_backticks.rs index a6c8db16f829b..d79f682a580f8 100644 --- a/src/librustdoc/passes/lint/unescaped_backticks.rs +++ b/src/librustdoc/passes/lint/unescaped_backticks.rs @@ -4,6 +4,7 @@ use std::ops::Range; use pulldown_cmark::{BrokenLink, Event, Parser}; use rustc_errors::Diag; +use rustc_hir::HirId; use rustc_lint_defs::Applicability; use rustc_resolve::rustdoc::source_span_for_markdown_range; @@ -11,17 +12,8 @@ use crate::clean::Item; use crate::core::DocContext; use crate::html::markdown::main_body_opts; -pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) { +pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: &str) { let tcx = cx.tcx; - let Some(hir_id) = DocContext::as_local_hir_id(tcx, item.item_id) else { - // If non-local, no need to check anything. - return; - }; - - let dox = item.doc_value(); - if dox.is_empty() { - return; - } let link_names = item.link_names(&cx.cache); let mut replacer = |broken_link: BrokenLink<'_>| { diff --git a/src/librustdoc/passes/lint/unportable_markdown.rs b/src/librustdoc/passes/lint/unportable_markdown.rs index 87fe0055883c2..f8368a866c882 100644 --- a/src/librustdoc/passes/lint/unportable_markdown.rs +++ b/src/librustdoc/passes/lint/unportable_markdown.rs @@ -12,6 +12,7 @@ use std::collections::{BTreeMap, BTreeSet}; +use rustc_hir::HirId; use rustc_lint_defs::Applicability; use rustc_resolve::rustdoc::source_span_for_markdown_range; use {pulldown_cmark as cmarkn, pulldown_cmark_old as cmarko}; @@ -19,17 +20,8 @@ use {pulldown_cmark as cmarkn, pulldown_cmark_old as cmarko}; use crate::clean::Item; use crate::core::DocContext; -pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) { +pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: &str) { let tcx = cx.tcx; - let Some(hir_id) = DocContext::as_local_hir_id(tcx, item.item_id) else { - // If non-local, no need to check anything. - return; - }; - - let dox = item.doc_value(); - if dox.is_empty() { - return; - } // P1: unintended strikethrough was fixed by requiring single-tildes to flank // the same way underscores do, so nothing is done here From 5f22103395c513a5dffcbe7c10b207900ce61967 Mon Sep 17 00:00:00 2001 From: Konstantinos Andrikopoulos Date: Sat, 27 Jul 2024 22:26:57 +0200 Subject: [PATCH 021/189] Detect pthread_mutex_t is moved See: #3749 --- src/tools/miri/src/concurrency/init_once.rs | 10 +- src/tools/miri/src/concurrency/sync.rs | 119 +++++++++- src/tools/miri/src/lib.rs | 5 +- src/tools/miri/src/shims/unix/macos/sync.rs | 2 +- src/tools/miri/src/shims/unix/sync.rs | 222 ++++++++++-------- .../libc_pthread_mutex_move.init.stderr | 20 ++ .../concurrency/libc_pthread_mutex_move.rs | 28 +++ ...hread_mutex_move.static_initializer.stderr | 20 ++ 8 files changed, 310 insertions(+), 116 deletions(-) create mode 100644 src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.init.stderr create mode 100644 src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.rs create mode 100644 src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.static_initializer.stderr diff --git a/src/tools/miri/src/concurrency/init_once.rs b/src/tools/miri/src/concurrency/init_once.rs index c23e5737280e7..d709e4e6eaedb 100644 --- a/src/tools/miri/src/concurrency/init_once.rs +++ b/src/tools/miri/src/concurrency/init_once.rs @@ -35,8 +35,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { offset: u64, ) -> InterpResult<'tcx, InitOnceId> { let this = self.eval_context_mut(); - this.get_or_create_id(lock_op, lock_layout, offset, |ecx| &mut ecx.machine.sync.init_onces)? - .ok_or_else(|| err_ub_format!("init_once has invalid ID").into()) + this.get_or_create_id( + lock_op, + lock_layout, + offset, + |ecx| &mut ecx.machine.sync.init_onces, + |_| Ok(Default::default()), + )? + .ok_or_else(|| err_ub_format!("init_once has invalid ID").into()) } #[inline] diff --git a/src/tools/miri/src/concurrency/sync.rs b/src/tools/miri/src/concurrency/sync.rs index d972831c7689f..97e910df6a2c0 100644 --- a/src/tools/miri/src/concurrency/sync.rs +++ b/src/tools/miri/src/concurrency/sync.rs @@ -66,6 +66,27 @@ pub(super) use declare_id; declare_id!(MutexId); +/// The mutex kind. +#[derive(Debug, Clone, Copy)] +#[non_exhaustive] +pub enum MutexKind { + Invalid, + Normal, + Default, + Recursive, + ErrorCheck, +} + +#[derive(Debug)] +/// Additional data that may be used by shim implementations. +pub struct AdditionalMutexData { + /// The mutex kind, used by some mutex implementations like pthreads mutexes. + pub kind: MutexKind, + + /// The address of the mutex. + pub address: u64, +} + /// The mutex state. #[derive(Default, Debug)] struct Mutex { @@ -77,6 +98,9 @@ struct Mutex { queue: VecDeque, /// Mutex clock. This tracks the moment of the last unlock. clock: VClock, + + /// Additional data that can be set by shim implementations. + data: Option, } declare_id!(RwLockId); @@ -168,13 +192,15 @@ pub(super) trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { /// Returns `None` if memory stores a non-zero invalid ID. /// /// `get_objs` must return the `IndexVec` that stores all the objects of this type. + /// `create_obj` must create the new object if initialization is needed. #[inline] - fn get_or_create_id( + fn get_or_create_id( &mut self, lock_op: &OpTy<'tcx>, lock_layout: TyAndLayout<'tcx>, offset: u64, get_objs: impl for<'a> Fn(&'a mut MiriInterpCx<'tcx>) -> &'a mut IndexVec, + create_obj: impl for<'a> FnOnce(&'a mut MiriInterpCx<'tcx>) -> InterpResult<'tcx, T>, ) -> InterpResult<'tcx, Option> { let this = self.eval_context_mut(); let value_place = @@ -196,7 +222,8 @@ pub(super) trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { Ok(if success.to_bool().expect("compare_exchange's second return value is a bool") { // We set the in-memory ID to `next_index`, now also create this object in the machine // state. - let new_index = get_objs(this).push(T::default()); + let obj = create_obj(this)?; + let new_index = get_objs(this).push(obj); assert_eq!(next_index, new_index); Some(new_index) } else { @@ -210,6 +237,32 @@ pub(super) trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { }) } + /// Eagerly creates a Miri sync structure. + /// + /// `create_id` will store the index of the sync_structure in the memory pointed to by + /// `lock_op`, so that future calls to `get_or_create_id` will see it as initialized. + /// - `lock_op` must hold a pointer to the sync structure. + /// - `lock_layout` must be the memory layout of the sync structure. + /// - `offset` must be the offset inside the sync structure where its miri id will be stored. + /// - `get_objs` is described in `get_or_create_id`. + /// - `obj` must be the new sync object. + fn create_id( + &mut self, + lock_op: &OpTy<'tcx>, + lock_layout: TyAndLayout<'tcx>, + offset: u64, + get_objs: impl for<'a> Fn(&'a mut MiriInterpCx<'tcx>) -> &'a mut IndexVec, + obj: T, + ) -> InterpResult<'tcx, Id> { + let this = self.eval_context_mut(); + let value_place = + this.deref_pointer_and_offset(lock_op, offset, lock_layout, this.machine.layouts.u32)?; + + let new_index = get_objs(this).push(obj); + this.write_scalar(Scalar::from_u32(new_index.to_u32()), &value_place)?; + Ok(new_index) + } + fn condvar_reacquire_mutex( &mut self, mutex: MutexId, @@ -236,15 +289,53 @@ pub(super) trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { // situations. impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { + /// Eagerly create and initialize a new mutex. + fn mutex_create( + &mut self, + lock_op: &OpTy<'tcx>, + lock_layout: TyAndLayout<'tcx>, + offset: u64, + data: Option, + ) -> InterpResult<'tcx, MutexId> { + let this = self.eval_context_mut(); + this.create_id( + lock_op, + lock_layout, + offset, + |ecx| &mut ecx.machine.sync.mutexes, + Mutex { data, ..Default::default() }, + ) + } + + /// Lazily create a new mutex. + /// `initialize_data` must return any additional data that a user wants to associate with the mutex. fn mutex_get_or_create_id( &mut self, lock_op: &OpTy<'tcx>, lock_layout: TyAndLayout<'tcx>, offset: u64, + initialize_data: impl for<'a> FnOnce( + &'a mut MiriInterpCx<'tcx>, + ) -> InterpResult<'tcx, Option>, ) -> InterpResult<'tcx, MutexId> { let this = self.eval_context_mut(); - this.get_or_create_id(lock_op, lock_layout, offset, |ecx| &mut ecx.machine.sync.mutexes)? - .ok_or_else(|| err_ub_format!("mutex has invalid ID").into()) + this.get_or_create_id( + lock_op, + lock_layout, + offset, + |ecx| &mut ecx.machine.sync.mutexes, + |ecx| initialize_data(ecx).map(|data| Mutex { data, ..Default::default() }), + )? + .ok_or_else(|| err_ub_format!("mutex has invalid ID").into()) + } + + /// Retrieve the additional data stored for a mutex. + fn mutex_get_data<'a>(&'a mut self, id: MutexId) -> Option<&'a AdditionalMutexData> + where + 'tcx: 'a, + { + let this = self.eval_context_ref(); + this.machine.sync.mutexes[id].data.as_ref() } fn rwlock_get_or_create_id( @@ -254,8 +345,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { offset: u64, ) -> InterpResult<'tcx, RwLockId> { let this = self.eval_context_mut(); - this.get_or_create_id(lock_op, lock_layout, offset, |ecx| &mut ecx.machine.sync.rwlocks)? - .ok_or_else(|| err_ub_format!("rwlock has invalid ID").into()) + this.get_or_create_id( + lock_op, + lock_layout, + offset, + |ecx| &mut ecx.machine.sync.rwlocks, + |_| Ok(Default::default()), + )? + .ok_or_else(|| err_ub_format!("rwlock has invalid ID").into()) } fn condvar_get_or_create_id( @@ -265,8 +362,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { offset: u64, ) -> InterpResult<'tcx, CondvarId> { let this = self.eval_context_mut(); - this.get_or_create_id(lock_op, lock_layout, offset, |ecx| &mut ecx.machine.sync.condvars)? - .ok_or_else(|| err_ub_format!("condvar has invalid ID").into()) + this.get_or_create_id( + lock_op, + lock_layout, + offset, + |ecx| &mut ecx.machine.sync.condvars, + |_| Ok(Default::default()), + )? + .ok_or_else(|| err_ub_format!("condvar has invalid ID").into()) } #[inline] diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index ece393caf9a1e..fdb12bd6912ad 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -130,7 +130,10 @@ pub use crate::concurrency::{ cpu_affinity::MAX_CPUS, data_race::{AtomicFenceOrd, AtomicReadOrd, AtomicRwOrd, AtomicWriteOrd, EvalContextExt as _}, init_once::{EvalContextExt as _, InitOnceId}, - sync::{CondvarId, EvalContextExt as _, MutexId, RwLockId, SynchronizationObjects}, + sync::{ + AdditionalMutexData, CondvarId, EvalContextExt as _, MutexId, MutexKind, RwLockId, + SynchronizationObjects, + }, thread::{ BlockReason, EvalContextExt as _, StackEmptyCallback, ThreadId, ThreadManager, TimeoutAnchor, TimeoutClock, UnblockCallback, diff --git a/src/tools/miri/src/shims/unix/macos/sync.rs b/src/tools/miri/src/shims/unix/macos/sync.rs index 5e5fccb587b4b..882c08cca154c 100644 --- a/src/tools/miri/src/shims/unix/macos/sync.rs +++ b/src/tools/miri/src/shims/unix/macos/sync.rs @@ -19,7 +19,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { // os_unfair_lock holds a 32-bit value, is initialized with zero and // must be assumed to be opaque. Therefore, we can just store our // internal mutex ID in the structure without anyone noticing. - this.mutex_get_or_create_id(lock_op, this.libc_ty_layout("os_unfair_lock"), 0) + this.mutex_get_or_create_id(lock_op, this.libc_ty_layout("os_unfair_lock"), 0, |_| Ok(None)) } } diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs index 0b889b1182248..5da5cab8fe4f5 100644 --- a/src/tools/miri/src/shims/unix/sync.rs +++ b/src/tools/miri/src/shims/unix/sync.rs @@ -74,6 +74,8 @@ fn mutex_id_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, u64> { // Sanity-check this against PTHREAD_MUTEX_INITIALIZER (but only once): // the id must start out as 0. + // FIXME on some platforms (e.g linux) there are more static initializers for + // recursive or error checking mutexes. We should also add thme in this sanity check. static SANITY: AtomicBool = AtomicBool::new(false); if !SANITY.swap(true, Ordering::Relaxed) { let static_initializer = ecx.eval_path(&["libc", "PTHREAD_MUTEX_INITIALIZER"]); @@ -90,79 +92,92 @@ fn mutex_id_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, u64> { Ok(offset) } -fn mutex_kind_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> u64 { - // These offsets are picked for compatibility with Linux's static initializer - // macros, e.g. PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP.) - let offset = if ecx.pointer_size().bytes() == 8 { 16 } else { 12 }; - - // Sanity-check this against PTHREAD_MUTEX_INITIALIZER (but only once): - // the kind must start out as PTHREAD_MUTEX_DEFAULT. - static SANITY: AtomicBool = AtomicBool::new(false); - if !SANITY.swap(true, Ordering::Relaxed) { - let static_initializer = ecx.eval_path(&["libc", "PTHREAD_MUTEX_INITIALIZER"]); - let kind_field = static_initializer - .offset(Size::from_bytes(mutex_kind_offset(ecx)), ecx.machine.layouts.i32, ecx) - .unwrap(); - let kind = ecx.read_scalar(&kind_field).unwrap().to_i32().unwrap(); - assert_eq!( - kind, - ecx.eval_libc_i32("PTHREAD_MUTEX_DEFAULT"), - "PTHREAD_MUTEX_INITIALIZER is incompatible with our pthread_mutex layout: kind is not PTHREAD_MUTEX_DEFAULT" - ); - } - - offset +/// Eagerly create and initialize a new mutex. +fn mutex_create<'tcx>( + ecx: &mut MiriInterpCx<'tcx>, + mutex_op: &OpTy<'tcx>, + kind: i32, +) -> InterpResult<'tcx> { + // FIXME: might be worth changing mutex_create to take the mplace + // rather than the `OpTy`. + let address = ecx.read_pointer(mutex_op)?.addr().bytes(); + let kind = translate_kind(ecx, kind)?; + let data = Some(AdditionalMutexData { address, kind }); + ecx.mutex_create(mutex_op, ecx.libc_ty_layout("pthread_mutex_t"), mutex_id_offset(ecx)?, data)?; + Ok(()) } +/// Returns the `MutexId` of the mutex stored at `mutex_op`. +/// +/// `mutex_get_id` will also check if the mutex has been moved since its first use and +/// return an error if it has. fn mutex_get_id<'tcx>( ecx: &mut MiriInterpCx<'tcx>, mutex_op: &OpTy<'tcx>, ) -> InterpResult<'tcx, MutexId> { - ecx.mutex_get_or_create_id( + let address = ecx.read_pointer(mutex_op)?.addr().bytes(); + + // FIXME: might be worth changing mutex_get_or_create_id to take the mplace + // rather than the `OpTy`. + let id = ecx.mutex_get_or_create_id( mutex_op, ecx.libc_ty_layout("pthread_mutex_t"), mutex_id_offset(ecx)?, - ) -} + |ecx| { + // This is called if a static initializer was used and the lock has not been assigned + // an ID yet. We have to determine the mutex kind from the static initializer. + let kind = kind_from_static_initializer(ecx, mutex_op)?; + + Ok(Some(AdditionalMutexData { kind, address })) + }, + )?; + + // Check that the mutex has not been moved since last use. + let data = ecx.mutex_get_data(id).expect("data should be always exist for pthreads"); + if data.address != address { + throw_ub_format!("pthread_mutex_t can't be moved after first use") + } -fn mutex_reset_id<'tcx>( - ecx: &mut MiriInterpCx<'tcx>, - mutex_op: &OpTy<'tcx>, -) -> InterpResult<'tcx, ()> { - ecx.deref_pointer_and_write( - mutex_op, - mutex_id_offset(ecx)?, - Scalar::from_u32(0), - ecx.libc_ty_layout("pthread_mutex_t"), - ecx.machine.layouts.u32, - ) + Ok(id) } -fn mutex_get_kind<'tcx>( +/// Returns the kind of a static initializer. +fn kind_from_static_initializer<'tcx>( ecx: &MiriInterpCx<'tcx>, mutex_op: &OpTy<'tcx>, -) -> InterpResult<'tcx, i32> { - ecx.deref_pointer_and_read( - mutex_op, - mutex_kind_offset(ecx), - ecx.libc_ty_layout("pthread_mutex_t"), - ecx.machine.layouts.i32, - )? - .to_i32() +) -> InterpResult<'tcx, MutexKind> { + // Only linux has static initializers other than PTHREAD_MUTEX_DEFAULT. + let kind = match &*ecx.tcx.sess.target.os { + "linux" => { + let offset = if ecx.pointer_size().bytes() == 8 { 16 } else { 12 }; + + ecx.deref_pointer_and_read( + mutex_op, + offset, + ecx.libc_ty_layout("pthread_mutex_t"), + ecx.machine.layouts.i32, + )? + .to_i32()? + } + | "illumos" | "solaris" | "macos" => ecx.eval_libc_i32("PTHREAD_MUTEX_DEFAULT"), + os => throw_unsup_format!("`pthread_mutex` is not supported on {os}"), + }; + + translate_kind(ecx, kind) } -fn mutex_set_kind<'tcx>( - ecx: &mut MiriInterpCx<'tcx>, - mutex_op: &OpTy<'tcx>, - kind: i32, -) -> InterpResult<'tcx, ()> { - ecx.deref_pointer_and_write( - mutex_op, - mutex_kind_offset(ecx), - Scalar::from_i32(kind), - ecx.libc_ty_layout("pthread_mutex_t"), - ecx.machine.layouts.i32, - ) +fn translate_kind<'tcx>(ecx: &MiriInterpCx<'tcx>, kind: i32) -> InterpResult<'tcx, MutexKind> { + Ok(if is_mutex_kind_default(ecx, kind)? { + MutexKind::Default + } else if is_mutex_kind_normal(ecx, kind)? { + MutexKind::Normal + } else if kind == ecx.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK") { + MutexKind::ErrorCheck + } else if kind == ecx.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE") { + MutexKind::Recursive + } else { + throw_unsup_format!("unsupported type of mutex: {kind}"); + }) } // pthread_rwlock_t is between 32 and 56 bytes, depending on the platform. @@ -452,10 +467,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { mutexattr_get_kind(this, attr_op)? }; - // Write 0 to use the same code path as the static initializers. - mutex_reset_id(this, mutex_op)?; - - mutex_set_kind(this, mutex_op, kind)?; + mutex_create(this, mutex_op, kind)?; Ok(()) } @@ -467,8 +479,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - let kind = mutex_get_kind(this, mutex_op)?; let id = mutex_get_id(this, mutex_op)?; + let kind = + this.mutex_get_data(id).expect("data should always exist for pthread mutexes").kind; let ret = if this.mutex_is_locked(id) { let owner_thread = this.mutex_get_owner(id); @@ -477,19 +490,19 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return Ok(()); } else { // Trying to acquire the same mutex again. - if is_mutex_kind_default(this, kind)? { - throw_ub_format!("trying to acquire already locked default mutex"); - } else if is_mutex_kind_normal(this, kind)? { - throw_machine_stop!(TerminationInfo::Deadlock); - } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK") { - this.eval_libc_i32("EDEADLK") - } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE") { - this.mutex_lock(id); - 0 - } else { - throw_unsup_format!( - "called pthread_mutex_lock on an unsupported type of mutex" - ); + match kind { + MutexKind::Default => + throw_ub_format!("trying to acquire already locked default mutex"), + MutexKind::Normal => throw_machine_stop!(TerminationInfo::Deadlock), + MutexKind::ErrorCheck => this.eval_libc_i32("EDEADLK"), + MutexKind::Recursive => { + this.mutex_lock(id); + 0 + } + _ => + throw_unsup_format!( + "called pthread_mutex_lock on an unsupported type of mutex" + ), } } } else { @@ -504,26 +517,26 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn pthread_mutex_trylock(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - let kind = mutex_get_kind(this, mutex_op)?; let id = mutex_get_id(this, mutex_op)?; + let kind = + this.mutex_get_data(id).expect("data should always exist for pthread mutexes").kind; Ok(Scalar::from_i32(if this.mutex_is_locked(id) { let owner_thread = this.mutex_get_owner(id); if owner_thread != this.active_thread() { this.eval_libc_i32("EBUSY") } else { - if is_mutex_kind_default(this, kind)? - || is_mutex_kind_normal(this, kind)? - || kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK") - { - this.eval_libc_i32("EBUSY") - } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE") { - this.mutex_lock(id); - 0 - } else { - throw_unsup_format!( - "called pthread_mutex_trylock on an unsupported type of mutex" - ); + match kind { + MutexKind::Default | MutexKind::Normal | MutexKind::ErrorCheck => + this.eval_libc_i32("EBUSY"), + MutexKind::Recursive => { + this.mutex_lock(id); + 0 + } + _ => + throw_unsup_format!( + "called pthread_mutex_trylock on an unsupported type of mutex" + ), } } } else { @@ -536,8 +549,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn pthread_mutex_unlock(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - let kind = mutex_get_kind(this, mutex_op)?; let id = mutex_get_id(this, mutex_op)?; + let kind = + this.mutex_get_data(id).expect("data should always exist for pthread mutexes").kind; if let Some(_old_locked_count) = this.mutex_unlock(id)? { // The mutex was locked by the current thread. @@ -546,20 +560,21 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // The mutex was locked by another thread or not locked at all. See // the “Unlock When Not Owner” column in // https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_unlock.html. - if is_mutex_kind_default(this, kind)? { - throw_ub_format!( - "unlocked a default mutex that was not locked by the current thread" - ); - } else if is_mutex_kind_normal(this, kind)? { - throw_ub_format!( - "unlocked a PTHREAD_MUTEX_NORMAL mutex that was not locked by the current thread" - ); - } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK") - || kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE") - { - Ok(Scalar::from_i32(this.eval_libc_i32("EPERM"))) - } else { - throw_unsup_format!("called pthread_mutex_unlock on an unsupported type of mutex"); + match kind { + MutexKind::Default => + throw_ub_format!( + "unlocked a default mutex that was not locked by the current thread" + ), + MutexKind::Normal => + throw_ub_format!( + "unlocked a PTHREAD_MUTEX_NORMAL mutex that was not locked by the current thread" + ), + MutexKind::ErrorCheck | MutexKind::Recursive => + Ok(Scalar::from_i32(this.eval_libc_i32("EPERM"))), + _ => + throw_unsup_format!( + "called pthread_mutex_unlock on an unsupported type of mutex" + ), } } } @@ -574,7 +589,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } // Destroying an uninit pthread_mutex is UB, so check to make sure it's not uninit. - mutex_get_kind(this, mutex_op)?; mutex_get_id(this, mutex_op)?; // This might lead to false positives, see comment in pthread_mutexattr_destroy diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.init.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.init.stderr new file mode 100644 index 0000000000000..5ca6acc3fbe6e --- /dev/null +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.init.stderr @@ -0,0 +1,20 @@ +error: Undefined Behavior: pthread_mutex_t can't be moved after first use + --> $DIR/libc_pthread_mutex_move.rs:LL:CC + | +LL | libc::pthread_mutex_lock(&mut m2 as *mut _); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pthread_mutex_t can't be moved after first use + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `check` at $DIR/libc_pthread_mutex_move.rs:LL:CC +note: inside `main` + --> $DIR/libc_pthread_mutex_move.rs:LL:CC + | +LL | check(); + | ^^^^^^^ + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.rs new file mode 100644 index 0000000000000..229335c97ce18 --- /dev/null +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.rs @@ -0,0 +1,28 @@ +//@ignore-target-windows: No pthreads on Windows +//@revisions: static_initializer init + +fn main() { + check(); +} + +#[cfg(init)] +fn check() { + unsafe { + let mut m: libc::pthread_mutex_t = std::mem::zeroed(); + assert_eq!(libc::pthread_mutex_init(&mut m as *mut _, std::ptr::null()), 0); + + let mut m2 = m; // move the mutex + libc::pthread_mutex_lock(&mut m2 as *mut _); //~[init] ERROR: pthread_mutex_t can't be moved after first use + } +} + +#[cfg(static_initializer)] +fn check() { + unsafe { + let mut m: libc::pthread_mutex_t = libc::PTHREAD_MUTEX_INITIALIZER; + libc::pthread_mutex_lock(&mut m as *mut _); + + let mut m2 = m; // move the mutex + libc::pthread_mutex_unlock(&mut m2 as *mut _); //~[static_initializer] ERROR: pthread_mutex_t can't be moved after first use + } +} diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.static_initializer.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.static_initializer.stderr new file mode 100644 index 0000000000000..c3632eca43ffa --- /dev/null +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_move.static_initializer.stderr @@ -0,0 +1,20 @@ +error: Undefined Behavior: pthread_mutex_t can't be moved after first use + --> $DIR/libc_pthread_mutex_move.rs:LL:CC + | +LL | libc::pthread_mutex_unlock(&mut m2 as *mut _); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pthread_mutex_t can't be moved after first use + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `check` at $DIR/libc_pthread_mutex_move.rs:LL:CC +note: inside `main` + --> $DIR/libc_pthread_mutex_move.rs:LL:CC + | +LL | check(); + | ^^^^^^^ + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + From 5396124aa3617458a3c70f128a6a5b74e93de613 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 5 Sep 2024 09:31:17 -0700 Subject: [PATCH 022/189] Update compiler-builtins to 0.1.125 This commit updates the compiler-builtins crate from 0.1.123 to 0.1.125. The changes in this update are: * https://github.com/rust-lang/compiler-builtins/pull/682 * https://github.com/rust-lang/compiler-builtins/pull/678 * https://github.com/rust-lang/compiler-builtins/pull/685 --- library/Cargo.lock | 4 ++-- library/alloc/Cargo.toml | 2 +- library/std/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library/Cargo.lock b/library/Cargo.lock index 54ad052c52322..ded30dd82f7b4 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -58,9 +58,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.123" +version = "0.1.125" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b47fcbecb558bdad78c7d3a998523c60a50dd6cd046d5fe74163e309e878fff7" +checksum = "bd02a01d7bc069bed818e956600fe437ee222dd1d6ad92bfb9db87b43b71fd87" dependencies = [ "cc", "rustc-std-workspace-core", diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index 1bd4434d4f7e9..1da947d196fd6 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -10,7 +10,7 @@ edition = "2021" [dependencies] core = { path = "../core" } -compiler_builtins = { version = "0.1.123", features = ['rustc-dep-of-std'] } +compiler_builtins = { version = "0.1.125", features = ['rustc-dep-of-std'] } [dev-dependencies] rand = { version = "0.8.5", default-features = false, features = ["alloc"] } diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index e20fe9feff114..9a31fd21dc71a 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -17,7 +17,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] } panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core", public = true } -compiler_builtins = { version = "0.1.123" } +compiler_builtins = { version = "0.1.125" } profiler_builtins = { path = "../profiler_builtins", optional = true } unwind = { path = "../unwind" } hashbrown = { version = "0.14", default-features = false, features = [ From 81a08bc67ab0d9186295d081e9579d8e0c2f1998 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Fri, 6 Sep 2024 05:01:31 +0000 Subject: [PATCH 023/189] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 4f14caf0e56c3..3fdad2a91e9fc 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -e71f9529121ca8f687e4b725e3c9adc3f1ebab4d +54fdef7799d9ff9470bb5cabd29fde9471a99eaa From 2d6489ecc1c874a9ae0cfce4455d76c9c185fd80 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 6 Sep 2024 08:43:39 +0200 Subject: [PATCH 024/189] miri.bat: use nightly toolchain --- src/tools/miri/miri.bat | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/miri/miri.bat b/src/tools/miri/miri.bat index 6f9a8f38d6559..b046b6310ddad 100644 --- a/src/tools/miri/miri.bat +++ b/src/tools/miri/miri.bat @@ -5,8 +5,8 @@ set MIRI_SCRIPT_TARGET_DIR=%0\..\miri-script\target :: If any other steps are added, the "|| exit /b" must be appended to early :: return from the script. If not, it will continue execution. -cargo +stable build %CARGO_EXTRA_FLAGS% -q --target-dir %MIRI_SCRIPT_TARGET_DIR% --manifest-path %0\..\miri-script\Cargo.toml ^ - || (echo Failed to build miri-script. Is the 'stable' toolchain installed? & exit /b) +cargo +nightly build %CARGO_EXTRA_FLAGS% -q --target-dir %MIRI_SCRIPT_TARGET_DIR% --manifest-path %0\..\miri-script\Cargo.toml ^ + || (echo Failed to build miri-script. Is the 'nightly' toolchain installed? & exit /b) :: Forwards all arguments to this file to the executable. :: We invoke the binary directly to avoid going through rustup, which would set some extra From 4dfafb1a8d34c6ee14af811b619801da782eb718 Mon Sep 17 00:00:00 2001 From: Konstantinos Andrikopoulos Date: Fri, 6 Sep 2024 12:13:55 +0200 Subject: [PATCH 025/189] Fix comment in mutex_id_offset We no longer store the kind inside the pthread_mutex_t, so this comment is outdated. --- src/tools/miri/src/shims/unix/sync.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs index 5da5cab8fe4f5..57cc9cf4618c8 100644 --- a/src/tools/miri/src/shims/unix/sync.rs +++ b/src/tools/miri/src/shims/unix/sync.rs @@ -62,7 +62,6 @@ fn is_mutex_kind_normal<'tcx>(ecx: &MiriInterpCx<'tcx>, kind: i32) -> InterpResu // pthread_mutex_t is between 24 and 48 bytes, depending on the platform. // We ignore the platform layout and store our own fields: // - id: u32 -// - kind: i32 fn mutex_id_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, u64> { let offset = match &*ecx.tcx.sess.target.os { From 7dd1be1d0d2911b16aa1347efa47e7c43c507ade Mon Sep 17 00:00:00 2001 From: Urgau Date: Fri, 6 Sep 2024 12:20:36 +0200 Subject: [PATCH 026/189] Also emit `missing_docs` lint with `--test` to fulfill expectations --- compiler/rustc_lint/src/builtin.rs | 6 ------ tests/ui/lint/lint-missing-doc-expect.rs | 13 +++++++++++++ 2 files changed, 13 insertions(+), 6 deletions(-) create mode 100644 tests/ui/lint/lint-missing-doc-expect.rs diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index d8482567bbe5b..5cb5195367402 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -426,12 +426,6 @@ impl MissingDoc { article: &'static str, desc: &'static str, ) { - // If we're building a test harness, then warning about - // documentation is probably not really relevant right now. - if cx.sess().opts.test { - return; - } - // Only check publicly-visible items, using the result from the privacy pass. // It's an option so the crate root can also use this function (it doesn't // have a `NodeId`). diff --git a/tests/ui/lint/lint-missing-doc-expect.rs b/tests/ui/lint/lint-missing-doc-expect.rs new file mode 100644 index 0000000000000..991f65003dc26 --- /dev/null +++ b/tests/ui/lint/lint-missing-doc-expect.rs @@ -0,0 +1,13 @@ +// Make sure that `#[expect(missing_docs)]` is always correctly fulfilled. + +//@ check-pass +//@ revisions: lib bin test +//@ [lib]compile-flags: --crate-type lib +//@ [bin]compile-flags: --crate-type bin +//@ [test]compile-flags: --test + +#[expect(missing_docs)] +pub fn foo() {} + +#[cfg(bin)] +fn main() {} From 5f367bbbd251b8cfb898f4d5711c9244888b1852 Mon Sep 17 00:00:00 2001 From: Urgau Date: Fri, 23 Aug 2024 16:53:21 +0200 Subject: [PATCH 027/189] Make `download-ci-llvm = true` check if CI llvm is available and make it the default for the compiler profile, as to prevent unnecessarily checking out `src/llvm-project` with `"if-unchanged"`. --- config.example.toml | 5 ++++- src/bootstrap/defaults/config.compiler.toml | 3 ++- src/bootstrap/src/core/config/config.rs | 3 ++- src/bootstrap/src/utils/change_tracker.rs | 5 +++++ 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/config.example.toml b/config.example.toml index e9433c9c9bd08..ed2db8218f00f 100644 --- a/config.example.toml +++ b/config.example.toml @@ -42,6 +42,9 @@ # Unless you're developing for a target where Rust CI doesn't build a compiler # toolchain or changing LLVM locally, you probably want to leave this enabled. # +# Set this to `true` to download if CI llvm available otherwise it builds +# from `src/llvm-project`. +# # Set this to `"if-unchanged"` to download only if the llvm-project has not # been modified. You can also use this if you are unsure whether you're on a # tier 1 target. All tier 1 targets are currently supported. @@ -236,7 +239,7 @@ # Instead of downloading the src/stage0 version of cargo-clippy specified, # use this cargo-clippy binary instead as the stage0 snapshot cargo-clippy. # -# Note that this option should be used with the same toolchain as the `rustc` option above. +# Note that this option should be used with the same toolchain as the `rustc` option above. # Otherwise, clippy is likely to fail due to a toolchain conflict. #cargo-clippy = "/path/to/cargo-clippy" diff --git a/src/bootstrap/defaults/config.compiler.toml b/src/bootstrap/defaults/config.compiler.toml index 789586b58f706..147939d2047e8 100644 --- a/src/bootstrap/defaults/config.compiler.toml +++ b/src/bootstrap/defaults/config.compiler.toml @@ -27,4 +27,5 @@ assertions = false # Enable warnings during the LLVM compilation (when LLVM is changed, causing a compilation) enable-warnings = true # Will download LLVM from CI if available on your platform. -download-ci-llvm = "if-unchanged" +# If you intend to modify `src/llvm-project`, use `"if-unchanged"` or `false` instead. +download-ci-llvm = true diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 52c1c462788af..2edf6d385080b 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -2781,7 +2781,8 @@ impl Config { ); } - b + // If download-ci-llvm=true we also want to check that CI llvm is available + b && llvm::is_ci_llvm_available(self, asserts) } Some(StringOrBool::String(s)) if s == "if-unchanged" => if_unchanged(), Some(StringOrBool::String(other)) => { diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index 80ab09881fe1c..99bcc6e0787ff 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -250,4 +250,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ severity: ChangeSeverity::Info, summary: "New option `llvm.enzyme` to control whether the llvm based autodiff tool (Enzyme) is built.", }, + ChangeInfo { + change_id: 129473, + severity: ChangeSeverity::Warning, + summary: "`download-ci-llvm = true` now checks if CI llvm is available and has become the default for the compiler profile", + }, ]; From c1ff6fd063305a19ec9a9560c2ba3bc76bb7391a Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 6 Sep 2024 09:20:53 -0700 Subject: [PATCH 028/189] Fix a typo in the wasm-component-ld README --- src/tools/wasm-component-ld/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/wasm-component-ld/README.md b/src/tools/wasm-component-ld/README.md index 54608a2dea1d4..b51de9a9dce2f 100644 --- a/src/tools/wasm-component-ld/README.md +++ b/src/tools/wasm-component-ld/README.md @@ -1,7 +1,7 @@ # `wasm-component-ld` -This wrapper is a wrapper around the [`wasm-component-ld`] crates.io crate. That -crate. That crate is itself a thin wrapper around two pieces: +This wrapper is a wrapper around the [`wasm-component-ld`] crates.io crate. +That crate is itself a thin wrapper around two pieces: * `wasm-ld` - the LLVM-based linker distributed as part of LLD and packaged in Rust as `rust-lld`. From c15469a7fec811d1a4f69ff26e18c6f383df41d2 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 6 Sep 2024 09:21:33 -0700 Subject: [PATCH 029/189] Fix enabling wasm-component-ld to match other tools It was [pointed out recently][comment] that enabling `wasm-component-ld` as a host tool is different from other host tools. This commit refactors the logic to match by deduplicating selection of when to build other tools and then using the same logic for `wasm-component-ld`. [comment]: https://github.com/rust-lang/rust/pull/127866#issuecomment-2333434720 --- src/bootstrap/src/core/build_steps/compile.rs | 2 +- src/bootstrap/src/core/build_steps/dist.rs | 2 +- src/bootstrap/src/core/build_steps/tool.rs | 38 +++---------------- src/bootstrap/src/lib.rs | 17 +++++---- 4 files changed, 17 insertions(+), 42 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 1936c91ef83c1..102c9fd255432 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -1912,7 +1912,7 @@ impl Step for Assemble { // delegates to the `rust-lld` binary for linking and then runs // logic to create the final binary. This is used by the // `wasm32-wasip2` target of Rust. - if builder.build_wasm_component_ld() { + if builder.tool_enabled("wasm-component-ld") { let wasm_component_ld_exe = builder.ensure(crate::core::build_steps::tool::WasmComponentLd { compiler: build_compiler, diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 4957de2e1b791..ccb5656d6716c 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -473,7 +473,7 @@ impl Step for Rustc { ); } } - if builder.build_wasm_component_ld() { + if builder.tool_enabled("wasm-component-ld") { let src_dir = builder.sysroot_libdir(compiler, host).parent().unwrap().join("bin"); let ld = exe("wasm-component-ld", compiler.host); builder.copy_link(&src_dir.join(&ld), &dst_dir.join(&ld)); diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index 3a1eb43b801f5..3c2d791c2090e 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -693,14 +693,7 @@ impl Step for Cargo { fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; - run.path("src/tools/cargo").default_condition( - builder.config.extended - && builder.config.tools.as_ref().map_or( - true, - // If `tools` is set, search list for this tool. - |tools| tools.iter().any(|tool| tool == "cargo"), - ), - ) + run.path("src/tools/cargo").default_condition(builder.tool_enabled("cargo")) } fn make_run(run: RunConfig<'_>) { @@ -772,14 +765,7 @@ impl Step for RustAnalyzer { fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; - run.path("src/tools/rust-analyzer").default_condition( - builder.config.extended - && builder - .config - .tools - .as_ref() - .map_or(true, |tools| tools.iter().any(|tool| tool == "rust-analyzer")), - ) + run.path("src/tools/rust-analyzer").default_condition(builder.tool_enabled("rust-analyzer")) } fn make_run(run: RunConfig<'_>) { @@ -821,12 +807,8 @@ impl Step for RustAnalyzerProcMacroSrv { run.path("src/tools/rust-analyzer") .path("src/tools/rust-analyzer/crates/proc-macro-srv-cli") .default_condition( - builder.config.extended - && builder.config.tools.as_ref().map_or(true, |tools| { - tools.iter().any(|tool| { - tool == "rust-analyzer" || tool == "rust-analyzer-proc-macro-srv" - }) - }), + builder.tool_enabled("rust-analyzer") + || builder.tool_enabled("rust-analyzer-proc-macro-srv"), ) } @@ -874,16 +856,8 @@ impl Step for LlvmBitcodeLinker { fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; - run.path("src/tools/llvm-bitcode-linker").default_condition( - builder.config.extended - && builder - .config - .tools - .as_ref() - .map_or(builder.build.unstable_features(), |tools| { - tools.iter().any(|tool| tool == "llvm-bitcode-linker") - }), - ) + run.path("src/tools/llvm-bitcode-linker") + .default_condition(builder.tool_enabled("llvm-bitcode-linker")) } fn make_run(run: RunConfig<'_>) { diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index c76ce3409562e..780024e307edc 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -1407,16 +1407,17 @@ Executed at: {executed_at}"#, None } - /// Returns whether it's requested that `wasm-component-ld` is built as part - /// of the sysroot. This is done either with the `extended` key in - /// `config.toml` or with the `tools` set. - fn build_wasm_component_ld(&self) -> bool { - if self.config.extended { - return true; + /// Returns whether the specified tool is configured as part of this build. + /// + /// This requires that both the `extended` key is set and the `tools` key is + /// either unset or specifically contains the specified tool. + fn tool_enabled(&self, tool: &str) -> bool { + if !self.config.extended { + return false; } match &self.config.tools { - Some(set) => set.contains("wasm-component-ld"), - None => false, + Some(set) => set.contains(tool), + None => true, } } From 717a11788d49a960c94509ec97d35114fa4b3a7f Mon Sep 17 00:00:00 2001 From: Georg Semmler Date: Fri, 6 Sep 2024 18:47:22 +0200 Subject: [PATCH 030/189] Correctly handle stability of `#[diagnostic]` attributes This commit changes the way we treat the stability of attributes in the `#[diagnostic]` namespace. Instead of relaying on ad-hoc checks to ensure at call side that a certain attribute is really usable at that location it centralises the logic to one place. For diagnostic attributes comming from other crates it just skips serializing attributes that are not stable and that do not have the corresponding feature enabled. For attributes from the current crate we can just use the feature information provided by `TyCtx`. --- compiler/rustc_feature/src/builtin_attrs.rs | 8 +++++ compiler/rustc_feature/src/lib.rs | 5 ++-- compiler/rustc_metadata/src/rmeta/encoder.rs | 10 +++++-- compiler/rustc_middle/src/ty/context.rs | 3 +- compiler/rustc_middle/src/ty/mod.rs | 31 ++++++++++++++++++++ 5 files changed, 51 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index e86421f2150db..3b7e0d82d0f62 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -1186,3 +1186,11 @@ pub static BUILTIN_ATTRIBUTE_MAP: LazyLock> } map }); + +pub fn is_stable_diagnostic_attribute(sym: Symbol, features: &Features) -> bool { + match sym { + sym::on_unimplemented => true, + sym::do_not_recommend => features.do_not_recommend, + _ => false, + } +} diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs index adaaba3cd235e..fe12930e6b9d6 100644 --- a/compiler/rustc_feature/src/lib.rs +++ b/compiler/rustc_feature/src/lib.rs @@ -130,8 +130,9 @@ pub fn find_feature_issue(feature: Symbol, issue: GateIssue) -> Option EncodeContext<'a, 'tcx> { } } -struct AnalyzeAttrState { +struct AnalyzeAttrState<'a> { is_exported: bool, is_doc_hidden: bool, + features: &'a Features, } /// Returns whether an attribute needs to be recorded in metadata, that is, if it's usable and @@ -812,7 +814,7 @@ struct AnalyzeAttrState { /// visibility: this is a piece of data that can be computed once per defid, and not once per /// attribute. Some attributes would only be usable downstream if they are public. #[inline] -fn analyze_attr(attr: &Attribute, state: &mut AnalyzeAttrState) -> bool { +fn analyze_attr(attr: &Attribute, state: &mut AnalyzeAttrState<'_>) -> bool { let mut should_encode = false; if !rustc_feature::encode_cross_crate(attr.name_or_empty()) { // Attributes not marked encode-cross-crate don't need to be encoded for downstream crates. @@ -837,6 +839,9 @@ fn analyze_attr(attr: &Attribute, state: &mut AnalyzeAttrState) -> bool { } } } + } else if attr.path().starts_with(&[sym::diagnostic]) && attr.path().len() == 2 { + should_encode = + rustc_feature::is_stable_diagnostic_attribute(attr.path()[1], state.features); } else { should_encode = true; } @@ -1343,6 +1348,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let mut state = AnalyzeAttrState { is_exported: tcx.effective_visibilities(()).is_exported(def_id), is_doc_hidden: false, + features: &tcx.features(), }; let attr_iter = tcx .hir() diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 20828067c469c..ff34555920de5 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -3183,8 +3183,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Whether this is a trait implementation that has `#[diagnostic::do_not_recommend]` pub fn do_not_recommend_impl(self, def_id: DefId) -> bool { - matches!(self.def_kind(def_id), DefKind::Impl { of_trait: true }) - && self.impl_trait_header(def_id).is_some_and(|header| header.do_not_recommend) + self.get_diagnostic_attr(def_id, sym::do_not_recommend).is_some() } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index ee70a6346d920..ee4f67f0e939e 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1797,6 +1797,37 @@ impl<'tcx> TyCtxt<'tcx> { } } + /// Get an attribute from the diagnostic attribute namespace + /// + /// This function requests an attribute with the following structure: + /// + /// `#[diagnostic::$attr]` + /// + /// This function performs feature checking, so if an attribute is returned + /// it can be used by the consumer + pub fn get_diagnostic_attr( + self, + did: impl Into, + attr: Symbol, + ) -> Option<&'tcx ast::Attribute> { + let did: DefId = did.into(); + if did.as_local().is_some() { + // it's a crate local item, we need to check feature flags + if rustc_feature::is_stable_diagnostic_attribute(attr, self.features()) { + self.get_attrs_by_path(did, &[sym::diagnostic, sym::do_not_recommend]).next() + } else { + None + } + } else { + // we filter out unstable diagnostic attributes before + // encoding attributes + debug_assert!(rustc_feature::encode_cross_crate(attr)); + self.item_attrs(did) + .iter() + .find(|a| matches!(a.path().as_ref(), [sym::diagnostic, a] if *a == attr)) + } + } + pub fn get_attrs_by_path<'attr>( self, did: DefId, From 7c9e818f028a899cf4597f80c67bfe64b7e1a4ed Mon Sep 17 00:00:00 2001 From: Georg Semmler Date: Fri, 6 Sep 2024 19:06:59 +0200 Subject: [PATCH 031/189] Revert ed7bdbb17b9c03fe3530e5e3f21b7c6c7879dbca --- compiler/rustc_hir_analysis/src/collect.rs | 2 -- compiler/rustc_middle/src/ty/mod.rs | 1 - 2 files changed, 3 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 92111805ab422..ac9976148e25c 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1698,8 +1698,6 @@ fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option { pub trait_ref: ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>, pub polarity: ImplPolarity, pub safety: hir::Safety, - pub do_not_recommend: bool, } #[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)] From 94f8347bae7404d894f4e6dc57fb64e63e8efb73 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 31 Aug 2024 14:32:15 +0000 Subject: [PATCH 032/189] Check AttrId for expectations. --- compiler/rustc_errors/src/diagnostic.rs | 24 +---- compiler/rustc_errors/src/lib.rs | 101 +++--------------- compiler/rustc_lint/src/expect.rs | 90 +++++++--------- tests/ui/lint/expect-unused-imports.rs | 9 ++ ...force_warn_expected_lints_fulfilled.stderr | 16 +-- 5 files changed, 73 insertions(+), 167 deletions(-) create mode 100644 tests/ui/lint/expect-unused-imports.rs diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 1c39840207ca6..412a2c17081a9 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -8,11 +8,11 @@ use std::thread::panicking; use rustc_data_structures::fx::FxIndexMap; use rustc_error_messages::{fluent_value_from_str_list_sep_by_and, FluentValue}; -use rustc_lint_defs::{Applicability, LintExpectationId}; +use rustc_lint_defs::Applicability; use rustc_macros::{Decodable, Encodable}; use rustc_span::source_map::Spanned; use rustc_span::symbol::Symbol; -use rustc_span::{AttrId, Span, DUMMY_SP}; +use rustc_span::{Span, DUMMY_SP}; use tracing::debug; use crate::snippet::Style; @@ -354,26 +354,6 @@ impl DiagInner { } } - pub(crate) fn update_unstable_expectation_id( - &mut self, - unstable_to_stable: &FxIndexMap, - ) { - if let Level::Expect(expectation_id) | Level::ForceWarning(Some(expectation_id)) = - &mut self.level - && let LintExpectationId::Unstable { attr_id, lint_index } = *expectation_id - { - // The unstable to stable map only maps the unstable `AttrId` to a stable `HirId` with an attribute index. - // The lint index inside the attribute is manually transferred here. - let Some(stable_id) = unstable_to_stable.get(&attr_id) else { - panic!("{expectation_id:?} must have a matching stable id") - }; - - let mut stable_id = *stable_id; - stable_id.set_lint_index(lint_index); - *expectation_id = stable_id; - } - } - /// Indicates whether this diagnostic should show up in cargo's future breakage report. pub(crate) fn has_future_breakage(&self) -> bool { matches!(self.is_lint, Some(IsLint { has_future_breakage: true, .. })) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 02ead41fc68f1..26e3a63c9d6d0 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -69,7 +69,7 @@ use rustc_macros::{Decodable, Encodable}; pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker}; use rustc_span::source_map::SourceMap; pub use rustc_span::ErrorGuaranteed; -use rustc_span::{AttrId, Loc, Span, DUMMY_SP}; +use rustc_span::{Loc, Span, DUMMY_SP}; pub use snippet::Style; // Used by external projects such as `rust-gpu`. // See https://github.com/rust-lang/rust/pull/115393. @@ -497,28 +497,18 @@ struct DiagCtxtInner { future_breakage_diagnostics: Vec, - /// The [`Self::unstable_expect_diagnostics`] should be empty when this struct is - /// dropped. However, it can have values if the compilation is stopped early - /// or is only partially executed. To avoid ICEs, like in rust#94953 we only - /// check if [`Self::unstable_expect_diagnostics`] is empty, if the expectation ids - /// have been converted. - check_unstable_expect_diagnostics: bool, - - /// Expected [`DiagInner`][struct@diagnostic::DiagInner]s store a [`LintExpectationId`] as part - /// of the lint level. [`LintExpectationId`]s created early during the compilation - /// (before `HirId`s have been defined) are not stable and can therefore not be - /// stored on disk. This buffer stores these diagnostics until the ID has been - /// replaced by a stable [`LintExpectationId`]. The [`DiagInner`][struct@diagnostic::DiagInner]s - /// are submitted for storage and added to the list of fulfilled expectations. - unstable_expect_diagnostics: Vec, - /// expected diagnostic will have the level `Expect` which additionally /// carries the [`LintExpectationId`] of the expectation that can be /// marked as fulfilled. This is a collection of all [`LintExpectationId`]s /// that have been marked as fulfilled this way. /// /// [RFC-2383]: https://rust-lang.github.io/rfcs/2383-lint-reasons.html - fulfilled_expectations: FxHashSet, + fulfilled_expectations: FxIndexSet, + + /// Whether `fulfilled_expectations` has been stolen. This is used to ICE in case we emit + /// an expectation diagnostic after stealing it, which means that expectation would not be + /// correctly handled. + stolen_fulfilled_expectations: bool, /// The file where the ICE information is stored. This allows delayed_span_bug backtraces to be /// stored along side the main panic backtrace. @@ -605,13 +595,6 @@ impl Drop for DiagCtxtInner { ); } } - - if self.check_unstable_expect_diagnostics { - assert!( - self.unstable_expect_diagnostics.is_empty(), - "all diagnostics with unstable expectations should have been converted", - ); - } } } @@ -740,9 +723,8 @@ impl DiagCtxt { emitted_diagnostics, stashed_diagnostics, future_breakage_diagnostics, - check_unstable_expect_diagnostics, - unstable_expect_diagnostics, fulfilled_expectations, + stolen_fulfilled_expectations: _, ice_file: _, } = inner.deref_mut(); @@ -761,8 +743,6 @@ impl DiagCtxt { *emitted_diagnostics = Default::default(); *stashed_diagnostics = Default::default(); *future_breakage_diagnostics = Default::default(); - *check_unstable_expect_diagnostics = false; - *unstable_expect_diagnostics = Default::default(); *fulfilled_expectations = Default::default(); } @@ -1094,44 +1074,11 @@ impl<'a> DiagCtxtHandle<'a> { inner.emitter.emit_unused_externs(lint_level, unused_externs) } - pub fn update_unstable_expectation_id( - &self, - unstable_to_stable: FxIndexMap, - ) { - let mut inner = self.inner.borrow_mut(); - let diags = std::mem::take(&mut inner.unstable_expect_diagnostics); - inner.check_unstable_expect_diagnostics = true; - - if !diags.is_empty() { - inner.suppressed_expected_diag = true; - for mut diag in diags.into_iter() { - diag.update_unstable_expectation_id(&unstable_to_stable); - - // Here the diagnostic is given back to `emit_diagnostic` where it was first - // intercepted. Now it should be processed as usual, since the unstable expectation - // id is now stable. - inner.emit_diagnostic(diag, self.tainted_with_errors); - } - } - - inner - .stashed_diagnostics - .values_mut() - .for_each(|(diag, _guar)| diag.update_unstable_expectation_id(&unstable_to_stable)); - inner - .future_breakage_diagnostics - .iter_mut() - .for_each(|diag| diag.update_unstable_expectation_id(&unstable_to_stable)); - } - /// This methods steals all [`LintExpectationId`]s that are stored inside /// [`DiagCtxtInner`] and indicate that the linked expectation has been fulfilled. #[must_use] - pub fn steal_fulfilled_expectation_ids(&self) -> FxHashSet { - assert!( - self.inner.borrow().unstable_expect_diagnostics.is_empty(), - "`DiagCtxtInner::unstable_expect_diagnostics` should be empty at this point", - ); + pub fn steal_fulfilled_expectation_ids(&self) -> FxIndexSet { + self.inner.borrow_mut().stolen_fulfilled_expectations = true; std::mem::take(&mut self.inner.borrow_mut().fulfilled_expectations) } @@ -1440,9 +1387,8 @@ impl DiagCtxtInner { emitted_diagnostics: Default::default(), stashed_diagnostics: Default::default(), future_breakage_diagnostics: Vec::new(), - check_unstable_expect_diagnostics: false, - unstable_expect_diagnostics: Vec::new(), fulfilled_expectations: Default::default(), + stolen_fulfilled_expectations: false, ice_file: None, } } @@ -1471,24 +1417,6 @@ impl DiagCtxtInner { mut diagnostic: DiagInner, taint: Option<&Cell>>, ) -> Option { - match diagnostic.level { - Expect(expect_id) | ForceWarning(Some(expect_id)) => { - // The `LintExpectationId` can be stable or unstable depending on when it was - // created. Diagnostics created before the definition of `HirId`s are unstable and - // can not yet be stored. Instead, they are buffered until the `LintExpectationId` - // is replaced by a stable one by the `LintLevelsBuilder`. - if let LintExpectationId::Unstable { .. } = expect_id { - // We don't call TRACK_DIAGNOSTIC because we wait for the - // unstable ID to be updated, whereupon the diagnostic will be - // passed into this method again. - self.unstable_expect_diagnostics.push(diagnostic); - return None; - } - // Continue through to the `Expect`/`ForceWarning` case below. - } - _ => {} - } - if diagnostic.has_future_breakage() { // Future breakages aren't emitted if they're `Level::Allow` or // `Level::Expect`, but they still need to be constructed and @@ -1564,9 +1492,10 @@ impl DiagCtxtInner { return None; } Expect(expect_id) | ForceWarning(Some(expect_id)) => { - if let LintExpectationId::Unstable { .. } = expect_id { - unreachable!(); // this case was handled at the top of this function - } + assert!( + !self.stolen_fulfilled_expectations, + "Attempting to emit an expected diagnostic after `check_expectations`.", + ); self.fulfilled_expectations.insert(expect_id); if let Expect(_) = diagnostic.level { // Nothing emitted here for expected lints. diff --git a/compiler/rustc_lint/src/expect.rs b/compiler/rustc_lint/src/expect.rs index d8afba3d5053c..2450afbca064a 100644 --- a/compiler/rustc_lint/src/expect.rs +++ b/compiler/rustc_lint/src/expect.rs @@ -1,10 +1,10 @@ -use rustc_data_structures::fx::FxIndexMap; -use rustc_hir::{HirId, CRATE_OWNER_ID}; +use rustc_data_structures::fx::FxHashSet; +use rustc_hir::CRATE_OWNER_ID; use rustc_middle::lint::LintExpectation; use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_session::lint::builtin::UNFULFILLED_LINT_EXPECTATIONS; -use rustc_session::lint::{Level, LintExpectationId}; +use rustc_session::lint::LintExpectationId; use rustc_span::Symbol; use crate::lints::{Expectation, ExpectationNote}; @@ -17,43 +17,12 @@ fn lint_expectations(tcx: TyCtxt<'_>, (): ()) -> Vec<(LintExpectationId, LintExp let krate = tcx.hir_crate_items(()); let mut expectations = Vec::new(); - let mut unstable_to_stable_ids = FxIndexMap::default(); - let mut record_stable = |attr_id, hir_id, attr_index| { - let expect_id = LintExpectationId::Stable { hir_id, attr_index, lint_index: None }; - unstable_to_stable_ids.entry(attr_id).or_insert(expect_id); - }; - let mut push_expectations = |owner| { + for owner in std::iter::once(CRATE_OWNER_ID).chain(krate.owners()) { let lints = tcx.shallow_lint_levels_on(owner); - if lints.expectations.is_empty() { - return; - } - expectations.extend_from_slice(&lints.expectations); - - let attrs = tcx.hir_attrs(owner); - for &(local_id, attrs) in attrs.map.iter() { - // Some attributes appear multiple times in HIR, to ensure they are correctly taken - // into account where they matter. This means we cannot just associate the AttrId to - // the first HirId where we see it, but need to check it actually appears in a lint - // level. - // FIXME(cjgillot): Can this cause an attribute to appear in multiple expectation ids? - if !lints.specs.contains_key(&local_id) { - continue; - } - for (attr_index, attr) in attrs.iter().enumerate() { - let Some(Level::Expect(_)) = Level::from_attr(attr) else { continue }; - record_stable(attr.id, HirId { owner, local_id }, attr_index.try_into().unwrap()); - } - } - }; - - push_expectations(CRATE_OWNER_ID); - for owner in krate.owners() { - push_expectations(owner); } - tcx.dcx().update_unstable_expectation_id(unstable_to_stable_ids); expectations } @@ -61,24 +30,43 @@ fn check_expectations(tcx: TyCtxt<'_>, tool_filter: Option) { let lint_expectations = tcx.lint_expectations(()); let fulfilled_expectations = tcx.dcx().steal_fulfilled_expectation_ids(); - for (id, expectation) in lint_expectations { - // This check will always be true, since `lint_expectations` only - // holds stable ids - if let LintExpectationId::Stable { hir_id, .. } = id { - if !fulfilled_expectations.contains(id) - && tool_filter.map_or(true, |filter| expectation.lint_tool == Some(filter)) - { - let rationale = expectation.reason.map(|rationale| ExpectationNote { rationale }); - let note = expectation.is_unfulfilled_lint_expectations; - tcx.emit_node_span_lint( - UNFULFILLED_LINT_EXPECTATIONS, - *hir_id, - expectation.emission_span, - Expectation { rationale, note }, - ); + // Turn a `LintExpectationId` into a `(AttrId, lint_index)` pair. + let canonicalize_id = |expect_id: &LintExpectationId| { + match *expect_id { + LintExpectationId::Unstable { attr_id, lint_index: Some(lint_index) } => { + (attr_id, lint_index) + } + LintExpectationId::Stable { hir_id, attr_index, lint_index: Some(lint_index) } => { + // We are an `eval_always` query, so looking at the attribute's `AttrId` is ok. + let attr_id = tcx.hir().attrs(hir_id)[attr_index as usize].id; + (attr_id, lint_index) } - } else { + _ => panic!("fulfilled expectations must have a lint index"), + } + }; + + let fulfilled_expectations: FxHashSet<_> = + fulfilled_expectations.iter().map(canonicalize_id).collect(); + + for (expect_id, expectation) in lint_expectations { + // This check will always be true, since `lint_expectations` only holds stable ids + let LintExpectationId::Stable { hir_id, .. } = expect_id else { unreachable!("at this stage all `LintExpectationId`s are stable"); + }; + + let expect_id = canonicalize_id(expect_id); + + if !fulfilled_expectations.contains(&expect_id) + && tool_filter.map_or(true, |filter| expectation.lint_tool == Some(filter)) + { + let rationale = expectation.reason.map(|rationale| ExpectationNote { rationale }); + let note = expectation.is_unfulfilled_lint_expectations; + tcx.emit_node_span_lint( + UNFULFILLED_LINT_EXPECTATIONS, + *hir_id, + expectation.emission_span, + Expectation { rationale, note }, + ); } } } diff --git a/tests/ui/lint/expect-unused-imports.rs b/tests/ui/lint/expect-unused-imports.rs new file mode 100644 index 0000000000000..fc5b1bf2a0fe6 --- /dev/null +++ b/tests/ui/lint/expect-unused-imports.rs @@ -0,0 +1,9 @@ +//@ check-pass + +#![deny(unused_imports)] +#![deny(unfulfilled_lint_expectations)] + +#[expect(unused_imports)] +use std::{io, fs}; + +fn main() {} diff --git a/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.stderr b/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.stderr index 29e579464c8de..eaf9edd8e8fee 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.stderr +++ b/tests/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.stderr @@ -1,3 +1,11 @@ +warning: denote infinite loops with `loop { ... }` + --> $DIR/force_warn_expected_lints_fulfilled.rs:8:5 + | +LL | while true { + | ^^^^^^^^^^ help: use `loop` + | + = note: requested on the command line with `--force-warn while-true` + warning: unused variable: `x` --> $DIR/force_warn_expected_lints_fulfilled.rs:18:9 | @@ -28,13 +36,5 @@ warning: unused variable: `this_should_fulfill_the_expectation` LL | let this_should_fulfill_the_expectation = "The `#[allow]` has no power here"; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_this_should_fulfill_the_expectation` -warning: denote infinite loops with `loop { ... }` - --> $DIR/force_warn_expected_lints_fulfilled.rs:8:5 - | -LL | while true { - | ^^^^^^^^^^ help: use `loop` - | - = note: requested on the command line with `--force-warn while-true` - warning: 5 warnings emitted From 6dfc4033be7c7d9f6551b2db093fd3bdbbc45cc2 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 7 Sep 2024 01:34:22 +0000 Subject: [PATCH 033/189] Do not ICE on expect(warnings). --- compiler/rustc_errors/src/lib.rs | 17 +++++------------ .../rfc-2383-lint-reason/expect_warnings.rs | 6 ++++++ 2 files changed, 11 insertions(+), 12 deletions(-) create mode 100644 tests/ui/lint/rfc-2383-lint-reason/expect_warnings.rs diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 26e3a63c9d6d0..13da1721a4a32 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -502,14 +502,14 @@ struct DiagCtxtInner { /// marked as fulfilled. This is a collection of all [`LintExpectationId`]s /// that have been marked as fulfilled this way. /// + /// Emitting expectations after having stolen this field can happen. In particular, an + /// `#[expect(warnings)]` can easily make the `UNFULFILLED_LINT_EXPECTATIONS` lint expect + /// itself. To avoid needless complexity in this corner case, we tolerate failing to track + /// those expectations. + /// /// [RFC-2383]: https://rust-lang.github.io/rfcs/2383-lint-reasons.html fulfilled_expectations: FxIndexSet, - /// Whether `fulfilled_expectations` has been stolen. This is used to ICE in case we emit - /// an expectation diagnostic after stealing it, which means that expectation would not be - /// correctly handled. - stolen_fulfilled_expectations: bool, - /// The file where the ICE information is stored. This allows delayed_span_bug backtraces to be /// stored along side the main panic backtrace. ice_file: Option, @@ -724,7 +724,6 @@ impl DiagCtxt { stashed_diagnostics, future_breakage_diagnostics, fulfilled_expectations, - stolen_fulfilled_expectations: _, ice_file: _, } = inner.deref_mut(); @@ -1078,7 +1077,6 @@ impl<'a> DiagCtxtHandle<'a> { /// [`DiagCtxtInner`] and indicate that the linked expectation has been fulfilled. #[must_use] pub fn steal_fulfilled_expectation_ids(&self) -> FxIndexSet { - self.inner.borrow_mut().stolen_fulfilled_expectations = true; std::mem::take(&mut self.inner.borrow_mut().fulfilled_expectations) } @@ -1388,7 +1386,6 @@ impl DiagCtxtInner { stashed_diagnostics: Default::default(), future_breakage_diagnostics: Vec::new(), fulfilled_expectations: Default::default(), - stolen_fulfilled_expectations: false, ice_file: None, } } @@ -1492,10 +1489,6 @@ impl DiagCtxtInner { return None; } Expect(expect_id) | ForceWarning(Some(expect_id)) => { - assert!( - !self.stolen_fulfilled_expectations, - "Attempting to emit an expected diagnostic after `check_expectations`.", - ); self.fulfilled_expectations.insert(expect_id); if let Expect(_) = diagnostic.level { // Nothing emitted here for expected lints. diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_warnings.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_warnings.rs new file mode 100644 index 0000000000000..35d9e02d3c3d9 --- /dev/null +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_warnings.rs @@ -0,0 +1,6 @@ +//@ check-pass + +#![expect(warnings)] + +#[expect(unused)] +fn main() {} From 46115fd6d3be8a868ebfdabb20d44673ab47ab60 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Fri, 6 Sep 2024 18:43:42 +0200 Subject: [PATCH 034/189] fix ICE in CMSE type validation --- .../src/hir_ty_lowering/cmse.rs | 13 +++--- .../cmse-nonsecure-call/generics.rs | 25 ++++++++++- .../cmse-nonsecure-call/generics.stderr | 45 ++++++++++++++++--- 3 files changed, 70 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs index 1b73cecd6664b..dd519fb92d951 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs @@ -18,6 +18,9 @@ pub(crate) fn validate_cmse_abi<'tcx>( abi: abi::Abi, fn_sig: ty::PolyFnSig<'tcx>, ) { + // this type is only used for layout computation, which does not rely on regions + let fn_sig = tcx.instantiate_bound_regions_with_erased(fn_sig); + if let abi::Abi::CCmseNonSecureCall = abi { let hir_node = tcx.hir_node(hir_id); let hir::Node::Ty(hir::Ty { @@ -67,13 +70,13 @@ pub(crate) fn validate_cmse_abi<'tcx>( /// Returns whether the inputs will fit into the available registers fn is_valid_cmse_inputs<'tcx>( tcx: TyCtxt<'tcx>, - fn_sig: ty::PolyFnSig<'tcx>, + fn_sig: ty::FnSig<'tcx>, ) -> Result, &'tcx LayoutError<'tcx>> { let mut span = None; let mut accum = 0u64; - for (index, arg_def) in fn_sig.inputs().iter().enumerate() { - let layout = tcx.layout_of(ParamEnv::reveal_all().and(*arg_def.skip_binder()))?; + for (index, ty) in fn_sig.inputs().iter().enumerate() { + let layout = tcx.layout_of(ParamEnv::reveal_all().and(*ty))?; let align = layout.layout.align().abi.bytes(); let size = layout.layout.size().bytes(); @@ -96,9 +99,9 @@ fn is_valid_cmse_inputs<'tcx>( /// Returns whether the output will fit into the available registers fn is_valid_cmse_output<'tcx>( tcx: TyCtxt<'tcx>, - fn_sig: ty::PolyFnSig<'tcx>, + fn_sig: ty::FnSig<'tcx>, ) -> Result> { - let mut ret_ty = fn_sig.output().skip_binder(); + let mut ret_ty = fn_sig.output(); let layout = tcx.layout_of(ParamEnv::reveal_all().and(ret_ty))?; let size = layout.layout.size().bytes(); diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.rs index e6b0bf3e6860b..9e0ffa75c2296 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.rs @@ -12,10 +12,31 @@ impl Copy for u32 {} struct Wrapper(T); struct Test { - f1: extern "C-cmse-nonsecure-call" fn(U, u32, u32, u32) -> u64, //~ ERROR cannot find type `U` in this scope - //~^ ERROR function pointer types may not have generic parameters + f1: extern "C-cmse-nonsecure-call" fn(U, u32, u32, u32) -> u64, + //~^ ERROR cannot find type `U` in this scope + //~| ERROR function pointer types may not have generic parameters f2: extern "C-cmse-nonsecure-call" fn(impl Copy, u32, u32, u32) -> u64, //~^ ERROR `impl Trait` is not allowed in `fn` pointer parameters f3: extern "C-cmse-nonsecure-call" fn(T, u32, u32, u32) -> u64, //~ ERROR [E0798] f4: extern "C-cmse-nonsecure-call" fn(Wrapper, u32, u32, u32) -> u64, //~ ERROR [E0798] } + +type WithReference = extern "C-cmse-nonsecure-call" fn(&usize); + +trait Trait {} +type WithTraitObject = extern "C-cmse-nonsecure-call" fn(&dyn Trait) -> &dyn Trait; +//~^ ERROR return value of `"C-cmse-nonsecure-call"` function too large to pass via registers [E0798] + +type WithStaticTraitObject = + extern "C-cmse-nonsecure-call" fn(&'static dyn Trait) -> &'static dyn Trait; +//~^ ERROR return value of `"C-cmse-nonsecure-call"` function too large to pass via registers [E0798] + +#[repr(transparent)] +struct WrapperTransparent<'a>(&'a dyn Trait); + +type WithTransparentTraitObject = + extern "C-cmse-nonsecure-call" fn(WrapperTransparent) -> WrapperTransparent; +//~^ ERROR return value of `"C-cmse-nonsecure-call"` function too large to pass via registers [E0798] + +type WithVarArgs = extern "C-cmse-nonsecure-call" fn(u32, ...); +//~^ ERROR C-variadic function must have a compatible calling convention, like `C` or `cdecl` [E0045] diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr index fa68d95218ccd..7cb8e135ea31b 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr @@ -22,7 +22,7 @@ LL | struct Test { | +++ error[E0562]: `impl Trait` is not allowed in `fn` pointer parameters - --> $DIR/generics.rs:17:43 + --> $DIR/generics.rs:18:43 | LL | f2: extern "C-cmse-nonsecure-call" fn(impl Copy, u32, u32, u32) -> u64, | ^^^^^^^^^ @@ -30,18 +30,51 @@ LL | f2: extern "C-cmse-nonsecure-call" fn(impl Copy, u32, u32, u32) -> u64, = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0798]: function pointers with the `"C-cmse-nonsecure-call"` ABI cannot contain generics in their type - --> $DIR/generics.rs:19:9 + --> $DIR/generics.rs:20:9 | LL | f3: extern "C-cmse-nonsecure-call" fn(T, u32, u32, u32) -> u64, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0798]: function pointers with the `"C-cmse-nonsecure-call"` ABI cannot contain generics in their type - --> $DIR/generics.rs:20:9 + --> $DIR/generics.rs:21:9 | LL | f4: extern "C-cmse-nonsecure-call" fn(Wrapper, u32, u32, u32) -> u64, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 5 previous errors +error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers + --> $DIR/generics.rs:27:73 + | +LL | type WithTraitObject = extern "C-cmse-nonsecure-call" fn(&dyn Trait) -> &dyn Trait; + | ^^^^^^^^^^ this type doesn't fit in the available registers + | + = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers + = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size + +error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers + --> $DIR/generics.rs:31:62 + | +LL | extern "C-cmse-nonsecure-call" fn(&'static dyn Trait) -> &'static dyn Trait; + | ^^^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers + | + = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers + = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size + +error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers + --> $DIR/generics.rs:38:62 + | +LL | extern "C-cmse-nonsecure-call" fn(WrapperTransparent) -> WrapperTransparent; + | ^^^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers + | + = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers + = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size + +error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl` + --> $DIR/generics.rs:41:20 + | +LL | type WithVarArgs = extern "C-cmse-nonsecure-call" fn(u32, ...); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention + +error: aborting due to 9 previous errors -Some errors have detailed explanations: E0412, E0562, E0798. -For more information about an error, try `rustc --explain E0412`. +Some errors have detailed explanations: E0045, E0412, E0562, E0798. +For more information about an error, try `rustc --explain E0045`. From a6c6eda61d68e7833ab541ea1479942a58f7ff3e Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sat, 7 Sep 2024 13:24:16 +0200 Subject: [PATCH 035/189] Remove now redundant check in symlink_hard_link test We support macOS 10.12 and above, so it now always uses linkat, so the check is redundant. This was missed in #126351. --- library/std/src/fs/tests.rs | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 13028c4c3b57e..fb8dd2b0ca149 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -1,7 +1,5 @@ use rand::RngCore; -#[cfg(target_os = "macos")] -use crate::ffi::{c_char, c_int}; use crate::fs::{self, File, FileTimes, OpenOptions}; use crate::io::prelude::*; use crate::io::{BorrowedBuf, ErrorKind, SeekFrom}; @@ -16,8 +14,6 @@ use crate::os::unix::fs::symlink as junction_point; use crate::os::windows::fs::{junction_point, symlink_dir, symlink_file, OpenOptionsExt}; use crate::path::Path; use crate::sync::Arc; -#[cfg(target_os = "macos")] -use crate::sys::weak::weak; use crate::sys_common::io::test::{tmpdir, TempDir}; use crate::time::{Duration, Instant, SystemTime}; use crate::{env, str, thread}; @@ -80,17 +76,6 @@ pub fn got_symlink_permission(tmpdir: &TempDir) -> bool { } } -#[cfg(target_os = "macos")] -fn able_to_not_follow_symlinks_while_hard_linking() -> bool { - weak!(fn linkat(c_int, *const c_char, c_int, *const c_char, c_int) -> c_int); - linkat.get().is_some() -} - -#[cfg(not(target_os = "macos"))] -fn able_to_not_follow_symlinks_while_hard_linking() -> bool { - return true; -} - #[test] fn file_test_io_smoke_test() { let message = "it's alright. have a good time"; @@ -1456,9 +1441,6 @@ fn symlink_hard_link() { if !got_symlink_permission(&tmpdir) { return; }; - if !able_to_not_follow_symlinks_while_hard_linking() { - return; - } // Create "file", a file. check!(fs::File::create(tmpdir.join("file"))); From c788dcc674c3067461e1dcfc33a52fe73bd409ba Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sat, 7 Sep 2024 13:51:14 +0200 Subject: [PATCH 036/189] Test codegen when setting deployment target --- src/tools/run-make-support/src/lib.rs | 2 +- src/tools/run-make-support/src/targets.rs | 18 ++ .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/apple-deployment-target/foo.rs | 1 + .../run-make/apple-deployment-target/rmake.rs | 157 ++++++++++++++++++ .../run-make/macos-deployment-target/Makefile | 21 --- .../with_deployment_target.rs | 4 - 7 files changed, 177 insertions(+), 27 deletions(-) create mode 100644 tests/run-make/apple-deployment-target/foo.rs create mode 100644 tests/run-make/apple-deployment-target/rmake.rs delete mode 100644 tests/run-make/macos-deployment-target/Makefile delete mode 100644 tests/run-make/macos-deployment-target/with_deployment_target.rs diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index fefafb95b33b1..980bd37dca8ae 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -73,7 +73,7 @@ pub use env::{env_var, env_var_os, set_current_dir}; pub use run::{cmd, run, run_fail, run_with_args}; /// Helpers for checking target information. -pub use targets::{is_darwin, is_msvc, is_windows, llvm_components_contain, target, uname}; +pub use targets::{is_darwin, is_msvc, is_windows, llvm_components_contain, target, uname, apple_os}; /// Helpers for building names of output artifacts that are potentially target-specific. pub use artifact_names::{ diff --git a/src/tools/run-make-support/src/targets.rs b/src/tools/run-make-support/src/targets.rs index 5dcb0b83430f9..896abb73fc108 100644 --- a/src/tools/run-make-support/src/targets.rs +++ b/src/tools/run-make-support/src/targets.rs @@ -28,6 +28,24 @@ pub fn is_darwin() -> bool { target().contains("darwin") } +/// Get the target OS on Apple operating systems. +#[must_use] +pub fn apple_os() -> &'static str { + if target().contains("darwin") { + "macos" + } else if target().contains("ios") { + "ios" + } else if target().contains("tvos") { + "tvos" + } else if target().contains("watchos") { + "watchos" + } else if target().contains("visionos") { + "visionos" + } else { + panic!("not an Apple OS") + } +} + /// Check if `component` is within `LLVM_COMPONENTS` #[must_use] pub fn llvm_components_contain(component: &str) -> bool { diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 22d1e93bf399a..50d21c7ed4c99 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -6,7 +6,6 @@ run-make/incr-add-rust-src-component/Makefile run-make/issue-84395-lto-embed-bitcode/Makefile run-make/jobserver-error/Makefile run-make/libs-through-symlinks/Makefile -run-make/macos-deployment-target/Makefile run-make/split-debuginfo/Makefile run-make/symbol-mangling-hashed/Makefile run-make/translation/Makefile diff --git a/tests/run-make/apple-deployment-target/foo.rs b/tests/run-make/apple-deployment-target/foo.rs new file mode 100644 index 0000000000000..f328e4d9d04c3 --- /dev/null +++ b/tests/run-make/apple-deployment-target/foo.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/tests/run-make/apple-deployment-target/rmake.rs b/tests/run-make/apple-deployment-target/rmake.rs new file mode 100644 index 0000000000000..b2d1af65177ef --- /dev/null +++ b/tests/run-make/apple-deployment-target/rmake.rs @@ -0,0 +1,157 @@ +//! Test codegen when setting deployment targets on Apple platforms. +//! +//! This is important since its a compatibility hazard. The linker will +//! generate load commands differently based on what minimum OS it can assume. +//! +//! See https://github.com/rust-lang/rust/pull/105123. + +//@ only-apple + +use run_make_support::{apple_os, cmd, run_in_tmpdir, rustc, target}; + +/// Run vtool to check the `minos` field in LC_BUILD_VERSION. +/// +/// On lower deployment targets, LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS and similar +/// are used instead of LC_BUILD_VERSION - these have a `version` field, so also check that. +#[track_caller] +fn minos(file: &str, version: &str) { + cmd("vtool") + .arg("-show-build") + .arg(file) + .run() + .assert_stdout_contains_regex(format!("(minos|version) {version}")); +} + +fn main() { + // These versions should generally be higher than the default versions + let (env_var, example_version, higher_example_version) = match apple_os() { + "macos" => ("MACOSX_DEPLOYMENT_TARGET", "12.0", "13.0"), + // armv7s-apple-ios and i386-apple-ios only supports iOS 10.0 + "ios" if target() == "armv7s-apple-ios" || target() == "i386-apple-ios" => { + ("IPHONEOS_DEPLOYMENT_TARGET", "10.0", "10.0") + } + "ios" => ("IPHONEOS_DEPLOYMENT_TARGET", "15.0", "16.0"), + "watchos" => ("WATCHOS_DEPLOYMENT_TARGET", "7.0", "9.0"), + "tvos" => ("TVOS_DEPLOYMENT_TARGET", "14.0", "15.0"), + "visionos" => ("XROS_DEPLOYMENT_TARGET", "1.1", "1.2"), + _ => unreachable!(), + }; + let default_version = + rustc().target(target()).env_remove(env_var).print("deployment-target").run().stdout_utf8(); + let default_version = default_version.strip_prefix("deployment_target=").unwrap().trim(); + + // Test that version makes it to the object file. + run_in_tmpdir(|| { + let rustc = || { + let mut rustc = rustc(); + rustc.target(target()); + rustc.crate_type("lib"); + rustc.emit("obj"); + rustc.input("foo.rs"); + rustc.output("foo.o"); + rustc + }; + + rustc().env(env_var, example_version).run(); + minos("foo.o", example_version); + + // FIXME(madsmtm): Doesn't work on Mac Catalyst and the simulator. + if !target().contains("macabi") && !target().contains("sim") { + rustc().env_remove(env_var).run(); + minos("foo.o", default_version); + } + }); + + // Test that version makes it to the linker when linking dylibs. + run_in_tmpdir(|| { + // Certain watchOS targets don't support dynamic linking, so we disable the test on those. + if apple_os() == "watchos" { + return; + } + + let rustc = || { + let mut rustc = rustc(); + rustc.target(target()); + rustc.crate_type("dylib"); + rustc.input("foo.rs"); + rustc.output("libfoo.dylib"); + rustc + }; + + rustc().env(env_var, example_version).run(); + minos("libfoo.dylib", example_version); + + // FIXME(madsmtm): Deployment target is not currently passed properly to linker + // rustc().env_remove(env_var).run(); + // minos("libfoo.dylib", default_version); + + // Test with ld64 instead + + rustc().arg("-Clinker-flavor=ld").env(env_var, example_version).run(); + minos("libfoo.dylib", example_version); + + rustc().arg("-Clinker-flavor=ld").env_remove(env_var).run(); + minos("libfoo.dylib", default_version); + }); + + // Test that version makes it to the linker when linking executables. + run_in_tmpdir(|| { + let rustc = || { + let mut rustc = rustc(); + rustc.target(target()); + rustc.crate_type("bin"); + rustc.input("foo.rs"); + rustc.output("foo"); + rustc + }; + + // FIXME(madsmtm): Doesn't work on watchOS for some reason? + if !target().contains("watchos") { + rustc().env(env_var, example_version).run(); + minos("foo", example_version); + + // FIXME(madsmtm): Deployment target is not currently passed properly to linker + // rustc().env_remove(env_var).run(); + // minos("foo", default_version); + } + + // Test with ld64 instead + + rustc().arg("-Clinker-flavor=ld").env(env_var, example_version).run(); + minos("foo", example_version); + + rustc().arg("-Clinker-flavor=ld").env_remove(env_var).run(); + minos("foo", default_version); + }); + + // Test that changing the deployment target busts the incremental cache. + run_in_tmpdir(|| { + let rustc = || { + let mut rustc = rustc(); + rustc.target(target()); + rustc.incremental("incremental"); + rustc.crate_type("lib"); + rustc.emit("obj"); + rustc.input("foo.rs"); + rustc.output("foo.o"); + rustc + }; + + // FIXME(madsmtm): Incremental cache is not yet busted + // https://github.com/rust-lang/rust/issues/118204 + let higher_example_version = example_version; + let default_version = example_version; + + rustc().env(env_var, example_version).run(); + minos("foo.o", example_version); + + rustc().env(env_var, higher_example_version).run(); + minos("foo.o", higher_example_version); + + // FIXME(madsmtm): Doesn't work on Mac Catalyst and the simulator. + if !target().contains("macabi") && !target().contains("sim") { + rustc().env_remove(env_var).run(); + minos("foo.o", default_version); + } + }); +} diff --git a/tests/run-make/macos-deployment-target/Makefile b/tests/run-make/macos-deployment-target/Makefile deleted file mode 100644 index 757ca6995350f..0000000000000 --- a/tests/run-make/macos-deployment-target/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -# only-macos -# -# Check that a set deployment target actually makes it to the linker. -# This is important since its a compatibility hazard. The linker will -# generate load commands differently based on what minimum OS it can assume. - -include ../tools.mk - -ifeq ($(strip $(shell uname -m)),arm64) - GREP_PATTERN = "minos 11.0" -else - GREP_PATTERN = "version 10.13" -endif - -OUT_FILE=$(TMPDIR)/with_deployment_target.dylib -all: - env MACOSX_DEPLOYMENT_TARGET=10.13 $(RUSTC) with_deployment_target.rs -o $(OUT_FILE) -# XXX: The check is for either the x86_64 minimum OR the aarch64 minimum (M1 starts at macOS 11). -# They also use different load commands, so we let that change with each too. The aarch64 check -# isn't as robust as the x86 one, but testing both seems unneeded. - vtool -show-build $(OUT_FILE) | $(CGREP) -e $(GREP_PATTERN) diff --git a/tests/run-make/macos-deployment-target/with_deployment_target.rs b/tests/run-make/macos-deployment-target/with_deployment_target.rs deleted file mode 100644 index 342fe0ecbcfcd..0000000000000 --- a/tests/run-make/macos-deployment-target/with_deployment_target.rs +++ /dev/null @@ -1,4 +0,0 @@ -#![crate_type = "cdylib"] - -#[allow(dead_code)] -fn something_and_nothing() {} From c0b06273f23846434f260834d2274ed2049b02ec Mon Sep 17 00:00:00 2001 From: Gurinder Singh Date: Sat, 7 Sep 2024 18:50:51 +0530 Subject: [PATCH 037/189] Rename variant `AddrOfRegion` of `RegionVariableOrigin` to `BorrowRegion` because "Borrow" is the more idiomatic Rust term than "AddrOf". --- compiler/rustc_hir_typeck/src/expr.rs | 2 +- compiler/rustc_infer/src/infer/mod.rs | 6 +++--- .../src/error_reporting/infer/region.rs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index f0d47e584ac28..9bad5633b69dc 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -447,7 +447,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // this time with enough precision to check that the value // whose address was taken can actually be made to live as long // as it needs to live. - let region = self.next_region_var(infer::AddrOfRegion(expr.span)); + let region = self.next_region_var(infer::BorrowRegion(expr.span)); Ty::new_ref(self.tcx, region, ty, mutbl) } } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 234dc5133f8db..63a729b13dc40 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -458,8 +458,8 @@ pub enum RegionVariableOrigin { PatternRegion(Span), /// Regions created by `&` operator. - /// - AddrOfRegion(Span), + BorrowRegion(Span), + /// Regions created as part of an autoref of a method receiver. Autoref(Span), @@ -1741,7 +1741,7 @@ impl RegionVariableOrigin { match *self { MiscVariable(a) | PatternRegion(a) - | AddrOfRegion(a) + | BorrowRegion(a) | Autoref(a) | Coercion(a) | RegionParameterDefinition(a, ..) diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index e4a4ec125a5c4..0473c73ef6255 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -1018,7 +1018,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let var_description = match var_origin { infer::MiscVariable(_) => String::new(), infer::PatternRegion(_) => " for pattern".to_string(), - infer::AddrOfRegion(_) => " for borrow expression".to_string(), + infer::BorrowRegion(_) => " for borrow expression".to_string(), infer::Autoref(_) => " for autoref".to_string(), infer::Coercion(_) => " for automatic coercion".to_string(), infer::BoundRegion(_, br, infer::FnCall) => { From f7d4da65c7df37c316d9e2793dff1ae6c994c44d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 7 Sep 2024 21:41:28 +0200 Subject: [PATCH 038/189] remove 'const' from 'Option::iter' --- library/core/src/option.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 50cb22b7eb3f5..b48c6136a4577 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1338,9 +1338,8 @@ impl Option { /// assert_eq!(x.iter().next(), None); /// ``` #[inline] - #[rustc_const_unstable(feature = "const_option", issue = "67441")] #[stable(feature = "rust1", since = "1.0.0")] - pub const fn iter(&self) -> Iter<'_, T> { + pub fn iter(&self) -> Iter<'_, T> { Iter { inner: Item { opt: self.as_ref() } } } From 03e0c8edb2114aaf92fb8d93a18dfb0028690765 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 7 Sep 2024 22:19:30 +0200 Subject: [PATCH 039/189] make Result::copied unstably const --- library/core/src/result.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 73b11f803d929..a7fd95e007982 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1535,11 +1535,17 @@ impl Result<&T, E> { /// ``` #[inline] #[stable(feature = "result_copied", since = "1.59.0")] - pub fn copied(self) -> Result + #[rustc_const_unstable(feature = "const_result", issue = "82814")] + pub const fn copied(self) -> Result where T: Copy, { - self.map(|&t| t) + // FIXME: this implementation, which sidesteps using `Result::map` since it's not const + // ready yet, should be reverted when possible to avoid code repetition + match self { + Ok(&v) => Ok(v), + Err(e) => Err(e), + } } /// Maps a `Result<&T, E>` to a `Result` by cloning the contents of the From cfe85a3a73ab756acd5fb85cebcb7c89aa1df4c8 Mon Sep 17 00:00:00 2001 From: Zack Slayton Date: Sat, 7 Sep 2024 17:36:47 -0400 Subject: [PATCH 040/189] Fixes typo in wasm32-wasip2 doc comment --- compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs index 40f026ca93814..876aa7073f812 100644 --- a/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs +++ b/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs @@ -1,6 +1,6 @@ //! The `wasm32-wasip2` target is the next evolution of the //! wasm32-wasi target. While the wasi specification is still under -//! active development, the {review 2 iteration is considered an "island +//! active development, the preview 2 iteration is considered an "island //! of stability" that should allow users to rely on it indefinitely. //! //! The `wasi` target is a proposal to define a standardized set of WebAssembly From 3782251c2c6e6e7fedb806a97664ee38ced1677b Mon Sep 17 00:00:00 2001 From: EtomicBomb Date: Mon, 26 Aug 2024 21:40:52 -0700 Subject: [PATCH 041/189] librustdoc::config: removed Input from Options The `librustdoc::config::Options` struct no longer includes `rustc_session::config::Input`. This is so that Input can be optional. In rfc#3662, the crate input is not required if `--merge=finalize`. Replacing Input with Option was decided against. In most places that Input is needed, it should be statically known to not be optional (means fewer unwraps). We just want to have an Input-free Options in librustdoc::main_args, where we can run the write shared procedure. --- src/librustdoc/config.rs | 18 ++++++------------ src/librustdoc/core.rs | 4 ++-- src/librustdoc/doctest.rs | 10 +++++++--- src/librustdoc/doctest/markdown.rs | 11 +++++------ src/librustdoc/lib.rs | 26 ++++++++++++++------------ 5 files changed, 34 insertions(+), 35 deletions(-) diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 9e7b69ec45faa..7e4e8fd506f5f 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -57,8 +57,6 @@ impl TryFrom<&str> for OutputFormat { #[derive(Clone)] pub(crate) struct Options { // Basic options / Options passed directly to rustc - /// The crate root or Markdown file to load. - pub(crate) input: Input, /// The name of the crate being documented. pub(crate) crate_name: Option, /// Whether or not this is a bin crate @@ -179,7 +177,6 @@ impl fmt::Debug for Options { } f.debug_struct("Options") - .field("input", &self.input.source_name()) .field("crate_name", &self.crate_name) .field("bin_crate", &self.bin_crate) .field("proc_macro_crate", &self.proc_macro_crate) @@ -348,7 +345,7 @@ impl Options { early_dcx: &mut EarlyDiagCtxt, matches: &getopts::Matches, args: Vec, - ) -> Option<(Options, RenderOptions)> { + ) -> Option<(Input, Options, RenderOptions)> { // Check for unstable options. nightly_options::check_nightly_options(early_dcx, matches, &opts()); @@ -751,7 +748,6 @@ impl Options { let unstable_features = rustc_feature::UnstableFeatures::from_environment(crate_name.as_deref()); let options = Options { - input, bin_crate, proc_macro_crate, error_format, @@ -824,15 +820,13 @@ impl Options { html_no_source, output_to_stdout, }; - Some((options, render_options)) + Some((input, options, render_options)) } +} - /// Returns `true` if the file given as `self.input` is a Markdown file. - pub(crate) fn markdown_input(&self) -> Option<&Path> { - self.input - .opt_path() - .filter(|p| matches!(p.extension(), Some(e) if e == "md" || e == "markdown")) - } +/// Returns `true` if the file given as `self.input` is a Markdown file. +pub(crate) fn markdown_input(input: &Input) -> Option<&Path> { + input.opt_path().filter(|p| matches!(p.extension(), Some(e) if e == "md" || e == "markdown")) } fn parse_remap_path_prefix( diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 2cde0ac5c5354..4fafef657925f 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -20,7 +20,7 @@ use rustc_interface::interface; use rustc_lint::{late_lint_mod, MissingDoc}; use rustc_middle::hir::nested_filter; use rustc_middle::ty::{ParamEnv, Ty, TyCtxt}; -use rustc_session::config::{self, CrateType, ErrorOutputType, ResolveDocLinks}; +use rustc_session::config::{self, CrateType, ErrorOutputType, Input, ResolveDocLinks}; pub(crate) use rustc_session::config::{Options, UnstableOptions}; use rustc_session::{lint, Session}; use rustc_span::symbol::sym; @@ -177,8 +177,8 @@ pub(crate) fn new_dcx( /// Parse, resolve, and typecheck the given crate. pub(crate) fn create_config( + input: Input, RustdocOptions { - input, crate_name, proc_macro_crate, error_format, diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 8b6588ea75c83..05ef72892012d 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -19,7 +19,7 @@ use rustc_errors::{ColorConfig, DiagCtxtHandle, ErrorGuaranteed, FatalError}; use rustc_hir::def_id::LOCAL_CRATE; use rustc_hir::CRATE_HIR_ID; use rustc_interface::interface; -use rustc_session::config::{self, CrateType, ErrorOutputType}; +use rustc_session::config::{self, CrateType, ErrorOutputType, Input}; use rustc_session::lint; use rustc_span::edition::Edition; use rustc_span::symbol::sym; @@ -88,7 +88,11 @@ fn get_doctest_dir() -> io::Result { TempFileBuilder::new().prefix("rustdoctest").tempdir() } -pub(crate) fn run(dcx: DiagCtxtHandle<'_>, options: RustdocOptions) -> Result<(), ErrorGuaranteed> { +pub(crate) fn run( + dcx: DiagCtxtHandle<'_>, + input: Input, + options: RustdocOptions, +) -> Result<(), ErrorGuaranteed> { let invalid_codeblock_attributes_name = crate::lint::INVALID_CODEBLOCK_ATTRIBUTES.name; // See core::create_config for what's going on here. @@ -135,7 +139,7 @@ pub(crate) fn run(dcx: DiagCtxtHandle<'_>, options: RustdocOptions) -> Result<() opts: sessopts, crate_cfg: cfgs, crate_check_cfg: options.check_cfgs.clone(), - input: options.input.clone(), + input: input.clone(), output_file: None, output_dir: None, file_loader: None, diff --git a/src/librustdoc/doctest/markdown.rs b/src/librustdoc/doctest/markdown.rs index 9a237f8684d8f..4f83bd5e8826a 100644 --- a/src/librustdoc/doctest/markdown.rs +++ b/src/librustdoc/doctest/markdown.rs @@ -3,6 +3,7 @@ use std::fs::read_to_string; use std::sync::{Arc, Mutex}; +use rustc_session::config::Input; use rustc_span::FileName; use tempfile::tempdir; @@ -69,9 +70,8 @@ impl DocTestVisitor for MdCollector { } /// Runs any tests/code examples in the markdown file `options.input`. -pub(crate) fn test(options: Options) -> Result<(), String> { - use rustc_session::config::Input; - let input_str = match &options.input { +pub(crate) fn test(input: &Input, options: Options) -> Result<(), String> { + let input_str = match input { Input::File(path) => { read_to_string(path).map_err(|err| format!("{}: {err}", path.display()))? } @@ -79,7 +79,7 @@ pub(crate) fn test(options: Options) -> Result<(), String> { }; // Obviously not a real crate name, but close enough for purposes of doctests. - let crate_name = options.input.filestem().to_string(); + let crate_name = input.filestem().to_string(); let temp_dir = tempdir().map_err(|error| format!("failed to create temporary directory: {error:?}"))?; let args_file = temp_dir.path().join("rustdoc-cfgs"); @@ -96,8 +96,7 @@ pub(crate) fn test(options: Options) -> Result<(), String> { let mut md_collector = MdCollector { tests: vec![], cur_path: vec![], - filename: options - .input + filename: input .opt_path() .map(ToOwned::to_owned) .map(FileName::from) diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index f25acbe080ada..e470aef3643e9 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -727,22 +727,24 @@ fn main_args( // Note that we discard any distinction between different non-zero exit // codes from `from_matches` here. - let (options, render_options) = match config::Options::from_matches(early_dcx, &matches, args) { - Some(opts) => opts, - None => return Ok(()), - }; + let (input, options, render_options) = + match config::Options::from_matches(early_dcx, &matches, args) { + Some(opts) => opts, + None => return Ok(()), + }; let dcx = core::new_dcx(options.error_format, None, options.diagnostic_width, &options.unstable_opts); let dcx = dcx.handle(); - match (options.should_test, options.markdown_input()) { - (true, Some(_)) => return wrap_return(dcx, doctest::test_markdown(options)), - (true, None) => return doctest::run(dcx, options), - (false, Some(input)) => { - let input = input.to_owned(); + match (options.should_test, config::markdown_input(&input)) { + (true, Some(_)) => return wrap_return(dcx, doctest::test_markdown(&input, options)), + (true, None) => return doctest::run(dcx, input, options), + (false, Some(md_input)) => { + let md_input = md_input.to_owned(); let edition = options.edition; - let config = core::create_config(options, &render_options, using_internal_features); + let config = + core::create_config(input, options, &render_options, using_internal_features); // `markdown::render` can invoke `doctest::make_test`, which // requires session globals and a thread pool, so we use @@ -750,7 +752,7 @@ fn main_args( return wrap_return( dcx, interface::run_compiler(config, |_compiler| { - markdown::render(&input, render_options, edition) + markdown::render(&md_input, render_options, edition) }), ); } @@ -775,7 +777,7 @@ fn main_args( let scrape_examples_options = options.scrape_examples_options.clone(); let bin_crate = options.bin_crate; - let config = core::create_config(options, &render_options, using_internal_features); + let config = core::create_config(input, options, &render_options, using_internal_features); interface::run_compiler(config, |compiler| { let sess = &compiler.sess; From 2e1cba64157c9bf60f7bc010268ac0bd5ca9438c Mon Sep 17 00:00:00 2001 From: EtomicBomb Date: Tue, 20 Aug 2024 23:34:19 +0000 Subject: [PATCH 042/189] rfc#3662 changes under unstable flags * All new functionality is under unstable options * Adds `--merge=shared|none|finalize` flags * Adds `--parts-out-dir=` for `--merge=none` to write cross-crate info file for a single crate * Adds `--include-parts-dir=` for `--merge=finalize` to write cross-crate info files * update tests/run-make/rustdoc-default-output/rmake.rs golden --- src/librustdoc/config.rs | 109 ++++++++++- src/librustdoc/html/render/context.rs | 175 ++++++++--------- src/librustdoc/html/render/mod.rs | 1 + src/librustdoc/html/render/write_shared.rs | 178 +++++++++++++----- .../html/render/write_shared/tests.rs | 10 +- src/librustdoc/lib.rs | 64 +++++++ .../output-default.stdout | 17 ++ 7 files changed, 419 insertions(+), 135 deletions(-) diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 7e4e8fd506f5f..b3c87a725080f 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -53,6 +53,14 @@ impl TryFrom<&str> for OutputFormat { } } +/// Either an input crate, markdown file, or nothing (--merge=finalize). +pub(crate) enum InputMode { + /// The `--merge=finalize` step does not need an input crate to rustdoc. + NoInputMergeFinalize, + /// A crate or markdown file. + HasFile(Input), +} + /// Configuration options for rustdoc. #[derive(Clone)] pub(crate) struct Options { @@ -286,6 +294,12 @@ pub(crate) struct RenderOptions { /// This field is only used for the JSON output. If it's set to true, no file will be created /// and content will be displayed in stdout directly. pub(crate) output_to_stdout: bool, + /// Whether we should read or write rendered cross-crate info in the doc root. + pub(crate) should_merge: ShouldMerge, + /// Path to crate-info for external crates. + pub(crate) include_parts_dir: Vec, + /// Where to write crate-info + pub(crate) parts_out_dir: Option, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] @@ -345,7 +359,7 @@ impl Options { early_dcx: &mut EarlyDiagCtxt, matches: &getopts::Matches, args: Vec, - ) -> Option<(Input, Options, RenderOptions)> { + ) -> Option<(InputMode, Options, RenderOptions)> { // Check for unstable options. nightly_options::check_nightly_options(early_dcx, matches, &opts()); @@ -475,15 +489,17 @@ impl Options { let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(early_dcx, matches); let input = if describe_lints { - "" // dummy, this won't be used + InputMode::HasFile(make_input(early_dcx, "")) } else { match matches.free.as_slice() { + [] if matches.opt_str("merge").as_deref() == Some("finalize") => { + InputMode::NoInputMergeFinalize + } [] => dcx.fatal("missing file operand"), - [input] => input, + [input] => InputMode::HasFile(make_input(early_dcx, input)), _ => dcx.fatal("too many file operands"), } }; - let input = make_input(early_dcx, input); let externs = parse_externs(early_dcx, matches, &unstable_opts); let extern_html_root_urls = match parse_extern_html_roots(matches) { @@ -491,6 +507,16 @@ impl Options { Err(err) => dcx.fatal(err), }; + let parts_out_dir = + match matches.opt_str("parts-out-dir").map(|p| PathToParts::from_flag(p)).transpose() { + Ok(parts_out_dir) => parts_out_dir, + Err(e) => dcx.fatal(e), + }; + let include_parts_dir = match parse_include_parts_dir(matches) { + Ok(include_parts_dir) => include_parts_dir, + Err(e) => dcx.fatal(e), + }; + let default_settings: Vec> = vec![ matches .opt_str("default-theme") @@ -732,6 +758,10 @@ impl Options { let extern_html_root_takes_precedence = matches.opt_present("extern-html-root-takes-precedence"); let html_no_source = matches.opt_present("html-no-source"); + let should_merge = match parse_merge(matches) { + Ok(result) => result, + Err(e) => dcx.fatal(format!("--merge option error: {e}")), + }; if generate_link_to_definition && (show_coverage || output_format != OutputFormat::Html) { dcx.struct_warn( @@ -819,6 +849,9 @@ impl Options { no_emit_shared: false, html_no_source, output_to_stdout, + should_merge, + include_parts_dir, + parts_out_dir, }; Some((input, options, render_options)) } @@ -894,3 +927,71 @@ fn parse_extern_html_roots( } Ok(externs) } + +/// Path directly to crate-info file. +/// +/// For example, `/home/user/project/target/doc.parts//crate-info`. +#[derive(Clone, Debug)] +pub(crate) struct PathToParts(pub(crate) PathBuf); + +impl PathToParts { + fn from_flag(path: String) -> Result { + let mut path = PathBuf::from(path); + // check here is for diagnostics + if path.exists() && !path.is_dir() { + Err(format!( + "--parts-out-dir and --include-parts-dir expect directories, found: {}", + path.display(), + )) + } else { + // if it doesn't exist, we'll create it. worry about that in write_shared + path.push("crate-info"); + Ok(PathToParts(path)) + } + } +} + +/// Reports error if --include-parts-dir / crate-info is not a file +fn parse_include_parts_dir(m: &getopts::Matches) -> Result, String> { + let mut ret = Vec::new(); + for p in m.opt_strs("include-parts-dir") { + let p = PathToParts::from_flag(p)?; + // this is just for diagnostic + if !p.0.is_file() { + return Err(format!("--include-parts-dir expected {} to be a file", p.0.display())); + } + ret.push(p); + } + Ok(ret) +} + +/// Controls merging of cross-crate information +#[derive(Debug, Clone)] +pub(crate) struct ShouldMerge { + /// Should we append to existing cci in the doc root + pub(crate) read_rendered_cci: bool, + /// Should we write cci to the doc root + pub(crate) write_rendered_cci: bool, +} + +/// Extracts read_rendered_cci and write_rendered_cci from command line arguments, or +/// reports an error if an invalid option was provided +fn parse_merge(m: &getopts::Matches) -> Result { + match m.opt_str("merge").as_deref() { + // default = read-write + None => Ok(ShouldMerge { read_rendered_cci: true, write_rendered_cci: true }), + Some("none") if m.opt_present("include-parts-dir") => { + Err("--include-parts-dir not allowed if --merge=none") + } + Some("none") => Ok(ShouldMerge { read_rendered_cci: false, write_rendered_cci: false }), + Some("shared") if m.opt_present("parts-out-dir") || m.opt_present("include-parts-dir") => { + Err("--parts-out-dir and --include-parts-dir not allowed if --merge=shared") + } + Some("shared") => Ok(ShouldMerge { read_rendered_cci: true, write_rendered_cci: true }), + Some("finalize") if m.opt_present("parts-out-dir") => { + Err("--parts-out-dir not allowed if --merge=finalize") + } + Some("finalize") => Ok(ShouldMerge { read_rendered_cci: false, write_rendered_cci: true }), + Some(_) => Err("argument to --merge must be `none`, `shared`, or `finalize`"), + } +} diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 9fe43e428f2ae..902ccd23e8afc 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -16,12 +16,11 @@ use tracing::info; use super::print_item::{full_path, item_path, print_item}; use super::sidebar::{print_sidebar, sidebar_module_like, ModuleLike, Sidebar}; -use super::write_shared::write_shared; use super::{collect_spans_and_sources, scrape_examples_help, AllTypes, LinkFromSrc, StylePath}; use crate::clean::types::ExternalLocation; use crate::clean::utils::has_doc_flag; use crate::clean::{self, ExternalCrate}; -use crate::config::{ModuleSorting, RenderOptions}; +use crate::config::{ModuleSorting, RenderOptions, ShouldMerge}; use crate::docfs::{DocFS, PathError}; use crate::error::Error; use crate::formats::cache::Cache; @@ -30,6 +29,7 @@ use crate::formats::FormatRenderer; use crate::html::escape::Escape; use crate::html::format::{join_with_double_colon, Buffer}; use crate::html::markdown::{self, plain_text_summary, ErrorCodes, IdMap}; +use crate::html::render::write_shared::write_shared; use crate::html::url_parts_builder::UrlPartsBuilder; use crate::html::{layout, sources, static_files}; use crate::scrape_examples::AllCallLocations; @@ -128,8 +128,10 @@ pub(crate) struct SharedContext<'tcx> { pub(crate) span_correspondence_map: FxHashMap, /// The [`Cache`] used during rendering. pub(crate) cache: Cache, - pub(crate) call_locations: AllCallLocations, + /// Controls whether we read / write to cci files in the doc root. Defaults read=true, + /// write=true + should_merge: ShouldMerge, } impl SharedContext<'_> { @@ -551,6 +553,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { span_correspondence_map: matches, cache, call_locations, + should_merge: options.should_merge, }; let dst = output; @@ -640,92 +643,96 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { ); shared.fs.write(final_file, v)?; - // Generating settings page. - page.title = "Settings"; - page.description = "Settings of Rustdoc"; - page.root_path = "./"; - page.rust_logo = true; + // if to avoid writing help, settings files to doc root unless we're on the final invocation + if shared.should_merge.write_rendered_cci { + // Generating settings page. + page.title = "Settings"; + page.description = "Settings of Rustdoc"; + page.root_path = "./"; + page.rust_logo = true; - let sidebar = "

Settings

"; - let v = layout::render( - &shared.layout, - &page, - sidebar, - |buf: &mut Buffer| { - write!( - buf, - "
\ -

Rustdoc settings

\ - \ - \ - Back\ - \ - \ -
\ - \ - ", - static_root_path = page.get_static_root_path(), - settings_js = static_files::STATIC_FILES.settings_js, - ); - // Pre-load all theme CSS files, so that switching feels seamless. - // - // When loading settings.html as a popover, the equivalent HTML is - // generated in main.js. - for file in &shared.style_files { - if let Ok(theme) = file.basename() { - write!( - buf, - "", - root_path = page.static_root_path.unwrap_or(""), - suffix = page.resource_suffix, - ); + let sidebar = "

Settings

"; + let v = layout::render( + &shared.layout, + &page, + sidebar, + |buf: &mut Buffer| { + write!( + buf, + "
\ +

Rustdoc settings

\ + \ + \ + Back\ + \ + \ +
\ + \ + ", + static_root_path = page.get_static_root_path(), + settings_js = static_files::STATIC_FILES.settings_js, + ); + // Pre-load all theme CSS files, so that switching feels seamless. + // + // When loading settings.html as a popover, the equivalent HTML is + // generated in main.js. + for file in &shared.style_files { + if let Ok(theme) = file.basename() { + write!( + buf, + "", + root_path = page.static_root_path.unwrap_or(""), + suffix = page.resource_suffix, + ); + } } - } - }, - &shared.style_files, - ); - shared.fs.write(settings_file, v)?; + }, + &shared.style_files, + ); + shared.fs.write(settings_file, v)?; - // Generating help page. - page.title = "Help"; - page.description = "Documentation for Rustdoc"; - page.root_path = "./"; - page.rust_logo = true; + // Generating help page. + page.title = "Help"; + page.description = "Documentation for Rustdoc"; + page.root_path = "./"; + page.rust_logo = true; - let sidebar = "

Help

"; - let v = layout::render( - &shared.layout, - &page, - sidebar, - |buf: &mut Buffer| { - write!( - buf, - "
\ -

Rustdoc help

\ - \ - \ - Back\ - \ - \ -
\ - ", - ) - }, - &shared.style_files, - ); - shared.fs.write(help_file, v)?; + let sidebar = "

Help

"; + let v = layout::render( + &shared.layout, + &page, + sidebar, + |buf: &mut Buffer| { + write!( + buf, + "
\ +

Rustdoc help

\ + \ + \ + Back\ + \ + \ +
\ + ", + ) + }, + &shared.style_files, + ); + shared.fs.write(help_file, v)?; + } - if shared.layout.scrape_examples_extension { + // if to avoid writing files to doc root unless we're on the final invocation + if shared.layout.scrape_examples_extension && shared.should_merge.write_rendered_cci { page.title = "About scraped examples"; page.description = "How the scraped examples feature works in Rustdoc"; let v = layout::render( diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index f67d006116cb6..245d805555229 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -61,6 +61,7 @@ use tracing::{debug, info}; pub(crate) use self::context::*; pub(crate) use self::span_map::{collect_spans_and_sources, LinkFromSrc}; +pub(crate) use self::write_shared::*; use crate::clean::{self, ItemId, RenderedLink}; use crate::error::Error; use crate::formats::cache::Cache; diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index b0af8d8c23ee5..302c454b2a11e 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -39,7 +39,7 @@ use serde::{Deserialize, Serialize, Serializer}; use super::{collect_paths_for_type, ensure_trailing_slash, Context, RenderMode}; use crate::clean::{Crate, Item, ItemId, ItemKind}; -use crate::config::{EmitType, RenderOptions}; +use crate::config::{EmitType, PathToParts, RenderOptions, ShouldMerge}; use crate::docfs::PathError; use crate::error::Error; use crate::formats::cache::Cache; @@ -50,12 +50,11 @@ use crate::html::layout; use crate::html::render::ordered_json::{EscapedJson, OrderedJson}; use crate::html::render::search_index::{build_index, SerializedSearchIndex}; use crate::html::render::sorted_template::{self, FileFormat, SortedTemplate}; -use crate::html::render::{AssocItemLink, ImplRenderingParameters}; +use crate::html::render::{AssocItemLink, ImplRenderingParameters, StylePath}; use crate::html::static_files::{self, suffix_path}; use crate::visit::DocVisitor; use crate::{try_err, try_none}; -/// Write cross-crate information files, static files, invocation-specific files, etc. to disk pub(crate) fn write_shared( cx: &mut Context<'_>, krate: &Crate, @@ -70,13 +69,14 @@ pub(crate) fn write_shared( let SerializedSearchIndex { index, desc } = build_index(&krate, &mut Rc::get_mut(&mut cx.shared).unwrap().cache, tcx); - write_search_desc(cx, &krate, &desc)?; // does not need to be merged; written unconditionally + write_search_desc(cx, &krate, &desc)?; // does not need to be merged let crate_name = krate.name(cx.tcx()); let crate_name = crate_name.as_str(); // rand let crate_name_json = OrderedJson::serialize(crate_name).unwrap(); // "rand" let external_crates = hack_get_external_crate_names(&cx.dst, &cx.shared.resource_suffix)?; let info = CrateInfo { + version: CrateInfoVersion::V1, src_files_js: SourcesPart::get(cx, &crate_name_json)?, search_index_js: SearchIndexPart::get(index, &cx.shared.resource_suffix)?, all_crates: AllCratesPart::get(crate_name_json.clone(), &cx.shared.resource_suffix)?, @@ -85,47 +85,103 @@ pub(crate) fn write_shared( type_impl: TypeAliasPart::get(cx, krate, &crate_name_json)?, }; - let crates = vec![info]; // we have info from just one crate. rest will found in out dir + if let Some(parts_out_dir) = &opt.parts_out_dir { + create_parents(&parts_out_dir.0)?; + try_err!( + fs::write(&parts_out_dir.0, serde_json::to_string(&info).unwrap()), + &parts_out_dir.0 + ); + } - write_static_files(cx, &opt)?; - let dst = &cx.dst; - if opt.emit.is_empty() || opt.emit.contains(&EmitType::InvocationSpecific) { - if cx.include_sources { - write_rendered_cci::(SourcesPart::blank, dst, &crates)?; - } - write_rendered_cci::(SearchIndexPart::blank, dst, &crates)?; - write_rendered_cci::(AllCratesPart::blank, dst, &crates)?; - } - write_rendered_cci::(TraitAliasPart::blank, dst, &crates)?; - write_rendered_cci::(TypeAliasPart::blank, dst, &crates)?; - match &opt.index_page { - Some(index_page) if opt.enable_index_page => { - let mut md_opts = opt.clone(); - md_opts.output = cx.dst.clone(); - md_opts.external_html = cx.shared.layout.external_html.clone(); - try_err!( - crate::markdown::render(&index_page, md_opts, cx.shared.edition()), - &index_page - ); - } - None if opt.enable_index_page => { - write_rendered_cci::(|| CratesIndexPart::blank(cx), dst, &crates)?; + let mut crates = CrateInfo::read_many(&opt.include_parts_dir)?; + crates.push(info); + + if opt.should_merge.write_rendered_cci { + write_not_crate_specific( + &crates, + &cx.dst, + opt, + &cx.shared.style_files, + cx.shared.layout.css_file_extension.as_deref(), + &cx.shared.resource_suffix, + cx.include_sources, + )?; + match &opt.index_page { + Some(index_page) if opt.enable_index_page => { + let mut md_opts = opt.clone(); + md_opts.output = cx.dst.clone(); + md_opts.external_html = cx.shared.layout.external_html.clone(); + try_err!( + crate::markdown::render(&index_page, md_opts, cx.shared.edition()), + &index_page + ); + } + None if opt.enable_index_page => { + write_rendered_cci::( + || CratesIndexPart::blank(cx), + &cx.dst, + &crates, + &opt.should_merge, + )?; + } + _ => {} // they don't want an index page } - _ => {} // they don't want an index page } Rc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(false); Ok(()) } -/// Writes the static files, the style files, and the css extensions -fn write_static_files(cx: &mut Context<'_>, options: &RenderOptions) -> Result<(), Error> { - let static_dir = cx.dst.join("static.files"); +/// Writes files that are written directly to the `--out-dir`, without the prefix from the current +/// crate. These are the rendered cross-crate files that encode info from multiple crates (e.g. +/// search index), and the static files. +pub(crate) fn write_not_crate_specific( + crates: &[CrateInfo], + dst: &Path, + opt: &RenderOptions, + style_files: &[StylePath], + css_file_extension: Option<&Path>, + resource_suffix: &str, + include_sources: bool, +) -> Result<(), Error> { + write_rendered_cross_crate_info(crates, dst, opt, include_sources)?; + write_static_files(dst, opt, style_files, css_file_extension, resource_suffix)?; + Ok(()) +} - cx.shared.fs.create_dir_all(&static_dir).map_err(|e| PathError::new(e, "static.files"))?; +fn write_rendered_cross_crate_info( + crates: &[CrateInfo], + dst: &Path, + opt: &RenderOptions, + include_sources: bool, +) -> Result<(), Error> { + let m = &opt.should_merge; + if opt.emit.is_empty() || opt.emit.contains(&EmitType::InvocationSpecific) { + if include_sources { + write_rendered_cci::(SourcesPart::blank, dst, &crates, m)?; + } + write_rendered_cci::(SearchIndexPart::blank, dst, &crates, m)?; + write_rendered_cci::(AllCratesPart::blank, dst, &crates, m)?; + } + write_rendered_cci::(TraitAliasPart::blank, dst, &crates, m)?; + write_rendered_cci::(TypeAliasPart::blank, dst, &crates, m)?; + Ok(()) +} + +/// Writes the static files, the style files, and the css extensions. +/// Have to be careful about these, because they write to the root out dir. +fn write_static_files( + dst: &Path, + opt: &RenderOptions, + style_files: &[StylePath], + css_file_extension: Option<&Path>, + resource_suffix: &str, +) -> Result<(), Error> { + let static_dir = dst.join("static.files"); + try_err!(fs::create_dir_all(&static_dir), &static_dir); // Handle added third-party themes - for entry in &cx.shared.style_files { + for entry in style_files { let theme = entry.basename()?; let extension = try_none!(try_none!(entry.path.extension(), &entry.path).to_str(), &entry.path); @@ -136,22 +192,24 @@ fn write_static_files(cx: &mut Context<'_>, options: &RenderOptions) -> Result<( } let bytes = try_err!(fs::read(&entry.path), &entry.path); - let filename = format!("{theme}{suffix}.{extension}", suffix = cx.shared.resource_suffix); - cx.shared.fs.write(cx.dst.join(filename), bytes)?; + let filename = format!("{theme}{resource_suffix}.{extension}"); + let dst_filename = dst.join(filename); + try_err!(fs::write(&dst_filename, bytes), &dst_filename); } // When the user adds their own CSS files with --extend-css, we write that as an // invocation-specific file (that is, with a resource suffix). - if let Some(ref css) = cx.shared.layout.css_file_extension { + if let Some(css) = css_file_extension { let buffer = try_err!(fs::read_to_string(css), css); - let path = static_files::suffix_path("theme.css", &cx.shared.resource_suffix); - cx.shared.fs.write(cx.dst.join(path), buffer)?; + let path = static_files::suffix_path("theme.css", resource_suffix); + let dst_path = dst.join(path); + try_err!(fs::write(&dst_path, buffer), &dst_path); } - if options.emit.is_empty() || options.emit.contains(&EmitType::Toolchain) { + if opt.emit.is_empty() || opt.emit.contains(&EmitType::Toolchain) { static_files::for_each(|f: &static_files::StaticFile| { let filename = static_dir.join(f.output_filename()); - cx.shared.fs.write(filename, f.minified()) + fs::write(&filename, f.minified()).map_err(|e| PathError::new(e, &filename)) })?; } @@ -186,7 +244,8 @@ fn write_search_desc( /// Contains pre-rendered contents to insert into the CCI template #[derive(Serialize, Deserialize, Clone, Debug)] -struct CrateInfo { +pub(crate) struct CrateInfo { + version: CrateInfoVersion, src_files_js: PartsAndLocations, search_index_js: PartsAndLocations, all_crates: PartsAndLocations, @@ -195,6 +254,33 @@ struct CrateInfo { type_impl: PartsAndLocations, } +impl CrateInfo { + /// Read all of the crate info from its location on the filesystem + pub(crate) fn read_many(parts_paths: &[PathToParts]) -> Result, Error> { + parts_paths + .iter() + .map(|parts_path| { + let path = &parts_path.0; + let parts = try_err!(fs::read(&path), &path); + let parts: CrateInfo = try_err!(serde_json::from_slice(&parts), &path); + Ok::<_, Error>(parts) + }) + .collect::, Error>>() + } +} + +/// Version for the format of the crate-info file. +/// +/// This enum should only ever have one variant, representing the current version. +/// Gives pretty good error message about expecting the current version on deserialize. +/// +/// Must be incremented (V2, V3, etc.) upon any changes to the search index or CrateInfo, +/// to provide better diagnostics about including an invalid file. +#[derive(Serialize, Deserialize, Clone, Debug)] +enum CrateInfoVersion { + V1, +} + /// Paths (relative to the doc root) and their pre-merge contents #[derive(Serialize, Deserialize, Debug, Clone)] #[serde(transparent)] @@ -900,10 +986,14 @@ fn create_parents(path: &Path) -> Result<(), Error> { fn read_template_or_blank( mut make_blank: F, path: &Path, + should_merge: &ShouldMerge, ) -> Result, Error> where F: FnMut() -> SortedTemplate, { + if !should_merge.read_rendered_cci { + return Ok(make_blank()); + } match fs::read_to_string(&path) { Ok(template) => Ok(try_err!(SortedTemplate::from_str(&template), &path)), Err(e) if e.kind() == io::ErrorKind::NotFound => Ok(make_blank()), @@ -916,6 +1006,7 @@ fn write_rendered_cci( mut make_blank: F, dst: &Path, crates_info: &[CrateInfo], + should_merge: &ShouldMerge, ) -> Result<(), Error> where F: FnMut() -> SortedTemplate, @@ -924,7 +1015,8 @@ where for (path, parts) in get_path_parts::(dst, crates_info) { create_parents(&path)?; // read previous rendered cci from storage, append to them - let mut template = read_template_or_blank::<_, T::FileFormat>(&mut make_blank, &path)?; + let mut template = + read_template_or_blank::<_, T::FileFormat>(&mut make_blank, &path, should_merge)?; for part in parts { template.append(part); } diff --git a/src/librustdoc/html/render/write_shared/tests.rs b/src/librustdoc/html/render/write_shared/tests.rs index e282cd99e43cc..a235f1d37243a 100644 --- a/src/librustdoc/html/render/write_shared/tests.rs +++ b/src/librustdoc/html/render/write_shared/tests.rs @@ -1,3 +1,4 @@ +use crate::config::ShouldMerge; use crate::html::render::ordered_json::{EscapedJson, OrderedJson}; use crate::html::render::sorted_template::{Html, SortedTemplate}; use crate::html::render::write_shared::*; @@ -192,16 +193,17 @@ fn read_template_test() { let path = path.path().join("file.html"); let make_blank = || SortedTemplate::::from_before_after("
", "
"); - let template = read_template_or_blank(make_blank, &path).unwrap(); + let should_merge = ShouldMerge { read_rendered_cci: true, write_rendered_cci: true }; + let template = read_template_or_blank(make_blank, &path, &should_merge).unwrap(); assert_eq!(but_last_line(&template.to_string()), "
"); fs::write(&path, template.to_string()).unwrap(); - let mut template = read_template_or_blank(make_blank, &path).unwrap(); + let mut template = read_template_or_blank(make_blank, &path, &should_merge).unwrap(); template.append("".to_string()); fs::write(&path, template.to_string()).unwrap(); - let mut template = read_template_or_blank(make_blank, &path).unwrap(); + let mut template = read_template_or_blank(make_blank, &path, &should_merge).unwrap(); template.append("
".to_string()); fs::write(&path, template.to_string()).unwrap(); - let template = read_template_or_blank(make_blank, &path).unwrap(); + let template = read_template_or_blank(make_blank, &path, &should_merge).unwrap(); assert_eq!(but_last_line(&template.to_string()), "

"); } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index e470aef3643e9..6649e1721a48b 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -603,6 +603,33 @@ fn opts() -> Vec { "path to function call information (for displaying examples in the documentation)", ) }), + unstable("merge", |o| { + o.optopt( + "", + "merge", + "Controls how rustdoc handles files from previously documented crates in the doc root + none = Do not write cross-crate information to the --out-dir + shared = Append current crate's info to files found in the --out-dir + finalize = Write current crate's info and --include-parts-dir info to the --out-dir, overwriting conflicting files", + "none|shared|finalize", + ) + }), + unstable("parts-out-dir", |o| { + o.optopt( + "", + "parts-out-dir", + "Writes trait implementations and other info for the current crate to provided path. Only use with --merge=none", + "path/to/doc.parts/", + ) + }), + unstable("include-parts-dir", |o| { + o.optmulti( + "", + "include-parts-dir", + "Includes trait implementations and other crate info from provided path. Only use with --merge=finalize", + "path/to/doc.parts/", + ) + }), // deprecated / removed options unstable("disable-minification", |o| o.optflagmulti("", "disable-minification", "removed")), stable("plugin-path", |o| { @@ -697,6 +724,32 @@ fn run_renderer<'tcx, T: formats::FormatRenderer<'tcx>>( } } +/// Renders and writes cross-crate info files, like the search index. This function exists so that +/// we can run rustdoc without a crate root in the `--merge=finalize` mode. Cross-crate info files +/// discovered via `--include-parts-dir` are combined and written to the doc root. +fn run_merge_finalize(opt: config::RenderOptions) -> Result<(), error::Error> { + assert!( + opt.should_merge.write_rendered_cci, + "config.rs only allows us to return InputMode::NoInputMergeFinalize if --merge=finalize" + ); + assert!( + !opt.should_merge.read_rendered_cci, + "config.rs only allows us to return InputMode::NoInputMergeFinalize if --merge=finalize" + ); + let crates = html::render::CrateInfo::read_many(&opt.include_parts_dir)?; + let include_sources = !opt.html_no_source; + html::render::write_not_crate_specific( + &crates, + &opt.output, + &opt, + &opt.themes, + opt.extension_css.as_deref(), + &opt.resource_suffix, + include_sources, + )?; + Ok(()) +} + fn main_args( early_dcx: &mut EarlyDiagCtxt, at_args: &[String], @@ -737,6 +790,17 @@ fn main_args( core::new_dcx(options.error_format, None, options.diagnostic_width, &options.unstable_opts); let dcx = dcx.handle(); + let input = match input { + config::InputMode::HasFile(input) => input, + config::InputMode::NoInputMergeFinalize => { + return wrap_return( + dcx, + run_merge_finalize(render_options) + .map_err(|e| format!("could not write merged cross-crate info: {e}")), + ); + } + }; + match (options.should_test, config::markdown_input(&input)) { (true, Some(_)) => return wrap_return(dcx, doctest::test_markdown(&input, options)), (true, None) => return doctest::run(dcx, input, options), diff --git a/tests/run-make/rustdoc-default-output/output-default.stdout b/tests/run-make/rustdoc-default-output/output-default.stdout index bc38d9e9dc6b3..125443ce61964 100644 --- a/tests/run-make/rustdoc-default-output/output-default.stdout +++ b/tests/run-make/rustdoc-default-output/output-default.stdout @@ -172,6 +172,23 @@ Options: --scrape-tests Include test code when scraping examples --with-examples path to function call information (for displaying examples in the documentation) + --merge none|shared|finalize + Controls how rustdoc handles files from previously + documented crates in the doc root + none = Do not write cross-crate information to the + --out-dir + shared = Append current crate's info to files found in + the --out-dir + finalize = Write current crate's info and + --include-parts-dir info to the --out-dir, overwriting + conflicting files + --parts-out-dir path/to/doc.parts/ + Writes trait implementations and other info for the + current crate to provided path. Only use with + --merge=none + --include-parts-dir path/to/doc.parts/ + Includes trait implementations and other crate info + from provided path. Only use with --merge=finalize --disable-minification removed --plugin-path DIR From 548b6e197d9bafef6fae86098ea2afabbe99a90a Mon Sep 17 00:00:00 2001 From: EtomicBomb Date: Sat, 7 Sep 2024 19:02:22 -0400 Subject: [PATCH 043/189] add tests for behavior in rfc#3662 * Adds tests for the behavior from rfc#3662 in `tests/rustdoc/` --- .../auxiliary/quebec.rs | 5 +++ .../auxiliary/tango.rs | 8 +++++ .../cargo-transitive-read-write/sierra.rs | 25 +++++++++++++ .../auxiliary/quebec.rs | 7 ++++ .../auxiliary/romeo.rs | 10 ++++++ .../auxiliary/sierra.rs | 11 ++++++ .../auxiliary/tango.rs | 10 ++++++ .../kitchen-sink-separate-dirs/indigo.rs | 35 +++++++++++++++++++ .../no-merge-separate/auxiliary/quebec.rs | 6 ++++ .../no-merge-separate/auxiliary/tango.rs | 9 +++++ .../no-merge-separate/sierra.rs | 17 +++++++++ .../no-merge-write-anyway/auxiliary/quebec.rs | 6 ++++ .../no-merge-write-anyway/auxiliary/tango.rs | 9 +++++ .../no-merge-write-anyway/sierra.rs | 18 ++++++++++ .../overwrite-but-include/auxiliary/quebec.rs | 6 ++++ .../overwrite-but-include/auxiliary/tango.rs | 9 +++++ .../overwrite-but-include/sierra.rs | 22 ++++++++++++ .../auxiliary/quebec.rs | 7 ++++ .../overwrite-but-separate/auxiliary/tango.rs | 10 ++++++ .../overwrite-but-separate/sierra.rs | 25 +++++++++++++ .../overwrite/auxiliary/quebec.rs | 5 +++ .../overwrite/auxiliary/tango.rs | 8 +++++ .../overwrite/sierra.rs | 20 +++++++++++ .../single-crate-finalize/quebec.rs | 13 +++++++ .../single-crate-read-write/quebec.rs | 12 +++++++ .../single-crate-write-anyway/quebec.rs | 13 +++++++ .../single-merge-none-useless-write/quebec.rs | 11 ++++++ .../transitive-finalize/auxiliary/quebec.rs | 5 +++ .../transitive-finalize/auxiliary/tango.rs | 8 +++++ .../transitive-finalize/sierra.rs | 20 +++++++++++ .../transitive-merge-none/auxiliary/quebec.rs | 6 ++++ .../transitive-merge-none/auxiliary/tango.rs | 9 +++++ .../transitive-merge-none/sierra.rs | 27 ++++++++++++++ .../auxiliary/quebec.rs | 5 +++ .../auxiliary/tango.rs | 8 +++++ .../transitive-merge-read-write/sierra.rs | 25 +++++++++++++ .../transitive-no-info/auxiliary/quebec.rs | 5 +++ .../transitive-no-info/auxiliary/tango.rs | 8 +++++ .../transitive-no-info/sierra.rs | 17 +++++++++ .../two-separate-out-dir/auxiliary/foxtrot.rs | 5 +++ .../two-separate-out-dir/echo.rs | 16 +++++++++ 41 files changed, 501 insertions(+) create mode 100644 tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/quebec.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/tango.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/sierra.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/quebec.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/romeo.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/sierra.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/tango.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/indigo.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/no-merge-separate/auxiliary/quebec.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/no-merge-separate/auxiliary/tango.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/no-merge-separate/sierra.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/auxiliary/quebec.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/auxiliary/tango.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/sierra.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/overwrite-but-include/auxiliary/quebec.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/overwrite-but-include/auxiliary/tango.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/overwrite-but-include/sierra.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/auxiliary/quebec.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/auxiliary/tango.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/sierra.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/overwrite/auxiliary/quebec.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/overwrite/auxiliary/tango.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/overwrite/sierra.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/single-crate-finalize/quebec.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/single-crate-read-write/quebec.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/single-crate-write-anyway/quebec.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/single-merge-none-useless-write/quebec.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/transitive-finalize/auxiliary/quebec.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/transitive-finalize/auxiliary/tango.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/transitive-finalize/sierra.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/transitive-merge-none/auxiliary/quebec.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/transitive-merge-none/auxiliary/tango.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/transitive-merge-none/sierra.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/auxiliary/quebec.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/auxiliary/tango.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/sierra.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/transitive-no-info/auxiliary/quebec.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/transitive-no-info/auxiliary/tango.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/transitive-no-info/sierra.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/two-separate-out-dir/auxiliary/foxtrot.rs create mode 100644 tests/rustdoc/merge-cross-crate-info/two-separate-out-dir/echo.rs diff --git a/tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/quebec.rs new file mode 100644 index 0000000000000..fdafb3b7ac341 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/quebec.rs @@ -0,0 +1,5 @@ +//@ doc-flags:--merge=shared +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +pub struct Quebec; diff --git a/tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/tango.rs new file mode 100644 index 0000000000000..ff12fe98d82c2 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/tango.rs @@ -0,0 +1,8 @@ +//@ aux-build:quebec.rs +//@ build-aux-docs +//@ doc-flags:--merge=shared +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +extern crate quebec; +pub trait Tango {} diff --git a/tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/sierra.rs b/tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/sierra.rs new file mode 100644 index 0000000000000..665f9567ba2d2 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/cargo-transitive-read-write/sierra.rs @@ -0,0 +1,25 @@ +//@ aux-build:tango.rs +//@ build-aux-docs +//@ doc-flags:--merge=shared +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ has index.html +//@ has index.html '//h1' 'List of all crates' +//@ has index.html '//ul[@class="all-items"]//a[@href="quebec/index.html"]' 'quebec' +//@ has index.html '//ul[@class="all-items"]//a[@href="sierra/index.html"]' 'sierra' +//@ has index.html '//ul[@class="all-items"]//a[@href="tango/index.html"]' 'tango' +//@ has quebec/struct.Quebec.html +//@ has sierra/struct.Sierra.html +//@ has tango/trait.Tango.html +//@ hasraw sierra/struct.Sierra.html 'Tango' +//@ hasraw trait.impl/tango/trait.Tango.js 'struct.Sierra.html' +//@ hasraw search-index.js 'Tango' +//@ hasraw search-index.js 'Sierra' +//@ hasraw search-index.js 'Quebec' + +// similar to cargo-workflow-transitive, but we use --merge=read-write, +// which is the default. +extern crate tango; +pub struct Sierra; +impl tango::Tango for Sierra {} diff --git a/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/quebec.rs new file mode 100644 index 0000000000000..d10bc0316ccad --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/quebec.rs @@ -0,0 +1,7 @@ +//@ unique-doc-out-dir +//@ doc-flags:--merge=none +//@ doc-flags:--parts-out-dir=info/doc.parts/quebec +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +pub struct Quebec; diff --git a/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/romeo.rs b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/romeo.rs new file mode 100644 index 0000000000000..6d0c8651db53f --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/romeo.rs @@ -0,0 +1,10 @@ +//@ aux-build:sierra.rs +//@ build-aux-docs +//@ unique-doc-out-dir +//@ doc-flags:--merge=none +//@ doc-flags:--parts-out-dir=info/doc.parts/romeo +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +extern crate sierra; +pub type Romeo = sierra::Sierra; diff --git a/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/sierra.rs b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/sierra.rs new file mode 100644 index 0000000000000..10898f3886477 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/sierra.rs @@ -0,0 +1,11 @@ +//@ aux-build:tango.rs +//@ build-aux-docs +//@ unique-doc-out-dir +//@ doc-flags:--merge=none +//@ doc-flags:--parts-out-dir=info/doc.parts/sierra +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +extern crate tango; +pub struct Sierra; +impl tango::Tango for Sierra {} diff --git a/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/tango.rs new file mode 100644 index 0000000000000..3c3721ee6eb7d --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/tango.rs @@ -0,0 +1,10 @@ +//@ aux-build:quebec.rs +//@ build-aux-docs +//@ unique-doc-out-dir +//@ doc-flags:--merge=none +//@ doc-flags:--parts-out-dir=info/doc.parts/tango +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +extern crate quebec; +pub trait Tango {} diff --git a/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/indigo.rs b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/indigo.rs new file mode 100644 index 0000000000000..f03f6bd6026fa --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/kitchen-sink-separate-dirs/indigo.rs @@ -0,0 +1,35 @@ +//@ aux-build:tango.rs +//@ aux-build:romeo.rs +//@ aux-build:quebec.rs +//@ aux-build:sierra.rs +//@ build-aux-docs +//@ doc-flags:--merge=finalize +//@ doc-flags:--include-parts-dir=info/doc.parts/tango +//@ doc-flags:--include-parts-dir=info/doc.parts/romeo +//@ doc-flags:--include-parts-dir=info/doc.parts/quebec +//@ doc-flags:--include-parts-dir=info/doc.parts/sierra +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ has index.html '//h1' 'List of all crates' +//@ has index.html +//@ has index.html '//ul[@class="all-items"]//a[@href="indigo/index.html"]' 'indigo' +//@ has index.html '//ul[@class="all-items"]//a[@href="quebec/index.html"]' 'quebec' +//@ has index.html '//ul[@class="all-items"]//a[@href="romeo/index.html"]' 'romeo' +//@ has index.html '//ul[@class="all-items"]//a[@href="sierra/index.html"]' 'sierra' +//@ has index.html '//ul[@class="all-items"]//a[@href="tango/index.html"]' 'tango' +//@ !has quebec/struct.Quebec.html +//@ !has romeo/type.Romeo.html +//@ !has sierra/struct.Sierra.html +//@ !has tango/trait.Tango.html +//@ hasraw trait.impl/tango/trait.Tango.js 'struct.Sierra.html' +//@ hasraw search-index.js 'Quebec' +//@ hasraw search-index.js 'Romeo' +//@ hasraw search-index.js 'Sierra' +//@ hasraw search-index.js 'Tango' +//@ has type.impl/sierra/struct.Sierra.js +//@ hasraw type.impl/sierra/struct.Sierra.js 'Tango' +//@ hasraw type.impl/sierra/struct.Sierra.js 'Romeo' + +// document everything in the default mode, there are separate out +// directories that are linked together diff --git a/tests/rustdoc/merge-cross-crate-info/no-merge-separate/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/no-merge-separate/auxiliary/quebec.rs new file mode 100644 index 0000000000000..61210529fa6bc --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/no-merge-separate/auxiliary/quebec.rs @@ -0,0 +1,6 @@ +//@ unique-doc-out-dir +//@ doc-flags:--merge=none +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +pub struct Quebec; diff --git a/tests/rustdoc/merge-cross-crate-info/no-merge-separate/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/no-merge-separate/auxiliary/tango.rs new file mode 100644 index 0000000000000..70d8a4b91f549 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/no-merge-separate/auxiliary/tango.rs @@ -0,0 +1,9 @@ +//@ aux-build:quebec.rs +//@ build-aux-docs +//@ unique-doc-out-dir +//@ doc-flags:--merge=none +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +extern crate quebec; +pub trait Tango {} diff --git a/tests/rustdoc/merge-cross-crate-info/no-merge-separate/sierra.rs b/tests/rustdoc/merge-cross-crate-info/no-merge-separate/sierra.rs new file mode 100644 index 0000000000000..7eac207e51886 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/no-merge-separate/sierra.rs @@ -0,0 +1,17 @@ +//@ aux-build:tango.rs +//@ build-aux-docs +//@ doc-flags:--merge=none +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ !has index.html +//@ has sierra/struct.Sierra.html +//@ hasraw sierra/struct.Sierra.html 'Tango' +//@ !has trait.impl/tango/trait.Tango.js +//@ !has search-index.js + +// we don't generate any cross-crate info if --merge=none, even if we +// document crates separately +extern crate tango; +pub struct Sierra; +impl tango::Tango for Sierra {} diff --git a/tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/auxiliary/quebec.rs new file mode 100644 index 0000000000000..6ab921533b037 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/auxiliary/quebec.rs @@ -0,0 +1,6 @@ +//@ doc-flags:--merge=none +//@ doc-flags:--parts-out-dir=info/doc.parts/quebec +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +pub struct Quebec; diff --git a/tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/auxiliary/tango.rs new file mode 100644 index 0000000000000..9fa99d3be8af4 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/auxiliary/tango.rs @@ -0,0 +1,9 @@ +//@ aux-build:quebec.rs +//@ build-aux-docs +//@ doc-flags:--merge=none +//@ doc-flags:--parts-out-dir=info/doc.parts/tango +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +extern crate quebec; +pub trait Tango {} diff --git a/tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/sierra.rs b/tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/sierra.rs new file mode 100644 index 0000000000000..f3340a80c848b --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/no-merge-write-anyway/sierra.rs @@ -0,0 +1,18 @@ +//@ aux-build:tango.rs +//@ build-aux-docs +//@ doc-flags:--merge=none +//@ doc-flags:--parts-out-dir=info/doc.parts/sierra +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ !has index.html +//@ has sierra/struct.Sierra.html +//@ has tango/trait.Tango.html +//@ hasraw sierra/struct.Sierra.html 'Tango' +//@ !has trait.impl/tango/trait.Tango.js +//@ !has search-index.js + +// we --merge=none, so --parts-out-dir doesn't do anything +extern crate tango; +pub struct Sierra; +impl tango::Tango for Sierra {} diff --git a/tests/rustdoc/merge-cross-crate-info/overwrite-but-include/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/overwrite-but-include/auxiliary/quebec.rs new file mode 100644 index 0000000000000..6ab921533b037 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/overwrite-but-include/auxiliary/quebec.rs @@ -0,0 +1,6 @@ +//@ doc-flags:--merge=none +//@ doc-flags:--parts-out-dir=info/doc.parts/quebec +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +pub struct Quebec; diff --git a/tests/rustdoc/merge-cross-crate-info/overwrite-but-include/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/overwrite-but-include/auxiliary/tango.rs new file mode 100644 index 0000000000000..9fa99d3be8af4 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/overwrite-but-include/auxiliary/tango.rs @@ -0,0 +1,9 @@ +//@ aux-build:quebec.rs +//@ build-aux-docs +//@ doc-flags:--merge=none +//@ doc-flags:--parts-out-dir=info/doc.parts/tango +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +extern crate quebec; +pub trait Tango {} diff --git a/tests/rustdoc/merge-cross-crate-info/overwrite-but-include/sierra.rs b/tests/rustdoc/merge-cross-crate-info/overwrite-but-include/sierra.rs new file mode 100644 index 0000000000000..8eb0f1d049831 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/overwrite-but-include/sierra.rs @@ -0,0 +1,22 @@ +//@ aux-build:tango.rs +//@ build-aux-docs +//@ doc-flags:--merge=finalize +//@ doc-flags:--include-parts-dir=info/doc.parts/tango +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ has quebec/struct.Quebec.html +//@ has sierra/struct.Sierra.html +//@ has tango/trait.Tango.html +//@ hasraw sierra/struct.Sierra.html 'Tango' +//@ hasraw trait.impl/tango/trait.Tango.js 'struct.Sierra.html' +//@ hasraw search-index.js 'Tango' +//@ hasraw search-index.js 'Sierra' +//@ !hasraw search-index.js 'Quebec' + +// we overwrite quebec and tango's cross-crate information, but we +// include the info from tango meaning that it should appear in the out +// dir +extern crate tango; +pub struct Sierra; +impl tango::Tango for Sierra {} diff --git a/tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/auxiliary/quebec.rs new file mode 100644 index 0000000000000..d10bc0316ccad --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/auxiliary/quebec.rs @@ -0,0 +1,7 @@ +//@ unique-doc-out-dir +//@ doc-flags:--merge=none +//@ doc-flags:--parts-out-dir=info/doc.parts/quebec +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +pub struct Quebec; diff --git a/tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/auxiliary/tango.rs new file mode 100644 index 0000000000000..3c3721ee6eb7d --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/auxiliary/tango.rs @@ -0,0 +1,10 @@ +//@ aux-build:quebec.rs +//@ build-aux-docs +//@ unique-doc-out-dir +//@ doc-flags:--merge=none +//@ doc-flags:--parts-out-dir=info/doc.parts/tango +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +extern crate quebec; +pub trait Tango {} diff --git a/tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/sierra.rs b/tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/sierra.rs new file mode 100644 index 0000000000000..4ee036238b4b1 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/overwrite-but-separate/sierra.rs @@ -0,0 +1,25 @@ +//@ aux-build:tango.rs +//@ build-aux-docs +//@ doc-flags:--merge=finalize +//@ doc-flags:--include-parts-dir=info/doc.parts/tango +//@ doc-flags:--include-parts-dir=info/doc.parts/quebec +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ has index.html +//@ has index.html '//h1' 'List of all crates' +//@ has index.html '//ul[@class="all-items"]//a[@href="quebec/index.html"]' 'quebec' +//@ has index.html '//ul[@class="all-items"]//a[@href="sierra/index.html"]' 'sierra' +//@ has index.html '//ul[@class="all-items"]//a[@href="tango/index.html"]' 'tango' +//@ has sierra/struct.Sierra.html +//@ hasraw trait.impl/tango/trait.Tango.js 'struct.Sierra.html' +//@ hasraw search-index.js 'Tango' +//@ hasraw search-index.js 'Sierra' +//@ hasraw search-index.js 'Quebec' + +// If these were documeted into the same directory, the info would be +// overwritten. However, since they are merged, we can still recover all +// of the cross-crate information +extern crate tango; +pub struct Sierra; +impl tango::Tango for Sierra {} diff --git a/tests/rustdoc/merge-cross-crate-info/overwrite/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/overwrite/auxiliary/quebec.rs new file mode 100644 index 0000000000000..0e28d8e646647 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/overwrite/auxiliary/quebec.rs @@ -0,0 +1,5 @@ +//@ doc-flags:--merge=none +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +pub struct Quebec; diff --git a/tests/rustdoc/merge-cross-crate-info/overwrite/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/overwrite/auxiliary/tango.rs new file mode 100644 index 0000000000000..363b2d5508e63 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/overwrite/auxiliary/tango.rs @@ -0,0 +1,8 @@ +//@ aux-build:quebec.rs +//@ build-aux-docs +//@ doc-flags:--merge=finalize +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +extern crate quebec; +pub trait Tango {} diff --git a/tests/rustdoc/merge-cross-crate-info/overwrite/sierra.rs b/tests/rustdoc/merge-cross-crate-info/overwrite/sierra.rs new file mode 100644 index 0000000000000..11e61dd2744b6 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/overwrite/sierra.rs @@ -0,0 +1,20 @@ +//@ aux-build:tango.rs +//@ build-aux-docs +//@ doc-flags:--merge=shared +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ has quebec/struct.Quebec.html +//@ has sierra/struct.Sierra.html +//@ has tango/trait.Tango.html +//@ hasraw sierra/struct.Sierra.html 'Tango' +//@ hasraw trait.impl/tango/trait.Tango.js 'struct.Sierra.html' +//@ hasraw search-index.js 'Tango' +//@ hasraw search-index.js 'Sierra' +//@ !hasraw search-index.js 'Quebec' + +// since tango is documented with --merge=finalize, we overwrite q's +// cross-crate information +extern crate tango; +pub struct Sierra; +impl tango::Tango for Sierra {} diff --git a/tests/rustdoc/merge-cross-crate-info/single-crate-finalize/quebec.rs b/tests/rustdoc/merge-cross-crate-info/single-crate-finalize/quebec.rs new file mode 100644 index 0000000000000..09bb78c06f1c2 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/single-crate-finalize/quebec.rs @@ -0,0 +1,13 @@ +//@ doc-flags:--merge=finalize +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ has index.html +//@ has index.html '//h1' 'List of all crates' +//@ has index.html '//ul[@class="all-items"]//a[@href="quebec/index.html"]' 'quebec' +//@ has quebec/struct.Quebec.html +//@ hasraw search-index.js 'Quebec' + +// there is nothing to read from the output directory if we use a single +// crate +pub struct Quebec; diff --git a/tests/rustdoc/merge-cross-crate-info/single-crate-read-write/quebec.rs b/tests/rustdoc/merge-cross-crate-info/single-crate-read-write/quebec.rs new file mode 100644 index 0000000000000..72475426f6edd --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/single-crate-read-write/quebec.rs @@ -0,0 +1,12 @@ +//@ doc-flags:--merge=shared +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ has index.html +//@ has index.html '//h1' 'List of all crates' +//@ has index.html '//ul[@class="all-items"]//a[@href="quebec/index.html"]' 'quebec' +//@ has quebec/struct.Quebec.html +//@ hasraw search-index.js 'Quebec' + +// read-write is the default and this does the same as `single-crate` +pub struct Quebec; diff --git a/tests/rustdoc/merge-cross-crate-info/single-crate-write-anyway/quebec.rs b/tests/rustdoc/merge-cross-crate-info/single-crate-write-anyway/quebec.rs new file mode 100644 index 0000000000000..b20e173a8307e --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/single-crate-write-anyway/quebec.rs @@ -0,0 +1,13 @@ +//@ doc-flags:--parts-out-dir=info/doc.parts/quebec +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ has index.html +//@ has index.html '//h1' 'List of all crates' +//@ has index.html '//ul[@class="all-items"]//a[@href="quebec/index.html"]' 'quebec' +//@ has quebec/struct.Quebec.html +//@ hasraw search-index.js 'Quebec' + +// we can --parts-out-dir, but that doesn't do anything other than create +// the file +pub struct Quebec; diff --git a/tests/rustdoc/merge-cross-crate-info/single-merge-none-useless-write/quebec.rs b/tests/rustdoc/merge-cross-crate-info/single-merge-none-useless-write/quebec.rs new file mode 100644 index 0000000000000..e888a43c46042 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/single-merge-none-useless-write/quebec.rs @@ -0,0 +1,11 @@ +//@ doc-flags:--merge=none +//@ doc-flags:--parts-out-dir=info/doc.parts/quebec +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ !has index.html +//@ has quebec/struct.Quebec.html +//@ !has search-index.js + +// --merge=none doesn't write anything, despite --parts-out-dir +pub struct Quebec; diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-finalize/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/transitive-finalize/auxiliary/quebec.rs new file mode 100644 index 0000000000000..1beca543f814f --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/transitive-finalize/auxiliary/quebec.rs @@ -0,0 +1,5 @@ +//@ doc-flags:--merge=finalize +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +pub struct Quebec; diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-finalize/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/transitive-finalize/auxiliary/tango.rs new file mode 100644 index 0000000000000..363b2d5508e63 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/transitive-finalize/auxiliary/tango.rs @@ -0,0 +1,8 @@ +//@ aux-build:quebec.rs +//@ build-aux-docs +//@ doc-flags:--merge=finalize +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +extern crate quebec; +pub trait Tango {} diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-finalize/sierra.rs b/tests/rustdoc/merge-cross-crate-info/transitive-finalize/sierra.rs new file mode 100644 index 0000000000000..68fc4b13fa8f7 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/transitive-finalize/sierra.rs @@ -0,0 +1,20 @@ +//@ aux-build:tango.rs +//@ build-aux-docs +//@ doc-flags:--merge=finalize +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ has index.html +//@ has index.html '//h1' 'List of all crates' +//@ has index.html '//ul[@class="all-items"]//a[@href="sierra/index.html"]' 'sierra' +//@ has index.html '//ul[@class="all-items"]//a[@href="tango/index.html"]' 'tango' +//@ has sierra/struct.Sierra.html +//@ has tango/trait.Tango.html +//@ hasraw sierra/struct.Sierra.html 'Tango' +//@ hasraw trait.impl/tango/trait.Tango.js 'struct.Sierra.html' +//@ hasraw search-index.js 'Sierra' + +// write only overwrites stuff in the output directory +extern crate tango; +pub struct Sierra; +impl tango::Tango for Sierra {} diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-merge-none/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/transitive-merge-none/auxiliary/quebec.rs new file mode 100644 index 0000000000000..6ab921533b037 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/transitive-merge-none/auxiliary/quebec.rs @@ -0,0 +1,6 @@ +//@ doc-flags:--merge=none +//@ doc-flags:--parts-out-dir=info/doc.parts/quebec +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +pub struct Quebec; diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-merge-none/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/transitive-merge-none/auxiliary/tango.rs new file mode 100644 index 0000000000000..9fa99d3be8af4 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/transitive-merge-none/auxiliary/tango.rs @@ -0,0 +1,9 @@ +//@ aux-build:quebec.rs +//@ build-aux-docs +//@ doc-flags:--merge=none +//@ doc-flags:--parts-out-dir=info/doc.parts/tango +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +extern crate quebec; +pub trait Tango {} diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-merge-none/sierra.rs b/tests/rustdoc/merge-cross-crate-info/transitive-merge-none/sierra.rs new file mode 100644 index 0000000000000..b407228085e88 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/transitive-merge-none/sierra.rs @@ -0,0 +1,27 @@ +//@ aux-build:tango.rs +//@ build-aux-docs +//@ doc-flags:--merge=finalize +//@ doc-flags:--include-parts-dir=info/doc.parts/tango +//@ doc-flags:--include-parts-dir=info/doc.parts/quebec +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ has index.html +//@ has index.html '//h1' 'List of all crates' +//@ has index.html '//ul[@class="all-items"]//a[@href="quebec/index.html"]' 'quebec' +//@ has index.html '//ul[@class="all-items"]//a[@href="sierra/index.html"]' 'sierra' +//@ has index.html '//ul[@class="all-items"]//a[@href="tango/index.html"]' 'tango' +//@ has quebec/struct.Quebec.html +//@ has sierra/struct.Sierra.html +//@ has tango/trait.Tango.html +//@ hasraw sierra/struct.Sierra.html 'Tango' +//@ hasraw trait.impl/tango/trait.Tango.js 'struct.Sierra.html' +//@ hasraw search-index.js 'Tango' +//@ hasraw search-index.js 'Sierra' +//@ hasraw search-index.js 'Quebec' + +// We avoid writing any cross-crate information, preferring to include it +// with --include-parts-dir. +extern crate tango; +pub struct Sierra; +impl tango::Tango for Sierra {} diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/auxiliary/quebec.rs new file mode 100644 index 0000000000000..1beca543f814f --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/auxiliary/quebec.rs @@ -0,0 +1,5 @@ +//@ doc-flags:--merge=finalize +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +pub struct Quebec; diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/auxiliary/tango.rs new file mode 100644 index 0000000000000..ff12fe98d82c2 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/auxiliary/tango.rs @@ -0,0 +1,8 @@ +//@ aux-build:quebec.rs +//@ build-aux-docs +//@ doc-flags:--merge=shared +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +extern crate quebec; +pub trait Tango {} diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/sierra.rs b/tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/sierra.rs new file mode 100644 index 0000000000000..15e32d5941fb2 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/transitive-merge-read-write/sierra.rs @@ -0,0 +1,25 @@ +//@ aux-build:tango.rs +//@ build-aux-docs +//@ doc-flags:--merge=shared +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ has index.html +//@ has index.html '//h1' 'List of all crates' +//@ has index.html '//ul[@class="all-items"]//a[@href="quebec/index.html"]' 'quebec' +//@ has index.html '//ul[@class="all-items"]//a[@href="sierra/index.html"]' 'sierra' +//@ has index.html '//ul[@class="all-items"]//a[@href="tango/index.html"]' 'tango' +//@ has quebec/struct.Quebec.html +//@ has sierra/struct.Sierra.html +//@ has tango/trait.Tango.html +//@ hasraw sierra/struct.Sierra.html 'Tango' +//@ hasraw trait.impl/tango/trait.Tango.js 'struct.Sierra.html' +//@ hasraw search-index.js 'Tango' +//@ hasraw search-index.js 'Sierra' +//@ hasraw search-index.js 'Quebec' + +// We can use read-write to emulate the default behavior of rustdoc, when +// --merge is left out. +extern crate tango; +pub struct Sierra; +impl tango::Tango for Sierra {} diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-no-info/auxiliary/quebec.rs b/tests/rustdoc/merge-cross-crate-info/transitive-no-info/auxiliary/quebec.rs new file mode 100644 index 0000000000000..0e28d8e646647 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/transitive-no-info/auxiliary/quebec.rs @@ -0,0 +1,5 @@ +//@ doc-flags:--merge=none +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +pub struct Quebec; diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-no-info/auxiliary/tango.rs b/tests/rustdoc/merge-cross-crate-info/transitive-no-info/auxiliary/tango.rs new file mode 100644 index 0000000000000..3827119f696f5 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/transitive-no-info/auxiliary/tango.rs @@ -0,0 +1,8 @@ +//@ aux-build:quebec.rs +//@ build-aux-docs +//@ doc-flags:--merge=none +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +extern crate quebec; +pub trait Tango {} diff --git a/tests/rustdoc/merge-cross-crate-info/transitive-no-info/sierra.rs b/tests/rustdoc/merge-cross-crate-info/transitive-no-info/sierra.rs new file mode 100644 index 0000000000000..3eb2cebd74363 --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/transitive-no-info/sierra.rs @@ -0,0 +1,17 @@ +//@ aux-build:tango.rs +//@ build-aux-docs +//@ doc-flags:--merge=none +//@ doc-flags:--enable-index-page +//@ doc-flags:-Zunstable-options + +//@ !has index.html +//@ has sierra/struct.Sierra.html +//@ has tango/trait.Tango.html +//@ hasraw sierra/struct.Sierra.html 'Tango' +//@ !has trait.impl/tango/trait.Tango.js +//@ !has search-index.js + +// --merge=none on all crates does not generate any cross-crate info +extern crate tango; +pub struct Sierra; +impl tango::Tango for Sierra {} diff --git a/tests/rustdoc/merge-cross-crate-info/two-separate-out-dir/auxiliary/foxtrot.rs b/tests/rustdoc/merge-cross-crate-info/two-separate-out-dir/auxiliary/foxtrot.rs new file mode 100644 index 0000000000000..e492b700dbc2b --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/two-separate-out-dir/auxiliary/foxtrot.rs @@ -0,0 +1,5 @@ +//@ unique-doc-out-dir +//@ doc-flags:--parts-out-dir=info/doc.parts/foxtrot +//@ doc-flags:-Zunstable-options + +pub trait Foxtrot {} diff --git a/tests/rustdoc/merge-cross-crate-info/two-separate-out-dir/echo.rs b/tests/rustdoc/merge-cross-crate-info/two-separate-out-dir/echo.rs new file mode 100644 index 0000000000000..ee2b646e43cda --- /dev/null +++ b/tests/rustdoc/merge-cross-crate-info/two-separate-out-dir/echo.rs @@ -0,0 +1,16 @@ +//@ aux-build:foxtrot.rs +//@ build-aux-docs +//@ doc-flags:--include-parts-dir=info/doc.parts/foxtrot +//@ doc-flags:-Zunstable-options + +//@ has echo/enum.Echo.html +//@ hasraw echo/enum.Echo.html 'Foxtrot' +//@ hasraw trait.impl/foxtrot/trait.Foxtrot.js 'enum.Echo.html' +//@ hasraw search-index.js 'Foxtrot' +//@ hasraw search-index.js 'Echo' + +// document two crates in different places, and merge their docs after +// they are generated +extern crate foxtrot; +pub enum Echo {} +impl foxtrot::Foxtrot for Echo {} From e80c9ac3e213c0c2e6d1a80ea2d4bf074ff8f887 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 30 Aug 2024 10:16:41 -0700 Subject: [PATCH 044/189] rustdoc: use `LocalDefId` for inline stmt It's never a cross-crate DefId, so save space by not storing it. --- src/librustdoc/clean/inline.rs | 22 +++++++++++----------- src/librustdoc/clean/mod.rs | 12 ++++++------ src/librustdoc/clean/types.rs | 8 +++++--- 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index d22c4cc4b76b7..7978ce6e22e3b 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -5,7 +5,7 @@ use std::sync::Arc; use rustc_data_structures::fx::FxHashSet; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{DefId, DefIdSet, LocalModDefId}; +use rustc_hir::def_id::{DefId, DefIdSet, LocalDefId, LocalModDefId}; use rustc_hir::Mutability; use rustc_metadata::creader::{CStore, LoadedMacro}; use rustc_middle::ty::fast_reject::SimplifiedType; @@ -43,7 +43,7 @@ pub(crate) fn try_inline( cx: &mut DocContext<'_>, res: Res, name: Symbol, - attrs: Option<(&[ast::Attribute], Option)>, + attrs: Option<(&[ast::Attribute], Option)>, visited: &mut DefIdSet, ) -> Option> { let did = res.opt_def_id()?; @@ -157,7 +157,7 @@ pub(crate) fn try_inline( kind, did, name, - import_def_id.and_then(|def_id| def_id.as_local()), + import_def_id, None, ); // The visibility needs to reflect the one from the reexport and not from the "source" DefId. @@ -198,7 +198,7 @@ pub(crate) fn try_inline_glob( visited, inlined_names, Some(&reexports), - Some((attrs, Some(import.owner_id.def_id.to_def_id()))), + Some((attrs, Some(import.owner_id.def_id))), ); items.retain(|item| { if let Some(name) = item.name { @@ -372,7 +372,7 @@ fn build_type_alias( pub(crate) fn build_impls( cx: &mut DocContext<'_>, did: DefId, - attrs: Option<(&[ast::Attribute], Option)>, + attrs: Option<(&[ast::Attribute], Option)>, ret: &mut Vec, ) { let _prof_timer = cx.tcx.sess.prof.generic_activity("build_inherent_impls"); @@ -405,7 +405,7 @@ pub(crate) fn build_impls( pub(crate) fn merge_attrs( cx: &mut DocContext<'_>, old_attrs: &[ast::Attribute], - new_attrs: Option<(&[ast::Attribute], Option)>, + new_attrs: Option<(&[ast::Attribute], Option)>, ) -> (clean::Attributes, Option>) { // NOTE: If we have additional attributes (from a re-export), // always insert them first. This ensure that re-export @@ -416,7 +416,7 @@ pub(crate) fn merge_attrs( both.extend_from_slice(old_attrs); ( if let Some(item_id) = item_id { - Attributes::from_ast_with_additional(old_attrs, (inner, item_id)) + Attributes::from_ast_with_additional(old_attrs, (inner, item_id.to_def_id())) } else { Attributes::from_ast(&both) }, @@ -431,7 +431,7 @@ pub(crate) fn merge_attrs( pub(crate) fn build_impl( cx: &mut DocContext<'_>, did: DefId, - attrs: Option<(&[ast::Attribute], Option)>, + attrs: Option<(&[ast::Attribute], Option)>, ret: &mut Vec, ) { if !cx.inlined.insert(did.into()) { @@ -641,7 +641,7 @@ fn build_module_items( visited: &mut DefIdSet, inlined_names: &mut FxHashSet<(ItemType, Symbol)>, allowed_def_ids: Option<&DefIdSet>, - attrs: Option<(&[ast::Attribute], Option)>, + attrs: Option<(&[ast::Attribute], Option)>, ) -> Vec { let mut items = Vec::new(); @@ -745,7 +745,7 @@ fn build_macro( cx: &mut DocContext<'_>, def_id: DefId, name: Symbol, - import_def_id: Option, + import_def_id: Option, macro_kind: MacroKind, is_doc_hidden: bool, ) -> clean::ItemKind { @@ -753,7 +753,7 @@ fn build_macro( LoadedMacro::MacroDef(item_def, _) => match macro_kind { MacroKind::Bang => { if let ast::ItemKind::MacroDef(ref def) = item_def.kind { - let vis = cx.tcx.visibility(import_def_id.unwrap_or(def_id)); + let vis = cx.tcx.visibility(import_def_id.map(|d| d.to_def_id()).unwrap_or(def_id)); clean::MacroItem(clean::Macro { source: utils::display_macro_source( cx, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 710bd4a5fdff7..1dc6d820780de 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -204,7 +204,7 @@ fn generate_item_with_correct_attrs( let name = renamed.or(Some(name)); let mut item = Item::from_def_id_and_attrs_and_parts(def_id, name, kind, Box::new(attrs), cfg); - item.inline_stmt_id = import_id.map(|local| local.to_def_id()); + item.inline_stmt_id = import_id; item } @@ -2927,7 +2927,7 @@ fn clean_extern_crate<'tcx>( }) && !cx.output_format.is_json(); - let krate_owner_def_id = krate.owner_id.to_def_id(); + let krate_owner_def_id = krate.owner_id.def_id; if please_inline { if let Some(items) = inline::try_inline( cx, @@ -2941,7 +2941,7 @@ fn clean_extern_crate<'tcx>( } vec![Item::from_def_id_and_parts( - krate_owner_def_id, + krate_owner_def_id.to_def_id(), Some(name), ExternCrateItem { src: orig_name }, cx, @@ -2988,7 +2988,7 @@ fn clean_use_statement_inner<'tcx>( let inline_attr = attrs.lists(sym::doc).get_word_attr(sym::inline); let pub_underscore = visibility.is_public() && name == kw::Underscore; let current_mod = cx.tcx.parent_module_from_def_id(import.owner_id.def_id); - let import_def_id = import.owner_id.def_id.to_def_id(); + let import_def_id = import.owner_id.def_id; // The parent of the module in which this import resides. This // is the same as `current_mod` if that's already the top @@ -3071,7 +3071,7 @@ fn clean_use_statement_inner<'tcx>( ) { items.push(Item::from_def_id_and_parts( - import_def_id, + import_def_id.to_def_id(), None, ImportItem(Import::new_simple(name, resolve_use_source(cx, path), false)), cx, @@ -3081,7 +3081,7 @@ fn clean_use_statement_inner<'tcx>( Import::new_simple(name, resolve_use_source(cx, path), true) }; - vec![Item::from_def_id_and_parts(import_def_id, None, ImportItem(inner), cx)] + vec![Item::from_def_id_and_parts(import_def_id.to_def_id(), None, ImportItem(inner), cx)] } fn clean_maybe_renamed_foreign_item<'tcx>( diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 5666b229078b4..19aab2116585d 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -325,8 +325,10 @@ pub(crate) struct Item { /// E.g., struct vs enum vs function. pub(crate) kind: Box, pub(crate) item_id: ItemId, - /// This is the `DefId` of the `use` statement if the item was inlined. - pub(crate) inline_stmt_id: Option, + /// This is the `LocalDefId` of the `use` statement if the item was inlined. + /// The crate metadata doesn't hold this information, so the `use` statement + /// always belongs to the current crate. + pub(crate) inline_stmt_id: Option, pub(crate) cfg: Option>, } @@ -702,7 +704,7 @@ impl Item { _ => {} } let def_id = match self.inline_stmt_id { - Some(inlined) => inlined, + Some(inlined) => inlined.to_def_id(), None => def_id, }; Some(tcx.visibility(def_id)) From 65903362ad810c572e8ae742f6ed5ae3548238e4 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 30 Aug 2024 10:52:45 -0700 Subject: [PATCH 045/189] rustdoc: use a single box to store Attributes and ItemKind --- src/librustdoc/clean/auto_trait.rs | 22 +++--- src/librustdoc/clean/blanket_impl.rs | 72 ++++++++++--------- src/librustdoc/clean/inline.rs | 51 +++++++------ src/librustdoc/clean/mod.rs | 2 +- src/librustdoc/clean/types.rs | 55 ++++++++------ src/librustdoc/clean/utils.rs | 6 +- src/librustdoc/fold.rs | 10 +-- src/librustdoc/formats/cache.rs | 26 ++++--- src/librustdoc/formats/item_type.rs | 2 +- src/librustdoc/formats/mod.rs | 2 +- src/librustdoc/formats/renderer.rs | 2 +- src/librustdoc/html/render/context.rs | 2 +- src/librustdoc/html/render/mod.rs | 22 +++--- src/librustdoc/html/render/print_item.rs | 38 +++++----- src/librustdoc/html/render/search_index.rs | 4 +- src/librustdoc/html/render/sidebar.rs | 10 +-- src/librustdoc/html/render/write_shared.rs | 2 +- src/librustdoc/json/conversions.rs | 6 +- src/librustdoc/json/import_finder.rs | 2 +- src/librustdoc/json/mod.rs | 4 +- .../passes/calculate_doc_coverage.rs | 2 +- .../passes/check_doc_test_visibility.rs | 2 +- src/librustdoc/passes/collect_trait_impls.rs | 10 +-- src/librustdoc/passes/propagate_doc_cfg.rs | 2 +- .../passes/strip_aliased_non_local.rs | 2 +- src/librustdoc/passes/strip_hidden.rs | 4 +- src/librustdoc/passes/stripper.rs | 8 +-- src/librustdoc/visit.rs | 4 +- 28 files changed, 195 insertions(+), 179 deletions(-) diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 654901080278d..7e3881c798b53 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -115,17 +115,19 @@ fn synthesize_auto_trait_impl<'tcx>( Some(clean::Item { name: None, - attrs: Default::default(), + inner: Box::new(clean::ItemInner { + attrs: Default::default(), + kind: clean::ImplItem(Box::new(clean::Impl { + safety: hir::Safety::Safe, + generics, + trait_: Some(clean_trait_ref_with_constraints(cx, trait_ref, ThinVec::new())), + for_: clean_middle_ty(ty::Binder::dummy(ty), cx, None, None), + items: Vec::new(), + polarity, + kind: clean::ImplKind::Auto, + })), + }), item_id: clean::ItemId::Auto { trait_: trait_def_id, for_: item_def_id }, - kind: Box::new(clean::ImplItem(Box::new(clean::Impl { - safety: hir::Safety::Safe, - generics, - trait_: Some(clean_trait_ref_with_constraints(cx, trait_ref, ThinVec::new())), - for_: clean_middle_ty(ty::Binder::dummy(ty), cx, None, None), - items: Vec::new(), - polarity, - kind: clean::ImplKind::Auto, - }))), cfg: None, inline_stmt_id: None, }) diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index 1f5f6602b9f23..95f6616cec345 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -84,42 +84,44 @@ pub(crate) fn synthesize_blanket_impls( blanket_impls.push(clean::Item { name: None, - attrs: Default::default(), item_id: clean::ItemId::Blanket { impl_id: impl_def_id, for_: item_def_id }, - kind: Box::new(clean::ImplItem(Box::new(clean::Impl { - safety: hir::Safety::Safe, - generics: clean_ty_generics( - cx, - tcx.generics_of(impl_def_id), - tcx.explicit_predicates_of(impl_def_id), - ), - // FIXME(eddyb) compute both `trait_` and `for_` from - // the post-inference `trait_ref`, as it's more accurate. - trait_: Some(clean_trait_ref_with_constraints( - cx, - ty::Binder::dummy(trait_ref.instantiate_identity()), - ThinVec::new(), - )), - for_: clean_middle_ty( - ty::Binder::dummy(ty.instantiate_identity()), - cx, - None, - None, - ), - items: tcx - .associated_items(impl_def_id) - .in_definition_order() - .filter(|item| !item.is_impl_trait_in_trait()) - .map(|item| clean_middle_assoc_item(item, cx)) - .collect(), - polarity: ty::ImplPolarity::Positive, - kind: clean::ImplKind::Blanket(Box::new(clean_middle_ty( - ty::Binder::dummy(trait_ref.instantiate_identity().self_ty()), - cx, - None, - None, - ))), - }))), + inner: Box::new(clean::ItemInner { + attrs: Default::default(), + kind: clean::ImplItem(Box::new(clean::Impl { + safety: hir::Safety::Safe, + generics: clean_ty_generics( + cx, + tcx.generics_of(impl_def_id), + tcx.explicit_predicates_of(impl_def_id), + ), + // FIXME(eddyb) compute both `trait_` and `for_` from + // the post-inference `trait_ref`, as it's more accurate. + trait_: Some(clean_trait_ref_with_constraints( + cx, + ty::Binder::dummy(trait_ref.instantiate_identity()), + ThinVec::new(), + )), + for_: clean_middle_ty( + ty::Binder::dummy(ty.instantiate_identity()), + cx, + None, + None, + ), + items: tcx + .associated_items(impl_def_id) + .in_definition_order() + .filter(|item| !item.is_impl_trait_in_trait()) + .map(|item| clean_middle_assoc_item(item, cx)) + .collect(), + polarity: ty::ImplPolarity::Positive, + kind: clean::ImplKind::Blanket(Box::new(clean_middle_ty( + ty::Binder::dummy(trait_ref.instantiate_identity().self_ty()), + cx, + None, + None, + ))), + })), + }), cfg: None, inline_stmt_id: None, }); diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 7978ce6e22e3b..8383012885f96 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -152,14 +152,8 @@ pub(crate) fn try_inline( }; cx.inlined.insert(did.into()); - let mut item = crate::clean::generate_item_with_correct_attrs( - cx, - kind, - did, - name, - import_def_id, - None, - ); + let mut item = + crate::clean::generate_item_with_correct_attrs(cx, kind, did, name, import_def_id, None); // The visibility needs to reflect the one from the reexport and not from the "source" DefId. item.inline_stmt_id = import_def_id; ret.push(item); @@ -623,7 +617,7 @@ pub(crate) fn build_impl( ImplKind::Normal }, })), - Box::new(merged_attrs), + merged_attrs, cfg, )); } @@ -673,27 +667,29 @@ fn build_module_items( let prim_ty = clean::PrimitiveType::from(p); items.push(clean::Item { name: None, - attrs: Box::default(), // We can use the item's `DefId` directly since the only information ever used // from it is `DefId.krate`. item_id: ItemId::DefId(did), - kind: Box::new(clean::ImportItem(clean::Import::new_simple( - item.ident.name, - clean::ImportSource { - path: clean::Path { - res, - segments: thin_vec![clean::PathSegment { - name: prim_ty.as_sym(), - args: clean::GenericArgs::AngleBracketed { - args: Default::default(), - constraints: ThinVec::new(), - }, - }], + inner: Box::new(clean::ItemInner { + attrs: Default::default(), + kind: clean::ImportItem(clean::Import::new_simple( + item.ident.name, + clean::ImportSource { + path: clean::Path { + res, + segments: thin_vec![clean::PathSegment { + name: prim_ty.as_sym(), + args: clean::GenericArgs::AngleBracketed { + args: Default::default(), + constraints: ThinVec::new(), + }, + }], + }, + did: None, }, - did: None, - }, - true, - ))), + true, + )), + }), cfg: None, inline_stmt_id: None, }); @@ -753,7 +749,8 @@ fn build_macro( LoadedMacro::MacroDef(item_def, _) => match macro_kind { MacroKind::Bang => { if let ast::ItemKind::MacroDef(ref def) = item_def.kind { - let vis = cx.tcx.visibility(import_def_id.map(|d| d.to_def_id()).unwrap_or(def_id)); + let vis = + cx.tcx.visibility(import_def_id.map(|d| d.to_def_id()).unwrap_or(def_id)); clean::MacroItem(clean::Macro { source: utils::display_macro_source( cx, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 1dc6d820780de..e47ae7df77fb6 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -203,7 +203,7 @@ fn generate_item_with_correct_attrs( let attrs = Attributes::from_ast_iter(attrs.iter().map(|(attr, did)| (&**attr, *did)), false); let name = renamed.or(Some(name)); - let mut item = Item::from_def_id_and_attrs_and_parts(def_id, name, kind, Box::new(attrs), cfg); + let mut item = Item::from_def_id_and_attrs_and_parts(def_id, name, kind, attrs, cfg); item.inline_stmt_id = import_id; item } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 19aab2116585d..383efe568ae09 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -320,10 +320,7 @@ pub(crate) struct Item { /// The name of this item. /// Optional because not every item has a name, e.g. impls. pub(crate) name: Option, - pub(crate) attrs: Box, - /// Information about this item that is specific to what kind of item it is. - /// E.g., struct vs enum vs function. - pub(crate) kind: Box, + pub(crate) inner: Box, pub(crate) item_id: ItemId, /// This is the `LocalDefId` of the `use` statement if the item was inlined. /// The crate metadata doesn't hold this information, so the `use` statement @@ -332,6 +329,21 @@ pub(crate) struct Item { pub(crate) cfg: Option>, } +#[derive(Clone)] +pub(crate) struct ItemInner { + /// Information about this item that is specific to what kind of item it is. + /// E.g., struct vs enum vs function. + pub(crate) kind: ItemKind, + pub(crate) attrs: Attributes, +} + +impl std::ops::Deref for Item { + type Target = ItemInner; + fn deref(&self) -> &ItemInner { + &*self.inner + } +} + /// NOTE: this does NOT unconditionally print every item, to avoid thousands of lines of logs. /// If you want to see the debug output for attributes and the `kind` as well, use `{:#?}` instead of `{:?}`. impl fmt::Debug for Item { @@ -391,9 +403,9 @@ impl Item { } pub(crate) fn span(&self, tcx: TyCtxt<'_>) -> Option { - let kind = match &*self.kind { - ItemKind::StrippedItem(k) => k, - _ => &*self.kind, + let kind = match &self.kind { + ItemKind::StrippedItem(k) => &*k, + _ => &self.kind, }; match kind { ItemKind::ModuleItem(Module { span, .. }) => Some(*span), @@ -438,7 +450,7 @@ impl Item { def_id, name, kind, - Box::new(Attributes::from_ast(ast_attrs)), + Attributes::from_ast(ast_attrs), ast_attrs.cfg(cx.tcx, &cx.cache.hidden_cfg), ) } @@ -447,16 +459,15 @@ impl Item { def_id: DefId, name: Option, kind: ItemKind, - attrs: Box, + attrs: Attributes, cfg: Option>, ) -> Item { trace!("name={name:?}, def_id={def_id:?} cfg={cfg:?}"); Item { item_id: def_id.into(), - kind: Box::new(kind), + inner: Box::new(ItemInner { kind, attrs }), name, - attrs, cfg, inline_stmt_id: None, } @@ -524,16 +535,16 @@ impl Item { self.type_() == ItemType::Variant } pub(crate) fn is_associated_type(&self) -> bool { - matches!(&*self.kind, AssocTypeItem(..) | StrippedItem(box AssocTypeItem(..))) + matches!(self.kind, AssocTypeItem(..) | StrippedItem(box AssocTypeItem(..))) } pub(crate) fn is_ty_associated_type(&self) -> bool { - matches!(&*self.kind, TyAssocTypeItem(..) | StrippedItem(box TyAssocTypeItem(..))) + matches!(self.kind, TyAssocTypeItem(..) | StrippedItem(box TyAssocTypeItem(..))) } pub(crate) fn is_associated_const(&self) -> bool { - matches!(&*self.kind, AssocConstItem(..) | StrippedItem(box AssocConstItem(..))) + matches!(self.kind, AssocConstItem(..) | StrippedItem(box AssocConstItem(..))) } pub(crate) fn is_ty_associated_const(&self) -> bool { - matches!(&*self.kind, TyAssocConstItem(..) | StrippedItem(box TyAssocConstItem(..))) + matches!(self.kind, TyAssocConstItem(..) | StrippedItem(box TyAssocConstItem(..))) } pub(crate) fn is_method(&self) -> bool { self.type_() == ItemType::Method @@ -557,14 +568,14 @@ impl Item { self.type_() == ItemType::Keyword } pub(crate) fn is_stripped(&self) -> bool { - match *self.kind { + match self.kind { StrippedItem(..) => true, ImportItem(ref i) => !i.should_be_displayed, _ => false, } } pub(crate) fn has_stripped_entries(&self) -> Option { - match *self.kind { + match self.kind { StructItem(ref struct_) => Some(struct_.has_stripped_entries()), UnionItem(ref union_) => Some(union_.has_stripped_entries()), EnumItem(ref enum_) => Some(enum_.has_stripped_entries()), @@ -607,7 +618,7 @@ impl Item { } pub(crate) fn is_default(&self) -> bool { - match *self.kind { + match self.kind { ItemKind::MethodItem(_, Some(defaultness)) => { defaultness.has_value() && !defaultness.is_final() } @@ -635,7 +646,7 @@ impl Item { }; hir::FnHeader { safety: sig.safety(), abi: sig.abi(), constness, asyncness } } - let header = match *self.kind { + let header = match self.kind { ItemKind::ForeignFunctionItem(_, safety) => { let def_id = self.def_id().unwrap(); let abi = tcx.fn_sig(def_id).skip_binder().abi(); @@ -674,7 +685,7 @@ impl Item { ItemId::DefId(def_id) => def_id, }; - match *self.kind { + match self.kind { // Primitives and Keywords are written in the source code as private modules. // The modules need to be private so that nobody actually uses them, but the // keywords and primitives that they are documenting are public. @@ -2561,13 +2572,13 @@ mod size_asserts { use super::*; // tidy-alphabetical-start - static_assert_size!(Crate, 64); // frequently moved by-value + static_assert_size!(Crate, 56); // frequently moved by-value static_assert_size!(DocFragment, 32); static_assert_size!(GenericArg, 32); static_assert_size!(GenericArgs, 32); static_assert_size!(GenericParamDef, 40); static_assert_size!(Generics, 16); - static_assert_size!(Item, 56); + static_assert_size!(Item, 48); static_assert_size!(ItemKind, 48); static_assert_size!(PathSegment, 40); static_assert_size!(Type, 32); diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 5686307d83dda..885758c17cf8e 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -36,7 +36,7 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate { // understood by rustdoc. let mut module = clean_doc_module(&module, cx); - match *module.kind { + match module.kind { ItemKind::ModuleItem(ref module) => { for it in &module.items { // `compiler_builtins` should be masked too, but we can't apply @@ -60,7 +60,7 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate { let primitives = local_crate.primitives(cx.tcx); let keywords = local_crate.keywords(cx.tcx); { - let ItemKind::ModuleItem(ref mut m) = *module.kind else { unreachable!() }; + let ItemKind::ModuleItem(ref mut m) = &mut module.inner.kind else { unreachable!() }; m.items.extend(primitives.iter().map(|&(def_id, prim)| { Item::from_def_id_and_parts( def_id, @@ -281,7 +281,7 @@ pub(crate) fn build_deref_target_impls( let tcx = cx.tcx; for item in items { - let target = match *item.kind { + let target = match item.kind { ItemKind::AssocTypeItem(ref t, _) => &t.type_, _ => continue, }; diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs index bf82c911f290f..c25a4ddb6f369 100644 --- a/src/librustdoc/fold.rs +++ b/src/librustdoc/fold.rs @@ -1,8 +1,8 @@ use crate::clean::*; pub(crate) fn strip_item(mut item: Item) -> Item { - if !matches!(*item.kind, StrippedItem(..)) { - item.kind = Box::new(StrippedItem(item.kind)); + if !matches!(item.inner.kind, StrippedItem(..)) { + item.inner.kind = StrippedItem(Box::new(item.inner.kind)); } item } @@ -99,10 +99,10 @@ pub(crate) trait DocFolder: Sized { /// don't override! fn fold_item_recur(&mut self, mut item: Item) -> Item { - item.kind = Box::new(match *item.kind { + item.inner.kind = match item.inner.kind { StrippedItem(box i) => StrippedItem(Box::new(self.fold_inner_recur(i))), - _ => self.fold_inner_recur(*item.kind), - }); + _ => self.fold_inner_recur(item.inner.kind), + }; item } diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index c5e2b33ccf874..1b3176e7918b7 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -216,7 +216,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { // If this is a stripped module, // we don't want it or its children in the search index. - let orig_stripped_mod = match *item.kind { + let orig_stripped_mod = match item.kind { clean::StrippedItem(box clean::ModuleItem(..)) => { mem::replace(&mut self.cache.stripped_mod, true) } @@ -232,7 +232,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { // If the impl is from a masked crate or references something from a // masked crate then remove it completely. - if let clean::ImplItem(ref i) = *item.kind + if let clean::ImplItem(ref i) = item.kind && (self.cache.masked_crates.contains(&item.item_id.krate()) || i.trait_ .as_ref() @@ -246,9 +246,9 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { // Propagate a trait method's documentation to all implementors of the // trait. - if let clean::TraitItem(ref t) = *item.kind { + if let clean::TraitItem(ref t) = item.kind { self.cache.traits.entry(item.item_id.expect_def_id()).or_insert_with(|| (**t).clone()); - } else if let clean::ImplItem(ref i) = *item.kind + } else if let clean::ImplItem(ref i) = item.kind && let Some(trait_) = &i.trait_ && !i.kind.is_blanket() { @@ -263,7 +263,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { // Index this method for searching later on. let search_name = if !item.is_stripped() { item.name.or_else(|| { - if let clean::ImportItem(ref i) = *item.kind + if let clean::ImportItem(ref i) = item.kind && let clean::ImportKind::Simple(s) = i.kind { Some(s) @@ -287,7 +287,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { _ => false, }; - match *item.kind { + match item.kind { clean::StructItem(..) | clean::EnumItem(..) | clean::TypeAliasItem(..) @@ -350,7 +350,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { } // Maintain the parent stack. - let (item, parent_pushed) = match *item.kind { + let (item, parent_pushed) = match item.kind { clean::TraitItem(..) | clean::EnumItem(..) | clean::ForeignTypeItem @@ -367,7 +367,11 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { // Once we've recursively found all the generics, hoard off all the // implementations elsewhere. - let ret = if let clean::Item { kind: box clean::ImplItem(ref i), .. } = item { + let ret = if let clean::Item { + inner: box clean::ItemInner { kind: clean::ImplItem(ref i), .. }, + .. + } = item + { // Figure out the id of this impl. This may map to a // primitive rather than always to a struct/enum. // Note: matching twice to restrict the lifetime of the `i` borrow. @@ -436,7 +440,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::Item, name: Symbol) { // Item has a name, so it must also have a DefId (can't be an impl, let alone a blanket or auto impl). let item_def_id = item.item_id.as_def_id().unwrap(); - let (parent_did, parent_path) = match *item.kind { + let (parent_did, parent_path) = match item.kind { clean::StrippedItem(..) => return, clean::AssocConstItem(..) | clean::AssocTypeItem(..) if cache.parent_stack.last().is_some_and(|parent| parent.is_trait_impl()) => @@ -528,7 +532,7 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It // - It's either an inline, or a true re-export // - It's got the same name // - Both of them have the same exact path - let defid = match &*item.kind { + let defid = match &item.kind { clean::ItemKind::ImportItem(import) => import.source.did.unwrap_or(item_def_id), _ => item_def_id, }; @@ -605,7 +609,7 @@ enum ParentStackItem { impl ParentStackItem { fn new(item: &clean::Item) -> Self { - match &*item.kind { + match &item.kind { clean::ItemKind::ImplItem(box clean::Impl { for_, trait_, generics, kind, .. }) => { ParentStackItem::Impl { for_: for_.clone(), diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs index 9754e1e6f74d4..383e3135faa86 100644 --- a/src/librustdoc/formats/item_type.rs +++ b/src/librustdoc/formats/item_type.rs @@ -70,7 +70,7 @@ impl Serialize for ItemType { impl<'a> From<&'a clean::Item> for ItemType { fn from(item: &'a clean::Item) -> ItemType { - let kind = match *item.kind { + let kind = match item.kind { clean::StrippedItem(box ref item) => item, ref kind => kind, }; diff --git a/src/librustdoc/formats/mod.rs b/src/librustdoc/formats/mod.rs index 84adca8efa997..0bdea36043ca6 100644 --- a/src/librustdoc/formats/mod.rs +++ b/src/librustdoc/formats/mod.rs @@ -16,7 +16,7 @@ pub(crate) struct Impl { impl Impl { pub(crate) fn inner_impl(&self) -> &clean::Impl { - match *self.impl_item.kind { + match self.impl_item.kind { clean::ImplItem(ref impl_) => impl_, _ => panic!("non-impl item found in impl"), } diff --git a/src/librustdoc/formats/renderer.rs b/src/librustdoc/formats/renderer.rs index cc57dca86c341..edd7d56b17983 100644 --- a/src/librustdoc/formats/renderer.rs +++ b/src/librustdoc/formats/renderer.rs @@ -77,7 +77,7 @@ pub(crate) fn run_format<'tcx, T: FormatRenderer<'tcx>>( cx.mod_item_in(&item)?; let (clean::StrippedItem(box clean::ModuleItem(module)) | clean::ModuleItem(module)) = - *item.kind + item.inner.kind else { unreachable!() }; diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 9fe43e428f2ae..58a228b74fcf3 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -800,7 +800,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { // Render sidebar-items.js used throughout this module. if !self.render_redirect_pages { let (clean::StrippedItem(box clean::ModuleItem(ref module)) - | clean::ModuleItem(ref module)) = *item.kind + | clean::ModuleItem(ref module)) = item.kind else { unreachable!() }; diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index f67d006116cb6..3b8eda08372e6 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -620,7 +620,7 @@ fn document_full_inner<'a, 'cx: 'a>( } } - let kind = match &*item.kind { + let kind = match &item.kind { clean::ItemKind::StrippedItem(box kind) | kind => kind, }; @@ -1072,7 +1072,7 @@ fn render_assoc_item( cx: &mut Context<'_>, render_mode: RenderMode, ) { - match &*item.kind { + match &item.kind { clean::StrippedItem(..) => {} clean::TyMethodItem(m) => { assoc_method(w, item, &m.generics, &m.decl, link, parent, cx, render_mode) @@ -1350,7 +1350,7 @@ fn render_deref_methods( .inner_impl() .items .iter() - .find_map(|item| match *item.kind { + .find_map(|item| match item.kind { clean::AssocTypeItem(box ref t, _) => Some(match *t { clean::TypeAlias { item_type: Some(ref type_), .. } => (type_, &t.type_), _ => (&t.type_, &t.type_), @@ -1381,7 +1381,7 @@ fn render_deref_methods( } fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) -> bool { - let self_type_opt = match *item.kind { + let self_type_opt = match item.kind { clean::MethodItem(ref method, _) => method.decl.receiver_type(), clean::TyMethodItem(ref method) => method.decl.receiver_type(), _ => None, @@ -1491,7 +1491,7 @@ fn notable_traits_decl(ty: &clean::Type, cx: &Context<'_>) -> (String, String) { write!(&mut out, "
{}
", impl_.print(false, cx)); for it in &impl_.items { - if let clean::AssocTypeItem(ref tydef, ref _bounds) = *it.kind { + if let clean::AssocTypeItem(ref tydef, ref _bounds) = it.kind { out.push_str("
"); let empty_set = FxHashSet::default(); let src_link = AssocItemLink::GotoSource(trait_did.into(), &empty_set); @@ -1659,7 +1659,7 @@ fn render_impl( let method_toggle_class = if item_type.is_method() { " method-toggle" } else { "" }; write!(w, "
"); } - match &*item.kind { + match &item.kind { clean::MethodItem(..) | clean::TyMethodItem(_) => { // Only render when the method is not static or we allow static methods if render_method_item { @@ -1690,7 +1690,7 @@ fn render_impl( w.write_str(""); } } - clean::TyAssocConstItem(generics, ty) => { + clean::TyAssocConstItem(ref generics, ref ty) => { let source_id = format!("{item_type}.{name}"); let id = cx.derive_id(&source_id); write!(w, "
"); @@ -1734,7 +1734,7 @@ fn render_impl( ); w.write_str("
"); } - clean::TyAssocTypeItem(generics, bounds) => { + clean::TyAssocTypeItem(ref generics, ref bounds) => { let source_id = format!("{item_type}.{name}"); let id = cx.derive_id(&source_id); write!(w, "
"); @@ -1808,7 +1808,7 @@ fn render_impl( if !impl_.is_negative_trait_impl() { for trait_item in &impl_.items { - match *trait_item.kind { + match trait_item.kind { clean::MethodItem(..) | clean::TyMethodItem(_) => methods.push(trait_item), clean::TyAssocTypeItem(..) | clean::AssocTypeItem(..) => { assoc_types.push(trait_item) @@ -2051,7 +2051,7 @@ pub(crate) fn render_impl_summary( write!(w, "{}", inner_impl.print(use_absolute, cx)); if show_def_docs { for it in &inner_impl.items { - if let clean::AssocTypeItem(ref tydef, ref _bounds) = *it.kind { + if let clean::AssocTypeItem(ref tydef, ref _bounds) = it.kind { w.write_str("
"); assoc_type( w, @@ -2172,7 +2172,7 @@ fn get_id_for_impl<'tcx>(tcx: TyCtxt<'tcx>, impl_id: ItemId) -> String { } fn extract_for_impl_name(item: &clean::Item, cx: &Context<'_>) -> Option<(String, String)> { - match *item.kind { + match item.kind { clean::ItemKind::ImplItem(ref i) if i.trait_.is_some() => { // Alternative format produces no URLs, // so this parameter does nothing. diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index cda5409a460ee..52e2515277087 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -178,7 +178,7 @@ fn print_where_clause_and_check<'a, 'tcx: 'a>( pub(super) fn print_item(cx: &mut Context<'_>, item: &clean::Item, buf: &mut Buffer) { debug_assert!(!item.is_stripped()); - let typ = match *item.kind { + let typ = match item.kind { clean::ModuleItem(_) => { if item.is_crate() { "Crate " @@ -252,7 +252,7 @@ pub(super) fn print_item(cx: &mut Context<'_>, item: &clean::Item, buf: &mut Buf item_vars.render_into(buf).unwrap(); - match &*item.kind { + match &item.kind { clean::ModuleItem(ref m) => item_module(buf, cx, item, &m.items), clean::FunctionItem(ref f) | clean::ForeignFunctionItem(ref f, _) => { item_function(buf, cx, item, f) @@ -411,7 +411,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: ); } - match *myitem.kind { + match myitem.kind { clean::ExternCrateItem { ref src } => { use crate::html::format::anchor; @@ -477,7 +477,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: continue; } - let unsafety_flag = match *myitem.kind { + let unsafety_flag = match myitem.kind { clean::FunctionItem(_) | clean::ForeignFunctionItem(..) if myitem.fn_header(tcx).unwrap().safety == hir::Safety::Unsafe => { @@ -1439,7 +1439,7 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean: self.s .fields .iter() - .filter_map(|f| match *f.kind { + .filter_map(|f| match f.kind { clean::StructFieldItem(ref ty) => Some((f, ty)), _ => None, }) @@ -1457,7 +1457,7 @@ fn print_tuple_struct_fields<'a, 'cx: 'a>( display_fn(|f| { if !s.is_empty() && s.iter().all(|field| { - matches!(*field.kind, clean::StrippedItem(box clean::StructFieldItem(..))) + matches!(field.kind, clean::StrippedItem(box clean::StructFieldItem(..))) }) { return f.write_str("/* private fields */"); @@ -1467,7 +1467,7 @@ fn print_tuple_struct_fields<'a, 'cx: 'a>( if i > 0 { f.write_str(", ")?; } - match *ty.kind { + match ty.kind { clean::StrippedItem(box clean::StructFieldItem(_)) => f.write_str("_")?, clean::StructFieldItem(ref ty) => write!(f, "{}", ty.print(cx))?, _ => unreachable!(), @@ -1521,7 +1521,7 @@ fn should_show_enum_discriminant( ) -> bool { let mut has_variants_with_value = false; for variant in variants { - if let clean::VariantItem(ref var) = *variant.kind + if let clean::VariantItem(ref var) = variant.kind && matches!(var.kind, clean::VariantKind::CLike) { has_variants_with_value |= var.discriminant.is_some(); @@ -1592,7 +1592,7 @@ fn render_enum_fields( continue; } w.write_str(TAB); - match *v.kind { + match v.kind { clean::VariantItem(ref var) => match var.kind { clean::VariantKind::CLike => display_c_like_variant( w, @@ -1659,7 +1659,7 @@ fn item_variants( " rightside", ); w.write_str("

"); - if let clean::VariantItem(ref var) = *variant.kind + if let clean::VariantItem(ref var) = variant.kind && let clean::VariantKind::CLike = var.kind { display_c_like_variant( @@ -1675,7 +1675,7 @@ fn item_variants( w.write_str(variant.name.unwrap().as_str()); } - let clean::VariantItem(variant_data) = &*variant.kind else { unreachable!() }; + let clean::VariantItem(variant_data) = &variant.kind else { unreachable!() }; if let clean::VariantKind::Tuple(ref s) = variant_data.kind { write!(w, "({})", print_tuple_struct_fields(cx, s)); @@ -1716,7 +1716,7 @@ fn item_variants( document_non_exhaustive(variant) ); for field in fields { - match *field.kind { + match field.kind { clean::StrippedItem(box clean::StructFieldItem(_)) => {} clean::StructFieldItem(ref ty) => { let id = cx.derive_id(format!( @@ -1886,7 +1886,7 @@ fn item_fields( ) { let mut fields = fields .iter() - .filter_map(|f| match *f.kind { + .filter_map(|f| match f.kind { clean::StructFieldItem(ref ty) => Some((f, ty)), _ => None, }) @@ -2196,14 +2196,14 @@ fn render_union<'a, 'cx: 'a>( write!(f, "{{\n")?; let count_fields = - fields.iter().filter(|field| matches!(*field.kind, clean::StructFieldItem(..))).count(); + fields.iter().filter(|field| matches!(field.kind, clean::StructFieldItem(..))).count(); let toggle = should_hide_fields(count_fields); if toggle { toggle_open(&mut f, format_args!("{count_fields} fields")); } for field in fields { - if let clean::StructFieldItem(ref ty) = *field.kind { + if let clean::StructFieldItem(ref ty) = field.kind { write!( f, " {}{}: {},\n", @@ -2279,14 +2279,14 @@ fn render_struct_fields( w.write_str("{"); } let count_fields = - fields.iter().filter(|f| matches!(*f.kind, clean::StructFieldItem(..))).count(); + fields.iter().filter(|f| matches!(f.kind, clean::StructFieldItem(..))).count(); let has_visible_fields = count_fields > 0; let toggle = should_hide_fields(count_fields); if toggle { toggle_open(&mut w, format_args!("{count_fields} fields")); } for field in fields { - if let clean::StructFieldItem(ref ty) = *field.kind { + if let clean::StructFieldItem(ref ty) = field.kind { write!( w, "\n{tab} {vis}{name}: {ty},", @@ -2314,7 +2314,7 @@ fn render_struct_fields( w.write_str("("); if !fields.is_empty() && fields.iter().all(|field| { - matches!(*field.kind, clean::StrippedItem(box clean::StructFieldItem(..))) + matches!(field.kind, clean::StrippedItem(box clean::StructFieldItem(..))) }) { write!(w, "/* private fields */"); @@ -2323,7 +2323,7 @@ fn render_struct_fields( if i > 0 { w.write_str(", "); } - match *field.kind { + match field.kind { clean::StrippedItem(box clean::StructFieldItem(..)) => write!(w, "_"), clean::StructFieldItem(ref ty) => { write!(w, "{}{}", visibility_print_with_space(field, cx), ty.print(cx),) diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index bfdf457c529d5..b84c22ac746c5 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -758,7 +758,7 @@ pub(crate) fn get_function_type_for_search<'tcx>( None } }); - let (mut inputs, mut output, where_clause) = match *item.kind { + let (mut inputs, mut output, where_clause) = match item.kind { clean::FunctionItem(ref f) | clean::MethodItem(ref f, _) | clean::TyMethodItem(ref f) => { get_fn_inputs_and_outputs(f, tcx, impl_or_trait_generics, cache) } @@ -1132,7 +1132,7 @@ fn simplify_fn_type<'tcx, 'a>( && trait_.items.iter().any(|at| at.is_ty_associated_type()) { for assoc_ty in &trait_.items { - if let clean::ItemKind::TyAssocTypeItem(_generics, bounds) = &*assoc_ty.kind + if let clean::ItemKind::TyAssocTypeItem(_generics, bounds) = &assoc_ty.kind && let Some(name) = assoc_ty.name { let idx = -isize::try_from(rgen.len() + 1).unwrap(); diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs index 06cc57b2a5536..842ee81624ef2 100644 --- a/src/librustdoc/html/render/sidebar.rs +++ b/src/librustdoc/html/render/sidebar.rs @@ -119,7 +119,7 @@ pub(crate) mod filters { pub(super) fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) { let mut ids = IdMap::new(); let mut blocks: Vec> = docblock_toc(cx, it, &mut ids).into_iter().collect(); - match *it.kind { + match it.kind { clean::StructItem(ref s) => sidebar_struct(cx, it, s, &mut blocks), clean::TraitItem(ref t) => sidebar_trait(cx, it, t, &mut blocks), clean::PrimitiveItem(_) => sidebar_primitive(cx, it, &mut blocks), @@ -143,7 +143,7 @@ pub(super) fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buf // crate title is displayed as part of logo lockup let (title_prefix, title) = if !blocks.is_empty() && !it.is_crate() { ( - match *it.kind { + match it.kind { clean::ModuleItem(..) => "Module ", _ => "", }, @@ -181,7 +181,7 @@ pub(super) fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buf fn get_struct_fields_name<'a>(fields: &'a [clean::Item]) -> Vec> { let mut fields = fields .iter() - .filter(|f| matches!(*f.kind, clean::StructFieldItem(..))) + .filter(|f| matches!(f.kind, clean::StructFieldItem(..))) .filter_map(|f| { f.name.as_ref().map(|name| Link::new(format!("structfield.{name}"), name.as_str())) }) @@ -467,7 +467,7 @@ fn sidebar_deref_methods<'a>( debug!("found Deref: {impl_:?}"); if let Some((target, real_target)) = - impl_.inner_impl().items.iter().find_map(|item| match *item.kind { + impl_.inner_impl().items.iter().find_map(|item| match item.kind { clean::AssocTypeItem(box ref t, _) => Some(match *t { clean::TypeAlias { item_type: Some(ref type_), .. } => (type_, &t.type_), _ => (&t.type_, &t.type_), @@ -587,7 +587,7 @@ fn sidebar_module( && it .name .or_else(|| { - if let clean::ImportItem(ref i) = *it.kind + if let clean::ImportItem(ref i) = it.kind && let clean::ImportKind::Simple(s) = i.kind { Some(s) diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index b0af8d8c23ee5..e8d12320f82fd 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -783,7 +783,7 @@ impl<'cx, 'cache> DocVisitor for TypeImplCollector<'cx, 'cache> { fn visit_item(&mut self, it: &Item) { self.visit_item_recur(it); let cache = self.cache; - let ItemKind::TypeAliasItem(ref t) = *it.kind else { return }; + let ItemKind::TypeAliasItem(ref t) = it.kind else { return }; let Some(self_did) = it.item_id.as_def_id() else { return }; if !self.visited_aliases.insert(self_did) { return; diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index b97d710c007ce..cae8d107da415 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -49,7 +49,7 @@ impl JsonRenderer<'_> { let visibility = item.visibility(self.tcx); let clean::Item { name, item_id, .. } = item; let id = id_from_item(&item, self.tcx); - let inner = match *item.kind { + let inner = match item.kind { clean::KeywordItem => return None, clean::StrippedItem(ref inner) => { match &**inner { @@ -294,7 +294,7 @@ pub(crate) fn id_from_item_inner( } pub(crate) fn id_from_item(item: &clean::Item, tcx: TyCtxt<'_>) -> Id { - match *item.kind { + match item.kind { clean::ItemKind::ImportItem(ref import) => { let extra = import.source.did.map(ItemId::from).map(|i| id_from_item_inner(i, tcx, None, None)); @@ -310,7 +310,7 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum { let is_crate = item.is_crate(); let header = item.fn_header(tcx); - match *item.kind { + match item.inner.kind { ModuleItem(m) => { ItemEnum::Module(Module { is_crate, items: ids(m.items, tcx), is_stripped: false }) } diff --git a/src/librustdoc/json/import_finder.rs b/src/librustdoc/json/import_finder.rs index 976a7fd69aeee..e21fe9668d400 100644 --- a/src/librustdoc/json/import_finder.rs +++ b/src/librustdoc/json/import_finder.rs @@ -24,7 +24,7 @@ struct ImportFinder { impl DocFolder for ImportFinder { fn fold_item(&mut self, i: Item) -> Option { - match *i.kind { + match i.kind { clean::ImportItem(Import { source: ImportSource { did: Some(did), .. }, .. }) => { self.imported.insert(did); Some(i) diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index 1b2d61a763797..d375946a8c853 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -85,7 +85,7 @@ impl<'tcx> JsonRenderer<'tcx> { // document primitive items in an arbitrary crate by using // `rustc_doc_primitive`. let mut is_primitive_impl = false; - if let clean::types::ItemKind::ImplItem(ref impl_) = *item.kind + if let clean::types::ItemKind::ImplItem(ref impl_) = item.kind && impl_.trait_.is_none() && let clean::types::Type::Primitive(_) = impl_.for_ { @@ -164,7 +164,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { // Flatten items that recursively store other items. We include orphaned items from // stripped modules and etc that are otherwise reachable. - if let ItemKind::StrippedItem(inner) = &*item.kind { + if let ItemKind::StrippedItem(inner) = &item.kind { inner.inner_items().for_each(|i| self.item(i.clone()).unwrap()); } diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index 1d0b41fc429c5..7391909406e36 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -195,7 +195,7 @@ impl<'a, 'b> DocVisitor for CoverageCalculator<'a, 'b> { return; } - match *i.kind { + match i.kind { clean::StrippedItem(..) => { // don't count items in stripped modules return; diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs index d456e8e24e6f1..733fd919e712b 100644 --- a/src/librustdoc/passes/check_doc_test_visibility.rs +++ b/src/librustdoc/passes/check_doc_test_visibility.rs @@ -57,7 +57,7 @@ impl crate::doctest::DocTestVisitor for Tests { pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -> bool { if !cx.cache.effective_visibilities.is_directly_public(cx.tcx, item.item_id.expect_def_id()) || matches!( - *item.kind, + item.kind, clean::StructFieldItem(_) | clean::VariantItem(_) | clean::AssocConstItem(..) diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index 394a64df4bc41..a9edc485d5e7a 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -160,13 +160,13 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> // scan through included items ahead of time to splice in Deref targets to the "valid" sets for it in new_items_external.iter().chain(new_items_local.iter()) { - if let ImplItem(box Impl { ref for_, ref trait_, ref items, .. }) = *it.kind + if let ImplItem(box Impl { ref for_, ref trait_, ref items, .. }) = it.kind && trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait() && cleaner.keep_impl(for_, true) { let target = items .iter() - .find_map(|item| match *item.kind { + .find_map(|item| match item.kind { AssocTypeItem(ref t, _) => Some(&t.type_), _ => None, }) @@ -200,7 +200,7 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> // Filter out external items that are not needed new_items_external.retain(|it| { - if let ImplItem(box Impl { ref for_, ref trait_, ref kind, .. }) = *it.kind { + if let ImplItem(box Impl { ref for_, ref trait_, ref kind, .. }) = it.kind { cleaner.keep_impl( for_, trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait(), @@ -211,7 +211,7 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> } }); - if let ModuleItem(Module { items, .. }) = &mut *krate.module.kind { + if let ModuleItem(Module { items, .. }) = &mut krate.module.inner.kind { items.extend(synth_impls); items.extend(new_items_external); items.extend(new_items_local); @@ -258,7 +258,7 @@ impl<'cache> DocVisitor for ItemAndAliasCollector<'cache> { fn visit_item(&mut self, i: &Item) { self.items.insert(i.item_id); - if let TypeAliasItem(alias) = &*i.kind + if let TypeAliasItem(alias) = &i.inner.kind && let Some(did) = alias.type_.def_id(self.cache) { self.items.insert(ItemId::DefId(did)); diff --git a/src/librustdoc/passes/propagate_doc_cfg.rs b/src/librustdoc/passes/propagate_doc_cfg.rs index 5aa6a5ee6045b..6be51dd156066 100644 --- a/src/librustdoc/passes/propagate_doc_cfg.rs +++ b/src/librustdoc/passes/propagate_doc_cfg.rs @@ -31,7 +31,7 @@ impl<'a, 'tcx> CfgPropagator<'a, 'tcx> { // Some items need to merge their attributes with their parents' otherwise a few of them // (mostly `cfg` ones) will be missing. fn merge_with_parent_attributes(&mut self, item: &mut Item) { - let check_parent = match &*item.kind { + let check_parent = match &item.kind { // impl blocks can be in different modules with different cfg and we need to get them // as well. ItemKind::ImplItem(_) => false, diff --git a/src/librustdoc/passes/strip_aliased_non_local.rs b/src/librustdoc/passes/strip_aliased_non_local.rs index e1dd2d3af0feb..6078ab3652891 100644 --- a/src/librustdoc/passes/strip_aliased_non_local.rs +++ b/src/librustdoc/passes/strip_aliased_non_local.rs @@ -23,7 +23,7 @@ struct AliasedNonLocalStripper<'tcx> { impl<'tcx> DocFolder for AliasedNonLocalStripper<'tcx> { fn fold_item(&mut self, i: Item) -> Option { - Some(match *i.kind { + Some(match i.kind { clean::TypeAliasItem(..) => { let mut stripper = NonLocalStripper { tcx: self.tcx }; // don't call `fold_item` as that could strip the type-alias it-self diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs index 86f14ddbe8506..7c5fbac94e4fc 100644 --- a/src/librustdoc/passes/strip_hidden.rs +++ b/src/librustdoc/passes/strip_hidden.rs @@ -89,7 +89,7 @@ impl<'a, 'tcx> Stripper<'a, 'tcx> { impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> { fn fold_item(&mut self, i: Item) -> Option { let has_doc_hidden = i.is_doc_hidden(); - let is_impl_or_exported_macro = match *i.kind { + let is_impl_or_exported_macro = match i.kind { clean::ImplItem(..) => true, // If the macro has the `#[macro_export]` attribute, it means it's accessible at the // crate level so it should be handled differently. @@ -138,7 +138,7 @@ impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> { // module it's defined in. Both of these are marked "stripped," and // not included in the final docs, but since they still have an effect // on the final doc, cannot be completely removed from the Clean IR. - match *i.kind { + match i.kind { clean::StructFieldItem(..) | clean::ModuleItem(..) | clean::VariantItem(..) => { // We need to recurse into stripped modules to // strip things like impl methods but when doing so diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs index 3f706ac951f25..a85428f8742a0 100644 --- a/src/librustdoc/passes/stripper.rs +++ b/src/librustdoc/passes/stripper.rs @@ -39,7 +39,7 @@ fn is_item_reachable( impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> { fn fold_item(&mut self, i: Item) -> Option { - match *i.kind { + match i.kind { clean::StrippedItem(..) => { // We need to recurse into stripped modules to strip things // like impl methods but when doing so we must not add any @@ -130,7 +130,7 @@ impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> { clean::KeywordItem => {} } - let fastreturn = match *i.kind { + let fastreturn = match i.kind { // nothing left to do for traits (don't want to filter their // methods out, visibility controlled by the trait) clean::TraitItem(..) => true, @@ -195,7 +195,7 @@ impl<'a> ImplStripper<'a, '_> { impl<'a> DocFolder for ImplStripper<'a, '_> { fn fold_item(&mut self, i: Item) -> Option { - if let clean::ImplItem(ref imp) = *i.kind { + if let clean::ImplItem(ref imp) = i.kind { // Impl blocks can be skipped if they are: empty; not a trait impl; and have no // documentation. // @@ -272,7 +272,7 @@ impl<'tcx> ImportStripper<'tcx> { impl<'tcx> DocFolder for ImportStripper<'tcx> { fn fold_item(&mut self, i: Item) -> Option { - match *i.kind { + match &i.kind { clean::ImportItem(imp) if !self.document_hidden && self.import_should_be_hidden(&i, &imp) => { diff --git a/src/librustdoc/visit.rs b/src/librustdoc/visit.rs index 430bbe991eaaf..7fb0a32cc9495 100644 --- a/src/librustdoc/visit.rs +++ b/src/librustdoc/visit.rs @@ -48,8 +48,8 @@ pub(crate) trait DocVisitor: Sized { /// don't override! fn visit_item_recur(&mut self, item: &Item) { - match &*item.kind { - StrippedItem(i) => self.visit_inner_recur(i), + match &item.kind { + StrippedItem(i) => self.visit_inner_recur(&*i), _ => self.visit_inner_recur(&item.kind), } } From 3de6838238dd72004acf0e6b3f158837952c1dc3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 8 Sep 2024 08:30:28 +0200 Subject: [PATCH 046/189] add some FIXME(const-hack) --- library/core/src/option.rs | 2 +- library/core/src/result.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 50cb22b7eb3f5..b62eec1897b09 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1894,7 +1894,7 @@ impl Option<&T> { where T: Copy, { - // FIXME: this implementation, which sidesteps using `Option::map` since it's not const + // FIXME(const-hack): this implementation, which sidesteps using `Option::map` since it's not const // ready yet, should be reverted when possible to avoid code repetition match self { Some(&v) => Some(v), diff --git a/library/core/src/result.rs b/library/core/src/result.rs index a7fd95e007982..5b6a81c8dae91 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1540,7 +1540,7 @@ impl Result<&T, E> { where T: Copy, { - // FIXME: this implementation, which sidesteps using `Result::map` since it's not const + // FIXME(const-hack): this implementation, which sidesteps using `Result::map` since it's not const // ready yet, should be reverted when possible to avoid code repetition match self { Ok(&v) => Ok(v), From 7f9a541059b1bf5322e94668792e933a48975917 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 8 Sep 2024 08:45:41 +0200 Subject: [PATCH 047/189] remove pointless rustc_const_unstable on trait impls --- library/core/src/ptr/alignment.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs index 19fe03d57cc0a..834cec9dcfc26 100644 --- a/library/core/src/ptr/alignment.rs +++ b/library/core/src/ptr/alignment.rs @@ -199,7 +199,6 @@ impl From for usize { } } -#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] #[unstable(feature = "ptr_alignment_type", issue = "102070")] impl cmp::Ord for Alignment { #[inline] @@ -208,7 +207,6 @@ impl cmp::Ord for Alignment { } } -#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] #[unstable(feature = "ptr_alignment_type", issue = "102070")] impl cmp::PartialOrd for Alignment { #[inline] From f98ca32b0a594b1ee59e22e1927198ed03eb0ce7 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sat, 7 Sep 2024 17:57:47 +0200 Subject: [PATCH 048/189] Fix linking error when compiling for 32-bit watchOS In https://github.com/rust-lang/rust/pull/124748, I mistakenly conflated "not SjLj" to mean "ARM EHABI", which isn't true, watchOS armv7k (specifically only that architecture) uses a third unwinding method called "DWARF CFI". --- library/std/src/sys/personality/dwarf/eh.rs | 6 +++--- library/std/src/sys/personality/gcc.rs | 13 +++++++------ library/unwind/src/libunwind.rs | 13 ++++++++----- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/library/std/src/sys/personality/dwarf/eh.rs b/library/std/src/sys/personality/dwarf/eh.rs index c37c3e442aea6..778d8686f023e 100644 --- a/library/std/src/sys/personality/dwarf/eh.rs +++ b/library/std/src/sys/personality/dwarf/eh.rs @@ -54,10 +54,10 @@ pub enum EHAction { Terminate, } -/// 32-bit Apple ARM uses SjLj exceptions, except for watchOS. +/// 32-bit ARM Darwin platforms uses SjLj exceptions. /// -/// I.e. iOS and tvOS, as those are the only Apple OSes that used 32-bit ARM -/// devices. +/// The exception is watchOS armv7k (specifically that subarchitecture), which +/// instead uses DWARF Call Frame Information (CFI) unwinding. /// /// pub const USING_SJLJ_EXCEPTIONS: bool = diff --git a/library/std/src/sys/personality/gcc.rs b/library/std/src/sys/personality/gcc.rs index f6b1844e153fd..ad596ecff65d5 100644 --- a/library/std/src/sys/personality/gcc.rs +++ b/library/std/src/sys/personality/gcc.rs @@ -95,14 +95,15 @@ const UNWIND_DATA_REG: (i32, i32) = (4, 5); // a0, a1 cfg_if::cfg_if! { if #[cfg(all( - target_arch = "arm", - not(all(target_vendor = "apple", not(target_os = "watchos"))), - not(target_os = "netbsd"), - ))] { + target_arch = "arm", + not(target_vendor = "apple"), + not(target_os = "netbsd"), + ))] { /// personality fn called by [ARM EHABI][armeabi-eh] /// - /// Apple 32-bit ARM (but not watchOS) uses the default routine instead - /// since it uses "setjmp-longjmp" unwinding. + /// 32-bit ARM on iOS/tvOS/watchOS does not use ARM EHABI, it uses + /// either "setjmp-longjmp" unwinding or DWARF CFI unwinding, which is + /// handled by the default routine. /// /// [armeabi-eh]: https://web.archive.org/web/20190728160938/https://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf #[lang = "eh_personality"] diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs index e5e28f32e4dbf..1d856ce1879a5 100644 --- a/library/unwind/src/libunwind.rs +++ b/library/unwind/src/libunwind.rs @@ -33,10 +33,10 @@ pub const unwinder_private_data_size: usize = 2; #[cfg(all(target_arch = "x86_64", target_os = "windows"))] pub const unwinder_private_data_size: usize = 6; -#[cfg(all(target_arch = "arm", not(all(target_vendor = "apple", not(target_os = "watchos")))))] +#[cfg(all(target_arch = "arm", not(target_vendor = "apple")))] pub const unwinder_private_data_size: usize = 20; -#[cfg(all(target_arch = "arm", all(target_vendor = "apple", not(target_os = "watchos"))))] +#[cfg(all(target_arch = "arm", target_vendor = "apple"))] pub const unwinder_private_data_size: usize = 5; #[cfg(all(target_arch = "aarch64", target_pointer_width = "64", not(target_os = "windows")))] @@ -123,8 +123,11 @@ extern "C" { } cfg_if::cfg_if! { -if #[cfg(any(all(target_vendor = "apple", not(target_os = "watchos")), target_os = "netbsd", not(target_arch = "arm")))] { +if #[cfg(any(target_vendor = "apple", target_os = "netbsd", not(target_arch = "arm")))] { // Not ARM EHABI + // + // 32-bit ARM on iOS/tvOS/watchOS use either DWARF/Compact unwinding or + // "setjmp-longjmp" / SjLj unwinding. #[repr(C)] #[derive(Copy, Clone, PartialEq)] pub enum _Unwind_Action { @@ -259,8 +262,8 @@ if #[cfg(any(all(target_vendor = "apple", not(target_os = "watchos")), target_os cfg_if::cfg_if! { if #[cfg(all(target_vendor = "apple", not(target_os = "watchos"), target_arch = "arm"))] { - // 32-bit ARM Apple (except for watchOS) uses SjLj and does not provide - // _Unwind_Backtrace() + // 32-bit ARM Apple (except for watchOS armv7k specifically) uses SjLj and + // does not provide _Unwind_Backtrace() extern "C-unwind" { pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code; } From ec11001f2b4b3fae70fc118ffaf533af0716d585 Mon Sep 17 00:00:00 2001 From: Florian Schmiderer Date: Fri, 6 Sep 2024 23:35:18 +0200 Subject: [PATCH 049/189] run-make-support: Add llvm-pdbutil --- .../src/external_deps/llvm.rs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/tools/run-make-support/src/external_deps/llvm.rs b/src/tools/run-make-support/src/external_deps/llvm.rs index 2522c4aeb9365..16c4251998fb2 100644 --- a/src/tools/run-make-support/src/external_deps/llvm.rs +++ b/src/tools/run-make-support/src/external_deps/llvm.rs @@ -110,6 +110,13 @@ pub struct LlvmDwarfdump { cmd: Command, } +/// A `llvm-pdbutil` invocation builder. +#[derive(Debug)] +#[must_use] +pub struct LlvmPdbutil { + cmd: Command, +} + crate::macros::impl_common_helpers!(LlvmReadobj); crate::macros::impl_common_helpers!(LlvmProfdata); crate::macros::impl_common_helpers!(LlvmFilecheck); @@ -118,6 +125,7 @@ crate::macros::impl_common_helpers!(LlvmAr); crate::macros::impl_common_helpers!(LlvmNm); crate::macros::impl_common_helpers!(LlvmBcanalyzer); crate::macros::impl_common_helpers!(LlvmDwarfdump); +crate::macros::impl_common_helpers!(LlvmPdbutil); /// Generate the path to the bin directory of LLVM. #[must_use] @@ -360,3 +368,19 @@ impl LlvmDwarfdump { self } } + +impl LlvmPdbutil { + /// Construct a new `llvm-pdbutil` invocation. This assumes that `llvm-pdbutil` is available + /// at `$LLVM_BIN_DIR/llvm-pdbutil`. + pub fn new() -> Self { + let llvm_pdbutil = llvm_bin_dir().join("llvm-pdbutil"); + let cmd = Command::new(llvm_pdbutil); + Self { cmd } + } + + /// Provide an input file. + pub fn input>(&mut self, path: P) -> &mut Self { + self.cmd.arg(path.as_ref()); + self + } +} From 9df7680ecf698bf7087616b595774ee1023d3c7b Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 30 Aug 2024 19:48:16 +0300 Subject: [PATCH 050/189] detect incompatible CI LLVM options more precisely Previously, the logic here was simply checking whether the option was set in `config.toml`. This approach was not manageable in our CI runners as we set so many options in config.toml. In reality, those values are not incompatible since they are usually the same value used to generate the CI llvm. Now, the new logic compares the configuration values with the values used to generate the CI llvm, so we get more precise results and make the process more manageable. Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/config.rs | 112 +++++++++++++++++++++++- src/bootstrap/src/core/download.rs | 31 ++++++- 2 files changed, 140 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 52c1c462788af..57c260a062486 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1216,13 +1216,19 @@ impl Config { } } + pub(crate) fn get_builder_toml(&self, build_name: &str) -> Result { + let builder_config_path = + self.out.join(self.build.triple).join(build_name).join(BUILDER_CONFIG_FILENAME); + Self::get_toml(&builder_config_path) + } + #[cfg(test)] - fn get_toml(_: &Path) -> Result { + pub(crate) fn get_toml(_: &Path) -> Result { Ok(TomlConfig::default()) } #[cfg(not(test))] - fn get_toml(file: &Path) -> Result { + pub(crate) fn get_toml(file: &Path) -> Result { let contents = t!(fs::read_to_string(file), format!("config file {} not found", file.display())); // Deserialize to Value and then TomlConfig to prevent the Deserialize impl of @@ -2846,6 +2852,108 @@ impl Config { } } +/// Compares the current `Llvm` options against those in the CI LLVM builder and detects any incompatible options. +/// It does this by destructuring the `Llvm` instance to make sure every `Llvm` field is covered and not missing. +pub(crate) fn check_incompatible_options_for_ci_llvm( + current_config_toml: TomlConfig, + ci_config_toml: TomlConfig, +) -> Result<(), String> { + macro_rules! err { + ($current:expr, $expected:expr) => { + if let Some(current) = &$current { + if Some(current) != $expected.as_ref() { + return Err(format!( + "ERROR: Setting `llvm.{}` is incompatible with `llvm.download-ci-llvm`. \ + Current value: {:?}, Expected value(s): {}{:?}", + stringify!($expected).replace("_", "-"), + $current, + if $expected.is_some() { "None/" } else { "" }, + $expected, + )); + }; + }; + }; + } + + macro_rules! warn { + ($current:expr, $expected:expr) => { + if let Some(current) = &$current { + if Some(current) != $expected.as_ref() { + println!( + "WARNING: `llvm.{}` has no effect with `llvm.download-ci-llvm`. \ + Current value: {:?}, Expected value(s): {}{:?}", + stringify!($expected).replace("_", "-"), + $current, + if $expected.is_some() { "None/" } else { "" }, + $expected, + ); + }; + }; + }; + } + + let (Some(current_llvm_config), Some(ci_llvm_config)) = + (current_config_toml.llvm, ci_config_toml.llvm) + else { + return Ok(()); + }; + + let Llvm { + optimize, + thin_lto, + release_debuginfo, + assertions: _, + tests: _, + plugins, + ccache: _, + static_libstdcpp: _, + libzstd, + ninja: _, + targets, + experimental_targets, + link_jobs: _, + link_shared: _, + version_suffix, + clang_cl, + cflags, + cxxflags, + ldflags, + use_libcxx, + use_linker, + allow_old_toolchain, + polly, + clang, + enable_warnings, + download_ci_llvm: _, + build_config, + enzyme, + } = ci_llvm_config; + + err!(current_llvm_config.optimize, optimize); + err!(current_llvm_config.thin_lto, thin_lto); + err!(current_llvm_config.release_debuginfo, release_debuginfo); + err!(current_llvm_config.libzstd, libzstd); + err!(current_llvm_config.targets, targets); + err!(current_llvm_config.experimental_targets, experimental_targets); + err!(current_llvm_config.clang_cl, clang_cl); + err!(current_llvm_config.version_suffix, version_suffix); + err!(current_llvm_config.cflags, cflags); + err!(current_llvm_config.cxxflags, cxxflags); + err!(current_llvm_config.ldflags, ldflags); + err!(current_llvm_config.use_libcxx, use_libcxx); + err!(current_llvm_config.use_linker, use_linker); + err!(current_llvm_config.allow_old_toolchain, allow_old_toolchain); + err!(current_llvm_config.polly, polly); + err!(current_llvm_config.clang, clang); + err!(current_llvm_config.build_config, build_config); + err!(current_llvm_config.plugins, plugins); + err!(current_llvm_config.enzyme, enzyme); + + warn!(current_llvm_config.enable_warnings, enable_warnings); + + Ok(()) +} + /// Compares the current Rust options against those in the CI rustc builder and detects any incompatible options. /// It does this by destructuring the `Rust` instance to make sure every `Rust` field is covered and not missing. fn check_incompatible_options_for_ci_rustc( diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index 3f5ec70b9abc9..25493c1f55b6c 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -316,6 +316,7 @@ impl Config { let mut tar = tar::Archive::new(decompressor); let is_ci_rustc = dst.ends_with("ci-rustc"); + let is_ci_llvm = dst.ends_with("ci-llvm"); // `compile::Sysroot` needs to know the contents of the `rustc-dev` tarball to avoid adding // it to the sysroot unless it was explicitly requested. But parsing the 100 MB tarball is slow. @@ -332,7 +333,9 @@ impl Config { let mut short_path = t!(original_path.strip_prefix(directory_prefix)); let is_builder_config = short_path.to_str() == Some(BUILDER_CONFIG_FILENAME); - if !(short_path.starts_with(pattern) || (is_ci_rustc && is_builder_config)) { + if !(short_path.starts_with(pattern) + || ((is_ci_rustc || is_ci_llvm) && is_builder_config)) + { continue; } short_path = short_path.strip_prefix(pattern).unwrap_or(short_path); @@ -717,17 +720,43 @@ download-rustc = false #[cfg(not(feature = "bootstrap-self-test"))] pub(crate) fn maybe_download_ci_llvm(&self) { + use build_helper::exit; + use crate::core::build_steps::llvm::detect_llvm_sha; + use crate::core::config::check_incompatible_options_for_ci_llvm; if !self.llvm_from_ci { return; } + let llvm_root = self.ci_llvm_root(); let llvm_stamp = llvm_root.join(".llvm-stamp"); let llvm_sha = detect_llvm_sha(self, self.rust_info.is_managed_git_subrepository()); let key = format!("{}{}", llvm_sha, self.llvm_assertions); if program_out_of_date(&llvm_stamp, &key) && !self.dry_run() { self.download_ci_llvm(&llvm_sha); + + if let Some(config_path) = &self.config { + let current_config_toml = Self::get_toml(config_path).unwrap(); + + match self.get_builder_toml("ci-llvm") { + Ok(ci_config_toml) => { + check_incompatible_options_for_ci_llvm(current_config_toml, ci_config_toml) + .unwrap(); + } + Err(e) if e.to_string().contains("unknown field") => { + println!( + "WARNING: CI rustc has some fields that are no longer supported in bootstrap; download-rustc will be disabled." + ); + println!("HELP: Consider rebasing to a newer commit if available."); + } + Err(e) => { + eprintln!("ERROR: Failed to parse CI LLVM config.toml: {e}"); + exit!(2); + } + }; + }; + if self.should_fix_bins_and_dylibs() { for entry in t!(fs::read_dir(llvm_root.join("bin"))) { self.fix_bin_or_dylib(&t!(entry).path()); From 23df3a9eeb01d3a50b2ce02db9f69e1d3e37caec Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 30 Aug 2024 19:50:52 +0300 Subject: [PATCH 051/189] remove `check_ci_llvm` usage Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/config.rs | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 57c260a062486..824f65cb6b8e5 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1914,30 +1914,6 @@ impl Config { "HELP: To use `llvm.libzstd` for LLVM/LLD builds, set `download-ci-llvm` option to false." ); } - - // None of the LLVM options, except assertions, are supported - // when using downloaded LLVM. We could just ignore these but - // that's potentially confusing, so force them to not be - // explicitly set. The defaults and CI defaults don't - // necessarily match but forcing people to match (somewhat - // arbitrary) CI configuration locally seems bad/hard. - check_ci_llvm!(optimize_toml); - check_ci_llvm!(thin_lto); - check_ci_llvm!(release_debuginfo); - check_ci_llvm!(targets); - check_ci_llvm!(experimental_targets); - check_ci_llvm!(clang_cl); - check_ci_llvm!(version_suffix); - check_ci_llvm!(cflags); - check_ci_llvm!(cxxflags); - check_ci_llvm!(ldflags); - check_ci_llvm!(use_libcxx); - check_ci_llvm!(use_linker); - check_ci_llvm!(allow_old_toolchain); - check_ci_llvm!(polly); - check_ci_llvm!(clang); - check_ci_llvm!(build_config); - check_ci_llvm!(plugins); } // NOTE: can never be hit when downloading from CI, since we call `check_ci_llvm!(thin_lto)` above. From ea34bb045264466c6b3bc63caf64264de219ad77 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 30 Aug 2024 19:56:58 +0300 Subject: [PATCH 052/189] print incompatible options even if we don't download Signed-off-by: onur-ozkan --- src/bootstrap/src/core/download.rs | 41 +++++++++++++++--------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index 25493c1f55b6c..d8b39ac0b6dac 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -736,27 +736,6 @@ download-rustc = false if program_out_of_date(&llvm_stamp, &key) && !self.dry_run() { self.download_ci_llvm(&llvm_sha); - if let Some(config_path) = &self.config { - let current_config_toml = Self::get_toml(config_path).unwrap(); - - match self.get_builder_toml("ci-llvm") { - Ok(ci_config_toml) => { - check_incompatible_options_for_ci_llvm(current_config_toml, ci_config_toml) - .unwrap(); - } - Err(e) if e.to_string().contains("unknown field") => { - println!( - "WARNING: CI rustc has some fields that are no longer supported in bootstrap; download-rustc will be disabled." - ); - println!("HELP: Consider rebasing to a newer commit if available."); - } - Err(e) => { - eprintln!("ERROR: Failed to parse CI LLVM config.toml: {e}"); - exit!(2); - } - }; - }; - if self.should_fix_bins_and_dylibs() { for entry in t!(fs::read_dir(llvm_root.join("bin"))) { self.fix_bin_or_dylib(&t!(entry).path()); @@ -789,6 +768,26 @@ download-rustc = false t!(fs::write(llvm_stamp, key)); } + + if let Some(config_path) = &self.config { + let current_config_toml = Self::get_toml(config_path).unwrap(); + + match self.get_builder_toml("ci-llvm") { + Ok(ci_config_toml) => { + t!(check_incompatible_options_for_ci_llvm(current_config_toml, ci_config_toml)); + } + Err(e) if e.to_string().contains("unknown field") => { + println!( + "WARNING: CI LLVM has some fields that are no longer supported in bootstrap; download-ci-llvm will be disabled." + ); + println!("HELP: Consider rebasing to a newer commit if available."); + } + Err(e) => { + eprintln!("ERROR: Failed to parse CI LLVM config.toml: {e}"); + exit!(2); + } + }; + }; } #[cfg(not(feature = "bootstrap-self-test"))] From 018ed9abb92496373da0dcf594767846eaeec4e3 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 30 Aug 2024 20:01:05 +0300 Subject: [PATCH 053/189] fix llvm ThinLTO behaviour Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/config.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 824f65cb6b8e5..327cf6c575a57 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1916,8 +1916,7 @@ impl Config { } } - // NOTE: can never be hit when downloading from CI, since we call `check_ci_llvm!(thin_lto)` above. - if config.llvm_thin_lto && link_shared.is_none() { + if !config.llvm_from_ci && config.llvm_thin_lto && link_shared.is_none() { // If we're building with ThinLTO on, by default we want to link // to LLVM shared, to avoid re-doing ThinLTO (which happens in // the link step) with each stage. From 13e16a910144492ed3896fb22c9c980bc474b174 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 30 Aug 2024 20:05:55 +0300 Subject: [PATCH 054/189] use `Config::get_builder_toml` for ci-rustc config parsing Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/config.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 327cf6c575a57..8f7195aba9a8c 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -2355,10 +2355,7 @@ impl Config { self.download_ci_rustc(commit); if let Some(config_path) = &self.config { - let builder_config_path = - self.out.join(self.build.triple).join("ci-rustc").join(BUILDER_CONFIG_FILENAME); - - let ci_config_toml = match Self::get_toml(&builder_config_path) { + let ci_config_toml = match self.get_builder_toml("ci-rustc") { Ok(ci_config_toml) => ci_config_toml, Err(e) if e.to_string().contains("unknown field") => { println!("WARNING: CI rustc has some fields that are no longer supported in bootstrap; download-rustc will be disabled."); @@ -2366,7 +2363,7 @@ impl Config { return None; }, Err(e) => { - eprintln!("ERROR: Failed to parse CI rustc config at '{}': {e}", builder_config_path.display()); + eprintln!("ERROR: Failed to parse CI rustc config.toml: {e}"); exit!(2); }, }; @@ -2829,6 +2826,7 @@ impl Config { /// Compares the current `Llvm` options against those in the CI LLVM builder and detects any incompatible options. /// It does this by destructuring the `Llvm` instance to make sure every `Llvm` field is covered and not missing. +#[cfg(not(feature = "bootstrap-self-test"))] pub(crate) fn check_incompatible_options_for_ci_llvm( current_config_toml: TomlConfig, ci_config_toml: TomlConfig, From 7b8cbe4f1ca1d870b2bb2196d8c3a4bc2a978f55 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 30 Aug 2024 22:56:11 +0300 Subject: [PATCH 055/189] handle dry-run mode in `Config::get_builder_toml` Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/config.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 8f7195aba9a8c..68b42305fdcc8 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1217,6 +1217,10 @@ impl Config { } pub(crate) fn get_builder_toml(&self, build_name: &str) -> Result { + if self.dry_run() { + return Ok(TomlConfig::default()); + } + let builder_config_path = self.out.join(self.build.triple).join(build_name).join(BUILDER_CONFIG_FILENAME); Self::get_toml(&builder_config_path) From f7b4f4a73bcaa2987fddfa86c240a497780c88c8 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 8 Sep 2024 09:24:06 +0200 Subject: [PATCH 056/189] Option, Result: put the &mut variants of 'copied' under the same feature as the '&' variants --- library/core/src/option.rs | 2 +- library/core/src/result.rs | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index b62eec1897b09..80598b8852955 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1942,7 +1942,7 @@ impl Option<&mut T> { /// ``` #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "copied", since = "1.35.0")] - #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + #[rustc_const_unstable(feature = "const_option", issue = "67441")] pub const fn copied(self) -> Option where T: Copy, diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 5b6a81c8dae91..02f6f783b512c 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1585,11 +1585,17 @@ impl Result<&mut T, E> { /// ``` #[inline] #[stable(feature = "result_copied", since = "1.59.0")] - pub fn copied(self) -> Result + #[rustc_const_unstable(feature = "const_result", issue = "82814")] + pub const fn copied(self) -> Result where T: Copy, { - self.map(|&mut t| t) + // FIXME(const-hack): this implementation, which sidesteps using `Result::map` since it's not const + // ready yet, should be reverted when possible to avoid code repetition + match self { + Ok(&mut v) => Ok(v), + Err(e) => Err(e), + } } /// Maps a `Result<&mut T, E>` to a `Result` by cloning the contents of the From fa60ea7d388890169683ad397aba1edf4979738a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 28 Aug 2024 17:39:09 +0200 Subject: [PATCH 057/189] interpret: remove Readable trait, we can use Projectable instead --- .../src/interpret/discriminant.rs | 4 +- .../rustc_const_eval/src/interpret/mod.rs | 2 +- .../rustc_const_eval/src/interpret/operand.rs | 40 ++++--------------- .../rustc_const_eval/src/interpret/place.rs | 14 +++---- src/tools/miri/src/helpers.rs | 8 ++-- 5 files changed, 21 insertions(+), 47 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs index 0008a15722bde..de93ed85704b5 100644 --- a/compiler/rustc_const_eval/src/interpret/discriminant.rs +++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs @@ -7,7 +7,7 @@ use rustc_target::abi::{self, TagEncoding, VariantIdx, Variants}; use tracing::{instrument, trace}; use super::{ - err_ub, throw_ub, ImmTy, InterpCx, InterpResult, Machine, Readable, Scalar, Writeable, + err_ub, throw_ub, ImmTy, InterpCx, InterpResult, Machine, Projectable, Scalar, Writeable, }; impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { @@ -60,7 +60,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { #[instrument(skip(self), level = "trace")] pub fn read_discriminant( &self, - op: &impl Readable<'tcx, M::Provenance>, + op: &impl Projectable<'tcx, M::Provenance>, ) -> InterpResult<'tcx, VariantIdx> { let ty = op.layout().ty; trace!("read_discriminant_value {:#?}", op.layout()); diff --git a/compiler/rustc_const_eval/src/interpret/mod.rs b/compiler/rustc_const_eval/src/interpret/mod.rs index 511756e3f86c9..c1e46cc3a15b4 100644 --- a/compiler/rustc_const_eval/src/interpret/mod.rs +++ b/compiler/rustc_const_eval/src/interpret/mod.rs @@ -33,7 +33,7 @@ pub(crate) use self::intrinsics::eval_nullary_intrinsic; pub use self::machine::{compile_time_machine, AllocMap, Machine, MayLeak, ReturnAction}; pub use self::memory::{AllocKind, AllocRef, AllocRefMut, FnVal, Memory, MemoryKind}; use self::operand::Operand; -pub use self::operand::{ImmTy, Immediate, OpTy, Readable}; +pub use self::operand::{ImmTy, Immediate, OpTy}; pub use self::place::{MPlaceTy, MemPlaceMeta, PlaceTy, Writeable}; use self::place::{MemPlace, Place}; pub use self::projection::{OffsetMode, Projectable}; diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 9a8ccaa7cc5ca..4e6159080056e 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -490,32 +490,6 @@ impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for OpTy<'tcx, Prov> { } } -/// The `Readable` trait describes interpreter values that one can read from. -pub trait Readable<'tcx, Prov: Provenance>: Projectable<'tcx, Prov> { - fn as_mplace_or_imm(&self) -> Either, ImmTy<'tcx, Prov>>; -} - -impl<'tcx, Prov: Provenance> Readable<'tcx, Prov> for OpTy<'tcx, Prov> { - #[inline(always)] - fn as_mplace_or_imm(&self) -> Either, ImmTy<'tcx, Prov>> { - self.as_mplace_or_imm() - } -} - -impl<'tcx, Prov: Provenance> Readable<'tcx, Prov> for MPlaceTy<'tcx, Prov> { - #[inline(always)] - fn as_mplace_or_imm(&self) -> Either, ImmTy<'tcx, Prov>> { - Left(self.clone()) - } -} - -impl<'tcx, Prov: Provenance> Readable<'tcx, Prov> for ImmTy<'tcx, Prov> { - #[inline(always)] - fn as_mplace_or_imm(&self) -> Either, ImmTy<'tcx, Prov>> { - Right(self.clone()) - } -} - impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// Try reading an immediate in memory; this is interesting particularly for `ScalarPair`. /// Returns `None` if the layout does not permit loading this as a value. @@ -588,9 +562,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// ConstProp needs it, though. pub fn read_immediate_raw( &self, - src: &impl Readable<'tcx, M::Provenance>, + src: &impl Projectable<'tcx, M::Provenance>, ) -> InterpResult<'tcx, Either, ImmTy<'tcx, M::Provenance>>> { - Ok(match src.as_mplace_or_imm() { + Ok(match src.to_op(self)?.as_mplace_or_imm() { Left(ref mplace) => { if let Some(val) = self.read_immediate_from_mplace_raw(mplace)? { Right(val) @@ -608,7 +582,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { #[inline(always)] pub fn read_immediate( &self, - op: &impl Readable<'tcx, M::Provenance>, + op: &impl Projectable<'tcx, M::Provenance>, ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> { if !matches!( op.layout().abi, @@ -627,7 +601,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// Read a scalar from a place pub fn read_scalar( &self, - op: &impl Readable<'tcx, M::Provenance>, + op: &impl Projectable<'tcx, M::Provenance>, ) -> InterpResult<'tcx, Scalar> { Ok(self.read_immediate(op)?.to_scalar()) } @@ -638,21 +612,21 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// Read a pointer from a place. pub fn read_pointer( &self, - op: &impl Readable<'tcx, M::Provenance>, + op: &impl Projectable<'tcx, M::Provenance>, ) -> InterpResult<'tcx, Pointer>> { self.read_scalar(op)?.to_pointer(self) } /// Read a pointer-sized unsigned integer from a place. pub fn read_target_usize( &self, - op: &impl Readable<'tcx, M::Provenance>, + op: &impl Projectable<'tcx, M::Provenance>, ) -> InterpResult<'tcx, u64> { self.read_scalar(op)?.to_target_usize(self) } /// Read a pointer-sized signed integer from a place. pub fn read_target_isize( &self, - op: &impl Readable<'tcx, M::Provenance>, + op: &impl Projectable<'tcx, M::Provenance>, ) -> InterpResult<'tcx, i64> { self.read_scalar(op)?.to_target_isize(self) } diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 840f7986c6e0a..224fac2f22045 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -15,7 +15,7 @@ use tracing::{instrument, trace}; use super::{ alloc_range, mir_assign_valid_types, AllocRef, AllocRefMut, CheckAlignMsg, CtfeProvenance, ImmTy, Immediate, InterpCx, InterpResult, Machine, MemoryKind, Misalignment, OffsetMode, OpTy, - Operand, Pointer, Projectable, Provenance, Readable, Scalar, + Operand, Pointer, Projectable, Provenance, Scalar, }; #[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)] @@ -436,7 +436,7 @@ where #[instrument(skip(self), level = "trace")] pub fn deref_pointer( &self, - src: &impl Readable<'tcx, M::Provenance>, + src: &impl Projectable<'tcx, M::Provenance>, ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> { if src.layout().ty.is_box() { // Derefer should have removed all Box derefs. @@ -768,7 +768,7 @@ where #[inline(always)] pub(super) fn copy_op_no_dest_validation( &mut self, - src: &impl Readable<'tcx, M::Provenance>, + src: &impl Projectable<'tcx, M::Provenance>, dest: &impl Writeable<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { self.copy_op_inner( @@ -781,7 +781,7 @@ where #[inline(always)] pub fn copy_op_allow_transmute( &mut self, - src: &impl Readable<'tcx, M::Provenance>, + src: &impl Projectable<'tcx, M::Provenance>, dest: &impl Writeable<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { self.copy_op_inner( @@ -794,7 +794,7 @@ where #[inline(always)] pub fn copy_op( &mut self, - src: &impl Readable<'tcx, M::Provenance>, + src: &impl Projectable<'tcx, M::Provenance>, dest: &impl Writeable<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { self.copy_op_inner( @@ -808,7 +808,7 @@ where #[instrument(skip(self), level = "trace")] fn copy_op_inner( &mut self, - src: &impl Readable<'tcx, M::Provenance>, + src: &impl Projectable<'tcx, M::Provenance>, dest: &impl Writeable<'tcx, M::Provenance>, allow_transmute: bool, validate_dest: bool, @@ -843,7 +843,7 @@ where #[instrument(skip(self), level = "trace")] fn copy_op_no_validate( &mut self, - src: &impl Readable<'tcx, M::Provenance>, + src: &impl Projectable<'tcx, M::Provenance>, dest: &impl Writeable<'tcx, M::Provenance>, allow_transmute: bool, ) -> InterpResult<'tcx> { diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index a546ad20fef98..cba99c0bd7a81 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -869,7 +869,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { /// Dereference a pointer operand to a place using `layout` instead of the pointer's declared type fn deref_pointer_as( &self, - op: &impl Readable<'tcx, Provenance>, + op: &impl Projectable<'tcx, Provenance>, layout: TyAndLayout<'tcx>, ) -> InterpResult<'tcx, MPlaceTy<'tcx>> { let this = self.eval_context_ref(); @@ -880,7 +880,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { /// Calculates the MPlaceTy given the offset and layout of an access on an operand fn deref_pointer_and_offset( &self, - op: &impl Readable<'tcx, Provenance>, + op: &impl Projectable<'tcx, Provenance>, offset: u64, base_layout: TyAndLayout<'tcx>, value_layout: TyAndLayout<'tcx>, @@ -897,7 +897,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn deref_pointer_and_read( &self, - op: &impl Readable<'tcx, Provenance>, + op: &impl Projectable<'tcx, Provenance>, offset: u64, base_layout: TyAndLayout<'tcx>, value_layout: TyAndLayout<'tcx>, @@ -909,7 +909,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn deref_pointer_and_write( &mut self, - op: &impl Readable<'tcx, Provenance>, + op: &impl Projectable<'tcx, Provenance>, offset: u64, value: impl Into, base_layout: TyAndLayout<'tcx>, From 8ad808db7e73bd445216ea004fd655f86758ee08 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 28 Aug 2024 17:42:05 +0200 Subject: [PATCH 058/189] interpret: make Writeable trait about a to_place operation --- .../rustc_const_eval/src/interpret/operand.rs | 2 +- .../rustc_const_eval/src/interpret/place.rs | 29 ++++++++----------- 2 files changed, 13 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 4e6159080056e..d9da0b3e00acb 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -691,7 +691,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { match place.as_mplace_or_local() { Left(mplace) => Ok(mplace.into()), - Right((local, offset, locals_addr)) => { + Right((local, offset, locals_addr, _)) => { debug_assert!(place.layout.is_sized()); // only sized locals can ever be `Place::Local`. debug_assert_eq!(locals_addr, self.frame().locals_addr()); let base = self.local_to_op(local, None)?; diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 224fac2f22045..45695186ff0f2 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -231,10 +231,12 @@ impl<'tcx, Prov: Provenance> PlaceTy<'tcx, Prov> { #[inline(always)] pub fn as_mplace_or_local( &self, - ) -> Either, (mir::Local, Option, usize)> { + ) -> Either, (mir::Local, Option, usize, TyAndLayout<'tcx>)> { match self.place { Place::Ptr(mplace) => Left(MPlaceTy { mplace, layout: self.layout }), - Place::Local { local, offset, locals_addr } => Right((local, offset, locals_addr)), + Place::Local { local, offset, locals_addr } => { + Right((local, offset, locals_addr, self.layout)) + } } } @@ -277,7 +279,7 @@ impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for PlaceTy<'tcx, Prov> { ) -> InterpResult<'tcx, Self> { Ok(match self.as_mplace_or_local() { Left(mplace) => mplace.offset_with_meta(offset, mode, meta, layout, ecx)?.into(), - Right((local, old_offset, locals_addr)) => { + Right((local, old_offset, locals_addr, _)) => { debug_assert!(layout.is_sized(), "unsized locals should live in memory"); assert_matches!(meta, MemPlaceMeta::None); // we couldn't store it anyway... // `Place::Local` are always in-bounds of their surrounding local, so we can just @@ -328,9 +330,7 @@ impl<'tcx, Prov: Provenance> OpTy<'tcx, Prov> { /// The `Weiteable` trait describes interpreter values that can be written to. pub trait Writeable<'tcx, Prov: Provenance>: Projectable<'tcx, Prov> { - fn as_mplace_or_local( - &self, - ) -> Either, (mir::Local, Option, usize, TyAndLayout<'tcx>)>; + fn to_place(&self) -> PlaceTy<'tcx, Prov>; fn force_mplace>( &self, @@ -340,11 +340,8 @@ pub trait Writeable<'tcx, Prov: Provenance>: Projectable<'tcx, Prov> { impl<'tcx, Prov: Provenance> Writeable<'tcx, Prov> for PlaceTy<'tcx, Prov> { #[inline(always)] - fn as_mplace_or_local( - &self, - ) -> Either, (mir::Local, Option, usize, TyAndLayout<'tcx>)> { - self.as_mplace_or_local() - .map_right(|(local, offset, locals_addr)| (local, offset, locals_addr, self.layout)) + fn to_place(&self) -> PlaceTy<'tcx, Prov> { + self.clone() } #[inline(always)] @@ -358,10 +355,8 @@ impl<'tcx, Prov: Provenance> Writeable<'tcx, Prov> for PlaceTy<'tcx, Prov> { impl<'tcx, Prov: Provenance> Writeable<'tcx, Prov> for MPlaceTy<'tcx, Prov> { #[inline(always)] - fn as_mplace_or_local( - &self, - ) -> Either, (mir::Local, Option, usize, TyAndLayout<'tcx>)> { - Left(self.clone()) + fn to_place(&self) -> PlaceTy<'tcx, Prov> { + self.clone().into() } #[inline(always)] @@ -615,7 +610,7 @@ where // See if we can avoid an allocation. This is the counterpart to `read_immediate_raw`, // but not factored as a separate function. - let mplace = match dest.as_mplace_or_local() { + let mplace = match dest.to_place().as_mplace_or_local() { Right((local, offset, locals_addr, layout)) => { if offset.is_some() { // This has been projected to a part of this local. We could have complicated @@ -728,7 +723,7 @@ where &mut self, dest: &impl Writeable<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { - let mplace = match dest.as_mplace_or_local() { + let mplace = match dest.to_place().as_mplace_or_local() { Left(mplace) => mplace, Right((local, offset, locals_addr, layout)) => { if offset.is_some() { From 85dc22f2cfc6328501dddfaa25b67618ee5d48e4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 29 Aug 2024 13:56:01 +0200 Subject: [PATCH 059/189] interpret: factor out common code for place mutation --- .../rustc_const_eval/src/interpret/operand.rs | 26 ++++ .../rustc_const_eval/src/interpret/place.rs | 143 ++++++++---------- .../rustc_const_eval/src/interpret/visitor.rs | 1 + 3 files changed, 89 insertions(+), 81 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index d9da0b3e00acb..72842fd6f1dcc 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -111,6 +111,32 @@ impl Immediate { Immediate::Uninit => bug!("Got uninit where a scalar or scalar pair was expected"), } } + + /// Assert that this immediate is a valid value for the given ABI. + pub fn assert_matches_abi(self, abi: Abi, cx: &impl HasDataLayout) { + match (self, abi) { + (Immediate::Scalar(scalar), Abi::Scalar(s)) => { + assert_eq!(scalar.size(), s.size(cx)); + if !matches!(s.primitive(), abi::Pointer(..)) { + assert!(matches!(scalar, Scalar::Int(..))); + } + } + (Immediate::ScalarPair(a_val, b_val), Abi::ScalarPair(a, b)) => { + assert_eq!(a_val.size(), a.size(cx)); + if !matches!(a.primitive(), abi::Pointer(..)) { + assert!(matches!(a_val, Scalar::Int(..))); + } + assert_eq!(b_val.size(), b.size(cx)); + if !matches!(b.primitive(), abi::Pointer(..)) { + assert!(matches!(b_val, Scalar::Int(..))); + } + } + (Immediate::Uninit, _) => {} + _ => { + bug!("value {self:?} does not match ABI {abi:?})",) + } + } + } } // ScalarPair needs a type to interpret, so we often have an immediate and a type together diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 45695186ff0f2..551a4012ddd45 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -180,7 +180,8 @@ pub(super) enum Place { Ptr(MemPlace), /// To support alloc-free locals, we are able to write directly to a local. The offset indicates - /// where in the local this place is located; if it is `None`, no projection has been applied. + /// where in the local this place is located; if it is `None`, no projection has been applied + /// and the type of the place is exactly the type of the local. /// Such projections are meaningful even if the offset is 0, since they can change layouts. /// (Without that optimization, we'd just always be a `MemPlace`.) /// `Local` places always refer to the current stack frame, so they are unstable under @@ -557,6 +558,40 @@ where Ok(place) } + /// Given a place, returns either the underlying mplace or a reference to where the value of + /// this place is stored. + fn as_mplace_or_mutable_local( + &mut self, + place: &PlaceTy<'tcx, M::Provenance>, + ) -> InterpResult< + 'tcx, + Either, (&mut Immediate, TyAndLayout<'tcx>)>, + > { + Ok(match place.to_place().as_mplace_or_local() { + Left(mplace) => Left(mplace), + Right((local, offset, locals_addr, layout)) => { + if offset.is_some() { + // This has been projected to a part of this local, or had the type changed. + // FIMXE: there are cases where we could still avoid allocating an mplace. + Left(place.force_mplace(self)?) + } else { + debug_assert_eq!(locals_addr, self.frame().locals_addr()); + debug_assert_eq!(self.layout_of_local(self.frame(), local, None)?, layout); + match self.frame_mut().locals[local].access_mut()? { + Operand::Indirect(mplace) => { + // The local is in memory. + Left(MPlaceTy { mplace: *mplace, layout }) + } + Operand::Immediate(local_val) => { + // The local still has the optimized representation. + Right((local_val, layout)) + } + } + } + } + }) + } + /// Write an immediate to a place #[inline(always)] #[instrument(skip(self), level = "trace")] @@ -608,60 +643,20 @@ where ) -> InterpResult<'tcx> { assert!(dest.layout().is_sized(), "Cannot write unsized immediate data"); - // See if we can avoid an allocation. This is the counterpart to `read_immediate_raw`, - // but not factored as a separate function. - let mplace = match dest.to_place().as_mplace_or_local() { - Right((local, offset, locals_addr, layout)) => { - if offset.is_some() { - // This has been projected to a part of this local. We could have complicated - // logic to still keep this local as an `Operand`... but it's much easier to - // just fall back to the indirect path. - dest.force_mplace(self)? - } else { - debug_assert_eq!(locals_addr, self.frame().locals_addr()); - match self.frame_mut().locals[local].access_mut()? { - Operand::Immediate(local_val) => { - // Local can be updated in-place. - *local_val = src; - // Double-check that the value we are storing and the local fit to each other. - // (*After* doing the update for borrow checker reasons.) - if cfg!(debug_assertions) { - let local_layout = - self.layout_of_local(&self.frame(), local, None)?; - match (src, local_layout.abi) { - (Immediate::Scalar(scalar), Abi::Scalar(s)) => { - assert_eq!(scalar.size(), s.size(self)) - } - ( - Immediate::ScalarPair(a_val, b_val), - Abi::ScalarPair(a, b), - ) => { - assert_eq!(a_val.size(), a.size(self)); - assert_eq!(b_val.size(), b.size(self)); - } - (Immediate::Uninit, _) => {} - (src, abi) => { - bug!( - "value {src:?} cannot be written into local with type {} (ABI {abi:?})", - local_layout.ty - ) - } - }; - } - return Ok(()); - } - Operand::Indirect(mplace) => { - // The local is in memory, go on below. - MPlaceTy { mplace: *mplace, layout } - } - } + match self.as_mplace_or_mutable_local(&dest.to_place())? { + Right((local_val, local_layout)) => { + // Local can be updated in-place. + *local_val = src; + // Double-check that the value we are storing and the local fit to each other. + if cfg!(debug_assertions) { + src.assert_matches_abi(local_layout.abi, self); } } - Left(mplace) => mplace, // already referring to memory - }; - - // This is already in memory, write there. - self.write_immediate_to_mplace_no_validate(src, mplace.layout, mplace.mplace) + Left(mplace) => { + self.write_immediate_to_mplace_no_validate(src, mplace.layout, mplace.mplace)?; + } + } + Ok(()) } /// Write an immediate to memory. @@ -673,6 +668,9 @@ where layout: TyAndLayout<'tcx>, dest: MemPlace, ) -> InterpResult<'tcx> { + if cfg!(debug_assertions) { + value.assert_matches_abi(layout.abi, self); + } // Note that it is really important that the type here is the right one, and matches the // type things are read at. In case `value` is a `ScalarPair`, we don't do any magic here // to handle padding properly, which is only correct if we never look at this data with the @@ -723,35 +721,18 @@ where &mut self, dest: &impl Writeable<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { - let mplace = match dest.to_place().as_mplace_or_local() { - Left(mplace) => mplace, - Right((local, offset, locals_addr, layout)) => { - if offset.is_some() { - // This has been projected to a part of this local. We could have complicated - // logic to still keep this local as an `Operand`... but it's much easier to - // just fall back to the indirect path. - // FIXME: share the logic with `write_immediate_no_validate`. - dest.force_mplace(self)? - } else { - debug_assert_eq!(locals_addr, self.frame().locals_addr()); - match self.frame_mut().locals[local].access_mut()? { - Operand::Immediate(local) => { - *local = Immediate::Uninit; - return Ok(()); - } - Operand::Indirect(mplace) => { - // The local is in memory, go on below. - MPlaceTy { mplace: *mplace, layout } - } - } - } + match self.as_mplace_or_mutable_local(&dest.to_place())? { + Right((local_val, _local_layout)) => { + *local_val = Immediate::Uninit; } - }; - let Some(mut alloc) = self.get_place_alloc_mut(&mplace)? else { - // Zero-sized access - return Ok(()); - }; - alloc.write_uninit()?; + Left(mplace) => { + let Some(mut alloc) = self.get_place_alloc_mut(&mplace)? else { + // Zero-sized access + return Ok(()); + }; + alloc.write_uninit()?; + } + } Ok(()) } diff --git a/compiler/rustc_const_eval/src/interpret/visitor.rs b/compiler/rustc_const_eval/src/interpret/visitor.rs index b02f12e3c7f0b..08b39fe8751be 100644 --- a/compiler/rustc_const_eval/src/interpret/visitor.rs +++ b/compiler/rustc_const_eval/src/interpret/visitor.rs @@ -82,6 +82,7 @@ pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized { self.visit_value(new_val) } + /// Traversal logic; should not be overloaded. fn walk_value(&mut self, v: &Self::V) -> InterpResult<'tcx> { let ty = v.layout().ty; trace!("walk_value: type: {ty}"); From cbdcbf0d6a586792c5e0a0b8965a3179bac56120 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 29 Aug 2024 08:59:52 +0200 Subject: [PATCH 060/189] interpret: reset provenance on typed copies --- .../src/const_eval/eval_queries.rs | 4 +- .../rustc_const_eval/src/interpret/memory.rs | 38 ++- .../rustc_const_eval/src/interpret/operand.rs | 14 + .../rustc_const_eval/src/interpret/place.rs | 69 +++-- .../src/interpret/validity.rs | 259 ++++++++++++------ .../src/util/check_validity_requirement.rs | 12 +- .../src/mir/interpret/allocation.rs | 6 + .../rustc_middle/src/mir/interpret/value.rs | 7 + src/tools/miri/src/concurrency/data_race.rs | 2 +- src/tools/miri/src/intrinsics/mod.rs | 6 +- .../provenance/int_copy_looses_provenance0.rs | 10 + .../int_copy_looses_provenance0.stderr | 15 + .../provenance/int_copy_looses_provenance1.rs | 10 + .../int_copy_looses_provenance1.stderr | 15 + .../provenance/int_copy_looses_provenance2.rs | 12 + .../int_copy_looses_provenance2.stderr | 15 + .../provenance/int_copy_looses_provenance3.rs | 29 ++ .../int_copy_looses_provenance3.stderr | 15 + .../ptr_copy_loses_partial_provenance0.rs | 17 ++ .../ptr_copy_loses_partial_provenance0.stderr | 15 + .../ptr_copy_loses_partial_provenance1.rs | 17 ++ .../ptr_copy_loses_partial_provenance1.stderr | 15 + src/tools/miri/tests/pass/provenance.rs | 22 ++ 23 files changed, 489 insertions(+), 135 deletions(-) create mode 100644 src/tools/miri/tests/fail/provenance/int_copy_looses_provenance0.rs create mode 100644 src/tools/miri/tests/fail/provenance/int_copy_looses_provenance0.stderr create mode 100644 src/tools/miri/tests/fail/provenance/int_copy_looses_provenance1.rs create mode 100644 src/tools/miri/tests/fail/provenance/int_copy_looses_provenance1.stderr create mode 100644 src/tools/miri/tests/fail/provenance/int_copy_looses_provenance2.rs create mode 100644 src/tools/miri/tests/fail/provenance/int_copy_looses_provenance2.stderr create mode 100644 src/tools/miri/tests/fail/provenance/int_copy_looses_provenance3.rs create mode 100644 src/tools/miri/tests/fail/provenance/int_copy_looses_provenance3.stderr create mode 100644 src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance0.rs create mode 100644 src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance0.stderr create mode 100644 src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance1.rs create mode 100644 src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance1.stderr diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 96b3ec6f18728..7ccebd83f24f7 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -94,7 +94,7 @@ fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>( let intern_result = intern_const_alloc_recursive(ecx, intern_kind, &ret); // Since evaluation had no errors, validate the resulting constant. - const_validate_mplace(&ecx, &ret, cid)?; + const_validate_mplace(ecx, &ret, cid)?; // Only report this after validation, as validaiton produces much better diagnostics. // FIXME: ensure validation always reports this and stop making interning care about it. @@ -391,7 +391,7 @@ fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>( #[inline(always)] fn const_validate_mplace<'tcx>( - ecx: &InterpCx<'tcx, CompileTimeMachine<'tcx>>, + ecx: &mut InterpCx<'tcx, CompileTimeMachine<'tcx>>, mplace: &MPlaceTy<'tcx>, cid: GlobalId<'tcx>, ) -> Result<(), ErrorHandled> { diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 45a5eb9bd52fc..53a9cd0b9ad6d 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -8,9 +8,8 @@ use std::assert_matches::assert_matches; use std::borrow::Cow; -use std::cell::Cell; use std::collections::VecDeque; -use std::{fmt, ptr}; +use std::{fmt, mem, ptr}; use rustc_ast::Mutability; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; @@ -118,7 +117,7 @@ pub struct Memory<'tcx, M: Machine<'tcx>> { /// This stores whether we are currently doing reads purely for the purpose of validation. /// Those reads do not trigger the machine's hooks for memory reads. /// Needless to say, this must only be set with great care! - validation_in_progress: Cell, + validation_in_progress: bool, } /// A reference to some allocation that was already bounds-checked for the given region @@ -145,7 +144,7 @@ impl<'tcx, M: Machine<'tcx>> Memory<'tcx, M> { alloc_map: M::MemoryMap::default(), extra_fn_ptr_map: FxIndexMap::default(), dead_alloc_map: FxIndexMap::default(), - validation_in_progress: Cell::new(false), + validation_in_progress: false, } } @@ -682,7 +681,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // We want to call the hook on *all* accesses that involve an AllocId, including zero-sized // accesses. That means we cannot rely on the closure above or the `Some` branch below. We // do this after `check_and_deref_ptr` to ensure some basic sanity has already been checked. - if !self.memory.validation_in_progress.get() { + if !self.memory.validation_in_progress { if let Ok((alloc_id, ..)) = self.ptr_try_get_alloc_id(ptr, size_i64) { M::before_alloc_read(self, alloc_id)?; } @@ -690,7 +689,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { if let Some((alloc_id, offset, prov, alloc)) = ptr_and_alloc { let range = alloc_range(offset, size); - if !self.memory.validation_in_progress.get() { + if !self.memory.validation_in_progress { M::before_memory_read( self.tcx, &self.machine, @@ -766,11 +765,14 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let parts = self.get_ptr_access(ptr, size)?; if let Some((alloc_id, offset, prov)) = parts { let tcx = self.tcx; + let validation_in_progress = self.memory.validation_in_progress; // FIXME: can we somehow avoid looking up the allocation twice here? // We cannot call `get_raw_mut` inside `check_and_deref_ptr` as that would duplicate `&mut self`. let (alloc, machine) = self.get_alloc_raw_mut(alloc_id)?; let range = alloc_range(offset, size); - M::before_memory_write(tcx, machine, &mut alloc.extra, (alloc_id, prov), range)?; + if !validation_in_progress { + M::before_memory_write(tcx, machine, &mut alloc.extra, (alloc_id, prov), range)?; + } Ok(Some(AllocRefMut { alloc, range, tcx: *tcx, alloc_id })) } else { Ok(None) @@ -1014,16 +1016,16 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// /// We do this so Miri's allocation access tracking does not show the validation /// reads as spurious accesses. - pub fn run_for_validation(&self, f: impl FnOnce() -> R) -> R { + pub fn run_for_validation(&mut self, f: impl FnOnce(&mut Self) -> R) -> R { // This deliberately uses `==` on `bool` to follow the pattern // `assert!(val.replace(new) == old)`. assert!( - self.memory.validation_in_progress.replace(true) == false, + mem::replace(&mut self.memory.validation_in_progress, true) == false, "`validation_in_progress` was already set" ); - let res = f(); + let res = f(self); assert!( - self.memory.validation_in_progress.replace(false) == true, + mem::replace(&mut self.memory.validation_in_progress, false) == true, "`validation_in_progress` was unset by someone else" ); res @@ -1115,6 +1117,10 @@ impl<'a, 'tcx, M: Machine<'tcx>> std::fmt::Debug for DumpAllocs<'a, 'tcx, M> { impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes> AllocRefMut<'a, 'tcx, Prov, Extra, Bytes> { + pub fn as_ref<'b>(&'b self) -> AllocRef<'b, 'tcx, Prov, Extra, Bytes> { + AllocRef { alloc: self.alloc, range: self.range, tcx: self.tcx, alloc_id: self.alloc_id } + } + /// `range` is relative to this allocation reference, not the base of the allocation. pub fn write_scalar(&mut self, range: AllocRange, val: Scalar) -> InterpResult<'tcx> { let range = self.range.subrange(range); @@ -1137,6 +1143,14 @@ impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes> .write_uninit(&self.tcx, self.range) .map_err(|e| e.to_interp_error(self.alloc_id))?) } + + /// Remove all provenance in the reference range. + pub fn clear_provenance(&mut self) -> InterpResult<'tcx> { + Ok(self + .alloc + .clear_provenance(&self.tcx, self.range) + .map_err(|e| e.to_interp_error(self.alloc_id))?) + } } impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes> AllocRef<'a, 'tcx, Prov, Extra, Bytes> { @@ -1278,7 +1292,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { }; let src_alloc = self.get_alloc_raw(src_alloc_id)?; let src_range = alloc_range(src_offset, size); - assert!(!self.memory.validation_in_progress.get(), "we can't be copying during validation"); + assert!(!self.memory.validation_in_progress, "we can't be copying during validation"); M::before_memory_read( tcx, &self.machine, diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 72842fd6f1dcc..b906e3422dba5 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -137,6 +137,20 @@ impl Immediate { } } } + + pub fn clear_provenance<'tcx>(&mut self) -> InterpResult<'tcx> { + match self { + Immediate::Scalar(s) => { + s.clear_provenance()?; + } + Immediate::ScalarPair(a, b) => { + a.clear_provenance()?; + b.clear_provenance()?; + } + Immediate::Uninit => {} + } + Ok(()) + } } // ScalarPair needs a type to interpret, so we often have an immediate and a type together diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 551a4012ddd45..e2aef0519186e 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -605,8 +605,9 @@ where if M::enforce_validity(self, dest.layout()) { // Data got changed, better make sure it matches the type! self.validate_operand( - &dest.to_op(self)?, + &dest.to_place(), M::enforce_validity_recursively(self, dest.layout()), + /*reset_provenance*/ true, )?; } @@ -636,7 +637,7 @@ where /// Write an immediate to a place. /// If you use this you are responsible for validating that things got copied at the /// right type. - fn write_immediate_no_validate( + pub(super) fn write_immediate_no_validate( &mut self, src: Immediate, dest: &impl Writeable<'tcx, M::Provenance>, @@ -684,15 +685,7 @@ where match value { Immediate::Scalar(scalar) => { - let Abi::Scalar(s) = layout.abi else { - span_bug!( - self.cur_span(), - "write_immediate_to_mplace: invalid Scalar layout: {layout:#?}", - ) - }; - let size = s.size(&tcx); - assert_eq!(size, layout.size, "abi::Scalar size does not match layout size"); - alloc.write_scalar(alloc_range(Size::ZERO, size), scalar) + alloc.write_scalar(alloc_range(Size::ZERO, scalar.size()), scalar) } Immediate::ScalarPair(a_val, b_val) => { let Abi::ScalarPair(a, b) = layout.abi else { @@ -702,16 +695,15 @@ where layout ) }; - let (a_size, b_size) = (a.size(&tcx), b.size(&tcx)); - let b_offset = a_size.align_to(b.align(&tcx).abi); + let b_offset = a.size(&tcx).align_to(b.align(&tcx).abi); assert!(b_offset.bytes() > 0); // in `operand_field` we use the offset to tell apart the fields // It is tempting to verify `b_offset` against `layout.fields.offset(1)`, // but that does not work: We could be a newtype around a pair, then the // fields do not match the `ScalarPair` components. - alloc.write_scalar(alloc_range(Size::ZERO, a_size), a_val)?; - alloc.write_scalar(alloc_range(b_offset, b_size), b_val) + alloc.write_scalar(alloc_range(Size::ZERO, a_val.size()), a_val)?; + alloc.write_scalar(alloc_range(b_offset, b_val.size()), b_val) } Immediate::Uninit => alloc.write_uninit(), } @@ -736,6 +728,26 @@ where Ok(()) } + /// Remove all provenance in the given place. + pub fn clear_provenance( + &mut self, + dest: &impl Writeable<'tcx, M::Provenance>, + ) -> InterpResult<'tcx> { + match self.as_mplace_or_mutable_local(&dest.to_place())? { + Right((local_val, _local_layout)) => { + local_val.clear_provenance()?; + } + Left(mplace) => { + let Some(mut alloc) = self.get_place_alloc_mut(&mplace)? else { + // Zero-sized access + return Ok(()); + }; + alloc.clear_provenance()?; + } + } + Ok(()) + } + /// Copies the data from an operand to a place. /// The layouts of the `src` and `dest` may disagree. /// Does not perform validation of the destination. @@ -789,23 +801,30 @@ where allow_transmute: bool, validate_dest: bool, ) -> InterpResult<'tcx> { - // Generally for transmutation, data must be valid both at the old and new type. - // But if the types are the same, the 2nd validation below suffices. - if src.layout().ty != dest.layout().ty && M::enforce_validity(self, src.layout()) { - self.validate_operand( - &src.to_op(self)?, - M::enforce_validity_recursively(self, src.layout()), - )?; - } + // These are technically *two* typed copies: `src` is a not-yet-loaded value, + // so we're going a typed copy at `src` type from there to some intermediate storage. + // And then we're doing a second typed copy from that intermediate storage to `dest`. + // But as an optimization, we only make a single direct copy here. // Do the actual copy. self.copy_op_no_validate(src, dest, allow_transmute)?; if validate_dest && M::enforce_validity(self, dest.layout()) { - // Data got changed, better make sure it matches the type! + let dest = dest.to_place(); + // Given that there were two typed copies, we have to ensure this is valid at both types, + // and we have to ensure this loses provenance and padding according to both types. + // But if the types are identical, we only do one pass. + if src.layout().ty != dest.layout().ty { + self.validate_operand( + &dest.transmute(src.layout(), self)?, + M::enforce_validity_recursively(self, src.layout()), + /*reset_provenance*/ true, + )?; + } self.validate_operand( - &dest.to_op(self)?, + &dest, M::enforce_validity_recursively(self, dest.layout()), + /*reset_provenance*/ true, )?; } diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 26b7251f6dbc5..953831a55e5ed 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -30,8 +30,8 @@ use tracing::trace; use super::machine::AllocMap; use super::{ err_ub, format_interp_error, throw_ub, AllocId, AllocKind, CheckInAllocMsg, GlobalAlloc, ImmTy, - Immediate, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, OpTy, Pointer, Projectable, - Scalar, ValueVisitor, + Immediate, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, PlaceTy, Pointer, + Projectable, Scalar, ValueVisitor, }; // for the validation errors @@ -163,22 +163,22 @@ impl RefTracking pub fn empty() -> Self { RefTracking { seen: FxHashSet::default(), todo: vec![] } } - pub fn new(op: T) -> Self { + pub fn new(val: T) -> Self { let mut ref_tracking_for_consts = - RefTracking { seen: FxHashSet::default(), todo: vec![(op.clone(), PATH::default())] }; - ref_tracking_for_consts.seen.insert(op); + RefTracking { seen: FxHashSet::default(), todo: vec![(val.clone(), PATH::default())] }; + ref_tracking_for_consts.seen.insert(val); ref_tracking_for_consts } pub fn next(&mut self) -> Option<(T, PATH)> { self.todo.pop() } - fn track(&mut self, op: T, path: impl FnOnce() -> PATH) { - if self.seen.insert(op.clone()) { - trace!("Recursing below ptr {:#?}", op); + fn track(&mut self, val: T, path: impl FnOnce() -> PATH) { + if self.seen.insert(val.clone()) { + trace!("Recursing below ptr {:#?}", val); let path = path(); // Remember to come back to this later. - self.todo.push((op, path)); + self.todo.push((val, path)); } } } @@ -217,7 +217,10 @@ struct ValidityVisitor<'rt, 'tcx, M: Machine<'tcx>> { ref_tracking: Option<&'rt mut RefTracking, Vec>>, /// `None` indicates this is not validating for CTFE (but for runtime). ctfe_mode: Option, - ecx: &'rt InterpCx<'tcx, M>, + ecx: &'rt mut InterpCx<'tcx, M>, + /// Whether provenance should be reset outside of pointers (emulating the effect of a typed + /// copy). + reset_provenance: bool, } impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { @@ -314,11 +317,11 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { fn read_immediate( &self, - op: &OpTy<'tcx, M::Provenance>, + val: &PlaceTy<'tcx, M::Provenance>, expected: ExpectedKind, ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> { Ok(try_validation!( - self.ecx.read_immediate(op), + self.ecx.read_immediate(val), self.path, Ub(InvalidUninitBytes(None)) => Uninit { expected }, @@ -332,10 +335,38 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { fn read_scalar( &self, - op: &OpTy<'tcx, M::Provenance>, + val: &PlaceTy<'tcx, M::Provenance>, expected: ExpectedKind, ) -> InterpResult<'tcx, Scalar> { - Ok(self.read_immediate(op, expected)?.to_scalar()) + Ok(self.read_immediate(val, expected)?.to_scalar()) + } + + fn deref_pointer( + &mut self, + val: &PlaceTy<'tcx, M::Provenance>, + expected: ExpectedKind, + ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> { + // Not using `ecx.deref_pointer` since we want to use our `read_immediate` wrapper. + let imm = self.read_immediate(val, expected)?; + // Reset provenance: ensure slice tail metadata does not preserve provenance, + // and ensure all pointers do not preserve partial provenance. + if self.reset_provenance { + if matches!(imm.layout.abi, Abi::Scalar(..)) { + // A thin pointer. If it has provenance, we don't have to do anything. + // If it does not, ensure we clear the provenance in memory. + if matches!(imm.to_scalar(), Scalar::Int(..)) { + self.ecx.clear_provenance(val)?; + } + } else { + // A wide pointer. This means we have to worry both about the pointer itself and the + // metadata. We do the lazy thing and just write back the value we got. Just + // clearing provenance in a targeted manner would be more efficient, but unless this + // is a perf hotspot it's just not worth the effort. + self.ecx.write_immediate_no_validate(*imm, val)?; + } + } + // Now turn it into a place. + self.ecx.ref_to_mplace(&imm) } fn check_wide_ptr_meta( @@ -376,11 +407,10 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { /// Check a reference or `Box`. fn check_safe_pointer( &mut self, - value: &OpTy<'tcx, M::Provenance>, + value: &PlaceTy<'tcx, M::Provenance>, ptr_kind: PointerKind, ) -> InterpResult<'tcx> { - // Not using `deref_pointer` since we want to use our `read_immediate` wrapper. - let place = self.ecx.ref_to_mplace(&self.read_immediate(value, ptr_kind.into())?)?; + let place = self.deref_pointer(value, ptr_kind.into())?; // Handle wide pointers. // Check metadata early, for better diagnostics if place.layout.is_unsized() { @@ -564,31 +594,37 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { /// Note that not all of these have `FieldsShape::Primitive`, e.g. wide references. fn try_visit_primitive( &mut self, - value: &OpTy<'tcx, M::Provenance>, + value: &PlaceTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx, bool> { // Go over all the primitive types let ty = value.layout.ty; match ty.kind() { ty::Bool => { - let value = self.read_scalar(value, ExpectedKind::Bool)?; + let scalar = self.read_scalar(value, ExpectedKind::Bool)?; try_validation!( - value.to_bool(), + scalar.to_bool(), self.path, Ub(InvalidBool(..)) => ValidationErrorKind::InvalidBool { - value: format!("{value:x}"), + value: format!("{scalar:x}"), } ); + if self.reset_provenance { + self.ecx.clear_provenance(value)?; + } Ok(true) } ty::Char => { - let value = self.read_scalar(value, ExpectedKind::Char)?; + let scalar = self.read_scalar(value, ExpectedKind::Char)?; try_validation!( - value.to_char(), + scalar.to_char(), self.path, Ub(InvalidChar(..)) => ValidationErrorKind::InvalidChar { - value: format!("{value:x}"), + value: format!("{scalar:x}"), } ); + if self.reset_provenance { + self.ecx.clear_provenance(value)?; + } Ok(true) } ty::Float(_) | ty::Int(_) | ty::Uint(_) => { @@ -602,11 +638,13 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { ExpectedKind::Int }, )?; + if self.reset_provenance { + self.ecx.clear_provenance(value)?; + } Ok(true) } ty::RawPtr(..) => { - let place = - self.ecx.ref_to_mplace(&self.read_immediate(value, ExpectedKind::RawPtr)?)?; + let place = self.deref_pointer(value, ExpectedKind::RawPtr)?; if place.layout.is_unsized() { self.check_wide_ptr_meta(place.meta(), place.layout)?; } @@ -617,11 +655,11 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { Ok(true) } ty::FnPtr(..) => { - let value = self.read_scalar(value, ExpectedKind::FnPtr)?; + let scalar = self.read_scalar(value, ExpectedKind::FnPtr)?; // If we check references recursively, also check that this points to a function. if let Some(_) = self.ref_tracking { - let ptr = value.to_pointer(self.ecx)?; + let ptr = scalar.to_pointer(self.ecx)?; let _fn = try_validation!( self.ecx.get_ptr_fn(ptr), self.path, @@ -631,10 +669,17 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { // FIXME: Check if the signature matches } else { // Otherwise (for standalone Miri), we have to still check it to be non-null. - if self.ecx.scalar_may_be_null(value)? { + if self.ecx.scalar_may_be_null(scalar)? { throw_validation_failure!(self.path, NullFnPtr); } } + if self.reset_provenance { + // Make sure we do not preserve partial provenance. This matches the thin + // pointer handling in `deref_pointer`. + if matches!(scalar, Scalar::Int(..)) { + self.ecx.clear_provenance(value)?; + } + } Ok(true) } ty::Never => throw_validation_failure!(self.path, NeverVal), @@ -716,13 +761,18 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { } } - fn in_mutable_memory(&self, op: &OpTy<'tcx, M::Provenance>) -> bool { - if let Some(mplace) = op.as_mplace_or_imm().left() { + fn in_mutable_memory(&self, val: &PlaceTy<'tcx, M::Provenance>) -> bool { + if let Some(mplace) = val.as_mplace_or_local().left() { if let Some(alloc_id) = mplace.ptr().provenance.and_then(|p| p.get_alloc_id()) { - return mutability(self.ecx, alloc_id).is_mut(); + mutability(self.ecx, alloc_id).is_mut() + } else { + // No memory at all. + false } + } else { + // A local variable -- definitely mutable. + true } - false } } @@ -774,7 +824,7 @@ fn mutability<'tcx>(ecx: &InterpCx<'tcx, impl Machine<'tcx>>, alloc_id: AllocId) } impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, 'tcx, M> { - type V = OpTy<'tcx, M::Provenance>; + type V = PlaceTy<'tcx, M::Provenance>; #[inline(always)] fn ecx(&self) -> &InterpCx<'tcx, M> { @@ -783,11 +833,11 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, fn read_discriminant( &mut self, - op: &OpTy<'tcx, M::Provenance>, + val: &PlaceTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx, VariantIdx> { self.with_elem(PathElem::EnumTag, move |this| { Ok(try_validation!( - this.ecx.read_discriminant(op), + this.ecx.read_discriminant(val), this.path, Ub(InvalidTag(val)) => InvalidEnumTag { value: format!("{val:x}"), @@ -802,40 +852,40 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, #[inline] fn visit_field( &mut self, - old_op: &OpTy<'tcx, M::Provenance>, + old_val: &PlaceTy<'tcx, M::Provenance>, field: usize, - new_op: &OpTy<'tcx, M::Provenance>, + new_val: &PlaceTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { - let elem = self.aggregate_field_path_elem(old_op.layout, field); - self.with_elem(elem, move |this| this.visit_value(new_op)) + let elem = self.aggregate_field_path_elem(old_val.layout, field); + self.with_elem(elem, move |this| this.visit_value(new_val)) } #[inline] fn visit_variant( &mut self, - old_op: &OpTy<'tcx, M::Provenance>, + old_val: &PlaceTy<'tcx, M::Provenance>, variant_id: VariantIdx, - new_op: &OpTy<'tcx, M::Provenance>, + new_val: &PlaceTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { - let name = match old_op.layout.ty.kind() { + let name = match old_val.layout.ty.kind() { ty::Adt(adt, _) => PathElem::Variant(adt.variant(variant_id).name), // Coroutines also have variants ty::Coroutine(..) => PathElem::CoroutineState(variant_id), - _ => bug!("Unexpected type with variant: {:?}", old_op.layout.ty), + _ => bug!("Unexpected type with variant: {:?}", old_val.layout.ty), }; - self.with_elem(name, move |this| this.visit_value(new_op)) + self.with_elem(name, move |this| this.visit_value(new_val)) } #[inline(always)] fn visit_union( &mut self, - op: &OpTy<'tcx, M::Provenance>, + val: &PlaceTy<'tcx, M::Provenance>, _fields: NonZero, ) -> InterpResult<'tcx> { // Special check for CTFE validation, preventing `UnsafeCell` inside unions in immutable memory. if self.ctfe_mode.is_some_and(|c| !c.allow_immutable_unsafe_cell()) { - if !op.layout.is_zst() && !op.layout.ty.is_freeze(*self.ecx.tcx, self.ecx.param_env) { - if !self.in_mutable_memory(op) { + if !val.layout.is_zst() && !val.layout.ty.is_freeze(*self.ecx.tcx, self.ecx.param_env) { + if !self.in_mutable_memory(val) { throw_validation_failure!(self.path, UnsafeCellInImmutable); } } @@ -847,39 +897,41 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, fn visit_box( &mut self, _box_ty: Ty<'tcx>, - op: &OpTy<'tcx, M::Provenance>, + val: &PlaceTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { - self.check_safe_pointer(op, PointerKind::Box)?; + self.check_safe_pointer(val, PointerKind::Box)?; Ok(()) } #[inline] - fn visit_value(&mut self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx> { - trace!("visit_value: {:?}, {:?}", *op, op.layout); + fn visit_value(&mut self, val: &PlaceTy<'tcx, M::Provenance>) -> InterpResult<'tcx> { + trace!("visit_value: {:?}, {:?}", *val, val.layout); // Check primitive types -- the leaves of our recursive descent. + // This is called even for enum discriminants (which are "fields" of their enum), + // so for integer-typed discriminants the provenance reset will happen here. // We assume that the Scalar validity range does not restrict these values // any further than `try_visit_primitive` does! - if self.try_visit_primitive(op)? { + if self.try_visit_primitive(val)? { return Ok(()); } // Special check preventing `UnsafeCell` in the inner part of constants if self.ctfe_mode.is_some_and(|c| !c.allow_immutable_unsafe_cell()) { - if !op.layout.is_zst() - && let Some(def) = op.layout.ty.ty_adt_def() + if !val.layout.is_zst() + && let Some(def) = val.layout.ty.ty_adt_def() && def.is_unsafe_cell() { - if !self.in_mutable_memory(op) { + if !self.in_mutable_memory(val) { throw_validation_failure!(self.path, UnsafeCellInImmutable); } } } // Recursively walk the value at its type. Apply optimizations for some large types. - match op.layout.ty.kind() { + match val.layout.ty.kind() { ty::Str => { - let mplace = op.assert_mem_place(); // strings are unsized and hence never immediate + let mplace = val.assert_mem_place(); // strings are unsized and hence never immediate let len = mplace.len(self.ecx)?; try_validation!( self.ecx.read_bytes_ptr_strip_provenance(mplace.ptr(), Size::from_bytes(len)), @@ -889,11 +941,10 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, ); } ty::Array(tys, ..) | ty::Slice(tys) - // This optimization applies for types that can hold arbitrary bytes (such as - // integer and floating point types) or for structs or tuples with no fields. - // FIXME(wesleywiser) This logic could be extended further to arbitrary structs - // or tuples made up of integer/floating point types or inhabited ZSTs with no - // padding. + // This optimization applies for types that can hold arbitrary non-provenance bytes (such as + // integer and floating point types). + // FIXME(wesleywiser) This logic could be extended further to arbitrary structs or + // tuples made up of integer/floating point types or inhabited ZSTs with no padding. if matches!(tys.kind(), ty::Int(..) | ty::Uint(..) | ty::Float(..)) => { @@ -901,7 +952,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, // Optimized handling for arrays of integer/float type. // This is the length of the array/slice. - let len = op.len(self.ecx)?; + let len = val.len(self.ecx)?; // This is the element type size. let layout = self.ecx.layout_of(*tys)?; // This is the size in bytes of the whole array. (This checks for overflow.) @@ -911,8 +962,9 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, if size == Size::ZERO { return Ok(()); } - // Now that we definitely have a non-ZST array, we know it lives in memory. - let mplace = match op.as_mplace_or_imm() { + // Now that we definitely have a non-ZST array, we know it lives in memory -- except it may + // be an uninitialized local variable, those are also "immediate". + let mplace = match val.to_op(self.ecx)?.as_mplace_or_imm() { Left(mplace) => mplace, Right(imm) => match *imm { Immediate::Uninit => @@ -958,20 +1010,28 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, } } } + + // Don't forget that these are all non-pointer types, and thus do not preserve + // provenance. + if self.reset_provenance { + // We can't share this with above as above, we might be looking at read-only memory. + let mut alloc = self.ecx.get_ptr_alloc_mut(mplace.ptr(), size)?.expect("we already excluded size 0"); + alloc.clear_provenance()?; + } } // Fast path for arrays and slices of ZSTs. We only need to check a single ZST element // of an array and not all of them, because there's only a single value of a specific // ZST type, so either validation fails for all elements or none. ty::Array(tys, ..) | ty::Slice(tys) if self.ecx.layout_of(*tys)?.is_zst() => { // Validate just the first element (if any). - if op.len(self.ecx)? > 0 { - self.visit_field(op, 0, &self.ecx.project_index(op, 0)?)?; + if val.len(self.ecx)? > 0 { + self.visit_field(val, 0, &self.ecx.project_index(val, 0)?)?; } } _ => { // default handler try_validation!( - self.walk_value(op), + self.walk_value(val), self.path, // It's not great to catch errors here, since we can't give a very good path, // but it's better than ICEing. @@ -992,15 +1052,15 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, // FIXME: We could avoid some redundant checks here. For newtypes wrapping // scalars, we do the same check on every "level" (e.g., first we check // MyNewtype and then the scalar in there). - match op.layout.abi { + match val.layout.abi { Abi::Uninhabited => { - let ty = op.layout.ty; + let ty = val.layout.ty; throw_validation_failure!(self.path, UninhabitedVal { ty }); } Abi::Scalar(scalar_layout) => { if !scalar_layout.is_uninit_valid() { // There is something to check here. - let scalar = self.read_scalar(op, ExpectedKind::InitScalar)?; + let scalar = self.read_scalar(val, ExpectedKind::InitScalar)?; self.visit_scalar(scalar, scalar_layout)?; } } @@ -1010,7 +1070,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, // the other must be init. if !a_layout.is_uninit_valid() && !b_layout.is_uninit_valid() { let (a, b) = - self.read_immediate(op, ExpectedKind::InitScalar)?.to_scalar_pair(); + self.read_immediate(val, ExpectedKind::InitScalar)?.to_scalar_pair(); self.visit_scalar(a, a_layout)?; self.visit_scalar(b, b_layout)?; } @@ -1031,19 +1091,20 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { fn validate_operand_internal( - &self, - op: &OpTy<'tcx, M::Provenance>, + &mut self, + val: &PlaceTy<'tcx, M::Provenance>, path: Vec, ref_tracking: Option<&mut RefTracking, Vec>>, ctfe_mode: Option, + reset_provenance: bool, ) -> InterpResult<'tcx> { - trace!("validate_operand_internal: {:?}, {:?}", *op, op.layout.ty); - - // Construct a visitor - let mut visitor = ValidityVisitor { path, ref_tracking, ctfe_mode, ecx: self }; + trace!("validate_operand_internal: {:?}, {:?}", *val, val.layout.ty); - // Run it. - match self.run_for_validation(|| visitor.visit_value(op)) { + // Run the visitor. + match self.run_for_validation(|ecx| { + let mut v = ValidityVisitor { path, ref_tracking, ctfe_mode, ecx, reset_provenance }; + v.visit_value(val) + }) { Ok(()) => Ok(()), // Pass through validation failures and "invalid program" issues. Err(err) @@ -1079,13 +1140,19 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// - no `UnsafeCell` or non-ZST `&mut`. #[inline(always)] pub(crate) fn const_validate_operand( - &self, - op: &OpTy<'tcx, M::Provenance>, + &mut self, + val: &PlaceTy<'tcx, M::Provenance>, path: Vec, ref_tracking: &mut RefTracking, Vec>, ctfe_mode: CtfeValidationMode, ) -> InterpResult<'tcx> { - self.validate_operand_internal(op, path, Some(ref_tracking), Some(ctfe_mode)) + self.validate_operand_internal( + val, + path, + Some(ref_tracking), + Some(ctfe_mode), + /*reset_provenance*/ false, + ) } /// This function checks the data at `op` to be runtime-valid. @@ -1093,21 +1160,35 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// It will error if the bits at the destination do not match the ones described by the layout. #[inline(always)] pub fn validate_operand( - &self, - op: &OpTy<'tcx, M::Provenance>, + &mut self, + val: &PlaceTy<'tcx, M::Provenance>, recursive: bool, + reset_provenance: bool, ) -> InterpResult<'tcx> { // Note that we *could* actually be in CTFE here with `-Zextra-const-ub-checks`, but it's // still correct to not use `ctfe_mode`: that mode is for validation of the final constant // value, it rules out things like `UnsafeCell` in awkward places. if !recursive { - return self.validate_operand_internal(op, vec![], None, None); + return self.validate_operand_internal(val, vec![], None, None, reset_provenance); } // Do a recursive check. let mut ref_tracking = RefTracking::empty(); - self.validate_operand_internal(op, vec![], Some(&mut ref_tracking), None)?; + self.validate_operand_internal( + val, + vec![], + Some(&mut ref_tracking), + None, + reset_provenance, + )?; while let Some((mplace, path)) = ref_tracking.todo.pop() { - self.validate_operand_internal(&mplace.into(), path, Some(&mut ref_tracking), None)?; + // Things behind reference do *not* have the provenance reset. + self.validate_operand_internal( + &mplace.into(), + path, + Some(&mut ref_tracking), + None, + /*reset_provenance*/ false, + )?; } Ok(()) } diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs index cbd1fdeea2aa3..5e424190d07dd 100644 --- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs +++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs @@ -4,7 +4,7 @@ use rustc_middle::ty::{ParamEnvAnd, Ty, TyCtxt}; use rustc_target::abi::{Abi, FieldsShape, Scalar, Variants}; use crate::const_eval::{CanAccessMutGlobal, CheckAlignment, CompileTimeMachine}; -use crate::interpret::{InterpCx, MemoryKind, OpTy}; +use crate::interpret::{InterpCx, MemoryKind}; /// Determines if this type permits "raw" initialization by just transmuting some memory into an /// instance of `T`. @@ -61,13 +61,17 @@ fn might_permit_raw_init_strict<'tcx>( .expect("failed to write bytes for zero valid check"); } - let ot: OpTy<'_, _> = allocated.into(); - // Assume that if it failed, it's a validation failure. // This does *not* actually check that references are dereferenceable, but since all types that // require dereferenceability also require non-null, we don't actually get any false negatives // due to this. - Ok(cx.validate_operand(&ot, /*recursive*/ false).is_ok()) + Ok(cx + .validate_operand( + &allocated.into(), + /*recursive*/ false, + /*reset_provenance*/ false, + ) + .is_ok()) } /// Implements the 'lax' (default) version of the `might_permit_raw_init` checks; see that function for diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 5fb8af576ae93..cd56d0edc0585 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -644,6 +644,12 @@ impl Allocation return Ok(()); } + /// Remove all provenance in the given memory range. + pub fn clear_provenance(&mut self, cx: &impl HasDataLayout, range: AllocRange) -> AllocResult { + self.provenance.clear(range, cx)?; + return Ok(()); + } + /// Applies a previously prepared provenance copy. /// The affected range, as defined in the parameters to `provenance().prepare_copy` is expected /// to be clear of provenance. diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs index 84c17b39a623e..989f03d3d1399 100644 --- a/compiler/rustc_middle/src/mir/interpret/value.rs +++ b/compiler/rustc_middle/src/mir/interpret/value.rs @@ -307,6 +307,13 @@ impl<'tcx, Prov: Provenance> Scalar { } } + pub fn clear_provenance(&mut self) -> InterpResult<'tcx> { + if matches!(self, Scalar::Ptr(..)) { + *self = self.to_scalar_int()?.into(); + } + Ok(()) + } + #[inline(always)] pub fn to_scalar_int(self) -> InterpResult<'tcx, ScalarInt> { self.try_to_scalar_int().map_err(|_| err_unsup!(ReadPointerAsInt(None)).into()) diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs index 6fd207c92b937..b604fd868a02a 100644 --- a/src/tools/miri/src/concurrency/data_race.rs +++ b/src/tools/miri/src/concurrency/data_race.rs @@ -637,7 +637,7 @@ pub trait EvalContextExt<'tcx>: MiriInterpCxExt<'tcx> { // The program didn't actually do a read, so suppress the memory access hooks. // This is also a very special exception where we just ignore an error -- if this read // was UB e.g. because the memory is uninitialized, we don't want to know! - let old_val = this.run_for_validation(|| this.read_scalar(dest)).ok(); + let old_val = this.run_for_validation(|this| this.read_scalar(dest)).ok(); this.allow_data_races_mut(move |this| this.write_scalar(val, dest))?; this.validate_atomic_store(dest, atomic)?; this.buffered_atomic_write(val, dest, atomic, old_val) diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs index 18b22827bdb15..0ab1b9dfb61e9 100644 --- a/src/tools/miri/src/intrinsics/mod.rs +++ b/src/tools/miri/src/intrinsics/mod.rs @@ -152,8 +152,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // ``` // Would not be considered UB, or the other way around (`is_val_statically_known(0)`). "is_val_statically_known" => { - let [arg] = check_arg_count(args)?; - this.validate_operand(arg, /*recursive*/ false)?; + let [_arg] = check_arg_count(args)?; + // FIXME: should we check for validity here? It's tricky because we do not have a + // place. Codegen does not seem to set any attributes like `noundef` for intrinsic + // calls, so we don't *have* to do anything. let branch: bool = this.machine.rng.get_mut().gen(); this.write_scalar(Scalar::from_bool(branch), dest)?; } diff --git a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance0.rs b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance0.rs new file mode 100644 index 0000000000000..fd0773ed916b7 --- /dev/null +++ b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance0.rs @@ -0,0 +1,10 @@ +use std::mem; + +// Doing a copy at integer type should lose provenance. +// This tests the unoptimized base case. +fn main() { + let ptrs = [(&42, true)]; + let ints: [(usize, bool); 1] = unsafe { mem::transmute(ptrs) }; + let ptr = (&raw const ints[0].0).cast::<&i32>(); + let _val = unsafe { *ptr.read() }; //~ERROR: dangling +} diff --git a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance0.stderr b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance0.stderr new file mode 100644 index 0000000000000..fc012af3ad877 --- /dev/null +++ b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance0.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: constructing invalid value: encountered a dangling reference ($HEX[noalloc] has no provenance) + --> $DIR/int_copy_looses_provenance0.rs:LL:CC + | +LL | let _val = unsafe { *ptr.read() }; + | ^^^^^^^^^^ constructing invalid value: encountered a dangling reference ($HEX[noalloc] has no provenance) + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/int_copy_looses_provenance0.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance1.rs b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance1.rs new file mode 100644 index 0000000000000..ce64dcc1a07c4 --- /dev/null +++ b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance1.rs @@ -0,0 +1,10 @@ +use std::mem; + +// Doing a copy at integer type should lose provenance. +// This tests the optimized-array case of integer copies. +fn main() { + let ptrs = [&42]; + let ints: [usize; 1] = unsafe { mem::transmute(ptrs) }; + let ptr = (&raw const ints[0]).cast::<&i32>(); + let _val = unsafe { *ptr.read() }; //~ERROR: dangling +} diff --git a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance1.stderr b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance1.stderr new file mode 100644 index 0000000000000..375262655d0cf --- /dev/null +++ b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance1.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: constructing invalid value: encountered a dangling reference ($HEX[noalloc] has no provenance) + --> $DIR/int_copy_looses_provenance1.rs:LL:CC + | +LL | let _val = unsafe { *ptr.read() }; + | ^^^^^^^^^^ constructing invalid value: encountered a dangling reference ($HEX[noalloc] has no provenance) + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/int_copy_looses_provenance1.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance2.rs b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance2.rs new file mode 100644 index 0000000000000..e8966c53d7059 --- /dev/null +++ b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance2.rs @@ -0,0 +1,12 @@ +use std::mem; + +// Doing a copy at integer type should lose provenance. +// This tests the case where provenacne is hiding in the metadata of a pointer. +fn main() { + let ptrs = [(&42, &42)]; + // Typed copy at wide pointer type (with integer-typed metadata). + let ints: [*const [usize]; 1] = unsafe { mem::transmute(ptrs) }; + // Get a pointer to the metadata field. + let ptr = (&raw const ints[0]).wrapping_byte_add(mem::size_of::<*const ()>()).cast::<&i32>(); + let _val = unsafe { *ptr.read() }; //~ERROR: dangling +} diff --git a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance2.stderr b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance2.stderr new file mode 100644 index 0000000000000..8402c7b5e130f --- /dev/null +++ b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance2.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: constructing invalid value: encountered a dangling reference ($HEX[noalloc] has no provenance) + --> $DIR/int_copy_looses_provenance2.rs:LL:CC + | +LL | let _val = unsafe { *ptr.read() }; + | ^^^^^^^^^^ constructing invalid value: encountered a dangling reference ($HEX[noalloc] has no provenance) + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/int_copy_looses_provenance2.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance3.rs b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance3.rs new file mode 100644 index 0000000000000..48a48ce4587ee --- /dev/null +++ b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance3.rs @@ -0,0 +1,29 @@ +#![feature(strict_provenance)] +use std::mem; + +#[repr(C, usize)] +#[allow(unused)] +enum E { + Var1(usize), + Var2(usize), +} + +// Doing a copy at integer type should lose provenance. +// This tests the case where provenacne is hiding in the discriminant of an enum. +fn main() { + assert_eq!(mem::size_of::(), 2*mem::size_of::()); + + // We want to store provenance in the enum discriminant, but the value still needs to + // be valid atfor the type. So we split provenance and data. + let ptr = &42; + let ptr = ptr as *const i32; + let ptrs = [(ptr.with_addr(0), ptr)]; + // Typed copy at the enum type. + let ints: [E; 1] = unsafe { mem::transmute(ptrs) }; + // Read the discriminant. + let discr = unsafe { (&raw const ints[0]).cast::<*const i32>().read() }; + // Take the provenance from there, together with the original address. + let ptr = discr.with_addr(ptr.addr()); + // There should be no provenance is `discr`, so this should be UB. + let _val = unsafe { *ptr }; //~ERROR: dangling +} diff --git a/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance3.stderr b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance3.stderr new file mode 100644 index 0000000000000..b50e23da96a7e --- /dev/null +++ b/src/tools/miri/tests/fail/provenance/int_copy_looses_provenance3.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: memory access failed: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance) + --> $DIR/int_copy_looses_provenance3.rs:LL:CC + | +LL | let _val = unsafe { *ptr }; + | ^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance) + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/int_copy_looses_provenance3.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance0.rs b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance0.rs new file mode 100644 index 0000000000000..0c6666b424e55 --- /dev/null +++ b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance0.rs @@ -0,0 +1,17 @@ +fn main() { + unsafe { + let mut bytes = [1u8; 16]; + let bytes = bytes.as_mut_ptr(); + + // Put a pointer in the middle. + bytes.add(4).cast::<&i32>().write_unaligned(&42); + // Typed copy of the entire thing as two pointers, but not perfectly + // overlapping with the pointer we have in there. + let copy = bytes.cast::<[*const (); 2]>().read_unaligned(); + let copy_bytes = copy.as_ptr().cast::(); + // Now go to the middle of the copy and get the pointer back out. + let ptr = copy_bytes.add(4).cast::<*const i32>().read_unaligned(); + // Dereferencing this should fail as the copy has removed the provenance. + let _val = *ptr; //~ERROR: dangling + } +} diff --git a/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance0.stderr b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance0.stderr new file mode 100644 index 0000000000000..ed38572a5f398 --- /dev/null +++ b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance0.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: memory access failed: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance) + --> $DIR/ptr_copy_loses_partial_provenance0.rs:LL:CC + | +LL | let _val = *ptr; + | ^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance) + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/ptr_copy_loses_partial_provenance0.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance1.rs b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance1.rs new file mode 100644 index 0000000000000..30d826413d2f9 --- /dev/null +++ b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance1.rs @@ -0,0 +1,17 @@ +fn main() { + unsafe { + let mut bytes = [1u8; 16]; + let bytes = bytes.as_mut_ptr(); + + // Put a pointer in the middle. + bytes.add(4).cast::<&i32>().write_unaligned(&42); + // Typed copy of the entire thing as two *function* pointers, but not perfectly + // overlapping with the pointer we have in there. + let copy = bytes.cast::<[fn(); 2]>().read_unaligned(); + let copy_bytes = copy.as_ptr().cast::(); + // Now go to the middle of the copy and get the pointer back out. + let ptr = copy_bytes.add(4).cast::<*const i32>().read_unaligned(); + // Dereferencing this should fail as the copy has removed the provenance. + let _val = *ptr; //~ERROR: dangling + } +} diff --git a/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance1.stderr b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance1.stderr new file mode 100644 index 0000000000000..2e11687175afe --- /dev/null +++ b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance1.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: memory access failed: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance) + --> $DIR/ptr_copy_loses_partial_provenance1.rs:LL:CC + | +LL | let _val = *ptr; + | ^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance) + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/ptr_copy_loses_partial_provenance1.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/pass/provenance.rs b/src/tools/miri/tests/pass/provenance.rs index 9e8a9651b3d96..2e4d240cc48a1 100644 --- a/src/tools/miri/tests/pass/provenance.rs +++ b/src/tools/miri/tests/pass/provenance.rs @@ -12,6 +12,7 @@ fn main() { bytewise_custom_memcpy(); bytewise_custom_memcpy_chunked(); int_load_strip_provenance(); + maybe_uninit_preserves_partial_provenance(); } /// Some basic smoke tests for provenance. @@ -145,3 +146,24 @@ fn int_load_strip_provenance() { let ints: [usize; 1] = unsafe { mem::transmute(ptrs) }; assert_eq!(ptrs[0] as *const _ as usize, ints[0]); } + +fn maybe_uninit_preserves_partial_provenance() { + // This is the same test as ptr_copy_loses_partial_provenance.rs, but using MaybeUninit and thus + // properly preserving partial provenance. + unsafe { + let mut bytes = [1u8; 16]; + let bytes = bytes.as_mut_ptr(); + + // Put a pointer in the middle. + bytes.add(4).cast::<&i32>().write_unaligned(&42); + // Copy the entire thing as two pointers but not perfectly + // overlapping with the pointer we have in there. + let copy = bytes.cast::<[mem::MaybeUninit<*const ()>; 2]>().read_unaligned(); + let copy_bytes = copy.as_ptr().cast::(); + // Now go to the middle of the copy and get the pointer back out. + let ptr = copy_bytes.add(4).cast::<*const i32>().read_unaligned(); + // And deref this to ensure we get the right value. + let val = *ptr; + assert_eq!(val, 42); + } +} From 8cd982caa1221c54dbdb036083d659c619024d45 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 29 Aug 2024 19:24:31 +0200 Subject: [PATCH 061/189] interpret: reset padding during validation --- .../src/const_eval/machine.rs | 27 +- .../rustc_const_eval/src/interpret/machine.rs | 12 +- .../rustc_const_eval/src/interpret/memory.rs | 11 +- .../rustc_const_eval/src/interpret/mod.rs | 2 +- .../rustc_const_eval/src/interpret/place.rs | 17 +- .../src/interpret/validity.rs | 287 ++++++++++++++++-- .../rustc_const_eval/src/interpret/visitor.rs | 12 + .../src/util/check_validity_requirement.rs | 2 +- src/tools/miri/src/machine.rs | 13 + .../ptr_copy_loses_partial_provenance0.rs | 11 +- .../ptr_copy_loses_partial_provenance1.rs | 11 +- .../miri/tests/fail/uninit/padding-enum.rs | 23 ++ .../tests/fail/uninit/padding-enum.stderr | 15 + .../miri/tests/fail/uninit/padding-pair.rs | 25 ++ .../tests/fail/uninit/padding-pair.stderr | 15 + .../fail/uninit/padding-struct-in-union.rs | 32 ++ .../uninit/padding-struct-in-union.stderr | 15 + .../miri/tests/fail/uninit/padding-struct.rs | 11 + .../tests/fail/uninit/padding-struct.stderr | 15 + .../miri/tests/fail/uninit/padding-union.rs | 14 + .../tests/fail/uninit/padding-union.stderr | 15 + .../{ => uninit}/transmute-pair-uninit.rs | 11 +- .../{ => uninit}/transmute-pair-uninit.stderr | 0 src/tools/miri/tests/pass/enums.rs | 38 +++ 24 files changed, 584 insertions(+), 50 deletions(-) create mode 100644 src/tools/miri/tests/fail/uninit/padding-enum.rs create mode 100644 src/tools/miri/tests/fail/uninit/padding-enum.stderr create mode 100644 src/tools/miri/tests/fail/uninit/padding-pair.rs create mode 100644 src/tools/miri/tests/fail/uninit/padding-pair.stderr create mode 100644 src/tools/miri/tests/fail/uninit/padding-struct-in-union.rs create mode 100644 src/tools/miri/tests/fail/uninit/padding-struct-in-union.stderr create mode 100644 src/tools/miri/tests/fail/uninit/padding-struct.rs create mode 100644 src/tools/miri/tests/fail/uninit/padding-struct.stderr create mode 100644 src/tools/miri/tests/fail/uninit/padding-union.rs create mode 100644 src/tools/miri/tests/fail/uninit/padding-union.stderr rename src/tools/miri/tests/fail/{ => uninit}/transmute-pair-uninit.rs (61%) rename src/tools/miri/tests/fail/{ => uninit}/transmute-pair-uninit.stderr (100%) diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 9c1fef095f552..7405ca09342da 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -1,16 +1,16 @@ -use std::borrow::Borrow; +use std::borrow::{Borrow, Cow}; use std::fmt; use std::hash::Hash; use std::ops::ControlFlow; use rustc_ast::Mutability; -use rustc_data_structures::fx::{FxIndexMap, IndexEntry}; +use rustc_data_structures::fx::{FxHashMap, FxIndexMap, IndexEntry}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{self as hir, LangItem, CRATE_HIR_ID}; use rustc_middle::mir::AssertMessage; use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::layout::{FnAbiOf, TyAndLayout}; -use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::{bug, mir}; use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; @@ -24,8 +24,8 @@ use crate::fluent_generated as fluent; use crate::interpret::{ self, compile_time_machine, err_ub, throw_exhaust, throw_inval, throw_ub_custom, throw_unsup, throw_unsup_format, AllocId, AllocRange, ConstAllocation, CtfeProvenance, FnArg, Frame, - GlobalAlloc, ImmTy, InterpCx, InterpResult, MPlaceTy, OpTy, Pointer, PointerArithmetic, Scalar, - StackPopCleanup, + GlobalAlloc, ImmTy, InterpCx, InterpResult, MPlaceTy, OpTy, Pointer, PointerArithmetic, + RangeSet, Scalar, StackPopCleanup, }; /// When hitting this many interpreted terminators we emit a deny by default lint @@ -65,6 +65,9 @@ pub struct CompileTimeMachine<'tcx> { /// storing the result in the given `AllocId`. /// Used to prevent reads from a static's base allocation, as that may allow for self-initialization loops. pub(crate) static_root_ids: Option<(AllocId, LocalDefId)>, + + /// A cache of "data range" computations for unions (i.e., the offsets of non-padding bytes). + union_data_ranges: FxHashMap, RangeSet>, } #[derive(Copy, Clone)] @@ -99,6 +102,7 @@ impl<'tcx> CompileTimeMachine<'tcx> { can_access_mut_global, check_alignment, static_root_ids: None, + union_data_ranges: FxHashMap::default(), } } } @@ -766,6 +770,19 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { } Ok(()) } + + fn cached_union_data_range<'e>( + ecx: &'e mut InterpCx<'tcx, Self>, + ty: Ty<'tcx>, + compute_range: impl FnOnce() -> RangeSet, + ) -> Cow<'e, RangeSet> { + if ecx.tcx.sess.opts.unstable_opts.extra_const_ub_checks { + Cow::Borrowed(ecx.machine.union_data_ranges.entry(ty).or_insert_with(compute_range)) + } else { + // Don't bother caching, we're only doing one validation at the end anyway. + Cow::Owned(compute_range()) + } + } } // Please do not add any code below the above `Machine` trait impl. I (oli-obk) plan more cleanups diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 6cfd7be48e624..8cab3c34eedfb 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -10,6 +10,7 @@ use rustc_apfloat::{Float, FloatConvert}; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::layout::TyAndLayout; +use rustc_middle::ty::Ty; use rustc_middle::{mir, ty}; use rustc_span::def_id::DefId; use rustc_span::Span; @@ -19,7 +20,7 @@ use rustc_target::spec::abi::Abi as CallAbi; use super::{ throw_unsup, throw_unsup_format, AllocBytes, AllocId, AllocKind, AllocRange, Allocation, ConstAllocation, CtfeProvenance, FnArg, Frame, ImmTy, InterpCx, InterpResult, MPlaceTy, - MemoryKind, Misalignment, OpTy, PlaceTy, Pointer, Provenance, CTFE_ALLOC_SALT, + MemoryKind, Misalignment, OpTy, PlaceTy, Pointer, Provenance, RangeSet, CTFE_ALLOC_SALT, }; /// Data returned by [`Machine::after_stack_pop`], and consumed by @@ -578,6 +579,15 @@ pub trait Machine<'tcx>: Sized { ecx: &InterpCx<'tcx, Self>, instance: Option>, ) -> usize; + + fn cached_union_data_range<'e>( + _ecx: &'e mut InterpCx<'tcx, Self>, + _ty: Ty<'tcx>, + compute_range: impl FnOnce() -> RangeSet, + ) -> Cow<'e, RangeSet> { + // Default to no caching. + Cow::Owned(compute_range()) + } } /// A lot of the flexibility above is just needed for `Miri`, but all "compile-time" machines diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 53a9cd0b9ad6d..d87588496c0bd 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -1136,8 +1136,17 @@ impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes> self.write_scalar(alloc_range(offset, self.tcx.data_layout().pointer_size), val) } + /// Mark the given sub-range (relative to this allocation reference) as uninitialized. + pub fn write_uninit(&mut self, range: AllocRange) -> InterpResult<'tcx> { + let range = self.range.subrange(range); + Ok(self + .alloc + .write_uninit(&self.tcx, range) + .map_err(|e| e.to_interp_error(self.alloc_id))?) + } + /// Mark the entire referenced range as uninitialized - pub fn write_uninit(&mut self) -> InterpResult<'tcx> { + pub fn write_uninit_full(&mut self) -> InterpResult<'tcx> { Ok(self .alloc .write_uninit(&self.tcx, self.range) diff --git a/compiler/rustc_const_eval/src/interpret/mod.rs b/compiler/rustc_const_eval/src/interpret/mod.rs index c1e46cc3a15b4..561d681f804a1 100644 --- a/compiler/rustc_const_eval/src/interpret/mod.rs +++ b/compiler/rustc_const_eval/src/interpret/mod.rs @@ -39,5 +39,5 @@ use self::place::{MemPlace, Place}; pub use self::projection::{OffsetMode, Projectable}; pub use self::stack::{Frame, FrameInfo, LocalState, StackPopCleanup, StackPopInfo}; pub(crate) use self::util::create_static_alloc; -pub use self::validity::{CtfeValidationMode, RefTracking}; +pub use self::validity::{CtfeValidationMode, RangeSet, RefTracking}; pub use self::visitor::ValueVisitor; diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index e2aef0519186e..3b14142da02ed 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -604,10 +604,11 @@ where if M::enforce_validity(self, dest.layout()) { // Data got changed, better make sure it matches the type! + // Also needed to reset padding. self.validate_operand( &dest.to_place(), M::enforce_validity_recursively(self, dest.layout()), - /*reset_provenance*/ true, + /*reset_provenance_and_padding*/ true, )?; } @@ -703,9 +704,11 @@ where // fields do not match the `ScalarPair` components. alloc.write_scalar(alloc_range(Size::ZERO, a_val.size()), a_val)?; - alloc.write_scalar(alloc_range(b_offset, b_val.size()), b_val) + alloc.write_scalar(alloc_range(b_offset, b_val.size()), b_val)?; + // We don't have to reset padding here, `write_immediate` will anyway do a validation run. + Ok(()) } - Immediate::Uninit => alloc.write_uninit(), + Immediate::Uninit => alloc.write_uninit_full(), } } @@ -722,7 +725,7 @@ where // Zero-sized access return Ok(()); }; - alloc.write_uninit()?; + alloc.write_uninit_full()?; } } Ok(()) @@ -814,17 +817,17 @@ where // Given that there were two typed copies, we have to ensure this is valid at both types, // and we have to ensure this loses provenance and padding according to both types. // But if the types are identical, we only do one pass. - if src.layout().ty != dest.layout().ty { + if allow_transmute && src.layout().ty != dest.layout().ty { self.validate_operand( &dest.transmute(src.layout(), self)?, M::enforce_validity_recursively(self, src.layout()), - /*reset_provenance*/ true, + /*reset_provenance_and_padding*/ true, )?; } self.validate_operand( &dest, M::enforce_validity_recursively(self, dest.layout()), - /*reset_provenance*/ true, + /*reset_provenance_and_padding*/ true, )?; } diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 953831a55e5ed..806ebb9dfed4d 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -4,6 +4,7 @@ //! That's useful because it means other passes (e.g. promotion) can rely on `const`s //! to be const-safe. +use std::borrow::Cow; use std::fmt::Write; use std::hash::Hash; use std::num::NonZero; @@ -16,14 +17,14 @@ use rustc_hir as hir; use rustc_middle::bug; use rustc_middle::mir::interpret::ValidationErrorKind::{self, *}; use rustc_middle::mir::interpret::{ - ExpectedKind, InterpError, InvalidMetaKind, Misalignment, PointerKind, Provenance, + alloc_range, ExpectedKind, InterpError, InvalidMetaKind, Misalignment, PointerKind, Provenance, UnsupportedOpInfo, ValidationErrorInfo, }; -use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::symbol::{sym, Symbol}; use rustc_target::abi::{ - Abi, FieldIdx, Scalar as ScalarAbi, Size, VariantIdx, Variants, WrappingRange, + Abi, FieldIdx, FieldsShape, Scalar as ScalarAbi, Size, VariantIdx, Variants, WrappingRange, }; use tracing::trace; @@ -125,6 +126,7 @@ pub enum PathElem { EnumTag, CoroutineTag, DynDowncast, + Vtable, } /// Extra things to check for during validation of CTFE results. @@ -204,11 +206,58 @@ fn write_path(out: &mut String, path: &[PathElem]) { // not the root. Deref => write!(out, "."), DynDowncast => write!(out, "."), + Vtable => write!(out, "."), } .unwrap() } } +/// Represents a set of `Size` values as a sorted list of ranges. +// These are (offset, length) pairs, and they are sorted and mutually disjoint, +// and never adjacent (i.e. there's always a gap between two of them). +#[derive(Debug, Clone)] +pub struct RangeSet(Vec<(Size, Size)>); + +impl RangeSet { + fn add_range(&mut self, offset: Size, size: Size) { + let v = &mut self.0; + // We scan for a partition point where the left partition is all the elements that end + // strictly before we start. Those are elements that are too "low" to merge with us. + let idx = + v.partition_point(|&(other_offset, other_size)| other_offset + other_size < offset); + // Now we want to either merge with the first element of the second partition, or insert ourselves before that. + if let Some(&(other_offset, other_size)) = v.get(idx) + && offset + size >= other_offset + { + // Their end is >= our start (otherwise it would not be in the 2nd partition) and + // our end is >= their start. This means we can merge the ranges. + let new_start = other_offset.min(offset); + let mut new_end = (other_offset + other_size).max(offset + size); + // We grew to the right, so merge with overlapping/adjacent elements. + // (We also may have grown to the left, but that can never make us adjacent with + // anything there since we selected the first such candidate via `partition_point`.) + let mut scan_right = 1; + while let Some(&(next_offset, next_size)) = v.get(idx + scan_right) + && new_end >= next_offset + { + // Increase our size to absorb the next element. + new_end = new_end.max(next_offset + next_size); + // Look at the next element. + scan_right += 1; + } + // Update the element we grew. + v[idx] = (new_start, new_end - new_start); + // Remove the elements we absorbed (if any). + if scan_right > 1 { + drop(v.drain((idx + 1)..(idx + scan_right))); + } + } else { + // Insert new element. + v.insert(idx, (offset, size)); + } + } +} + struct ValidityVisitor<'rt, 'tcx, M: Machine<'tcx>> { /// The `path` may be pushed to, but the part that is present when a function /// starts must not be changed! `visit_fields` and `visit_array` rely on @@ -220,7 +269,14 @@ struct ValidityVisitor<'rt, 'tcx, M: Machine<'tcx>> { ecx: &'rt mut InterpCx<'tcx, M>, /// Whether provenance should be reset outside of pointers (emulating the effect of a typed /// copy). - reset_provenance: bool, + reset_provenance_and_padding: bool, + /// This tracks which byte ranges in this value contain data; the remaining bytes are padding. + /// The ideal representation here would be pointer-length pairs, but to keep things more compact + /// we only store a (range) set of offsets -- the base pointer is the same throughout the entire + /// visit, after all. + /// If this is `Some`, then `reset_provenance_and_padding` must be true (but not vice versa: + /// we might not track data vs padding bytes if the operand isn't stored in memory anyway). + data_bytes: Option, } impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { @@ -290,8 +346,14 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { // arrays/slices ty::Array(..) | ty::Slice(..) => PathElem::ArrayElem(field), + // dyn* vtables + ty::Dynamic(_, _, ty::DynKind::DynStar) if field == 1 => PathElem::Vtable, + // dyn traits - ty::Dynamic(..) => PathElem::DynDowncast, + ty::Dynamic(..) => { + assert_eq!(field, 0); + PathElem::DynDowncast + } // nothing else has an aggregate layout _ => bug!("aggregate_field_path_elem: got non-aggregate type {:?}", layout.ty), @@ -350,7 +412,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { let imm = self.read_immediate(val, expected)?; // Reset provenance: ensure slice tail metadata does not preserve provenance, // and ensure all pointers do not preserve partial provenance. - if self.reset_provenance { + if self.reset_provenance_and_padding { if matches!(imm.layout.abi, Abi::Scalar(..)) { // A thin pointer. If it has provenance, we don't have to do anything. // If it does not, ensure we clear the provenance in memory. @@ -364,6 +426,8 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { // is a perf hotspot it's just not worth the effort. self.ecx.write_immediate_no_validate(*imm, val)?; } + // The entire thing is data, not padding. + self.add_data_range_place(val); } // Now turn it into a place. self.ecx.ref_to_mplace(&imm) @@ -608,8 +672,9 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { value: format!("{scalar:x}"), } ); - if self.reset_provenance { + if self.reset_provenance_and_padding { self.ecx.clear_provenance(value)?; + self.add_data_range_place(value); } Ok(true) } @@ -622,8 +687,9 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { value: format!("{scalar:x}"), } ); - if self.reset_provenance { + if self.reset_provenance_and_padding { self.ecx.clear_provenance(value)?; + self.add_data_range_place(value); } Ok(true) } @@ -638,8 +704,9 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { ExpectedKind::Int }, )?; - if self.reset_provenance { + if self.reset_provenance_and_padding { self.ecx.clear_provenance(value)?; + self.add_data_range_place(value); } Ok(true) } @@ -673,12 +740,13 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { throw_validation_failure!(self.path, NullFnPtr); } } - if self.reset_provenance { + if self.reset_provenance_and_padding { // Make sure we do not preserve partial provenance. This matches the thin // pointer handling in `deref_pointer`. if matches!(scalar, Scalar::Int(..)) { self.ecx.clear_provenance(value)?; } + self.add_data_range_place(value); } Ok(true) } @@ -774,6 +842,155 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { true } } + + /// Add the given pointer-length pair to the "data" range of this visit. + fn add_data_range(&mut self, ptr: Pointer>, size: Size) { + if let Some(data_bytes) = self.data_bytes.as_mut() { + // We only have to store the offset, the rest is the same for all pointers here. + let (_prov, offset) = ptr.into_parts(); + // Add this. + data_bytes.add_range(offset, size); + }; + } + + /// Add the entire given place to the "data" range of this visit. + fn add_data_range_place(&mut self, place: &PlaceTy<'tcx, M::Provenance>) { + // Only sized places can be added this way. + debug_assert!(place.layout.abi.is_sized()); + if let Some(data_bytes) = self.data_bytes.as_mut() { + let offset = Self::data_range_offset(self.ecx, place); + data_bytes.add_range(offset, place.layout.size); + } + } + + /// Convert a place into the offset it starts at, for the purpose of data_range tracking. + /// Must only be called if `data_bytes` is `Some(_)`. + fn data_range_offset(ecx: &InterpCx<'tcx, M>, place: &PlaceTy<'tcx, M::Provenance>) -> Size { + // The presence of `data_bytes` implies that our place is in memory. + let ptr = ecx + .place_to_op(place) + .expect("place must be in memory") + .as_mplace_or_imm() + .expect_left("place must be in memory") + .ptr(); + let (_prov, offset) = ptr.into_parts(); + offset + } + + fn reset_padding(&mut self, place: &PlaceTy<'tcx, M::Provenance>) -> InterpResult<'tcx> { + let Some(data_bytes) = self.data_bytes.as_mut() else { return Ok(()) }; + // Our value must be in memory, otherwise we would not have set up `data_bytes`. + let mplace = self.ecx.force_allocation(place)?; + // Determine starting offset and size. + let (_prov, start_offset) = mplace.ptr().into_parts(); + let (size, _align) = self + .ecx + .size_and_align_of_mplace(&mplace)? + .unwrap_or((mplace.layout.size, mplace.layout.align.abi)); + // If there is no padding at all, we can skip the rest: check for + // a single data range covering the entire value. + if data_bytes.0 == &[(start_offset, size)] { + return Ok(()); + } + // Get a handle for the allocation. Do this only once, to avoid looking up the same + // allocation over and over again. (Though to be fair, iterating the value already does + // exactly that.) + let Some(mut alloc) = self.ecx.get_ptr_alloc_mut(mplace.ptr(), size)? else { + // A ZST, no padding to clear. + return Ok(()); + }; + // Add a "finalizer" data range at the end, so that the iteration below finds all gaps + // between ranges. + data_bytes.0.push((start_offset + size, Size::ZERO)); + // Iterate, and reset gaps. + let mut padding_cleared_until = start_offset; + for &(offset, size) in data_bytes.0.iter() { + assert!( + offset >= padding_cleared_until, + "reset_padding on {}: previous field ended at offset {}, next field starts at {} (and has a size of {} bytes)", + mplace.layout.ty, + (padding_cleared_until - start_offset).bytes(), + (offset - start_offset).bytes(), + size.bytes(), + ); + if offset > padding_cleared_until { + // We found padding. Adjust the range to be relative to `alloc`, and make it uninit. + let padding_start = padding_cleared_until - start_offset; + let padding_size = offset - padding_cleared_until; + let range = alloc_range(padding_start, padding_size); + trace!("reset_padding on {}: resetting padding range {range:?}", mplace.layout.ty); + alloc.write_uninit(range)?; + } + padding_cleared_until = offset + size; + } + assert!(padding_cleared_until == start_offset + size); + Ok(()) + } + + /// Computes the data range of this union type: + /// which bytes are inside a field (i.e., not padding.) + fn union_data_range<'e>( + ecx: &'e mut InterpCx<'tcx, M>, + layout: TyAndLayout<'tcx>, + ) -> Cow<'e, RangeSet> { + assert!(layout.ty.is_union()); + assert!(layout.abi.is_sized(), "there are no unsized unions"); + let layout_cx = LayoutCx { tcx: *ecx.tcx, param_env: ecx.param_env }; + return M::cached_union_data_range(ecx, layout.ty, || { + let mut out = RangeSet(Vec::new()); + union_data_range_(&layout_cx, layout, Size::ZERO, &mut out); + out + }); + + /// Helper for recursive traversal: add data ranges of the given type to `out`. + fn union_data_range_<'tcx>( + cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, + layout: TyAndLayout<'tcx>, + base_offset: Size, + out: &mut RangeSet, + ) { + // Just recursively add all the fields of everything to the output. + match &layout.fields { + FieldsShape::Primitive => { + out.add_range(base_offset, layout.size); + } + &FieldsShape::Union(fields) => { + // Currently, all fields start at offset 0. + for field in 0..fields.get() { + let field = layout.field(cx, field); + union_data_range_(cx, field, base_offset, out); + } + } + &FieldsShape::Array { stride, count } => { + let elem = layout.field(cx, 0); + for idx in 0..count { + // This repeats the same computation for every array elements... but the alternative + // is to allocate temporary storage for a dedicated `out` set for the array element, + // and replicating that N times. Is that better? + union_data_range_(cx, elem, base_offset + idx * stride, out); + } + } + FieldsShape::Arbitrary { offsets, .. } => { + for (field, &offset) in offsets.iter_enumerated() { + let field = layout.field(cx, field.as_usize()); + union_data_range_(cx, field, base_offset + offset, out); + } + } + } + // Don't forget potential other variants. + match &layout.variants { + Variants::Single { .. } => { + // Fully handled above. + } + Variants::Multiple { variants, .. } => { + for variant in variants.indices() { + let variant = layout.for_variant(cx, variant); + union_data_range_(cx, variant, base_offset, out); + } + } + } + } + } } /// Returns whether the allocation is mutable, and whether it's actually a static. @@ -890,6 +1107,16 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, } } } + if self.reset_provenance_and_padding + && let Some(data_bytes) = self.data_bytes.as_mut() + { + let base_offset = Self::data_range_offset(self.ecx, val); + // Determine and add data range for this union. + let union_data_range = Self::union_data_range(self.ecx, val.layout); + for &(offset, size) in union_data_range.0.iter() { + data_bytes.add_range(base_offset + offset, size); + } + } Ok(()) } @@ -1013,10 +1240,12 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, // Don't forget that these are all non-pointer types, and thus do not preserve // provenance. - if self.reset_provenance { + if self.reset_provenance_and_padding { // We can't share this with above as above, we might be looking at read-only memory. let mut alloc = self.ecx.get_ptr_alloc_mut(mplace.ptr(), size)?.expect("we already excluded size 0"); alloc.clear_provenance()?; + // Also, mark this as containing data, not padding. + self.add_data_range(mplace.ptr(), size); } } // Fast path for arrays and slices of ZSTs. We only need to check a single ZST element @@ -1096,14 +1325,28 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { path: Vec, ref_tracking: Option<&mut RefTracking, Vec>>, ctfe_mode: Option, - reset_provenance: bool, + reset_provenance_and_padding: bool, ) -> InterpResult<'tcx> { trace!("validate_operand_internal: {:?}, {:?}", *val, val.layout.ty); // Run the visitor. match self.run_for_validation(|ecx| { - let mut v = ValidityVisitor { path, ref_tracking, ctfe_mode, ecx, reset_provenance }; - v.visit_value(val) + let reset_padding = reset_provenance_and_padding && { + // Check if `val` is actually stored in memory. If not, padding is not even + // represented and we need not reset it. + ecx.place_to_op(val)?.as_mplace_or_imm().is_left() + }; + let mut v = ValidityVisitor { + path, + ref_tracking, + ctfe_mode, + ecx, + reset_provenance_and_padding, + data_bytes: reset_padding.then_some(RangeSet(Vec::new())), + }; + v.visit_value(val)?; + v.reset_padding(val)?; + InterpResult::Ok(()) }) { Ok(()) => Ok(()), // Pass through validation failures and "invalid program" issues. @@ -1163,13 +1406,19 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { &mut self, val: &PlaceTy<'tcx, M::Provenance>, recursive: bool, - reset_provenance: bool, + reset_provenance_and_padding: bool, ) -> InterpResult<'tcx> { // Note that we *could* actually be in CTFE here with `-Zextra-const-ub-checks`, but it's // still correct to not use `ctfe_mode`: that mode is for validation of the final constant // value, it rules out things like `UnsafeCell` in awkward places. if !recursive { - return self.validate_operand_internal(val, vec![], None, None, reset_provenance); + return self.validate_operand_internal( + val, + vec![], + None, + None, + reset_provenance_and_padding, + ); } // Do a recursive check. let mut ref_tracking = RefTracking::empty(); @@ -1178,7 +1427,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { vec![], Some(&mut ref_tracking), None, - reset_provenance, + reset_provenance_and_padding, )?; while let Some((mplace, path)) = ref_tracking.todo.pop() { // Things behind reference do *not* have the provenance reset. @@ -1187,7 +1436,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { path, Some(&mut ref_tracking), None, - /*reset_provenance*/ false, + /*reset_provenance_and_padding*/ false, )?; } Ok(()) diff --git a/compiler/rustc_const_eval/src/interpret/visitor.rs b/compiler/rustc_const_eval/src/interpret/visitor.rs index 08b39fe8751be..d8af67bd0e705 100644 --- a/compiler/rustc_const_eval/src/interpret/visitor.rs +++ b/compiler/rustc_const_eval/src/interpret/visitor.rs @@ -5,6 +5,7 @@ use std::num::NonZero; use rustc_index::IndexVec; use rustc_middle::mir::interpret::InterpResult; +use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Ty}; use rustc_target::abi::{FieldIdx, FieldsShape, VariantIdx, Variants}; use tracing::trace; @@ -105,6 +106,17 @@ pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized { // DynStar types. Very different from a dyn type (but strangely part of the // same variant in `TyKind`): These are pairs where the 2nd component is the // vtable, and the first component is the data (which must be ptr-sized). + + // First make sure the vtable can be read at its type. + // The type of this vtable is fake, it claims to be a reference to some actual memory but that isn't true. + // So we transmute it to a raw pointer. + let raw_ptr_ty = Ty::new_mut_ptr(*self.ecx().tcx, self.ecx().tcx.types.unit); + let raw_ptr_ty = self.ecx().layout_of(raw_ptr_ty)?; + let vtable_field = + self.ecx().project_field(v, 1)?.transmute(raw_ptr_ty, self.ecx())?; + self.visit_field(v, 1, &vtable_field)?; + + // Then unpack the first field, and continue. let data = self.ecx().unpack_dyn_star(v, data)?; return self.visit_field(v, 0, &data); } diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs index 5e424190d07dd..26fd59bc6ef77 100644 --- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs +++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs @@ -69,7 +69,7 @@ fn might_permit_raw_init_strict<'tcx>( .validate_operand( &allocated.into(), /*recursive*/ false, - /*reset_provenance*/ false, + /*reset_provenance_and_padding*/ false, ) .is_ok()) } diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 66c6966d1a6c3..d1267cd68668a 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -572,6 +572,9 @@ pub struct MiriMachine<'tcx> { /// Invariant: the promised alignment will never be less than the native alignment of the /// allocation. pub(crate) symbolic_alignment: RefCell>, + + /// A cache of "data range" computations for unions (i.e., the offsets of non-padding bytes). + union_data_ranges: FxHashMap, RangeSet>, } impl<'tcx> MiriMachine<'tcx> { @@ -714,6 +717,7 @@ impl<'tcx> MiriMachine<'tcx> { allocation_spans: RefCell::new(FxHashMap::default()), const_cache: RefCell::new(FxHashMap::default()), symbolic_alignment: RefCell::new(FxHashMap::default()), + union_data_ranges: FxHashMap::default(), } } @@ -826,6 +830,7 @@ impl VisitProvenance for MiriMachine<'_> { allocation_spans: _, const_cache: _, symbolic_alignment: _, + union_data_ranges: _, } = self; threads.visit_provenance(visit); @@ -1627,4 +1632,12 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { ecx.machine.rng.borrow_mut().gen::() % ADDRS_PER_ANON_GLOBAL } } + + fn cached_union_data_range<'e>( + ecx: &'e mut InterpCx<'tcx, Self>, + ty: Ty<'tcx>, + compute_range: impl FnOnce() -> RangeSet, + ) -> Cow<'e, RangeSet> { + Cow::Borrowed(ecx.machine.union_data_ranges.entry(ty).or_insert_with(compute_range)) + } } diff --git a/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance0.rs b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance0.rs index 0c6666b424e55..ff94f2263c517 100644 --- a/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance0.rs +++ b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance0.rs @@ -1,16 +1,17 @@ fn main() { - unsafe { - let mut bytes = [1u8; 16]; - let bytes = bytes.as_mut_ptr(); + let half_ptr = std::mem::size_of::<*const ()>() / 2; + let mut bytes = [1u8; 16]; + let bytes = bytes.as_mut_ptr(); + unsafe { // Put a pointer in the middle. - bytes.add(4).cast::<&i32>().write_unaligned(&42); + bytes.add(half_ptr).cast::<&i32>().write_unaligned(&42); // Typed copy of the entire thing as two pointers, but not perfectly // overlapping with the pointer we have in there. let copy = bytes.cast::<[*const (); 2]>().read_unaligned(); let copy_bytes = copy.as_ptr().cast::(); // Now go to the middle of the copy and get the pointer back out. - let ptr = copy_bytes.add(4).cast::<*const i32>().read_unaligned(); + let ptr = copy_bytes.add(half_ptr).cast::<*const i32>().read_unaligned(); // Dereferencing this should fail as the copy has removed the provenance. let _val = *ptr; //~ERROR: dangling } diff --git a/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance1.rs b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance1.rs index 30d826413d2f9..d0e3dac7792b0 100644 --- a/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance1.rs +++ b/src/tools/miri/tests/fail/provenance/ptr_copy_loses_partial_provenance1.rs @@ -1,16 +1,17 @@ fn main() { - unsafe { - let mut bytes = [1u8; 16]; - let bytes = bytes.as_mut_ptr(); + let half_ptr = std::mem::size_of::<*const ()>() / 2; + let mut bytes = [1u8; 16]; + let bytes = bytes.as_mut_ptr(); + unsafe { // Put a pointer in the middle. - bytes.add(4).cast::<&i32>().write_unaligned(&42); + bytes.add(half_ptr).cast::<&i32>().write_unaligned(&42); // Typed copy of the entire thing as two *function* pointers, but not perfectly // overlapping with the pointer we have in there. let copy = bytes.cast::<[fn(); 2]>().read_unaligned(); let copy_bytes = copy.as_ptr().cast::(); // Now go to the middle of the copy and get the pointer back out. - let ptr = copy_bytes.add(4).cast::<*const i32>().read_unaligned(); + let ptr = copy_bytes.add(half_ptr).cast::<*const i32>().read_unaligned(); // Dereferencing this should fail as the copy has removed the provenance. let _val = *ptr; //~ERROR: dangling } diff --git a/src/tools/miri/tests/fail/uninit/padding-enum.rs b/src/tools/miri/tests/fail/uninit/padding-enum.rs new file mode 100644 index 0000000000000..0ab9be275815d --- /dev/null +++ b/src/tools/miri/tests/fail/uninit/padding-enum.rs @@ -0,0 +1,23 @@ +use std::mem; + +// We have three fields to avoid the ScalarPair optimization. +#[allow(unused)] +enum E { + None, + Some(&'static (), &'static (), usize), +} + +fn main() { unsafe { + let mut p: mem::MaybeUninit = mem::MaybeUninit::zeroed(); + // The copy when `E` is returned from `transmute` should destroy padding + // (even when we use `write_unaligned`, which under the hood uses an untyped copy). + p.as_mut_ptr().write_unaligned(mem::transmute((0usize, 0usize, 0usize))); + // This is a `None`, so everything but the discriminant is padding. + assert!(matches!(*p.as_ptr(), E::None)); + + // Turns out the discriminant is (currently) stored + // in the 2nd pointer, so the first half is padding. + let c = &p as *const _ as *const u8; + let _val = *c.add(0); // Get the padding byte. + //~^ERROR: uninitialized +} } diff --git a/src/tools/miri/tests/fail/uninit/padding-enum.stderr b/src/tools/miri/tests/fail/uninit/padding-enum.stderr new file mode 100644 index 0000000000000..a507a5d49bc2c --- /dev/null +++ b/src/tools/miri/tests/fail/uninit/padding-enum.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory + --> $DIR/padding-enum.rs:LL:CC + | +LL | let _val = *c.add(0); // Get the padding byte. + | ^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/padding-enum.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/uninit/padding-pair.rs b/src/tools/miri/tests/fail/uninit/padding-pair.rs new file mode 100644 index 0000000000000..c8c00b3c65a06 --- /dev/null +++ b/src/tools/miri/tests/fail/uninit/padding-pair.rs @@ -0,0 +1,25 @@ +#![feature(core_intrinsics)] + +use std::mem::{self, MaybeUninit}; + +fn main() { + // This constructs a `(usize, bool)` pair: 9 bytes initialized, the rest not. + // Ensure that these 9 bytes are indeed initialized, and the rest is indeed not. + // This should be the case even if we write into previously initialized storage. + let mut x: MaybeUninit> = MaybeUninit::zeroed(); + let z = std::intrinsics::add_with_overflow(0usize, 0usize); + unsafe { x.as_mut_ptr().cast::<(usize, bool)>().write(z) }; + // Now read this bytewise. There should be (`ptr_size + 1`) def bytes followed by + // (`ptr_size - 1`) undef bytes (the padding after the bool) in there. + let z: *const u8 = &x as *const _ as *const _; + let first_undef = mem::size_of::() as isize + 1; + for i in 0..first_undef { + let byte = unsafe { *z.offset(i) }; + assert_eq!(byte, 0); + } + let v = unsafe { *z.offset(first_undef) }; + //~^ ERROR: uninitialized + if v == 0 { + println!("it is zero"); + } +} diff --git a/src/tools/miri/tests/fail/uninit/padding-pair.stderr b/src/tools/miri/tests/fail/uninit/padding-pair.stderr new file mode 100644 index 0000000000000..d35934d83d58f --- /dev/null +++ b/src/tools/miri/tests/fail/uninit/padding-pair.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory + --> $DIR/padding-pair.rs:LL:CC + | +LL | let v = unsafe { *z.offset(first_undef) }; + | ^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/padding-pair.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/uninit/padding-struct-in-union.rs b/src/tools/miri/tests/fail/uninit/padding-struct-in-union.rs new file mode 100644 index 0000000000000..132b85828362d --- /dev/null +++ b/src/tools/miri/tests/fail/uninit/padding-struct-in-union.rs @@ -0,0 +1,32 @@ +#[repr(C)] +#[derive(Debug, Copy, Clone)] +struct Foo { + val16: u16, + // Padding bytes go here! + val32: u32, +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +struct Bar { + bytes: [u8; 8], +} + +#[repr(C)] +union FooBar { + foo: Foo, + bar: Bar, +} + +pub fn main() { + // Initialize as u8 to ensure padding bytes are zeroed. + let mut foobar = FooBar { bar: Bar { bytes: [0u8; 8] } }; + // Reading either field is ok. + let _val = unsafe { (foobar.foo, foobar.bar) }; + // Does this assignment copy the uninitialized padding bytes + // over the initialized padding bytes? miri doesn't seem to think so. + foobar.foo = Foo { val16: 1, val32: 2 }; + // This resets the padding to uninit. + let _val = unsafe { (foobar.foo, foobar.bar) }; + //~^ ERROR: uninitialized +} diff --git a/src/tools/miri/tests/fail/uninit/padding-struct-in-union.stderr b/src/tools/miri/tests/fail/uninit/padding-struct-in-union.stderr new file mode 100644 index 0000000000000..e122249af16e5 --- /dev/null +++ b/src/tools/miri/tests/fail/uninit/padding-struct-in-union.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: constructing invalid value at .bytes[2]: encountered uninitialized memory, but expected an integer + --> $DIR/padding-struct-in-union.rs:LL:CC + | +LL | let _val = unsafe { (foobar.foo, foobar.bar) }; + | ^^^^^^^^^^ constructing invalid value at .bytes[2]: encountered uninitialized memory, but expected an integer + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/padding-struct-in-union.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/uninit/padding-struct.rs b/src/tools/miri/tests/fail/uninit/padding-struct.rs new file mode 100644 index 0000000000000..dd3be50343902 --- /dev/null +++ b/src/tools/miri/tests/fail/uninit/padding-struct.rs @@ -0,0 +1,11 @@ +use std::mem; + +#[repr(C)] +struct Pair(u8, u16); + +fn main() { unsafe { + let p: Pair = mem::transmute(0u32); // The copy when `Pair` is returned from `transmute` should destroy padding. + let c = &p as *const _ as *const u8; + let _val = *c.add(1); // Get the padding byte. + //~^ERROR: uninitialized +} } diff --git a/src/tools/miri/tests/fail/uninit/padding-struct.stderr b/src/tools/miri/tests/fail/uninit/padding-struct.stderr new file mode 100644 index 0000000000000..8dc40a482ac52 --- /dev/null +++ b/src/tools/miri/tests/fail/uninit/padding-struct.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory + --> $DIR/padding-struct.rs:LL:CC + | +LL | let _val = *c.add(1); // Get the padding byte. + | ^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/padding-struct.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/uninit/padding-union.rs b/src/tools/miri/tests/fail/uninit/padding-union.rs new file mode 100644 index 0000000000000..2e9e0a40d6c68 --- /dev/null +++ b/src/tools/miri/tests/fail/uninit/padding-union.rs @@ -0,0 +1,14 @@ +use std::mem; + +#[allow(unused)] +#[repr(C)] +union U { + field: (u8, u16), +} + +fn main() { unsafe { + let p: U = mem::transmute(0u32); // The copy when `U` is returned from `transmute` should destroy padding. + let c = &p as *const _ as *const [u8; 4]; + let _val = *c; // Read the entire thing, definitely contains the padding byte. + //~^ERROR: uninitialized +} } diff --git a/src/tools/miri/tests/fail/uninit/padding-union.stderr b/src/tools/miri/tests/fail/uninit/padding-union.stderr new file mode 100644 index 0000000000000..04002da4f195c --- /dev/null +++ b/src/tools/miri/tests/fail/uninit/padding-union.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: constructing invalid value at [1]: encountered uninitialized memory, but expected an integer + --> $DIR/padding-union.rs:LL:CC + | +LL | let _val = *c; // Read the entire thing, definitely contains the padding byte. + | ^^ constructing invalid value at [1]: encountered uninitialized memory, but expected an integer + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/padding-union.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/transmute-pair-uninit.rs b/src/tools/miri/tests/fail/uninit/transmute-pair-uninit.rs similarity index 61% rename from src/tools/miri/tests/fail/transmute-pair-uninit.rs rename to src/tools/miri/tests/fail/uninit/transmute-pair-uninit.rs index bc95f3cb7ad3a..0ba5520a54468 100644 --- a/src/tools/miri/tests/fail/transmute-pair-uninit.rs +++ b/src/tools/miri/tests/fail/uninit/transmute-pair-uninit.rs @@ -1,16 +1,17 @@ #![feature(core_intrinsics)] -use std::mem; +use std::mem::{self, MaybeUninit}; fn main() { - let x: Option> = unsafe { + // This constructs a `(usize, bool)` pair: 9 bytes initialized, the rest not. + // Ensure that these 9 bytes are indeed initialized, and the rest is indeed not. + let x: MaybeUninit> = unsafe { let z = std::intrinsics::add_with_overflow(0usize, 0usize); - std::mem::transmute::<(usize, bool), Option>>(z) + std::mem::transmute::<(usize, bool), MaybeUninit>>(z) }; - let y = &x; // Now read this bytewise. There should be (`ptr_size + 1`) def bytes followed by // (`ptr_size - 1`) undef bytes (the padding after the bool) in there. - let z: *const u8 = y as *const _ as *const _; + let z: *const u8 = &x as *const _ as *const _; let first_undef = mem::size_of::() as isize + 1; for i in 0..first_undef { let byte = unsafe { *z.offset(i) }; diff --git a/src/tools/miri/tests/fail/transmute-pair-uninit.stderr b/src/tools/miri/tests/fail/uninit/transmute-pair-uninit.stderr similarity index 100% rename from src/tools/miri/tests/fail/transmute-pair-uninit.stderr rename to src/tools/miri/tests/fail/uninit/transmute-pair-uninit.stderr diff --git a/src/tools/miri/tests/pass/enums.rs b/src/tools/miri/tests/pass/enums.rs index 1dafef025e958..9fc61f07c047f 100644 --- a/src/tools/miri/tests/pass/enums.rs +++ b/src/tools/miri/tests/pass/enums.rs @@ -132,6 +132,43 @@ fn overaligned_casts() { assert_eq!(aligned as u8, 0); } +// This hits a corner case in the logic for clearing padding on typed copies. +fn padding_clear_corner_case() { + #[allow(unused)] + #[derive(Copy, Clone)] + #[repr(C)] + pub struct Decoded { + /// The scaled mantissa. + pub mant: u64, + /// The lower error range. + pub minus: u64, + /// The upper error range. + pub plus: u64, + /// The shared exponent in base 2. + pub exp: i16, + /// True when the error range is inclusive. + /// + /// In IEEE 754, this is true when the original mantissa was even. + pub inclusive: bool, + } + + #[allow(unused)] + #[derive(Copy, Clone)] + pub enum FullDecoded { + /// Not-a-number. + Nan, + /// Infinities, either positive or negative. + Infinite, + /// Zero, either positive or negative. + Zero, + /// Finite numbers with further decoded fields. + Finite(Decoded), + } + + let val = FullDecoded::Finite(Decoded { mant: 0, minus: 0, plus: 0, exp: 0, inclusive: false }); + let _val2 = val; // trigger typed copy +} + fn main() { test(MyEnum::MyEmptyVariant); test(MyEnum::MyNewtypeVariant(42)); @@ -141,4 +178,5 @@ fn main() { discriminant_overflow(); more_discriminant_overflow(); overaligned_casts(); + padding_clear_corner_case(); } From a2410425b3ee0fa75533ada2ea1bb7ebfb2bc84d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 5 Sep 2024 07:44:03 +0200 Subject: [PATCH 062/189] clarify comments and names in check_validity_requirement --- .../src/util/check_validity_requirement.rs | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs index 26fd59bc6ef77..611a8e1a88497 100644 --- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs +++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs @@ -32,15 +32,15 @@ pub fn check_validity_requirement<'tcx>( let layout_cx = LayoutCx { tcx, param_env: param_env_and_ty.param_env }; if kind == ValidityRequirement::Uninit || tcx.sess.opts.unstable_opts.strict_init_checks { - might_permit_raw_init_strict(layout, &layout_cx, kind) + check_validity_requirement_strict(layout, &layout_cx, kind) } else { - might_permit_raw_init_lax(layout, &layout_cx, kind) + check_validity_requirement_lax(layout, &layout_cx, kind) } } -/// Implements the 'strict' version of the `might_permit_raw_init` checks; see that function for -/// details. -fn might_permit_raw_init_strict<'tcx>( +/// Implements the 'strict' version of the [`check_validity_requirement`] checks; see that function +/// for details. +fn check_validity_requirement_strict<'tcx>( ty: TyAndLayout<'tcx>, cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, kind: ValidityRequirement, @@ -65,6 +65,8 @@ fn might_permit_raw_init_strict<'tcx>( // This does *not* actually check that references are dereferenceable, but since all types that // require dereferenceability also require non-null, we don't actually get any false negatives // due to this. + // The value we are validating is temporary and discarded at the end of this function, so + // there is no point in reseting provenance and padding. Ok(cx .validate_operand( &allocated.into(), @@ -74,9 +76,9 @@ fn might_permit_raw_init_strict<'tcx>( .is_ok()) } -/// Implements the 'lax' (default) version of the `might_permit_raw_init` checks; see that function for -/// details. -fn might_permit_raw_init_lax<'tcx>( +/// Implements the 'lax' (default) version of the [`check_validity_requirement`] checks; see that +/// function for details. +fn check_validity_requirement_lax<'tcx>( this: TyAndLayout<'tcx>, cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, init_kind: ValidityRequirement, @@ -141,7 +143,7 @@ fn might_permit_raw_init_lax<'tcx>( } FieldsShape::Arbitrary { offsets, .. } => { for idx in 0..offsets.len() { - if !might_permit_raw_init_lax(this.field(cx, idx), cx, init_kind)? { + if !check_validity_requirement_lax(this.field(cx, idx), cx, init_kind)? { // We found a field that is unhappy with this kind of initialization. return Ok(false); } From 11bd99de8cc67683f215317dba55c91aaf3b5767 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 5 Sep 2024 08:21:19 +0200 Subject: [PATCH 063/189] IntervalSet: add comment about representation --- compiler/rustc_index/src/interval.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_index/src/interval.rs b/compiler/rustc_index/src/interval.rs index 503470f896d09..34f541a8cc639 100644 --- a/compiler/rustc_index/src/interval.rs +++ b/compiler/rustc_index/src/interval.rs @@ -17,7 +17,7 @@ mod tests; /// first value of the following element. #[derive(Debug, Clone)] pub struct IntervalSet { - // Start, end + // Start, end (both inclusive) map: SmallVec<[(u32, u32); 2]>, domain: usize, _data: PhantomData, From 11d51aae863d46a73ad39ec607bd7592fdb836e3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 8 Sep 2024 18:59:30 +0200 Subject: [PATCH 064/189] const: make ptr.is_null() stop execution on ambiguity --- library/core/src/ptr/const_ptr.rs | 10 ++++++---- library/core/src/ptr/mut_ptr.rs | 17 +---------------- tests/ui/consts/const-ptr-is-null.rs | 20 ++++++++++++++++++++ tests/ui/consts/const-ptr-is-null.stderr | 19 +++++++++++++++++++ 4 files changed, 46 insertions(+), 20 deletions(-) create mode 100644 tests/ui/consts/const-ptr-is-null.rs create mode 100644 tests/ui/consts/const-ptr-is-null.stderr diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 3b635e2a4aa9e..febb3fed96302 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -40,15 +40,17 @@ impl *const T { #[inline] const fn const_impl(ptr: *const u8) -> bool { - // Compare via a cast to a thin pointer, so fat pointers are only - // considering their "data" part for null-ness. match (ptr).guaranteed_eq(null_mut()) { - None => false, Some(res) => res, + // To remain maximally convervative, we stop execution when we don't + // know whether the pointer is null or not. + // We can *not* return `false` here, that would be unsound in `NonNull::new`! + None => panic!("null-ness of this pointer cannot be determined in const context"), } } - #[allow(unused_unsafe)] + // Compare via a cast to a thin pointer, so fat pointers are only + // considering their "data" part for null-ness. const_eval_select((self as *const u8,), const_impl, runtime_impl) } diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 42975cc927b8e..bebc4b2f271eb 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -33,22 +33,7 @@ impl *mut T { #[rustc_diagnostic_item = "ptr_is_null"] #[inline] pub const fn is_null(self) -> bool { - #[inline] - fn runtime_impl(ptr: *mut u8) -> bool { - ptr.addr() == 0 - } - - #[inline] - const fn const_impl(ptr: *mut u8) -> bool { - // Compare via a cast to a thin pointer, so fat pointers are only - // considering their "data" part for null-ness. - match (ptr).guaranteed_eq(null_mut()) { - None => false, - Some(res) => res, - } - } - - const_eval_select((self as *mut u8,), const_impl, runtime_impl) + self.cast_const().is_null() } /// Casts to a pointer of another type. diff --git a/tests/ui/consts/const-ptr-is-null.rs b/tests/ui/consts/const-ptr-is-null.rs new file mode 100644 index 0000000000000..82c293c0ad6e3 --- /dev/null +++ b/tests/ui/consts/const-ptr-is-null.rs @@ -0,0 +1,20 @@ +#![feature(const_ptr_is_null)] +use std::ptr; + +const IS_NULL: () = { + assert!(ptr::null::().is_null()); +}; +const IS_NOT_NULL: () = { + assert!(!ptr::null::().wrapping_add(1).is_null()); +}; + +const MAYBE_NULL: () = { + let x = 15; + let ptr = &x as *const i32; + // This one is still unambiguous... + assert!(!ptr.is_null()); + // but once we shift outside the allocation, we might become null. + assert!(!ptr.wrapping_sub(512).is_null()); //~inside `MAYBE_NULL` +}; + +fn main() {} diff --git a/tests/ui/consts/const-ptr-is-null.stderr b/tests/ui/consts/const-ptr-is-null.stderr new file mode 100644 index 0000000000000..20e44a1401f9e --- /dev/null +++ b/tests/ui/consts/const-ptr-is-null.stderr @@ -0,0 +1,19 @@ +error[E0080]: evaluation of constant value failed + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL + | + = note: the evaluated program panicked at 'null-ness of this pointer cannot be determined in const context', $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL + | +note: inside `std::ptr::const_ptr::::is_null::const_impl` + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL +note: inside `std::ptr::const_ptr::::is_null` + --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL +note: inside `MAYBE_NULL` + --> $DIR/const-ptr-is-null.rs:17:14 + | +LL | assert!(!ptr.wrapping_sub(512).is_null()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. From 5f3fdd14dfc47b0c6ab7f5887052d6e628b56919 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20S=C3=A1nchez=20Mu=C3=B1oz?= Date: Sun, 8 Sep 2024 21:51:00 +0200 Subject: [PATCH 065/189] Remove needless returns detected by clippy in libraries --- library/alloc/src/collections/vec_deque/iter.rs | 4 ++-- library/alloc/src/collections/vec_deque/iter_mut.rs | 4 ++-- library/alloc/src/vec/in_place_collect.rs | 2 +- library/alloc/src/vec/into_iter.rs | 4 ++-- library/core/src/ptr/metadata.rs | 4 ++-- library/core/src/str/pattern.rs | 4 ++-- library/std/src/sys/pal/unix/linux/pidfd.rs | 11 ++++++----- library/std/src/sys/pal/wasi/fs.rs | 4 ++-- library/std/src/sys/pal/wasi/helpers.rs | 2 +- 9 files changed, 20 insertions(+), 19 deletions(-) diff --git a/library/alloc/src/collections/vec_deque/iter.rs b/library/alloc/src/collections/vec_deque/iter.rs index bf4dd66f47638..6922ea9b79bfd 100644 --- a/library/alloc/src/collections/vec_deque/iter.rs +++ b/library/alloc/src/collections/vec_deque/iter.rs @@ -73,7 +73,7 @@ impl<'a, T> Iterator for Iter<'a, T> { fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { let remaining = self.i1.advance_by(n); match remaining { - Ok(()) => return Ok(()), + Ok(()) => Ok(()), Err(n) => { mem::swap(&mut self.i1, &mut self.i2); self.i1.advance_by(n.get()) @@ -144,7 +144,7 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> { fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { match self.i2.advance_back_by(n) { - Ok(()) => return Ok(()), + Ok(()) => Ok(()), Err(n) => { mem::swap(&mut self.i1, &mut self.i2); self.i2.advance_back_by(n.get()) diff --git a/library/alloc/src/collections/vec_deque/iter_mut.rs b/library/alloc/src/collections/vec_deque/iter_mut.rs index 7a349a1b4edd0..84b7410958013 100644 --- a/library/alloc/src/collections/vec_deque/iter_mut.rs +++ b/library/alloc/src/collections/vec_deque/iter_mut.rs @@ -64,7 +64,7 @@ impl<'a, T> Iterator for IterMut<'a, T> { fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { match self.i1.advance_by(n) { - Ok(()) => return Ok(()), + Ok(()) => Ok(()), Err(remaining) => { mem::swap(&mut self.i1, &mut self.i2); self.i1.advance_by(remaining.get()) @@ -135,7 +135,7 @@ impl<'a, T> DoubleEndedIterator for IterMut<'a, T> { fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { match self.i2.advance_back_by(n) { - Ok(()) => return Ok(()), + Ok(()) => Ok(()), Err(remaining) => { mem::swap(&mut self.i1, &mut self.i2); self.i2.advance_back_by(remaining.get()) diff --git a/library/alloc/src/vec/in_place_collect.rs b/library/alloc/src/vec/in_place_collect.rs index d119e6ca397c5..ec0ab8ee7289c 100644 --- a/library/alloc/src/vec/in_place_collect.rs +++ b/library/alloc/src/vec/in_place_collect.rs @@ -208,7 +208,7 @@ const fn needs_realloc(src_cap: usize, dst_cap: usize) -> bool { // type layouts don't guarantee a fit, so do a runtime check to see if // the allocations happen to match - return src_cap > 0 && src_cap * mem::size_of::() != dst_cap * mem::size_of::(); + src_cap > 0 && src_cap * mem::size_of::() != dst_cap * mem::size_of::() } /// This provides a shorthand for the source type since local type aliases aren't a thing. diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index fad8abad49353..92c5e360da453 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -288,11 +288,11 @@ impl Iterator for IntoIter { // Safety: `len` is larger than the array size. Copy a fixed amount here to fully initialize // the array. - return unsafe { + unsafe { ptr::copy_nonoverlapping(self.ptr.as_ptr(), raw_ary.as_mut_ptr() as *mut T, N); self.ptr = self.ptr.add(N); Ok(raw_ary.transpose().assume_init()) - }; + } } fn fold(mut self, mut accum: B, mut f: F) -> B diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs index ccc9f8754f00c..76a0e2ba77483 100644 --- a/library/core/src/ptr/metadata.rs +++ b/library/core/src/ptr/metadata.rs @@ -187,14 +187,14 @@ impl DynMetadata { // Consider a reference like `&(i32, dyn Send)`: the vtable will only store the size of the // `Send` part! // SAFETY: DynMetadata always contains a valid vtable pointer - return unsafe { crate::intrinsics::vtable_size(self.vtable_ptr() as *const ()) }; + unsafe { crate::intrinsics::vtable_size(self.vtable_ptr() as *const ()) } } /// Returns the alignment of the type associated with this vtable. #[inline] pub fn align_of(self) -> usize { // SAFETY: DynMetadata always contains a valid vtable pointer - return unsafe { crate::intrinsics::vtable_align(self.vtable_ptr() as *const ()) }; + unsafe { crate::intrinsics::vtable_align(self.vtable_ptr() as *const ()) } } /// Returns the size and alignment together as a `Layout` diff --git a/library/core/src/str/pattern.rs b/library/core/src/str/pattern.rs index 2f1096db8f00c..9f1294d760647 100644 --- a/library/core/src/str/pattern.rs +++ b/library/core/src/str/pattern.rs @@ -1814,7 +1814,7 @@ fn simd_contains(needle: &str, haystack: &str) -> Option { } mask &= !(1 << trailing); } - return false; + false }; let test_chunk = |idx| -> u16 { @@ -1830,7 +1830,7 @@ fn simd_contains(needle: &str, haystack: &str) -> Option { let both = eq_first.bitand(eq_last); let mask = both.to_bitmask() as u16; - return mask; + mask }; let mut i = 0; diff --git a/library/std/src/sys/pal/unix/linux/pidfd.rs b/library/std/src/sys/pal/unix/linux/pidfd.rs index 7474f80e94f9d..78744430f3b51 100644 --- a/library/std/src/sys/pal/unix/linux/pidfd.rs +++ b/library/std/src/sys/pal/unix/linux/pidfd.rs @@ -13,7 +13,7 @@ pub(crate) struct PidFd(FileDesc); impl PidFd { pub fn kill(&self) -> io::Result<()> { - return cvt(unsafe { + cvt(unsafe { libc::syscall( libc::SYS_pidfd_send_signal, self.0.as_raw_fd(), @@ -22,7 +22,7 @@ impl PidFd { 0, ) }) - .map(drop); + .map(drop) } pub fn wait(&self) -> io::Result { @@ -30,7 +30,7 @@ impl PidFd { cvt(unsafe { libc::waitid(libc::P_PIDFD, self.0.as_raw_fd() as u32, &mut siginfo, libc::WEXITED) })?; - return Ok(ExitStatus::from_waitid_siginfo(siginfo)); + Ok(ExitStatus::from_waitid_siginfo(siginfo)) } pub fn try_wait(&self) -> io::Result> { @@ -45,9 +45,10 @@ impl PidFd { ) })?; if unsafe { siginfo.si_pid() } == 0 { - return Ok(None); + Ok(None) + } else { + Ok(Some(ExitStatus::from_waitid_siginfo(siginfo))) } - return Ok(Some(ExitStatus::from_waitid_siginfo(siginfo))); } } diff --git a/library/std/src/sys/pal/wasi/fs.rs b/library/std/src/sys/pal/wasi/fs.rs index 88b1e543ec7c2..e1c61cae9f810 100644 --- a/library/std/src/sys/pal/wasi/fs.rs +++ b/library/std/src/sys/pal/wasi/fs.rs @@ -265,7 +265,7 @@ impl OpenOptions { pub fn new() -> OpenOptions { let mut base = OpenOptions::default(); base.dirflags = wasi::LOOKUPFLAGS_SYMLINK_FOLLOW; - return base; + base } pub fn read(&mut self, read: bool) { @@ -382,7 +382,7 @@ impl OpenOptions { base |= wasi::RIGHTS_PATH_UNLINK_FILE; base |= wasi::RIGHTS_POLL_FD_READWRITE; - return base; + base } fn rights_inheriting(&self) -> wasi::Rights { diff --git a/library/std/src/sys/pal/wasi/helpers.rs b/library/std/src/sys/pal/wasi/helpers.rs index d047bf2fce857..37ef17858cb96 100644 --- a/library/std/src/sys/pal/wasi/helpers.rs +++ b/library/std/src/sys/pal/wasi/helpers.rs @@ -115,7 +115,7 @@ pub fn hashmap_random_keys() -> (u64, u64) { let len = mem::size_of_val(&ret); wasi::random_get(base, len).expect("random_get failure"); } - return ret; + ret } #[inline] From 332fa6aa6ed70e285c155d112a30027947cad12b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 8 Sep 2024 16:35:34 +0200 Subject: [PATCH 066/189] add FIXME(const-hack) --- .../rustc_mir_transform/src/pass_manager.rs | 6 ++--- .../alloc/src/collections/vec_deque/mod.rs | 4 ++-- library/alloc/src/raw_vec.rs | 15 +----------- library/alloc/src/vec/in_place_collect.rs | 2 +- library/alloc/src/vec/into_iter.rs | 2 +- library/alloc/src/vec/mod.rs | 2 +- library/core/src/char/convert.rs | 2 +- library/core/src/char/methods.rs | 2 +- library/core/src/num/mod.rs | 2 +- library/core/src/option.rs | 24 ++++++------------- library/core/src/slice/index.rs | 9 ++++--- library/core/src/slice/mod.rs | 6 ++--- library/core/src/str/converts.rs | 4 ++-- library/core/src/str/error.rs | 2 +- library/core/src/time.rs | 2 ++ library/core/src/unicode/unicode_data.rs | 6 ++--- library/core/tests/hash/mod.rs | 7 ++---- library/std/src/sys/pal/windows/args.rs | 2 +- 18 files changed, 38 insertions(+), 61 deletions(-) diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index 28d4e1a1c9184..e5f145ea31ae8 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -42,7 +42,7 @@ fn to_profiler_name(type_name: &'static str) -> &'static str { // const wrapper for `if let Some((_, tail)) = name.rsplit_once(':') { tail } else { name }` const fn c_name(name: &'static str) -> &'static str { - // FIXME Simplify the implementation once more `str` methods get const-stable. + // FIXME(const-hack) Simplify the implementation once more `str` methods get const-stable. // and inline into call site let bytes = name.as_bytes(); let mut i = bytes.len(); @@ -61,7 +61,7 @@ const fn c_name(name: &'static str) -> &'static str { /// loop that goes over each available MIR and applies `run_pass`. pub(super) trait MirPass<'tcx> { fn name(&self) -> &'static str { - // FIXME Simplify the implementation once more `str` methods get const-stable. + // FIXME(const-hack) Simplify the implementation once more `str` methods get const-stable. // See copypaste in `MirLint` const { let name = std::any::type_name::(); @@ -89,7 +89,7 @@ pub(super) trait MirPass<'tcx> { /// disabled (via the `Lint` adapter). pub(super) trait MirLint<'tcx> { fn name(&self) -> &'static str { - // FIXME Simplify the implementation once more `str` methods get const-stable. + // FIXME(const-hack) Simplify the implementation once more `str` methods get const-stable. // See copypaste in `MirPass` const { let name = std::any::type_name::(); diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index dc725ec0f56e4..8c9db063105ce 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -554,8 +554,8 @@ impl VecDeque { #[rustc_const_stable(feature = "const_vec_deque_new", since = "1.68.0")] #[must_use] pub const fn new() -> VecDeque { - // FIXME: This should just be `VecDeque::new_in(Global)` once that hits stable. - VecDeque { head: 0, len: 0, buf: RawVec::NEW } + // FIXME(const-hack): This should just be `VecDeque::new_in(Global)` once that hits stable. + VecDeque { head: 0, len: 0, buf: RawVec::new() } } /// Creates an empty deque with space for at least `capacity` elements. diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index a651ba067e47c..436e0596e3d5e 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -96,13 +96,6 @@ struct RawVecInner { } impl RawVec { - /// HACK(Centril): This exists because stable `const fn` can only call stable `const fn`, so - /// they cannot call `Self::new()`. - /// - /// If you change `RawVec::new` or dependencies, please take care to not introduce anything - /// that would truly const-call something unstable. - pub const NEW: Self = Self::new(); - /// Creates the biggest possible `RawVec` (on the system heap) /// without allocating. If `T` has positive size, then this makes a /// `RawVec` with capacity `0`. If `T` is zero-sized, then it makes a @@ -111,7 +104,7 @@ impl RawVec { #[must_use] #[rustc_const_stable(feature = "raw_vec_internals_const", since = "1.81")] pub const fn new() -> Self { - Self { inner: RawVecInner::new::(), _marker: PhantomData } + Self::new_in(Global) } /// Creates a `RawVec` (on the system heap) with exactly the @@ -149,12 +142,6 @@ impl RawVec { } impl RawVecInner { - #[must_use] - #[rustc_const_stable(feature = "raw_vec_internals_const", since = "1.81")] - const fn new() -> Self { - Self::new_in(Global, core::mem::align_of::()) - } - #[cfg(not(any(no_global_oom_handling, test)))] #[must_use] #[inline] diff --git a/library/alloc/src/vec/in_place_collect.rs b/library/alloc/src/vec/in_place_collect.rs index d119e6ca397c5..2604843994506 100644 --- a/library/alloc/src/vec/in_place_collect.rs +++ b/library/alloc/src/vec/in_place_collect.rs @@ -191,7 +191,7 @@ const fn in_place_collectible( const fn needs_realloc(src_cap: usize, dst_cap: usize) -> bool { if const { mem::align_of::() != mem::align_of::() } { - // FIXME: use unreachable! once that works in const + // FIXME(const-hack): use unreachable! once that works in const panic!("in_place_collectible() prevents this"); } diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index fad8abad49353..487d5cc7224bc 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -142,7 +142,7 @@ impl IntoIter { // struct and then overwriting &mut self. // this creates less assembly self.cap = 0; - self.buf = RawVec::NEW.non_null(); + self.buf = RawVec::new().non_null(); self.ptr = self.buf; self.end = self.buf.as_ptr(); diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 162791ba59d03..ff084edba8dc8 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -419,7 +419,7 @@ impl Vec { #[stable(feature = "rust1", since = "1.0.0")] #[must_use] pub const fn new() -> Self { - Vec { buf: RawVec::NEW, len: 0 } + Vec { buf: RawVec::new(), len: 0 } } /// Constructs a new, empty `Vec` with at least the specified capacity. diff --git a/library/core/src/char/convert.rs b/library/core/src/char/convert.rs index f0c2636307fcf..73ab4f1e52ade 100644 --- a/library/core/src/char/convert.rs +++ b/library/core/src/char/convert.rs @@ -11,7 +11,7 @@ use crate::ub_checks::assert_unsafe_precondition; #[must_use] #[inline] pub(super) const fn from_u32(i: u32) -> Option { - // FIXME: once Result::ok is const fn, use it here + // FIXME(const-hack): once Result::ok is const fn, use it here match char_try_from_u32(i) { Ok(c) => Some(c), Err(_) => None, diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 41a19665779b6..6e7494af12f8e 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -386,7 +386,7 @@ impl char { // Force the 6th bit to be set to ensure ascii is lower case. digit = (self as u32 | 0b10_0000).wrapping_sub('a' as u32).saturating_add(10); } - // FIXME: once then_some is const fn, use it here + // FIXME(const-hack): once then_some is const fn, use it here if digit < radix { Some(digit) } else { None } } diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 37c9db7f474b5..dca644ebef4ad 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -6,7 +6,7 @@ use crate::str::FromStr; use crate::ub_checks::assert_unsafe_precondition; use crate::{ascii, intrinsics, mem}; -// Used because the `?` operator is not allowed in a const context. +// FIXME(const-hack): Used because the `?` operator is not allowed in a const context. macro_rules! try_opt { ($e:expr) => { match $e { diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 212e4f0215463..18604a8ae3532 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -739,6 +739,7 @@ impl Option { #[stable(feature = "pin", since = "1.33.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] pub const fn as_pin_ref(self: Pin<&Self>) -> Option> { + // FIXME(const-hack): use `map` once that is possible match Pin::get_ref(self).as_ref() { // SAFETY: `x` is guaranteed to be pinned because it comes from `self` // which is pinned. @@ -758,6 +759,7 @@ impl Option { // SAFETY: `get_unchecked_mut` is never used to move the `Option` inside `self`. // `x` is guaranteed to be pinned because it comes from `self` which is pinned. unsafe { + // FIXME(const-hack): use `map` once that is possible match Pin::get_unchecked_mut(self).as_mut() { Some(x) => Some(Pin::new_unchecked(x)), None => None, @@ -1290,10 +1292,7 @@ impl Option { where T: Deref, { - match self.as_ref() { - Some(t) => Some(t.deref()), - None => None, - } + self.as_ref().map(|t| t.deref()) } /// Converts from `Option` (or `&mut Option`) to `Option<&mut T::Target>`. @@ -1316,10 +1315,7 @@ impl Option { where T: DerefMut, { - match self.as_mut() { - Some(t) => Some(t.deref_mut()), - None => None, - } + self.as_mut().map(|t| t.deref_mut()) } ///////////////////////////////////////////////////////////////////////// @@ -1633,13 +1629,7 @@ impl Option { #[inline] #[stable(feature = "option_entry", since = "1.20.0")] pub fn get_or_insert(&mut self, value: T) -> &mut T { - if let None = *self { - *self = Some(value); - } - - // SAFETY: a `None` variant for `self` would have been replaced by a `Some` - // variant in the code above. - unsafe { self.as_mut().unwrap_unchecked() } + self.get_or_insert_with(|| value) } /// Inserts the default value into the option if it is [`None`], then @@ -1725,7 +1715,7 @@ impl Option { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option", issue = "67441")] pub const fn take(&mut self) -> Option { - // FIXME replace `mem::replace` by `mem::take` when the latter is const ready + // FIXME(const-hack) replace `mem::replace` by `mem::take` when the latter is const ready mem::replace(self, None) } @@ -1894,7 +1884,7 @@ impl Option<&T> { where T: Copy, { - // FIXME: this implementation, which sidesteps using `Option::map` since it's not const + // FIXME(const-hack): this implementation, which sidesteps using `Option::map` since it's not const // ready yet, should be reverted when possible to avoid code repetition match self { Some(&v) => Some(v), diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index de1492e82ce7d..7adcee1ed6b64 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -33,10 +33,11 @@ where #[track_caller] #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] const fn slice_start_index_len_fail(index: usize, len: usize) -> ! { + // FIXME(const-hack): once integer formatting in panics is possible, we + // should use the same implementation at compiletime and runtime. const_eval_select((index, len), slice_start_index_len_fail_ct, slice_start_index_len_fail_rt) } -// FIXME const-hack #[inline] #[track_caller] fn slice_start_index_len_fail_rt(index: usize, len: usize) -> ! { @@ -54,10 +55,11 @@ const fn slice_start_index_len_fail_ct(_: usize, _: usize) -> ! { #[track_caller] #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] const fn slice_end_index_len_fail(index: usize, len: usize) -> ! { + // FIXME(const-hack): once integer formatting in panics is possible, we + // should use the same implementation at compiletime and runtime. const_eval_select((index, len), slice_end_index_len_fail_ct, slice_end_index_len_fail_rt) } -// FIXME const-hack #[inline] #[track_caller] fn slice_end_index_len_fail_rt(index: usize, len: usize) -> ! { @@ -75,10 +77,11 @@ const fn slice_end_index_len_fail_ct(_: usize, _: usize) -> ! { #[track_caller] #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] const fn slice_index_order_fail(index: usize, end: usize) -> ! { + // FIXME(const-hack): once integer formatting in panics is possible, we + // should use the same implementation at compiletime and runtime. const_eval_select((index, end), slice_index_order_fail_ct, slice_index_order_fail_rt) } -// FIXME const-hack #[inline] #[track_caller] fn slice_index_order_fail_rt(index: usize, end: usize) -> ! { diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 166189f4b6cf3..3a02966a168a7 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -529,7 +529,7 @@ impl [T] { None } else { // SAFETY: We manually verified the bounds of the slice. - // FIXME: Without const traits, we need this instead of `get_unchecked`. + // FIXME(const-hack): Without const traits, we need this instead of `get_unchecked`. let last = unsafe { self.split_at_unchecked(self.len() - N).1 }; // SAFETY: We explicitly check for the correct number of elements, @@ -563,7 +563,7 @@ impl [T] { None } else { // SAFETY: We manually verified the bounds of the slice. - // FIXME: Without const traits, we need this instead of `get_unchecked`. + // FIXME(const-hack): Without const traits, we need this instead of `get_unchecked`. let last = unsafe { self.split_at_mut_unchecked(self.len() - N).1 }; // SAFETY: We explicitly check for the correct number of elements, @@ -1952,7 +1952,7 @@ impl [T] { #[inline] #[must_use] pub const unsafe fn split_at_unchecked(&self, mid: usize) -> (&[T], &[T]) { - // HACK: the const function `from_raw_parts` is used to make this + // FIXME(const-hack): the const function `from_raw_parts` is used to make this // function const; previously the implementation used // `(self.get_unchecked(..mid), self.get_unchecked(mid..))` diff --git a/library/core/src/str/converts.rs b/library/core/src/str/converts.rs index 1956a04829d1d..dcddc40ba4b99 100644 --- a/library/core/src/str/converts.rs +++ b/library/core/src/str/converts.rs @@ -85,7 +85,7 @@ use crate::{mem, ptr}; #[rustc_allow_const_fn_unstable(str_internals)] #[rustc_diagnostic_item = "str_from_utf8"] pub const fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> { - // FIXME: This should use `?` again, once it's `const` + // FIXME(const-hack): This should use `?` again, once it's `const` match run_utf8_validation(v) { Ok(_) => { // SAFETY: validation succeeded. @@ -129,7 +129,7 @@ pub const fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> { #[rustc_const_unstable(feature = "const_str_from_utf8", issue = "91006")] #[rustc_diagnostic_item = "str_from_utf8_mut"] pub const fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> { - // This should use `?` again, once it's `const` + // FIXME(const-hack): This should use `?` again, once it's `const` match run_utf8_validation(v) { Ok(_) => { // SAFETY: validation succeeded. diff --git a/library/core/src/str/error.rs b/library/core/src/str/error.rs index a11b5add42ebf..4c8231a2286e1 100644 --- a/library/core/src/str/error.rs +++ b/library/core/src/str/error.rs @@ -100,7 +100,7 @@ impl Utf8Error { #[must_use] #[inline] pub const fn error_len(&self) -> Option { - // FIXME: This should become `map` again, once it's `const` + // FIXME(const-hack): This should become `map` again, once it's `const` match self.error_len { Some(len) => Some(len as usize), None => None, diff --git a/library/core/src/time.rs b/library/core/src/time.rs index c19eeedb35426..65560dfcf9d2d 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -213,6 +213,7 @@ impl Duration { // SAFETY: nanos < NANOS_PER_SEC, therefore nanos is within the valid range Duration { secs, nanos: unsafe { Nanoseconds(nanos) } } } else { + // FIXME(const-hack): use `.expect` once that is possible. let secs = match secs.checked_add((nanos / NANOS_PER_SEC) as u64) { Some(secs) => secs, None => panic!("overflow in Duration::new"), @@ -768,6 +769,7 @@ impl Duration { let total_nanos = self.nanos.0 as u64 * rhs as u64; let extra_secs = total_nanos / (NANOS_PER_SEC as u64); let nanos = (total_nanos % (NANOS_PER_SEC as u64)) as u32; + // FIXME(const-hack): use `and_then` once that is possible. if let Some(s) = self.secs.checked_mul(rhs as u64) { if let Some(secs) = s.checked_add(extra_secs) { debug_assert!(nanos < NANOS_PER_SEC); diff --git a/library/core/src/unicode/unicode_data.rs b/library/core/src/unicode/unicode_data.rs index 1b3d6729663b5..9783e81608403 100644 --- a/library/core/src/unicode/unicode_data.rs +++ b/library/core/src/unicode/unicode_data.rs @@ -18,16 +18,14 @@ const fn bitset_search< let bucket_idx = (needle / 64) as usize; let chunk_map_idx = bucket_idx / CHUNK_SIZE; let chunk_piece = bucket_idx % CHUNK_SIZE; - // FIXME: const-hack: Revert to `slice::get` after `const_slice_index` - // feature stabilizes. + // FIXME(const-hack): Revert to `slice::get` when slice indexing becomes possible in const. let chunk_idx = if chunk_map_idx < chunk_idx_map.len() { chunk_idx_map[chunk_map_idx] } else { return false; }; let idx = bitset_chunk_idx[chunk_idx as usize][chunk_piece] as usize; - // FIXME: const-hack: Revert to `slice::get` after `const_slice_index` - // feature stabilizes. + // FIXME(const-hack): Revert to `slice::get` when slice indexing becomes possible in const. let word = if idx < bitset_canonical.len() { bitset_canonical[idx] } else { diff --git a/library/core/tests/hash/mod.rs b/library/core/tests/hash/mod.rs index bdd1c2579ded8..03826fc4c92cd 100644 --- a/library/core/tests/hash/mod.rs +++ b/library/core/tests/hash/mod.rs @@ -16,11 +16,8 @@ impl Default for MyHasher { impl Hasher for MyHasher { fn write(&mut self, buf: &[u8]) { - // FIXME(const_trait_impl): change to for loop - let mut i = 0; - while i < buf.len() { - self.hash += buf[i] as u64; - i += 1; + for byte in buf { + self.hash += *byte as u64; } } fn write_str(&mut self, s: &str) { diff --git a/library/std/src/sys/pal/windows/args.rs b/library/std/src/sys/pal/windows/args.rs index 66e75a8357149..77d82678f1dcc 100644 --- a/library/std/src/sys/pal/windows/args.rs +++ b/library/std/src/sys/pal/windows/args.rs @@ -20,7 +20,7 @@ use crate::{fmt, io, iter, vec}; /// This is the const equivalent to `NonZero::new(n).unwrap()` /// -/// FIXME: This can be removed once `Option::unwrap` is stably const. +/// FIXME(const-hack): This can be removed once `Option::unwrap` is stably const. /// See the `const_option` feature (#67441). const fn non_zero_u16(n: u16) -> NonZero { match NonZero::new(n) { From 7a3a317618885a8949c8b95c9a38f3f9729b1f3c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 8 Sep 2024 08:54:01 +0200 Subject: [PATCH 067/189] remove const_slice_index annotations, it never had a feature gate anyway --- library/core/src/lib.rs | 1 - library/core/src/slice/index.rs | 10 ---------- library/core/src/slice/memchr.rs | 1 - library/core/src/str/traits.rs | 6 ------ tests/ui/consts/const-eval/ub-slice-get-unchecked.rs | 2 -- .../ui/consts/const-eval/ub-slice-get-unchecked.stderr | 2 +- 6 files changed, 1 insertion(+), 21 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index bda3825436273..5b5d5d1a9610e 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -149,7 +149,6 @@ #![feature(const_size_of_val_raw)] #![feature(const_slice_from_raw_parts_mut)] #![feature(const_slice_from_ref)] -#![feature(const_slice_index)] #![feature(const_slice_split_at_mut)] #![feature(const_str_from_utf8_unchecked_mut)] #![feature(const_strict_overflow_ops)] diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index 7adcee1ed6b64..bc8571c8503e9 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -31,7 +31,6 @@ where #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[track_caller] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] const fn slice_start_index_len_fail(index: usize, len: usize) -> ! { // FIXME(const-hack): once integer formatting in panics is possible, we // should use the same implementation at compiletime and runtime. @@ -53,7 +52,6 @@ const fn slice_start_index_len_fail_ct(_: usize, _: usize) -> ! { #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[track_caller] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] const fn slice_end_index_len_fail(index: usize, len: usize) -> ! { // FIXME(const-hack): once integer formatting in panics is possible, we // should use the same implementation at compiletime and runtime. @@ -75,7 +73,6 @@ const fn slice_end_index_len_fail_ct(_: usize, _: usize) -> ! { #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[track_caller] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] const fn slice_index_order_fail(index: usize, end: usize) -> ! { // FIXME(const-hack): once integer formatting in panics is possible, we // should use the same implementation at compiletime and runtime. @@ -249,7 +246,6 @@ pub unsafe trait SliceIndex: private_slice_index::Sealed { /// The methods `index` and `index_mut` panic if the index is out of bounds. #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex<[T]> for usize { type Output = T; @@ -389,7 +385,6 @@ unsafe impl SliceIndex<[T]> for ops::IndexRange { /// - the start of the range is greater than the end of the range or /// - the end of the range is out of bounds. #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex<[T]> for ops::Range { type Output = [T]; @@ -525,7 +520,6 @@ unsafe impl SliceIndex<[T]> for range::Range { /// The methods `index` and `index_mut` panic if the end of the range is out of bounds. #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex<[T]> for ops::RangeTo { type Output = [T]; @@ -564,7 +558,6 @@ unsafe impl SliceIndex<[T]> for ops::RangeTo { /// The methods `index` and `index_mut` panic if the start of the range is out of bounds. #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex<[T]> for ops::RangeFrom { type Output = [T]; @@ -647,7 +640,6 @@ unsafe impl SliceIndex<[T]> for range::RangeFrom { } #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex<[T]> for ops::RangeFull { type Output = [T]; @@ -687,7 +679,6 @@ unsafe impl SliceIndex<[T]> for ops::RangeFull { /// - the start of the range is greater than the end of the range or /// - the end of the range is out of bounds. #[stable(feature = "inclusive_range", since = "1.26.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex<[T]> for ops::RangeInclusive { type Output = [T]; @@ -769,7 +760,6 @@ unsafe impl SliceIndex<[T]> for range::RangeInclusive { /// The methods `index` and `index_mut` panic if the end of the range is out of bounds. #[stable(feature = "inclusive_range", since = "1.26.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex<[T]> for ops::RangeToInclusive { type Output = [T]; diff --git a/library/core/src/slice/memchr.rs b/library/core/src/slice/memchr.rs index da7ceb2dd0a0d..be19c3d3bc153 100644 --- a/library/core/src/slice/memchr.rs +++ b/library/core/src/slice/memchr.rs @@ -51,7 +51,6 @@ const fn memchr_naive(x: u8, text: &[u8]) -> Option { } #[rustc_allow_const_fn_unstable(const_cmp)] -#[rustc_allow_const_fn_unstable(const_slice_index)] #[rustc_allow_const_fn_unstable(const_align_offset)] #[rustc_const_stable(feature = "const_memchr", since = "1.65.0")] const fn memchr_aligned(x: u8, text: &[u8]) -> Option { diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs index b69c476ae5e53..77c70b978fd15 100644 --- a/library/core/src/str/traits.rs +++ b/library/core/src/str/traits.rs @@ -92,7 +92,6 @@ const fn str_index_overflow_fail() -> ! { /// /// Equivalent to `&self[0 .. len]` or `&mut self[0 .. len]`. #[stable(feature = "str_checked_slicing", since = "1.20.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex for ops::RangeFull { type Output = str; #[inline] @@ -157,7 +156,6 @@ unsafe impl SliceIndex for ops::RangeFull { /// // &s[3 .. 100]; /// ``` #[stable(feature = "str_checked_slicing", since = "1.20.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex for ops::Range { type Output = str; #[inline] @@ -429,7 +427,6 @@ unsafe impl SliceIndex for (ops::Bound, ops::Bound) { /// Panics if `end` does not point to the starting byte offset of a /// character (as defined by `is_char_boundary`), or if `end > len`. #[stable(feature = "str_checked_slicing", since = "1.20.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex for ops::RangeTo { type Output = str; #[inline] @@ -498,7 +495,6 @@ unsafe impl SliceIndex for ops::RangeTo { /// Panics if `begin` does not point to the starting byte offset of /// a character (as defined by `is_char_boundary`), or if `begin > len`. #[stable(feature = "str_checked_slicing", since = "1.20.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex for ops::RangeFrom { type Output = str; #[inline] @@ -625,7 +621,6 @@ unsafe impl SliceIndex for range::RangeFrom { /// to the ending byte offset of a character (`end + 1` is either a starting /// byte offset or equal to `len`), if `begin > end`, or if `end >= len`. #[stable(feature = "inclusive_range", since = "1.26.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex for ops::RangeInclusive { type Output = str; #[inline] @@ -714,7 +709,6 @@ unsafe impl SliceIndex for range::RangeInclusive { /// (`end + 1` is either a starting byte offset as defined by /// `is_char_boundary`, or equal to `len`), or if `end >= len`. #[stable(feature = "inclusive_range", since = "1.26.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex for ops::RangeToInclusive { type Output = str; #[inline] diff --git a/tests/ui/consts/const-eval/ub-slice-get-unchecked.rs b/tests/ui/consts/const-eval/ub-slice-get-unchecked.rs index 3800abddd4240..e805ac01c9d06 100644 --- a/tests/ui/consts/const-eval/ub-slice-get-unchecked.rs +++ b/tests/ui/consts/const-eval/ub-slice-get-unchecked.rs @@ -1,7 +1,5 @@ //@ known-bug: #110395 -#![feature(const_slice_index)] - const A: [(); 5] = [(), (), (), (), ()]; // Since the indexing is on a ZST, the addresses are all fine, diff --git a/tests/ui/consts/const-eval/ub-slice-get-unchecked.stderr b/tests/ui/consts/const-eval/ub-slice-get-unchecked.stderr index de96821e8b987..94aa3ee4d7a1f 100644 --- a/tests/ui/consts/const-eval/ub-slice-get-unchecked.stderr +++ b/tests/ui/consts/const-eval/ub-slice-get-unchecked.stderr @@ -1,5 +1,5 @@ error[E0015]: cannot call non-const fn `core::slice::::get_unchecked::>` in constants - --> $DIR/ub-slice-get-unchecked.rs:9:29 + --> $DIR/ub-slice-get-unchecked.rs:7:29 | LL | const B: &[()] = unsafe { A.get_unchecked(3..1) }; | ^^^^^^^^^^^^^^^^^^^ From 76260158484b53551caa913772f25a0c8f9a24a2 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Fri, 26 Jul 2024 12:04:05 +0200 Subject: [PATCH 068/189] added support for GNU/Hurd on x86_64 --- compiler/rustc_target/src/spec/mod.rs | 1 + .../spec/targets/x86_64_unknown_hurd_gnu.rs | 26 +++++++++++++++++++ src/doc/rustc/src/platform-support.md | 1 + src/doc/rustc/src/platform-support/hurd.md | 7 ++--- tests/assembly/targets/targets-elf.rs | 3 +++ 5 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 compiler/rustc_target/src/spec/targets/x86_64_unknown_hurd_gnu.rs diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 58d47c201f018..c3e7f74c56410 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1645,6 +1645,7 @@ supported_targets! { ("x86_64-unknown-haiku", x86_64_unknown_haiku), ("i686-unknown-hurd-gnu", i686_unknown_hurd_gnu), + ("x86_64-unknown-hurd-gnu", x86_64_unknown_hurd_gnu), ("aarch64-apple-darwin", aarch64_apple_darwin), ("arm64e-apple-darwin", arm64e_apple_darwin), diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_hurd_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_hurd_gnu.rs new file mode 100644 index 0000000000000..6461ece5dd141 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_hurd_gnu.rs @@ -0,0 +1,26 @@ +use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target}; + +pub(crate) fn target() -> Target { + let mut base = base::hurd_gnu::opts(); + base.cpu = "x86-64".into(); + base.plt_by_default = false; + base.max_atomic_width = Some(64); + base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]); + base.stack_probes = StackProbeType::Inline; + base.supports_xray = true; + + Target { + llvm_target: "x86_64-unknown-hurd-gnu".into(), + metadata: crate::spec::TargetMetadata { + description: Some("64-bit GNU/Hurd".into()), + tier: Some(3), + host_tools: Some(true), + std: Some(true), + }, + pointer_width: 64, + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), + arch: "x86_64".into(), + options: base, + } +} diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 319dc9a7c08cb..9a35b35af713b 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -382,6 +382,7 @@ target | std | host | notes [`x86_64-unikraft-linux-musl`](platform-support/unikraft-linux-musl.md) | ✓ | | 64-bit Unikraft with musl 1.2.3 `x86_64-unknown-dragonfly` | ✓ | ✓ | 64-bit DragonFlyBSD `x86_64-unknown-haiku` | ✓ | ✓ | 64-bit Haiku +[`x86_64-unknown-hurd-gnu`](platform-support/hurd.md) | ✓ | ✓ | 64-bit GNU/Hurd [`x86_64-unknown-hermit`](platform-support/hermit.md) | ✓ | | x86_64 Hermit `x86_64-unknown-l4re-uclibc` | ? | | [`x86_64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 64-bit OpenBSD diff --git a/src/doc/rustc/src/platform-support/hurd.md b/src/doc/rustc/src/platform-support/hurd.md index ddf40213ed49d..2521f79dc5e65 100644 --- a/src/doc/rustc/src/platform-support/hurd.md +++ b/src/doc/rustc/src/platform-support/hurd.md @@ -1,4 +1,4 @@ -# `i686-unknown-hurd-gnu` +# `i686-unknown-hurd-gnu` and `x86_64-unknown-hurd-gnu` **Tier: 3** @@ -16,7 +16,8 @@ The GNU/Hurd target supports `std` and uses the standard ELF file format. ## Building the target -This target can be built by adding `i686-unknown-hurd-gnu` as target in the rustc list. +This target can be built by adding `i686-unknown-hurd-gnu` and +`x86_64-unknown-hurd-gnu` as targets in the rustc list. ## Building Rust programs @@ -32,4 +33,4 @@ Tests can be run in the same way as a regular binary. ## Cross-compilation toolchains and C code The target supports C code, the GNU toolchain calls the target -`i686-unknown-gnu`. +`i686-unknown-gnu` and `x86_64-unknown-gnu`. diff --git a/tests/assembly/targets/targets-elf.rs b/tests/assembly/targets/targets-elf.rs index c8610e03939da..4e1c5e6806e80 100644 --- a/tests/assembly/targets/targets-elf.rs +++ b/tests/assembly/targets/targets-elf.rs @@ -552,6 +552,9 @@ //@ revisions: x86_64_unknown_haiku //@ [x86_64_unknown_haiku] compile-flags: --target x86_64-unknown-haiku //@ [x86_64_unknown_haiku] needs-llvm-components: x86 +//@ revisions: x86_64_unknown_hurd_gnu +//@ [x86_64_unknown_hurd_gnu] compile-flags: --target x86_64-unknown-hurd-gnu +//@ [x86_64_unknown_hurd_gnu] needs-llvm-components: x86 //@ revisions: x86_64_unknown_hermit //@ [x86_64_unknown_hermit] compile-flags: --target x86_64-unknown-hermit //@ [x86_64_unknown_hermit] needs-llvm-components: x86 From 6af470e360b775a9079bd0e6634488d7a1936290 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 28 Aug 2024 09:39:59 +1000 Subject: [PATCH 069/189] Reduce visibilities, and add `warn(unreachable_pub)`. Lots of unnecessary `pub`s in this crate. Most are downgraded to `pub(super)`, though some don't need any visibility. --- .../src/abort_unwinding_calls.rs | 2 +- .../src/add_call_guards.rs | 6 ++-- .../src/add_moves_for_packed_drops.rs | 4 +-- compiler/rustc_mir_transform/src/add_retag.rs | 2 +- .../src/add_subtyping_projections.rs | 6 ++-- .../src/check_alignment.rs | 2 +- .../src/check_const_item_mutation.rs | 2 +- .../src/check_packed_ref.rs | 2 +- .../src/cleanup_post_borrowck.rs | 2 +- compiler/rustc_mir_transform/src/copy_prop.rs | 2 +- compiler/rustc_mir_transform/src/coroutine.rs | 4 +-- .../src/coroutine/by_move_body.rs | 2 +- .../rustc_mir_transform/src/cost_checker.rs | 8 ++--- .../rustc_mir_transform/src/coverage/mod.rs | 4 +-- .../src/cross_crate_inline.rs | 2 +- .../rustc_mir_transform/src/ctfe_limit.rs | 2 +- .../src/dataflow_const_prop.rs | 4 +-- .../src/dead_store_elimination.rs | 4 +-- .../src/deduce_param_attrs.rs | 2 +- .../src/deduplicate_blocks.rs | 2 +- .../src/deref_separator.rs | 6 ++-- compiler/rustc_mir_transform/src/dest_prop.rs | 2 +- compiler/rustc_mir_transform/src/dump_mir.rs | 2 +- .../src/early_otherwise_branch.rs | 2 +- .../src/elaborate_box_derefs.rs | 6 ++-- .../src/elaborate_drops.rs | 2 +- compiler/rustc_mir_transform/src/errors.rs | 2 +- .../src/function_item_references.rs | 2 +- compiler/rustc_mir_transform/src/gvn.rs | 2 +- compiler/rustc_mir_transform/src/inline.rs | 2 ++ .../rustc_mir_transform/src/instsimplify.rs | 4 +-- .../rustc_mir_transform/src/jump_threading.rs | 2 +- .../src/known_panics_lint.rs | 8 ++--- .../rustc_mir_transform/src/large_enums.rs | 2 +- compiler/rustc_mir_transform/src/lib.rs | 7 +++-- compiler/rustc_mir_transform/src/lint.rs | 2 +- .../src/lower_intrinsics.rs | 2 +- .../src/lower_slice_len.rs | 4 +-- .../rustc_mir_transform/src/match_branches.rs | 2 +- .../src/mentioned_items.rs | 2 +- .../src/multiple_return_terminators.rs | 2 +- compiler/rustc_mir_transform/src/nrvo.rs | 2 +- .../rustc_mir_transform/src/pass_manager.rs | 7 +---- compiler/rustc_mir_transform/src/prettify.rs | 8 ++--- .../rustc_mir_transform/src/promote_consts.rs | 2 +- compiler/rustc_mir_transform/src/ref_prop.rs | 2 +- .../src/remove_noop_landing_pads.rs | 2 +- .../src/remove_place_mention.rs | 2 +- .../src/remove_storage_markers.rs | 2 +- .../src/remove_uninit_drops.rs | 2 +- .../src/remove_unneeded_drops.rs | 2 +- .../rustc_mir_transform/src/remove_zsts.rs | 2 +- .../src/required_consts.rs | 4 +-- .../rustc_mir_transform/src/reveal_all.rs | 2 +- compiler/rustc_mir_transform/src/shim.rs | 6 ++-- .../src/shim/async_destructor_ctor.rs | 2 +- compiler/rustc_mir_transform/src/simplify.rs | 22 +++++++------- .../src/simplify_branches.rs | 3 +- .../src/simplify_comparison_integral.rs | 2 +- .../src/single_use_consts.rs | 2 +- compiler/rustc_mir_transform/src/sroa.rs | 2 +- compiler/rustc_mir_transform/src/ssa.rs | 30 +++++++++++-------- .../src/unreachable_enum_branching.rs | 2 +- .../src/unreachable_prop.rs | 2 +- compiler/rustc_mir_transform/src/validate.rs | 4 +-- 65 files changed, 125 insertions(+), 120 deletions(-) diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs index e4bc6b3efe422..06ec065c91a21 100644 --- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs +++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs @@ -20,7 +20,7 @@ use rustc_target::spec::PanicStrategy; /// This forces all unwinds, in panic=abort mode happening in foreign code, to /// trigger a process abort. #[derive(PartialEq)] -pub struct AbortUnwindingCalls; +pub(super) struct AbortUnwindingCalls; impl<'tcx> crate::MirPass<'tcx> for AbortUnwindingCalls { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { diff --git a/compiler/rustc_mir_transform/src/add_call_guards.rs b/compiler/rustc_mir_transform/src/add_call_guards.rs index 78e850de3c772..18a0746f54f08 100644 --- a/compiler/rustc_mir_transform/src/add_call_guards.rs +++ b/compiler/rustc_mir_transform/src/add_call_guards.rs @@ -4,11 +4,11 @@ use rustc_middle::ty::TyCtxt; use tracing::debug; #[derive(PartialEq)] -pub enum AddCallGuards { +pub(super) enum AddCallGuards { AllCallEdges, CriticalCallEdges, } -pub use self::AddCallGuards::*; +pub(super) use self::AddCallGuards::*; /** * Breaks outgoing critical edges for call terminators in the MIR. @@ -37,7 +37,7 @@ impl<'tcx> crate::MirPass<'tcx> for AddCallGuards { } impl AddCallGuards { - pub fn add_call_guards(&self, body: &mut Body<'_>) { + pub(super) fn add_call_guards(&self, body: &mut Body<'_>) { let mut pred_count: IndexVec<_, _> = body.basic_blocks.predecessors().iter().map(|ps| ps.len()).collect(); pred_count[START_BLOCK] += 1; diff --git a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs index 4a8196aeff5b0..47572d8d3b22b 100644 --- a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs +++ b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs @@ -35,7 +35,7 @@ use crate::util; /// /// The storage instructions are required to avoid stack space /// blowup. -pub struct AddMovesForPackedDrops; +pub(super) struct AddMovesForPackedDrops; impl<'tcx> crate::MirPass<'tcx> for AddMovesForPackedDrops { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { @@ -44,7 +44,7 @@ impl<'tcx> crate::MirPass<'tcx> for AddMovesForPackedDrops { } } -pub fn add_moves_for_packed_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { +fn add_moves_for_packed_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let patch = add_moves_for_packed_drops_patch(tcx, body); patch.apply(body); } diff --git a/compiler/rustc_mir_transform/src/add_retag.rs b/compiler/rustc_mir_transform/src/add_retag.rs index 2e12064fe7351..794e85fbfedfb 100644 --- a/compiler/rustc_mir_transform/src/add_retag.rs +++ b/compiler/rustc_mir_transform/src/add_retag.rs @@ -8,7 +8,7 @@ use rustc_hir::LangItem; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, TyCtxt}; -pub struct AddRetag; +pub(super) struct AddRetag; /// Determine whether this type may contain a reference (or box), and thus needs retagging. /// We will only recurse `depth` times into Tuples/ADTs to bound the cost of this. diff --git a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs index 369f6c6008440..5e43937fbe69c 100644 --- a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs +++ b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs @@ -4,9 +4,9 @@ use rustc_middle::mir::visit::MutVisitor; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; -pub struct Subtyper; +pub(super) struct Subtyper; -pub struct SubTypeChecker<'a, 'tcx> { +struct SubTypeChecker<'a, 'tcx> { tcx: TyCtxt<'tcx>, patcher: MirPatch<'tcx>, local_decls: &'a IndexVec>, @@ -52,7 +52,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for SubTypeChecker<'a, 'tcx> { // // gets transformed to // let temp: rval_ty = rval; // let place: place_ty = temp as place_ty; -pub fn subtype_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { +fn subtype_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let patch = MirPatch::new(body); let mut checker = SubTypeChecker { tcx, patcher: patch, local_decls: &body.local_decls }; diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs index 2e072aa262aac..e1d5152ae5150 100644 --- a/compiler/rustc_mir_transform/src/check_alignment.rs +++ b/compiler/rustc_mir_transform/src/check_alignment.rs @@ -7,7 +7,7 @@ use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt}; use rustc_session::Session; use tracing::{debug, trace}; -pub struct CheckAlignment; +pub(super) struct CheckAlignment; impl<'tcx> crate::MirPass<'tcx> for CheckAlignment { fn is_enabled(&self, sess: &Session) -> bool { diff --git a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs index fb03323e37e6e..234ed8206f5d5 100644 --- a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs +++ b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs @@ -8,7 +8,7 @@ use rustc_span::Span; use crate::errors; -pub struct CheckConstItemMutation; +pub(super) struct CheckConstItemMutation; impl<'tcx> crate::MirLint<'tcx> for CheckConstItemMutation { fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { diff --git a/compiler/rustc_mir_transform/src/check_packed_ref.rs b/compiler/rustc_mir_transform/src/check_packed_ref.rs index 2f957de7e78d8..1922d4fef25de 100644 --- a/compiler/rustc_mir_transform/src/check_packed_ref.rs +++ b/compiler/rustc_mir_transform/src/check_packed_ref.rs @@ -5,7 +5,7 @@ use rustc_middle::ty::{self, TyCtxt}; use crate::{errors, util}; -pub struct CheckPackedRef; +pub(super) struct CheckPackedRef; impl<'tcx> crate::MirLint<'tcx> for CheckPackedRef { fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { diff --git a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs index 2f3be1e425d8d..97ce16c06616f 100644 --- a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs +++ b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs @@ -21,7 +21,7 @@ use rustc_middle::mir::{Body, BorrowKind, CastKind, Rvalue, StatementKind, Termi use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::TyCtxt; -pub struct CleanupPostBorrowck; +pub(super) struct CleanupPostBorrowck; impl<'tcx> crate::MirPass<'tcx> for CleanupPostBorrowck { fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { diff --git a/compiler/rustc_mir_transform/src/copy_prop.rs b/compiler/rustc_mir_transform/src/copy_prop.rs index 85d25ca22318d..dc4ee58ea83e3 100644 --- a/compiler/rustc_mir_transform/src/copy_prop.rs +++ b/compiler/rustc_mir_transform/src/copy_prop.rs @@ -17,7 +17,7 @@ use crate::ssa::SsaLocals; /// where each of the locals is only assigned once. /// /// We want to replace all those locals by `_a`, either copied or moved. -pub struct CopyProp; +pub(super) struct CopyProp; impl<'tcx> crate::MirPass<'tcx> for CopyProp { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index eefb748e49d51..ab77817eb9ee7 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -53,7 +53,7 @@ mod by_move_body; use std::{iter, ops}; -pub use by_move_body::coroutine_by_move_body_def_id; +pub(super) use by_move_body::coroutine_by_move_body_def_id; use rustc_data_structures::fx::FxHashSet; use rustc_errors::pluralize; use rustc_hir as hir; @@ -85,7 +85,7 @@ use tracing::{debug, instrument, trace}; use crate::deref_separator::deref_finder; use crate::{abort_unwinding_calls, errors, pass_manager as pm, simplify}; -pub struct StateTransform; +pub(super) struct StateTransform; struct RenameLocalVisitor<'tcx> { from: Local, diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs index 9e35dfed0ee8d..6476f3c623841 100644 --- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs +++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs @@ -82,7 +82,7 @@ use rustc_middle::ty::{self, InstanceKind, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::symbol::kw; use rustc_target::abi::{FieldIdx, VariantIdx}; -pub fn coroutine_by_move_body_def_id<'tcx>( +pub(crate) fn coroutine_by_move_body_def_id<'tcx>( tcx: TyCtxt<'tcx>, coroutine_def_id: LocalDefId, ) -> DefId { diff --git a/compiler/rustc_mir_transform/src/cost_checker.rs b/compiler/rustc_mir_transform/src/cost_checker.rs index a1c1422912ee3..59b403538a33d 100644 --- a/compiler/rustc_mir_transform/src/cost_checker.rs +++ b/compiler/rustc_mir_transform/src/cost_checker.rs @@ -12,7 +12,7 @@ const CONST_SWITCH_BONUS: usize = 10; /// Verify that the callee body is compatible with the caller. #[derive(Clone)] -pub(crate) struct CostChecker<'b, 'tcx> { +pub(super) struct CostChecker<'b, 'tcx> { tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, penalty: usize, @@ -22,7 +22,7 @@ pub(crate) struct CostChecker<'b, 'tcx> { } impl<'b, 'tcx> CostChecker<'b, 'tcx> { - pub fn new( + pub(super) fn new( tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, instance: Option>, @@ -36,7 +36,7 @@ impl<'b, 'tcx> CostChecker<'b, 'tcx> { /// Needed because the `CostChecker` is used sometimes for just blocks, /// and even the full `Inline` doesn't call `visit_body`, so there's nowhere /// to put this logic in the visitor. - pub fn add_function_level_costs(&mut self) { + pub(super) fn add_function_level_costs(&mut self) { fn is_call_like(bbd: &BasicBlockData<'_>) -> bool { use TerminatorKind::*; match bbd.terminator().kind { @@ -64,7 +64,7 @@ impl<'b, 'tcx> CostChecker<'b, 'tcx> { } } - pub fn cost(&self) -> usize { + pub(super) fn cost(&self) -> usize { usize::saturating_sub(self.penalty, self.bonus) } diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 4edba61fdec9e..042f589768a99 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -1,4 +1,4 @@ -pub mod query; +pub(super) mod query; mod counters; mod graph; @@ -32,7 +32,7 @@ use crate::coverage::mappings::ExtractedMappings; /// Inserts `StatementKind::Coverage` statements that either instrument the binary with injected /// counters, via intrinsic `llvm.instrprof.increment`, and/or inject metadata used during codegen /// to construct the coverage map. -pub struct InstrumentCoverage; +pub(super) struct InstrumentCoverage; impl<'tcx> crate::MirPass<'tcx> for InstrumentCoverage { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { diff --git a/compiler/rustc_mir_transform/src/cross_crate_inline.rs b/compiler/rustc_mir_transform/src/cross_crate_inline.rs index 50aaed090f6b8..ce109ef7674f0 100644 --- a/compiler/rustc_mir_transform/src/cross_crate_inline.rs +++ b/compiler/rustc_mir_transform/src/cross_crate_inline.rs @@ -10,7 +10,7 @@ use rustc_span::sym; use crate::{inline, pass_manager as pm}; -pub fn provide(providers: &mut Providers) { +pub(super) fn provide(providers: &mut Providers) { providers.cross_crate_inlinable = cross_crate_inlinable; } diff --git a/compiler/rustc_mir_transform/src/ctfe_limit.rs b/compiler/rustc_mir_transform/src/ctfe_limit.rs index ea473b64ce540..bd58b1b668997 100644 --- a/compiler/rustc_mir_transform/src/ctfe_limit.rs +++ b/compiler/rustc_mir_transform/src/ctfe_limit.rs @@ -8,7 +8,7 @@ use rustc_middle::mir::{ use rustc_middle::ty::TyCtxt; use tracing::instrument; -pub struct CtfeLimit; +pub(super) struct CtfeLimit; impl<'tcx> crate::MirPass<'tcx> for CtfeLimit { #[instrument(skip(self, _tcx, body))] diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 46f7408ef8064..d365989c8df20 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -26,7 +26,7 @@ use tracing::{debug, debug_span, instrument}; const BLOCK_LIMIT: usize = 100; const PLACE_LIMIT: usize = 100; -pub struct DataflowConstProp; +pub(super) struct DataflowConstProp; impl<'tcx> crate::MirPass<'tcx> for DataflowConstProp { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { @@ -332,7 +332,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> { } impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { - pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, map: Map<'tcx>) -> Self { + fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, map: Map<'tcx>) -> Self { let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); Self { map, diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs index 9081a2e2e3028..65c037559c595 100644 --- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs +++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs @@ -28,7 +28,7 @@ use crate::util::is_within_packed; /// /// The `borrowed` set must be a `BitSet` of all the locals that are ever borrowed in this body. It /// can be generated via the [`borrowed_locals`] function. -pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { +fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let borrowed_locals = borrowed_locals(body); // If the user requests complete debuginfo, mark the locals that appear in it as live, so @@ -127,7 +127,7 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { } } -pub enum DeadStoreElimination { +pub(super) enum DeadStoreElimination { Initial, Final, } diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs index 71af099199ea9..e870a71b05aa7 100644 --- a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs +++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs @@ -150,7 +150,7 @@ fn type_will_always_be_passed_directly(ty: Ty<'_>) -> bool { /// body of the function instead of just the signature. These can be useful for optimization /// purposes on a best-effort basis. We compute them here and store them into the crate metadata so /// dependent crates can use them. -pub fn deduced_param_attrs<'tcx>( +pub(super) fn deduced_param_attrs<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, ) -> &'tcx [DeducedParamAttrs] { diff --git a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs index be50c1da8a438..c8179d513c7ce 100644 --- a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs +++ b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs @@ -13,7 +13,7 @@ use tracing::debug; use super::simplify::simplify_cfg; -pub struct DeduplicateBlocks; +pub(super) struct DeduplicateBlocks; impl<'tcx> crate::MirPass<'tcx> for DeduplicateBlocks { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { diff --git a/compiler/rustc_mir_transform/src/deref_separator.rs b/compiler/rustc_mir_transform/src/deref_separator.rs index a878f777448f5..60bf323613d29 100644 --- a/compiler/rustc_mir_transform/src/deref_separator.rs +++ b/compiler/rustc_mir_transform/src/deref_separator.rs @@ -5,9 +5,9 @@ use rustc_middle::mir::visit::{MutVisitor, PlaceContext}; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; -pub struct Derefer; +pub(super) struct Derefer; -pub struct DerefChecker<'a, 'tcx> { +struct DerefChecker<'a, 'tcx> { tcx: TyCtxt<'tcx>, patcher: MirPatch<'tcx>, local_decls: &'a IndexVec>, @@ -67,7 +67,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for DerefChecker<'a, 'tcx> { } } -pub fn deref_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { +pub(super) fn deref_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let patch = MirPatch::new(body); let mut checker = DerefChecker { tcx, patcher: patch, local_decls: &body.local_decls }; diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index 67bee36b8a5e2..175097e30ee30 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -146,7 +146,7 @@ use rustc_mir_dataflow::points::{save_as_intervals, DenseLocationMap, PointIndex use rustc_mir_dataflow::Analysis; use tracing::{debug, trace}; -pub struct DestinationPropagation; +pub(super) struct DestinationPropagation; impl<'tcx> crate::MirPass<'tcx> for DestinationPropagation { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { diff --git a/compiler/rustc_mir_transform/src/dump_mir.rs b/compiler/rustc_mir_transform/src/dump_mir.rs index 06ae1b490d75c..1640d34d6c8ee 100644 --- a/compiler/rustc_mir_transform/src/dump_mir.rs +++ b/compiler/rustc_mir_transform/src/dump_mir.rs @@ -7,7 +7,7 @@ use rustc_middle::mir::{write_mir_pretty, Body}; use rustc_middle::ty::TyCtxt; use rustc_session::config::{OutFileName, OutputType}; -pub struct Marker(pub &'static str); +pub(super) struct Marker(pub &'static str); impl<'tcx> crate::MirPass<'tcx> for Marker { fn name(&self) -> &'static str { diff --git a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs index 1c54cd70023d6..c18344c3aa3a9 100644 --- a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs +++ b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs @@ -90,7 +90,7 @@ use super::simplify::simplify_cfg; /// | ... | /// ================= /// ``` -pub struct EarlyOtherwiseBranch; +pub(super) struct EarlyOtherwiseBranch; impl<'tcx> crate::MirPass<'tcx> for EarlyOtherwiseBranch { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { diff --git a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs index 66e49d556e23c..d2ef648a20ffa 100644 --- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs +++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs @@ -11,7 +11,7 @@ use rustc_middle::ty::{Ty, TyCtxt}; use rustc_target::abi::FieldIdx; /// Constructs the types used when accessing a Box's pointer -pub fn build_ptr_tys<'tcx>( +fn build_ptr_tys<'tcx>( tcx: TyCtxt<'tcx>, pointee: Ty<'tcx>, unique_did: DefId, @@ -26,7 +26,7 @@ pub fn build_ptr_tys<'tcx>( } /// Constructs the projection needed to access a Box's pointer -pub fn build_projection<'tcx>( +pub(super) fn build_projection<'tcx>( unique_ty: Ty<'tcx>, nonnull_ty: Ty<'tcx>, ptr_ty: Ty<'tcx>, @@ -88,7 +88,7 @@ impl<'tcx, 'a> MutVisitor<'tcx> for ElaborateBoxDerefVisitor<'tcx, 'a> { } } -pub struct ElaborateBoxDerefs; +pub(super) struct ElaborateBoxDerefs; impl<'tcx> crate::MirPass<'tcx> for ElaborateBoxDerefs { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index f4a951ebde600..fba4320fb5dc5 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -47,7 +47,7 @@ use crate::deref_separator::deref_finder; /// } /// } /// ``` -pub struct ElaborateDrops; +pub(super) struct ElaborateDrops; impl<'tcx> crate::MirPass<'tcx> for ElaborateDrops { #[instrument(level = "trace", skip(self, tcx, body))] diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index 2703dc57cdad9..9a93c3a72b1c9 100644 --- a/compiler/rustc_mir_transform/src/errors.rs +++ b/compiler/rustc_mir_transform/src/errors.rs @@ -64,7 +64,7 @@ impl<'a, P: std::fmt::Debug> LintDiagnostic<'a, ()> for AssertLint

{ } impl AssertLintKind { - pub fn lint(&self) -> &'static Lint { + pub(crate) fn lint(&self) -> &'static Lint { match self { AssertLintKind::ArithmeticOverflow => lint::builtin::ARITHMETIC_OVERFLOW, AssertLintKind::UnconditionalPanic => lint::builtin::UNCONDITIONAL_PANIC, diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs index 199fd0f10ee2c..0efaa172e0c6f 100644 --- a/compiler/rustc_mir_transform/src/function_item_references.rs +++ b/compiler/rustc_mir_transform/src/function_item_references.rs @@ -11,7 +11,7 @@ use rustc_target::spec::abi::Abi; use crate::errors; -pub struct FunctionItemReferences; +pub(super) struct FunctionItemReferences; impl<'tcx> crate::MirLint<'tcx> for FunctionItemReferences { fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index df0fcc42e5926..e5d2b13efd8fe 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -109,7 +109,7 @@ use tracing::{debug, instrument, trace}; use crate::ssa::{AssignedValue, SsaLocals}; -pub struct GVN; +pub(super) struct GVN; impl<'tcx> crate::MirPass<'tcx> for GVN { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 6cc7e0ee1e4bc..9d2addecb6e50 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -32,6 +32,8 @@ pub(crate) mod cycle; const TOP_DOWN_DEPTH_LIMIT: usize = 5; +// Made public so that `mir_drops_elaborated_and_const_checked` can be overridden +// by custom rustc drivers, running all the steps by themselves. See #114628. pub struct Inline; #[derive(Copy, Clone, Debug)] diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index 4fbfa744e6733..a9591bf39848f 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -13,13 +13,13 @@ use rustc_target::spec::abi::Abi; use crate::simplify::simplify_duplicate_switch_targets; use crate::take_array; -pub enum InstSimplify { +pub(super) enum InstSimplify { BeforeInline, AfterSimplifyCfg, } impl InstSimplify { - pub fn name(&self) -> &'static str { + fn name(&self) -> &'static str { match self { InstSimplify::BeforeInline => "InstSimplify-before-inline", InstSimplify::AfterSimplifyCfg => "InstSimplify-after-simplifycfg", diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index 02dd56e1b4fdb..e950c2cb72ab8 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -55,7 +55,7 @@ use tracing::{debug, instrument, trace}; use crate::cost_checker::CostChecker; -pub struct JumpThreading; +pub(super) struct JumpThreading; const MAX_BACKTRACK: usize = 5; const MAX_COST: usize = 100; diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs index 61405fb25c6f2..e964310c5429e 100644 --- a/compiler/rustc_mir_transform/src/known_panics_lint.rs +++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs @@ -26,7 +26,7 @@ use tracing::{debug, instrument, trace}; use crate::errors::{AssertLint, AssertLintKind}; -pub struct KnownPanicsLint; +pub(super) struct KnownPanicsLint; impl<'tcx> crate::MirLint<'tcx> for KnownPanicsLint { fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { @@ -852,7 +852,7 @@ const MAX_ALLOC_LIMIT: u64 = 1024; /// The mode that `ConstProp` is allowed to run in for a given `Local`. #[derive(Clone, Copy, Debug, PartialEq)] -pub enum ConstPropMode { +enum ConstPropMode { /// The `Local` can be propagated into and reads of this `Local` can also be propagated. FullConstProp, /// The `Local` can only be propagated into and from its own block. @@ -864,7 +864,7 @@ pub enum ConstPropMode { /// A visitor that determines locals in a MIR body /// that can be const propagated -pub struct CanConstProp { +struct CanConstProp { can_const_prop: IndexVec, // False at the beginning. Once set, no more assignments are allowed to that local. found_assignment: BitSet, @@ -872,7 +872,7 @@ pub struct CanConstProp { impl CanConstProp { /// Returns true if `local` can be propagated - pub fn check<'tcx>( + fn check<'tcx>( tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, body: &Body<'tcx>, diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs index f02ba71ddc64c..f61cf236f77cc 100644 --- a/compiler/rustc_mir_transform/src/large_enums.rs +++ b/compiler/rustc_mir_transform/src/large_enums.rs @@ -23,7 +23,7 @@ use rustc_target::abi::{HasDataLayout, Size, TagEncoding, Variants}; /// In summary, what this does is at runtime determine which enum variant is active, /// and instead of copying all the bytes of the largest possible variant, /// copy only the bytes for the currently active variant. -pub struct EnumSizeOpt { +pub(super) struct EnumSizeOpt { pub(crate) discrepancy: u64, } diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 62e73ba2c8e24..0bbbf047f634c 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -11,6 +11,7 @@ #![feature(round_char_boundary)] #![feature(try_blocks)] #![feature(yeet_expr)] +#![warn(unreachable_pub)] // tidy-alphabetical-end use hir::ConstContext; @@ -72,6 +73,8 @@ mod errors; mod ffi_unwind_calls; mod function_item_references; mod gvn; +// Made public so that `mir_drops_elaborated_and_const_checked` can be overridden +// by custom rustc drivers, running all the steps by themselves. See #114628. pub mod inline; mod instsimplify; mod jump_threading; @@ -459,8 +462,8 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> & tcx.alloc_steal_mir(body) } -// Made public such that `mir_drops_elaborated_and_const_checked` can be overridden -// by custom rustc drivers, running all the steps by themselves. +// Made public so that `mir_drops_elaborated_and_const_checked` can be overridden +// by custom rustc drivers, running all the steps by themselves. See #114628. pub fn run_analysis_to_runtime_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { assert!(body.phase == MirPhase::Analysis(AnalysisPhase::Initial)); let did = body.source.def_id(); diff --git a/compiler/rustc_mir_transform/src/lint.rs b/compiler/rustc_mir_transform/src/lint.rs index 746068064b8fb..23733994a8b4a 100644 --- a/compiler/rustc_mir_transform/src/lint.rs +++ b/compiler/rustc_mir_transform/src/lint.rs @@ -13,7 +13,7 @@ use rustc_mir_dataflow::impls::{MaybeStorageDead, MaybeStorageLive}; use rustc_mir_dataflow::storage::always_storage_live_locals; use rustc_mir_dataflow::{Analysis, ResultsCursor}; -pub fn lint_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, when: String) { +pub(super) fn lint_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, when: String) { let always_live_locals = &always_storage_live_locals(body); let maybe_storage_live = MaybeStorageLive::new(Cow::Borrowed(always_live_locals)) diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index 55eec33230615..134a4cad265b4 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -7,7 +7,7 @@ use rustc_span::symbol::sym; use crate::take_array; -pub struct LowerIntrinsics; +pub(super) struct LowerIntrinsics; impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { diff --git a/compiler/rustc_mir_transform/src/lower_slice_len.rs b/compiler/rustc_mir_transform/src/lower_slice_len.rs index 555309a775001..ca59d4d12acad 100644 --- a/compiler/rustc_mir_transform/src/lower_slice_len.rs +++ b/compiler/rustc_mir_transform/src/lower_slice_len.rs @@ -5,7 +5,7 @@ use rustc_hir::def_id::DefId; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; -pub struct LowerSliceLenCalls; +pub(super) struct LowerSliceLenCalls; impl<'tcx> crate::MirPass<'tcx> for LowerSliceLenCalls { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { @@ -17,7 +17,7 @@ impl<'tcx> crate::MirPass<'tcx> for LowerSliceLenCalls { } } -pub fn lower_slice_len_calls<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { +fn lower_slice_len_calls<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let language_items = tcx.lang_items(); let Some(slice_len_fn_item_def_id) = language_items.slice_len_fn() else { // there is no lang item to compare to :) diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs index 233b39fb47a41..2a2616b20a6de 100644 --- a/compiler/rustc_mir_transform/src/match_branches.rs +++ b/compiler/rustc_mir_transform/src/match_branches.rs @@ -10,7 +10,7 @@ use rustc_type_ir::TyKind::*; use super::simplify::simplify_cfg; -pub struct MatchBranchSimplification; +pub(super) struct MatchBranchSimplification; impl<'tcx> crate::MirPass<'tcx> for MatchBranchSimplification { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { diff --git a/compiler/rustc_mir_transform/src/mentioned_items.rs b/compiler/rustc_mir_transform/src/mentioned_items.rs index 41ce03caf0873..7f9d0a5b6985c 100644 --- a/compiler/rustc_mir_transform/src/mentioned_items.rs +++ b/compiler/rustc_mir_transform/src/mentioned_items.rs @@ -5,7 +5,7 @@ use rustc_middle::ty::{self, TyCtxt}; use rustc_session::Session; use rustc_span::source_map::Spanned; -pub struct MentionedItems; +pub(super) struct MentionedItems; struct MentionedItemsVisitor<'a, 'tcx> { tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_mir_transform/src/multiple_return_terminators.rs b/compiler/rustc_mir_transform/src/multiple_return_terminators.rs index 1b4972d487eea..b6d6ef5de1da9 100644 --- a/compiler/rustc_mir_transform/src/multiple_return_terminators.rs +++ b/compiler/rustc_mir_transform/src/multiple_return_terminators.rs @@ -7,7 +7,7 @@ use rustc_middle::ty::TyCtxt; use crate::simplify; -pub struct MultipleReturnTerminators; +pub(super) struct MultipleReturnTerminators; impl<'tcx> crate::MirPass<'tcx> for MultipleReturnTerminators { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { diff --git a/compiler/rustc_mir_transform/src/nrvo.rs b/compiler/rustc_mir_transform/src/nrvo.rs index 94573a9d89bfd..98fa149e2bc71 100644 --- a/compiler/rustc_mir_transform/src/nrvo.rs +++ b/compiler/rustc_mir_transform/src/nrvo.rs @@ -30,7 +30,7 @@ use tracing::{debug, trace}; /// /// [#47954]: https://github.com/rust-lang/rust/pull/47954 /// [#71003]: https://github.com/rust-lang/rust/pull/71003 -pub struct RenameReturnPlace; +pub(super) struct RenameReturnPlace; impl<'tcx> crate::MirPass<'tcx> for RenameReturnPlace { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index 28d4e1a1c9184..60ece5e7db97d 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -269,12 +269,7 @@ pub(super) fn validate_body<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, when validate::Validator { when, mir_phase: body.phase }.run_pass(tcx, body); } -pub(super) fn dump_mir_for_pass<'tcx>( - tcx: TyCtxt<'tcx>, - body: &Body<'tcx>, - pass_name: &str, - is_after: bool, -) { +fn dump_mir_for_pass<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, pass_name: &str, is_after: bool) { mir::dump_mir( tcx, true, diff --git a/compiler/rustc_mir_transform/src/prettify.rs b/compiler/rustc_mir_transform/src/prettify.rs index ad71c6226601c..ef011d230c279 100644 --- a/compiler/rustc_mir_transform/src/prettify.rs +++ b/compiler/rustc_mir_transform/src/prettify.rs @@ -15,7 +15,7 @@ use rustc_session::Session; /// /// Thus after this pass, all the successors of a block are later than it in the /// `IndexVec`, unless that successor is a back-edge (such as from a loop). -pub struct ReorderBasicBlocks; +pub(super) struct ReorderBasicBlocks; impl<'tcx> crate::MirPass<'tcx> for ReorderBasicBlocks { fn is_enabled(&self, _session: &Session) -> bool { @@ -43,7 +43,7 @@ impl<'tcx> crate::MirPass<'tcx> for ReorderBasicBlocks { /// assigned or referenced will have a smaller number. /// /// (Does not reorder arguments nor the [`RETURN_PLACE`].) -pub struct ReorderLocals; +pub(super) struct ReorderLocals; impl<'tcx> crate::MirPass<'tcx> for ReorderLocals { fn is_enabled(&self, _session: &Session) -> bool { @@ -135,8 +135,8 @@ impl<'tcx> Visitor<'tcx> for LocalFinder { } struct LocalUpdater<'tcx> { - pub map: IndexVec, - pub tcx: TyCtxt<'tcx>, + map: IndexVec, + tcx: TyCtxt<'tcx>, } impl<'tcx> MutVisitor<'tcx> for LocalUpdater<'tcx> { diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index cf0a569ffa494..65309f63d5937 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -37,7 +37,7 @@ use tracing::{debug, instrument}; /// After this pass is run, `promoted_fragments` will hold the MIR body corresponding to each /// newly created `Constant`. #[derive(Default)] -pub struct PromoteTemps<'tcx> { +pub(super) struct PromoteTemps<'tcx> { pub promoted_fragments: Cell>>, } diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs index 4a447d24ccec7..25b98786c66b7 100644 --- a/compiler/rustc_mir_transform/src/ref_prop.rs +++ b/compiler/rustc_mir_transform/src/ref_prop.rs @@ -70,7 +70,7 @@ use crate::ssa::{SsaLocals, StorageLiveLocals}; /// /// For immutable borrows, we do not need to preserve such uniqueness property, /// so we perform all the possible instantiations without removing the `_1 = &_2` statement. -pub struct ReferencePropagation; +pub(super) struct ReferencePropagation; impl<'tcx> crate::MirPass<'tcx> for ReferencePropagation { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs index ccba8d015e3a6..37197c3f573d3 100644 --- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs +++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs @@ -8,7 +8,7 @@ use tracing::debug; /// A pass that removes noop landing pads and replaces jumps to them with /// `UnwindAction::Continue`. This is important because otherwise LLVM generates /// terrible code for these. -pub struct RemoveNoopLandingPads; +pub(super) struct RemoveNoopLandingPads; impl<'tcx> crate::MirPass<'tcx> for RemoveNoopLandingPads { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { diff --git a/compiler/rustc_mir_transform/src/remove_place_mention.rs b/compiler/rustc_mir_transform/src/remove_place_mention.rs index 5801fdedcebb2..71399eb72f004 100644 --- a/compiler/rustc_mir_transform/src/remove_place_mention.rs +++ b/compiler/rustc_mir_transform/src/remove_place_mention.rs @@ -4,7 +4,7 @@ use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; use tracing::trace; -pub struct RemovePlaceMention; +pub(super) struct RemovePlaceMention; impl<'tcx> crate::MirPass<'tcx> for RemovePlaceMention { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { diff --git a/compiler/rustc_mir_transform/src/remove_storage_markers.rs b/compiler/rustc_mir_transform/src/remove_storage_markers.rs index 329b30d3890a3..3ecb4a8994f5f 100644 --- a/compiler/rustc_mir_transform/src/remove_storage_markers.rs +++ b/compiler/rustc_mir_transform/src/remove_storage_markers.rs @@ -4,7 +4,7 @@ use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; use tracing::trace; -pub struct RemoveStorageMarkers; +pub(super) struct RemoveStorageMarkers; impl<'tcx> crate::MirPass<'tcx> for RemoveStorageMarkers { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { diff --git a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs index aafe971311d31..c58f492655a84 100644 --- a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs @@ -14,7 +14,7 @@ use rustc_target::abi::FieldIdx; /// like [#90770]. /// /// [#90770]: https://github.com/rust-lang/rust/issues/90770 -pub struct RemoveUninitDrops; +pub(super) struct RemoveUninitDrops; impl<'tcx> crate::MirPass<'tcx> for RemoveUninitDrops { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { diff --git a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs index 43109aae0fb6c..28925ba1beb13 100644 --- a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs @@ -10,7 +10,7 @@ use tracing::{debug, trace}; use super::simplify::simplify_cfg; -pub struct RemoveUnneededDrops; +pub(super) struct RemoveUnneededDrops; impl<'tcx> crate::MirPass<'tcx> for RemoveUnneededDrops { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs index 9aa46bd4fbae6..f13bb1c5993d5 100644 --- a/compiler/rustc_mir_transform/src/remove_zsts.rs +++ b/compiler/rustc_mir_transform/src/remove_zsts.rs @@ -4,7 +4,7 @@ use rustc_middle::mir::visit::*; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, TyCtxt}; -pub struct RemoveZsts; +pub(super) struct RemoveZsts; impl<'tcx> crate::MirPass<'tcx> for RemoveZsts { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { diff --git a/compiler/rustc_mir_transform/src/required_consts.rs b/compiler/rustc_mir_transform/src/required_consts.rs index 50637e2ac03bb..ebcf5b5d27b84 100644 --- a/compiler/rustc_mir_transform/src/required_consts.rs +++ b/compiler/rustc_mir_transform/src/required_consts.rs @@ -1,7 +1,7 @@ use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::{traversal, Body, ConstOperand, Location}; -pub struct RequiredConstsVisitor<'a, 'tcx> { +pub(super) struct RequiredConstsVisitor<'a, 'tcx> { required_consts: &'a mut Vec>, } @@ -10,7 +10,7 @@ impl<'a, 'tcx> RequiredConstsVisitor<'a, 'tcx> { RequiredConstsVisitor { required_consts } } - pub fn compute_required_consts(body: &mut Body<'tcx>) { + pub(super) fn compute_required_consts(body: &mut Body<'tcx>) { let mut required_consts = Vec::new(); let mut required_consts_visitor = RequiredConstsVisitor::new(&mut required_consts); for (bb, bb_data) in traversal::reverse_postorder(&body) { diff --git a/compiler/rustc_mir_transform/src/reveal_all.rs b/compiler/rustc_mir_transform/src/reveal_all.rs index 29312a99cbc01..3db962bd94aee 100644 --- a/compiler/rustc_mir_transform/src/reveal_all.rs +++ b/compiler/rustc_mir_transform/src/reveal_all.rs @@ -4,7 +4,7 @@ use rustc_middle::mir::visit::*; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, TyCtxt}; -pub struct RevealAll; +pub(super) struct RevealAll; impl<'tcx> crate::MirPass<'tcx> for RevealAll { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 8c70e4291185d..cf8ef580b2720 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -26,7 +26,7 @@ use crate::{ mod async_destructor_ctor; -pub fn provide(providers: &mut Providers) { +pub(super) fn provide(providers: &mut Providers) { providers.mir_shims = make_shim; } @@ -331,7 +331,7 @@ fn new_body<'tcx>( body } -pub struct DropShimElaborator<'a, 'tcx> { +pub(super) struct DropShimElaborator<'a, 'tcx> { pub body: &'a Body<'tcx>, pub patch: MirPatch<'tcx>, pub tcx: TyCtxt<'tcx>, @@ -913,7 +913,7 @@ fn build_call_shim<'tcx>( body } -pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> { +pub(super) fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> { debug_assert!(tcx.is_constructor(ctor_id)); let param_env = tcx.param_env_reveal_all_normalized(ctor_id); diff --git a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs index 50810f23113f3..c88953a1d1a20 100644 --- a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs +++ b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs @@ -23,7 +23,7 @@ use tracing::debug; use super::{local_decls_for_sig, new_body}; -pub fn build_async_destructor_ctor_shim<'tcx>( +pub(super) fn build_async_destructor_ctor_shim<'tcx>( tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>, diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index 1478b86d3c765..cb8e1dfda98ba 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -35,7 +35,7 @@ use rustc_span::DUMMY_SP; use smallvec::SmallVec; use tracing::{debug, trace}; -pub enum SimplifyCfg { +pub(super) enum SimplifyCfg { Initial, PromoteConsts, RemoveFalseEdges, @@ -50,7 +50,7 @@ pub enum SimplifyCfg { } impl SimplifyCfg { - pub fn name(&self) -> &'static str { + fn name(&self) -> &'static str { match self { SimplifyCfg::Initial => "SimplifyCfg-initial", SimplifyCfg::PromoteConsts => "SimplifyCfg-promote-consts", @@ -66,7 +66,7 @@ impl SimplifyCfg { } } -pub(crate) fn simplify_cfg(body: &mut Body<'_>) { +pub(super) fn simplify_cfg(body: &mut Body<'_>) { CfgSimplifier::new(body).simplify(); remove_dead_blocks(body); @@ -85,13 +85,13 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyCfg { } } -pub struct CfgSimplifier<'a, 'tcx> { +struct CfgSimplifier<'a, 'tcx> { basic_blocks: &'a mut IndexSlice>, pred_count: IndexVec, } impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { - pub fn new(body: &'a mut Body<'tcx>) -> Self { + fn new(body: &'a mut Body<'tcx>) -> Self { let mut pred_count = IndexVec::from_elem(0u32, &body.basic_blocks); // we can't use mir.predecessors() here because that counts @@ -111,7 +111,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { CfgSimplifier { basic_blocks, pred_count } } - pub fn simplify(mut self) { + fn simplify(mut self) { self.strip_nops(); // Vec of the blocks that should be merged. We store the indices here, instead of the @@ -280,7 +280,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { } } -pub fn simplify_duplicate_switch_targets(terminator: &mut Terminator<'_>) { +pub(super) fn simplify_duplicate_switch_targets(terminator: &mut Terminator<'_>) { if let TerminatorKind::SwitchInt { targets, .. } = &mut terminator.kind { let otherwise = targets.otherwise(); if targets.iter().any(|t| t.1 == otherwise) { @@ -292,7 +292,7 @@ pub fn simplify_duplicate_switch_targets(terminator: &mut Terminator<'_>) { } } -pub(crate) fn remove_dead_blocks(body: &mut Body<'_>) { +pub(super) fn remove_dead_blocks(body: &mut Body<'_>) { let should_deduplicate_unreachable = |bbdata: &BasicBlockData<'_>| { // CfgSimplifier::simplify leaves behind some unreachable basic blocks without a // terminator. Those blocks will be deleted by remove_dead_blocks, but we run just @@ -360,7 +360,7 @@ pub(crate) fn remove_dead_blocks(body: &mut Body<'_>) { } } -pub enum SimplifyLocals { +pub(super) enum SimplifyLocals { BeforeConstProp, AfterGVN, Final, @@ -385,7 +385,7 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyLocals { } } -pub fn remove_unused_definitions<'tcx>(body: &mut Body<'tcx>) { +pub(super) fn remove_unused_definitions<'tcx>(body: &mut Body<'tcx>) { // First, we're going to get a count of *actual* uses for every `Local`. let mut used_locals = UsedLocals::new(body); @@ -397,7 +397,7 @@ pub fn remove_unused_definitions<'tcx>(body: &mut Body<'tcx>) { remove_unused_definitions_helper(&mut used_locals, body); } -pub fn simplify_locals<'tcx>(body: &mut Body<'tcx>, tcx: TyCtxt<'tcx>) { +fn simplify_locals<'tcx>(body: &mut Body<'tcx>, tcx: TyCtxt<'tcx>) { // First, we're going to get a count of *actual* uses for every `Local`. let mut used_locals = UsedLocals::new(body); diff --git a/compiler/rustc_mir_transform/src/simplify_branches.rs b/compiler/rustc_mir_transform/src/simplify_branches.rs index 5a014bb734683..e83b4727c4856 100644 --- a/compiler/rustc_mir_transform/src/simplify_branches.rs +++ b/compiler/rustc_mir_transform/src/simplify_branches.rs @@ -2,10 +2,11 @@ use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; use tracing::trace; -pub enum SimplifyConstCondition { +pub(super) enum SimplifyConstCondition { AfterConstProp, Final, } + /// A pass that replaces a branch with a goto when its condition is known. impl<'tcx> crate::MirPass<'tcx> for SimplifyConstCondition { fn name(&self) -> &'static str { diff --git a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs index bd30ecc59b3d7..644bcb58d567d 100644 --- a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs +++ b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs @@ -23,7 +23,7 @@ use tracing::trace; /// ```ignore (MIR) /// switchInt(_4) -> [43i32: bb3, otherwise: bb2]; /// ``` -pub struct SimplifyComparisonIntegral; +pub(super) struct SimplifyComparisonIntegral; impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { diff --git a/compiler/rustc_mir_transform/src/single_use_consts.rs b/compiler/rustc_mir_transform/src/single_use_consts.rs index 64a928728307b..26059268c37d4 100644 --- a/compiler/rustc_mir_transform/src/single_use_consts.rs +++ b/compiler/rustc_mir_transform/src/single_use_consts.rs @@ -19,7 +19,7 @@ use rustc_middle::ty::TyCtxt; /// /// It also removes *never*-used constants, since it had all the information /// needed to do that too, including updating the debug info. -pub struct SingleUseConsts; +pub(super) struct SingleUseConsts; impl<'tcx> crate::MirPass<'tcx> for SingleUseConsts { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs index 3c5ccc0c99a8a..e6dd2cfd862d8 100644 --- a/compiler/rustc_mir_transform/src/sroa.rs +++ b/compiler/rustc_mir_transform/src/sroa.rs @@ -11,7 +11,7 @@ use rustc_mir_dataflow::value_analysis::{excluded_locals, iter_fields}; use rustc_target::abi::{FieldIdx, FIRST_VARIANT}; use tracing::{debug, instrument}; -pub struct ScalarReplacementOfAggregates; +pub(super) struct ScalarReplacementOfAggregates; impl<'tcx> crate::MirPass<'tcx> for ScalarReplacementOfAggregates { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs index c1254766f0a97..cf8622cadd1ff 100644 --- a/compiler/rustc_mir_transform/src/ssa.rs +++ b/compiler/rustc_mir_transform/src/ssa.rs @@ -16,7 +16,7 @@ use rustc_middle::mir::*; use rustc_middle::ty::{ParamEnv, TyCtxt}; use tracing::{debug, instrument, trace}; -pub struct SsaLocals { +pub(super) struct SsaLocals { /// Assignments to each local. This defines whether the local is SSA. assignments: IndexVec>, /// We visit the body in reverse postorder, to ensure each local is assigned before it is used. @@ -32,14 +32,18 @@ pub struct SsaLocals { borrowed_locals: BitSet, } -pub enum AssignedValue<'a, 'tcx> { +pub(super) enum AssignedValue<'a, 'tcx> { Arg, Rvalue(&'a mut Rvalue<'tcx>), Terminator, } impl SsaLocals { - pub fn new<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, param_env: ParamEnv<'tcx>) -> SsaLocals { + pub(super) fn new<'tcx>( + tcx: TyCtxt<'tcx>, + body: &Body<'tcx>, + param_env: ParamEnv<'tcx>, + ) -> SsaLocals { let assignment_order = Vec::with_capacity(body.local_decls.len()); let assignments = IndexVec::from_elem(Set1::Empty, &body.local_decls); @@ -101,25 +105,25 @@ impl SsaLocals { ssa } - pub fn num_locals(&self) -> usize { + pub(super) fn num_locals(&self) -> usize { self.assignments.len() } - pub fn locals(&self) -> impl Iterator { + pub(super) fn locals(&self) -> impl Iterator { self.assignments.indices() } - pub fn is_ssa(&self, local: Local) -> bool { + pub(super) fn is_ssa(&self, local: Local) -> bool { matches!(self.assignments[local], Set1::One(_)) } /// Return the number of uses if a local that are not "Deref". - pub fn num_direct_uses(&self, local: Local) -> u32 { + pub(super) fn num_direct_uses(&self, local: Local) -> u32 { self.direct_uses[local] } #[inline] - pub fn assignment_dominates( + pub(super) fn assignment_dominates( &self, dominators: &Dominators, local: Local, @@ -131,7 +135,7 @@ impl SsaLocals { } } - pub fn assignments<'a, 'tcx>( + pub(super) fn assignments<'a, 'tcx>( &'a self, body: &'a Body<'tcx>, ) -> impl Iterator, Location)> + 'a { @@ -148,7 +152,7 @@ impl SsaLocals { }) } - pub fn for_each_assignment_mut<'tcx>( + pub(super) fn for_each_assignment_mut<'tcx>( &self, basic_blocks: &mut IndexSlice>, mut f: impl FnMut(Local, AssignedValue<'_, 'tcx>, Location), @@ -194,17 +198,17 @@ impl SsaLocals { /// _d => _a // transitively through _c /// /// Exception: we do not see through the return place, as it cannot be instantiated. - pub fn copy_classes(&self) -> &IndexSlice { + pub(super) fn copy_classes(&self) -> &IndexSlice { &self.copy_classes } /// Set of SSA locals that are immutably borrowed. - pub fn borrowed_locals(&self) -> &BitSet { + pub(super) fn borrowed_locals(&self) -> &BitSet { &self.borrowed_locals } /// Make a property uniform on a copy equivalence class by removing elements. - pub fn meet_copy_equivalence(&self, property: &mut BitSet) { + pub(super) fn meet_copy_equivalence(&self, property: &mut BitSet) { // Consolidate to have a local iff all its copies are. // // `copy_classes` defines equivalence classes between locals. The `local`s that recursively diff --git a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs index 51a322628ee69..6957394ed1044 100644 --- a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs +++ b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs @@ -12,7 +12,7 @@ use rustc_middle::ty::{Ty, TyCtxt}; use rustc_target::abi::{Abi, Variants}; use tracing::trace; -pub struct UnreachableEnumBranching; +pub(super) struct UnreachableEnumBranching; fn get_discriminant_local(terminator: &TerminatorKind<'_>) -> Option { if let TerminatorKind::SwitchInt { discr: Operand::Move(p), .. } = terminator { diff --git a/compiler/rustc_mir_transform/src/unreachable_prop.rs b/compiler/rustc_mir_transform/src/unreachable_prop.rs index b8da86f1a8dde..c60cbae21422c 100644 --- a/compiler/rustc_mir_transform/src/unreachable_prop.rs +++ b/compiler/rustc_mir_transform/src/unreachable_prop.rs @@ -10,7 +10,7 @@ use rustc_middle::mir::*; use rustc_middle::ty::{self, TyCtxt}; use rustc_target::abi::Size; -pub struct UnreachablePropagation; +pub(super) struct UnreachablePropagation; impl crate::MirPass<'_> for UnreachablePropagation { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index e515dfc5ea57f..18865c73f75b1 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -26,7 +26,7 @@ enum EdgeKind { Normal, } -pub struct Validator { +pub(super) struct Validator { /// Describes at which point in the pipeline this validation is happening. pub when: String, /// The phase for which we are upholding the dialect. If the given phase forbids a specific @@ -531,7 +531,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { /// /// `caller_body` is used to detect cycles in MIR inlining and MIR validation before /// `optimized_mir` is available. -pub fn validate_types<'tcx>( +pub(super) fn validate_types<'tcx>( tcx: TyCtxt<'tcx>, mir_phase: MirPhase, param_env: ty::ParamEnv<'tcx>, From cd9fd274d1acf918468e197bdb65c1ed46309b78 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 28 Aug 2024 14:11:37 +1000 Subject: [PATCH 070/189] Factor out some more repetitive code. --- compiler/rustc_mir_transform/src/coroutine.rs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index ab77817eb9ee7..a9c56174206f1 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -1199,7 +1199,7 @@ fn insert_panic_block<'tcx>( message: AssertMessage<'tcx>, ) -> BasicBlock { let assert_block = BasicBlock::new(body.basic_blocks.len()); - let term = TerminatorKind::Assert { + let kind = TerminatorKind::Assert { cond: Operand::Constant(Box::new(ConstOperand { span: body.span, user_ty: None, @@ -1211,14 +1211,7 @@ fn insert_panic_block<'tcx>( unwind: UnwindAction::Continue, }; - let source_info = SourceInfo::outermost(body.span); - body.basic_blocks_mut().push(BasicBlockData { - statements: Vec::new(), - terminator: Some(Terminator { source_info, kind: term }), - is_cleanup: false, - }); - - assert_block + insert_term_block(body, kind) } fn can_return<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { From bbe28cf1d9c52888f2a48324001c6599fc3d2853 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 5 Sep 2024 17:17:26 +1000 Subject: [PATCH 071/189] Remove `serialized_bitcode` from `LtoModuleCodegen`. It's unused. --- compiler/rustc_codegen_gcc/src/back/lto.rs | 4 +--- compiler/rustc_codegen_llvm/src/back/lto.rs | 8 ++------ compiler/rustc_codegen_ssa/src/back/lto.rs | 12 ++++-------- 3 files changed, 7 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/back/lto.rs b/compiler/rustc_codegen_gcc/src/back/lto.rs index 6b2dbbbed6771..c2adab7137f62 100644 --- a/compiler/rustc_codegen_gcc/src/back/lto.rs +++ b/compiler/rustc_codegen_gcc/src/back/lto.rs @@ -272,7 +272,6 @@ fn fat_lto( }*/ } }; - let mut serialized_bitcode = Vec::new(); { info!("using {:?} as a base module", module.name); @@ -317,7 +316,6 @@ fn fat_lto( unimplemented!("from uncompressed file") } } - serialized_bitcode.push(bc_decoded); } save_temp_bitcode(cgcx, &module, "lto.input"); @@ -337,7 +335,7 @@ fn fat_lto( // of now. module.module_llvm.temp_dir = Some(tmp_path); - Ok(LtoModuleCodegen::Fat { module, _serialized_bitcode: serialized_bitcode }) + Ok(LtoModuleCodegen::Fat(module)) } pub struct ModuleBuffer(PathBuf); diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index aa6842c75cec7..09896b89ebf42 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -314,7 +314,6 @@ fn fat_lto( } } }; - let mut serialized_bitcode = Vec::new(); { let (llcx, llmod) = { let llvm = &module.module_llvm; @@ -342,9 +341,7 @@ fn fat_lto( serialized_modules.sort_by(|module1, module2| module1.1.cmp(&module2.1)); // For all serialized bitcode files we parse them and link them in as we did - // above, this is all mostly handled in C++. Like above, though, we don't - // know much about the memory management here so we err on the side of being - // save and persist everything with the original module. + // above, this is all mostly handled in C++. let mut linker = Linker::new(llmod); for (bc_decoded, name) in serialized_modules { let _timer = cgcx @@ -355,7 +352,6 @@ fn fat_lto( info!("linking {:?}", name); let data = bc_decoded.data(); linker.add(data).map_err(|()| write::llvm_err(dcx, LlvmError::LoadBitcode { name }))?; - serialized_bitcode.push(bc_decoded); } drop(linker); save_temp_bitcode(cgcx, &module, "lto.input"); @@ -372,7 +368,7 @@ fn fat_lto( } } - Ok(LtoModuleCodegen::Fat { module, _serialized_bitcode: serialized_bitcode }) + Ok(LtoModuleCodegen::Fat(module)) } pub(crate) struct Linker<'a>(&'a mut llvm::Linker<'a>); diff --git a/compiler/rustc_codegen_ssa/src/back/lto.rs b/compiler/rustc_codegen_ssa/src/back/lto.rs index 8b6f6b5a220a4..1e1e039882be0 100644 --- a/compiler/rustc_codegen_ssa/src/back/lto.rs +++ b/compiler/rustc_codegen_ssa/src/back/lto.rs @@ -41,18 +41,14 @@ pub struct ThinShared { } pub enum LtoModuleCodegen { - Fat { - module: ModuleCodegen, - _serialized_bitcode: Vec>, - }, - + Fat(ModuleCodegen), Thin(ThinModule), } impl LtoModuleCodegen { pub fn name(&self) -> &str { match *self { - LtoModuleCodegen::Fat { .. } => "everything", + LtoModuleCodegen::Fat(_) => "everything", LtoModuleCodegen::Thin(ref m) => m.name(), } } @@ -68,7 +64,7 @@ impl LtoModuleCodegen { cgcx: &CodegenContext, ) -> Result, FatalError> { match self { - LtoModuleCodegen::Fat { mut module, .. } => { + LtoModuleCodegen::Fat(mut module) => { B::optimize_fat(cgcx, &mut module)?; Ok(module) } @@ -81,7 +77,7 @@ impl LtoModuleCodegen { pub fn cost(&self) -> u64 { match *self { // Only one module with fat LTO, so the cost doesn't matter. - LtoModuleCodegen::Fat { .. } => 0, + LtoModuleCodegen::Fat(_) => 0, LtoModuleCodegen::Thin(ref m) => m.cost(), } } From a6735e44ca28207d0f2c87c1f47769fed82b56fe Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 9 Sep 2024 14:11:43 +1000 Subject: [PATCH 072/189] Add an explicit ignore message for "up-to-date" tests When running tests without the `--force-rerun` flag, compiletest will automatically skip any tests that (in its judgement) don't need to be run again since the last time they were run. This patch adds an explicit reason to those skipped tests, which is visible when running with `rust.verbose-tests = true` in `config.toml`. --- src/tools/compiletest/src/lib.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 5402e69bc664e..3294a3bd080b3 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -808,8 +808,11 @@ fn make_test( &config, cache, test_name, &test_path, src_file, revision, poisoned, ); // Ignore tests that already run and are up to date with respect to inputs. - if !config.force_rerun { - desc.ignore |= is_up_to_date(&config, testpaths, &early_props, revision, inputs); + if !config.force_rerun + && is_up_to_date(&config, testpaths, &early_props, revision, inputs) + { + desc.ignore = true; + desc.ignore_message = Some("up-to-date"); } test::TestDescAndFn { desc, From ec6fe4e19881bafa048e4b9c7c45610a555ff888 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 28 Aug 2024 15:27:51 +1000 Subject: [PATCH 073/189] Streamline `AbortUnwindingCalls`. Currently it constructs two vectors `calls_to_terminated` and `cleanups_to_remove` in the main loop, and then processes them after the main loop. But the processing can be done in the main loop, avoiding the need for the vectors. --- .../src/abort_unwinding_calls.rs | 41 +++++++------------ 1 file changed, 14 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs index 06ec065c91a21..8291df9be5349 100644 --- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs +++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs @@ -50,9 +50,7 @@ impl<'tcx> crate::MirPass<'tcx> for AbortUnwindingCalls { // with a function call, and whose function we're calling may unwind. // This will filter to functions with `extern "C-unwind"` ABIs, for // example. - let mut calls_to_terminate = Vec::new(); - let mut cleanups_to_remove = Vec::new(); - for (id, block) in body.basic_blocks.iter_enumerated() { + for block in body.basic_blocks.as_mut() { if block.is_cleanup { continue; } @@ -61,7 +59,7 @@ impl<'tcx> crate::MirPass<'tcx> for AbortUnwindingCalls { let call_can_unwind = match &terminator.kind { TerminatorKind::Call { func, .. } => { - let ty = func.ty(body, tcx); + let ty = func.ty(&body.local_decls, tcx); let sig = ty.fn_sig(tcx); let fn_def_id = match ty.kind() { ty::FnPtr(..) => None, @@ -86,33 +84,22 @@ impl<'tcx> crate::MirPass<'tcx> for AbortUnwindingCalls { _ => continue, }; - // If this function call can't unwind, then there's no need for it - // to have a landing pad. This means that we can remove any cleanup - // registered for it. if !call_can_unwind { - cleanups_to_remove.push(id); - continue; - } - - // Otherwise if this function can unwind, then if the outer function - // can also unwind there's nothing to do. If the outer function - // can't unwind, however, we need to change the landing pad for this - // function call to one that aborts. - if !body_can_unwind { - calls_to_terminate.push(id); + // If this function call can't unwind, then there's no need for it + // to have a landing pad. This means that we can remove any cleanup + // registered for it. + let cleanup = block.terminator_mut().unwind_mut().unwrap(); + *cleanup = UnwindAction::Unreachable; + } else if !body_can_unwind { + // Otherwise if this function can unwind, then if the outer function + // can also unwind there's nothing to do. If the outer function + // can't unwind, however, we need to change the landing pad for this + // function call to one that aborts. + let cleanup = block.terminator_mut().unwind_mut().unwrap(); + *cleanup = UnwindAction::Terminate(UnwindTerminateReason::Abi); } } - for id in calls_to_terminate { - let cleanup = body.basic_blocks_mut()[id].terminator_mut().unwind_mut().unwrap(); - *cleanup = UnwindAction::Terminate(UnwindTerminateReason::Abi); - } - - for id in cleanups_to_remove { - let cleanup = body.basic_blocks_mut()[id].terminator_mut().unwind_mut().unwrap(); - *cleanup = UnwindAction::Unreachable; - } - // We may have invalidated some `cleanup` blocks so clean those up now. super::simplify::remove_dead_blocks(body); } From cc09ab3c7510548ab5bcc23ca2e9e9517cd6acdf Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 29 Aug 2024 15:36:24 +1000 Subject: [PATCH 074/189] Simplify `verify_candidate_branch`. Let chains are perfect for this kind of function. --- .../src/early_otherwise_branch.rs | 60 +++++++------------ 1 file changed, 23 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs index c18344c3aa3a9..3884321df2a2c 100644 --- a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs +++ b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs @@ -310,42 +310,28 @@ fn verify_candidate_branch<'tcx>( ) -> bool { // In order for the optimization to be correct, the branch must... // ...have exactly one statement - let [statement] = branch.statements.as_slice() else { - return false; - }; - // ...assign the discriminant of `place` in that statement - let StatementKind::Assign(boxed) = &statement.kind else { return false }; - let (discr_place, Rvalue::Discriminant(from_place)) = &**boxed else { return false }; - if *from_place != place { - return false; - } - // ...make that assignment to a local - if discr_place.projection.len() != 0 { - return false; - } - // ...terminate on a `SwitchInt` that invalidates that local - let TerminatorKind::SwitchInt { discr: switch_op, targets, .. } = &branch.terminator().kind - else { - return false; - }; - if *switch_op != Operand::Move(*discr_place) { - return false; - } - // ...fall through to `destination` if the switch misses - if destination != targets.otherwise() { - return false; - } - // ...have a branch for value `value` - let mut iter = targets.iter(); - let Some((target_value, _)) = iter.next() else { - return false; - }; - if target_value != value { - return false; - } - // ...and have no more branches - if let Some(_) = iter.next() { - return false; + if let [statement] = branch.statements.as_slice() + // ...assign the discriminant of `place` in that statement + && let StatementKind::Assign(boxed) = &statement.kind + && let (discr_place, Rvalue::Discriminant(from_place)) = &**boxed + && *from_place == place + // ...make that assignment to a local + && discr_place.projection.is_empty() + // ...terminate on a `SwitchInt` that invalidates that local + && let TerminatorKind::SwitchInt { discr: switch_op, targets, .. } = + &branch.terminator().kind + && *switch_op == Operand::Move(*discr_place) + // ...fall through to `destination` if the switch misses + && destination == targets.otherwise() + // ...have a branch for value `value` + && let mut iter = targets.iter() + && let Some((target_value, _)) = iter.next() + && target_value == value + // ...and have no more branches + && iter.next().is_none() + { + true + } else { + false } - true } From 181fbd5ce8bd943e9b78fdd71dfb8f069ea44072 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 9 Sep 2024 08:49:47 +1000 Subject: [PATCH 075/189] Use `let`/`else` to de-indent `ElaborateBoxDerefs::run_pass`. --- .../src/elaborate_box_derefs.rs | 91 +++++++++---------- 1 file changed, 44 insertions(+), 47 deletions(-) diff --git a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs index d2ef648a20ffa..367a8c0759315 100644 --- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs +++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs @@ -92,64 +92,61 @@ pub(super) struct ElaborateBoxDerefs; impl<'tcx> crate::MirPass<'tcx> for ElaborateBoxDerefs { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if let Some(def_id) = tcx.lang_items().owned_box() { - let unique_did = tcx.adt_def(def_id).non_enum_variant().fields[FieldIdx::ZERO].did; + // If box is not present, this pass doesn't need to do anything. + let Some(def_id) = tcx.lang_items().owned_box() else { return }; - let Some(nonnull_def) = tcx.type_of(unique_did).instantiate_identity().ty_adt_def() - else { - span_bug!(tcx.def_span(unique_did), "expected Box to contain Unique") - }; + let unique_did = tcx.adt_def(def_id).non_enum_variant().fields[FieldIdx::ZERO].did; - let nonnull_did = nonnull_def.non_enum_variant().fields[FieldIdx::ZERO].did; + let Some(nonnull_def) = tcx.type_of(unique_did).instantiate_identity().ty_adt_def() else { + span_bug!(tcx.def_span(unique_did), "expected Box to contain Unique") + }; - let patch = MirPatch::new(body); + let nonnull_did = nonnull_def.non_enum_variant().fields[FieldIdx::ZERO].did; - let local_decls = &mut body.local_decls; + let patch = MirPatch::new(body); - let mut visitor = - ElaborateBoxDerefVisitor { tcx, unique_did, nonnull_did, local_decls, patch }; + let local_decls = &mut body.local_decls; - for (block, data) in body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut() { - visitor.visit_basic_block_data(block, data); - } + let mut visitor = + ElaborateBoxDerefVisitor { tcx, unique_did, nonnull_did, local_decls, patch }; - visitor.patch.apply(body); - - for debug_info in body.var_debug_info.iter_mut() { - if let VarDebugInfoContents::Place(place) = &mut debug_info.value { - let mut new_projections: Option> = None; - - for (base, elem) in place.iter_projections() { - let base_ty = base.ty(&body.local_decls, tcx).ty; - - if let PlaceElem::Deref = elem - && let Some(boxed_ty) = base_ty.boxed_ty() - { - // Clone the projections before us, since now we need to mutate them. - let new_projections = - new_projections.get_or_insert_with(|| base.projection.to_vec()); - - let (unique_ty, nonnull_ty, ptr_ty) = - build_ptr_tys(tcx, boxed_ty, unique_did, nonnull_did); - - new_projections.extend_from_slice(&build_projection( - unique_ty, nonnull_ty, ptr_ty, - )); - new_projections.push(PlaceElem::Deref); - } else if let Some(new_projections) = new_projections.as_mut() { - // Keep building up our projections list once we've started it. - new_projections.push(elem); - } - } + for (block, data) in body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut() { + visitor.visit_basic_block_data(block, data); + } + + visitor.patch.apply(body); + + for debug_info in body.var_debug_info.iter_mut() { + if let VarDebugInfoContents::Place(place) = &mut debug_info.value { + let mut new_projections: Option> = None; - // Store the mutated projections if we actually changed something. - if let Some(new_projections) = new_projections { - place.projection = tcx.mk_place_elems(&new_projections); + for (base, elem) in place.iter_projections() { + let base_ty = base.ty(&body.local_decls, tcx).ty; + + if let PlaceElem::Deref = elem + && let Some(boxed_ty) = base_ty.boxed_ty() + { + // Clone the projections before us, since now we need to mutate them. + let new_projections = + new_projections.get_or_insert_with(|| base.projection.to_vec()); + + let (unique_ty, nonnull_ty, ptr_ty) = + build_ptr_tys(tcx, boxed_ty, unique_did, nonnull_did); + + new_projections + .extend_from_slice(&build_projection(unique_ty, nonnull_ty, ptr_ty)); + new_projections.push(PlaceElem::Deref); + } else if let Some(new_projections) = new_projections.as_mut() { + // Keep building up our projections list once we've started it. + new_projections.push(elem); } } + + // Store the mutated projections if we actually changed something. + if let Some(new_projections) = new_projections { + place.projection = tcx.mk_place_elems(&new_projections); + } } - } else { - // box is not present, this pass doesn't need to do anything } } } From 4f2588f23a8e71bc9244990b7331accf02f83348 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 30 Aug 2024 15:57:43 +1000 Subject: [PATCH 076/189] Remove an unnecessary `continue`. Nothing comes after it within the loop. --- compiler/rustc_mir_transform/src/inline.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 9d2addecb6e50..b65e8c097d12d 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -158,7 +158,6 @@ impl<'tcx> Inliner<'tcx> { match self.try_inlining(caller_body, &callsite) { Err(reason) => { debug!("not-inlined {} [{}]", callsite.callee, reason); - continue; } Ok(new_blocks) => { debug!("inlined {}", callsite.callee); From 9cf90b9fc987a58c873643fbd0e26296b9675943 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 30 Aug 2024 16:09:47 +1000 Subject: [PATCH 077/189] Remove some unnecessary dereferences. --- compiler/rustc_mir_transform/src/inline.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index b65e8c097d12d..702efabe87193 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -639,7 +639,7 @@ impl<'tcx> Inliner<'tcx> { ); let dest_ty = dest.ty(caller_body, self.tcx); let temp = - Place::from(self.new_call_temp(caller_body, &callsite, dest_ty, return_block)); + Place::from(self.new_call_temp(caller_body, callsite, dest_ty, return_block)); caller_body[callsite.block].statements.push(Statement { source_info: callsite.source_info, kind: StatementKind::Assign(Box::new((temp, dest))), @@ -658,7 +658,7 @@ impl<'tcx> Inliner<'tcx> { true, self.new_call_temp( caller_body, - &callsite, + callsite, destination.ty(caller_body, self.tcx).ty, return_block, ), @@ -666,7 +666,7 @@ impl<'tcx> Inliner<'tcx> { }; // Copy the arguments if needed. - let args = self.make_call_args(args, &callsite, caller_body, &callee_body, return_block); + let args = self.make_call_args(args, callsite, caller_body, &callee_body, return_block); let mut integrator = Integrator { args: &args, From 7adde3f07494df316698c330f39a00e8105d53b1 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 30 Aug 2024 16:10:03 +1000 Subject: [PATCH 078/189] Make `CallSite` non-`Copy`. It doesn't need to be, and it's 72 bytes on 64-bit platforms, which is fairly large. --- compiler/rustc_mir_transform/src/inline.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 702efabe87193..03ef808efecb6 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -36,7 +36,7 @@ const TOP_DOWN_DEPTH_LIMIT: usize = 5; // by custom rustc drivers, running all the steps by themselves. See #114628. pub struct Inline; -#[derive(Copy, Clone, Debug)] +#[derive(Clone, Debug)] struct CallSite<'tcx> { callee: Instance<'tcx>, fn_sig: ty::PolyFnSig<'tcx>, From 751c8b481b71f47f8e337bd8e097af06bdcca0bc Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 30 Aug 2024 17:08:51 +1000 Subject: [PATCH 079/189] Use `LocalDecls` in a couple of places. It's nicer than the `IndexVec` type. --- compiler/rustc_mir_transform/src/add_subtyping_projections.rs | 3 +-- compiler/rustc_mir_transform/src/deref_separator.rs | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs index 5e43937fbe69c..ab6bf18b30cb3 100644 --- a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs +++ b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs @@ -1,4 +1,3 @@ -use rustc_index::IndexVec; use rustc_middle::mir::patch::MirPatch; use rustc_middle::mir::visit::MutVisitor; use rustc_middle::mir::*; @@ -9,7 +8,7 @@ pub(super) struct Subtyper; struct SubTypeChecker<'a, 'tcx> { tcx: TyCtxt<'tcx>, patcher: MirPatch<'tcx>, - local_decls: &'a IndexVec>, + local_decls: &'a LocalDecls<'tcx>, } impl<'a, 'tcx> MutVisitor<'tcx> for SubTypeChecker<'a, 'tcx> { diff --git a/compiler/rustc_mir_transform/src/deref_separator.rs b/compiler/rustc_mir_transform/src/deref_separator.rs index 60bf323613d29..ad7ccef4976aa 100644 --- a/compiler/rustc_mir_transform/src/deref_separator.rs +++ b/compiler/rustc_mir_transform/src/deref_separator.rs @@ -1,4 +1,3 @@ -use rustc_index::IndexVec; use rustc_middle::mir::patch::MirPatch; use rustc_middle::mir::visit::NonUseContext::VarDebugInfo; use rustc_middle::mir::visit::{MutVisitor, PlaceContext}; @@ -10,7 +9,7 @@ pub(super) struct Derefer; struct DerefChecker<'a, 'tcx> { tcx: TyCtxt<'tcx>, patcher: MirPatch<'tcx>, - local_decls: &'a IndexVec>, + local_decls: &'a LocalDecls<'tcx>, } impl<'a, 'tcx> MutVisitor<'tcx> for DerefChecker<'a, 'tcx> { From 54459536591630d33a864e89520638c52d8bcf56 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 3 Sep 2024 11:31:46 +1000 Subject: [PATCH 080/189] Improve consistency in `LowerIntrinsics`. In some cases `target` and `arg` are obtained fallibly, and in some cases they are obtained infallibly. This commit changes them all to infallible. --- .../src/lower_intrinsics.rs | 125 +++++++++--------- 1 file changed, 63 insertions(+), 62 deletions(-) diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index 134a4cad265b4..6d635606687a9 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -35,20 +35,19 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { terminator.kind = TerminatorKind::Goto { target }; } sym::forget => { - if let Some(target) = *target { - block.statements.push(Statement { - source_info: terminator.source_info, - kind: StatementKind::Assign(Box::new(( - *destination, - Rvalue::Use(Operand::Constant(Box::new(ConstOperand { - span: terminator.source_info.span, - user_ty: None, - const_: Const::zero_sized(tcx.types.unit), - }))), - ))), - }); - terminator.kind = TerminatorKind::Goto { target }; - } + let target = target.unwrap(); + block.statements.push(Statement { + source_info: terminator.source_info, + kind: StatementKind::Assign(Box::new(( + *destination, + Rvalue::Use(Operand::Constant(Box::new(ConstOperand { + span: terminator.source_info.span, + user_ty: None, + const_: Const::zero_sized(tcx.types.unit), + }))), + ))), + }); + terminator.kind = TerminatorKind::Goto { target }; } sym::copy_nonoverlapping => { let target = target.unwrap(); @@ -121,43 +120,41 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { terminator.kind = TerminatorKind::Goto { target }; } sym::add_with_overflow | sym::sub_with_overflow | sym::mul_with_overflow => { - if let Some(target) = *target { - let Ok([lhs, rhs]) = take_array(args) else { - bug!("Wrong arguments for {} intrinsic", intrinsic.name); - }; - let bin_op = match intrinsic.name { - sym::add_with_overflow => BinOp::AddWithOverflow, - sym::sub_with_overflow => BinOp::SubWithOverflow, - sym::mul_with_overflow => BinOp::MulWithOverflow, - _ => bug!("unexpected intrinsic"), - }; - block.statements.push(Statement { - source_info: terminator.source_info, - kind: StatementKind::Assign(Box::new(( - *destination, - Rvalue::BinaryOp(bin_op, Box::new((lhs.node, rhs.node))), - ))), - }); - terminator.kind = TerminatorKind::Goto { target }; - } + let target = target.unwrap(); + let Ok([lhs, rhs]) = take_array(args) else { + bug!("Wrong arguments for {} intrinsic", intrinsic.name); + }; + let bin_op = match intrinsic.name { + sym::add_with_overflow => BinOp::AddWithOverflow, + sym::sub_with_overflow => BinOp::SubWithOverflow, + sym::mul_with_overflow => BinOp::MulWithOverflow, + _ => bug!("unexpected intrinsic"), + }; + block.statements.push(Statement { + source_info: terminator.source_info, + kind: StatementKind::Assign(Box::new(( + *destination, + Rvalue::BinaryOp(bin_op, Box::new((lhs.node, rhs.node))), + ))), + }); + terminator.kind = TerminatorKind::Goto { target }; } sym::size_of | sym::min_align_of => { - if let Some(target) = *target { - let tp_ty = generic_args.type_at(0); - let null_op = match intrinsic.name { - sym::size_of => NullOp::SizeOf, - sym::min_align_of => NullOp::AlignOf, - _ => bug!("unexpected intrinsic"), - }; - block.statements.push(Statement { - source_info: terminator.source_info, - kind: StatementKind::Assign(Box::new(( - *destination, - Rvalue::NullaryOp(null_op, tp_ty), - ))), - }); - terminator.kind = TerminatorKind::Goto { target }; - } + let target = target.unwrap(); + let tp_ty = generic_args.type_at(0); + let null_op = match intrinsic.name { + sym::size_of => NullOp::SizeOf, + sym::min_align_of => NullOp::AlignOf, + _ => bug!("unexpected intrinsic"), + }; + block.statements.push(Statement { + source_info: terminator.source_info, + kind: StatementKind::Assign(Box::new(( + *destination, + Rvalue::NullaryOp(null_op, tp_ty), + ))), + }); + terminator.kind = TerminatorKind::Goto { target }; } sym::read_via_copy => { let Ok([arg]) = take_array(args) else { @@ -219,17 +216,23 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { terminator.kind = TerminatorKind::Goto { target }; } sym::discriminant_value => { - if let (Some(target), Some(arg)) = (*target, args[0].node.place()) { - let arg = tcx.mk_place_deref(arg); - block.statements.push(Statement { - source_info: terminator.source_info, - kind: StatementKind::Assign(Box::new(( - *destination, - Rvalue::Discriminant(arg), - ))), - }); - terminator.kind = TerminatorKind::Goto { target }; - } + let target = target.unwrap(); + let Ok([arg]) = take_array(args) else { + span_bug!( + terminator.source_info.span, + "Wrong arguments for discriminant_value intrinsic" + ); + }; + let arg = arg.node.place().unwrap(); + let arg = tcx.mk_place_deref(arg); + block.statements.push(Statement { + source_info: terminator.source_info, + kind: StatementKind::Assign(Box::new(( + *destination, + Rvalue::Discriminant(arg), + ))), + }); + terminator.kind = TerminatorKind::Goto { target }; } sym::offset => { let target = target.unwrap(); @@ -267,7 +270,6 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { Rvalue::Cast(CastKind::Transmute, arg.node, dst_ty), ))), }); - if let Some(target) = *target { terminator.kind = TerminatorKind::Goto { target }; } else { @@ -299,7 +301,6 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { Rvalue::Aggregate(Box::new(kind), fields.into()), ))), }); - terminator.kind = TerminatorKind::Goto { target }; } sym::ptr_metadata => { From acccb39bff3c589b286c2dfe0d2f2afc8d1a3775 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 9 Sep 2024 14:30:02 +1000 Subject: [PATCH 081/189] Print a helpful message if any tests were skipped for being up-to-date --- src/bootstrap/src/utils/render_tests.rs | 15 +++++++++++++++ src/tools/compiletest/src/lib.rs | 1 + 2 files changed, 16 insertions(+) diff --git a/src/bootstrap/src/utils/render_tests.rs b/src/bootstrap/src/utils/render_tests.rs index b8aebc2854906..eb2c8254dc0f4 100644 --- a/src/bootstrap/src/utils/render_tests.rs +++ b/src/bootstrap/src/utils/render_tests.rs @@ -88,6 +88,9 @@ struct Renderer<'a> { builder: &'a Builder<'a>, tests_count: Option, executed_tests: usize, + /// Number of tests that were skipped due to already being up-to-date + /// (i.e. no relevant changes occurred since they last ran). + up_to_date_tests: usize, terse_tests_in_line: usize, } @@ -100,6 +103,7 @@ impl<'a> Renderer<'a> { builder, tests_count: None, executed_tests: 0, + up_to_date_tests: 0, terse_tests_in_line: 0, } } @@ -127,6 +131,12 @@ impl<'a> Renderer<'a> { } } } + + if self.up_to_date_tests > 0 { + let n = self.up_to_date_tests; + let s = if n > 1 { "s" } else { "" }; + println!("help: ignored {n} up-to-date test{s}; use `--force-rerun` to prevent this\n"); + } } /// Renders the stdout characters one by one @@ -149,6 +159,11 @@ impl<'a> Renderer<'a> { fn render_test_outcome(&mut self, outcome: Outcome<'_>, test: &TestOutcome) { self.executed_tests += 1; + // Keep this in sync with the "up-to-date" ignore message inserted by compiletest. + if let Outcome::Ignored { reason: Some("up-to-date") } = outcome { + self.up_to_date_tests += 1; + } + #[cfg(feature = "build-metrics")] self.builder.metrics.record_test( &test.name, diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 3294a3bd080b3..33687a3dad35b 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -812,6 +812,7 @@ fn make_test( && is_up_to_date(&config, testpaths, &early_props, revision, inputs) { desc.ignore = true; + // Keep this in sync with the "up-to-date" message detected by bootstrap. desc.ignore_message = Some("up-to-date"); } test::TestDescAndFn { From 3fe7dd6893aa1ee6d02f6112697e2a4abb62254f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 6 Sep 2024 09:18:17 +1000 Subject: [PATCH 082/189] Remove unnecessary lifetimes in dataflow structs. There are four related dataflow structs: `MaybeInitializedPlaces`, `MaybeUninitializedPlaces`, and `EverInitializedPlaces`, `DefinitelyInitializedPlaces`. They all have a `&Body` and a `&MoveData<'tcx>` field. The first three use different lifetimes for the two fields, but the last one uses the same lifetime for both. This commit changes the first three to use the same lifetime, removing the need for one of the lifetimes. Other structs that also lose a lifetime as a result of this are `LivenessContext`, `LivenessResults`, `InitializationData`. It then does similar things in various other structs. --- .../rustc_borrowck/src/borrowck_errors.rs | 2 +- compiler/rustc_borrowck/src/dataflow.rs | 39 +++++----- .../src/diagnostics/bound_region_errors.rs | 14 ++-- .../src/diagnostics/conflict_errors.rs | 8 +- .../src/diagnostics/explain_borrow.rs | 2 +- .../rustc_borrowck/src/diagnostics/mod.rs | 4 +- .../src/diagnostics/move_errors.rs | 2 +- .../src/diagnostics/mutability_errors.rs | 2 +- .../src/diagnostics/outlives_suggestion.rs | 8 +- .../src/diagnostics/region_errors.rs | 2 +- .../src/diagnostics/region_name.rs | 2 +- compiler/rustc_borrowck/src/lib.rs | 73 +++++++++---------- compiler/rustc_borrowck/src/nll.rs | 4 +- compiler/rustc_borrowck/src/prefixes.rs | 2 +- .../src/type_check/liveness/mod.rs | 4 +- .../src/type_check/liveness/trace.rs | 28 +++---- compiler/rustc_borrowck/src/type_check/mod.rs | 4 +- compiler/rustc_borrowck/src/used_muts.rs | 12 +-- .../src/impls/initialized.rs | 46 ++++++------ .../src/elaborate_drops.rs | 34 ++++----- 20 files changed, 141 insertions(+), 151 deletions(-) diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs index 2c672dbf8c4ae..3a7e407f3e7a6 100644 --- a/compiler/rustc_borrowck/src/borrowck_errors.rs +++ b/compiler/rustc_borrowck/src/borrowck_errors.rs @@ -8,7 +8,7 @@ use rustc_middle::span_bug; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::Span; -impl<'infcx, 'tcx> crate::MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { +impl<'infcx, 'tcx> crate::MirBorrowckCtxt<'_, 'infcx, 'tcx> { pub(crate) fn dcx(&self) -> DiagCtxtHandle<'infcx> { self.infcx.dcx() } diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index 9bb6109e66d95..39994ad784a95 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -15,24 +15,24 @@ use tracing::debug; use crate::{places_conflict, BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext}; /// The results of the dataflow analyses used by the borrow checker. -pub(crate) struct BorrowckResults<'a, 'mir, 'tcx> { - pub(crate) borrows: Results<'tcx, Borrows<'a, 'mir, 'tcx>>, - pub(crate) uninits: Results<'tcx, MaybeUninitializedPlaces<'a, 'mir, 'tcx>>, - pub(crate) ever_inits: Results<'tcx, EverInitializedPlaces<'a, 'mir, 'tcx>>, +pub(crate) struct BorrowckResults<'a, 'tcx> { + pub(crate) borrows: Results<'tcx, Borrows<'a, 'tcx>>, + pub(crate) uninits: Results<'tcx, MaybeUninitializedPlaces<'a, 'tcx>>, + pub(crate) ever_inits: Results<'tcx, EverInitializedPlaces<'a, 'tcx>>, } /// The transient state of the dataflow analyses used by the borrow checker. #[derive(Debug)] -pub(crate) struct BorrowckFlowState<'a, 'mir, 'tcx> { - pub(crate) borrows: as AnalysisDomain<'tcx>>::Domain, - pub(crate) uninits: as AnalysisDomain<'tcx>>::Domain, - pub(crate) ever_inits: as AnalysisDomain<'tcx>>::Domain, +pub(crate) struct BorrowckFlowState<'a, 'tcx> { + pub(crate) borrows: as AnalysisDomain<'tcx>>::Domain, + pub(crate) uninits: as AnalysisDomain<'tcx>>::Domain, + pub(crate) ever_inits: as AnalysisDomain<'tcx>>::Domain, } -impl<'a, 'mir, 'tcx> ResultsVisitable<'tcx> for BorrowckResults<'a, 'mir, 'tcx> { +impl<'a, 'tcx> ResultsVisitable<'tcx> for BorrowckResults<'a, 'tcx> { // All three analyses are forward, but we have to use just one here. - type Direction = as AnalysisDomain<'tcx>>::Direction; - type FlowState = BorrowckFlowState<'a, 'mir, 'tcx>; + type Direction = as AnalysisDomain<'tcx>>::Direction; + type FlowState = BorrowckFlowState<'a, 'tcx>; fn new_flow_state(&self, body: &mir::Body<'tcx>) -> Self::FlowState { BorrowckFlowState { @@ -106,10 +106,9 @@ rustc_index::newtype_index! { /// `BorrowIndex`, and maps each such index to a `BorrowData` /// describing the borrow. These indexes are used for representing the /// borrows in compact bitvectors. -pub struct Borrows<'a, 'mir, 'tcx> { +pub struct Borrows<'a, 'tcx> { tcx: TyCtxt<'tcx>, - body: &'mir Body<'tcx>, - + body: &'a Body<'tcx>, borrow_set: &'a BorrowSet<'tcx>, borrows_out_of_scope_at_location: FxIndexMap>, } @@ -389,10 +388,10 @@ impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> { } } -impl<'a, 'mir, 'tcx> Borrows<'a, 'mir, 'tcx> { +impl<'a, 'tcx> Borrows<'a, 'tcx> { pub fn new( tcx: TyCtxt<'tcx>, - body: &'mir Body<'tcx>, + body: &'a Body<'tcx>, regioncx: &RegionInferenceContext<'tcx>, borrow_set: &'a BorrowSet<'tcx>, ) -> Self { @@ -494,7 +493,7 @@ impl<'a, 'mir, 'tcx> Borrows<'a, 'mir, 'tcx> { } } -impl<'tcx> rustc_mir_dataflow::AnalysisDomain<'tcx> for Borrows<'_, '_, 'tcx> { +impl<'tcx> rustc_mir_dataflow::AnalysisDomain<'tcx> for Borrows<'_, 'tcx> { type Domain = BitSet; const NAME: &'static str = "borrows"; @@ -517,7 +516,7 @@ impl<'tcx> rustc_mir_dataflow::AnalysisDomain<'tcx> for Borrows<'_, '_, 'tcx> { /// region stops containing the CFG points reachable from the issuing location. /// - we also kill loans of conflicting places when overwriting a shared path: e.g. borrows of /// `a.b.c` when `a` is overwritten. -impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, '_, 'tcx> { +impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> { type Idx = BorrowIndex; fn domain_size(&self, _: &mir::Body<'tcx>) -> usize { @@ -617,8 +616,8 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, '_, 'tcx> { } } -impl DebugWithContext> for BorrowIndex { - fn fmt_with(&self, ctxt: &Borrows<'_, '_, '_>, f: &mut fmt::Formatter<'_>) -> fmt::Result { +impl DebugWithContext> for BorrowIndex { + fn fmt_with(&self, ctxt: &Borrows<'_, '_>, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}", ctxt.location(*self)) } } diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index 8a4e89d47bdc0..ee28e556cbc34 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -52,7 +52,7 @@ impl<'tcx> UniverseInfo<'tcx> { pub(crate) fn report_error( &self, - mbcx: &mut MirBorrowckCtxt<'_, '_, '_, 'tcx>, + mbcx: &mut MirBorrowckCtxt<'_, '_, 'tcx>, placeholder: ty::PlaceholderRegion, error_element: RegionElement, cause: ObligationCause<'tcx>, @@ -151,7 +151,7 @@ trait TypeOpInfo<'tcx> { fn nice_error<'infcx>( &self, - mbcx: &mut MirBorrowckCtxt<'_, '_, 'infcx, 'tcx>, + mbcx: &mut MirBorrowckCtxt<'_, 'infcx, 'tcx>, cause: ObligationCause<'tcx>, placeholder_region: ty::Region<'tcx>, error_region: Option>, @@ -160,7 +160,7 @@ trait TypeOpInfo<'tcx> { #[instrument(level = "debug", skip(self, mbcx))] fn report_error( &self, - mbcx: &mut MirBorrowckCtxt<'_, '_, '_, 'tcx>, + mbcx: &mut MirBorrowckCtxt<'_, '_, 'tcx>, placeholder: ty::PlaceholderRegion, error_element: RegionElement, cause: ObligationCause<'tcx>, @@ -233,7 +233,7 @@ impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> { fn nice_error<'infcx>( &self, - mbcx: &mut MirBorrowckCtxt<'_, '_, 'infcx, 'tcx>, + mbcx: &mut MirBorrowckCtxt<'_, 'infcx, 'tcx>, cause: ObligationCause<'tcx>, placeholder_region: ty::Region<'tcx>, error_region: Option>, @@ -277,7 +277,7 @@ where fn nice_error<'infcx>( &self, - mbcx: &mut MirBorrowckCtxt<'_, '_, 'infcx, 'tcx>, + mbcx: &mut MirBorrowckCtxt<'_, 'infcx, 'tcx>, cause: ObligationCause<'tcx>, placeholder_region: ty::Region<'tcx>, error_region: Option>, @@ -324,7 +324,7 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> { fn nice_error<'infcx>( &self, - mbcx: &mut MirBorrowckCtxt<'_, '_, 'infcx, 'tcx>, + mbcx: &mut MirBorrowckCtxt<'_, 'infcx, 'tcx>, cause: ObligationCause<'tcx>, placeholder_region: ty::Region<'tcx>, error_region: Option>, @@ -357,7 +357,7 @@ impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> { fn nice_error<'infcx>( &self, - mbcx: &mut MirBorrowckCtxt<'_, '_, 'infcx, 'tcx>, + mbcx: &mut MirBorrowckCtxt<'_, 'infcx, 'tcx>, _cause: ObligationCause<'tcx>, placeholder_region: ty::Region<'tcx>, error_region: Option>, diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index c817b6fac7134..a47518fca3f9b 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -69,7 +69,7 @@ enum StorageDeadOrDrop<'tcx> { Destructor(Ty<'tcx>), } -impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { +impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { pub(crate) fn report_use_of_moved_or_uninitialized( &mut self, location: Location, @@ -4358,11 +4358,7 @@ enum AnnotatedBorrowFnSignature<'tcx> { impl<'tcx> AnnotatedBorrowFnSignature<'tcx> { /// Annotate the provided diagnostic with information about borrow from the fn signature that /// helps explain. - pub(crate) fn emit( - &self, - cx: &MirBorrowckCtxt<'_, '_, '_, 'tcx>, - diag: &mut Diag<'_>, - ) -> String { + pub(crate) fn emit(&self, cx: &MirBorrowckCtxt<'_, '_, 'tcx>, diag: &mut Diag<'_>) -> String { match self { &AnnotatedBorrowFnSignature::Closure { argument_ty, argument_span } => { diag.span_label( diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index c720b0928feb0..419e72df00b02 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -390,7 +390,7 @@ impl<'tcx> BorrowExplanation<'tcx> { } } -impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { +impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { fn free_region_constraint_info( &self, borrow_region: RegionVid, diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 878ce6162e0f9..e52ddfa3eb543 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -68,7 +68,7 @@ pub(super) struct DescribePlaceOpt { pub(super) struct IncludingTupleField(pub(super) bool); -impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { +impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { /// Adds a suggestion when a closure is invoked twice with a moved variable or when a closure /// is moved after being invoked. /// @@ -772,7 +772,7 @@ struct CapturedMessageOpt { maybe_reinitialized_locations_is_empty: bool, } -impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { +impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { /// Finds the spans associated to a move or copy of move_place at location. pub(super) fn move_spans( &self, diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 3dab027bff057..5a9eba34d07f1 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -93,7 +93,7 @@ enum GroupedMoveError<'tcx> { }, } -impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { +impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { pub(crate) fn report_move_errors(&mut self) { let grouped_errors = self.group_move_errors(); for error in grouped_errors { diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 337125f5ecc11..6e3fac1e68075 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -32,7 +32,7 @@ pub(crate) enum AccessKind { Mutate, } -impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { +impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { pub(crate) fn report_mutability_error( &mut self, access_place: Place<'tcx>, diff --git a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs index b205dc9ff4922..bd0cf3578c2bb 100644 --- a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs +++ b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs @@ -76,7 +76,7 @@ impl OutlivesSuggestionBuilder { /// Returns a name for the region if it is suggestable. See `region_name_is_suggestable`. fn region_vid_to_name( &self, - mbcx: &MirBorrowckCtxt<'_, '_, '_, '_>, + mbcx: &MirBorrowckCtxt<'_, '_, '_>, region: RegionVid, ) -> Option { mbcx.give_region_a_name(region).filter(Self::region_name_is_suggestable) @@ -85,7 +85,7 @@ impl OutlivesSuggestionBuilder { /// Compiles a list of all suggestions to be printed in the final big suggestion. fn compile_all_suggestions( &self, - mbcx: &MirBorrowckCtxt<'_, '_, '_, '_>, + mbcx: &MirBorrowckCtxt<'_, '_, '_>, ) -> SmallVec<[SuggestedConstraint; 2]> { let mut suggested = SmallVec::new(); @@ -161,7 +161,7 @@ impl OutlivesSuggestionBuilder { /// Emit an intermediate note on the given `Diag` if the involved regions are suggestable. pub(crate) fn intermediate_suggestion( &mut self, - mbcx: &MirBorrowckCtxt<'_, '_, '_, '_>, + mbcx: &MirBorrowckCtxt<'_, '_, '_>, errci: &ErrorConstraintInfo<'_>, diag: &mut Diag<'_>, ) { @@ -180,7 +180,7 @@ impl OutlivesSuggestionBuilder { /// If there is a suggestion to emit, add a diagnostic to the buffer. This is the final /// suggestion including all collected constraints. - pub(crate) fn add_suggestion(&self, mbcx: &mut MirBorrowckCtxt<'_, '_, '_, '_>) { + pub(crate) fn add_suggestion(&self, mbcx: &mut MirBorrowckCtxt<'_, '_, '_>) { // No constraints to add? Done. if self.constraints_to_add.is_empty() { debug!("No constraints to suggest."); diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index d49d36dedafc1..57c3a0843a694 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -156,7 +156,7 @@ pub(crate) struct ErrorConstraintInfo<'tcx> { pub(super) span: Span, } -impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { +impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { /// Converts a region inference variable into a `ty::Region` that /// we can use for error reporting. If `r` is universally bound, /// then we use the name that we have on record for it. If `r` is diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index cb05812ec7b5c..58fcda2571cc0 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -200,7 +200,7 @@ impl rustc_errors::IntoDiagArg for RegionName { } } -impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { +impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { pub(crate) fn mir_def_id(&self) -> hir::def_id::LocalDefId { self.body.source.def_id().expect_local() } diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index d40dcfa58054a..d5f297a591382 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -304,11 +304,11 @@ fn do_mir_borrowck<'tcx>( promoted_mbcx.report_move_errors(); diags = promoted_mbcx.diags; - struct MoveVisitor<'a, 'b, 'mir, 'infcx, 'tcx> { - ctxt: &'a mut MirBorrowckCtxt<'b, 'mir, 'infcx, 'tcx>, + struct MoveVisitor<'a, 'b, 'infcx, 'tcx> { + ctxt: &'a mut MirBorrowckCtxt<'b, 'infcx, 'tcx>, } - impl<'tcx> Visitor<'tcx> for MoveVisitor<'_, '_, '_, '_, 'tcx> { + impl<'tcx> Visitor<'tcx> for MoveVisitor<'_, '_, '_, 'tcx> { fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) { if let Operand::Move(place) = operand { self.ctxt.check_movable_place(location, *place); @@ -522,10 +522,10 @@ impl<'tcx> Deref for BorrowckInferCtxt<'tcx> { } } -struct MirBorrowckCtxt<'a, 'mir, 'infcx, 'tcx> { +struct MirBorrowckCtxt<'a, 'infcx, 'tcx> { infcx: &'infcx BorrowckInferCtxt<'tcx>, param_env: ParamEnv<'tcx>, - body: &'mir Body<'tcx>, + body: &'a Body<'tcx>, move_data: &'a MoveData<'tcx>, /// Map from MIR `Location` to `LocationIndex`; created @@ -599,16 +599,16 @@ struct MirBorrowckCtxt<'a, 'mir, 'infcx, 'tcx> { // 2. loans made in overlapping scopes do not conflict // 3. assignments do not affect things loaned out as immutable // 4. moves do not affect things loaned out in any way -impl<'a, 'mir, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx, R> - for MirBorrowckCtxt<'a, 'mir, '_, 'tcx> +impl<'a, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'a, 'tcx, R> + for MirBorrowckCtxt<'a, '_, 'tcx> { - type FlowState = Flows<'a, 'mir, 'tcx>; + type FlowState = Flows<'a, 'tcx>; fn visit_statement_before_primary_effect( &mut self, _results: &mut R, - flow_state: &Flows<'_, 'mir, 'tcx>, - stmt: &'mir Statement<'tcx>, + flow_state: &Flows<'a, 'tcx>, + stmt: &'a Statement<'tcx>, location: Location, ) { debug!("MirBorrowckCtxt::process_statement({:?}, {:?}): {:?}", location, stmt, flow_state); @@ -677,8 +677,8 @@ impl<'a, 'mir, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx, R> fn visit_terminator_before_primary_effect( &mut self, _results: &mut R, - flow_state: &Flows<'_, 'mir, 'tcx>, - term: &'mir Terminator<'tcx>, + flow_state: &Flows<'a, 'tcx>, + term: &'a Terminator<'tcx>, loc: Location, ) { debug!("MirBorrowckCtxt::process_terminator({:?}, {:?}): {:?}", loc, term, flow_state); @@ -794,8 +794,8 @@ impl<'a, 'mir, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx, R> fn visit_terminator_after_primary_effect( &mut self, _results: &mut R, - flow_state: &Flows<'_, 'mir, 'tcx>, - term: &'mir Terminator<'tcx>, + flow_state: &Flows<'a, 'tcx>, + term: &'a Terminator<'tcx>, loc: Location, ) { let span = term.source_info.span; @@ -972,8 +972,8 @@ impl InitializationRequiringAction { } } -impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { - fn body(&self) -> &'mir Body<'tcx> { +impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { + fn body(&self) -> &'a Body<'tcx> { self.body } @@ -989,7 +989,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { place_span: (Place<'tcx>, Span), kind: (AccessDepth, ReadOrWrite), is_local_mutation_allowed: LocalMutationIsAllowed, - flow_state: &Flows<'_, 'mir, 'tcx>, + flow_state: &Flows<'a, 'tcx>, ) { let (sd, rw) = kind; @@ -1039,7 +1039,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { place_span: (Place<'tcx>, Span), sd: AccessDepth, rw: ReadOrWrite, - flow_state: &Flows<'_, 'mir, 'tcx>, + flow_state: &Flows<'a, 'tcx>, ) -> bool { let mut error_reported = false; let borrow_set = Rc::clone(&self.borrow_set); @@ -1180,7 +1180,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { location: Location, place_span: (Place<'tcx>, Span), kind: AccessDepth, - flow_state: &Flows<'_, 'mir, 'tcx>, + flow_state: &Flows<'a, 'tcx>, ) { // Write of P[i] or *P requires P init'd. self.check_if_assigned_path_is_moved(location, place_span, flow_state); @@ -1197,8 +1197,8 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { fn consume_rvalue( &mut self, location: Location, - (rvalue, span): (&'mir Rvalue<'tcx>, Span), - flow_state: &Flows<'_, 'mir, 'tcx>, + (rvalue, span): (&'a Rvalue<'tcx>, Span), + flow_state: &Flows<'a, 'tcx>, ) { match rvalue { &Rvalue::Ref(_ /*rgn*/, bk, place) => { @@ -1455,8 +1455,8 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { fn consume_operand( &mut self, location: Location, - (operand, span): (&'mir Operand<'tcx>, Span), - flow_state: &Flows<'_, 'mir, 'tcx>, + (operand, span): (&'a Operand<'tcx>, Span), + flow_state: &Flows<'a, 'tcx>, ) { match *operand { Operand::Copy(place) => { @@ -1576,12 +1576,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { } } - fn check_activations( - &mut self, - location: Location, - span: Span, - flow_state: &Flows<'_, 'mir, 'tcx>, - ) { + fn check_activations(&mut self, location: Location, span: Span, flow_state: &Flows<'a, 'tcx>) { // Two-phase borrow support: For each activation that is newly // generated at this statement, check if it interferes with // another borrow. @@ -1744,7 +1739,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { location: Location, desired_action: InitializationRequiringAction, place_span: (PlaceRef<'tcx>, Span), - flow_state: &Flows<'_, 'mir, 'tcx>, + flow_state: &Flows<'a, 'tcx>, ) { let maybe_uninits = &flow_state.uninits; @@ -1849,7 +1844,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { location: Location, desired_action: InitializationRequiringAction, place_span: (PlaceRef<'tcx>, Span), - flow_state: &Flows<'_, 'mir, 'tcx>, + flow_state: &Flows<'a, 'tcx>, ) { let maybe_uninits = &flow_state.uninits; @@ -1948,7 +1943,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { &mut self, location: Location, (place, span): (Place<'tcx>, Span), - flow_state: &Flows<'_, 'mir, 'tcx>, + flow_state: &Flows<'a, 'tcx>, ) { debug!("check_if_assigned_path_is_moved place: {:?}", place); @@ -2009,12 +2004,12 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { } } - fn check_parent_of_field<'mir, 'tcx>( - this: &mut MirBorrowckCtxt<'_, 'mir, '_, 'tcx>, + fn check_parent_of_field<'a, 'tcx>( + this: &mut MirBorrowckCtxt<'a, '_, 'tcx>, location: Location, base: PlaceRef<'tcx>, span: Span, - flow_state: &Flows<'_, 'mir, 'tcx>, + flow_state: &Flows<'a, 'tcx>, ) { // rust-lang/rust#21232: Until Rust allows reads from the // initialized parts of partially initialized structs, we @@ -2105,7 +2100,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { (place, span): (Place<'tcx>, Span), kind: ReadOrWrite, is_local_mutation_allowed: LocalMutationIsAllowed, - flow_state: &Flows<'_, 'mir, 'tcx>, + flow_state: &Flows<'a, 'tcx>, location: Location, ) -> bool { debug!( @@ -2221,7 +2216,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { fn is_local_ever_initialized( &self, local: Local, - flow_state: &Flows<'_, 'mir, 'tcx>, + flow_state: &Flows<'a, 'tcx>, ) -> Option { let mpi = self.move_data.rev_lookup.find_local(local)?; let ii = &self.move_data.init_path_map[mpi]; @@ -2229,7 +2224,7 @@ impl<'mir, 'tcx> MirBorrowckCtxt<'_, 'mir, '_, 'tcx> { } /// Adds the place into the used mutable variables set - fn add_used_mut(&mut self, root_place: RootPlace<'tcx>, flow_state: &Flows<'_, 'mir, 'tcx>) { + fn add_used_mut(&mut self, root_place: RootPlace<'tcx>, flow_state: &Flows<'a, 'tcx>) { match root_place { RootPlace { place_local: local, place_projection: [], is_local_mutation_allowed } => { // If the local may have been initialized, and it is now currently being @@ -2484,7 +2479,7 @@ mod diags { } } - impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { + impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { pub(crate) fn buffer_error(&mut self, diag: Diag<'infcx>) { self.diags.buffer_error(diag); } diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 6525befc13b99..0d6ecab7d27ca 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -75,14 +75,14 @@ pub(crate) fn replace_regions_in_mir<'tcx>( /// Computes the (non-lexical) regions from the input MIR. /// /// This may result in errors being reported. -pub(crate) fn compute_regions<'cx, 'tcx>( +pub(crate) fn compute_regions<'a, 'tcx>( infcx: &BorrowckInferCtxt<'tcx>, universal_regions: UniversalRegions<'tcx>, body: &Body<'tcx>, promoted: &IndexSlice>, location_table: &LocationTable, param_env: ty::ParamEnv<'tcx>, - flow_inits: &mut ResultsCursor<'cx, 'tcx, MaybeInitializedPlaces<'_, 'cx, 'tcx>>, + flow_inits: &mut ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>, move_data: &MoveData<'tcx>, borrow_set: &BorrowSet<'tcx>, upvars: &[&ty::CapturedPlace<'tcx>], diff --git a/compiler/rustc_borrowck/src/prefixes.rs b/compiler/rustc_borrowck/src/prefixes.rs index 39d831378cde6..aeb8a6c014a4f 100644 --- a/compiler/rustc_borrowck/src/prefixes.rs +++ b/compiler/rustc_borrowck/src/prefixes.rs @@ -34,7 +34,7 @@ pub(super) enum PrefixSet { Shallow, } -impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { +impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { /// Returns an iterator over the prefixes of `place` /// (inclusive) from longest to smallest, potentially /// terminating the iteration early based on `kind`. diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs index a24fd95e3e650..79db8f4252b55 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs @@ -30,11 +30,11 @@ mod trace; /// /// N.B., this computation requires normalization; therefore, it must be /// performed before -pub(super) fn generate<'mir, 'tcx>( +pub(super) fn generate<'a, 'tcx>( typeck: &mut TypeChecker<'_, 'tcx>, body: &Body<'tcx>, elements: &Rc, - flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'_, 'mir, 'tcx>>, + flow_inits: &mut ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>, move_data: &MoveData<'tcx>, ) { debug!("liveness::generate"); diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index 6186904e5fbb6..4d47863ae76ad 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -37,11 +37,11 @@ use crate::type_check::{NormalizeLocation, TypeChecker}; /// DROP-LIVE set are to the liveness sets for regions found in the /// `dropck_outlives` result of the variable's type (in particular, /// this respects `#[may_dangle]` annotations). -pub(super) fn trace<'mir, 'tcx>( +pub(super) fn trace<'a, 'tcx>( typeck: &mut TypeChecker<'_, 'tcx>, body: &Body<'tcx>, elements: &Rc, - flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'_, 'mir, 'tcx>>, + flow_inits: &mut ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>, move_data: &MoveData<'tcx>, relevant_live_locals: Vec, boring_locals: Vec, @@ -99,29 +99,29 @@ pub(super) fn trace<'mir, 'tcx>( } /// Contextual state for the type-liveness coroutine. -struct LivenessContext<'a, 'me, 'typeck, 'flow, 'tcx> { +struct LivenessContext<'a, 'typeck, 'b, 'tcx> { /// Current type-checker, giving us our inference context etc. - typeck: &'me mut TypeChecker<'typeck, 'tcx>, + typeck: &'a mut TypeChecker<'typeck, 'tcx>, /// Defines the `PointIndex` mapping - elements: &'me DenseLocationMap, + elements: &'a DenseLocationMap, /// MIR we are analyzing. - body: &'me Body<'tcx>, + body: &'a Body<'tcx>, /// Mapping to/from the various indices used for initialization tracking. - move_data: &'me MoveData<'tcx>, + move_data: &'a MoveData<'tcx>, /// Cache for the results of `dropck_outlives` query. drop_data: FxIndexMap, DropData<'tcx>>, /// Results of dataflow tracking which variables (and paths) have been /// initialized. - flow_inits: &'me mut ResultsCursor<'flow, 'tcx, MaybeInitializedPlaces<'a, 'flow, 'tcx>>, + flow_inits: &'a mut ResultsCursor<'b, 'tcx, MaybeInitializedPlaces<'b, 'tcx>>, /// Index indicating where each variable is assigned, used, or /// dropped. - local_use_map: &'me LocalUseMap, + local_use_map: &'a LocalUseMap, } struct DropData<'tcx> { @@ -129,8 +129,8 @@ struct DropData<'tcx> { region_constraint_data: Option<&'tcx QueryRegionConstraints<'tcx>>, } -struct LivenessResults<'a, 'me, 'typeck, 'flow, 'tcx> { - cx: LivenessContext<'a, 'me, 'typeck, 'flow, 'tcx>, +struct LivenessResults<'a, 'typeck, 'b, 'tcx> { + cx: LivenessContext<'a, 'typeck, 'b, 'tcx>, /// Set of points that define the current local. defs: BitSet, @@ -151,8 +151,8 @@ struct LivenessResults<'a, 'me, 'typeck, 'flow, 'tcx> { stack: Vec, } -impl<'a, 'me, 'typeck, 'flow, 'tcx> LivenessResults<'a, 'me, 'typeck, 'flow, 'tcx> { - fn new(cx: LivenessContext<'a, 'me, 'typeck, 'flow, 'tcx>) -> Self { +impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> { + fn new(cx: LivenessContext<'a, 'typeck, 'b, 'tcx>) -> Self { let num_points = cx.elements.num_points(); LivenessResults { cx, @@ -505,7 +505,7 @@ impl<'a, 'me, 'typeck, 'flow, 'tcx> LivenessResults<'a, 'me, 'typeck, 'flow, 'tc } } -impl<'tcx> LivenessContext<'_, '_, '_, '_, 'tcx> { +impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> { /// Returns `true` if the local variable (or some part of it) is initialized at the current /// cursor position. Callers should call one of the `seek` methods immediately before to point /// the cursor to the desired location. diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 3c9a43883ad64..3e5a6ad85fa56 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -116,7 +116,7 @@ mod relate_tys; /// - `flow_inits` -- results of a maybe-init dataflow analysis /// - `move_data` -- move-data constructed when performing the maybe-init dataflow analysis /// - `elements` -- MIR region map -pub(crate) fn type_check<'mir, 'tcx>( +pub(crate) fn type_check<'a, 'tcx>( infcx: &BorrowckInferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, body: &Body<'tcx>, @@ -125,7 +125,7 @@ pub(crate) fn type_check<'mir, 'tcx>( location_table: &LocationTable, borrow_set: &BorrowSet<'tcx>, all_facts: &mut Option, - flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'_, 'mir, 'tcx>>, + flow_inits: &mut ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>, move_data: &MoveData<'tcx>, elements: &Rc, upvars: &[&ty::CapturedPlace<'tcx>], diff --git a/compiler/rustc_borrowck/src/used_muts.rs b/compiler/rustc_borrowck/src/used_muts.rs index 981e7daf6702e..bde07c05c0e16 100644 --- a/compiler/rustc_borrowck/src/used_muts.rs +++ b/compiler/rustc_borrowck/src/used_muts.rs @@ -7,7 +7,7 @@ use tracing::debug; use crate::MirBorrowckCtxt; -impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { +impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { /// Walks the MIR adding to the set of `used_mut` locals that will be ignored for the purposes /// of the `unused_mut` lint. /// @@ -46,13 +46,13 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> { /// MIR visitor for collecting used mutable variables. /// The 'visit lifetime represents the duration of the MIR walk. -struct GatherUsedMutsVisitor<'visit, 'a, 'mir, 'infcx, 'tcx> { +struct GatherUsedMutsVisitor<'a, 'b, 'infcx, 'tcx> { temporary_used_locals: FxIndexSet, - never_initialized_mut_locals: &'visit mut FxIndexSet, - mbcx: &'visit mut MirBorrowckCtxt<'a, 'mir, 'infcx, 'tcx>, + never_initialized_mut_locals: &'a mut FxIndexSet, + mbcx: &'a mut MirBorrowckCtxt<'b, 'infcx, 'tcx>, } -impl GatherUsedMutsVisitor<'_, '_, '_, '_, '_> { +impl GatherUsedMutsVisitor<'_, '_, '_, '_> { fn remove_never_initialized_mut_locals(&mut self, into: Place<'_>) { // Remove any locals that we found were initialized from the // `never_initialized_mut_locals` set. At the end, the only remaining locals will @@ -64,7 +64,7 @@ impl GatherUsedMutsVisitor<'_, '_, '_, '_, '_> { } } -impl<'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'_, '_, '_, '_, 'tcx> { +impl<'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'_, '_, '_, 'tcx> { fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { debug!("visit_terminator: terminator={:?}", terminator); match &terminator.kind { diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs index ddfd0739358d1..a88927427bac2 100644 --- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs +++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs @@ -51,15 +51,15 @@ use crate::{ /// Similarly, at a given `drop` statement, the set-intersection /// between this data and `MaybeUninitializedPlaces` yields the set of /// places that would require a dynamic drop-flag at that statement. -pub struct MaybeInitializedPlaces<'a, 'mir, 'tcx> { +pub struct MaybeInitializedPlaces<'a, 'tcx> { tcx: TyCtxt<'tcx>, - body: &'mir Body<'tcx>, + body: &'a Body<'tcx>, move_data: &'a MoveData<'tcx>, skip_unreachable_unwind: bool, } -impl<'a, 'mir, 'tcx> MaybeInitializedPlaces<'a, 'mir, 'tcx> { - pub fn new(tcx: TyCtxt<'tcx>, body: &'mir Body<'tcx>, move_data: &'a MoveData<'tcx>) -> Self { +impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> { + pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, move_data: &'a MoveData<'tcx>) -> Self { MaybeInitializedPlaces { tcx, body, move_data, skip_unreachable_unwind: false } } @@ -85,7 +85,7 @@ impl<'a, 'mir, 'tcx> MaybeInitializedPlaces<'a, 'mir, 'tcx> { } } -impl<'a, 'mir, 'tcx> HasMoveData<'tcx> for MaybeInitializedPlaces<'a, 'mir, 'tcx> { +impl<'a, 'tcx> HasMoveData<'tcx> for MaybeInitializedPlaces<'a, 'tcx> { fn move_data(&self) -> &MoveData<'tcx> { self.move_data } @@ -126,17 +126,17 @@ impl<'a, 'mir, 'tcx> HasMoveData<'tcx> for MaybeInitializedPlaces<'a, 'mir, 'tcx /// Similarly, at a given `drop` statement, the set-intersection /// between this data and `MaybeInitializedPlaces` yields the set of /// places that would require a dynamic drop-flag at that statement. -pub struct MaybeUninitializedPlaces<'a, 'mir, 'tcx> { +pub struct MaybeUninitializedPlaces<'a, 'tcx> { tcx: TyCtxt<'tcx>, - body: &'mir Body<'tcx>, + body: &'a Body<'tcx>, move_data: &'a MoveData<'tcx>, mark_inactive_variants_as_uninit: bool, skip_unreachable_unwind: BitSet, } -impl<'a, 'mir, 'tcx> MaybeUninitializedPlaces<'a, 'mir, 'tcx> { - pub fn new(tcx: TyCtxt<'tcx>, body: &'mir Body<'tcx>, move_data: &'a MoveData<'tcx>) -> Self { +impl<'a, 'tcx> MaybeUninitializedPlaces<'a, 'tcx> { + pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, move_data: &'a MoveData<'tcx>) -> Self { MaybeUninitializedPlaces { tcx, body, @@ -165,7 +165,7 @@ impl<'a, 'mir, 'tcx> MaybeUninitializedPlaces<'a, 'mir, 'tcx> { } } -impl<'a, 'tcx> HasMoveData<'tcx> for MaybeUninitializedPlaces<'a, '_, 'tcx> { +impl<'tcx> HasMoveData<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { fn move_data(&self) -> &MoveData<'tcx> { self.move_data } @@ -251,24 +251,24 @@ impl<'a, 'tcx> HasMoveData<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> { /// c = S; // {a, b, c, d } /// } /// ``` -pub struct EverInitializedPlaces<'a, 'mir, 'tcx> { - body: &'mir Body<'tcx>, +pub struct EverInitializedPlaces<'a, 'tcx> { + body: &'a Body<'tcx>, move_data: &'a MoveData<'tcx>, } -impl<'a, 'mir, 'tcx> EverInitializedPlaces<'a, 'mir, 'tcx> { - pub fn new(body: &'mir Body<'tcx>, move_data: &'a MoveData<'tcx>) -> Self { +impl<'a, 'tcx> EverInitializedPlaces<'a, 'tcx> { + pub fn new(body: &'a Body<'tcx>, move_data: &'a MoveData<'tcx>) -> Self { EverInitializedPlaces { body, move_data } } } -impl<'a, 'tcx> HasMoveData<'tcx> for EverInitializedPlaces<'a, '_, 'tcx> { +impl<'tcx> HasMoveData<'tcx> for EverInitializedPlaces<'_, 'tcx> { fn move_data(&self) -> &MoveData<'tcx> { self.move_data } } -impl<'a, 'mir, 'tcx> MaybeInitializedPlaces<'a, 'mir, 'tcx> { +impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> { fn update_bits( trans: &mut impl GenKill, path: MovePathIndex, @@ -281,7 +281,7 @@ impl<'a, 'mir, 'tcx> MaybeInitializedPlaces<'a, 'mir, 'tcx> { } } -impl<'a, 'tcx> MaybeUninitializedPlaces<'a, '_, 'tcx> { +impl<'tcx> MaybeUninitializedPlaces<'_, 'tcx> { fn update_bits( trans: &mut impl GenKill, path: MovePathIndex, @@ -307,7 +307,7 @@ impl<'a, 'tcx> DefinitelyInitializedPlaces<'a, 'tcx> { } } -impl<'tcx> AnalysisDomain<'tcx> for MaybeInitializedPlaces<'_, '_, 'tcx> { +impl<'tcx> AnalysisDomain<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { /// There can be many more `MovePathIndex` than there are locals in a MIR body. /// We use a chunked bitset to avoid paying too high a memory footprint. type Domain = MaybeReachable>; @@ -329,7 +329,7 @@ impl<'tcx> AnalysisDomain<'tcx> for MaybeInitializedPlaces<'_, '_, 'tcx> { } } -impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, '_, 'tcx> { +impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { type Idx = MovePathIndex; fn domain_size(&self, _: &Body<'tcx>) -> usize { @@ -442,7 +442,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, '_, 'tcx> { } } -impl<'tcx> AnalysisDomain<'tcx> for MaybeUninitializedPlaces<'_, '_, 'tcx> { +impl<'tcx> AnalysisDomain<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { /// There can be many more `MovePathIndex` than there are locals in a MIR body. /// We use a chunked bitset to avoid paying too high a memory footprint. type Domain = ChunkedBitSet; @@ -466,7 +466,7 @@ impl<'tcx> AnalysisDomain<'tcx> for MaybeUninitializedPlaces<'_, '_, 'tcx> { } } -impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, '_, 'tcx> { +impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { type Idx = MovePathIndex; fn domain_size(&self, _: &Body<'tcx>) -> usize { @@ -643,7 +643,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for DefinitelyInitializedPlaces<'_, 'tcx> { } } -impl<'tcx> AnalysisDomain<'tcx> for EverInitializedPlaces<'_, '_, 'tcx> { +impl<'tcx> AnalysisDomain<'tcx> for EverInitializedPlaces<'_, 'tcx> { /// There can be many more `InitIndex` than there are locals in a MIR body. /// We use a chunked bitset to avoid paying too high a memory footprint. type Domain = ChunkedBitSet; @@ -662,7 +662,7 @@ impl<'tcx> AnalysisDomain<'tcx> for EverInitializedPlaces<'_, '_, 'tcx> { } } -impl<'tcx> GenKillAnalysis<'tcx> for EverInitializedPlaces<'_, '_, 'tcx> { +impl<'tcx> GenKillAnalysis<'tcx> for EverInitializedPlaces<'_, 'tcx> { type Idx = InitIndex; fn domain_size(&self, _: &Body<'tcx>) -> usize { diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index f4a951ebde600..ffffdf53916a7 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -98,9 +98,9 @@ impl<'tcx> crate::MirPass<'tcx> for ElaborateDrops { /// Records unwind edges which are known to be unreachable, because they are in `drop` terminators /// that can't drop anything. #[instrument(level = "trace", skip(body, flow_inits), ret)] -fn compute_dead_unwinds<'mir, 'tcx>( - body: &'mir Body<'tcx>, - flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'_, 'mir, 'tcx>>, +fn compute_dead_unwinds<'a, 'tcx>( + body: &'a Body<'tcx>, + flow_inits: &mut ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>, ) -> BitSet { // We only need to do this pass once, because unwind edges can only // reach cleanup blocks, which can't have unwind edges themselves. @@ -121,12 +121,12 @@ fn compute_dead_unwinds<'mir, 'tcx>( dead_unwinds } -struct InitializationData<'a, 'mir, 'tcx> { - inits: ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'a, 'mir, 'tcx>>, - uninits: ResultsCursor<'mir, 'tcx, MaybeUninitializedPlaces<'a, 'mir, 'tcx>>, +struct InitializationData<'a, 'tcx> { + inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>, + uninits: ResultsCursor<'a, 'tcx, MaybeUninitializedPlaces<'a, 'tcx>>, } -impl InitializationData<'_, '_, '_> { +impl InitializationData<'_, '_> { fn seek_before(&mut self, loc: Location) { self.inits.seek_before_primary_effect(loc); self.uninits.seek_before_primary_effect(loc); @@ -137,24 +137,24 @@ impl InitializationData<'_, '_, '_> { } } -struct Elaborator<'a, 'b, 'mir, 'tcx> { - ctxt: &'a mut ElaborateDropsCtxt<'b, 'mir, 'tcx>, +struct Elaborator<'a, 'b, 'tcx> { + ctxt: &'a mut ElaborateDropsCtxt<'b, 'tcx>, } -impl fmt::Debug for Elaborator<'_, '_, '_, '_> { +impl fmt::Debug for Elaborator<'_, '_, '_> { fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { Ok(()) } } -impl<'a, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, '_, '_, 'tcx> { +impl<'b, 'tcx> DropElaborator<'b, 'tcx> for Elaborator<'_, 'b, 'tcx> { type Path = MovePathIndex; fn patch(&mut self) -> &mut MirPatch<'tcx> { &mut self.ctxt.patch } - fn body(&self) -> &'a Body<'tcx> { + fn body(&self) -> &'b Body<'tcx> { self.ctxt.body } @@ -241,17 +241,17 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, '_, '_, 'tcx> { } } -struct ElaborateDropsCtxt<'a, 'mir, 'tcx> { +struct ElaborateDropsCtxt<'a, 'tcx> { tcx: TyCtxt<'tcx>, - body: &'mir Body<'tcx>, + body: &'a Body<'tcx>, env: &'a MoveDataParamEnv<'tcx>, - init_data: InitializationData<'a, 'mir, 'tcx>, + init_data: InitializationData<'a, 'tcx>, drop_flags: IndexVec>, patch: MirPatch<'tcx>, } -impl<'b, 'mir, 'tcx> ElaborateDropsCtxt<'b, 'mir, 'tcx> { - fn move_data(&self) -> &'b MoveData<'tcx> { +impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> { + fn move_data(&self) -> &'a MoveData<'tcx> { &self.env.move_data } From bed91f506559d17add56379f565372be031cdb36 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 6 Sep 2024 10:29:32 +1000 Subject: [PATCH 083/189] Remove unnecessary lifetime in `PlaceCollector`. --- compiler/rustc_mir_dataflow/src/value_analysis.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 2b20a35b61e29..0540436632014 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -923,14 +923,14 @@ impl<'tcx> Map<'tcx> { } } -struct PlaceCollector<'a, 'b, 'tcx> { +struct PlaceCollector<'a, 'tcx> { tcx: TyCtxt<'tcx>, - body: &'b Body<'tcx>, + body: &'a Body<'tcx>, map: &'a mut Map<'tcx>, assignments: FxIndexSet<(PlaceIndex, PlaceIndex)>, } -impl<'tcx> PlaceCollector<'_, '_, 'tcx> { +impl<'tcx> PlaceCollector<'_, 'tcx> { #[tracing::instrument(level = "trace", skip(self))] fn register_place(&mut self, place: Place<'tcx>) -> Option { // Create a place for this projection. @@ -967,7 +967,7 @@ impl<'tcx> PlaceCollector<'_, '_, 'tcx> { } } -impl<'tcx> Visitor<'tcx> for PlaceCollector<'_, '_, 'tcx> { +impl<'tcx> Visitor<'tcx> for PlaceCollector<'_, 'tcx> { #[tracing::instrument(level = "trace", skip(self))] fn visit_place(&mut self, place: &Place<'tcx>, ctxt: PlaceContext, _: Location) { if !ctxt.is_use() { From 1aafeb2d5a07f98d5fab4f5627666396ed292f68 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 6 Sep 2024 14:23:30 +1000 Subject: [PATCH 084/189] Remove unnecessary lifetime from `OperandCollector`. Also put the remaining lifetimes into the usual order. --- compiler/rustc_mir_transform/src/dataflow_const_prop.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 46f7408ef8064..5fe5ba76dbc34 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -838,14 +838,14 @@ impl<'tcx> MutVisitor<'tcx> for Patch<'tcx> { } } -struct OperandCollector<'tcx, 'map, 'locals, 'a> { +struct OperandCollector<'a, 'locals, 'tcx> { state: &'a State>, visitor: &'a mut Collector<'tcx, 'locals>, - ecx: &'map mut InterpCx<'tcx, DummyMachine>, - map: &'map Map<'tcx>, + ecx: &'a mut InterpCx<'tcx, DummyMachine>, + map: &'a Map<'tcx>, } -impl<'tcx> Visitor<'tcx> for OperandCollector<'tcx, '_, '_, '_> { +impl<'tcx> Visitor<'tcx> for OperandCollector<'_, '_, 'tcx> { fn visit_projection_elem( &mut self, _: PlaceRef<'tcx>, From 28a6dc4d1e8140ea22fadef82ce999926e3881f1 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 6 Sep 2024 13:40:20 +1000 Subject: [PATCH 085/189] Rename some lifetimes. Give them the names used in most places. --- compiler/rustc_borrowck/src/nll.rs | 6 +++--- compiler/rustc_borrowck/src/universal_regions.rs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 0d6ecab7d27ca..8575eb9e9a52d 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -301,13 +301,13 @@ pub(super) fn dump_nll_mir<'tcx>( #[allow(rustc::diagnostic_outside_of_impl)] #[allow(rustc::untranslatable_diagnostic)] -pub(super) fn dump_annotation<'tcx, 'cx>( - infcx: &'cx BorrowckInferCtxt<'tcx>, +pub(super) fn dump_annotation<'tcx, 'infcx>( + infcx: &'infcx BorrowckInferCtxt<'tcx>, body: &Body<'tcx>, regioncx: &RegionInferenceContext<'tcx>, closure_region_requirements: &Option>, opaque_type_values: &FxIndexMap>, - diags: &mut crate::diags::BorrowckDiags<'cx, 'tcx>, + diags: &mut crate::diags::BorrowckDiags<'infcx, 'tcx>, ) { let tcx = infcx.tcx; let base_def_id = tcx.typeck_root_def_id(body.source.def_id()); diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 164be73f49296..c3edbcb50cc3d 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -423,8 +423,8 @@ impl<'tcx> UniversalRegions<'tcx> { } } -struct UniversalRegionsBuilder<'cx, 'tcx> { - infcx: &'cx BorrowckInferCtxt<'tcx>, +struct UniversalRegionsBuilder<'infcx, 'tcx> { + infcx: &'infcx BorrowckInferCtxt<'tcx>, mir_def: LocalDefId, param_env: ty::ParamEnv<'tcx>, } From dc62f07458078d1e80a316a2f5b9990a43486f5d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 6 Sep 2024 16:35:17 +1000 Subject: [PATCH 086/189] Remove `Gatherer`. It's a very thin wrapper that pairs `MoveDataBuilder` with a `Location`, and it has four lifetime arguments. This commit removes it by just adding a `Location` to `MoveDataBuilder`. --- .../src/move_paths/builder.rs | 75 +++++++------------ 1 file changed, 29 insertions(+), 46 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index 14390723ba4b6..87ea729923895 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -16,6 +16,7 @@ use super::{ struct MoveDataBuilder<'a, 'tcx, F> { body: &'a Body<'tcx>, + loc: Location, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, data: MoveData<'tcx>, @@ -56,6 +57,7 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> { MoveDataBuilder { body, + loc: Location::START, tcx, param_env, data: MoveData { @@ -107,7 +109,7 @@ enum MovePathResult { Error, } -impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { +impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> { /// This creates a MovePath for a given place, returning an `MovePathError` /// if that place can't be moved from. /// @@ -116,7 +118,7 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { /// /// Maybe we should have separate "borrowck" and "moveck" modes. fn move_path_for(&mut self, place: Place<'tcx>) -> MovePathResult { - let data = &mut self.builder.data; + let data = &mut self.data; debug!("lookup({:?})", place); let Some(mut base) = data.rev_lookup.find_local(place.local) else { @@ -131,8 +133,8 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { let mut union_path = None; for (place_ref, elem) in data.rev_lookup.un_derefer.iter_projections(place.as_ref()) { - let body = self.builder.body; - let tcx = self.builder.tcx; + let body = self.body; + let tcx = self.tcx; let place_ty = place_ref.ty(body, tcx).ty; if place_ty.references_error() { return MovePathResult::Error; @@ -238,7 +240,7 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { | ProjectionElem::Downcast(_, _) => (), } let elem_ty = PlaceTy::from_ty(place_ty).projection_ty(tcx, elem).ty; - if !(self.builder.filter)(elem_ty) { + if !(self.filter)(elem_ty) { return MovePathResult::Error; } if union_path.is_none() { @@ -274,7 +276,7 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { data: MoveData { rev_lookup, move_paths, path_map, init_path_map, .. }, tcx, .. - } = self.builder; + } = self; *rev_lookup.projections.entry((base, elem.lift())).or_insert_with(move || { new_move_path(move_paths, path_map, init_path_map, Some(base), mk_place(*tcx)) }) @@ -285,9 +287,7 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { // drop), so this not being a valid move path is OK. let _ = self.move_path_for(place); } -} -impl<'a, 'tcx, F> MoveDataBuilder<'a, 'tcx, F> { fn finalize(self) -> MoveData<'tcx> { debug!("{}", { debug!("moves for {:?}:", self.body.span); @@ -317,12 +317,12 @@ pub(super) fn gather_moves<'tcx>( for (bb, block) in body.basic_blocks.iter_enumerated() { for (i, stmt) in block.statements.iter().enumerate() { - let source = Location { block: bb, statement_index: i }; - builder.gather_statement(source, stmt); + builder.loc = Location { block: bb, statement_index: i }; + builder.gather_statement(stmt); } - let terminator_loc = Location { block: bb, statement_index: block.statements.len() }; - builder.gather_terminator(terminator_loc, block.terminator()); + builder.loc = Location { block: bb, statement_index: block.statements.len() }; + builder.gather_terminator(block.terminator()); } builder.finalize() @@ -345,30 +345,14 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> { } } - fn gather_statement(&mut self, loc: Location, stmt: &Statement<'tcx>) { - debug!("gather_statement({:?}, {:?})", loc, stmt); - (Gatherer { builder: self, loc }).gather_statement(stmt); - } - - fn gather_terminator(&mut self, loc: Location, term: &Terminator<'tcx>) { - debug!("gather_terminator({:?}, {:?})", loc, term); - (Gatherer { builder: self, loc }).gather_terminator(term); - } -} - -struct Gatherer<'b, 'a, 'tcx, F> { - builder: &'b mut MoveDataBuilder<'a, 'tcx, F>, - loc: Location, -} - -impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { fn gather_statement(&mut self, stmt: &Statement<'tcx>) { + debug!("gather_statement({:?}, {:?})", self.loc, stmt); match &stmt.kind { StatementKind::Assign(box (place, Rvalue::CopyForDeref(reffed))) => { let local = place.as_local().unwrap(); - assert!(self.builder.body.local_decls[local].is_deref_temp()); + assert!(self.body.local_decls[local].is_deref_temp()); - let rev_lookup = &mut self.builder.data.rev_lookup; + let rev_lookup = &mut self.data.rev_lookup; rev_lookup.un_derefer.insert(local, reffed.as_ref()); let base_local = rev_lookup.un_derefer.deref_chain(local).first().unwrap().local; @@ -380,7 +364,7 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { // Box starts out uninitialized - need to create a separate // move-path for the interior so it will be separate from // the exterior. - self.create_move_path(self.builder.tcx.mk_place_deref(*place)); + self.create_move_path(self.tcx.mk_place_deref(*place)); self.gather_init(place.as_ref(), InitKind::Shallow); } else { self.gather_init(place.as_ref(), InitKind::Deep); @@ -393,7 +377,7 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { StatementKind::StorageLive(_) => {} StatementKind::StorageDead(local) => { // DerefTemp locals (results of CopyForDeref) don't actually move anything. - if !self.builder.body.local_decls[*local].is_deref_temp() { + if !self.body.local_decls[*local].is_deref_temp() { self.gather_move(Place::from(*local)); } } @@ -443,6 +427,7 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { } fn gather_terminator(&mut self, term: &Terminator<'tcx>) { + debug!("gather_terminator({:?}, {:?})", self.loc, term); match term.kind { TerminatorKind::Goto { target: _ } | TerminatorKind::FalseEdge { .. } @@ -551,7 +536,7 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { // `ConstIndex` patterns. This is done to ensure that all move paths // are disjoint, which is expected by drop elaboration. let base_place = - Place { local: place.local, projection: self.builder.tcx.mk_place_elems(base) }; + Place { local: place.local, projection: self.tcx.mk_place_elems(base) }; let base_path = match self.move_path_for(base_place) { MovePathResult::Path(path) => path, MovePathResult::Union(path) => { @@ -562,11 +547,9 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { return; } }; - let base_ty = base_place.ty(self.builder.body, self.builder.tcx).ty; + let base_ty = base_place.ty(self.body, self.tcx).ty; let len: u64 = match base_ty.kind() { - ty::Array(_, size) => { - size.eval_target_usize(self.builder.tcx, self.builder.param_env) - } + ty::Array(_, size) => size.eval_target_usize(self.tcx, self.param_env), _ => bug!("from_end: false slice pattern of non-array type"), }; for offset in from..to { @@ -587,13 +570,13 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { } fn record_move(&mut self, place: Place<'tcx>, path: MovePathIndex) { - let move_out = self.builder.data.moves.push(MoveOut { path, source: self.loc }); + let move_out = self.data.moves.push(MoveOut { path, source: self.loc }); debug!( "gather_move({:?}, {:?}): adding move {:?} of {:?}", self.loc, place, move_out, path ); - self.builder.data.path_map[path].push(move_out); - self.builder.data.loc_map[self.loc].push(move_out); + self.data.path_map[path].push(move_out); + self.data.loc_map[self.loc].push(move_out); } fn gather_init(&mut self, place: PlaceRef<'tcx>, kind: InitKind) { @@ -604,13 +587,13 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { // Check if we are assigning into a field of a union, if so, lookup the place // of the union so it is marked as initialized again. if let Some((place_base, ProjectionElem::Field(_, _))) = place.last_projection() { - if place_base.ty(self.builder.body, self.builder.tcx).ty.is_union() { + if place_base.ty(self.body, self.tcx).ty.is_union() { place = place_base; } } - if let LookupResult::Exact(path) = self.builder.data.rev_lookup.find(place) { - let init = self.builder.data.inits.push(Init { + if let LookupResult::Exact(path) = self.data.rev_lookup.find(place) { + let init = self.data.inits.push(Init { location: InitLocation::Statement(self.loc), path, kind, @@ -621,8 +604,8 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { self.loc, place, init, path ); - self.builder.data.init_path_map[path].push(init); - self.builder.data.init_loc_map[self.loc].push(init); + self.data.init_path_map[path].push(init); + self.data.init_loc_map[self.loc].push(init); } } } From 0b032f8f83216b1bee09562d07d113657ddc6527 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 6 Sep 2024 16:47:28 +1000 Subject: [PATCH 087/189] Remove `Elaborator`. It's a trivial wrapper around `ElaborateDropsCtxt` that serves no apparent purpose. --- .../src/elaborate_drops.rs | 60 ++++++++----------- 1 file changed, 24 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index ffffdf53916a7..af110878e9c28 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -137,45 +137,35 @@ impl InitializationData<'_, '_> { } } -struct Elaborator<'a, 'b, 'tcx> { - ctxt: &'a mut ElaborateDropsCtxt<'b, 'tcx>, -} - -impl fmt::Debug for Elaborator<'_, '_, '_> { - fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { - Ok(()) - } -} - -impl<'b, 'tcx> DropElaborator<'b, 'tcx> for Elaborator<'_, 'b, 'tcx> { +impl<'a, 'tcx> DropElaborator<'a, 'tcx> for ElaborateDropsCtxt<'a, 'tcx> { type Path = MovePathIndex; fn patch(&mut self) -> &mut MirPatch<'tcx> { - &mut self.ctxt.patch + &mut self.patch } - fn body(&self) -> &'b Body<'tcx> { - self.ctxt.body + fn body(&self) -> &'a Body<'tcx> { + self.body } fn tcx(&self) -> TyCtxt<'tcx> { - self.ctxt.tcx + self.tcx } fn param_env(&self) -> ty::ParamEnv<'tcx> { - self.ctxt.param_env() + self.param_env() } #[instrument(level = "debug", skip(self), ret)] fn drop_style(&self, path: Self::Path, mode: DropFlagMode) -> DropStyle { let ((maybe_live, maybe_dead), multipart) = match mode { - DropFlagMode::Shallow => (self.ctxt.init_data.maybe_live_dead(path), false), + DropFlagMode::Shallow => (self.init_data.maybe_live_dead(path), false), DropFlagMode::Deep => { let mut some_live = false; let mut some_dead = false; let mut children_count = 0; - on_all_children_bits(self.ctxt.move_data(), path, |child| { - let (live, dead) = self.ctxt.init_data.maybe_live_dead(child); + on_all_children_bits(self.move_data(), path, |child| { + let (live, dead) = self.init_data.maybe_live_dead(child); debug!("elaborate_drop: state({:?}) = {:?}", child, (live, dead)); some_live |= live; some_dead |= dead; @@ -195,25 +185,25 @@ impl<'b, 'tcx> DropElaborator<'b, 'tcx> for Elaborator<'_, 'b, 'tcx> { fn clear_drop_flag(&mut self, loc: Location, path: Self::Path, mode: DropFlagMode) { match mode { DropFlagMode::Shallow => { - self.ctxt.set_drop_flag(loc, path, DropFlagState::Absent); + self.set_drop_flag(loc, path, DropFlagState::Absent); } DropFlagMode::Deep => { - on_all_children_bits(self.ctxt.move_data(), path, |child| { - self.ctxt.set_drop_flag(loc, child, DropFlagState::Absent) + on_all_children_bits(self.move_data(), path, |child| { + self.set_drop_flag(loc, child, DropFlagState::Absent) }); } } } fn field_subpath(&self, path: Self::Path, field: FieldIdx) -> Option { - rustc_mir_dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| match e { + rustc_mir_dataflow::move_path_children_matching(self.move_data(), path, |e| match e { ProjectionElem::Field(idx, _) => idx == field, _ => false, }) } fn array_subpath(&self, path: Self::Path, index: u64, size: u64) -> Option { - rustc_mir_dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| match e { + rustc_mir_dataflow::move_path_children_matching(self.move_data(), path, |e| match e { ProjectionElem::ConstantIndex { offset, min_length, from_end } => { debug_assert!(size == min_length, "min_length should be exact for arrays"); assert!(!from_end, "from_end should not be used for array element ConstantIndex"); @@ -224,20 +214,20 @@ impl<'b, 'tcx> DropElaborator<'b, 'tcx> for Elaborator<'_, 'b, 'tcx> { } fn deref_subpath(&self, path: Self::Path) -> Option { - rustc_mir_dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| { + rustc_mir_dataflow::move_path_children_matching(self.move_data(), path, |e| { e == ProjectionElem::Deref }) } fn downcast_subpath(&self, path: Self::Path, variant: VariantIdx) -> Option { - rustc_mir_dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| match e { + rustc_mir_dataflow::move_path_children_matching(self.move_data(), path, |e| match e { ProjectionElem::Downcast(_, idx) => idx == variant, _ => false, }) } fn get_drop_flag(&mut self, path: Self::Path) -> Option> { - self.ctxt.drop_flag(path).map(Operand::Copy) + self.drop_flag(path).map(Operand::Copy) } } @@ -250,6 +240,12 @@ struct ElaborateDropsCtxt<'a, 'tcx> { patch: MirPatch<'tcx>, } +impl fmt::Debug for ElaborateDropsCtxt<'_, '_> { + fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { + Ok(()) + } +} + impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> { fn move_data(&self) -> &'a MoveData<'tcx> { &self.env.move_data @@ -370,15 +366,7 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> { } }; self.init_data.seek_before(self.body.terminator_loc(bb)); - elaborate_drop( - &mut Elaborator { ctxt: self }, - terminator.source_info, - place, - path, - target, - unwind, - bb, - ) + elaborate_drop(self, terminator.source_info, place, path, target, unwind, bb) } LookupResult::Parent(None) => {} LookupResult::Parent(Some(_)) => { From 5c3502772ae8298b82d1a0e5b4cb4fb15f930766 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 6 Sep 2024 16:55:42 +1000 Subject: [PATCH 088/189] Remove unnecessary lifetime from `StorageConflictVisitor`. --- compiler/rustc_mir_transform/src/coroutine.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index eefb748e49d51..cb84149df69fe 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -872,9 +872,9 @@ fn compute_storage_conflicts<'mir, 'tcx>( storage_conflicts } -struct StorageConflictVisitor<'mir, 'tcx, 's> { - body: &'mir Body<'tcx>, - saved_locals: &'s CoroutineSavedLocals, +struct StorageConflictVisitor<'a, 'tcx> { + body: &'a Body<'tcx>, + saved_locals: &'a CoroutineSavedLocals, // FIXME(tmandry): Consider using sparse bitsets here once we have good // benchmarks for coroutines. local_conflicts: BitMatrix, @@ -882,8 +882,8 @@ struct StorageConflictVisitor<'mir, 'tcx, 's> { eligible_storage_live: BitSet, } -impl<'mir, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx, R> - for StorageConflictVisitor<'mir, 'tcx, '_> +impl<'a, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'a, 'tcx, R> + for StorageConflictVisitor<'a, 'tcx> { type FlowState = BitSet; @@ -891,7 +891,7 @@ impl<'mir, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx, R> &mut self, _results: &mut R, state: &Self::FlowState, - _statement: &'mir Statement<'tcx>, + _statement: &'a Statement<'tcx>, loc: Location, ) { self.apply_state(state, loc); @@ -901,14 +901,14 @@ impl<'mir, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx, R> &mut self, _results: &mut R, state: &Self::FlowState, - _terminator: &'mir Terminator<'tcx>, + _terminator: &'a Terminator<'tcx>, loc: Location, ) { self.apply_state(state, loc); } } -impl StorageConflictVisitor<'_, '_, '_> { +impl StorageConflictVisitor<'_, '_> { fn apply_state(&mut self, flow_state: &BitSet, loc: Location) { // Ignore unreachable blocks. if let TerminatorKind::Unreachable = self.body.basic_blocks[loc.block].terminator().kind { From 0f8efb3b5c628ac3162d5f9f37539ce19956ad80 Mon Sep 17 00:00:00 2001 From: Gurinder Singh Date: Mon, 9 Sep 2024 12:27:36 +0530 Subject: [PATCH 089/189] Fix ICE caused by missing span in a region error --- .../src/error_reporting/infer/region.rs | 14 +++++-- .../wf/ice-wf-missing-span-in-error-130012.rs | 18 ++++++++ ...ice-wf-missing-span-in-error-130012.stderr | 41 +++++++++++++++++++ 3 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 tests/ui/wf/ice-wf-missing-span-in-error-130012.rs create mode 100644 tests/ui/wf/ice-wf-missing-span-in-error-130012.stderr diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index e4a4ec125a5c4..5bd63ab1fee10 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -625,11 +625,19 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if let ObligationCauseCode::WhereClause(_, span) | ObligationCauseCode::WhereClauseInExpr(_, span, ..) = &trace.cause.code().peel_derives() - && !span.is_dummy() { let span = *span; - self.report_concrete_failure(generic_param_scope, placeholder_origin, sub, sup) - .with_span_note(span, "the lifetime requirement is introduced here") + let mut err = self.report_concrete_failure( + generic_param_scope, + placeholder_origin, + sub, + sup, + ); + if !span.is_dummy() { + err = + err.with_span_note(span, "the lifetime requirement is introduced here"); + } + err } else { unreachable!( "control flow ensures we have a `BindingObligation` or `WhereClauseInExpr` here..." diff --git a/tests/ui/wf/ice-wf-missing-span-in-error-130012.rs b/tests/ui/wf/ice-wf-missing-span-in-error-130012.rs new file mode 100644 index 0000000000000..e107069d0dfa9 --- /dev/null +++ b/tests/ui/wf/ice-wf-missing-span-in-error-130012.rs @@ -0,0 +1,18 @@ +// Regression test for ICE #130012 +// Checks that we do not ICE while reporting +// lifetime mistmatch error + +trait Fun { + type Assoc; +} + +trait MyTrait: for<'a> Fun {} +//~^ ERROR binding for associated type `Assoc` references lifetime `'a`, which does not appear in the trait input types +//~| ERROR binding for associated type `Assoc` references lifetime `'a`, which does not appear in the trait input types +//~| ERROR binding for associated type `Assoc` references lifetime `'a`, which does not appear in the trait input types + +impl Fun> MyTrait for F {} +//~^ ERROR binding for associated type `Assoc` references lifetime `'b`, which does not appear in the trait input types +//~| ERROR mismatched types + +fn main() {} diff --git a/tests/ui/wf/ice-wf-missing-span-in-error-130012.stderr b/tests/ui/wf/ice-wf-missing-span-in-error-130012.stderr new file mode 100644 index 0000000000000..357e504bd5eb9 --- /dev/null +++ b/tests/ui/wf/ice-wf-missing-span-in-error-130012.stderr @@ -0,0 +1,41 @@ +error[E0582]: binding for associated type `Assoc` references lifetime `'a`, which does not appear in the trait input types + --> $DIR/ice-wf-missing-span-in-error-130012.rs:9:28 + | +LL | trait MyTrait: for<'a> Fun {} + | ^^^^^^^^^^^^^^ + +error[E0582]: binding for associated type `Assoc` references lifetime `'a`, which does not appear in the trait input types + --> $DIR/ice-wf-missing-span-in-error-130012.rs:9:28 + | +LL | trait MyTrait: for<'a> Fun {} + | ^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0582]: binding for associated type `Assoc` references lifetime `'a`, which does not appear in the trait input types + --> $DIR/ice-wf-missing-span-in-error-130012.rs:9:28 + | +LL | trait MyTrait: for<'a> Fun {} + | ^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0582]: binding for associated type `Assoc` references lifetime `'b`, which does not appear in the trait input types + --> $DIR/ice-wf-missing-span-in-error-130012.rs:14:21 + | +LL | impl Fun> MyTrait for F {} + | ^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/ice-wf-missing-span-in-error-130012.rs:14:50 + | +LL | impl Fun> MyTrait for F {} + | ^ lifetime mismatch + | + = note: expected reference `&()` + found reference `&'b ()` + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0308, E0582. +For more information about an error, try `rustc --explain E0308`. From 54672ac392e3a4af640f59db01e93200b96c97d5 Mon Sep 17 00:00:00 2001 From: Rain Date: Mon, 9 Sep 2024 06:48:56 +0000 Subject: [PATCH 090/189] [illumos] enable SIGSEGV handler to detect stack overflows Use the same code as Solaris. I couldn't find any tests regarding this, but I did test a stage0 build against my stack-exhaust-test binary [1]. Before: ``` running with use_stacker = No, new_thread = false, make_large_local = false zsh: segmentation fault (core dumped) cargo run ``` After: ``` running with use_stacker = No, new_thread = false, make_large_local = false thread 'main' has overflowed its stack fatal runtime error: stack overflow zsh: IOT instruction (core dumped) cargo +stage0 run ``` Fixes #128568. [1] https://github.com/sunshowers/stack-exhaust-test/ --- library/std/src/sys/pal/unix/stack_overflow.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/library/std/src/sys/pal/unix/stack_overflow.rs b/library/std/src/sys/pal/unix/stack_overflow.rs index 9ff44b54c41a1..728ce8d60f639 100644 --- a/library/std/src/sys/pal/unix/stack_overflow.rs +++ b/library/std/src/sys/pal/unix/stack_overflow.rs @@ -32,7 +32,8 @@ impl Drop for Handler { target_os = "macos", target_os = "netbsd", target_os = "openbsd", - target_os = "solaris" + target_os = "solaris", + target_os = "illumos", ))] mod imp { #[cfg(not(all(target_os = "linux", target_env = "gnu")))] @@ -280,7 +281,7 @@ mod imp { libc::SIGSTKSZ } - #[cfg(target_os = "solaris")] + #[cfg(any(target_os = "solaris", target_os = "illumos"))] unsafe fn get_stack_start() -> Option<*mut libc::c_void> { let mut current_stack: libc::stack_t = crate::mem::zeroed(); assert_eq!(libc::stack_getbounds(&mut current_stack), 0); @@ -486,7 +487,12 @@ mod imp { Some(guardaddr..guardaddr + page_size) } - #[cfg(any(target_os = "macos", target_os = "openbsd", target_os = "solaris"))] + #[cfg(any( + target_os = "macos", + target_os = "openbsd", + target_os = "solaris", + target_os = "illumos", + ))] // FIXME: I am probably not unsafe. unsafe fn current_guard() -> Option> { let stackptr = get_stack_start()?; @@ -569,7 +575,8 @@ mod imp { target_os = "macos", target_os = "netbsd", target_os = "openbsd", - target_os = "solaris" + target_os = "solaris", + target_os = "illumos", )))] mod imp { pub unsafe fn init() {} From c33aa863f8852ab0388aed6e578ba015eae702a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Mon, 9 Sep 2024 09:45:59 +0200 Subject: [PATCH 091/189] Do not skip linker configuration for `check` builds It was causing unexpected rebuilds. --- src/bootstrap/src/core/builder.rs | 5 +++-- src/bootstrap/src/utils/cc_detect.rs | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 8f7ade7940342..1e8779817fb71 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -2465,8 +2465,9 @@ impl Cargo { let mut cargo = builder.cargo(compiler, mode, source_type, target, cmd_kind); match cmd_kind { - // No need to configure the target linker for these command types. - Kind::Clean | Kind::Check | Kind::Suggest | Kind::Format | Kind::Setup => {} + // No need to configure the target linker for these command types, + // as they don't invoke rustc at all. + Kind::Clean | Kind::Suggest | Kind::Format | Kind::Setup => {} _ => { cargo.configure_linker(builder); } diff --git a/src/bootstrap/src/utils/cc_detect.rs b/src/bootstrap/src/utils/cc_detect.rs index a2c7ab31df8a5..c39415e7c1865 100644 --- a/src/bootstrap/src/utils/cc_detect.rs +++ b/src/bootstrap/src/utils/cc_detect.rs @@ -90,7 +90,6 @@ pub fn find(build: &Build) { let targets: HashSet<_> = match build.config.cmd { // We don't need to check cross targets for these commands. crate::Subcommand::Clean { .. } - | crate::Subcommand::Check { .. } | crate::Subcommand::Suggest { .. } | crate::Subcommand::Format { .. } | crate::Subcommand::Setup { .. } => { From e186cc6df8e22341036560f79cb99691bb54b483 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Mon, 9 Sep 2024 11:09:22 +0200 Subject: [PATCH 092/189] do `PolyFnSig` -> `FnSig` conversion later --- .../rustc_hir_analysis/src/hir_ty_lowering/cmse.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs index dd519fb92d951..5150db7f51b19 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs @@ -18,9 +18,6 @@ pub(crate) fn validate_cmse_abi<'tcx>( abi: abi::Abi, fn_sig: ty::PolyFnSig<'tcx>, ) { - // this type is only used for layout computation, which does not rely on regions - let fn_sig = tcx.instantiate_bound_regions_with_erased(fn_sig); - if let abi::Abi::CCmseNonSecureCall = abi { let hir_node = tcx.hir_node(hir_id); let hir::Node::Ty(hir::Ty { @@ -70,11 +67,14 @@ pub(crate) fn validate_cmse_abi<'tcx>( /// Returns whether the inputs will fit into the available registers fn is_valid_cmse_inputs<'tcx>( tcx: TyCtxt<'tcx>, - fn_sig: ty::FnSig<'tcx>, + fn_sig: ty::PolyFnSig<'tcx>, ) -> Result, &'tcx LayoutError<'tcx>> { let mut span = None; let mut accum = 0u64; + // this type is only used for layout computation, which does not rely on regions + let fn_sig = tcx.instantiate_bound_regions_with_erased(fn_sig); + for (index, ty) in fn_sig.inputs().iter().enumerate() { let layout = tcx.layout_of(ParamEnv::reveal_all().and(*ty))?; @@ -99,8 +99,11 @@ fn is_valid_cmse_inputs<'tcx>( /// Returns whether the output will fit into the available registers fn is_valid_cmse_output<'tcx>( tcx: TyCtxt<'tcx>, - fn_sig: ty::FnSig<'tcx>, + fn_sig: ty::PolyFnSig<'tcx>, ) -> Result> { + // this type is only used for layout computation, which does not rely on regions + let fn_sig = tcx.instantiate_bound_regions_with_erased(fn_sig); + let mut ret_ty = fn_sig.output(); let layout = tcx.layout_of(ParamEnv::reveal_all().and(ret_ty))?; let size = layout.layout.size().bytes(); From 62d196feb1607c93fb4bc9dc54bf08883496a6a2 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 9 Sep 2024 11:20:22 +0200 Subject: [PATCH 093/189] bootstrap/Makefile.in: miri: add missing BOOTSTRAP ARGS also don't unnecessarily set BOOTSTRAP_SKIP_TARGET_SANITY while we are at it --- src/bootstrap/mk/Makefile.in | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in index 9acd85cddde6a..3fa2b3c22921e 100644 --- a/src/bootstrap/mk/Makefile.in +++ b/src/bootstrap/mk/Makefile.in @@ -54,30 +54,34 @@ check-aux: src/etc/test-float-parse \ $(BOOTSTRAP_ARGS) # Run standard library tests in Miri. - $(Q)BOOTSTRAP_SKIP_TARGET_SANITY=1 \ - $(BOOTSTRAP) miri --stage 2 \ + $(Q)$(BOOTSTRAP) miri --stage 2 \ library/core \ library/alloc \ + $(BOOTSTRAP_ARGS) \ --no-doc # Some doctests use file system operations to demonstrate dealing with `Result`. $(Q)MIRIFLAGS="-Zmiri-disable-isolation" \ $(BOOTSTRAP) miri --stage 2 \ library/core \ library/alloc \ + $(BOOTSTRAP_ARGS) \ --doc # In `std` we cannot test everything, so we skip some modules. $(Q)MIRIFLAGS="-Zmiri-disable-isolation" \ $(BOOTSTRAP) miri --stage 2 library/std \ + $(BOOTSTRAP_ARGS) \ --no-doc -- \ --skip fs:: --skip net:: --skip process:: --skip sys::pal:: $(Q)MIRIFLAGS="-Zmiri-disable-isolation" \ $(BOOTSTRAP) miri --stage 2 library/std \ + $(BOOTSTRAP_ARGS) \ --doc -- \ --skip fs:: --skip net:: --skip process:: --skip sys::pal:: # Also test some very target-specific modules on other targets # (making sure to cover an i686 target as well). $(Q)MIRIFLAGS="-Zmiri-disable-isolation" BOOTSTRAP_SKIP_TARGET_SANITY=1 \ $(BOOTSTRAP) miri --stage 2 library/std \ + $(BOOTSTRAP_ARGS) \ --target aarch64-apple-darwin,i686-pc-windows-msvc \ --no-doc -- \ time:: sync:: thread:: env:: From 02378997ea98b17973a14298a59568700435965d Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Mon, 9 Sep 2024 12:47:40 +0200 Subject: [PATCH 094/189] bootstrap `naked_asm!` for `compiler-builtins` in this commit, `naked_asm!` is an alias for `asm!` with one difference: `options(noreturn)` is always enabled by `naked_asm!`. That makes it future-compatible for when `naked_asm!` starts disallowing `options(noreturn)` later. --- compiler/rustc_builtin_macros/src/asm.rs | 38 ++++++++++++++++++++++++ compiler/rustc_builtin_macros/src/lib.rs | 1 + compiler/rustc_span/src/symbol.rs | 1 + library/core/src/arch.rs | 14 +++++++++ tests/ui/asm/naked-functions-inline.rs | 12 ++++---- 5 files changed, 60 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index ae2627d693867..e313016e3d863 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -812,6 +812,44 @@ pub(super) fn expand_asm<'cx>( }) } +pub(super) fn expand_naked_asm<'cx>( + ecx: &'cx mut ExtCtxt<'_>, + sp: Span, + tts: TokenStream, +) -> MacroExpanderResult<'cx> { + ExpandResult::Ready(match parse_args(ecx, sp, tts, false) { + Ok(args) => { + let ExpandResult::Ready(mac) = expand_preparsed_asm(ecx, args) else { + return ExpandResult::Retry(()); + }; + let expr = match mac { + Ok(mut inline_asm) => { + // for future compatibility, we always set the NORETURN option. + // + // When we turn `asm!` into `naked_asm!` with this implementation, we can drop + // the `options(noreturn)`, which makes the upgrade smooth when `naked_asm!` + // starts disallowing the `noreturn` option in the future + inline_asm.options |= ast::InlineAsmOptions::NORETURN; + + P(ast::Expr { + id: ast::DUMMY_NODE_ID, + kind: ast::ExprKind::InlineAsm(P(inline_asm)), + span: sp, + attrs: ast::AttrVec::new(), + tokens: None, + }) + } + Err(guar) => DummyResult::raw_expr(sp, Some(guar)), + }; + MacEager::expr(expr) + } + Err(err) => { + let guar = err.emit(); + DummyResult::any(sp, guar) + } + }) +} + pub(super) fn expand_global_asm<'cx>( ecx: &'cx mut ExtCtxt<'_>, sp: Span, diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 30e1c8d262216..ebe5e2b544292 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -94,6 +94,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { line: source_util::expand_line, log_syntax: log_syntax::expand_log_syntax, module_path: source_util::expand_mod, + naked_asm: asm::expand_naked_asm, option_env: env::expand_option_env, pattern_type: pattern_type::expand, std_panic: edition_panic::expand_panic, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 418d1078900ac..1f3fb71909bc6 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1254,6 +1254,7 @@ symbols! { mut_preserve_binding_mode_2024, mut_ref, naked, + naked_asm, naked_functions, name, names, diff --git a/library/core/src/arch.rs b/library/core/src/arch.rs index d681bd124fe13..b07cc9a71a8a0 100644 --- a/library/core/src/arch.rs +++ b/library/core/src/arch.rs @@ -26,6 +26,20 @@ pub macro asm("assembly template", $(operands,)* $(options($(option),*))?) { /* compiler built-in */ } +/// Inline assembly used in combination with `#[naked]` functions. +/// +/// Refer to [Rust By Example] for a usage guide and the [reference] for +/// detailed information about the syntax and available options. +/// +/// [Rust By Example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html +/// [reference]: https://doc.rust-lang.org/nightly/reference/inline-assembly.html +#[unstable(feature = "naked_functions", issue = "90957")] +#[rustc_builtin_macro] +#[cfg(not(bootstrap))] +pub macro naked_asm("assembly template", $(operands,)* $(options($(option),*))?) { + /* compiler built-in */ +} + /// Module-level inline assembly. /// /// Refer to [Rust By Example] for a usage guide and the [reference] for diff --git a/tests/ui/asm/naked-functions-inline.rs b/tests/ui/asm/naked-functions-inline.rs index cfb38f2e73848..74049e8ecbc7c 100644 --- a/tests/ui/asm/naked-functions-inline.rs +++ b/tests/ui/asm/naked-functions-inline.rs @@ -2,37 +2,37 @@ #![feature(naked_functions)] #![crate_type = "lib"] -use std::arch::asm; +use std::arch::naked_asm; #[naked] pub unsafe extern "C" fn inline_none() { - asm!("", options(noreturn)); + naked_asm!(""); } #[naked] #[inline] //~^ ERROR [E0736] pub unsafe extern "C" fn inline_hint() { - asm!("", options(noreturn)); + naked_asm!(""); } #[naked] #[inline(always)] //~^ ERROR [E0736] pub unsafe extern "C" fn inline_always() { - asm!("", options(noreturn)); + naked_asm!(""); } #[naked] #[inline(never)] //~^ ERROR [E0736] pub unsafe extern "C" fn inline_never() { - asm!("", options(noreturn)); + naked_asm!(""); } #[naked] #[cfg_attr(all(), inline(never))] //~^ ERROR [E0736] pub unsafe extern "C" fn conditional_inline_never() { - asm!("", options(noreturn)); + naked_asm!(""); } From 0b20ffcb63b00acbbe70ae6f59a746bcde4c8b96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20S=C3=A1nchez=20Mu=C3=B1oz?= Date: Mon, 9 Sep 2024 12:22:00 +0200 Subject: [PATCH 095/189] Remove needless returns detected by clippy in the compiler --- compiler/rustc_ast/src/ast_traits.rs | 4 ++-- compiler/rustc_attr/src/builtin.rs | 2 +- .../src/diagnostics/conflict_errors.rs | 2 +- .../rustc_borrowck/src/type_check/relate_tys.rs | 2 +- compiler/rustc_codegen_llvm/src/llvm_util.rs | 2 +- compiler/rustc_codegen_ssa/src/back/link.rs | 6 +++--- compiler/rustc_codegen_ssa/src/back/linker.rs | 1 - compiler/rustc_codegen_ssa/src/back/metadata.rs | 8 ++++---- compiler/rustc_const_eval/src/interpret/call.rs | 4 ++-- compiler/rustc_expand/src/mbe/transcribe.rs | 16 ++++++++-------- .../src/check/compare_impl_item.rs | 2 +- .../rustc_hir_analysis/src/coherence/builtin.rs | 2 +- compiler/rustc_hir_typeck/src/closure.rs | 2 +- compiler/rustc_hir_typeck/src/demand.rs | 2 +- .../rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs | 4 ++-- .../rustc_hir_typeck/src/fn_ctxt/suggestions.rs | 2 +- compiler/rustc_infer/src/infer/mod.rs | 4 ++-- .../rustc_lint/src/for_loops_over_fallibles.rs | 2 +- compiler/rustc_middle/src/hir/map/mod.rs | 12 ++++++------ .../rustc_middle/src/mir/interpret/allocation.rs | 2 +- compiler/rustc_middle/src/mir/mod.rs | 5 ++--- compiler/rustc_middle/src/ty/context.rs | 2 +- compiler/rustc_middle/src/ty/region.rs | 2 +- .../rustc_mir_build/src/build/custom/parse.rs | 12 +++++------- compiler/rustc_monomorphize/src/collector.rs | 2 +- compiler/rustc_parse/src/lexer/tokentrees.rs | 2 +- compiler/rustc_parse/src/parser/diagnostics.rs | 2 +- compiler/rustc_parse/src/parser/item.rs | 2 +- compiler/rustc_passes/src/check_attr.rs | 5 +---- compiler/rustc_passes/src/dead.rs | 2 +- compiler/rustc_resolve/src/diagnostics.rs | 2 +- compiler/rustc_resolve/src/late.rs | 2 +- compiler/rustc_resolve/src/late/diagnostics.rs | 2 +- compiler/rustc_session/src/filesearch.rs | 2 +- compiler/rustc_session/src/options.rs | 2 +- compiler/rustc_span/src/source_map.rs | 2 +- compiler/rustc_target/src/abi/call/mod.rs | 6 ++---- compiler/rustc_target/src/abi/call/sparc64.rs | 6 +++--- 38 files changed, 66 insertions(+), 75 deletions(-) diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs index 6b95fb7dd36b8..60f8c6e10481b 100644 --- a/compiler/rustc_ast/src/ast_traits.rs +++ b/compiler/rustc_ast/src/ast_traits.rs @@ -153,7 +153,7 @@ impl HasTokens for StmtKind { StmtKind::Let(local) => local.tokens.as_ref(), StmtKind::Item(item) => item.tokens(), StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.tokens(), - StmtKind::Empty => return None, + StmtKind::Empty => None, StmtKind::MacCall(mac) => mac.tokens.as_ref(), } } @@ -162,7 +162,7 @@ impl HasTokens for StmtKind { StmtKind::Let(local) => Some(&mut local.tokens), StmtKind::Item(item) => item.tokens_mut(), StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.tokens_mut(), - StmtKind::Empty => return None, + StmtKind::Empty => None, StmtKind::MacCall(mac) => Some(&mut mac.tokens), } } diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index e46dabc7a6e22..309049b98f0e2 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -1240,5 +1240,5 @@ pub fn parse_confusables(attr: &Attribute) -> Option> { candidates.push(meta_lit.symbol); } - return Some(candidates); + Some(candidates) } diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index c817b6fac7134..30e6f1acf1031 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -3669,7 +3669,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { reinits.push(location); return true; } - return false; + false }; while let Some(location) = stack.pop() { diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index bb4a58930e1bb..421f4e2efe0e8 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -214,7 +214,7 @@ impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> { let delegate = FnMutDelegate { regions: &mut |br: ty::BoundRegion| { if let Some(ex_reg_var) = reg_map.get(&br) { - return *ex_reg_var; + *ex_reg_var } else { let ex_reg_var = self.next_existential_region_var(true, br.kind.get_name()); debug!(?ex_reg_var); diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index d55220ba5c3a4..6e4ddbb6f3b6a 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -290,7 +290,7 @@ pub(crate) fn check_tied_features( } } } - return None; + None } /// Used to generate cfg variables and apply features diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index e8143b9a5f38f..dbb65707bd23b 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -438,7 +438,7 @@ fn link_rlib<'a>( ab.add_file(&lib) } - return Ok(ab); + Ok(ab) } /// Extract all symbols defined in raw-dylib libraries, collated by library name. @@ -1319,7 +1319,7 @@ fn link_sanitizer_runtime( fn find_sanitizer_runtime(sess: &Session, filename: &str) -> PathBuf { let path = sess.target_tlib_path.dir.join(filename); if path.exists() { - return sess.target_tlib_path.dir.clone(); + sess.target_tlib_path.dir.clone() } else { let default_sysroot = filesearch::get_or_default_sysroot().expect("Failed finding sysroot"); @@ -1327,7 +1327,7 @@ fn link_sanitizer_runtime( &default_sysroot, sess.opts.target_triple.triple(), ); - return default_tlib; + default_tlib } } diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index cb266247e0dde..ea71b92de3ae7 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -1484,7 +1484,6 @@ impl<'a> Linker for L4Bender<'a> { fn export_symbols(&mut self, _: &Path, _: CrateType, _: &[String]) { // ToDo, not implemented, copy from GCC self.sess.dcx().emit_warn(errors::L4BenderExportingSymbolsUnimplemented); - return; } fn subsystem(&mut self, subsystem: &str) { diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index 0fd9d7fffe8f9..6215616e51000 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -171,10 +171,10 @@ pub(super) fn get_metadata_xcoff<'a>(path: &Path, data: &'a [u8]) -> Result<&'a "Metadata at offset {offset} with size {len} is beyond .info section" )); } - return Ok(&info_data[offset..(offset + len)]); + Ok(&info_data[offset..(offset + len)]) } else { - return Err(format!("Unable to find symbol {AIX_METADATA_SYMBOL_NAME}")); - }; + Err(format!("Unable to find symbol {AIX_METADATA_SYMBOL_NAME}")) + } } pub(crate) fn create_object_file(sess: &Session) -> Option> { @@ -413,7 +413,7 @@ fn macho_object_build_version_for_target(target: &Target) -> object::write::Mach /// Is Apple's CPU subtype `arm64e`s fn macho_is_arm64e(target: &Target) -> bool { - return target.llvm_target.starts_with("arm64e"); + target.llvm_target.starts_with("arm64e") } pub enum MetadataPosition { diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index 568a9a3a637be..419d412b0630b 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -235,13 +235,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { if self.layout_compat(caller_abi.layout, callee_abi.layout)? { // Ensure that our checks imply actual ABI compatibility for this concrete call. assert!(caller_abi.eq_abi(callee_abi)); - return Ok(true); + Ok(true) } else { trace!( "check_argument_compat: incompatible ABIs:\ncaller: {:?}\ncallee: {:?}", caller_abi, callee_abi ); - return Ok(false); + Ok(false) } } diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 39489a8df1bed..2bd78d347368a 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -773,18 +773,20 @@ fn extract_symbol_from_pnr<'a>( match pnr { ParseNtResult::Ident(nt_ident, is_raw) => { if let IdentIsRaw::Yes = is_raw { - return Err(dcx.struct_span_err(span_err, RAW_IDENT_ERR)); + Err(dcx.struct_span_err(span_err, RAW_IDENT_ERR)) + } else { + Ok(nt_ident.name) } - return Ok(nt_ident.name); } ParseNtResult::Tt(TokenTree::Token( Token { kind: TokenKind::Ident(symbol, is_raw), .. }, _, )) => { if let IdentIsRaw::Yes = is_raw { - return Err(dcx.struct_span_err(span_err, RAW_IDENT_ERR)); + Err(dcx.struct_span_err(span_err, RAW_IDENT_ERR)) + } else { + Ok(*symbol) } - return Ok(*symbol); } ParseNtResult::Tt(TokenTree::Token( Token { @@ -792,15 +794,13 @@ fn extract_symbol_from_pnr<'a>( .. }, _, - )) => { - return Ok(*symbol); - } + )) => Ok(*symbol), ParseNtResult::Nt(nt) if let Nonterminal::NtLiteral(expr) = &**nt && let ExprKind::Lit(Lit { kind: LitKind::Str, symbol, suffix: None }) = &expr.kind => { - return Ok(*symbol); + Ok(*symbol) } _ => Err(dcx .struct_err( diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 2afed04c5bcd5..388e02b36e02c 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -1038,7 +1038,7 @@ fn report_trait_method_mismatch<'tcx>( false, ); - return diag.emit(); + diag.emit() } fn check_region_bounds_on_impl_item<'tcx>( diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 30fc06829ed8e..480116a624921 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -274,7 +274,7 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<() return false; } - return true; + true }) .collect::>(); diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 5117eef9ed8f5..f71427e42d4a5 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -605,7 +605,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Abi::Rust, )); - return Some(ExpectedSig { cause_span, sig }); + Some(ExpectedSig { cause_span, sig }) } fn sig_of_closure( diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 0da299f017942..80a71f27a9990 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -1042,7 +1042,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return true; } } - return false; + false } fn explain_self_literal( diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs index cb77d3f85d935..358bc389bd138 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs @@ -307,7 +307,7 @@ impl<'tcx> ArgMatrix<'tcx> { permutation.into_iter().map(|x| x.unwrap()).collect(); return Some(Issue::Permutation(final_permutation)); } - return None; + None } // Obviously, detecting exact user intention is impossible, so the goal here is to @@ -410,6 +410,6 @@ impl<'tcx> ArgMatrix<'tcx> { // sort errors with same type by the order they appear in the source // so that suggestion will be handled properly, see #112507 errors.sort(); - return (errors, matched_inputs); + (errors, matched_inputs) } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 4454703645e79..c9ffdeea998e7 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -2028,7 +2028,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let span = expr.span.find_oldest_ancestor_in_same_ctxt(); err.span_suggestion_verbose(span.shrink_to_hi(), msg, sugg, Applicability::HasPlaceholders); - return true; + true } pub(crate) fn suggest_coercing_result_via_try_operator( diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 234dc5133f8db..5ebc67a7f2cc3 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1481,7 +1481,7 @@ impl<'tcx> InferCtxt<'tcx> { // This hoists the borrow/release out of the loop body. let inner = self.inner.try_borrow(); - return move |infer_var: TyOrConstInferVar| match (infer_var, &inner) { + move |infer_var: TyOrConstInferVar| match (infer_var, &inner) { (TyOrConstInferVar::Ty(ty_var), Ok(inner)) => { use self::type_variable::TypeVariableValue; @@ -1491,7 +1491,7 @@ impl<'tcx> InferCtxt<'tcx> { ) } _ => false, - }; + } } /// `ty_or_const_infer_var_changed` is equivalent to one of these two: diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs index 2793d48dc512b..1b25f21ef84dd 100644 --- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs +++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs @@ -133,7 +133,7 @@ fn extract_iterator_next_call<'tcx>( { Some(recv) } else { - return None; + None } } diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 3d346b9cc5d0a..8b0a855612c19 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -71,7 +71,7 @@ impl<'hir> Iterator for ParentHirIterator<'hir> { debug_assert_ne!(parent_id, self.current_id); self.current_id = parent_id; - return Some(parent_id); + Some(parent_id) } } @@ -103,7 +103,7 @@ impl<'hir> Iterator for ParentOwnerIterator<'hir> { self.current_id = HirId::make_owner(parent_id.def_id); let node = self.map.tcx.hir_owner_node(self.current_id.owner); - return Some((self.current_id.owner, node)); + Some((self.current_id.owner, node)) } } @@ -1233,14 +1233,14 @@ pub(super) fn hir_module_items(tcx: TyCtxt<'_>, module_id: LocalModDefId) -> Mod body_owners, .. } = collector; - return ModuleItems { + ModuleItems { submodules: submodules.into_boxed_slice(), free_items: items.into_boxed_slice(), trait_items: trait_items.into_boxed_slice(), impl_items: impl_items.into_boxed_slice(), foreign_items: foreign_items.into_boxed_slice(), body_owners: body_owners.into_boxed_slice(), - }; + } } pub(crate) fn hir_crate_items(tcx: TyCtxt<'_>, _: ()) -> ModuleItems { @@ -1262,14 +1262,14 @@ pub(crate) fn hir_crate_items(tcx: TyCtxt<'_>, _: ()) -> ModuleItems { .. } = collector; - return ModuleItems { + ModuleItems { submodules: submodules.into_boxed_slice(), free_items: items.into_boxed_slice(), trait_items: trait_items.into_boxed_slice(), impl_items: impl_items.into_boxed_slice(), foreign_items: foreign_items.into_boxed_slice(), body_owners: body_owners.into_boxed_slice(), - }; + } } struct ItemCollector<'tcx> { diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 5fb8af576ae93..ca3bc82184ff4 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -641,7 +641,7 @@ impl Allocation pub fn write_uninit(&mut self, cx: &impl HasDataLayout, range: AllocRange) -> AllocResult { self.mark_init(range, false); self.provenance.clear(range, cx)?; - return Ok(()); + Ok(()) } /// Applies a previously prepared provenance copy. diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 081a23b6ff317..26addb1e357f5 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1166,10 +1166,9 @@ impl<'tcx> LocalDecl<'tcx> { /// Returns `true` if this is a DerefTemp pub fn is_deref_temp(&self) -> bool { match self.local_info() { - LocalInfo::DerefTemp => return true, - _ => (), + LocalInfo::DerefTemp => true, + _ => false, } - return false; } /// Returns `true` is the local is from a compiler desugaring, e.g., diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 2a3008897c676..2571cbbf29965 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2003,7 +2003,7 @@ impl<'tcx> TyCtxt<'tcx> { )); } } - return None; + None } /// Checks if the bound region is in Impl Item. diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs index a2a961057771a..44956d5b0a6bd 100644 --- a/compiler/rustc_middle/src/ty/region.rs +++ b/compiler/rustc_middle/src/ty/region.rs @@ -431,7 +431,7 @@ impl BoundRegionKind { pub fn get_id(&self) -> Option { match *self { - BoundRegionKind::BrNamed(id, _) => return Some(id), + BoundRegionKind::BrNamed(id, _) => Some(id), _ => None, } } diff --git a/compiler/rustc_mir_build/src/build/custom/parse.rs b/compiler/rustc_mir_build/src/build/custom/parse.rs index 646aefa08829e..1f186c8f99afe 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse.rs @@ -82,13 +82,11 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { fn statement_as_expr(&self, stmt_id: StmtId) -> PResult { match &self.thir[stmt_id].kind { StmtKind::Expr { expr, .. } => Ok(*expr), - kind @ StmtKind::Let { pattern, .. } => { - return Err(ParseError { - span: pattern.span, - item_description: format!("{kind:?}"), - expected: "expression".to_string(), - }); - } + kind @ StmtKind::Let { pattern, .. } => Err(ParseError { + span: pattern.span, + item_description: format!("{kind:?}"), + expected: "expression".to_string(), + }), } } diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 093697a290c00..c3f228962005b 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1193,7 +1193,7 @@ fn assoc_fn_of_type<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, fn_ident: Ident) -> return Some(new.def_id); } } - return None; + None } /// Scans the MIR in order to find function calls, closures, and drop-glue. diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs index e7a7105803fcd..c83d8bf4021ee 100644 --- a/compiler/rustc_parse/src/lexer/tokentrees.rs +++ b/compiler/rustc_parse/src/lexer/tokentrees.rs @@ -299,7 +299,7 @@ impl<'psess, 'src> TokenTreesReader<'psess, 'src> { } return diff_errs; } - return errs; + errs } fn close_delim_err(&mut self, delim: Delimiter) -> PErr<'psess> { diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index f6f66821df7fb..bee73c58cb794 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2553,7 +2553,7 @@ impl<'a> Parser<'a> { err.delay_as_bug(); } } - return Ok(false); // Don't continue. + Ok(false) // Don't continue. } /// Attempt to parse a generic const argument that has not been enclosed in braces. diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index c6a5e1908f704..83d10dea6a8fb 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -457,7 +457,7 @@ impl<'a> Parser<'a> { fn parse_item_builtin(&mut self) -> PResult<'a, Option> { // To be expanded - return Ok(None); + Ok(None) } /// Parses an item macro, e.g., `item!();`. diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index e41f89a3c9da9..4fb9b93b80c8d 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1905,10 +1905,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { || (int_reprs == 1 && is_c && item.is_some_and(|item| { - if let ItemLike::Item(item) = item { - return is_c_like_enum(item); - } - return false; + if let ItemLike::Item(item) = item { is_c_like_enum(item) } else { false } })) { self.tcx.emit_node_span_lint( diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 7f1e906ffd737..ef534c645a461 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -394,7 +394,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { } } - return false; + false } fn visit_node(&mut self, node: Node<'tcx>) { diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index bcbdf627b5662..182577b82c49d 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -3076,7 +3076,7 @@ fn search_for_any_use_in_items(items: &[P]) -> Option { } } } - return None; + None } fn is_span_suitable_for_use_injection(s: Span) -> bool { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 917cb81aa511f..40a6ac70bfdd8 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -5016,5 +5016,5 @@ fn def_id_matches_path(tcx: TyCtxt<'_>, mut def_id: DefId, expected_path: &[&str } def_id = parent; } - return true; + true } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 8f516c2db0900..098509cd1d508 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -779,7 +779,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { candidates = self.smart_resolve_partial_mod_path_errors(path, following_seg); } - return (false, candidates); + (false, candidates) } fn suggest_trait_and_bounds( diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs index d78f4a78de732..e72d4face3c87 100644 --- a/compiler/rustc_session/src/filesearch.rs +++ b/compiler/rustc_session/src/filesearch.rs @@ -182,7 +182,7 @@ pub fn sysroot_candidates() -> SmallVec<[PathBuf; 2]> { } } - return sysroot_candidates; + sysroot_candidates } /// Returns the provided sysroot or calls [`get_or_default_sysroot`] if it's none. diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index a57dc80b3168d..982a3d5cf110d 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -353,7 +353,7 @@ fn build_options( None => early_dcx.early_fatal(format!("unknown {outputname} option: `{key}`")), } } - return op; + op } #[allow(non_upper_case_globals)] diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index f914e8dc1baaa..98447147d3e13 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -779,7 +779,7 @@ impl SourceMap { return Ok(false); } } - return Ok(true); + Ok(true) }) .is_ok_and(|is_accessible| is_accessible) } diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index 082c169b210f8..c2826b55dc5b1 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -188,7 +188,7 @@ impl ArgAttributes { if self.arg_ext != other.arg_ext { return false; } - return true; + true } } @@ -632,7 +632,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> { PassMode::Indirect { .. } => { self.mode = PassMode::Direct(ArgAttributes::new()); } - PassMode::Ignore | PassMode::Direct(_) | PassMode::Pair(_, _) => return, // already direct + PassMode::Ignore | PassMode::Direct(_) | PassMode::Pair(_, _) => {} // already direct _ => panic!("Tried to make {:?} direct", self.mode), } } @@ -646,7 +646,6 @@ impl<'a, Ty> ArgAbi<'a, Ty> { } PassMode::Indirect { attrs: _, meta_attrs: _, on_stack: false } => { // already indirect - return; } _ => panic!("Tried to make {:?} indirect", self.mode), } @@ -661,7 +660,6 @@ impl<'a, Ty> ArgAbi<'a, Ty> { } PassMode::Indirect { attrs: _, meta_attrs: _, on_stack: false } => { // already indirect - return; } _ => panic!("Tried to make {:?} indirect (expected `PassMode::Ignore`)", self.mode), } diff --git a/compiler/rustc_target/src/abi/call/sparc64.rs b/compiler/rustc_target/src/abi/call/sparc64.rs index 2954d9642df95..835353f76fc9a 100644 --- a/compiler/rustc_target/src/abi/call/sparc64.rs +++ b/compiler/rustc_target/src/abi/call/sparc64.rs @@ -66,7 +66,7 @@ where data.last_offset = offset + Reg::f64().size; } data.prefix_index += 1; - return data; + data } fn arg_scalar_pair( @@ -92,7 +92,7 @@ where offset += Size::from_bytes(4 - (offset.bytes() % 4)); } data = arg_scalar(cx, scalar2, offset, data); - return data; + data } fn parse_structure<'a, Ty, C>( @@ -128,7 +128,7 @@ where } } - return data; + data } fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, in_registers_max: Size) From db6361184e49e7eaba3c1bf854b9d8345b462680 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Mon, 9 Sep 2024 14:33:48 +0300 Subject: [PATCH 096/189] Helper function for formatting with `LifetimeSuggestionPosition` --- compiler/rustc_hir/src/hir.rs | 13 +++++++++++++ .../src/collect/resolve_bound_vars.rs | 18 +----------------- .../src/error_reporting/infer/region.rs | 13 +------------ 3 files changed, 15 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 57c47d29857c3..b01c24cf3053e 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -168,6 +168,19 @@ impl Lifetime { (LifetimeSuggestionPosition::Normal, self.ident.span) } } + + pub fn suggestion(&self, new_lifetime: &str) -> (Span, String) { + debug_assert!(new_lifetime.starts_with('\'')); + let (pos, span) = self.suggestion_position(); + let code = match pos { + LifetimeSuggestionPosition::Normal => format!("{new_lifetime}"), + LifetimeSuggestionPosition::Ampersand => format!("{new_lifetime} "), + LifetimeSuggestionPosition::ElidedPath => format!("<{new_lifetime}>"), + LifetimeSuggestionPosition::ElidedPathArgument => format!("{new_lifetime}, "), + LifetimeSuggestionPosition::ObjectDefault => format!("+ {new_lifetime}"), + }; + (span, code) + } } /// A `Path` is essentially Rust's notion of a name; for instance, diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index fe46eb583f1df..b4cbd1f309c97 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -1191,23 +1191,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { (generics.span, "<'a>".to_owned()) }; - let lifetime_sugg = match lifetime_ref.suggestion_position() { - (hir::LifetimeSuggestionPosition::Normal, span) => { - (span, "'a".to_owned()) - } - (hir::LifetimeSuggestionPosition::Ampersand, span) => { - (span, "'a ".to_owned()) - } - (hir::LifetimeSuggestionPosition::ElidedPath, span) => { - (span, "<'a>".to_owned()) - } - (hir::LifetimeSuggestionPosition::ElidedPathArgument, span) => { - (span, "'a, ".to_owned()) - } - (hir::LifetimeSuggestionPosition::ObjectDefault, span) => { - (span, "+ 'a".to_owned()) - } - }; + let lifetime_sugg = lifetime_ref.suggestion("'a"); let suggestions = vec![lifetime_sugg, new_param_sugg]; diag.span_label( diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index e4a4ec125a5c4..30f3face11b85 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -844,18 +844,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { impl<'hir, 'tcx> hir::intravisit::Visitor<'hir> for LifetimeReplaceVisitor<'tcx, '_> { fn visit_lifetime(&mut self, lt: &'hir hir::Lifetime) { if lt.res == self.needle { - let (pos, span) = lt.suggestion_position(); - let new_lt = &self.new_lt; - let sugg = match pos { - hir::LifetimeSuggestionPosition::Normal => format!("{new_lt}"), - hir::LifetimeSuggestionPosition::Ampersand => format!("{new_lt} "), - hir::LifetimeSuggestionPosition::ElidedPath => format!("<{new_lt}>"), - hir::LifetimeSuggestionPosition::ElidedPathArgument => { - format!("{new_lt}, ") - } - hir::LifetimeSuggestionPosition::ObjectDefault => format!("+ {new_lt}"), - }; - self.add_lt_suggs.push((span, sugg)); + self.add_lt_suggs.push(lt.suggestion(self.new_lt)); } } From 843708a32ee8e0c75a98b2b95927b348e3089b24 Mon Sep 17 00:00:00 2001 From: Urgau Date: Fri, 6 Sep 2024 13:48:17 +0200 Subject: [PATCH 097/189] Add missing `#[allow(missing_docs)]` on hack functions in alloc --- library/alloc/src/slice.rs | 2 ++ library/alloc/src/string.rs | 1 + library/std/src/io/buffered/bufreader.rs | 1 + 3 files changed, 4 insertions(+) diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index 9d70487032699..8cdba166c9dff 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -96,6 +96,7 @@ pub(crate) mod hack { // We shouldn't add inline attribute to this since this is used in // `vec!` macro mostly and causes perf regression. See #71204 for // discussion and perf results. + #[allow(missing_docs)] pub fn into_vec(b: Box<[T], A>) -> Vec { unsafe { let len = b.len(); @@ -105,6 +106,7 @@ pub(crate) mod hack { } #[cfg(not(no_global_oom_handling))] + #[allow(missing_docs)] #[inline] pub fn to_vec(s: &[T], alloc: A) -> Vec { T::to_vec(s, alloc) diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index bc8b7e24bf12b..05617669ed231 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -508,6 +508,7 @@ impl String { // NB see the slice::hack module in slice.rs for more information #[inline] #[cfg(test)] + #[allow(missing_docs)] pub fn from_str(_: &str) -> String { panic!("not available with cfg(test)"); } diff --git a/library/std/src/io/buffered/bufreader.rs b/library/std/src/io/buffered/bufreader.rs index cf226bd28d005..035afbb8368b4 100644 --- a/library/std/src/io/buffered/bufreader.rs +++ b/library/std/src/io/buffered/bufreader.rs @@ -267,6 +267,7 @@ impl BufReader { // This is only used by a test which asserts that the initialization-tracking is correct. #[cfg(test)] impl BufReader { + #[allow(missing_docs)] pub fn initialized(&self) -> usize { self.buf.initialized() } From 97df8fb7ecce4ff77d1da199742a822dfddeac2f Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Wed, 21 Aug 2024 18:21:39 +0200 Subject: [PATCH 098/189] Fix default/minimum deployment target for Aarch64 simulator targets The minimum that `rustc` encoded did not match the version in Clang, and that meant that that when linking, we ended up bumping the version. Specifically, this sets the correct deployment target of the following simulator and Mac Catalyst targets: - `aarch64-apple-ios-sim` from 10.0 to 14.0 - `aarch64-apple-tvos-sim` from 10.0 to 14.0 - `aarch64-apple-watchos-sim` from 5.0 to 7.0 - `aarch64-apple-ios-macabi` from 13.1 to 14.0 I have chosen to not document the simulator target versions in the platform support docs, as it is fundamentally uninteresting; the normal targets (e.g. `aarch64-apple-ios`, `aarch64-apple-tvos`) still have the same deployment target as before, and that's what developers should actually target. --- .../rustc_target/src/spec/base/apple/mod.rs | 10 +++++-- .../src/platform-support/apple-ios-macabi.md | 2 +- .../src/platform-support/arm64e-apple-ios.md | 2 +- .../run-make/apple-deployment-target/rmake.rs | 28 +++++++++++-------- 4 files changed, 26 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs index b1fe49f76caa3..5da47322b92a8 100644 --- a/compiler/rustc_target/src/spec/base/apple/mod.rs +++ b/compiler/rustc_target/src/spec/base/apple/mod.rs @@ -323,12 +323,18 @@ fn deployment_target(os: &str, arch: Arch, abi: TargetAbi) -> (u16, u8, u8) { }; // On certain targets it makes sense to raise the minimum OS version. + // + // This matches what LLVM does, see: + // let min = match (os, arch, abi) { - // Use 11.0 on Aarch64 as that's the earliest version with M1 support. ("macos", Arch::Arm64 | Arch::Arm64e, _) => (11, 0, 0), - ("ios", Arch::Arm64e, _) => (14, 0, 0), + ("ios", Arch::Arm64 | Arch::Arm64e, TargetAbi::MacCatalyst) => (14, 0, 0), + ("ios", Arch::Arm64 | Arch::Arm64e, TargetAbi::Simulator) => (14, 0, 0), + ("ios", Arch::Arm64e, TargetAbi::Normal) => (14, 0, 0), // Mac Catalyst defaults to 13.1 in Clang. ("ios", _, TargetAbi::MacCatalyst) => (13, 1, 0), + ("tvos", Arch::Arm64 | Arch::Arm64e, TargetAbi::Simulator) => (14, 0, 0), + ("watchos", Arch::Arm64 | Arch::Arm64e, TargetAbi::Simulator) => (7, 0, 0), _ => os_min, }; diff --git a/src/doc/rustc/src/platform-support/apple-ios-macabi.md b/src/doc/rustc/src/platform-support/apple-ios-macabi.md index 678630873b135..a54656190d1f3 100644 --- a/src/doc/rustc/src/platform-support/apple-ios-macabi.md +++ b/src/doc/rustc/src/platform-support/apple-ios-macabi.md @@ -24,7 +24,7 @@ environment variable. ### OS version -The minimum supported version is iOS 13.1. +The minimum supported version is iOS 13.1 on x86 and 14.0 on Aarch64. This can be raised per-binary by changing the deployment target. `rustc` respects the common environment variables used by Xcode to do so, in this diff --git a/src/doc/rustc/src/platform-support/arm64e-apple-ios.md b/src/doc/rustc/src/platform-support/arm64e-apple-ios.md index 3c878f7250e97..fc4ec5e373fb0 100644 --- a/src/doc/rustc/src/platform-support/arm64e-apple-ios.md +++ b/src/doc/rustc/src/platform-support/arm64e-apple-ios.md @@ -2,7 +2,7 @@ **Tier: 3** -ARM64e iOS (12.0+) +ARM64e iOS (14.0+) ## Target maintainers diff --git a/tests/run-make/apple-deployment-target/rmake.rs b/tests/run-make/apple-deployment-target/rmake.rs index b2d1af65177ef..230f33a8d7867 100644 --- a/tests/run-make/apple-deployment-target/rmake.rs +++ b/tests/run-make/apple-deployment-target/rmake.rs @@ -55,11 +55,8 @@ fn main() { rustc().env(env_var, example_version).run(); minos("foo.o", example_version); - // FIXME(madsmtm): Doesn't work on Mac Catalyst and the simulator. - if !target().contains("macabi") && !target().contains("sim") { - rustc().env_remove(env_var).run(); - minos("foo.o", default_version); - } + rustc().env_remove(env_var).run(); + minos("foo.o", default_version); }); // Test that version makes it to the linker when linking dylibs. @@ -105,8 +102,18 @@ fn main() { rustc }; - // FIXME(madsmtm): Doesn't work on watchOS for some reason? - if !target().contains("watchos") { + // FIXME(madsmtm): Xcode's version of Clang seems to require a minimum + // version of 9.0 on aarch64-apple-watchos for some reason? Which is + // odd, because the first Aarch64 watch was Apple Watch Series 4, + // which runs on as low as watchOS 5.0. + // + // You can see Clang's behaviour by running: + // ``` + // echo "int main() { return 0; }" > main.c + // xcrun --sdk watchos clang --target=aarch64-apple-watchos main.c + // vtool -show a.out + // ``` + if target() != "aarch64-apple-watchos" { rustc().env(env_var, example_version).run(); minos("foo", example_version); @@ -148,10 +155,7 @@ fn main() { rustc().env(env_var, higher_example_version).run(); minos("foo.o", higher_example_version); - // FIXME(madsmtm): Doesn't work on Mac Catalyst and the simulator. - if !target().contains("macabi") && !target().contains("sim") { - rustc().env_remove(env_var).run(); - minos("foo.o", default_version); - } + rustc().env_remove(env_var).run(); + minos("foo.o", default_version); }); } From dd35398545006f5ad4da8fc2ef0190c55ffda29c Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Wed, 21 Aug 2024 17:23:50 +0200 Subject: [PATCH 099/189] Pass deployment target when linking with cc on Apple targets When linking macOS targets with cc, pass the `-mmacosx-version-min=.` option to specify the desired deployment target. Also, no longer pass `-m32`/`-m64`, these are redundant since we already pass `-arch`. When linking with cc on other Apple targets, always pass `-target`. (We assume for these targets that cc => clang). --- .../rustc_target/src/spec/base/apple/mod.rs | 30 ++++++++++++++++++- .../src/spec/targets/i686_apple_darwin.rs | 6 ++-- .../src/spec/targets/x86_64_apple_darwin.rs | 5 ++-- .../src/spec/targets/x86_64h_apple_darwin.rs | 3 +- .../run-make/apple-deployment-target/rmake.rs | 10 +++---- 5 files changed, 38 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs index b1fe49f76caa3..d2886a89b53aa 100644 --- a/compiler/rustc_target/src/spec/base/apple/mod.rs +++ b/compiler/rustc_target/src/spec/base/apple/mod.rs @@ -168,7 +168,26 @@ fn pre_link_args(os: &'static str, arch: Arch, abi: TargetAbi) -> LinkArgs { ["-platform_version".into(), platform_name, min_version, sdk_version].into_iter(), ); - if abi != TargetAbi::MacCatalyst { + // We need to communicate four things to the C compiler to be able to link: + // - The architecture. + // - The operating system (and that it's an Apple platform). + // - The deployment target. + // - The environment / ABI. + // + // We'd like to use `-target` everywhere, since that can uniquely + // communicate all of these, but that doesn't work on GCC, and since we + // don't know whether the `cc` compiler is Clang, GCC, or something else, + // we fall back to other options that also work on GCC when compiling for + // macOS. + // + // Targets other than macOS are ill-supported by GCC (it doesn't even + // support e.g. `-miphoneos-version-min`), so in those cases we can fairly + // safely use `-target`. See also the following, where it is made explicit + // that the recommendation by LLVM developers is to use `-target`: + // + if os == "macos" { + // `-arch` communicates the architecture. + // // CC forwards the `-arch` to the linker, so we use the same value // here intentionally. add_link_args( @@ -176,6 +195,15 @@ fn pre_link_args(os: &'static str, arch: Arch, abi: TargetAbi) -> LinkArgs { LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-arch", arch.ld_arch()], ); + // The presence of `-mmacosx-version-min` makes CC default to macOS, + // and it sets the deployment target. + let (major, minor, patch) = deployment_target(os, arch, abi); + let opt = format!("-mmacosx-version-min={major}.{minor}.{patch}").into(); + add_link_args_iter(&mut args, LinkerFlavor::Darwin(Cc::Yes, Lld::No), [opt].into_iter()); + // macOS has no environment, so with these two, we've told CC all the + // desired parameters. + // + // We avoid `-m32`/`-m64`, as this is already encoded by `-arch`. } else { add_link_args_iter( &mut args, diff --git a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs index 67afe35bee402..3e27f1f899b72 100644 --- a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs @@ -1,10 +1,8 @@ use crate::spec::base::apple::{base, Arch, TargetAbi}; -use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, TargetOptions}; +use crate::spec::{FramePointer, Target, TargetOptions}; pub(crate) fn target() -> Target { - let (mut opts, llvm_target, arch) = base("macos", Arch::I686, TargetAbi::Normal); - opts.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m32"]); - + let (opts, llvm_target, arch) = base("macos", Arch::I686, TargetAbi::Normal); Target { llvm_target, metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs index e7f14aa920963..4304dfc3f682d 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs @@ -1,9 +1,8 @@ use crate::spec::base::apple::{base, Arch, TargetAbi}; -use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet, Target, TargetOptions}; +use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; pub(crate) fn target() -> Target { - let (mut opts, llvm_target, arch) = base("macos", Arch::X86_64, TargetAbi::Normal); - opts.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]); + let (opts, llvm_target, arch) = base("macos", Arch::X86_64, TargetAbi::Normal); Target { llvm_target, metadata: crate::spec::TargetMetadata { diff --git a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs index f44bc660a62f9..9fb5a46187a31 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs @@ -1,11 +1,10 @@ use crate::spec::base::apple::{base, Arch, TargetAbi}; -use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet, Target, TargetOptions}; +use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions}; pub(crate) fn target() -> Target { let (mut opts, llvm_target, arch) = base("macos", Arch::X86_64h, TargetAbi::Normal); opts.max_atomic_width = Some(128); opts.frame_pointer = FramePointer::Always; - opts.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]); opts.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::LEAK | SanitizerSet::THREAD; diff --git a/tests/run-make/apple-deployment-target/rmake.rs b/tests/run-make/apple-deployment-target/rmake.rs index b2d1af65177ef..304b008563127 100644 --- a/tests/run-make/apple-deployment-target/rmake.rs +++ b/tests/run-make/apple-deployment-target/rmake.rs @@ -81,9 +81,8 @@ fn main() { rustc().env(env_var, example_version).run(); minos("libfoo.dylib", example_version); - // FIXME(madsmtm): Deployment target is not currently passed properly to linker - // rustc().env_remove(env_var).run(); - // minos("libfoo.dylib", default_version); + rustc().env_remove(env_var).run(); + minos("libfoo.dylib", default_version); // Test with ld64 instead @@ -110,9 +109,8 @@ fn main() { rustc().env(env_var, example_version).run(); minos("foo", example_version); - // FIXME(madsmtm): Deployment target is not currently passed properly to linker - // rustc().env_remove(env_var).run(); - // minos("foo", default_version); + rustc().env_remove(env_var).run(); + minos("foo", default_version); } // Test with ld64 instead From 65c70900ceda1c276c8eef1dad4e2c4f7a0756d0 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 9 Sep 2024 14:42:03 +0200 Subject: [PATCH 100/189] union padding computation: add fast-path for ZST Also avoid even tracking empty ranges, and add fast-path for arrays of scalars --- .../src/interpret/validity.rs | 39 +++++++++++++------ compiler/rustc_middle/src/ty/sty.rs | 1 + src/tools/miri/tests/pass/arrays.rs | 15 +++++++ 3 files changed, 43 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 806ebb9dfed4d..fb24f983ca9c3 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -220,6 +220,10 @@ pub struct RangeSet(Vec<(Size, Size)>); impl RangeSet { fn add_range(&mut self, offset: Size, size: Size) { + if size.bytes() == 0 { + // No need to track empty ranges. + return; + } let v = &mut self.0; // We scan for a partition point where the left partition is all the elements that end // strictly before we start. Those are elements that are too "low" to merge with us. @@ -938,42 +942,53 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { let layout_cx = LayoutCx { tcx: *ecx.tcx, param_env: ecx.param_env }; return M::cached_union_data_range(ecx, layout.ty, || { let mut out = RangeSet(Vec::new()); - union_data_range_(&layout_cx, layout, Size::ZERO, &mut out); + union_data_range_uncached(&layout_cx, layout, Size::ZERO, &mut out); out }); /// Helper for recursive traversal: add data ranges of the given type to `out`. - fn union_data_range_<'tcx>( + fn union_data_range_uncached<'tcx>( cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, layout: TyAndLayout<'tcx>, base_offset: Size, out: &mut RangeSet, ) { + // If this is a ZST, we don't contain any data. In particular, this helps us to quickly + // skip over huge arrays of ZST. + if layout.is_zst() { + return; + } // Just recursively add all the fields of everything to the output. match &layout.fields { FieldsShape::Primitive => { out.add_range(base_offset, layout.size); } &FieldsShape::Union(fields) => { - // Currently, all fields start at offset 0. + // Currently, all fields start at offset 0 (relative to `base_offset`). for field in 0..fields.get() { let field = layout.field(cx, field); - union_data_range_(cx, field, base_offset, out); + union_data_range_uncached(cx, field, base_offset, out); } } &FieldsShape::Array { stride, count } => { let elem = layout.field(cx, 0); - for idx in 0..count { - // This repeats the same computation for every array elements... but the alternative - // is to allocate temporary storage for a dedicated `out` set for the array element, - // and replicating that N times. Is that better? - union_data_range_(cx, elem, base_offset + idx * stride, out); + + // Fast-path for large arrays of simple types that do not contain any padding. + if elem.abi.is_scalar() { + out.add_range(base_offset, elem.size * count); + } else { + for idx in 0..count { + // This repeats the same computation for every array element... but the alternative + // is to allocate temporary storage for a dedicated `out` set for the array element, + // and replicating that N times. Is that better? + union_data_range_uncached(cx, elem, base_offset + idx * stride, out); + } } } FieldsShape::Arbitrary { offsets, .. } => { for (field, &offset) in offsets.iter_enumerated() { let field = layout.field(cx, field.as_usize()); - union_data_range_(cx, field, base_offset + offset, out); + union_data_range_uncached(cx, field, base_offset + offset, out); } } } @@ -985,7 +1000,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { Variants::Multiple { variants, .. } => { for variant in variants.indices() { let variant = layout.for_variant(cx, variant); - union_data_range_(cx, variant, base_offset, out); + union_data_range_uncached(cx, variant, base_offset, out); } } } @@ -1185,7 +1200,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, // This is the size in bytes of the whole array. (This checks for overflow.) let size = layout.size * len; // If the size is 0, there is nothing to check. - // (`size` can only be 0 of `len` is 0, and empty arrays are always valid.) + // (`size` can only be 0 if `len` is 0, and empty arrays are always valid.) if size == Size::ZERO { return Ok(()); } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 1f4f2c62d7084..730ba265b19d6 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1136,6 +1136,7 @@ impl<'tcx> Ty<'tcx> { } /// Tests if this is any kind of primitive pointer type (reference, raw pointer, fn pointer). + /// `Box` is *not* considered a pointer here! #[inline] pub fn is_any_ptr(self) -> bool { self.is_ref() || self.is_unsafe_ptr() || self.is_fn_ptr() diff --git a/src/tools/miri/tests/pass/arrays.rs b/src/tools/miri/tests/pass/arrays.rs index 61b44453e9bd9..b0c6f54cab87c 100644 --- a/src/tools/miri/tests/pass/arrays.rs +++ b/src/tools/miri/tests/pass/arrays.rs @@ -61,6 +61,20 @@ fn debug() { println!("{:?}", array); } +fn huge_zst() { + fn id(x: T) -> T { x } + + // A "huge" zero-sized array. Make sure we don't loop over it in any part of Miri. + let val = [(); usize::MAX]; + id(val); // make a copy + + let val = [val; 2]; + id(val); + + // Also wrap it in a union (which, in particular, hits the logic for computing union padding). + let _copy = std::mem::MaybeUninit::new(val); +} + fn main() { assert_eq!(empty_array(), []); assert_eq!(index_unsafe(), 20); @@ -73,4 +87,5 @@ fn main() { from(); eq(); debug(); + huge_zst(); } From a1a8627dd789bd7444c78b7a5d360328709a54eb Mon Sep 17 00:00:00 2001 From: Urgau Date: Mon, 9 Sep 2024 13:43:25 +0200 Subject: [PATCH 101/189] Allow `missing_docs` lint on the generated test harness --- compiler/rustc_builtin_macros/src/test_harness.rs | 4 +++- compiler/rustc_span/src/symbol.rs | 1 + tests/pretty/tests-are-sorted.pp | 1 + tests/ui/lint/lint-missing-doc-test.rs | 5 +++++ 4 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 tests/ui/lint/lint-missing-doc-test.rs diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index a9e4434581163..a694d3b8c2857 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -326,6 +326,8 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { let main_attr = ecx.attr_word(sym::rustc_main, sp); // #[coverage(off)] let coverage_attr = ecx.attr_nested_word(sym::coverage, sym::off, sp); + // #[allow(missing_docs)] + let missing_docs_attr = ecx.attr_nested_word(sym::allow, sym::missing_docs, sp); // pub fn main() { ... } let main_ret_ty = ecx.ty(sp, ast::TyKind::Tup(ThinVec::new())); @@ -355,7 +357,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { let main = P(ast::Item { ident: main_id, - attrs: thin_vec![main_attr, coverage_attr], + attrs: thin_vec![main_attr, coverage_attr, missing_docs_attr], id: ast::DUMMY_NODE_ID, kind: main, vis: ast::Visibility { span: sp, kind: ast::VisibilityKind::Public, tokens: None }, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 36b31d10c4d29..db4f44ebcbc33 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1235,6 +1235,7 @@ symbols! { mir_unwind_unreachable, mir_variant, miri, + missing_docs, mmx_reg, modifiers, module, diff --git a/tests/pretty/tests-are-sorted.pp b/tests/pretty/tests-are-sorted.pp index 816cd5a5c072c..a4b15dde4530e 100644 --- a/tests/pretty/tests-are-sorted.pp +++ b/tests/pretty/tests-are-sorted.pp @@ -83,6 +83,7 @@ fn a_test() {} #[rustc_main] #[coverage(off)] +#[allow(missing_docs)] pub fn main() -> () { extern crate test; test::test_main_static(&[&a_test, &m_test, &z_test]) diff --git a/tests/ui/lint/lint-missing-doc-test.rs b/tests/ui/lint/lint-missing-doc-test.rs new file mode 100644 index 0000000000000..93d4e4a44e928 --- /dev/null +++ b/tests/ui/lint/lint-missing-doc-test.rs @@ -0,0 +1,5 @@ +//! This test checks that denying the missing_docs lint does not trigger +//! on the generated test harness. + +//@ check-pass +//@ compile-flags: --test -Dmissing_docs From 0f9cb070bc312df3c9cadd358efaa1d1efe4a9d0 Mon Sep 17 00:00:00 2001 From: Urgau Date: Mon, 9 Sep 2024 14:07:36 +0200 Subject: [PATCH 102/189] Add test about missing docs at crate level --- tests/ui/lint/lint-missing-doc-crate.rs | 4 ++++ tests/ui/lint/lint-missing-doc-crate.stderr | 10 ++++++++++ 2 files changed, 14 insertions(+) create mode 100644 tests/ui/lint/lint-missing-doc-crate.rs create mode 100644 tests/ui/lint/lint-missing-doc-crate.stderr diff --git a/tests/ui/lint/lint-missing-doc-crate.rs b/tests/ui/lint/lint-missing-doc-crate.rs new file mode 100644 index 0000000000000..afda73cbc603a --- /dev/null +++ b/tests/ui/lint/lint-missing-doc-crate.rs @@ -0,0 +1,4 @@ +// This test checks that we lint on the crate when it's missing a documentation. +// +//@ compile-flags: -Dmissing-docs --crate-type=lib +//~ ERROR missing documentation for the crate diff --git a/tests/ui/lint/lint-missing-doc-crate.stderr b/tests/ui/lint/lint-missing-doc-crate.stderr new file mode 100644 index 0000000000000..8efd3a17263fe --- /dev/null +++ b/tests/ui/lint/lint-missing-doc-crate.stderr @@ -0,0 +1,10 @@ +error: missing documentation for the crate + --> $DIR/lint-missing-doc-crate.rs:4:47 + | +LL | + | ^ + | + = note: requested on the command line with `-D missing-docs` + +error: aborting due to 1 previous error + From 383f50622774357b80eb9f0904f22fe89552a562 Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Mon, 9 Sep 2024 13:29:47 +0000 Subject: [PATCH 103/189] adapt a test for llvm 20 No functional changes intended. --- tests/codegen/naked-asan.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/codegen/naked-asan.rs b/tests/codegen/naked-asan.rs index a45b95780f793..ac36018eed3a1 100644 --- a/tests/codegen/naked-asan.rs +++ b/tests/codegen/naked-asan.rs @@ -20,3 +20,4 @@ pub extern "x86-interrupt" fn page_fault_handler(_: u64, _: u64) { // CHECK: #[[ATTRS]] = // CHECK-NOT: sanitize_address +// CHECK: !llvm.module.flags From 0a70924c2160c8f93a446328e207a1983e62596a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 9 Sep 2024 16:11:17 +0200 Subject: [PATCH 104/189] fix UB in a test also add an explicit test for the fact that a Option has padding when it is None --- library/core/tests/mem.rs | 7 ++++++- .../miri/tests/fail/uninit/padding-enum.rs | 2 +- .../miri/tests/fail/uninit/padding-enum.stderr | 2 +- .../miri/tests/fail/uninit/padding-wide-ptr.rs | 18 ++++++++++++++++++ .../tests/fail/uninit/padding-wide-ptr.stderr | 15 +++++++++++++++ 5 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 src/tools/miri/tests/fail/uninit/padding-wide-ptr.rs create mode 100644 src/tools/miri/tests/fail/uninit/padding-wide-ptr.stderr diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs index b7eee10ec3f9c..f3b4387f6a898 100644 --- a/library/core/tests/mem.rs +++ b/library/core/tests/mem.rs @@ -773,15 +773,20 @@ fn offset_of_addr() { #[test] fn const_maybe_uninit_zeroed() { // Sanity check for `MaybeUninit::zeroed` in a realistic const situation (plugin array term) + + // It is crucial that this type has no padding! #[repr(C)] struct Foo { - a: Option<&'static str>, + a: Option<&'static u8>, b: Bar, c: f32, + _pad: u32, d: *const u8, } + #[repr(C)] struct Bar(usize); + struct FooPtr(*const Foo); unsafe impl Sync for FooPtr {} diff --git a/src/tools/miri/tests/fail/uninit/padding-enum.rs b/src/tools/miri/tests/fail/uninit/padding-enum.rs index 0ab9be275815d..3852ac5c477d5 100644 --- a/src/tools/miri/tests/fail/uninit/padding-enum.rs +++ b/src/tools/miri/tests/fail/uninit/padding-enum.rs @@ -18,6 +18,6 @@ fn main() { unsafe { // Turns out the discriminant is (currently) stored // in the 2nd pointer, so the first half is padding. let c = &p as *const _ as *const u8; - let _val = *c.add(0); // Get the padding byte. + let _val = *c.add(0); // Get a padding byte. //~^ERROR: uninitialized } } diff --git a/src/tools/miri/tests/fail/uninit/padding-enum.stderr b/src/tools/miri/tests/fail/uninit/padding-enum.stderr index a507a5d49bc2c..c571f18874076 100644 --- a/src/tools/miri/tests/fail/uninit/padding-enum.stderr +++ b/src/tools/miri/tests/fail/uninit/padding-enum.stderr @@ -1,7 +1,7 @@ error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory --> $DIR/padding-enum.rs:LL:CC | -LL | let _val = *c.add(0); // Get the padding byte. +LL | let _val = *c.add(0); // Get a padding byte. | ^^^^^^^^^ using uninitialized data, but this operation requires initialized memory | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior diff --git a/src/tools/miri/tests/fail/uninit/padding-wide-ptr.rs b/src/tools/miri/tests/fail/uninit/padding-wide-ptr.rs new file mode 100644 index 0000000000000..0403a9caba66d --- /dev/null +++ b/src/tools/miri/tests/fail/uninit/padding-wide-ptr.rs @@ -0,0 +1,18 @@ +use std::mem; + +// If this is `None`, the metadata becomes padding. +type T = Option<&'static str>; + +fn main() { unsafe { + let mut p: mem::MaybeUninit = mem::MaybeUninit::zeroed(); + // The copy when `T` is returned from `transmute` should destroy padding + // (even when we use `write_unaligned`, which under the hood uses an untyped copy). + p.as_mut_ptr().write_unaligned(mem::transmute((0usize, 0usize))); + // Null epresents `None`. + assert!(matches!(*p.as_ptr(), None)); + + // The second part, with the length, becomes padding. + let c = &p as *const _ as *const u8; + let _val = *c.add(mem::size_of::<*const u8>()); // Get a padding byte. + //~^ERROR: uninitialized +} } diff --git a/src/tools/miri/tests/fail/uninit/padding-wide-ptr.stderr b/src/tools/miri/tests/fail/uninit/padding-wide-ptr.stderr new file mode 100644 index 0000000000000..0da72550b2e08 --- /dev/null +++ b/src/tools/miri/tests/fail/uninit/padding-wide-ptr.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory + --> $DIR/padding-wide-ptr.rs:LL:CC + | +LL | let _val = *c.add(mem::size_of::<*const u8>()); // Get a padding byte. + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/padding-wide-ptr.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + From 19b8f9e17cf86cf83bd1fc742cf159605d0504dd Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 9 Sep 2024 18:47:38 +0300 Subject: [PATCH 105/189] use verbose flag as a default value for `rust.verbose-tests` Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/config.rs | 3 +++ src/bootstrap/src/core/config/tests.rs | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 68b42305fdcc8..de861c42c4c4e 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1600,6 +1600,9 @@ impl Config { config.verbose = cmp::max(config.verbose, flags.verbose as usize); + // Verbose flag is a good default for `rust.verbose-tests`. + config.verbose_tests = config.is_verbose(); + if let Some(install) = toml.install { let Install { prefix, sysconfdir, docdir, bindir, libdir, mandir, datadir } = install; config.prefix = prefix.map(PathBuf::from); diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs index 219c5a6ec914e..f54a5d3b5125d 100644 --- a/src/bootstrap/src/core/config/tests.rs +++ b/src/bootstrap/src/core/config/tests.rs @@ -317,3 +317,12 @@ fn order_of_clippy_rules() { assert_eq!(expected, actual); } + +#[test] +fn verbose_tests_default_value() { + let config = Config::parse(Flags::parse(&["build".into(), "compiler".into()])); + assert_eq!(config.verbose_tests, false); + + let config = Config::parse(Flags::parse(&["build".into(), "compiler".into(), "-v".into()])); + assert_eq!(config.verbose_tests, true); +} From bc70fa2f223181dc6bf20c1da8f986a46dac3ae5 Mon Sep 17 00:00:00 2001 From: okaneco <47607823+okaneco@users.noreply.github.com> Date: Mon, 9 Sep 2024 11:46:44 -0400 Subject: [PATCH 106/189] Stabilize `char::MIN` --- library/core/src/char/methods.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 41a19665779b6..113a2d6a2b171 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -15,7 +15,6 @@ impl char { /// for you: /// /// ``` - /// #![feature(char_min)] /// let dist = u32::from(char::MAX) - u32::from(char::MIN); /// let size = (char::MIN..=char::MAX).count() as u32; /// assert!(size < dist); @@ -29,7 +28,6 @@ impl char { /// # Examples /// /// ``` - /// #![feature(char_min)] /// # fn something_which_returns_char() -> char { 'a' } /// let c: char = something_which_returns_char(); /// assert!(char::MIN <= c); @@ -37,7 +35,7 @@ impl char { /// let value_at_min = u32::from(char::MIN); /// assert_eq!(char::from_u32(value_at_min), Some('\0')); /// ``` - #[unstable(feature = "char_min", issue = "114298")] + #[stable(feature = "char_min", since = "CURRENT_RUSTC_VERSION")] pub const MIN: char = '\0'; /// The highest valid code point a `char` can have, `'\u{10FFFF}'`. @@ -48,7 +46,6 @@ impl char { /// for you: /// /// ``` - /// #![feature(char_min)] /// let dist = u32::from(char::MAX) - u32::from(char::MIN); /// let size = (char::MIN..=char::MAX).count() as u32; /// assert!(size < dist); From 13ea104798dfdb31613963d49be43e615c6f6dfe Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 9 Sep 2024 18:56:37 +0300 Subject: [PATCH 107/189] update `rust.verbose-tests` doc in `config.example.toml` Signed-off-by: onur-ozkan --- config.example.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.example.toml b/config.example.toml index e9433c9c9bd08..17fe9be7d567f 100644 --- a/config.example.toml +++ b/config.example.toml @@ -641,7 +641,7 @@ #stack-protector = "none" # Prints each test name as it is executed, to help debug issues in the test harness itself. -#verbose-tests = false +#verbose-tests = if is_verbose { true } else { false } # Flag indicating whether tests are compiled with optimizations (the -O flag). #optimize-tests = true From 8b052eaad15d77e96a95b6ff9e89ebfd20ab1e55 Mon Sep 17 00:00:00 2001 From: rustbot <47979223+rustbot@users.noreply.github.com> Date: Mon, 9 Sep 2024 13:00:45 -0400 Subject: [PATCH 108/189] Update books --- src/doc/edition-guide | 2 +- src/doc/embedded-book | 2 +- src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- src/doc/rustc-dev-guide | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/doc/edition-guide b/src/doc/edition-guide index eeba2cb9c37ab..b3ca7ade0f87d 160000 --- a/src/doc/edition-guide +++ b/src/doc/edition-guide @@ -1 +1 @@ -Subproject commit eeba2cb9c37ab74118a4fb5e5233f7397e4a91f8 +Subproject commit b3ca7ade0f87d7e3fb538776defc5b2cc4188172 diff --git a/src/doc/embedded-book b/src/doc/embedded-book index ff5d61d56f11e..dbae36bf3f841 160000 --- a/src/doc/embedded-book +++ b/src/doc/embedded-book @@ -1 +1 @@ -Subproject commit ff5d61d56f11e1986bfa9652c6aff7731576c37d +Subproject commit dbae36bf3f8410aa4313b3bad42e374735d48a9d diff --git a/src/doc/reference b/src/doc/reference index 0668397076da3..687faf9958c52 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 0668397076da350c404dadcf07b6cbc433ad3743 +Subproject commit 687faf9958c52116d003b41dfd29cc1cf44f5311 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 859786c5bc993..c79ec345f08a1 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 859786c5bc99301bbc22fc631a5c2b341860da08 +Subproject commit c79ec345f08a1e94494cdc8c999709a90203fd88 diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide index fa928a6d19e16..0ed9229f5b6f7 160000 --- a/src/doc/rustc-dev-guide +++ b/src/doc/rustc-dev-guide @@ -1 +1 @@ -Subproject commit fa928a6d19e1666d8d811dfe3fd35cdad3b4e459 +Subproject commit 0ed9229f5b6f7824b333beabd7e3d5ba4b9bd971 From 99cad123edfa915723a5e5c0537d43b71f2cc0c5 Mon Sep 17 00:00:00 2001 From: "James C. Wise" Date: Mon, 9 Sep 2024 13:13:45 -0400 Subject: [PATCH 109/189] Fix slice::first_mut docs pointer -> reference --- library/core/src/slice/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 166189f4b6cf3..fb732f82989c0 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -156,7 +156,7 @@ impl [T] { if let [first, ..] = self { Some(first) } else { None } } - /// Returns a mutable pointer to the first element of the slice, or `None` if it is empty. + /// Returns a mutable reference to the first element of the slice, or `None` if it is empty. /// /// # Examples /// From 05043a370a77f8647b5fa609488dbdfebb71d1a4 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 9 Sep 2024 20:17:34 +0300 Subject: [PATCH 110/189] add `git_merge_commit_email` into `GitConfig` Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/config.rs | 1 + src/tools/build_helper/src/git.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 68b42305fdcc8..646e76d46b680 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -2509,6 +2509,7 @@ impl Config { GitConfig { git_repository: &self.stage0_metadata.config.git_repository, nightly_branch: &self.stage0_metadata.config.nightly_branch, + git_merge_commit_email: &self.stage0_metadata.config.git_merge_commit_email, } } diff --git a/src/tools/build_helper/src/git.rs b/src/tools/build_helper/src/git.rs index cc48a8964a372..98e5b7a328eb9 100644 --- a/src/tools/build_helper/src/git.rs +++ b/src/tools/build_helper/src/git.rs @@ -4,6 +4,7 @@ use std::process::{Command, Stdio}; pub struct GitConfig<'a> { pub git_repository: &'a str, pub nightly_branch: &'a str, + pub git_merge_commit_email: &'a str, } /// Runs a command and returns the output From dc9c5f251c06c2c0193aff779a5074cff3d233ee Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 9 Sep 2024 20:18:06 +0300 Subject: [PATCH 111/189] implement `build_helper::git::get_closest_merge_commit` Compare to `get_git_merge_base`, this doesn't require configuring the upstream remote. Signed-off-by: onur-ozkan --- src/tools/build_helper/src/git.rs | 40 ++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/src/tools/build_helper/src/git.rs b/src/tools/build_helper/src/git.rs index 98e5b7a328eb9..7da3c9de60c45 100644 --- a/src/tools/build_helper/src/git.rs +++ b/src/tools/build_helper/src/git.rs @@ -1,4 +1,4 @@ -use std::path::Path; +use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; pub struct GitConfig<'a> { @@ -96,10 +96,7 @@ pub fn updated_master_branch( Err("Cannot find any suitable upstream master branch".to_owned()) } -pub fn get_git_merge_base( - config: &GitConfig<'_>, - git_dir: Option<&Path>, -) -> Result { +fn get_git_merge_base(config: &GitConfig<'_>, git_dir: Option<&Path>) -> Result { let updated_master = updated_master_branch(config, git_dir)?; let mut git = Command::new("git"); if let Some(git_dir) = git_dir { @@ -108,6 +105,37 @@ pub fn get_git_merge_base( Ok(output_result(git.arg("merge-base").arg(&updated_master).arg("HEAD"))?.trim().to_owned()) } +/// Resolves the closest merge commit by the given `author` and `target_paths`. +/// +/// If it fails to find the commit from upstream using `git merge-base`, fallbacks to HEAD. +pub fn get_closest_merge_commit( + git_dir: Option<&Path>, + config: &GitConfig<'_>, + target_paths: &[PathBuf], +) -> Result { + let mut git = Command::new("git"); + + if let Some(git_dir) = git_dir { + git.current_dir(git_dir); + } + + let merge_base = get_git_merge_base(config, git_dir).unwrap_or_else(|_| "HEAD".into()); + + git.args([ + "rev-list", + &format!("--author={}", config.git_merge_commit_email), + "-n1", + "--first-parent", + &merge_base, + ]); + + if !target_paths.is_empty() { + git.arg("--").args(target_paths); + } + + Ok(output_result(&mut git)?.trim().to_owned()) +} + /// Returns the files that have been modified in the current branch compared to the master branch. /// The `extensions` parameter can be used to filter the files by their extension. /// Does not include removed files. @@ -117,7 +145,7 @@ pub fn get_git_modified_files( git_dir: Option<&Path>, extensions: &[&str], ) -> Result>, String> { - let merge_base = get_git_merge_base(config, git_dir)?; + let merge_base = get_closest_merge_commit(git_dir, config, &[])?; let mut git = Command::new("git"); if let Some(git_dir) = git_dir { From 9aa823cc6727fd4c68cf3fdc50478e47b5ef5989 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 9 Sep 2024 20:19:29 +0300 Subject: [PATCH 112/189] replace `get_closest_merge_base_commit` with `get_closest_merge_commit` Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/compile.rs | 14 ++++------- src/bootstrap/src/core/build_steps/llvm.rs | 4 ++-- src/bootstrap/src/core/build_steps/tool.rs | 7 +++--- src/bootstrap/src/core/config/config.rs | 20 ++++------------ src/bootstrap/src/utils/helpers.rs | 23 ------------------- 5 files changed, 15 insertions(+), 53 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 102c9fd255432..bb07d478f71aa 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -15,6 +15,7 @@ use std::path::{Path, PathBuf}; use std::process::Stdio; use std::{env, fs, str}; +use build_helper::git::get_closest_merge_commit; use serde_derive::Deserialize; use crate::core::build_steps::tool::SourceType; @@ -26,8 +27,7 @@ use crate::core::builder::{ use crate::core::config::{DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection}; use crate::utils::exec::command; use crate::utils::helpers::{ - self, exe, get_clang_cl_resource_dir, get_closest_merge_base_commit, is_debug_info, is_dylib, - symlink_dir, t, up_to_date, + self, exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, symlink_dir, t, up_to_date, }; use crate::{CLang, Compiler, DependencyType, GitRepo, Mode, LLVM_TOOLS}; @@ -127,13 +127,9 @@ impl Step for Std { // the `rust.download-rustc=true` option. let force_recompile = if builder.rust_info().is_managed_git_subrepository() && builder.download_rustc() { - let closest_merge_commit = get_closest_merge_base_commit( - Some(&builder.src), - &builder.config.git_config(), - &builder.config.stage0_metadata.config.git_merge_commit_email, - &[], - ) - .unwrap(); + let closest_merge_commit = + get_closest_merge_commit(Some(&builder.src), &builder.config.git_config(), &[]) + .unwrap(); // Check if `library` has changes (returns false otherwise) !t!(helpers::git(Some(&builder.src)) diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index 442638d32034b..94b03b1b1386b 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -16,6 +16,7 @@ use std::sync::OnceLock; use std::{env, io}; use build_helper::ci::CiEnv; +use build_helper::git::get_closest_merge_commit; use crate::core::builder::{Builder, RunConfig, ShouldRun, Step}; use crate::core::config::{Config, TargetSelection}; @@ -153,10 +154,9 @@ pub fn prebuilt_llvm_config(builder: &Builder<'_>, target: TargetSelection) -> L /// This retrieves the LLVM sha we *want* to use, according to git history. pub(crate) fn detect_llvm_sha(config: &Config, is_git: bool) -> String { let llvm_sha = if is_git { - helpers::get_closest_merge_base_commit( + get_closest_merge_commit( Some(&config.src), &config.git_config(), - &config.stage0_metadata.config.git_merge_commit_email, &[ config.src.join("src/llvm-project"), config.src.join("src/bootstrap/download-ci-llvm-stamp"), diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index 3c2d791c2090e..a437f829ba5a6 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -1,6 +1,8 @@ use std::path::PathBuf; use std::{env, fs}; +use build_helper::git::get_closest_merge_commit; + use crate::core::build_steps::compile; use crate::core::build_steps::toolstate::ToolState; use crate::core::builder; @@ -8,7 +10,7 @@ use crate::core::builder::{Builder, Cargo as CargoCommand, RunConfig, ShouldRun, use crate::core::config::TargetSelection; use crate::utils::channel::GitInfo; use crate::utils::exec::{command, BootstrapCommand}; -use crate::utils::helpers::{add_dylib_path, exe, get_closest_merge_base_commit, git, t}; +use crate::utils::helpers::{add_dylib_path, exe, git, t}; use crate::{gha, Compiler, Kind, Mode}; #[derive(Debug, Clone, Hash, PartialEq, Eq)] @@ -576,10 +578,9 @@ impl Step for Rustdoc { && target_compiler.stage > 0 && builder.rust_info().is_managed_git_subrepository() { - let commit = get_closest_merge_base_commit( + let commit = get_closest_merge_commit( Some(&builder.config.src), &builder.config.git_config(), - &builder.config.stage0_metadata.config.git_merge_commit_email, &[], ) .unwrap(); diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 646e76d46b680..9be4f59bfbba4 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -14,7 +14,7 @@ use std::sync::OnceLock; use std::{cmp, env, fs}; use build_helper::exit; -use build_helper::git::{output_result, GitConfig}; +use build_helper::git::{get_closest_merge_commit, output_result, GitConfig}; use serde::{Deserialize, Deserializer}; use serde_derive::Deserialize; @@ -24,7 +24,7 @@ pub use crate::core::config::flags::Subcommand; use crate::core::config::flags::{Color, Flags, Warnings}; use crate::utils::cache::{Interned, INTERNER}; use crate::utils::channel::{self, GitInfo}; -use crate::utils::helpers::{self, exe, get_closest_merge_base_commit, output, t}; +use crate::utils::helpers::{self, exe, output, t}; macro_rules! check_ci_llvm { ($name:expr) => { @@ -2686,13 +2686,7 @@ impl Config { // Look for a version to compare to based on the current commit. // Only commits merged by bors will have CI artifacts. - let commit = get_closest_merge_base_commit( - Some(&self.src), - &self.git_config(), - &self.stage0_metadata.config.git_merge_commit_email, - &[], - ) - .unwrap(); + let commit = get_closest_merge_commit(Some(&self.src), &self.git_config(), &[]).unwrap(); if commit.is_empty() { println!("ERROR: could not find commit hash for downloading rustc"); println!("HELP: maybe your repository history is too shallow?"); @@ -2783,13 +2777,7 @@ impl Config { ) -> Option { // Look for a version to compare to based on the current commit. // Only commits merged by bors will have CI artifacts. - let commit = get_closest_merge_base_commit( - Some(&self.src), - &self.git_config(), - &self.stage0_metadata.config.git_merge_commit_email, - &[], - ) - .unwrap(); + let commit = get_closest_merge_commit(Some(&self.src), &self.git_config(), &[]).unwrap(); if commit.is_empty() { println!("error: could not find commit hash for downloading components from CI"); println!("help: maybe your repository history is too shallow?"); diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs index a856c99ff55a5..beb3c5fb09842 100644 --- a/src/bootstrap/src/utils/helpers.rs +++ b/src/bootstrap/src/utils/helpers.rs @@ -10,7 +10,6 @@ use std::sync::OnceLock; use std::time::{Instant, SystemTime, UNIX_EPOCH}; use std::{env, fs, io, str}; -use build_helper::git::{get_git_merge_base, output_result, GitConfig}; use build_helper::util::fail; use crate::core::builder::Builder; @@ -523,28 +522,6 @@ pub fn git(source_dir: Option<&Path>) -> BootstrapCommand { git } -/// Returns the closest commit available from upstream for the given `author` and `target_paths`. -/// -/// If it fails to find the commit from upstream using `git merge-base`, fallbacks to HEAD. -pub fn get_closest_merge_base_commit( - source_dir: Option<&Path>, - config: &GitConfig<'_>, - author: &str, - target_paths: &[PathBuf], -) -> Result { - let mut git = git(source_dir); - - let merge_base = get_git_merge_base(config, source_dir).unwrap_or_else(|_| "HEAD".into()); - - git.args(["rev-list", &format!("--author={author}"), "-n1", "--first-parent", &merge_base]); - - if !target_paths.is_empty() { - git.arg("--").args(target_paths); - } - - Ok(output_result(git.as_command_mut())?.trim().to_owned()) -} - /// Sets the file times for a given file at `path`. pub fn set_file_times>(path: P, times: fs::FileTimes) -> io::Result<()> { // Windows requires file to be writable to modify file times. But on Linux CI the file does not From 667cf22f486cf16dfa1d26e7c4d670bce7293629 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 9 Sep 2024 20:31:58 +0300 Subject: [PATCH 113/189] bump download-ci-llvm-stamp Signed-off-by: onur-ozkan --- src/bootstrap/download-ci-llvm-stamp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp index 909015305015b..42cecbf5df9bb 100644 --- a/src/bootstrap/download-ci-llvm-stamp +++ b/src/bootstrap/download-ci-llvm-stamp @@ -1,4 +1,4 @@ Change this file to make users of the `download-ci-llvm` configuration download a new version of LLVM from CI, even if the LLVM submodule hasn’t changed. -Last change is for: https://github.com/rust-lang/rust/pull/129116 +Last change is for: https://github.com/rust-lang/rust/pull/129788 From 720bd0dd6cdb3192886bc822c2fa8576d6772a38 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 9 Sep 2024 19:59:16 +0200 Subject: [PATCH 114/189] move some const fn out of the const_ptr_as_ref feature --- library/core/src/ptr/const_ptr.rs | 6 +++--- library/core/src/ptr/mut_ptr.rs | 12 ++++++------ library/core/src/ptr/non_null.rs | 8 ++++---- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 3b635e2a4aa9e..81149b2061c5e 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -300,7 +300,7 @@ impl *const T { /// ``` // FIXME: mention it in the docs for `as_ref` and `as_uninit_ref` once stabilized. #[unstable(feature = "ptr_as_ref_unchecked", issue = "122034")] - #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + #[rustc_const_unstable(feature = "ptr_as_ref_unchecked", issue = "122034")] #[inline] #[must_use] pub const unsafe fn as_ref_unchecked<'a>(self) -> &'a T { @@ -334,7 +334,7 @@ impl *const T { /// ``` #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")] pub const unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit> where T: Sized, @@ -1662,7 +1662,7 @@ impl *const [T] { /// [allocated object]: crate::ptr#allocated-object #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")] pub const unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit]> { if self.is_null() { None diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 42975cc927b8e..595c583cffc64 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -310,7 +310,7 @@ impl *mut T { /// ``` // FIXME: mention it in the docs for `as_ref` and `as_uninit_ref` once stabilized. #[unstable(feature = "ptr_as_ref_unchecked", issue = "122034")] - #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + #[rustc_const_unstable(feature = "ptr_as_ref_unchecked", issue = "122034")] #[inline] #[must_use] pub const unsafe fn as_ref_unchecked<'a>(self) -> &'a T { @@ -349,7 +349,7 @@ impl *mut T { /// ``` #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")] pub const unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit> where T: Sized, @@ -631,7 +631,7 @@ impl *mut T { /// ``` // FIXME: mention it in the docs for `as_mut` and `as_uninit_mut` once stabilized. #[unstable(feature = "ptr_as_ref_unchecked", issue = "122034")] - #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + #[rustc_const_unstable(feature = "ptr_as_ref_unchecked", issue = "122034")] #[inline] #[must_use] pub const unsafe fn as_mut_unchecked<'a>(self) -> &'a mut T { @@ -654,7 +654,7 @@ impl *mut T { /// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion). #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")] pub const unsafe fn as_uninit_mut<'a>(self) -> Option<&'a mut MaybeUninit> where T: Sized, @@ -2031,7 +2031,7 @@ impl *mut [T] { /// [allocated object]: crate::ptr#allocated-object #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")] pub const unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit]> { if self.is_null() { None @@ -2083,7 +2083,7 @@ impl *mut [T] { /// [allocated object]: crate::ptr#allocated-object #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")] pub const unsafe fn as_uninit_slice_mut<'a>(self) -> Option<&'a mut [MaybeUninit]> { if self.is_null() { None diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index b1429fff74434..673acc2972fe4 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -133,7 +133,7 @@ impl NonNull { #[inline] #[must_use] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")] pub const unsafe fn as_uninit_ref<'a>(self) -> &'a MaybeUninit { // SAFETY: the caller must guarantee that `self` meets all the // requirements for a reference. @@ -157,7 +157,7 @@ impl NonNull { #[inline] #[must_use] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")] pub const unsafe fn as_uninit_mut<'a>(self) -> &'a mut MaybeUninit { // SAFETY: the caller must guarantee that `self` meets all the // requirements for a reference. @@ -1563,7 +1563,7 @@ impl NonNull<[T]> { #[inline] #[must_use] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")] pub const unsafe fn as_uninit_slice<'a>(self) -> &'a [MaybeUninit] { // SAFETY: the caller must uphold the safety contract for `as_uninit_slice`. unsafe { slice::from_raw_parts(self.cast().as_ptr(), self.len()) } @@ -1628,7 +1628,7 @@ impl NonNull<[T]> { #[inline] #[must_use] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + #[rustc_const_unstable(feature = "ptr_as_uninit", issue = "75402")] pub const unsafe fn as_uninit_slice_mut<'a>(self) -> &'a mut [MaybeUninit] { // SAFETY: the caller must uphold the safety contract for `as_uninit_slice_mut`. unsafe { slice::from_raw_parts_mut(self.cast().as_ptr(), self.len()) } From 12998c2e11a089e6c591e1704a63a7942826208e Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 9 Sep 2024 21:03:51 +0300 Subject: [PATCH 115/189] handle `GitConfig` for `tools/suggest-tests` Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/suggest.rs | 1 + src/tools/suggest-tests/src/main.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/bootstrap/src/core/build_steps/suggest.rs b/src/bootstrap/src/core/build_steps/suggest.rs index 8aaffab514d88..ba9b1b2fc3317 100644 --- a/src/bootstrap/src/core/build_steps/suggest.rs +++ b/src/bootstrap/src/core/build_steps/suggest.rs @@ -17,6 +17,7 @@ pub fn suggest(builder: &Builder<'_>, run: bool) { .tool_cmd(Tool::SuggestTests) .env("SUGGEST_TESTS_GIT_REPOSITORY", git_config.git_repository) .env("SUGGEST_TESTS_NIGHTLY_BRANCH", git_config.nightly_branch) + .env("SUGGEST_TESTS_MERGE_COMMIT_EMAIL", git_config.git_merge_commit_email) .run_capture_stdout(builder) .stdout(); diff --git a/src/tools/suggest-tests/src/main.rs b/src/tools/suggest-tests/src/main.rs index 8e3625c244916..6f09bddcf60b8 100644 --- a/src/tools/suggest-tests/src/main.rs +++ b/src/tools/suggest-tests/src/main.rs @@ -8,6 +8,7 @@ fn main() -> ExitCode { &GitConfig { git_repository: &env("SUGGEST_TESTS_GIT_REPOSITORY"), nightly_branch: &env("SUGGEST_TESTS_NIGHTLY_BRANCH"), + git_merge_commit_email: &env("SUGGEST_TESTS_MERGE_COMMIT_EMAIL"), }, None, &Vec::new(), From e10224a7c3b7dbe5942e021d0b7f8230128cb9af Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 9 Sep 2024 20:09:13 +0200 Subject: [PATCH 116/189] move const fn with a null check into const_ptr_is_null gate --- library/core/src/ptr/const_ptr.rs | 2 +- library/core/src/ptr/mut_ptr.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 81149b2061c5e..6dbc5e210ad3a 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -268,7 +268,7 @@ impl *const T { /// } /// ``` #[stable(feature = "ptr_as_ref", since = "1.9.0")] - #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")] #[inline] pub const unsafe fn as_ref<'a>(self) -> Option<&'a T> { // SAFETY: the caller must guarantee that `self` is valid diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 595c583cffc64..d0b4e493107c9 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -276,7 +276,7 @@ impl *mut T { /// } /// ``` #[stable(feature = "ptr_as_ref", since = "1.9.0")] - #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")] #[inline] pub const unsafe fn as_ref<'a>(self) -> Option<&'a T> { // SAFETY: the caller must guarantee that `self` is valid for a @@ -595,7 +595,7 @@ impl *mut T { /// println!("{s:?}"); // It'll print: "[4, 2, 3]". /// ``` #[stable(feature = "ptr_as_ref", since = "1.9.0")] - #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")] #[inline] pub const unsafe fn as_mut<'a>(self) -> Option<&'a mut T> { // SAFETY: the caller must guarantee that `self` is be valid for From 2f1e1be6ffbf39e3a7b219343e4be38cab599cf4 Mon Sep 17 00:00:00 2001 From: Julius Liu Date: Mon, 9 Sep 2024 11:55:44 -0700 Subject: [PATCH 117/189] maint: update docs for change_time ext and doc links --- library/std/src/os/windows/fs.rs | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/library/std/src/os/windows/fs.rs b/library/std/src/os/windows/fs.rs index 7cac8c39ea89f..285d9c3fc78d6 100644 --- a/library/std/src/os/windows/fs.rs +++ b/library/std/src/os/windows/fs.rs @@ -299,7 +299,7 @@ impl OpenOptionsExt for OpenOptions { /// of the [`BY_HANDLE_FILE_INFORMATION`] structure. /// /// [`BY_HANDLE_FILE_INFORMATION`]: -/// https://docs.microsoft.com/en-us/windows/win32/api/fileapi/ns-fileapi-by_handle_file_information +/// https://docs.microsoft.com/windows/win32/api/fileapi/ns-fileapi-by_handle_file_information #[stable(feature = "metadata_ext", since = "1.1.0")] pub trait MetadataExt { /// Returns the value of the `dwFileAttributes` field of this metadata. @@ -323,7 +323,7 @@ pub trait MetadataExt { /// ``` /// /// [File Attribute Constants]: - /// https://docs.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants + /// https://docs.microsoft.com/windows/win32/fileio/file-attribute-constants #[stable(feature = "metadata_ext", since = "1.1.0")] fn file_attributes(&self) -> u32; @@ -352,7 +352,7 @@ pub trait MetadataExt { /// } /// ``` /// - /// [`FILETIME`]: https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime + /// [`FILETIME`]: https://docs.microsoft.com/windows/win32/api/minwinbase/ns-minwinbase-filetime #[stable(feature = "metadata_ext", since = "1.1.0")] fn creation_time(&self) -> u64; @@ -387,7 +387,7 @@ pub trait MetadataExt { /// } /// ``` /// - /// [`FILETIME`]: https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime + /// [`FILETIME`]: https://docs.microsoft.com/windows/win32/api/minwinbase/ns-minwinbase-filetime #[stable(feature = "metadata_ext", since = "1.1.0")] fn last_access_time(&self) -> u64; @@ -420,7 +420,7 @@ pub trait MetadataExt { /// } /// ``` /// - /// [`FILETIME`]: https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime + /// [`FILETIME`]: https://docs.microsoft.com/windows/win32/api/minwinbase/ns-minwinbase-filetime #[stable(feature = "metadata_ext", since = "1.1.0")] fn last_write_time(&self) -> u64; @@ -472,10 +472,21 @@ pub trait MetadataExt { #[unstable(feature = "windows_by_handle", issue = "63010")] fn file_index(&self) -> Option; - /// Returns the change time, which is the last time file metadata was changed, such as - /// renames, attributes, etc - /// - /// This will return `None` if the `Metadata` instance was not created using the `FILE_BASIC_INFO` type. + /// Returns the value of the `ChangeTime{Low,High}` field from the + /// [`FILE_BASIC_INFO`] struct associated with the current file handle. + /// [`ChangeTime`] is the last time file metadata was changed, such as + /// renames, attributes, etc. + /// + /// This will return `None` if `Metadata` was populated without access to + /// [`FILE_BASIC_INFO`]. For example, the result of `std::fs::read_dir` + /// will be derived from [`WIN32_FIND_DATA`] which does not have access to + /// `ChangeTime`. + /// + /// [`FILE_BASIC_INFO`]: https://learn.microsoft.com/windows/win32/api/winbase/ns-winbase-file_basic_info + /// [`WIN32_FIND_DATA`]: https://learn.microsoft.com/windows/win32/api/minwinbase/ns-minwinbase-win32_find_dataw + /// [`FindFirstFile`]: https://learn.microsoft.com/windows/win32/api/fileapi/nf-fileapi-findfirstfilea + /// [`FindNextFile`]: https://learn.microsoft.com/windows/win32/api/fileapi/nf-fileapi-findnextfilea + /// [`ChangeTime`]: https://devblogs.microsoft.com/oldnewthing/20100709-00/?p=13463. #[unstable(feature = "windows_change_time", issue = "121478")] fn change_time(&self) -> Option; } From d243c8fbc4e55885f94a74c271aa9c8fe3425a03 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Sat, 7 Sep 2024 18:29:08 -0700 Subject: [PATCH 118/189] compiler: Inform the solver of concurrency Parallel compilation of a program can cause unexpected event sequencing. Inform the solver when this is true so it can skip invalid asserts, then assert replaced solutions are equal if Some --- compiler/rustc_middle/src/ty/context.rs | 4 +++ compiler/rustc_type_ir/src/interner.rs | 5 ++++ .../src/search_graph/global_cache.rs | 14 +++++++--- .../rustc_type_ir/src/search_graph/mod.rs | 2 ++ .../global-cache-and-parallel-frontend.rs | 27 +++++++++++++++++++ .../global-cache-and-parallel-frontend.stderr | 24 +++++++++++++++++ 6 files changed, 72 insertions(+), 4 deletions(-) create mode 100644 tests/ui/traits/next-solver/global-cache-and-parallel-frontend.rs create mode 100644 tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 5334e7677664d..56fcfe8e798b1 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -181,6 +181,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> { } } + fn evaluation_is_concurrent(&self) -> bool { + self.sess.threads() > 1 + } + fn expand_abstract_consts>>(self, t: T) -> T { self.expand_abstract_consts(t) } diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index f2492ede4f5ea..8dec2133a45dd 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -137,6 +137,8 @@ pub trait Interner: f: impl FnOnce(&mut search_graph::GlobalCache) -> R, ) -> R; + fn evaluation_is_concurrent(&self) -> bool; + fn expand_abstract_consts>(self, t: T) -> T; type GenericsOf: GenericsOf; @@ -404,4 +406,7 @@ impl search_graph::Cx for I { ) -> R { I::with_global_cache(self, mode, f) } + fn evaluation_is_concurrent(&self) -> bool { + self.evaluation_is_concurrent() + } } diff --git a/compiler/rustc_type_ir/src/search_graph/global_cache.rs b/compiler/rustc_type_ir/src/search_graph/global_cache.rs index 47f7cefac6ad1..0ce927b58bb38 100644 --- a/compiler/rustc_type_ir/src/search_graph/global_cache.rs +++ b/compiler/rustc_type_ir/src/search_graph/global_cache.rs @@ -44,22 +44,28 @@ impl GlobalCache { cx: X, input: X::Input, - result: X::Result, + origin_result: X::Result, dep_node: X::DepNodeIndex, additional_depth: usize, encountered_overflow: bool, nested_goals: NestedGoals, ) { - let result = cx.mk_tracked(result, dep_node); + let result = cx.mk_tracked(origin_result, dep_node); let entry = self.map.entry(input).or_default(); if encountered_overflow { let with_overflow = WithOverflow { nested_goals, result }; let prev = entry.with_overflow.insert(additional_depth, with_overflow); - assert!(prev.is_none()); + if let Some(prev) = &prev { + assert!(cx.evaluation_is_concurrent()); + assert_eq!(cx.get_tracked(&prev.result), origin_result); + } } else { let prev = entry.success.replace(Success { additional_depth, nested_goals, result }); - assert!(prev.is_none()); + if let Some(prev) = &prev { + assert!(cx.evaluation_is_concurrent()); + assert_eq!(cx.get_tracked(&prev.result), origin_result); + } } } diff --git a/compiler/rustc_type_ir/src/search_graph/mod.rs b/compiler/rustc_type_ir/src/search_graph/mod.rs index 418139c3aadc0..ac4d0795a92e8 100644 --- a/compiler/rustc_type_ir/src/search_graph/mod.rs +++ b/compiler/rustc_type_ir/src/search_graph/mod.rs @@ -53,6 +53,8 @@ pub trait Cx: Copy { mode: SolverMode, f: impl FnOnce(&mut GlobalCache) -> R, ) -> R; + + fn evaluation_is_concurrent(&self) -> bool; } pub trait Delegate { diff --git a/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.rs b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.rs new file mode 100644 index 0000000000000..2b4f7ba9fa29e --- /dev/null +++ b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.rs @@ -0,0 +1,27 @@ +//@ compile-flags: -Zthreads=16 + +// original issue: https://github.com/rust-lang/rust/issues/129112 +// Previously, the "next" solver asserted that each successful solution is only obtained once. +// This test exhibits a repro that, with next-solver + -Zthreads, triggered that old assert. +// In the presence of multithreaded solving, it's possible to concurrently evaluate things twice, +// which leads to replacing already-solved solutions in the global solution cache! +// We assume this is fine if we check to make sure they are solved the same way each time. + +// This test only nondeterministically fails but that's okay, as it will be rerun by CI many times, +// so it should almost always fail before anything is merged. As other thread tests already exist, +// we already face this difficulty, probably. If we need to fix this by reducing the error margin, +// we should improve compiletest. + +#[derive(Clone, Eq)] //~ ERROR [E0277] +pub struct Struct(T); + +impl PartialEq for Struct +where + U: Into> + Clone +{ + fn eq(&self, _other: &U) -> bool { + todo!() + } +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr new file mode 100644 index 0000000000000..65e7dd2ab34bc --- /dev/null +++ b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr @@ -0,0 +1,24 @@ +error[E0277]: the trait bound `T: Clone` is not satisfied + --> $DIR/global-cache-and-parallel-frontend.rs:15:17 + | +LL | #[derive(Clone, Eq)] + | ^^ the trait `Clone` is not implemented for `T`, which is required by `Struct: PartialEq` + | +note: required for `Struct` to implement `PartialEq` + --> $DIR/global-cache-and-parallel-frontend.rs:18:19 + | +LL | impl PartialEq for Struct + | ----- ^^^^^^^^^^^^ ^^^^^^^^^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `Eq` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `T` + | +LL | pub struct Struct(T); + | +++++++++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. From 6d61dfd2e48d4f183ca4bca4aaa60b2e2ffb4fa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Mon, 9 Sep 2024 22:35:10 +0200 Subject: [PATCH 119/189] rustdoc: add two regression tests --- .../projection-as-union-type-error.rs | 14 +++++++++++ .../projection-as-union-type-error.stderr | 15 ++++++++++++ ...ias-impl-trait-declaration-too-subtle-2.rs | 23 +++++++++++++++++++ 3 files changed, 52 insertions(+) create mode 100644 tests/rustdoc-ui/projection-as-union-type-error.rs create mode 100644 tests/rustdoc-ui/projection-as-union-type-error.stderr create mode 100644 tests/rustdoc-ui/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs diff --git a/tests/rustdoc-ui/projection-as-union-type-error.rs b/tests/rustdoc-ui/projection-as-union-type-error.rs new file mode 100644 index 0000000000000..d1d2e72249dc0 --- /dev/null +++ b/tests/rustdoc-ui/projection-as-union-type-error.rs @@ -0,0 +1,14 @@ +// Test to ensure that there is no ICE when normalizing a projection. +// See also . +// issue: rust-lang/rust#107872 + +pub trait Identity { + type Identity; +} + +pub type Foo = u8; + +pub union Bar { + a: ::Identity, //~ ERROR the trait bound `u8: Identity` is not satisfied + b: u8, +} diff --git a/tests/rustdoc-ui/projection-as-union-type-error.stderr b/tests/rustdoc-ui/projection-as-union-type-error.stderr new file mode 100644 index 0000000000000..32598015864cb --- /dev/null +++ b/tests/rustdoc-ui/projection-as-union-type-error.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `u8: Identity` is not satisfied + --> $DIR/projection-as-union-type-error.rs:12:9 + | +LL | a: ::Identity, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Identity` is not implemented for `u8` + | +help: this trait has no implementations, consider adding one + --> $DIR/projection-as-union-type-error.rs:5:1 + | +LL | pub trait Identity { + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/rustdoc-ui/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs b/tests/rustdoc-ui/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs new file mode 100644 index 0000000000000..9f8053d553876 --- /dev/null +++ b/tests/rustdoc-ui/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs @@ -0,0 +1,23 @@ +// issue: rust-lang/rust#98250 +//@ check-pass + +#![feature(type_alias_impl_trait)] + +mod foo { + pub type Foo = impl PartialEq<(Foo, i32)>; + + fn foo() -> Foo { + super::Bar + } +} +use foo::Foo; + +struct Bar; + +impl PartialEq<(Foo, i32)> for Bar { + fn eq(&self, _other: &(Foo, i32)) -> bool { + true + } +} + +fn main() {} From a0a89e55387dc4291442e5fc401bd1e35b94fbe8 Mon Sep 17 00:00:00 2001 From: Julius Liu Date: Mon, 9 Sep 2024 13:56:41 -0700 Subject: [PATCH 120/189] chore: removing supporting links in favor of existing doc-comment style --- library/std/src/os/windows/fs.rs | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/library/std/src/os/windows/fs.rs b/library/std/src/os/windows/fs.rs index 285d9c3fc78d6..d03f9e0e330dd 100644 --- a/library/std/src/os/windows/fs.rs +++ b/library/std/src/os/windows/fs.rs @@ -472,21 +472,14 @@ pub trait MetadataExt { #[unstable(feature = "windows_by_handle", issue = "63010")] fn file_index(&self) -> Option; - /// Returns the value of the `ChangeTime{Low,High}` field from the - /// [`FILE_BASIC_INFO`] struct associated with the current file handle. - /// [`ChangeTime`] is the last time file metadata was changed, such as - /// renames, attributes, etc. + /// Returns the value of the `ChangeTime{Low,High}` fields of this metadata. /// - /// This will return `None` if `Metadata` was populated without access to - /// [`FILE_BASIC_INFO`]. For example, the result of `std::fs::read_dir` - /// will be derived from [`WIN32_FIND_DATA`] which does not have access to - /// `ChangeTime`. + /// `ChangeTime` is the last time file metadata was changed, such as + /// renames, attributes, etc. /// - /// [`FILE_BASIC_INFO`]: https://learn.microsoft.com/windows/win32/api/winbase/ns-winbase-file_basic_info - /// [`WIN32_FIND_DATA`]: https://learn.microsoft.com/windows/win32/api/minwinbase/ns-minwinbase-win32_find_dataw - /// [`FindFirstFile`]: https://learn.microsoft.com/windows/win32/api/fileapi/nf-fileapi-findfirstfilea - /// [`FindNextFile`]: https://learn.microsoft.com/windows/win32/api/fileapi/nf-fileapi-findnextfilea - /// [`ChangeTime`]: https://devblogs.microsoft.com/oldnewthing/20100709-00/?p=13463. + /// This will return `None` if `Metadata` instance was created from a call to + /// `DirEntry::metadata` or if the `target_vendor` is outside the current platform + /// support for this api. #[unstable(feature = "windows_change_time", issue = "121478")] fn change_time(&self) -> Option; } From 8235af07d21d60012acbd217f24049e1386081bd Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 28 Aug 2024 08:24:10 +1000 Subject: [PATCH 121/189] Improve comment formatting. By reflowing comment lines that are too long, and a few that are very short. Plus some other very minor formatting tweaks. --- compiler/rustc_mir_transform/src/add_retag.rs | 10 +++-- .../src/check_const_item_mutation.rs | 1 + compiler/rustc_mir_transform/src/copy_prop.rs | 3 +- .../rustc_mir_transform/src/coverage/mod.rs | 3 +- .../src/dataflow_const_prop.rs | 3 +- .../src/deduce_param_attrs.rs | 6 +-- .../src/deduplicate_blocks.rs | 7 ++-- .../src/early_otherwise_branch.rs | 4 +- .../src/elaborate_drops.rs | 16 ++++---- .../src/ffi_unwind_calls.rs | 5 ++- .../src/function_item_references.rs | 4 +- compiler/rustc_mir_transform/src/gvn.rs | 10 +++-- compiler/rustc_mir_transform/src/inline.rs | 3 +- .../src/known_panics_lint.rs | 11 +++--- .../rustc_mir_transform/src/large_enums.rs | 5 ++- compiler/rustc_mir_transform/src/lib.rs | 31 +++++++++------ .../rustc_mir_transform/src/match_branches.rs | 14 ++++--- .../src/mentioned_items.rs | 4 +- compiler/rustc_mir_transform/src/prettify.rs | 4 +- .../rustc_mir_transform/src/promote_consts.rs | 38 ++++++++++--------- .../src/remove_uninit_drops.rs | 5 ++- .../rustc_mir_transform/src/reveal_all.rs | 6 +-- compiler/rustc_mir_transform/src/shim.rs | 3 +- .../src/simplify_comparison_integral.rs | 22 +++++++---- .../src/unreachable_enum_branching.rs | 6 +-- .../src/unreachable_prop.rs | 8 ++-- compiler/rustc_mir_transform/src/validate.rs | 30 ++++++++------- 27 files changed, 151 insertions(+), 111 deletions(-) diff --git a/compiler/rustc_mir_transform/src/add_retag.rs b/compiler/rustc_mir_transform/src/add_retag.rs index 794e85fbfedfb..8ad364ed05502 100644 --- a/compiler/rustc_mir_transform/src/add_retag.rs +++ b/compiler/rustc_mir_transform/src/add_retag.rs @@ -60,7 +60,9 @@ impl<'tcx> crate::MirPass<'tcx> for AddRetag { let basic_blocks = body.basic_blocks.as_mut(); let local_decls = &body.local_decls; let needs_retag = |place: &Place<'tcx>| { - !place.is_indirect_first_projection() // we're not really interested in stores to "outside" locations, they are hard to keep track of anyway + // We're not really interested in stores to "outside" locations, they are hard to keep + // track of anyway. + !place.is_indirect_first_projection() && may_contain_reference(place.ty(&*local_decls, tcx).ty, /*depth*/ 3, tcx) && !local_decls[place.local].is_deref_temp() }; @@ -129,9 +131,9 @@ impl<'tcx> crate::MirPass<'tcx> for AddRetag { StatementKind::Assign(box (ref place, ref rvalue)) => { let add_retag = match rvalue { // Ptr-creating operations already do their own internal retagging, no - // need to also add a retag statement. - // *Except* if we are deref'ing a Box, because those get desugared to directly working - // with the inner raw pointer! That's relevant for `RawPtr` as Miri otherwise makes it + // need to also add a retag statement. *Except* if we are deref'ing a + // Box, because those get desugared to directly working with the inner + // raw pointer! That's relevant for `RawPtr` as Miri otherwise makes it // a NOP when the original pointer is already raw. Rvalue::RawPtr(_mutbl, place) => { // Using `is_box_global` here is a bit sketchy: if this code is diff --git a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs index 234ed8206f5d5..048dd9ccb8f3c 100644 --- a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs +++ b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs @@ -123,6 +123,7 @@ impl<'tcx> Visitor<'tcx> for ConstMutationChecker<'_, 'tcx> { self.super_statement(stmt, loc); self.target_local = None; } + fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, loc: Location) { if let Rvalue::Ref(_, BorrowKind::Mut { .. }, place) = rvalue { let local = place.local; diff --git a/compiler/rustc_mir_transform/src/copy_prop.rs b/compiler/rustc_mir_transform/src/copy_prop.rs index dc4ee58ea83e3..1cb56d29b85e0 100644 --- a/compiler/rustc_mir_transform/src/copy_prop.rs +++ b/compiler/rustc_mir_transform/src/copy_prop.rs @@ -140,7 +140,8 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> { fn visit_operand(&mut self, operand: &mut Operand<'tcx>, loc: Location) { if let Operand::Move(place) = *operand - // A move out of a projection of a copy is equivalent to a copy of the original projection. + // A move out of a projection of a copy is equivalent to a copy of the original + // projection. && !place.is_indirect_first_projection() && !self.fully_moved.contains(place.local) { diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 042f589768a99..f78fc7931f9f9 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -279,7 +279,8 @@ fn inject_mcdc_statements<'tcx>( basic_coverage_blocks: &CoverageGraph, extracted_mappings: &ExtractedMappings, ) { - // Inject test vector update first because `inject_statement` always insert new statement at head. + // Inject test vector update first because `inject_statement` always insert new statement at + // head. for &mappings::MCDCDecision { span: _, ref end_bcbs, diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 79f12be4bc353..7ac019ce81216 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -647,7 +647,8 @@ fn try_write_constant<'tcx>( ty::FnDef(..) => {} // Those are scalars, must be handled above. - ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => throw_machine_stop_str!("primitive type with provenance"), + ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => + throw_machine_stop_str!("primitive type with provenance"), ty::Tuple(elem_tys) => { for (i, elem) in elem_tys.iter().enumerate() { diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs index e870a71b05aa7..c645bbee08a54 100644 --- a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs +++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs @@ -42,9 +42,9 @@ impl<'tcx> Visitor<'tcx> for DeduceReadOnly { } PlaceContext::NonMutatingUse(NonMutatingUseContext::RawBorrow) => { // Whether mutating though a `&raw const` is allowed is still undecided, so we - // disable any sketchy `readonly` optimizations for now. - // But we only need to do this if the pointer would point into the argument. - // IOW: for indirect places, like `&raw (*local).field`, this surely cannot mutate `local`. + // disable any sketchy `readonly` optimizations for now. But we only need to do + // this if the pointer would point into the argument. IOW: for indirect places, + // like `&raw (*local).field`, this surely cannot mutate `local`. !place.is_indirect() } PlaceContext::NonMutatingUse(..) | PlaceContext::NonUse(..) => { diff --git a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs index c8179d513c7ce..ad204e76d0d15 100644 --- a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs +++ b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs @@ -69,8 +69,8 @@ fn find_duplicates(body: &Body<'_>) -> FxHashMap { // For example, if bb1, bb2 and bb3 are duplicates, we will first insert bb3 in same_hashes. // Then we will see that bb2 is a duplicate of bb3, // and insert bb2 with the replacement bb3 in the duplicates list. - // When we see bb1, we see that it is a duplicate of bb3, and therefore insert it in the duplicates list - // with replacement bb3. + // When we see bb1, we see that it is a duplicate of bb3, and therefore insert it in the + // duplicates list with replacement bb3. // When the duplicates are removed, we will end up with only bb3. for (bb, bbd) in body.basic_blocks.iter_enumerated().rev().filter(|(_, bbd)| !bbd.is_cleanup) { // Basic blocks can get really big, so to avoid checking for duplicates in basic blocks @@ -105,7 +105,8 @@ struct BasicBlockHashable<'tcx, 'a> { impl Hash for BasicBlockHashable<'_, '_> { fn hash(&self, state: &mut H) { hash_statements(state, self.basic_block_data.statements.iter()); - // Note that since we only hash the kind, we lose span information if we deduplicate the blocks + // Note that since we only hash the kind, we lose span information if we deduplicate the + // blocks. self.basic_block_data.terminator().kind.hash(state); } } diff --git a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs index 3884321df2a2c..704ed508b22a8 100644 --- a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs +++ b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs @@ -261,8 +261,8 @@ fn evaluate_candidate<'tcx>( // }; // ``` // - // Hoisting the `discriminant(Q)` out of the `A` arm causes us to compute the discriminant of an - // invalid value, which is UB. + // Hoisting the `discriminant(Q)` out of the `A` arm causes us to compute the discriminant + // of an invalid value, which is UB. // In order to fix this, **we would either need to show that the discriminant computation of // `place` is computed in all branches**. // FIXME(#95162) For the moment, we adopt a conservative approach and diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index cb729792dc538..42d13fa3613ab 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -20,8 +20,8 @@ use tracing::{debug, instrument}; use crate::deref_separator::deref_finder; /// During MIR building, Drop terminators are inserted in every place where a drop may occur. -/// However, in this phase, the presence of these terminators does not guarantee that a destructor will run, -/// as the target of the drop may be uninitialized. +/// However, in this phase, the presence of these terminators does not guarantee that a destructor +/// will run, as the target of the drop may be uninitialized. /// In general, the compiler cannot determine at compile time whether a destructor will run or not. /// /// At a high level, this pass refines Drop to only run the destructor if the @@ -30,10 +30,10 @@ use crate::deref_separator::deref_finder; /// Once this is complete, Drop terminators in the MIR correspond to a call to the "drop glue" or /// "drop shim" for the type of the dropped place. /// -/// This pass relies on dropped places having an associated move path, which is then used to determine -/// the initialization status of the place and its descendants. -/// It's worth noting that a MIR containing a Drop without an associated move path is probably ill formed, -/// as it would allow running a destructor on a place behind a reference: +/// This pass relies on dropped places having an associated move path, which is then used to +/// determine the initialization status of the place and its descendants. +/// It's worth noting that a MIR containing a Drop without an associated move path is probably ill +/// formed, as it would allow running a destructor on a place behind a reference: /// /// ```text /// fn drop_term(t: &mut T) { @@ -377,8 +377,8 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> { ); } // A drop and replace behind a pointer/array/whatever. - // The borrow checker requires that these locations are initialized before the assignment, - // so we just leave an unconditional drop. + // The borrow checker requires that these locations are initialized before the + // assignment, so we just leave an unconditional drop. assert!(!data.is_cleanup); } } diff --git a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs index 81875e3d01246..8490b7e235818 100644 --- a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs +++ b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs @@ -60,8 +60,9 @@ fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool { let fn_def_id = match ty.kind() { ty::FnPtr(..) => None, &ty::FnDef(def_id, _) => { - // Rust calls cannot themselves create foreign unwinds (even if they use a non-Rust ABI). - // So the leak of the foreign unwind into Rust can only be elsewhere, not here. + // Rust calls cannot themselves create foreign unwinds (even if they use a non-Rust + // ABI). So the leak of the foreign unwind into Rust can only be elsewhere, not + // here. if !tcx.is_foreign_item(def_id) { continue; } diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs index 0efaa172e0c6f..eb09a7d3b2114 100644 --- a/compiler/rustc_mir_transform/src/function_item_references.rs +++ b/compiler/rustc_mir_transform/src/function_item_references.rs @@ -92,8 +92,8 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> { { let mut span = self.nth_arg_span(args, arg_num); if span.from_expansion() { - // The operand's ctxt wouldn't display the lint since it's inside a macro so - // we have to use the callsite's ctxt. + // The operand's ctxt wouldn't display the lint since it's + // inside a macro so we have to use the callsite's ctxt. let callsite_ctxt = span.source_callsite().ctxt(); span = span.with_ctxt(callsite_ctxt); } diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index e5d2b13efd8fe..715461de06482 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -139,8 +139,8 @@ fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // Try to get some insight. AssignedValue::Rvalue(rvalue) => { let value = state.simplify_rvalue(rvalue, location); - // FIXME(#112651) `rvalue` may have a subtype to `local`. We can only mark `local` as - // reusable if we have an exact type match. + // FIXME(#112651) `rvalue` may have a subtype to `local`. We can only mark + // `local` as reusable if we have an exact type match. if state.local_decls[local].ty != rvalue.ty(state.local_decls, tcx) { return; } @@ -480,7 +480,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { let pointer = self.evaluated[local].as_ref()?; let mut mplace = self.ecx.deref_pointer(pointer).ok()?; for proj in place.projection.iter().skip(1) { - // We have no call stack to associate a local with a value, so we cannot interpret indexing. + // We have no call stack to associate a local with a value, so we cannot + // interpret indexing. if matches!(proj, ProjectionElem::Index(_)) { return None; } @@ -1382,7 +1383,8 @@ fn op_to_prop_const<'tcx>( return Some(ConstValue::ZeroSized); } - // Do not synthetize too large constants. Codegen will just memcpy them, which we'd like to avoid. + // Do not synthetize too large constants. Codegen will just memcpy them, which we'd like to + // avoid. if !matches!(op.layout.abi, Abi::Scalar(..) | Abi::ScalarPair(..)) { return None; } diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 03ef808efecb6..870cb180ce1be 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -568,7 +568,8 @@ impl<'tcx> Inliner<'tcx> { // if the no-attribute function ends up with the same instruction set anyway. return Err("Cannot move inline-asm across instruction sets"); } else if let TerminatorKind::TailCall { .. } = term.kind { - // FIXME(explicit_tail_calls): figure out how exactly functions containing tail calls can be inlined (and if they even should) + // FIXME(explicit_tail_calls): figure out how exactly functions containing tail + // calls can be inlined (and if they even should) return Err("can't inline functions with tail calls"); } else { work_list.extend(term.successors()) diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs index e964310c5429e..46b17c3c7e04d 100644 --- a/compiler/rustc_mir_transform/src/known_panics_lint.rs +++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs @@ -1,8 +1,6 @@ -//! A lint that checks for known panics like -//! overflows, division by zero, -//! out-of-bound access etc. -//! Uses const propagation to determine the -//! values of operands during checks. +//! A lint that checks for known panics like overflows, division by zero, +//! out-of-bound access etc. Uses const propagation to determine the values of +//! operands during checks. use std::fmt::Debug; @@ -562,7 +560,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let val = self.use_ecx(|this| this.ecx.binary_op(bin_op, &left, &right))?; if matches!(val.layout.abi, Abi::ScalarPair(..)) { - // FIXME `Value` should properly support pairs in `Immediate`... but currently it does not. + // FIXME `Value` should properly support pairs in `Immediate`... but currently + // it does not. let (val, overflow) = val.to_pair(&self.ecx); Value::Aggregate { variant: VariantIdx::ZERO, diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs index f61cf236f77cc..45edcff29eb28 100644 --- a/compiler/rustc_mir_transform/src/large_enums.rs +++ b/compiler/rustc_mir_transform/src/large_enums.rs @@ -16,8 +16,7 @@ use rustc_target::abi::{HasDataLayout, Size, TagEncoding, Variants}; /// Large([u32; 1024]), /// } /// ``` -/// Instead of emitting moves of the large variant, -/// Perform a memcpy instead. +/// Instead of emitting moves of the large variant, perform a memcpy instead. /// Based off of [this HackMD](https://hackmd.io/@ft4bxUsFT5CEUBmRKYHr7w/rJM8BBPzD). /// /// In summary, what this does is at runtime determine which enum variant is active, @@ -34,6 +33,7 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt { // https://github.com/rust-lang/rust/pull/85158#issuecomment-1101836457 sess.opts.unstable_opts.unsound_mir_opts || sess.mir_opt_level() >= 3 } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // NOTE: This pass may produce different MIR based on the alignment of the target // platform, but it will still be valid. @@ -116,6 +116,7 @@ impl EnumSizeOpt { let alloc = tcx.reserve_and_set_memory_alloc(tcx.mk_const_alloc(alloc)); Some((*adt_def, num_discrs, *alloc_cache.entry(ty).or_insert(alloc))) } + fn optim<'tcx>(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let mut alloc_cache = FxHashMap::default(); let body_did = body.source.def_id(); diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 0bbbf047f634c..dcfcad7cc7c5b 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -168,8 +168,9 @@ fn remap_mir_for_const_eval_select<'tcx>( let (method, place): (fn(Place<'tcx>) -> Operand<'tcx>, Place<'tcx>) = match tupled_args.node { Operand::Constant(_) => { - // there is no good way of extracting a tuple arg from a constant (const generic stuff) - // so we just create a temporary and deconstruct that. + // There is no good way of extracting a tuple arg from a constant + // (const generic stuff) so we just create a temporary and deconstruct + // that. let local = body.local_decls.push(LocalDecl::new(ty, fn_span)); bb.statements.push(Statement { source_info: SourceInfo::outermost(fn_span), @@ -480,7 +481,8 @@ pub fn run_analysis_to_runtime_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<' &[&remove_uninit_drops::RemoveUninitDrops, &simplify::SimplifyCfg::RemoveFalseEdges], None, ); - check_consts::post_drop_elaboration::check_live_drops(tcx, body); // FIXME: make this a MIR lint + // FIXME: make this a MIR lint + check_consts::post_drop_elaboration::check_live_drops(tcx, body); } debug!("runtime_mir_lowering({:?})", did); @@ -509,10 +511,12 @@ fn run_analysis_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { /// Returns the sequence of passes that lowers analysis to runtime MIR. fn run_runtime_lowering_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let passes: &[&dyn MirPass<'tcx>] = &[ - // These next passes must be executed together + // These next passes must be executed together. &add_call_guards::CriticalCallEdges, - &reveal_all::RevealAll, // has to be done before drop elaboration, since we need to drop opaque types, too. - &add_subtyping_projections::Subtyper, // calling this after reveal_all ensures that we don't deal with opaque types + // Must be done before drop elaboration because we need to drop opaque types, too. + &reveal_all::RevealAll, + // Calling this after reveal_all ensures that we don't deal with opaque types. + &add_subtyping_projections::Subtyper, &elaborate_drops::ElaborateDrops, // This will remove extraneous landing pads which are no longer // necessary as well as forcing any call in a non-unwinding @@ -521,8 +525,8 @@ fn run_runtime_lowering_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // AddMovesForPackedDrops needs to run after drop // elaboration. &add_moves_for_packed_drops::AddMovesForPackedDrops, - // `AddRetag` needs to run after `ElaborateDrops` but before `ElaborateBoxDerefs`. Otherwise it should run fairly late, - // but before optimizations begin. + // `AddRetag` needs to run after `ElaborateDrops` but before `ElaborateBoxDerefs`. + // Otherwise it should run fairly late, but before optimizations begin. &add_retag::AddRetag, &elaborate_box_derefs::ElaborateBoxDerefs, &coroutine::StateTransform, @@ -563,13 +567,15 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // Before inlining: trim down MIR with passes to reduce inlining work. // Has to be done before inlining, otherwise actual call will be almost always inlined. - // Also simple, so can just do first + // Also simple, so can just do first. &lower_slice_len::LowerSliceLenCalls, - // Perform instsimplify before inline to eliminate some trivial calls (like clone shims). + // Perform instsimplify before inline to eliminate some trivial calls (like clone + // shims). &instsimplify::InstSimplify::BeforeInline, // Perform inlining, which may add a lot of code. &inline::Inline, - // Code from other crates may have storage markers, so this needs to happen after inlining. + // Code from other crates may have storage markers, so this needs to happen after + // inlining. &remove_storage_markers::RemoveStorageMarkers, // Inlining and instantiation may introduce ZST and useless drops. &remove_zsts::RemoveZsts, @@ -586,7 +592,8 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { &match_branches::MatchBranchSimplification, // inst combine is after MatchBranchSimplification to clean up Ne(_1, false) &multiple_return_terminators::MultipleReturnTerminators, - // After simplifycfg, it allows us to discover new opportunities for peephole optimizations. + // After simplifycfg, it allows us to discover new opportunities for peephole + // optimizations. &instsimplify::InstSimplify::AfterSimplifyCfg, &simplify::SimplifyLocals::BeforeConstProp, &dead_store_elimination::DeadStoreElimination::Initial, diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs index 2a2616b20a6de..0f981425cfd0d 100644 --- a/compiler/rustc_mir_transform/src/match_branches.rs +++ b/compiler/rustc_mir_transform/src/match_branches.rs @@ -57,8 +57,9 @@ impl<'tcx> crate::MirPass<'tcx> for MatchBranchSimplification { } trait SimplifyMatch<'tcx> { - /// Simplifies a match statement, returning true if the simplification succeeds, false otherwise. - /// Generic code is written here, and we generally don't need a custom implementation. + /// Simplifies a match statement, returning true if the simplification succeeds, false + /// otherwise. Generic code is written here, and we generally don't need a custom + /// implementation. fn simplify( &mut self, tcx: TyCtxt<'tcx>, @@ -240,7 +241,8 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToIf { // Same value in both blocks. Use statement as is. patch.add_statement(parent_end, f.kind.clone()); } else { - // Different value between blocks. Make value conditional on switch condition. + // Different value between blocks. Make value conditional on switch + // condition. let size = tcx.layout_of(param_env.and(discr_ty)).unwrap().size; let const_cmp = Operand::const_from_scalar( tcx, @@ -394,14 +396,16 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp { return None; } - // We first compare the two branches, and then the other branches need to fulfill the same conditions. + // We first compare the two branches, and then the other branches need to fulfill the same + // conditions. let mut expected_transform_kinds = Vec::new(); for (f, s) in iter::zip(first_stmts, second_stmts) { let compare_type = match (&f.kind, &s.kind) { // If two statements are exactly the same, we can optimize. (f_s, s_s) if f_s == s_s => ExpectedTransformKind::Same(f_s), - // If two statements are assignments with the match values to the same place, we can optimize. + // If two statements are assignments with the match values to the same place, we + // can optimize. ( StatementKind::Assign(box (lhs_f, Rvalue::Use(Operand::Constant(f_c)))), StatementKind::Assign(box (lhs_s, Rvalue::Use(Operand::Constant(s_c)))), diff --git a/compiler/rustc_mir_transform/src/mentioned_items.rs b/compiler/rustc_mir_transform/src/mentioned_items.rs index 7f9d0a5b6985c..4402e0dd42d40 100644 --- a/compiler/rustc_mir_transform/src/mentioned_items.rs +++ b/compiler/rustc_mir_transform/src/mentioned_items.rs @@ -82,7 +82,9 @@ impl<'tcx> Visitor<'tcx> for MentionedItemsVisitor<'_, 'tcx> { source_ty.builtin_deref(true).map(|t| t.kind()), target_ty.builtin_deref(true).map(|t| t.kind()), ) { - (Some(ty::Array(..)), Some(ty::Str | ty::Slice(..))) => false, // &str/&[T] unsizing + // &str/&[T] unsizing + (Some(ty::Array(..)), Some(ty::Str | ty::Slice(..))) => false, + _ => true, }; if may_involve_vtable { diff --git a/compiler/rustc_mir_transform/src/prettify.rs b/compiler/rustc_mir_transform/src/prettify.rs index ef011d230c279..937c207776b35 100644 --- a/compiler/rustc_mir_transform/src/prettify.rs +++ b/compiler/rustc_mir_transform/src/prettify.rs @@ -63,7 +63,7 @@ impl<'tcx> crate::MirPass<'tcx> for ReorderLocals { finder.visit_basic_block_data(bb, bbd); } - // track everything in case there are some locals that we never saw, + // Track everything in case there are some locals that we never saw, // such as in non-block things like debug info or in non-uses. for local in body.local_decls.indices() { finder.track(local); @@ -87,7 +87,7 @@ impl<'tcx> crate::MirPass<'tcx> for ReorderLocals { fn permute(data: &mut IndexVec, map: &IndexSlice) { // FIXME: It would be nice to have a less-awkward way to apply permutations, - // but I don't know one that exists. `sort_by_cached_key` has logic for it + // but I don't know one that exists. `sort_by_cached_key` has logic for it // internally, but not in a way that we're allowed to use here. let mut enumerated: Vec<_> = std::mem::take(data).into_iter_enumerated().collect(); enumerated.sort_by_key(|p| map[p.0]); diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index 65309f63d5937..c968053a6d6e8 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -1,16 +1,14 @@ //! A pass that promotes borrows of constant rvalues. //! -//! The rvalues considered constant are trees of temps, -//! each with exactly one initialization, and holding -//! a constant value with no interior mutability. -//! They are placed into a new MIR constant body in -//! `promoted` and the borrow rvalue is replaced with -//! a `Literal::Promoted` using the index into `promoted` -//! of that constant MIR. +//! The rvalues considered constant are trees of temps, each with exactly one +//! initialization, and holding a constant value with no interior mutability. +//! They are placed into a new MIR constant body in `promoted` and the borrow +//! rvalue is replaced with a `Literal::Promoted` using the index into +//! `promoted` of that constant MIR. //! -//! This pass assumes that every use is dominated by an -//! initialization and can otherwise silence errors, if -//! move analysis runs after promotion on broken MIR. +//! This pass assumes that every use is dominated by an initialization and can +//! otherwise silence errors, if move analysis runs after promotion on broken +//! MIR. use std::assert_matches::assert_matches; use std::cell::Cell; @@ -386,7 +384,8 @@ impl<'tcx> Validator<'_, 'tcx> { fn validate_ref(&mut self, kind: BorrowKind, place: &Place<'tcx>) -> Result<(), Unpromotable> { match kind { // Reject these borrow types just to be safe. - // FIXME(RalfJung): could we allow them? Should we? No point in it until we have a usecase. + // FIXME(RalfJung): could we allow them? Should we? No point in it until we have a + // usecase. BorrowKind::Fake(_) | BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture } => { return Err(Unpromotable); } @@ -468,7 +467,8 @@ impl<'tcx> Validator<'_, 'tcx> { let lhs_ty = lhs.ty(self.body, self.tcx); if let ty::RawPtr(_, _) | ty::FnPtr(..) = lhs_ty.kind() { - // Raw and fn pointer operations are not allowed inside consts and thus not promotable. + // Raw and fn pointer operations are not allowed inside consts and thus not + // promotable. assert_matches!( op, BinOp::Eq @@ -498,7 +498,8 @@ impl<'tcx> Validator<'_, 'tcx> { Some(x) if x != 0 => {} // okay _ => return Err(Unpromotable), // value not known or 0 -- not okay } - // Furthermore, for signed division, we also have to exclude `int::MIN / -1`. + // Furthermore, for signed division, we also have to exclude `int::MIN / + // -1`. if lhs_ty.is_signed() { match rhs_val.map(|x| x.to_int(sz)) { Some(-1) | None => { @@ -512,8 +513,11 @@ impl<'tcx> Validator<'_, 'tcx> { }; let lhs_min = sz.signed_int_min(); match lhs_val.map(|x| x.to_int(sz)) { - Some(x) if x != lhs_min => {} // okay - _ => return Err(Unpromotable), // value not known or int::MIN -- not okay + // okay + Some(x) if x != lhs_min => {} + + // value not known or int::MIN -- not okay + _ => return Err(Unpromotable), } } _ => {} @@ -815,8 +819,8 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { TerminatorKind::Call { mut func, mut args, call_source: desugar, fn_span, .. } => { - // This promoted involves a function call, so it may fail to evaluate. - // Let's make sure it is added to `required_consts` so that failure cannot get lost. + // This promoted involves a function call, so it may fail to evaluate. Let's + // make sure it is added to `required_consts` so that failure cannot get lost. self.add_to_required = true; self.visit_operand(&mut func, loc); diff --git a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs index c58f492655a84..d80a4edecdf37 100644 --- a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs @@ -106,8 +106,9 @@ fn is_needs_drop_and_init<'tcx>( // If its projection *is* present in `MoveData`, then the field may have been moved // from separate from its parent. Recurse. adt.variants().iter_enumerated().any(|(vid, variant)| { - // Enums have multiple variants, which are discriminated with a `Downcast` projection. - // Structs have a single variant, and don't use a `Downcast` projection. + // Enums have multiple variants, which are discriminated with a `Downcast` + // projection. Structs have a single variant, and don't use a `Downcast` + // projection. let mpi = if adt.is_enum() { let downcast = move_path_children_matching(move_data, mpi, |x| x.is_downcast_to(vid)); diff --git a/compiler/rustc_mir_transform/src/reveal_all.rs b/compiler/rustc_mir_transform/src/reveal_all.rs index 3db962bd94aee..f3b2f78b31c3a 100644 --- a/compiler/rustc_mir_transform/src/reveal_all.rs +++ b/compiler/rustc_mir_transform/src/reveal_all.rs @@ -35,9 +35,9 @@ impl<'tcx> MutVisitor<'tcx> for RevealAllVisitor<'tcx> { if place.projection.iter().all(|elem| !matches!(elem, ProjectionElem::OpaqueCast(_))) { return; } - // `OpaqueCast` projections are only needed if there are opaque types on which projections are performed. - // After the `RevealAll` pass, all opaque types are replaced with their hidden types, so we don't need these - // projections anymore. + // `OpaqueCast` projections are only needed if there are opaque types on which projections + // are performed. After the `RevealAll` pass, all opaque types are replaced with their + // hidden types, so we don't need these projections anymore. place.projection = self.tcx.mk_place_elems( &place .projection diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index cf8ef580b2720..e1615c76bb6f9 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -1003,7 +1003,8 @@ fn build_fn_ptr_addr_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'t let locals = local_decls_for_sig(&sig, span); let source_info = SourceInfo::outermost(span); - // FIXME: use `expose_provenance` once we figure out whether function pointers have meaningful provenance. + // FIXME: use `expose_provenance` once we figure out whether function pointers have meaningful + // provenance. let rvalue = Rvalue::Cast( CastKind::FnPtrToPtr, Operand::Move(Place::from(Local::new(1))), diff --git a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs index 644bcb58d567d..e8d8335b136b5 100644 --- a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs +++ b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs @@ -73,12 +73,13 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral { _ => unreachable!(), } - // delete comparison statement if it the value being switched on was moved, which means it can not be user later on + // delete comparison statement if it the value being switched on was moved, which means + // it can not be user later on if opt.can_remove_bin_op_stmt { bb.statements[opt.bin_op_stmt_idx].make_nop(); } else { - // if the integer being compared to a const integral is being moved into the comparison, - // e.g `_2 = Eq(move _3, const 'x');` + // if the integer being compared to a const integral is being moved into the + // comparison, e.g `_2 = Eq(move _3, const 'x');` // we want to avoid making a double move later on in the switchInt on _3. // So to avoid `switchInt(move _3) -> ['x': bb2, otherwise: bb1];`, // we convert the move in the comparison statement to a copy. @@ -102,12 +103,15 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral { // remove StorageDead (if it exists) being used in the assign of the comparison for (stmt_idx, stmt) in bb.statements.iter().enumerate() { - if !matches!(stmt.kind, StatementKind::StorageDead(local) if local == opt.to_switch_on.local) - { + if !matches!( + stmt.kind, + StatementKind::StorageDead(local) if local == opt.to_switch_on.local + ) { continue; } storage_deads_to_remove.push((stmt_idx, opt.bb_idx)); - // if we have StorageDeads to remove then make sure to insert them at the top of each target + // if we have StorageDeads to remove then make sure to insert them at the top of + // each target for bb_idx in new_targets.all_targets() { storage_deads_to_insert.push(( *bb_idx, @@ -207,7 +211,8 @@ fn find_branch_value_info<'tcx>( (Constant(branch_value), Copy(to_switch_on) | Move(to_switch_on)) | (Copy(to_switch_on) | Move(to_switch_on), Constant(branch_value)) => { let branch_value_ty = branch_value.const_.ty(); - // we only want to apply this optimization if we are matching on integrals (and chars), as it is not possible to switch on floats + // we only want to apply this optimization if we are matching on integrals (and chars), + // as it is not possible to switch on floats if !branch_value_ty.is_integral() && !branch_value_ty.is_char() { return None; }; @@ -222,7 +227,8 @@ fn find_branch_value_info<'tcx>( struct OptimizationInfo<'tcx> { /// Basic block to apply the optimization bb_idx: BasicBlock, - /// Statement index of Eq/Ne assignment that can be removed. None if the assignment can not be removed - i.e the statement is used later on + /// Statement index of Eq/Ne assignment that can be removed. None if the assignment can not be + /// removed - i.e the statement is used later on bin_op_stmt_idx: usize, /// Can remove Eq/Ne assignment can_remove_bin_op_stmt: bool, diff --git a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs index 6957394ed1044..5612e779d6bca 100644 --- a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs +++ b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs @@ -156,9 +156,9 @@ impl<'tcx> crate::MirPass<'tcx> for UnreachableEnumBranching { }; true } - // If and only if there is a variant that does not have a branch set, - // change the current of otherwise as the variant branch and set otherwise to unreachable. - // It transforms following code + // If and only if there is a variant that does not have a branch set, change the + // current of otherwise as the variant branch and set otherwise to unreachable. It + // transforms following code // ```rust // match c { // Ordering::Less => 1, diff --git a/compiler/rustc_mir_transform/src/unreachable_prop.rs b/compiler/rustc_mir_transform/src/unreachable_prop.rs index c60cbae21422c..f3dafd13824f3 100644 --- a/compiler/rustc_mir_transform/src/unreachable_prop.rs +++ b/compiler/rustc_mir_transform/src/unreachable_prop.rs @@ -26,7 +26,8 @@ impl crate::MirPass<'_> for UnreachablePropagation { let terminator = bb_data.terminator(); let is_unreachable = match &terminator.kind { TerminatorKind::Unreachable => true, - // This will unconditionally run into an unreachable and is therefore unreachable as well. + // This will unconditionally run into an unreachable and is therefore unreachable + // as well. TerminatorKind::Goto { target } if unreachable_blocks.contains(target) => { patch.patch_terminator(bb, TerminatorKind::Unreachable); true @@ -85,8 +86,9 @@ fn remove_successors_from_switch<'tcx>( // } // } // - // This generates a `switchInt() -> [0: 0, 1: 1, otherwise: unreachable]`, which allows us or LLVM to - // turn it into just `x` later. Without the unreachable, such a transformation would be illegal. + // This generates a `switchInt() -> [0: 0, 1: 1, otherwise: unreachable]`, which allows us or + // LLVM to turn it into just `x` later. Without the unreachable, such a transformation would be + // illegal. // // In order to preserve this information, we record reachable and unreachable targets as // `Assume` statements in MIR. diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 18865c73f75b1..3b84755ddedde 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -388,10 +388,11 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { } self.check_unwind_edge(location, unwind); - // The code generation assumes that there are no critical call edges. The assumption - // is used to simplify inserting code that should be executed along the return edge - // from the call. FIXME(tmiasko): Since this is a strictly code generation concern, - // the code generation should be responsible for handling it. + // The code generation assumes that there are no critical call edges. The + // assumption is used to simplify inserting code that should be executed along + // the return edge from the call. FIXME(tmiasko): Since this is a strictly code + // generation concern, the code generation should be responsible for handling + // it. if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Optimized) && self.is_critical_call_edge(target, unwind) { @@ -404,8 +405,8 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { ); } - // The call destination place and Operand::Move place used as an argument might be - // passed by a reference to the callee. Consequently they cannot be packed. + // The call destination place and Operand::Move place used as an argument might + // be passed by a reference to the callee. Consequently they cannot be packed. if is_within_packed(self.tcx, &self.body.local_decls, destination).is_some() { // This is bad! The callee will expect the memory to be aligned. self.fail( @@ -953,9 +954,9 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } AggregateKind::RawPtr(pointee_ty, mutability) => { if !matches!(self.mir_phase, MirPhase::Runtime(_)) { - // It would probably be fine to support this in earlier phases, - // but at the time of writing it's only ever introduced from intrinsic lowering, - // so earlier things just `bug!` on it. + // It would probably be fine to support this in earlier phases, but at the + // time of writing it's only ever introduced from intrinsic lowering, so + // earlier things just `bug!` on it. self.fail(location, "RawPtr should be in runtime MIR only"); } @@ -1109,10 +1110,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } UnOp::PtrMetadata => { if !matches!(self.mir_phase, MirPhase::Runtime(_)) { - // It would probably be fine to support this in earlier phases, - // but at the time of writing it's only ever introduced from intrinsic lowering - // or other runtime-phase optimization passes, - // so earlier things can just `bug!` on it. + // It would probably be fine to support this in earlier phases, but at + // the time of writing it's only ever introduced from intrinsic + // lowering or other runtime-phase optimization passes, so earlier + // things can just `bug!` on it. self.fail(location, "PtrMetadata should be in runtime MIR only"); } @@ -1506,7 +1507,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } if let TerminatorKind::TailCall { .. } = terminator.kind { - // FIXME(explicit_tail_calls): implement tail-call specific checks here (such as signature matching, forbidding closures, etc) + // FIXME(explicit_tail_calls): implement tail-call specific checks here (such + // as signature matching, forbidding closures, etc) } } TerminatorKind::Assert { cond, .. } => { From 48064d44982d505412d9328004ed5cc67cb5f210 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 28 Aug 2024 10:13:17 +1000 Subject: [PATCH 122/189] Inline and remove some functions. These are all functions with a single callsite, where having a separate function does nothing to help with readability. These changes make the code a little shorter and easier to read. --- .../src/add_call_guards.rs | 6 - .../src/add_moves_for_packed_drops.rs | 45 ++- .../src/add_subtyping_projections.rs | 18 +- compiler/rustc_mir_transform/src/copy_prop.rs | 45 ++- compiler/rustc_mir_transform/src/gvn.rs | 85 +++-- .../rustc_mir_transform/src/instsimplify.rs | 8 +- .../rustc_mir_transform/src/large_enums.rs | 345 +++++++++--------- .../src/lower_slice_len.rs | 26 +- .../src/remove_noop_landing_pads.rs | 113 +++--- compiler/rustc_mir_transform/src/simplify.rs | 48 ++- 10 files changed, 344 insertions(+), 395 deletions(-) diff --git a/compiler/rustc_mir_transform/src/add_call_guards.rs b/compiler/rustc_mir_transform/src/add_call_guards.rs index 18a0746f54f08..24c955c0c78c6 100644 --- a/compiler/rustc_mir_transform/src/add_call_guards.rs +++ b/compiler/rustc_mir_transform/src/add_call_guards.rs @@ -32,12 +32,6 @@ pub(super) use self::AddCallGuards::*; impl<'tcx> crate::MirPass<'tcx> for AddCallGuards { fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - self.add_call_guards(body); - } -} - -impl AddCallGuards { - pub(super) fn add_call_guards(&self, body: &mut Body<'_>) { let mut pred_count: IndexVec<_, _> = body.basic_blocks.predecessors().iter().map(|ps| ps.len()).collect(); pred_count[START_BLOCK] += 1; diff --git a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs index 47572d8d3b22b..74df5f7479e06 100644 --- a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs +++ b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs @@ -40,35 +40,34 @@ pub(super) struct AddMovesForPackedDrops; impl<'tcx> crate::MirPass<'tcx> for AddMovesForPackedDrops { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { debug!("add_moves_for_packed_drops({:?} @ {:?})", body.source, body.span); - add_moves_for_packed_drops(tcx, body); - } -} - -fn add_moves_for_packed_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let patch = add_moves_for_packed_drops_patch(tcx, body); - patch.apply(body); -} -fn add_moves_for_packed_drops_patch<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> MirPatch<'tcx> { - let def_id = body.source.def_id(); - let mut patch = MirPatch::new(body); - let param_env = tcx.param_env(def_id); + let def_id = body.source.def_id(); + let mut patch = MirPatch::new(body); + let param_env = tcx.param_env(def_id); - for (bb, data) in body.basic_blocks.iter_enumerated() { - let loc = Location { block: bb, statement_index: data.statements.len() }; - let terminator = data.terminator(); + for (bb, data) in body.basic_blocks.iter_enumerated() { + let loc = Location { block: bb, statement_index: data.statements.len() }; + let terminator = data.terminator(); - match terminator.kind { - TerminatorKind::Drop { place, .. } - if util::is_disaligned(tcx, body, param_env, place) => - { - add_move_for_packed_drop(tcx, body, &mut patch, terminator, loc, data.is_cleanup); + match terminator.kind { + TerminatorKind::Drop { place, .. } + if util::is_disaligned(tcx, body, param_env, place) => + { + add_move_for_packed_drop( + tcx, + body, + &mut patch, + terminator, + loc, + data.is_cleanup, + ); + } + _ => {} } - _ => {} } - } - patch + patch.apply(body); + } } fn add_move_for_packed_drop<'tcx>( diff --git a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs index ab6bf18b30cb3..e585e338613d8 100644 --- a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs +++ b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs @@ -51,18 +51,14 @@ impl<'a, 'tcx> MutVisitor<'tcx> for SubTypeChecker<'a, 'tcx> { // // gets transformed to // let temp: rval_ty = rval; // let place: place_ty = temp as place_ty; -fn subtype_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let patch = MirPatch::new(body); - let mut checker = SubTypeChecker { tcx, patcher: patch, local_decls: &body.local_decls }; - - for (bb, data) in body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut() { - checker.visit_basic_block_data(bb, data); - } - checker.patcher.apply(body); -} - impl<'tcx> crate::MirPass<'tcx> for Subtyper { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - subtype_finder(tcx, body); + let patch = MirPatch::new(body); + let mut checker = SubTypeChecker { tcx, patcher: patch, local_decls: &body.local_decls }; + + for (bb, data) in body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut() { + checker.visit_basic_block_data(bb, data); + } + checker.patcher.apply(body); } } diff --git a/compiler/rustc_mir_transform/src/copy_prop.rs b/compiler/rustc_mir_transform/src/copy_prop.rs index 1cb56d29b85e0..b3db566912108 100644 --- a/compiler/rustc_mir_transform/src/copy_prop.rs +++ b/compiler/rustc_mir_transform/src/copy_prop.rs @@ -27,37 +27,34 @@ impl<'tcx> crate::MirPass<'tcx> for CopyProp { #[instrument(level = "trace", skip(self, tcx, body))] fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { debug!(def_id = ?body.source.def_id()); - propagate_ssa(tcx, body); - } -} -fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); - let ssa = SsaLocals::new(tcx, body, param_env); + let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); + let ssa = SsaLocals::new(tcx, body, param_env); - let fully_moved = fully_moved_locals(&ssa, body); - debug!(?fully_moved); + let fully_moved = fully_moved_locals(&ssa, body); + debug!(?fully_moved); - let mut storage_to_remove = BitSet::new_empty(fully_moved.domain_size()); - for (local, &head) in ssa.copy_classes().iter_enumerated() { - if local != head { - storage_to_remove.insert(head); + let mut storage_to_remove = BitSet::new_empty(fully_moved.domain_size()); + for (local, &head) in ssa.copy_classes().iter_enumerated() { + if local != head { + storage_to_remove.insert(head); + } } - } - let any_replacement = ssa.copy_classes().iter_enumerated().any(|(l, &h)| l != h); + let any_replacement = ssa.copy_classes().iter_enumerated().any(|(l, &h)| l != h); - Replacer { - tcx, - copy_classes: ssa.copy_classes(), - fully_moved, - borrowed_locals: ssa.borrowed_locals(), - storage_to_remove, - } - .visit_body_preserves_cfg(body); + Replacer { + tcx, + copy_classes: ssa.copy_classes(), + fully_moved, + borrowed_locals: ssa.borrowed_locals(), + storage_to_remove, + } + .visit_body_preserves_cfg(body); - if any_replacement { - crate::simplify::remove_unused_definitions(body); + if any_replacement { + crate::simplify::remove_unused_definitions(body); + } } } diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 715461de06482..d514664f368d6 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -119,53 +119,50 @@ impl<'tcx> crate::MirPass<'tcx> for GVN { #[instrument(level = "trace", skip(self, tcx, body))] fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { debug!(def_id = ?body.source.def_id()); - propagate_ssa(tcx, body); - } -} -fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); - let ssa = SsaLocals::new(tcx, body, param_env); - // Clone dominators as we need them while mutating the body. - let dominators = body.basic_blocks.dominators().clone(); - - let mut state = VnState::new(tcx, body, param_env, &ssa, &dominators, &body.local_decls); - ssa.for_each_assignment_mut( - body.basic_blocks.as_mut_preserves_cfg(), - |local, value, location| { - let value = match value { - // We do not know anything of this assigned value. - AssignedValue::Arg | AssignedValue::Terminator => None, - // Try to get some insight. - AssignedValue::Rvalue(rvalue) => { - let value = state.simplify_rvalue(rvalue, location); - // FIXME(#112651) `rvalue` may have a subtype to `local`. We can only mark - // `local` as reusable if we have an exact type match. - if state.local_decls[local].ty != rvalue.ty(state.local_decls, tcx) { - return; + let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); + let ssa = SsaLocals::new(tcx, body, param_env); + // Clone dominators as we need them while mutating the body. + let dominators = body.basic_blocks.dominators().clone(); + + let mut state = VnState::new(tcx, body, param_env, &ssa, &dominators, &body.local_decls); + ssa.for_each_assignment_mut( + body.basic_blocks.as_mut_preserves_cfg(), + |local, value, location| { + let value = match value { + // We do not know anything of this assigned value. + AssignedValue::Arg | AssignedValue::Terminator => None, + // Try to get some insight. + AssignedValue::Rvalue(rvalue) => { + let value = state.simplify_rvalue(rvalue, location); + // FIXME(#112651) `rvalue` may have a subtype to `local`. We can only mark + // `local` as reusable if we have an exact type match. + if state.local_decls[local].ty != rvalue.ty(state.local_decls, tcx) { + return; + } + value } - value - } - }; - // `next_opaque` is `Some`, so `new_opaque` must return `Some`. - let value = value.or_else(|| state.new_opaque()).unwrap(); - state.assign(local, value); - }, - ); - - // Stop creating opaques during replacement as it is useless. - state.next_opaque = None; - - let reverse_postorder = body.basic_blocks.reverse_postorder().to_vec(); - for bb in reverse_postorder { - let data = &mut body.basic_blocks.as_mut_preserves_cfg()[bb]; - state.visit_basic_block_data(bb, data); - } + }; + // `next_opaque` is `Some`, so `new_opaque` must return `Some`. + let value = value.or_else(|| state.new_opaque()).unwrap(); + state.assign(local, value); + }, + ); + + // Stop creating opaques during replacement as it is useless. + state.next_opaque = None; - // For each local that is reused (`y` above), we remove its storage statements do avoid any - // difficulty. Those locals are SSA, so should be easy to optimize by LLVM without storage - // statements. - StorageRemover { tcx, reused_locals: state.reused_locals }.visit_body_preserves_cfg(body); + let reverse_postorder = body.basic_blocks.reverse_postorder().to_vec(); + for bb in reverse_postorder { + let data = &mut body.basic_blocks.as_mut_preserves_cfg()[bb]; + state.visit_basic_block_data(bb, data); + } + + // For each local that is reused (`y` above), we remove its storage statements do avoid any + // difficulty. Those locals are SSA, so should be easy to optimize by LLVM without storage + // statements. + StorageRemover { tcx, reused_locals: state.reused_locals }.visit_body_preserves_cfg(body); + } } newtype_index! { diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index a9591bf39848f..0b344f29b078b 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -18,19 +18,13 @@ pub(super) enum InstSimplify { AfterSimplifyCfg, } -impl InstSimplify { +impl<'tcx> crate::MirPass<'tcx> for InstSimplify { fn name(&self) -> &'static str { match self { InstSimplify::BeforeInline => "InstSimplify-before-inline", InstSimplify::AfterSimplifyCfg => "InstSimplify-after-simplifycfg", } } -} - -impl<'tcx> crate::MirPass<'tcx> for InstSimplify { - fn name(&self) -> &'static str { - self.name() - } fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.mir_opt_level() > 0 diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs index 45edcff29eb28..8a33849f20e0b 100644 --- a/compiler/rustc_mir_transform/src/large_enums.rs +++ b/compiler/rustc_mir_transform/src/large_enums.rs @@ -37,7 +37,169 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // NOTE: This pass may produce different MIR based on the alignment of the target // platform, but it will still be valid. - self.optim(tcx, body); + + let mut alloc_cache = FxHashMap::default(); + let body_did = body.source.def_id(); + let param_env = tcx.param_env_reveal_all_normalized(body_did); + + let blocks = body.basic_blocks.as_mut(); + let local_decls = &mut body.local_decls; + + for bb in blocks { + bb.expand_statements(|st| { + let StatementKind::Assign(box ( + lhs, + Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs)), + )) = &st.kind + else { + return None; + }; + + let ty = lhs.ty(local_decls, tcx).ty; + + let (adt_def, num_variants, alloc_id) = + self.candidate(tcx, param_env, ty, &mut alloc_cache)?; + + let source_info = st.source_info; + let span = source_info.span; + + let tmp_ty = Ty::new_array(tcx, tcx.types.usize, num_variants as u64); + let size_array_local = local_decls.push(LocalDecl::new(tmp_ty, span)); + let store_live = + Statement { source_info, kind: StatementKind::StorageLive(size_array_local) }; + + let place = Place::from(size_array_local); + let constant_vals = ConstOperand { + span, + user_ty: None, + const_: Const::Val( + ConstValue::Indirect { alloc_id, offset: Size::ZERO }, + tmp_ty, + ), + }; + let rval = Rvalue::Use(Operand::Constant(Box::new(constant_vals))); + let const_assign = + Statement { source_info, kind: StatementKind::Assign(Box::new((place, rval))) }; + + let discr_place = Place::from( + local_decls.push(LocalDecl::new(adt_def.repr().discr_type().to_ty(tcx), span)), + ); + let store_discr = Statement { + source_info, + kind: StatementKind::Assign(Box::new(( + discr_place, + Rvalue::Discriminant(*rhs), + ))), + }; + + let discr_cast_place = + Place::from(local_decls.push(LocalDecl::new(tcx.types.usize, span))); + let cast_discr = Statement { + source_info, + kind: StatementKind::Assign(Box::new(( + discr_cast_place, + Rvalue::Cast( + CastKind::IntToInt, + Operand::Copy(discr_place), + tcx.types.usize, + ), + ))), + }; + + let size_place = + Place::from(local_decls.push(LocalDecl::new(tcx.types.usize, span))); + let store_size = Statement { + source_info, + kind: StatementKind::Assign(Box::new(( + size_place, + Rvalue::Use(Operand::Copy(Place { + local: size_array_local, + projection: tcx + .mk_place_elems(&[PlaceElem::Index(discr_cast_place.local)]), + })), + ))), + }; + + let dst = + Place::from(local_decls.push(LocalDecl::new(Ty::new_mut_ptr(tcx, ty), span))); + let dst_ptr = Statement { + source_info, + kind: StatementKind::Assign(Box::new(( + dst, + Rvalue::RawPtr(Mutability::Mut, *lhs), + ))), + }; + + let dst_cast_ty = Ty::new_mut_ptr(tcx, tcx.types.u8); + let dst_cast_place = + Place::from(local_decls.push(LocalDecl::new(dst_cast_ty, span))); + let dst_cast = Statement { + source_info, + kind: StatementKind::Assign(Box::new(( + dst_cast_place, + Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(dst), dst_cast_ty), + ))), + }; + + let src = + Place::from(local_decls.push(LocalDecl::new(Ty::new_imm_ptr(tcx, ty), span))); + let src_ptr = Statement { + source_info, + kind: StatementKind::Assign(Box::new(( + src, + Rvalue::RawPtr(Mutability::Not, *rhs), + ))), + }; + + let src_cast_ty = Ty::new_imm_ptr(tcx, tcx.types.u8); + let src_cast_place = + Place::from(local_decls.push(LocalDecl::new(src_cast_ty, span))); + let src_cast = Statement { + source_info, + kind: StatementKind::Assign(Box::new(( + src_cast_place, + Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(src), src_cast_ty), + ))), + }; + + let deinit_old = + Statement { source_info, kind: StatementKind::Deinit(Box::new(dst)) }; + + let copy_bytes = Statement { + source_info, + kind: StatementKind::Intrinsic(Box::new( + NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping { + src: Operand::Copy(src_cast_place), + dst: Operand::Copy(dst_cast_place), + count: Operand::Copy(size_place), + }), + )), + }; + + let store_dead = + Statement { source_info, kind: StatementKind::StorageDead(size_array_local) }; + + let iter = [ + store_live, + const_assign, + store_discr, + cast_discr, + store_size, + dst_ptr, + dst_cast, + src_ptr, + src_cast, + deinit_old, + copy_bytes, + store_dead, + ] + .into_iter(); + + st.make_nop(); + + Some(iter) + }); + } } } @@ -116,185 +278,4 @@ impl EnumSizeOpt { let alloc = tcx.reserve_and_set_memory_alloc(tcx.mk_const_alloc(alloc)); Some((*adt_def, num_discrs, *alloc_cache.entry(ty).or_insert(alloc))) } - - fn optim<'tcx>(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let mut alloc_cache = FxHashMap::default(); - let body_did = body.source.def_id(); - let param_env = tcx.param_env_reveal_all_normalized(body_did); - - let blocks = body.basic_blocks.as_mut(); - let local_decls = &mut body.local_decls; - - for bb in blocks { - bb.expand_statements(|st| { - if let StatementKind::Assign(box ( - lhs, - Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs)), - )) = &st.kind - { - let ty = lhs.ty(local_decls, tcx).ty; - - let source_info = st.source_info; - let span = source_info.span; - - let (adt_def, num_variants, alloc_id) = - self.candidate(tcx, param_env, ty, &mut alloc_cache)?; - - let tmp_ty = Ty::new_array(tcx, tcx.types.usize, num_variants as u64); - - let size_array_local = local_decls.push(LocalDecl::new(tmp_ty, span)); - let store_live = Statement { - source_info, - kind: StatementKind::StorageLive(size_array_local), - }; - - let place = Place::from(size_array_local); - let constant_vals = ConstOperand { - span, - user_ty: None, - const_: Const::Val( - ConstValue::Indirect { alloc_id, offset: Size::ZERO }, - tmp_ty, - ), - }; - let rval = Rvalue::Use(Operand::Constant(Box::new(constant_vals))); - - let const_assign = Statement { - source_info, - kind: StatementKind::Assign(Box::new((place, rval))), - }; - - let discr_place = Place::from( - local_decls - .push(LocalDecl::new(adt_def.repr().discr_type().to_ty(tcx), span)), - ); - - let store_discr = Statement { - source_info, - kind: StatementKind::Assign(Box::new(( - discr_place, - Rvalue::Discriminant(*rhs), - ))), - }; - - let discr_cast_place = - Place::from(local_decls.push(LocalDecl::new(tcx.types.usize, span))); - - let cast_discr = Statement { - source_info, - kind: StatementKind::Assign(Box::new(( - discr_cast_place, - Rvalue::Cast( - CastKind::IntToInt, - Operand::Copy(discr_place), - tcx.types.usize, - ), - ))), - }; - - let size_place = - Place::from(local_decls.push(LocalDecl::new(tcx.types.usize, span))); - - let store_size = Statement { - source_info, - kind: StatementKind::Assign(Box::new(( - size_place, - Rvalue::Use(Operand::Copy(Place { - local: size_array_local, - projection: tcx - .mk_place_elems(&[PlaceElem::Index(discr_cast_place.local)]), - })), - ))), - }; - - let dst = Place::from( - local_decls.push(LocalDecl::new(Ty::new_mut_ptr(tcx, ty), span)), - ); - - let dst_ptr = Statement { - source_info, - kind: StatementKind::Assign(Box::new(( - dst, - Rvalue::RawPtr(Mutability::Mut, *lhs), - ))), - }; - - let dst_cast_ty = Ty::new_mut_ptr(tcx, tcx.types.u8); - let dst_cast_place = - Place::from(local_decls.push(LocalDecl::new(dst_cast_ty, span))); - - let dst_cast = Statement { - source_info, - kind: StatementKind::Assign(Box::new(( - dst_cast_place, - Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(dst), dst_cast_ty), - ))), - }; - - let src = Place::from( - local_decls.push(LocalDecl::new(Ty::new_imm_ptr(tcx, ty), span)), - ); - - let src_ptr = Statement { - source_info, - kind: StatementKind::Assign(Box::new(( - src, - Rvalue::RawPtr(Mutability::Not, *rhs), - ))), - }; - - let src_cast_ty = Ty::new_imm_ptr(tcx, tcx.types.u8); - let src_cast_place = - Place::from(local_decls.push(LocalDecl::new(src_cast_ty, span))); - - let src_cast = Statement { - source_info, - kind: StatementKind::Assign(Box::new(( - src_cast_place, - Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(src), src_cast_ty), - ))), - }; - - let deinit_old = - Statement { source_info, kind: StatementKind::Deinit(Box::new(dst)) }; - - let copy_bytes = Statement { - source_info, - kind: StatementKind::Intrinsic(Box::new( - NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping { - src: Operand::Copy(src_cast_place), - dst: Operand::Copy(dst_cast_place), - count: Operand::Copy(size_place), - }), - )), - }; - - let store_dead = Statement { - source_info, - kind: StatementKind::StorageDead(size_array_local), - }; - let iter = [ - store_live, - const_assign, - store_discr, - cast_discr, - store_size, - dst_ptr, - dst_cast, - src_ptr, - src_cast, - deinit_old, - copy_bytes, - store_dead, - ] - .into_iter(); - - st.make_nop(); - Some(iter) - } else { - None - } - }); - } - } } diff --git a/compiler/rustc_mir_transform/src/lower_slice_len.rs b/compiler/rustc_mir_transform/src/lower_slice_len.rs index ca59d4d12acad..420661f29c8cf 100644 --- a/compiler/rustc_mir_transform/src/lower_slice_len.rs +++ b/compiler/rustc_mir_transform/src/lower_slice_len.rs @@ -13,22 +13,18 @@ impl<'tcx> crate::MirPass<'tcx> for LowerSliceLenCalls { } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - lower_slice_len_calls(tcx, body) - } -} - -fn lower_slice_len_calls<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let language_items = tcx.lang_items(); - let Some(slice_len_fn_item_def_id) = language_items.slice_len_fn() else { - // there is no lang item to compare to :) - return; - }; + let language_items = tcx.lang_items(); + let Some(slice_len_fn_item_def_id) = language_items.slice_len_fn() else { + // there is no lang item to compare to :) + return; + }; - // The one successor remains unchanged, so no need to invalidate - let basic_blocks = body.basic_blocks.as_mut_preserves_cfg(); - for block in basic_blocks { - // lower `<[_]>::len` calls - lower_slice_len_call(block, slice_len_fn_item_def_id); + // The one successor remains unchanged, so no need to invalidate + let basic_blocks = body.basic_blocks.as_mut_preserves_cfg(); + for block in basic_blocks { + // lower `<[_]>::len` calls + lower_slice_len_call(block, slice_len_fn_item_def_id); + } } } diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs index 37197c3f573d3..55394e93a5cb7 100644 --- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs +++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs @@ -18,7 +18,61 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveNoopLandingPads { fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let def_id = body.source.def_id(); debug!(?def_id); - self.remove_nop_landing_pads(body) + + // Skip the pass if there are no blocks with a resume terminator. + let has_resume = body + .basic_blocks + .iter_enumerated() + .any(|(_bb, block)| matches!(block.terminator().kind, TerminatorKind::UnwindResume)); + if !has_resume { + debug!("remove_noop_landing_pads: no resume block in MIR"); + return; + } + + // make sure there's a resume block without any statements + let resume_block = { + let mut patch = MirPatch::new(body); + let resume_block = patch.resume_block(); + patch.apply(body); + resume_block + }; + debug!("remove_noop_landing_pads: resume block is {:?}", resume_block); + + let mut jumps_folded = 0; + let mut landing_pads_removed = 0; + let mut nop_landing_pads = BitSet::new_empty(body.basic_blocks.len()); + + // This is a post-order traversal, so that if A post-dominates B + // then A will be visited before B. + let postorder: Vec<_> = traversal::postorder(body).map(|(bb, _)| bb).collect(); + for bb in postorder { + debug!(" processing {:?}", bb); + if let Some(unwind) = body[bb].terminator_mut().unwind_mut() { + if let UnwindAction::Cleanup(unwind_bb) = *unwind { + if nop_landing_pads.contains(unwind_bb) { + debug!(" removing noop landing pad"); + landing_pads_removed += 1; + *unwind = UnwindAction::Continue; + } + } + } + + for target in body[bb].terminator_mut().successors_mut() { + if *target != resume_block && nop_landing_pads.contains(*target) { + debug!(" folding noop jump to {:?} to resume block", target); + *target = resume_block; + jumps_folded += 1; + } + } + + let is_nop_landing_pad = self.is_nop_landing_pad(bb, body, &nop_landing_pads); + if is_nop_landing_pad { + nop_landing_pads.insert(bb); + } + debug!(" is_nop_landing_pad({:?}) = {}", bb, is_nop_landing_pad); + } + + debug!("removed {:?} jumps and {:?} landing pads", jumps_folded, landing_pads_removed); } } @@ -82,61 +136,4 @@ impl RemoveNoopLandingPads { | TerminatorKind::InlineAsm { .. } => false, } } - - fn remove_nop_landing_pads(&self, body: &mut Body<'_>) { - // Skip the pass if there are no blocks with a resume terminator. - let has_resume = body - .basic_blocks - .iter_enumerated() - .any(|(_bb, block)| matches!(block.terminator().kind, TerminatorKind::UnwindResume)); - if !has_resume { - debug!("remove_noop_landing_pads: no resume block in MIR"); - return; - } - - // make sure there's a resume block without any statements - let resume_block = { - let mut patch = MirPatch::new(body); - let resume_block = patch.resume_block(); - patch.apply(body); - resume_block - }; - debug!("remove_noop_landing_pads: resume block is {:?}", resume_block); - - let mut jumps_folded = 0; - let mut landing_pads_removed = 0; - let mut nop_landing_pads = BitSet::new_empty(body.basic_blocks.len()); - - // This is a post-order traversal, so that if A post-dominates B - // then A will be visited before B. - let postorder: Vec<_> = traversal::postorder(body).map(|(bb, _)| bb).collect(); - for bb in postorder { - debug!(" processing {:?}", bb); - if let Some(unwind) = body[bb].terminator_mut().unwind_mut() { - if let UnwindAction::Cleanup(unwind_bb) = *unwind { - if nop_landing_pads.contains(unwind_bb) { - debug!(" removing noop landing pad"); - landing_pads_removed += 1; - *unwind = UnwindAction::Continue; - } - } - } - - for target in body[bb].terminator_mut().successors_mut() { - if *target != resume_block && nop_landing_pads.contains(*target) { - debug!(" folding noop jump to {:?} to resume block", target); - *target = resume_block; - jumps_folded += 1; - } - } - - let is_nop_landing_pad = self.is_nop_landing_pad(bb, body, &nop_landing_pads); - if is_nop_landing_pad { - nop_landing_pads.insert(bb); - } - debug!(" is_nop_landing_pad({:?}) = {}", bb, is_nop_landing_pad); - } - - debug!("removed {:?} jumps and {:?} landing pads", jumps_folded, landing_pads_removed); - } } diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index cb8e1dfda98ba..7ed43547e1127 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -381,23 +381,33 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyLocals { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { trace!("running SimplifyLocals on {:?}", body.source); - simplify_locals(body, tcx); - } -} -pub(super) fn remove_unused_definitions<'tcx>(body: &mut Body<'tcx>) { - // First, we're going to get a count of *actual* uses for every `Local`. - let mut used_locals = UsedLocals::new(body); + // First, we're going to get a count of *actual* uses for every `Local`. + let mut used_locals = UsedLocals::new(body); - // Next, we're going to remove any `Local` with zero actual uses. When we remove those - // `Locals`, we're also going to subtract any uses of other `Locals` from the `used_locals` - // count. For example, if we removed `_2 = discriminant(_1)`, then we'll subtract one from - // `use_counts[_1]`. That in turn might make `_1` unused, so we loop until we hit a - // fixedpoint where there are no more unused locals. - remove_unused_definitions_helper(&mut used_locals, body); + // Next, we're going to remove any `Local` with zero actual uses. When we remove those + // `Locals`, we're also going to subtract any uses of other `Locals` from the `used_locals` + // count. For example, if we removed `_2 = discriminant(_1)`, then we'll subtract one from + // `use_counts[_1]`. That in turn might make `_1` unused, so we loop until we hit a + // fixedpoint where there are no more unused locals. + remove_unused_definitions_helper(&mut used_locals, body); + + // Finally, we'll actually do the work of shrinking `body.local_decls` and remapping the + // `Local`s. + let map = make_local_map(&mut body.local_decls, &used_locals); + + // Only bother running the `LocalUpdater` if we actually found locals to remove. + if map.iter().any(Option::is_none) { + // Update references to all vars and tmps now + let mut updater = LocalUpdater { map, tcx }; + updater.visit_body_preserves_cfg(body); + + body.local_decls.shrink_to_fit(); + } + } } -fn simplify_locals<'tcx>(body: &mut Body<'tcx>, tcx: TyCtxt<'tcx>) { +pub(super) fn remove_unused_definitions<'tcx>(body: &mut Body<'tcx>) { // First, we're going to get a count of *actual* uses for every `Local`. let mut used_locals = UsedLocals::new(body); @@ -407,18 +417,6 @@ fn simplify_locals<'tcx>(body: &mut Body<'tcx>, tcx: TyCtxt<'tcx>) { // `use_counts[_1]`. That in turn might make `_1` unused, so we loop until we hit a // fixedpoint where there are no more unused locals. remove_unused_definitions_helper(&mut used_locals, body); - - // Finally, we'll actually do the work of shrinking `body.local_decls` and remapping the `Local`s. - let map = make_local_map(&mut body.local_decls, &used_locals); - - // Only bother running the `LocalUpdater` if we actually found locals to remove. - if map.iter().any(Option::is_none) { - // Update references to all vars and tmps now - let mut updater = LocalUpdater { map, tcx }; - updater.visit_body_preserves_cfg(body); - - body.local_decls.shrink_to_fit(); - } } /// Construct the mapping while swapping out unused stuff out from the `vec`. From baa16d24715abeed857202ad917a0f05e364b8a5 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 30 Aug 2024 13:51:59 +1000 Subject: [PATCH 123/189] Clarify a comment. The "as" is equivalent to "because", but I originally read it more like "when", which was confusing. --- compiler/rustc_mir_transform/src/gvn.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index d514664f368d6..0b78affc31cc1 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -122,7 +122,7 @@ impl<'tcx> crate::MirPass<'tcx> for GVN { let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); let ssa = SsaLocals::new(tcx, body, param_env); - // Clone dominators as we need them while mutating the body. + // Clone dominators because we need them while mutating the body. let dominators = body.basic_blocks.dominators().clone(); let mut state = VnState::new(tcx, body, param_env, &ssa, &dominators, &body.local_decls); From e26692d559c3b564a3efdd5b6db316c0c67fb52e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 3 Sep 2024 11:00:15 +1000 Subject: [PATCH 124/189] Add a useful comment. --- compiler/rustc_mir_transform/src/large_enums.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs index 8a33849f20e0b..3e263aa406774 100644 --- a/compiler/rustc_mir_transform/src/large_enums.rs +++ b/compiler/rustc_mir_transform/src/large_enums.rs @@ -244,6 +244,8 @@ impl EnumSizeOpt { let ptr_sized_int = data_layout.ptr_sized_integer(); let target_bytes = ptr_sized_int.size().bytes() as usize; let mut data = vec![0; target_bytes * num_discrs]; + + // We use a macro because `$bytes` can be u32 or u64. macro_rules! encode_store { ($curr_idx: expr, $endian: expr, $bytes: expr) => { let bytes = match $endian { From 51e1c3958dd68372c4a4499d59223ccecc1a7955 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 4 Sep 2024 13:20:20 +1000 Subject: [PATCH 125/189] Add a useful comment about `PromoteTemps`. This was non-obvious to me. --- compiler/rustc_mir_transform/src/promote_consts.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index c968053a6d6e8..59df99f858dcf 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -36,6 +36,7 @@ use tracing::{debug, instrument}; /// newly created `Constant`. #[derive(Default)] pub(super) struct PromoteTemps<'tcx> { + // Must use `Cell` because `run_pass` takes `&self`, not `&mut self`. pub promoted_fragments: Cell>>, } From d1c55a305eefedbe3153c7348c4b373ecd07d144 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 4 Sep 2024 13:58:26 +1000 Subject: [PATCH 126/189] Use `IndexVec::from_raw` to construct a const `IndexVec`. --- compiler/rustc_mir_transform/src/shim.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index e1615c76bb6f9..f1bd803d83530 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -404,8 +404,7 @@ fn build_thread_local_shim<'tcx>( let span = tcx.def_span(def_id); let source_info = SourceInfo::outermost(span); - let mut blocks = IndexVec::with_capacity(1); - blocks.push(BasicBlockData { + let blocks = IndexVec::from_raw(vec![BasicBlockData { statements: vec![Statement { source_info, kind: StatementKind::Assign(Box::new(( @@ -415,7 +414,7 @@ fn build_thread_local_shim<'tcx>( }], terminator: Some(Terminator { source_info, kind: TerminatorKind::Return }), is_cleanup: false, - }); + }]); new_body( MirSource::from_instance(instance), From 702340269136b9818359a82c5f7fc659ec26a0bf Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 4 Sep 2024 13:47:26 +1000 Subject: [PATCH 127/189] Remove references from some structs. In all cases the struct can own the relevant thing instead of having a reference to it. This makes the code simpler, and in some cases removes a struct lifetime. --- compiler/rustc_mir_transform/src/dest_prop.rs | 14 +++---- compiler/rustc_mir_transform/src/gvn.rs | 8 ++-- .../rustc_mir_transform/src/jump_threading.rs | 42 +++++++++---------- compiler/rustc_mir_transform/src/lib.rs | 14 ++++--- .../src/mentioned_items.rs | 8 ++-- compiler/rustc_mir_transform/src/ref_prop.rs | 15 +++---- .../src/required_consts.rs | 19 ++++----- 7 files changed, 56 insertions(+), 64 deletions(-) diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index 175097e30ee30..f123658580da4 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -242,7 +242,7 @@ impl<'tcx> crate::MirPass<'tcx> for DestinationPropagation { } round_count += 1; - apply_merges(body, tcx, &merges, &merged_locals); + apply_merges(body, tcx, merges, merged_locals); } trace!(round_count); @@ -281,20 +281,20 @@ struct Candidates { fn apply_merges<'tcx>( body: &mut Body<'tcx>, tcx: TyCtxt<'tcx>, - merges: &FxIndexMap, - merged_locals: &BitSet, + merges: FxIndexMap, + merged_locals: BitSet, ) { let mut merger = Merger { tcx, merges, merged_locals }; merger.visit_body_preserves_cfg(body); } -struct Merger<'a, 'tcx> { +struct Merger<'tcx> { tcx: TyCtxt<'tcx>, - merges: &'a FxIndexMap, - merged_locals: &'a BitSet, + merges: FxIndexMap, + merged_locals: BitSet, } -impl<'a, 'tcx> MutVisitor<'tcx> for Merger<'a, 'tcx> { +impl<'tcx> MutVisitor<'tcx> for Merger<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 0b78affc31cc1..598bf61483d2f 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -125,7 +125,7 @@ impl<'tcx> crate::MirPass<'tcx> for GVN { // Clone dominators because we need them while mutating the body. let dominators = body.basic_blocks.dominators().clone(); - let mut state = VnState::new(tcx, body, param_env, &ssa, &dominators, &body.local_decls); + let mut state = VnState::new(tcx, body, param_env, &ssa, dominators, &body.local_decls); ssa.for_each_assignment_mut( body.basic_blocks.as_mut_preserves_cfg(), |local, value, location| { @@ -258,7 +258,7 @@ struct VnState<'body, 'tcx> { /// Cache the value of the `unsized_locals` features, to avoid fetching it repeatedly in a loop. feature_unsized_locals: bool, ssa: &'body SsaLocals, - dominators: &'body Dominators, + dominators: Dominators, reused_locals: BitSet, } @@ -268,7 +268,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { body: &Body<'tcx>, param_env: ty::ParamEnv<'tcx>, ssa: &'body SsaLocals, - dominators: &'body Dominators, + dominators: Dominators, local_decls: &'body LocalDecls<'tcx>, ) -> Self { // Compute a rough estimate of the number of values in the body from the number of @@ -1490,7 +1490,7 @@ impl<'tcx> VnState<'_, 'tcx> { let other = self.rev_locals.get(index)?; other .iter() - .find(|&&other| self.ssa.assignment_dominates(self.dominators, other, loc)) + .find(|&&other| self.ssa.assignment_dominates(&self.dominators, other, loc)) .copied() } } diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index e950c2cb72ab8..d48df59ada860 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -78,18 +78,16 @@ impl<'tcx> crate::MirPass<'tcx> for JumpThreading { } let param_env = tcx.param_env_reveal_all_normalized(def_id); - let map = Map::new(tcx, body, Some(MAX_PLACES)); - let loop_headers = loop_headers(body); - let arena = DroplessArena::default(); + let arena = &DroplessArena::default(); let mut finder = TOFinder { tcx, param_env, ecx: InterpCx::new(tcx, DUMMY_SP, param_env, DummyMachine), body, - arena: &arena, - map: &map, - loop_headers: &loop_headers, + arena, + map: Map::new(tcx, body, Some(MAX_PLACES)), + loop_headers: loop_headers(body), opportunities: Vec::new(), }; @@ -105,7 +103,7 @@ impl<'tcx> crate::MirPass<'tcx> for JumpThreading { // Verify that we do not thread through a loop header. for to in opportunities.iter() { - assert!(to.chain.iter().all(|&block| !loop_headers.contains(block))); + assert!(to.chain.iter().all(|&block| !finder.loop_headers.contains(block))); } OpportunitySet::new(body, opportunities).apply(body); } @@ -124,8 +122,8 @@ struct TOFinder<'tcx, 'a> { param_env: ty::ParamEnv<'tcx>, ecx: InterpCx<'tcx, DummyMachine>, body: &'a Body<'tcx>, - map: &'a Map<'tcx>, - loop_headers: &'a BitSet, + map: Map<'tcx>, + loop_headers: BitSet, /// We use an arena to avoid cloning the slices when cloning `state`. arena: &'a DroplessArena, opportunities: Vec, @@ -223,7 +221,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { })) }; let conds = ConditionSet(conds); - state.insert_value_idx(discr, conds, self.map); + state.insert_value_idx(discr, conds, &self.map); self.find_opportunity(bb, state, cost, 0); } @@ -264,7 +262,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { // _1 = 5 // Whatever happens here, it won't change the result of a `SwitchInt`. // _1 = 6 if let Some((lhs, tail)) = self.mutated_statement(stmt) { - state.flood_with_tail_elem(lhs.as_ref(), tail, self.map, ConditionSet::BOTTOM); + state.flood_with_tail_elem(lhs.as_ref(), tail, &self.map, ConditionSet::BOTTOM); } } @@ -370,7 +368,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { self.opportunities.push(ThreadingOpportunity { chain: vec![bb], target: c.target }) }; - if let Some(conditions) = state.try_get_idx(lhs, self.map) + if let Some(conditions) = state.try_get_idx(lhs, &self.map) && let Immediate::Scalar(Scalar::Int(int)) = *rhs { conditions.iter_matches(int).for_each(register_opportunity); @@ -406,7 +404,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { } }, &mut |place, op| { - if let Some(conditions) = state.try_get_idx(place, self.map) + if let Some(conditions) = state.try_get_idx(place, &self.map) && let Ok(imm) = self.ecx.read_immediate_raw(op) && let Some(imm) = imm.right() && let Immediate::Scalar(Scalar::Int(int)) = *imm @@ -441,7 +439,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { // Transfer the conditions on the copied rhs. Operand::Move(rhs) | Operand::Copy(rhs) => { let Some(rhs) = self.map.find(rhs.as_ref()) else { return }; - state.insert_place_idx(rhs, lhs, self.map); + state.insert_place_idx(rhs, lhs, &self.map); } } } @@ -461,7 +459,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { Rvalue::CopyForDeref(rhs) => self.process_operand(bb, lhs, &Operand::Copy(*rhs), state), Rvalue::Discriminant(rhs) => { let Some(rhs) = self.map.find_discr(rhs.as_ref()) else { return }; - state.insert_place_idx(rhs, lhs, self.map); + state.insert_place_idx(rhs, lhs, &self.map); } // If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`. Rvalue::Aggregate(box ref kind, ref operands) => { @@ -492,10 +490,10 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { } // Transfer the conditions on the copy rhs, after inversing polarity. Rvalue::UnaryOp(UnOp::Not, Operand::Move(place) | Operand::Copy(place)) => { - let Some(conditions) = state.try_get_idx(lhs, self.map) else { return }; + let Some(conditions) = state.try_get_idx(lhs, &self.map) else { return }; let Some(place) = self.map.find(place.as_ref()) else { return }; let conds = conditions.map(self.arena, Condition::inv); - state.insert_value_idx(place, conds, self.map); + state.insert_value_idx(place, conds, &self.map); } // We expect `lhs ?= A`. We found `lhs = Eq(rhs, B)`. // Create a condition on `rhs ?= B`. @@ -504,7 +502,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { box (Operand::Move(place) | Operand::Copy(place), Operand::Constant(value)) | box (Operand::Constant(value), Operand::Move(place) | Operand::Copy(place)), ) => { - let Some(conditions) = state.try_get_idx(lhs, self.map) else { return }; + let Some(conditions) = state.try_get_idx(lhs, &self.map) else { return }; let Some(place) = self.map.find(place.as_ref()) else { return }; let equals = match op { BinOp::Eq => ScalarInt::TRUE, @@ -528,7 +526,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { polarity: if c.matches(equals) { Polarity::Eq } else { Polarity::Ne }, ..c }); - state.insert_value_idx(place, conds, self.map); + state.insert_value_idx(place, conds, &self.map); } _ => {} @@ -583,7 +581,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume( Operand::Copy(place) | Operand::Move(place), )) => { - let Some(conditions) = state.try_get(place.as_ref(), self.map) else { return }; + let Some(conditions) = state.try_get(place.as_ref(), &self.map) else { return }; conditions.iter_matches(ScalarInt::TRUE).for_each(register_opportunity); } StatementKind::Assign(box (lhs_place, rhs)) => { @@ -631,7 +629,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { // We can recurse through this terminator. let mut state = state(); if let Some(place_to_flood) = place_to_flood { - state.flood_with(place_to_flood.as_ref(), self.map, ConditionSet::BOTTOM); + state.flood_with(place_to_flood.as_ref(), &self.map, ConditionSet::BOTTOM); } self.find_opportunity(bb, state, cost.clone(), depth + 1); } @@ -650,7 +648,7 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> { let Some(discr) = discr.place() else { return }; let discr_ty = discr.ty(self.body, self.tcx).ty; let Ok(discr_layout) = self.ecx.layout_of(discr_ty) else { return }; - let Some(conditions) = state.try_get(discr.as_ref(), self.map) else { return }; + let Some(conditions) = state.try_get(discr.as_ref(), &self.map) else { return }; if let Some((value, _)) = targets.iter().find(|&(_, target)| target == target_bb) { let Some(value) = ScalarInt::try_from_uint(value, discr_layout.size) else { return }; diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index dcfcad7cc7c5b..6c9b46d8b6f6a 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -223,14 +223,14 @@ fn is_mir_available(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { /// MIR associated with them. fn mir_keys(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet { // All body-owners have MIR associated with them. - let mut set: FxIndexSet<_> = tcx.hir().body_owners().collect(); + let set: FxIndexSet<_> = tcx.hir().body_owners().collect(); // Additionally, tuple struct/variant constructors have MIR, but // they don't have a BodyId, so we need to build them separately. - struct GatherCtors<'a> { - set: &'a mut FxIndexSet, + struct GatherCtors { + set: FxIndexSet, } - impl<'tcx> Visitor<'tcx> for GatherCtors<'_> { + impl<'tcx> Visitor<'tcx> for GatherCtors { fn visit_variant_data(&mut self, v: &'tcx hir::VariantData<'tcx>) { if let hir::VariantData::Tuple(_, _, def_id) = *v { self.set.insert(def_id); @@ -238,9 +238,11 @@ fn mir_keys(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet { intravisit::walk_struct_def(self, v) } } - tcx.hir().visit_all_item_likes_in_crate(&mut GatherCtors { set: &mut set }); - set + let mut gather_ctors = GatherCtors { set }; + tcx.hir().visit_all_item_likes_in_crate(&mut gather_ctors); + + gather_ctors.set } fn mir_const_qualif(tcx: TyCtxt<'_>, def: LocalDefId) -> ConstQualifs { diff --git a/compiler/rustc_mir_transform/src/mentioned_items.rs b/compiler/rustc_mir_transform/src/mentioned_items.rs index 4402e0dd42d40..f24de609e6b29 100644 --- a/compiler/rustc_mir_transform/src/mentioned_items.rs +++ b/compiler/rustc_mir_transform/src/mentioned_items.rs @@ -10,7 +10,7 @@ pub(super) struct MentionedItems; struct MentionedItemsVisitor<'a, 'tcx> { tcx: TyCtxt<'tcx>, body: &'a mir::Body<'tcx>, - mentioned_items: &'a mut Vec>>, + mentioned_items: Vec>>, } impl<'tcx> crate::MirPass<'tcx> for MentionedItems { @@ -23,9 +23,9 @@ impl<'tcx> crate::MirPass<'tcx> for MentionedItems { } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut mir::Body<'tcx>) { - let mut mentioned_items = Vec::new(); - MentionedItemsVisitor { tcx, body, mentioned_items: &mut mentioned_items }.visit_body(body); - body.set_mentioned_items(mentioned_items); + let mut visitor = MentionedItemsVisitor { tcx, body, mentioned_items: Vec::new() }; + visitor.visit_body(body); + body.set_mentioned_items(visitor.mentioned_items); } } diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs index 25b98786c66b7..4c3a99b79d4f2 100644 --- a/compiler/rustc_mir_transform/src/ref_prop.rs +++ b/compiler/rustc_mir_transform/src/ref_prop.rs @@ -253,11 +253,8 @@ fn compute_replacement<'tcx>( debug!(?targets); - let mut finder = ReplacementFinder { - targets: &mut targets, - can_perform_opt, - allowed_replacements: FxHashSet::default(), - }; + let mut finder = + ReplacementFinder { targets, can_perform_opt, allowed_replacements: FxHashSet::default() }; let reachable_blocks = traversal::reachable_as_bitset(body); for (bb, bbdata) in body.basic_blocks.iter_enumerated() { // Only visit reachable blocks as we rely on dataflow. @@ -269,19 +266,19 @@ fn compute_replacement<'tcx>( let allowed_replacements = finder.allowed_replacements; return Replacer { tcx, - targets, + targets: finder.targets, storage_to_remove, allowed_replacements, any_replacement: false, }; - struct ReplacementFinder<'a, 'tcx, F> { - targets: &'a mut IndexVec>, + struct ReplacementFinder<'tcx, F> { + targets: IndexVec>, can_perform_opt: F, allowed_replacements: FxHashSet<(Local, Location)>, } - impl<'tcx, F> Visitor<'tcx> for ReplacementFinder<'_, 'tcx, F> + impl<'tcx, F> Visitor<'tcx> for ReplacementFinder<'tcx, F> where F: FnMut(Place<'tcx>, Location) -> bool, { diff --git a/compiler/rustc_mir_transform/src/required_consts.rs b/compiler/rustc_mir_transform/src/required_consts.rs index ebcf5b5d27b84..99d1cd6f63ecf 100644 --- a/compiler/rustc_mir_transform/src/required_consts.rs +++ b/compiler/rustc_mir_transform/src/required_consts.rs @@ -1,26 +1,21 @@ use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::{traversal, Body, ConstOperand, Location}; -pub(super) struct RequiredConstsVisitor<'a, 'tcx> { - required_consts: &'a mut Vec>, +pub(super) struct RequiredConstsVisitor<'tcx> { + required_consts: Vec>, } -impl<'a, 'tcx> RequiredConstsVisitor<'a, 'tcx> { - fn new(required_consts: &'a mut Vec>) -> Self { - RequiredConstsVisitor { required_consts } - } - +impl<'tcx> RequiredConstsVisitor<'tcx> { pub(super) fn compute_required_consts(body: &mut Body<'tcx>) { - let mut required_consts = Vec::new(); - let mut required_consts_visitor = RequiredConstsVisitor::new(&mut required_consts); + let mut visitor = RequiredConstsVisitor { required_consts: Vec::new() }; for (bb, bb_data) in traversal::reverse_postorder(&body) { - required_consts_visitor.visit_basic_block_data(bb, bb_data); + visitor.visit_basic_block_data(bb, bb_data); } - body.set_required_consts(required_consts); + body.set_required_consts(visitor.required_consts); } } -impl<'tcx> Visitor<'tcx> for RequiredConstsVisitor<'_, 'tcx> { +impl<'tcx> Visitor<'tcx> for RequiredConstsVisitor<'tcx> { fn visit_const_operand(&mut self, constant: &ConstOperand<'tcx>, _: Location) { if constant.const_.is_required_const() { self.required_consts.push(*constant); From 8949b443d5d0415c0c95fc931b1e4ee54de2f301 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 5 Sep 2024 10:39:11 +1000 Subject: [PATCH 128/189] Make `check_live_drops` into a `MirLint`. It's a thin wrapper around `check_live_drops`, but it's enough to fix the FIXME comment. --- compiler/rustc_mir_transform/src/lib.rs | 9 ++++++--- .../src/post_drop_elaboration.rs | 13 +++++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 compiler/rustc_mir_transform/src/post_drop_elaboration.rs diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 6c9b46d8b6f6a..84d07d3833071 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -87,6 +87,7 @@ mod match_branches; mod mentioned_items; mod multiple_return_terminators; mod nrvo; +mod post_drop_elaboration; mod prettify; mod promote_consts; mod ref_prop; @@ -480,11 +481,13 @@ pub fn run_analysis_to_runtime_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<' pm::run_passes( tcx, body, - &[&remove_uninit_drops::RemoveUninitDrops, &simplify::SimplifyCfg::RemoveFalseEdges], + &[ + &remove_uninit_drops::RemoveUninitDrops, + &simplify::SimplifyCfg::RemoveFalseEdges, + &Lint(post_drop_elaboration::CheckLiveDrops), + ], None, ); - // FIXME: make this a MIR lint - check_consts::post_drop_elaboration::check_live_drops(tcx, body); } debug!("runtime_mir_lowering({:?})", did); diff --git a/compiler/rustc_mir_transform/src/post_drop_elaboration.rs b/compiler/rustc_mir_transform/src/post_drop_elaboration.rs new file mode 100644 index 0000000000000..75721d4607626 --- /dev/null +++ b/compiler/rustc_mir_transform/src/post_drop_elaboration.rs @@ -0,0 +1,13 @@ +use rustc_const_eval::check_consts; +use rustc_middle::mir::*; +use rustc_middle::ty::TyCtxt; + +use crate::MirLint; + +pub(super) struct CheckLiveDrops; + +impl<'tcx> MirLint<'tcx> for CheckLiveDrops { + fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { + check_consts::post_drop_elaboration::check_live_drops(tcx, body); + } +} From d2309c2a9d308ddcd94c0ee8f4d2a01d1bd93560 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Thu, 22 Aug 2024 01:28:20 -0700 Subject: [PATCH 129/189] Ban non-array SIMD --- .../src/error_codes/E0074.md | 4 +- .../src/error_codes/E0075.md | 18 +- .../src/error_codes/E0076.md | 10 +- .../src/error_codes/E0077.md | 4 +- .../src/error_codes/E0511.md | 4 +- .../rustc_hir_analysis/src/check/check.rs | 42 ++-- compiler/rustc_middle/src/ty/sty.rs | 38 ++-- library/alloc/benches/slice.rs | 4 +- tests/assembly/asm/aarch64-types.rs | 31 +-- tests/assembly/asm/arm-modifiers.rs | 5 +- tests/assembly/asm/arm-types.rs | 27 ++- tests/assembly/asm/x86-types.rs | 209 ++---------------- tests/codegen/align-byval-vector.rs | 8 +- tests/codegen/const-vector.rs | 36 +-- tests/codegen/repr/transparent.rs | 2 +- .../simd-intrinsic-float-abs.rs | 19 +- .../simd-intrinsic-float-ceil.rs | 19 +- .../simd-intrinsic-float-cos.rs | 19 +- .../simd-intrinsic-float-exp.rs | 19 +- .../simd-intrinsic-float-exp2.rs | 19 +- .../simd-intrinsic-float-floor.rs | 19 +- .../simd-intrinsic-float-fma.rs | 19 +- .../simd-intrinsic-float-fsqrt.rs | 19 +- .../simd-intrinsic-float-log.rs | 19 +- .../simd-intrinsic-float-log10.rs | 19 +- .../simd-intrinsic-float-log2.rs | 19 +- .../simd-intrinsic-float-minmax.rs | 2 +- .../simd-intrinsic-float-pow.rs | 19 +- .../simd-intrinsic-float-powi.rs | 19 +- .../simd-intrinsic-float-sin.rs | 19 +- ...intrinsic-generic-arithmetic-saturating.rs | 146 ++++-------- .../simd-intrinsic-generic-bitmask.rs | 10 +- .../simd-intrinsic-generic-gather.rs | 4 +- .../simd-intrinsic-generic-masked-load.rs | 4 +- .../simd-intrinsic-generic-masked-store.rs | 4 +- .../simd-intrinsic-generic-scatter.rs | 4 +- .../simd-intrinsic-generic-select.rs | 6 +- .../simd-intrinsic-transmute-array.rs | 25 +-- tests/codegen/simd/unpadded-simd.rs | 2 +- tests/codegen/union-abi.rs | 2 +- tests/codegen/zst-offset.rs | 2 +- tests/debuginfo/simd.rs | 64 +++--- tests/incremental/issue-61530.rs | 6 +- tests/run-make/simd-ffi/simd.rs | 6 +- tests/rustdoc/inline_cross/auxiliary/repr.rs | 2 +- tests/ui/abi/arm-unadjusted-intrinsic.rs | 9 +- .../homogenous-floats-target-feature-mixup.rs | 30 +-- tests/ui/asm/aarch64/type-check-2-2.rs | 4 +- tests/ui/asm/aarch64/type-check-2.rs | 8 +- tests/ui/asm/aarch64/type-check-2.stderr | 4 +- tests/ui/asm/aarch64/type-check-3.rs | 4 +- tests/ui/asm/aarch64/type-check-4.rs | 2 +- tests/ui/asm/x86_64/type-check-2.rs | 4 +- tests/ui/asm/x86_64/type-check-2.stderr | 4 +- tests/ui/asm/x86_64/type-check-5.rs | 5 +- tests/ui/asm/x86_64/type-check-5.stderr | 6 +- .../consts/const-eval/simd/insert_extract.rs | 23 +- tests/ui/error-codes/E0075.rs | 3 + tests/ui/error-codes/E0075.stderr | 8 +- tests/ui/error-codes/E0076.rs | 2 +- tests/ui/error-codes/E0076.stderr | 6 +- tests/ui/error-codes/E0077.rs | 2 +- tests/ui/error-codes/E0077.stderr | 2 +- .../feature-gates/feature-gate-repr-simd.rs | 4 +- .../ui/feature-gates/feature-gate-simd-ffi.rs | 2 +- tests/ui/feature-gates/feature-gate-simd.rs | 5 +- tests/ui/layout/debug.rs | 2 +- tests/ui/repr/attr-usage-repr.rs | 2 +- tests/ui/repr/explicit-rust-repr-conflicts.rs | 2 +- tests/ui/simd/const-err-trumps-simd-err.rs | 4 +- .../ui/simd/const-err-trumps-simd-err.stderr | 4 +- tests/ui/simd/generics.rs | 6 +- tests/ui/simd/intrinsic/float-math-pass.rs | 18 +- tests/ui/simd/intrinsic/float-minmax-pass.rs | 12 +- .../ui/simd/intrinsic/generic-arithmetic-2.rs | 12 +- .../simd/intrinsic/generic-arithmetic-pass.rs | 168 +++++++------- .../generic-arithmetic-saturating-2.rs | 12 +- .../generic-arithmetic-saturating-pass.rs | 12 +- .../ui/simd/intrinsic/generic-bitmask-pass.rs | 16 +- tests/ui/simd/intrinsic/generic-cast.rs | 12 +- tests/ui/simd/intrinsic/generic-cast.stderr | 8 +- .../simd/intrinsic/generic-comparison-pass.rs | 34 +-- tests/ui/simd/intrinsic/generic-comparison.rs | 7 +- .../simd/intrinsic/generic-comparison.stderr | 36 +-- .../simd/intrinsic/generic-elements-pass.rs | 65 +++--- tests/ui/simd/intrinsic/generic-elements.rs | 14 +- .../ui/simd/intrinsic/generic-gather-pass.rs | 40 ++-- .../simd/intrinsic/generic-reduction-pass.rs | 28 +-- tests/ui/simd/intrinsic/generic-reduction.rs | 8 +- .../ui/simd/intrinsic/generic-select-pass.rs | 80 +++---- tests/ui/simd/intrinsic/generic-select.rs | 16 +- .../simd/intrinsic/inlining-issue67557-ice.rs | 4 +- .../ui/simd/intrinsic/inlining-issue67557.rs | 10 +- tests/ui/simd/issue-17170.rs | 4 +- tests/ui/simd/issue-32947.rs | 4 +- tests/ui/simd/issue-39720.rs | 6 +- tests/ui/simd/issue-89193.rs | 20 +- tests/ui/simd/monomorphize-heterogeneous.rs | 6 +- .../ui/simd/monomorphize-heterogeneous.stderr | 15 +- tests/ui/simd/monomorphize-too-long.rs | 11 + tests/ui/simd/monomorphize-too-long.stderr | 4 + tests/ui/simd/monomorphize-zero-length.rs | 11 + tests/ui/simd/monomorphize-zero-length.stderr | 4 + tests/ui/simd/target-feature-mixup.rs | 30 +-- ...ric-monomorphisation-extern-nonnull-ptr.rs | 4 +- .../type-generic-monomorphisation-wide-ptr.rs | 6 +- ...e-generic-monomorphisation-wide-ptr.stderr | 2 +- .../ui/simd/type-generic-monomorphisation.rs | 4 +- tests/ui/simd/type-len.rs | 9 +- tests/ui/simd/type-len.stderr | 30 ++- tests/ui/span/gated-features-attr-spans.rs | 3 +- 111 files changed, 826 insertions(+), 1113 deletions(-) create mode 100644 tests/ui/simd/monomorphize-too-long.rs create mode 100644 tests/ui/simd/monomorphize-too-long.stderr create mode 100644 tests/ui/simd/monomorphize-zero-length.rs create mode 100644 tests/ui/simd/monomorphize-zero-length.stderr diff --git a/compiler/rustc_error_codes/src/error_codes/E0074.md b/compiler/rustc_error_codes/src/error_codes/E0074.md index 785d6de226d3d..71d89f5eb60a4 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0074.md +++ b/compiler/rustc_error_codes/src/error_codes/E0074.md @@ -11,7 +11,7 @@ This will cause an error: #![feature(repr_simd)] #[repr(simd)] -struct Bad(T, T, T, T); +struct Bad([T; 4]); ``` This will not: @@ -20,5 +20,5 @@ This will not: #![feature(repr_simd)] #[repr(simd)] -struct Good(u32, u32, u32, u32); +struct Good([u32; 4]); ``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0075.md b/compiler/rustc_error_codes/src/error_codes/E0075.md index 969c1ee71313e..b58018eafc30c 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0075.md +++ b/compiler/rustc_error_codes/src/error_codes/E0075.md @@ -1,6 +1,6 @@ -A `#[simd]` attribute was applied to an empty tuple struct. +A `#[simd]` attribute was applied to an empty or multi-field struct. -Erroneous code example: +Erroneous code examples: ```compile_fail,E0075 #![feature(repr_simd)] @@ -9,9 +9,15 @@ Erroneous code example: struct Bad; // error! ``` -The `#[simd]` attribute can only be applied to non empty tuple structs, because -it doesn't make sense to try to use SIMD operations when there are no values to -operate on. +```compile_fail,E0075 +#![feature(repr_simd)] + +#[repr(simd)] +struct Bad([u32; 1], [u32; 1]); // error! +``` + +The `#[simd]` attribute can only be applied to a single-field struct, because +the one field must be the array of values in the vector. Fixed example: @@ -19,5 +25,5 @@ Fixed example: #![feature(repr_simd)] #[repr(simd)] -struct Good(u32); // ok! +struct Good([u32; 2]); // ok! ``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0076.md b/compiler/rustc_error_codes/src/error_codes/E0076.md index 1da8caa9506d7..b1943de63e5d4 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0076.md +++ b/compiler/rustc_error_codes/src/error_codes/E0076.md @@ -1,4 +1,4 @@ -All types in a tuple struct aren't the same when using the `#[simd]` +The type of the field in a tuple struct isn't an array when using the `#[simd]` attribute. Erroneous code example: @@ -7,12 +7,12 @@ Erroneous code example: #![feature(repr_simd)] #[repr(simd)] -struct Bad(u16, u32, u32 u32); // error! +struct Bad(u16); // error! ``` When using the `#[simd]` attribute to automatically use SIMD operations in tuple -struct, the types in the struct must all be of the same type, or the compiler -will trigger this error. +structs, if you want a single-lane vector then the field must be a 1-element +array, or the compiler will trigger this error. Fixed example: @@ -20,5 +20,5 @@ Fixed example: #![feature(repr_simd)] #[repr(simd)] -struct Good(u32, u32, u32, u32); // ok! +struct Good([u16; 1]); // ok! ``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0077.md b/compiler/rustc_error_codes/src/error_codes/E0077.md index 91aa24d1f52f4..688bfd3e72795 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0077.md +++ b/compiler/rustc_error_codes/src/error_codes/E0077.md @@ -7,7 +7,7 @@ Erroneous code example: #![feature(repr_simd)] #[repr(simd)] -struct Bad(String); // error! +struct Bad([String; 2]); // error! ``` When using the `#[simd]` attribute on a tuple struct, the elements in the tuple @@ -19,5 +19,5 @@ Fixed example: #![feature(repr_simd)] #[repr(simd)] -struct Good(u32, u32, u32, u32); // ok! +struct Good([u32; 4]); // ok! ``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0511.md b/compiler/rustc_error_codes/src/error_codes/E0511.md index 681f4e611c32d..45ff49bdebb29 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0511.md +++ b/compiler/rustc_error_codes/src/error_codes/E0511.md @@ -23,11 +23,11 @@ The generic type has to be a SIMD type. Example: #[repr(simd)] #[derive(Copy, Clone)] -struct i32x2(i32, i32); +struct i32x2([i32; 2]); extern "rust-intrinsic" { fn simd_add(a: T, b: T) -> T; } -unsafe { simd_add(i32x2(0, 0), i32x2(1, 2)); } // ok! +unsafe { simd_add(i32x2([0, 0]), i32x2([1, 2])); } // ok! ``` diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index e47c707ee18d9..d7b2510a1dffa 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -1064,20 +1064,29 @@ fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) { struct_span_code_err!(tcx.dcx(), sp, E0075, "SIMD vector cannot be empty").emit(); return; } - let e = fields[FieldIdx::ZERO].ty(tcx, args); - if !fields.iter().all(|f| f.ty(tcx, args) == e) { - struct_span_code_err!(tcx.dcx(), sp, E0076, "SIMD vector should be homogeneous") - .with_span_label(sp, "SIMD elements must have the same type") + + let array_field = &fields[FieldIdx::ZERO]; + let array_ty = array_field.ty(tcx, args); + let ty::Array(element_ty, len_const) = array_ty.kind() else { + struct_span_code_err!( + tcx.dcx(), + sp, + E0076, + "SIMD vector's only field must be an array" + ) + .with_span_label(tcx.def_span(array_field.did), "not an array") + .emit(); + return; + }; + + if let Some(second_field) = fields.get(FieldIdx::from_u32(1)) { + struct_span_code_err!(tcx.dcx(), sp, E0075, "SIMD vector cannot have multiple fields") + .with_span_label(tcx.def_span(second_field.did), "excess field") .emit(); return; } - let len = if let ty::Array(_ty, c) = e.kind() { - c.try_eval_target_usize(tcx, tcx.param_env(def.did())) - } else { - Some(fields.len() as u64) - }; - if let Some(len) = len { + if let Some(len) = len_const.try_eval_target_usize(tcx, tcx.param_env(def.did())) { if len == 0 { struct_span_code_err!(tcx.dcx(), sp, E0075, "SIMD vector cannot be empty").emit(); return; @@ -1097,16 +1106,9 @@ fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) { // These are scalar types which directly match a "machine" type // Yes: Integers, floats, "thin" pointers // No: char, "fat" pointers, compound types - match e.kind() { - ty::Param(_) => (), // pass struct(T, T, T, T) through, let monomorphization catch errors - ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::RawPtr(_, _) => (), // struct(u8, u8, u8, u8) is ok - ty::Array(t, _) if matches!(t.kind(), ty::Param(_)) => (), // pass struct([T; N]) through, let monomorphization catch errors - ty::Array(t, _clen) - if matches!( - t.kind(), - ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::RawPtr(_, _) - ) => - { /* struct([f32; 4]) is ok */ } + match element_ty.kind() { + ty::Param(_) => (), // pass struct([T; 4]) through, let monomorphization catch errors + ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::RawPtr(_, _) => (), // struct([u8; 4]) is ok _ => { struct_span_code_err!( tcx.dcx(), diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 1f4f2c62d7084..4dd81659da830 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1091,29 +1091,21 @@ impl<'tcx> Ty<'tcx> { } pub fn simd_size_and_type(self, tcx: TyCtxt<'tcx>) -> (u64, Ty<'tcx>) { - match self.kind() { - Adt(def, args) => { - assert!(def.repr().simd(), "`simd_size_and_type` called on non-SIMD type"); - let variant = def.non_enum_variant(); - let f0_ty = variant.fields[FieldIdx::ZERO].ty(tcx, args); - - match f0_ty.kind() { - // If the first field is an array, we assume it is the only field and its - // elements are the SIMD components. - Array(f0_elem_ty, f0_len) => { - // FIXME(repr_simd): https://github.com/rust-lang/rust/pull/78863#discussion_r522784112 - // The way we evaluate the `N` in `[T; N]` here only works since we use - // `simd_size_and_type` post-monomorphization. It will probably start to ICE - // if we use it in generic code. See the `simd-array-trait` ui test. - (f0_len.eval_target_usize(tcx, ParamEnv::empty()), *f0_elem_ty) - } - // Otherwise, the fields of this Adt are the SIMD components (and we assume they - // all have the same type). - _ => (variant.fields.len() as u64, f0_ty), - } - } - _ => bug!("`simd_size_and_type` called on invalid type"), - } + let Adt(def, args) = self.kind() else { + bug!("`simd_size_and_type` called on invalid type") + }; + assert!(def.repr().simd(), "`simd_size_and_type` called on non-SIMD type"); + let variant = def.non_enum_variant(); + assert_eq!(variant.fields.len(), 1); + let field_ty = variant.fields[FieldIdx::ZERO].ty(tcx, args); + let Array(f0_elem_ty, f0_len) = field_ty.kind() else { + bug!("Simd type has non-array field type {field_ty:?}") + }; + // FIXME(repr_simd): https://github.com/rust-lang/rust/pull/78863#discussion_r522784112 + // The way we evaluate the `N` in `[T; N]` here only works since we use + // `simd_size_and_type` post-monomorphization. It will probably start to ICE + // if we use it in generic code. See the `simd-array-trait` ui test. + (f0_len.eval_target_usize(tcx, ParamEnv::empty()), *f0_elem_ty) } #[inline] diff --git a/library/alloc/benches/slice.rs b/library/alloc/benches/slice.rs index b62be9d39a1cd..ab46603d7739c 100644 --- a/library/alloc/benches/slice.rs +++ b/library/alloc/benches/slice.rs @@ -336,10 +336,10 @@ reverse!(reverse_u32, u32, |x| x as u32); reverse!(reverse_u64, u64, |x| x as u64); reverse!(reverse_u128, u128, |x| x as u128); #[repr(simd)] -struct F64x4(f64, f64, f64, f64); +struct F64x4([f64; 4]); reverse!(reverse_simd_f64x4, F64x4, |x| { let x = x as f64; - F64x4(x, x, x, x) + F64x4([x, x, x, x]) }); macro_rules! rotate { diff --git a/tests/assembly/asm/aarch64-types.rs b/tests/assembly/asm/aarch64-types.rs index cf1882ba1a22e..1173ba8a4eb56 100644 --- a/tests/assembly/asm/aarch64-types.rs +++ b/tests/assembly/asm/aarch64-types.rs @@ -31,36 +31,39 @@ trait Sized {} #[lang = "copy"] trait Copy {} +// Do we really need to use no_core for this?!? +impl Copy for [T; N] {} + type ptr = *mut u8; #[repr(simd)] -pub struct i8x8(i8, i8, i8, i8, i8, i8, i8, i8); +pub struct i8x8([i8; 8]); #[repr(simd)] -pub struct i16x4(i16, i16, i16, i16); +pub struct i16x4([i16; 4]); #[repr(simd)] -pub struct i32x2(i32, i32); +pub struct i32x2([i32; 2]); #[repr(simd)] -pub struct i64x1(i64); +pub struct i64x1([i64; 1]); #[repr(simd)] -pub struct f16x4(f16, f16, f16, f16); +pub struct f16x4([f16; 4]); #[repr(simd)] -pub struct f32x2(f32, f32); +pub struct f32x2([f32; 2]); #[repr(simd)] -pub struct f64x1(f64); +pub struct f64x1([f64; 1]); #[repr(simd)] -pub struct i8x16(i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8); +pub struct i8x16([i8; 16]); #[repr(simd)] -pub struct i16x8(i16, i16, i16, i16, i16, i16, i16, i16); +pub struct i16x8([i16; 8]); #[repr(simd)] -pub struct i32x4(i32, i32, i32, i32); +pub struct i32x4([i32; 4]); #[repr(simd)] -pub struct i64x2(i64, i64); +pub struct i64x2([i64; 2]); #[repr(simd)] -pub struct f16x8(f16, f16, f16, f16, f16, f16, f16, f16); +pub struct f16x8([f16; 8]); #[repr(simd)] -pub struct f32x4(f32, f32, f32, f32); +pub struct f32x4([f32; 4]); #[repr(simd)] -pub struct f64x2(f64, f64); +pub struct f64x2([f64; 2]); impl Copy for i8 {} impl Copy for i16 {} diff --git a/tests/assembly/asm/arm-modifiers.rs b/tests/assembly/asm/arm-modifiers.rs index d421e0e6954cc..7d8d7e8387037 100644 --- a/tests/assembly/asm/arm-modifiers.rs +++ b/tests/assembly/asm/arm-modifiers.rs @@ -28,8 +28,11 @@ trait Sized {} #[lang = "copy"] trait Copy {} +// Do we really need to use no_core for this?!? +impl Copy for [T; N] {} + #[repr(simd)] -pub struct f32x4(f32, f32, f32, f32); +pub struct f32x4([f32; 4]); impl Copy for i32 {} impl Copy for f32 {} diff --git a/tests/assembly/asm/arm-types.rs b/tests/assembly/asm/arm-types.rs index 448b92aa8399a..9cebb588aaf86 100644 --- a/tests/assembly/asm/arm-types.rs +++ b/tests/assembly/asm/arm-types.rs @@ -31,32 +31,35 @@ trait Sized {} #[lang = "copy"] trait Copy {} +// Do we really need to use no_core for this?!? +impl Copy for [T; N] {} + type ptr = *mut u8; #[repr(simd)] -pub struct i8x8(i8, i8, i8, i8, i8, i8, i8, i8); +pub struct i8x8([i8; 8]); #[repr(simd)] -pub struct i16x4(i16, i16, i16, i16); +pub struct i16x4([i16; 4]); #[repr(simd)] -pub struct i32x2(i32, i32); +pub struct i32x2([i32; 2]); #[repr(simd)] -pub struct i64x1(i64); +pub struct i64x1([i64; 1]); #[repr(simd)] -pub struct f16x4(f16, f16, f16, f16); +pub struct f16x4([f16; 4]); #[repr(simd)] -pub struct f32x2(f32, f32); +pub struct f32x2([f32; 2]); #[repr(simd)] -pub struct i8x16(i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8); +pub struct i8x16([i8; 16]); #[repr(simd)] -pub struct i16x8(i16, i16, i16, i16, i16, i16, i16, i16); +pub struct i16x8([i16; 8]); #[repr(simd)] -pub struct i32x4(i32, i32, i32, i32); +pub struct i32x4([i32; 4]); #[repr(simd)] -pub struct i64x2(i64, i64); +pub struct i64x2([i64; 2]); #[repr(simd)] -pub struct f16x8(f16, f16, f16, f16, f16, f16, f16, f16); +pub struct f16x8([f16; 8]); #[repr(simd)] -pub struct f32x4(f32, f32, f32, f32); +pub struct f32x4([f32; 4]); impl Copy for i8 {} impl Copy for i16 {} diff --git a/tests/assembly/asm/x86-types.rs b/tests/assembly/asm/x86-types.rs index a40bc10d9915c..567dc7a8245fe 100644 --- a/tests/assembly/asm/x86-types.rs +++ b/tests/assembly/asm/x86-types.rs @@ -31,216 +31,55 @@ trait Sized {} #[lang = "copy"] trait Copy {} +// Do we really need to use no_core for this?!? +impl Copy for [T; N] {} + type ptr = *mut u8; #[repr(simd)] -pub struct i8x16(i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8); +pub struct i8x16([i8; 16]); #[repr(simd)] -pub struct i16x8(i16, i16, i16, i16, i16, i16, i16, i16); +pub struct i16x8([i16; 8]); #[repr(simd)] -pub struct i32x4(i32, i32, i32, i32); +pub struct i32x4([i32; 4]); #[repr(simd)] -pub struct i64x2(i64, i64); +pub struct i64x2([i64; 2]); #[repr(simd)] -pub struct f16x8(f16, f16, f16, f16, f16, f16, f16, f16); +pub struct f16x8([f16; 8]); #[repr(simd)] -pub struct f32x4(f32, f32, f32, f32); +pub struct f32x4([f32; 4]); #[repr(simd)] -pub struct f64x2(f64, f64); +pub struct f64x2([f64; 2]); #[repr(simd)] -pub struct i8x32( - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, -); +pub struct i8x32([i8; 32]); #[repr(simd)] -pub struct i16x16(i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16); +pub struct i16x16([i16; 16]); #[repr(simd)] -pub struct i32x8(i32, i32, i32, i32, i32, i32, i32, i32); +pub struct i32x8([i32; 8]); #[repr(simd)] -pub struct i64x4(i64, i64, i64, i64); +pub struct i64x4([i64; 4]); #[repr(simd)] -pub struct f16x16(f16, f16, f16, f16, f16, f16, f16, f16, f16, f16, f16, f16, f16, f16, f16, f16); +pub struct f16x16([f16; 16]); #[repr(simd)] -pub struct f32x8(f32, f32, f32, f32, f32, f32, f32, f32); +pub struct f32x8([f32; 8]); #[repr(simd)] -pub struct f64x4(f64, f64, f64, f64); +pub struct f64x4([f64; 4]); #[repr(simd)] -pub struct i8x64( - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, - i8, -); +pub struct i8x64([i8; 64]); #[repr(simd)] -pub struct i16x32( - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, - i16, -); +pub struct i16x32([i16; 32]); #[repr(simd)] -pub struct i32x16(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32); +pub struct i32x16([i32; 16]); #[repr(simd)] -pub struct i64x8(i64, i64, i64, i64, i64, i64, i64, i64); +pub struct i64x8([i64; 8]); #[repr(simd)] -pub struct f16x32( - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, - f16, -); +pub struct f16x32([f16; 32]); #[repr(simd)] -pub struct f32x16(f32, f32, f32, f32, f32, f32, f32, f32, f32, f32, f32, f32, f32, f32, f32, f32); +pub struct f32x16([f32; 16]); #[repr(simd)] -pub struct f64x8(f64, f64, f64, f64, f64, f64, f64, f64); +pub struct f64x8([f64; 8]); macro_rules! impl_copy { ($($ty:ident)*) => { diff --git a/tests/codegen/align-byval-vector.rs b/tests/codegen/align-byval-vector.rs index 02b7d6b0c5e28..60d49f9308197 100644 --- a/tests/codegen/align-byval-vector.rs +++ b/tests/codegen/align-byval-vector.rs @@ -21,7 +21,7 @@ trait Freeze {} trait Copy {} #[repr(simd)] -pub struct i32x4(i32, i32, i32, i32); +pub struct i32x4([i32; 4]); #[repr(C)] pub struct Foo { @@ -47,12 +47,12 @@ extern "C" { } pub fn main() { - unsafe { f(Foo { a: i32x4(1, 2, 3, 4), b: 0 }) } + unsafe { f(Foo { a: i32x4([1, 2, 3, 4]), b: 0 }) } unsafe { g(DoubleFoo { - one: Foo { a: i32x4(1, 2, 3, 4), b: 0 }, - two: Foo { a: i32x4(1, 2, 3, 4), b: 0 }, + one: Foo { a: i32x4([1, 2, 3, 4]), b: 0 }, + two: Foo { a: i32x4([1, 2, 3, 4]), b: 0 }, }) } } diff --git a/tests/codegen/const-vector.rs b/tests/codegen/const-vector.rs index d368838201e2b..8343594e5d23c 100644 --- a/tests/codegen/const-vector.rs +++ b/tests/codegen/const-vector.rs @@ -13,19 +13,11 @@ // Setting up structs that can be used as const vectors #[repr(simd)] #[derive(Clone)] -pub struct i8x2(i8, i8); +pub struct i8x2([i8; 2]); #[repr(simd)] #[derive(Clone)] -pub struct i8x2_arr([i8; 2]); - -#[repr(simd)] -#[derive(Clone)] -pub struct f32x2(f32, f32); - -#[repr(simd)] -#[derive(Clone)] -pub struct f32x2_arr([f32; 2]); +pub struct f32x2([f32; 2]); #[repr(simd, packed)] #[derive(Copy, Clone)] @@ -35,42 +27,34 @@ pub struct Simd([T; N]); // that they are called with a const vector extern "unadjusted" { - #[no_mangle] fn test_i8x2(a: i8x2); } extern "unadjusted" { - #[no_mangle] fn test_i8x2_two_args(a: i8x2, b: i8x2); } extern "unadjusted" { - #[no_mangle] fn test_i8x2_mixed_args(a: i8x2, c: i32, b: i8x2); } extern "unadjusted" { - #[no_mangle] - fn test_i8x2_arr(a: i8x2_arr); + fn test_i8x2_arr(a: i8x2); } extern "unadjusted" { - #[no_mangle] fn test_f32x2(a: f32x2); } extern "unadjusted" { - #[no_mangle] - fn test_f32x2_arr(a: f32x2_arr); + fn test_f32x2_arr(a: f32x2); } extern "unadjusted" { - #[no_mangle] fn test_simd(a: Simd); } extern "unadjusted" { - #[no_mangle] fn test_simd_unaligned(a: Simd); } @@ -81,22 +65,22 @@ extern "unadjusted" { pub fn do_call() { unsafe { // CHECK: call void @test_i8x2(<2 x i8> - test_i8x2(const { i8x2(32, 64) }); + test_i8x2(const { i8x2([32, 64]) }); // CHECK: call void @test_i8x2_two_args(<2 x i8> , <2 x i8> - test_i8x2_two_args(const { i8x2(32, 64) }, const { i8x2(8, 16) }); + test_i8x2_two_args(const { i8x2([32, 64]) }, const { i8x2([8, 16]) }); // CHECK: call void @test_i8x2_mixed_args(<2 x i8> , i32 43, <2 x i8> - test_i8x2_mixed_args(const { i8x2(32, 64) }, 43, const { i8x2(8, 16) }); + test_i8x2_mixed_args(const { i8x2([32, 64]) }, 43, const { i8x2([8, 16]) }); // CHECK: call void @test_i8x2_arr(<2 x i8> - test_i8x2_arr(const { i8x2_arr([32, 64]) }); + test_i8x2_arr(const { i8x2([32, 64]) }); // CHECK: call void @test_f32x2(<2 x float> - test_f32x2(const { f32x2(0.32, 0.64) }); + test_f32x2(const { f32x2([0.32, 0.64]) }); // CHECK: void @test_f32x2_arr(<2 x float> - test_f32x2_arr(const { f32x2_arr([0.32, 0.64]) }); + test_f32x2_arr(const { f32x2([0.32, 0.64]) }); // CHECK: call void @test_simd(<4 x i32> test_simd(const { Simd::([2, 4, 6, 8]) }); diff --git a/tests/codegen/repr/transparent.rs b/tests/codegen/repr/transparent.rs index 9140b8542ecac..adcd3aacd2ace 100644 --- a/tests/codegen/repr/transparent.rs +++ b/tests/codegen/repr/transparent.rs @@ -132,7 +132,7 @@ pub extern "C" fn test_Nested2(_: Nested2) -> Nested2 { } #[repr(simd)] -struct f32x4(f32, f32, f32, f32); +struct f32x4([f32; 4]); #[repr(transparent)] pub struct Vector(f32x4); diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-abs.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-abs.rs index f8efb678f76ef..4a5a6391c052f 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-abs.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-abs.rs @@ -7,23 +7,19 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub f32, pub f32); +pub struct f32x2(pub [f32; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x8(pub [f32; 8]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x16(pub [f32; 16]); extern "rust-intrinsic" { fn simd_fabs(x: T) -> T; @@ -59,16 +55,15 @@ pub unsafe fn fabs_32x16(a: f32x16) -> f32x16 { #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub f64, pub f64); +pub struct f64x2(pub [f64; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub f64, pub f64, pub f64, pub f64); +pub struct f64x4(pub [f64; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub f64, pub f64, pub f64, pub f64, - pub f64, pub f64, pub f64, pub f64); +pub struct f64x8(pub [f64; 8]); // CHECK-LABEL: @fabs_64x4 #[no_mangle] diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-ceil.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-ceil.rs index a3ebec174b679..89e54f579ff7c 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-ceil.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-ceil.rs @@ -7,23 +7,19 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub f32, pub f32); +pub struct f32x2(pub [f32; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x8(pub [f32; 8]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x16(pub [f32; 16]); extern "rust-intrinsic" { fn simd_ceil(x: T) -> T; @@ -59,16 +55,15 @@ pub unsafe fn ceil_32x16(a: f32x16) -> f32x16 { #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub f64, pub f64); +pub struct f64x2(pub [f64; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub f64, pub f64, pub f64, pub f64); +pub struct f64x4(pub [f64; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub f64, pub f64, pub f64, pub f64, - pub f64, pub f64, pub f64, pub f64); +pub struct f64x8(pub [f64; 8]); // CHECK-LABEL: @ceil_64x4 #[no_mangle] diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-cos.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-cos.rs index 00f97eef6f0cb..b40fd5365de57 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-cos.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-cos.rs @@ -7,23 +7,19 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub f32, pub f32); +pub struct f32x2(pub [f32; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x8(pub [f32; 8]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x16(pub [f32; 16]); extern "rust-intrinsic" { fn simd_fcos(x: T) -> T; @@ -59,16 +55,15 @@ pub unsafe fn fcos_32x16(a: f32x16) -> f32x16 { #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub f64, pub f64); +pub struct f64x2(pub [f64; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub f64, pub f64, pub f64, pub f64); +pub struct f64x4(pub [f64; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub f64, pub f64, pub f64, pub f64, - pub f64, pub f64, pub f64, pub f64); +pub struct f64x8(pub [f64; 8]); // CHECK-LABEL: @fcos_64x4 #[no_mangle] diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-exp.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-exp.rs index 48c1a8ec489db..fef003dde5bb8 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-exp.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-exp.rs @@ -7,23 +7,19 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub f32, pub f32); +pub struct f32x2(pub [f32; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x8(pub [f32; 8]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x16(pub [f32; 16]); extern "rust-intrinsic" { fn simd_fexp(x: T) -> T; @@ -59,16 +55,15 @@ pub unsafe fn exp_32x16(a: f32x16) -> f32x16 { #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub f64, pub f64); +pub struct f64x2(pub [f64; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub f64, pub f64, pub f64, pub f64); +pub struct f64x4(pub [f64; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub f64, pub f64, pub f64, pub f64, - pub f64, pub f64, pub f64, pub f64); +pub struct f64x8(pub [f64; 8]); // CHECK-LABEL: @exp_64x4 #[no_mangle] diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-exp2.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-exp2.rs index 23c38d8162157..779c0fc403a3d 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-exp2.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-exp2.rs @@ -7,23 +7,19 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub f32, pub f32); +pub struct f32x2(pub [f32; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x8(pub [f32; 8]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x16(pub [f32; 16]); extern "rust-intrinsic" { fn simd_fexp2(x: T) -> T; @@ -59,16 +55,15 @@ pub unsafe fn exp2_32x16(a: f32x16) -> f32x16 { #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub f64, pub f64); +pub struct f64x2(pub [f64; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub f64, pub f64, pub f64, pub f64); +pub struct f64x4(pub [f64; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub f64, pub f64, pub f64, pub f64, - pub f64, pub f64, pub f64, pub f64); +pub struct f64x8(pub [f64; 8]); // CHECK-LABEL: @exp2_64x4 #[no_mangle] diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-floor.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-floor.rs index 978f263031ac3..b2bd27a5b75c2 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-floor.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-floor.rs @@ -7,23 +7,19 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub f32, pub f32); +pub struct f32x2(pub [f32; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x8(pub [f32; 8]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x16(pub [f32; 16]); extern "rust-intrinsic" { fn simd_floor(x: T) -> T; @@ -59,16 +55,15 @@ pub unsafe fn floor_32x16(a: f32x16) -> f32x16 { #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub f64, pub f64); +pub struct f64x2(pub [f64; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub f64, pub f64, pub f64, pub f64); +pub struct f64x4(pub [f64; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub f64, pub f64, pub f64, pub f64, - pub f64, pub f64, pub f64, pub f64); +pub struct f64x8(pub [f64; 8]); // CHECK-LABEL: @floor_64x4 #[no_mangle] diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-fma.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-fma.rs index 200d67180265a..37f4782626add 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-fma.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-fma.rs @@ -7,23 +7,19 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub f32, pub f32); +pub struct f32x2(pub [f32; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x8(pub [f32; 8]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x16(pub [f32; 16]); extern "rust-intrinsic" { fn simd_fma(x: T, b: T, c: T) -> T; @@ -59,16 +55,15 @@ pub unsafe fn fma_32x16(a: f32x16, b: f32x16, c: f32x16) -> f32x16 { #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub f64, pub f64); +pub struct f64x2(pub [f64; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub f64, pub f64, pub f64, pub f64); +pub struct f64x4(pub [f64; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub f64, pub f64, pub f64, pub f64, - pub f64, pub f64, pub f64, pub f64); +pub struct f64x8(pub [f64; 8]); // CHECK-LABEL: @fma_64x4 #[no_mangle] diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-fsqrt.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-fsqrt.rs index f70de3e27536e..336adf6db73f1 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-fsqrt.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-fsqrt.rs @@ -7,23 +7,19 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub f32, pub f32); +pub struct f32x2(pub [f32; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x8(pub [f32; 8]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x16(pub [f32; 16]); extern "rust-intrinsic" { fn simd_fsqrt(x: T) -> T; @@ -59,16 +55,15 @@ pub unsafe fn fsqrt_32x16(a: f32x16) -> f32x16 { #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub f64, pub f64); +pub struct f64x2(pub [f64; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub f64, pub f64, pub f64, pub f64); +pub struct f64x4(pub [f64; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub f64, pub f64, pub f64, pub f64, - pub f64, pub f64, pub f64, pub f64); +pub struct f64x8(pub [f64; 8]); // CHECK-LABEL: @fsqrt_64x4 #[no_mangle] diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-log.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-log.rs index c0edd3ea48fc9..8e97abc3a6618 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-log.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-log.rs @@ -7,23 +7,19 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub f32, pub f32); +pub struct f32x2(pub [f32; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x8(pub [f32; 8]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x16(pub [f32; 16]); extern "rust-intrinsic" { fn simd_flog(x: T) -> T; @@ -59,16 +55,15 @@ pub unsafe fn log_32x16(a: f32x16) -> f32x16 { #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub f64, pub f64); +pub struct f64x2(pub [f64; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub f64, pub f64, pub f64, pub f64); +pub struct f64x4(pub [f64; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub f64, pub f64, pub f64, pub f64, - pub f64, pub f64, pub f64, pub f64); +pub struct f64x8(pub [f64; 8]); // CHECK-LABEL: @log_64x4 #[no_mangle] diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-log10.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-log10.rs index 766307f47ed35..1d4d4dc24e9ad 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-log10.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-log10.rs @@ -7,23 +7,19 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub f32, pub f32); +pub struct f32x2(pub [f32; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x8(pub [f32; 8]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x16(pub [f32; 16]); extern "rust-intrinsic" { fn simd_flog10(x: T) -> T; @@ -59,16 +55,15 @@ pub unsafe fn log10_32x16(a: f32x16) -> f32x16 { #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub f64, pub f64); +pub struct f64x2(pub [f64; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub f64, pub f64, pub f64, pub f64); +pub struct f64x4(pub [f64; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub f64, pub f64, pub f64, pub f64, - pub f64, pub f64, pub f64, pub f64); +pub struct f64x8(pub [f64; 8]); // CHECK-LABEL: @log10_64x4 #[no_mangle] diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-log2.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-log2.rs index 90c5918c33ea3..28f2f1516175c 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-log2.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-log2.rs @@ -7,23 +7,19 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub f32, pub f32); +pub struct f32x2(pub [f32; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x8(pub [f32; 8]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x16(pub [f32; 16]); extern "rust-intrinsic" { fn simd_flog2(x: T) -> T; @@ -59,16 +55,15 @@ pub unsafe fn log2_32x16(a: f32x16) -> f32x16 { #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub f64, pub f64); +pub struct f64x2(pub [f64; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub f64, pub f64, pub f64, pub f64); +pub struct f64x4(pub [f64; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub f64, pub f64, pub f64, pub f64, - pub f64, pub f64, pub f64, pub f64); +pub struct f64x8(pub [f64; 8]); // CHECK-LABEL: @log2_64x4 #[no_mangle] diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-minmax.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-minmax.rs index d949112bae762..50c51bebe37ee 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-minmax.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-minmax.rs @@ -7,7 +7,7 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); extern "rust-intrinsic" { fn simd_fmin(x: T, y: T) -> T; diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-pow.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-pow.rs index 21641c80d313c..3527f71c00b47 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-pow.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-pow.rs @@ -7,23 +7,19 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub f32, pub f32); +pub struct f32x2(pub [f32; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x8(pub [f32; 8]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x16(pub [f32; 16]); extern "rust-intrinsic" { fn simd_fpow(x: T, b: T) -> T; @@ -59,16 +55,15 @@ pub unsafe fn fpow_32x16(a: f32x16, b: f32x16) -> f32x16 { #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub f64, pub f64); +pub struct f64x2(pub [f64; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub f64, pub f64, pub f64, pub f64); +pub struct f64x4(pub [f64; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub f64, pub f64, pub f64, pub f64, - pub f64, pub f64, pub f64, pub f64); +pub struct f64x8(pub [f64; 8]); // CHECK-LABEL: @fpow_64x4 #[no_mangle] diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-powi.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-powi.rs index 3985bdd50df70..4f0b5e4e01a3e 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-powi.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-powi.rs @@ -7,23 +7,19 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub f32, pub f32); +pub struct f32x2(pub [f32; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x8(pub [f32; 8]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x16(pub [f32; 16]); extern "rust-intrinsic" { fn simd_fpowi(x: T, b: i32) -> T; @@ -59,16 +55,15 @@ pub unsafe fn fpowi_32x16(a: f32x16, b: i32) -> f32x16 { #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub f64, pub f64); +pub struct f64x2(pub [f64; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub f64, pub f64, pub f64, pub f64); +pub struct f64x4(pub [f64; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub f64, pub f64, pub f64, pub f64, - pub f64, pub f64, pub f64, pub f64); +pub struct f64x8(pub [f64; 8]); // CHECK-LABEL: @fpowi_64x4 #[no_mangle] diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-float-sin.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-float-sin.rs index f6978e32df724..4173809e3a9b3 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-float-sin.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-float-sin.rs @@ -7,23 +7,19 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x2(pub f32, pub f32); +pub struct f32x2(pub [f32; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x8(pub [f32; 8]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x16(pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32, - pub f32, pub f32, pub f32, pub f32); +pub struct f32x16(pub [f32; 16]); extern "rust-intrinsic" { fn simd_fsin(x: T) -> T; @@ -59,16 +55,15 @@ pub unsafe fn fsin_32x16(a: f32x16) -> f32x16 { #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x2(pub f64, pub f64); +pub struct f64x2(pub [f64; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x4(pub f64, pub f64, pub f64, pub f64); +pub struct f64x4(pub [f64; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f64x8(pub f64, pub f64, pub f64, pub f64, - pub f64, pub f64, pub f64, pub f64); +pub struct f64x8(pub [f64; 8]); // CHECK-LABEL: @fsin_64x4 #[no_mangle] diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs index 809f9a32226f4..a5afa27876a0f 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs @@ -9,107 +9,57 @@ // signed integer types -#[repr(simd)] #[derive(Copy, Clone)] pub struct i8x2(i8, i8); -#[repr(simd)] #[derive(Copy, Clone)] pub struct i8x4(i8, i8, i8, i8); -#[repr(simd)] #[derive(Copy, Clone)] pub struct i8x8( - i8, i8, i8, i8, i8, i8, i8, i8, -); -#[repr(simd)] #[derive(Copy, Clone)] pub struct i8x16( - i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, -); -#[repr(simd)] #[derive(Copy, Clone)] pub struct i8x32( - i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, - i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, -); -#[repr(simd)] #[derive(Copy, Clone)] pub struct i8x64( - i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, - i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, - i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, - i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, -); - -#[repr(simd)] #[derive(Copy, Clone)] pub struct i16x2(i16, i16); -#[repr(simd)] #[derive(Copy, Clone)] pub struct i16x4(i16, i16, i16, i16); -#[repr(simd)] #[derive(Copy, Clone)] pub struct i16x8( - i16, i16, i16, i16, i16, i16, i16, i16, -); -#[repr(simd)] #[derive(Copy, Clone)] pub struct i16x16( - i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, -); -#[repr(simd)] #[derive(Copy, Clone)] pub struct i16x32( - i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, - i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, -); - -#[repr(simd)] #[derive(Copy, Clone)] pub struct i32x2(i32, i32); -#[repr(simd)] #[derive(Copy, Clone)] pub struct i32x4(i32, i32, i32, i32); -#[repr(simd)] #[derive(Copy, Clone)] pub struct i32x8( - i32, i32, i32, i32, i32, i32, i32, i32, -); -#[repr(simd)] #[derive(Copy, Clone)] pub struct i32x16( - i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, -); - -#[repr(simd)] #[derive(Copy, Clone)] pub struct i64x2(i64, i64); -#[repr(simd)] #[derive(Copy, Clone)] pub struct i64x4(i64, i64, i64, i64); -#[repr(simd)] #[derive(Copy, Clone)] pub struct i64x8( - i64, i64, i64, i64, i64, i64, i64, i64, -); - -#[repr(simd)] #[derive(Copy, Clone)] pub struct i128x2(i128, i128); -#[repr(simd)] #[derive(Copy, Clone)] pub struct i128x4(i128, i128, i128, i128); +#[repr(simd)] #[derive(Copy, Clone)] pub struct i8x2([i8; 2]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct i8x4([i8; 4]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct i8x8([i8; 8]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct i8x16([i8; 16]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct i8x32([i8; 32]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct i8x64([i8; 64]); + +#[repr(simd)] #[derive(Copy, Clone)] pub struct i16x2([i16; 2]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct i16x4([i16; 4]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct i16x8([i16; 8]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct i16x16([i16; 16]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct i16x32([i16; 32]); + +#[repr(simd)] #[derive(Copy, Clone)] pub struct i32x2([i32; 2]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct i32x4([i32; 4]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct i32x8([i32; 8]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct i32x16([i32; 16]); + +#[repr(simd)] #[derive(Copy, Clone)] pub struct i64x2([i64; 2]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct i64x4([i64; 4]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct i64x8([i64; 8]); + +#[repr(simd)] #[derive(Copy, Clone)] pub struct i128x2([i128; 2]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct i128x4([i128; 4]); // unsigned integer types -#[repr(simd)] #[derive(Copy, Clone)] pub struct u8x2(u8, u8); -#[repr(simd)] #[derive(Copy, Clone)] pub struct u8x4(u8, u8, u8, u8); -#[repr(simd)] #[derive(Copy, Clone)] pub struct u8x8( - u8, u8, u8, u8, u8, u8, u8, u8, -); -#[repr(simd)] #[derive(Copy, Clone)] pub struct u8x16( - u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, -); -#[repr(simd)] #[derive(Copy, Clone)] pub struct u8x32( - u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, - u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, -); -#[repr(simd)] #[derive(Copy, Clone)] pub struct u8x64( - u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, - u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, - u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, - u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, -); - -#[repr(simd)] #[derive(Copy, Clone)] pub struct u16x2(u16, u16); -#[repr(simd)] #[derive(Copy, Clone)] pub struct u16x4(u16, u16, u16, u16); -#[repr(simd)] #[derive(Copy, Clone)] pub struct u16x8( - u16, u16, u16, u16, u16, u16, u16, u16, -); -#[repr(simd)] #[derive(Copy, Clone)] pub struct u16x16( - u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, -); -#[repr(simd)] #[derive(Copy, Clone)] pub struct u16x32( - u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, - u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, u16, -); - -#[repr(simd)] #[derive(Copy, Clone)] pub struct u32x2(u32, u32); -#[repr(simd)] #[derive(Copy, Clone)] pub struct u32x4(u32, u32, u32, u32); -#[repr(simd)] #[derive(Copy, Clone)] pub struct u32x8( - u32, u32, u32, u32, u32, u32, u32, u32, -); -#[repr(simd)] #[derive(Copy, Clone)] pub struct u32x16( - u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, -); - -#[repr(simd)] #[derive(Copy, Clone)] pub struct u64x2(u64, u64); -#[repr(simd)] #[derive(Copy, Clone)] pub struct u64x4(u64, u64, u64, u64); -#[repr(simd)] #[derive(Copy, Clone)] pub struct u64x8( - u64, u64, u64, u64, u64, u64, u64, u64, -); - -#[repr(simd)] #[derive(Copy, Clone)] pub struct u128x2(u128, u128); -#[repr(simd)] #[derive(Copy, Clone)] pub struct u128x4(u128, u128, u128, u128); +#[repr(simd)] #[derive(Copy, Clone)] pub struct u8x2([u8; 2]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct u8x4([u8; 4]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct u8x8([u8; 8]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct u8x16([u8; 16]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct u8x32([u8; 32]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct u8x64([u8; 64]); + +#[repr(simd)] #[derive(Copy, Clone)] pub struct u16x2([u16; 2]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct u16x4([u16; 4]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct u16x8([u16; 8]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct u16x16([u16; 16]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct u16x32([u16; 32]); + +#[repr(simd)] #[derive(Copy, Clone)] pub struct u32x2([u32; 2]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct u32x4([u32; 4]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct u32x8([u32; 8]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct u32x16([u32; 16]); + +#[repr(simd)] #[derive(Copy, Clone)] pub struct u64x2([u64; 2]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct u64x4([u64; 4]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct u64x8([u64; 8]); + +#[repr(simd)] #[derive(Copy, Clone)] pub struct u128x2([u128; 2]); +#[repr(simd)] #[derive(Copy, Clone)] pub struct u128x4([u128; 4]); extern "rust-intrinsic" { fn simd_saturating_add(x: T, y: T) -> T; diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-bitmask.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-bitmask.rs index 44a4c52d64a87..81ac90269b7df 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-bitmask.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-bitmask.rs @@ -8,19 +8,15 @@ #[repr(simd)] #[derive(Copy, Clone)] -pub struct u32x2(u32, u32); +pub struct u32x2([u32; 2]); #[repr(simd)] #[derive(Copy, Clone)] -pub struct i32x2(i32, i32); +pub struct i32x2([i32; 2]); #[repr(simd)] #[derive(Copy, Clone)] -pub struct i8x16( - i8, i8, i8, i8, i8, i8, i8, i8, - i8, i8, i8, i8, i8, i8, i8, i8, -); - +pub struct i8x16([i8; 16]); extern "rust-intrinsic" { fn simd_bitmask(x: T) -> U; diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-gather.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-gather.rs index 863a9606c7e99..10ceeecf9007e 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-gather.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-gather.rs @@ -9,11 +9,11 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct Vec2(pub T, pub T); +pub struct Vec2(pub [T; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct Vec4(pub T, pub T, pub T, pub T); +pub struct Vec4(pub [T; 4]); extern "rust-intrinsic" { fn simd_gather(value: T, pointers: P, mask: M) -> T; diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-load.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-load.rs index b41c42810aafd..073dc0ac94d9e 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-load.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-load.rs @@ -7,11 +7,11 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct Vec2(pub T, pub T); +pub struct Vec2(pub [T; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct Vec4(pub T, pub T, pub T, pub T); +pub struct Vec4(pub [T; 4]); extern "rust-intrinsic" { fn simd_masked_load(mask: M, pointer: P, values: T) -> T; diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-store.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-store.rs index 066392bcde682..7c3393e6f2e7b 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-store.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-store.rs @@ -7,11 +7,11 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct Vec2(pub T, pub T); +pub struct Vec2(pub [T; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct Vec4(pub T, pub T, pub T, pub T); +pub struct Vec4(pub [T; 4]); extern "rust-intrinsic" { fn simd_masked_store(mask: M, pointer: P, values: T) -> (); diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-scatter.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-scatter.rs index e85bd61c7f83b..3c75ef5be40be 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-scatter.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-scatter.rs @@ -9,11 +9,11 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct Vec2(pub T, pub T); +pub struct Vec2(pub [T; 2]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct Vec4(pub T, pub T, pub T, pub T); +pub struct Vec4(pub [T; 4]); extern "rust-intrinsic" { fn simd_scatter(value: T, pointers: P, mask: M); diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-select.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-select.rs index 05d2bf627ef12..c12fefa413b24 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-select.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-select.rs @@ -7,15 +7,15 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct f32x8(f32, f32, f32, f32, f32, f32, f32, f32); +pub struct f32x8([f32; 8]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -pub struct b8x4(pub i8, pub i8, pub i8, pub i8); +pub struct b8x4(pub [i8; 4]); extern "rust-intrinsic" { fn simd_select(x: T, a: U, b: U) -> U; diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs index c416f4d28bb53..75f989d6e12c4 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs @@ -13,10 +13,6 @@ pub struct S([f32; N]); #[derive(Copy, Clone)] pub struct T([f32; 4]); -#[repr(simd)] -#[derive(Copy, Clone)] -pub struct U(f32, f32, f32, f32); - // CHECK-LABEL: @array_align( #[no_mangle] pub fn array_align() -> usize { @@ -28,7 +24,7 @@ pub fn array_align() -> usize { #[no_mangle] pub fn vector_align() -> usize { // CHECK: ret [[USIZE]] [[VECTOR_ALIGN:[0-9]+]] - const { std::mem::align_of::() } + const { std::mem::align_of::() } } // CHECK-LABEL: @build_array_s @@ -60,22 +56,3 @@ pub fn build_array_transmute_t(x: [f32; 4]) -> T { // CHECK: store <4 x float> %[[VAL:.+]], ptr %_0, align [[VECTOR_ALIGN]] unsafe { std::mem::transmute(x) } } - -// CHECK-LABEL: @build_array_u -#[no_mangle] -pub fn build_array_u(x: [f32; 4]) -> U { - // CHECK: store float %a, {{.+}}, align [[VECTOR_ALIGN]] - // CHECK: store float %b, {{.+}}, align [[ARRAY_ALIGN]] - // CHECK: store float %c, {{.+}}, align - // CHECK: store float %d, {{.+}}, align [[ARRAY_ALIGN]] - let [a, b, c, d] = x; - U(a, b, c, d) -} - -// CHECK-LABEL: @build_array_transmute_u -#[no_mangle] -pub fn build_array_transmute_u(x: [f32; 4]) -> U { - // CHECK: %[[VAL:.+]] = load <4 x float>, ptr %x, align [[ARRAY_ALIGN]] - // CHECK: store <4 x float> %[[VAL:.+]], ptr %_0, align [[VECTOR_ALIGN]] - unsafe { std::mem::transmute(x) } -} diff --git a/tests/codegen/simd/unpadded-simd.rs b/tests/codegen/simd/unpadded-simd.rs index 66d9298c0068c..ef067a15702c3 100644 --- a/tests/codegen/simd/unpadded-simd.rs +++ b/tests/codegen/simd/unpadded-simd.rs @@ -7,7 +7,7 @@ #[derive(Copy, Clone)] #[repr(simd)] -pub struct int16x4_t(pub i16, pub i16, pub i16, pub i16); +pub struct int16x4_t(pub [i16; 4]); #[derive(Copy, Clone)] pub struct int16x4x2_t(pub int16x4_t, pub int16x4_t); diff --git a/tests/codegen/union-abi.rs b/tests/codegen/union-abi.rs index 08015014456ce..a1c081d7d61c2 100644 --- a/tests/codegen/union-abi.rs +++ b/tests/codegen/union-abi.rs @@ -16,7 +16,7 @@ pub enum Unhab {} #[repr(simd)] #[derive(Copy, Clone)] -pub struct i64x4(i64, i64, i64, i64); +pub struct i64x4([i64; 4]); #[derive(Copy, Clone)] pub union UnionI64x4 { diff --git a/tests/codegen/zst-offset.rs b/tests/codegen/zst-offset.rs index 14e97fd26ddf7..475394a881561 100644 --- a/tests/codegen/zst-offset.rs +++ b/tests/codegen/zst-offset.rs @@ -27,7 +27,7 @@ pub fn scalarpair_layout(s: &(u64, u32, ())) { } #[repr(simd)] -pub struct U64x4(u64, u64, u64, u64); +pub struct U64x4([u64; 4]); // Check that we correctly generate a GEP for a ZST that is not included in Vector layout // CHECK-LABEL: @vector_layout diff --git a/tests/debuginfo/simd.rs b/tests/debuginfo/simd.rs index e4fe262235bae..12675a71a5708 100644 --- a/tests/debuginfo/simd.rs +++ b/tests/debuginfo/simd.rs @@ -10,27 +10,27 @@ // gdb-command:run // gdb-command:print vi8x16 -// gdb-check:$1 = simd::i8x16 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) +// gdb-check:$1 = simd::i8x16 ([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) // gdb-command:print vi16x8 -// gdb-check:$2 = simd::i16x8 (16, 17, 18, 19, 20, 21, 22, 23) +// gdb-check:$2 = simd::i16x8 ([16, 17, 18, 19, 20, 21, 22, 23]) // gdb-command:print vi32x4 -// gdb-check:$3 = simd::i32x4 (24, 25, 26, 27) +// gdb-check:$3 = simd::i32x4 ([24, 25, 26, 27]) // gdb-command:print vi64x2 -// gdb-check:$4 = simd::i64x2 (28, 29) +// gdb-check:$4 = simd::i64x2 ([28, 29]) // gdb-command:print vu8x16 -// gdb-check:$5 = simd::u8x16 (30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45) +// gdb-check:$5 = simd::u8x16 ([30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45]) // gdb-command:print vu16x8 -// gdb-check:$6 = simd::u16x8 (46, 47, 48, 49, 50, 51, 52, 53) +// gdb-check:$6 = simd::u16x8 ([46, 47, 48, 49, 50, 51, 52, 53]) // gdb-command:print vu32x4 -// gdb-check:$7 = simd::u32x4 (54, 55, 56, 57) +// gdb-check:$7 = simd::u32x4 ([54, 55, 56, 57]) // gdb-command:print vu64x2 -// gdb-check:$8 = simd::u64x2 (58, 59) +// gdb-check:$8 = simd::u64x2 ([58, 59]) // gdb-command:print vf32x4 -// gdb-check:$9 = simd::f32x4 (60.5, 61.5, 62.5, 63.5) +// gdb-check:$9 = simd::f32x4 ([60.5, 61.5, 62.5, 63.5]) // gdb-command:print vf64x2 -// gdb-check:$10 = simd::f64x2 (64.5, 65.5) +// gdb-check:$10 = simd::f64x2 ([64.5, 65.5]) // gdb-command:continue @@ -40,43 +40,43 @@ #![feature(repr_simd)] #[repr(simd)] -struct i8x16(i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8); +struct i8x16([i8; 16]); #[repr(simd)] -struct i16x8(i16, i16, i16, i16, i16, i16, i16, i16); +struct i16x8([i16; 8]); #[repr(simd)] -struct i32x4(i32, i32, i32, i32); +struct i32x4([i32; 4]); #[repr(simd)] -struct i64x2(i64, i64); +struct i64x2([i64; 2]); #[repr(simd)] -struct u8x16(u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8); +struct u8x16([u8; 16]); #[repr(simd)] -struct u16x8(u16, u16, u16, u16, u16, u16, u16, u16); +struct u16x8([u16; 8]); #[repr(simd)] -struct u32x4(u32, u32, u32, u32); +struct u32x4([u32; 4]); #[repr(simd)] -struct u64x2(u64, u64); +struct u64x2([u64; 2]); #[repr(simd)] -struct f32x4(f32, f32, f32, f32); +struct f32x4([f32; 4]); #[repr(simd)] -struct f64x2(f64, f64); +struct f64x2([f64; 2]); fn main() { - let vi8x16 = i8x16(0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15); + let vi8x16 = i8x16([0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15]); - let vi16x8 = i16x8(16, 17, 18, 19, 20, 21, 22, 23); - let vi32x4 = i32x4(24, 25, 26, 27); - let vi64x2 = i64x2(28, 29); + let vi16x8 = i16x8([16, 17, 18, 19, 20, 21, 22, 23]); + let vi32x4 = i32x4([24, 25, 26, 27]); + let vi64x2 = i64x2([28, 29]); - let vu8x16 = u8x16(30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45); - let vu16x8 = u16x8(46, 47, 48, 49, 50, 51, 52, 53); - let vu32x4 = u32x4(54, 55, 56, 57); - let vu64x2 = u64x2(58, 59); + let vu8x16 = u8x16([30, 31, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 41, 42, 43, 44, 45]); + let vu16x8 = u16x8([46, 47, 48, 49, 50, 51, 52, 53]); + let vu32x4 = u32x4([54, 55, 56, 57]); + let vu64x2 = u64x2([58, 59]); - let vf32x4 = f32x4(60.5f32, 61.5f32, 62.5f32, 63.5f32); - let vf64x2 = f64x2(64.5f64, 65.5f64); + let vf32x4 = f32x4([60.5f32, 61.5f32, 62.5f32, 63.5f32]); + let vf64x2 = f64x2([64.5f64, 65.5f64]); zzz(); // #break } diff --git a/tests/incremental/issue-61530.rs b/tests/incremental/issue-61530.rs index e4ee8ccbc4bd2..b4914dda11ae1 100644 --- a/tests/incremental/issue-61530.rs +++ b/tests/incremental/issue-61530.rs @@ -3,7 +3,7 @@ //@ revisions:rpass1 rpass2 #[repr(simd)] -struct I32x2(i32, i32); +struct I32x2([i32; 2]); extern "rust-intrinsic" { fn simd_shuffle(x: T, y: T, idx: I) -> U; @@ -12,7 +12,7 @@ extern "rust-intrinsic" { fn main() { unsafe { const IDX: [u32; 2] = [0, 0]; - let _: I32x2 = simd_shuffle(I32x2(1, 2), I32x2(3, 4), IDX); - let _: I32x2 = simd_shuffle(I32x2(1, 2), I32x2(3, 4), IDX); + let _: I32x2 = simd_shuffle(I32x2([1, 2]), I32x2([3, 4]), IDX); + let _: I32x2 = simd_shuffle(I32x2([1, 2]), I32x2([3, 4]), IDX); } } diff --git a/tests/run-make/simd-ffi/simd.rs b/tests/run-make/simd-ffi/simd.rs index d11cfd77c5bf9..b72078faafa26 100644 --- a/tests/run-make/simd-ffi/simd.rs +++ b/tests/run-make/simd-ffi/simd.rs @@ -8,7 +8,7 @@ #[derive(Copy)] #[repr(simd)] -pub struct f32x4(f32, f32, f32, f32); +pub struct f32x4([f32; 4]); extern "C" { #[link_name = "llvm.sqrt.v4f32"] @@ -21,7 +21,7 @@ pub fn foo(x: f32x4) -> f32x4 { #[derive(Copy)] #[repr(simd)] -pub struct i32x4(i32, i32, i32, i32); +pub struct i32x4([i32; 4]); extern "C" { // _mm_sll_epi32 @@ -62,6 +62,8 @@ pub trait Copy {} impl Copy for f32 {} impl Copy for i32 {} +impl Copy for [f32; 4] {} +impl Copy for [i32; 4] {} pub mod marker { pub use Copy; diff --git a/tests/rustdoc/inline_cross/auxiliary/repr.rs b/tests/rustdoc/inline_cross/auxiliary/repr.rs index 35f08c11b7b3a..0211e1a86588f 100644 --- a/tests/rustdoc/inline_cross/auxiliary/repr.rs +++ b/tests/rustdoc/inline_cross/auxiliary/repr.rs @@ -6,7 +6,7 @@ pub struct ReprC { } #[repr(simd, packed(2))] pub struct ReprSimd { - field: u8, + field: [u8; 1], } #[repr(transparent)] pub struct ReprTransparent { diff --git a/tests/ui/abi/arm-unadjusted-intrinsic.rs b/tests/ui/abi/arm-unadjusted-intrinsic.rs index 7a728d4b241d9..533cd40b30a5c 100644 --- a/tests/ui/abi/arm-unadjusted-intrinsic.rs +++ b/tests/ui/abi/arm-unadjusted-intrinsic.rs @@ -25,16 +25,13 @@ impl Copy for i8 {} impl Copy for *const T {} impl Copy for *mut T {} +// I hate no_core tests! +impl Copy for [T; N] {} // Regression test for https://github.com/rust-lang/rust/issues/118124. #[repr(simd)] -pub struct int8x16_t( - pub(crate) i8, pub(crate) i8, pub(crate) i8, pub(crate) i8, - pub(crate) i8, pub(crate) i8, pub(crate) i8, pub(crate) i8, - pub(crate) i8, pub(crate) i8, pub(crate) i8, pub(crate) i8, - pub(crate) i8, pub(crate) i8, pub(crate) i8, pub(crate) i8, -); +pub struct int8x16_t(pub(crate) [i8; 16]); impl Copy for int8x16_t {} #[repr(C)] diff --git a/tests/ui/abi/homogenous-floats-target-feature-mixup.rs b/tests/ui/abi/homogenous-floats-target-feature-mixup.rs index 3a8540a825ca2..4afb710b193eb 100644 --- a/tests/ui/abi/homogenous-floats-target-feature-mixup.rs +++ b/tests/ui/abi/homogenous-floats-target-feature-mixup.rs @@ -65,13 +65,13 @@ fn is_sigill(status: ExitStatus) -> bool { #[allow(nonstandard_style)] mod test { #[derive(PartialEq, Debug, Clone, Copy)] - struct f32x2(f32, f32); + struct f32x2([f32; 2]); #[derive(PartialEq, Debug, Clone, Copy)] - struct f32x4(f32, f32, f32, f32); + struct f32x4([f32; 4]); #[derive(PartialEq, Debug, Clone, Copy)] - struct f32x8(f32, f32, f32, f32, f32, f32, f32, f32); + struct f32x8([f32; 8]); pub fn main(level: &str) { unsafe { @@ -97,9 +97,9 @@ mod test { )*) => ($( $(#[$attr])* unsafe fn $main(level: &str) { - let m128 = f32x2(1., 2.); - let m256 = f32x4(3., 4., 5., 6.); - let m512 = f32x8(7., 8., 9., 10., 11., 12., 13., 14.); + let m128 = f32x2([1., 2.]); + let m256 = f32x4([3., 4., 5., 6.]); + let m512 = f32x8([7., 8., 9., 10., 11., 12., 13., 14.]); assert_eq!(id_sse_128(m128), m128); assert_eq!(id_sse_256(m256), m256); assert_eq!(id_sse_512(m512), m512); @@ -133,55 +133,55 @@ mod test { #[target_feature(enable = "sse2")] unsafe fn id_sse_128(a: f32x2) -> f32x2 { - assert_eq!(a, f32x2(1., 2.)); + assert_eq!(a, f32x2([1., 2.])); a.clone() } #[target_feature(enable = "sse2")] unsafe fn id_sse_256(a: f32x4) -> f32x4 { - assert_eq!(a, f32x4(3., 4., 5., 6.)); + assert_eq!(a, f32x4([3., 4., 5., 6.])); a.clone() } #[target_feature(enable = "sse2")] unsafe fn id_sse_512(a: f32x8) -> f32x8 { - assert_eq!(a, f32x8(7., 8., 9., 10., 11., 12., 13., 14.)); + assert_eq!(a, f32x8([7., 8., 9., 10., 11., 12., 13., 14.])); a.clone() } #[target_feature(enable = "avx")] unsafe fn id_avx_128(a: f32x2) -> f32x2 { - assert_eq!(a, f32x2(1., 2.)); + assert_eq!(a, f32x2([1., 2.])); a.clone() } #[target_feature(enable = "avx")] unsafe fn id_avx_256(a: f32x4) -> f32x4 { - assert_eq!(a, f32x4(3., 4., 5., 6.)); + assert_eq!(a, f32x4([3., 4., 5., 6.])); a.clone() } #[target_feature(enable = "avx")] unsafe fn id_avx_512(a: f32x8) -> f32x8 { - assert_eq!(a, f32x8(7., 8., 9., 10., 11., 12., 13., 14.)); + assert_eq!(a, f32x8([7., 8., 9., 10., 11., 12., 13., 14.])); a.clone() } #[target_feature(enable = "avx512bw")] unsafe fn id_avx512_128(a: f32x2) -> f32x2 { - assert_eq!(a, f32x2(1., 2.)); + assert_eq!(a, f32x2([1., 2.])); a.clone() } #[target_feature(enable = "avx512bw")] unsafe fn id_avx512_256(a: f32x4) -> f32x4 { - assert_eq!(a, f32x4(3., 4., 5., 6.)); + assert_eq!(a, f32x4([3., 4., 5., 6.])); a.clone() } #[target_feature(enable = "avx512bw")] unsafe fn id_avx512_512(a: f32x8) -> f32x8 { - assert_eq!(a, f32x8(7., 8., 9., 10., 11., 12., 13., 14.)); + assert_eq!(a, f32x8([7., 8., 9., 10., 11., 12., 13., 14.])); a.clone() } } diff --git a/tests/ui/asm/aarch64/type-check-2-2.rs b/tests/ui/asm/aarch64/type-check-2-2.rs index f442ce81476ed..4b8ee1d922986 100644 --- a/tests/ui/asm/aarch64/type-check-2-2.rs +++ b/tests/ui/asm/aarch64/type-check-2-2.rs @@ -6,10 +6,10 @@ use std::arch::{asm, global_asm}; #[repr(simd)] #[derive(Clone, Copy)] -struct SimdType(f32, f32, f32, f32); +struct SimdType([f32; 4]); #[repr(simd)] -struct SimdNonCopy(f32, f32, f32, f32); +struct SimdNonCopy([f32; 4]); fn main() { unsafe { diff --git a/tests/ui/asm/aarch64/type-check-2.rs b/tests/ui/asm/aarch64/type-check-2.rs index 46667ae3a6565..ad223b799b786 100644 --- a/tests/ui/asm/aarch64/type-check-2.rs +++ b/tests/ui/asm/aarch64/type-check-2.rs @@ -6,10 +6,10 @@ use std::arch::{asm, global_asm}; #[repr(simd)] #[derive(Clone, Copy)] -struct SimdType(f32, f32, f32, f32); +struct SimdType([f32; 4]); #[repr(simd)] -struct SimdNonCopy(f32, f32, f32, f32); +struct SimdNonCopy([f32; 4]); fn main() { unsafe { @@ -17,7 +17,7 @@ fn main() { // Register operands must be Copy - asm!("{:v}", in(vreg) SimdNonCopy(0.0, 0.0, 0.0, 0.0)); + asm!("{:v}", in(vreg) SimdNonCopy([0.0, 0.0, 0.0, 0.0])); //~^ ERROR arguments for inline assembly must be copyable // Register operands must be integers, floats, SIMD vectors, pointers or @@ -25,7 +25,7 @@ fn main() { asm!("{}", in(reg) 0i64); asm!("{}", in(reg) 0f64); - asm!("{:v}", in(vreg) SimdType(0.0, 0.0, 0.0, 0.0)); + asm!("{:v}", in(vreg) SimdType([0.0, 0.0, 0.0, 0.0])); asm!("{}", in(reg) 0 as *const u8); asm!("{}", in(reg) 0 as *mut u8); asm!("{}", in(reg) main as fn()); diff --git a/tests/ui/asm/aarch64/type-check-2.stderr b/tests/ui/asm/aarch64/type-check-2.stderr index b7723fc74d4b6..84bc5f08b4ed1 100644 --- a/tests/ui/asm/aarch64/type-check-2.stderr +++ b/tests/ui/asm/aarch64/type-check-2.stderr @@ -1,8 +1,8 @@ error: arguments for inline assembly must be copyable --> $DIR/type-check-2.rs:20:31 | -LL | asm!("{:v}", in(vreg) SimdNonCopy(0.0, 0.0, 0.0, 0.0)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | asm!("{:v}", in(vreg) SimdNonCopy([0.0, 0.0, 0.0, 0.0])); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `SimdNonCopy` does not implement the Copy trait diff --git a/tests/ui/asm/aarch64/type-check-3.rs b/tests/ui/asm/aarch64/type-check-3.rs index b64473f98c090..2f8439d0a0f9e 100644 --- a/tests/ui/asm/aarch64/type-check-3.rs +++ b/tests/ui/asm/aarch64/type-check-3.rs @@ -8,11 +8,11 @@ use std::arch::{asm, global_asm}; #[repr(simd)] #[derive(Copy, Clone)] -struct Simd256bit(f64, f64, f64, f64); +struct Simd256bit([f64; 4]); fn main() { let f64x2: float64x2_t = unsafe { std::mem::transmute(0i128) }; - let f64x4 = Simd256bit(0.0, 0.0, 0.0, 0.0); + let f64x4 = Simd256bit([0.0, 0.0, 0.0, 0.0]); unsafe { // Types must be listed in the register class. diff --git a/tests/ui/asm/aarch64/type-check-4.rs b/tests/ui/asm/aarch64/type-check-4.rs index 41eb9de5669f6..1169c3dcfa843 100644 --- a/tests/ui/asm/aarch64/type-check-4.rs +++ b/tests/ui/asm/aarch64/type-check-4.rs @@ -8,7 +8,7 @@ use std::arch::{asm, global_asm}; #[repr(simd)] #[derive(Copy, Clone)] -struct Simd256bit(f64, f64, f64, f64); +struct Simd256bit([f64; 4]); fn main() {} diff --git a/tests/ui/asm/x86_64/type-check-2.rs b/tests/ui/asm/x86_64/type-check-2.rs index ff811961462df..1650c595faebb 100644 --- a/tests/ui/asm/x86_64/type-check-2.rs +++ b/tests/ui/asm/x86_64/type-check-2.rs @@ -5,7 +5,7 @@ use std::arch::{asm, global_asm}; #[repr(simd)] -struct SimdNonCopy(f32, f32, f32, f32); +struct SimdNonCopy([f32; 4]); fn main() { unsafe { @@ -29,7 +29,7 @@ fn main() { // Register operands must be Copy - asm!("{}", in(xmm_reg) SimdNonCopy(0.0, 0.0, 0.0, 0.0)); + asm!("{}", in(xmm_reg) SimdNonCopy([0.0, 0.0, 0.0, 0.0])); //~^ ERROR arguments for inline assembly must be copyable // Register operands must be integers, floats, SIMD vectors, pointers or diff --git a/tests/ui/asm/x86_64/type-check-2.stderr b/tests/ui/asm/x86_64/type-check-2.stderr index c72e695aefb83..8b1bfa85fa2c4 100644 --- a/tests/ui/asm/x86_64/type-check-2.stderr +++ b/tests/ui/asm/x86_64/type-check-2.stderr @@ -1,8 +1,8 @@ error: arguments for inline assembly must be copyable --> $DIR/type-check-2.rs:32:32 | -LL | asm!("{}", in(xmm_reg) SimdNonCopy(0.0, 0.0, 0.0, 0.0)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | asm!("{}", in(xmm_reg) SimdNonCopy([0.0, 0.0, 0.0, 0.0])); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `SimdNonCopy` does not implement the Copy trait diff --git a/tests/ui/asm/x86_64/type-check-5.rs b/tests/ui/asm/x86_64/type-check-5.rs index b5b51f6116890..81e096a72300a 100644 --- a/tests/ui/asm/x86_64/type-check-5.rs +++ b/tests/ui/asm/x86_64/type-check-5.rs @@ -1,12 +1,9 @@ //@ only-x86_64 -#![feature(repr_simd, never_type)] +#![feature(never_type)] use std::arch::asm; -#[repr(simd)] -struct SimdNonCopy(f32, f32, f32, f32); - fn main() { unsafe { // Inputs must be initialized diff --git a/tests/ui/asm/x86_64/type-check-5.stderr b/tests/ui/asm/x86_64/type-check-5.stderr index 4fb759934636d..377e1d19f6c5c 100644 --- a/tests/ui/asm/x86_64/type-check-5.stderr +++ b/tests/ui/asm/x86_64/type-check-5.stderr @@ -1,5 +1,5 @@ error[E0381]: used binding `x` isn't initialized - --> $DIR/type-check-5.rs:15:28 + --> $DIR/type-check-5.rs:12:28 | LL | let x: u64; | - binding declared here but left uninitialized @@ -12,7 +12,7 @@ LL | let x: u64 = 42; | ++++ error[E0381]: used binding `y` isn't initialized - --> $DIR/type-check-5.rs:18:9 + --> $DIR/type-check-5.rs:15:9 | LL | let mut y: u64; | ----- binding declared here but left uninitialized @@ -25,7 +25,7 @@ LL | let mut y: u64 = 42; | ++++ error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable - --> $DIR/type-check-5.rs:24:13 + --> $DIR/type-check-5.rs:21:13 | LL | let v: Vec = vec![0, 1, 2]; | ^ not mutable diff --git a/tests/ui/consts/const-eval/simd/insert_extract.rs b/tests/ui/consts/const-eval/simd/insert_extract.rs index fc7dbd5a41c34..f4f25327aaf11 100644 --- a/tests/ui/consts/const-eval/simd/insert_extract.rs +++ b/tests/ui/consts/const-eval/simd/insert_extract.rs @@ -5,10 +5,9 @@ #![stable(feature = "foo", since = "1.3.37")] #![allow(non_camel_case_types)] -#[repr(simd)] struct i8x1(i8); -#[repr(simd)] struct u16x2(u16, u16); -// Make some of them array types to ensure those also work. -#[repr(simd)] struct i8x1_arr([i8; 1]); +// repr(simd) now only supports array types +#[repr(simd)] struct i8x1([i8; 1]); +#[repr(simd)] struct u16x2([u16; 2]); #[repr(simd)] struct f32x4([f32; 4]); extern "rust-intrinsic" { @@ -20,26 +19,18 @@ extern "rust-intrinsic" { fn main() { { - const U: i8x1 = i8x1(13); + const U: i8x1 = i8x1([13]); const V: i8x1 = unsafe { simd_insert(U, 0_u32, 42_i8) }; - const X0: i8 = V.0; - const Y0: i8 = unsafe { simd_extract(V, 0) }; - assert_eq!(X0, 42); - assert_eq!(Y0, 42); - } - { - const U: i8x1_arr = i8x1_arr([13]); - const V: i8x1_arr = unsafe { simd_insert(U, 0_u32, 42_i8) }; const X0: i8 = V.0[0]; const Y0: i8 = unsafe { simd_extract(V, 0) }; assert_eq!(X0, 42); assert_eq!(Y0, 42); } { - const U: u16x2 = u16x2(13, 14); + const U: u16x2 = u16x2([13, 14]); const V: u16x2 = unsafe { simd_insert(U, 1_u32, 42_u16) }; - const X0: u16 = V.0; - const X1: u16 = V.1; + const X0: u16 = V.0[0]; + const X1: u16 = V.0[1]; const Y0: u16 = unsafe { simd_extract(V, 0) }; const Y1: u16 = unsafe { simd_extract(V, 1) }; assert_eq!(X0, 13); diff --git a/tests/ui/error-codes/E0075.rs b/tests/ui/error-codes/E0075.rs index 7feab0a8bd7a2..2c610d9186b64 100644 --- a/tests/ui/error-codes/E0075.rs +++ b/tests/ui/error-codes/E0075.rs @@ -3,5 +3,8 @@ #[repr(simd)] struct Bad; //~ ERROR E0075 +#[repr(simd)] +struct AlsoBad([i32; 1], [i32; 1]); //~ ERROR E0075 + fn main() { } diff --git a/tests/ui/error-codes/E0075.stderr b/tests/ui/error-codes/E0075.stderr index 43e9971e3095d..0a44a2eadebd1 100644 --- a/tests/ui/error-codes/E0075.stderr +++ b/tests/ui/error-codes/E0075.stderr @@ -4,6 +4,12 @@ error[E0075]: SIMD vector cannot be empty LL | struct Bad; | ^^^^^^^^^^ -error: aborting due to 1 previous error +error[E0075]: SIMD vector cannot have multiple fields + --> $DIR/E0075.rs:7:1 + | +LL | struct AlsoBad([i32; 1], [i32; 1]); + | ^^^^^^^^^^^^^^ -------- excess field + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0075`. diff --git a/tests/ui/error-codes/E0076.rs b/tests/ui/error-codes/E0076.rs index a27072eb71e68..2c0376fe7e0bd 100644 --- a/tests/ui/error-codes/E0076.rs +++ b/tests/ui/error-codes/E0076.rs @@ -1,7 +1,7 @@ #![feature(repr_simd)] #[repr(simd)] -struct Bad(u16, u32, u32); +struct Bad(u32); //~^ ERROR E0076 fn main() { diff --git a/tests/ui/error-codes/E0076.stderr b/tests/ui/error-codes/E0076.stderr index ea3bbf094976f..8bf46cf38e338 100644 --- a/tests/ui/error-codes/E0076.stderr +++ b/tests/ui/error-codes/E0076.stderr @@ -1,8 +1,8 @@ -error[E0076]: SIMD vector should be homogeneous +error[E0076]: SIMD vector's only field must be an array --> $DIR/E0076.rs:4:1 | -LL | struct Bad(u16, u32, u32); - | ^^^^^^^^^^ SIMD elements must have the same type +LL | struct Bad(u32); + | ^^^^^^^^^^ --- not an array error: aborting due to 1 previous error diff --git a/tests/ui/error-codes/E0077.rs b/tests/ui/error-codes/E0077.rs index fa2d5e24fa3ca..2704bbeb4ea17 100644 --- a/tests/ui/error-codes/E0077.rs +++ b/tests/ui/error-codes/E0077.rs @@ -1,7 +1,7 @@ #![feature(repr_simd)] #[repr(simd)] -struct Bad(String); //~ ERROR E0077 +struct Bad([String; 2]); //~ ERROR E0077 fn main() { } diff --git a/tests/ui/error-codes/E0077.stderr b/tests/ui/error-codes/E0077.stderr index aae4b3f2c2927..063b40a147c57 100644 --- a/tests/ui/error-codes/E0077.stderr +++ b/tests/ui/error-codes/E0077.stderr @@ -1,7 +1,7 @@ error[E0077]: SIMD vector element type should be a primitive scalar (integer/float/pointer) type --> $DIR/E0077.rs:4:1 | -LL | struct Bad(String); +LL | struct Bad([String; 2]); | ^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/feature-gates/feature-gate-repr-simd.rs b/tests/ui/feature-gates/feature-gate-repr-simd.rs index c527404f57270..65ade97c7e1c3 100644 --- a/tests/ui/feature-gates/feature-gate-repr-simd.rs +++ b/tests/ui/feature-gates/feature-gate-repr-simd.rs @@ -1,9 +1,9 @@ #[repr(simd)] //~ error: SIMD types are experimental -struct Foo(u64, u64); +struct Foo([u64; 2]); #[repr(C)] //~ ERROR conflicting representation hints //~^ WARN this was previously accepted #[repr(simd)] //~ error: SIMD types are experimental -struct Bar(u64, u64); +struct Bar([u64; 2]); fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-simd-ffi.rs b/tests/ui/feature-gates/feature-gate-simd-ffi.rs index abffa4a10010d..2ee935e07ffa4 100644 --- a/tests/ui/feature-gates/feature-gate-simd-ffi.rs +++ b/tests/ui/feature-gates/feature-gate-simd-ffi.rs @@ -3,7 +3,7 @@ #[repr(simd)] #[derive(Copy, Clone)] -struct LocalSimd(u8, u8); +struct LocalSimd([u8; 2]); extern "C" { fn baz() -> LocalSimd; //~ ERROR use of SIMD type diff --git a/tests/ui/feature-gates/feature-gate-simd.rs b/tests/ui/feature-gates/feature-gate-simd.rs index de5f645e6fd0b..e7aef5a97f2ee 100644 --- a/tests/ui/feature-gates/feature-gate-simd.rs +++ b/tests/ui/feature-gates/feature-gate-simd.rs @@ -2,10 +2,7 @@ #[repr(simd)] //~ ERROR SIMD types are experimental struct RGBA { - r: f32, - g: f32, - b: f32, - a: f32 + rgba: [f32; 4], } pub fn main() {} diff --git a/tests/ui/layout/debug.rs b/tests/ui/layout/debug.rs index aeacbc784462d..91e96d78ff556 100644 --- a/tests/ui/layout/debug.rs +++ b/tests/ui/layout/debug.rs @@ -49,7 +49,7 @@ union P2 { x: (u32, u32) } //~ ERROR: layout_of #[repr(simd)] #[derive(Copy, Clone)] -struct F32x4(f32, f32, f32, f32); +struct F32x4([f32; 4]); #[rustc_layout(debug)] #[repr(packed(1))] diff --git a/tests/ui/repr/attr-usage-repr.rs b/tests/ui/repr/attr-usage-repr.rs index 8965decc37989..dc0d4f5be2e30 100644 --- a/tests/ui/repr/attr-usage-repr.rs +++ b/tests/ui/repr/attr-usage-repr.rs @@ -10,7 +10,7 @@ struct SExtern(f64, f64); struct SPacked(f64, f64); #[repr(simd)] -struct SSimd(f64, f64); +struct SSimd([f64; 2]); #[repr(i8)] //~ ERROR: attribute should be applied to an enum struct SInt(f64, f64); diff --git a/tests/ui/repr/explicit-rust-repr-conflicts.rs b/tests/ui/repr/explicit-rust-repr-conflicts.rs index 22dd12d316ac5..5278f5e6ae0cc 100644 --- a/tests/ui/repr/explicit-rust-repr-conflicts.rs +++ b/tests/ui/repr/explicit-rust-repr-conflicts.rs @@ -18,6 +18,6 @@ enum U { #[repr(Rust, simd)] //~^ ERROR conflicting representation hints //~| ERROR SIMD types are experimental and possibly buggy -struct F32x4(f32, f32, f32, f32); +struct F32x4([f32; 4]); fn main() {} diff --git a/tests/ui/simd/const-err-trumps-simd-err.rs b/tests/ui/simd/const-err-trumps-simd-err.rs index fda044344517d..fb87fe1cbca83 100644 --- a/tests/ui/simd/const-err-trumps-simd-err.rs +++ b/tests/ui/simd/const-err-trumps-simd-err.rs @@ -10,7 +10,7 @@ use std::intrinsics::simd::*; #[repr(simd)] #[allow(non_camel_case_types)] -struct int8x4_t(u8,u8,u8,u8); +struct int8x4_t([u8; 4]); fn get_elem(a: int8x4_t) -> u8 { const { assert!(LANE < 4); } // the error should be here... @@ -20,5 +20,5 @@ fn get_elem(a: int8x4_t) -> u8 { } fn main() { - get_elem::<4>(int8x4_t(0,0,0,0)); + get_elem::<4>(int8x4_t([0, 0, 0, 0])); } diff --git a/tests/ui/simd/const-err-trumps-simd-err.stderr b/tests/ui/simd/const-err-trumps-simd-err.stderr index 1e46667cf4e2a..11cbcad227ff8 100644 --- a/tests/ui/simd/const-err-trumps-simd-err.stderr +++ b/tests/ui/simd/const-err-trumps-simd-err.stderr @@ -15,8 +15,8 @@ LL | const { assert!(LANE < 4); } // the error should be here... note: the above error was encountered while instantiating `fn get_elem::<4>` --> $DIR/const-err-trumps-simd-err.rs:23:5 | -LL | get_elem::<4>(int8x4_t(0,0,0,0)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | get_elem::<4>(int8x4_t([0, 0, 0, 0])); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/simd/generics.rs b/tests/ui/simd/generics.rs index bd048b19ca886..f96a7cd75e933 100644 --- a/tests/ui/simd/generics.rs +++ b/tests/ui/simd/generics.rs @@ -6,7 +6,7 @@ use std::ops; #[repr(simd)] #[derive(Copy, Clone)] -struct f32x4(f32, f32, f32, f32); +struct f32x4([f32; 4]); #[repr(simd)] #[derive(Copy, Clone)] @@ -67,8 +67,8 @@ pub fn main() { let y = [2.0f32, 4.0f32, 6.0f32, 8.0f32]; // lame-o - let a = f32x4(1.0f32, 2.0f32, 3.0f32, 4.0f32); - let f32x4(a0, a1, a2, a3) = add(a, a); + let a = f32x4([1.0f32, 2.0f32, 3.0f32, 4.0f32]); + let f32x4([a0, a1, a2, a3]) = add(a, a); assert_eq!(a0, 2.0f32); assert_eq!(a1, 4.0f32); assert_eq!(a2, 6.0f32); diff --git a/tests/ui/simd/intrinsic/float-math-pass.rs b/tests/ui/simd/intrinsic/float-math-pass.rs index ea31e2a7c570e..9b14d410acbe3 100644 --- a/tests/ui/simd/intrinsic/float-math-pass.rs +++ b/tests/ui/simd/intrinsic/float-math-pass.rs @@ -13,7 +13,7 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -struct f32x4(pub f32, pub f32, pub f32, pub f32); +struct f32x4(pub [f32; 4]); extern "rust-intrinsic" { fn simd_fsqrt(x: T) -> T; @@ -47,19 +47,19 @@ macro_rules! assert_approx_eq { ($a:expr, $b:expr) => ({ let a = $a; let b = $b; - assert_approx_eq_f32!(a.0, b.0); - assert_approx_eq_f32!(a.1, b.1); - assert_approx_eq_f32!(a.2, b.2); - assert_approx_eq_f32!(a.3, b.3); + assert_approx_eq_f32!(a.0[0], b.0[0]); + assert_approx_eq_f32!(a.0[1], b.0[1]); + assert_approx_eq_f32!(a.0[2], b.0[2]); + assert_approx_eq_f32!(a.0[3], b.0[3]); }) } fn main() { - let x = f32x4(1.0, 1.0, 1.0, 1.0); - let y = f32x4(-1.0, -1.0, -1.0, -1.0); - let z = f32x4(0.0, 0.0, 0.0, 0.0); + let x = f32x4([1.0, 1.0, 1.0, 1.0]); + let y = f32x4([-1.0, -1.0, -1.0, -1.0]); + let z = f32x4([0.0, 0.0, 0.0, 0.0]); - let h = f32x4(0.5, 0.5, 0.5, 0.5); + let h = f32x4([0.5, 0.5, 0.5, 0.5]); unsafe { let r = simd_fabs(y); diff --git a/tests/ui/simd/intrinsic/float-minmax-pass.rs b/tests/ui/simd/intrinsic/float-minmax-pass.rs index d6cbcd4e05a63..00c0d8cea3fa5 100644 --- a/tests/ui/simd/intrinsic/float-minmax-pass.rs +++ b/tests/ui/simd/intrinsic/float-minmax-pass.rs @@ -8,13 +8,13 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -struct f32x4(pub f32, pub f32, pub f32, pub f32); +struct f32x4(pub [f32; 4]); use std::intrinsics::simd::*; fn main() { - let x = f32x4(1.0, 2.0, 3.0, 4.0); - let y = f32x4(2.0, 1.0, 4.0, 3.0); + let x = f32x4([1.0, 2.0, 3.0, 4.0]); + let y = f32x4([2.0, 1.0, 4.0, 3.0]); #[cfg(not(any(target_arch = "mips", target_arch = "mips64")))] let nan = f32::NAN; @@ -23,13 +23,13 @@ fn main() { #[cfg(any(target_arch = "mips", target_arch = "mips64"))] let nan = f32::from_bits(f32::NAN.to_bits() - 1); - let n = f32x4(nan, nan, nan, nan); + let n = f32x4([nan, nan, nan, nan]); unsafe { let min0 = simd_fmin(x, y); let min1 = simd_fmin(y, x); assert_eq!(min0, min1); - let e = f32x4(1.0, 1.0, 3.0, 3.0); + let e = f32x4([1.0, 1.0, 3.0, 3.0]); assert_eq!(min0, e); let minn = simd_fmin(x, n); assert_eq!(minn, x); @@ -39,7 +39,7 @@ fn main() { let max0 = simd_fmax(x, y); let max1 = simd_fmax(y, x); assert_eq!(max0, max1); - let e = f32x4(2.0, 2.0, 4.0, 4.0); + let e = f32x4([2.0, 2.0, 4.0, 4.0]); assert_eq!(max0, e); let maxn = simd_fmax(x, n); assert_eq!(maxn, x); diff --git a/tests/ui/simd/intrinsic/generic-arithmetic-2.rs b/tests/ui/simd/intrinsic/generic-arithmetic-2.rs index fc3087cbf7542..663bcdf198193 100644 --- a/tests/ui/simd/intrinsic/generic-arithmetic-2.rs +++ b/tests/ui/simd/intrinsic/generic-arithmetic-2.rs @@ -4,15 +4,15 @@ #![allow(non_camel_case_types)] #[repr(simd)] #[derive(Copy, Clone)] -pub struct i32x4(pub i32, pub i32, pub i32, pub i32); +pub struct i32x4(pub [i32; 4]); #[repr(simd)] #[derive(Copy, Clone)] -pub struct u32x4(pub u32, pub u32, pub u32, pub u32); +pub struct u32x4(pub [u32; 4]); #[repr(simd)] #[derive(Copy, Clone)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); extern "rust-intrinsic" { fn simd_add(x: T, y: T) -> T; @@ -35,9 +35,9 @@ extern "rust-intrinsic" { } fn main() { - let x = i32x4(0, 0, 0, 0); - let y = u32x4(0, 0, 0, 0); - let z = f32x4(0.0, 0.0, 0.0, 0.0); + let x = i32x4([0, 0, 0, 0]); + let y = u32x4([0, 0, 0, 0]); + let z = f32x4([0.0, 0.0, 0.0, 0.0]); unsafe { simd_add(x, x); diff --git a/tests/ui/simd/intrinsic/generic-arithmetic-pass.rs b/tests/ui/simd/intrinsic/generic-arithmetic-pass.rs index 60dfa62741488..e4eb2a9da2718 100644 --- a/tests/ui/simd/intrinsic/generic-arithmetic-pass.rs +++ b/tests/ui/simd/intrinsic/generic-arithmetic-pass.rs @@ -5,7 +5,7 @@ #[repr(simd)] #[derive(Copy, Clone)] -struct i32x4(pub i32, pub i32, pub i32, pub i32); +struct i32x4(pub [i32; 4]); #[repr(simd)] #[derive(Copy, Clone)] @@ -13,17 +13,9 @@ struct U32([u32; N]); #[repr(simd)] #[derive(Copy, Clone)] -struct f32x4(pub f32, pub f32, pub f32, pub f32); +struct f32x4(pub [f32; 4]); macro_rules! all_eq { - ($a: expr, $b: expr) => {{ - let a = $a; - let b = $b; - assert!(a.0 == b.0 && a.1 == b.1 && a.2 == b.2 && a.3 == b.3); - }}; -} - -macro_rules! all_eq_ { ($a: expr, $b: expr) => {{ let a = $a; let b = $b; @@ -52,112 +44,112 @@ extern "rust-intrinsic" { } fn main() { - let x1 = i32x4(1, 2, 3, 4); + let x1 = i32x4([1, 2, 3, 4]); let y1 = U32::<4>([1, 2, 3, 4]); - let z1 = f32x4(1.0, 2.0, 3.0, 4.0); - let x2 = i32x4(2, 3, 4, 5); + let z1 = f32x4([1.0, 2.0, 3.0, 4.0]); + let x2 = i32x4([2, 3, 4, 5]); let y2 = U32::<4>([2, 3, 4, 5]); - let z2 = f32x4(2.0, 3.0, 4.0, 5.0); - let x3 = i32x4(0, i32::MAX, i32::MIN, -1_i32); + let z2 = f32x4([2.0, 3.0, 4.0, 5.0]); + let x3 = i32x4([0, i32::MAX, i32::MIN, -1_i32]); let y3 = U32::<4>([0, i32::MAX as _, i32::MIN as _, -1_i32 as _]); unsafe { - all_eq!(simd_add(x1, x2), i32x4(3, 5, 7, 9)); - all_eq!(simd_add(x2, x1), i32x4(3, 5, 7, 9)); - all_eq_!(simd_add(y1, y2), U32::<4>([3, 5, 7, 9])); - all_eq_!(simd_add(y2, y1), U32::<4>([3, 5, 7, 9])); - all_eq!(simd_add(z1, z2), f32x4(3.0, 5.0, 7.0, 9.0)); - all_eq!(simd_add(z2, z1), f32x4(3.0, 5.0, 7.0, 9.0)); - - all_eq!(simd_mul(x1, x2), i32x4(2, 6, 12, 20)); - all_eq!(simd_mul(x2, x1), i32x4(2, 6, 12, 20)); - all_eq_!(simd_mul(y1, y2), U32::<4>([2, 6, 12, 20])); - all_eq_!(simd_mul(y2, y1), U32::<4>([2, 6, 12, 20])); - all_eq!(simd_mul(z1, z2), f32x4(2.0, 6.0, 12.0, 20.0)); - all_eq!(simd_mul(z2, z1), f32x4(2.0, 6.0, 12.0, 20.0)); - - all_eq!(simd_sub(x2, x1), i32x4(1, 1, 1, 1)); - all_eq!(simd_sub(x1, x2), i32x4(-1, -1, -1, -1)); - all_eq_!(simd_sub(y2, y1), U32::<4>([1, 1, 1, 1])); - all_eq_!(simd_sub(y1, y2), U32::<4>([!0, !0, !0, !0])); - all_eq!(simd_sub(z2, z1), f32x4(1.0, 1.0, 1.0, 1.0)); - all_eq!(simd_sub(z1, z2), f32x4(-1.0, -1.0, -1.0, -1.0)); - - all_eq!(simd_div(x1, x1), i32x4(1, 1, 1, 1)); - all_eq!(simd_div(i32x4(2, 4, 6, 8), i32x4(2, 2, 2, 2)), x1); - all_eq_!(simd_div(y1, y1), U32::<4>([1, 1, 1, 1])); - all_eq_!(simd_div(U32::<4>([2, 4, 6, 8]), U32::<4>([2, 2, 2, 2])), y1); - all_eq!(simd_div(z1, z1), f32x4(1.0, 1.0, 1.0, 1.0)); - all_eq!(simd_div(z1, z2), f32x4(1.0 / 2.0, 2.0 / 3.0, 3.0 / 4.0, 4.0 / 5.0)); - all_eq!(simd_div(z2, z1), f32x4(2.0 / 1.0, 3.0 / 2.0, 4.0 / 3.0, 5.0 / 4.0)); - - all_eq!(simd_rem(x1, x1), i32x4(0, 0, 0, 0)); - all_eq!(simd_rem(x2, x1), i32x4(0, 1, 1, 1)); - all_eq_!(simd_rem(y1, y1), U32::<4>([0, 0, 0, 0])); - all_eq_!(simd_rem(y2, y1), U32::<4>([0, 1, 1, 1])); - all_eq!(simd_rem(z1, z1), f32x4(0.0, 0.0, 0.0, 0.0)); + all_eq!(simd_add(x1, x2), i32x4([3, 5, 7, 9])); + all_eq!(simd_add(x2, x1), i32x4([3, 5, 7, 9])); + all_eq!(simd_add(y1, y2), U32::<4>([3, 5, 7, 9])); + all_eq!(simd_add(y2, y1), U32::<4>([3, 5, 7, 9])); + all_eq!(simd_add(z1, z2), f32x4([3.0, 5.0, 7.0, 9.0])); + all_eq!(simd_add(z2, z1), f32x4([3.0, 5.0, 7.0, 9.0])); + + all_eq!(simd_mul(x1, x2), i32x4([2, 6, 12, 20])); + all_eq!(simd_mul(x2, x1), i32x4([2, 6, 12, 20])); + all_eq!(simd_mul(y1, y2), U32::<4>([2, 6, 12, 20])); + all_eq!(simd_mul(y2, y1), U32::<4>([2, 6, 12, 20])); + all_eq!(simd_mul(z1, z2), f32x4([2.0, 6.0, 12.0, 20.0])); + all_eq!(simd_mul(z2, z1), f32x4([2.0, 6.0, 12.0, 20.0])); + + all_eq!(simd_sub(x2, x1), i32x4([1, 1, 1, 1])); + all_eq!(simd_sub(x1, x2), i32x4([-1, -1, -1, -1])); + all_eq!(simd_sub(y2, y1), U32::<4>([1, 1, 1, 1])); + all_eq!(simd_sub(y1, y2), U32::<4>([!0, !0, !0, !0])); + all_eq!(simd_sub(z2, z1), f32x4([1.0, 1.0, 1.0, 1.0])); + all_eq!(simd_sub(z1, z2), f32x4([-1.0, -1.0, -1.0, -1.0])); + + all_eq!(simd_div(x1, x1), i32x4([1, 1, 1, 1])); + all_eq!(simd_div(i32x4([2, 4, 6, 8]), i32x4([2, 2, 2, 2])), x1); + all_eq!(simd_div(y1, y1), U32::<4>([1, 1, 1, 1])); + all_eq!(simd_div(U32::<4>([2, 4, 6, 8]), U32::<4>([2, 2, 2, 2])), y1); + all_eq!(simd_div(z1, z1), f32x4([1.0, 1.0, 1.0, 1.0])); + all_eq!(simd_div(z1, z2), f32x4([1.0 / 2.0, 2.0 / 3.0, 3.0 / 4.0, 4.0 / 5.0])); + all_eq!(simd_div(z2, z1), f32x4([2.0 / 1.0, 3.0 / 2.0, 4.0 / 3.0, 5.0 / 4.0])); + + all_eq!(simd_rem(x1, x1), i32x4([0, 0, 0, 0])); + all_eq!(simd_rem(x2, x1), i32x4([0, 1, 1, 1])); + all_eq!(simd_rem(y1, y1), U32::<4>([0, 0, 0, 0])); + all_eq!(simd_rem(y2, y1), U32::<4>([0, 1, 1, 1])); + all_eq!(simd_rem(z1, z1), f32x4([0.0, 0.0, 0.0, 0.0])); all_eq!(simd_rem(z1, z2), z1); - all_eq!(simd_rem(z2, z1), f32x4(0.0, 1.0, 1.0, 1.0)); + all_eq!(simd_rem(z2, z1), f32x4([0.0, 1.0, 1.0, 1.0])); - all_eq!(simd_shl(x1, x2), i32x4(1 << 2, 2 << 3, 3 << 4, 4 << 5)); - all_eq!(simd_shl(x2, x1), i32x4(2 << 1, 3 << 2, 4 << 3, 5 << 4)); - all_eq_!(simd_shl(y1, y2), U32::<4>([1 << 2, 2 << 3, 3 << 4, 4 << 5])); - all_eq_!(simd_shl(y2, y1), U32::<4>([2 << 1, 3 << 2, 4 << 3, 5 << 4])); + all_eq!(simd_shl(x1, x2), i32x4([1 << 2, 2 << 3, 3 << 4, 4 << 5])); + all_eq!(simd_shl(x2, x1), i32x4([2 << 1, 3 << 2, 4 << 3, 5 << 4])); + all_eq!(simd_shl(y1, y2), U32::<4>([1 << 2, 2 << 3, 3 << 4, 4 << 5])); + all_eq!(simd_shl(y2, y1), U32::<4>([2 << 1, 3 << 2, 4 << 3, 5 << 4])); // test right-shift by assuming left-shift is correct all_eq!(simd_shr(simd_shl(x1, x2), x2), x1); all_eq!(simd_shr(simd_shl(x2, x1), x1), x2); - all_eq_!(simd_shr(simd_shl(y1, y2), y2), y1); - all_eq_!(simd_shr(simd_shl(y2, y1), y1), y2); + all_eq!(simd_shr(simd_shl(y1, y2), y2), y1); + all_eq!(simd_shr(simd_shl(y2, y1), y1), y2); // ensure we get logical vs. arithmetic shifts correct let (a, b, c, d) = (-12, -123, -1234, -12345); - all_eq!(simd_shr(i32x4(a, b, c, d), x1), i32x4(a >> 1, b >> 2, c >> 3, d >> 4)); - all_eq_!( + all_eq!(simd_shr(i32x4([a, b, c, d]), x1), i32x4([a >> 1, b >> 2, c >> 3, d >> 4])); + all_eq!( simd_shr(U32::<4>([a as u32, b as u32, c as u32, d as u32]), y1), U32::<4>([(a as u32) >> 1, (b as u32) >> 2, (c as u32) >> 3, (d as u32) >> 4]) ); - all_eq!(simd_and(x1, x2), i32x4(0, 2, 0, 4)); - all_eq!(simd_and(x2, x1), i32x4(0, 2, 0, 4)); - all_eq_!(simd_and(y1, y2), U32::<4>([0, 2, 0, 4])); - all_eq_!(simd_and(y2, y1), U32::<4>([0, 2, 0, 4])); + all_eq!(simd_and(x1, x2), i32x4([0, 2, 0, 4])); + all_eq!(simd_and(x2, x1), i32x4([0, 2, 0, 4])); + all_eq!(simd_and(y1, y2), U32::<4>([0, 2, 0, 4])); + all_eq!(simd_and(y2, y1), U32::<4>([0, 2, 0, 4])); - all_eq!(simd_or(x1, x2), i32x4(3, 3, 7, 5)); - all_eq!(simd_or(x2, x1), i32x4(3, 3, 7, 5)); - all_eq_!(simd_or(y1, y2), U32::<4>([3, 3, 7, 5])); - all_eq_!(simd_or(y2, y1), U32::<4>([3, 3, 7, 5])); + all_eq!(simd_or(x1, x2), i32x4([3, 3, 7, 5])); + all_eq!(simd_or(x2, x1), i32x4([3, 3, 7, 5])); + all_eq!(simd_or(y1, y2), U32::<4>([3, 3, 7, 5])); + all_eq!(simd_or(y2, y1), U32::<4>([3, 3, 7, 5])); - all_eq!(simd_xor(x1, x2), i32x4(3, 1, 7, 1)); - all_eq!(simd_xor(x2, x1), i32x4(3, 1, 7, 1)); - all_eq_!(simd_xor(y1, y2), U32::<4>([3, 1, 7, 1])); - all_eq_!(simd_xor(y2, y1), U32::<4>([3, 1, 7, 1])); + all_eq!(simd_xor(x1, x2), i32x4([3, 1, 7, 1])); + all_eq!(simd_xor(x2, x1), i32x4([3, 1, 7, 1])); + all_eq!(simd_xor(y1, y2), U32::<4>([3, 1, 7, 1])); + all_eq!(simd_xor(y2, y1), U32::<4>([3, 1, 7, 1])); - all_eq!(simd_neg(x1), i32x4(-1, -2, -3, -4)); - all_eq!(simd_neg(x2), i32x4(-2, -3, -4, -5)); - all_eq!(simd_neg(z1), f32x4(-1.0, -2.0, -3.0, -4.0)); - all_eq!(simd_neg(z2), f32x4(-2.0, -3.0, -4.0, -5.0)); + all_eq!(simd_neg(x1), i32x4([-1, -2, -3, -4])); + all_eq!(simd_neg(x2), i32x4([-2, -3, -4, -5])); + all_eq!(simd_neg(z1), f32x4([-1.0, -2.0, -3.0, -4.0])); + all_eq!(simd_neg(z2), f32x4([-2.0, -3.0, -4.0, -5.0])); - all_eq!(simd_bswap(x1), i32x4(0x01000000, 0x02000000, 0x03000000, 0x04000000)); - all_eq_!(simd_bswap(y1), U32::<4>([0x01000000, 0x02000000, 0x03000000, 0x04000000])); + all_eq!(simd_bswap(x1), i32x4([0x01000000, 0x02000000, 0x03000000, 0x04000000])); + all_eq!(simd_bswap(y1), U32::<4>([0x01000000, 0x02000000, 0x03000000, 0x04000000])); all_eq!( simd_bitreverse(x1), - i32x4(0x80000000u32 as i32, 0x40000000, 0xc0000000u32 as i32, 0x20000000) + i32x4([0x80000000u32 as i32, 0x40000000, 0xc0000000u32 as i32, 0x20000000]) ); - all_eq_!(simd_bitreverse(y1), U32::<4>([0x80000000, 0x40000000, 0xc0000000, 0x20000000])); + all_eq!(simd_bitreverse(y1), U32::<4>([0x80000000, 0x40000000, 0xc0000000, 0x20000000])); - all_eq!(simd_ctlz(x1), i32x4(31, 30, 30, 29)); - all_eq_!(simd_ctlz(y1), U32::<4>([31, 30, 30, 29])); + all_eq!(simd_ctlz(x1), i32x4([31, 30, 30, 29])); + all_eq!(simd_ctlz(y1), U32::<4>([31, 30, 30, 29])); - all_eq!(simd_ctpop(x1), i32x4(1, 1, 2, 1)); - all_eq_!(simd_ctpop(y1), U32::<4>([1, 1, 2, 1])); - all_eq!(simd_ctpop(x2), i32x4(1, 2, 1, 2)); - all_eq_!(simd_ctpop(y2), U32::<4>([1, 2, 1, 2])); - all_eq!(simd_ctpop(x3), i32x4(0, 31, 1, 32)); - all_eq_!(simd_ctpop(y3), U32::<4>([0, 31, 1, 32])); + all_eq!(simd_ctpop(x1), i32x4([1, 1, 2, 1])); + all_eq!(simd_ctpop(y1), U32::<4>([1, 1, 2, 1])); + all_eq!(simd_ctpop(x2), i32x4([1, 2, 1, 2])); + all_eq!(simd_ctpop(y2), U32::<4>([1, 2, 1, 2])); + all_eq!(simd_ctpop(x3), i32x4([0, 31, 1, 32])); + all_eq!(simd_ctpop(y3), U32::<4>([0, 31, 1, 32])); - all_eq!(simd_cttz(x1), i32x4(0, 1, 0, 2)); - all_eq_!(simd_cttz(y1), U32::<4>([0, 1, 0, 2])); + all_eq!(simd_cttz(x1), i32x4([0, 1, 0, 2])); + all_eq!(simd_cttz(y1), U32::<4>([0, 1, 0, 2])); } } diff --git a/tests/ui/simd/intrinsic/generic-arithmetic-saturating-2.rs b/tests/ui/simd/intrinsic/generic-arithmetic-saturating-2.rs index 36be8cc62a8c8..ec6ac78df1a7a 100644 --- a/tests/ui/simd/intrinsic/generic-arithmetic-saturating-2.rs +++ b/tests/ui/simd/intrinsic/generic-arithmetic-saturating-2.rs @@ -4,15 +4,15 @@ #![allow(non_camel_case_types)] #[repr(simd)] #[derive(Copy, Clone)] -pub struct i32x4(pub i32, pub i32, pub i32, pub i32); +pub struct i32x4(pub [i32; 4]); #[repr(simd)] #[derive(Copy, Clone)] -pub struct x4(pub T, pub T, pub T, pub T); +pub struct x4(pub [T; 4]); #[repr(simd)] #[derive(Copy, Clone)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); extern "rust-intrinsic" { fn simd_saturating_add(x: T, y: T) -> T; @@ -20,9 +20,9 @@ extern "rust-intrinsic" { } fn main() { - let x = i32x4(0, 0, 0, 0); - let y = x4(0_usize, 0, 0, 0); - let z = f32x4(0.0, 0.0, 0.0, 0.0); + let x = i32x4([0, 0, 0, 0]); + let y = x4([0_usize, 0, 0, 0]); + let z = f32x4([0.0, 0.0, 0.0, 0.0]); unsafe { simd_saturating_add(x, x); diff --git a/tests/ui/simd/intrinsic/generic-arithmetic-saturating-pass.rs b/tests/ui/simd/intrinsic/generic-arithmetic-saturating-pass.rs index deee9c2ac41e6..57bda5c2d624e 100644 --- a/tests/ui/simd/intrinsic/generic-arithmetic-saturating-pass.rs +++ b/tests/ui/simd/intrinsic/generic-arithmetic-saturating-pass.rs @@ -6,7 +6,7 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -struct u32x4(pub u32, pub u32, pub u32, pub u32); +struct u32x4(pub [u32; 4]); #[repr(simd)] #[derive(Copy, Clone)] @@ -22,11 +22,11 @@ fn main() { { const M: u32 = u32::MAX; - let a = u32x4(1, 2, 3, 4); - let b = u32x4(2, 4, 6, 8); - let m = u32x4(M, M, M, M); - let m1 = u32x4(M - 1, M - 1, M - 1, M - 1); - let z = u32x4(0, 0, 0, 0); + let a = u32x4([1, 2, 3, 4]); + let b = u32x4([2, 4, 6, 8]); + let m = u32x4([M, M, M, M]); + let m1 = u32x4([M - 1, M - 1, M - 1, M - 1]); + let z = u32x4([0, 0, 0, 0]); unsafe { assert_eq!(simd_saturating_add(z, z), z); diff --git a/tests/ui/simd/intrinsic/generic-bitmask-pass.rs b/tests/ui/simd/intrinsic/generic-bitmask-pass.rs index 5c6a07876e35e..db10020bd469b 100644 --- a/tests/ui/simd/intrinsic/generic-bitmask-pass.rs +++ b/tests/ui/simd/intrinsic/generic-bitmask-pass.rs @@ -11,36 +11,36 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -struct u32x4(pub u32, pub u32, pub u32, pub u32); +struct u32x4(pub [u32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -struct u8x4(pub u8, pub u8, pub u8, pub u8); +struct u8x4(pub [u8; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -struct Tx4(pub T, pub T, pub T, pub T); +struct Tx4(pub [T; 4]); extern "rust-intrinsic" { fn simd_bitmask(x: T) -> U; } fn main() { - let z = u32x4(0, 0, 0, 0); + let z = u32x4([0, 0, 0, 0]); let ez = 0_u8; - let o = u32x4(!0, !0, !0, !0); + let o = u32x4([!0, !0, !0, !0]); let eo = 0b_1111_u8; - let m0 = u32x4(!0, 0, !0, 0); + let m0 = u32x4([!0, 0, !0, 0]); let e0 = 0b_0000_0101_u8; // Check that the MSB is extracted: - let m = u8x4(0b_1000_0000, 0b_0100_0001, 0b_1100_0001, 0b_1111_1111); + let m = u8x4([0b_1000_0000, 0b_0100_0001, 0b_1100_0001, 0b_1111_1111]); let e = 0b_1101; // Check usize / isize - let msize: Tx4 = Tx4(usize::MAX, 0, usize::MAX, usize::MAX); + let msize: Tx4 = Tx4([usize::MAX, 0, usize::MAX, usize::MAX]); unsafe { let r: u8 = simd_bitmask(z); diff --git a/tests/ui/simd/intrinsic/generic-cast.rs b/tests/ui/simd/intrinsic/generic-cast.rs index f3fdbe3403f79..33978a2f7395d 100644 --- a/tests/ui/simd/intrinsic/generic-cast.rs +++ b/tests/ui/simd/intrinsic/generic-cast.rs @@ -5,22 +5,20 @@ #[repr(simd)] #[derive(Copy, Clone)] #[allow(non_camel_case_types)] -struct i32x4(i32, i32, i32, i32); +struct i32x4([i32; 4]); #[repr(simd)] #[derive(Copy, Clone)] #[allow(non_camel_case_types)] -struct i32x8(i32, i32, i32, i32, - i32, i32, i32, i32); +struct i32x8([i32; 8]); #[repr(simd)] #[derive(Copy, Clone)] #[allow(non_camel_case_types)] -struct f32x4(f32, f32, f32, f32); +struct f32x4([f32; 4]); #[repr(simd)] #[derive(Copy, Clone)] #[allow(non_camel_case_types)] -struct f32x8(f32, f32, f32, f32, - f32, f32, f32, f32); +struct f32x8([f32; 8]); extern "rust-intrinsic" { @@ -28,7 +26,7 @@ extern "rust-intrinsic" { } fn main() { - let x = i32x4(0, 0, 0, 0); + let x = i32x4([0, 0, 0, 0]); unsafe { simd_cast::(0); diff --git a/tests/ui/simd/intrinsic/generic-cast.stderr b/tests/ui/simd/intrinsic/generic-cast.stderr index 2226bbbe1bd55..2f9d44037afb5 100644 --- a/tests/ui/simd/intrinsic/generic-cast.stderr +++ b/tests/ui/simd/intrinsic/generic-cast.stderr @@ -1,23 +1,23 @@ error[E0511]: invalid monomorphization of `simd_cast` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-cast.rs:34:9 + --> $DIR/generic-cast.rs:32:9 | LL | simd_cast::(0); | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_cast` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-cast.rs:36:9 + --> $DIR/generic-cast.rs:34:9 | LL | simd_cast::(0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_cast` intrinsic: expected SIMD return type, found non-SIMD `i32` - --> $DIR/generic-cast.rs:38:9 + --> $DIR/generic-cast.rs:36:9 | LL | simd_cast::(x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_cast` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i32x8` with length 8 - --> $DIR/generic-cast.rs:40:9 + --> $DIR/generic-cast.rs:38:9 | LL | simd_cast::<_, i32x8>(x); | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/simd/intrinsic/generic-comparison-pass.rs b/tests/ui/simd/intrinsic/generic-comparison-pass.rs index a4df836b6f82a..a4d84a4c53482 100644 --- a/tests/ui/simd/intrinsic/generic-comparison-pass.rs +++ b/tests/ui/simd/intrinsic/generic-comparison-pass.rs @@ -6,13 +6,13 @@ #[repr(simd)] #[derive(Copy, Clone)] -struct i32x4(i32, i32, i32, i32); +struct i32x4([i32; 4]); #[repr(simd)] #[derive(Copy, Clone)] -struct u32x4(pub u32, pub u32, pub u32, pub u32); +struct u32x4(pub [u32; 4]); #[repr(simd)] #[derive(Copy, Clone)] -struct f32x4(pub f32, pub f32, pub f32, pub f32); +struct f32x4(pub [f32; 4]); extern "rust-intrinsic" { fn simd_eq(x: T, y: T) -> U; @@ -29,10 +29,10 @@ macro_rules! cmp { let rhs = $rhs; let e: u32x4 = concat_idents!(simd_, $method)($lhs, $rhs); // assume the scalar version is correct/the behaviour we want. - assert!((e.0 != 0) == lhs.0 .$method(&rhs.0)); - assert!((e.1 != 0) == lhs.1 .$method(&rhs.1)); - assert!((e.2 != 0) == lhs.2 .$method(&rhs.2)); - assert!((e.3 != 0) == lhs.3 .$method(&rhs.3)); + assert!((e.0[0] != 0) == lhs.0[0] .$method(&rhs.0[0])); + assert!((e.0[1] != 0) == lhs.0[1] .$method(&rhs.0[1])); + assert!((e.0[2] != 0) == lhs.0[2] .$method(&rhs.0[2])); + assert!((e.0[3] != 0) == lhs.0[3] .$method(&rhs.0[3])); }} } macro_rules! tests { @@ -61,17 +61,17 @@ macro_rules! tests { fn main() { // 13 vs. -100 tests that we get signed vs. unsigned comparisons // correct (i32: 13 > -100, u32: 13 < -100). let i1 = i32x4(10, -11, 12, 13); - let i1 = i32x4(10, -11, 12, 13); - let i2 = i32x4(5, -5, 20, -100); - let i3 = i32x4(10, -11, 20, -100); + let i1 = i32x4([10, -11, 12, 13]); + let i2 = i32x4([5, -5, 20, -100]); + let i3 = i32x4([10, -11, 20, -100]); - let u1 = u32x4(10, !11+1, 12, 13); - let u2 = u32x4(5, !5+1, 20, !100+1); - let u3 = u32x4(10, !11+1, 20, !100+1); + let u1 = u32x4([10, !11+1, 12, 13]); + let u2 = u32x4([5, !5+1, 20, !100+1]); + let u3 = u32x4([10, !11+1, 20, !100+1]); - let f1 = f32x4(10.0, -11.0, 12.0, 13.0); - let f2 = f32x4(5.0, -5.0, 20.0, -100.0); - let f3 = f32x4(10.0, -11.0, 20.0, -100.0); + let f1 = f32x4([10.0, -11.0, 12.0, 13.0]); + let f2 = f32x4([5.0, -5.0, 20.0, -100.0]); + let f3 = f32x4([10.0, -11.0, 20.0, -100.0]); unsafe { tests! { @@ -92,7 +92,7 @@ fn main() { // NAN comparisons are special: // -11 (*) 13 // -5 -100 (*) - let f4 = f32x4(f32::NAN, f1.1, f32::NAN, f2.3); + let f4 = f32x4([f32::NAN, f1.0[1], f32::NAN, f2.0[3]]); unsafe { tests! { diff --git a/tests/ui/simd/intrinsic/generic-comparison.rs b/tests/ui/simd/intrinsic/generic-comparison.rs index bb2720f615fef..f7f0655f3d244 100644 --- a/tests/ui/simd/intrinsic/generic-comparison.rs +++ b/tests/ui/simd/intrinsic/generic-comparison.rs @@ -5,12 +5,11 @@ #[repr(simd)] #[derive(Copy, Clone)] #[allow(non_camel_case_types)] -struct i32x4(i32, i32, i32, i32); +struct i32x4([i32; 4]); #[repr(simd)] #[derive(Copy, Clone)] #[allow(non_camel_case_types)] -struct i16x8(i16, i16, i16, i16, - i16, i16, i16, i16); +struct i16x8([i16; 8]); extern "rust-intrinsic" { fn simd_eq(x: T, y: T) -> U; @@ -22,7 +21,7 @@ extern "rust-intrinsic" { } fn main() { - let x = i32x4(0, 0, 0, 0); + let x = i32x4([0, 0, 0, 0]); unsafe { simd_eq::(0, 0); diff --git a/tests/ui/simd/intrinsic/generic-comparison.stderr b/tests/ui/simd/intrinsic/generic-comparison.stderr index 0eae2688bced0..ac4d491882742 100644 --- a/tests/ui/simd/intrinsic/generic-comparison.stderr +++ b/tests/ui/simd/intrinsic/generic-comparison.stderr @@ -1,107 +1,107 @@ error[E0511]: invalid monomorphization of `simd_eq` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-comparison.rs:28:9 + --> $DIR/generic-comparison.rs:27:9 | LL | simd_eq::(0, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_ne` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-comparison.rs:30:9 + --> $DIR/generic-comparison.rs:29:9 | LL | simd_ne::(0, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_lt` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-comparison.rs:32:9 + --> $DIR/generic-comparison.rs:31:9 | LL | simd_lt::(0, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_le` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-comparison.rs:34:9 + --> $DIR/generic-comparison.rs:33:9 | LL | simd_le::(0, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_gt` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-comparison.rs:36:9 + --> $DIR/generic-comparison.rs:35:9 | LL | simd_gt::(0, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_ge` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-comparison.rs:38:9 + --> $DIR/generic-comparison.rs:37:9 | LL | simd_ge::(0, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_eq` intrinsic: expected SIMD return type, found non-SIMD `i32` - --> $DIR/generic-comparison.rs:41:9 + --> $DIR/generic-comparison.rs:40:9 | LL | simd_eq::<_, i32>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_ne` intrinsic: expected SIMD return type, found non-SIMD `i32` - --> $DIR/generic-comparison.rs:43:9 + --> $DIR/generic-comparison.rs:42:9 | LL | simd_ne::<_, i32>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_lt` intrinsic: expected SIMD return type, found non-SIMD `i32` - --> $DIR/generic-comparison.rs:45:9 + --> $DIR/generic-comparison.rs:44:9 | LL | simd_lt::<_, i32>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_le` intrinsic: expected SIMD return type, found non-SIMD `i32` - --> $DIR/generic-comparison.rs:47:9 + --> $DIR/generic-comparison.rs:46:9 | LL | simd_le::<_, i32>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_gt` intrinsic: expected SIMD return type, found non-SIMD `i32` - --> $DIR/generic-comparison.rs:49:9 + --> $DIR/generic-comparison.rs:48:9 | LL | simd_gt::<_, i32>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_ge` intrinsic: expected SIMD return type, found non-SIMD `i32` - --> $DIR/generic-comparison.rs:51:9 + --> $DIR/generic-comparison.rs:50:9 | LL | simd_ge::<_, i32>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_eq` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 - --> $DIR/generic-comparison.rs:54:9 + --> $DIR/generic-comparison.rs:53:9 | LL | simd_eq::<_, i16x8>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_ne` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 - --> $DIR/generic-comparison.rs:56:9 + --> $DIR/generic-comparison.rs:55:9 | LL | simd_ne::<_, i16x8>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_lt` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 - --> $DIR/generic-comparison.rs:58:9 + --> $DIR/generic-comparison.rs:57:9 | LL | simd_lt::<_, i16x8>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_le` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 - --> $DIR/generic-comparison.rs:60:9 + --> $DIR/generic-comparison.rs:59:9 | LL | simd_le::<_, i16x8>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_gt` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 - --> $DIR/generic-comparison.rs:62:9 + --> $DIR/generic-comparison.rs:61:9 | LL | simd_gt::<_, i16x8>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_ge` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 - --> $DIR/generic-comparison.rs:64:9 + --> $DIR/generic-comparison.rs:63:9 | LL | simd_ge::<_, i16x8>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/simd/intrinsic/generic-elements-pass.rs b/tests/ui/simd/intrinsic/generic-elements-pass.rs index a81d8ebdf50c2..b159387ab62cc 100644 --- a/tests/ui/simd/intrinsic/generic-elements-pass.rs +++ b/tests/ui/simd/intrinsic/generic-elements-pass.rs @@ -6,16 +6,15 @@ #[repr(simd)] #[derive(Copy, Clone, Debug, PartialEq)] #[allow(non_camel_case_types)] -struct i32x2(i32, i32); +struct i32x2([i32; 2]); #[repr(simd)] #[derive(Copy, Clone, Debug, PartialEq)] #[allow(non_camel_case_types)] -struct i32x4(i32, i32, i32, i32); +struct i32x4([i32; 4]); #[repr(simd)] #[derive(Copy, Clone, Debug, PartialEq)] #[allow(non_camel_case_types)] -struct i32x8(i32, i32, i32, i32, - i32, i32, i32, i32); +struct i32x8([i32; 8]); extern "rust-intrinsic" { fn simd_insert(x: T, idx: u32, y: E) -> T; @@ -37,26 +36,26 @@ macro_rules! all_eq { } fn main() { - let x2 = i32x2(20, 21); - let x4 = i32x4(40, 41, 42, 43); - let x8 = i32x8(80, 81, 82, 83, 84, 85, 86, 87); + let x2 = i32x2([20, 21]); + let x4 = i32x4([40, 41, 42, 43]); + let x8 = i32x8([80, 81, 82, 83, 84, 85, 86, 87]); unsafe { - all_eq!(simd_insert(x2, 0, 100), i32x2(100, 21)); - all_eq!(simd_insert(x2, 1, 100), i32x2(20, 100)); + all_eq!(simd_insert(x2, 0, 100), i32x2([100, 21])); + all_eq!(simd_insert(x2, 1, 100), i32x2([20, 100])); - all_eq!(simd_insert(x4, 0, 100), i32x4(100, 41, 42, 43)); - all_eq!(simd_insert(x4, 1, 100), i32x4(40, 100, 42, 43)); - all_eq!(simd_insert(x4, 2, 100), i32x4(40, 41, 100, 43)); - all_eq!(simd_insert(x4, 3, 100), i32x4(40, 41, 42, 100)); + all_eq!(simd_insert(x4, 0, 100), i32x4([100, 41, 42, 43])); + all_eq!(simd_insert(x4, 1, 100), i32x4([40, 100, 42, 43])); + all_eq!(simd_insert(x4, 2, 100), i32x4([40, 41, 100, 43])); + all_eq!(simd_insert(x4, 3, 100), i32x4([40, 41, 42, 100])); - all_eq!(simd_insert(x8, 0, 100), i32x8(100, 81, 82, 83, 84, 85, 86, 87)); - all_eq!(simd_insert(x8, 1, 100), i32x8(80, 100, 82, 83, 84, 85, 86, 87)); - all_eq!(simd_insert(x8, 2, 100), i32x8(80, 81, 100, 83, 84, 85, 86, 87)); - all_eq!(simd_insert(x8, 3, 100), i32x8(80, 81, 82, 100, 84, 85, 86, 87)); - all_eq!(simd_insert(x8, 4, 100), i32x8(80, 81, 82, 83, 100, 85, 86, 87)); - all_eq!(simd_insert(x8, 5, 100), i32x8(80, 81, 82, 83, 84, 100, 86, 87)); - all_eq!(simd_insert(x8, 6, 100), i32x8(80, 81, 82, 83, 84, 85, 100, 87)); - all_eq!(simd_insert(x8, 7, 100), i32x8(80, 81, 82, 83, 84, 85, 86, 100)); + all_eq!(simd_insert(x8, 0, 100), i32x8([100, 81, 82, 83, 84, 85, 86, 87])); + all_eq!(simd_insert(x8, 1, 100), i32x8([80, 100, 82, 83, 84, 85, 86, 87])); + all_eq!(simd_insert(x8, 2, 100), i32x8([80, 81, 100, 83, 84, 85, 86, 87])); + all_eq!(simd_insert(x8, 3, 100), i32x8([80, 81, 82, 100, 84, 85, 86, 87])); + all_eq!(simd_insert(x8, 4, 100), i32x8([80, 81, 82, 83, 100, 85, 86, 87])); + all_eq!(simd_insert(x8, 5, 100), i32x8([80, 81, 82, 83, 84, 100, 86, 87])); + all_eq!(simd_insert(x8, 6, 100), i32x8([80, 81, 82, 83, 84, 85, 100, 87])); + all_eq!(simd_insert(x8, 7, 100), i32x8([80, 81, 82, 83, 84, 85, 86, 100])); all_eq!(simd_extract(x2, 0), 20); all_eq!(simd_extract(x2, 1), 21); @@ -76,24 +75,24 @@ fn main() { all_eq!(simd_extract(x8, 7), 87); } - let y2 = i32x2(120, 121); - let y4 = i32x4(140, 141, 142, 143); - let y8 = i32x8(180, 181, 182, 183, 184, 185, 186, 187); + let y2 = i32x2([120, 121]); + let y4 = i32x4([140, 141, 142, 143]); + let y8 = i32x8([180, 181, 182, 183, 184, 185, 186, 187]); unsafe { - all_eq!(simd_shuffle(x2, y2, const { [3u32, 0] }), i32x2(121, 20)); - all_eq!(simd_shuffle(x2, y2, const { [3u32, 0, 1, 2] }), i32x4(121, 20, 21, 120)); + all_eq!(simd_shuffle(x2, y2, const { [3u32, 0] }), i32x2([121, 20])); + all_eq!(simd_shuffle(x2, y2, const { [3u32, 0, 1, 2] }), i32x4([121, 20, 21, 120])); all_eq!(simd_shuffle(x2, y2, const { [3u32, 0, 1, 2, 1, 2, 3, 0] }), - i32x8(121, 20, 21, 120, 21, 120, 121, 20)); + i32x8([121, 20, 21, 120, 21, 120, 121, 20])); - all_eq!(simd_shuffle(x4, y4, const { [7u32, 2] }), i32x2(143, 42)); - all_eq!(simd_shuffle(x4, y4, const { [7u32, 2, 5, 0] }), i32x4(143, 42, 141, 40)); + all_eq!(simd_shuffle(x4, y4, const { [7u32, 2] }), i32x2([143, 42])); + all_eq!(simd_shuffle(x4, y4, const { [7u32, 2, 5, 0] }), i32x4([143, 42, 141, 40])); all_eq!(simd_shuffle(x4, y4, const { [7u32, 2, 5, 0, 3, 6, 4, 1] }), - i32x8(143, 42, 141, 40, 43, 142, 140, 41)); + i32x8([143, 42, 141, 40, 43, 142, 140, 41])); - all_eq!(simd_shuffle(x8, y8, const { [11u32, 5] }), i32x2(183, 85)); - all_eq!(simd_shuffle(x8, y8, const { [11u32, 5, 15, 0] }), i32x4(183, 85, 187, 80)); + all_eq!(simd_shuffle(x8, y8, const { [11u32, 5] }), i32x2([183, 85])); + all_eq!(simd_shuffle(x8, y8, const { [11u32, 5, 15, 0] }), i32x4([183, 85, 187, 80])); all_eq!(simd_shuffle(x8, y8, const { [11u32, 5, 15, 0, 3, 8, 12, 1] }), - i32x8(183, 85, 187, 80, 83, 180, 184, 81)); + i32x8([183, 85, 187, 80, 83, 180, 184, 81])); } } diff --git a/tests/ui/simd/intrinsic/generic-elements.rs b/tests/ui/simd/intrinsic/generic-elements.rs index aec75a673067e..4848fd1b803af 100644 --- a/tests/ui/simd/intrinsic/generic-elements.rs +++ b/tests/ui/simd/intrinsic/generic-elements.rs @@ -6,28 +6,28 @@ #[repr(simd)] #[derive(Copy, Clone)] #[allow(non_camel_case_types)] -struct i32x2(i32, i32); +struct i32x2([i32; 2]); #[repr(simd)] #[derive(Copy, Clone)] #[allow(non_camel_case_types)] -struct i32x4(i32, i32, i32, i32); +struct i32x4([i32; 4]); #[repr(simd)] #[derive(Copy, Clone)] #[allow(non_camel_case_types)] -struct i32x8(i32, i32, i32, i32, i32, i32, i32, i32); +struct i32x8([i32; 8]); #[repr(simd)] #[derive(Copy, Clone)] #[allow(non_camel_case_types)] -struct f32x2(f32, f32); +struct f32x2([f32; 2]); #[repr(simd)] #[derive(Copy, Clone)] #[allow(non_camel_case_types)] -struct f32x4(f32, f32, f32, f32); +struct f32x4([f32; 4]); #[repr(simd)] #[derive(Copy, Clone)] #[allow(non_camel_case_types)] -struct f32x8(f32, f32, f32, f32, f32, f32, f32, f32); +struct f32x8([f32; 8]); extern "rust-intrinsic" { fn simd_insert(x: T, idx: u32, y: E) -> T; @@ -38,7 +38,7 @@ extern "rust-intrinsic" { } fn main() { - let x = i32x4(0, 0, 0, 0); + let x = i32x4([0, 0, 0, 0]); unsafe { simd_insert(0, 0, 0); diff --git a/tests/ui/simd/intrinsic/generic-gather-pass.rs b/tests/ui/simd/intrinsic/generic-gather-pass.rs index a00bc67e73bd4..3315d1cdaa22d 100644 --- a/tests/ui/simd/intrinsic/generic-gather-pass.rs +++ b/tests/ui/simd/intrinsic/generic-gather-pass.rs @@ -8,7 +8,7 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -struct x4(pub T, pub T, pub T, pub T); +struct x4(pub [T; 4]); extern "rust-intrinsic" { fn simd_gather(x: T, y: U, z: V) -> T; @@ -18,19 +18,19 @@ extern "rust-intrinsic" { fn main() { let mut x = [0_f32, 1., 2., 3., 4., 5., 6., 7.]; - let default = x4(-3_f32, -3., -3., -3.); - let s_strided = x4(0_f32, 2., -3., 6.); - let mask = x4(-1_i32, -1, 0, -1); + let default = x4([-3_f32, -3., -3., -3.]); + let s_strided = x4([0_f32, 2., -3., 6.]); + let mask = x4([-1_i32, -1, 0, -1]); // reading from *const unsafe { let pointer = x.as_ptr(); - let pointers = x4( + let pointers = x4([ pointer.offset(0), pointer.offset(2), pointer.offset(4), pointer.offset(6) - ); + ]); let r_strided = simd_gather(default, pointers, mask); @@ -40,12 +40,12 @@ fn main() { // reading from *mut unsafe { let pointer = x.as_mut_ptr(); - let pointers = x4( + let pointers = x4([ pointer.offset(0), pointer.offset(2), pointer.offset(4), pointer.offset(6) - ); + ]); let r_strided = simd_gather(default, pointers, mask); @@ -55,14 +55,14 @@ fn main() { // writing to *mut unsafe { let pointer = x.as_mut_ptr(); - let pointers = x4( + let pointers = x4([ pointer.offset(0), pointer.offset(2), pointer.offset(4), pointer.offset(6) - ); + ]); - let values = x4(42_f32, 43_f32, 44_f32, 45_f32); + let values = x4([42_f32, 43_f32, 44_f32, 45_f32]); simd_scatter(values, pointers, mask); assert_eq!(x, [42., 1., 43., 3., 4., 5., 45., 7.]); @@ -80,18 +80,18 @@ fn main() { &x[7] as *const f32 ]; - let default = x4(y[0], y[0], y[0], y[0]); - let s_strided = x4(y[0], y[2], y[0], y[6]); + let default = x4([y[0], y[0], y[0], y[0]]); + let s_strided = x4([y[0], y[2], y[0], y[6]]); // reading from *const unsafe { let pointer = y.as_ptr(); - let pointers = x4( + let pointers = x4([ pointer.offset(0), pointer.offset(2), pointer.offset(4), pointer.offset(6) - ); + ]); let r_strided = simd_gather(default, pointers, mask); @@ -101,12 +101,12 @@ fn main() { // reading from *mut unsafe { let pointer = y.as_mut_ptr(); - let pointers = x4( + let pointers = x4([ pointer.offset(0), pointer.offset(2), pointer.offset(4), pointer.offset(6) - ); + ]); let r_strided = simd_gather(default, pointers, mask); @@ -116,14 +116,14 @@ fn main() { // writing to *mut unsafe { let pointer = y.as_mut_ptr(); - let pointers = x4( + let pointers = x4([ pointer.offset(0), pointer.offset(2), pointer.offset(4), pointer.offset(6) - ); + ]); - let values = x4(y[7], y[6], y[5], y[1]); + let values = x4([y[7], y[6], y[5], y[1]]); simd_scatter(values, pointers, mask); let s = [ diff --git a/tests/ui/simd/intrinsic/generic-reduction-pass.rs b/tests/ui/simd/intrinsic/generic-reduction-pass.rs index 64902788709eb..699fb396259dc 100644 --- a/tests/ui/simd/intrinsic/generic-reduction-pass.rs +++ b/tests/ui/simd/intrinsic/generic-reduction-pass.rs @@ -10,19 +10,19 @@ #[repr(simd)] #[derive(Copy, Clone)] -struct i32x4(pub i32, pub i32, pub i32, pub i32); +struct i32x4(pub [i32; 4]); #[repr(simd)] #[derive(Copy, Clone)] -struct u32x4(pub u32, pub u32, pub u32, pub u32); +struct u32x4(pub [u32; 4]); #[repr(simd)] #[derive(Copy, Clone)] -struct f32x4(pub f32, pub f32, pub f32, pub f32); +struct f32x4(pub [f32; 4]); #[repr(simd)] #[derive(Copy, Clone)] -struct b8x4(pub i8, pub i8, pub i8, pub i8); +struct b8x4(pub [i8; 4]); extern "rust-intrinsic" { fn simd_reduce_add_unordered(x: T) -> U; @@ -40,7 +40,7 @@ extern "rust-intrinsic" { fn main() { unsafe { - let x = i32x4(1, -2, 3, 4); + let x = i32x4([1, -2, 3, 4]); let r: i32 = simd_reduce_add_unordered(x); assert_eq!(r, 6_i32); let r: i32 = simd_reduce_mul_unordered(x); @@ -55,7 +55,7 @@ fn main() { let r: i32 = simd_reduce_max(x); assert_eq!(r, 4_i32); - let x = i32x4(-1, -1, -1, -1); + let x = i32x4([-1, -1, -1, -1]); let r: i32 = simd_reduce_and(x); assert_eq!(r, -1_i32); let r: i32 = simd_reduce_or(x); @@ -63,7 +63,7 @@ fn main() { let r: i32 = simd_reduce_xor(x); assert_eq!(r, 0_i32); - let x = i32x4(-1, -1, 0, -1); + let x = i32x4([-1, -1, 0, -1]); let r: i32 = simd_reduce_and(x); assert_eq!(r, 0_i32); let r: i32 = simd_reduce_or(x); @@ -73,7 +73,7 @@ fn main() { } unsafe { - let x = u32x4(1, 2, 3, 4); + let x = u32x4([1, 2, 3, 4]); let r: u32 = simd_reduce_add_unordered(x); assert_eq!(r, 10_u32); let r: u32 = simd_reduce_mul_unordered(x); @@ -89,7 +89,7 @@ fn main() { assert_eq!(r, 4_u32); let t = u32::MAX; - let x = u32x4(t, t, t, t); + let x = u32x4([t, t, t, t]); let r: u32 = simd_reduce_and(x); assert_eq!(r, t); let r: u32 = simd_reduce_or(x); @@ -97,7 +97,7 @@ fn main() { let r: u32 = simd_reduce_xor(x); assert_eq!(r, 0_u32); - let x = u32x4(t, t, 0, t); + let x = u32x4([t, t, 0, t]); let r: u32 = simd_reduce_and(x); assert_eq!(r, 0_u32); let r: u32 = simd_reduce_or(x); @@ -107,7 +107,7 @@ fn main() { } unsafe { - let x = f32x4(1., -2., 3., 4.); + let x = f32x4([1., -2., 3., 4.]); let r: f32 = simd_reduce_add_unordered(x); assert_eq!(r, 6_f32); let r: f32 = simd_reduce_mul_unordered(x); @@ -128,19 +128,19 @@ fn main() { } unsafe { - let x = b8x4(!0, !0, !0, !0); + let x = b8x4([!0, !0, !0, !0]); let r: bool = simd_reduce_all(x); assert_eq!(r, true); let r: bool = simd_reduce_any(x); assert_eq!(r, true); - let x = b8x4(!0, !0, 0, !0); + let x = b8x4([!0, !0, 0, !0]); let r: bool = simd_reduce_all(x); assert_eq!(r, false); let r: bool = simd_reduce_any(x); assert_eq!(r, true); - let x = b8x4(0, 0, 0, 0); + let x = b8x4([0, 0, 0, 0]); let r: bool = simd_reduce_all(x); assert_eq!(r, false); let r: bool = simd_reduce_any(x); diff --git a/tests/ui/simd/intrinsic/generic-reduction.rs b/tests/ui/simd/intrinsic/generic-reduction.rs index 96df73591693f..1986deafb6ab5 100644 --- a/tests/ui/simd/intrinsic/generic-reduction.rs +++ b/tests/ui/simd/intrinsic/generic-reduction.rs @@ -9,11 +9,11 @@ #[repr(simd)] #[derive(Copy, Clone)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); #[repr(simd)] #[derive(Copy, Clone)] -pub struct u32x4(pub u32, pub u32, pub u32, pub u32); +pub struct u32x4(pub [u32; 4]); extern "rust-intrinsic" { @@ -27,8 +27,8 @@ extern "rust-intrinsic" { } fn main() { - let x = u32x4(0, 0, 0, 0); - let z = f32x4(0.0, 0.0, 0.0, 0.0); + let x = u32x4([0, 0, 0, 0]); + let z = f32x4([0.0, 0.0, 0.0, 0.0]); unsafe { simd_reduce_add_ordered(z, 0); diff --git a/tests/ui/simd/intrinsic/generic-select-pass.rs b/tests/ui/simd/intrinsic/generic-select-pass.rs index 98e1534e6e622..5690bad504844 100644 --- a/tests/ui/simd/intrinsic/generic-select-pass.rs +++ b/tests/ui/simd/intrinsic/generic-select-pass.rs @@ -11,23 +11,23 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -struct i32x4(pub i32, pub i32, pub i32, pub i32); +struct i32x4(pub [i32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -struct u32x4(pub u32, pub u32, pub u32, pub u32); +struct u32x4(pub [u32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -struct u32x8(u32, u32, u32, u32, u32, u32, u32, u32); +struct u32x8([u32; 8]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -struct f32x4(pub f32, pub f32, pub f32, pub f32); +struct f32x4(pub [f32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -struct b8x4(pub i8, pub i8, pub i8, pub i8); +struct b8x4(pub [i8; 4]); extern "rust-intrinsic" { fn simd_select(x: T, a: U, b: U) -> U; @@ -35,15 +35,15 @@ extern "rust-intrinsic" { } fn main() { - let m0 = b8x4(!0, !0, !0, !0); - let m1 = b8x4(0, 0, 0, 0); - let m2 = b8x4(!0, !0, 0, 0); - let m3 = b8x4(0, 0, !0, !0); - let m4 = b8x4(!0, 0, !0, 0); + let m0 = b8x4([!0, !0, !0, !0]); + let m1 = b8x4([0, 0, 0, 0]); + let m2 = b8x4([!0, !0, 0, 0]); + let m3 = b8x4([0, 0, !0, !0]); + let m4 = b8x4([!0, 0, !0, 0]); unsafe { - let a = i32x4(1, -2, 3, 4); - let b = i32x4(5, 6, -7, 8); + let a = i32x4([1, -2, 3, 4]); + let b = i32x4([5, 6, -7, 8]); let r: i32x4 = simd_select(m0, a, b); let e = a; @@ -54,21 +54,21 @@ fn main() { assert_eq!(r, e); let r: i32x4 = simd_select(m2, a, b); - let e = i32x4(1, -2, -7, 8); + let e = i32x4([1, -2, -7, 8]); assert_eq!(r, e); let r: i32x4 = simd_select(m3, a, b); - let e = i32x4(5, 6, 3, 4); + let e = i32x4([5, 6, 3, 4]); assert_eq!(r, e); let r: i32x4 = simd_select(m4, a, b); - let e = i32x4(1, 6, 3, 8); + let e = i32x4([1, 6, 3, 8]); assert_eq!(r, e); } unsafe { - let a = u32x4(1, 2, 3, 4); - let b = u32x4(5, 6, 7, 8); + let a = u32x4([1, 2, 3, 4]); + let b = u32x4([5, 6, 7, 8]); let r: u32x4 = simd_select(m0, a, b); let e = a; @@ -79,21 +79,21 @@ fn main() { assert_eq!(r, e); let r: u32x4 = simd_select(m2, a, b); - let e = u32x4(1, 2, 7, 8); + let e = u32x4([1, 2, 7, 8]); assert_eq!(r, e); let r: u32x4 = simd_select(m3, a, b); - let e = u32x4(5, 6, 3, 4); + let e = u32x4([5, 6, 3, 4]); assert_eq!(r, e); let r: u32x4 = simd_select(m4, a, b); - let e = u32x4(1, 6, 3, 8); + let e = u32x4([1, 6, 3, 8]); assert_eq!(r, e); } unsafe { - let a = f32x4(1., 2., 3., 4.); - let b = f32x4(5., 6., 7., 8.); + let a = f32x4([1., 2., 3., 4.]); + let b = f32x4([5., 6., 7., 8.]); let r: f32x4 = simd_select(m0, a, b); let e = a; @@ -104,23 +104,23 @@ fn main() { assert_eq!(r, e); let r: f32x4 = simd_select(m2, a, b); - let e = f32x4(1., 2., 7., 8.); + let e = f32x4([1., 2., 7., 8.]); assert_eq!(r, e); let r: f32x4 = simd_select(m3, a, b); - let e = f32x4(5., 6., 3., 4.); + let e = f32x4([5., 6., 3., 4.]); assert_eq!(r, e); let r: f32x4 = simd_select(m4, a, b); - let e = f32x4(1., 6., 3., 8.); + let e = f32x4([1., 6., 3., 8.]); assert_eq!(r, e); } unsafe { let t = !0 as i8; let f = 0 as i8; - let a = b8x4(t, f, t, f); - let b = b8x4(f, f, f, t); + let a = b8x4([t, f, t, f]); + let b = b8x4([f, f, f, t]); let r: b8x4 = simd_select(m0, a, b); let e = a; @@ -131,21 +131,21 @@ fn main() { assert_eq!(r, e); let r: b8x4 = simd_select(m2, a, b); - let e = b8x4(t, f, f, t); + let e = b8x4([t, f, f, t]); assert_eq!(r, e); let r: b8x4 = simd_select(m3, a, b); - let e = b8x4(f, f, t, f); + let e = b8x4([f, f, t, f]); assert_eq!(r, e); let r: b8x4 = simd_select(m4, a, b); - let e = b8x4(t, f, t, t); + let e = b8x4([t, f, t, t]); assert_eq!(r, e); } unsafe { - let a = u32x8(0, 1, 2, 3, 4, 5, 6, 7); - let b = u32x8(8, 9, 10, 11, 12, 13, 14, 15); + let a = u32x8([0, 1, 2, 3, 4, 5, 6, 7]); + let b = u32x8([8, 9, 10, 11, 12, 13, 14, 15]); let r: u32x8 = simd_select_bitmask(0u8, a, b); let e = b; @@ -156,21 +156,21 @@ fn main() { assert_eq!(r, e); let r: u32x8 = simd_select_bitmask(0b01010101u8, a, b); - let e = u32x8(0, 9, 2, 11, 4, 13, 6, 15); + let e = u32x8([0, 9, 2, 11, 4, 13, 6, 15]); assert_eq!(r, e); let r: u32x8 = simd_select_bitmask(0b10101010u8, a, b); - let e = u32x8(8, 1, 10, 3, 12, 5, 14, 7); + let e = u32x8([8, 1, 10, 3, 12, 5, 14, 7]); assert_eq!(r, e); let r: u32x8 = simd_select_bitmask(0b11110000u8, a, b); - let e = u32x8(8, 9, 10, 11, 4, 5, 6, 7); + let e = u32x8([8, 9, 10, 11, 4, 5, 6, 7]); assert_eq!(r, e); } unsafe { - let a = u32x4(0, 1, 2, 3); - let b = u32x4(4, 5, 6, 7); + let a = u32x4([0, 1, 2, 3]); + let b = u32x4([4, 5, 6, 7]); let r: u32x4 = simd_select_bitmask(0u8, a, b); let e = b; @@ -181,15 +181,15 @@ fn main() { assert_eq!(r, e); let r: u32x4 = simd_select_bitmask(0b0101u8, a, b); - let e = u32x4(0, 5, 2, 7); + let e = u32x4([0, 5, 2, 7]); assert_eq!(r, e); let r: u32x4 = simd_select_bitmask(0b1010u8, a, b); - let e = u32x4(4, 1, 6, 3); + let e = u32x4([4, 1, 6, 3]); assert_eq!(r, e); let r: u32x4 = simd_select_bitmask(0b1100u8, a, b); - let e = u32x4(4, 5, 2, 3); + let e = u32x4([4, 5, 2, 3]); assert_eq!(r, e); } } diff --git a/tests/ui/simd/intrinsic/generic-select.rs b/tests/ui/simd/intrinsic/generic-select.rs index 215ae405c37e2..52e02649590ab 100644 --- a/tests/ui/simd/intrinsic/generic-select.rs +++ b/tests/ui/simd/intrinsic/generic-select.rs @@ -8,19 +8,19 @@ #[repr(simd)] #[derive(Copy, Clone)] -pub struct f32x4(pub f32, pub f32, pub f32, pub f32); +pub struct f32x4(pub [f32; 4]); #[repr(simd)] #[derive(Copy, Clone)] -pub struct u32x4(pub u32, pub u32, pub u32, pub u32); +pub struct u32x4(pub [u32; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq)] -struct b8x4(pub i8, pub i8, pub i8, pub i8); +struct b8x4(pub [i8; 4]); #[repr(simd)] #[derive(Copy, Clone, PartialEq)] -struct b8x8(pub i8, pub i8, pub i8, pub i8, pub i8, pub i8, pub i8, pub i8); +struct b8x8(pub [i8; 8]); extern "rust-intrinsic" { fn simd_select(x: T, a: U, b: U) -> U; @@ -28,10 +28,10 @@ extern "rust-intrinsic" { } fn main() { - let m4 = b8x4(0, 0, 0, 0); - let m8 = b8x8(0, 0, 0, 0, 0, 0, 0, 0); - let x = u32x4(0, 0, 0, 0); - let z = f32x4(0.0, 0.0, 0.0, 0.0); + let m4 = b8x4([0, 0, 0, 0]); + let m8 = b8x8([0, 0, 0, 0, 0, 0, 0, 0]); + let x = u32x4([0, 0, 0, 0]); + let z = f32x4([0.0, 0.0, 0.0, 0.0]); unsafe { simd_select(m4, x, x); diff --git a/tests/ui/simd/intrinsic/inlining-issue67557-ice.rs b/tests/ui/simd/intrinsic/inlining-issue67557-ice.rs index 928d3824703e7..a64a7c0b48a1e 100644 --- a/tests/ui/simd/intrinsic/inlining-issue67557-ice.rs +++ b/tests/ui/simd/intrinsic/inlining-issue67557-ice.rs @@ -11,7 +11,7 @@ extern "rust-intrinsic" { #[repr(simd)] #[derive(Debug, PartialEq)] -struct Simd2(u8, u8); +struct Simd2([u8; 2]); fn main() { unsafe { @@ -22,5 +22,5 @@ fn main() { #[inline(always)] unsafe fn inline_me() -> Simd2 { const IDX: [u32; 2] = [0, 3]; - simd_shuffle(Simd2(10, 11), Simd2(12, 13), IDX) + simd_shuffle(Simd2([10, 11]), Simd2([12, 13]), IDX) } diff --git a/tests/ui/simd/intrinsic/inlining-issue67557.rs b/tests/ui/simd/intrinsic/inlining-issue67557.rs index b8b8dbba547d1..cb80d65d46838 100644 --- a/tests/ui/simd/intrinsic/inlining-issue67557.rs +++ b/tests/ui/simd/intrinsic/inlining-issue67557.rs @@ -11,12 +11,12 @@ extern "rust-intrinsic" { #[repr(simd)] #[derive(Debug, PartialEq)] -struct Simd2(u8, u8); +struct Simd2([u8; 2]); fn main() { unsafe { const IDX: [u32; 2] = [0, 1]; - let p_res: Simd2 = simd_shuffle(Simd2(10, 11), Simd2(12, 13), IDX); + let p_res: Simd2 = simd_shuffle(Simd2([10, 11]), Simd2([12, 13]), IDX); let a_res: Simd2 = inline_me(); assert_10_11(p_res); @@ -26,17 +26,17 @@ fn main() { #[inline(never)] fn assert_10_11(x: Simd2) { - assert_eq!(x, Simd2(10, 11)); + assert_eq!(x, Simd2([10, 11])); } #[inline(never)] fn assert_10_13(x: Simd2) { - assert_eq!(x, Simd2(10, 13)); + assert_eq!(x, Simd2([10, 13])); } #[inline(always)] unsafe fn inline_me() -> Simd2 { const IDX: [u32; 2] = [0, 3]; - simd_shuffle(Simd2(10, 11), Simd2(12, 13), IDX) + simd_shuffle(Simd2([10, 11]), Simd2([12, 13]), IDX) } diff --git a/tests/ui/simd/issue-17170.rs b/tests/ui/simd/issue-17170.rs index abfc1c25ffb78..2d13962843c44 100644 --- a/tests/ui/simd/issue-17170.rs +++ b/tests/ui/simd/issue-17170.rs @@ -2,9 +2,9 @@ #![feature(repr_simd)] #[repr(simd)] -struct T(f64, f64, f64); +struct T([f64; 3]); -static X: T = T(0.0, 0.0, 0.0); +static X: T = T([0.0, 0.0, 0.0]); fn main() { let _ = X; diff --git a/tests/ui/simd/issue-32947.rs b/tests/ui/simd/issue-32947.rs index bccca25c52b1d..dc5e7a4ec9153 100644 --- a/tests/ui/simd/issue-32947.rs +++ b/tests/ui/simd/issue-32947.rs @@ -6,7 +6,7 @@ extern crate test; #[repr(simd)] -pub struct Mu64(pub u64, pub u64, pub u64, pub u64); +pub struct Mu64(pub [u64; 4]); fn main() { // This ensures an unaligned pointer even in optimized builds, though LLVM @@ -18,7 +18,7 @@ fn main() { let misaligned_ptr: &mut [u8; 32] = { std::mem::transmute(memory.offset(1)) }; - *misaligned_ptr = std::mem::transmute(Mu64(1, 1, 1, 1)); + *misaligned_ptr = std::mem::transmute(Mu64([1, 1, 1, 1])); test::black_box(memory); } } diff --git a/tests/ui/simd/issue-39720.rs b/tests/ui/simd/issue-39720.rs index 4610b1d50044b..2b51c0224c633 100644 --- a/tests/ui/simd/issue-39720.rs +++ b/tests/ui/simd/issue-39720.rs @@ -5,18 +5,18 @@ #[repr(simd)] #[derive(Copy, Clone, Debug)] -pub struct Char3(pub i8, pub i8, pub i8); +pub struct Char3(pub [i8; 3]); #[repr(simd)] #[derive(Copy, Clone, Debug)] -pub struct Short3(pub i16, pub i16, pub i16); +pub struct Short3(pub [i16; 3]); extern "rust-intrinsic" { fn simd_cast(x: T) -> U; } fn main() { - let cast: Short3 = unsafe { simd_cast(Char3(10, -3, -9)) }; + let cast: Short3 = unsafe { simd_cast(Char3([10, -3, -9])) }; println!("{:?}", cast); } diff --git a/tests/ui/simd/issue-89193.rs b/tests/ui/simd/issue-89193.rs index a4ed9be9962fb..9530124a7cc81 100644 --- a/tests/ui/simd/issue-89193.rs +++ b/tests/ui/simd/issue-89193.rs @@ -8,7 +8,7 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -struct x4(pub T, pub T, pub T, pub T); +struct x4(pub [T; 4]); extern "rust-intrinsic" { fn simd_gather(x: T, y: U, z: V) -> T; @@ -16,36 +16,36 @@ extern "rust-intrinsic" { fn main() { let x: [usize; 4] = [10, 11, 12, 13]; - let default = x4(0_usize, 1, 2, 3); + let default = x4([0_usize, 1, 2, 3]); let all_set = u8::MAX as i8; // aka -1 - let mask = x4(all_set, all_set, all_set, all_set); - let expected = x4(10_usize, 11, 12, 13); + let mask = x4([all_set, all_set, all_set, all_set]); + let expected = x4([10_usize, 11, 12, 13]); unsafe { let pointer = x.as_ptr(); - let pointers = x4( + let pointers = x4([ pointer.offset(0), pointer.offset(1), pointer.offset(2), pointer.offset(3) - ); + ]); let result = simd_gather(default, pointers, mask); assert_eq!(result, expected); } // and again for isize let x: [isize; 4] = [10, 11, 12, 13]; - let default = x4(0_isize, 1, 2, 3); - let expected = x4(10_isize, 11, 12, 13); + let default = x4([0_isize, 1, 2, 3]); + let expected = x4([10_isize, 11, 12, 13]); unsafe { let pointer = x.as_ptr(); - let pointers = x4( + let pointers = x4([ pointer.offset(0), pointer.offset(1), pointer.offset(2), pointer.offset(3) - ); + ]); let result = simd_gather(default, pointers, mask); assert_eq!(result, expected); } diff --git a/tests/ui/simd/monomorphize-heterogeneous.rs b/tests/ui/simd/monomorphize-heterogeneous.rs index 42e380dbb779b..326e52acc34d1 100644 --- a/tests/ui/simd/monomorphize-heterogeneous.rs +++ b/tests/ui/simd/monomorphize-heterogeneous.rs @@ -2,7 +2,11 @@ #[repr(simd)] struct I64F64(i64, f64); -//~^ ERROR SIMD vector should be homogeneous +//~^ ERROR SIMD vector's only field must be an array + +#[repr(simd)] +struct I64x4F64x0([i64; 4], [f64; 0]); +//~^ ERROR SIMD vector cannot have multiple fields static X: I64F64 = I64F64(1, 2.0); diff --git a/tests/ui/simd/monomorphize-heterogeneous.stderr b/tests/ui/simd/monomorphize-heterogeneous.stderr index 58e2b7c834766..610a1a49038aa 100644 --- a/tests/ui/simd/monomorphize-heterogeneous.stderr +++ b/tests/ui/simd/monomorphize-heterogeneous.stderr @@ -1,9 +1,16 @@ -error[E0076]: SIMD vector should be homogeneous +error[E0076]: SIMD vector's only field must be an array --> $DIR/monomorphize-heterogeneous.rs:4:1 | LL | struct I64F64(i64, f64); - | ^^^^^^^^^^^^^ SIMD elements must have the same type + | ^^^^^^^^^^^^^ --- not an array -error: aborting due to 1 previous error +error[E0075]: SIMD vector cannot have multiple fields + --> $DIR/monomorphize-heterogeneous.rs:8:1 + | +LL | struct I64x4F64x0([i64; 4], [f64; 0]); + | ^^^^^^^^^^^^^^^^^ -------- excess field + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0076`. +Some errors have detailed explanations: E0075, E0076. +For more information about an error, try `rustc --explain E0075`. diff --git a/tests/ui/simd/monomorphize-too-long.rs b/tests/ui/simd/monomorphize-too-long.rs new file mode 100644 index 0000000000000..4bcde782292d6 --- /dev/null +++ b/tests/ui/simd/monomorphize-too-long.rs @@ -0,0 +1,11 @@ +//@ build-fail +//@ error-pattern: monomorphising SIMD type `Simd` of length greater than 32768 + +#![feature(repr_simd)] + +#[repr(simd)] +struct Simd([T; N]); + +fn main() { + let _too_big = Simd([1_u16; 54321]); +} diff --git a/tests/ui/simd/monomorphize-too-long.stderr b/tests/ui/simd/monomorphize-too-long.stderr new file mode 100644 index 0000000000000..978eef307abd1 --- /dev/null +++ b/tests/ui/simd/monomorphize-too-long.stderr @@ -0,0 +1,4 @@ +error: monomorphising SIMD type `Simd` of length greater than 32768 + +error: aborting due to 1 previous error + diff --git a/tests/ui/simd/monomorphize-zero-length.rs b/tests/ui/simd/monomorphize-zero-length.rs new file mode 100644 index 0000000000000..44b4cfc0bcfab --- /dev/null +++ b/tests/ui/simd/monomorphize-zero-length.rs @@ -0,0 +1,11 @@ +//@ build-fail +//@ error-pattern: monomorphising SIMD type `Simd` of zero length + +#![feature(repr_simd)] + +#[repr(simd)] +struct Simd([T; N]); + +fn main() { + let _empty = Simd([1.0; 0]); +} diff --git a/tests/ui/simd/monomorphize-zero-length.stderr b/tests/ui/simd/monomorphize-zero-length.stderr new file mode 100644 index 0000000000000..738c20fe51a46 --- /dev/null +++ b/tests/ui/simd/monomorphize-zero-length.stderr @@ -0,0 +1,4 @@ +error: monomorphising SIMD type `Simd` of zero length + +error: aborting due to 1 previous error + diff --git a/tests/ui/simd/target-feature-mixup.rs b/tests/ui/simd/target-feature-mixup.rs index 034cb867c95fc..62d87c3a6dc6c 100644 --- a/tests/ui/simd/target-feature-mixup.rs +++ b/tests/ui/simd/target-feature-mixup.rs @@ -54,17 +54,17 @@ mod test { // An SSE type #[repr(simd)] #[derive(PartialEq, Debug, Clone, Copy)] - struct __m128i(u64, u64); + struct __m128i([u64; 2]); // An AVX type #[repr(simd)] #[derive(PartialEq, Debug, Clone, Copy)] - struct __m256i(u64, u64, u64, u64); + struct __m256i([u64; 4]); // An AVX-512 type #[repr(simd)] #[derive(PartialEq, Debug, Clone, Copy)] - struct __m512i(u64, u64, u64, u64, u64, u64, u64, u64); + struct __m512i([u64; 8]); pub fn main(level: &str) { unsafe { @@ -90,9 +90,9 @@ mod test { )*) => ($( $(#[$attr])* unsafe fn $main(level: &str) { - let m128 = __m128i(1, 2); - let m256 = __m256i(3, 4, 5, 6); - let m512 = __m512i(7, 8, 9, 10, 11, 12, 13, 14); + let m128 = __m128i([1, 2]); + let m256 = __m256i([3, 4, 5, 6]); + let m512 = __m512i([7, 8, 9, 10, 11, 12, 13, 14]); assert_eq!(id_sse_128(m128), m128); assert_eq!(id_sse_256(m256), m256); assert_eq!(id_sse_512(m512), m512); @@ -127,55 +127,55 @@ mod test { #[target_feature(enable = "sse2")] unsafe fn id_sse_128(a: __m128i) -> __m128i { - assert_eq!(a, __m128i(1, 2)); + assert_eq!(a, __m128i([1, 2])); a.clone() } #[target_feature(enable = "sse2")] unsafe fn id_sse_256(a: __m256i) -> __m256i { - assert_eq!(a, __m256i(3, 4, 5, 6)); + assert_eq!(a, __m256i([3, 4, 5, 6])); a.clone() } #[target_feature(enable = "sse2")] unsafe fn id_sse_512(a: __m512i) -> __m512i { - assert_eq!(a, __m512i(7, 8, 9, 10, 11, 12, 13, 14)); + assert_eq!(a, __m512i([7, 8, 9, 10, 11, 12, 13, 14])); a.clone() } #[target_feature(enable = "avx")] unsafe fn id_avx_128(a: __m128i) -> __m128i { - assert_eq!(a, __m128i(1, 2)); + assert_eq!(a, __m128i([1, 2])); a.clone() } #[target_feature(enable = "avx")] unsafe fn id_avx_256(a: __m256i) -> __m256i { - assert_eq!(a, __m256i(3, 4, 5, 6)); + assert_eq!(a, __m256i([3, 4, 5, 6])); a.clone() } #[target_feature(enable = "avx")] unsafe fn id_avx_512(a: __m512i) -> __m512i { - assert_eq!(a, __m512i(7, 8, 9, 10, 11, 12, 13, 14)); + assert_eq!(a, __m512i([7, 8, 9, 10, 11, 12, 13, 14])); a.clone() } #[target_feature(enable = "avx512bw")] unsafe fn id_avx512_128(a: __m128i) -> __m128i { - assert_eq!(a, __m128i(1, 2)); + assert_eq!(a, __m128i([1, 2])); a.clone() } #[target_feature(enable = "avx512bw")] unsafe fn id_avx512_256(a: __m256i) -> __m256i { - assert_eq!(a, __m256i(3, 4, 5, 6)); + assert_eq!(a, __m256i([3, 4, 5, 6])); a.clone() } #[target_feature(enable = "avx512bw")] unsafe fn id_avx512_512(a: __m512i) -> __m512i { - assert_eq!(a, __m512i(7, 8, 9, 10, 11, 12, 13, 14)); + assert_eq!(a, __m512i([7, 8, 9, 10, 11, 12, 13, 14])); a.clone() } } diff --git a/tests/ui/simd/type-generic-monomorphisation-extern-nonnull-ptr.rs b/tests/ui/simd/type-generic-monomorphisation-extern-nonnull-ptr.rs index dbe2d9ddd54a7..a969295c9f9cd 100644 --- a/tests/ui/simd/type-generic-monomorphisation-extern-nonnull-ptr.rs +++ b/tests/ui/simd/type-generic-monomorphisation-extern-nonnull-ptr.rs @@ -11,7 +11,7 @@ extern { } #[repr(simd)] -struct S(T); +struct S([T; 4]); #[inline(never)] fn identity(v: T) -> T { @@ -19,5 +19,5 @@ fn identity(v: T) -> T { } fn main() { - let _v: S<[Option>; 4]> = identity(S([None; 4])); + let _v: S>> = identity(S([None; 4])); } diff --git a/tests/ui/simd/type-generic-monomorphisation-wide-ptr.rs b/tests/ui/simd/type-generic-monomorphisation-wide-ptr.rs index 564118e9b1343..18fc075343069 100644 --- a/tests/ui/simd/type-generic-monomorphisation-wide-ptr.rs +++ b/tests/ui/simd/type-generic-monomorphisation-wide-ptr.rs @@ -2,11 +2,11 @@ #![feature(repr_simd)] -//@ error-pattern:monomorphising SIMD type `S<[*mut [u8]; 4]>` with a non-primitive-scalar (integer/float/pointer) element type `*mut [u8]` +//@ error-pattern:monomorphising SIMD type `S<*mut [u8]>` with a non-primitive-scalar (integer/float/pointer) element type `*mut [u8]` #[repr(simd)] -struct S(T); +struct S([T; 4]); fn main() { - let _v: Option> = None; + let _v: Option> = None; } diff --git a/tests/ui/simd/type-generic-monomorphisation-wide-ptr.stderr b/tests/ui/simd/type-generic-monomorphisation-wide-ptr.stderr index 7ac8d71536034..13b8b0315ba75 100644 --- a/tests/ui/simd/type-generic-monomorphisation-wide-ptr.stderr +++ b/tests/ui/simd/type-generic-monomorphisation-wide-ptr.stderr @@ -1,4 +1,4 @@ -error: monomorphising SIMD type `S<[*mut [u8]; 4]>` with a non-primitive-scalar (integer/float/pointer) element type `*mut [u8]` +error: monomorphising SIMD type `S<*mut [u8]>` with a non-primitive-scalar (integer/float/pointer) element type `*mut [u8]` error: aborting due to 1 previous error diff --git a/tests/ui/simd/type-generic-monomorphisation.rs b/tests/ui/simd/type-generic-monomorphisation.rs index 2eeba55ef913a..8b8d645a2649b 100644 --- a/tests/ui/simd/type-generic-monomorphisation.rs +++ b/tests/ui/simd/type-generic-monomorphisation.rs @@ -7,8 +7,8 @@ struct X(Vec); #[repr(simd)] -struct Simd2(T, T); +struct Simd2([T; 2]); fn main() { - let _ = Simd2(X(vec![]), X(vec![])); + let _ = Simd2([X(vec![]), X(vec![])]); } diff --git a/tests/ui/simd/type-len.rs b/tests/ui/simd/type-len.rs index d82c70b8d8268..a971177e1543a 100644 --- a/tests/ui/simd/type-len.rs +++ b/tests/ui/simd/type-len.rs @@ -1,7 +1,6 @@ #![feature(repr_simd)] #![allow(non_camel_case_types)] - #[repr(simd)] struct empty; //~ ERROR SIMD vector cannot be empty @@ -12,12 +11,12 @@ struct empty2([f32; 0]); //~ ERROR SIMD vector cannot be empty struct pow2([f32; 7]); #[repr(simd)] -struct i64f64(i64, f64); //~ ERROR SIMD vector should be homogeneous +struct i64f64(i64, f64); //~ ERROR SIMD vector's only field must be an array struct Foo; #[repr(simd)] -struct FooV(Foo, Foo); //~ ERROR SIMD vector element type should be a primitive scalar (integer/float/pointer) type +struct FooV(Foo, Foo); //~ ERROR SIMD vector's only field must be an array #[repr(simd)] struct FooV2([Foo; 2]); //~ ERROR SIMD vector element type should be a primitive scalar (integer/float/pointer) type @@ -29,11 +28,11 @@ struct TooBig([f32; 65536]); //~ ERROR SIMD vector cannot have more than 32768 e struct JustRight([u128; 32768]); #[repr(simd)] -struct RGBA { +struct RGBA { //~ ERROR SIMD vector's only field must be an array r: f32, g: f32, b: f32, - a: f32 + a: f32, } fn main() {} diff --git a/tests/ui/simd/type-len.stderr b/tests/ui/simd/type-len.stderr index 2a6bd1b0fd58a..04c4ca7677cfc 100644 --- a/tests/ui/simd/type-len.stderr +++ b/tests/ui/simd/type-len.stderr @@ -1,40 +1,48 @@ error[E0075]: SIMD vector cannot be empty - --> $DIR/type-len.rs:6:1 + --> $DIR/type-len.rs:5:1 | LL | struct empty; | ^^^^^^^^^^^^ error[E0075]: SIMD vector cannot be empty - --> $DIR/type-len.rs:9:1 + --> $DIR/type-len.rs:8:1 | LL | struct empty2([f32; 0]); | ^^^^^^^^^^^^^ -error[E0076]: SIMD vector should be homogeneous - --> $DIR/type-len.rs:15:1 +error[E0076]: SIMD vector's only field must be an array + --> $DIR/type-len.rs:14:1 | LL | struct i64f64(i64, f64); - | ^^^^^^^^^^^^^ SIMD elements must have the same type + | ^^^^^^^^^^^^^ --- not an array -error[E0077]: SIMD vector element type should be a primitive scalar (integer/float/pointer) type - --> $DIR/type-len.rs:20:1 +error[E0076]: SIMD vector's only field must be an array + --> $DIR/type-len.rs:19:1 | LL | struct FooV(Foo, Foo); - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ --- not an array error[E0077]: SIMD vector element type should be a primitive scalar (integer/float/pointer) type - --> $DIR/type-len.rs:23:1 + --> $DIR/type-len.rs:22:1 | LL | struct FooV2([Foo; 2]); | ^^^^^^^^^^^^ error[E0075]: SIMD vector cannot have more than 32768 elements - --> $DIR/type-len.rs:26:1 + --> $DIR/type-len.rs:25:1 | LL | struct TooBig([f32; 65536]); | ^^^^^^^^^^^^^ -error: aborting due to 6 previous errors +error[E0076]: SIMD vector's only field must be an array + --> $DIR/type-len.rs:31:1 + | +LL | struct RGBA { + | ^^^^^^^^^^^ +LL | r: f32, + | ------ not an array + +error: aborting due to 7 previous errors Some errors have detailed explanations: E0075, E0076, E0077. For more information about an error, try `rustc --explain E0075`. diff --git a/tests/ui/span/gated-features-attr-spans.rs b/tests/ui/span/gated-features-attr-spans.rs index 69511ab8e1fc7..55527fa8add01 100644 --- a/tests/ui/span/gated-features-attr-spans.rs +++ b/tests/ui/span/gated-features-attr-spans.rs @@ -1,7 +1,6 @@ #[repr(simd)] //~ ERROR are experimental struct Coord { - x: u32, - y: u32, + v: [u32; 2], } fn main() {} From 24c505070c710dea13c02e965cf0b227e856ade1 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Fri, 23 Aug 2024 01:59:26 -0700 Subject: [PATCH 130/189] Fix the examples in cg_clif --- .../example/float-minmax-pass.rs | 12 ++++++------ .../rustc_codegen_cranelift/example/std_example.rs | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/example/float-minmax-pass.rs b/compiler/rustc_codegen_cranelift/example/float-minmax-pass.rs index c54574d801d3a..ad46e18c11c0d 100644 --- a/compiler/rustc_codegen_cranelift/example/float-minmax-pass.rs +++ b/compiler/rustc_codegen_cranelift/example/float-minmax-pass.rs @@ -9,13 +9,13 @@ #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] -struct f32x4(pub f32, pub f32, pub f32, pub f32); +struct f32x4(pub [f32; 4]); use std::intrinsics::simd::*; fn main() { - let x = f32x4(1.0, 2.0, 3.0, 4.0); - let y = f32x4(2.0, 1.0, 4.0, 3.0); + let x = f32x4([1.0, 2.0, 3.0, 4.0]); + let y = f32x4([2.0, 1.0, 4.0, 3.0]); #[cfg(not(any(target_arch = "mips", target_arch = "mips64")))] let nan = f32::NAN; @@ -24,13 +24,13 @@ fn main() { #[cfg(any(target_arch = "mips", target_arch = "mips64"))] let nan = f32::from_bits(f32::NAN.to_bits() - 1); - let n = f32x4(nan, nan, nan, nan); + let n = f32x4([nan, nan, nan, nan]); unsafe { let min0 = simd_fmin(x, y); let min1 = simd_fmin(y, x); assert_eq!(min0, min1); - let e = f32x4(1.0, 1.0, 3.0, 3.0); + let e = f32x4([1.0, 1.0, 3.0, 3.0]); assert_eq!(min0, e); let minn = simd_fmin(x, n); assert_eq!(minn, x); @@ -40,7 +40,7 @@ fn main() { let max0 = simd_fmax(x, y); let max1 = simd_fmax(y, x); assert_eq!(max0, max1); - let e = f32x4(2.0, 2.0, 4.0, 4.0); + let e = f32x4([2.0, 2.0, 4.0, 4.0]); assert_eq!(max0, e); let maxn = simd_fmax(x, n); assert_eq!(maxn, x); diff --git a/compiler/rustc_codegen_cranelift/example/std_example.rs b/compiler/rustc_codegen_cranelift/example/std_example.rs index e99763e272233..f27d4ef57e0c0 100644 --- a/compiler/rustc_codegen_cranelift/example/std_example.rs +++ b/compiler/rustc_codegen_cranelift/example/std_example.rs @@ -166,7 +166,7 @@ fn main() { enum Never {} } - foo(I64X2(0, 0)); + foo(I64X2([0, 0])); transmute_fat_pointer(); @@ -204,7 +204,7 @@ fn rust_call_abi() { } #[repr(simd)] -struct I64X2(i64, i64); +struct I64X2([i64; 2]); #[allow(improper_ctypes_definitions)] extern "C" fn foo(_a: I64X2) {} From 51d0f68b781a9fde6cf7712b89d01991420ed70f Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Fri, 23 Aug 2024 12:21:20 -0700 Subject: [PATCH 131/189] Update the MIRI tests --- .../tests/fail/intrinsics/simd-div-by-zero.rs | 6 +++--- .../tests/fail/intrinsics/simd-div-overflow.rs | 6 +++--- .../intrinsics/simd-reduce-invalid-bool.rs | 4 ++-- .../tests/fail/intrinsics/simd-rem-by-zero.rs | 6 +++--- .../intrinsics/simd-select-bitmask-invalid.rs | 4 ++-- .../intrinsics/simd-select-invalid-bool.rs | 4 ++-- .../tests/fail/intrinsics/simd-shl-too-far.rs | 6 +++--- .../tests/fail/intrinsics/simd-shr-too-far.rs | 6 +++--- .../pass/simd-intrinsic-generic-elements.rs | 18 +++++++++--------- 9 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/tools/miri/tests/fail/intrinsics/simd-div-by-zero.rs b/src/tools/miri/tests/fail/intrinsics/simd-div-by-zero.rs index ba474332b811c..57a9b66d8ecde 100644 --- a/src/tools/miri/tests/fail/intrinsics/simd-div-by-zero.rs +++ b/src/tools/miri/tests/fail/intrinsics/simd-div-by-zero.rs @@ -4,12 +4,12 @@ use std::intrinsics::simd::simd_div; #[repr(simd)] #[allow(non_camel_case_types)] -struct i32x2(i32, i32); +struct i32x2([i32; 2]); fn main() { unsafe { - let x = i32x2(1, 1); - let y = i32x2(1, 0); + let x = i32x2([1, 1]); + let y = i32x2([1, 0]); simd_div(x, y); //~ERROR: Undefined Behavior: dividing by zero } } diff --git a/src/tools/miri/tests/fail/intrinsics/simd-div-overflow.rs b/src/tools/miri/tests/fail/intrinsics/simd-div-overflow.rs index d01e41de0e4be..8ffc2669828c4 100644 --- a/src/tools/miri/tests/fail/intrinsics/simd-div-overflow.rs +++ b/src/tools/miri/tests/fail/intrinsics/simd-div-overflow.rs @@ -4,12 +4,12 @@ use std::intrinsics::simd::simd_div; #[repr(simd)] #[allow(non_camel_case_types)] -struct i32x2(i32, i32); +struct i32x2([i32; 2]); fn main() { unsafe { - let x = i32x2(1, i32::MIN); - let y = i32x2(1, -1); + let x = i32x2([1, i32::MIN]); + let y = i32x2([1, -1]); simd_div(x, y); //~ERROR: Undefined Behavior: overflow in signed division } } diff --git a/src/tools/miri/tests/fail/intrinsics/simd-reduce-invalid-bool.rs b/src/tools/miri/tests/fail/intrinsics/simd-reduce-invalid-bool.rs index a194f0dd18aa8..ea0f908d996ff 100644 --- a/src/tools/miri/tests/fail/intrinsics/simd-reduce-invalid-bool.rs +++ b/src/tools/miri/tests/fail/intrinsics/simd-reduce-invalid-bool.rs @@ -4,11 +4,11 @@ use std::intrinsics::simd::simd_reduce_any; #[repr(simd)] #[allow(non_camel_case_types)] -struct i32x2(i32, i32); +struct i32x2([i32; 2]); fn main() { unsafe { - let x = i32x2(0, 1); + let x = i32x2([0, 1]); simd_reduce_any(x); //~ERROR: must be all-0-bits or all-1-bits } } diff --git a/src/tools/miri/tests/fail/intrinsics/simd-rem-by-zero.rs b/src/tools/miri/tests/fail/intrinsics/simd-rem-by-zero.rs index cd1e4b8162b36..21c9520efc48a 100644 --- a/src/tools/miri/tests/fail/intrinsics/simd-rem-by-zero.rs +++ b/src/tools/miri/tests/fail/intrinsics/simd-rem-by-zero.rs @@ -4,12 +4,12 @@ use std::intrinsics::simd::simd_rem; #[repr(simd)] #[allow(non_camel_case_types)] -struct i32x2(i32, i32); +struct i32x2([i32; 2]); fn main() { unsafe { - let x = i32x2(1, 1); - let y = i32x2(1, 0); + let x = i32x2([1, 1]); + let y = i32x2([1, 0]); simd_rem(x, y); //~ERROR: Undefined Behavior: calculating the remainder with a divisor of zero } } diff --git a/src/tools/miri/tests/fail/intrinsics/simd-select-bitmask-invalid.rs b/src/tools/miri/tests/fail/intrinsics/simd-select-bitmask-invalid.rs index 96802fae49c23..409098ac3b5df 100644 --- a/src/tools/miri/tests/fail/intrinsics/simd-select-bitmask-invalid.rs +++ b/src/tools/miri/tests/fail/intrinsics/simd-select-bitmask-invalid.rs @@ -5,11 +5,11 @@ use std::intrinsics::simd::simd_select_bitmask; #[repr(simd)] #[allow(non_camel_case_types)] #[derive(Copy, Clone)] -struct i32x2(i32, i32); +struct i32x2([i32; 2]); fn main() { unsafe { - let x = i32x2(0, 1); + let x = i32x2([0, 1]); simd_select_bitmask(0b11111111u8, x, x); //~ERROR: bitmask less than 8 bits long must be filled with 0s for the remaining bits } } diff --git a/src/tools/miri/tests/fail/intrinsics/simd-select-invalid-bool.rs b/src/tools/miri/tests/fail/intrinsics/simd-select-invalid-bool.rs index 388fb2e2a84ae..a81ce95ada62f 100644 --- a/src/tools/miri/tests/fail/intrinsics/simd-select-invalid-bool.rs +++ b/src/tools/miri/tests/fail/intrinsics/simd-select-invalid-bool.rs @@ -5,11 +5,11 @@ use std::intrinsics::simd::simd_select; #[repr(simd)] #[allow(non_camel_case_types)] #[derive(Copy, Clone)] -struct i32x2(i32, i32); +struct i32x2([i32; 2]); fn main() { unsafe { - let x = i32x2(0, 1); + let x = i32x2([0, 1]); simd_select(x, x, x); //~ERROR: must be all-0-bits or all-1-bits } } diff --git a/src/tools/miri/tests/fail/intrinsics/simd-shl-too-far.rs b/src/tools/miri/tests/fail/intrinsics/simd-shl-too-far.rs index 12aa7c10af4e4..ed317254ee66c 100644 --- a/src/tools/miri/tests/fail/intrinsics/simd-shl-too-far.rs +++ b/src/tools/miri/tests/fail/intrinsics/simd-shl-too-far.rs @@ -4,12 +4,12 @@ use std::intrinsics::simd::simd_shl; #[repr(simd)] #[allow(non_camel_case_types)] -struct i32x2(i32, i32); +struct i32x2([i32; 2]); fn main() { unsafe { - let x = i32x2(1, 1); - let y = i32x2(100, 0); + let x = i32x2([1, 1]); + let y = i32x2([100, 0]); simd_shl(x, y); //~ERROR: overflowing shift by 100 in `simd_shl` in lane 0 } } diff --git a/src/tools/miri/tests/fail/intrinsics/simd-shr-too-far.rs b/src/tools/miri/tests/fail/intrinsics/simd-shr-too-far.rs index ada7cf408c4ed..5d2ff1b82ed06 100644 --- a/src/tools/miri/tests/fail/intrinsics/simd-shr-too-far.rs +++ b/src/tools/miri/tests/fail/intrinsics/simd-shr-too-far.rs @@ -4,12 +4,12 @@ use std::intrinsics::simd::simd_shr; #[repr(simd)] #[allow(non_camel_case_types)] -struct i32x2(i32, i32); +struct i32x2([i32; 2]); fn main() { unsafe { - let x = i32x2(1, 1); - let y = i32x2(20, 40); + let x = i32x2([1, 1]); + let y = i32x2([20, 40]); simd_shr(x, y); //~ERROR: overflowing shift by 40 in `simd_shr` in lane 1 } } diff --git a/src/tools/miri/tests/pass/simd-intrinsic-generic-elements.rs b/src/tools/miri/tests/pass/simd-intrinsic-generic-elements.rs index 4a87f8c3ca720..9cf0c2ddef333 100644 --- a/src/tools/miri/tests/pass/simd-intrinsic-generic-elements.rs +++ b/src/tools/miri/tests/pass/simd-intrinsic-generic-elements.rs @@ -3,22 +3,22 @@ #[repr(simd)] #[derive(Copy, Clone, Debug, PartialEq)] #[allow(non_camel_case_types)] -struct i32x2(i32, i32); +struct i32x2([i32; 2]); #[repr(simd)] #[derive(Copy, Clone, Debug, PartialEq)] #[allow(non_camel_case_types)] -struct i32x4(i32, i32, i32, i32); +struct i32x4([i32; 4]); #[repr(simd)] #[derive(Copy, Clone, Debug, PartialEq)] #[allow(non_camel_case_types)] -struct i32x8(i32, i32, i32, i32, i32, i32, i32, i32); +struct i32x8([i32; 8]); fn main() { - let _x2 = i32x2(20, 21); - let _x4 = i32x4(40, 41, 42, 43); - let _x8 = i32x8(80, 81, 82, 83, 84, 85, 86, 87); + let _x2 = i32x2([20, 21]); + let _x4 = i32x4([40, 41, 42, 43]); + let _x8 = i32x8([80, 81, 82, 83, 84, 85, 86, 87]); - let _y2 = i32x2(120, 121); - let _y4 = i32x4(140, 141, 142, 143); - let _y8 = i32x8(180, 181, 182, 183, 184, 185, 186, 187); + let _y2 = i32x2([120, 121]); + let _y4 = i32x4([140, 141, 142, 143]); + let _y8 = i32x8([180, 181, 182, 183, 184, 185, 186, 187]); } From bdda4ec2f5d764134e568421206b29bdeeb7c647 Mon Sep 17 00:00:00 2001 From: Marcondiro <46560192+Marcondiro@users.noreply.github.com> Date: Tue, 10 Sep 2024 10:50:20 +0200 Subject: [PATCH 132/189] Bump unicode_data to version 16.0.0 --- library/core/src/unicode/unicode_data.rs | 1321 +++++++++++----------- 1 file changed, 670 insertions(+), 651 deletions(-) diff --git a/library/core/src/unicode/unicode_data.rs b/library/core/src/unicode/unicode_data.rs index 1b3d6729663b5..143beb3770680 100644 --- a/library/core/src/unicode/unicode_data.rs +++ b/library/core/src/unicode/unicode_data.rs @@ -99,75 +99,77 @@ fn skip_search( offset_idx % 2 == 1 } -pub const UNICODE_VERSION: (u8, u8, u8) = (15, 1, 0); +pub const UNICODE_VERSION: (u8, u8, u8) = (16, 0, 0); #[rustfmt::skip] pub mod alphabetic { - static SHORT_OFFSET_RUNS: [u32; 54] = [ - 706, 33559113, 872420973, 952114966, 1161831606, 1310731264, 1314926597, 1394619392, - 1444957632, 1447077005, 1451271693, 1459672996, 1648425216, 1658911342, 1661009214, - 1707147904, 1793132343, 1887506048, 2040601600, 2392923872, 2481005466, 2504077200, - 2514564144, 2520859648, 2527151687, 2529257472, 2531355193, 2533453376, 2564917240, - 2596375766, 2600579056, 2606870819, 2621551356, 2642525184, 2644628480, 2665600678, - 2743197440, 2791432848, 2841765072, 2850154464, 2854350336, 2887905584, 3026321408, - 3038947040, 3041048378, 3045248674, 3053644769, 3057839710, 3062036480, 3064134174, - 3066232832, 3068334923, 3070436272, 3075744688, + static SHORT_OFFSET_RUNS: [u32; 53] = [ + 706, 33559113, 876615277, 956309270, 1166025910, 1314925568, 1319120901, 1398813696, + 1449151936, 1451271309, 1455465997, 1463867300, 1652619520, 1663105646, 1665203518, + 1711342208, 1797326647, 1895898848, 2560697242, 2583768976, 2594255920, 2600551419, + 2608940615, 2613141760, 2615240704, 2619435577, 2621533504, 2652997624, 2688650454, + 2692853744, 2699145507, 2713826044, 2734799872, 2736903168, 2757875366, 2835472128, + 2883707536, 2934039760, 2942429152, 2955013632, 2988568880, 3126984704, 3139610336, + 3141711674, 3145911970, 3154308065, 3158503006, 3162699776, 3164797470, 3166896128, + 3168998219, 3171099568, 3176407984, ]; - static OFFSETS: [u8; 1467] = [ - 65, 26, 6, 26, 47, 1, 10, 1, 4, 1, 5, 23, 1, 31, 1, 0, 4, 12, 14, 5, 7, 1, 1, 1, 86, 1, 42, - 5, 1, 2, 2, 4, 1, 1, 6, 1, 1, 3, 1, 1, 1, 20, 1, 83, 1, 139, 8, 166, 1, 38, 2, 1, 6, 41, 39, - 14, 1, 1, 1, 2, 1, 2, 1, 1, 8, 27, 4, 4, 29, 11, 5, 56, 1, 7, 14, 102, 1, 8, 4, 8, 4, 3, 10, - 3, 2, 1, 16, 48, 13, 101, 24, 33, 9, 2, 4, 1, 5, 24, 2, 19, 19, 25, 7, 11, 5, 24, 1, 6, 17, - 42, 10, 12, 3, 7, 6, 76, 1, 16, 1, 3, 4, 15, 13, 19, 1, 8, 2, 2, 2, 22, 1, 7, 1, 1, 3, 4, 3, - 8, 2, 2, 2, 2, 1, 1, 8, 1, 4, 2, 1, 5, 12, 2, 10, 1, 4, 3, 1, 6, 4, 2, 2, 22, 1, 7, 1, 2, 1, - 2, 1, 2, 4, 5, 4, 2, 2, 2, 4, 1, 7, 4, 1, 1, 17, 6, 11, 3, 1, 9, 1, 3, 1, 22, 1, 7, 1, 2, 1, - 5, 3, 9, 1, 3, 1, 2, 3, 1, 15, 4, 21, 4, 4, 3, 1, 8, 2, 2, 2, 22, 1, 7, 1, 2, 1, 5, 3, 8, 2, - 2, 2, 2, 9, 2, 4, 2, 1, 5, 13, 1, 16, 2, 1, 6, 3, 3, 1, 4, 3, 2, 1, 1, 1, 2, 3, 2, 3, 3, 3, - 12, 4, 5, 3, 3, 1, 3, 3, 1, 6, 1, 40, 13, 1, 3, 1, 23, 1, 16, 3, 8, 1, 3, 1, 3, 8, 2, 1, 3, - 2, 1, 2, 4, 28, 4, 1, 8, 1, 3, 1, 23, 1, 10, 1, 5, 3, 8, 1, 3, 1, 3, 8, 2, 6, 2, 1, 4, 13, - 3, 12, 13, 1, 3, 1, 41, 2, 8, 1, 3, 1, 3, 1, 1, 5, 4, 7, 5, 22, 6, 1, 3, 1, 18, 3, 24, 1, 9, - 1, 1, 2, 7, 8, 6, 1, 1, 1, 8, 18, 2, 13, 58, 5, 7, 6, 1, 51, 2, 1, 1, 1, 5, 1, 24, 1, 1, 1, - 19, 1, 3, 2, 5, 1, 1, 6, 1, 14, 4, 32, 1, 63, 8, 1, 36, 4, 19, 4, 16, 1, 36, 67, 55, 1, 1, - 2, 5, 16, 64, 10, 4, 2, 38, 1, 1, 5, 1, 2, 43, 1, 0, 1, 4, 2, 7, 1, 1, 1, 4, 2, 41, 1, 4, 2, - 33, 1, 4, 2, 7, 1, 1, 1, 4, 2, 15, 1, 57, 1, 4, 2, 67, 37, 16, 16, 86, 2, 6, 3, 0, 2, 17, 1, - 26, 5, 75, 3, 11, 7, 20, 11, 21, 12, 20, 12, 13, 1, 3, 1, 2, 12, 52, 2, 19, 14, 1, 4, 1, 67, - 89, 7, 43, 5, 70, 10, 31, 1, 12, 4, 9, 23, 30, 2, 5, 11, 44, 4, 26, 54, 28, 4, 63, 2, 20, - 50, 1, 23, 2, 11, 3, 49, 52, 1, 15, 1, 8, 51, 42, 2, 4, 10, 44, 1, 11, 14, 55, 22, 3, 10, - 36, 2, 9, 7, 43, 2, 3, 41, 4, 1, 6, 1, 2, 3, 1, 5, 192, 39, 14, 11, 0, 2, 6, 2, 38, 2, 6, 2, - 8, 1, 1, 1, 1, 1, 1, 1, 31, 2, 53, 1, 7, 1, 1, 3, 3, 1, 7, 3, 4, 2, 6, 4, 13, 5, 3, 1, 7, - 116, 1, 13, 1, 16, 13, 101, 1, 4, 1, 2, 10, 1, 1, 3, 5, 6, 1, 1, 1, 1, 1, 1, 4, 1, 11, 2, 4, - 5, 5, 4, 1, 17, 41, 0, 52, 0, 229, 6, 4, 3, 2, 12, 38, 1, 1, 5, 1, 2, 56, 7, 1, 16, 23, 9, - 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 32, 47, 1, 0, 3, 25, 9, 7, 5, 2, 5, 4, 86, - 6, 3, 1, 90, 1, 4, 5, 43, 1, 94, 17, 32, 48, 16, 0, 0, 64, 0, 67, 46, 2, 0, 3, 16, 10, 2, - 20, 47, 5, 8, 3, 113, 39, 9, 2, 103, 2, 64, 5, 2, 1, 1, 1, 5, 24, 20, 1, 33, 24, 52, 12, 68, - 1, 1, 44, 6, 3, 1, 1, 3, 10, 33, 5, 35, 13, 29, 3, 51, 1, 12, 15, 1, 16, 16, 10, 5, 1, 55, - 9, 14, 18, 23, 3, 69, 1, 1, 1, 1, 24, 3, 2, 16, 2, 4, 11, 6, 2, 6, 2, 6, 9, 7, 1, 7, 1, 43, - 1, 14, 6, 123, 21, 0, 12, 23, 4, 49, 0, 0, 2, 106, 38, 7, 12, 5, 5, 12, 1, 13, 1, 5, 1, 1, - 1, 2, 1, 2, 1, 108, 33, 0, 18, 64, 2, 54, 40, 12, 116, 5, 1, 135, 36, 26, 6, 26, 11, 89, 3, - 6, 2, 6, 2, 6, 2, 3, 35, 12, 1, 26, 1, 19, 1, 2, 1, 15, 2, 14, 34, 123, 69, 53, 0, 29, 3, - 49, 47, 32, 13, 30, 5, 43, 5, 30, 2, 36, 4, 8, 1, 5, 42, 158, 18, 36, 4, 36, 4, 40, 8, 52, - 12, 11, 1, 15, 1, 7, 1, 2, 1, 11, 1, 15, 1, 7, 1, 2, 67, 0, 9, 22, 10, 8, 24, 6, 1, 42, 1, - 9, 69, 6, 2, 1, 1, 44, 1, 2, 3, 1, 2, 23, 10, 23, 9, 31, 65, 19, 1, 2, 10, 22, 10, 26, 70, - 56, 6, 2, 64, 4, 1, 2, 5, 8, 1, 3, 1, 29, 42, 29, 3, 29, 35, 8, 1, 28, 27, 54, 10, 22, 10, - 19, 13, 18, 110, 73, 55, 51, 13, 51, 13, 40, 0, 42, 1, 2, 3, 2, 78, 29, 10, 1, 8, 22, 42, - 18, 46, 21, 27, 23, 9, 70, 43, 5, 10, 57, 9, 1, 13, 25, 23, 51, 17, 4, 8, 35, 3, 1, 9, 64, - 1, 4, 9, 2, 10, 1, 1, 1, 35, 18, 1, 34, 2, 1, 6, 4, 62, 7, 1, 1, 1, 4, 1, 15, 1, 10, 7, 57, - 23, 4, 1, 8, 2, 2, 2, 22, 1, 7, 1, 2, 1, 5, 3, 8, 2, 2, 2, 2, 3, 1, 6, 1, 5, 7, 156, 66, 1, - 3, 1, 4, 20, 3, 30, 66, 2, 2, 1, 1, 184, 54, 2, 7, 25, 6, 34, 63, 1, 1, 3, 1, 59, 54, 2, 1, - 71, 27, 2, 14, 21, 7, 185, 57, 103, 64, 31, 8, 2, 1, 2, 8, 1, 2, 1, 30, 1, 2, 2, 2, 2, 4, - 93, 8, 2, 46, 2, 6, 1, 1, 1, 2, 27, 51, 2, 10, 17, 72, 5, 1, 18, 73, 0, 9, 1, 45, 1, 7, 1, - 1, 49, 30, 2, 22, 1, 14, 73, 7, 1, 2, 1, 44, 3, 1, 1, 2, 1, 3, 1, 1, 2, 2, 24, 6, 1, 2, 1, - 37, 1, 2, 1, 4, 1, 1, 0, 23, 9, 17, 1, 41, 3, 3, 111, 1, 79, 0, 102, 111, 17, 196, 0, 97, - 15, 0, 17, 6, 0, 0, 0, 0, 7, 31, 17, 79, 17, 30, 18, 48, 16, 4, 31, 21, 5, 19, 0, 64, 128, - 75, 4, 57, 7, 17, 64, 2, 1, 1, 12, 2, 14, 0, 8, 0, 42, 9, 0, 4, 1, 7, 1, 2, 1, 0, 15, 1, 29, - 3, 2, 1, 14, 4, 8, 0, 0, 107, 5, 13, 3, 9, 7, 10, 4, 1, 0, 85, 1, 71, 1, 2, 2, 1, 2, 2, 2, - 4, 1, 12, 1, 1, 1, 7, 1, 65, 1, 4, 2, 8, 1, 7, 1, 28, 1, 4, 1, 5, 1, 1, 3, 7, 1, 0, 2, 25, - 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 8, 0, 31, 6, 6, 213, 7, 1, - 17, 2, 7, 1, 2, 1, 5, 5, 62, 33, 1, 112, 45, 10, 7, 16, 1, 0, 30, 18, 44, 0, 28, 0, 7, 1, 4, - 1, 2, 1, 15, 1, 197, 59, 68, 3, 1, 3, 1, 0, 4, 1, 27, 1, 2, 1, 1, 2, 1, 1, 10, 1, 4, 1, 1, - 1, 1, 6, 1, 4, 1, 1, 1, 1, 1, 1, 3, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, - 4, 1, 7, 1, 4, 1, 4, 1, 1, 1, 10, 1, 17, 5, 3, 1, 5, 1, 17, 0, 26, 6, 26, 6, 26, 0, 0, 32, - 0, 6, 222, 2, 0, 14, 0, 15, 0, 0, 0, 0, 0, 5, 0, 0, + static OFFSETS: [u8; 1515] = [ + 65, 26, 6, 26, 47, 1, 10, 1, 4, 1, 5, 23, 1, 31, 1, 0, 4, 12, 14, 5, 7, 1, 1, 1, 86, 1, 29, + 18, 1, 2, 2, 4, 1, 1, 6, 1, 1, 3, 1, 1, 1, 20, 1, 83, 1, 139, 8, 166, 1, 38, 2, 1, 6, 41, + 39, 14, 1, 1, 1, 2, 1, 2, 1, 1, 8, 27, 4, 4, 29, 11, 5, 56, 1, 7, 14, 102, 1, 8, 4, 8, 4, 3, + 10, 3, 2, 1, 16, 48, 13, 101, 24, 33, 9, 2, 4, 1, 5, 24, 2, 19, 19, 25, 7, 11, 5, 24, 1, 6, + 8, 1, 8, 42, 10, 12, 3, 7, 6, 76, 1, 16, 1, 3, 4, 15, 13, 19, 1, 8, 2, 2, 2, 22, 1, 7, 1, 1, + 3, 4, 3, 8, 2, 2, 2, 2, 1, 1, 8, 1, 4, 2, 1, 5, 12, 2, 10, 1, 4, 3, 1, 6, 4, 2, 2, 22, 1, 7, + 1, 2, 1, 2, 1, 2, 4, 5, 4, 2, 2, 2, 4, 1, 7, 4, 1, 1, 17, 6, 11, 3, 1, 9, 1, 3, 1, 22, 1, 7, + 1, 2, 1, 5, 3, 9, 1, 3, 1, 2, 3, 1, 15, 4, 21, 4, 4, 3, 1, 8, 2, 2, 2, 22, 1, 7, 1, 2, 1, 5, + 3, 8, 2, 2, 2, 2, 9, 2, 4, 2, 1, 5, 13, 1, 16, 2, 1, 6, 3, 3, 1, 4, 3, 2, 1, 1, 1, 2, 3, 2, + 3, 3, 3, 12, 4, 5, 3, 3, 1, 3, 3, 1, 6, 1, 40, 13, 1, 3, 1, 23, 1, 16, 3, 8, 1, 3, 1, 3, 8, + 2, 1, 3, 2, 1, 2, 4, 28, 4, 1, 8, 1, 3, 1, 23, 1, 10, 1, 5, 3, 8, 1, 3, 1, 3, 8, 2, 6, 2, 1, + 4, 13, 3, 12, 13, 1, 3, 1, 41, 2, 8, 1, 3, 1, 3, 1, 1, 5, 4, 7, 5, 22, 6, 1, 3, 1, 18, 3, + 24, 1, 9, 1, 1, 2, 7, 8, 6, 1, 1, 1, 8, 18, 2, 13, 58, 5, 7, 6, 1, 51, 2, 1, 1, 1, 5, 1, 24, + 1, 1, 1, 19, 1, 3, 2, 5, 1, 1, 6, 1, 14, 4, 32, 1, 63, 8, 1, 36, 4, 19, 4, 16, 1, 36, 67, + 55, 1, 1, 2, 5, 16, 64, 10, 4, 2, 38, 1, 1, 5, 1, 2, 43, 1, 0, 1, 4, 2, 7, 1, 1, 1, 4, 2, + 41, 1, 4, 2, 33, 1, 4, 2, 7, 1, 1, 1, 4, 2, 15, 1, 57, 1, 4, 2, 67, 37, 16, 16, 86, 2, 6, 3, + 0, 2, 17, 1, 26, 5, 75, 3, 11, 7, 20, 11, 21, 12, 20, 12, 13, 1, 3, 1, 2, 12, 52, 2, 19, 14, + 1, 4, 1, 67, 89, 7, 43, 5, 70, 10, 31, 1, 12, 4, 9, 23, 30, 2, 5, 11, 44, 4, 26, 54, 28, 4, + 63, 2, 20, 50, 1, 23, 2, 11, 3, 49, 52, 1, 15, 1, 8, 51, 42, 2, 4, 10, 44, 1, 11, 14, 55, + 22, 3, 10, 36, 2, 11, 5, 43, 2, 3, 41, 4, 1, 6, 1, 2, 3, 1, 5, 192, 19, 34, 11, 0, 2, 6, 2, + 38, 2, 6, 2, 8, 1, 1, 1, 1, 1, 1, 1, 31, 2, 53, 1, 7, 1, 1, 3, 3, 1, 7, 3, 4, 2, 6, 4, 13, + 5, 3, 1, 7, 116, 1, 13, 1, 16, 13, 101, 1, 4, 1, 2, 10, 1, 1, 3, 5, 6, 1, 1, 1, 1, 1, 1, 4, + 1, 11, 2, 4, 5, 5, 4, 1, 17, 41, 0, 52, 0, 229, 6, 4, 3, 2, 12, 38, 1, 1, 5, 1, 2, 56, 7, 1, + 16, 23, 9, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 32, 47, 1, 0, 3, 25, 9, 7, 5, 2, + 5, 4, 86, 6, 3, 1, 90, 1, 4, 5, 43, 1, 94, 17, 32, 48, 16, 0, 0, 64, 0, 67, 46, 2, 0, 3, 16, + 10, 2, 20, 47, 5, 8, 3, 113, 39, 9, 2, 103, 2, 67, 2, 2, 1, 1, 1, 8, 21, 20, 1, 33, 24, 52, + 12, 68, 1, 1, 44, 6, 3, 1, 1, 3, 10, 33, 5, 35, 13, 29, 3, 51, 1, 12, 15, 1, 16, 16, 10, 5, + 1, 55, 9, 14, 18, 23, 3, 69, 1, 1, 1, 1, 24, 3, 2, 16, 2, 4, 11, 6, 2, 6, 2, 6, 9, 7, 1, 7, + 1, 43, 1, 14, 6, 123, 21, 0, 12, 23, 4, 49, 0, 0, 2, 106, 38, 7, 12, 5, 5, 12, 1, 13, 1, 5, + 1, 1, 1, 2, 1, 2, 1, 108, 33, 0, 18, 64, 2, 54, 40, 12, 116, 5, 1, 135, 36, 26, 6, 26, 11, + 89, 3, 6, 2, 6, 2, 6, 2, 3, 35, 12, 1, 26, 1, 19, 1, 2, 1, 15, 2, 14, 34, 123, 69, 53, 0, + 29, 3, 49, 47, 32, 13, 30, 5, 43, 5, 30, 2, 36, 4, 8, 1, 5, 42, 158, 18, 36, 4, 36, 4, 40, + 8, 52, 12, 11, 1, 15, 1, 7, 1, 2, 1, 11, 1, 15, 1, 7, 1, 2, 3, 52, 12, 0, 9, 22, 10, 8, 24, + 6, 1, 42, 1, 9, 69, 6, 2, 1, 1, 44, 1, 2, 3, 1, 2, 23, 10, 23, 9, 31, 65, 19, 1, 2, 10, 22, + 10, 26, 70, 56, 6, 2, 64, 4, 1, 2, 5, 8, 1, 3, 1, 29, 42, 29, 3, 29, 35, 8, 1, 28, 27, 54, + 10, 22, 10, 19, 13, 18, 110, 73, 55, 51, 13, 51, 13, 40, 34, 28, 3, 1, 5, 23, 250, 42, 1, 2, + 3, 2, 16, 3, 55, 1, 3, 29, 10, 1, 8, 22, 42, 18, 46, 21, 27, 23, 9, 70, 43, 5, 10, 57, 9, 1, + 13, 25, 23, 51, 17, 4, 8, 35, 3, 1, 9, 64, 1, 4, 9, 2, 10, 1, 1, 1, 35, 18, 1, 34, 2, 1, 6, + 4, 62, 7, 1, 1, 1, 4, 1, 15, 1, 10, 7, 57, 23, 4, 1, 8, 2, 2, 2, 22, 1, 7, 1, 2, 1, 5, 3, 8, + 2, 2, 2, 2, 3, 1, 6, 1, 5, 7, 28, 10, 1, 1, 2, 1, 1, 38, 1, 10, 1, 1, 2, 1, 1, 4, 1, 2, 3, + 1, 1, 1, 44, 66, 1, 3, 1, 4, 20, 3, 30, 66, 2, 2, 1, 1, 184, 54, 2, 7, 25, 6, 34, 63, 1, 1, + 3, 1, 59, 54, 2, 1, 71, 27, 2, 14, 21, 7, 185, 57, 103, 64, 31, 8, 2, 1, 2, 8, 1, 2, 1, 30, + 1, 2, 2, 2, 2, 4, 93, 8, 2, 46, 2, 6, 1, 1, 1, 2, 27, 51, 2, 10, 17, 72, 5, 1, 18, 73, 199, + 33, 31, 9, 1, 45, 1, 7, 1, 1, 49, 30, 2, 22, 1, 14, 73, 7, 1, 2, 1, 44, 3, 1, 1, 2, 1, 3, 1, + 1, 2, 2, 24, 6, 1, 2, 1, 37, 1, 2, 1, 4, 1, 1, 0, 23, 9, 17, 1, 41, 3, 3, 111, 1, 79, 0, + 102, 111, 17, 196, 0, 97, 15, 0, 17, 6, 25, 0, 5, 0, 0, 47, 0, 0, 7, 31, 17, 79, 17, 30, 18, + 48, 16, 4, 31, 21, 5, 19, 0, 45, 211, 64, 128, 75, 4, 57, 7, 17, 64, 2, 1, 1, 12, 2, 14, 0, + 8, 0, 41, 10, 0, 4, 1, 7, 1, 2, 1, 0, 15, 1, 29, 3, 2, 1, 14, 4, 8, 0, 0, 107, 5, 13, 3, 9, + 7, 10, 4, 1, 0, 85, 1, 71, 1, 2, 2, 1, 2, 2, 2, 4, 1, 12, 1, 1, 1, 7, 1, 65, 1, 4, 2, 8, 1, + 7, 1, 28, 1, 4, 1, 5, 1, 1, 3, 7, 1, 0, 2, 25, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, + 25, 1, 31, 1, 25, 1, 8, 0, 31, 6, 6, 213, 7, 1, 17, 2, 7, 1, 2, 1, 5, 5, 62, 33, 1, 112, 45, + 10, 7, 16, 1, 0, 30, 18, 44, 0, 28, 228, 30, 2, 1, 0, 7, 1, 4, 1, 2, 1, 15, 1, 197, 59, 68, + 3, 1, 3, 1, 0, 4, 1, 27, 1, 2, 1, 1, 2, 1, 1, 10, 1, 4, 1, 1, 1, 1, 6, 1, 4, 1, 1, 1, 1, 1, + 1, 3, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 4, 1, 7, 1, 4, 1, 4, 1, 1, 1, + 10, 1, 17, 5, 3, 1, 5, 1, 17, 0, 26, 6, 26, 6, 26, 0, 0, 32, 0, 6, 222, 2, 0, 14, 0, 15, 0, + 0, 0, 0, 0, 5, 0, 0, ]; pub fn lookup(c: char) -> bool { super::skip_search( @@ -180,18 +182,18 @@ pub mod alphabetic { #[rustfmt::skip] pub mod case_ignorable { - static SHORT_OFFSET_RUNS: [u32; 35] = [ + static SHORT_OFFSET_RUNS: [u32; 37] = [ 688, 44045149, 572528402, 576724925, 807414908, 878718981, 903913493, 929080568, 933275148, 937491230, 1138818560, 1147208189, 1210124160, 1222707713, 1235291428, 1260457643, - 1264654383, 1499535675, 1507925040, 1566646003, 1629566000, 1650551536, 1658941263, - 1671540720, 1688321181, 1700908800, 1709298023, 1717688832, 1738661888, 1763828398, - 1797383403, 1805773008, 1809970171, 1819148289, 1824457200, + 1277237295, 1537284411, 1545673776, 1604394739, 1667314736, 1692492062, 1700883184, + 1709272384, 1721855823, 1730260976, 1747041437, 1759629056, 1768018279, 1776409088, + 1797382144, 1822548654, 1856103659, 1864493264, 1872884731, 1882062849, 1887371760, ]; - static OFFSETS: [u8; 875] = [ + static OFFSETS: [u8; 905] = [ 39, 1, 6, 1, 11, 1, 35, 1, 1, 1, 71, 1, 4, 1, 1, 1, 4, 1, 2, 2, 0, 192, 4, 2, 4, 1, 9, 2, 1, 1, 251, 7, 207, 1, 5, 1, 49, 45, 1, 1, 1, 2, 1, 2, 1, 1, 44, 1, 11, 6, 10, 11, 1, 1, 35, 1, 10, 21, 16, 1, 101, 8, 1, 10, 1, 4, 33, 1, 1, 1, 30, 27, 91, 11, 58, 11, 4, 1, 2, 1, 24, - 24, 43, 3, 44, 1, 7, 2, 6, 8, 41, 58, 55, 1, 1, 1, 4, 8, 4, 1, 3, 7, 10, 2, 13, 1, 15, 1, + 24, 43, 3, 44, 1, 7, 2, 5, 9, 41, 58, 55, 1, 1, 1, 4, 8, 4, 1, 3, 7, 10, 2, 13, 1, 15, 1, 58, 1, 4, 4, 8, 1, 20, 2, 26, 1, 2, 2, 57, 1, 4, 2, 4, 2, 2, 3, 3, 1, 30, 2, 3, 1, 11, 2, 57, 1, 4, 5, 1, 2, 4, 1, 20, 2, 22, 6, 1, 1, 58, 1, 2, 1, 1, 4, 8, 1, 7, 2, 11, 2, 30, 1, 61, 1, 12, 1, 50, 1, 3, 1, 55, 1, 1, 3, 5, 3, 1, 4, 7, 2, 11, 2, 29, 1, 58, 1, 2, 1, 6, 1, @@ -209,17 +211,18 @@ pub mod case_ignorable { 2, 2, 17, 1, 21, 2, 66, 6, 2, 2, 2, 2, 12, 1, 8, 1, 35, 1, 11, 1, 51, 1, 1, 3, 2, 2, 5, 2, 1, 1, 27, 1, 14, 2, 5, 2, 1, 1, 100, 5, 9, 3, 121, 1, 2, 1, 4, 1, 0, 1, 147, 17, 0, 16, 3, 1, 12, 16, 34, 1, 2, 1, 169, 1, 7, 1, 6, 1, 11, 1, 35, 1, 1, 1, 47, 1, 45, 2, 67, 1, 21, 3, - 0, 1, 226, 1, 149, 5, 0, 6, 1, 42, 1, 9, 0, 3, 1, 2, 5, 4, 40, 3, 4, 1, 165, 2, 0, 4, 0, 2, - 80, 3, 70, 11, 49, 4, 123, 1, 54, 15, 41, 1, 2, 2, 10, 3, 49, 4, 2, 2, 2, 1, 4, 1, 10, 1, - 50, 3, 36, 5, 1, 8, 62, 1, 12, 2, 52, 9, 10, 4, 2, 1, 95, 3, 2, 1, 1, 2, 6, 1, 2, 1, 157, 1, - 3, 8, 21, 2, 57, 2, 3, 1, 37, 7, 3, 5, 195, 8, 2, 3, 1, 1, 23, 1, 84, 6, 1, 1, 4, 2, 1, 2, - 238, 4, 6, 2, 1, 2, 27, 2, 85, 8, 2, 1, 1, 2, 106, 1, 1, 1, 2, 6, 1, 1, 101, 3, 2, 4, 1, 5, - 0, 9, 1, 2, 0, 2, 1, 1, 4, 1, 144, 4, 2, 2, 4, 1, 32, 10, 40, 6, 2, 4, 8, 1, 9, 6, 2, 3, 46, - 13, 1, 2, 0, 7, 1, 6, 1, 1, 82, 22, 2, 7, 1, 2, 1, 2, 122, 6, 3, 1, 1, 2, 1, 7, 1, 1, 72, 2, - 3, 1, 1, 1, 0, 2, 11, 2, 52, 5, 5, 1, 1, 1, 0, 17, 6, 15, 0, 5, 59, 7, 9, 4, 0, 1, 63, 17, - 64, 2, 1, 2, 0, 4, 1, 7, 1, 2, 0, 2, 1, 4, 0, 46, 2, 23, 0, 3, 9, 16, 2, 7, 30, 4, 148, 3, - 0, 55, 4, 50, 8, 1, 14, 1, 22, 5, 1, 15, 0, 7, 1, 17, 2, 7, 1, 2, 1, 5, 5, 62, 33, 1, 160, - 14, 0, 1, 61, 4, 0, 5, 0, 7, 109, 8, 0, 5, 0, 1, 30, 96, 128, 240, 0, + 0, 1, 226, 1, 149, 5, 0, 6, 1, 42, 1, 9, 0, 3, 1, 2, 5, 4, 40, 3, 4, 1, 165, 2, 0, 4, 38, 1, + 26, 5, 1, 1, 0, 2, 79, 4, 70, 11, 49, 4, 123, 1, 54, 15, 41, 1, 2, 2, 10, 3, 49, 4, 2, 2, 2, + 1, 4, 1, 10, 1, 50, 3, 36, 5, 1, 8, 62, 1, 12, 2, 52, 9, 10, 4, 2, 1, 95, 3, 2, 1, 1, 2, 6, + 1, 2, 1, 157, 1, 3, 8, 21, 2, 57, 2, 3, 1, 37, 7, 3, 5, 70, 6, 13, 1, 1, 1, 1, 1, 14, 2, 85, + 8, 2, 3, 1, 1, 23, 1, 84, 6, 1, 1, 4, 2, 1, 2, 238, 4, 6, 2, 1, 2, 27, 2, 85, 8, 2, 1, 1, 2, + 106, 1, 1, 1, 2, 6, 1, 1, 101, 1, 1, 1, 2, 4, 1, 5, 0, 9, 1, 2, 0, 2, 1, 1, 4, 1, 144, 4, 2, + 2, 4, 1, 32, 10, 40, 6, 2, 4, 8, 1, 9, 6, 2, 3, 46, 13, 1, 2, 0, 7, 1, 6, 1, 1, 82, 22, 2, + 7, 1, 2, 1, 2, 122, 6, 3, 1, 1, 2, 1, 7, 1, 1, 72, 2, 3, 1, 1, 1, 0, 2, 11, 2, 52, 5, 5, 1, + 1, 1, 23, 1, 0, 17, 6, 15, 0, 12, 3, 3, 0, 5, 59, 7, 9, 4, 0, 3, 40, 2, 0, 1, 63, 17, 64, 2, + 1, 2, 0, 4, 1, 7, 1, 2, 0, 2, 1, 4, 0, 46, 2, 23, 0, 3, 9, 16, 2, 7, 30, 4, 148, 3, 0, 55, + 4, 50, 8, 1, 14, 1, 22, 5, 1, 15, 0, 7, 1, 17, 2, 7, 1, 2, 1, 5, 5, 62, 33, 1, 160, 14, 0, + 1, 61, 4, 0, 5, 254, 2, 0, 7, 109, 8, 0, 5, 0, 1, 30, 96, 128, 240, 0, ]; pub fn lookup(c: char) -> bool { super::skip_search( @@ -234,22 +237,22 @@ pub mod case_ignorable { pub mod cased { static SHORT_OFFSET_RUNS: [u32; 22] = [ 4256, 115348384, 136322176, 144711446, 163587254, 320875520, 325101120, 350268208, - 392231680, 404815649, 413205504, 421595008, 467733632, 484513952, 492924480, 497144832, - 501339814, 578936576, 627171376, 639756544, 643952944, 649261450, + 392231680, 404815649, 413205504, 421595008, 467733632, 484513952, 501313088, 505533440, + 509728422, 587325184, 635559984, 648145152, 652341552, 657650058, ]; - static OFFSETS: [u8; 315] = [ + static OFFSETS: [u8; 319] = [ 65, 26, 6, 26, 47, 1, 10, 1, 4, 1, 5, 23, 1, 31, 1, 195, 1, 4, 4, 208, 1, 36, 7, 2, 30, 5, 96, 1, 42, 4, 2, 2, 2, 4, 1, 1, 6, 1, 1, 3, 1, 1, 1, 20, 1, 83, 1, 139, 8, 166, 1, 38, 9, - 41, 0, 38, 1, 1, 5, 1, 2, 43, 1, 4, 0, 86, 2, 6, 0, 9, 7, 43, 2, 3, 64, 192, 64, 0, 2, 6, 2, - 38, 2, 6, 2, 8, 1, 1, 1, 1, 1, 1, 1, 31, 2, 53, 1, 7, 1, 1, 3, 3, 1, 7, 3, 4, 2, 6, 4, 13, - 5, 3, 1, 7, 116, 1, 13, 1, 16, 13, 101, 1, 4, 1, 2, 10, 1, 1, 3, 5, 6, 1, 1, 1, 1, 1, 1, 4, - 1, 6, 4, 1, 2, 4, 5, 5, 4, 1, 17, 32, 3, 2, 0, 52, 0, 229, 6, 4, 3, 2, 12, 38, 1, 1, 5, 1, - 0, 46, 18, 30, 132, 102, 3, 4, 1, 59, 5, 2, 1, 1, 1, 5, 24, 5, 1, 3, 0, 43, 1, 14, 6, 80, 0, - 7, 12, 5, 0, 26, 6, 26, 0, 80, 96, 36, 4, 36, 116, 11, 1, 15, 1, 7, 1, 2, 1, 11, 1, 15, 1, - 7, 1, 2, 0, 1, 2, 3, 1, 42, 1, 9, 0, 51, 13, 51, 0, 64, 0, 64, 0, 85, 1, 71, 1, 2, 2, 1, 2, - 2, 2, 4, 1, 12, 1, 1, 1, 7, 1, 65, 1, 4, 2, 8, 1, 7, 1, 28, 1, 4, 1, 5, 1, 1, 3, 7, 1, 0, 2, - 25, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 8, 0, 10, 1, 20, 6, 6, - 0, 62, 0, 68, 0, 26, 6, 26, 6, 26, 0, + 41, 0, 38, 1, 1, 5, 1, 2, 43, 1, 4, 0, 86, 2, 6, 0, 11, 5, 43, 2, 3, 64, 192, 64, 0, 2, 6, + 2, 38, 2, 6, 2, 8, 1, 1, 1, 1, 1, 1, 1, 31, 2, 53, 1, 7, 1, 1, 3, 3, 1, 7, 3, 4, 2, 6, 4, + 13, 5, 3, 1, 7, 116, 1, 13, 1, 16, 13, 101, 1, 4, 1, 2, 10, 1, 1, 3, 5, 6, 1, 1, 1, 1, 1, 1, + 4, 1, 6, 4, 1, 2, 4, 5, 5, 4, 1, 17, 32, 3, 2, 0, 52, 0, 229, 6, 4, 3, 2, 12, 38, 1, 1, 5, + 1, 0, 46, 18, 30, 132, 102, 3, 4, 1, 62, 2, 2, 1, 1, 1, 8, 21, 5, 1, 3, 0, 43, 1, 14, 6, 80, + 0, 7, 12, 5, 0, 26, 6, 26, 0, 80, 96, 36, 4, 36, 116, 11, 1, 15, 1, 7, 1, 2, 1, 11, 1, 15, + 1, 7, 1, 2, 0, 1, 2, 3, 1, 42, 1, 9, 0, 51, 13, 51, 93, 22, 10, 22, 0, 64, 0, 64, 0, 85, 1, + 71, 1, 2, 2, 1, 2, 2, 2, 4, 1, 12, 1, 1, 1, 7, 1, 65, 1, 4, 2, 8, 1, 7, 1, 28, 1, 4, 1, 5, + 1, 1, 3, 7, 1, 0, 2, 25, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, + 8, 0, 10, 1, 20, 6, 6, 0, 62, 0, 68, 0, 26, 6, 26, 6, 26, 0, ]; pub fn lookup(c: char) -> bool { super::skip_search( @@ -279,41 +282,41 @@ pub mod cc { #[rustfmt::skip] pub mod grapheme_extend { - static SHORT_OFFSET_RUNS: [u32; 33] = [ - 768, 2098307, 6292881, 10490717, 522196754, 526393356, 731917551, 740306986, 752920175, - 761309186, 778107678, 908131840, 912326558, 920715773, 924912129, 937495844, 962662059, - 966858799, 1214323760, 1285627635, 1348547648, 1369533168, 1377922895, 1386331293, - 1398918912, 1403113829, 1411504640, 1440866304, 1466032814, 1495393516, 1503783120, - 1508769824, 1518273008, + static SHORT_OFFSET_RUNS: [u32; 34] = [ + 768, 2098307, 6292881, 10490717, 522196754, 526393356, 723528943, 731918378, 744531567, + 752920578, 769719070, 908131840, 912326558, 920715773, 924912129, 937495844, 962662059, + 971053103, 1256266800, 1323376371, 1386296384, 1407279390, 1415670512, 1424060239, + 1432468637, 1449250560, 1453445477, 1461836288, 1487003648, 1512170158, 1541530860, + 1549920464, 1559101472, 1568604656, ]; - static OFFSETS: [u8; 727] = [ + static OFFSETS: [u8; 751] = [ 0, 112, 0, 7, 0, 45, 1, 1, 1, 2, 1, 2, 1, 1, 72, 11, 48, 21, 16, 1, 101, 7, 2, 6, 2, 2, 1, - 4, 35, 1, 30, 27, 91, 11, 58, 9, 9, 1, 24, 4, 1, 9, 1, 3, 1, 5, 43, 3, 60, 8, 42, 24, 1, 32, + 4, 35, 1, 30, 27, 91, 11, 58, 9, 9, 1, 24, 4, 1, 9, 1, 3, 1, 5, 43, 3, 59, 9, 42, 24, 1, 32, 55, 1, 1, 1, 4, 8, 4, 1, 3, 7, 10, 2, 29, 1, 58, 1, 1, 1, 2, 4, 8, 1, 9, 1, 10, 2, 26, 1, 2, 2, 57, 1, 4, 2, 4, 2, 2, 3, 3, 1, 30, 2, 3, 1, 11, 2, 57, 1, 4, 5, 1, 2, 4, 1, 20, 2, 22, 6, 1, 1, 58, 1, 1, 2, 1, 4, 8, 1, 7, 3, 10, 2, 30, 1, 59, 1, 1, 1, 12, 1, 9, 1, 40, 1, 3, 1, - 55, 1, 1, 3, 5, 3, 1, 4, 7, 2, 11, 2, 29, 1, 58, 1, 2, 1, 2, 1, 3, 1, 5, 2, 7, 2, 11, 2, 28, + 55, 1, 1, 3, 5, 3, 1, 4, 7, 2, 11, 2, 29, 1, 58, 1, 2, 2, 1, 1, 3, 3, 1, 4, 7, 2, 11, 2, 28, 2, 57, 2, 1, 1, 2, 4, 8, 1, 9, 1, 10, 2, 29, 1, 72, 1, 4, 1, 2, 3, 1, 1, 8, 1, 81, 1, 2, 7, 12, 8, 98, 1, 2, 9, 11, 7, 73, 2, 27, 1, 1, 1, 1, 1, 55, 14, 1, 5, 1, 2, 5, 11, 1, 36, 9, 1, - 102, 4, 1, 6, 1, 2, 2, 2, 25, 2, 4, 3, 16, 4, 13, 1, 2, 2, 6, 1, 15, 1, 0, 3, 0, 3, 29, 2, - 30, 2, 30, 2, 64, 2, 1, 7, 8, 1, 2, 11, 9, 1, 45, 3, 1, 1, 117, 2, 34, 1, 118, 3, 4, 2, 9, - 1, 6, 3, 219, 2, 2, 1, 58, 1, 1, 7, 1, 1, 1, 1, 2, 8, 6, 10, 2, 1, 48, 31, 49, 4, 48, 7, 1, - 1, 5, 1, 40, 9, 12, 2, 32, 4, 2, 2, 1, 3, 56, 1, 1, 2, 3, 1, 1, 3, 58, 8, 2, 2, 152, 3, 1, - 13, 1, 7, 4, 1, 6, 1, 3, 2, 198, 64, 0, 1, 195, 33, 0, 3, 141, 1, 96, 32, 0, 6, 105, 2, 0, - 4, 1, 10, 32, 2, 80, 2, 0, 1, 3, 1, 4, 1, 25, 2, 5, 1, 151, 2, 26, 18, 13, 1, 38, 8, 25, 11, - 46, 3, 48, 1, 2, 4, 2, 2, 39, 1, 67, 6, 2, 2, 2, 2, 12, 1, 8, 1, 47, 1, 51, 1, 1, 3, 2, 2, - 5, 2, 1, 1, 42, 2, 8, 1, 238, 1, 2, 1, 4, 1, 0, 1, 0, 16, 16, 16, 0, 2, 0, 1, 226, 1, 149, - 5, 0, 3, 1, 2, 5, 4, 40, 3, 4, 1, 165, 2, 0, 4, 0, 2, 80, 3, 70, 11, 49, 4, 123, 1, 54, 15, - 41, 1, 2, 2, 10, 3, 49, 4, 2, 2, 7, 1, 61, 3, 36, 5, 1, 8, 62, 1, 12, 2, 52, 9, 10, 4, 2, 1, - 95, 3, 2, 1, 1, 2, 6, 1, 2, 1, 157, 1, 3, 8, 21, 2, 57, 2, 1, 1, 1, 1, 22, 1, 14, 7, 3, 5, - 195, 8, 2, 3, 1, 1, 23, 1, 81, 1, 2, 6, 1, 1, 2, 1, 1, 2, 1, 2, 235, 1, 2, 4, 6, 2, 1, 2, - 27, 2, 85, 8, 2, 1, 1, 2, 106, 1, 1, 1, 2, 6, 1, 1, 101, 3, 2, 4, 1, 5, 0, 9, 1, 2, 245, 1, - 10, 2, 1, 1, 4, 1, 144, 4, 2, 2, 4, 1, 32, 10, 40, 6, 2, 4, 8, 1, 9, 6, 2, 3, 46, 13, 1, 2, - 0, 7, 1, 6, 1, 1, 82, 22, 2, 7, 1, 2, 1, 2, 122, 6, 3, 1, 1, 2, 1, 7, 1, 1, 72, 2, 3, 1, 1, - 1, 0, 2, 11, 2, 52, 5, 5, 1, 1, 1, 0, 1, 6, 15, 0, 5, 59, 7, 0, 1, 63, 4, 81, 1, 0, 2, 0, - 46, 2, 23, 0, 1, 1, 3, 4, 5, 8, 8, 2, 7, 30, 4, 148, 3, 0, 55, 4, 50, 8, 1, 14, 1, 22, 5, 1, - 15, 0, 7, 1, 17, 2, 7, 1, 2, 1, 5, 100, 1, 160, 7, 0, 1, 61, 4, 0, 4, 0, 7, 109, 7, 0, 96, - 128, 240, 0, + 102, 4, 1, 6, 1, 2, 2, 2, 25, 2, 4, 3, 16, 4, 13, 1, 2, 2, 6, 1, 15, 1, 0, 3, 0, 4, 28, 3, + 29, 2, 30, 2, 64, 2, 1, 7, 8, 1, 2, 11, 9, 1, 45, 3, 1, 1, 117, 2, 34, 1, 118, 3, 4, 2, 9, + 1, 6, 3, 219, 2, 2, 1, 58, 1, 1, 7, 1, 1, 1, 1, 2, 8, 6, 10, 2, 1, 48, 31, 49, 4, 48, 10, 4, + 3, 38, 9, 12, 2, 32, 4, 2, 6, 56, 1, 1, 2, 3, 1, 1, 5, 56, 8, 2, 2, 152, 3, 1, 13, 1, 7, 4, + 1, 6, 1, 3, 2, 198, 64, 0, 1, 195, 33, 0, 3, 141, 1, 96, 32, 0, 6, 105, 2, 0, 4, 1, 10, 32, + 2, 80, 2, 0, 1, 3, 1, 4, 1, 25, 2, 5, 1, 151, 2, 26, 18, 13, 1, 38, 8, 25, 11, 1, 1, 44, 3, + 48, 1, 2, 4, 2, 2, 2, 1, 36, 1, 67, 6, 2, 2, 2, 2, 12, 1, 8, 1, 47, 1, 51, 1, 1, 3, 2, 2, 5, + 2, 1, 1, 42, 2, 8, 1, 238, 1, 2, 1, 4, 1, 0, 1, 0, 16, 16, 16, 0, 2, 0, 1, 226, 1, 149, 5, + 0, 3, 1, 2, 5, 4, 40, 3, 4, 1, 165, 2, 0, 4, 65, 5, 0, 2, 79, 4, 70, 11, 49, 4, 123, 1, 54, + 15, 41, 1, 2, 2, 10, 3, 49, 4, 2, 2, 7, 1, 61, 3, 36, 5, 1, 8, 62, 1, 12, 2, 52, 9, 1, 1, 8, + 4, 2, 1, 95, 3, 2, 4, 6, 1, 2, 1, 157, 1, 3, 8, 21, 2, 57, 2, 1, 1, 1, 1, 12, 1, 9, 1, 14, + 7, 3, 5, 67, 1, 2, 6, 1, 1, 2, 1, 1, 3, 4, 3, 1, 1, 14, 2, 85, 8, 2, 3, 1, 1, 23, 1, 81, 1, + 2, 6, 1, 1, 2, 1, 1, 2, 1, 2, 235, 1, 2, 4, 6, 2, 1, 2, 27, 2, 85, 8, 2, 1, 1, 2, 106, 1, 1, + 1, 2, 8, 101, 1, 1, 1, 2, 4, 1, 5, 0, 9, 1, 2, 245, 1, 10, 4, 4, 1, 144, 4, 2, 2, 4, 1, 32, + 10, 40, 6, 2, 4, 8, 1, 9, 6, 2, 3, 46, 13, 1, 2, 0, 7, 1, 6, 1, 1, 82, 22, 2, 7, 1, 2, 1, 2, + 122, 6, 3, 1, 1, 2, 1, 7, 1, 1, 72, 2, 3, 1, 1, 1, 0, 2, 11, 2, 52, 5, 5, 3, 23, 1, 0, 1, 6, + 15, 0, 12, 3, 3, 0, 5, 59, 7, 0, 1, 63, 4, 81, 1, 11, 2, 0, 2, 0, 46, 2, 23, 0, 5, 3, 6, 8, + 8, 2, 7, 30, 4, 148, 3, 0, 55, 4, 50, 8, 1, 14, 1, 22, 5, 1, 15, 0, 7, 1, 17, 2, 7, 1, 2, 1, + 5, 100, 1, 160, 7, 0, 1, 61, 4, 0, 4, 254, 2, 0, 7, 109, 7, 0, 96, 128, 240, 0, ]; #[inline] pub fn lookup(c: char) -> bool { @@ -339,27 +342,27 @@ pub mod lowercase { ]; const BITSET_INDEX_CHUNKS: &'static [[u8; 16]; 20] = &[ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 14, 55, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 14, 56, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 43, 0, 51, 47, 49, 33], - [0, 0, 0, 0, 10, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 43, 0, 52, 48, 50, 33], + [0, 0, 0, 0, 10, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 3, 0, 16, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27], - [0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 69, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 57, 0, 55, 55, 55, 0, 22, 22, 67, 22, 36, 25, 24, 37], - [0, 5, 68, 0, 29, 15, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 64, 34, 17, 23, 52, 53, 48, 46, 8, 35, 42, 0, 28, 13, 31], - [11, 58, 0, 6, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 32, 0], + [0, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 46, 0, 56, 56, 56, 0, 22, 22, 69, 22, 36, 25, 24, 37], + [0, 5, 70, 0, 29, 15, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 66, 34, 17, 23, 53, 54, 49, 47, 8, 35, 42, 0, 28, 13, 31], + [11, 60, 0, 6, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 32, 0], [16, 26, 22, 38, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [16, 50, 2, 21, 66, 9, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [16, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [63, 41, 54, 12, 75, 61, 18, 1, 7, 62, 74, 20, 71, 72, 4, 45], + [16, 51, 2, 21, 68, 9, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [16, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [65, 41, 55, 12, 77, 63, 18, 1, 7, 64, 76, 20, 73, 74, 4, 45], ]; - const BITSET_CANONICAL: &'static [u64; 55] = &[ + const BITSET_CANONICAL: &'static [u64; 56] = &[ 0b0000000000000000000000000000000000000000000000000000000000000000, 0b1111111111111111110000000000000000000000000011111111111111111111, 0b1010101010101010101010101010101010101010101010101010100000000010, @@ -393,7 +396,7 @@ pub mod lowercase { 0b0001101111111011111111111111101111111111100000000000000000000000, 0b0001100100101111101010101010101010101010111000110111111111111111, 0b0000011111111101111111111111111111111111111111111111111110111001, - 0b0000011101011100000000000000000000000010101010100000010100001010, + 0b0000011101011100000000000000000000001010101010100010010100001010, 0b0000010000100000000001000000000000000000000000000000000000000000, 0b0000000111111111111111111111111111111111111011111111111111111111, 0b0000000011111111000000001111111100000000001111110000000011111111, @@ -406,6 +409,7 @@ pub mod lowercase { 0b0000000000000000000000000000000000111010101010101010101010101010, 0b0000000000000000000000000000000000000000111110000000000001111111, 0b0000000000000000000000000000000000000000000000000000101111110111, + 0b0000000000000000000000000000000000000000000000000000010111111111, 0b1001001111111010101010101010101010101010101010101010101010101010, 0b1001010111111111101010101010101010101010101010101010101010101010, 0b1010101000101001101010101010101010110101010101010101001001000000, @@ -416,9 +420,9 @@ pub mod lowercase { 0b1110011001010001001011010010101001001110001001000011000100101001, 0b1110101111000000000000000000000000001111111111111111111111111100, ]; - const BITSET_MAPPING: &'static [(u8, u8); 21] = &[ - (0, 64), (1, 188), (1, 183), (1, 176), (1, 109), (1, 124), (1, 126), (1, 66), (1, 70), - (1, 77), (2, 146), (2, 144), (2, 83), (3, 93), (3, 147), (3, 133), (4, 12), (4, 6), + const BITSET_MAPPING: &'static [(u8, u8); 22] = &[ + (0, 64), (1, 188), (1, 186), (1, 183), (1, 176), (1, 109), (1, 124), (1, 126), (1, 66), + (1, 70), (1, 77), (2, 146), (2, 144), (2, 83), (3, 93), (3, 147), (3, 133), (4, 12), (4, 6), (5, 187), (6, 78), (7, 132), ]; @@ -436,14 +440,15 @@ pub mod lowercase { #[rustfmt::skip] pub mod n { - static SHORT_OFFSET_RUNS: [u32; 39] = [ + static SHORT_OFFSET_RUNS: [u32; 42] = [ 1632, 18876774, 31461440, 102765417, 111154926, 115349830, 132128880, 165684320, 186656630, 195046653, 199241735, 203436434, 216049184, 241215536, 249605104, 274792208, 278987015, - 283181793, 295766104, 320933114, 383848032, 392238160, 434181712, 442570976, 455154768, - 463544144, 476128256, 484534880, 488730240, 505533120, 509728718, 522314048, 526508784, - 530703600, 534898887, 539094129, 547483904, 568458224, 573766650, + 283181793, 295766104, 320933114, 383848032, 396432464, 438376016, 446765280, 463543280, + 471932752, 488711168, 497115440, 501312096, 505507184, 522284672, 526503152, 530698944, + 534894542, 547479872, 551674608, 555869424, 560064711, 568454257, 576844032, 597818352, + 603126778, ]; - static OFFSETS: [u8; 275] = [ + static OFFSETS: [u8; 289] = [ 48, 10, 120, 2, 5, 1, 2, 3, 0, 10, 134, 10, 198, 10, 0, 10, 118, 10, 4, 6, 108, 10, 118, 10, 118, 10, 2, 6, 110, 13, 115, 10, 8, 7, 103, 10, 104, 7, 7, 19, 109, 10, 96, 10, 118, 10, 70, 20, 0, 10, 70, 10, 0, 20, 0, 3, 239, 10, 6, 10, 22, 10, 0, 10, 128, 11, 165, 10, 6, 10, @@ -451,11 +456,11 @@ pub mod n { 1, 0, 1, 25, 9, 14, 3, 0, 4, 138, 10, 30, 8, 1, 15, 32, 10, 39, 15, 0, 10, 188, 10, 0, 6, 154, 10, 38, 10, 198, 10, 22, 10, 86, 10, 0, 10, 0, 10, 0, 45, 12, 57, 17, 2, 0, 27, 36, 4, 29, 1, 8, 1, 134, 5, 202, 10, 0, 8, 25, 7, 39, 9, 75, 5, 22, 6, 160, 2, 2, 16, 2, 46, 64, 9, - 52, 2, 30, 3, 75, 5, 104, 8, 24, 8, 41, 7, 0, 6, 48, 10, 0, 31, 158, 10, 42, 4, 112, 7, 134, - 30, 128, 10, 60, 10, 144, 10, 7, 20, 251, 10, 0, 10, 118, 10, 0, 10, 102, 10, 102, 12, 0, - 19, 93, 10, 0, 29, 227, 10, 70, 10, 0, 10, 102, 21, 0, 111, 0, 10, 86, 10, 134, 10, 1, 7, 0, - 23, 0, 20, 12, 20, 108, 25, 0, 50, 0, 10, 0, 10, 0, 10, 0, 9, 128, 10, 0, 59, 1, 3, 1, 4, - 76, 45, 1, 15, 0, 13, 0, 10, 0, + 52, 2, 30, 3, 75, 5, 104, 8, 24, 8, 41, 7, 0, 6, 48, 10, 6, 10, 0, 31, 158, 10, 42, 4, 112, + 7, 134, 30, 128, 10, 60, 10, 144, 10, 7, 20, 251, 10, 0, 10, 118, 10, 0, 10, 102, 10, 6, 20, + 76, 12, 0, 19, 93, 10, 0, 10, 86, 29, 227, 10, 70, 10, 0, 10, 102, 21, 0, 111, 0, 10, 0, 10, + 86, 10, 134, 10, 1, 7, 0, 10, 0, 23, 0, 10, 0, 20, 12, 20, 108, 25, 0, 50, 0, 10, 0, 10, 0, + 10, 247, 10, 0, 9, 128, 10, 0, 59, 1, 3, 1, 4, 76, 45, 1, 15, 0, 13, 0, 10, 0, ]; pub fn lookup(c: char) -> bool { super::skip_search( @@ -476,30 +481,30 @@ pub mod uppercase { 6, 6, 9, 6, 3, ]; const BITSET_INDEX_CHUNKS: &'static [[u8; 16]; 17] = &[ - [43, 43, 5, 34, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 5, 1], - [43, 43, 5, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43], - [43, 43, 39, 43, 43, 43, 43, 43, 17, 17, 62, 17, 42, 29, 24, 23], - [43, 43, 43, 43, 9, 8, 44, 43, 43, 43, 43, 43, 43, 43, 43, 43], - [43, 43, 43, 43, 36, 28, 66, 43, 43, 43, 43, 43, 43, 43, 43, 43], - [43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 0, 43, 43, 43], - [43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43], - [43, 43, 43, 43, 43, 43, 43, 43, 43, 54, 43, 43, 43, 43, 43, 43], - [43, 43, 43, 43, 43, 43, 43, 43, 43, 61, 60, 43, 20, 14, 16, 4], - [43, 43, 43, 43, 55, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43], - [43, 43, 58, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43], - [43, 43, 59, 45, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43], - [43, 48, 43, 31, 35, 21, 22, 15, 13, 33, 43, 43, 43, 11, 30, 38], - [51, 53, 26, 49, 12, 7, 25, 50, 40, 52, 6, 3, 65, 64, 63, 67], - [56, 43, 9, 46, 43, 41, 32, 43, 43, 43, 43, 43, 43, 43, 43, 43], - [57, 19, 2, 18, 10, 47, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43], - [57, 37, 17, 27, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43], + [44, 44, 5, 35, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 5, 1], + [44, 44, 5, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44], + [44, 44, 40, 44, 44, 44, 44, 44, 17, 17, 63, 17, 43, 29, 24, 23], + [44, 44, 44, 44, 9, 8, 45, 44, 44, 44, 44, 44, 44, 44, 44, 44], + [44, 44, 44, 44, 37, 28, 67, 44, 44, 44, 44, 44, 44, 44, 44, 44], + [44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 0, 44, 44, 44], + [44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44], + [44, 44, 44, 44, 44, 44, 44, 44, 44, 55, 44, 44, 44, 44, 44, 44], + [44, 44, 44, 44, 44, 44, 44, 44, 44, 62, 61, 44, 20, 14, 16, 4], + [44, 44, 44, 44, 56, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44], + [44, 44, 59, 44, 44, 31, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44], + [44, 44, 60, 46, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44], + [44, 49, 44, 32, 36, 21, 22, 15, 13, 34, 44, 44, 44, 11, 30, 39], + [52, 54, 26, 50, 12, 7, 25, 51, 41, 53, 6, 3, 66, 65, 64, 68], + [57, 44, 9, 47, 44, 42, 33, 44, 44, 44, 44, 44, 44, 44, 44, 44], + [58, 19, 2, 18, 10, 48, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44], + [58, 38, 17, 27, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44], ]; - const BITSET_CANONICAL: &'static [u64; 43] = &[ + const BITSET_CANONICAL: &'static [u64; 44] = &[ 0b0000011111111111111111111111111000000000000000000000000000000000, 0b0000000000111111111111111111111111111111111111111111111111111111, 0b0101010101010101010101010101010101010101010101010101010000000001, 0b0000011111111111111111111111110000000000000000000000000000000001, - 0b0000000000100000000000000000000000000001010000010000001011110101, + 0b0000000000100000000000000000000000010101010000010001101011110101, 0b1111111111111111111111111111111100000000000000000000000000000000, 0b1111111111111111111111110000000000000000000000000000001111111111, 0b1111111111111111111100000000000000000000000000011111110001011111, @@ -526,6 +531,7 @@ pub mod uppercase { 0b0000000000000000111111111111111100000000000000000000000000100000, 0b0000000000000000111111110000000010101010000000000011111100000000, 0b0000000000000000000011111111101111111111111111101101011101000000, + 0b0000000000000000000000000011111111111111111111110000000000000000, 0b0000000000000000000000000000000001111111011111111111111111111111, 0b0000000000000000000000000000000000000000001101111111011111111111, 0b0000000000000000000000000000000000000000000000000101010101111010, @@ -534,7 +540,7 @@ pub mod uppercase { 0b1100000000001111001111010101000000111110001001110011100010000100, 0b1100000000100101111010101001110100000000000000000000000000000000, 0b1110011010010000010101010101010101010101000111001000000000000000, - 0b1110011111111111111111111111111111111111111111110000000000000000, + 0b1110011111111111111111111111111111111111111111110000001000000000, 0b1111000000000000000000000000001111111111111111111111111100000000, 0b1111011111111111000000000000000000000000000000000000000000000000, 0b1111111100000000111111110000000000111111000000001111111100000000, @@ -751,216 +757,223 @@ pub mod conversions { ('\u{13ea}', 43962), ('\u{13eb}', 43963), ('\u{13ec}', 43964), ('\u{13ed}', 43965), ('\u{13ee}', 43966), ('\u{13ef}', 43967), ('\u{13f0}', 5112), ('\u{13f1}', 5113), ('\u{13f2}', 5114), ('\u{13f3}', 5115), ('\u{13f4}', 5116), ('\u{13f5}', 5117), - ('\u{1c90}', 4304), ('\u{1c91}', 4305), ('\u{1c92}', 4306), ('\u{1c93}', 4307), - ('\u{1c94}', 4308), ('\u{1c95}', 4309), ('\u{1c96}', 4310), ('\u{1c97}', 4311), - ('\u{1c98}', 4312), ('\u{1c99}', 4313), ('\u{1c9a}', 4314), ('\u{1c9b}', 4315), - ('\u{1c9c}', 4316), ('\u{1c9d}', 4317), ('\u{1c9e}', 4318), ('\u{1c9f}', 4319), - ('\u{1ca0}', 4320), ('\u{1ca1}', 4321), ('\u{1ca2}', 4322), ('\u{1ca3}', 4323), - ('\u{1ca4}', 4324), ('\u{1ca5}', 4325), ('\u{1ca6}', 4326), ('\u{1ca7}', 4327), - ('\u{1ca8}', 4328), ('\u{1ca9}', 4329), ('\u{1caa}', 4330), ('\u{1cab}', 4331), - ('\u{1cac}', 4332), ('\u{1cad}', 4333), ('\u{1cae}', 4334), ('\u{1caf}', 4335), - ('\u{1cb0}', 4336), ('\u{1cb1}', 4337), ('\u{1cb2}', 4338), ('\u{1cb3}', 4339), - ('\u{1cb4}', 4340), ('\u{1cb5}', 4341), ('\u{1cb6}', 4342), ('\u{1cb7}', 4343), - ('\u{1cb8}', 4344), ('\u{1cb9}', 4345), ('\u{1cba}', 4346), ('\u{1cbd}', 4349), - ('\u{1cbe}', 4350), ('\u{1cbf}', 4351), ('\u{1e00}', 7681), ('\u{1e02}', 7683), - ('\u{1e04}', 7685), ('\u{1e06}', 7687), ('\u{1e08}', 7689), ('\u{1e0a}', 7691), - ('\u{1e0c}', 7693), ('\u{1e0e}', 7695), ('\u{1e10}', 7697), ('\u{1e12}', 7699), - ('\u{1e14}', 7701), ('\u{1e16}', 7703), ('\u{1e18}', 7705), ('\u{1e1a}', 7707), - ('\u{1e1c}', 7709), ('\u{1e1e}', 7711), ('\u{1e20}', 7713), ('\u{1e22}', 7715), - ('\u{1e24}', 7717), ('\u{1e26}', 7719), ('\u{1e28}', 7721), ('\u{1e2a}', 7723), - ('\u{1e2c}', 7725), ('\u{1e2e}', 7727), ('\u{1e30}', 7729), ('\u{1e32}', 7731), - ('\u{1e34}', 7733), ('\u{1e36}', 7735), ('\u{1e38}', 7737), ('\u{1e3a}', 7739), - ('\u{1e3c}', 7741), ('\u{1e3e}', 7743), ('\u{1e40}', 7745), ('\u{1e42}', 7747), - ('\u{1e44}', 7749), ('\u{1e46}', 7751), ('\u{1e48}', 7753), ('\u{1e4a}', 7755), - ('\u{1e4c}', 7757), ('\u{1e4e}', 7759), ('\u{1e50}', 7761), ('\u{1e52}', 7763), - ('\u{1e54}', 7765), ('\u{1e56}', 7767), ('\u{1e58}', 7769), ('\u{1e5a}', 7771), - ('\u{1e5c}', 7773), ('\u{1e5e}', 7775), ('\u{1e60}', 7777), ('\u{1e62}', 7779), - ('\u{1e64}', 7781), ('\u{1e66}', 7783), ('\u{1e68}', 7785), ('\u{1e6a}', 7787), - ('\u{1e6c}', 7789), ('\u{1e6e}', 7791), ('\u{1e70}', 7793), ('\u{1e72}', 7795), - ('\u{1e74}', 7797), ('\u{1e76}', 7799), ('\u{1e78}', 7801), ('\u{1e7a}', 7803), - ('\u{1e7c}', 7805), ('\u{1e7e}', 7807), ('\u{1e80}', 7809), ('\u{1e82}', 7811), - ('\u{1e84}', 7813), ('\u{1e86}', 7815), ('\u{1e88}', 7817), ('\u{1e8a}', 7819), - ('\u{1e8c}', 7821), ('\u{1e8e}', 7823), ('\u{1e90}', 7825), ('\u{1e92}', 7827), - ('\u{1e94}', 7829), ('\u{1e9e}', 223), ('\u{1ea0}', 7841), ('\u{1ea2}', 7843), - ('\u{1ea4}', 7845), ('\u{1ea6}', 7847), ('\u{1ea8}', 7849), ('\u{1eaa}', 7851), - ('\u{1eac}', 7853), ('\u{1eae}', 7855), ('\u{1eb0}', 7857), ('\u{1eb2}', 7859), - ('\u{1eb4}', 7861), ('\u{1eb6}', 7863), ('\u{1eb8}', 7865), ('\u{1eba}', 7867), - ('\u{1ebc}', 7869), ('\u{1ebe}', 7871), ('\u{1ec0}', 7873), ('\u{1ec2}', 7875), - ('\u{1ec4}', 7877), ('\u{1ec6}', 7879), ('\u{1ec8}', 7881), ('\u{1eca}', 7883), - ('\u{1ecc}', 7885), ('\u{1ece}', 7887), ('\u{1ed0}', 7889), ('\u{1ed2}', 7891), - ('\u{1ed4}', 7893), ('\u{1ed6}', 7895), ('\u{1ed8}', 7897), ('\u{1eda}', 7899), - ('\u{1edc}', 7901), ('\u{1ede}', 7903), ('\u{1ee0}', 7905), ('\u{1ee2}', 7907), - ('\u{1ee4}', 7909), ('\u{1ee6}', 7911), ('\u{1ee8}', 7913), ('\u{1eea}', 7915), - ('\u{1eec}', 7917), ('\u{1eee}', 7919), ('\u{1ef0}', 7921), ('\u{1ef2}', 7923), - ('\u{1ef4}', 7925), ('\u{1ef6}', 7927), ('\u{1ef8}', 7929), ('\u{1efa}', 7931), - ('\u{1efc}', 7933), ('\u{1efe}', 7935), ('\u{1f08}', 7936), ('\u{1f09}', 7937), - ('\u{1f0a}', 7938), ('\u{1f0b}', 7939), ('\u{1f0c}', 7940), ('\u{1f0d}', 7941), - ('\u{1f0e}', 7942), ('\u{1f0f}', 7943), ('\u{1f18}', 7952), ('\u{1f19}', 7953), - ('\u{1f1a}', 7954), ('\u{1f1b}', 7955), ('\u{1f1c}', 7956), ('\u{1f1d}', 7957), - ('\u{1f28}', 7968), ('\u{1f29}', 7969), ('\u{1f2a}', 7970), ('\u{1f2b}', 7971), - ('\u{1f2c}', 7972), ('\u{1f2d}', 7973), ('\u{1f2e}', 7974), ('\u{1f2f}', 7975), - ('\u{1f38}', 7984), ('\u{1f39}', 7985), ('\u{1f3a}', 7986), ('\u{1f3b}', 7987), - ('\u{1f3c}', 7988), ('\u{1f3d}', 7989), ('\u{1f3e}', 7990), ('\u{1f3f}', 7991), - ('\u{1f48}', 8000), ('\u{1f49}', 8001), ('\u{1f4a}', 8002), ('\u{1f4b}', 8003), - ('\u{1f4c}', 8004), ('\u{1f4d}', 8005), ('\u{1f59}', 8017), ('\u{1f5b}', 8019), - ('\u{1f5d}', 8021), ('\u{1f5f}', 8023), ('\u{1f68}', 8032), ('\u{1f69}', 8033), - ('\u{1f6a}', 8034), ('\u{1f6b}', 8035), ('\u{1f6c}', 8036), ('\u{1f6d}', 8037), - ('\u{1f6e}', 8038), ('\u{1f6f}', 8039), ('\u{1f88}', 8064), ('\u{1f89}', 8065), - ('\u{1f8a}', 8066), ('\u{1f8b}', 8067), ('\u{1f8c}', 8068), ('\u{1f8d}', 8069), - ('\u{1f8e}', 8070), ('\u{1f8f}', 8071), ('\u{1f98}', 8080), ('\u{1f99}', 8081), - ('\u{1f9a}', 8082), ('\u{1f9b}', 8083), ('\u{1f9c}', 8084), ('\u{1f9d}', 8085), - ('\u{1f9e}', 8086), ('\u{1f9f}', 8087), ('\u{1fa8}', 8096), ('\u{1fa9}', 8097), - ('\u{1faa}', 8098), ('\u{1fab}', 8099), ('\u{1fac}', 8100), ('\u{1fad}', 8101), - ('\u{1fae}', 8102), ('\u{1faf}', 8103), ('\u{1fb8}', 8112), ('\u{1fb9}', 8113), - ('\u{1fba}', 8048), ('\u{1fbb}', 8049), ('\u{1fbc}', 8115), ('\u{1fc8}', 8050), - ('\u{1fc9}', 8051), ('\u{1fca}', 8052), ('\u{1fcb}', 8053), ('\u{1fcc}', 8131), - ('\u{1fd8}', 8144), ('\u{1fd9}', 8145), ('\u{1fda}', 8054), ('\u{1fdb}', 8055), - ('\u{1fe8}', 8160), ('\u{1fe9}', 8161), ('\u{1fea}', 8058), ('\u{1feb}', 8059), - ('\u{1fec}', 8165), ('\u{1ff8}', 8056), ('\u{1ff9}', 8057), ('\u{1ffa}', 8060), - ('\u{1ffb}', 8061), ('\u{1ffc}', 8179), ('\u{2126}', 969), ('\u{212a}', 107), - ('\u{212b}', 229), ('\u{2132}', 8526), ('\u{2160}', 8560), ('\u{2161}', 8561), - ('\u{2162}', 8562), ('\u{2163}', 8563), ('\u{2164}', 8564), ('\u{2165}', 8565), - ('\u{2166}', 8566), ('\u{2167}', 8567), ('\u{2168}', 8568), ('\u{2169}', 8569), - ('\u{216a}', 8570), ('\u{216b}', 8571), ('\u{216c}', 8572), ('\u{216d}', 8573), - ('\u{216e}', 8574), ('\u{216f}', 8575), ('\u{2183}', 8580), ('\u{24b6}', 9424), - ('\u{24b7}', 9425), ('\u{24b8}', 9426), ('\u{24b9}', 9427), ('\u{24ba}', 9428), - ('\u{24bb}', 9429), ('\u{24bc}', 9430), ('\u{24bd}', 9431), ('\u{24be}', 9432), - ('\u{24bf}', 9433), ('\u{24c0}', 9434), ('\u{24c1}', 9435), ('\u{24c2}', 9436), - ('\u{24c3}', 9437), ('\u{24c4}', 9438), ('\u{24c5}', 9439), ('\u{24c6}', 9440), - ('\u{24c7}', 9441), ('\u{24c8}', 9442), ('\u{24c9}', 9443), ('\u{24ca}', 9444), - ('\u{24cb}', 9445), ('\u{24cc}', 9446), ('\u{24cd}', 9447), ('\u{24ce}', 9448), - ('\u{24cf}', 9449), ('\u{2c00}', 11312), ('\u{2c01}', 11313), ('\u{2c02}', 11314), - ('\u{2c03}', 11315), ('\u{2c04}', 11316), ('\u{2c05}', 11317), ('\u{2c06}', 11318), - ('\u{2c07}', 11319), ('\u{2c08}', 11320), ('\u{2c09}', 11321), ('\u{2c0a}', 11322), - ('\u{2c0b}', 11323), ('\u{2c0c}', 11324), ('\u{2c0d}', 11325), ('\u{2c0e}', 11326), - ('\u{2c0f}', 11327), ('\u{2c10}', 11328), ('\u{2c11}', 11329), ('\u{2c12}', 11330), - ('\u{2c13}', 11331), ('\u{2c14}', 11332), ('\u{2c15}', 11333), ('\u{2c16}', 11334), - ('\u{2c17}', 11335), ('\u{2c18}', 11336), ('\u{2c19}', 11337), ('\u{2c1a}', 11338), - ('\u{2c1b}', 11339), ('\u{2c1c}', 11340), ('\u{2c1d}', 11341), ('\u{2c1e}', 11342), - ('\u{2c1f}', 11343), ('\u{2c20}', 11344), ('\u{2c21}', 11345), ('\u{2c22}', 11346), - ('\u{2c23}', 11347), ('\u{2c24}', 11348), ('\u{2c25}', 11349), ('\u{2c26}', 11350), - ('\u{2c27}', 11351), ('\u{2c28}', 11352), ('\u{2c29}', 11353), ('\u{2c2a}', 11354), - ('\u{2c2b}', 11355), ('\u{2c2c}', 11356), ('\u{2c2d}', 11357), ('\u{2c2e}', 11358), - ('\u{2c2f}', 11359), ('\u{2c60}', 11361), ('\u{2c62}', 619), ('\u{2c63}', 7549), - ('\u{2c64}', 637), ('\u{2c67}', 11368), ('\u{2c69}', 11370), ('\u{2c6b}', 11372), - ('\u{2c6d}', 593), ('\u{2c6e}', 625), ('\u{2c6f}', 592), ('\u{2c70}', 594), - ('\u{2c72}', 11379), ('\u{2c75}', 11382), ('\u{2c7e}', 575), ('\u{2c7f}', 576), - ('\u{2c80}', 11393), ('\u{2c82}', 11395), ('\u{2c84}', 11397), ('\u{2c86}', 11399), - ('\u{2c88}', 11401), ('\u{2c8a}', 11403), ('\u{2c8c}', 11405), ('\u{2c8e}', 11407), - ('\u{2c90}', 11409), ('\u{2c92}', 11411), ('\u{2c94}', 11413), ('\u{2c96}', 11415), - ('\u{2c98}', 11417), ('\u{2c9a}', 11419), ('\u{2c9c}', 11421), ('\u{2c9e}', 11423), - ('\u{2ca0}', 11425), ('\u{2ca2}', 11427), ('\u{2ca4}', 11429), ('\u{2ca6}', 11431), - ('\u{2ca8}', 11433), ('\u{2caa}', 11435), ('\u{2cac}', 11437), ('\u{2cae}', 11439), - ('\u{2cb0}', 11441), ('\u{2cb2}', 11443), ('\u{2cb4}', 11445), ('\u{2cb6}', 11447), - ('\u{2cb8}', 11449), ('\u{2cba}', 11451), ('\u{2cbc}', 11453), ('\u{2cbe}', 11455), - ('\u{2cc0}', 11457), ('\u{2cc2}', 11459), ('\u{2cc4}', 11461), ('\u{2cc6}', 11463), - ('\u{2cc8}', 11465), ('\u{2cca}', 11467), ('\u{2ccc}', 11469), ('\u{2cce}', 11471), - ('\u{2cd0}', 11473), ('\u{2cd2}', 11475), ('\u{2cd4}', 11477), ('\u{2cd6}', 11479), - ('\u{2cd8}', 11481), ('\u{2cda}', 11483), ('\u{2cdc}', 11485), ('\u{2cde}', 11487), - ('\u{2ce0}', 11489), ('\u{2ce2}', 11491), ('\u{2ceb}', 11500), ('\u{2ced}', 11502), - ('\u{2cf2}', 11507), ('\u{a640}', 42561), ('\u{a642}', 42563), ('\u{a644}', 42565), - ('\u{a646}', 42567), ('\u{a648}', 42569), ('\u{a64a}', 42571), ('\u{a64c}', 42573), - ('\u{a64e}', 42575), ('\u{a650}', 42577), ('\u{a652}', 42579), ('\u{a654}', 42581), - ('\u{a656}', 42583), ('\u{a658}', 42585), ('\u{a65a}', 42587), ('\u{a65c}', 42589), - ('\u{a65e}', 42591), ('\u{a660}', 42593), ('\u{a662}', 42595), ('\u{a664}', 42597), - ('\u{a666}', 42599), ('\u{a668}', 42601), ('\u{a66a}', 42603), ('\u{a66c}', 42605), - ('\u{a680}', 42625), ('\u{a682}', 42627), ('\u{a684}', 42629), ('\u{a686}', 42631), - ('\u{a688}', 42633), ('\u{a68a}', 42635), ('\u{a68c}', 42637), ('\u{a68e}', 42639), - ('\u{a690}', 42641), ('\u{a692}', 42643), ('\u{a694}', 42645), ('\u{a696}', 42647), - ('\u{a698}', 42649), ('\u{a69a}', 42651), ('\u{a722}', 42787), ('\u{a724}', 42789), - ('\u{a726}', 42791), ('\u{a728}', 42793), ('\u{a72a}', 42795), ('\u{a72c}', 42797), - ('\u{a72e}', 42799), ('\u{a732}', 42803), ('\u{a734}', 42805), ('\u{a736}', 42807), - ('\u{a738}', 42809), ('\u{a73a}', 42811), ('\u{a73c}', 42813), ('\u{a73e}', 42815), - ('\u{a740}', 42817), ('\u{a742}', 42819), ('\u{a744}', 42821), ('\u{a746}', 42823), - ('\u{a748}', 42825), ('\u{a74a}', 42827), ('\u{a74c}', 42829), ('\u{a74e}', 42831), - ('\u{a750}', 42833), ('\u{a752}', 42835), ('\u{a754}', 42837), ('\u{a756}', 42839), - ('\u{a758}', 42841), ('\u{a75a}', 42843), ('\u{a75c}', 42845), ('\u{a75e}', 42847), - ('\u{a760}', 42849), ('\u{a762}', 42851), ('\u{a764}', 42853), ('\u{a766}', 42855), - ('\u{a768}', 42857), ('\u{a76a}', 42859), ('\u{a76c}', 42861), ('\u{a76e}', 42863), - ('\u{a779}', 42874), ('\u{a77b}', 42876), ('\u{a77d}', 7545), ('\u{a77e}', 42879), - ('\u{a780}', 42881), ('\u{a782}', 42883), ('\u{a784}', 42885), ('\u{a786}', 42887), - ('\u{a78b}', 42892), ('\u{a78d}', 613), ('\u{a790}', 42897), ('\u{a792}', 42899), - ('\u{a796}', 42903), ('\u{a798}', 42905), ('\u{a79a}', 42907), ('\u{a79c}', 42909), - ('\u{a79e}', 42911), ('\u{a7a0}', 42913), ('\u{a7a2}', 42915), ('\u{a7a4}', 42917), - ('\u{a7a6}', 42919), ('\u{a7a8}', 42921), ('\u{a7aa}', 614), ('\u{a7ab}', 604), - ('\u{a7ac}', 609), ('\u{a7ad}', 620), ('\u{a7ae}', 618), ('\u{a7b0}', 670), - ('\u{a7b1}', 647), ('\u{a7b2}', 669), ('\u{a7b3}', 43859), ('\u{a7b4}', 42933), - ('\u{a7b6}', 42935), ('\u{a7b8}', 42937), ('\u{a7ba}', 42939), ('\u{a7bc}', 42941), - ('\u{a7be}', 42943), ('\u{a7c0}', 42945), ('\u{a7c2}', 42947), ('\u{a7c4}', 42900), - ('\u{a7c5}', 642), ('\u{a7c6}', 7566), ('\u{a7c7}', 42952), ('\u{a7c9}', 42954), - ('\u{a7d0}', 42961), ('\u{a7d6}', 42967), ('\u{a7d8}', 42969), ('\u{a7f5}', 42998), - ('\u{ff21}', 65345), ('\u{ff22}', 65346), ('\u{ff23}', 65347), ('\u{ff24}', 65348), - ('\u{ff25}', 65349), ('\u{ff26}', 65350), ('\u{ff27}', 65351), ('\u{ff28}', 65352), - ('\u{ff29}', 65353), ('\u{ff2a}', 65354), ('\u{ff2b}', 65355), ('\u{ff2c}', 65356), - ('\u{ff2d}', 65357), ('\u{ff2e}', 65358), ('\u{ff2f}', 65359), ('\u{ff30}', 65360), - ('\u{ff31}', 65361), ('\u{ff32}', 65362), ('\u{ff33}', 65363), ('\u{ff34}', 65364), - ('\u{ff35}', 65365), ('\u{ff36}', 65366), ('\u{ff37}', 65367), ('\u{ff38}', 65368), - ('\u{ff39}', 65369), ('\u{ff3a}', 65370), ('\u{10400}', 66600), ('\u{10401}', 66601), - ('\u{10402}', 66602), ('\u{10403}', 66603), ('\u{10404}', 66604), ('\u{10405}', 66605), - ('\u{10406}', 66606), ('\u{10407}', 66607), ('\u{10408}', 66608), ('\u{10409}', 66609), - ('\u{1040a}', 66610), ('\u{1040b}', 66611), ('\u{1040c}', 66612), ('\u{1040d}', 66613), - ('\u{1040e}', 66614), ('\u{1040f}', 66615), ('\u{10410}', 66616), ('\u{10411}', 66617), - ('\u{10412}', 66618), ('\u{10413}', 66619), ('\u{10414}', 66620), ('\u{10415}', 66621), - ('\u{10416}', 66622), ('\u{10417}', 66623), ('\u{10418}', 66624), ('\u{10419}', 66625), - ('\u{1041a}', 66626), ('\u{1041b}', 66627), ('\u{1041c}', 66628), ('\u{1041d}', 66629), - ('\u{1041e}', 66630), ('\u{1041f}', 66631), ('\u{10420}', 66632), ('\u{10421}', 66633), - ('\u{10422}', 66634), ('\u{10423}', 66635), ('\u{10424}', 66636), ('\u{10425}', 66637), - ('\u{10426}', 66638), ('\u{10427}', 66639), ('\u{104b0}', 66776), ('\u{104b1}', 66777), - ('\u{104b2}', 66778), ('\u{104b3}', 66779), ('\u{104b4}', 66780), ('\u{104b5}', 66781), - ('\u{104b6}', 66782), ('\u{104b7}', 66783), ('\u{104b8}', 66784), ('\u{104b9}', 66785), - ('\u{104ba}', 66786), ('\u{104bb}', 66787), ('\u{104bc}', 66788), ('\u{104bd}', 66789), - ('\u{104be}', 66790), ('\u{104bf}', 66791), ('\u{104c0}', 66792), ('\u{104c1}', 66793), - ('\u{104c2}', 66794), ('\u{104c3}', 66795), ('\u{104c4}', 66796), ('\u{104c5}', 66797), - ('\u{104c6}', 66798), ('\u{104c7}', 66799), ('\u{104c8}', 66800), ('\u{104c9}', 66801), - ('\u{104ca}', 66802), ('\u{104cb}', 66803), ('\u{104cc}', 66804), ('\u{104cd}', 66805), - ('\u{104ce}', 66806), ('\u{104cf}', 66807), ('\u{104d0}', 66808), ('\u{104d1}', 66809), - ('\u{104d2}', 66810), ('\u{104d3}', 66811), ('\u{10570}', 66967), ('\u{10571}', 66968), - ('\u{10572}', 66969), ('\u{10573}', 66970), ('\u{10574}', 66971), ('\u{10575}', 66972), - ('\u{10576}', 66973), ('\u{10577}', 66974), ('\u{10578}', 66975), ('\u{10579}', 66976), - ('\u{1057a}', 66977), ('\u{1057c}', 66979), ('\u{1057d}', 66980), ('\u{1057e}', 66981), - ('\u{1057f}', 66982), ('\u{10580}', 66983), ('\u{10581}', 66984), ('\u{10582}', 66985), - ('\u{10583}', 66986), ('\u{10584}', 66987), ('\u{10585}', 66988), ('\u{10586}', 66989), - ('\u{10587}', 66990), ('\u{10588}', 66991), ('\u{10589}', 66992), ('\u{1058a}', 66993), - ('\u{1058c}', 66995), ('\u{1058d}', 66996), ('\u{1058e}', 66997), ('\u{1058f}', 66998), - ('\u{10590}', 66999), ('\u{10591}', 67000), ('\u{10592}', 67001), ('\u{10594}', 67003), - ('\u{10595}', 67004), ('\u{10c80}', 68800), ('\u{10c81}', 68801), ('\u{10c82}', 68802), - ('\u{10c83}', 68803), ('\u{10c84}', 68804), ('\u{10c85}', 68805), ('\u{10c86}', 68806), - ('\u{10c87}', 68807), ('\u{10c88}', 68808), ('\u{10c89}', 68809), ('\u{10c8a}', 68810), - ('\u{10c8b}', 68811), ('\u{10c8c}', 68812), ('\u{10c8d}', 68813), ('\u{10c8e}', 68814), - ('\u{10c8f}', 68815), ('\u{10c90}', 68816), ('\u{10c91}', 68817), ('\u{10c92}', 68818), - ('\u{10c93}', 68819), ('\u{10c94}', 68820), ('\u{10c95}', 68821), ('\u{10c96}', 68822), - ('\u{10c97}', 68823), ('\u{10c98}', 68824), ('\u{10c99}', 68825), ('\u{10c9a}', 68826), - ('\u{10c9b}', 68827), ('\u{10c9c}', 68828), ('\u{10c9d}', 68829), ('\u{10c9e}', 68830), - ('\u{10c9f}', 68831), ('\u{10ca0}', 68832), ('\u{10ca1}', 68833), ('\u{10ca2}', 68834), - ('\u{10ca3}', 68835), ('\u{10ca4}', 68836), ('\u{10ca5}', 68837), ('\u{10ca6}', 68838), - ('\u{10ca7}', 68839), ('\u{10ca8}', 68840), ('\u{10ca9}', 68841), ('\u{10caa}', 68842), - ('\u{10cab}', 68843), ('\u{10cac}', 68844), ('\u{10cad}', 68845), ('\u{10cae}', 68846), - ('\u{10caf}', 68847), ('\u{10cb0}', 68848), ('\u{10cb1}', 68849), ('\u{10cb2}', 68850), - ('\u{118a0}', 71872), ('\u{118a1}', 71873), ('\u{118a2}', 71874), ('\u{118a3}', 71875), - ('\u{118a4}', 71876), ('\u{118a5}', 71877), ('\u{118a6}', 71878), ('\u{118a7}', 71879), - ('\u{118a8}', 71880), ('\u{118a9}', 71881), ('\u{118aa}', 71882), ('\u{118ab}', 71883), - ('\u{118ac}', 71884), ('\u{118ad}', 71885), ('\u{118ae}', 71886), ('\u{118af}', 71887), - ('\u{118b0}', 71888), ('\u{118b1}', 71889), ('\u{118b2}', 71890), ('\u{118b3}', 71891), - ('\u{118b4}', 71892), ('\u{118b5}', 71893), ('\u{118b6}', 71894), ('\u{118b7}', 71895), - ('\u{118b8}', 71896), ('\u{118b9}', 71897), ('\u{118ba}', 71898), ('\u{118bb}', 71899), - ('\u{118bc}', 71900), ('\u{118bd}', 71901), ('\u{118be}', 71902), ('\u{118bf}', 71903), - ('\u{16e40}', 93792), ('\u{16e41}', 93793), ('\u{16e42}', 93794), ('\u{16e43}', 93795), - ('\u{16e44}', 93796), ('\u{16e45}', 93797), ('\u{16e46}', 93798), ('\u{16e47}', 93799), - ('\u{16e48}', 93800), ('\u{16e49}', 93801), ('\u{16e4a}', 93802), ('\u{16e4b}', 93803), - ('\u{16e4c}', 93804), ('\u{16e4d}', 93805), ('\u{16e4e}', 93806), ('\u{16e4f}', 93807), - ('\u{16e50}', 93808), ('\u{16e51}', 93809), ('\u{16e52}', 93810), ('\u{16e53}', 93811), - ('\u{16e54}', 93812), ('\u{16e55}', 93813), ('\u{16e56}', 93814), ('\u{16e57}', 93815), - ('\u{16e58}', 93816), ('\u{16e59}', 93817), ('\u{16e5a}', 93818), ('\u{16e5b}', 93819), - ('\u{16e5c}', 93820), ('\u{16e5d}', 93821), ('\u{16e5e}', 93822), ('\u{16e5f}', 93823), - ('\u{1e900}', 125218), ('\u{1e901}', 125219), ('\u{1e902}', 125220), ('\u{1e903}', 125221), - ('\u{1e904}', 125222), ('\u{1e905}', 125223), ('\u{1e906}', 125224), ('\u{1e907}', 125225), - ('\u{1e908}', 125226), ('\u{1e909}', 125227), ('\u{1e90a}', 125228), ('\u{1e90b}', 125229), - ('\u{1e90c}', 125230), ('\u{1e90d}', 125231), ('\u{1e90e}', 125232), ('\u{1e90f}', 125233), - ('\u{1e910}', 125234), ('\u{1e911}', 125235), ('\u{1e912}', 125236), ('\u{1e913}', 125237), - ('\u{1e914}', 125238), ('\u{1e915}', 125239), ('\u{1e916}', 125240), ('\u{1e917}', 125241), - ('\u{1e918}', 125242), ('\u{1e919}', 125243), ('\u{1e91a}', 125244), ('\u{1e91b}', 125245), - ('\u{1e91c}', 125246), ('\u{1e91d}', 125247), ('\u{1e91e}', 125248), ('\u{1e91f}', 125249), - ('\u{1e920}', 125250), ('\u{1e921}', 125251), + ('\u{1c89}', 7306), ('\u{1c90}', 4304), ('\u{1c91}', 4305), ('\u{1c92}', 4306), + ('\u{1c93}', 4307), ('\u{1c94}', 4308), ('\u{1c95}', 4309), ('\u{1c96}', 4310), + ('\u{1c97}', 4311), ('\u{1c98}', 4312), ('\u{1c99}', 4313), ('\u{1c9a}', 4314), + ('\u{1c9b}', 4315), ('\u{1c9c}', 4316), ('\u{1c9d}', 4317), ('\u{1c9e}', 4318), + ('\u{1c9f}', 4319), ('\u{1ca0}', 4320), ('\u{1ca1}', 4321), ('\u{1ca2}', 4322), + ('\u{1ca3}', 4323), ('\u{1ca4}', 4324), ('\u{1ca5}', 4325), ('\u{1ca6}', 4326), + ('\u{1ca7}', 4327), ('\u{1ca8}', 4328), ('\u{1ca9}', 4329), ('\u{1caa}', 4330), + ('\u{1cab}', 4331), ('\u{1cac}', 4332), ('\u{1cad}', 4333), ('\u{1cae}', 4334), + ('\u{1caf}', 4335), ('\u{1cb0}', 4336), ('\u{1cb1}', 4337), ('\u{1cb2}', 4338), + ('\u{1cb3}', 4339), ('\u{1cb4}', 4340), ('\u{1cb5}', 4341), ('\u{1cb6}', 4342), + ('\u{1cb7}', 4343), ('\u{1cb8}', 4344), ('\u{1cb9}', 4345), ('\u{1cba}', 4346), + ('\u{1cbd}', 4349), ('\u{1cbe}', 4350), ('\u{1cbf}', 4351), ('\u{1e00}', 7681), + ('\u{1e02}', 7683), ('\u{1e04}', 7685), ('\u{1e06}', 7687), ('\u{1e08}', 7689), + ('\u{1e0a}', 7691), ('\u{1e0c}', 7693), ('\u{1e0e}', 7695), ('\u{1e10}', 7697), + ('\u{1e12}', 7699), ('\u{1e14}', 7701), ('\u{1e16}', 7703), ('\u{1e18}', 7705), + ('\u{1e1a}', 7707), ('\u{1e1c}', 7709), ('\u{1e1e}', 7711), ('\u{1e20}', 7713), + ('\u{1e22}', 7715), ('\u{1e24}', 7717), ('\u{1e26}', 7719), ('\u{1e28}', 7721), + ('\u{1e2a}', 7723), ('\u{1e2c}', 7725), ('\u{1e2e}', 7727), ('\u{1e30}', 7729), + ('\u{1e32}', 7731), ('\u{1e34}', 7733), ('\u{1e36}', 7735), ('\u{1e38}', 7737), + ('\u{1e3a}', 7739), ('\u{1e3c}', 7741), ('\u{1e3e}', 7743), ('\u{1e40}', 7745), + ('\u{1e42}', 7747), ('\u{1e44}', 7749), ('\u{1e46}', 7751), ('\u{1e48}', 7753), + ('\u{1e4a}', 7755), ('\u{1e4c}', 7757), ('\u{1e4e}', 7759), ('\u{1e50}', 7761), + ('\u{1e52}', 7763), ('\u{1e54}', 7765), ('\u{1e56}', 7767), ('\u{1e58}', 7769), + ('\u{1e5a}', 7771), ('\u{1e5c}', 7773), ('\u{1e5e}', 7775), ('\u{1e60}', 7777), + ('\u{1e62}', 7779), ('\u{1e64}', 7781), ('\u{1e66}', 7783), ('\u{1e68}', 7785), + ('\u{1e6a}', 7787), ('\u{1e6c}', 7789), ('\u{1e6e}', 7791), ('\u{1e70}', 7793), + ('\u{1e72}', 7795), ('\u{1e74}', 7797), ('\u{1e76}', 7799), ('\u{1e78}', 7801), + ('\u{1e7a}', 7803), ('\u{1e7c}', 7805), ('\u{1e7e}', 7807), ('\u{1e80}', 7809), + ('\u{1e82}', 7811), ('\u{1e84}', 7813), ('\u{1e86}', 7815), ('\u{1e88}', 7817), + ('\u{1e8a}', 7819), ('\u{1e8c}', 7821), ('\u{1e8e}', 7823), ('\u{1e90}', 7825), + ('\u{1e92}', 7827), ('\u{1e94}', 7829), ('\u{1e9e}', 223), ('\u{1ea0}', 7841), + ('\u{1ea2}', 7843), ('\u{1ea4}', 7845), ('\u{1ea6}', 7847), ('\u{1ea8}', 7849), + ('\u{1eaa}', 7851), ('\u{1eac}', 7853), ('\u{1eae}', 7855), ('\u{1eb0}', 7857), + ('\u{1eb2}', 7859), ('\u{1eb4}', 7861), ('\u{1eb6}', 7863), ('\u{1eb8}', 7865), + ('\u{1eba}', 7867), ('\u{1ebc}', 7869), ('\u{1ebe}', 7871), ('\u{1ec0}', 7873), + ('\u{1ec2}', 7875), ('\u{1ec4}', 7877), ('\u{1ec6}', 7879), ('\u{1ec8}', 7881), + ('\u{1eca}', 7883), ('\u{1ecc}', 7885), ('\u{1ece}', 7887), ('\u{1ed0}', 7889), + ('\u{1ed2}', 7891), ('\u{1ed4}', 7893), ('\u{1ed6}', 7895), ('\u{1ed8}', 7897), + ('\u{1eda}', 7899), ('\u{1edc}', 7901), ('\u{1ede}', 7903), ('\u{1ee0}', 7905), + ('\u{1ee2}', 7907), ('\u{1ee4}', 7909), ('\u{1ee6}', 7911), ('\u{1ee8}', 7913), + ('\u{1eea}', 7915), ('\u{1eec}', 7917), ('\u{1eee}', 7919), ('\u{1ef0}', 7921), + ('\u{1ef2}', 7923), ('\u{1ef4}', 7925), ('\u{1ef6}', 7927), ('\u{1ef8}', 7929), + ('\u{1efa}', 7931), ('\u{1efc}', 7933), ('\u{1efe}', 7935), ('\u{1f08}', 7936), + ('\u{1f09}', 7937), ('\u{1f0a}', 7938), ('\u{1f0b}', 7939), ('\u{1f0c}', 7940), + ('\u{1f0d}', 7941), ('\u{1f0e}', 7942), ('\u{1f0f}', 7943), ('\u{1f18}', 7952), + ('\u{1f19}', 7953), ('\u{1f1a}', 7954), ('\u{1f1b}', 7955), ('\u{1f1c}', 7956), + ('\u{1f1d}', 7957), ('\u{1f28}', 7968), ('\u{1f29}', 7969), ('\u{1f2a}', 7970), + ('\u{1f2b}', 7971), ('\u{1f2c}', 7972), ('\u{1f2d}', 7973), ('\u{1f2e}', 7974), + ('\u{1f2f}', 7975), ('\u{1f38}', 7984), ('\u{1f39}', 7985), ('\u{1f3a}', 7986), + ('\u{1f3b}', 7987), ('\u{1f3c}', 7988), ('\u{1f3d}', 7989), ('\u{1f3e}', 7990), + ('\u{1f3f}', 7991), ('\u{1f48}', 8000), ('\u{1f49}', 8001), ('\u{1f4a}', 8002), + ('\u{1f4b}', 8003), ('\u{1f4c}', 8004), ('\u{1f4d}', 8005), ('\u{1f59}', 8017), + ('\u{1f5b}', 8019), ('\u{1f5d}', 8021), ('\u{1f5f}', 8023), ('\u{1f68}', 8032), + ('\u{1f69}', 8033), ('\u{1f6a}', 8034), ('\u{1f6b}', 8035), ('\u{1f6c}', 8036), + ('\u{1f6d}', 8037), ('\u{1f6e}', 8038), ('\u{1f6f}', 8039), ('\u{1f88}', 8064), + ('\u{1f89}', 8065), ('\u{1f8a}', 8066), ('\u{1f8b}', 8067), ('\u{1f8c}', 8068), + ('\u{1f8d}', 8069), ('\u{1f8e}', 8070), ('\u{1f8f}', 8071), ('\u{1f98}', 8080), + ('\u{1f99}', 8081), ('\u{1f9a}', 8082), ('\u{1f9b}', 8083), ('\u{1f9c}', 8084), + ('\u{1f9d}', 8085), ('\u{1f9e}', 8086), ('\u{1f9f}', 8087), ('\u{1fa8}', 8096), + ('\u{1fa9}', 8097), ('\u{1faa}', 8098), ('\u{1fab}', 8099), ('\u{1fac}', 8100), + ('\u{1fad}', 8101), ('\u{1fae}', 8102), ('\u{1faf}', 8103), ('\u{1fb8}', 8112), + ('\u{1fb9}', 8113), ('\u{1fba}', 8048), ('\u{1fbb}', 8049), ('\u{1fbc}', 8115), + ('\u{1fc8}', 8050), ('\u{1fc9}', 8051), ('\u{1fca}', 8052), ('\u{1fcb}', 8053), + ('\u{1fcc}', 8131), ('\u{1fd8}', 8144), ('\u{1fd9}', 8145), ('\u{1fda}', 8054), + ('\u{1fdb}', 8055), ('\u{1fe8}', 8160), ('\u{1fe9}', 8161), ('\u{1fea}', 8058), + ('\u{1feb}', 8059), ('\u{1fec}', 8165), ('\u{1ff8}', 8056), ('\u{1ff9}', 8057), + ('\u{1ffa}', 8060), ('\u{1ffb}', 8061), ('\u{1ffc}', 8179), ('\u{2126}', 969), + ('\u{212a}', 107), ('\u{212b}', 229), ('\u{2132}', 8526), ('\u{2160}', 8560), + ('\u{2161}', 8561), ('\u{2162}', 8562), ('\u{2163}', 8563), ('\u{2164}', 8564), + ('\u{2165}', 8565), ('\u{2166}', 8566), ('\u{2167}', 8567), ('\u{2168}', 8568), + ('\u{2169}', 8569), ('\u{216a}', 8570), ('\u{216b}', 8571), ('\u{216c}', 8572), + ('\u{216d}', 8573), ('\u{216e}', 8574), ('\u{216f}', 8575), ('\u{2183}', 8580), + ('\u{24b6}', 9424), ('\u{24b7}', 9425), ('\u{24b8}', 9426), ('\u{24b9}', 9427), + ('\u{24ba}', 9428), ('\u{24bb}', 9429), ('\u{24bc}', 9430), ('\u{24bd}', 9431), + ('\u{24be}', 9432), ('\u{24bf}', 9433), ('\u{24c0}', 9434), ('\u{24c1}', 9435), + ('\u{24c2}', 9436), ('\u{24c3}', 9437), ('\u{24c4}', 9438), ('\u{24c5}', 9439), + ('\u{24c6}', 9440), ('\u{24c7}', 9441), ('\u{24c8}', 9442), ('\u{24c9}', 9443), + ('\u{24ca}', 9444), ('\u{24cb}', 9445), ('\u{24cc}', 9446), ('\u{24cd}', 9447), + ('\u{24ce}', 9448), ('\u{24cf}', 9449), ('\u{2c00}', 11312), ('\u{2c01}', 11313), + ('\u{2c02}', 11314), ('\u{2c03}', 11315), ('\u{2c04}', 11316), ('\u{2c05}', 11317), + ('\u{2c06}', 11318), ('\u{2c07}', 11319), ('\u{2c08}', 11320), ('\u{2c09}', 11321), + ('\u{2c0a}', 11322), ('\u{2c0b}', 11323), ('\u{2c0c}', 11324), ('\u{2c0d}', 11325), + ('\u{2c0e}', 11326), ('\u{2c0f}', 11327), ('\u{2c10}', 11328), ('\u{2c11}', 11329), + ('\u{2c12}', 11330), ('\u{2c13}', 11331), ('\u{2c14}', 11332), ('\u{2c15}', 11333), + ('\u{2c16}', 11334), ('\u{2c17}', 11335), ('\u{2c18}', 11336), ('\u{2c19}', 11337), + ('\u{2c1a}', 11338), ('\u{2c1b}', 11339), ('\u{2c1c}', 11340), ('\u{2c1d}', 11341), + ('\u{2c1e}', 11342), ('\u{2c1f}', 11343), ('\u{2c20}', 11344), ('\u{2c21}', 11345), + ('\u{2c22}', 11346), ('\u{2c23}', 11347), ('\u{2c24}', 11348), ('\u{2c25}', 11349), + ('\u{2c26}', 11350), ('\u{2c27}', 11351), ('\u{2c28}', 11352), ('\u{2c29}', 11353), + ('\u{2c2a}', 11354), ('\u{2c2b}', 11355), ('\u{2c2c}', 11356), ('\u{2c2d}', 11357), + ('\u{2c2e}', 11358), ('\u{2c2f}', 11359), ('\u{2c60}', 11361), ('\u{2c62}', 619), + ('\u{2c63}', 7549), ('\u{2c64}', 637), ('\u{2c67}', 11368), ('\u{2c69}', 11370), + ('\u{2c6b}', 11372), ('\u{2c6d}', 593), ('\u{2c6e}', 625), ('\u{2c6f}', 592), + ('\u{2c70}', 594), ('\u{2c72}', 11379), ('\u{2c75}', 11382), ('\u{2c7e}', 575), + ('\u{2c7f}', 576), ('\u{2c80}', 11393), ('\u{2c82}', 11395), ('\u{2c84}', 11397), + ('\u{2c86}', 11399), ('\u{2c88}', 11401), ('\u{2c8a}', 11403), ('\u{2c8c}', 11405), + ('\u{2c8e}', 11407), ('\u{2c90}', 11409), ('\u{2c92}', 11411), ('\u{2c94}', 11413), + ('\u{2c96}', 11415), ('\u{2c98}', 11417), ('\u{2c9a}', 11419), ('\u{2c9c}', 11421), + ('\u{2c9e}', 11423), ('\u{2ca0}', 11425), ('\u{2ca2}', 11427), ('\u{2ca4}', 11429), + ('\u{2ca6}', 11431), ('\u{2ca8}', 11433), ('\u{2caa}', 11435), ('\u{2cac}', 11437), + ('\u{2cae}', 11439), ('\u{2cb0}', 11441), ('\u{2cb2}', 11443), ('\u{2cb4}', 11445), + ('\u{2cb6}', 11447), ('\u{2cb8}', 11449), ('\u{2cba}', 11451), ('\u{2cbc}', 11453), + ('\u{2cbe}', 11455), ('\u{2cc0}', 11457), ('\u{2cc2}', 11459), ('\u{2cc4}', 11461), + ('\u{2cc6}', 11463), ('\u{2cc8}', 11465), ('\u{2cca}', 11467), ('\u{2ccc}', 11469), + ('\u{2cce}', 11471), ('\u{2cd0}', 11473), ('\u{2cd2}', 11475), ('\u{2cd4}', 11477), + ('\u{2cd6}', 11479), ('\u{2cd8}', 11481), ('\u{2cda}', 11483), ('\u{2cdc}', 11485), + ('\u{2cde}', 11487), ('\u{2ce0}', 11489), ('\u{2ce2}', 11491), ('\u{2ceb}', 11500), + ('\u{2ced}', 11502), ('\u{2cf2}', 11507), ('\u{a640}', 42561), ('\u{a642}', 42563), + ('\u{a644}', 42565), ('\u{a646}', 42567), ('\u{a648}', 42569), ('\u{a64a}', 42571), + ('\u{a64c}', 42573), ('\u{a64e}', 42575), ('\u{a650}', 42577), ('\u{a652}', 42579), + ('\u{a654}', 42581), ('\u{a656}', 42583), ('\u{a658}', 42585), ('\u{a65a}', 42587), + ('\u{a65c}', 42589), ('\u{a65e}', 42591), ('\u{a660}', 42593), ('\u{a662}', 42595), + ('\u{a664}', 42597), ('\u{a666}', 42599), ('\u{a668}', 42601), ('\u{a66a}', 42603), + ('\u{a66c}', 42605), ('\u{a680}', 42625), ('\u{a682}', 42627), ('\u{a684}', 42629), + ('\u{a686}', 42631), ('\u{a688}', 42633), ('\u{a68a}', 42635), ('\u{a68c}', 42637), + ('\u{a68e}', 42639), ('\u{a690}', 42641), ('\u{a692}', 42643), ('\u{a694}', 42645), + ('\u{a696}', 42647), ('\u{a698}', 42649), ('\u{a69a}', 42651), ('\u{a722}', 42787), + ('\u{a724}', 42789), ('\u{a726}', 42791), ('\u{a728}', 42793), ('\u{a72a}', 42795), + ('\u{a72c}', 42797), ('\u{a72e}', 42799), ('\u{a732}', 42803), ('\u{a734}', 42805), + ('\u{a736}', 42807), ('\u{a738}', 42809), ('\u{a73a}', 42811), ('\u{a73c}', 42813), + ('\u{a73e}', 42815), ('\u{a740}', 42817), ('\u{a742}', 42819), ('\u{a744}', 42821), + ('\u{a746}', 42823), ('\u{a748}', 42825), ('\u{a74a}', 42827), ('\u{a74c}', 42829), + ('\u{a74e}', 42831), ('\u{a750}', 42833), ('\u{a752}', 42835), ('\u{a754}', 42837), + ('\u{a756}', 42839), ('\u{a758}', 42841), ('\u{a75a}', 42843), ('\u{a75c}', 42845), + ('\u{a75e}', 42847), ('\u{a760}', 42849), ('\u{a762}', 42851), ('\u{a764}', 42853), + ('\u{a766}', 42855), ('\u{a768}', 42857), ('\u{a76a}', 42859), ('\u{a76c}', 42861), + ('\u{a76e}', 42863), ('\u{a779}', 42874), ('\u{a77b}', 42876), ('\u{a77d}', 7545), + ('\u{a77e}', 42879), ('\u{a780}', 42881), ('\u{a782}', 42883), ('\u{a784}', 42885), + ('\u{a786}', 42887), ('\u{a78b}', 42892), ('\u{a78d}', 613), ('\u{a790}', 42897), + ('\u{a792}', 42899), ('\u{a796}', 42903), ('\u{a798}', 42905), ('\u{a79a}', 42907), + ('\u{a79c}', 42909), ('\u{a79e}', 42911), ('\u{a7a0}', 42913), ('\u{a7a2}', 42915), + ('\u{a7a4}', 42917), ('\u{a7a6}', 42919), ('\u{a7a8}', 42921), ('\u{a7aa}', 614), + ('\u{a7ab}', 604), ('\u{a7ac}', 609), ('\u{a7ad}', 620), ('\u{a7ae}', 618), + ('\u{a7b0}', 670), ('\u{a7b1}', 647), ('\u{a7b2}', 669), ('\u{a7b3}', 43859), + ('\u{a7b4}', 42933), ('\u{a7b6}', 42935), ('\u{a7b8}', 42937), ('\u{a7ba}', 42939), + ('\u{a7bc}', 42941), ('\u{a7be}', 42943), ('\u{a7c0}', 42945), ('\u{a7c2}', 42947), + ('\u{a7c4}', 42900), ('\u{a7c5}', 642), ('\u{a7c6}', 7566), ('\u{a7c7}', 42952), + ('\u{a7c9}', 42954), ('\u{a7cb}', 612), ('\u{a7cc}', 42957), ('\u{a7d0}', 42961), + ('\u{a7d6}', 42967), ('\u{a7d8}', 42969), ('\u{a7da}', 42971), ('\u{a7dc}', 411), + ('\u{a7f5}', 42998), ('\u{ff21}', 65345), ('\u{ff22}', 65346), ('\u{ff23}', 65347), + ('\u{ff24}', 65348), ('\u{ff25}', 65349), ('\u{ff26}', 65350), ('\u{ff27}', 65351), + ('\u{ff28}', 65352), ('\u{ff29}', 65353), ('\u{ff2a}', 65354), ('\u{ff2b}', 65355), + ('\u{ff2c}', 65356), ('\u{ff2d}', 65357), ('\u{ff2e}', 65358), ('\u{ff2f}', 65359), + ('\u{ff30}', 65360), ('\u{ff31}', 65361), ('\u{ff32}', 65362), ('\u{ff33}', 65363), + ('\u{ff34}', 65364), ('\u{ff35}', 65365), ('\u{ff36}', 65366), ('\u{ff37}', 65367), + ('\u{ff38}', 65368), ('\u{ff39}', 65369), ('\u{ff3a}', 65370), ('\u{10400}', 66600), + ('\u{10401}', 66601), ('\u{10402}', 66602), ('\u{10403}', 66603), ('\u{10404}', 66604), + ('\u{10405}', 66605), ('\u{10406}', 66606), ('\u{10407}', 66607), ('\u{10408}', 66608), + ('\u{10409}', 66609), ('\u{1040a}', 66610), ('\u{1040b}', 66611), ('\u{1040c}', 66612), + ('\u{1040d}', 66613), ('\u{1040e}', 66614), ('\u{1040f}', 66615), ('\u{10410}', 66616), + ('\u{10411}', 66617), ('\u{10412}', 66618), ('\u{10413}', 66619), ('\u{10414}', 66620), + ('\u{10415}', 66621), ('\u{10416}', 66622), ('\u{10417}', 66623), ('\u{10418}', 66624), + ('\u{10419}', 66625), ('\u{1041a}', 66626), ('\u{1041b}', 66627), ('\u{1041c}', 66628), + ('\u{1041d}', 66629), ('\u{1041e}', 66630), ('\u{1041f}', 66631), ('\u{10420}', 66632), + ('\u{10421}', 66633), ('\u{10422}', 66634), ('\u{10423}', 66635), ('\u{10424}', 66636), + ('\u{10425}', 66637), ('\u{10426}', 66638), ('\u{10427}', 66639), ('\u{104b0}', 66776), + ('\u{104b1}', 66777), ('\u{104b2}', 66778), ('\u{104b3}', 66779), ('\u{104b4}', 66780), + ('\u{104b5}', 66781), ('\u{104b6}', 66782), ('\u{104b7}', 66783), ('\u{104b8}', 66784), + ('\u{104b9}', 66785), ('\u{104ba}', 66786), ('\u{104bb}', 66787), ('\u{104bc}', 66788), + ('\u{104bd}', 66789), ('\u{104be}', 66790), ('\u{104bf}', 66791), ('\u{104c0}', 66792), + ('\u{104c1}', 66793), ('\u{104c2}', 66794), ('\u{104c3}', 66795), ('\u{104c4}', 66796), + ('\u{104c5}', 66797), ('\u{104c6}', 66798), ('\u{104c7}', 66799), ('\u{104c8}', 66800), + ('\u{104c9}', 66801), ('\u{104ca}', 66802), ('\u{104cb}', 66803), ('\u{104cc}', 66804), + ('\u{104cd}', 66805), ('\u{104ce}', 66806), ('\u{104cf}', 66807), ('\u{104d0}', 66808), + ('\u{104d1}', 66809), ('\u{104d2}', 66810), ('\u{104d3}', 66811), ('\u{10570}', 66967), + ('\u{10571}', 66968), ('\u{10572}', 66969), ('\u{10573}', 66970), ('\u{10574}', 66971), + ('\u{10575}', 66972), ('\u{10576}', 66973), ('\u{10577}', 66974), ('\u{10578}', 66975), + ('\u{10579}', 66976), ('\u{1057a}', 66977), ('\u{1057c}', 66979), ('\u{1057d}', 66980), + ('\u{1057e}', 66981), ('\u{1057f}', 66982), ('\u{10580}', 66983), ('\u{10581}', 66984), + ('\u{10582}', 66985), ('\u{10583}', 66986), ('\u{10584}', 66987), ('\u{10585}', 66988), + ('\u{10586}', 66989), ('\u{10587}', 66990), ('\u{10588}', 66991), ('\u{10589}', 66992), + ('\u{1058a}', 66993), ('\u{1058c}', 66995), ('\u{1058d}', 66996), ('\u{1058e}', 66997), + ('\u{1058f}', 66998), ('\u{10590}', 66999), ('\u{10591}', 67000), ('\u{10592}', 67001), + ('\u{10594}', 67003), ('\u{10595}', 67004), ('\u{10c80}', 68800), ('\u{10c81}', 68801), + ('\u{10c82}', 68802), ('\u{10c83}', 68803), ('\u{10c84}', 68804), ('\u{10c85}', 68805), + ('\u{10c86}', 68806), ('\u{10c87}', 68807), ('\u{10c88}', 68808), ('\u{10c89}', 68809), + ('\u{10c8a}', 68810), ('\u{10c8b}', 68811), ('\u{10c8c}', 68812), ('\u{10c8d}', 68813), + ('\u{10c8e}', 68814), ('\u{10c8f}', 68815), ('\u{10c90}', 68816), ('\u{10c91}', 68817), + ('\u{10c92}', 68818), ('\u{10c93}', 68819), ('\u{10c94}', 68820), ('\u{10c95}', 68821), + ('\u{10c96}', 68822), ('\u{10c97}', 68823), ('\u{10c98}', 68824), ('\u{10c99}', 68825), + ('\u{10c9a}', 68826), ('\u{10c9b}', 68827), ('\u{10c9c}', 68828), ('\u{10c9d}', 68829), + ('\u{10c9e}', 68830), ('\u{10c9f}', 68831), ('\u{10ca0}', 68832), ('\u{10ca1}', 68833), + ('\u{10ca2}', 68834), ('\u{10ca3}', 68835), ('\u{10ca4}', 68836), ('\u{10ca5}', 68837), + ('\u{10ca6}', 68838), ('\u{10ca7}', 68839), ('\u{10ca8}', 68840), ('\u{10ca9}', 68841), + ('\u{10caa}', 68842), ('\u{10cab}', 68843), ('\u{10cac}', 68844), ('\u{10cad}', 68845), + ('\u{10cae}', 68846), ('\u{10caf}', 68847), ('\u{10cb0}', 68848), ('\u{10cb1}', 68849), + ('\u{10cb2}', 68850), ('\u{10d50}', 68976), ('\u{10d51}', 68977), ('\u{10d52}', 68978), + ('\u{10d53}', 68979), ('\u{10d54}', 68980), ('\u{10d55}', 68981), ('\u{10d56}', 68982), + ('\u{10d57}', 68983), ('\u{10d58}', 68984), ('\u{10d59}', 68985), ('\u{10d5a}', 68986), + ('\u{10d5b}', 68987), ('\u{10d5c}', 68988), ('\u{10d5d}', 68989), ('\u{10d5e}', 68990), + ('\u{10d5f}', 68991), ('\u{10d60}', 68992), ('\u{10d61}', 68993), ('\u{10d62}', 68994), + ('\u{10d63}', 68995), ('\u{10d64}', 68996), ('\u{10d65}', 68997), ('\u{118a0}', 71872), + ('\u{118a1}', 71873), ('\u{118a2}', 71874), ('\u{118a3}', 71875), ('\u{118a4}', 71876), + ('\u{118a5}', 71877), ('\u{118a6}', 71878), ('\u{118a7}', 71879), ('\u{118a8}', 71880), + ('\u{118a9}', 71881), ('\u{118aa}', 71882), ('\u{118ab}', 71883), ('\u{118ac}', 71884), + ('\u{118ad}', 71885), ('\u{118ae}', 71886), ('\u{118af}', 71887), ('\u{118b0}', 71888), + ('\u{118b1}', 71889), ('\u{118b2}', 71890), ('\u{118b3}', 71891), ('\u{118b4}', 71892), + ('\u{118b5}', 71893), ('\u{118b6}', 71894), ('\u{118b7}', 71895), ('\u{118b8}', 71896), + ('\u{118b9}', 71897), ('\u{118ba}', 71898), ('\u{118bb}', 71899), ('\u{118bc}', 71900), + ('\u{118bd}', 71901), ('\u{118be}', 71902), ('\u{118bf}', 71903), ('\u{16e40}', 93792), + ('\u{16e41}', 93793), ('\u{16e42}', 93794), ('\u{16e43}', 93795), ('\u{16e44}', 93796), + ('\u{16e45}', 93797), ('\u{16e46}', 93798), ('\u{16e47}', 93799), ('\u{16e48}', 93800), + ('\u{16e49}', 93801), ('\u{16e4a}', 93802), ('\u{16e4b}', 93803), ('\u{16e4c}', 93804), + ('\u{16e4d}', 93805), ('\u{16e4e}', 93806), ('\u{16e4f}', 93807), ('\u{16e50}', 93808), + ('\u{16e51}', 93809), ('\u{16e52}', 93810), ('\u{16e53}', 93811), ('\u{16e54}', 93812), + ('\u{16e55}', 93813), ('\u{16e56}', 93814), ('\u{16e57}', 93815), ('\u{16e58}', 93816), + ('\u{16e59}', 93817), ('\u{16e5a}', 93818), ('\u{16e5b}', 93819), ('\u{16e5c}', 93820), + ('\u{16e5d}', 93821), ('\u{16e5e}', 93822), ('\u{16e5f}', 93823), ('\u{1e900}', 125218), + ('\u{1e901}', 125219), ('\u{1e902}', 125220), ('\u{1e903}', 125221), ('\u{1e904}', 125222), + ('\u{1e905}', 125223), ('\u{1e906}', 125224), ('\u{1e907}', 125225), ('\u{1e908}', 125226), + ('\u{1e909}', 125227), ('\u{1e90a}', 125228), ('\u{1e90b}', 125229), ('\u{1e90c}', 125230), + ('\u{1e90d}', 125231), ('\u{1e90e}', 125232), ('\u{1e90f}', 125233), ('\u{1e910}', 125234), + ('\u{1e911}', 125235), ('\u{1e912}', 125236), ('\u{1e913}', 125237), ('\u{1e914}', 125238), + ('\u{1e915}', 125239), ('\u{1e916}', 125240), ('\u{1e917}', 125241), ('\u{1e918}', 125242), + ('\u{1e919}', 125243), ('\u{1e91a}', 125244), ('\u{1e91b}', 125245), ('\u{1e91c}', 125246), + ('\u{1e91d}', 125247), ('\u{1e91e}', 125248), ('\u{1e91f}', 125249), ('\u{1e920}', 125250), + ('\u{1e921}', 125251), ]; static LOWERCASE_TABLE_MULTI: &[[char; 3]] = &[ @@ -989,14 +1002,14 @@ pub mod conversions { ('\u{16f}', 366), ('\u{171}', 368), ('\u{173}', 370), ('\u{175}', 372), ('\u{177}', 374), ('\u{17a}', 377), ('\u{17c}', 379), ('\u{17e}', 381), ('\u{17f}', 83), ('\u{180}', 579), ('\u{183}', 386), ('\u{185}', 388), ('\u{188}', 391), ('\u{18c}', 395), ('\u{192}', 401), - ('\u{195}', 502), ('\u{199}', 408), ('\u{19a}', 573), ('\u{19e}', 544), ('\u{1a1}', 416), - ('\u{1a3}', 418), ('\u{1a5}', 420), ('\u{1a8}', 423), ('\u{1ad}', 428), ('\u{1b0}', 431), - ('\u{1b4}', 435), ('\u{1b6}', 437), ('\u{1b9}', 440), ('\u{1bd}', 444), ('\u{1bf}', 503), - ('\u{1c5}', 452), ('\u{1c6}', 452), ('\u{1c8}', 455), ('\u{1c9}', 455), ('\u{1cb}', 458), - ('\u{1cc}', 458), ('\u{1ce}', 461), ('\u{1d0}', 463), ('\u{1d2}', 465), ('\u{1d4}', 467), - ('\u{1d6}', 469), ('\u{1d8}', 471), ('\u{1da}', 473), ('\u{1dc}', 475), ('\u{1dd}', 398), - ('\u{1df}', 478), ('\u{1e1}', 480), ('\u{1e3}', 482), ('\u{1e5}', 484), ('\u{1e7}', 486), - ('\u{1e9}', 488), ('\u{1eb}', 490), ('\u{1ed}', 492), ('\u{1ef}', 494), + ('\u{195}', 502), ('\u{199}', 408), ('\u{19a}', 573), ('\u{19b}', 42972), ('\u{19e}', 544), + ('\u{1a1}', 416), ('\u{1a3}', 418), ('\u{1a5}', 420), ('\u{1a8}', 423), ('\u{1ad}', 428), + ('\u{1b0}', 431), ('\u{1b4}', 435), ('\u{1b6}', 437), ('\u{1b9}', 440), ('\u{1bd}', 444), + ('\u{1bf}', 503), ('\u{1c5}', 452), ('\u{1c6}', 452), ('\u{1c8}', 455), ('\u{1c9}', 455), + ('\u{1cb}', 458), ('\u{1cc}', 458), ('\u{1ce}', 461), ('\u{1d0}', 463), ('\u{1d2}', 465), + ('\u{1d4}', 467), ('\u{1d6}', 469), ('\u{1d8}', 471), ('\u{1da}', 473), ('\u{1dc}', 475), + ('\u{1dd}', 398), ('\u{1df}', 478), ('\u{1e1}', 480), ('\u{1e3}', 482), ('\u{1e5}', 484), + ('\u{1e7}', 486), ('\u{1e9}', 488), ('\u{1eb}', 490), ('\u{1ed}', 492), ('\u{1ef}', 494), ('\u{1f0}', 4194306), ('\u{1f2}', 497), ('\u{1f3}', 497), ('\u{1f5}', 500), ('\u{1f9}', 504), ('\u{1fb}', 506), ('\u{1fd}', 508), ('\u{1ff}', 510), ('\u{201}', 512), ('\u{203}', 514), ('\u{205}', 516), ('\u{207}', 518), ('\u{209}', 520), ('\u{20b}', 522), @@ -1008,25 +1021,25 @@ pub mod conversions { ('\u{249}', 584), ('\u{24b}', 586), ('\u{24d}', 588), ('\u{24f}', 590), ('\u{250}', 11375), ('\u{251}', 11373), ('\u{252}', 11376), ('\u{253}', 385), ('\u{254}', 390), ('\u{256}', 393), ('\u{257}', 394), ('\u{259}', 399), ('\u{25b}', 400), ('\u{25c}', 42923), - ('\u{260}', 403), ('\u{261}', 42924), ('\u{263}', 404), ('\u{265}', 42893), - ('\u{266}', 42922), ('\u{268}', 407), ('\u{269}', 406), ('\u{26a}', 42926), - ('\u{26b}', 11362), ('\u{26c}', 42925), ('\u{26f}', 412), ('\u{271}', 11374), - ('\u{272}', 413), ('\u{275}', 415), ('\u{27d}', 11364), ('\u{280}', 422), - ('\u{282}', 42949), ('\u{283}', 425), ('\u{287}', 42929), ('\u{288}', 430), - ('\u{289}', 580), ('\u{28a}', 433), ('\u{28b}', 434), ('\u{28c}', 581), ('\u{292}', 439), - ('\u{29d}', 42930), ('\u{29e}', 42928), ('\u{345}', 921), ('\u{371}', 880), - ('\u{373}', 882), ('\u{377}', 886), ('\u{37b}', 1021), ('\u{37c}', 1022), ('\u{37d}', 1023), - ('\u{390}', 4194307), ('\u{3ac}', 902), ('\u{3ad}', 904), ('\u{3ae}', 905), - ('\u{3af}', 906), ('\u{3b0}', 4194308), ('\u{3b1}', 913), ('\u{3b2}', 914), - ('\u{3b3}', 915), ('\u{3b4}', 916), ('\u{3b5}', 917), ('\u{3b6}', 918), ('\u{3b7}', 919), - ('\u{3b8}', 920), ('\u{3b9}', 921), ('\u{3ba}', 922), ('\u{3bb}', 923), ('\u{3bc}', 924), - ('\u{3bd}', 925), ('\u{3be}', 926), ('\u{3bf}', 927), ('\u{3c0}', 928), ('\u{3c1}', 929), - ('\u{3c2}', 931), ('\u{3c3}', 931), ('\u{3c4}', 932), ('\u{3c5}', 933), ('\u{3c6}', 934), - ('\u{3c7}', 935), ('\u{3c8}', 936), ('\u{3c9}', 937), ('\u{3ca}', 938), ('\u{3cb}', 939), - ('\u{3cc}', 908), ('\u{3cd}', 910), ('\u{3ce}', 911), ('\u{3d0}', 914), ('\u{3d1}', 920), - ('\u{3d5}', 934), ('\u{3d6}', 928), ('\u{3d7}', 975), ('\u{3d9}', 984), ('\u{3db}', 986), - ('\u{3dd}', 988), ('\u{3df}', 990), ('\u{3e1}', 992), ('\u{3e3}', 994), ('\u{3e5}', 996), - ('\u{3e7}', 998), ('\u{3e9}', 1000), ('\u{3eb}', 1002), ('\u{3ed}', 1004), + ('\u{260}', 403), ('\u{261}', 42924), ('\u{263}', 404), ('\u{264}', 42955), + ('\u{265}', 42893), ('\u{266}', 42922), ('\u{268}', 407), ('\u{269}', 406), + ('\u{26a}', 42926), ('\u{26b}', 11362), ('\u{26c}', 42925), ('\u{26f}', 412), + ('\u{271}', 11374), ('\u{272}', 413), ('\u{275}', 415), ('\u{27d}', 11364), + ('\u{280}', 422), ('\u{282}', 42949), ('\u{283}', 425), ('\u{287}', 42929), + ('\u{288}', 430), ('\u{289}', 580), ('\u{28a}', 433), ('\u{28b}', 434), ('\u{28c}', 581), + ('\u{292}', 439), ('\u{29d}', 42930), ('\u{29e}', 42928), ('\u{345}', 921), + ('\u{371}', 880), ('\u{373}', 882), ('\u{377}', 886), ('\u{37b}', 1021), ('\u{37c}', 1022), + ('\u{37d}', 1023), ('\u{390}', 4194307), ('\u{3ac}', 902), ('\u{3ad}', 904), + ('\u{3ae}', 905), ('\u{3af}', 906), ('\u{3b0}', 4194308), ('\u{3b1}', 913), + ('\u{3b2}', 914), ('\u{3b3}', 915), ('\u{3b4}', 916), ('\u{3b5}', 917), ('\u{3b6}', 918), + ('\u{3b7}', 919), ('\u{3b8}', 920), ('\u{3b9}', 921), ('\u{3ba}', 922), ('\u{3bb}', 923), + ('\u{3bc}', 924), ('\u{3bd}', 925), ('\u{3be}', 926), ('\u{3bf}', 927), ('\u{3c0}', 928), + ('\u{3c1}', 929), ('\u{3c2}', 931), ('\u{3c3}', 931), ('\u{3c4}', 932), ('\u{3c5}', 933), + ('\u{3c6}', 934), ('\u{3c7}', 935), ('\u{3c8}', 936), ('\u{3c9}', 937), ('\u{3ca}', 938), + ('\u{3cb}', 939), ('\u{3cc}', 908), ('\u{3cd}', 910), ('\u{3ce}', 911), ('\u{3d0}', 914), + ('\u{3d1}', 920), ('\u{3d5}', 934), ('\u{3d6}', 928), ('\u{3d7}', 975), ('\u{3d9}', 984), + ('\u{3db}', 986), ('\u{3dd}', 988), ('\u{3df}', 990), ('\u{3e1}', 992), ('\u{3e3}', 994), + ('\u{3e5}', 996), ('\u{3e7}', 998), ('\u{3e9}', 1000), ('\u{3eb}', 1002), ('\u{3ed}', 1004), ('\u{3ef}', 1006), ('\u{3f0}', 922), ('\u{3f1}', 929), ('\u{3f2}', 1017), ('\u{3f3}', 895), ('\u{3f5}', 917), ('\u{3f8}', 1015), ('\u{3fb}', 1018), ('\u{430}', 1040), ('\u{431}', 1041), ('\u{432}', 1042), ('\u{433}', 1043), ('\u{434}', 1044), @@ -1090,248 +1103,254 @@ pub mod conversions { ('\u{13f8}', 5104), ('\u{13f9}', 5105), ('\u{13fa}', 5106), ('\u{13fb}', 5107), ('\u{13fc}', 5108), ('\u{13fd}', 5109), ('\u{1c80}', 1042), ('\u{1c81}', 1044), ('\u{1c82}', 1054), ('\u{1c83}', 1057), ('\u{1c84}', 1058), ('\u{1c85}', 1058), - ('\u{1c86}', 1066), ('\u{1c87}', 1122), ('\u{1c88}', 42570), ('\u{1d79}', 42877), - ('\u{1d7d}', 11363), ('\u{1d8e}', 42950), ('\u{1e01}', 7680), ('\u{1e03}', 7682), - ('\u{1e05}', 7684), ('\u{1e07}', 7686), ('\u{1e09}', 7688), ('\u{1e0b}', 7690), - ('\u{1e0d}', 7692), ('\u{1e0f}', 7694), ('\u{1e11}', 7696), ('\u{1e13}', 7698), - ('\u{1e15}', 7700), ('\u{1e17}', 7702), ('\u{1e19}', 7704), ('\u{1e1b}', 7706), - ('\u{1e1d}', 7708), ('\u{1e1f}', 7710), ('\u{1e21}', 7712), ('\u{1e23}', 7714), - ('\u{1e25}', 7716), ('\u{1e27}', 7718), ('\u{1e29}', 7720), ('\u{1e2b}', 7722), - ('\u{1e2d}', 7724), ('\u{1e2f}', 7726), ('\u{1e31}', 7728), ('\u{1e33}', 7730), - ('\u{1e35}', 7732), ('\u{1e37}', 7734), ('\u{1e39}', 7736), ('\u{1e3b}', 7738), - ('\u{1e3d}', 7740), ('\u{1e3f}', 7742), ('\u{1e41}', 7744), ('\u{1e43}', 7746), - ('\u{1e45}', 7748), ('\u{1e47}', 7750), ('\u{1e49}', 7752), ('\u{1e4b}', 7754), - ('\u{1e4d}', 7756), ('\u{1e4f}', 7758), ('\u{1e51}', 7760), ('\u{1e53}', 7762), - ('\u{1e55}', 7764), ('\u{1e57}', 7766), ('\u{1e59}', 7768), ('\u{1e5b}', 7770), - ('\u{1e5d}', 7772), ('\u{1e5f}', 7774), ('\u{1e61}', 7776), ('\u{1e63}', 7778), - ('\u{1e65}', 7780), ('\u{1e67}', 7782), ('\u{1e69}', 7784), ('\u{1e6b}', 7786), - ('\u{1e6d}', 7788), ('\u{1e6f}', 7790), ('\u{1e71}', 7792), ('\u{1e73}', 7794), - ('\u{1e75}', 7796), ('\u{1e77}', 7798), ('\u{1e79}', 7800), ('\u{1e7b}', 7802), - ('\u{1e7d}', 7804), ('\u{1e7f}', 7806), ('\u{1e81}', 7808), ('\u{1e83}', 7810), - ('\u{1e85}', 7812), ('\u{1e87}', 7814), ('\u{1e89}', 7816), ('\u{1e8b}', 7818), - ('\u{1e8d}', 7820), ('\u{1e8f}', 7822), ('\u{1e91}', 7824), ('\u{1e93}', 7826), - ('\u{1e95}', 7828), ('\u{1e96}', 4194310), ('\u{1e97}', 4194311), ('\u{1e98}', 4194312), - ('\u{1e99}', 4194313), ('\u{1e9a}', 4194314), ('\u{1e9b}', 7776), ('\u{1ea1}', 7840), - ('\u{1ea3}', 7842), ('\u{1ea5}', 7844), ('\u{1ea7}', 7846), ('\u{1ea9}', 7848), - ('\u{1eab}', 7850), ('\u{1ead}', 7852), ('\u{1eaf}', 7854), ('\u{1eb1}', 7856), - ('\u{1eb3}', 7858), ('\u{1eb5}', 7860), ('\u{1eb7}', 7862), ('\u{1eb9}', 7864), - ('\u{1ebb}', 7866), ('\u{1ebd}', 7868), ('\u{1ebf}', 7870), ('\u{1ec1}', 7872), - ('\u{1ec3}', 7874), ('\u{1ec5}', 7876), ('\u{1ec7}', 7878), ('\u{1ec9}', 7880), - ('\u{1ecb}', 7882), ('\u{1ecd}', 7884), ('\u{1ecf}', 7886), ('\u{1ed1}', 7888), - ('\u{1ed3}', 7890), ('\u{1ed5}', 7892), ('\u{1ed7}', 7894), ('\u{1ed9}', 7896), - ('\u{1edb}', 7898), ('\u{1edd}', 7900), ('\u{1edf}', 7902), ('\u{1ee1}', 7904), - ('\u{1ee3}', 7906), ('\u{1ee5}', 7908), ('\u{1ee7}', 7910), ('\u{1ee9}', 7912), - ('\u{1eeb}', 7914), ('\u{1eed}', 7916), ('\u{1eef}', 7918), ('\u{1ef1}', 7920), - ('\u{1ef3}', 7922), ('\u{1ef5}', 7924), ('\u{1ef7}', 7926), ('\u{1ef9}', 7928), - ('\u{1efb}', 7930), ('\u{1efd}', 7932), ('\u{1eff}', 7934), ('\u{1f00}', 7944), - ('\u{1f01}', 7945), ('\u{1f02}', 7946), ('\u{1f03}', 7947), ('\u{1f04}', 7948), - ('\u{1f05}', 7949), ('\u{1f06}', 7950), ('\u{1f07}', 7951), ('\u{1f10}', 7960), - ('\u{1f11}', 7961), ('\u{1f12}', 7962), ('\u{1f13}', 7963), ('\u{1f14}', 7964), - ('\u{1f15}', 7965), ('\u{1f20}', 7976), ('\u{1f21}', 7977), ('\u{1f22}', 7978), - ('\u{1f23}', 7979), ('\u{1f24}', 7980), ('\u{1f25}', 7981), ('\u{1f26}', 7982), - ('\u{1f27}', 7983), ('\u{1f30}', 7992), ('\u{1f31}', 7993), ('\u{1f32}', 7994), - ('\u{1f33}', 7995), ('\u{1f34}', 7996), ('\u{1f35}', 7997), ('\u{1f36}', 7998), - ('\u{1f37}', 7999), ('\u{1f40}', 8008), ('\u{1f41}', 8009), ('\u{1f42}', 8010), - ('\u{1f43}', 8011), ('\u{1f44}', 8012), ('\u{1f45}', 8013), ('\u{1f50}', 4194315), - ('\u{1f51}', 8025), ('\u{1f52}', 4194316), ('\u{1f53}', 8027), ('\u{1f54}', 4194317), - ('\u{1f55}', 8029), ('\u{1f56}', 4194318), ('\u{1f57}', 8031), ('\u{1f60}', 8040), - ('\u{1f61}', 8041), ('\u{1f62}', 8042), ('\u{1f63}', 8043), ('\u{1f64}', 8044), - ('\u{1f65}', 8045), ('\u{1f66}', 8046), ('\u{1f67}', 8047), ('\u{1f70}', 8122), - ('\u{1f71}', 8123), ('\u{1f72}', 8136), ('\u{1f73}', 8137), ('\u{1f74}', 8138), - ('\u{1f75}', 8139), ('\u{1f76}', 8154), ('\u{1f77}', 8155), ('\u{1f78}', 8184), - ('\u{1f79}', 8185), ('\u{1f7a}', 8170), ('\u{1f7b}', 8171), ('\u{1f7c}', 8186), - ('\u{1f7d}', 8187), ('\u{1f80}', 4194319), ('\u{1f81}', 4194320), ('\u{1f82}', 4194321), - ('\u{1f83}', 4194322), ('\u{1f84}', 4194323), ('\u{1f85}', 4194324), ('\u{1f86}', 4194325), - ('\u{1f87}', 4194326), ('\u{1f88}', 4194327), ('\u{1f89}', 4194328), ('\u{1f8a}', 4194329), - ('\u{1f8b}', 4194330), ('\u{1f8c}', 4194331), ('\u{1f8d}', 4194332), ('\u{1f8e}', 4194333), - ('\u{1f8f}', 4194334), ('\u{1f90}', 4194335), ('\u{1f91}', 4194336), ('\u{1f92}', 4194337), - ('\u{1f93}', 4194338), ('\u{1f94}', 4194339), ('\u{1f95}', 4194340), ('\u{1f96}', 4194341), - ('\u{1f97}', 4194342), ('\u{1f98}', 4194343), ('\u{1f99}', 4194344), ('\u{1f9a}', 4194345), - ('\u{1f9b}', 4194346), ('\u{1f9c}', 4194347), ('\u{1f9d}', 4194348), ('\u{1f9e}', 4194349), - ('\u{1f9f}', 4194350), ('\u{1fa0}', 4194351), ('\u{1fa1}', 4194352), ('\u{1fa2}', 4194353), - ('\u{1fa3}', 4194354), ('\u{1fa4}', 4194355), ('\u{1fa5}', 4194356), ('\u{1fa6}', 4194357), - ('\u{1fa7}', 4194358), ('\u{1fa8}', 4194359), ('\u{1fa9}', 4194360), ('\u{1faa}', 4194361), - ('\u{1fab}', 4194362), ('\u{1fac}', 4194363), ('\u{1fad}', 4194364), ('\u{1fae}', 4194365), - ('\u{1faf}', 4194366), ('\u{1fb0}', 8120), ('\u{1fb1}', 8121), ('\u{1fb2}', 4194367), - ('\u{1fb3}', 4194368), ('\u{1fb4}', 4194369), ('\u{1fb6}', 4194370), ('\u{1fb7}', 4194371), - ('\u{1fbc}', 4194372), ('\u{1fbe}', 921), ('\u{1fc2}', 4194373), ('\u{1fc3}', 4194374), - ('\u{1fc4}', 4194375), ('\u{1fc6}', 4194376), ('\u{1fc7}', 4194377), ('\u{1fcc}', 4194378), - ('\u{1fd0}', 8152), ('\u{1fd1}', 8153), ('\u{1fd2}', 4194379), ('\u{1fd3}', 4194380), - ('\u{1fd6}', 4194381), ('\u{1fd7}', 4194382), ('\u{1fe0}', 8168), ('\u{1fe1}', 8169), - ('\u{1fe2}', 4194383), ('\u{1fe3}', 4194384), ('\u{1fe4}', 4194385), ('\u{1fe5}', 8172), - ('\u{1fe6}', 4194386), ('\u{1fe7}', 4194387), ('\u{1ff2}', 4194388), ('\u{1ff3}', 4194389), - ('\u{1ff4}', 4194390), ('\u{1ff6}', 4194391), ('\u{1ff7}', 4194392), ('\u{1ffc}', 4194393), - ('\u{214e}', 8498), ('\u{2170}', 8544), ('\u{2171}', 8545), ('\u{2172}', 8546), - ('\u{2173}', 8547), ('\u{2174}', 8548), ('\u{2175}', 8549), ('\u{2176}', 8550), - ('\u{2177}', 8551), ('\u{2178}', 8552), ('\u{2179}', 8553), ('\u{217a}', 8554), - ('\u{217b}', 8555), ('\u{217c}', 8556), ('\u{217d}', 8557), ('\u{217e}', 8558), - ('\u{217f}', 8559), ('\u{2184}', 8579), ('\u{24d0}', 9398), ('\u{24d1}', 9399), - ('\u{24d2}', 9400), ('\u{24d3}', 9401), ('\u{24d4}', 9402), ('\u{24d5}', 9403), - ('\u{24d6}', 9404), ('\u{24d7}', 9405), ('\u{24d8}', 9406), ('\u{24d9}', 9407), - ('\u{24da}', 9408), ('\u{24db}', 9409), ('\u{24dc}', 9410), ('\u{24dd}', 9411), - ('\u{24de}', 9412), ('\u{24df}', 9413), ('\u{24e0}', 9414), ('\u{24e1}', 9415), - ('\u{24e2}', 9416), ('\u{24e3}', 9417), ('\u{24e4}', 9418), ('\u{24e5}', 9419), - ('\u{24e6}', 9420), ('\u{24e7}', 9421), ('\u{24e8}', 9422), ('\u{24e9}', 9423), - ('\u{2c30}', 11264), ('\u{2c31}', 11265), ('\u{2c32}', 11266), ('\u{2c33}', 11267), - ('\u{2c34}', 11268), ('\u{2c35}', 11269), ('\u{2c36}', 11270), ('\u{2c37}', 11271), - ('\u{2c38}', 11272), ('\u{2c39}', 11273), ('\u{2c3a}', 11274), ('\u{2c3b}', 11275), - ('\u{2c3c}', 11276), ('\u{2c3d}', 11277), ('\u{2c3e}', 11278), ('\u{2c3f}', 11279), - ('\u{2c40}', 11280), ('\u{2c41}', 11281), ('\u{2c42}', 11282), ('\u{2c43}', 11283), - ('\u{2c44}', 11284), ('\u{2c45}', 11285), ('\u{2c46}', 11286), ('\u{2c47}', 11287), - ('\u{2c48}', 11288), ('\u{2c49}', 11289), ('\u{2c4a}', 11290), ('\u{2c4b}', 11291), - ('\u{2c4c}', 11292), ('\u{2c4d}', 11293), ('\u{2c4e}', 11294), ('\u{2c4f}', 11295), - ('\u{2c50}', 11296), ('\u{2c51}', 11297), ('\u{2c52}', 11298), ('\u{2c53}', 11299), - ('\u{2c54}', 11300), ('\u{2c55}', 11301), ('\u{2c56}', 11302), ('\u{2c57}', 11303), - ('\u{2c58}', 11304), ('\u{2c59}', 11305), ('\u{2c5a}', 11306), ('\u{2c5b}', 11307), - ('\u{2c5c}', 11308), ('\u{2c5d}', 11309), ('\u{2c5e}', 11310), ('\u{2c5f}', 11311), - ('\u{2c61}', 11360), ('\u{2c65}', 570), ('\u{2c66}', 574), ('\u{2c68}', 11367), - ('\u{2c6a}', 11369), ('\u{2c6c}', 11371), ('\u{2c73}', 11378), ('\u{2c76}', 11381), - ('\u{2c81}', 11392), ('\u{2c83}', 11394), ('\u{2c85}', 11396), ('\u{2c87}', 11398), - ('\u{2c89}', 11400), ('\u{2c8b}', 11402), ('\u{2c8d}', 11404), ('\u{2c8f}', 11406), - ('\u{2c91}', 11408), ('\u{2c93}', 11410), ('\u{2c95}', 11412), ('\u{2c97}', 11414), - ('\u{2c99}', 11416), ('\u{2c9b}', 11418), ('\u{2c9d}', 11420), ('\u{2c9f}', 11422), - ('\u{2ca1}', 11424), ('\u{2ca3}', 11426), ('\u{2ca5}', 11428), ('\u{2ca7}', 11430), - ('\u{2ca9}', 11432), ('\u{2cab}', 11434), ('\u{2cad}', 11436), ('\u{2caf}', 11438), - ('\u{2cb1}', 11440), ('\u{2cb3}', 11442), ('\u{2cb5}', 11444), ('\u{2cb7}', 11446), - ('\u{2cb9}', 11448), ('\u{2cbb}', 11450), ('\u{2cbd}', 11452), ('\u{2cbf}', 11454), - ('\u{2cc1}', 11456), ('\u{2cc3}', 11458), ('\u{2cc5}', 11460), ('\u{2cc7}', 11462), - ('\u{2cc9}', 11464), ('\u{2ccb}', 11466), ('\u{2ccd}', 11468), ('\u{2ccf}', 11470), - ('\u{2cd1}', 11472), ('\u{2cd3}', 11474), ('\u{2cd5}', 11476), ('\u{2cd7}', 11478), - ('\u{2cd9}', 11480), ('\u{2cdb}', 11482), ('\u{2cdd}', 11484), ('\u{2cdf}', 11486), - ('\u{2ce1}', 11488), ('\u{2ce3}', 11490), ('\u{2cec}', 11499), ('\u{2cee}', 11501), - ('\u{2cf3}', 11506), ('\u{2d00}', 4256), ('\u{2d01}', 4257), ('\u{2d02}', 4258), - ('\u{2d03}', 4259), ('\u{2d04}', 4260), ('\u{2d05}', 4261), ('\u{2d06}', 4262), - ('\u{2d07}', 4263), ('\u{2d08}', 4264), ('\u{2d09}', 4265), ('\u{2d0a}', 4266), - ('\u{2d0b}', 4267), ('\u{2d0c}', 4268), ('\u{2d0d}', 4269), ('\u{2d0e}', 4270), - ('\u{2d0f}', 4271), ('\u{2d10}', 4272), ('\u{2d11}', 4273), ('\u{2d12}', 4274), - ('\u{2d13}', 4275), ('\u{2d14}', 4276), ('\u{2d15}', 4277), ('\u{2d16}', 4278), - ('\u{2d17}', 4279), ('\u{2d18}', 4280), ('\u{2d19}', 4281), ('\u{2d1a}', 4282), - ('\u{2d1b}', 4283), ('\u{2d1c}', 4284), ('\u{2d1d}', 4285), ('\u{2d1e}', 4286), - ('\u{2d1f}', 4287), ('\u{2d20}', 4288), ('\u{2d21}', 4289), ('\u{2d22}', 4290), - ('\u{2d23}', 4291), ('\u{2d24}', 4292), ('\u{2d25}', 4293), ('\u{2d27}', 4295), - ('\u{2d2d}', 4301), ('\u{a641}', 42560), ('\u{a643}', 42562), ('\u{a645}', 42564), - ('\u{a647}', 42566), ('\u{a649}', 42568), ('\u{a64b}', 42570), ('\u{a64d}', 42572), - ('\u{a64f}', 42574), ('\u{a651}', 42576), ('\u{a653}', 42578), ('\u{a655}', 42580), - ('\u{a657}', 42582), ('\u{a659}', 42584), ('\u{a65b}', 42586), ('\u{a65d}', 42588), - ('\u{a65f}', 42590), ('\u{a661}', 42592), ('\u{a663}', 42594), ('\u{a665}', 42596), - ('\u{a667}', 42598), ('\u{a669}', 42600), ('\u{a66b}', 42602), ('\u{a66d}', 42604), - ('\u{a681}', 42624), ('\u{a683}', 42626), ('\u{a685}', 42628), ('\u{a687}', 42630), - ('\u{a689}', 42632), ('\u{a68b}', 42634), ('\u{a68d}', 42636), ('\u{a68f}', 42638), - ('\u{a691}', 42640), ('\u{a693}', 42642), ('\u{a695}', 42644), ('\u{a697}', 42646), - ('\u{a699}', 42648), ('\u{a69b}', 42650), ('\u{a723}', 42786), ('\u{a725}', 42788), - ('\u{a727}', 42790), ('\u{a729}', 42792), ('\u{a72b}', 42794), ('\u{a72d}', 42796), - ('\u{a72f}', 42798), ('\u{a733}', 42802), ('\u{a735}', 42804), ('\u{a737}', 42806), - ('\u{a739}', 42808), ('\u{a73b}', 42810), ('\u{a73d}', 42812), ('\u{a73f}', 42814), - ('\u{a741}', 42816), ('\u{a743}', 42818), ('\u{a745}', 42820), ('\u{a747}', 42822), - ('\u{a749}', 42824), ('\u{a74b}', 42826), ('\u{a74d}', 42828), ('\u{a74f}', 42830), - ('\u{a751}', 42832), ('\u{a753}', 42834), ('\u{a755}', 42836), ('\u{a757}', 42838), - ('\u{a759}', 42840), ('\u{a75b}', 42842), ('\u{a75d}', 42844), ('\u{a75f}', 42846), - ('\u{a761}', 42848), ('\u{a763}', 42850), ('\u{a765}', 42852), ('\u{a767}', 42854), - ('\u{a769}', 42856), ('\u{a76b}', 42858), ('\u{a76d}', 42860), ('\u{a76f}', 42862), - ('\u{a77a}', 42873), ('\u{a77c}', 42875), ('\u{a77f}', 42878), ('\u{a781}', 42880), - ('\u{a783}', 42882), ('\u{a785}', 42884), ('\u{a787}', 42886), ('\u{a78c}', 42891), - ('\u{a791}', 42896), ('\u{a793}', 42898), ('\u{a794}', 42948), ('\u{a797}', 42902), - ('\u{a799}', 42904), ('\u{a79b}', 42906), ('\u{a79d}', 42908), ('\u{a79f}', 42910), - ('\u{a7a1}', 42912), ('\u{a7a3}', 42914), ('\u{a7a5}', 42916), ('\u{a7a7}', 42918), - ('\u{a7a9}', 42920), ('\u{a7b5}', 42932), ('\u{a7b7}', 42934), ('\u{a7b9}', 42936), - ('\u{a7bb}', 42938), ('\u{a7bd}', 42940), ('\u{a7bf}', 42942), ('\u{a7c1}', 42944), - ('\u{a7c3}', 42946), ('\u{a7c8}', 42951), ('\u{a7ca}', 42953), ('\u{a7d1}', 42960), - ('\u{a7d7}', 42966), ('\u{a7d9}', 42968), ('\u{a7f6}', 42997), ('\u{ab53}', 42931), - ('\u{ab70}', 5024), ('\u{ab71}', 5025), ('\u{ab72}', 5026), ('\u{ab73}', 5027), - ('\u{ab74}', 5028), ('\u{ab75}', 5029), ('\u{ab76}', 5030), ('\u{ab77}', 5031), - ('\u{ab78}', 5032), ('\u{ab79}', 5033), ('\u{ab7a}', 5034), ('\u{ab7b}', 5035), - ('\u{ab7c}', 5036), ('\u{ab7d}', 5037), ('\u{ab7e}', 5038), ('\u{ab7f}', 5039), - ('\u{ab80}', 5040), ('\u{ab81}', 5041), ('\u{ab82}', 5042), ('\u{ab83}', 5043), - ('\u{ab84}', 5044), ('\u{ab85}', 5045), ('\u{ab86}', 5046), ('\u{ab87}', 5047), - ('\u{ab88}', 5048), ('\u{ab89}', 5049), ('\u{ab8a}', 5050), ('\u{ab8b}', 5051), - ('\u{ab8c}', 5052), ('\u{ab8d}', 5053), ('\u{ab8e}', 5054), ('\u{ab8f}', 5055), - ('\u{ab90}', 5056), ('\u{ab91}', 5057), ('\u{ab92}', 5058), ('\u{ab93}', 5059), - ('\u{ab94}', 5060), ('\u{ab95}', 5061), ('\u{ab96}', 5062), ('\u{ab97}', 5063), - ('\u{ab98}', 5064), ('\u{ab99}', 5065), ('\u{ab9a}', 5066), ('\u{ab9b}', 5067), - ('\u{ab9c}', 5068), ('\u{ab9d}', 5069), ('\u{ab9e}', 5070), ('\u{ab9f}', 5071), - ('\u{aba0}', 5072), ('\u{aba1}', 5073), ('\u{aba2}', 5074), ('\u{aba3}', 5075), - ('\u{aba4}', 5076), ('\u{aba5}', 5077), ('\u{aba6}', 5078), ('\u{aba7}', 5079), - ('\u{aba8}', 5080), ('\u{aba9}', 5081), ('\u{abaa}', 5082), ('\u{abab}', 5083), - ('\u{abac}', 5084), ('\u{abad}', 5085), ('\u{abae}', 5086), ('\u{abaf}', 5087), - ('\u{abb0}', 5088), ('\u{abb1}', 5089), ('\u{abb2}', 5090), ('\u{abb3}', 5091), - ('\u{abb4}', 5092), ('\u{abb5}', 5093), ('\u{abb6}', 5094), ('\u{abb7}', 5095), - ('\u{abb8}', 5096), ('\u{abb9}', 5097), ('\u{abba}', 5098), ('\u{abbb}', 5099), - ('\u{abbc}', 5100), ('\u{abbd}', 5101), ('\u{abbe}', 5102), ('\u{abbf}', 5103), - ('\u{fb00}', 4194394), ('\u{fb01}', 4194395), ('\u{fb02}', 4194396), ('\u{fb03}', 4194397), - ('\u{fb04}', 4194398), ('\u{fb05}', 4194399), ('\u{fb06}', 4194400), ('\u{fb13}', 4194401), - ('\u{fb14}', 4194402), ('\u{fb15}', 4194403), ('\u{fb16}', 4194404), ('\u{fb17}', 4194405), - ('\u{ff41}', 65313), ('\u{ff42}', 65314), ('\u{ff43}', 65315), ('\u{ff44}', 65316), - ('\u{ff45}', 65317), ('\u{ff46}', 65318), ('\u{ff47}', 65319), ('\u{ff48}', 65320), - ('\u{ff49}', 65321), ('\u{ff4a}', 65322), ('\u{ff4b}', 65323), ('\u{ff4c}', 65324), - ('\u{ff4d}', 65325), ('\u{ff4e}', 65326), ('\u{ff4f}', 65327), ('\u{ff50}', 65328), - ('\u{ff51}', 65329), ('\u{ff52}', 65330), ('\u{ff53}', 65331), ('\u{ff54}', 65332), - ('\u{ff55}', 65333), ('\u{ff56}', 65334), ('\u{ff57}', 65335), ('\u{ff58}', 65336), - ('\u{ff59}', 65337), ('\u{ff5a}', 65338), ('\u{10428}', 66560), ('\u{10429}', 66561), - ('\u{1042a}', 66562), ('\u{1042b}', 66563), ('\u{1042c}', 66564), ('\u{1042d}', 66565), - ('\u{1042e}', 66566), ('\u{1042f}', 66567), ('\u{10430}', 66568), ('\u{10431}', 66569), - ('\u{10432}', 66570), ('\u{10433}', 66571), ('\u{10434}', 66572), ('\u{10435}', 66573), - ('\u{10436}', 66574), ('\u{10437}', 66575), ('\u{10438}', 66576), ('\u{10439}', 66577), - ('\u{1043a}', 66578), ('\u{1043b}', 66579), ('\u{1043c}', 66580), ('\u{1043d}', 66581), - ('\u{1043e}', 66582), ('\u{1043f}', 66583), ('\u{10440}', 66584), ('\u{10441}', 66585), - ('\u{10442}', 66586), ('\u{10443}', 66587), ('\u{10444}', 66588), ('\u{10445}', 66589), - ('\u{10446}', 66590), ('\u{10447}', 66591), ('\u{10448}', 66592), ('\u{10449}', 66593), - ('\u{1044a}', 66594), ('\u{1044b}', 66595), ('\u{1044c}', 66596), ('\u{1044d}', 66597), - ('\u{1044e}', 66598), ('\u{1044f}', 66599), ('\u{104d8}', 66736), ('\u{104d9}', 66737), - ('\u{104da}', 66738), ('\u{104db}', 66739), ('\u{104dc}', 66740), ('\u{104dd}', 66741), - ('\u{104de}', 66742), ('\u{104df}', 66743), ('\u{104e0}', 66744), ('\u{104e1}', 66745), - ('\u{104e2}', 66746), ('\u{104e3}', 66747), ('\u{104e4}', 66748), ('\u{104e5}', 66749), - ('\u{104e6}', 66750), ('\u{104e7}', 66751), ('\u{104e8}', 66752), ('\u{104e9}', 66753), - ('\u{104ea}', 66754), ('\u{104eb}', 66755), ('\u{104ec}', 66756), ('\u{104ed}', 66757), - ('\u{104ee}', 66758), ('\u{104ef}', 66759), ('\u{104f0}', 66760), ('\u{104f1}', 66761), - ('\u{104f2}', 66762), ('\u{104f3}', 66763), ('\u{104f4}', 66764), ('\u{104f5}', 66765), - ('\u{104f6}', 66766), ('\u{104f7}', 66767), ('\u{104f8}', 66768), ('\u{104f9}', 66769), - ('\u{104fa}', 66770), ('\u{104fb}', 66771), ('\u{10597}', 66928), ('\u{10598}', 66929), - ('\u{10599}', 66930), ('\u{1059a}', 66931), ('\u{1059b}', 66932), ('\u{1059c}', 66933), - ('\u{1059d}', 66934), ('\u{1059e}', 66935), ('\u{1059f}', 66936), ('\u{105a0}', 66937), - ('\u{105a1}', 66938), ('\u{105a3}', 66940), ('\u{105a4}', 66941), ('\u{105a5}', 66942), - ('\u{105a6}', 66943), ('\u{105a7}', 66944), ('\u{105a8}', 66945), ('\u{105a9}', 66946), - ('\u{105aa}', 66947), ('\u{105ab}', 66948), ('\u{105ac}', 66949), ('\u{105ad}', 66950), - ('\u{105ae}', 66951), ('\u{105af}', 66952), ('\u{105b0}', 66953), ('\u{105b1}', 66954), - ('\u{105b3}', 66956), ('\u{105b4}', 66957), ('\u{105b5}', 66958), ('\u{105b6}', 66959), - ('\u{105b7}', 66960), ('\u{105b8}', 66961), ('\u{105b9}', 66962), ('\u{105bb}', 66964), - ('\u{105bc}', 66965), ('\u{10cc0}', 68736), ('\u{10cc1}', 68737), ('\u{10cc2}', 68738), - ('\u{10cc3}', 68739), ('\u{10cc4}', 68740), ('\u{10cc5}', 68741), ('\u{10cc6}', 68742), - ('\u{10cc7}', 68743), ('\u{10cc8}', 68744), ('\u{10cc9}', 68745), ('\u{10cca}', 68746), - ('\u{10ccb}', 68747), ('\u{10ccc}', 68748), ('\u{10ccd}', 68749), ('\u{10cce}', 68750), - ('\u{10ccf}', 68751), ('\u{10cd0}', 68752), ('\u{10cd1}', 68753), ('\u{10cd2}', 68754), - ('\u{10cd3}', 68755), ('\u{10cd4}', 68756), ('\u{10cd5}', 68757), ('\u{10cd6}', 68758), - ('\u{10cd7}', 68759), ('\u{10cd8}', 68760), ('\u{10cd9}', 68761), ('\u{10cda}', 68762), - ('\u{10cdb}', 68763), ('\u{10cdc}', 68764), ('\u{10cdd}', 68765), ('\u{10cde}', 68766), - ('\u{10cdf}', 68767), ('\u{10ce0}', 68768), ('\u{10ce1}', 68769), ('\u{10ce2}', 68770), - ('\u{10ce3}', 68771), ('\u{10ce4}', 68772), ('\u{10ce5}', 68773), ('\u{10ce6}', 68774), - ('\u{10ce7}', 68775), ('\u{10ce8}', 68776), ('\u{10ce9}', 68777), ('\u{10cea}', 68778), - ('\u{10ceb}', 68779), ('\u{10cec}', 68780), ('\u{10ced}', 68781), ('\u{10cee}', 68782), - ('\u{10cef}', 68783), ('\u{10cf0}', 68784), ('\u{10cf1}', 68785), ('\u{10cf2}', 68786), - ('\u{118c0}', 71840), ('\u{118c1}', 71841), ('\u{118c2}', 71842), ('\u{118c3}', 71843), - ('\u{118c4}', 71844), ('\u{118c5}', 71845), ('\u{118c6}', 71846), ('\u{118c7}', 71847), - ('\u{118c8}', 71848), ('\u{118c9}', 71849), ('\u{118ca}', 71850), ('\u{118cb}', 71851), - ('\u{118cc}', 71852), ('\u{118cd}', 71853), ('\u{118ce}', 71854), ('\u{118cf}', 71855), - ('\u{118d0}', 71856), ('\u{118d1}', 71857), ('\u{118d2}', 71858), ('\u{118d3}', 71859), - ('\u{118d4}', 71860), ('\u{118d5}', 71861), ('\u{118d6}', 71862), ('\u{118d7}', 71863), - ('\u{118d8}', 71864), ('\u{118d9}', 71865), ('\u{118da}', 71866), ('\u{118db}', 71867), - ('\u{118dc}', 71868), ('\u{118dd}', 71869), ('\u{118de}', 71870), ('\u{118df}', 71871), - ('\u{16e60}', 93760), ('\u{16e61}', 93761), ('\u{16e62}', 93762), ('\u{16e63}', 93763), - ('\u{16e64}', 93764), ('\u{16e65}', 93765), ('\u{16e66}', 93766), ('\u{16e67}', 93767), - ('\u{16e68}', 93768), ('\u{16e69}', 93769), ('\u{16e6a}', 93770), ('\u{16e6b}', 93771), - ('\u{16e6c}', 93772), ('\u{16e6d}', 93773), ('\u{16e6e}', 93774), ('\u{16e6f}', 93775), - ('\u{16e70}', 93776), ('\u{16e71}', 93777), ('\u{16e72}', 93778), ('\u{16e73}', 93779), - ('\u{16e74}', 93780), ('\u{16e75}', 93781), ('\u{16e76}', 93782), ('\u{16e77}', 93783), - ('\u{16e78}', 93784), ('\u{16e79}', 93785), ('\u{16e7a}', 93786), ('\u{16e7b}', 93787), - ('\u{16e7c}', 93788), ('\u{16e7d}', 93789), ('\u{16e7e}', 93790), ('\u{16e7f}', 93791), - ('\u{1e922}', 125184), ('\u{1e923}', 125185), ('\u{1e924}', 125186), ('\u{1e925}', 125187), - ('\u{1e926}', 125188), ('\u{1e927}', 125189), ('\u{1e928}', 125190), ('\u{1e929}', 125191), - ('\u{1e92a}', 125192), ('\u{1e92b}', 125193), ('\u{1e92c}', 125194), ('\u{1e92d}', 125195), - ('\u{1e92e}', 125196), ('\u{1e92f}', 125197), ('\u{1e930}', 125198), ('\u{1e931}', 125199), - ('\u{1e932}', 125200), ('\u{1e933}', 125201), ('\u{1e934}', 125202), ('\u{1e935}', 125203), - ('\u{1e936}', 125204), ('\u{1e937}', 125205), ('\u{1e938}', 125206), ('\u{1e939}', 125207), - ('\u{1e93a}', 125208), ('\u{1e93b}', 125209), ('\u{1e93c}', 125210), ('\u{1e93d}', 125211), - ('\u{1e93e}', 125212), ('\u{1e93f}', 125213), ('\u{1e940}', 125214), ('\u{1e941}', 125215), - ('\u{1e942}', 125216), ('\u{1e943}', 125217), + ('\u{1c86}', 1066), ('\u{1c87}', 1122), ('\u{1c88}', 42570), ('\u{1c8a}', 7305), + ('\u{1d79}', 42877), ('\u{1d7d}', 11363), ('\u{1d8e}', 42950), ('\u{1e01}', 7680), + ('\u{1e03}', 7682), ('\u{1e05}', 7684), ('\u{1e07}', 7686), ('\u{1e09}', 7688), + ('\u{1e0b}', 7690), ('\u{1e0d}', 7692), ('\u{1e0f}', 7694), ('\u{1e11}', 7696), + ('\u{1e13}', 7698), ('\u{1e15}', 7700), ('\u{1e17}', 7702), ('\u{1e19}', 7704), + ('\u{1e1b}', 7706), ('\u{1e1d}', 7708), ('\u{1e1f}', 7710), ('\u{1e21}', 7712), + ('\u{1e23}', 7714), ('\u{1e25}', 7716), ('\u{1e27}', 7718), ('\u{1e29}', 7720), + ('\u{1e2b}', 7722), ('\u{1e2d}', 7724), ('\u{1e2f}', 7726), ('\u{1e31}', 7728), + ('\u{1e33}', 7730), ('\u{1e35}', 7732), ('\u{1e37}', 7734), ('\u{1e39}', 7736), + ('\u{1e3b}', 7738), ('\u{1e3d}', 7740), ('\u{1e3f}', 7742), ('\u{1e41}', 7744), + ('\u{1e43}', 7746), ('\u{1e45}', 7748), ('\u{1e47}', 7750), ('\u{1e49}', 7752), + ('\u{1e4b}', 7754), ('\u{1e4d}', 7756), ('\u{1e4f}', 7758), ('\u{1e51}', 7760), + ('\u{1e53}', 7762), ('\u{1e55}', 7764), ('\u{1e57}', 7766), ('\u{1e59}', 7768), + ('\u{1e5b}', 7770), ('\u{1e5d}', 7772), ('\u{1e5f}', 7774), ('\u{1e61}', 7776), + ('\u{1e63}', 7778), ('\u{1e65}', 7780), ('\u{1e67}', 7782), ('\u{1e69}', 7784), + ('\u{1e6b}', 7786), ('\u{1e6d}', 7788), ('\u{1e6f}', 7790), ('\u{1e71}', 7792), + ('\u{1e73}', 7794), ('\u{1e75}', 7796), ('\u{1e77}', 7798), ('\u{1e79}', 7800), + ('\u{1e7b}', 7802), ('\u{1e7d}', 7804), ('\u{1e7f}', 7806), ('\u{1e81}', 7808), + ('\u{1e83}', 7810), ('\u{1e85}', 7812), ('\u{1e87}', 7814), ('\u{1e89}', 7816), + ('\u{1e8b}', 7818), ('\u{1e8d}', 7820), ('\u{1e8f}', 7822), ('\u{1e91}', 7824), + ('\u{1e93}', 7826), ('\u{1e95}', 7828), ('\u{1e96}', 4194310), ('\u{1e97}', 4194311), + ('\u{1e98}', 4194312), ('\u{1e99}', 4194313), ('\u{1e9a}', 4194314), ('\u{1e9b}', 7776), + ('\u{1ea1}', 7840), ('\u{1ea3}', 7842), ('\u{1ea5}', 7844), ('\u{1ea7}', 7846), + ('\u{1ea9}', 7848), ('\u{1eab}', 7850), ('\u{1ead}', 7852), ('\u{1eaf}', 7854), + ('\u{1eb1}', 7856), ('\u{1eb3}', 7858), ('\u{1eb5}', 7860), ('\u{1eb7}', 7862), + ('\u{1eb9}', 7864), ('\u{1ebb}', 7866), ('\u{1ebd}', 7868), ('\u{1ebf}', 7870), + ('\u{1ec1}', 7872), ('\u{1ec3}', 7874), ('\u{1ec5}', 7876), ('\u{1ec7}', 7878), + ('\u{1ec9}', 7880), ('\u{1ecb}', 7882), ('\u{1ecd}', 7884), ('\u{1ecf}', 7886), + ('\u{1ed1}', 7888), ('\u{1ed3}', 7890), ('\u{1ed5}', 7892), ('\u{1ed7}', 7894), + ('\u{1ed9}', 7896), ('\u{1edb}', 7898), ('\u{1edd}', 7900), ('\u{1edf}', 7902), + ('\u{1ee1}', 7904), ('\u{1ee3}', 7906), ('\u{1ee5}', 7908), ('\u{1ee7}', 7910), + ('\u{1ee9}', 7912), ('\u{1eeb}', 7914), ('\u{1eed}', 7916), ('\u{1eef}', 7918), + ('\u{1ef1}', 7920), ('\u{1ef3}', 7922), ('\u{1ef5}', 7924), ('\u{1ef7}', 7926), + ('\u{1ef9}', 7928), ('\u{1efb}', 7930), ('\u{1efd}', 7932), ('\u{1eff}', 7934), + ('\u{1f00}', 7944), ('\u{1f01}', 7945), ('\u{1f02}', 7946), ('\u{1f03}', 7947), + ('\u{1f04}', 7948), ('\u{1f05}', 7949), ('\u{1f06}', 7950), ('\u{1f07}', 7951), + ('\u{1f10}', 7960), ('\u{1f11}', 7961), ('\u{1f12}', 7962), ('\u{1f13}', 7963), + ('\u{1f14}', 7964), ('\u{1f15}', 7965), ('\u{1f20}', 7976), ('\u{1f21}', 7977), + ('\u{1f22}', 7978), ('\u{1f23}', 7979), ('\u{1f24}', 7980), ('\u{1f25}', 7981), + ('\u{1f26}', 7982), ('\u{1f27}', 7983), ('\u{1f30}', 7992), ('\u{1f31}', 7993), + ('\u{1f32}', 7994), ('\u{1f33}', 7995), ('\u{1f34}', 7996), ('\u{1f35}', 7997), + ('\u{1f36}', 7998), ('\u{1f37}', 7999), ('\u{1f40}', 8008), ('\u{1f41}', 8009), + ('\u{1f42}', 8010), ('\u{1f43}', 8011), ('\u{1f44}', 8012), ('\u{1f45}', 8013), + ('\u{1f50}', 4194315), ('\u{1f51}', 8025), ('\u{1f52}', 4194316), ('\u{1f53}', 8027), + ('\u{1f54}', 4194317), ('\u{1f55}', 8029), ('\u{1f56}', 4194318), ('\u{1f57}', 8031), + ('\u{1f60}', 8040), ('\u{1f61}', 8041), ('\u{1f62}', 8042), ('\u{1f63}', 8043), + ('\u{1f64}', 8044), ('\u{1f65}', 8045), ('\u{1f66}', 8046), ('\u{1f67}', 8047), + ('\u{1f70}', 8122), ('\u{1f71}', 8123), ('\u{1f72}', 8136), ('\u{1f73}', 8137), + ('\u{1f74}', 8138), ('\u{1f75}', 8139), ('\u{1f76}', 8154), ('\u{1f77}', 8155), + ('\u{1f78}', 8184), ('\u{1f79}', 8185), ('\u{1f7a}', 8170), ('\u{1f7b}', 8171), + ('\u{1f7c}', 8186), ('\u{1f7d}', 8187), ('\u{1f80}', 4194319), ('\u{1f81}', 4194320), + ('\u{1f82}', 4194321), ('\u{1f83}', 4194322), ('\u{1f84}', 4194323), ('\u{1f85}', 4194324), + ('\u{1f86}', 4194325), ('\u{1f87}', 4194326), ('\u{1f88}', 4194327), ('\u{1f89}', 4194328), + ('\u{1f8a}', 4194329), ('\u{1f8b}', 4194330), ('\u{1f8c}', 4194331), ('\u{1f8d}', 4194332), + ('\u{1f8e}', 4194333), ('\u{1f8f}', 4194334), ('\u{1f90}', 4194335), ('\u{1f91}', 4194336), + ('\u{1f92}', 4194337), ('\u{1f93}', 4194338), ('\u{1f94}', 4194339), ('\u{1f95}', 4194340), + ('\u{1f96}', 4194341), ('\u{1f97}', 4194342), ('\u{1f98}', 4194343), ('\u{1f99}', 4194344), + ('\u{1f9a}', 4194345), ('\u{1f9b}', 4194346), ('\u{1f9c}', 4194347), ('\u{1f9d}', 4194348), + ('\u{1f9e}', 4194349), ('\u{1f9f}', 4194350), ('\u{1fa0}', 4194351), ('\u{1fa1}', 4194352), + ('\u{1fa2}', 4194353), ('\u{1fa3}', 4194354), ('\u{1fa4}', 4194355), ('\u{1fa5}', 4194356), + ('\u{1fa6}', 4194357), ('\u{1fa7}', 4194358), ('\u{1fa8}', 4194359), ('\u{1fa9}', 4194360), + ('\u{1faa}', 4194361), ('\u{1fab}', 4194362), ('\u{1fac}', 4194363), ('\u{1fad}', 4194364), + ('\u{1fae}', 4194365), ('\u{1faf}', 4194366), ('\u{1fb0}', 8120), ('\u{1fb1}', 8121), + ('\u{1fb2}', 4194367), ('\u{1fb3}', 4194368), ('\u{1fb4}', 4194369), ('\u{1fb6}', 4194370), + ('\u{1fb7}', 4194371), ('\u{1fbc}', 4194372), ('\u{1fbe}', 921), ('\u{1fc2}', 4194373), + ('\u{1fc3}', 4194374), ('\u{1fc4}', 4194375), ('\u{1fc6}', 4194376), ('\u{1fc7}', 4194377), + ('\u{1fcc}', 4194378), ('\u{1fd0}', 8152), ('\u{1fd1}', 8153), ('\u{1fd2}', 4194379), + ('\u{1fd3}', 4194380), ('\u{1fd6}', 4194381), ('\u{1fd7}', 4194382), ('\u{1fe0}', 8168), + ('\u{1fe1}', 8169), ('\u{1fe2}', 4194383), ('\u{1fe3}', 4194384), ('\u{1fe4}', 4194385), + ('\u{1fe5}', 8172), ('\u{1fe6}', 4194386), ('\u{1fe7}', 4194387), ('\u{1ff2}', 4194388), + ('\u{1ff3}', 4194389), ('\u{1ff4}', 4194390), ('\u{1ff6}', 4194391), ('\u{1ff7}', 4194392), + ('\u{1ffc}', 4194393), ('\u{214e}', 8498), ('\u{2170}', 8544), ('\u{2171}', 8545), + ('\u{2172}', 8546), ('\u{2173}', 8547), ('\u{2174}', 8548), ('\u{2175}', 8549), + ('\u{2176}', 8550), ('\u{2177}', 8551), ('\u{2178}', 8552), ('\u{2179}', 8553), + ('\u{217a}', 8554), ('\u{217b}', 8555), ('\u{217c}', 8556), ('\u{217d}', 8557), + ('\u{217e}', 8558), ('\u{217f}', 8559), ('\u{2184}', 8579), ('\u{24d0}', 9398), + ('\u{24d1}', 9399), ('\u{24d2}', 9400), ('\u{24d3}', 9401), ('\u{24d4}', 9402), + ('\u{24d5}', 9403), ('\u{24d6}', 9404), ('\u{24d7}', 9405), ('\u{24d8}', 9406), + ('\u{24d9}', 9407), ('\u{24da}', 9408), ('\u{24db}', 9409), ('\u{24dc}', 9410), + ('\u{24dd}', 9411), ('\u{24de}', 9412), ('\u{24df}', 9413), ('\u{24e0}', 9414), + ('\u{24e1}', 9415), ('\u{24e2}', 9416), ('\u{24e3}', 9417), ('\u{24e4}', 9418), + ('\u{24e5}', 9419), ('\u{24e6}', 9420), ('\u{24e7}', 9421), ('\u{24e8}', 9422), + ('\u{24e9}', 9423), ('\u{2c30}', 11264), ('\u{2c31}', 11265), ('\u{2c32}', 11266), + ('\u{2c33}', 11267), ('\u{2c34}', 11268), ('\u{2c35}', 11269), ('\u{2c36}', 11270), + ('\u{2c37}', 11271), ('\u{2c38}', 11272), ('\u{2c39}', 11273), ('\u{2c3a}', 11274), + ('\u{2c3b}', 11275), ('\u{2c3c}', 11276), ('\u{2c3d}', 11277), ('\u{2c3e}', 11278), + ('\u{2c3f}', 11279), ('\u{2c40}', 11280), ('\u{2c41}', 11281), ('\u{2c42}', 11282), + ('\u{2c43}', 11283), ('\u{2c44}', 11284), ('\u{2c45}', 11285), ('\u{2c46}', 11286), + ('\u{2c47}', 11287), ('\u{2c48}', 11288), ('\u{2c49}', 11289), ('\u{2c4a}', 11290), + ('\u{2c4b}', 11291), ('\u{2c4c}', 11292), ('\u{2c4d}', 11293), ('\u{2c4e}', 11294), + ('\u{2c4f}', 11295), ('\u{2c50}', 11296), ('\u{2c51}', 11297), ('\u{2c52}', 11298), + ('\u{2c53}', 11299), ('\u{2c54}', 11300), ('\u{2c55}', 11301), ('\u{2c56}', 11302), + ('\u{2c57}', 11303), ('\u{2c58}', 11304), ('\u{2c59}', 11305), ('\u{2c5a}', 11306), + ('\u{2c5b}', 11307), ('\u{2c5c}', 11308), ('\u{2c5d}', 11309), ('\u{2c5e}', 11310), + ('\u{2c5f}', 11311), ('\u{2c61}', 11360), ('\u{2c65}', 570), ('\u{2c66}', 574), + ('\u{2c68}', 11367), ('\u{2c6a}', 11369), ('\u{2c6c}', 11371), ('\u{2c73}', 11378), + ('\u{2c76}', 11381), ('\u{2c81}', 11392), ('\u{2c83}', 11394), ('\u{2c85}', 11396), + ('\u{2c87}', 11398), ('\u{2c89}', 11400), ('\u{2c8b}', 11402), ('\u{2c8d}', 11404), + ('\u{2c8f}', 11406), ('\u{2c91}', 11408), ('\u{2c93}', 11410), ('\u{2c95}', 11412), + ('\u{2c97}', 11414), ('\u{2c99}', 11416), ('\u{2c9b}', 11418), ('\u{2c9d}', 11420), + ('\u{2c9f}', 11422), ('\u{2ca1}', 11424), ('\u{2ca3}', 11426), ('\u{2ca5}', 11428), + ('\u{2ca7}', 11430), ('\u{2ca9}', 11432), ('\u{2cab}', 11434), ('\u{2cad}', 11436), + ('\u{2caf}', 11438), ('\u{2cb1}', 11440), ('\u{2cb3}', 11442), ('\u{2cb5}', 11444), + ('\u{2cb7}', 11446), ('\u{2cb9}', 11448), ('\u{2cbb}', 11450), ('\u{2cbd}', 11452), + ('\u{2cbf}', 11454), ('\u{2cc1}', 11456), ('\u{2cc3}', 11458), ('\u{2cc5}', 11460), + ('\u{2cc7}', 11462), ('\u{2cc9}', 11464), ('\u{2ccb}', 11466), ('\u{2ccd}', 11468), + ('\u{2ccf}', 11470), ('\u{2cd1}', 11472), ('\u{2cd3}', 11474), ('\u{2cd5}', 11476), + ('\u{2cd7}', 11478), ('\u{2cd9}', 11480), ('\u{2cdb}', 11482), ('\u{2cdd}', 11484), + ('\u{2cdf}', 11486), ('\u{2ce1}', 11488), ('\u{2ce3}', 11490), ('\u{2cec}', 11499), + ('\u{2cee}', 11501), ('\u{2cf3}', 11506), ('\u{2d00}', 4256), ('\u{2d01}', 4257), + ('\u{2d02}', 4258), ('\u{2d03}', 4259), ('\u{2d04}', 4260), ('\u{2d05}', 4261), + ('\u{2d06}', 4262), ('\u{2d07}', 4263), ('\u{2d08}', 4264), ('\u{2d09}', 4265), + ('\u{2d0a}', 4266), ('\u{2d0b}', 4267), ('\u{2d0c}', 4268), ('\u{2d0d}', 4269), + ('\u{2d0e}', 4270), ('\u{2d0f}', 4271), ('\u{2d10}', 4272), ('\u{2d11}', 4273), + ('\u{2d12}', 4274), ('\u{2d13}', 4275), ('\u{2d14}', 4276), ('\u{2d15}', 4277), + ('\u{2d16}', 4278), ('\u{2d17}', 4279), ('\u{2d18}', 4280), ('\u{2d19}', 4281), + ('\u{2d1a}', 4282), ('\u{2d1b}', 4283), ('\u{2d1c}', 4284), ('\u{2d1d}', 4285), + ('\u{2d1e}', 4286), ('\u{2d1f}', 4287), ('\u{2d20}', 4288), ('\u{2d21}', 4289), + ('\u{2d22}', 4290), ('\u{2d23}', 4291), ('\u{2d24}', 4292), ('\u{2d25}', 4293), + ('\u{2d27}', 4295), ('\u{2d2d}', 4301), ('\u{a641}', 42560), ('\u{a643}', 42562), + ('\u{a645}', 42564), ('\u{a647}', 42566), ('\u{a649}', 42568), ('\u{a64b}', 42570), + ('\u{a64d}', 42572), ('\u{a64f}', 42574), ('\u{a651}', 42576), ('\u{a653}', 42578), + ('\u{a655}', 42580), ('\u{a657}', 42582), ('\u{a659}', 42584), ('\u{a65b}', 42586), + ('\u{a65d}', 42588), ('\u{a65f}', 42590), ('\u{a661}', 42592), ('\u{a663}', 42594), + ('\u{a665}', 42596), ('\u{a667}', 42598), ('\u{a669}', 42600), ('\u{a66b}', 42602), + ('\u{a66d}', 42604), ('\u{a681}', 42624), ('\u{a683}', 42626), ('\u{a685}', 42628), + ('\u{a687}', 42630), ('\u{a689}', 42632), ('\u{a68b}', 42634), ('\u{a68d}', 42636), + ('\u{a68f}', 42638), ('\u{a691}', 42640), ('\u{a693}', 42642), ('\u{a695}', 42644), + ('\u{a697}', 42646), ('\u{a699}', 42648), ('\u{a69b}', 42650), ('\u{a723}', 42786), + ('\u{a725}', 42788), ('\u{a727}', 42790), ('\u{a729}', 42792), ('\u{a72b}', 42794), + ('\u{a72d}', 42796), ('\u{a72f}', 42798), ('\u{a733}', 42802), ('\u{a735}', 42804), + ('\u{a737}', 42806), ('\u{a739}', 42808), ('\u{a73b}', 42810), ('\u{a73d}', 42812), + ('\u{a73f}', 42814), ('\u{a741}', 42816), ('\u{a743}', 42818), ('\u{a745}', 42820), + ('\u{a747}', 42822), ('\u{a749}', 42824), ('\u{a74b}', 42826), ('\u{a74d}', 42828), + ('\u{a74f}', 42830), ('\u{a751}', 42832), ('\u{a753}', 42834), ('\u{a755}', 42836), + ('\u{a757}', 42838), ('\u{a759}', 42840), ('\u{a75b}', 42842), ('\u{a75d}', 42844), + ('\u{a75f}', 42846), ('\u{a761}', 42848), ('\u{a763}', 42850), ('\u{a765}', 42852), + ('\u{a767}', 42854), ('\u{a769}', 42856), ('\u{a76b}', 42858), ('\u{a76d}', 42860), + ('\u{a76f}', 42862), ('\u{a77a}', 42873), ('\u{a77c}', 42875), ('\u{a77f}', 42878), + ('\u{a781}', 42880), ('\u{a783}', 42882), ('\u{a785}', 42884), ('\u{a787}', 42886), + ('\u{a78c}', 42891), ('\u{a791}', 42896), ('\u{a793}', 42898), ('\u{a794}', 42948), + ('\u{a797}', 42902), ('\u{a799}', 42904), ('\u{a79b}', 42906), ('\u{a79d}', 42908), + ('\u{a79f}', 42910), ('\u{a7a1}', 42912), ('\u{a7a3}', 42914), ('\u{a7a5}', 42916), + ('\u{a7a7}', 42918), ('\u{a7a9}', 42920), ('\u{a7b5}', 42932), ('\u{a7b7}', 42934), + ('\u{a7b9}', 42936), ('\u{a7bb}', 42938), ('\u{a7bd}', 42940), ('\u{a7bf}', 42942), + ('\u{a7c1}', 42944), ('\u{a7c3}', 42946), ('\u{a7c8}', 42951), ('\u{a7ca}', 42953), + ('\u{a7cd}', 42956), ('\u{a7d1}', 42960), ('\u{a7d7}', 42966), ('\u{a7d9}', 42968), + ('\u{a7db}', 42970), ('\u{a7f6}', 42997), ('\u{ab53}', 42931), ('\u{ab70}', 5024), + ('\u{ab71}', 5025), ('\u{ab72}', 5026), ('\u{ab73}', 5027), ('\u{ab74}', 5028), + ('\u{ab75}', 5029), ('\u{ab76}', 5030), ('\u{ab77}', 5031), ('\u{ab78}', 5032), + ('\u{ab79}', 5033), ('\u{ab7a}', 5034), ('\u{ab7b}', 5035), ('\u{ab7c}', 5036), + ('\u{ab7d}', 5037), ('\u{ab7e}', 5038), ('\u{ab7f}', 5039), ('\u{ab80}', 5040), + ('\u{ab81}', 5041), ('\u{ab82}', 5042), ('\u{ab83}', 5043), ('\u{ab84}', 5044), + ('\u{ab85}', 5045), ('\u{ab86}', 5046), ('\u{ab87}', 5047), ('\u{ab88}', 5048), + ('\u{ab89}', 5049), ('\u{ab8a}', 5050), ('\u{ab8b}', 5051), ('\u{ab8c}', 5052), + ('\u{ab8d}', 5053), ('\u{ab8e}', 5054), ('\u{ab8f}', 5055), ('\u{ab90}', 5056), + ('\u{ab91}', 5057), ('\u{ab92}', 5058), ('\u{ab93}', 5059), ('\u{ab94}', 5060), + ('\u{ab95}', 5061), ('\u{ab96}', 5062), ('\u{ab97}', 5063), ('\u{ab98}', 5064), + ('\u{ab99}', 5065), ('\u{ab9a}', 5066), ('\u{ab9b}', 5067), ('\u{ab9c}', 5068), + ('\u{ab9d}', 5069), ('\u{ab9e}', 5070), ('\u{ab9f}', 5071), ('\u{aba0}', 5072), + ('\u{aba1}', 5073), ('\u{aba2}', 5074), ('\u{aba3}', 5075), ('\u{aba4}', 5076), + ('\u{aba5}', 5077), ('\u{aba6}', 5078), ('\u{aba7}', 5079), ('\u{aba8}', 5080), + ('\u{aba9}', 5081), ('\u{abaa}', 5082), ('\u{abab}', 5083), ('\u{abac}', 5084), + ('\u{abad}', 5085), ('\u{abae}', 5086), ('\u{abaf}', 5087), ('\u{abb0}', 5088), + ('\u{abb1}', 5089), ('\u{abb2}', 5090), ('\u{abb3}', 5091), ('\u{abb4}', 5092), + ('\u{abb5}', 5093), ('\u{abb6}', 5094), ('\u{abb7}', 5095), ('\u{abb8}', 5096), + ('\u{abb9}', 5097), ('\u{abba}', 5098), ('\u{abbb}', 5099), ('\u{abbc}', 5100), + ('\u{abbd}', 5101), ('\u{abbe}', 5102), ('\u{abbf}', 5103), ('\u{fb00}', 4194394), + ('\u{fb01}', 4194395), ('\u{fb02}', 4194396), ('\u{fb03}', 4194397), ('\u{fb04}', 4194398), + ('\u{fb05}', 4194399), ('\u{fb06}', 4194400), ('\u{fb13}', 4194401), ('\u{fb14}', 4194402), + ('\u{fb15}', 4194403), ('\u{fb16}', 4194404), ('\u{fb17}', 4194405), ('\u{ff41}', 65313), + ('\u{ff42}', 65314), ('\u{ff43}', 65315), ('\u{ff44}', 65316), ('\u{ff45}', 65317), + ('\u{ff46}', 65318), ('\u{ff47}', 65319), ('\u{ff48}', 65320), ('\u{ff49}', 65321), + ('\u{ff4a}', 65322), ('\u{ff4b}', 65323), ('\u{ff4c}', 65324), ('\u{ff4d}', 65325), + ('\u{ff4e}', 65326), ('\u{ff4f}', 65327), ('\u{ff50}', 65328), ('\u{ff51}', 65329), + ('\u{ff52}', 65330), ('\u{ff53}', 65331), ('\u{ff54}', 65332), ('\u{ff55}', 65333), + ('\u{ff56}', 65334), ('\u{ff57}', 65335), ('\u{ff58}', 65336), ('\u{ff59}', 65337), + ('\u{ff5a}', 65338), ('\u{10428}', 66560), ('\u{10429}', 66561), ('\u{1042a}', 66562), + ('\u{1042b}', 66563), ('\u{1042c}', 66564), ('\u{1042d}', 66565), ('\u{1042e}', 66566), + ('\u{1042f}', 66567), ('\u{10430}', 66568), ('\u{10431}', 66569), ('\u{10432}', 66570), + ('\u{10433}', 66571), ('\u{10434}', 66572), ('\u{10435}', 66573), ('\u{10436}', 66574), + ('\u{10437}', 66575), ('\u{10438}', 66576), ('\u{10439}', 66577), ('\u{1043a}', 66578), + ('\u{1043b}', 66579), ('\u{1043c}', 66580), ('\u{1043d}', 66581), ('\u{1043e}', 66582), + ('\u{1043f}', 66583), ('\u{10440}', 66584), ('\u{10441}', 66585), ('\u{10442}', 66586), + ('\u{10443}', 66587), ('\u{10444}', 66588), ('\u{10445}', 66589), ('\u{10446}', 66590), + ('\u{10447}', 66591), ('\u{10448}', 66592), ('\u{10449}', 66593), ('\u{1044a}', 66594), + ('\u{1044b}', 66595), ('\u{1044c}', 66596), ('\u{1044d}', 66597), ('\u{1044e}', 66598), + ('\u{1044f}', 66599), ('\u{104d8}', 66736), ('\u{104d9}', 66737), ('\u{104da}', 66738), + ('\u{104db}', 66739), ('\u{104dc}', 66740), ('\u{104dd}', 66741), ('\u{104de}', 66742), + ('\u{104df}', 66743), ('\u{104e0}', 66744), ('\u{104e1}', 66745), ('\u{104e2}', 66746), + ('\u{104e3}', 66747), ('\u{104e4}', 66748), ('\u{104e5}', 66749), ('\u{104e6}', 66750), + ('\u{104e7}', 66751), ('\u{104e8}', 66752), ('\u{104e9}', 66753), ('\u{104ea}', 66754), + ('\u{104eb}', 66755), ('\u{104ec}', 66756), ('\u{104ed}', 66757), ('\u{104ee}', 66758), + ('\u{104ef}', 66759), ('\u{104f0}', 66760), ('\u{104f1}', 66761), ('\u{104f2}', 66762), + ('\u{104f3}', 66763), ('\u{104f4}', 66764), ('\u{104f5}', 66765), ('\u{104f6}', 66766), + ('\u{104f7}', 66767), ('\u{104f8}', 66768), ('\u{104f9}', 66769), ('\u{104fa}', 66770), + ('\u{104fb}', 66771), ('\u{10597}', 66928), ('\u{10598}', 66929), ('\u{10599}', 66930), + ('\u{1059a}', 66931), ('\u{1059b}', 66932), ('\u{1059c}', 66933), ('\u{1059d}', 66934), + ('\u{1059e}', 66935), ('\u{1059f}', 66936), ('\u{105a0}', 66937), ('\u{105a1}', 66938), + ('\u{105a3}', 66940), ('\u{105a4}', 66941), ('\u{105a5}', 66942), ('\u{105a6}', 66943), + ('\u{105a7}', 66944), ('\u{105a8}', 66945), ('\u{105a9}', 66946), ('\u{105aa}', 66947), + ('\u{105ab}', 66948), ('\u{105ac}', 66949), ('\u{105ad}', 66950), ('\u{105ae}', 66951), + ('\u{105af}', 66952), ('\u{105b0}', 66953), ('\u{105b1}', 66954), ('\u{105b3}', 66956), + ('\u{105b4}', 66957), ('\u{105b5}', 66958), ('\u{105b6}', 66959), ('\u{105b7}', 66960), + ('\u{105b8}', 66961), ('\u{105b9}', 66962), ('\u{105bb}', 66964), ('\u{105bc}', 66965), + ('\u{10cc0}', 68736), ('\u{10cc1}', 68737), ('\u{10cc2}', 68738), ('\u{10cc3}', 68739), + ('\u{10cc4}', 68740), ('\u{10cc5}', 68741), ('\u{10cc6}', 68742), ('\u{10cc7}', 68743), + ('\u{10cc8}', 68744), ('\u{10cc9}', 68745), ('\u{10cca}', 68746), ('\u{10ccb}', 68747), + ('\u{10ccc}', 68748), ('\u{10ccd}', 68749), ('\u{10cce}', 68750), ('\u{10ccf}', 68751), + ('\u{10cd0}', 68752), ('\u{10cd1}', 68753), ('\u{10cd2}', 68754), ('\u{10cd3}', 68755), + ('\u{10cd4}', 68756), ('\u{10cd5}', 68757), ('\u{10cd6}', 68758), ('\u{10cd7}', 68759), + ('\u{10cd8}', 68760), ('\u{10cd9}', 68761), ('\u{10cda}', 68762), ('\u{10cdb}', 68763), + ('\u{10cdc}', 68764), ('\u{10cdd}', 68765), ('\u{10cde}', 68766), ('\u{10cdf}', 68767), + ('\u{10ce0}', 68768), ('\u{10ce1}', 68769), ('\u{10ce2}', 68770), ('\u{10ce3}', 68771), + ('\u{10ce4}', 68772), ('\u{10ce5}', 68773), ('\u{10ce6}', 68774), ('\u{10ce7}', 68775), + ('\u{10ce8}', 68776), ('\u{10ce9}', 68777), ('\u{10cea}', 68778), ('\u{10ceb}', 68779), + ('\u{10cec}', 68780), ('\u{10ced}', 68781), ('\u{10cee}', 68782), ('\u{10cef}', 68783), + ('\u{10cf0}', 68784), ('\u{10cf1}', 68785), ('\u{10cf2}', 68786), ('\u{10d70}', 68944), + ('\u{10d71}', 68945), ('\u{10d72}', 68946), ('\u{10d73}', 68947), ('\u{10d74}', 68948), + ('\u{10d75}', 68949), ('\u{10d76}', 68950), ('\u{10d77}', 68951), ('\u{10d78}', 68952), + ('\u{10d79}', 68953), ('\u{10d7a}', 68954), ('\u{10d7b}', 68955), ('\u{10d7c}', 68956), + ('\u{10d7d}', 68957), ('\u{10d7e}', 68958), ('\u{10d7f}', 68959), ('\u{10d80}', 68960), + ('\u{10d81}', 68961), ('\u{10d82}', 68962), ('\u{10d83}', 68963), ('\u{10d84}', 68964), + ('\u{10d85}', 68965), ('\u{118c0}', 71840), ('\u{118c1}', 71841), ('\u{118c2}', 71842), + ('\u{118c3}', 71843), ('\u{118c4}', 71844), ('\u{118c5}', 71845), ('\u{118c6}', 71846), + ('\u{118c7}', 71847), ('\u{118c8}', 71848), ('\u{118c9}', 71849), ('\u{118ca}', 71850), + ('\u{118cb}', 71851), ('\u{118cc}', 71852), ('\u{118cd}', 71853), ('\u{118ce}', 71854), + ('\u{118cf}', 71855), ('\u{118d0}', 71856), ('\u{118d1}', 71857), ('\u{118d2}', 71858), + ('\u{118d3}', 71859), ('\u{118d4}', 71860), ('\u{118d5}', 71861), ('\u{118d6}', 71862), + ('\u{118d7}', 71863), ('\u{118d8}', 71864), ('\u{118d9}', 71865), ('\u{118da}', 71866), + ('\u{118db}', 71867), ('\u{118dc}', 71868), ('\u{118dd}', 71869), ('\u{118de}', 71870), + ('\u{118df}', 71871), ('\u{16e60}', 93760), ('\u{16e61}', 93761), ('\u{16e62}', 93762), + ('\u{16e63}', 93763), ('\u{16e64}', 93764), ('\u{16e65}', 93765), ('\u{16e66}', 93766), + ('\u{16e67}', 93767), ('\u{16e68}', 93768), ('\u{16e69}', 93769), ('\u{16e6a}', 93770), + ('\u{16e6b}', 93771), ('\u{16e6c}', 93772), ('\u{16e6d}', 93773), ('\u{16e6e}', 93774), + ('\u{16e6f}', 93775), ('\u{16e70}', 93776), ('\u{16e71}', 93777), ('\u{16e72}', 93778), + ('\u{16e73}', 93779), ('\u{16e74}', 93780), ('\u{16e75}', 93781), ('\u{16e76}', 93782), + ('\u{16e77}', 93783), ('\u{16e78}', 93784), ('\u{16e79}', 93785), ('\u{16e7a}', 93786), + ('\u{16e7b}', 93787), ('\u{16e7c}', 93788), ('\u{16e7d}', 93789), ('\u{16e7e}', 93790), + ('\u{16e7f}', 93791), ('\u{1e922}', 125184), ('\u{1e923}', 125185), ('\u{1e924}', 125186), + ('\u{1e925}', 125187), ('\u{1e926}', 125188), ('\u{1e927}', 125189), ('\u{1e928}', 125190), + ('\u{1e929}', 125191), ('\u{1e92a}', 125192), ('\u{1e92b}', 125193), ('\u{1e92c}', 125194), + ('\u{1e92d}', 125195), ('\u{1e92e}', 125196), ('\u{1e92f}', 125197), ('\u{1e930}', 125198), + ('\u{1e931}', 125199), ('\u{1e932}', 125200), ('\u{1e933}', 125201), ('\u{1e934}', 125202), + ('\u{1e935}', 125203), ('\u{1e936}', 125204), ('\u{1e937}', 125205), ('\u{1e938}', 125206), + ('\u{1e939}', 125207), ('\u{1e93a}', 125208), ('\u{1e93b}', 125209), ('\u{1e93c}', 125210), + ('\u{1e93d}', 125211), ('\u{1e93e}', 125212), ('\u{1e93f}', 125213), ('\u{1e940}', 125214), + ('\u{1e941}', 125215), ('\u{1e942}', 125216), ('\u{1e943}', 125217), ]; static UPPERCASE_TABLE_MULTI: &[[char; 3]] = &[ From c8d9bd488a17e71c78f1e982ad1a3a3d921cd76e Mon Sep 17 00:00:00 2001 From: Marcondiro <46560192+Marcondiro@users.noreply.github.com> Date: Tue, 10 Sep 2024 11:13:35 +0200 Subject: [PATCH 133/189] Bump unicode printable to version 16.0.0 --- library/core/src/unicode/printable.rs | 130 +++++++++++++++----------- 1 file changed, 73 insertions(+), 57 deletions(-) diff --git a/library/core/src/unicode/printable.rs b/library/core/src/unicode/printable.rs index 33c3ef8083de5..d8fb50e4ed296 100644 --- a/library/core/src/unicode/printable.rs +++ b/library/core/src/unicode/printable.rs @@ -118,7 +118,7 @@ const SINGLETONS0U: &[(u8, u8)] = &[ (0x30, 4), (0x31, 2), (0x32, 1), - (0xa7, 2), + (0xa7, 4), (0xa9, 2), (0xaa, 4), (0xab, 8), @@ -155,17 +155,18 @@ const SINGLETONS0L: &[u8] = &[ 0x11, 0x16, 0x17, 0x5b, 0x5c, 0xf6, 0xf7, 0xfe, 0xff, 0x80, 0x6d, 0x71, 0xde, 0xdf, 0x0e, 0x1f, 0x6e, 0x6f, 0x1c, 0x1d, 0x5f, 0x7d, 0x7e, 0xae, - 0xaf, 0x7f, 0xbb, 0xbc, 0x16, 0x17, 0x1e, 0x1f, + 0xaf, 0x4d, 0xbb, 0xbc, 0x16, 0x17, 0x1e, 0x1f, 0x46, 0x47, 0x4e, 0x4f, 0x58, 0x5a, 0x5c, 0x5e, 0x7e, 0x7f, 0xb5, 0xc5, 0xd4, 0xd5, 0xdc, 0xf0, 0xf1, 0xf5, 0x72, 0x73, 0x8f, 0x74, 0x75, 0x96, 0x26, 0x2e, 0x2f, 0xa7, 0xaf, 0xb7, 0xbf, 0xc7, 0xcf, 0xd7, 0xdf, 0x9a, 0x00, 0x40, 0x97, 0x98, - 0x30, 0x8f, 0x1f, 0xd2, 0xd4, 0xce, 0xff, 0x4e, - 0x4f, 0x5a, 0x5b, 0x07, 0x08, 0x0f, 0x10, 0x27, - 0x2f, 0xee, 0xef, 0x6e, 0x6f, 0x37, 0x3d, 0x3f, - 0x42, 0x45, 0x90, 0x91, 0x53, 0x67, 0x75, 0xc8, - 0xc9, 0xd0, 0xd1, 0xd8, 0xd9, 0xe7, 0xfe, 0xff, + 0x30, 0x8f, 0x1f, 0xce, 0xcf, 0xd2, 0xd4, 0xce, + 0xff, 0x4e, 0x4f, 0x5a, 0x5b, 0x07, 0x08, 0x0f, + 0x10, 0x27, 0x2f, 0xee, 0xef, 0x6e, 0x6f, 0x37, + 0x3d, 0x3f, 0x42, 0x45, 0x90, 0x91, 0x53, 0x67, + 0x75, 0xc8, 0xc9, 0xd0, 0xd1, 0xd8, 0xd9, 0xe7, + 0xfe, 0xff, ]; #[rustfmt::skip] const SINGLETONS1U: &[(u8, u8)] = &[ @@ -183,7 +184,7 @@ const SINGLETONS1U: &[(u8, u8)] = &[ (0x10, 1), (0x11, 2), (0x12, 5), - (0x13, 17), + (0x13, 28), (0x14, 1), (0x15, 2), (0x17, 2), @@ -211,7 +212,7 @@ const SINGLETONS1U: &[(u8, u8)] = &[ (0xee, 32), (0xf0, 4), (0xf8, 2), - (0xfa, 3), + (0xfa, 4), (0xfb, 1), ]; #[rustfmt::skip] @@ -224,23 +225,24 @@ const SINGLETONS1L: &[u8] = &[ 0xbd, 0x35, 0xe0, 0x12, 0x87, 0x89, 0x8e, 0x9e, 0x04, 0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31, 0x34, 0x3a, 0x45, 0x46, 0x49, 0x4a, 0x4e, 0x4f, 0x64, - 0x65, 0x5c, 0xb6, 0xb7, 0x1b, 0x1c, 0x07, 0x08, - 0x0a, 0x0b, 0x14, 0x17, 0x36, 0x39, 0x3a, 0xa8, - 0xa9, 0xd8, 0xd9, 0x09, 0x37, 0x90, 0x91, 0xa8, - 0x07, 0x0a, 0x3b, 0x3e, 0x66, 0x69, 0x8f, 0x92, - 0x11, 0x6f, 0x5f, 0xbf, 0xee, 0xef, 0x5a, 0x62, - 0xf4, 0xfc, 0xff, 0x53, 0x54, 0x9a, 0x9b, 0x2e, - 0x2f, 0x27, 0x28, 0x55, 0x9d, 0xa0, 0xa1, 0xa3, - 0xa4, 0xa7, 0xa8, 0xad, 0xba, 0xbc, 0xc4, 0x06, - 0x0b, 0x0c, 0x15, 0x1d, 0x3a, 0x3f, 0x45, 0x51, - 0xa6, 0xa7, 0xcc, 0xcd, 0xa0, 0x07, 0x19, 0x1a, - 0x22, 0x25, 0x3e, 0x3f, 0xe7, 0xec, 0xef, 0xff, - 0xc5, 0xc6, 0x04, 0x20, 0x23, 0x25, 0x26, 0x28, - 0x33, 0x38, 0x3a, 0x48, 0x4a, 0x4c, 0x50, 0x53, - 0x55, 0x56, 0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x63, - 0x65, 0x66, 0x6b, 0x73, 0x78, 0x7d, 0x7f, 0x8a, - 0xa4, 0xaa, 0xaf, 0xb0, 0xc0, 0xd0, 0xae, 0xaf, - 0x6e, 0x6f, 0xbe, 0x93, + 0x65, 0x8a, 0x8c, 0x8d, 0x8f, 0xb6, 0xc1, 0xc3, + 0xc4, 0xc6, 0xcb, 0xd6, 0x5c, 0xb6, 0xb7, 0x1b, + 0x1c, 0x07, 0x08, 0x0a, 0x0b, 0x14, 0x17, 0x36, + 0x39, 0x3a, 0xa8, 0xa9, 0xd8, 0xd9, 0x09, 0x37, + 0x90, 0x91, 0xa8, 0x07, 0x0a, 0x3b, 0x3e, 0x66, + 0x69, 0x8f, 0x92, 0x11, 0x6f, 0x5f, 0xbf, 0xee, + 0xef, 0x5a, 0x62, 0xf4, 0xfc, 0xff, 0x53, 0x54, + 0x9a, 0x9b, 0x2e, 0x2f, 0x27, 0x28, 0x55, 0x9d, + 0xa0, 0xa1, 0xa3, 0xa4, 0xa7, 0xa8, 0xad, 0xba, + 0xbc, 0xc4, 0x06, 0x0b, 0x0c, 0x15, 0x1d, 0x3a, + 0x3f, 0x45, 0x51, 0xa6, 0xa7, 0xcc, 0xcd, 0xa0, + 0x07, 0x19, 0x1a, 0x22, 0x25, 0x3e, 0x3f, 0xe7, + 0xec, 0xef, 0xff, 0xc5, 0xc6, 0x04, 0x20, 0x23, + 0x25, 0x26, 0x28, 0x33, 0x38, 0x3a, 0x48, 0x4a, + 0x4c, 0x50, 0x53, 0x55, 0x56, 0x58, 0x5a, 0x5c, + 0x5e, 0x60, 0x63, 0x65, 0x66, 0x6b, 0x73, 0x78, + 0x7d, 0x7f, 0x8a, 0xa4, 0xaa, 0xaf, 0xb0, 0xc0, + 0xd0, 0xae, 0xaf, 0x6e, 0x6f, 0xdd, 0xde, 0x93, ]; #[rustfmt::skip] const NORMAL0: &[u8] = &[ @@ -252,8 +254,8 @@ const NORMAL0: &[u8] = &[ 0x06, 0x11, 0x81, 0xac, 0x0e, 0x80, 0xab, 0x05, - 0x1f, 0x09, - 0x81, 0x1b, 0x03, + 0x1f, 0x08, + 0x81, 0x1c, 0x03, 0x19, 0x08, 0x01, 0x04, 0x2f, 0x04, @@ -318,11 +320,10 @@ const NORMAL0: &[u8] = &[ 0x80, 0xac, 0x06, 0x0a, 0x06, 0x2f, 0x31, - 0x4d, 0x03, - 0x80, 0xa4, 0x08, + 0x80, 0xf4, 0x08, 0x3c, 0x03, 0x0f, 0x03, - 0x3c, 0x07, + 0x3e, 0x05, 0x38, 0x08, 0x2b, 0x05, 0x82, 0xff, 0x11, @@ -332,7 +333,7 @@ const NORMAL0: &[u8] = &[ 0x21, 0x0f, 0x21, 0x0f, 0x80, 0x8c, 0x04, - 0x82, 0x97, 0x19, + 0x82, 0x9a, 0x16, 0x0b, 0x15, 0x88, 0x94, 0x05, 0x2f, 0x05, @@ -343,13 +344,12 @@ const NORMAL0: &[u8] = &[ 0x74, 0x0c, 0x80, 0xd6, 0x1a, 0x81, 0x10, 0x05, - 0x80, 0xdf, 0x0b, + 0x80, 0xe1, 0x09, 0xf2, 0x9e, 0x03, 0x37, 0x09, 0x81, 0x5c, 0x14, 0x80, 0xb8, 0x08, - 0x80, 0xcb, 0x05, - 0x0a, 0x18, + 0x80, 0xdd, 0x15, 0x3b, 0x03, 0x0a, 0x06, 0x38, 0x08, @@ -402,7 +402,8 @@ const NORMAL1: &[u8] = &[ 0x24, 0x04, 0x28, 0x08, 0x34, 0x0b, - 0x4e, 0x43, + 0x4e, 0x03, + 0x34, 0x0c, 0x81, 0x37, 0x09, 0x16, 0x0a, 0x08, 0x18, @@ -431,9 +432,13 @@ const NORMAL1: &[u8] = &[ 0x33, 0x0d, 0x33, 0x07, 0x2e, 0x08, - 0x0a, 0x81, 0x26, - 0x52, 0x4b, - 0x2b, 0x08, + 0x0a, 0x06, + 0x26, 0x03, + 0x1d, 0x08, + 0x02, 0x80, 0xd0, + 0x52, 0x10, + 0x03, 0x37, + 0x2c, 0x08, 0x2a, 0x16, 0x1a, 0x26, 0x1c, 0x14, @@ -453,7 +458,9 @@ const NORMAL1: &[u8] = &[ 0x51, 0x06, 0x01, 0x05, 0x10, 0x03, - 0x05, 0x80, 0x8b, + 0x05, 0x0b, + 0x59, 0x08, + 0x02, 0x1d, 0x62, 0x1e, 0x48, 0x08, 0x0a, 0x80, 0xa6, @@ -462,7 +469,8 @@ const NORMAL1: &[u8] = &[ 0x0a, 0x06, 0x0d, 0x13, 0x3a, 0x06, - 0x0a, 0x36, + 0x0a, 0x06, + 0x14, 0x1c, 0x2c, 0x04, 0x17, 0x80, 0xb9, 0x3c, 0x64, @@ -473,7 +481,9 @@ const NORMAL1: &[u8] = &[ 0x48, 0x08, 0x53, 0x0d, 0x49, 0x07, - 0x0a, 0x80, 0xf6, + 0x0a, 0x80, 0xb6, + 0x22, 0x0e, + 0x0a, 0x06, 0x46, 0x0a, 0x1d, 0x03, 0x47, 0x49, @@ -484,7 +494,7 @@ const NORMAL1: &[u8] = &[ 0x0a, 0x81, 0x36, 0x19, 0x07, 0x3b, 0x03, - 0x1c, 0x56, + 0x1d, 0x55, 0x01, 0x0f, 0x32, 0x0d, 0x83, 0x9b, 0x66, @@ -492,15 +502,18 @@ const NORMAL1: &[u8] = &[ 0x80, 0xc4, 0x8a, 0x4c, 0x63, 0x0d, 0x84, 0x30, 0x10, - 0x16, 0x8f, 0xaa, - 0x82, 0x47, 0xa1, 0xb9, + 0x16, 0x0a, + 0x8f, 0x9b, 0x05, + 0x82, 0x47, 0x9a, 0xb9, + 0x3a, 0x86, 0xc6, 0x82, 0x39, 0x07, 0x2a, 0x04, 0x5c, 0x06, 0x26, 0x0a, 0x46, 0x0a, 0x28, 0x05, - 0x13, 0x82, 0xb0, + 0x13, 0x81, 0xb0, + 0x3a, 0x80, 0xc6, 0x5b, 0x65, 0x4b, 0x04, 0x39, 0x07, @@ -508,8 +521,8 @@ const NORMAL1: &[u8] = &[ 0x05, 0x0b, 0x02, 0x0e, 0x97, 0xf8, 0x08, - 0x84, 0xd6, 0x2a, - 0x09, 0xa2, 0xe7, + 0x84, 0xd6, 0x29, + 0x0a, 0xa2, 0xe7, 0x81, 0x33, 0x0f, 0x01, 0x1d, 0x06, 0x0e, @@ -518,7 +531,9 @@ const NORMAL1: &[u8] = &[ 0x6b, 0x05, 0x0d, 0x03, 0x09, 0x07, - 0x10, 0x92, 0x60, + 0x10, 0x8f, 0x60, + 0x80, 0xfa, 0x06, + 0x81, 0xb4, 0x4c, 0x47, 0x09, 0x74, 0x3c, 0x80, 0xf6, 0x0a, @@ -543,7 +558,9 @@ const NORMAL1: &[u8] = &[ 0x1f, 0x11, 0x3a, 0x05, 0x01, 0x81, 0xd0, - 0x2a, 0x82, 0xe6, + 0x2a, 0x80, 0xd6, + 0x2b, 0x04, + 0x01, 0x81, 0xe0, 0x80, 0xf7, 0x29, 0x4c, 0x04, 0x0a, 0x04, @@ -575,14 +592,13 @@ const NORMAL1: &[u8] = &[ 0x38, 0x08, 0x0a, 0x06, 0x28, 0x08, - 0x22, 0x4e, + 0x2c, 0x04, + 0x02, 0x3e, 0x81, 0x54, 0x0c, 0x1d, 0x03, + 0x0a, 0x05, + 0x38, 0x07, + 0x1c, 0x06, 0x09, 0x07, - 0x36, 0x08, - 0x0e, 0x04, - 0x09, 0x07, - 0x09, 0x07, - 0x80, 0xcb, 0x25, - 0x0a, 0x84, 0x06, + 0x80, 0xfa, 0x84, 0x06, ]; From 96d545a33bb6dc4ed3c1c80b997cce2035c571a6 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 10 Sep 2024 20:16:43 +1000 Subject: [PATCH 134/189] coverage: Avoid referring to "coverage spans" in counter creation The counter-creation code needs to know which BCB nodes require counters, but isn't interested in why, so treat that as an opaque detail. --- .../src/coverage/counters.rs | 43 +++++++------------ 1 file changed, 15 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs index ea1c0d2df4517..c9eceff9b507b 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters.rs @@ -74,12 +74,11 @@ pub(super) struct CoverageCounters { } impl CoverageCounters { - /// Makes [`BcbCounter`] `Counter`s and `Expressions` for the `BasicCoverageBlock`s directly or - /// indirectly associated with coverage spans, and accumulates additional `Expression`s - /// representing intermediate values. + /// Ensures that each BCB node needing a counter has one, by creating physical + /// counters or counter expressions for nodes and edges as required. pub(super) fn make_bcb_counters( basic_coverage_blocks: &CoverageGraph, - bcb_has_coverage_spans: impl Fn(BasicCoverageBlock) -> bool, + bcb_needs_counter: impl Fn(BasicCoverageBlock) -> bool, ) -> Self { let num_bcbs = basic_coverage_blocks.num_nodes(); @@ -91,8 +90,7 @@ impl CoverageCounters { expressions_memo: FxHashMap::default(), }; - MakeBcbCounters::new(&mut this, basic_coverage_blocks) - .make_bcb_counters(bcb_has_coverage_spans); + MakeBcbCounters::new(&mut this, basic_coverage_blocks).make_bcb_counters(bcb_needs_counter); this } @@ -241,10 +239,7 @@ impl CoverageCounters { } } -/// Traverse the `CoverageGraph` and add either a `Counter` or `Expression` to every BCB, to be -/// injected with coverage spans. `Expressions` have no runtime overhead, so if a viable expression -/// (adding or subtracting two other counters or expressions) can compute the same result as an -/// embedded counter, an `Expression` should be used. +/// Helper struct that allows counter creation to inspect the BCB graph. struct MakeBcbCounters<'a> { coverage_counters: &'a mut CoverageCounters, basic_coverage_blocks: &'a CoverageGraph, @@ -264,30 +259,21 @@ impl<'a> MakeBcbCounters<'a> { /// One way to predict which branch executes the least is by considering loops. A loop is exited /// at a branch, so the branch that jumps to a `BasicCoverageBlock` outside the loop is almost /// always executed less than the branch that does not exit the loop. - fn make_bcb_counters(&mut self, bcb_has_coverage_spans: impl Fn(BasicCoverageBlock) -> bool) { + fn make_bcb_counters(&mut self, bcb_needs_counter: impl Fn(BasicCoverageBlock) -> bool) { debug!("make_bcb_counters(): adding a counter or expression to each BasicCoverageBlock"); - // Walk the `CoverageGraph`. For each `BasicCoverageBlock` node with an associated - // coverage span, add a counter. If the `BasicCoverageBlock` branches, add a counter or - // expression to each branch `BasicCoverageBlock` (if the branch BCB has only one incoming - // edge) or edge from the branching BCB to the branch BCB (if the branch BCB has multiple - // incoming edges). + // Traverse the coverage graph, ensuring that every node that needs a + // coverage counter has one. // - // The `TraverseCoverageGraphWithLoops` traversal ensures that, when a loop is encountered, - // all `BasicCoverageBlock` nodes in the loop are visited before visiting any node outside - // the loop. The `traversal` state includes a `context_stack`, providing a way to know if - // the current BCB is in one or more nested loops or not. + // The traversal tries to ensure that, when a loop is encountered, all + // nodes within the loop are visited before visiting any nodes outside + // the loop. It also keeps track of which loop(s) the traversal is + // currently inside. let mut traversal = TraverseCoverageGraphWithLoops::new(self.basic_coverage_blocks); while let Some(bcb) = traversal.next() { - if bcb_has_coverage_spans(bcb) { - debug!("{:?} has at least one coverage span. Get or make its counter", bcb); + let _span = debug_span!("traversal", ?bcb).entered(); + if bcb_needs_counter(bcb) { self.make_node_and_branch_counters(&traversal, bcb); - } else { - debug!( - "{:?} does not have any coverage spans. A counter will only be added if \ - and when a covered BCB has an expression dependency.", - bcb, - ); } } @@ -298,6 +284,7 @@ impl<'a> MakeBcbCounters<'a> { ); } + #[instrument(level = "debug", skip(self, traversal))] fn make_node_and_branch_counters( &mut self, traversal: &TraverseCoverageGraphWithLoops<'_>, From 8be70c7b2c88be04e07adcf0c2dafbd0e8a6d70f Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 10 Sep 2024 20:44:15 +1000 Subject: [PATCH 135/189] coverage: Avoid referring to out-edges as "branches" This makes the graph terminology a bit more consistent, and avoids potential confusion with branch coverage. --- .../src/coverage/counters.rs | 177 ++++++++---------- 1 file changed, 80 insertions(+), 97 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs index c9eceff9b507b..f55d6cf8efc71 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters.rs @@ -253,12 +253,6 @@ impl<'a> MakeBcbCounters<'a> { Self { coverage_counters, basic_coverage_blocks } } - /// If two `BasicCoverageBlock`s branch from another `BasicCoverageBlock`, one of the branches - /// can be counted by `Expression` by subtracting the other branch from the branching - /// block. Otherwise, the `BasicCoverageBlock` executed the least should have the `Counter`. - /// One way to predict which branch executes the least is by considering loops. A loop is exited - /// at a branch, so the branch that jumps to a `BasicCoverageBlock` outside the loop is almost - /// always executed less than the branch that does not exit the loop. fn make_bcb_counters(&mut self, bcb_needs_counter: impl Fn(BasicCoverageBlock) -> bool) { debug!("make_bcb_counters(): adding a counter or expression to each BasicCoverageBlock"); @@ -273,7 +267,7 @@ impl<'a> MakeBcbCounters<'a> { while let Some(bcb) = traversal.next() { let _span = debug_span!("traversal", ?bcb).entered(); if bcb_needs_counter(bcb) { - self.make_node_and_branch_counters(&traversal, bcb); + self.make_node_counter_and_out_edge_counters(&traversal, bcb); } } @@ -284,74 +278,66 @@ impl<'a> MakeBcbCounters<'a> { ); } + /// Make sure the given node has a node counter, and then make sure each of + /// its out-edges has an edge counter (if appropriate). #[instrument(level = "debug", skip(self, traversal))] - fn make_node_and_branch_counters( + fn make_node_counter_and_out_edge_counters( &mut self, traversal: &TraverseCoverageGraphWithLoops<'_>, from_bcb: BasicCoverageBlock, ) { // First, ensure that this node has a counter of some kind. - // We might also use its term later to compute one of the branch counters. + // We might also use that counter to compute one of the out-edge counters. let from_bcb_operand = self.get_or_make_counter_operand(from_bcb); - let branch_target_bcbs = self.basic_coverage_blocks.successors[from_bcb].as_slice(); + let successors = self.basic_coverage_blocks.successors[from_bcb].as_slice(); // If this node doesn't have multiple out-edges, or all of its out-edges // already have counters, then we don't need to create edge counters. - let needs_branch_counters = branch_target_bcbs.len() > 1 - && branch_target_bcbs - .iter() - .any(|&to_bcb| self.branch_has_no_counter(from_bcb, to_bcb)); - if !needs_branch_counters { + let needs_out_edge_counters = successors.len() > 1 + && successors.iter().any(|&to_bcb| self.edge_has_no_counter(from_bcb, to_bcb)); + if !needs_out_edge_counters { return; } - debug!( - "{from_bcb:?} has some branch(es) without counters:\n {}", - branch_target_bcbs - .iter() - .map(|&to_bcb| { - format!("{from_bcb:?}->{to_bcb:?}: {:?}", self.branch_counter(from_bcb, to_bcb)) - }) - .collect::>() - .join("\n "), - ); + if tracing::enabled!(tracing::Level::DEBUG) { + let _span = + debug_span!("node has some out-edges without counters", ?from_bcb).entered(); + for &to_bcb in successors { + debug!(?to_bcb, counter=?self.edge_counter(from_bcb, to_bcb)); + } + } - // Of the branch edges that don't have counters yet, one can be given an expression - // (computed from the other edges) instead of a dedicated counter. - let expression_to_bcb = self.choose_preferred_expression_branch(traversal, from_bcb); + // Of the out-edges that don't have counters yet, one can be given an expression + // (computed from the other out-edges) instead of a dedicated counter. + let expression_to_bcb = self.choose_out_edge_for_expression(traversal, from_bcb); - // For each branch arm other than the one that was chosen to get an expression, + // For each out-edge other than the one that was chosen to get an expression, // ensure that it has a counter (existing counter/expression or a new counter), - // and accumulate the corresponding terms into a single sum term. - let sum_of_all_other_branches: BcbCounter = { - let _span = debug_span!("sum_of_all_other_branches", ?expression_to_bcb).entered(); - branch_target_bcbs + // and accumulate the corresponding counters into a single sum expression. + let sum_of_all_other_out_edges: BcbCounter = { + let _span = debug_span!("sum_of_all_other_out_edges", ?expression_to_bcb).entered(); + successors .iter() .copied() - // Skip the chosen branch, since we'll calculate it from the other branches. + // Skip the chosen edge, since we'll calculate its count from this sum. .filter(|&to_bcb| to_bcb != expression_to_bcb) .fold(None, |accum, to_bcb| { let _span = debug_span!("to_bcb", ?accum, ?to_bcb).entered(); - let branch_counter = self.get_or_make_edge_counter_operand(from_bcb, to_bcb); - Some(self.coverage_counters.make_sum_expression(accum, branch_counter)) + let edge_counter = self.get_or_make_edge_counter_operand(from_bcb, to_bcb); + Some(self.coverage_counters.make_sum_expression(accum, edge_counter)) }) - .expect("there must be at least one other branch") + .expect("there must be at least one other out-edge") }; - // For the branch that was chosen to get an expression, create that expression - // by taking the count of the node we're branching from, and subtracting the - // sum of all the other branches. - debug!( - "Making an expression for the selected expression_branch: \ - {expression_to_bcb:?} (expression_branch predecessors: {:?})", - self.bcb_predecessors(expression_to_bcb), - ); + // Now create an expression for the chosen edge, by taking the counter + // for its source node and subtracting the sum of its sibling out-edges. let expression = self.coverage_counters.make_expression( from_bcb_operand, Op::Subtract, - sum_of_all_other_branches, + sum_of_all_other_out_edges, ); + debug!("{expression_to_bcb:?} gets an expression: {expression:?}"); if self.basic_coverage_blocks.bcb_has_multiple_in_edges(expression_to_bcb) { self.coverage_counters.set_bcb_edge_counter(from_bcb, expression_to_bcb, expression); @@ -442,82 +428,79 @@ impl<'a> MakeBcbCounters<'a> { self.coverage_counters.set_bcb_edge_counter(from_bcb, to_bcb, counter_kind) } - /// Select a branch for the expression, either the recommended `reloop_branch`, or if none was - /// found, select any branch. - fn choose_preferred_expression_branch( + /// Choose one of the out-edges of `from_bcb` to receive an expression + /// instead of a physical counter, and returns that edge's target node. + /// + /// - Precondition: The node must have at least one out-edge without a counter. + /// - Postcondition: The selected edge does not have an edge counter. + fn choose_out_edge_for_expression( &self, traversal: &TraverseCoverageGraphWithLoops<'_>, from_bcb: BasicCoverageBlock, ) -> BasicCoverageBlock { - let good_reloop_branch = self.find_good_reloop_branch(traversal, from_bcb); - if let Some(reloop_target) = good_reloop_branch { - assert!(self.branch_has_no_counter(from_bcb, reloop_target)); + if let Some(reloop_target) = self.find_good_reloop_edge(traversal, from_bcb) { + assert!(self.edge_has_no_counter(from_bcb, reloop_target)); debug!("Selecting reloop target {reloop_target:?} to get an expression"); - reloop_target - } else { - let &branch_without_counter = self - .bcb_successors(from_bcb) - .iter() - .find(|&&to_bcb| self.branch_has_no_counter(from_bcb, to_bcb)) - .expect( - "needs_branch_counters was `true` so there should be at least one \ - branch", - ); - debug!( - "Selecting any branch={:?} that still needs a counter, to get the \ - `Expression` because there was no `reloop_branch`, or it already had a \ - counter", - branch_without_counter - ); - branch_without_counter + return reloop_target; } + + // We couldn't identify a "good" edge, so just choose any edge that + // doesn't already have a counter. + let arbitrary_target = self + .bcb_successors(from_bcb) + .iter() + .copied() + .find(|&to_bcb| self.edge_has_no_counter(from_bcb, to_bcb)) + .expect("precondition: at least one out-edge without a counter"); + debug!(?arbitrary_target, "selecting arbitrary out-edge to get an expression"); + arbitrary_target } - /// Tries to find a branch that leads back to the top of a loop, and that - /// doesn't already have a counter. Such branches are good candidates to + /// Tries to find an edge that leads back to the top of a loop, and that + /// doesn't already have a counter. Such edges are good candidates to /// be given an expression (instead of a physical counter), because they - /// will tend to be executed more times than a loop-exit branch. - fn find_good_reloop_branch( + /// will tend to be executed more times than a loop-exit edge. + fn find_good_reloop_edge( &self, traversal: &TraverseCoverageGraphWithLoops<'_>, from_bcb: BasicCoverageBlock, ) -> Option { - let branch_target_bcbs = self.bcb_successors(from_bcb); + let successors = self.bcb_successors(from_bcb); // Consider each loop on the current traversal context stack, top-down. for reloop_bcbs in traversal.reloop_bcbs_per_loop() { - let mut all_branches_exit_this_loop = true; + let mut all_edges_exit_this_loop = true; - // Try to find a branch that doesn't exit this loop and doesn't + // Try to find an out-edge that doesn't exit this loop and doesn't // already have a counter. - for &branch_target_bcb in branch_target_bcbs { - // A branch is a reloop branch if it dominates any BCB that has - // an edge back to the loop header. (Other branches are exits.) - let is_reloop_branch = reloop_bcbs.iter().any(|&reloop_bcb| { - self.basic_coverage_blocks.dominates(branch_target_bcb, reloop_bcb) + for &target_bcb in successors { + // An edge is a reloop edge if its target dominates any BCB that has + // an edge back to the loop header. (Otherwise it's an exit edge.) + let is_reloop_edge = reloop_bcbs.iter().any(|&reloop_bcb| { + self.basic_coverage_blocks.dominates(target_bcb, reloop_bcb) }); - if is_reloop_branch { - all_branches_exit_this_loop = false; - if self.branch_has_no_counter(from_bcb, branch_target_bcb) { - // We found a good branch to be given an expression. - return Some(branch_target_bcb); + if is_reloop_edge { + all_edges_exit_this_loop = false; + if self.edge_has_no_counter(from_bcb, target_bcb) { + // We found a good out-edge to be given an expression. + return Some(target_bcb); } - // Keep looking for another reloop branch without a counter. + // Keep looking for another reloop edge without a counter. } else { - // This branch exits the loop. + // This edge exits the loop. } } - if !all_branches_exit_this_loop { - // We found one or more reloop branches, but all of them already - // have counters. Let the caller choose one of the exit branches. - debug!("All reloop branches had counters; skip checking the other loops"); + if !all_edges_exit_this_loop { + // We found one or more reloop edges, but all of them already + // have counters. Let the caller choose one of the other edges. + debug!("All reloop edges had counters; skipping the other loops"); return None; } - // All of the branches exit this loop, so keep looking for a good - // reloop branch for one of the outer loops. + // All of the out-edges exit this loop, so keep looking for a good + // reloop edge for one of the outer loops. } None @@ -534,15 +517,15 @@ impl<'a> MakeBcbCounters<'a> { } #[inline] - fn branch_has_no_counter( + fn edge_has_no_counter( &self, from_bcb: BasicCoverageBlock, to_bcb: BasicCoverageBlock, ) -> bool { - self.branch_counter(from_bcb, to_bcb).is_none() + self.edge_counter(from_bcb, to_bcb).is_none() } - fn branch_counter( + fn edge_counter( &self, from_bcb: BasicCoverageBlock, to_bcb: BasicCoverageBlock, From 10cd5e8386a1ed20dc7fe07b481d3965e51e592f Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 10 Sep 2024 20:48:28 +1000 Subject: [PATCH 136/189] coverage: Avoid referring to "operands" in counter creation --- .../rustc_mir_transform/src/coverage/counters.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs index f55d6cf8efc71..1c240366afa2e 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters.rs @@ -288,7 +288,7 @@ impl<'a> MakeBcbCounters<'a> { ) { // First, ensure that this node has a counter of some kind. // We might also use that counter to compute one of the out-edge counters. - let from_bcb_operand = self.get_or_make_counter_operand(from_bcb); + let node_counter = self.get_or_make_node_counter(from_bcb); let successors = self.basic_coverage_blocks.successors[from_bcb].as_slice(); @@ -324,7 +324,7 @@ impl<'a> MakeBcbCounters<'a> { .filter(|&to_bcb| to_bcb != expression_to_bcb) .fold(None, |accum, to_bcb| { let _span = debug_span!("to_bcb", ?accum, ?to_bcb).entered(); - let edge_counter = self.get_or_make_edge_counter_operand(from_bcb, to_bcb); + let edge_counter = self.get_or_make_edge_counter(from_bcb, to_bcb); Some(self.coverage_counters.make_sum_expression(accum, edge_counter)) }) .expect("there must be at least one other out-edge") @@ -333,7 +333,7 @@ impl<'a> MakeBcbCounters<'a> { // Now create an expression for the chosen edge, by taking the counter // for its source node and subtracting the sum of its sibling out-edges. let expression = self.coverage_counters.make_expression( - from_bcb_operand, + node_counter, Op::Subtract, sum_of_all_other_out_edges, ); @@ -347,7 +347,7 @@ impl<'a> MakeBcbCounters<'a> { } #[instrument(level = "debug", skip(self))] - fn get_or_make_counter_operand(&mut self, bcb: BasicCoverageBlock) -> BcbCounter { + fn get_or_make_node_counter(&mut self, bcb: BasicCoverageBlock) -> BcbCounter { // If the BCB already has a counter, return it. if let Some(counter_kind) = self.coverage_counters.bcb_counters[bcb] { debug!("{bcb:?} already has a counter: {counter_kind:?}"); @@ -384,7 +384,7 @@ impl<'a> MakeBcbCounters<'a> { .copied() .fold(None, |accum, from_bcb| { let _span = debug_span!("from_bcb", ?accum, ?from_bcb).entered(); - let edge_counter = self.get_or_make_edge_counter_operand(from_bcb, bcb); + let edge_counter = self.get_or_make_edge_counter(from_bcb, bcb); Some(self.coverage_counters.make_sum_expression(accum, edge_counter)) }) .expect("there must be at least one in-edge") @@ -395,7 +395,7 @@ impl<'a> MakeBcbCounters<'a> { } #[instrument(level = "debug", skip(self))] - fn get_or_make_edge_counter_operand( + fn get_or_make_edge_counter( &mut self, from_bcb: BasicCoverageBlock, to_bcb: BasicCoverageBlock, @@ -404,13 +404,13 @@ impl<'a> MakeBcbCounters<'a> { // a node counter instead, since it will have the same value. if !self.basic_coverage_blocks.bcb_has_multiple_in_edges(to_bcb) { assert_eq!([from_bcb].as_slice(), self.basic_coverage_blocks.predecessors[to_bcb]); - return self.get_or_make_counter_operand(to_bcb); + return self.get_or_make_node_counter(to_bcb); } // If the source BCB has only one successor (assumed to be the given target), an edge // counter is unnecessary. Just get or make a counter for the source BCB. if self.bcb_successors(from_bcb).len() == 1 { - return self.get_or_make_counter_operand(from_bcb); + return self.get_or_make_node_counter(from_bcb); } // If the edge already has a counter, return it. From 86075759cc96748e56d70f6e25bbf319141ea82f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 10 Sep 2024 13:18:20 +0200 Subject: [PATCH 137/189] abi/compatibility test: remove tests inside repr(C) wrappers --- tests/ui/abi/compatibility.rs | 52 ++++++++--------------------------- 1 file changed, 11 insertions(+), 41 deletions(-) diff --git a/tests/ui/abi/compatibility.rs b/tests/ui/abi/compatibility.rs index d37e793d9892d..9600c8dff67b1 100644 --- a/tests/ui/abi/compatibility.rs +++ b/tests/ui/abi/compatibility.rs @@ -189,7 +189,7 @@ mod prelude { #[cfg(not(host))] use prelude::*; -macro_rules! assert_abi_compatible { +macro_rules! test_abi_compatible { ($name:ident, $t1:ty, $t2:ty) => { mod $name { use super::*; @@ -212,16 +212,6 @@ impl Clone for Zst { } } -#[repr(C)] -struct ReprC1(T); -#[repr(C)] -struct ReprC2Int(i32, T); -#[repr(C)] -struct ReprC2Float(f32, T); -#[repr(C)] -struct ReprC4(T, Vec, Zst, T); -#[repr(C)] -struct ReprC4Mixed(T, f32, i32, T); #[repr(C)] enum ReprCEnum { Variant1, @@ -233,23 +223,6 @@ union ReprCUnion { something: ManuallyDrop, } -macro_rules! test_abi_compatible { - ($name:ident, $t1:ty, $t2:ty) => { - mod $name { - use super::*; - assert_abi_compatible!(plain, $t1, $t2); - // We also do some tests with differences in fields of `repr(C)` types. - assert_abi_compatible!(repr_c_1, ReprC1<$t1>, ReprC1<$t2>); - assert_abi_compatible!(repr_c_2_int, ReprC2Int<$t1>, ReprC2Int<$t2>); - assert_abi_compatible!(repr_c_2_float, ReprC2Float<$t1>, ReprC2Float<$t2>); - assert_abi_compatible!(repr_c_4, ReprC4<$t1>, ReprC4<$t2>); - assert_abi_compatible!(repr_c_4mixed, ReprC4Mixed<$t1>, ReprC4Mixed<$t2>); - assert_abi_compatible!(repr_c_enum, ReprCEnum<$t1>, ReprCEnum<$t2>); - assert_abi_compatible!(repr_c_union, ReprCUnion<$t1>, ReprCUnion<$t2>); - } - }; -} - // Compatibility of pointers. test_abi_compatible!(ptr_mut, *const i32, *mut i32); test_abi_compatible!(ptr_pointee, *const i32, *const Vec); @@ -268,7 +241,6 @@ test_abi_compatible!(isize_int, isize, i64); // Compatibility of 1-ZST. test_abi_compatible!(zst_unit, Zst, ()); -#[cfg(not(any(target_arch = "sparc64")))] test_abi_compatible!(zst_array, Zst, [u8; 0]); test_abi_compatible!(nonzero_int, NonZero, i32); @@ -285,13 +257,13 @@ test_abi_compatible!(arc, Arc, *mut i32); // `repr(transparent)` compatibility. #[repr(transparent)] -struct Wrapper1(T); +struct TransparentWrapper1(T); #[repr(transparent)] -struct Wrapper2((), Zst, T); +struct TransparentWrapper2((), Zst, T); #[repr(transparent)] -struct Wrapper3(T, [u8; 0], PhantomData); +struct TransparentWrapper3(T, [u8; 0], PhantomData); #[repr(transparent)] -union WrapperUnion { +union TransparentWrapperUnion { nothing: (), something: ManuallyDrop, } @@ -300,10 +272,10 @@ macro_rules! test_transparent { ($name:ident, $t:ty) => { mod $name { use super::*; - test_abi_compatible!(wrap1, $t, Wrapper1<$t>); - test_abi_compatible!(wrap2, $t, Wrapper2<$t>); - test_abi_compatible!(wrap3, $t, Wrapper3<$t>); - test_abi_compatible!(wrap4, $t, WrapperUnion<$t>); + test_abi_compatible!(wrap1, $t, TransparentWrapper1<$t>); + test_abi_compatible!(wrap2, $t, TransparentWrapper2<$t>); + test_abi_compatible!(wrap3, $t, TransparentWrapper3<$t>); + test_abi_compatible!(wrap4, $t, TransparentWrapperUnion<$t>); } }; } @@ -342,10 +314,8 @@ macro_rules! test_transparent_unsized { ($name:ident, $t:ty) => { mod $name { use super::*; - assert_abi_compatible!(wrap1, $t, Wrapper1<$t>); - assert_abi_compatible!(wrap1_reprc, ReprC1<$t>, ReprC1>); - assert_abi_compatible!(wrap2, $t, Wrapper2<$t>); - assert_abi_compatible!(wrap2_reprc, ReprC1<$t>, ReprC1>); + test_abi_compatible!(wrap1, $t, TransparentWrapper1<$t>); + test_abi_compatible!(wrap2, $t, TransparentWrapper2<$t>); } }; } From 6ca5ec7b4ef0466a1cdf3fbce9212cabc171d21a Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Tue, 10 Sep 2024 14:42:17 +0200 Subject: [PATCH 138/189] disallow `naked_asm!` outside of `#[naked]` functions --- compiler/rustc_ast/src/ast.rs | 11 +++++ compiler/rustc_ast/src/mut_visit.rs | 1 + compiler/rustc_ast/src/visit.rs | 1 + compiler/rustc_ast_lowering/src/asm.rs | 10 +++- compiler/rustc_builtin_macros/src/asm.rs | 11 +++-- compiler/rustc_hir/src/hir.rs | 1 + compiler/rustc_passes/messages.ftl | 3 ++ compiler/rustc_passes/src/errors.rs | 7 +++ compiler/rustc_passes/src/naked_functions.rs | 48 ++++++++++++++----- tests/ui/asm/naked-asm-outside-naked-fn.rs | 35 ++++++++++++++ .../ui/asm/naked-asm-outside-naked-fn.stderr | 20 ++++++++ 11 files changed, 132 insertions(+), 16 deletions(-) create mode 100644 tests/ui/asm/naked-asm-outside-naked-fn.rs create mode 100644 tests/ui/asm/naked-asm-outside-naked-fn.stderr diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 85d38a0e28b0f..42741bdca2295 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2418,11 +2418,22 @@ impl InlineAsmOperand { } } +#[derive(Clone, Copy, Encodable, Decodable, Debug, HashStable_Generic)] +pub enum AsmMacro { + /// The `asm!` macro + Asm, + /// The `global_asm!` macro + GlobalAsm, + /// The `naked_asm!` macro + NakedAsm, +} + /// Inline assembly. /// /// E.g., `asm!("NOP");`. #[derive(Clone, Encodable, Decodable, Debug)] pub struct InlineAsm { + pub asm_macro: AsmMacro, pub template: Vec, pub template_strs: Box<[(Symbol, Option, Span)]>, pub operands: Vec<(InlineAsmOperand, Span)>, diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 7c8af6c4a5564..1bef51aa73f7b 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1388,6 +1388,7 @@ fn walk_anon_const(vis: &mut T, AnonConst { id, value }: &mut Ano fn walk_inline_asm(vis: &mut T, asm: &mut InlineAsm) { // FIXME: Visit spans inside all this currently ignored stuff. let InlineAsm { + asm_macro: _, template: _, template_strs: _, operands, diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 7b041768983e6..bae7ad93f90fa 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -976,6 +976,7 @@ pub fn walk_anon_const<'a, V: Visitor<'a>>(visitor: &mut V, constant: &'a AnonCo pub fn walk_inline_asm<'a, V: Visitor<'a>>(visitor: &mut V, asm: &'a InlineAsm) -> V::Result { let InlineAsm { + asm_macro: _, template: _, template_strs: _, operands, diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index e077c54496586..4413c259efbf3 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -474,8 +474,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ); let line_spans = self.arena.alloc_from_iter(asm.line_spans.iter().map(|span| self.lower_span(*span))); - let hir_asm = - hir::InlineAsm { template, template_strs, operands, options: asm.options, line_spans }; + let hir_asm = hir::InlineAsm { + asm_macro: asm.asm_macro, + template, + template_strs, + operands, + options: asm.options, + line_spans, + }; self.arena.alloc(hir_asm) } } diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index e313016e3d863..d6248899655dc 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -3,6 +3,7 @@ use lint::BuiltinLintDiag; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter}; use rustc_ast::tokenstream::TokenStream; +use rustc_ast::AsmMacro; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_errors::PResult; use rustc_expand::base::*; @@ -484,6 +485,7 @@ fn parse_reg<'a>( fn expand_preparsed_asm( ecx: &mut ExtCtxt<'_>, + asm_macro: ast::AsmMacro, args: AsmArgs, ) -> ExpandResult, ()> { let mut template = vec![]; @@ -774,6 +776,7 @@ fn expand_preparsed_asm( } ExpandResult::Ready(Ok(ast::InlineAsm { + asm_macro, template, template_strs: template_strs.into_boxed_slice(), operands: args.operands, @@ -790,7 +793,7 @@ pub(super) fn expand_asm<'cx>( ) -> MacroExpanderResult<'cx> { ExpandResult::Ready(match parse_args(ecx, sp, tts, false) { Ok(args) => { - let ExpandResult::Ready(mac) = expand_preparsed_asm(ecx, args) else { + let ExpandResult::Ready(mac) = expand_preparsed_asm(ecx, AsmMacro::Asm, args) else { return ExpandResult::Retry(()); }; let expr = match mac { @@ -819,7 +822,8 @@ pub(super) fn expand_naked_asm<'cx>( ) -> MacroExpanderResult<'cx> { ExpandResult::Ready(match parse_args(ecx, sp, tts, false) { Ok(args) => { - let ExpandResult::Ready(mac) = expand_preparsed_asm(ecx, args) else { + let ExpandResult::Ready(mac) = expand_preparsed_asm(ecx, AsmMacro::NakedAsm, args) + else { return ExpandResult::Retry(()); }; let expr = match mac { @@ -857,7 +861,8 @@ pub(super) fn expand_global_asm<'cx>( ) -> MacroExpanderResult<'cx> { ExpandResult::Ready(match parse_args(ecx, sp, tts, true) { Ok(args) => { - let ExpandResult::Ready(mac) = expand_preparsed_asm(ecx, args) else { + let ExpandResult::Ready(mac) = expand_preparsed_asm(ecx, AsmMacro::GlobalAsm, args) + else { return ExpandResult::Retry(()); }; match mac { diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index b01c24cf3053e..ee03f780e16f5 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2927,6 +2927,7 @@ impl<'hir> InlineAsmOperand<'hir> { #[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct InlineAsm<'hir> { + pub asm_macro: ast::AsmMacro, pub template: &'hir [InlineAsmTemplatePiece], pub template_strs: &'hir [(Symbol, Option, Span)], pub operands: &'hir [(InlineAsmOperand<'hir>, Span)], diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index e7f208d5ad544..5369f54afb908 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -484,6 +484,9 @@ passes_must_not_suspend = passes_must_use_no_effect = `#[must_use]` has no effect when applied to {$article} {$target} +passes_naked_asm_outside_naked_fn = + the `naked_asm!` macro can only be used in functions marked with `#[naked]` + passes_naked_functions_asm_block = naked functions must contain a single asm block .label_multiple_asm = multiple asm blocks are unsupported in naked functions diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index f5d982e1a5cd1..a985ecb019a19 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1221,6 +1221,13 @@ pub(crate) struct NakedFunctionIncompatibleAttribute { pub attr: Symbol, } +#[derive(Diagnostic)] +#[diag(passes_naked_asm_outside_naked_fn)] +pub(crate) struct NakedAsmOutsideNakedFn { + #[primary_span] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(passes_attr_only_in_functions)] pub(crate) struct AttrOnlyInFunctions { diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs index b72ce239c4a96..ab6385dd7d738 100644 --- a/compiler/rustc_passes/src/naked_functions.rs +++ b/compiler/rustc_passes/src/naked_functions.rs @@ -6,6 +6,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::{LocalDefId, LocalModDefId}; use rustc_hir::intravisit::Visitor; use rustc_hir::{ExprKind, HirIdSet, InlineAsmOperand, StmtKind}; +use rustc_middle::hir::nested_filter::OnlyBodies; use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_session::lint::builtin::UNDEFINED_NAKED_FUNCTION_ABI; @@ -14,8 +15,9 @@ use rustc_span::Span; use rustc_target::spec::abi::Abi; use crate::errors::{ - NakedFunctionsAsmBlock, NakedFunctionsAsmOptions, NakedFunctionsMustUseNoreturn, - NakedFunctionsOperands, NoPatterns, ParamsNotAllowed, UndefinedNakedFunctionAbi, + NakedAsmOutsideNakedFn, NakedFunctionsAsmBlock, NakedFunctionsAsmOptions, + NakedFunctionsMustUseNoreturn, NakedFunctionsOperands, NoPatterns, ParamsNotAllowed, + UndefinedNakedFunctionAbi, }; pub(crate) fn provide(providers: &mut Providers) { @@ -29,11 +31,6 @@ fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { continue; } - let naked = tcx.has_attr(def_id, sym::naked); - if !naked { - continue; - } - let (fn_header, body_id) = match tcx.hir_node_by_def_id(def_id) { hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. }) | hir::Node::TraitItem(hir::TraitItem { @@ -48,10 +45,17 @@ fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { }; let body = tcx.hir().body(body_id); - check_abi(tcx, def_id, fn_header.abi); - check_no_patterns(tcx, body.params); - check_no_parameters_use(tcx, body); - check_asm(tcx, def_id, body); + + if tcx.has_attr(def_id, sym::naked) { + check_abi(tcx, def_id, fn_header.abi); + check_no_patterns(tcx, body.params); + check_no_parameters_use(tcx, body); + check_asm(tcx, def_id, body); + } else { + // `naked_asm!` is not allowed outside of functions marked as `#[naked]` + let mut visitor = CheckNakedAsmInNakedFn { tcx }; + visitor.visit_body(body); + } } } @@ -276,3 +280,25 @@ impl<'tcx> Visitor<'tcx> for CheckInlineAssembly<'tcx> { self.check_expr(expr, expr.span); } } + +struct CheckNakedAsmInNakedFn<'tcx> { + tcx: TyCtxt<'tcx>, +} + +impl<'tcx> Visitor<'tcx> for CheckNakedAsmInNakedFn<'tcx> { + type NestedFilter = OnlyBodies; + + fn nested_visit_map(&mut self) -> Self::Map { + self.tcx.hir() + } + + fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { + if let ExprKind::InlineAsm(inline_asm) = expr.kind { + if let rustc_ast::AsmMacro::NakedAsm = inline_asm.asm_macro { + self.tcx.dcx().emit_err(NakedAsmOutsideNakedFn { span: expr.span }); + } + } + + hir::intravisit::walk_expr(self, expr); + } +} diff --git a/tests/ui/asm/naked-asm-outside-naked-fn.rs b/tests/ui/asm/naked-asm-outside-naked-fn.rs new file mode 100644 index 0000000000000..1696008f3397d --- /dev/null +++ b/tests/ui/asm/naked-asm-outside-naked-fn.rs @@ -0,0 +1,35 @@ +//@ edition: 2021 +//@ needs-asm-support +//@ ignore-nvptx64 +//@ ignore-spirv + +#![feature(naked_functions)] +#![crate_type = "lib"] + +use std::arch::naked_asm; + +fn main() { + test1(); +} + +#[naked] +extern "C" fn test1() { + unsafe { naked_asm!("") } +} + +extern "C" fn test2() { + unsafe { naked_asm!("") } + //~^ ERROR the `naked_asm!` macro can only be used in functions marked with `#[naked]` +} + +extern "C" fn test3() { + unsafe { (|| naked_asm!(""))() } + //~^ ERROR the `naked_asm!` macro can only be used in functions marked with `#[naked]` +} + +fn test4() { + async move { + unsafe { naked_asm!("") } ; + //~^ ERROR the `naked_asm!` macro can only be used in functions marked with `#[naked]` + }; +} diff --git a/tests/ui/asm/naked-asm-outside-naked-fn.stderr b/tests/ui/asm/naked-asm-outside-naked-fn.stderr new file mode 100644 index 0000000000000..6e91359669ca2 --- /dev/null +++ b/tests/ui/asm/naked-asm-outside-naked-fn.stderr @@ -0,0 +1,20 @@ +error: the `naked_asm!` macro can only be used in functions marked with `#[naked]` + --> $DIR/naked-asm-outside-naked-fn.rs:21:14 + | +LL | unsafe { naked_asm!("") } + | ^^^^^^^^^^^^^^ + +error: the `naked_asm!` macro can only be used in functions marked with `#[naked]` + --> $DIR/naked-asm-outside-naked-fn.rs:26:18 + | +LL | unsafe { (|| naked_asm!(""))() } + | ^^^^^^^^^^^^^^ + +error: the `naked_asm!` macro can only be used in functions marked with `#[naked]` + --> $DIR/naked-asm-outside-naked-fn.rs:32:19 + | +LL | unsafe { naked_asm!("") } ; + | ^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + From 7a57a74bf52306d18d265fa4b498064634c91652 Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 10 Sep 2024 15:21:57 +0200 Subject: [PATCH 139/189] generalize: track relevant info in cache key --- .../rustc_infer/src/infer/relate/generalize.rs | 18 +++++++++--------- .../occurs-check/unused-substs-3.rs | 6 ++++-- .../occurs-check/unused-substs-3.stderr | 8 +++----- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index f2a511d7a886b..fbe64f47741ba 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -259,11 +259,11 @@ impl<'tcx> InferCtxt<'tcx> { structurally_relate_aliases, root_vid, for_universe, - ambient_variance, root_term: source_term.into(), + ambient_variance, in_alias: false, - has_unconstrained_ty_var: false, cache: Default::default(), + has_unconstrained_ty_var: false, }; let value_may_be_infer = generalizer.relate(source_term, source_term)?; @@ -304,14 +304,12 @@ struct Generalizer<'me, 'tcx> { /// we reject the relation. for_universe: ty::UniverseIndex, - /// After we generalize this type, we are going to relate it to - /// some other type. What will be the variance at this point? - ambient_variance: ty::Variance, - /// The root term (const or type) we're generalizing. Used for cycle errors. root_term: Term<'tcx>, - cache: SsoHashMap, Ty<'tcx>>, + /// After we generalize this type, we are going to relate it to + /// some other type. What will be the variance at this point? + ambient_variance: ty::Variance, /// This is set once we're generalizing the arguments of an alias. /// @@ -320,6 +318,8 @@ struct Generalizer<'me, 'tcx> { /// hold by either normalizing the outer or the inner associated type. in_alias: bool, + cache: SsoHashMap<(Ty<'tcx>, ty::Variance, bool), Ty<'tcx>>, + /// See the field `has_unconstrained_ty_var` in `Generalization`. has_unconstrained_ty_var: bool, } @@ -451,7 +451,7 @@ impl<'tcx> TypeRelation> for Generalizer<'_, 'tcx> { fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { assert_eq!(t, t2); // we are misusing TypeRelation here; both LHS and RHS ought to be == - if let Some(&result) = self.cache.get(&t) { + if let Some(&result) = self.cache.get(&(t, self.ambient_variance, self.in_alias)) { return Ok(result); } @@ -557,7 +557,7 @@ impl<'tcx> TypeRelation> for Generalizer<'_, 'tcx> { _ => relate::structurally_relate_tys(self, t, t), }?; - self.cache.insert(t, g); + self.cache.insert((t, self.ambient_variance, self.in_alias), g); Ok(g) } diff --git a/tests/ui/const-generics/occurs-check/unused-substs-3.rs b/tests/ui/const-generics/occurs-check/unused-substs-3.rs index 6db18d587d3e2..dfb051192e2f3 100644 --- a/tests/ui/const-generics/occurs-check/unused-substs-3.rs +++ b/tests/ui/const-generics/occurs-check/unused-substs-3.rs @@ -11,9 +11,11 @@ fn bind() -> (T, [u8; 6 + 1]) { fn main() { let (mut t, foo) = bind(); + //~^ ERROR mismatched types + //~| NOTE cyclic type + // `t` is `ty::Infer(TyVar(?1t))` // `foo` contains `ty::Infer(TyVar(?1t))` in its substs t = foo; - //~^ ERROR mismatched types - //~| NOTE cyclic type + } diff --git a/tests/ui/const-generics/occurs-check/unused-substs-3.stderr b/tests/ui/const-generics/occurs-check/unused-substs-3.stderr index bcb59705c6b2f..30a2a7901bdf5 100644 --- a/tests/ui/const-generics/occurs-check/unused-substs-3.stderr +++ b/tests/ui/const-generics/occurs-check/unused-substs-3.stderr @@ -1,10 +1,8 @@ error[E0308]: mismatched types - --> $DIR/unused-substs-3.rs:16:9 + --> $DIR/unused-substs-3.rs:13:24 | -LL | t = foo; - | ^^^- help: try using a conversion method: `.to_vec()` - | | - | cyclic type of infinite size +LL | let (mut t, foo) = bind(); + | ^^^^^^ cyclic type of infinite size error: aborting due to 1 previous error From 713828d4f430e1393535f588e73dd5d8bb5d793a Mon Sep 17 00:00:00 2001 From: Florian Schmiderer Date: Fri, 6 Sep 2024 23:41:16 +0200 Subject: [PATCH 140/189] Add test for S_OBJNAME and update test for LF_BUILDINFO cl and cmd for pdb files. --- .../src/external_deps/llvm.rs | 6 +++++ .../pdb-buildinfo-cl-cmd/filecheck.txt | 4 ++++ tests/run-make/pdb-buildinfo-cl-cmd/rmake.rs | 24 ++++--------------- tests/run-make/pdb-sobjname/main.rs | 1 + tests/run-make/pdb-sobjname/rmake.rs | 20 ++++++++++++++++ 5 files changed, 36 insertions(+), 19 deletions(-) create mode 100644 tests/run-make/pdb-buildinfo-cl-cmd/filecheck.txt create mode 100644 tests/run-make/pdb-sobjname/main.rs create mode 100644 tests/run-make/pdb-sobjname/rmake.rs diff --git a/src/tools/run-make-support/src/external_deps/llvm.rs b/src/tools/run-make-support/src/external_deps/llvm.rs index 16c4251998fb2..38a9ac923b4dc 100644 --- a/src/tools/run-make-support/src/external_deps/llvm.rs +++ b/src/tools/run-make-support/src/external_deps/llvm.rs @@ -54,6 +54,12 @@ pub fn llvm_dwarfdump() -> LlvmDwarfdump { LlvmDwarfdump::new() } +/// Construct a new `llvm-pdbutil` invocation. This assumes that `llvm-pdbutil` is available +/// at `$LLVM_BIN_DIR/llvm-pdbutil`. +pub fn llvm_pdbutil() -> LlvmPdbutil { + LlvmPdbutil::new() +} + /// A `llvm-readobj` invocation builder. #[derive(Debug)] #[must_use] diff --git a/tests/run-make/pdb-buildinfo-cl-cmd/filecheck.txt b/tests/run-make/pdb-buildinfo-cl-cmd/filecheck.txt new file mode 100644 index 0000000000000..a01999d5bdf76 --- /dev/null +++ b/tests/run-make/pdb-buildinfo-cl-cmd/filecheck.txt @@ -0,0 +1,4 @@ +CHECK: LF_BUILDINFO +CHECK: rustc.exe +CHECK: main.rs +CHECK: "-g" "--crate-name" "my_crate_name" "--crate-type" "bin" "-Cmetadata=dc9ef878b0a48666" diff --git a/tests/run-make/pdb-buildinfo-cl-cmd/rmake.rs b/tests/run-make/pdb-buildinfo-cl-cmd/rmake.rs index 2ab9057b24c1b..9418f4f8d84d3 100644 --- a/tests/run-make/pdb-buildinfo-cl-cmd/rmake.rs +++ b/tests/run-make/pdb-buildinfo-cl-cmd/rmake.rs @@ -7,7 +7,7 @@ //@ only-windows-msvc // Reason: pdb files are unique to this architecture -use run_make_support::{assert_contains, bstr, env_var, rfs, rustc}; +use run_make_support::{llvm, rustc}; fn main() { rustc() @@ -17,23 +17,9 @@ fn main() { .crate_type("bin") .metadata("dc9ef878b0a48666") .run(); - let tests = [ - &env_var("RUSTC"), - r#""main.rs""#, - r#""-g""#, - r#""--crate-name""#, - r#""my_crate_name""#, - r#""--crate-type""#, - r#""bin""#, - r#""-Cmetadata=dc9ef878b0a48666""#, - ]; - for test in tests { - assert_pdb_contains(test); - } -} -fn assert_pdb_contains(needle: &str) { - let needle = needle.as_bytes(); - use bstr::ByteSlice; - assert!(&rfs::read("my_crate_name.pdb").find(needle).is_some()); + let pdbutil_result = + llvm::llvm_pdbutil().arg("dump").arg("-ids").input("my_crate_name.pdb").run(); + + llvm::llvm_filecheck().patterns("filecheck.txt").stdin_buf(pdbutil_result.stdout_utf8()).run(); } diff --git a/tests/run-make/pdb-sobjname/main.rs b/tests/run-make/pdb-sobjname/main.rs new file mode 100644 index 0000000000000..f328e4d9d04c3 --- /dev/null +++ b/tests/run-make/pdb-sobjname/main.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/tests/run-make/pdb-sobjname/rmake.rs b/tests/run-make/pdb-sobjname/rmake.rs new file mode 100644 index 0000000000000..83c39fdccd3c7 --- /dev/null +++ b/tests/run-make/pdb-sobjname/rmake.rs @@ -0,0 +1,20 @@ +// Check if the pdb file contains an S_OBJNAME entry with the name of the .o file + +// This is because it used to be missing in #96475. +// See https://github.com/rust-lang/rust/pull/115704 + +//@ only-windows-msvc +// Reason: pdb files are unique to this architecture + +use run_make_support::{llvm, rustc}; + +fn main() { + rustc().input("main.rs").arg("-g").crate_name("my_great_crate_name").crate_type("bin").run(); + + let pdbutil_result = llvm::llvm_pdbutil() + .arg("dump") + .arg("-symbols") + .input("my_great_crate_name.pdb") + .run() + .assert_stdout_contains_regex("S_OBJNAME.+my_great_crate_name.*\\.o"); +} From 35ce85e0fd6ae70ffb61139c1fcdb739e0ca1d95 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 9 Sep 2024 21:09:30 +0300 Subject: [PATCH 141/189] handle `GitConfig` for `tools/compiletest` Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/test.rs | 1 + src/tools/compiletest/src/common.rs | 7 ++++++- src/tools/compiletest/src/header/tests.rs | 1 + src/tools/compiletest/src/lib.rs | 4 +++- 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 83f65615c8ded..a7e9352bb1c4c 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -2098,6 +2098,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the let git_config = builder.config.git_config(); cmd.arg("--git-repository").arg(git_config.git_repository); cmd.arg("--nightly-branch").arg(git_config.nightly_branch); + cmd.arg("--git-merge-commit-email").arg(git_config.git_merge_commit_email); cmd.force_coloring_in_ci(); #[cfg(feature = "build-metrics")] diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 773d795f75a72..5c18179b6fe2f 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -384,6 +384,7 @@ pub struct Config { // Needed both to construct build_helper::git::GitConfig pub git_repository: String, pub nightly_branch: String, + pub git_merge_commit_email: String, /// True if the profiler runtime is enabled for this target. /// Used by the "needs-profiler-support" header in test files. @@ -461,7 +462,11 @@ impl Config { } pub fn git_config(&self) -> GitConfig<'_> { - GitConfig { git_repository: &self.git_repository, nightly_branch: &self.nightly_branch } + GitConfig { + git_repository: &self.git_repository, + nightly_branch: &self.nightly_branch, + git_merge_commit_email: &self.git_merge_commit_email, + } } } diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 29e11e77f1ce1..3a9a7eb911889 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -148,6 +148,7 @@ impl ConfigBuilder { self.target.as_deref().unwrap_or("x86_64-unknown-linux-gnu"), "--git-repository=", "--nightly-branch=", + "--git-merge-commit-email=", ]; let mut args: Vec = args.iter().map(ToString::to_string).collect(); diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 5402e69bc664e..624111d48adfa 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -163,7 +163,8 @@ pub fn parse_config(args: Vec) -> Config { ) .optopt("", "edition", "default Rust edition", "EDITION") .reqopt("", "git-repository", "name of the git repository", "ORG/REPO") - .reqopt("", "nightly-branch", "name of the git branch for nightly", "BRANCH"); + .reqopt("", "nightly-branch", "name of the git branch for nightly", "BRANCH") + .reqopt("", "git-merge-commit-email", "email address used for the merge commits", "EMAIL"); let (argv0, args_) = args.split_first().unwrap(); if args.len() == 1 || args[1] == "-h" || args[1] == "--help" { @@ -346,6 +347,7 @@ pub fn parse_config(args: Vec) -> Config { git_repository: matches.opt_str("git-repository").unwrap(), nightly_branch: matches.opt_str("nightly-branch").unwrap(), + git_merge_commit_email: matches.opt_str("git-merge-commit-email").unwrap(), profiler_support: matches.opt_present("profiler-support"), } From 0a7f9e213448bfbe336bbb6d5f1f9a79961427f9 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 9 Sep 2024 21:23:06 +0300 Subject: [PATCH 142/189] skip formatting if no files have been modified Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/format.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs index 91fbc57429a96..bbd81fb570bd5 100644 --- a/src/bootstrap/src/core/build_steps/format.rs +++ b/src/bootstrap/src/core/build_steps/format.rs @@ -200,6 +200,11 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) { adjective = Some("modified"); match get_modified_rs_files(build) { Ok(Some(files)) => { + if files.is_empty() { + println!("fmt info: No modified files detected for formatting."); + return; + } + for file in files { override_builder.add(&format!("/{file}")).expect(&file); } From 3810386bbe95e989d399a2d46d806bcf7c607c06 Mon Sep 17 00:00:00 2001 From: Paul Menage Date: Tue, 10 Sep 2024 12:19:16 -0700 Subject: [PATCH 143/189] Add -Z small-data-threshold This flag allows specifying the threshold size above which LLVM should not consider placing small objects in a .sdata or .sbss section. Support is indicated in the target options via the small-data-threshold-support target option, which can indicate either an LLVM argument or an LLVM module flag. To avoid duplicate specifications in a large number of targets, the default value for support is DefaultForArch, which is translated to a concrete value according to the target's architecture. --- compiler/rustc_codegen_llvm/src/context.rs | 20 +++- compiler/rustc_codegen_llvm/src/llvm_util.rs | 14 ++- compiler/rustc_interface/src/tests.rs | 1 + compiler/rustc_session/messages.ftl | 2 + compiler/rustc_session/src/errors.rs | 6 ++ compiler/rustc_session/src/options.rs | 2 + compiler/rustc_session/src/session.rs | 12 ++- compiler/rustc_target/src/spec/mod.rs | 76 +++++++++++++++ .../compiler-flags/small-data-threshold.md | 20 ++++ tests/assembly/small_data_threshold.rs | 92 +++++++++++++++++++ 10 files changed, 241 insertions(+), 4 deletions(-) create mode 100644 src/doc/unstable-book/src/compiler-flags/small-data-threshold.md create mode 100644 tests/assembly/small_data_threshold.rs diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 01aae24ab56c2..73c2c15717fc1 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -27,7 +27,7 @@ use rustc_span::source_map::Spanned; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::call::FnAbi; use rustc_target::abi::{HasDataLayout, TargetDataLayout, VariantIdx}; -use rustc_target::spec::{HasTargetSpec, RelocModel, Target, TlsModel}; +use rustc_target::spec::{HasTargetSpec, RelocModel, SmallDataThresholdSupport, Target, TlsModel}; use smallvec::SmallVec; use crate::back::write::to_llvm_code_model; @@ -387,6 +387,24 @@ pub(crate) unsafe fn create_module<'ll>( } } + match (sess.opts.unstable_opts.small_data_threshold, sess.target.small_data_threshold_support()) + { + // Set up the small-data optimization limit for architectures that use + // an LLVM module flag to control this. + (Some(threshold), SmallDataThresholdSupport::LlvmModuleFlag(flag)) => { + let flag = SmallCStr::new(flag.as_ref()); + unsafe { + llvm::LLVMRustAddModuleFlagU32( + llmod, + llvm::LLVMModFlagBehavior::Error, + flag.as_c_str().as_ptr(), + threshold as u32, + ) + } + } + _ => (), + }; + // Insert `llvm.ident` metadata. // // On the wasm targets it will get hooked up to the "producer" sections diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index d55220ba5c3a4..ea0abb1fa53fa 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -14,7 +14,7 @@ use rustc_middle::bug; use rustc_session::config::{PrintKind, PrintRequest}; use rustc_session::Session; use rustc_span::symbol::Symbol; -use rustc_target::spec::{MergeFunctions, PanicStrategy}; +use rustc_target::spec::{MergeFunctions, PanicStrategy, SmallDataThresholdSupport}; use rustc_target::target_features::{RUSTC_SPECIAL_FEATURES, RUSTC_SPECIFIC_FEATURES}; use crate::back::write::create_informational_target_machine; @@ -125,6 +125,18 @@ unsafe fn configure_llvm(sess: &Session) { for arg in sess_args { add(&(*arg), true); } + + match ( + sess.opts.unstable_opts.small_data_threshold, + sess.target.small_data_threshold_support(), + ) { + // Set up the small-data optimization limit for architectures that use + // an LLVM argument to control this. + (Some(threshold), SmallDataThresholdSupport::LlvmArg(arg)) => { + add(&format!("--{arg}={threshold}"), false) + } + _ => (), + }; } if sess.opts.unstable_opts.llvm_time_trace { diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 50422df8ee648..baeac6c32f939 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -847,6 +847,7 @@ fn test_unstable_options_tracking_hash() { tracked!(share_generics, Some(true)); tracked!(show_span, Some(String::from("abc"))); tracked!(simulate_remapped_rust_src_base, Some(PathBuf::from("/rustc/abc"))); + tracked!(small_data_threshold, Some(16)); tracked!(split_lto_unit, Some(true)); tracked!(src_hash_algorithm, Some(SourceFileHashAlgorithm::Sha1)); tracked!(stack_protector, StackProtector::All); diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl index 01c371ee49884..a4fbab8477b13 100644 --- a/compiler/rustc_session/messages.ftl +++ b/compiler/rustc_session/messages.ftl @@ -113,6 +113,8 @@ session_split_lto_unit_requires_lto = `-Zsplit-lto-unit` requires `-Clto`, `-Clt session_target_requires_unwind_tables = target requires unwind tables, they cannot be disabled with `-C force-unwind-tables=no` +session_target_small_data_threshold_not_supported = `-Z small-data-threshold` is not supported for target {$target_triple} and will be ignored + session_target_stack_protector_not_supported = `-Z stack-protector={$stack_protector}` is not supported for target {$target_triple} and will be ignored session_unleashed_feature_help_named = skipping check for `{$gate}` feature diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 15bbd4ff7bf4b..462e2a97c33da 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -182,6 +182,12 @@ pub(crate) struct StackProtectorNotSupportedForTarget<'a> { pub(crate) target_triple: &'a TargetTriple, } +#[derive(Diagnostic)] +#[diag(session_target_small_data_threshold_not_supported)] +pub(crate) struct SmallDataThresholdNotSupportedForTarget<'a> { + pub(crate) target_triple: &'a TargetTriple, +} + #[derive(Diagnostic)] #[diag(session_branch_protection_requires_aarch64)] pub(crate) struct BranchProtectionRequiresAArch64; diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index a57dc80b3168d..5a6fa25fd3d6a 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2014,6 +2014,8 @@ written to standard error output)"), simulate_remapped_rust_src_base: Option = (None, parse_opt_pathbuf, [TRACKED], "simulate the effect of remap-debuginfo = true at bootstrapping by remapping path \ to rust's source base directory. only meant for testing purposes"), + small_data_threshold: Option = (None, parse_opt_number, [TRACKED], + "Set the threshold for objects to be stored in a \"small data\" section"), span_debug: bool = (false, parse_bool, [UNTRACKED], "forward proc_macro::Span's `Debug` impl to `Span`"), /// o/w tests have closure@path diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 70430d82ab55b..387ae1b78c480 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -30,8 +30,8 @@ use rustc_span::source_map::{FilePathMapping, SourceMap}; use rustc_span::{FileNameDisplayPreference, RealFileName, Span, Symbol}; use rustc_target::asm::InlineAsmArch; use rustc_target::spec::{ - CodeModel, DebuginfoKind, PanicStrategy, RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, - StackProtector, Target, TargetTriple, TlsModel, + CodeModel, DebuginfoKind, PanicStrategy, RelocModel, RelroLevel, SanitizerSet, + SmallDataThresholdSupport, SplitDebuginfo, StackProtector, Target, TargetTriple, TlsModel, }; use crate::code_stats::CodeStats; @@ -1278,6 +1278,14 @@ fn validate_commandline_args_with_session_available(sess: &Session) { } } + if sess.opts.unstable_opts.small_data_threshold.is_some() { + if sess.target.small_data_threshold_support() == SmallDataThresholdSupport::None { + sess.dcx().emit_warn(errors::SmallDataThresholdNotSupportedForTarget { + target_triple: &sess.opts.target_triple, + }) + } + } + if sess.opts.unstable_opts.branch_protection.is_some() && sess.target.arch != "aarch64" { sess.dcx().emit_err(errors::BranchProtectionRequiresAArch64); } diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index c3e7f74c56410..f12e3e595adf6 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -855,6 +855,43 @@ impl ToJson for RelroLevel { } } +#[derive(Clone, Debug, PartialEq, Hash)] +pub enum SmallDataThresholdSupport { + None, + DefaultForArch, + LlvmModuleFlag(StaticCow), + LlvmArg(StaticCow), +} + +impl FromStr for SmallDataThresholdSupport { + type Err = (); + + fn from_str(s: &str) -> Result { + if s == "none" { + Ok(Self::None) + } else if s == "default-for-arch" { + Ok(Self::DefaultForArch) + } else if let Some(flag) = s.strip_prefix("llvm-module-flag=") { + Ok(Self::LlvmModuleFlag(flag.to_string().into())) + } else if let Some(arg) = s.strip_prefix("llvm-arg=") { + Ok(Self::LlvmArg(arg.to_string().into())) + } else { + Err(()) + } + } +} + +impl ToJson for SmallDataThresholdSupport { + fn to_json(&self) -> Value { + match self { + Self::None => "none".to_json(), + Self::DefaultForArch => "default-for-arch".to_json(), + Self::LlvmModuleFlag(flag) => format!("llvm-module-flag={flag}").to_json(), + Self::LlvmArg(arg) => format!("llvm-arg={arg}").to_json(), + } + } +} + #[derive(Clone, Copy, Debug, PartialEq, Hash)] pub enum MergeFunctions { Disabled, @@ -2392,6 +2429,9 @@ pub struct TargetOptions { /// Whether the target supports XRay instrumentation. pub supports_xray: bool, + + /// Whether the targets supports -Z small-data-threshold + small_data_threshold_support: SmallDataThresholdSupport, } /// Add arguments for the given flavor and also for its "twin" flavors @@ -2609,6 +2649,7 @@ impl Default for TargetOptions { entry_name: "main".into(), entry_abi: Conv::C, supports_xray: false, + small_data_threshold_support: SmallDataThresholdSupport::DefaultForArch, } } } @@ -2884,6 +2925,15 @@ impl Target { Some(Ok(())) })).unwrap_or(Ok(())) } ); + ($key_name:ident, SmallDataThresholdSupport) => ( { + obj.remove("small-data-threshold-support").and_then(|o| o.as_str().and_then(|s| { + match s.parse::() { + Ok(support) => base.small_data_threshold_support = support, + _ => return Some(Err(format!("'{s}' is not a valid value for small-data-threshold-support."))), + } + Some(Ok(())) + })).unwrap_or(Ok(())) + } ); ($key_name:ident, PanicStrategy) => ( { let name = (stringify!($key_name)).replace("_", "-"); obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { @@ -3321,6 +3371,7 @@ impl Target { key!(supported_sanitizers, SanitizerSet)?; key!(generate_arange_section, bool); key!(supports_stack_protector, bool); + key!(small_data_threshold_support, SmallDataThresholdSupport)?; key!(entry_name); key!(entry_abi, Conv)?; key!(supports_xray, bool); @@ -3415,6 +3466,30 @@ impl Target { } } } + + /// Return the target's small data threshold support, converting + /// `DefaultForArch` into a concrete value. + pub fn small_data_threshold_support(&self) -> SmallDataThresholdSupport { + match &self.options.small_data_threshold_support { + // Avoid having to duplicate the small data support in every + // target file by supporting a default value for each + // architecture. + SmallDataThresholdSupport::DefaultForArch => match self.arch.as_ref() { + "mips" | "mips64" | "mips32r6" => { + SmallDataThresholdSupport::LlvmArg("mips-ssection-threshold".into()) + } + "hexagon" => { + SmallDataThresholdSupport::LlvmArg("hexagon-small-data-threshold".into()) + } + "m68k" => SmallDataThresholdSupport::LlvmArg("m68k-ssection-threshold".into()), + "riscv32" | "riscv64" => { + SmallDataThresholdSupport::LlvmModuleFlag("SmallDataLimit".into()) + } + _ => SmallDataThresholdSupport::None, + }, + s => s.clone(), + } + } } impl ToJson for Target { @@ -3577,6 +3652,7 @@ impl ToJson for Target { target_option_val!(c_enum_min_bits); target_option_val!(generate_arange_section); target_option_val!(supports_stack_protector); + target_option_val!(small_data_threshold_support); target_option_val!(entry_name); target_option_val!(entry_abi); target_option_val!(supports_xray); diff --git a/src/doc/unstable-book/src/compiler-flags/small-data-threshold.md b/src/doc/unstable-book/src/compiler-flags/small-data-threshold.md new file mode 100644 index 0000000000000..1734433181e38 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/small-data-threshold.md @@ -0,0 +1,20 @@ +# `small-data-threshold` + +----------------------- + +This flag controls the maximum static variable size that may be included in the +"small data sections" (.sdata, .sbss) supported by some architectures (RISCV, +MIPS, M68K, Hexagon). Can be set to `0` to disable the use of small data +sections. + +Target support is indicated by the `small_data_threshold_support` target +option which can be: + +- `none` (`SmallDataThresholdSupport::None`) for no support +- `default-for-arch` (`SmallDataThresholdSupport::DefaultForArch`) which + is automatically translated into an appropriate value for the target. +- `llvm-module-flag=` + (`SmallDataThresholdSupport::LlvmModuleFlag`) for specifying the + threshold via an LLVM module flag +- `llvm-arg=` (`SmallDataThresholdSupport::LlvmArg`) for + specifying the threshold via an LLVM argument. diff --git a/tests/assembly/small_data_threshold.rs b/tests/assembly/small_data_threshold.rs new file mode 100644 index 0000000000000..b0c0a63ca492d --- /dev/null +++ b/tests/assembly/small_data_threshold.rs @@ -0,0 +1,92 @@ +// Test for -Z small_data_threshold=... +//@ revisions: RISCV MIPS HEXAGON M68K +//@ assembly-output: emit-asm +//@ compile-flags: -Z small_data_threshold=4 +//@ [RISCV] compile-flags: --target=riscv32im-unknown-none-elf +//@ [RISCV] needs-llvm-components: riscv +//@ [MIPS] compile-flags: --target=mips-unknown-linux-uclibc -C relocation-model=static +//@ [MIPS] compile-flags: -C llvm-args=-mgpopt -C llvm-args=-mlocal-sdata +//@ [MIPS] compile-flags: -C target-feature=+noabicalls +//@ [MIPS] needs-llvm-components: mips +//@ [HEXAGON] compile-flags: --target=hexagon-unknown-linux-musl -C target-feature=+small-data +//@ [HEXAGON] compile-flags: -C llvm-args=--hexagon-statics-in-small-data +//@ [HEXAGON] needs-llvm-components: hexagon +//@ [M68K] compile-flags: --target=m68k-unknown-linux-gnu +//@ [M68K] needs-llvm-components: m68k + +#![feature(no_core, lang_items)] +#![no_std] +#![no_core] +#![crate_type = "lib"] + +#[lang = "sized"] +trait Sized {} + +#[lang = "drop_in_place"] +fn drop_in_place(_: *mut T) {} + +#[used] +#[no_mangle] +// U is below the threshold, should be in sdata +static mut U: u16 = 123; + +#[used] +#[no_mangle] +// V is below the threshold, should be in sbss +static mut V: u16 = 0; + +#[used] +#[no_mangle] +// W is at the threshold, should be in sdata +static mut W: u32 = 123; + +#[used] +#[no_mangle] +// X is at the threshold, should be in sbss +static mut X: u32 = 0; + +#[used] +#[no_mangle] +// Y is over the threshold, should be in its own .data section +static mut Y: u64 = 123; + +#[used] +#[no_mangle] +// Z is over the threshold, should be in its own .bss section +static mut Z: u64 = 0; + +// Currently, only MIPS and RISCV successfully put any objects in the small data +// sections so the U/V/W/X tests are skipped on Hexagon and M68K + +//@ RISCV: .section .sdata, +//@ RISCV-NOT: .section +//@ RISCV: U: +//@ RISCV: .section .sbss +//@ RISCV-NOT: .section +//@ RISCV: V: +//@ RISCV: .section .sdata +//@ RISCV-NOT: .section +//@ RISCV: W: +//@ RISCV: .section .sbss +//@ RISCV-NOT: .section +//@ RISCV: X: + +//@ MIPS: .section .sdata, +//@ MIPS-NOT: .section +//@ MIPS: U: +//@ MIPS: .section .sbss +//@ MIPS-NOT: .section +//@ MIPS: V: +//@ MIPS: .section .sdata +//@ MIPS-NOT: .section +//@ MIPS: W: +//@ MIPS: .section .sbss +//@ MIPS-NOT: .section +//@ MIPS: X: + +//@ CHECK: .section .data.Y, +//@ CHECK-NOT: .section +//@ CHECK: Y: +//@ CHECK: .section .bss.Z, +//@ CHECK-NOT: .section +//@ CHECK: Z: From f93df1f7dcea3588620b77e2a0eaac12b46a7678 Mon Sep 17 00:00:00 2001 From: Ding Xiang Fei Date: Tue, 24 Jan 2023 16:06:35 +0800 Subject: [PATCH 144/189] rescope temp lifetime in let-chain into IfElse apply rules by span edition --- .../src/diagnostics/conflict_errors.rs | 29 +- .../src/diagnostics/explain_borrow.rs | 95 +++++- compiler/rustc_feature/src/unstable.rs | 2 + .../rustc_hir_analysis/src/check/region.rs | 14 +- compiler/rustc_lint/messages.ftl | 5 + compiler/rustc_lint/src/if_let_rescope.rs | 312 ++++++++++++++++++ compiler/rustc_lint/src/lib.rs | 3 + compiler/rustc_middle/src/middle/region.rs | 6 + compiler/rustc_middle/src/mir/mod.rs | 3 + compiler/rustc_middle/src/ty/rvalue_scopes.rs | 10 +- .../rustc_mir_build/src/build/expr/as_temp.rs | 10 + compiler/rustc_mir_build/src/thir/cx/expr.rs | 8 +- compiler/rustc_span/src/symbol.rs | 1 + tests/ui/drop/drop_order.rs | 22 ++ tests/ui/drop/drop_order_if_let_rescope.rs | 122 +++++++ .../if-let-rescope-borrowck-suggestions.fixed | 26 ++ .../if-let-rescope-borrowck-suggestions.rs | 25 ++ ...if-let-rescope-borrowck-suggestions.stderr | 26 ++ tests/ui/drop/lint-if-let-rescope-gated.rs | 31 ++ ...let-rescope-gated.with_feature_gate.stderr | 30 ++ .../ui/drop/lint-if-let-rescope-with-macro.rs | 41 +++ .../lint-if-let-rescope-with-macro.stderr | 39 +++ tests/ui/drop/lint-if-let-rescope.fixed | 48 +++ tests/ui/drop/lint-if-let-rescope.rs | 48 +++ tests/ui/drop/lint-if-let-rescope.stderr | 74 +++++ .../feature-gate-if-let-rescope.rs | 27 ++ .../feature-gate-if-let-rescope.stderr | 18 + tests/ui/mir/mir_let_chains_drop_order.rs | 41 ++- ...=> issue-54556-niconii.edition2021.stderr} | 2 +- tests/ui/nll/issue-54556-niconii.rs | 19 +- 30 files changed, 1102 insertions(+), 35 deletions(-) create mode 100644 compiler/rustc_lint/src/if_let_rescope.rs create mode 100644 tests/ui/drop/drop_order_if_let_rescope.rs create mode 100644 tests/ui/drop/if-let-rescope-borrowck-suggestions.fixed create mode 100644 tests/ui/drop/if-let-rescope-borrowck-suggestions.rs create mode 100644 tests/ui/drop/if-let-rescope-borrowck-suggestions.stderr create mode 100644 tests/ui/drop/lint-if-let-rescope-gated.rs create mode 100644 tests/ui/drop/lint-if-let-rescope-gated.with_feature_gate.stderr create mode 100644 tests/ui/drop/lint-if-let-rescope-with-macro.rs create mode 100644 tests/ui/drop/lint-if-let-rescope-with-macro.stderr create mode 100644 tests/ui/drop/lint-if-let-rescope.fixed create mode 100644 tests/ui/drop/lint-if-let-rescope.rs create mode 100644 tests/ui/drop/lint-if-let-rescope.stderr create mode 100644 tests/ui/feature-gates/feature-gate-if-let-rescope.rs create mode 100644 tests/ui/feature-gates/feature-gate-if-let-rescope.stderr rename tests/ui/nll/{issue-54556-niconii.stderr => issue-54556-niconii.edition2021.stderr} (96%) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index a47518fca3f9b..215e0476f01f7 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1999,19 +1999,32 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { ) { let used_in_call = matches!( explanation, - BorrowExplanation::UsedLater(LaterUseKind::Call | LaterUseKind::Other, _call_span, _) + BorrowExplanation::UsedLater( + _, + LaterUseKind::Call | LaterUseKind::Other, + _call_span, + _ + ) ); if !used_in_call { debug!("not later used in call"); return; } + if matches!( + self.body.local_decls[issued_borrow.borrowed_place.local].local_info(), + LocalInfo::IfThenRescopeTemp { .. } + ) { + // A better suggestion will be issued by the `if_let_rescope` lint + return; + } - let use_span = - if let BorrowExplanation::UsedLater(LaterUseKind::Other, use_span, _) = explanation { - Some(use_span) - } else { - None - }; + let use_span = if let BorrowExplanation::UsedLater(_, LaterUseKind::Other, use_span, _) = + explanation + { + Some(use_span) + } else { + None + }; let outer_call_loc = if let TwoPhaseActivation::ActivatedAt(loc) = issued_borrow.activation_location { @@ -2862,7 +2875,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { // and `move` will not help here. ( Some(name), - BorrowExplanation::UsedLater(LaterUseKind::ClosureCapture, var_or_use_span, _), + BorrowExplanation::UsedLater(_, LaterUseKind::ClosureCapture, var_or_use_span, _), ) if borrow_spans.for_coroutine() || borrow_spans.for_closure() => self .report_escaping_closure_capture( borrow_spans, diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 419e72df00b02..22327d2ba0d46 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -30,7 +30,7 @@ use crate::{MirBorrowckCtxt, WriteKind}; #[derive(Debug)] pub(crate) enum BorrowExplanation<'tcx> { - UsedLater(LaterUseKind, Span, Option), + UsedLater(Local, LaterUseKind, Span, Option), UsedLaterInLoop(LaterUseKind, Span, Option), UsedLaterWhenDropped { drop_loc: Location, @@ -99,7 +99,12 @@ impl<'tcx> BorrowExplanation<'tcx> { } } match *self { - BorrowExplanation::UsedLater(later_use_kind, var_or_use_span, path_span) => { + BorrowExplanation::UsedLater( + dropped_local, + later_use_kind, + var_or_use_span, + path_span, + ) => { let message = match later_use_kind { LaterUseKind::TraitCapture => "captured here by trait object", LaterUseKind::ClosureCapture => "captured here by closure", @@ -107,9 +112,26 @@ impl<'tcx> BorrowExplanation<'tcx> { LaterUseKind::FakeLetRead => "stored here", LaterUseKind::Other => "used here", }; - // We can use `var_or_use_span` if either `path_span` is not present, or both spans are the same - if path_span.map(|path_span| path_span == var_or_use_span).unwrap_or(true) { - if borrow_span.map(|sp| !sp.overlaps(var_or_use_span)).unwrap_or(true) { + let local_decl = &body.local_decls[dropped_local]; + + if let &LocalInfo::IfThenRescopeTemp { if_then } = local_decl.local_info() + && let Some((_, hir::Node::Expr(expr))) = tcx.hir().parent_iter(if_then).next() + && let hir::ExprKind::If(cond, conseq, alt) = expr.kind + && let hir::ExprKind::Let(&hir::LetExpr { + span: _, + pat, + init, + // FIXME(#101728): enable rewrite when type ascription is stabilized again + ty: None, + recovered: _, + }) = cond.kind + && pat.span.can_be_used_for_suggestions() + && let Ok(pat) = tcx.sess.source_map().span_to_snippet(pat.span) + { + suggest_rewrite_if_let(expr, &pat, init, conseq, alt, err); + } else if path_span.map_or(true, |path_span| path_span == var_or_use_span) { + // We can use `var_or_use_span` if either `path_span` is not present, or both spans are the same + if borrow_span.map_or(true, |sp| !sp.overlaps(var_or_use_span)) { err.span_label( var_or_use_span, format!("{borrow_desc}borrow later {message}"), @@ -255,6 +277,22 @@ impl<'tcx> BorrowExplanation<'tcx> { Applicability::MaybeIncorrect, ); }; + } else if let &LocalInfo::IfThenRescopeTemp { if_then } = + local_decl.local_info() + && let hir::Node::Expr(expr) = tcx.hir_node(if_then) + && let hir::ExprKind::If(cond, conseq, alt) = expr.kind + && let hir::ExprKind::Let(&hir::LetExpr { + span: _, + pat, + init, + // FIXME(#101728): enable rewrite when type ascription is stabilized again + ty: None, + recovered: _, + }) = cond.kind + && pat.span.can_be_used_for_suggestions() + && let Ok(pat) = tcx.sess.source_map().span_to_snippet(pat.span) + { + suggest_rewrite_if_let(expr, &pat, init, conseq, alt, err); } } } @@ -390,6 +428,38 @@ impl<'tcx> BorrowExplanation<'tcx> { } } +fn suggest_rewrite_if_let<'tcx>( + expr: &hir::Expr<'tcx>, + pat: &str, + init: &hir::Expr<'tcx>, + conseq: &hir::Expr<'tcx>, + alt: Option<&hir::Expr<'tcx>>, + err: &mut Diag<'_>, +) { + err.span_note( + conseq.span.shrink_to_hi(), + "lifetime for temporaries generated in `if let`s have been shorted in Edition 2024", + ); + if expr.span.can_be_used_for_suggestions() && conseq.span.can_be_used_for_suggestions() { + let mut sugg = vec![ + (expr.span.shrink_to_lo().between(init.span), "match ".into()), + (conseq.span.shrink_to_lo(), format!(" {{ {pat} => ")), + ]; + let expr_end = expr.span.shrink_to_hi(); + if let Some(alt) = alt { + sugg.push((conseq.span.between(alt.span), format!(" _ => "))); + sugg.push((expr_end, "}".into())); + } else { + sugg.push((expr_end, " _ => {} }".into())); + } + err.multipart_suggestion( + "consider rewriting the `if` into `match` which preserves the extended lifetime", + sugg, + Applicability::MachineApplicable, + ); + } +} + impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { fn free_region_constraint_info( &self, @@ -465,14 +535,21 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { .or_else(|| self.borrow_spans(span, location)); if use_in_later_iteration_of_loop { - let later_use = self.later_use_kind(borrow, spans, use_location); - BorrowExplanation::UsedLaterInLoop(later_use.0, later_use.1, later_use.2) + let (later_use_kind, var_or_use_span, path_span) = + self.later_use_kind(borrow, spans, use_location); + BorrowExplanation::UsedLaterInLoop(later_use_kind, var_or_use_span, path_span) } else { // Check if the location represents a `FakeRead`, and adapt the error // message to the `FakeReadCause` it is from: in particular, // the ones inserted in optimized `let var = ` patterns. - let later_use = self.later_use_kind(borrow, spans, location); - BorrowExplanation::UsedLater(later_use.0, later_use.1, later_use.2) + let (later_use_kind, var_or_use_span, path_span) = + self.later_use_kind(borrow, spans, location); + BorrowExplanation::UsedLater( + borrow.borrowed_place.local, + later_use_kind, + var_or_use_span, + path_span, + ) } } diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 3254dab9a0344..1359b6248dcb0 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -497,6 +497,8 @@ declare_features! ( (unstable, half_open_range_patterns_in_slices, "1.66.0", Some(67264)), /// Allows `if let` guard in match arms. (unstable, if_let_guard, "1.47.0", Some(51114)), + /// Rescoping temporaries in `if let` to align with Rust 2024. + (unstable, if_let_rescope, "CURRENT_RUSTC_VERSION", Some(124085)), /// Allows `impl Trait` to be used inside associated types (RFC 2515). (unstable, impl_trait_in_assoc_type, "1.70.0", Some(63063)), /// Allows `impl Trait` as output type in `Fn` traits in return position of functions. diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 2d6147cff2a5a..33e58a92e3755 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -472,7 +472,12 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h hir::ExprKind::If(cond, then, Some(otherwise)) => { let expr_cx = visitor.cx; - visitor.enter_scope(Scope { id: then.hir_id.local_id, data: ScopeData::IfThen }); + let data = if expr.span.at_least_rust_2024() && visitor.tcx.features().if_let_rescope { + ScopeData::IfThenRescope + } else { + ScopeData::IfThen + }; + visitor.enter_scope(Scope { id: then.hir_id.local_id, data }); visitor.cx.var_parent = visitor.cx.parent; visitor.visit_expr(cond); visitor.visit_expr(then); @@ -482,7 +487,12 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h hir::ExprKind::If(cond, then, None) => { let expr_cx = visitor.cx; - visitor.enter_scope(Scope { id: then.hir_id.local_id, data: ScopeData::IfThen }); + let data = if expr.span.at_least_rust_2024() && visitor.tcx.features().if_let_rescope { + ScopeData::IfThenRescope + } else { + ScopeData::IfThen + }; + visitor.enter_scope(Scope { id: then.hir_id.local_id, data }); visitor.cx.var_parent = visitor.cx.parent; visitor.visit_expr(cond); visitor.visit_expr(then); diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 7d4dee45c261b..1f8dca337fc8e 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -334,6 +334,11 @@ lint_identifier_uncommon_codepoints = identifier contains {$codepoints_len -> *[other] {" "}{$identifier_type} } Unicode general security profile +lint_if_let_rescope = `if let` assigns a shorter lifetime since Edition 2024 + .label = this value has a significant drop implementation which may observe a major change in drop order and requires your discretion + .help = the value is now dropped here in Edition 2024 + .suggestion = rewrite this `if let` into a `match` with a single arm to preserve the drop order up to Edition 2021 + lint_ignored_unless_crate_specified = {$level}({$name}) is ignored unless specified at crate level lint_ill_formed_attribute_input = {$num_suggestions -> diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs new file mode 100644 index 0000000000000..143965ae58f7e --- /dev/null +++ b/compiler/rustc_lint/src/if_let_rescope.rs @@ -0,0 +1,312 @@ +use std::ops::ControlFlow; + +use hir::intravisit::Visitor; +use rustc_ast::Recovered; +use rustc_hir as hir; +use rustc_macros::{LintDiagnostic, Subdiagnostic}; +use rustc_session::lint::FutureIncompatibilityReason; +use rustc_session::{declare_lint, declare_lint_pass}; +use rustc_span::edition::Edition; +use rustc_span::Span; + +use crate::{LateContext, LateLintPass}; + +declare_lint! { + /// The `if_let_rescope` lint detects cases where a temporary value with + /// significant drop is generated on the right hand side of `if let` + /// and suggests a rewrite into `match` when possible. + /// + /// ### Example + /// + /// ```rust,edition2021 + /// #![feature(if_let_rescope)] + /// #![warn(if_let_rescope)] + /// #![allow(unused_variables)] + /// + /// struct Droppy; + /// impl Drop for Droppy { + /// fn drop(&mut self) { + /// // Custom destructor, including this `drop` implementation, is considered + /// // significant. + /// // Rust does not check whether this destructor emits side-effects that can + /// // lead to observable change in program semantics, when the drop order changes. + /// // Rust biases to be on the safe side, so that you can apply discretion whether + /// // this change indeed breaches any contract or specification that your code needs + /// // to honour. + /// println!("dropped"); + /// } + /// } + /// impl Droppy { + /// fn get(&self) -> Option { + /// None + /// } + /// } + /// + /// fn main() { + /// if let Some(value) = Droppy.get() { + /// // do something + /// } else { + /// // do something else + /// } + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// With Edition 2024, temporaries generated while evaluating `if let`s + /// will be dropped before the `else` block. + /// This lint captures a possible change in runtime behaviour due to + /// a change in sequence of calls to significant `Drop::drop` destructors. + /// + /// A significant [`Drop::drop`](https://doc.rust-lang.org/std/ops/trait.Drop.html) + /// destructor here refers to an explicit, arbitrary implementation of the `Drop` trait on the type + /// with exceptions including `Vec`, `Box`, `Rc`, `BTreeMap` and `HashMap` + /// that are marked by the compiler otherwise so long that the generic types have + /// no significant destructor recursively. + /// In other words, a type has a significant drop destructor when it has a `Drop` implementation + /// or its destructor invokes a significant destructor on a type. + /// Since we cannot completely reason about the change by just inspecting the existence of + /// a significant destructor, this lint remains only a suggestion and is set to `allow` by default. + /// + /// Whenever possible, a rewrite into an equivalent `match` expression that + /// observe the same order of calls to such destructors is proposed by this lint. + /// Authors may take their own discretion whether the rewrite suggestion shall be + /// accepted, or rejected to continue the use of the `if let` expression. + pub IF_LET_RESCOPE, + Allow, + "`if let` assigns a shorter lifetime to temporary values being pattern-matched against in Edition 2024 and \ + rewriting in `match` is an option to preserve the semantics up to Edition 2021", + @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2024), + reference: "issue #124085 ", + }; +} + +declare_lint_pass!( + /// Lint for potential change in program semantics of `if let`s + IfLetRescope => [IF_LET_RESCOPE] +); + +impl<'tcx> LateLintPass<'tcx> for IfLetRescope { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { + if !expr.span.edition().at_least_rust_2021() || !cx.tcx.features().if_let_rescope { + return; + } + let hir::ExprKind::If(cond, conseq, alt) = expr.kind else { return }; + let hir::ExprKind::Let(&hir::LetExpr { + span, + pat, + init, + ty: ty_ascription, + recovered: Recovered::No, + }) = cond.kind + else { + return; + }; + let source_map = cx.tcx.sess.source_map(); + let expr_end = expr.span.shrink_to_hi(); + let if_let_pat = expr.span.shrink_to_lo().between(init.span); + let before_conseq = conseq.span.shrink_to_lo(); + let lifetime_end = source_map.end_point(conseq.span); + + if let ControlFlow::Break(significant_dropper) = + (FindSignificantDropper { cx }).visit_expr(init) + { + let lint_without_suggestion = || { + cx.tcx.emit_node_span_lint( + IF_LET_RESCOPE, + expr.hir_id, + span, + IfLetRescopeRewrite { significant_dropper, lifetime_end, sugg: None }, + ) + }; + if ty_ascription.is_some() + || !expr.span.can_be_used_for_suggestions() + || !pat.span.can_be_used_for_suggestions() + { + // Our `match` rewrites does not support type ascription, + // so we just bail. + // Alternatively when the span comes from proc macro expansion, + // we will also bail. + // FIXME(#101728): change this when type ascription syntax is stabilized again + lint_without_suggestion(); + } else { + let Ok(pat) = source_map.span_to_snippet(pat.span) else { + lint_without_suggestion(); + return; + }; + if let Some(alt) = alt { + let alt_start = conseq.span.between(alt.span); + if !alt_start.can_be_used_for_suggestions() { + lint_without_suggestion(); + return; + } + cx.tcx.emit_node_span_lint( + IF_LET_RESCOPE, + expr.hir_id, + span, + IfLetRescopeRewrite { + significant_dropper, + lifetime_end, + sugg: Some(IfLetRescopeRewriteSuggestion::WithElse { + if_let_pat, + before_conseq, + pat, + expr_end, + alt_start, + }), + }, + ); + } else { + cx.tcx.emit_node_span_lint( + IF_LET_RESCOPE, + expr.hir_id, + span, + IfLetRescopeRewrite { + significant_dropper, + lifetime_end, + sugg: Some(IfLetRescopeRewriteSuggestion::WithoutElse { + if_let_pat, + before_conseq, + pat, + expr_end, + }), + }, + ); + } + } + } + } +} + +#[derive(LintDiagnostic)] +#[diag(lint_if_let_rescope)] +struct IfLetRescopeRewrite { + #[label] + significant_dropper: Span, + #[help] + lifetime_end: Span, + #[subdiagnostic] + sugg: Option, +} + +#[derive(Subdiagnostic)] +enum IfLetRescopeRewriteSuggestion { + #[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] + WithElse { + #[suggestion_part(code = "match ")] + if_let_pat: Span, + #[suggestion_part(code = " {{ {pat} => ")] + before_conseq: Span, + pat: String, + #[suggestion_part(code = "}}")] + expr_end: Span, + #[suggestion_part(code = " _ => ")] + alt_start: Span, + }, + #[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] + WithoutElse { + #[suggestion_part(code = "match ")] + if_let_pat: Span, + #[suggestion_part(code = " {{ {pat} => ")] + before_conseq: Span, + pat: String, + #[suggestion_part(code = " _ => {{}} }}")] + expr_end: Span, + }, +} + +struct FindSignificantDropper<'tcx, 'a> { + cx: &'a LateContext<'tcx>, +} + +impl<'tcx, 'a> Visitor<'tcx> for FindSignificantDropper<'tcx, 'a> { + type Result = ControlFlow; + + fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Self::Result { + if self + .cx + .typeck_results() + .expr_ty(expr) + .has_significant_drop(self.cx.tcx, self.cx.param_env) + { + return ControlFlow::Break(expr.span); + } + match expr.kind { + hir::ExprKind::ConstBlock(_) + | hir::ExprKind::Lit(_) + | hir::ExprKind::Path(_) + | hir::ExprKind::Assign(_, _, _) + | hir::ExprKind::AssignOp(_, _, _) + | hir::ExprKind::Break(_, _) + | hir::ExprKind::Continue(_) + | hir::ExprKind::Ret(_) + | hir::ExprKind::Become(_) + | hir::ExprKind::InlineAsm(_) + | hir::ExprKind::OffsetOf(_, _) + | hir::ExprKind::Repeat(_, _) + | hir::ExprKind::Err(_) + | hir::ExprKind::Struct(_, _, _) + | hir::ExprKind::Closure(_) + | hir::ExprKind::Block(_, _) + | hir::ExprKind::DropTemps(_) + | hir::ExprKind::Loop(_, _, _, _) => ControlFlow::Continue(()), + + hir::ExprKind::Tup(exprs) | hir::ExprKind::Array(exprs) => { + for expr in exprs { + self.visit_expr(expr)?; + } + ControlFlow::Continue(()) + } + hir::ExprKind::Call(callee, args) => { + self.visit_expr(callee)?; + for expr in args { + self.visit_expr(expr)?; + } + ControlFlow::Continue(()) + } + hir::ExprKind::MethodCall(_, receiver, args, _) => { + self.visit_expr(receiver)?; + for expr in args { + self.visit_expr(expr)?; + } + ControlFlow::Continue(()) + } + hir::ExprKind::Index(left, right, _) | hir::ExprKind::Binary(_, left, right) => { + self.visit_expr(left)?; + self.visit_expr(right) + } + hir::ExprKind::Unary(_, expr) + | hir::ExprKind::Cast(expr, _) + | hir::ExprKind::Type(expr, _) + | hir::ExprKind::Yield(expr, _) + | hir::ExprKind::AddrOf(_, _, expr) + | hir::ExprKind::Match(expr, _, _) + | hir::ExprKind::Field(expr, _) + | hir::ExprKind::Let(&hir::LetExpr { + init: expr, + span: _, + pat: _, + ty: _, + recovered: Recovered::No, + }) => self.visit_expr(expr), + hir::ExprKind::Let(_) => ControlFlow::Continue(()), + + hir::ExprKind::If(cond, _, _) => { + if let hir::ExprKind::Let(hir::LetExpr { + init, + span: _, + pat: _, + ty: _, + recovered: Recovered::No, + }) = cond.kind + { + self.visit_expr(init)?; + } + ControlFlow::Continue(()) + } + } + } +} diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index a9627e9b78907..58b51240a9097 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -56,6 +56,7 @@ mod expect; mod for_loops_over_fallibles; mod foreign_modules; pub mod hidden_unicode_codepoints; +mod if_let_rescope; mod impl_trait_overcaptures; mod internal; mod invalid_from_utf8; @@ -94,6 +95,7 @@ use drop_forget_useless::*; use enum_intrinsics_non_enums::EnumIntrinsicsNonEnums; use for_loops_over_fallibles::*; use hidden_unicode_codepoints::*; +use if_let_rescope::IfLetRescope; use impl_trait_overcaptures::ImplTraitOvercaptures; use internal::*; use invalid_from_utf8::*; @@ -243,6 +245,7 @@ late_lint_methods!( NonLocalDefinitions: NonLocalDefinitions::default(), ImplTraitOvercaptures: ImplTraitOvercaptures, TailExprDropOrder: TailExprDropOrder, + IfLetRescope: IfLetRescope, ] ] ); diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs index 6ef1801717c81..999743ed73b84 100644 --- a/compiler/rustc_middle/src/middle/region.rs +++ b/compiler/rustc_middle/src/middle/region.rs @@ -96,6 +96,7 @@ impl fmt::Debug for Scope { ScopeData::Arguments => write!(fmt, "Arguments({:?})", self.id), ScopeData::Destruction => write!(fmt, "Destruction({:?})", self.id), ScopeData::IfThen => write!(fmt, "IfThen({:?})", self.id), + ScopeData::IfThenRescope => write!(fmt, "IfThen[edition2024]({:?})", self.id), ScopeData::Remainder(fsi) => write!( fmt, "Remainder {{ block: {:?}, first_statement_index: {}}}", @@ -126,6 +127,11 @@ pub enum ScopeData { /// Used for variables introduced in an if-let expression. IfThen, + /// Scope of the condition and then block of an if expression + /// Used for variables introduced in an if-let expression, + /// whose lifetimes do not cross beyond this scope. + IfThenRescope, + /// Scope following a `let id = expr;` binding in a block. Remainder(FirstStatementIndex), } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 081a23b6ff317..557d2b29e75be 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1084,6 +1084,9 @@ pub enum LocalInfo<'tcx> { /// (with no intervening statement context). // FIXME(matthewjasper) Don't store in this in `Body` BlockTailTemp(BlockTailInfo), + /// A temporary created during evaluating `if` predicate, possibly for pattern matching for `let`s, + /// and subject to Edition 2024 temporary lifetime rules + IfThenRescopeTemp { if_then: HirId }, /// A temporary created during the pass `Derefer` to avoid it's retagging DerefTemp, /// A temporary created for borrow checking. diff --git a/compiler/rustc_middle/src/ty/rvalue_scopes.rs b/compiler/rustc_middle/src/ty/rvalue_scopes.rs index bcab54cf8bad0..37dcf7c0d649f 100644 --- a/compiler/rustc_middle/src/ty/rvalue_scopes.rs +++ b/compiler/rustc_middle/src/ty/rvalue_scopes.rs @@ -41,7 +41,15 @@ impl RvalueScopes { debug!("temporary_scope({expr_id:?}) = {id:?} [enclosing]"); return Some(id); } - _ => id = p, + ScopeData::IfThenRescope => { + debug!("temporary_scope({expr_id:?}) = {p:?} [enclosing]"); + return Some(p); + } + ScopeData::Node + | ScopeData::CallSite + | ScopeData::Arguments + | ScopeData::IfThen + | ScopeData::Remainder(_) => id = p, } } diff --git a/compiler/rustc_mir_build/src/build/expr/as_temp.rs b/compiler/rustc_mir_build/src/build/expr/as_temp.rs index af5940ff50e61..b8b5e4634ed89 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_temp.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_temp.rs @@ -1,7 +1,9 @@ //! See docs in build/expr/mod.rs use rustc_data_structures::stack::ensure_sufficient_stack; +use rustc_hir::HirId; use rustc_middle::middle::region; +use rustc_middle::middle::region::{Scope, ScopeData}; use rustc_middle::mir::*; use rustc_middle::thir::*; use tracing::{debug, instrument}; @@ -73,11 +75,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { _ if let Some(tail_info) = this.block_context.currently_in_block_tail() => { LocalInfo::BlockTailTemp(tail_info) } + + _ if let Some(Scope { data: ScopeData::IfThenRescope, id }) = temp_lifetime => { + LocalInfo::IfThenRescopeTemp { + if_then: HirId { owner: this.hir_id.owner, local_id: id }, + } + } + _ => LocalInfo::Boring, }; **local_decl.local_info.as_mut().assert_crate_local() = local_info; this.local_decls.push(local_decl) }; + debug!(?temp); if deduplicate_temps { this.fixed_temps.insert(expr_id, temp); } diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 89f98a40201e7..aa8ccc8b7ddd6 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -706,7 +706,13 @@ impl<'tcx> Cx<'tcx> { hir::ExprKind::If(cond, then, else_opt) => ExprKind::If { if_then_scope: region::Scope { id: then.hir_id.local_id, - data: region::ScopeData::IfThen, + data: { + if expr.span.at_least_rust_2024() && tcx.features().if_let_rescope { + region::ScopeData::IfThenRescope + } else { + region::ScopeData::IfThen + } + }, }, cond: self.mirror_expr(cond), then: self.mirror_expr(then), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index d5240a05310b6..d340b56fbe46b 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1017,6 +1017,7 @@ symbols! { ident, if_let, if_let_guard, + if_let_rescope, if_while_or_patterns, ignore, impl_header_lifetime_elision, diff --git a/tests/ui/drop/drop_order.rs b/tests/ui/drop/drop_order.rs index 54e9e491f7873..cf06253800745 100644 --- a/tests/ui/drop/drop_order.rs +++ b/tests/ui/drop/drop_order.rs @@ -1,6 +1,11 @@ //@ run-pass //@ compile-flags: -Z validate-mir +//@ revisions: edition2021 edition2024 +//@ [edition2021] edition: 2021 +//@ [edition2024] compile-flags: -Z unstable-options +//@ [edition2024] edition: 2024 #![feature(let_chains)] +#![cfg_attr(edition2024, feature(if_let_rescope))] use std::cell::RefCell; use std::convert::TryInto; @@ -55,11 +60,18 @@ impl DropOrderCollector { } fn if_let(&self) { + #[cfg(edition2021)] if let None = self.option_loud_drop(2) { unreachable!(); } else { self.print(1); } + #[cfg(edition2024)] + if let None = self.option_loud_drop(1) { + unreachable!(); + } else { + self.print(2); + } if let Some(_) = self.option_loud_drop(4) { self.print(3); @@ -194,6 +206,7 @@ impl DropOrderCollector { self.print(3); // 3 } + #[cfg(edition2021)] // take the "else" branch if self.option_loud_drop(5).is_some() // 1 && self.option_loud_drop(6).is_some() // 2 @@ -202,6 +215,15 @@ impl DropOrderCollector { } else { self.print(7); // 3 } + #[cfg(edition2024)] + // take the "else" branch + if self.option_loud_drop(5).is_some() // 1 + && self.option_loud_drop(6).is_some() // 2 + && let None = self.option_loud_drop(7) { // 4 + unreachable!(); + } else { + self.print(8); // 3 + } // let exprs interspersed if self.option_loud_drop(9).is_some() // 1 diff --git a/tests/ui/drop/drop_order_if_let_rescope.rs b/tests/ui/drop/drop_order_if_let_rescope.rs new file mode 100644 index 0000000000000..ae9f381820e16 --- /dev/null +++ b/tests/ui/drop/drop_order_if_let_rescope.rs @@ -0,0 +1,122 @@ +//@ run-pass +//@ edition:2024 +//@ compile-flags: -Z validate-mir -Zunstable-options + +#![feature(let_chains)] +#![feature(if_let_rescope)] + +use std::cell::RefCell; +use std::convert::TryInto; + +#[derive(Default)] +struct DropOrderCollector(RefCell>); + +struct LoudDrop<'a>(&'a DropOrderCollector, u32); + +impl Drop for LoudDrop<'_> { + fn drop(&mut self) { + println!("{}", self.1); + self.0.0.borrow_mut().push(self.1); + } +} + +impl DropOrderCollector { + fn option_loud_drop(&self, n: u32) -> Option { + Some(LoudDrop(self, n)) + } + + fn print(&self, n: u32) { + println!("{}", n); + self.0.borrow_mut().push(n) + } + + fn assert_sorted(self) { + assert!( + self.0 + .into_inner() + .into_iter() + .enumerate() + .all(|(idx, item)| idx + 1 == item.try_into().unwrap()) + ); + } + + fn if_let(&self) { + if let None = self.option_loud_drop(1) { + unreachable!(); + } else { + self.print(2); + } + + if let Some(_) = self.option_loud_drop(4) { + self.print(3); + } + + if let Some(_d) = self.option_loud_drop(6) { + self.print(5); + } + } + + fn let_chain(&self) { + // take the "then" branch + if self.option_loud_drop(1).is_some() // 1 + && self.option_loud_drop(2).is_some() // 2 + && let Some(_d) = self.option_loud_drop(4) + // 4 + { + self.print(3); // 3 + } + + // take the "else" branch + if self.option_loud_drop(5).is_some() // 1 + && self.option_loud_drop(6).is_some() // 2 + && let None = self.option_loud_drop(7) + // 3 + { + unreachable!(); + } else { + self.print(8); // 4 + } + + // let exprs interspersed + if self.option_loud_drop(9).is_some() // 1 + && let Some(_d) = self.option_loud_drop(13) // 5 + && self.option_loud_drop(10).is_some() // 2 + && let Some(_e) = self.option_loud_drop(12) + // 4 + { + self.print(11); // 3 + } + + // let exprs first + if let Some(_d) = self.option_loud_drop(18) // 5 + && let Some(_e) = self.option_loud_drop(17) // 4 + && self.option_loud_drop(14).is_some() // 1 + && self.option_loud_drop(15).is_some() + // 2 + { + self.print(16); // 3 + } + + // let exprs last + if self.option_loud_drop(19).is_some() // 1 + && self.option_loud_drop(20).is_some() // 2 + && let Some(_d) = self.option_loud_drop(23) // 5 + && let Some(_e) = self.option_loud_drop(22) + // 4 + { + self.print(21); // 3 + } + } +} + +fn main() { + println!("-- if let --"); + let collector = DropOrderCollector::default(); + collector.if_let(); + collector.assert_sorted(); + + println!("-- let chain --"); + let collector = DropOrderCollector::default(); + collector.let_chain(); + collector.assert_sorted(); +} diff --git a/tests/ui/drop/if-let-rescope-borrowck-suggestions.fixed b/tests/ui/drop/if-let-rescope-borrowck-suggestions.fixed new file mode 100644 index 0000000000000..129e78ea9fe7d --- /dev/null +++ b/tests/ui/drop/if-let-rescope-borrowck-suggestions.fixed @@ -0,0 +1,26 @@ +//@ edition: 2024 +//@ compile-flags: -Z validate-mir -Zunstable-options +//@ run-rustfix + +#![feature(if_let_rescope)] +#![deny(if_let_rescope)] + +struct Droppy; +impl Drop for Droppy { + fn drop(&mut self) { + println!("dropped"); + } +} +impl Droppy { + fn get_ref(&self) -> Option<&u8> { + None + } +} + +fn do_something(_: &T) {} + +fn main() { + let binding = Droppy; + do_something(match binding.get_ref() { Some(value) => { value } _ => { &0 }}); + //~^ ERROR: temporary value dropped while borrowed +} diff --git a/tests/ui/drop/if-let-rescope-borrowck-suggestions.rs b/tests/ui/drop/if-let-rescope-borrowck-suggestions.rs new file mode 100644 index 0000000000000..1970d5c0f7ed2 --- /dev/null +++ b/tests/ui/drop/if-let-rescope-borrowck-suggestions.rs @@ -0,0 +1,25 @@ +//@ edition: 2024 +//@ compile-flags: -Z validate-mir -Zunstable-options +//@ run-rustfix + +#![feature(if_let_rescope)] +#![deny(if_let_rescope)] + +struct Droppy; +impl Drop for Droppy { + fn drop(&mut self) { + println!("dropped"); + } +} +impl Droppy { + fn get_ref(&self) -> Option<&u8> { + None + } +} + +fn do_something(_: &T) {} + +fn main() { + do_something(if let Some(value) = Droppy.get_ref() { value } else { &0 }); + //~^ ERROR: temporary value dropped while borrowed +} diff --git a/tests/ui/drop/if-let-rescope-borrowck-suggestions.stderr b/tests/ui/drop/if-let-rescope-borrowck-suggestions.stderr new file mode 100644 index 0000000000000..fa154f01a12e9 --- /dev/null +++ b/tests/ui/drop/if-let-rescope-borrowck-suggestions.stderr @@ -0,0 +1,26 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/if-let-rescope-borrowck-suggestions.rs:23:39 + | +LL | do_something(if let Some(value) = Droppy.get_ref() { value } else { &0 }); + | ^^^^^^ - temporary value is freed at the end of this statement + | | + | creates a temporary value which is freed while still in use + | +note: lifetime for temporaries generated in `if let`s have been shorted in Edition 2024 + --> $DIR/if-let-rescope-borrowck-suggestions.rs:23:65 + | +LL | do_something(if let Some(value) = Droppy.get_ref() { value } else { &0 }); + | ^ +help: consider using a `let` binding to create a longer lived value + | +LL ~ let binding = Droppy; +LL ~ do_something(if let Some(value) = binding.get_ref() { value } else { &0 }); + | +help: consider rewriting the `if` into `match` which preserves the extended lifetime + | +LL | do_something(match Droppy.get_ref() { Some(value) => { value } _ => { &0 }}); + | ~~~~~ ++++++++++++++++ ~~~~ + + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/drop/lint-if-let-rescope-gated.rs b/tests/ui/drop/lint-if-let-rescope-gated.rs new file mode 100644 index 0000000000000..f8844a09f7c50 --- /dev/null +++ b/tests/ui/drop/lint-if-let-rescope-gated.rs @@ -0,0 +1,31 @@ +// This test checks that the lint `if_let_rescope` only actions +// when the feature gate is enabled. +// Edition 2021 is used here because the lint should work especially +// when edition migration towards 2024 is run. + +//@ revisions: with_feature_gate without_feature_gate +//@ [without_feature_gate] check-pass +//@ edition: 2021 + +#![cfg_attr(with_feature_gate, feature(if_let_rescope))] +#![deny(if_let_rescope)] +#![allow(irrefutable_let_patterns)] + +struct Droppy; +impl Drop for Droppy { + fn drop(&mut self) { + println!("dropped"); + } +} +impl Droppy { + fn get(&self) -> Option { + None + } +} + +fn main() { + if let Some(_value) = Droppy.get() { + //[with_feature_gate]~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //[with_feature_gate]~| WARN: this changes meaning in Rust 2024 + }; +} diff --git a/tests/ui/drop/lint-if-let-rescope-gated.with_feature_gate.stderr b/tests/ui/drop/lint-if-let-rescope-gated.with_feature_gate.stderr new file mode 100644 index 0000000000000..7c295b7f9d89f --- /dev/null +++ b/tests/ui/drop/lint-if-let-rescope-gated.with_feature_gate.stderr @@ -0,0 +1,30 @@ +error: `if let` assigns a shorter lifetime since Edition 2024 + --> $DIR/lint-if-let-rescope-gated.rs:27:8 + | +LL | if let Some(_value) = Droppy.get() { + | ^^^^^^^^^^^^^^^^^^^------^^^^^^ + | | + | this value has a significant drop implementation which may observe a major change in drop order and requires your discretion + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see issue #124085 +help: the value is now dropped here in Edition 2024 + --> $DIR/lint-if-let-rescope-gated.rs:30:5 + | +LL | }; + | ^ +note: the lint level is defined here + --> $DIR/lint-if-let-rescope-gated.rs:11:9 + | +LL | #![deny(if_let_rescope)] + | ^^^^^^^^^^^^^^ +help: rewrite this `if let` into a `match` with a single arm to preserve the drop order up to Edition 2021 + | +LL ~ match Droppy.get() { Some(_value) => { +LL | +LL | +LL ~ } _ => {} }; + | + +error: aborting due to 1 previous error + diff --git a/tests/ui/drop/lint-if-let-rescope-with-macro.rs b/tests/ui/drop/lint-if-let-rescope-with-macro.rs new file mode 100644 index 0000000000000..282b3320d3004 --- /dev/null +++ b/tests/ui/drop/lint-if-let-rescope-with-macro.rs @@ -0,0 +1,41 @@ +// This test ensures that no suggestion is emitted if the span originates from +// an expansion that is probably not under a user's control. + +//@ edition:2021 +//@ compile-flags: -Z unstable-options + +#![feature(if_let_rescope)] +#![deny(if_let_rescope)] +#![allow(irrefutable_let_patterns)] + +macro_rules! edition_2021_if_let { + ($p:pat, $e:expr, { $($conseq:tt)* } { $($alt:tt)* }) => { + if let $p = $e { $($conseq)* } else { $($alt)* } + //~^ ERROR `if let` assigns a shorter lifetime since Edition 2024 + //~| WARN this changes meaning in Rust 2024 + } +} + +fn droppy() -> Droppy { + Droppy +} +struct Droppy; +impl Drop for Droppy { + fn drop(&mut self) { + println!("dropped"); + } +} +impl Droppy { + fn get(&self) -> Option { + None + } +} + +fn main() { + edition_2021_if_let! { + Some(_value), + droppy().get(), + {} + {} + }; +} diff --git a/tests/ui/drop/lint-if-let-rescope-with-macro.stderr b/tests/ui/drop/lint-if-let-rescope-with-macro.stderr new file mode 100644 index 0000000000000..5fd0c61d17a57 --- /dev/null +++ b/tests/ui/drop/lint-if-let-rescope-with-macro.stderr @@ -0,0 +1,39 @@ +error: `if let` assigns a shorter lifetime since Edition 2024 + --> $DIR/lint-if-let-rescope-with-macro.rs:13:12 + | +LL | if let $p = $e { $($conseq)* } else { $($alt)* } + | ^^^ +... +LL | / edition_2021_if_let! { +LL | | Some(_value), +LL | | droppy().get(), + | | -------- this value has a significant drop implementation which may observe a major change in drop order and requires your discretion +LL | | {} +LL | | {} +LL | | }; + | |_____- in this macro invocation + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see issue #124085 +help: the value is now dropped here in Edition 2024 + --> $DIR/lint-if-let-rescope-with-macro.rs:13:38 + | +LL | if let $p = $e { $($conseq)* } else { $($alt)* } + | ^ +... +LL | / edition_2021_if_let! { +LL | | Some(_value), +LL | | droppy().get(), +LL | | {} +LL | | {} +LL | | }; + | |_____- in this macro invocation +note: the lint level is defined here + --> $DIR/lint-if-let-rescope-with-macro.rs:8:9 + | +LL | #![deny(if_let_rescope)] + | ^^^^^^^^^^^^^^ + = note: this error originates in the macro `edition_2021_if_let` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 1 previous error + diff --git a/tests/ui/drop/lint-if-let-rescope.fixed b/tests/ui/drop/lint-if-let-rescope.fixed new file mode 100644 index 0000000000000..7ed7e4b279c03 --- /dev/null +++ b/tests/ui/drop/lint-if-let-rescope.fixed @@ -0,0 +1,48 @@ +//@ edition:2024 +//@ compile-flags: -Z validate-mir -Zunstable-options +//@ run-rustfix + +#![feature(if_let_rescope)] +#![deny(if_let_rescope)] +#![allow(irrefutable_let_patterns)] + +fn droppy() -> Droppy { + Droppy +} +struct Droppy; +impl Drop for Droppy { + fn drop(&mut self) { + println!("dropped"); + } +} +impl Droppy { + fn get(&self) -> Option { + None + } +} + +fn main() { + match droppy().get() { Some(_value) => { + //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //~| WARN: this changes meaning in Rust 2024 + //~| HELP: rewrite this `if let` into a `match` + // do something + } _ => { + //~^ HELP: the value is now dropped here in Edition 2024 + // do something else + }} + + if let Some(1) = { match Droppy.get() { Some(_value) => { Some(1) } _ => { None }} } { + //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //~| WARN: this changes meaning in Rust 2024 + //~| HELP: rewrite this `if let` into a `match` + //~| HELP: the value is now dropped here in Edition 2024 + } + + if let () = { match Droppy.get() { Some(_value) => {} _ => {} } } { + //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //~| WARN: this changes meaning in Rust 2024 + //~| HELP: rewrite this `if let` into a `match` + //~| HELP: the value is now dropped here in Edition 2024 + } +} diff --git a/tests/ui/drop/lint-if-let-rescope.rs b/tests/ui/drop/lint-if-let-rescope.rs new file mode 100644 index 0000000000000..d282cd2626b8f --- /dev/null +++ b/tests/ui/drop/lint-if-let-rescope.rs @@ -0,0 +1,48 @@ +//@ edition:2024 +//@ compile-flags: -Z validate-mir -Zunstable-options +//@ run-rustfix + +#![feature(if_let_rescope)] +#![deny(if_let_rescope)] +#![allow(irrefutable_let_patterns)] + +fn droppy() -> Droppy { + Droppy +} +struct Droppy; +impl Drop for Droppy { + fn drop(&mut self) { + println!("dropped"); + } +} +impl Droppy { + fn get(&self) -> Option { + None + } +} + +fn main() { + if let Some(_value) = droppy().get() { + //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //~| WARN: this changes meaning in Rust 2024 + //~| HELP: rewrite this `if let` into a `match` + // do something + } else { + //~^ HELP: the value is now dropped here in Edition 2024 + // do something else + } + + if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } else { None } } { + //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //~| WARN: this changes meaning in Rust 2024 + //~| HELP: rewrite this `if let` into a `match` + //~| HELP: the value is now dropped here in Edition 2024 + } + + if let () = { if let Some(_value) = Droppy.get() {} } { + //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //~| WARN: this changes meaning in Rust 2024 + //~| HELP: rewrite this `if let` into a `match` + //~| HELP: the value is now dropped here in Edition 2024 + } +} diff --git a/tests/ui/drop/lint-if-let-rescope.stderr b/tests/ui/drop/lint-if-let-rescope.stderr new file mode 100644 index 0000000000000..832e73b898cbb --- /dev/null +++ b/tests/ui/drop/lint-if-let-rescope.stderr @@ -0,0 +1,74 @@ +error: `if let` assigns a shorter lifetime since Edition 2024 + --> $DIR/lint-if-let-rescope.rs:25:8 + | +LL | if let Some(_value) = droppy().get() { + | ^^^^^^^^^^^^^^^^^^^--------^^^^^^ + | | + | this value has a significant drop implementation which may observe a major change in drop order and requires your discretion + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see issue #124085 +help: the value is now dropped here in Edition 2024 + --> $DIR/lint-if-let-rescope.rs:30:5 + | +LL | } else { + | ^ +note: the lint level is defined here + --> $DIR/lint-if-let-rescope.rs:6:9 + | +LL | #![deny(if_let_rescope)] + | ^^^^^^^^^^^^^^ +help: rewrite this `if let` into a `match` with a single arm to preserve the drop order up to Edition 2021 + | +LL ~ match droppy().get() { Some(_value) => { +LL | +... +LL | // do something +LL ~ } _ => { +LL | +LL | // do something else +LL ~ }} + | + +error: `if let` assigns a shorter lifetime since Edition 2024 + --> $DIR/lint-if-let-rescope.rs:35:27 + | +LL | if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } else { None } } { + | ^^^^^^^^^^^^^^^^^^^------^^^^^^ + | | + | this value has a significant drop implementation which may observe a major change in drop order and requires your discretion + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see issue #124085 +help: the value is now dropped here in Edition 2024 + --> $DIR/lint-if-let-rescope.rs:35:69 + | +LL | if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } else { None } } { + | ^ +help: rewrite this `if let` into a `match` with a single arm to preserve the drop order up to Edition 2021 + | +LL | if let Some(1) = { match Droppy.get() { Some(_value) => { Some(1) } _ => { None }} } { + | ~~~~~ +++++++++++++++++ ~~~~ + + +error: `if let` assigns a shorter lifetime since Edition 2024 + --> $DIR/lint-if-let-rescope.rs:42:22 + | +LL | if let () = { if let Some(_value) = Droppy.get() {} } { + | ^^^^^^^^^^^^^^^^^^^------^^^^^^ + | | + | this value has a significant drop implementation which may observe a major change in drop order and requires your discretion + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see issue #124085 +help: the value is now dropped here in Edition 2024 + --> $DIR/lint-if-let-rescope.rs:42:55 + | +LL | if let () = { if let Some(_value) = Droppy.get() {} } { + | ^ +help: rewrite this `if let` into a `match` with a single arm to preserve the drop order up to Edition 2021 + | +LL | if let () = { match Droppy.get() { Some(_value) => {} _ => {} } } { + | ~~~~~ +++++++++++++++++ +++++++++ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/feature-gates/feature-gate-if-let-rescope.rs b/tests/ui/feature-gates/feature-gate-if-let-rescope.rs new file mode 100644 index 0000000000000..bd1efd4fb7c1f --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-if-let-rescope.rs @@ -0,0 +1,27 @@ +// This test shows the code that could have been accepted by enabling #![feature(if_let_rescope)] + +struct A; +struct B<'a, T>(&'a mut T); + +impl A { + fn f(&mut self) -> Option> { + Some(B(self)) + } +} + +impl<'a, T> Drop for B<'a, T> { + fn drop(&mut self) { + // this is needed to keep NLL's hands off and to ensure + // the inner mutable borrow stays alive + } +} + +fn main() { + let mut a = A; + if let None = a.f().as_ref() { + unreachable!() + } else { + a.f().unwrap(); + //~^ ERROR cannot borrow `a` as mutable more than once at a time + }; +} diff --git a/tests/ui/feature-gates/feature-gate-if-let-rescope.stderr b/tests/ui/feature-gates/feature-gate-if-let-rescope.stderr new file mode 100644 index 0000000000000..ff1846ae0b1f5 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-if-let-rescope.stderr @@ -0,0 +1,18 @@ +error[E0499]: cannot borrow `a` as mutable more than once at a time + --> $DIR/feature-gate-if-let-rescope.rs:24:9 + | +LL | if let None = a.f().as_ref() { + | ----- + | | + | first mutable borrow occurs here + | a temporary with access to the first borrow is created here ... +... +LL | a.f().unwrap(); + | ^ second mutable borrow occurs here +LL | +LL | }; + | - ... and the first borrow might be used here, when that temporary is dropped and runs the destructor for type `Option>` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/mir/mir_let_chains_drop_order.rs b/tests/ui/mir/mir_let_chains_drop_order.rs index 5cbfdf2e35a74..daf0a62fc85f3 100644 --- a/tests/ui/mir/mir_let_chains_drop_order.rs +++ b/tests/ui/mir/mir_let_chains_drop_order.rs @@ -1,9 +1,14 @@ //@ run-pass //@ needs-unwind +//@ revisions: edition2021 edition2024 +//@ [edition2021] edition: 2021 +//@ [edition2024] compile-flags: -Z unstable-options +//@ [edition2024] edition: 2024 // See `mir_drop_order.rs` for more information #![feature(let_chains)] +#![cfg_attr(edition2024, feature(if_let_rescope))] #![allow(irrefutable_let_patterns)] use std::cell::RefCell; @@ -39,25 +44,32 @@ fn main() { 0, d( 1, - if let Some(_) = d(2, Some(true)).extra && let DropLogger { .. } = d(3, None) { + if let Some(_) = d(2, Some(true)).extra + && let DropLogger { .. } = d(3, None) + { None } else { Some(true) - } - ).extra + }, + ) + .extra, ), d(4, None), &d(5, None), d(6, None), - if let DropLogger { .. } = d(7, None) && let DropLogger { .. } = d(8, None) { + if let DropLogger { .. } = d(7, None) + && let DropLogger { .. } = d(8, None) + { d(9, None) - } - else { + } else { // 10 is not constructed d(10, None) }, ); + #[cfg(edition2021)] assert_eq!(get(), vec![8, 7, 1, 3, 2]); + #[cfg(edition2024)] + assert_eq!(get(), vec![3, 2, 8, 7, 1]); } assert_eq!(get(), vec![0, 4, 6, 9, 5]); @@ -73,21 +85,26 @@ fn main() { None } else { Some(true) - } - ).extra + }, + ) + .extra, ), d(15, None), &d(16, None), d(17, None), - if let DropLogger { .. } = d(18, None) && let DropLogger { .. } = d(19, None) { + if let DropLogger { .. } = d(18, None) + && let DropLogger { .. } = d(19, None) + { d(20, None) - } - else { + } else { // 10 is not constructed d(21, None) }, - panic::panic_any(InjectedFailure) + panic::panic_any(InjectedFailure), ); }); + #[cfg(edition2021)] assert_eq!(get(), vec![20, 17, 15, 11, 19, 18, 16, 12, 14, 13]); + #[cfg(edition2024)] + assert_eq!(get(), vec![14, 13, 19, 18, 20, 17, 15, 11, 16, 12]); } diff --git a/tests/ui/nll/issue-54556-niconii.stderr b/tests/ui/nll/issue-54556-niconii.edition2021.stderr similarity index 96% rename from tests/ui/nll/issue-54556-niconii.stderr rename to tests/ui/nll/issue-54556-niconii.edition2021.stderr index 015d9e1821205..31a03abbc9826 100644 --- a/tests/ui/nll/issue-54556-niconii.stderr +++ b/tests/ui/nll/issue-54556-niconii.edition2021.stderr @@ -1,5 +1,5 @@ error[E0597]: `counter` does not live long enough - --> $DIR/issue-54556-niconii.rs:22:20 + --> $DIR/issue-54556-niconii.rs:30:20 | LL | let counter = Mutex; | ------- binding `counter` declared here diff --git a/tests/ui/nll/issue-54556-niconii.rs b/tests/ui/nll/issue-54556-niconii.rs index cae389e8ccb52..1a7ad17cc84c0 100644 --- a/tests/ui/nll/issue-54556-niconii.rs +++ b/tests/ui/nll/issue-54556-niconii.rs @@ -6,6 +6,14 @@ // of temp drop order, and thus why inserting a semi-colon after the // `if let` expression in `main` works. +//@ revisions: edition2021 edition2024 +//@ [edition2021] edition: 2021 +//@ [edition2024] edition: 2024 +//@ [edition2024] compile-flags: -Z unstable-options +//@ [edition2024] check-pass + +#![cfg_attr(edition2024, feature(if_let_rescope))] + struct Mutex; struct MutexGuard<'a>(&'a Mutex); @@ -19,8 +27,10 @@ impl Mutex { fn main() { let counter = Mutex; - if let Ok(_) = counter.lock() { } //~ ERROR does not live long enough + if let Ok(_) = counter.lock() { } + //[edition2021]~^ ERROR: does not live long enough + // Up until Edition 2021: // With this code as written, the dynamic semantics here implies // that `Mutex::drop` for `counter` runs *before* // `MutexGuard::drop`, which would be unsound since `MutexGuard` @@ -28,4 +38,11 @@ fn main() { // // The goal of #54556 is to explain that within a compiler // diagnostic. + + // From Edition 2024: + // Now `MutexGuard::drop` runs *before* `Mutex::drop` because + // the lifetime of the `MutexGuard` is shortened to cover only + // from `if let` until the end of the consequent block. + // Therefore, Niconii's issue is properly solved thanks to the new + // temporary lifetime rule for `if let`s. } From e2120a7c3853226e486988b40196ff87b5eacb42 Mon Sep 17 00:00:00 2001 From: Ding Xiang Fei Date: Fri, 6 Sep 2024 03:03:10 +0800 Subject: [PATCH 145/189] coalesce lint suggestions that can intersect --- compiler/rustc_lint/messages.ftl | 4 +- compiler/rustc_lint/src/if_let_rescope.rs | 319 ++++++++++++------ compiler/rustc_lint/src/lib.rs | 2 +- tests/ui/drop/lint-if-let-rescope-gated.rs | 5 +- ...let-rescope-gated.with_feature_gate.stderr | 40 ++- tests/ui/drop/lint-if-let-rescope.fixed | 69 +++- tests/ui/drop/lint-if-let-rescope.rs | 63 +++- tests/ui/drop/lint-if-let-rescope.stderr | 223 ++++++++++-- 8 files changed, 568 insertions(+), 157 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 1f8dca337fc8e..2d062465bcfba 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -337,7 +337,9 @@ lint_identifier_uncommon_codepoints = identifier contains {$codepoints_len -> lint_if_let_rescope = `if let` assigns a shorter lifetime since Edition 2024 .label = this value has a significant drop implementation which may observe a major change in drop order and requires your discretion .help = the value is now dropped here in Edition 2024 - .suggestion = rewrite this `if let` into a `match` with a single arm to preserve the drop order up to Edition 2021 + +lint_if_let_rescope_suggestion = a `match` with a single arm can preserve the drop order up to Edition 2021 + .suggestion = rewrite this `if let` into `match` lint_ignored_unless_crate_specified = {$level}({$name}) is ignored unless specified at crate level diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs index 143965ae58f7e..e5bf192d23e31 100644 --- a/compiler/rustc_lint/src/if_let_rescope.rs +++ b/compiler/rustc_lint/src/if_let_rescope.rs @@ -1,11 +1,16 @@ +use std::iter::repeat; use std::ops::ControlFlow; use hir::intravisit::Visitor; use rustc_ast::Recovered; -use rustc_hir as hir; +use rustc_errors::{ + Applicability, Diag, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic, SuggestionStyle, +}; +use rustc_hir::{self as hir, HirIdSet}; use rustc_macros::{LintDiagnostic, Subdiagnostic}; -use rustc_session::lint::FutureIncompatibilityReason; -use rustc_session::{declare_lint, declare_lint_pass}; +use rustc_middle::ty::TyCtxt; +use rustc_session::lint::{FutureIncompatibilityReason, Level}; +use rustc_session::{declare_lint, impl_lint_pass}; use rustc_span::edition::Edition; use rustc_span::Span; @@ -84,138 +89,236 @@ declare_lint! { }; } -declare_lint_pass!( - /// Lint for potential change in program semantics of `if let`s - IfLetRescope => [IF_LET_RESCOPE] -); +/// Lint for potential change in program semantics of `if let`s +#[derive(Default)] +pub(crate) struct IfLetRescope { + skip: HirIdSet, +} -impl<'tcx> LateLintPass<'tcx> for IfLetRescope { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { - if !expr.span.edition().at_least_rust_2021() || !cx.tcx.features().if_let_rescope { +fn expr_parent_is_else(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool { + let Some((_, hir::Node::Expr(expr))) = tcx.hir().parent_iter(hir_id).next() else { + return false; + }; + let hir::ExprKind::If(_cond, _conseq, Some(alt)) = expr.kind else { return false }; + alt.hir_id == hir_id +} + +fn expr_parent_is_stmt(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool { + let Some((_, hir::Node::Stmt(stmt))) = tcx.hir().parent_iter(hir_id).next() else { + return false; + }; + let (hir::StmtKind::Semi(expr) | hir::StmtKind::Expr(expr)) = stmt.kind else { return false }; + expr.hir_id == hir_id +} + +fn match_head_needs_bracket(tcx: TyCtxt<'_>, expr: &hir::Expr<'_>) -> bool { + expr_parent_is_else(tcx, expr.hir_id) && matches!(expr.kind, hir::ExprKind::If(..)) +} + +impl IfLetRescope { + fn probe_if_cascade<'tcx>(&mut self, cx: &LateContext<'tcx>, mut expr: &'tcx hir::Expr<'tcx>) { + if self.skip.contains(&expr.hir_id) { return; } - let hir::ExprKind::If(cond, conseq, alt) = expr.kind else { return }; - let hir::ExprKind::Let(&hir::LetExpr { - span, - pat, - init, - ty: ty_ascription, - recovered: Recovered::No, - }) = cond.kind - else { - return; - }; - let source_map = cx.tcx.sess.source_map(); + let tcx = cx.tcx; + let source_map = tcx.sess.source_map(); let expr_end = expr.span.shrink_to_hi(); - let if_let_pat = expr.span.shrink_to_lo().between(init.span); - let before_conseq = conseq.span.shrink_to_lo(); - let lifetime_end = source_map.end_point(conseq.span); + let mut add_bracket_to_match_head = match_head_needs_bracket(tcx, expr); + let mut closing_brackets = 0; + let mut alt_heads = vec![]; + let mut match_heads = vec![]; + let mut consequent_heads = vec![]; + let mut first_if_to_rewrite = None; + let mut empty_alt = false; + while let hir::ExprKind::If(cond, conseq, alt) = expr.kind { + self.skip.insert(expr.hir_id); + let hir::ExprKind::Let(&hir::LetExpr { + span, + pat, + init, + ty: ty_ascription, + recovered: Recovered::No, + }) = cond.kind + else { + if let Some(alt) = alt { + add_bracket_to_match_head = matches!(alt.kind, hir::ExprKind::If(..)); + expr = alt; + continue; + } else { + // finalize and emit span + break; + } + }; + let if_let_pat = expr.span.shrink_to_lo().between(init.span); + // the consequent fragment is always a block + let before_conseq = conseq.span.shrink_to_lo(); + let lifetime_end = source_map.end_point(conseq.span); - if let ControlFlow::Break(significant_dropper) = - (FindSignificantDropper { cx }).visit_expr(init) - { - let lint_without_suggestion = || { - cx.tcx.emit_node_span_lint( + if let ControlFlow::Break(significant_dropper) = + (FindSignificantDropper { cx }).visit_expr(init) + { + tcx.emit_node_span_lint( IF_LET_RESCOPE, expr.hir_id, span, - IfLetRescopeRewrite { significant_dropper, lifetime_end, sugg: None }, - ) - }; - if ty_ascription.is_some() - || !expr.span.can_be_used_for_suggestions() - || !pat.span.can_be_used_for_suggestions() - { - // Our `match` rewrites does not support type ascription, - // so we just bail. - // Alternatively when the span comes from proc macro expansion, - // we will also bail. - // FIXME(#101728): change this when type ascription syntax is stabilized again - lint_without_suggestion(); - } else { - let Ok(pat) = source_map.span_to_snippet(pat.span) else { - lint_without_suggestion(); - return; - }; - if let Some(alt) = alt { - let alt_start = conseq.span.between(alt.span); - if !alt_start.can_be_used_for_suggestions() { - lint_without_suggestion(); - return; + IfLetRescopeLint { significant_dropper, lifetime_end }, + ); + if ty_ascription.is_some() + || !expr.span.can_be_used_for_suggestions() + || !pat.span.can_be_used_for_suggestions() + { + // Our `match` rewrites does not support type ascription, + // so we just bail. + // Alternatively when the span comes from proc macro expansion, + // we will also bail. + // FIXME(#101728): change this when type ascription syntax is stabilized again + } else if let Ok(pat) = source_map.span_to_snippet(pat.span) { + let emit_suggestion = || { + first_if_to_rewrite = + first_if_to_rewrite.or_else(|| Some((expr.span, expr.hir_id))); + if add_bracket_to_match_head { + closing_brackets += 2; + match_heads.push(SingleArmMatchBegin::WithOpenBracket(if_let_pat)); + } else { + // It has to be a block + closing_brackets += 1; + match_heads.push(SingleArmMatchBegin::WithoutOpenBracket(if_let_pat)); + } + consequent_heads.push(ConsequentRewrite { span: before_conseq, pat }); + }; + if let Some(alt) = alt { + let alt_head = conseq.span.between(alt.span); + if alt_head.can_be_used_for_suggestions() { + // lint + emit_suggestion(); + alt_heads.push(AltHead(alt_head)); + } + } else { + emit_suggestion(); + empty_alt = true; + break; } - cx.tcx.emit_node_span_lint( - IF_LET_RESCOPE, - expr.hir_id, - span, - IfLetRescopeRewrite { - significant_dropper, - lifetime_end, - sugg: Some(IfLetRescopeRewriteSuggestion::WithElse { - if_let_pat, - before_conseq, - pat, - expr_end, - alt_start, - }), - }, - ); - } else { - cx.tcx.emit_node_span_lint( - IF_LET_RESCOPE, - expr.hir_id, - span, - IfLetRescopeRewrite { - significant_dropper, - lifetime_end, - sugg: Some(IfLetRescopeRewriteSuggestion::WithoutElse { - if_let_pat, - before_conseq, - pat, - expr_end, - }), - }, - ); } } + if let Some(alt) = alt { + add_bracket_to_match_head = matches!(alt.kind, hir::ExprKind::If(..)); + expr = alt; + } else { + break; + } + } + if let Some((span, hir_id)) = first_if_to_rewrite { + tcx.emit_node_span_lint( + IF_LET_RESCOPE, + hir_id, + span, + IfLetRescopeRewrite { + match_heads, + consequent_heads, + closing_brackets: ClosingBrackets { + span: expr_end, + count: closing_brackets, + empty_alt, + }, + alt_heads, + }, + ); } } } +impl_lint_pass!( + IfLetRescope => [IF_LET_RESCOPE] +); + +impl<'tcx> LateLintPass<'tcx> for IfLetRescope { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { + if expr.span.edition().at_least_rust_2024() || !cx.tcx.features().if_let_rescope { + return; + } + if let (Level::Allow, _) = cx.tcx.lint_level_at_node(IF_LET_RESCOPE, expr.hir_id) { + return; + } + if expr_parent_is_stmt(cx.tcx, expr.hir_id) + && matches!(expr.kind, hir::ExprKind::If(_cond, _conseq, None)) + { + // `if let` statement without an `else` branch has no observable change + // so we can skip linting it + return; + } + self.probe_if_cascade(cx, expr); + } +} + #[derive(LintDiagnostic)] #[diag(lint_if_let_rescope)] -struct IfLetRescopeRewrite { +struct IfLetRescopeLint { #[label] significant_dropper: Span, #[help] lifetime_end: Span, +} + +#[derive(LintDiagnostic)] +#[diag(lint_if_let_rescope_suggestion)] +struct IfLetRescopeRewrite { + #[subdiagnostic] + match_heads: Vec, + #[subdiagnostic] + consequent_heads: Vec, #[subdiagnostic] - sugg: Option, + closing_brackets: ClosingBrackets, + #[subdiagnostic] + alt_heads: Vec, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] +struct AltHead(#[suggestion_part(code = " _ => ")] Span); + +#[derive(Subdiagnostic)] +#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] +struct ConsequentRewrite { + #[suggestion_part(code = "{{ {pat} => ")] + span: Span, + pat: String, +} + +struct ClosingBrackets { + span: Span, + count: usize, + empty_alt: bool, +} + +impl Subdiagnostic for ClosingBrackets { + fn add_to_diag_with>( + self, + diag: &mut Diag<'_, G>, + f: &F, + ) { + let code: String = self + .empty_alt + .then_some(" _ => {}".chars()) + .into_iter() + .flatten() + .chain(repeat('}').take(self.count)) + .collect(); + let msg = f(diag, crate::fluent_generated::lint_suggestion.into()); + diag.multipart_suggestion_with_style( + msg, + vec![(self.span, code)], + Applicability::MachineApplicable, + SuggestionStyle::ShowCode, + ); + } } #[derive(Subdiagnostic)] -enum IfLetRescopeRewriteSuggestion { +enum SingleArmMatchBegin { #[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] - WithElse { - #[suggestion_part(code = "match ")] - if_let_pat: Span, - #[suggestion_part(code = " {{ {pat} => ")] - before_conseq: Span, - pat: String, - #[suggestion_part(code = "}}")] - expr_end: Span, - #[suggestion_part(code = " _ => ")] - alt_start: Span, - }, + WithOpenBracket(#[suggestion_part(code = "{{ match ")] Span), #[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] - WithoutElse { - #[suggestion_part(code = "match ")] - if_let_pat: Span, - #[suggestion_part(code = " {{ {pat} => ")] - before_conseq: Span, - pat: String, - #[suggestion_part(code = " _ => {{}} }}")] - expr_end: Span, - }, + WithoutOpenBracket(#[suggestion_part(code = "match ")] Span), } struct FindSignificantDropper<'tcx, 'a> { diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 58b51240a9097..0c32157758cdf 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -245,7 +245,7 @@ late_lint_methods!( NonLocalDefinitions: NonLocalDefinitions::default(), ImplTraitOvercaptures: ImplTraitOvercaptures, TailExprDropOrder: TailExprDropOrder, - IfLetRescope: IfLetRescope, + IfLetRescope: IfLetRescope::default(), ] ] ); diff --git a/tests/ui/drop/lint-if-let-rescope-gated.rs b/tests/ui/drop/lint-if-let-rescope-gated.rs index f8844a09f7c50..08ded67a51257 100644 --- a/tests/ui/drop/lint-if-let-rescope-gated.rs +++ b/tests/ui/drop/lint-if-let-rescope-gated.rs @@ -26,6 +26,9 @@ impl Droppy { fn main() { if let Some(_value) = Droppy.get() { //[with_feature_gate]~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //[with_feature_gate]~| ERROR: a `match` with a single arm can preserve the drop order up to Edition 2021 //[with_feature_gate]~| WARN: this changes meaning in Rust 2024 - }; + //[with_feature_gate]~| WARN: this changes meaning in Rust 2024 + } else { + } } diff --git a/tests/ui/drop/lint-if-let-rescope-gated.with_feature_gate.stderr b/tests/ui/drop/lint-if-let-rescope-gated.with_feature_gate.stderr index 7c295b7f9d89f..e0f2bebdbf1ed 100644 --- a/tests/ui/drop/lint-if-let-rescope-gated.with_feature_gate.stderr +++ b/tests/ui/drop/lint-if-let-rescope-gated.with_feature_gate.stderr @@ -9,22 +9,46 @@ LL | if let Some(_value) = Droppy.get() { = warning: this changes meaning in Rust 2024 = note: for more information, see issue #124085 help: the value is now dropped here in Edition 2024 - --> $DIR/lint-if-let-rescope-gated.rs:30:5 + --> $DIR/lint-if-let-rescope-gated.rs:32:5 | -LL | }; +LL | } else { | ^ note: the lint level is defined here --> $DIR/lint-if-let-rescope-gated.rs:11:9 | LL | #![deny(if_let_rescope)] | ^^^^^^^^^^^^^^ -help: rewrite this `if let` into a `match` with a single arm to preserve the drop order up to Edition 2021 + +error: a `match` with a single arm can preserve the drop order up to Edition 2021 + --> $DIR/lint-if-let-rescope-gated.rs:27:5 + | +LL | / if let Some(_value) = Droppy.get() { +LL | | +LL | | +LL | | +LL | | +LL | | } else { +LL | | } + | |_____^ + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see issue #124085 +help: rewrite this `if let` into `match` + | +LL | match Droppy.get() { + | ~~~~~ +help: rewrite this `if let` into `match` + | +LL | if let Some(_value) = Droppy.get() { Some(_value) => { + | +++++++++++++++++ +help: rewrite this `if let` into `match` | -LL ~ match Droppy.get() { Some(_value) => { -LL | -LL | -LL ~ } _ => {} }; +LL | }} + | + +help: rewrite this `if let` into `match` | +LL | } _ => { + | ~~~~ -error: aborting due to 1 previous error +error: aborting due to 2 previous errors diff --git a/tests/ui/drop/lint-if-let-rescope.fixed b/tests/ui/drop/lint-if-let-rescope.fixed index 7ed7e4b279c03..85ffa320796ad 100644 --- a/tests/ui/drop/lint-if-let-rescope.fixed +++ b/tests/ui/drop/lint-if-let-rescope.fixed @@ -1,9 +1,7 @@ -//@ edition:2024 -//@ compile-flags: -Z validate-mir -Zunstable-options //@ run-rustfix -#![feature(if_let_rescope)] #![deny(if_let_rescope)] +#![feature(if_let_rescope)] #![allow(irrefutable_let_patterns)] fn droppy() -> Droppy { @@ -22,27 +20,80 @@ impl Droppy { } fn main() { - match droppy().get() { Some(_value) => { + if let Some(_value) = droppy().get() { + // Should not lint + } + + match droppy().get() { Some(_value) => { //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 //~| WARN: this changes meaning in Rust 2024 - //~| HELP: rewrite this `if let` into a `match` + //~| WARN: this changes meaning in Rust 2024 + //~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021 + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` // do something } _ => { //~^ HELP: the value is now dropped here in Edition 2024 + //~| HELP: rewrite this `if let` into `match` // do something else }} + //~^ HELP: rewrite this `if let` into `match` + + match droppy().get() { Some(_value) => { + //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //~| WARN: this changes meaning in Rust 2024 + //~| WARN: this changes meaning in Rust 2024 + //~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021 + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` + // do something + } _ => { match droppy().get() { Some(_value) => { + //~^ HELP: the value is now dropped here in Edition 2024 + //~| ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //~| WARN: this changes meaning in Rust 2024 + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` + // do something else + } _ => {}}}} + //~^ HELP: rewrite this `if let` into `match` + //~| HELP: the value is now dropped here in Edition 2024 + + if droppy().get().is_some() { + // Should not lint + } else { match droppy().get() { Some(_value) => { + //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021 + //~| WARN: this changes meaning in Rust 2024 + //~| WARN: this changes meaning in Rust 2024 + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` + } _ => if droppy().get().is_none() { + //~^ HELP: the value is now dropped here in Edition 2024 + //~| HELP: rewrite this `if let` into `match` + }}} + //~^ HELP: rewrite this `if let` into `match` - if let Some(1) = { match Droppy.get() { Some(_value) => { Some(1) } _ => { None }} } { + if let Some(1) = { match Droppy.get() { Some(_value) => { Some(1) } _ => { None }} } { //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021 //~| WARN: this changes meaning in Rust 2024 - //~| HELP: rewrite this `if let` into a `match` + //~| WARN: this changes meaning in Rust 2024 + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` //~| HELP: the value is now dropped here in Edition 2024 } - if let () = { match Droppy.get() { Some(_value) => {} _ => {} } } { + if let () = { match Droppy.get() { Some(_value) => {} _ => {}} } { //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021 + //~| WARN: this changes meaning in Rust 2024 //~| WARN: this changes meaning in Rust 2024 - //~| HELP: rewrite this `if let` into a `match` + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` //~| HELP: the value is now dropped here in Edition 2024 } } diff --git a/tests/ui/drop/lint-if-let-rescope.rs b/tests/ui/drop/lint-if-let-rescope.rs index d282cd2626b8f..776b34fdbeafe 100644 --- a/tests/ui/drop/lint-if-let-rescope.rs +++ b/tests/ui/drop/lint-if-let-rescope.rs @@ -1,9 +1,7 @@ -//@ edition:2024 -//@ compile-flags: -Z validate-mir -Zunstable-options //@ run-rustfix -#![feature(if_let_rescope)] #![deny(if_let_rescope)] +#![feature(if_let_rescope)] #![allow(irrefutable_let_patterns)] fn droppy() -> Droppy { @@ -22,27 +20,80 @@ impl Droppy { } fn main() { + if let Some(_value) = droppy().get() { + // Should not lint + } + if let Some(_value) = droppy().get() { //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 //~| WARN: this changes meaning in Rust 2024 - //~| HELP: rewrite this `if let` into a `match` + //~| WARN: this changes meaning in Rust 2024 + //~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021 + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` // do something } else { //~^ HELP: the value is now dropped here in Edition 2024 + //~| HELP: rewrite this `if let` into `match` + // do something else + } + //~^ HELP: rewrite this `if let` into `match` + + if let Some(_value) = droppy().get() { + //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //~| WARN: this changes meaning in Rust 2024 + //~| WARN: this changes meaning in Rust 2024 + //~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021 + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` + // do something + } else if let Some(_value) = droppy().get() { + //~^ HELP: the value is now dropped here in Edition 2024 + //~| ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //~| WARN: this changes meaning in Rust 2024 + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` // do something else } + //~^ HELP: rewrite this `if let` into `match` + //~| HELP: the value is now dropped here in Edition 2024 + + if droppy().get().is_some() { + // Should not lint + } else if let Some(_value) = droppy().get() { + //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021 + //~| WARN: this changes meaning in Rust 2024 + //~| WARN: this changes meaning in Rust 2024 + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` + } else if droppy().get().is_none() { + //~^ HELP: the value is now dropped here in Edition 2024 + //~| HELP: rewrite this `if let` into `match` + } + //~^ HELP: rewrite this `if let` into `match` if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } else { None } } { //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021 + //~| WARN: this changes meaning in Rust 2024 //~| WARN: this changes meaning in Rust 2024 - //~| HELP: rewrite this `if let` into a `match` + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` //~| HELP: the value is now dropped here in Edition 2024 } if let () = { if let Some(_value) = Droppy.get() {} } { //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 + //~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021 + //~| WARN: this changes meaning in Rust 2024 //~| WARN: this changes meaning in Rust 2024 - //~| HELP: rewrite this `if let` into a `match` + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` + //~| HELP: rewrite this `if let` into `match` //~| HELP: the value is now dropped here in Edition 2024 } } diff --git a/tests/ui/drop/lint-if-let-rescope.stderr b/tests/ui/drop/lint-if-let-rescope.stderr index 832e73b898cbb..a08d95e113869 100644 --- a/tests/ui/drop/lint-if-let-rescope.stderr +++ b/tests/ui/drop/lint-if-let-rescope.stderr @@ -1,5 +1,5 @@ error: `if let` assigns a shorter lifetime since Edition 2024 - --> $DIR/lint-if-let-rescope.rs:25:8 + --> $DIR/lint-if-let-rescope.rs:27:8 | LL | if let Some(_value) = droppy().get() { | ^^^^^^^^^^^^^^^^^^^--------^^^^^^ @@ -9,29 +9,168 @@ LL | if let Some(_value) = droppy().get() { = warning: this changes meaning in Rust 2024 = note: for more information, see issue #124085 help: the value is now dropped here in Edition 2024 - --> $DIR/lint-if-let-rescope.rs:30:5 + --> $DIR/lint-if-let-rescope.rs:35:5 | LL | } else { | ^ note: the lint level is defined here - --> $DIR/lint-if-let-rescope.rs:6:9 + --> $DIR/lint-if-let-rescope.rs:3:9 | LL | #![deny(if_let_rescope)] | ^^^^^^^^^^^^^^ -help: rewrite this `if let` into a `match` with a single arm to preserve the drop order up to Edition 2021 + +error: a `match` with a single arm can preserve the drop order up to Edition 2021 + --> $DIR/lint-if-let-rescope.rs:27:5 + | +LL | / if let Some(_value) = droppy().get() { +LL | | +LL | | +LL | | +... | +LL | | // do something else +LL | | } + | |_____^ + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see issue #124085 +help: rewrite this `if let` into `match` | -LL ~ match droppy().get() { Some(_value) => { -LL | -... -LL | // do something -LL ~ } _ => { -LL | -LL | // do something else -LL ~ }} +LL | match droppy().get() { + | ~~~~~ +help: rewrite this `if let` into `match` + | +LL | if let Some(_value) = droppy().get() { Some(_value) => { + | +++++++++++++++++ +help: rewrite this `if let` into `match` + | +LL | }} + | + +help: rewrite this `if let` into `match` + | +LL | } _ => { + | ~~~~ + +error: `if let` assigns a shorter lifetime since Edition 2024 + --> $DIR/lint-if-let-rescope.rs:42:8 + | +LL | if let Some(_value) = droppy().get() { + | ^^^^^^^^^^^^^^^^^^^--------^^^^^^ + | | + | this value has a significant drop implementation which may observe a major change in drop order and requires your discretion + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see issue #124085 +help: the value is now dropped here in Edition 2024 + --> $DIR/lint-if-let-rescope.rs:50:5 | +LL | } else if let Some(_value) = droppy().get() { + | ^ error: `if let` assigns a shorter lifetime since Edition 2024 - --> $DIR/lint-if-let-rescope.rs:35:27 + --> $DIR/lint-if-let-rescope.rs:50:15 + | +LL | } else if let Some(_value) = droppy().get() { + | ^^^^^^^^^^^^^^^^^^^--------^^^^^^ + | | + | this value has a significant drop implementation which may observe a major change in drop order and requires your discretion + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see issue #124085 +help: the value is now dropped here in Edition 2024 + --> $DIR/lint-if-let-rescope.rs:58:5 + | +LL | } + | ^ + +error: a `match` with a single arm can preserve the drop order up to Edition 2021 + --> $DIR/lint-if-let-rescope.rs:42:5 + | +LL | / if let Some(_value) = droppy().get() { +LL | | +LL | | +LL | | +... | +LL | | // do something else +LL | | } + | |_____^ + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see issue #124085 +help: rewrite this `if let` into `match` + | +LL | match droppy().get() { + | ~~~~~ +help: rewrite this `if let` into `match` + | +LL | } else { match droppy().get() { + | ~~~~~~~ +help: rewrite this `if let` into `match` + | +LL | if let Some(_value) = droppy().get() { Some(_value) => { + | +++++++++++++++++ +help: rewrite this `if let` into `match` + | +LL | } else if let Some(_value) = droppy().get() { Some(_value) => { + | +++++++++++++++++ +help: rewrite this `if let` into `match` + | +LL | } _ => {}}}} + | ++++++++++ +help: rewrite this `if let` into `match` + | +LL | } _ => if let Some(_value) = droppy().get() { + | ~~~~ + +error: `if let` assigns a shorter lifetime since Edition 2024 + --> $DIR/lint-if-let-rescope.rs:64:15 + | +LL | } else if let Some(_value) = droppy().get() { + | ^^^^^^^^^^^^^^^^^^^--------^^^^^^ + | | + | this value has a significant drop implementation which may observe a major change in drop order and requires your discretion + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see issue #124085 +help: the value is now dropped here in Edition 2024 + --> $DIR/lint-if-let-rescope.rs:71:5 + | +LL | } else if droppy().get().is_none() { + | ^ + +error: a `match` with a single arm can preserve the drop order up to Edition 2021 + --> $DIR/lint-if-let-rescope.rs:64:12 + | +LL | } else if let Some(_value) = droppy().get() { + | ____________^ +LL | | +LL | | +LL | | +... | +LL | | +LL | | } + | |_____^ + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see issue #124085 +help: rewrite this `if let` into `match` + | +LL | } else { match droppy().get() { + | ~~~~~~~ +help: rewrite this `if let` into `match` + | +LL | } else if let Some(_value) = droppy().get() { Some(_value) => { + | +++++++++++++++++ +help: rewrite this `if let` into `match` + | +LL | }}} + | ++ +help: rewrite this `if let` into `match` + | +LL | } _ => if droppy().get().is_none() { + | ~~~~ + +error: `if let` assigns a shorter lifetime since Edition 2024 + --> $DIR/lint-if-let-rescope.rs:77:27 | LL | if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } else { None } } { | ^^^^^^^^^^^^^^^^^^^------^^^^^^ @@ -41,17 +180,38 @@ LL | if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } else = warning: this changes meaning in Rust 2024 = note: for more information, see issue #124085 help: the value is now dropped here in Edition 2024 - --> $DIR/lint-if-let-rescope.rs:35:69 + --> $DIR/lint-if-let-rescope.rs:77:69 | LL | if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } else { None } } { | ^ -help: rewrite this `if let` into a `match` with a single arm to preserve the drop order up to Edition 2021 + +error: a `match` with a single arm can preserve the drop order up to Edition 2021 + --> $DIR/lint-if-let-rescope.rs:77:24 + | +LL | if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } else { None } } { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see issue #124085 +help: rewrite this `if let` into `match` + | +LL | if let Some(1) = { match Droppy.get() { Some(1) } else { None } } { + | ~~~~~ +help: rewrite this `if let` into `match` + | +LL | if let Some(1) = { if let Some(_value) = Droppy.get() { Some(_value) => { Some(1) } else { None } } { + | +++++++++++++++++ +help: rewrite this `if let` into `match` | -LL | if let Some(1) = { match Droppy.get() { Some(_value) => { Some(1) } _ => { None }} } { - | ~~~~~ +++++++++++++++++ ~~~~ + +LL | if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } else { None }} } { + | + +help: rewrite this `if let` into `match` + | +LL | if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } _ => { None } } { + | ~~~~ error: `if let` assigns a shorter lifetime since Edition 2024 - --> $DIR/lint-if-let-rescope.rs:42:22 + --> $DIR/lint-if-let-rescope.rs:89:22 | LL | if let () = { if let Some(_value) = Droppy.get() {} } { | ^^^^^^^^^^^^^^^^^^^------^^^^^^ @@ -61,14 +221,31 @@ LL | if let () = { if let Some(_value) = Droppy.get() {} } { = warning: this changes meaning in Rust 2024 = note: for more information, see issue #124085 help: the value is now dropped here in Edition 2024 - --> $DIR/lint-if-let-rescope.rs:42:55 + --> $DIR/lint-if-let-rescope.rs:89:55 | LL | if let () = { if let Some(_value) = Droppy.get() {} } { | ^ -help: rewrite this `if let` into a `match` with a single arm to preserve the drop order up to Edition 2021 + +error: a `match` with a single arm can preserve the drop order up to Edition 2021 + --> $DIR/lint-if-let-rescope.rs:89:19 + | +LL | if let () = { if let Some(_value) = Droppy.get() {} } { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see issue #124085 +help: rewrite this `if let` into `match` + | +LL | if let () = { match Droppy.get() {} } { + | ~~~~~ +help: rewrite this `if let` into `match` + | +LL | if let () = { if let Some(_value) = Droppy.get() { Some(_value) => {} } { + | +++++++++++++++++ +help: rewrite this `if let` into `match` | -LL | if let () = { match Droppy.get() { Some(_value) => {} _ => {} } } { - | ~~~~~ +++++++++++++++++ +++++++++ +LL | if let () = { if let Some(_value) = Droppy.get() {} _ => {}} } { + | ++++++++ -error: aborting due to 3 previous errors +error: aborting due to 11 previous errors From 89682a53131803c81c8d6c5f013d1bbe410c8ae1 Mon Sep 17 00:00:00 2001 From: Ding Xiang Fei Date: Wed, 11 Sep 2024 04:07:13 +0800 Subject: [PATCH 146/189] downgrade borrowck suggestion level due to possible span conflict --- .../src/diagnostics/explain_borrow.rs | 43 +++++++---- .../if-let-rescope-borrowck-suggestions.fixed | 26 ------- .../if-let-rescope-borrowck-suggestions.rs | 10 ++- ...if-let-rescope-borrowck-suggestions.stderr | 77 +++++++++++++++++-- 4 files changed, 108 insertions(+), 48 deletions(-) delete mode 100644 tests/ui/drop/if-let-rescope-borrowck-suggestions.fixed diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 22327d2ba0d46..d9b5fd8b5c182 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -128,7 +128,7 @@ impl<'tcx> BorrowExplanation<'tcx> { && pat.span.can_be_used_for_suggestions() && let Ok(pat) = tcx.sess.source_map().span_to_snippet(pat.span) { - suggest_rewrite_if_let(expr, &pat, init, conseq, alt, err); + suggest_rewrite_if_let(tcx, expr, &pat, init, conseq, alt, err); } else if path_span.map_or(true, |path_span| path_span == var_or_use_span) { // We can use `var_or_use_span` if either `path_span` is not present, or both spans are the same if borrow_span.map_or(true, |sp| !sp.overlaps(var_or_use_span)) { @@ -292,7 +292,7 @@ impl<'tcx> BorrowExplanation<'tcx> { && pat.span.can_be_used_for_suggestions() && let Ok(pat) = tcx.sess.source_map().span_to_snippet(pat.span) { - suggest_rewrite_if_let(expr, &pat, init, conseq, alt, err); + suggest_rewrite_if_let(tcx, expr, &pat, init, conseq, alt, err); } } } @@ -428,34 +428,49 @@ impl<'tcx> BorrowExplanation<'tcx> { } } -fn suggest_rewrite_if_let<'tcx>( - expr: &hir::Expr<'tcx>, +fn suggest_rewrite_if_let( + tcx: TyCtxt<'_>, + expr: &hir::Expr<'_>, pat: &str, - init: &hir::Expr<'tcx>, - conseq: &hir::Expr<'tcx>, - alt: Option<&hir::Expr<'tcx>>, + init: &hir::Expr<'_>, + conseq: &hir::Expr<'_>, + alt: Option<&hir::Expr<'_>>, err: &mut Diag<'_>, ) { + let source_map = tcx.sess.source_map(); err.span_note( - conseq.span.shrink_to_hi(), - "lifetime for temporaries generated in `if let`s have been shorted in Edition 2024", + source_map.end_point(conseq.span), + "lifetimes for temporaries generated in `if let`s have been shortened in Edition 2024 so that they are dropped here instead", ); if expr.span.can_be_used_for_suggestions() && conseq.span.can_be_used_for_suggestions() { + let needs_block = if let Some(hir::Node::Expr(expr)) = + alt.and_then(|alt| tcx.hir().parent_iter(alt.hir_id).next()).map(|(_, node)| node) + { + matches!(expr.kind, hir::ExprKind::If(..)) + } else { + false + }; let mut sugg = vec![ - (expr.span.shrink_to_lo().between(init.span), "match ".into()), + ( + expr.span.shrink_to_lo().between(init.span), + if needs_block { "{ match ".into() } else { "match ".into() }, + ), (conseq.span.shrink_to_lo(), format!(" {{ {pat} => ")), ]; let expr_end = expr.span.shrink_to_hi(); + let mut expr_end_code; if let Some(alt) = alt { - sugg.push((conseq.span.between(alt.span), format!(" _ => "))); - sugg.push((expr_end, "}".into())); + sugg.push((conseq.span.between(alt.span), " _ => ".into())); + expr_end_code = "}".to_string(); } else { - sugg.push((expr_end, " _ => {} }".into())); + expr_end_code = " _ => {} }".into(); } + expr_end_code.push('}'); + sugg.push((expr_end, expr_end_code)); err.multipart_suggestion( "consider rewriting the `if` into `match` which preserves the extended lifetime", sugg, - Applicability::MachineApplicable, + Applicability::MaybeIncorrect, ); } } diff --git a/tests/ui/drop/if-let-rescope-borrowck-suggestions.fixed b/tests/ui/drop/if-let-rescope-borrowck-suggestions.fixed deleted file mode 100644 index 129e78ea9fe7d..0000000000000 --- a/tests/ui/drop/if-let-rescope-borrowck-suggestions.fixed +++ /dev/null @@ -1,26 +0,0 @@ -//@ edition: 2024 -//@ compile-flags: -Z validate-mir -Zunstable-options -//@ run-rustfix - -#![feature(if_let_rescope)] -#![deny(if_let_rescope)] - -struct Droppy; -impl Drop for Droppy { - fn drop(&mut self) { - println!("dropped"); - } -} -impl Droppy { - fn get_ref(&self) -> Option<&u8> { - None - } -} - -fn do_something(_: &T) {} - -fn main() { - let binding = Droppy; - do_something(match binding.get_ref() { Some(value) => { value } _ => { &0 }}); - //~^ ERROR: temporary value dropped while borrowed -} diff --git a/tests/ui/drop/if-let-rescope-borrowck-suggestions.rs b/tests/ui/drop/if-let-rescope-borrowck-suggestions.rs index 1970d5c0f7ed2..2476f7cf2580a 100644 --- a/tests/ui/drop/if-let-rescope-borrowck-suggestions.rs +++ b/tests/ui/drop/if-let-rescope-borrowck-suggestions.rs @@ -1,6 +1,5 @@ //@ edition: 2024 //@ compile-flags: -Z validate-mir -Zunstable-options -//@ run-rustfix #![feature(if_let_rescope)] #![deny(if_let_rescope)] @@ -22,4 +21,13 @@ fn do_something(_: &T) {} fn main() { do_something(if let Some(value) = Droppy.get_ref() { value } else { &0 }); //~^ ERROR: temporary value dropped while borrowed + do_something(if let Some(value) = Droppy.get_ref() { + //~^ ERROR: temporary value dropped while borrowed + value + } else if let Some(value) = Droppy.get_ref() { + //~^ ERROR: temporary value dropped while borrowed + value + } else { + &0 + }); } diff --git a/tests/ui/drop/if-let-rescope-borrowck-suggestions.stderr b/tests/ui/drop/if-let-rescope-borrowck-suggestions.stderr index fa154f01a12e9..0c6f1ea28d2ae 100644 --- a/tests/ui/drop/if-let-rescope-borrowck-suggestions.stderr +++ b/tests/ui/drop/if-let-rescope-borrowck-suggestions.stderr @@ -1,16 +1,16 @@ error[E0716]: temporary value dropped while borrowed - --> $DIR/if-let-rescope-borrowck-suggestions.rs:23:39 + --> $DIR/if-let-rescope-borrowck-suggestions.rs:22:39 | LL | do_something(if let Some(value) = Droppy.get_ref() { value } else { &0 }); | ^^^^^^ - temporary value is freed at the end of this statement | | | creates a temporary value which is freed while still in use | -note: lifetime for temporaries generated in `if let`s have been shorted in Edition 2024 - --> $DIR/if-let-rescope-borrowck-suggestions.rs:23:65 +note: lifetimes for temporaries generated in `if let`s have been shortened in Edition 2024 so that they are dropped here instead + --> $DIR/if-let-rescope-borrowck-suggestions.rs:22:64 | LL | do_something(if let Some(value) = Droppy.get_ref() { value } else { &0 }); - | ^ + | ^ help: consider using a `let` binding to create a longer lived value | LL ~ let binding = Droppy; @@ -18,9 +18,72 @@ LL ~ do_something(if let Some(value) = binding.get_ref() { value } else { &0 | help: consider rewriting the `if` into `match` which preserves the extended lifetime | -LL | do_something(match Droppy.get_ref() { Some(value) => { value } _ => { &0 }}); - | ~~~~~ ++++++++++++++++ ~~~~ + +LL | do_something({ match Droppy.get_ref() { Some(value) => { value } _ => { &0 }}}); + | ~~~~~~~ ++++++++++++++++ ~~~~ ++ -error: aborting due to 1 previous error +error[E0716]: temporary value dropped while borrowed + --> $DIR/if-let-rescope-borrowck-suggestions.rs:24:39 + | +LL | do_something(if let Some(value) = Droppy.get_ref() { + | ^^^^^^ creates a temporary value which is freed while still in use +... +LL | } else if let Some(value) = Droppy.get_ref() { + | - temporary value is freed at the end of this statement + | +note: lifetimes for temporaries generated in `if let`s have been shortened in Edition 2024 so that they are dropped here instead + --> $DIR/if-let-rescope-borrowck-suggestions.rs:27:5 + | +LL | } else if let Some(value) = Droppy.get_ref() { + | ^ +help: consider using a `let` binding to create a longer lived value + | +LL ~ let binding = Droppy; +LL ~ do_something(if let Some(value) = binding.get_ref() { + | +help: consider rewriting the `if` into `match` which preserves the extended lifetime + | +LL ~ do_something({ match Droppy.get_ref() { Some(value) => { +LL | +LL | value +LL ~ } _ => if let Some(value) = Droppy.get_ref() { +LL | +... +LL | &0 +LL ~ }}}); + | + +error[E0716]: temporary value dropped while borrowed + --> $DIR/if-let-rescope-borrowck-suggestions.rs:27:33 + | +LL | } else if let Some(value) = Droppy.get_ref() { + | ^^^^^^ creates a temporary value which is freed while still in use +... +LL | } else { + | - temporary value is freed at the end of this statement + | +note: lifetimes for temporaries generated in `if let`s have been shortened in Edition 2024 so that they are dropped here instead + --> $DIR/if-let-rescope-borrowck-suggestions.rs:30:5 + | +LL | } else { + | ^ +help: consider using a `let` binding to create a longer lived value + | +LL ~ let binding = Droppy; +LL ~ do_something(if let Some(value) = Droppy.get_ref() { +LL | +LL | value +LL ~ } else if let Some(value) = binding.get_ref() { + | +help: consider rewriting the `if` into `match` which preserves the extended lifetime + | +LL ~ } else { match Droppy.get_ref() { Some(value) => { +LL | +LL | value +LL ~ } _ => { +LL | &0 +LL ~ }}}); + | + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0716`. From d104dedad97c935aa328c9b3ebdc6ce6a68414ad Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 10 Sep 2024 15:54:47 +0200 Subject: [PATCH 147/189] interpret: mark some hot functions inline(always) recovers some of the perf regressions from #129778 --- compiler/rustc_const_eval/src/interpret/operand.rs | 2 ++ compiler/rustc_const_eval/src/interpret/place.rs | 3 +++ 2 files changed, 5 insertions(+) diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index b906e3422dba5..bb7e58b83ac7a 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -433,6 +433,7 @@ impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for ImmTy<'tcx, Prov> { Ok(self.offset_(offset, layout, ecx)) } + #[inline(always)] fn to_op>( &self, _ecx: &InterpCx<'tcx, M>, @@ -522,6 +523,7 @@ impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for OpTy<'tcx, Prov> { } } + #[inline(always)] fn to_op>( &self, _ecx: &InterpCx<'tcx, M>, diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 3b14142da02ed..1eca92812dfb4 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -166,6 +166,7 @@ impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for MPlaceTy<'tcx, Prov> { Ok(MPlaceTy { mplace: self.mplace.offset_with_meta_(offset, mode, meta, ecx)?, layout }) } + #[inline(always)] fn to_op>( &self, _ecx: &InterpCx<'tcx, M>, @@ -299,6 +300,7 @@ impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for PlaceTy<'tcx, Prov> { }) } + #[inline(always)] fn to_op>( &self, ecx: &InterpCx<'tcx, M>, @@ -560,6 +562,7 @@ where /// Given a place, returns either the underlying mplace or a reference to where the value of /// this place is stored. + #[inline(always)] fn as_mplace_or_mutable_local( &mut self, place: &PlaceTy<'tcx, M::Provenance>, From 4cecf429717ceab06007570fd699086a0855a027 Mon Sep 17 00:00:00 2001 From: FedericoBruzzone Date: Mon, 9 Sep 2024 01:17:49 +0200 Subject: [PATCH 148/189] Report the `note` when specified in `diagnostic::on_unimplemented` Signed-off-by: FedericoBruzzone --- .../rustc_hir_typeck/src/method/suggest.rs | 14 +++++--- .../methods/suggest-convert-ptr-to-ref.stderr | 2 ++ .../custom-on-unimplemented-diagnostic.rs | 19 +++++++++++ .../custom-on-unimplemented-diagnostic.stderr | 32 +++++++++++++++++++ 4 files changed, 62 insertions(+), 5 deletions(-) create mode 100644 tests/ui/traits/custom-on-unimplemented-diagnostic.rs create mode 100644 tests/ui/traits/custom-on-unimplemented-diagnostic.stderr diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 14ad5830111b4..178d5dce08643 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1317,7 +1317,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let actual_prefix = rcvr_ty.prefix_string(self.tcx); info!("unimplemented_traits.len() == {}", unimplemented_traits.len()); let mut long_ty_file = None; - let (primary_message, label) = if unimplemented_traits.len() == 1 + let (primary_message, label, notes) = if unimplemented_traits.len() == 1 && unimplemented_traits_only { unimplemented_traits @@ -1327,16 +1327,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if trait_ref.self_ty().references_error() || rcvr_ty.references_error() { // Avoid crashing. - return (None, None); + return (None, None, Vec::new()); } - let OnUnimplementedNote { message, label, .. } = self + let OnUnimplementedNote { message, label, notes, .. } = self .err_ctxt() .on_unimplemented_note(trait_ref, &obligation, &mut long_ty_file); - (message, label) + (message, label, notes) }) .unwrap() } else { - (None, None) + (None, None, Vec::new()) }; let primary_message = primary_message.unwrap_or_else(|| { format!( @@ -1363,6 +1363,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "the following trait bounds were not satisfied:\n{bound_list}" )); } + for note in notes { + err.note(note); + } + suggested_derive = self.suggest_derive(&mut err, unsatisfied_predicates); unsatisfied_bounds = true; diff --git a/tests/ui/methods/suggest-convert-ptr-to-ref.stderr b/tests/ui/methods/suggest-convert-ptr-to-ref.stderr index 69b20d57be829..0e1565e251adc 100644 --- a/tests/ui/methods/suggest-convert-ptr-to-ref.stderr +++ b/tests/ui/methods/suggest-convert-ptr-to-ref.stderr @@ -11,6 +11,7 @@ note: the method `to_string` exists on the type `&u8` = note: the following trait bounds were not satisfied: `*const u8: std::fmt::Display` which is required by `*const u8: ToString` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead error[E0599]: `*mut u8` doesn't implement `std::fmt::Display` --> $DIR/suggest-convert-ptr-to-ref.rs:8:22 @@ -25,6 +26,7 @@ note: the method `to_string` exists on the type `&&mut u8` = note: the following trait bounds were not satisfied: `*mut u8: std::fmt::Display` which is required by `*mut u8: ToString` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead error[E0599]: no method named `make_ascii_lowercase` found for raw pointer `*mut u8` in the current scope --> $DIR/suggest-convert-ptr-to-ref.rs:9:7 diff --git a/tests/ui/traits/custom-on-unimplemented-diagnostic.rs b/tests/ui/traits/custom-on-unimplemented-diagnostic.rs new file mode 100644 index 0000000000000..d7e257ef3bbe3 --- /dev/null +++ b/tests/ui/traits/custom-on-unimplemented-diagnostic.rs @@ -0,0 +1,19 @@ +#[diagnostic::on_unimplemented(message = "my message", label = "my label", note = "my note")] +pub trait ProviderLt {} + +pub trait ProviderExt { + fn request(&self) { + todo!() + } +} + +impl ProviderExt for T {} + +struct B; + +fn main() { + B.request(); + //~^ my message [E0599] + //~| my label + //~| my note +} diff --git a/tests/ui/traits/custom-on-unimplemented-diagnostic.stderr b/tests/ui/traits/custom-on-unimplemented-diagnostic.stderr new file mode 100644 index 0000000000000..f9788360d06ad --- /dev/null +++ b/tests/ui/traits/custom-on-unimplemented-diagnostic.stderr @@ -0,0 +1,32 @@ +error[E0599]: my message + --> $DIR/custom-on-unimplemented-diagnostic.rs:15:7 + | +LL | struct B; + | -------- method `request` not found for this struct because it doesn't satisfy `B: ProviderExt` or `B: ProviderLt` +... +LL | B.request(); + | ^^^^^^^ my label + | +note: trait bound `B: ProviderLt` was not satisfied + --> $DIR/custom-on-unimplemented-diagnostic.rs:10:18 + | +LL | impl ProviderExt for T {} + | ^^^^^^^^^^ ----------- - + | | + | unsatisfied trait bound introduced here + = note: my note +note: the trait `ProviderLt` must be implemented + --> $DIR/custom-on-unimplemented-diagnostic.rs:2:1 + | +LL | pub trait ProviderLt {} + | ^^^^^^^^^^^^^^^^^^^^ + = help: items from traits can only be used if the trait is implemented and in scope +note: `ProviderExt` defines an item `request`, perhaps you need to implement it + --> $DIR/custom-on-unimplemented-diagnostic.rs:4:1 + | +LL | pub trait ProviderExt { + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0599`. From 8f815978b56c908dcfe7c30b4108fa0486921272 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Wed, 11 Sep 2024 00:15:43 +0300 Subject: [PATCH 149/189] Map `WSAEDQUOT` to `ErrorKind::FilesystemQuotaExceeded` --- library/std/src/sys/pal/windows/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs index 1cc9a2b7ffa98..af98de3276a37 100644 --- a/library/std/src/sys/pal/windows/mod.rs +++ b/library/std/src/sys/pal/windows/mod.rs @@ -139,6 +139,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { c::WSAEHOSTUNREACH => HostUnreachable, c::WSAENETDOWN => NetworkDown, c::WSAENETUNREACH => NetworkUnreachable, + c::WSAEDQUOT => FilesystemQuotaExceeded, _ => Uncategorized, } From 49b3df92452ca5ce15017e69bb3f9c65d1af4139 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Wed, 11 Sep 2024 00:18:23 +0300 Subject: [PATCH 150/189] Map `ERROR_CANT_RESOLVE_FILENAME` to `ErrorKind::FilesystemLoop` --- library/std/src/sys/pal/windows/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs index 1cc9a2b7ffa98..b19a225fc27d8 100644 --- a/library/std/src/sys/pal/windows/mod.rs +++ b/library/std/src/sys/pal/windows/mod.rs @@ -122,6 +122,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { c::ERROR_NOT_SAME_DEVICE => return CrossesDevices, c::ERROR_TOO_MANY_LINKS => return TooManyLinks, c::ERROR_FILENAME_EXCED_RANGE => return InvalidFilename, + c::ERROR_CANT_RESOLVE_FILENAME => return FilesystemLoop, _ => {} } From 4198594ef2d95de255bc0535900dac182ecfbe08 Mon Sep 17 00:00:00 2001 From: James Liu <777445+root-goblin@users.noreply.github.com> Date: Sun, 1 Sep 2024 15:27:48 -0400 Subject: [PATCH 151/189] Clarify docs for std::collections Page affected: https://doc.rust-lang.org/std/collections/index.html#performance Changes: - bulleted conventions - expanded definitions on terms used - more accessible language - merged Sequence and Map performance cost tables --- library/std/src/collections/mod.rs | 62 +++++++++++++++++------------- 1 file changed, 35 insertions(+), 27 deletions(-) diff --git a/library/std/src/collections/mod.rs b/library/std/src/collections/mod.rs index 3b04412e76630..21bebff96b956 100644 --- a/library/std/src/collections/mod.rs +++ b/library/std/src/collections/mod.rs @@ -79,41 +79,49 @@ //! see each type's documentation, and note that the names of actual methods may //! differ from the tables below on certain collections. //! -//! Throughout the documentation, we will follow a few conventions. For all -//! operations, the collection's size is denoted by n. If another collection is -//! involved in the operation, it contains m elements. Operations which have an -//! *amortized* cost are suffixed with a `*`. Operations with an *expected* -//! cost are suffixed with a `~`. +//! Throughout the documentation, we will adhere to the following conventions +//! for operation notation: //! -//! All amortized costs are for the potential need to resize when capacity is -//! exhausted. If a resize occurs it will take *O*(*n*) time. Our collections never -//! automatically shrink, so removal operations aren't amortized. Over a -//! sufficiently large series of operations, the average cost per operation will -//! deterministically equal the given cost. +//! * The collection's size is denoted by `n`. +//! * If a second collection is involved, its size is denoted by `m`. +//! * Item indices are denoted by `i`. +//! * Operations which have an *amortized* cost are suffixed with a `*`. +//! * Operations with an *expected* cost are suffixed with a `~`. //! -//! Only [`HashMap`] has expected costs, due to the probabilistic nature of hashing. -//! It is theoretically possible, though very unlikely, for [`HashMap`] to -//! experience worse performance. +//! Calling operations that add to a collection will occasionally require a +//! collection to be resized - an extra operation that takes *O*(*n*) time. //! -//! ## Sequences +//! *Amortized* costs are calculated to account for the time cost of such resize +//! operations *over a sufficiently large series of operations*. An individual +//! operation may be slower or faster due to the sporadic nature of collection +//! resizing, however the average cost per operation will approach the amortized +//! cost. //! -//! | | get(i) | insert(i) | remove(i) | append | split_off(i) | -//! |----------------|------------------------|-------------------------|------------------------|-----------|------------------------| -//! | [`Vec`] | *O*(1) | *O*(*n*-*i*)* | *O*(*n*-*i*) | *O*(*m*)* | *O*(*n*-*i*) | -//! | [`VecDeque`] | *O*(1) | *O*(min(*i*, *n*-*i*))* | *O*(min(*i*, *n*-*i*)) | *O*(*m*)* | *O*(min(*i*, *n*-*i*)) | -//! | [`LinkedList`] | *O*(min(*i*, *n*-*i*)) | *O*(min(*i*, *n*-*i*)) | *O*(min(*i*, *n*-*i*)) | *O*(1) | *O*(min(*i*, *n*-*i*)) | +//! Rust's collections never automatically shrink, so removal operations aren't +//! amortized. //! -//! Note that where ties occur, [`Vec`] is generally going to be faster than [`VecDeque`], and -//! [`VecDeque`] is generally going to be faster than [`LinkedList`]. +//! [`HashMap`] uses *expected* costs. It is theoretically possible, though very +//! unlikely, for [`HashMap`] to experience significantly worse performance than +//! the expected cost. This is due to the probabilistic nature of hashing - i.e. +//! it is possible to generate a duplicate hash given some input key that will +//! requires extra computation to correct. //! -//! ## Maps +//! ## Cost of Collection Operations //! -//! For Sets, all operations have the cost of the equivalent Map operation. //! -//! | | get | insert | remove | range | append | -//! |--------------|---------------|---------------|---------------|---------------|--------------| -//! | [`HashMap`] | *O*(1)~ | *O*(1)~* | *O*(1)~ | N/A | N/A | -//! | [`BTreeMap`] | *O*(log(*n*)) | *O*(log(*n*)) | *O*(log(*n*)) | *O*(log(*n*)) | *O*(*n*+*m*) | +//! | | get(i) | insert(i) | remove(i) | append(Vec(m)) | split_off(i) | range | append | +//! |----------------|------------------------|-------------------------|------------------------|-------------------|------------------------|-----------------|--------------| +//! | [`Vec`] | *O*(1) | *O*(*n*-*i*)* | *O*(*n*-*i*) | *O*(*m*)* | *O*(*n*-*i*) | N/A | N/A | +//! | [`VecDeque`] | *O*(1) | *O*(min(*i*, *n*-*i*))* | *O*(min(*i*, *n*-*i*)) | *O*(*m*)* | *O*(min(*i*, *n*-*i*)) | N/A | N/A | +//! | [`LinkedList`] | *O*(min(*i*, *n*-*i*)) | *O*(min(*i*, *n*-*i*)) | *O*(min(*i*, *n*-*i*)) | *O*(1) | *O*(min(*i*, *n*-*i*)) | N/A | N/A | +//! | [`HashMap`] | *O*(1)~ | *O*(1)~* | *O*(1)~ | N/A | N/A | N/A | N/A | +//! | [`BTreeMap`] | *O*(log(*n*)) | *O*(log(*n*)) | *O*(log(*n*)) | N/A | N/A | *O*(log(*n*)) | *O*(*n*+*m*) | +//! +//! Note that where ties occur, [`Vec`] is generally going to be faster than +//! [`VecDeque`], and [`VecDeque`] is generally going to be faster than +//! [`LinkedList`]. +//! +//! For Sets, all operations have the cost of the equivalent Map operation. //! //! # Correct and Efficient Usage of Collections //! From 180eacea1c51610f6ddd550dc0dac5e33d313030 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 31 Aug 2024 22:18:30 +0200 Subject: [PATCH 152/189] these tests seem to work fine on i586 these days --- library/std/src/f32/tests.rs | 13 ------------- library/std/src/f64/tests.rs | 13 ------------- 2 files changed, 26 deletions(-) diff --git a/library/std/src/f32/tests.rs b/library/std/src/f32/tests.rs index 3a4c1c120a495..99cfcfb231dad 100644 --- a/library/std/src/f32/tests.rs +++ b/library/std/src/f32/tests.rs @@ -2,31 +2,24 @@ use crate::f32::consts; use crate::num::{FpCategory as Fp, *}; /// Smallest number -#[allow(dead_code)] // unused on x86 const TINY_BITS: u32 = 0x1; /// Next smallest number -#[allow(dead_code)] // unused on x86 const TINY_UP_BITS: u32 = 0x2; /// Exponent = 0b11...10, Sifnificand 0b1111..10. Min val > 0 -#[allow(dead_code)] // unused on x86 const MAX_DOWN_BITS: u32 = 0x7f7f_fffe; /// Zeroed exponent, full significant -#[allow(dead_code)] // unused on x86 const LARGEST_SUBNORMAL_BITS: u32 = 0x007f_ffff; /// Exponent = 0b1, zeroed significand -#[allow(dead_code)] // unused on x86 const SMALLEST_NORMAL_BITS: u32 = 0x0080_0000; /// First pattern over the mantissa -#[allow(dead_code)] // unused on x86 const NAN_MASK1: u32 = 0x002a_aaaa; /// Second pattern over the mantissa -#[allow(dead_code)] // unused on x86 const NAN_MASK2: u32 = 0x0055_5555; #[allow(unused_macros)] @@ -353,9 +346,6 @@ fn test_is_sign_negative() { assert!((-f32::NAN).is_sign_negative()); } -// Ignore test on x87 floating point, these platforms do not guarantee NaN -// payloads are preserved and flush denormals to zero, failing the tests. -#[cfg(not(target_arch = "x86"))] #[test] fn test_next_up() { let tiny = f32::from_bits(TINY_BITS); @@ -386,9 +376,6 @@ fn test_next_up() { assert_f32_biteq!(nan2.next_up(), nan2); } -// Ignore test on x87 floating point, these platforms do not guarantee NaN -// payloads are preserved and flush denormals to zero, failing the tests. -#[cfg(not(target_arch = "x86"))] #[test] fn test_next_down() { let tiny = f32::from_bits(TINY_BITS); diff --git a/library/std/src/f64/tests.rs b/library/std/src/f64/tests.rs index bac8405f97361..3fac2efe0d76c 100644 --- a/library/std/src/f64/tests.rs +++ b/library/std/src/f64/tests.rs @@ -2,31 +2,24 @@ use crate::f64::consts; use crate::num::{FpCategory as Fp, *}; /// Smallest number -#[allow(dead_code)] // unused on x86 const TINY_BITS: u64 = 0x1; /// Next smallest number -#[allow(dead_code)] // unused on x86 const TINY_UP_BITS: u64 = 0x2; /// Exponent = 0b11...10, Sifnificand 0b1111..10. Min val > 0 -#[allow(dead_code)] // unused on x86 const MAX_DOWN_BITS: u64 = 0x7fef_ffff_ffff_fffe; /// Zeroed exponent, full significant -#[allow(dead_code)] // unused on x86 const LARGEST_SUBNORMAL_BITS: u64 = 0x000f_ffff_ffff_ffff; /// Exponent = 0b1, zeroed significand -#[allow(dead_code)] // unused on x86 const SMALLEST_NORMAL_BITS: u64 = 0x0010_0000_0000_0000; /// First pattern over the mantissa -#[allow(dead_code)] // unused on x86 const NAN_MASK1: u64 = 0x000a_aaaa_aaaa_aaaa; /// Second pattern over the mantissa -#[allow(dead_code)] // unused on x86 const NAN_MASK2: u64 = 0x0005_5555_5555_5555; #[allow(unused_macros)] @@ -343,9 +336,6 @@ fn test_is_sign_negative() { assert!((-f64::NAN).is_sign_negative()); } -// Ignore test on x87 floating point, these platforms do not guarantee NaN -// payloads are preserved and flush denormals to zero, failing the tests. -#[cfg(not(target_arch = "x86"))] #[test] fn test_next_up() { let tiny = f64::from_bits(TINY_BITS); @@ -375,9 +365,6 @@ fn test_next_up() { assert_f64_biteq!(nan2.next_up(), nan2); } -// Ignore test on x87 floating point, these platforms do not guarantee NaN -// payloads are preserved and flush denormals to zero, failing the tests. -#[cfg(not(target_arch = "x86"))] #[test] fn test_next_down() { let tiny = f64::from_bits(TINY_BITS); From c40ee79b849daee16f3ab07a5e2bae409d40aca1 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 10 Sep 2024 16:05:37 -0700 Subject: [PATCH 153/189] move float tests into their own dir --- .../const-float-classify.rs => float/classify-runtime-const.rs} | 0 .../classify-runtime-const.stderr} | 0 .../const-float-bits-conv.rs => float/conv-bits-runtime-const.rs} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename tests/ui/{consts/const-float-classify.rs => float/classify-runtime-const.rs} (100%) rename tests/ui/{consts/const-float-classify.stderr => float/classify-runtime-const.stderr} (100%) rename tests/ui/{consts/const-float-bits-conv.rs => float/conv-bits-runtime-const.rs} (100%) diff --git a/tests/ui/consts/const-float-classify.rs b/tests/ui/float/classify-runtime-const.rs similarity index 100% rename from tests/ui/consts/const-float-classify.rs rename to tests/ui/float/classify-runtime-const.rs diff --git a/tests/ui/consts/const-float-classify.stderr b/tests/ui/float/classify-runtime-const.stderr similarity index 100% rename from tests/ui/consts/const-float-classify.stderr rename to tests/ui/float/classify-runtime-const.stderr diff --git a/tests/ui/consts/const-float-bits-conv.rs b/tests/ui/float/conv-bits-runtime-const.rs similarity index 100% rename from tests/ui/consts/const-float-bits-conv.rs rename to tests/ui/float/conv-bits-runtime-const.rs From 3daa9518d5234d0768ba8ea81fd19c372ab98445 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 31 Aug 2024 22:23:13 +0200 Subject: [PATCH 154/189] enable and extend float-classify test --- tests/ui/float/classify-runtime-const.rs | 74 ++++---- tests/ui/float/classify-runtime-const.stderr | 11 -- tests/ui/float/conv-bits-runtime-const.rs | 169 ++++++++++--------- 3 files changed, 128 insertions(+), 126 deletions(-) delete mode 100644 tests/ui/float/classify-runtime-const.stderr diff --git a/tests/ui/float/classify-runtime-const.rs b/tests/ui/float/classify-runtime-const.rs index 6e5097f7f2b9c..59a232c255e8d 100644 --- a/tests/ui/float/classify-runtime-const.rs +++ b/tests/ui/float/classify-runtime-const.rs @@ -1,40 +1,46 @@ //@ compile-flags: -Zmir-opt-level=0 -Znext-solver -//@ known-bug: #110395 -// FIXME(effects) run-pass +//@ run-pass +// ignore-tidy-linelength +// This tests the float classification functions, for regular runtime code and for const evaluation. + +#![feature(f16_const)] +#![feature(f128_const)] #![feature(const_float_classify)] -#![feature(const_trait_impl, effects)] -#![allow(incomplete_features)] -// Don't promote -const fn nop(x: T) -> T { x } +use std::hint::black_box; +use std::num::FpCategory::*; -impl const PartialEq for bool { - fn eq(&self, _: &NonDet) -> bool { - true - } -} - -macro_rules! const_assert { - ($a:expr, $b:expr) => { +macro_rules! both_assert { + ($a:expr, NonDet) => { { - const _: () = assert!($a == $b); - assert!(nop($a) == nop($b)); + // Compute `a`, but do not compare with anything as the result is non-deterministic. + const _: () = { let _val = $a; }; + // `black_box` prevents promotion, and MIR opts are disabled above, so this is truly + // going through LLVM. + let _val = black_box($a); + } + }; + ($a:expr, $b:ident) => { + { + const _: () = assert!(matches!($a, $b)); + assert!(black_box($a) == black_box($b)); } }; } macro_rules! suite { - ( $( $tt:tt )* ) => { + ( $tyname:ident: $( $tt:tt )* ) => { fn f32() { + type $tyname = f32; suite_inner!(f32 $($tt)*); } fn f64() { + type $tyname = f64; suite_inner!(f64 $($tt)*); } } - } macro_rules! suite_inner { @@ -44,33 +50,33 @@ macro_rules! suite_inner { $( $tail:tt )* ) => { - $( const_assert!($ty::$fn($val), $out); )* + $( both_assert!($ty::$fn($val), $out); )* suite_inner!($ty [$($fn),*] $($tail)*) }; ( $ty:ident [$( $fn:ident ),*]) => {}; } -#[derive(Debug)] -struct NonDet; - -// The result of the `is_sign` methods are not checked for correctness, since LLVM does not +// The result of the `is_sign` methods are not checked for correctness, since we do not // guarantee anything about the signedness of NaNs. See -// https://github.com/rust-lang/rust/issues/55131. +// https://rust-lang.github.io/rfcs/3514-float-semantics.html. -suite! { - [is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative] - -0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] - 0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] - 1.0 => [ false, false, true, true, true, false] - -1.0 => [ false, false, true, true, false, true] - 0.0 => [ false, false, true, false, true, false] - -0.0 => [ false, false, true, false, false, true] - 1.0 / 0.0 => [ false, true, false, false, true, false] - -1.0 / 0.0 => [ false, true, false, false, false, true] +suite! { T: // type alias for the type we are testing + [ classify, is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative] + -0.0 / 0.0 => [ Nan, true, false, false, false, NonDet, NonDet] + 0.0 / 0.0 => [ Nan, true, false, false, false, NonDet, NonDet] + 1.0 => [ Normal, false, false, true, true, true, false] + -1.0 => [ Normal, false, false, true, true, false, true] + 0.0 => [ Zero, false, false, true, false, true, false] + -0.0 => [ Zero, false, false, true, false, false, true] + 1.0 / 0.0 => [ Infinite, false, true, false, false, true, false] + -1.0 / 0.0 => [ Infinite, false, true, false, false, false, true] + 1.0 / T::MAX => [Subnormal, false, false, true, false, true, false] + -1.0 / T::MAX => [Subnormal, false, false, true, false, false, true] } fn main() { f32(); f64(); + // FIXME(f16_f128): also test f16 and f128 } diff --git a/tests/ui/float/classify-runtime-const.stderr b/tests/ui/float/classify-runtime-const.stderr deleted file mode 100644 index a35de8ad0eabd..0000000000000 --- a/tests/ui/float/classify-runtime-const.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` - --> $DIR/const-float-classify.rs:12:12 - | -LL | impl const PartialEq for bool { - | ^^^^^^^^^^^^^^^^^ - | - = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` - = note: adding a non-const method body in the future would be a breaking change - -error: aborting due to 1 previous error - diff --git a/tests/ui/float/conv-bits-runtime-const.rs b/tests/ui/float/conv-bits-runtime-const.rs index 869498d107612..e85a889d2c240 100644 --- a/tests/ui/float/conv-bits-runtime-const.rs +++ b/tests/ui/float/conv-bits-runtime-const.rs @@ -1,49 +1,55 @@ //@ compile-flags: -Zmir-opt-level=0 //@ run-pass +// This tests the float classification functions, for regular runtime code and for const evaluation. + #![feature(const_float_classify)] -#![feature(f16, f16_const)] -#![feature(f128, f128_const)] +#![feature(f16)] +#![feature(f128)] +#![feature(f16_const)] +#![feature(f128_const)] #![allow(unused_macro_rules)] -// Don't promote -const fn nop(x: T) -> T { x } -macro_rules! const_assert { +use std::hint::black_box; + +macro_rules! both_assert { ($a:expr) => { { const _: () = assert!($a); - assert!(nop($a)); + // `black_box` prevents promotion, and MIR opts are disabled above, so this is truly + // going through LLVM. + assert!(black_box($a)); } }; ($a:expr, $b:expr) => { { const _: () = assert!($a == $b); - assert_eq!(nop($a), nop($b)); + assert_eq!(black_box($a), black_box($b)); } }; } fn has_broken_floats() -> bool { // i586 targets are broken due to . - std::env::var("TARGET").is_ok_and(|v| v.contains("i586")) + cfg!(all(target_arch = "x86", not(target_feature = "sse2"))) } #[cfg(target_arch = "x86_64")] fn f16(){ - const_assert!((1f16).to_bits(), 0x3c00); - const_assert!(u16::from_be_bytes(1f16.to_be_bytes()), 0x3c00); - const_assert!((12.5f16).to_bits(), 0x4a40); - const_assert!(u16::from_le_bytes(12.5f16.to_le_bytes()), 0x4a40); - const_assert!((1337f16).to_bits(), 0x6539); - const_assert!(u16::from_ne_bytes(1337f16.to_ne_bytes()), 0x6539); - const_assert!((-14.25f16).to_bits(), 0xcb20); - const_assert!(f16::from_bits(0x3c00), 1.0); - const_assert!(f16::from_be_bytes(0x3c00u16.to_be_bytes()), 1.0); - const_assert!(f16::from_bits(0x4a40), 12.5); - const_assert!(f16::from_le_bytes(0x4a40u16.to_le_bytes()), 12.5); - const_assert!(f16::from_bits(0x5be0), 252.0); - const_assert!(f16::from_ne_bytes(0x5be0u16.to_ne_bytes()), 252.0); - const_assert!(f16::from_bits(0xcb20), -14.25); + both_assert!((1f16).to_bits(), 0x3c00); + both_assert!(u16::from_be_bytes(1f16.to_be_bytes()), 0x3c00); + both_assert!((12.5f16).to_bits(), 0x4a40); + both_assert!(u16::from_le_bytes(12.5f16.to_le_bytes()), 0x4a40); + both_assert!((1337f16).to_bits(), 0x6539); + both_assert!(u16::from_ne_bytes(1337f16.to_ne_bytes()), 0x6539); + both_assert!((-14.25f16).to_bits(), 0xcb20); + both_assert!(f16::from_bits(0x3c00), 1.0); + both_assert!(f16::from_be_bytes(0x3c00u16.to_be_bytes()), 1.0); + both_assert!(f16::from_bits(0x4a40), 12.5); + both_assert!(f16::from_le_bytes(0x4a40u16.to_le_bytes()), 12.5); + both_assert!(f16::from_bits(0x5be0), 252.0); + both_assert!(f16::from_ne_bytes(0x5be0u16.to_ne_bytes()), 252.0); + both_assert!(f16::from_bits(0xcb20), -14.25); // Check that NaNs roundtrip their bits regardless of signalingness // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits @@ -51,29 +57,29 @@ fn f16(){ const QUIET_NAN: u16 = f16::NAN.to_bits() ^ 0x0155; const SIGNALING_NAN: u16 = f16::NAN.to_bits() ^ 0x02AA; - const_assert!(f16::from_bits(QUIET_NAN).is_nan()); - const_assert!(f16::from_bits(SIGNALING_NAN).is_nan()); - const_assert!(f16::from_bits(QUIET_NAN).to_bits(), QUIET_NAN); + both_assert!(f16::from_bits(QUIET_NAN).is_nan()); + both_assert!(f16::from_bits(SIGNALING_NAN).is_nan()); + both_assert!(f16::from_bits(QUIET_NAN).to_bits(), QUIET_NAN); if !has_broken_floats() { - const_assert!(f16::from_bits(SIGNALING_NAN).to_bits(), SIGNALING_NAN); + both_assert!(f16::from_bits(SIGNALING_NAN).to_bits(), SIGNALING_NAN); } } fn f32() { - const_assert!((1f32).to_bits(), 0x3f800000); - const_assert!(u32::from_be_bytes(1f32.to_be_bytes()), 0x3f800000); - const_assert!((12.5f32).to_bits(), 0x41480000); - const_assert!(u32::from_le_bytes(12.5f32.to_le_bytes()), 0x41480000); - const_assert!((1337f32).to_bits(), 0x44a72000); - const_assert!(u32::from_ne_bytes(1337f32.to_ne_bytes()), 0x44a72000); - const_assert!((-14.25f32).to_bits(), 0xc1640000); - const_assert!(f32::from_bits(0x3f800000), 1.0); - const_assert!(f32::from_be_bytes(0x3f800000u32.to_be_bytes()), 1.0); - const_assert!(f32::from_bits(0x41480000), 12.5); - const_assert!(f32::from_le_bytes(0x41480000u32.to_le_bytes()), 12.5); - const_assert!(f32::from_bits(0x44a72000), 1337.0); - const_assert!(f32::from_ne_bytes(0x44a72000u32.to_ne_bytes()), 1337.0); - const_assert!(f32::from_bits(0xc1640000), -14.25); + both_assert!((1f32).to_bits(), 0x3f800000); + both_assert!(u32::from_be_bytes(1f32.to_be_bytes()), 0x3f800000); + both_assert!((12.5f32).to_bits(), 0x41480000); + both_assert!(u32::from_le_bytes(12.5f32.to_le_bytes()), 0x41480000); + both_assert!((1337f32).to_bits(), 0x44a72000); + both_assert!(u32::from_ne_bytes(1337f32.to_ne_bytes()), 0x44a72000); + both_assert!((-14.25f32).to_bits(), 0xc1640000); + both_assert!(f32::from_bits(0x3f800000), 1.0); + both_assert!(f32::from_be_bytes(0x3f800000u32.to_be_bytes()), 1.0); + both_assert!(f32::from_bits(0x41480000), 12.5); + both_assert!(f32::from_le_bytes(0x41480000u32.to_le_bytes()), 12.5); + both_assert!(f32::from_bits(0x44a72000), 1337.0); + both_assert!(f32::from_ne_bytes(0x44a72000u32.to_ne_bytes()), 1337.0); + both_assert!(f32::from_bits(0xc1640000), -14.25); // Check that NaNs roundtrip their bits regardless of signalingness // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits @@ -81,29 +87,29 @@ fn f32() { const QUIET_NAN: u32 = f32::NAN.to_bits() ^ 0x002A_AAAA; const SIGNALING_NAN: u32 = f32::NAN.to_bits() ^ 0x0055_5555; - const_assert!(f32::from_bits(QUIET_NAN).is_nan()); - const_assert!(f32::from_bits(SIGNALING_NAN).is_nan()); - const_assert!(f32::from_bits(QUIET_NAN).to_bits(), QUIET_NAN); + both_assert!(f32::from_bits(QUIET_NAN).is_nan()); + both_assert!(f32::from_bits(SIGNALING_NAN).is_nan()); + both_assert!(f32::from_bits(QUIET_NAN).to_bits(), QUIET_NAN); if !has_broken_floats() { - const_assert!(f32::from_bits(SIGNALING_NAN).to_bits(), SIGNALING_NAN); + both_assert!(f32::from_bits(SIGNALING_NAN).to_bits(), SIGNALING_NAN); } } fn f64() { - const_assert!((1f64).to_bits(), 0x3ff0000000000000); - const_assert!(u64::from_be_bytes(1f64.to_be_bytes()), 0x3ff0000000000000); - const_assert!((12.5f64).to_bits(), 0x4029000000000000); - const_assert!(u64::from_le_bytes(12.5f64.to_le_bytes()), 0x4029000000000000); - const_assert!((1337f64).to_bits(), 0x4094e40000000000); - const_assert!(u64::from_ne_bytes(1337f64.to_ne_bytes()), 0x4094e40000000000); - const_assert!((-14.25f64).to_bits(), 0xc02c800000000000); - const_assert!(f64::from_bits(0x3ff0000000000000), 1.0); - const_assert!(f64::from_be_bytes(0x3ff0000000000000u64.to_be_bytes()), 1.0); - const_assert!(f64::from_bits(0x4029000000000000), 12.5); - const_assert!(f64::from_le_bytes(0x4029000000000000u64.to_le_bytes()), 12.5); - const_assert!(f64::from_bits(0x4094e40000000000), 1337.0); - const_assert!(f64::from_ne_bytes(0x4094e40000000000u64.to_ne_bytes()), 1337.0); - const_assert!(f64::from_bits(0xc02c800000000000), -14.25); + both_assert!((1f64).to_bits(), 0x3ff0000000000000); + both_assert!(u64::from_be_bytes(1f64.to_be_bytes()), 0x3ff0000000000000); + both_assert!((12.5f64).to_bits(), 0x4029000000000000); + both_assert!(u64::from_le_bytes(12.5f64.to_le_bytes()), 0x4029000000000000); + both_assert!((1337f64).to_bits(), 0x4094e40000000000); + both_assert!(u64::from_ne_bytes(1337f64.to_ne_bytes()), 0x4094e40000000000); + both_assert!((-14.25f64).to_bits(), 0xc02c800000000000); + both_assert!(f64::from_bits(0x3ff0000000000000), 1.0); + both_assert!(f64::from_be_bytes(0x3ff0000000000000u64.to_be_bytes()), 1.0); + both_assert!(f64::from_bits(0x4029000000000000), 12.5); + both_assert!(f64::from_le_bytes(0x4029000000000000u64.to_le_bytes()), 12.5); + both_assert!(f64::from_bits(0x4094e40000000000), 1337.0); + both_assert!(f64::from_ne_bytes(0x4094e40000000000u64.to_ne_bytes()), 1337.0); + both_assert!(f64::from_bits(0xc02c800000000000), -14.25); // Check that NaNs roundtrip their bits regardless of signalingness // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits @@ -111,30 +117,30 @@ fn f64() { const QUIET_NAN: u64 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555; const SIGNALING_NAN: u64 = f64::NAN.to_bits() ^ 0x000A_AAAA_AAAA_AAAA; - const_assert!(f64::from_bits(QUIET_NAN).is_nan()); - const_assert!(f64::from_bits(SIGNALING_NAN).is_nan()); - const_assert!(f64::from_bits(QUIET_NAN).to_bits(), QUIET_NAN); + both_assert!(f64::from_bits(QUIET_NAN).is_nan()); + both_assert!(f64::from_bits(SIGNALING_NAN).is_nan()); + both_assert!(f64::from_bits(QUIET_NAN).to_bits(), QUIET_NAN); if !has_broken_floats() { - const_assert!(f64::from_bits(SIGNALING_NAN).to_bits(), SIGNALING_NAN); + both_assert!(f64::from_bits(SIGNALING_NAN).to_bits(), SIGNALING_NAN); } } #[cfg(target_arch = "x86_64")] fn f128() { - const_assert!((1f128).to_bits(), 0x3fff0000000000000000000000000000); - const_assert!(u128::from_be_bytes(1f128.to_be_bytes()), 0x3fff0000000000000000000000000000); - const_assert!((12.5f128).to_bits(), 0x40029000000000000000000000000000); - const_assert!(u128::from_le_bytes(12.5f128.to_le_bytes()), 0x40029000000000000000000000000000); - const_assert!((1337f128).to_bits(), 0x40094e40000000000000000000000000); - const_assert!(u128::from_ne_bytes(1337f128.to_ne_bytes()), 0x40094e40000000000000000000000000); - const_assert!((-14.25f128).to_bits(), 0xc002c800000000000000000000000000); - const_assert!(f128::from_bits(0x3fff0000000000000000000000000000), 1.0); - const_assert!(f128::from_be_bytes(0x3fff0000000000000000000000000000u128.to_be_bytes()), 1.0); - const_assert!(f128::from_bits(0x40029000000000000000000000000000), 12.5); - const_assert!(f128::from_le_bytes(0x40029000000000000000000000000000u128.to_le_bytes()), 12.5); - const_assert!(f128::from_bits(0x40094e40000000000000000000000000), 1337.0); + both_assert!((1f128).to_bits(), 0x3fff0000000000000000000000000000); + both_assert!(u128::from_be_bytes(1f128.to_be_bytes()), 0x3fff0000000000000000000000000000); + both_assert!((12.5f128).to_bits(), 0x40029000000000000000000000000000); + both_assert!(u128::from_le_bytes(12.5f128.to_le_bytes()), 0x40029000000000000000000000000000); + both_assert!((1337f128).to_bits(), 0x40094e40000000000000000000000000); + both_assert!(u128::from_ne_bytes(1337f128.to_ne_bytes()), 0x40094e40000000000000000000000000); + both_assert!((-14.25f128).to_bits(), 0xc002c800000000000000000000000000); + both_assert!(f128::from_bits(0x3fff0000000000000000000000000000), 1.0); + both_assert!(f128::from_be_bytes(0x3fff0000000000000000000000000000u128.to_be_bytes()), 1.0); + both_assert!(f128::from_bits(0x40029000000000000000000000000000), 12.5); + both_assert!(f128::from_le_bytes(0x40029000000000000000000000000000u128.to_le_bytes()), 12.5); + both_assert!(f128::from_bits(0x40094e40000000000000000000000000), 1337.0); assert_eq!(f128::from_ne_bytes(0x40094e40000000000000000000000000u128.to_ne_bytes()), 1337.0); - const_assert!(f128::from_bits(0xc002c800000000000000000000000000), -14.25); + both_assert!(f128::from_bits(0xc002c800000000000000000000000000), -14.25); // Check that NaNs roundtrip their bits regardless of signalingness // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits @@ -142,20 +148,21 @@ fn f128() { const QUIET_NAN: u128 = f128::NAN.to_bits() | 0x0000_AAAA_AAAA_AAAA_AAAA_AAAA_AAAA_AAAA; const SIGNALING_NAN: u128 = f128::NAN.to_bits() ^ 0x0000_5555_5555_5555_5555_5555_5555_5555; - const_assert!(f128::from_bits(QUIET_NAN).is_nan()); - const_assert!(f128::from_bits(SIGNALING_NAN).is_nan()); - const_assert!(f128::from_bits(QUIET_NAN).to_bits(), QUIET_NAN); + both_assert!(f128::from_bits(QUIET_NAN).is_nan()); + both_assert!(f128::from_bits(SIGNALING_NAN).is_nan()); + both_assert!(f128::from_bits(QUIET_NAN).to_bits(), QUIET_NAN); if !has_broken_floats() { - const_assert!(f128::from_bits(SIGNALING_NAN).to_bits(), SIGNALING_NAN); + both_assert!(f128::from_bits(SIGNALING_NAN).to_bits(), SIGNALING_NAN); } } fn main() { + f32(); + f64(); + #[cfg(target_arch = "x86_64")] { f16(); f128(); } - f32(); - f64(); } From e556c136f3a4e5ff36afa248a6dd0e2cc9ddaced Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 31 Aug 2024 22:28:17 +0200 Subject: [PATCH 155/189] clean up internal comments about float semantics - remove an outdated FIXME - add reference to floating-point semantics issue Co-authored-by: Jubilee --- library/core/src/num/f16.rs | 1 + library/core/src/num/f32.rs | 5 +---- library/core/src/num/f64.rs | 5 +---- tests/ui/numbers-arithmetic/issue-105626.rs | 1 + 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs index 9252e8c601558..da92da1086dab 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -435,6 +435,7 @@ impl f16 { // WASM, see llvm/llvm-project#96437). These are platforms bugs, and Rust will misbehave on // such platforms, but we can at least try to make things seem as sane as possible by being // careful here. + // see also https://github.com/rust-lang/rust/issues/114479 if self.is_infinite() { // Thus, a value may compare unequal to infinity, despite having a "full" exponent mask. FpCategory::Infinite diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index 2bc897224970d..885f7608a337e 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -662,10 +662,7 @@ impl f32 { // hardware flushes subnormals to zero. These are platforms bugs, and Rust will misbehave on // such hardware, but we can at least try to make things seem as sane as possible by being // careful here. - // - // FIXME(jubilee): Using x87 operations is never necessary in order to function - // on x86 processors for Rust-to-Rust calls, so this issue should not happen. - // Code generation should be adjusted to use non-C calling conventions, avoiding this. + // see also https://github.com/rust-lang/rust/issues/114479 if self.is_infinite() { // A value may compare unequal to infinity, despite having a "full" exponent mask. FpCategory::Infinite diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index b3f5be9fc8a46..28cc231ccc76d 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -660,10 +660,7 @@ impl f64 { // float semantics Rust relies on: x87 uses a too-large exponent, and some hardware flushes // subnormals to zero. These are platforms bugs, and Rust will misbehave on such hardware, // but we can at least try to make things seem as sane as possible by being careful here. - // - // FIXME(jubilee): Using x87 operations is never necessary in order to function - // on x86 processors for Rust-to-Rust calls, so this issue should not happen. - // Code generation should be adjusted to use non-C calling conventions, avoiding this. + // see also https://github.com/rust-lang/rust/issues/114479 // // Thus, a value may compare unequal to infinity, despite having a "full" exponent mask. // And it may not be NaN, as it can simply be an "overextended" finite value. diff --git a/tests/ui/numbers-arithmetic/issue-105626.rs b/tests/ui/numbers-arithmetic/issue-105626.rs index f942cf1283d0d..8d4a7c308e7fe 100644 --- a/tests/ui/numbers-arithmetic/issue-105626.rs +++ b/tests/ui/numbers-arithmetic/issue-105626.rs @@ -11,6 +11,7 @@ fn main() { assert_ne!((n as f64) as f32, n as f32); // FIXME: these assertions fail if only x87 is enabled + // see also https://github.com/rust-lang/rust/issues/114479 assert_eq!(n as i64 as f32, r); assert_eq!(n as u64 as f32, r); } From 7c692e13b171c04b6bb6baa4d5aa138beecf8da8 Mon Sep 17 00:00:00 2001 From: DianQK Date: Wed, 11 Sep 2024 07:59:27 +0800 Subject: [PATCH 156/189] Update LLVM to 19 327ca6c --- src/llvm-project | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm-project b/src/llvm-project index 2b259b3c201f9..4b8d29c585687 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit 2b259b3c201f939f2ed8d2fb0a0e9b37dd2d1321 +Subproject commit 4b8d29c585687084bbcf21471e04f279d1eddc0a From 5f327176492e3ef66d8140fb771d77bc2b5eebac Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Tue, 10 Sep 2024 20:06:35 +0300 Subject: [PATCH 157/189] document the new git logic in more detail Signed-off-by: onur-ozkan --- src/tools/build_helper/src/git.rs | 16 ++++++++++++---- src/tools/compiletest/src/lib.rs | 7 ++++++- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/tools/build_helper/src/git.rs b/src/tools/build_helper/src/git.rs index 7da3c9de60c45..15d863caf0c5f 100644 --- a/src/tools/build_helper/src/git.rs +++ b/src/tools/build_helper/src/git.rs @@ -96,7 +96,14 @@ pub fn updated_master_branch( Err("Cannot find any suitable upstream master branch".to_owned()) } -fn get_git_merge_base(config: &GitConfig<'_>, git_dir: Option<&Path>) -> Result { +/// Finds the nearest merge commit by comparing the local `HEAD` with the upstream branch's state. +/// To work correctly, the upstream remote must be properly configured using `git remote add `. +/// In most cases `get_closest_merge_commit` is the function you are looking for as it doesn't require remote +/// to be configured. +fn git_upstream_merge_base( + config: &GitConfig<'_>, + git_dir: Option<&Path>, +) -> Result { let updated_master = updated_master_branch(config, git_dir)?; let mut git = Command::new("git"); if let Some(git_dir) = git_dir { @@ -105,9 +112,10 @@ fn get_git_merge_base(config: &GitConfig<'_>, git_dir: Option<&Path>) -> Result< Ok(output_result(git.arg("merge-base").arg(&updated_master).arg("HEAD"))?.trim().to_owned()) } -/// Resolves the closest merge commit by the given `author` and `target_paths`. +/// Searches for the nearest merge commit in the repository that also exists upstream. /// -/// If it fails to find the commit from upstream using `git merge-base`, fallbacks to HEAD. +/// If it fails to find the upstream remote, it then looks for the most recent commit made +/// by the merge bot by matching the author's email address with the merge bot's email. pub fn get_closest_merge_commit( git_dir: Option<&Path>, config: &GitConfig<'_>, @@ -119,7 +127,7 @@ pub fn get_closest_merge_commit( git.current_dir(git_dir); } - let merge_base = get_git_merge_base(config, git_dir).unwrap_or_else(|_| "HEAD".into()); + let merge_base = git_upstream_merge_base(config, git_dir).unwrap_or_else(|_| "HEAD".into()); git.args([ "rev-list", diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 624111d48adfa..5324c0a494ac0 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -164,7 +164,12 @@ pub fn parse_config(args: Vec) -> Config { .optopt("", "edition", "default Rust edition", "EDITION") .reqopt("", "git-repository", "name of the git repository", "ORG/REPO") .reqopt("", "nightly-branch", "name of the git branch for nightly", "BRANCH") - .reqopt("", "git-merge-commit-email", "email address used for the merge commits", "EMAIL"); + .reqopt( + "", + "git-merge-commit-email", + "email address used for finding merge commits", + "EMAIL", + ); let (argv0, args_) = args.split_first().unwrap(); if args.len() == 1 || args[1] == "-h" || args[1] == "--help" { From b44f1dd758b01d6be035e24b7dac3b6ba0bda66d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 28 Aug 2024 16:02:59 +0200 Subject: [PATCH 158/189] update stdarch --- library/stdarch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/stdarch b/library/stdarch index d9466edb4c53c..ace72223a0e32 160000 --- a/library/stdarch +++ b/library/stdarch @@ -1 +1 @@ -Subproject commit d9466edb4c53cece8686ee6e17b028436ddf4151 +Subproject commit ace72223a0e321c1b0a37b5862aa756fe8ab5111 From 542a6c67aef7cf5fa234e5d8134b88cffb9a3c36 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 11 Sep 2024 11:18:35 +0200 Subject: [PATCH 159/189] miri: support vector index arguments in simd_shuffle --- src/tools/miri/src/intrinsics/simd.rs | 15 ++++++--------- .../miri/tests/pass/intrinsics/portable-simd.rs | 8 ++++++++ .../simd-intrinsic-generic-elements.rs | 0 3 files changed, 14 insertions(+), 9 deletions(-) rename src/tools/miri/tests/pass/{ => intrinsics}/simd-intrinsic-generic-elements.rs (100%) diff --git a/src/tools/miri/src/intrinsics/simd.rs b/src/tools/miri/src/intrinsics/simd.rs index a5afd029b6519..85d7459bb4595 100644 --- a/src/tools/miri/src/intrinsics/simd.rs +++ b/src/tools/miri/src/intrinsics/simd.rs @@ -666,22 +666,19 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let (right, right_len) = this.operand_to_simd(right)?; let (dest, dest_len) = this.mplace_to_simd(dest)?; - // `index` is an array, not a SIMD type - let ty::Array(_, index_len) = index.layout.ty.kind() else { - span_bug!( - this.cur_span(), - "simd_shuffle index argument has non-array type {}", - index.layout.ty - ) + // `index` is an array or a SIMD type + let (index, index_len) = match index.layout.ty.kind() { + // FIXME: remove this once `index` must always be a SIMD vector. + ty::Array(..) => (index.assert_mem_place(), index.len(this)?), + _ => this.operand_to_simd(index)?, }; - let index_len = index_len.eval_target_usize(*this.tcx, this.param_env()); assert_eq!(left_len, right_len); assert_eq!(index_len, dest_len); for i in 0..dest_len { let src_index: u64 = this - .read_immediate(&this.project_index(index, i)?)? + .read_immediate(&this.project_index(&index, i)?)? .to_scalar() .to_u32()? .into(); diff --git a/src/tools/miri/tests/pass/intrinsics/portable-simd.rs b/src/tools/miri/tests/pass/intrinsics/portable-simd.rs index c4ba11d0a436f..daf75fee8fe13 100644 --- a/src/tools/miri/tests/pass/intrinsics/portable-simd.rs +++ b/src/tools/miri/tests/pass/intrinsics/portable-simd.rs @@ -620,6 +620,10 @@ fn simd_intrinsics() { ); assert_eq!(simd_shuffle_generic::<_, i32x4, { &[3, 1, 0, 2] }>(a, b), a,); assert_eq!(simd_shuffle::<_, _, i32x4>(a, b, const { [3u32, 1, 0, 2] }), a,); + assert_eq!( + simd_shuffle::<_, _, i32x4>(a, b, const { u32x4::from_array([3u32, 1, 0, 2]) }), + a, + ); assert_eq!( simd_shuffle_generic::<_, i32x4, { &[7, 5, 4, 6] }>(a, b), i32x4::from_array([4, 2, 1, 10]), @@ -628,6 +632,10 @@ fn simd_intrinsics() { simd_shuffle::<_, _, i32x4>(a, b, const { [7u32, 5, 4, 6] }), i32x4::from_array([4, 2, 1, 10]), ); + assert_eq!( + simd_shuffle::<_, _, i32x4>(a, b, const { u32x4::from_array([7u32, 5, 4, 6]) }), + i32x4::from_array([4, 2, 1, 10]), + ); } } diff --git a/src/tools/miri/tests/pass/simd-intrinsic-generic-elements.rs b/src/tools/miri/tests/pass/intrinsics/simd-intrinsic-generic-elements.rs similarity index 100% rename from src/tools/miri/tests/pass/simd-intrinsic-generic-elements.rs rename to src/tools/miri/tests/pass/intrinsics/simd-intrinsic-generic-elements.rs From 6eddbb704ee4d80f18e6359c027e9f249ad2a7ae Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Wed, 11 Sep 2024 10:35:02 +0200 Subject: [PATCH 160/189] Fix false positive with `missing_docs` and `#[test]` Since #130025, the compiler don't ignore missing_docs when compiling the tests. But there is now a false positive warning for every `#[test]` For example, this code ```rust //! Crate docs fn just_a_test() {} ``` Would emit this warning when running `cargo test` ``` warning: missing documentation for a constant --> src/lib.rs:5:1 | 4 | #[test] | ------- in this procedural macro expansion 5 | fn just_a_test() {} | ^^^^^^^^^^^^^^^^^^^ ``` --- compiler/rustc_builtin_macros/src/test.rs | 2 ++ tests/pretty/tests-are-sorted.pp | 3 +++ tests/ui/lint/lint-missing-doc-test.rs | 3 +++ 3 files changed, 8 insertions(+) diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index 1b76a5f3234a2..ab3517d362721 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -277,6 +277,8 @@ pub(crate) fn expand_test_or_bench( cx.attr_nested_word(sym::cfg, sym::test, attr_sp), // #[rustc_test_marker = "test_case_sort_key"] cx.attr_name_value_str(sym::rustc_test_marker, test_path_symbol, attr_sp), + // #[allow(missing_docs)] + cx.attr_nested_word(sym::allow, sym::missing_docs, attr_sp), ], // const $ident: test::TestDescAndFn = ast::ItemKind::Const( diff --git a/tests/pretty/tests-are-sorted.pp b/tests/pretty/tests-are-sorted.pp index a4b15dde4530e..0a31c3fc1b58f 100644 --- a/tests/pretty/tests-are-sorted.pp +++ b/tests/pretty/tests-are-sorted.pp @@ -12,6 +12,7 @@ extern crate test; #[cfg(test)] #[rustc_test_marker = "m_test"] +#[allow(missing_docs)] pub const m_test: test::TestDescAndFn = test::TestDescAndFn { desc: test::TestDesc { @@ -36,6 +37,7 @@ extern crate test; #[cfg(test)] #[rustc_test_marker = "z_test"] +#[allow(missing_docs)] pub const z_test: test::TestDescAndFn = test::TestDescAndFn { desc: test::TestDesc { @@ -61,6 +63,7 @@ extern crate test; #[cfg(test)] #[rustc_test_marker = "a_test"] +#[allow(missing_docs)] pub const a_test: test::TestDescAndFn = test::TestDescAndFn { desc: test::TestDesc { diff --git a/tests/ui/lint/lint-missing-doc-test.rs b/tests/ui/lint/lint-missing-doc-test.rs index 93d4e4a44e928..466b79c0fb949 100644 --- a/tests/ui/lint/lint-missing-doc-test.rs +++ b/tests/ui/lint/lint-missing-doc-test.rs @@ -3,3 +3,6 @@ //@ check-pass //@ compile-flags: --test -Dmissing_docs + +#[test] +fn test() {} From 9566163364a91678006a2b22d62d2a73a6012ff5 Mon Sep 17 00:00:00 2001 From: Vetle Rasmussen Date: Wed, 11 Sep 2024 11:40:01 +0200 Subject: [PATCH 161/189] Make SearchPath::new public --- compiler/rustc_session/src/search_paths.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_session/src/search_paths.rs b/compiler/rustc_session/src/search_paths.rs index d65b1b8b3f15a..b212f6afa1717 100644 --- a/compiler/rustc_session/src/search_paths.rs +++ b/compiler/rustc_session/src/search_paths.rs @@ -96,7 +96,7 @@ impl SearchPath { Self::new(PathKind::All, make_target_lib_path(sysroot, triple)) } - fn new(kind: PathKind, dir: PathBuf) -> Self { + pub fn new(kind: PathKind, dir: PathBuf) -> Self { // Get the files within the directory. let files = match std::fs::read_dir(&dir) { Ok(files) => files From 5d456dfaa1a712f1b1619c3b5a6f725776d5f101 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Wed, 11 Sep 2024 11:49:27 +0200 Subject: [PATCH 162/189] Use `#[doc(hidden)]` instead of `#[allow(missing_docs)]` on the const generated for `#[test]` --- compiler/rustc_builtin_macros/src/test.rs | 4 ++-- tests/pretty/tests-are-sorted.pp | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index ab3517d362721..40dc75339efd7 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -277,8 +277,8 @@ pub(crate) fn expand_test_or_bench( cx.attr_nested_word(sym::cfg, sym::test, attr_sp), // #[rustc_test_marker = "test_case_sort_key"] cx.attr_name_value_str(sym::rustc_test_marker, test_path_symbol, attr_sp), - // #[allow(missing_docs)] - cx.attr_nested_word(sym::allow, sym::missing_docs, attr_sp), + // #[doc(hidden)] + cx.attr_nested_word(sym::doc, sym::hidden, attr_sp), ], // const $ident: test::TestDescAndFn = ast::ItemKind::Const( diff --git a/tests/pretty/tests-are-sorted.pp b/tests/pretty/tests-are-sorted.pp index 0a31c3fc1b58f..d10368a89cbc7 100644 --- a/tests/pretty/tests-are-sorted.pp +++ b/tests/pretty/tests-are-sorted.pp @@ -12,7 +12,7 @@ extern crate test; #[cfg(test)] #[rustc_test_marker = "m_test"] -#[allow(missing_docs)] +#[doc(hidden)] pub const m_test: test::TestDescAndFn = test::TestDescAndFn { desc: test::TestDesc { @@ -37,7 +37,7 @@ extern crate test; #[cfg(test)] #[rustc_test_marker = "z_test"] -#[allow(missing_docs)] +#[doc(hidden)] pub const z_test: test::TestDescAndFn = test::TestDescAndFn { desc: test::TestDesc { @@ -63,7 +63,7 @@ extern crate test; #[cfg(test)] #[rustc_test_marker = "a_test"] -#[allow(missing_docs)] +#[doc(hidden)] pub const a_test: test::TestDescAndFn = test::TestDescAndFn { desc: test::TestDesc { From cc34d64c511feaf576854797fc291e03f5f275a7 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Wed, 11 Sep 2024 12:08:14 +0200 Subject: [PATCH 163/189] Use `doc(hidden)` instead of `allow(missing_docs)` in the test harness So that it doesn't fail with `forbid(missing_docs)` Fixes #130218 --- compiler/rustc_builtin_macros/src/test_harness.rs | 6 +++--- compiler/rustc_span/src/symbol.rs | 1 - tests/pretty/tests-are-sorted.pp | 2 +- tests/ui/lint/lint-missing-doc-test.rs | 4 +++- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index a694d3b8c2857..400557ca260b2 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -326,8 +326,8 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { let main_attr = ecx.attr_word(sym::rustc_main, sp); // #[coverage(off)] let coverage_attr = ecx.attr_nested_word(sym::coverage, sym::off, sp); - // #[allow(missing_docs)] - let missing_docs_attr = ecx.attr_nested_word(sym::allow, sym::missing_docs, sp); + // #[doc(hidden)] + let doc_hidden_attr = ecx.attr_nested_word(sym::doc, sym::hidden, sp); // pub fn main() { ... } let main_ret_ty = ecx.ty(sp, ast::TyKind::Tup(ThinVec::new())); @@ -357,7 +357,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { let main = P(ast::Item { ident: main_id, - attrs: thin_vec![main_attr, coverage_attr, missing_docs_attr], + attrs: thin_vec![main_attr, coverage_attr, doc_hidden_attr], id: ast::DUMMY_NODE_ID, kind: main, vis: ast::Visibility { span: sp, kind: ast::VisibilityKind::Public, tokens: None }, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index d5240a05310b6..28d18f2dfcc15 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1236,7 +1236,6 @@ symbols! { mir_unwind_unreachable, mir_variant, miri, - missing_docs, mmx_reg, modifiers, module, diff --git a/tests/pretty/tests-are-sorted.pp b/tests/pretty/tests-are-sorted.pp index d10368a89cbc7..31449b51dc3e1 100644 --- a/tests/pretty/tests-are-sorted.pp +++ b/tests/pretty/tests-are-sorted.pp @@ -86,7 +86,7 @@ fn a_test() {} #[rustc_main] #[coverage(off)] -#[allow(missing_docs)] +#[doc(hidden)] pub fn main() -> () { extern crate test; test::test_main_static(&[&a_test, &m_test, &z_test]) diff --git a/tests/ui/lint/lint-missing-doc-test.rs b/tests/ui/lint/lint-missing-doc-test.rs index 466b79c0fb949..d86ec3525df36 100644 --- a/tests/ui/lint/lint-missing-doc-test.rs +++ b/tests/ui/lint/lint-missing-doc-test.rs @@ -2,7 +2,9 @@ //! on the generated test harness. //@ check-pass -//@ compile-flags: --test -Dmissing_docs +//@ compile-flags: --test + +#![forbid(missing_docs)] #[test] fn test() {} From db40dc316818aa6d12666ded7256fc4defb50f5a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 11 Sep 2024 16:31:05 +0200 Subject: [PATCH 164/189] notify Miri when intrinsics are changed --- triagebot.toml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/triagebot.toml b/triagebot.toml index f379f8cc7af50..467e64bb8b00b 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -570,7 +570,7 @@ cc = ["@bjorn3"] cc = ["@antoyo", "@GuillaumeGomez"] [mentions."compiler/rustc_const_eval/src/interpret"] -message = "Some changes occurred to the CTFE / Miri engine" +message = "Some changes occurred to the CTFE / Miri interpreter" cc = ["@rust-lang/miri"] [mentions."compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs"] @@ -590,7 +590,7 @@ message = "changes to `inspect_obligations.rs`" cc = ["@compiler-errors", "@lcnr"] [mentions."compiler/rustc_middle/src/mir/interpret"] -message = "Some changes occurred to the CTFE / Miri engine" +message = "Some changes occurred to the CTFE / Miri interpreter" cc = ["@rust-lang/miri"] [mentions."compiler/rustc_mir_transform/src/"] @@ -659,6 +659,13 @@ LLVM backend as well as portable-simd gets adapted for the changes. """ cc = ["@antoyo", "@GuillaumeGomez", "@bjorn3", "@calebzulawski", "@programmerjake"] +[mentions."library/core/src/intrinsics"] +message = """ +Some changes occurred to the intrinsics. Make sure the CTFE / Miri interpreter +gets adapted for the changes, if necessary. +""" +cc = ["@rust-lang/miri"] + [mentions."library/portable-simd"] message = """ Portable SIMD is developed in its own repository. If possible, consider \ From 5b7be148ea0128daad309cf5a123c868a65d7737 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 28 Aug 2024 20:10:26 +0200 Subject: [PATCH 165/189] Revert warning empty patterns as unreachable --- .../rustc_pattern_analysis/src/usefulness.rs | 6 +- .../usefulness/empty-types.never_pats.stderr | 188 +----------------- .../usefulness/empty-types.normal.stderr | 188 +----------------- tests/ui/pattern/usefulness/empty-types.rs | 46 ++--- .../usefulness/explain-unreachable-pats.rs | 1 + .../explain-unreachable-pats.stderr | 28 +-- tests/ui/pattern/usefulness/impl-trait.rs | 1 + tests/ui/pattern/usefulness/impl-trait.stderr | 32 +-- .../ui/reachable/unreachable-loop-patterns.rs | 1 + .../unreachable-loop-patterns.stderr | 4 +- .../rfc-0000-never_patterns/unreachable.rs | 1 + .../unreachable.stderr | 14 +- .../issue-65157-repeated-match-arm.rs | 1 - .../issue-65157-repeated-match-arm.stderr | 17 +- .../uninhabited/patterns.rs | 1 + .../uninhabited/patterns.stderr | 10 +- .../uninhabited/patterns_same_crate.rs | 1 + .../uninhabited/patterns_same_crate.stderr | 12 +- tests/ui/uninhabited/uninhabited-patterns.rs | 1 + .../uninhabited/uninhabited-patterns.stderr | 8 +- 20 files changed, 96 insertions(+), 465 deletions(-) diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index 6535afcc39862..814559a66c568 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -951,7 +951,11 @@ impl PlaceInfo { self.is_scrutinee && matches!(ctors_for_ty, ConstructorSet::NoConstructors); // Whether empty patterns are counted as useful or not. We only warn an empty arm unreachable if // it is guaranteed unreachable by the opsem (i.e. if the place is `known_valid`). - let empty_arms_are_unreachable = self.validity.is_known_valid(); + // We don't want to warn empty patterns as unreachable by default just yet. We will in a + // later version of rust or under a different lint name, see + // https://github.com/rust-lang/rust/pull/129103. + let empty_arms_are_unreachable = self.validity.is_known_valid() + && (is_toplevel_exception || cx.is_exhaustive_patterns_feature_on()); // Whether empty patterns can be omitted for exhaustiveness. We ignore place validity in the // toplevel exception and `exhaustive_patterns` cases for backwards compatibility. let can_omit_empty_arms = self.validity.is_known_valid() diff --git a/tests/ui/pattern/usefulness/empty-types.never_pats.stderr b/tests/ui/pattern/usefulness/empty-types.never_pats.stderr index 68213a2d661e0..fe9c431982004 100644 --- a/tests/ui/pattern/usefulness/empty-types.never_pats.stderr +++ b/tests/ui/pattern/usefulness/empty-types.never_pats.stderr @@ -43,30 +43,6 @@ LL + _ => todo!(), LL + } | -error: unreachable pattern - --> $DIR/empty-types.rs:70:9 - | -LL | (_, _) => {} - | ^^^^^^ matches no values because `(u32, !)` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - -error: unreachable pattern - --> $DIR/empty-types.rs:76:9 - | -LL | _ => {} - | ^ matches no values because `(!, !)` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - -error: unreachable pattern - --> $DIR/empty-types.rs:79:9 - | -LL | (_, _) => {} - | ^^^^^^ matches no values because `(!, !)` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - error: unreachable pattern --> $DIR/empty-types.rs:83:9 | @@ -94,22 +70,6 @@ LL + Ok(_) => todo!(), LL + } | -error: unreachable pattern - --> $DIR/empty-types.rs:94:9 - | -LL | Err(_) => {} - | ^^^^^^ matches no values because `!` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - -error: unreachable pattern - --> $DIR/empty-types.rs:99:9 - | -LL | Err(_) => {} - | ^^^^^^ matches no values because `!` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered --> $DIR/empty-types.rs:96:11 | @@ -156,54 +116,6 @@ help: you might want to use `let else` to handle the variant that isn't matched LL | let Ok(_x) = &res_u32_never else { todo!() }; | ++++++++++++++++ -error: unreachable pattern - --> $DIR/empty-types.rs:112:9 - | -LL | _ => {} - | ^ matches no values because `Result` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - -error: unreachable pattern - --> $DIR/empty-types.rs:115:9 - | -LL | Ok(_) => {} - | ^^^^^ matches no values because `Result` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - -error: unreachable pattern - --> $DIR/empty-types.rs:118:9 - | -LL | Ok(_) => {} - | ^^^^^ matches no values because `Result` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - -error: unreachable pattern - --> $DIR/empty-types.rs:119:9 - | -LL | _ => {} - | ^ matches no values because `Result` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - -error: unreachable pattern - --> $DIR/empty-types.rs:122:9 - | -LL | Ok(_) => {} - | ^^^^^ matches no values because `Result` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - -error: unreachable pattern - --> $DIR/empty-types.rs:123:9 - | -LL | Err(_) => {} - | ^^^^^^ matches no values because `Result` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - error: unreachable pattern --> $DIR/empty-types.rs:132:13 | @@ -220,22 +132,6 @@ LL | _ if false => {} | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types -error: unreachable pattern - --> $DIR/empty-types.rs:143:13 - | -LL | Some(_) => {} - | ^^^^^^^ matches no values because `Void` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - -error: unreachable pattern - --> $DIR/empty-types.rs:147:13 - | -LL | None => {} - | ---- matches all the relevant values -LL | _ => {} - | ^ no value can reach this - error[E0004]: non-exhaustive patterns: `Some(!)` not covered --> $DIR/empty-types.rs:156:15 | @@ -303,30 +199,6 @@ LL | _ => {} | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types -error: unreachable pattern - --> $DIR/empty-types.rs:284:9 - | -LL | (_, _) => {} - | ^^^^^^ matches no values because `(!, !)` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - -error: unreachable pattern - --> $DIR/empty-types.rs:287:9 - | -LL | Ok(_) => {} - | ^^^^^ matches no values because `Result` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - -error: unreachable pattern - --> $DIR/empty-types.rs:288:9 - | -LL | Err(_) => {} - | ^^^^^^ matches no values because `Result` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - error[E0005]: refutable pattern in local binding --> $DIR/empty-types.rs:297:13 | @@ -474,30 +346,6 @@ LL + _ => todo!(), LL + } | -error: unreachable pattern - --> $DIR/empty-types.rs:368:9 - | -LL | _ => {} - | ^ matches no values because `[!; 3]` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - -error: unreachable pattern - --> $DIR/empty-types.rs:371:9 - | -LL | [_, _, _] => {} - | ^^^^^^^^^ matches no values because `[!; 3]` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - -error: unreachable pattern - --> $DIR/empty-types.rs:374:9 - | -LL | [_, ..] => {} - | ^^^^^^^ matches no values because `[!; 3]` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty --> $DIR/empty-types.rs:388:11 | @@ -534,40 +382,6 @@ LL ~ [..] if false => {}, LL + [] => todo!() | -error: unreachable pattern - --> $DIR/empty-types.rs:416:9 - | -LL | Some(_) => {} - | ^^^^^^^ matches no values because `!` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - -error: unreachable pattern - --> $DIR/empty-types.rs:421:9 - | -LL | Some(_a) => {} - | ^^^^^^^^ matches no values because `!` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - -error: unreachable pattern - --> $DIR/empty-types.rs:426:9 - | -LL | None => {} - | ---- matches all the relevant values -LL | // !useful, !reachable -LL | _ => {} - | ^ no value can reach this - -error: unreachable pattern - --> $DIR/empty-types.rs:431:9 - | -LL | None => {} - | ---- matches all the relevant values -LL | // !useful, !reachable -LL | _a => {} - | ^^ no value can reach this - error[E0004]: non-exhaustive patterns: `&Some(!)` not covered --> $DIR/empty-types.rs:451:11 | @@ -744,7 +558,7 @@ LL ~ None => {}, LL + Some(!) | -error: aborting due to 65 previous errors; 1 warning emitted +error: aborting due to 42 previous errors; 1 warning emitted Some errors have detailed explanations: E0004, E0005. For more information about an error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/empty-types.normal.stderr b/tests/ui/pattern/usefulness/empty-types.normal.stderr index 8f60dad4467bc..201b0b5c3fde3 100644 --- a/tests/ui/pattern/usefulness/empty-types.normal.stderr +++ b/tests/ui/pattern/usefulness/empty-types.normal.stderr @@ -34,30 +34,6 @@ LL + _ => todo!(), LL + } | -error: unreachable pattern - --> $DIR/empty-types.rs:70:9 - | -LL | (_, _) => {} - | ^^^^^^ matches no values because `(u32, !)` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - -error: unreachable pattern - --> $DIR/empty-types.rs:76:9 - | -LL | _ => {} - | ^ matches no values because `(!, !)` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - -error: unreachable pattern - --> $DIR/empty-types.rs:79:9 - | -LL | (_, _) => {} - | ^^^^^^ matches no values because `(!, !)` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - error: unreachable pattern --> $DIR/empty-types.rs:83:9 | @@ -85,22 +61,6 @@ LL + Ok(_) => todo!(), LL + } | -error: unreachable pattern - --> $DIR/empty-types.rs:94:9 - | -LL | Err(_) => {} - | ^^^^^^ matches no values because `!` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - -error: unreachable pattern - --> $DIR/empty-types.rs:99:9 - | -LL | Err(_) => {} - | ^^^^^^ matches no values because `!` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered --> $DIR/empty-types.rs:96:11 | @@ -147,54 +107,6 @@ help: you might want to use `let else` to handle the variant that isn't matched LL | let Ok(_x) = &res_u32_never else { todo!() }; | ++++++++++++++++ -error: unreachable pattern - --> $DIR/empty-types.rs:112:9 - | -LL | _ => {} - | ^ matches no values because `Result` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - -error: unreachable pattern - --> $DIR/empty-types.rs:115:9 - | -LL | Ok(_) => {} - | ^^^^^ matches no values because `Result` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - -error: unreachable pattern - --> $DIR/empty-types.rs:118:9 - | -LL | Ok(_) => {} - | ^^^^^ matches no values because `Result` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - -error: unreachable pattern - --> $DIR/empty-types.rs:119:9 - | -LL | _ => {} - | ^ matches no values because `Result` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - -error: unreachable pattern - --> $DIR/empty-types.rs:122:9 - | -LL | Ok(_) => {} - | ^^^^^ matches no values because `Result` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - -error: unreachable pattern - --> $DIR/empty-types.rs:123:9 - | -LL | Err(_) => {} - | ^^^^^^ matches no values because `Result` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - error: unreachable pattern --> $DIR/empty-types.rs:132:13 | @@ -211,22 +123,6 @@ LL | _ if false => {} | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types -error: unreachable pattern - --> $DIR/empty-types.rs:143:13 - | -LL | Some(_) => {} - | ^^^^^^^ matches no values because `Void` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - -error: unreachable pattern - --> $DIR/empty-types.rs:147:13 - | -LL | None => {} - | ---- matches all the relevant values -LL | _ => {} - | ^ no value can reach this - error[E0004]: non-exhaustive patterns: `Some(_)` not covered --> $DIR/empty-types.rs:156:15 | @@ -294,30 +190,6 @@ LL | _ => {} | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types -error: unreachable pattern - --> $DIR/empty-types.rs:284:9 - | -LL | (_, _) => {} - | ^^^^^^ matches no values because `(!, !)` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - -error: unreachable pattern - --> $DIR/empty-types.rs:287:9 - | -LL | Ok(_) => {} - | ^^^^^ matches no values because `Result` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - -error: unreachable pattern - --> $DIR/empty-types.rs:288:9 - | -LL | Err(_) => {} - | ^^^^^^ matches no values because `Result` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - error[E0005]: refutable pattern in local binding --> $DIR/empty-types.rs:297:13 | @@ -465,30 +337,6 @@ LL + _ => todo!(), LL + } | -error: unreachable pattern - --> $DIR/empty-types.rs:368:9 - | -LL | _ => {} - | ^ matches no values because `[!; 3]` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - -error: unreachable pattern - --> $DIR/empty-types.rs:371:9 - | -LL | [_, _, _] => {} - | ^^^^^^^^^ matches no values because `[!; 3]` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - -error: unreachable pattern - --> $DIR/empty-types.rs:374:9 - | -LL | [_, ..] => {} - | ^^^^^^^ matches no values because `[!; 3]` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty --> $DIR/empty-types.rs:388:11 | @@ -525,40 +373,6 @@ LL ~ [..] if false => {}, LL + [] => todo!() | -error: unreachable pattern - --> $DIR/empty-types.rs:416:9 - | -LL | Some(_) => {} - | ^^^^^^^ matches no values because `!` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - -error: unreachable pattern - --> $DIR/empty-types.rs:421:9 - | -LL | Some(_a) => {} - | ^^^^^^^^ matches no values because `!` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - -error: unreachable pattern - --> $DIR/empty-types.rs:426:9 - | -LL | None => {} - | ---- matches all the relevant values -LL | // !useful, !reachable -LL | _ => {} - | ^ no value can reach this - -error: unreachable pattern - --> $DIR/empty-types.rs:431:9 - | -LL | None => {} - | ---- matches all the relevant values -LL | // !useful, !reachable -LL | _a => {} - | ^^ no value can reach this - error[E0004]: non-exhaustive patterns: `&Some(_)` not covered --> $DIR/empty-types.rs:451:11 | @@ -735,7 +549,7 @@ LL ~ None => {}, LL + Some(_) => todo!() | -error: aborting due to 65 previous errors +error: aborting due to 42 previous errors Some errors have detailed explanations: E0004, E0005. For more information about an error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/empty-types.rs b/tests/ui/pattern/usefulness/empty-types.rs index d561a0e9c128b..9e5f273a39052 100644 --- a/tests/ui/pattern/usefulness/empty-types.rs +++ b/tests/ui/pattern/usefulness/empty-types.rs @@ -67,16 +67,16 @@ fn basic(x: NeverBundle) { let tuple_half_never: (u32, !) = x.tuple_half_never; match tuple_half_never {} match tuple_half_never { - (_, _) => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern + (_, _) => {} //[exhaustive_patterns]~ ERROR unreachable pattern } let tuple_never: (!, !) = x.tuple_never; match tuple_never {} match tuple_never { - _ => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern + _ => {} //[exhaustive_patterns]~ ERROR unreachable pattern } match tuple_never { - (_, _) => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern + (_, _) => {} //[exhaustive_patterns]~ ERROR unreachable pattern } match tuple_never.0 {} match tuple_never.0 { @@ -91,12 +91,12 @@ fn basic(x: NeverBundle) { } match res_u32_never { Ok(_) => {} - Err(_) => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern + Err(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern } match res_u32_never { //~^ ERROR non-exhaustive Ok(0) => {} - Err(_) => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern + Err(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern } let Ok(_x) = res_u32_never; let Ok(_x) = res_u32_never.as_ref(); @@ -109,18 +109,18 @@ fn basic(x: NeverBundle) { let result_never: Result = x.result_never; match result_never {} match result_never { - _ => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern + _ => {} //[exhaustive_patterns]~ ERROR unreachable pattern } match result_never { - Ok(_) => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern + Ok(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern } match result_never { - Ok(_) => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern - _ => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern + Ok(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern + _ => {} //[exhaustive_patterns]~ ERROR unreachable pattern } match result_never { - Ok(_) => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern - Err(_) => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern + Ok(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern + Err(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern } } @@ -140,11 +140,11 @@ fn void_same_as_never(x: NeverBundle) { } match opt_void { None => {} - Some(_) => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern + Some(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern } match opt_void { None => {} - _ => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern + _ => {} //[exhaustive_patterns]~ ERROR unreachable pattern } let ref_void: &Void = &x.void; @@ -281,11 +281,11 @@ fn nested_validity_tracking(bundle: NeverBundle) { _ => {} //~ ERROR unreachable pattern } match tuple_never { - (_, _) => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern + (_, _) => {} //[exhaustive_patterns]~ ERROR unreachable pattern } match result_never { - Ok(_) => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern - Err(_) => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern + Ok(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern + Err(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern } // These should be considered !known_valid and not warn unreachable. @@ -365,13 +365,13 @@ fn arrays_and_slices(x: NeverBundle) { let array_3_never: [!; 3] = x.array_3_never; match array_3_never {} match array_3_never { - _ => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern + _ => {} //[exhaustive_patterns]~ ERROR unreachable pattern } match array_3_never { - [_, _, _] => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern + [_, _, _] => {} //[exhaustive_patterns]~ ERROR unreachable pattern } match array_3_never { - [_, ..] => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern + [_, ..] => {} //[exhaustive_patterns]~ ERROR unreachable pattern } let ref_array_3_never: &[!; 3] = &array_3_never; @@ -413,22 +413,22 @@ fn bindings(x: NeverBundle) { match opt_never { None => {} // !useful, !reachable - Some(_) => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern + Some(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern } match opt_never { None => {} // !useful, !reachable - Some(_a) => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern + Some(_a) => {} //[exhaustive_patterns]~ ERROR unreachable pattern } match opt_never { None => {} // !useful, !reachable - _ => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern + _ => {} //[exhaustive_patterns]~ ERROR unreachable pattern } match opt_never { None => {} // !useful, !reachable - _a => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern + _a => {} //[exhaustive_patterns]~ ERROR unreachable pattern } // The scrutinee is known_valid, but under the `&` isn't anymore. diff --git a/tests/ui/pattern/usefulness/explain-unreachable-pats.rs b/tests/ui/pattern/usefulness/explain-unreachable-pats.rs index 1cfa5212414bb..f1af7f294cbd8 100644 --- a/tests/ui/pattern/usefulness/explain-unreachable-pats.rs +++ b/tests/ui/pattern/usefulness/explain-unreachable-pats.rs @@ -1,4 +1,5 @@ #![feature(never_type)] +#![feature(exhaustive_patterns)] #![deny(unreachable_patterns)] //~^ NOTE lint level is defined here diff --git a/tests/ui/pattern/usefulness/explain-unreachable-pats.stderr b/tests/ui/pattern/usefulness/explain-unreachable-pats.stderr index 7023c2775e9a7..67f83a8517504 100644 --- a/tests/ui/pattern/usefulness/explain-unreachable-pats.stderr +++ b/tests/ui/pattern/usefulness/explain-unreachable-pats.stderr @@ -1,5 +1,5 @@ error: unreachable pattern - --> $DIR/explain-unreachable-pats.rs:10:9 + --> $DIR/explain-unreachable-pats.rs:11:9 | LL | (1 | 2,) => {} | -------- matches all the relevant values @@ -8,19 +8,19 @@ LL | (2,) => {} | ^^^^ no value can reach this | note: the lint level is defined here - --> $DIR/explain-unreachable-pats.rs:2:9 + --> $DIR/explain-unreachable-pats.rs:3:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/explain-unreachable-pats.rs:21:9 + --> $DIR/explain-unreachable-pats.rs:22:9 | LL | (1 | 2,) => {} | ^^^^^^^^ no value can reach this | note: multiple earlier patterns match some of the same values - --> $DIR/explain-unreachable-pats.rs:21:9 + --> $DIR/explain-unreachable-pats.rs:22:9 | LL | (1,) => {} | ---- matches some of the same values @@ -32,13 +32,13 @@ LL | (1 | 2,) => {} | ^^^^^^^^ collectively making this unreachable error: unreachable pattern - --> $DIR/explain-unreachable-pats.rs:40:9 + --> $DIR/explain-unreachable-pats.rs:41:9 | LL | 1 ..= 6 => {} | ^^^^^^^ no value can reach this | note: multiple earlier patterns match some of the same values - --> $DIR/explain-unreachable-pats.rs:40:9 + --> $DIR/explain-unreachable-pats.rs:41:9 | LL | 1 => {} | - matches some of the same values @@ -56,7 +56,7 @@ LL | 1 ..= 6 => {} | ^^^^^^^ ...and 2 other patterns collectively make this unreachable error: unreachable pattern - --> $DIR/explain-unreachable-pats.rs:51:9 + --> $DIR/explain-unreachable-pats.rs:52:9 | LL | Err(_) => {} | ^^^^^^ matches no values because `!` is uninhabited @@ -64,7 +64,7 @@ LL | Err(_) => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/explain-unreachable-pats.rs:65:9 + --> $DIR/explain-unreachable-pats.rs:66:9 | LL | (Err(_), Err(_)) => {} | ^^^^^^^^^^^^^^^^ matches no values because `Void2` is uninhabited @@ -72,7 +72,7 @@ LL | (Err(_), Err(_)) => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/explain-unreachable-pats.rs:72:9 + --> $DIR/explain-unreachable-pats.rs:73:9 | LL | (Err(_), Err(_)) => {} | ^^^^^^^^^^^^^^^^ matches no values because `Void1` is uninhabited @@ -80,7 +80,7 @@ LL | (Err(_), Err(_)) => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/explain-unreachable-pats.rs:82:11 + --> $DIR/explain-unreachable-pats.rs:83:11 | LL | if let (0 | - matches all the relevant values @@ -89,13 +89,13 @@ LL | | 0, _) = (0, 0) {} | ^ no value can reach this error: unreachable pattern - --> $DIR/explain-unreachable-pats.rs:92:9 + --> $DIR/explain-unreachable-pats.rs:93:9 | LL | (_, true) => {} | ^^^^^^^^^ no value can reach this | note: multiple earlier patterns match some of the same values - --> $DIR/explain-unreachable-pats.rs:92:9 + --> $DIR/explain-unreachable-pats.rs:93:9 | LL | (true, _) => {} | --------- matches some of the same values @@ -107,7 +107,7 @@ LL | (_, true) => {} | ^^^^^^^^^ collectively making this unreachable error: unreachable pattern - --> $DIR/explain-unreachable-pats.rs:105:9 + --> $DIR/explain-unreachable-pats.rs:106:9 | LL | (true, _) => {} | --------- matches all the relevant values @@ -116,7 +116,7 @@ LL | (true, true) => {} | ^^^^^^^^^^^^ no value can reach this error: unreachable pattern - --> $DIR/explain-unreachable-pats.rs:117:9 + --> $DIR/explain-unreachable-pats.rs:118:9 | LL | (_, true, 0..10) => {} | ---------------- matches all the relevant values diff --git a/tests/ui/pattern/usefulness/impl-trait.rs b/tests/ui/pattern/usefulness/impl-trait.rs index c1cc279f74ce9..16560a092675f 100644 --- a/tests/ui/pattern/usefulness/impl-trait.rs +++ b/tests/ui/pattern/usefulness/impl-trait.rs @@ -1,6 +1,7 @@ #![feature(never_type)] #![feature(type_alias_impl_trait)] #![feature(non_exhaustive_omitted_patterns_lint)] +#![feature(exhaustive_patterns)] #![deny(unreachable_patterns)] // Test that the lint traversal handles opaques correctly #![deny(non_exhaustive_omitted_patterns)] diff --git a/tests/ui/pattern/usefulness/impl-trait.stderr b/tests/ui/pattern/usefulness/impl-trait.stderr index 34b157f0fc443..f2945fca82bed 100644 --- a/tests/ui/pattern/usefulness/impl-trait.stderr +++ b/tests/ui/pattern/usefulness/impl-trait.stderr @@ -1,18 +1,18 @@ error: unreachable pattern - --> $DIR/impl-trait.rs:16:13 + --> $DIR/impl-trait.rs:17:13 | LL | _ => {} | ^ matches no values because `Void` is uninhabited | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here - --> $DIR/impl-trait.rs:4:9 + --> $DIR/impl-trait.rs:5:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/impl-trait.rs:30:13 + --> $DIR/impl-trait.rs:31:13 | LL | _ => {} | ^ matches no values because `Void` is uninhabited @@ -20,7 +20,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/impl-trait.rs:44:13 + --> $DIR/impl-trait.rs:45:13 | LL | Some(_) => {} | ^^^^^^^ matches no values because `Void` is uninhabited @@ -28,7 +28,7 @@ LL | Some(_) => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/impl-trait.rs:48:13 + --> $DIR/impl-trait.rs:49:13 | LL | None => {} | ---- matches all the relevant values @@ -36,7 +36,7 @@ LL | _ => {} | ^ no value can reach this error: unreachable pattern - --> $DIR/impl-trait.rs:58:13 + --> $DIR/impl-trait.rs:59:13 | LL | Some(_) => {} | ^^^^^^^ matches no values because `Void` is uninhabited @@ -44,7 +44,7 @@ LL | Some(_) => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/impl-trait.rs:62:13 + --> $DIR/impl-trait.rs:63:13 | LL | None => {} | ---- matches all the relevant values @@ -52,7 +52,7 @@ LL | _ => {} | ^ no value can reach this error: unreachable pattern - --> $DIR/impl-trait.rs:75:9 + --> $DIR/impl-trait.rs:76:9 | LL | _ => {} | ^ matches no values because `Void` is uninhabited @@ -60,7 +60,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/impl-trait.rs:85:9 + --> $DIR/impl-trait.rs:86:9 | LL | _ => {} | - matches any value @@ -68,7 +68,7 @@ LL | Some((a, b)) => {} | ^^^^^^^^^^^^ no value can reach this error: unreachable pattern - --> $DIR/impl-trait.rs:93:13 + --> $DIR/impl-trait.rs:94:13 | LL | _ => {} | ^ matches no values because `Void` is uninhabited @@ -76,7 +76,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/impl-trait.rs:104:9 + --> $DIR/impl-trait.rs:105:9 | LL | Some((a, b)) => {} | ------------ matches all the relevant values @@ -84,7 +84,7 @@ LL | Some((mut x, mut y)) => { | ^^^^^^^^^^^^^^^^^^^^ no value can reach this error: unreachable pattern - --> $DIR/impl-trait.rs:123:13 + --> $DIR/impl-trait.rs:124:13 | LL | _ => {} | - matches any value @@ -92,7 +92,7 @@ LL | Rec { n: 0, w: Some(Rec { n: 0, w: _ }) } => {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no value can reach this error: unreachable pattern - --> $DIR/impl-trait.rs:137:13 + --> $DIR/impl-trait.rs:138:13 | LL | _ => {} | ^ matches no values because `SecretelyVoid` is uninhabited @@ -100,7 +100,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/impl-trait.rs:150:13 + --> $DIR/impl-trait.rs:151:13 | LL | _ => {} | ^ matches no values because `SecretelyDoubleVoid` is uninhabited @@ -108,7 +108,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: type `impl Copy` is non-empty - --> $DIR/impl-trait.rs:22:11 + --> $DIR/impl-trait.rs:23:11 | LL | match return_never_rpit(x) {} | ^^^^^^^^^^^^^^^^^^^^ @@ -122,7 +122,7 @@ LL + } | error[E0004]: non-exhaustive patterns: type `T` is non-empty - --> $DIR/impl-trait.rs:36:11 + --> $DIR/impl-trait.rs:37:11 | LL | match return_never_tait(x) {} | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/reachable/unreachable-loop-patterns.rs b/tests/ui/reachable/unreachable-loop-patterns.rs index d074e3a6ece4b..9be37ecf2bb27 100644 --- a/tests/ui/reachable/unreachable-loop-patterns.rs +++ b/tests/ui/reachable/unreachable-loop-patterns.rs @@ -1,3 +1,4 @@ +#![feature(exhaustive_patterns)] #![feature(never_type, never_type_fallback)] #![allow(unreachable_code)] #![deny(unreachable_patterns)] diff --git a/tests/ui/reachable/unreachable-loop-patterns.stderr b/tests/ui/reachable/unreachable-loop-patterns.stderr index 03959ac160695..290f45700b2e4 100644 --- a/tests/ui/reachable/unreachable-loop-patterns.stderr +++ b/tests/ui/reachable/unreachable-loop-patterns.stderr @@ -1,12 +1,12 @@ error: unreachable pattern - --> $DIR/unreachable-loop-patterns.rs:16:9 + --> $DIR/unreachable-loop-patterns.rs:17:9 | LL | for _ in unimplemented!() as Void {} | ^ matches no values because `Void` is uninhabited | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here - --> $DIR/unreachable-loop-patterns.rs:3:9 + --> $DIR/unreachable-loop-patterns.rs:4:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.rs b/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.rs index f68da4aa17316..6d7815f7a9eb0 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.rs +++ b/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.rs @@ -1,3 +1,4 @@ +#![feature(exhaustive_patterns)] #![feature(never_patterns)] #![allow(incomplete_features)] #![allow(dead_code, unreachable_code)] diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.stderr index 6b3f303eeab84..90874760a56fa 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.stderr +++ b/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.stderr @@ -1,18 +1,18 @@ error: unreachable pattern - --> $DIR/unreachable.rs:14:9 + --> $DIR/unreachable.rs:15:9 | LL | Err(!), | ^^^^^^ matches no values because `Void` is uninhabited | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here - --> $DIR/unreachable.rs:4:9 + --> $DIR/unreachable.rs:5:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/unreachable.rs:17:19 + --> $DIR/unreachable.rs:18:19 | LL | let (Ok(_x) | Err(!)) = res_void; | ^^^^^^ matches no values because `Void` is uninhabited @@ -20,7 +20,7 @@ LL | let (Ok(_x) | Err(!)) = res_void; = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/unreachable.rs:19:12 + --> $DIR/unreachable.rs:20:12 | LL | if let Err(!) = res_void {} | ^^^^^^ matches no values because `Void` is uninhabited @@ -28,7 +28,7 @@ LL | if let Err(!) = res_void {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/unreachable.rs:21:24 + --> $DIR/unreachable.rs:22:24 | LL | if let (Ok(true) | Err(!)) = res_void {} | ^^^^^^ matches no values because `Void` is uninhabited @@ -36,7 +36,7 @@ LL | if let (Ok(true) | Err(!)) = res_void {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/unreachable.rs:23:23 + --> $DIR/unreachable.rs:24:23 | LL | for (Ok(mut _x) | Err(!)) in [res_void] {} | ^^^^^^ matches no values because `Void` is uninhabited @@ -44,7 +44,7 @@ LL | for (Ok(mut _x) | Err(!)) in [res_void] {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/unreachable.rs:27:18 + --> $DIR/unreachable.rs:28:18 | LL | fn foo((Ok(_x) | Err(!)): Result) {} | ^^^^^^ matches no values because `Void` is uninhabited diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.rs index 6bee019e89782..ca7c528715420 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.rs +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.rs @@ -12,7 +12,6 @@ use uninhabited::PartiallyInhabitedVariants; pub fn foo(x: PartiallyInhabitedVariants) { match x { PartiallyInhabitedVariants::Struct { .. } => {} - //~^ ERROR unreachable pattern PartiallyInhabitedVariants::Struct { .. } => {} //~^ ERROR unreachable pattern _ => {} diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr index 4fa53101a55f1..86df9ef9b564c 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr @@ -1,23 +1,16 @@ error: unreachable pattern - --> $DIR/issue-65157-repeated-match-arm.rs:14:9 + --> $DIR/issue-65157-repeated-match-arm.rs:15:9 | LL | PartiallyInhabitedVariants::Struct { .. } => {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ matches no values because `PartiallyInhabitedVariants` is uninhabited + | ----------------------------------------- matches all the relevant values +LL | PartiallyInhabitedVariants::Struct { .. } => {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no value can reach this | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here --> $DIR/issue-65157-repeated-match-arm.rs:2:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ -error: unreachable pattern - --> $DIR/issue-65157-repeated-match-arm.rs:16:9 - | -LL | PartiallyInhabitedVariants::Struct { .. } => {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ matches no values because `PartiallyInhabitedVariants` is uninhabited - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.rs index edc588777eb98..088331b0e7f72 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.rs +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.rs @@ -1,4 +1,5 @@ //@ aux-build:uninhabited.rs +#![feature(exhaustive_patterns)] #![deny(unreachable_patterns)] extern crate uninhabited; diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.stderr index deaa2ffd92720..83300049ea9b4 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.stderr @@ -1,18 +1,18 @@ error: unreachable pattern - --> $DIR/patterns.rs:41:9 + --> $DIR/patterns.rs:42:9 | LL | Some(_x) => (), | ^^^^^^^^ matches no values because `UninhabitedVariants` is uninhabited | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here - --> $DIR/patterns.rs:2:9 + --> $DIR/patterns.rs:3:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/patterns.rs:46:15 + --> $DIR/patterns.rs:47:15 | LL | while let PartiallyInhabitedVariants::Struct { x, .. } = partially_inhabited_variant() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ matches no values because `!` is uninhabited @@ -20,7 +20,7 @@ LL | while let PartiallyInhabitedVariants::Struct { x, .. } = partially_inha = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/patterns.rs:48:15 + --> $DIR/patterns.rs:49:15 | LL | while let Some(_x) = uninhabited_struct() { | ^^^^^^^^ matches no values because `UninhabitedStruct` is uninhabited @@ -28,7 +28,7 @@ LL | while let Some(_x) = uninhabited_struct() { = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/patterns.rs:51:15 + --> $DIR/patterns.rs:52:15 | LL | while let Some(_x) = uninhabited_tuple_struct() { | ^^^^^^^^ matches no values because `UninhabitedTupleStruct` is uninhabited diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs index 58cced3d23d61..3d89ca15d3778 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs @@ -1,3 +1,4 @@ +#![feature(exhaustive_patterns)] #![deny(unreachable_patterns)] #![feature(never_type)] diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr index 38524bf5b952e..4b107b0364506 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr @@ -1,18 +1,18 @@ error: unreachable pattern - --> $DIR/patterns_same_crate.rs:52:9 + --> $DIR/patterns_same_crate.rs:53:9 | LL | Some(_x) => (), | ^^^^^^^^ matches no values because `UninhabitedEnum` is uninhabited | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here - --> $DIR/patterns_same_crate.rs:1:9 + --> $DIR/patterns_same_crate.rs:2:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/patterns_same_crate.rs:57:9 + --> $DIR/patterns_same_crate.rs:58:9 | LL | Some(_x) => (), | ^^^^^^^^ matches no values because `UninhabitedVariants` is uninhabited @@ -20,7 +20,7 @@ LL | Some(_x) => (), = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/patterns_same_crate.rs:61:15 + --> $DIR/patterns_same_crate.rs:62:15 | LL | while let PartiallyInhabitedVariants::Struct { x } = partially_inhabited_variant() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ matches no values because `!` is uninhabited @@ -28,7 +28,7 @@ LL | while let PartiallyInhabitedVariants::Struct { x } = partially_inhabite = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/patterns_same_crate.rs:65:15 + --> $DIR/patterns_same_crate.rs:66:15 | LL | while let Some(_x) = uninhabited_struct() { | ^^^^^^^^ matches no values because `UninhabitedStruct` is uninhabited @@ -36,7 +36,7 @@ LL | while let Some(_x) = uninhabited_struct() { = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/patterns_same_crate.rs:68:15 + --> $DIR/patterns_same_crate.rs:69:15 | LL | while let Some(_x) = uninhabited_tuple_struct() { | ^^^^^^^^ matches no values because `UninhabitedTupleStruct` is uninhabited diff --git a/tests/ui/uninhabited/uninhabited-patterns.rs b/tests/ui/uninhabited/uninhabited-patterns.rs index 988383e691b4e..b7429464fa5a0 100644 --- a/tests/ui/uninhabited/uninhabited-patterns.rs +++ b/tests/ui/uninhabited/uninhabited-patterns.rs @@ -1,3 +1,4 @@ +#![feature(exhaustive_patterns)] #![feature(box_patterns)] #![feature(never_type)] #![deny(unreachable_patterns)] diff --git a/tests/ui/uninhabited/uninhabited-patterns.stderr b/tests/ui/uninhabited/uninhabited-patterns.stderr index 0e1c9d31a731f..db0166ad5f2c5 100644 --- a/tests/ui/uninhabited/uninhabited-patterns.stderr +++ b/tests/ui/uninhabited/uninhabited-patterns.stderr @@ -1,18 +1,18 @@ error: unreachable pattern - --> $DIR/uninhabited-patterns.rs:29:9 + --> $DIR/uninhabited-patterns.rs:30:9 | LL | Ok(box _) => (), | ^^^^^^^^^ matches no values because `NotSoSecretlyEmpty` is uninhabited | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here - --> $DIR/uninhabited-patterns.rs:3:9 + --> $DIR/uninhabited-patterns.rs:4:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/uninhabited-patterns.rs:38:9 + --> $DIR/uninhabited-patterns.rs:39:9 | LL | Err(Ok(_y)) => (), | ^^^^^^^^^^^ matches no values because `NotSoSecretlyEmpty` is uninhabited @@ -20,7 +20,7 @@ LL | Err(Ok(_y)) => (), = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/uninhabited-patterns.rs:41:15 + --> $DIR/uninhabited-patterns.rs:42:15 | LL | while let Some(_y) = foo() { | ^^^^^^^^ matches no values because `NotSoSecretlyEmpty` is uninhabited From 6c8423865f65fd11ee42d33336a349b9817a02ff Mon Sep 17 00:00:00 2001 From: Julius Liu Date: Wed, 11 Sep 2024 09:59:05 -0700 Subject: [PATCH 166/189] docs: remove struct info --- library/std/src/os/windows/fs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/os/windows/fs.rs b/library/std/src/os/windows/fs.rs index d03f9e0e330dd..c3b91967953ff 100644 --- a/library/std/src/os/windows/fs.rs +++ b/library/std/src/os/windows/fs.rs @@ -472,7 +472,7 @@ pub trait MetadataExt { #[unstable(feature = "windows_by_handle", issue = "63010")] fn file_index(&self) -> Option; - /// Returns the value of the `ChangeTime{Low,High}` fields of this metadata. + /// Returns the value of the `ChangeTime` fields of this metadata. /// /// `ChangeTime` is the last time file metadata was changed, such as /// renames, attributes, etc. From 954419aab01264707f116899e77be682b02764ea Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 11 Sep 2024 13:32:53 -0400 Subject: [PATCH 167/189] Simplify some nested if statements --- compiler/rustc_ast_lowering/src/index.rs | 36 +++--- .../rustc_ast_passes/src/ast_validation.rs | 14 +-- .../src/diagnostics/conflict_errors.rs | 47 ++++---- compiler/rustc_borrowck/src/lib.rs | 10 +- .../src/type_check/liveness/trace.rs | 10 +- compiler/rustc_codegen_llvm/src/back/lto.rs | 8 +- .../rustc_codegen_ssa/src/codegen_attrs.rs | 41 ++++--- .../src/interpret/eval_context.rs | 22 ++-- compiler/rustc_driver_impl/src/pretty.rs | 6 +- compiler/rustc_hir_analysis/src/check/mod.rs | 10 +- .../rustc_hir_analysis/src/coherence/mod.rs | 20 ++-- .../errors/wrong_number_of_generic_args.rs | 22 ++-- compiler/rustc_hir_typeck/src/cast.rs | 11 +- compiler/rustc_hir_typeck/src/expr.rs | 18 ++- .../rustc_hir_typeck/src/method/suggest.rs | 19 ++-- compiler/rustc_lint/src/builtin.rs | 6 +- compiler/rustc_middle/src/middle/stability.rs | 9 +- .../src/mir/interpret/allocation.rs | 30 +++-- compiler/rustc_middle/src/ty/context.rs | 50 ++++----- compiler/rustc_middle/src/ty/layout.rs | 8 +- compiler/rustc_middle/src/ty/print/pretty.rs | 6 +- .../src/build/coverageinfo/mcdc.rs | 5 +- .../src/check_const_item_mutation.rs | 24 ++-- .../src/deduce_param_attrs.rs | 9 +- .../src/known_panics_lint.rs | 20 ++-- .../rustc_monomorphize/src/partitioning.rs | 6 +- .../src/canonicalizer.rs | 6 +- compiler/rustc_parse/src/parser/path.rs | 12 +- compiler/rustc_passes/src/stability.rs | 18 ++- compiler/rustc_resolve/src/diagnostics.rs | 105 +++++++++--------- compiler/rustc_resolve/src/ident.rs | 12 +- compiler/rustc_resolve/src/late.rs | 16 ++- .../rustc_resolve/src/late/diagnostics.rs | 33 +++--- .../src/traits/select/candidate_assembly.rs | 5 +- .../src/traits/select/mod.rs | 38 +++---- compiler/rustc_ty_utils/src/opaque_types.rs | 6 +- 36 files changed, 339 insertions(+), 379 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index 23729124e21a9..f90a0612db692 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -78,26 +78,24 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { // Make sure that the DepNode of some node coincides with the HirId // owner of that node. - if cfg!(debug_assertions) { - if hir_id.owner != self.owner { - span_bug!( - span, - "inconsistent HirId at `{:?}` for `{:?}`: \ + if cfg!(debug_assertions) && hir_id.owner != self.owner { + span_bug!( + span, + "inconsistent HirId at `{:?}` for `{:?}`: \ current_dep_node_owner={} ({:?}), hir_id.owner={} ({:?})", - self.tcx.sess.source_map().span_to_diagnostic_string(span), - node, - self.tcx - .definitions_untracked() - .def_path(self.owner.def_id) - .to_string_no_crate_verbose(), - self.owner, - self.tcx - .definitions_untracked() - .def_path(hir_id.owner.def_id) - .to_string_no_crate_verbose(), - hir_id.owner, - ) - } + self.tcx.sess.source_map().span_to_diagnostic_string(span), + node, + self.tcx + .definitions_untracked() + .def_path(self.owner.def_id) + .to_string_no_crate_verbose(), + self.owner, + self.tcx + .definitions_untracked() + .def_path(hir_id.owner.def_id) + .to_string_no_crate_verbose(), + hir_id.owner, + ) } self.nodes[hir_id.local_id] = ParentedNode { parent: self.parent_node, node }; diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index ed9672a9e79b3..67dd18fd89cca 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -447,13 +447,13 @@ impl<'a> AstValidator<'a> { fn check_item_safety(&self, span: Span, safety: Safety) { match self.extern_mod_safety { Some(extern_safety) => { - if matches!(safety, Safety::Unsafe(_) | Safety::Safe(_)) { - if extern_safety == Safety::Default { - self.dcx().emit_err(errors::InvalidSafetyOnExtern { - item_span: span, - block: Some(self.current_extern_span().shrink_to_lo()), - }); - } + if matches!(safety, Safety::Unsafe(_) | Safety::Safe(_)) + && extern_safety == Safety::Default + { + self.dcx().emit_err(errors::InvalidSafetyOnExtern { + item_span: span, + block: Some(self.current_extern_span().shrink_to_lo()), + }); } } None => { diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index a47518fca3f9b..357ed470748d3 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -2574,33 +2574,31 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } impl<'hir> Visitor<'hir> for ExpressionFinder<'hir> { fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) { - if e.span.contains(self.capture_span) { - if let hir::ExprKind::Closure(&hir::Closure { + if e.span.contains(self.capture_span) + && let hir::ExprKind::Closure(&hir::Closure { kind: hir::ClosureKind::Closure, body, fn_arg_span, fn_decl: hir::FnDecl { inputs, .. }, .. }) = e.kind - && let hir::Node::Expr(body) = self.tcx.hir_node(body.hir_id) - { - self.suggest_arg = "this: &Self".to_string(); - if inputs.len() > 0 { - self.suggest_arg.push_str(", "); - } - self.in_closure = true; - self.closure_arg_span = fn_arg_span; - self.visit_expr(body); - self.in_closure = false; + && let hir::Node::Expr(body) = self.tcx.hir_node(body.hir_id) + { + self.suggest_arg = "this: &Self".to_string(); + if inputs.len() > 0 { + self.suggest_arg.push_str(", "); } + self.in_closure = true; + self.closure_arg_span = fn_arg_span; + self.visit_expr(body); + self.in_closure = false; } - if let hir::Expr { kind: hir::ExprKind::Path(path), .. } = e { - if let hir::QPath::Resolved(_, hir::Path { segments: [seg], .. }) = path - && seg.ident.name == kw::SelfLower - && self.in_closure - { - self.closure_change_spans.push(e.span); - } + if let hir::Expr { kind: hir::ExprKind::Path(path), .. } = e + && let hir::QPath::Resolved(_, hir::Path { segments: [seg], .. }) = path + && seg.ident.name == kw::SelfLower + && self.in_closure + { + self.closure_change_spans.push(e.span); } hir::intravisit::walk_expr(self, e); } @@ -2609,8 +2607,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { if let hir::Pat { kind: hir::PatKind::Binding(_, hir_id, _ident, _), .. } = local.pat && let Some(init) = local.init - { - if let hir::Expr { + && let hir::Expr { kind: hir::ExprKind::Closure(&hir::Closure { kind: hir::ClosureKind::Closure, @@ -2618,11 +2615,11 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { }), .. } = init - && init.span.contains(self.capture_span) - { - self.closure_local_id = Some(*hir_id); - } + && init.span.contains(self.capture_span) + { + self.closure_local_id = Some(*hir_id); } + hir::intravisit::walk_local(self, local); } diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index d5f297a591382..d98c66b0f3bb3 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -2069,12 +2069,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { // no move out from an earlier location) then this is an attempt at initialization // of the union - we should error in that case. let tcx = this.infcx.tcx; - if base.ty(this.body(), tcx).ty.is_union() { - if this.move_data.path_map[mpi].iter().any(|moi| { + if base.ty(this.body(), tcx).ty.is_union() + && this.move_data.path_map[mpi].iter().any(|moi| { this.move_data.moves[*moi].source.is_predecessor_of(location, this.body) - }) { - return; - } + }) + { + return; } this.report_use_of_moved_or_uninitialized( diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index 4d47863ae76ad..1ac2757345390 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -353,11 +353,11 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> { let location = self.cx.elements.to_location(drop_point); debug_assert_eq!(self.cx.body.terminator_loc(location.block), location,); - if self.cx.initialized_at_terminator(location.block, mpi) { - if self.drop_live_at.insert(drop_point) { - self.drop_locations.push(location); - self.stack.push(drop_point); - } + if self.cx.initialized_at_terminator(location.block, mpi) + && self.drop_live_at.insert(drop_point) + { + self.drop_locations.push(location); + self.stack.push(drop_point); } } diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index 09896b89ebf42..2ebe0be53aa11 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -92,11 +92,9 @@ fn prepare_lto( dcx.emit_err(LtoDylib); return Err(FatalError); } - } else if *crate_type == CrateType::ProcMacro { - if !cgcx.opts.unstable_opts.dylib_lto { - dcx.emit_err(LtoProcMacro); - return Err(FatalError); - } + } else if *crate_type == CrateType::ProcMacro && !cgcx.opts.unstable_opts.dylib_lto { + dcx.emit_err(LtoProcMacro); + return Err(FatalError); } } diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 4ab20c154ccd0..9149c60229668 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -617,32 +617,29 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { // purpose functions as they wouldn't have the right target features // enabled. For that reason we also forbid #[inline(always)] as it can't be // respected. - if !codegen_fn_attrs.target_features.is_empty() { - if codegen_fn_attrs.inline == InlineAttr::Always { - if let Some(span) = inline_span { - tcx.dcx().span_err( - span, - "cannot use `#[inline(always)]` with \ + if !codegen_fn_attrs.target_features.is_empty() && codegen_fn_attrs.inline == InlineAttr::Always + { + if let Some(span) = inline_span { + tcx.dcx().span_err( + span, + "cannot use `#[inline(always)]` with \ `#[target_feature]`", - ); - } + ); } } - if !codegen_fn_attrs.no_sanitize.is_empty() { - if codegen_fn_attrs.inline == InlineAttr::Always { - if let (Some(no_sanitize_span), Some(inline_span)) = (no_sanitize_span, inline_span) { - let hir_id = tcx.local_def_id_to_hir_id(did); - tcx.node_span_lint( - lint::builtin::INLINE_NO_SANITIZE, - hir_id, - no_sanitize_span, - |lint| { - lint.primary_message("`no_sanitize` will have no effect after inlining"); - lint.span_note(inline_span, "inlining requested here"); - }, - ) - } + if !codegen_fn_attrs.no_sanitize.is_empty() && codegen_fn_attrs.inline == InlineAttr::Always { + if let (Some(no_sanitize_span), Some(inline_span)) = (no_sanitize_span, inline_span) { + let hir_id = tcx.local_def_id_to_hir_id(did); + tcx.node_span_lint( + lint::builtin::INLINE_NO_SANITIZE, + hir_id, + no_sanitize_span, + |lint| { + lint.primary_message("`no_sanitize` will have no effect after inlining"); + lint.span_note(inline_span, "inlining requested here"); + }, + ) } } diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index dd744c51f23be..16d40fcceb6bb 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -16,7 +16,7 @@ use rustc_span::Span; use rustc_target::abi::call::FnAbi; use rustc_target::abi::{Align, HasDataLayout, Size, TargetDataLayout}; use rustc_trait_selection::traits::ObligationCtxt; -use tracing::{debug, trace}; +use tracing::{debug, instrument, trace}; use super::{ err_inval, throw_inval, throw_ub, throw_ub_custom, Frame, FrameInfo, GlobalId, InterpErrorInfo, @@ -315,6 +315,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// Check if the two things are equal in the current param_env, using an infctx to get proper /// equality checks. + #[instrument(level = "trace", skip(self), ret)] pub(super) fn eq_in_param_env(&self, a: T, b: T) -> bool where T: PartialEq + TypeFoldable> + ToTrace<'tcx>, @@ -330,13 +331,20 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // equate the two trait refs after normalization let a = ocx.normalize(&cause, self.param_env, a); let b = ocx.normalize(&cause, self.param_env, b); - if ocx.eq(&cause, self.param_env, a, b).is_ok() { - if ocx.select_all_or_error().is_empty() { - // All good. - return true; - } + + if let Err(terr) = ocx.eq(&cause, self.param_env, a, b) { + trace!(?terr); + return false; + } + + let errors = ocx.select_all_or_error(); + if !errors.is_empty() { + trace!(?errors); + return false; } - return false; + + // All good. + true } /// Walks up the callstack from the intrinsic's callsite, searching for the first callsite in a diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs index c973fcec0e19a..74225d646bd2d 100644 --- a/compiler/rustc_driver_impl/src/pretty.rs +++ b/compiler/rustc_driver_impl/src/pretty.rs @@ -222,10 +222,8 @@ impl<'tcx> PrintExtra<'tcx> { } pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) { - if ppm.needs_analysis() { - if ex.tcx().analysis(()).is_err() { - FatalError.raise(); - } + if ppm.needs_analysis() && ex.tcx().analysis(()).is_err() { + FatalError.raise(); } let (src, src_name) = get_source(sess); diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 6820a44f141bd..dbdad2eb41d84 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -186,17 +186,15 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId) { if let Ok(alloc) = tcx.eval_static_initializer(id.to_def_id()) && alloc.inner().provenance().ptrs().len() != 0 - { - if attrs + && attrs .link_section .map(|link_section| !link_section.as_str().starts_with(".init_array")) .unwrap() - { - let msg = "statics with a custom `#[link_section]` must be a \ + { + let msg = "statics with a custom `#[link_section]` must be a \ simple list of bytes on the wasm target with no \ extra levels of indirection such as references"; - tcx.dcx().span_err(tcx.def_span(id), msg); - } + tcx.dcx().span_err(tcx.def_span(id), msg); } } diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index db809e4837d66..f2a97d0677130 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -53,17 +53,15 @@ fn enforce_trait_manually_implementable( ) -> Result<(), ErrorGuaranteed> { let impl_header_span = tcx.def_span(impl_def_id); - if tcx.is_lang_item(trait_def_id, LangItem::Freeze) { - if !tcx.features().freeze_impls { - feature_err( - &tcx.sess, - sym::freeze_impls, - impl_header_span, - "explicit impls for the `Freeze` trait are not permitted", - ) - .with_span_label(impl_header_span, format!("impl of `Freeze` not allowed")) - .emit(); - } + if tcx.is_lang_item(trait_def_id, LangItem::Freeze) && !tcx.features().freeze_impls { + feature_err( + &tcx.sess, + sym::freeze_impls, + impl_header_span, + "explicit impls for the `Freeze` trait are not permitted", + ) + .with_span_label(impl_header_span, format!("impl of `Freeze` not allowed")) + .emit(); } // Disallow *all* explicit impls of traits marked `#[rustc_deny_explicit_impl]` diff --git a/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs index da89f5769d1fc..97402dd1109f3 100644 --- a/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs +++ b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs @@ -827,20 +827,18 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { if num_generic_args_supplied_to_trait + num_assoc_fn_excess_args == num_trait_generics_except_self + && let Some(span) = self.gen_args.span_ext() + && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { - if let Some(span) = self.gen_args.span_ext() - && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) - { - let sugg = vec![ - ( - self.path_segment.ident.span, - format!("{}::{}", snippet, self.path_segment.ident), - ), - (span.with_lo(self.path_segment.ident.span.hi()), "".to_owned()), - ]; + let sugg = vec![ + ( + self.path_segment.ident.span, + format!("{}::{}", snippet, self.path_segment.ident), + ), + (span.with_lo(self.path_segment.ident.span.hi()), "".to_owned()), + ]; - err.multipart_suggestion(msg, sugg, Applicability::MaybeIncorrect); - } + err.multipart_suggestion(msg, sugg, Applicability::MaybeIncorrect); } } } diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 1e1e007862e1c..36892aaf80c56 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -732,12 +732,11 @@ impl<'a, 'tcx> CastCheck<'tcx> { } _ => return Err(CastError::NonScalar), }; - if let ty::Adt(adt_def, _) = *self.expr_ty.kind() { - if adt_def.did().krate != LOCAL_CRATE { - if adt_def.variants().iter().any(VariantDef::is_field_list_non_exhaustive) { - return Err(CastError::ForeignNonExhaustiveAdt); - } - } + if let ty::Adt(adt_def, _) = *self.expr_ty.kind() + && adt_def.did().krate != LOCAL_CRATE + && adt_def.variants().iter().any(VariantDef::is_field_list_non_exhaustive) + { + return Err(CastError::ForeignNonExhaustiveAdt); } match (t_from, t_cast) { // These types have invariants! can't cast into them. diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 9bad5633b69dc..197f802960f80 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1780,16 +1780,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } // Make sure the programmer specified correct number of fields. - if adt_kind == AdtKind::Union { - if hir_fields.len() != 1 { - struct_span_code_err!( - self.dcx(), - span, - E0784, - "union expressions should have exactly one field", - ) - .emit(); - } + if adt_kind == AdtKind::Union && hir_fields.len() != 1 { + struct_span_code_err!( + self.dcx(), + span, + E0784, + "union expressions should have exactly one field", + ) + .emit(); } // If check_expr_struct_fields hit an error, do not attempt to populate diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 14ad5830111b4..6ec4a005bed9c 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1252,11 +1252,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && suggested_bounds.contains(parent) { // We don't suggest `PartialEq` when we already suggest `Eq`. - } else if !suggested_bounds.contains(pred) { - if collect_type_param_suggestions(self_ty, *pred, &p) { - suggested = true; - suggested_bounds.insert(pred); - } + } else if !suggested_bounds.contains(pred) + && collect_type_param_suggestions(self_ty, *pred, &p) + { + suggested = true; + suggested_bounds.insert(pred); } ( match parent_pred { @@ -1267,14 +1267,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if !suggested && !suggested_bounds.contains(pred) && !suggested_bounds.contains(parent_pred) - { - if collect_type_param_suggestions( + && collect_type_param_suggestions( self_ty, *parent_pred, &p, - ) { - suggested_bounds.insert(pred); - } + ) + { + suggested_bounds.insert(pred); } format!("`{p}`\nwhich is required by `{parent_p}`") } diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 7de92a43a9ab4..8b92180e9bd00 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -429,10 +429,8 @@ impl MissingDoc { // Only check publicly-visible items, using the result from the privacy pass. // It's an option so the crate root can also use this function (it doesn't // have a `NodeId`). - if def_id != CRATE_DEF_ID { - if !cx.effective_visibilities.is_exported(def_id) { - return; - } + if def_id != CRATE_DEF_ID && !cx.effective_visibilities.is_exported(def_id) { + return; } let attrs = cx.tcx.hir().attrs(cx.tcx.local_def_id_to_hir_id(def_id)); diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index 3b8861378e08e..86dca27f04f7e 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -444,10 +444,11 @@ impl<'tcx> TyCtxt<'tcx> { // the `-Z force-unstable-if-unmarked` flag present (we're // compiling a compiler crate), then let this missing feature // annotation slide. - if feature == sym::rustc_private && issue == NonZero::new(27812) { - if self.sess.opts.unstable_opts.force_unstable_if_unmarked { - return EvalResult::Allow; - } + if feature == sym::rustc_private + && issue == NonZero::new(27812) + && self.sess.opts.unstable_opts.force_unstable_if_unmarked + { + return EvalResult::Allow; } if matches!(allow_unstable, AllowUnstable::Yes) { diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index cd56d0edc0585..f5fef2491678b 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -448,22 +448,20 @@ impl Allocation bad: uninit_range, })) })?; - if !Prov::OFFSET_IS_ADDR { - if !self.provenance.range_empty(range, cx) { - // Find the provenance. - let (offset, _prov) = self - .provenance - .range_get_ptrs(range, cx) - .first() - .copied() - .expect("there must be provenance somewhere here"); - let start = offset.max(range.start); // the pointer might begin before `range`! - let end = (offset + cx.pointer_size()).min(range.end()); // the pointer might end after `range`! - return Err(AllocError::ReadPointerAsInt(Some(BadBytesAccess { - access: range, - bad: AllocRange::from(start..end), - }))); - } + if !Prov::OFFSET_IS_ADDR && !self.provenance.range_empty(range, cx) { + // Find the provenance. + let (offset, _prov) = self + .provenance + .range_get_ptrs(range, cx) + .first() + .copied() + .expect("there must be provenance somewhere here"); + let start = offset.max(range.start); // the pointer might begin before `range`! + let end = (offset + cx.pointer_size()).min(range.end()); // the pointer might end after `range`! + return Err(AllocError::ReadPointerAsInt(Some(BadBytesAccess { + access: range, + bad: AllocRange::from(start..end), + }))); } Ok(self.get_bytes_unchecked(range)) } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 56fcfe8e798b1..75d5c8d1711fd 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2606,33 +2606,31 @@ impl<'tcx> TyCtxt<'tcx> { /// With `cfg(debug_assertions)`, assert that args are compatible with their generics, /// and print out the args if not. pub fn debug_assert_args_compatible(self, def_id: DefId, args: &'tcx [ty::GenericArg<'tcx>]) { - if cfg!(debug_assertions) { - if !self.check_args_compatible(def_id, args) { - if let DefKind::AssocTy = self.def_kind(def_id) - && let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(def_id)) - { - bug!( - "args not compatible with generics for {}: args={:#?}, generics={:#?}", - self.def_path_str(def_id), - args, - // Make `[Self, GAT_ARGS...]` (this could be simplified) - self.mk_args_from_iter( - [self.types.self_param.into()].into_iter().chain( - self.generics_of(def_id) - .own_args(ty::GenericArgs::identity_for_item(self, def_id)) - .iter() - .copied() - ) + if cfg!(debug_assertions) && !self.check_args_compatible(def_id, args) { + if let DefKind::AssocTy = self.def_kind(def_id) + && let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(def_id)) + { + bug!( + "args not compatible with generics for {}: args={:#?}, generics={:#?}", + self.def_path_str(def_id), + args, + // Make `[Self, GAT_ARGS...]` (this could be simplified) + self.mk_args_from_iter( + [self.types.self_param.into()].into_iter().chain( + self.generics_of(def_id) + .own_args(ty::GenericArgs::identity_for_item(self, def_id)) + .iter() + .copied() ) - ); - } else { - bug!( - "args not compatible with generics for {}: args={:#?}, generics={:#?}", - self.def_path_str(def_id), - args, - ty::GenericArgs::identity_for_item(self, def_id) - ); - } + ) + ); + } else { + bug!( + "args not compatible with generics for {}: args={:#?}, generics={:#?}", + self.def_path_str(def_id), + args, + ty::GenericArgs::identity_for_item(self, def_id) + ); } } } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 8cec8eac1898a..254a0119920c3 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -1183,10 +1183,10 @@ pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option, abi: SpecAbi) -> // // This is not part of `codegen_fn_attrs` as it can differ between crates // and therefore cannot be computed in core. - if tcx.sess.opts.unstable_opts.panic_in_drop == PanicStrategy::Abort { - if tcx.is_lang_item(did, LangItem::DropInPlace) { - return false; - } + if tcx.sess.opts.unstable_opts.panic_in_drop == PanicStrategy::Abort + && tcx.is_lang_item(did, LangItem::DropInPlace) + { + return false; } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index f1ff90831b04f..7f783f75f3a9d 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -3361,10 +3361,8 @@ pub fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> DefIdMap { // name. // // Any stable ordering would be fine here though. - if *v.get() != symbol { - if v.get().as_str() > symbol.as_str() { - v.insert(symbol); - } + if *v.get() != symbol && v.get().as_str() > symbol.as_str() { + v.insert(symbol); } } Vacant(v) => { diff --git a/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs b/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs index 3aa6e708476d5..6019a93e7876a 100644 --- a/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs +++ b/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs @@ -268,10 +268,9 @@ impl Builder<'_, '_> { pub(crate) fn mcdc_decrement_depth_if_enabled(&mut self) { if let Some(coverage_info) = self.coverage_info.as_mut() && let Some(mcdc_info) = coverage_info.mcdc_info.as_mut() + && mcdc_info.state.decision_ctx_stack.pop().is_none() { - if mcdc_info.state.decision_ctx_stack.pop().is_none() { - bug!("Unexpected empty decision stack"); - } + bug!("Unexpected empty decision stack"); }; } } diff --git a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs index 048dd9ccb8f3c..9c3cbbe1fc963 100644 --- a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs +++ b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs @@ -95,19 +95,19 @@ impl<'tcx> Visitor<'tcx> for ConstMutationChecker<'_, 'tcx> { // Check for assignment to fields of a constant // Assigning directly to a constant (e.g. `FOO = true;`) is a hard error, // so emitting a lint would be redundant. - if !lhs.projection.is_empty() { - if let Some(def_id) = self.is_const_item_without_destructor(lhs.local) - && let Some((lint_root, span, item)) = - self.should_lint_const_item_usage(lhs, def_id, loc) - { - self.tcx.emit_node_span_lint( - CONST_ITEM_MUTATION, - lint_root, - span, - errors::ConstMutate::Modify { konst: item }, - ); - } + if !lhs.projection.is_empty() + && let Some(def_id) = self.is_const_item_without_destructor(lhs.local) + && let Some((lint_root, span, item)) = + self.should_lint_const_item_usage(lhs, def_id, loc) + { + self.tcx.emit_node_span_lint( + CONST_ITEM_MUTATION, + lint_root, + span, + errors::ConstMutate::Modify { konst: item }, + ); } + // We are looking for MIR of the form: // // ``` diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs index c645bbee08a54..c0cb0e641ac1b 100644 --- a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs +++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs @@ -168,17 +168,16 @@ pub(super) fn deduced_param_attrs<'tcx>( // Codegen won't use this information for anything if all the function parameters are passed // directly. Detect that and bail, for compilation speed. let fn_ty = tcx.type_of(def_id).instantiate_identity(); - if matches!(fn_ty.kind(), ty::FnDef(..)) { - if fn_ty + if matches!(fn_ty.kind(), ty::FnDef(..)) + && fn_ty .fn_sig(tcx) .inputs() .skip_binder() .iter() .cloned() .all(type_will_always_be_passed_directly) - { - return &[]; - } + { + return &[]; } // Don't deduce any attributes for functions that have no MIR. diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs index 46b17c3c7e04d..f123f39bf4244 100644 --- a/compiler/rustc_mir_transform/src/known_panics_lint.rs +++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs @@ -378,19 +378,19 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { if let (Some(l), Some(r)) = (l, r) && l.layout.ty.is_integral() && op.is_overflowing() - { - if self.use_ecx(|this| { + && self.use_ecx(|this| { let (_res, overflow) = this.ecx.binary_op(op, &l, &r)?.to_scalar_pair(); overflow.to_bool() - })? { - self.report_assert_as_lint( - location, - AssertLintKind::ArithmeticOverflow, - AssertKind::Overflow(op, l.to_const_int(), r.to_const_int()), - ); - return None; - } + })? + { + self.report_assert_as_lint( + location, + AssertLintKind::ArithmeticOverflow, + AssertKind::Overflow(op, l.to_const_int(), r.to_const_int()), + ); + return None; } + Some(()) } diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index 0d295b8f280f5..2d9dbdbaec23f 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -504,10 +504,8 @@ fn compute_inlined_overlap<'tcx>(cgu1: &CodegenUnit<'tcx>, cgu2: &CodegenUnit<'t let mut overlap = 0; for (item, data) in src_cgu.items().iter() { - if data.inlined { - if dst_cgu.items().contains_key(item) { - overlap += data.size_estimate; - } + if data.inlined && dst_cgu.items().contains_key(item) { + overlap += data.size_estimate; } } overlap diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs index 394518daa4250..196ddeb244302 100644 --- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs @@ -185,10 +185,8 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { for var in var_infos.iter_mut() { // We simply put all regions from the input into the highest // compressed universe, so we only deal with them at the end. - if !var.is_region() { - if is_existential == var.is_existential() { - update_uv(var, orig_uv, is_existential) - } + if !var.is_region() && is_existential == var.is_existential() { + update_uv(var, orig_uv, is_existential) } } } diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 8ee40ecd77e3f..42039c621d63c 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -671,12 +671,12 @@ impl<'a> Parser<'a> { err.emit(); continue; } - if !self.token.kind.should_end_const_arg() { - if self.handle_ambiguous_unbraced_const_arg(&mut args)? { - // We've managed to (partially) recover, so continue trying to parse - // arguments. - continue; - } + if !self.token.kind.should_end_const_arg() + && self.handle_ambiguous_unbraced_const_arg(&mut args)? + { + // We've managed to (partially) recover, so continue trying to parse + // arguments. + continue; } break; } diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index ba4c300ea61af..e2c9067c0b966 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -174,16 +174,14 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { // If the current node is a function, has const stability attributes and if it doesn not have an intrinsic ABI, // check if the function/method is const or the parent impl block is const - if let (Some(const_span), Some(fn_sig)) = (const_span, fn_sig) { - if fn_sig.header.abi != Abi::RustIntrinsic && !fn_sig.header.is_const() { - if !self.in_trait_impl - || (self.in_trait_impl && !self.tcx.is_const_fn_raw(def_id.to_def_id())) - { - self.tcx - .dcx() - .emit_err(errors::MissingConstErr { fn_sig_span: fn_sig.span, const_span }); - } - } + if let (Some(const_span), Some(fn_sig)) = (const_span, fn_sig) + && fn_sig.header.abi != Abi::RustIntrinsic + && !fn_sig.header.is_const() + && (!self.in_trait_impl || !self.tcx.is_const_fn_raw(def_id.to_def_id())) + { + self.tcx + .dcx() + .emit_err(errors::MissingConstErr { fn_sig_span: fn_sig.span, const_span }); } // `impl const Trait for Type` items forward their const stability to their diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index bcbdf627b5662..b32eb5854ca10 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1233,64 +1233,63 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { && ns == namespace && in_module != parent_scope.module && !ident.span.normalize_to_macros_2_0().from_expansion() + && filter_fn(res) { - if filter_fn(res) { - // create the path - let mut segms = if lookup_ident.span.at_least_rust_2018() { - // crate-local absolute paths start with `crate::` in edition 2018 - // FIXME: may also be stabilized for Rust 2015 (Issues #45477, #44660) - crate_path.clone() - } else { - ThinVec::new() - }; - segms.append(&mut path_segments.clone()); + // create the path + let mut segms = if lookup_ident.span.at_least_rust_2018() { + // crate-local absolute paths start with `crate::` in edition 2018 + // FIXME: may also be stabilized for Rust 2015 (Issues #45477, #44660) + crate_path.clone() + } else { + ThinVec::new() + }; + segms.append(&mut path_segments.clone()); - segms.push(ast::PathSegment::from_ident(ident)); - let path = Path { span: name_binding.span, segments: segms, tokens: None }; + segms.push(ast::PathSegment::from_ident(ident)); + let path = Path { span: name_binding.span, segments: segms, tokens: None }; - if child_accessible { - // Remove invisible match if exists - if let Some(idx) = candidates - .iter() - .position(|v: &ImportSuggestion| v.did == did && !v.accessible) - { - candidates.remove(idx); - } + if child_accessible { + // Remove invisible match if exists + if let Some(idx) = candidates + .iter() + .position(|v: &ImportSuggestion| v.did == did && !v.accessible) + { + candidates.remove(idx); } + } - if candidates.iter().all(|v: &ImportSuggestion| v.did != did) { - // See if we're recommending TryFrom, TryInto, or FromIterator and add - // a note about editions - let note = if let Some(did) = did { - let requires_note = !did.is_local() - && this.tcx.get_attrs(did, sym::rustc_diagnostic_item).any( - |attr| { - [sym::TryInto, sym::TryFrom, sym::FromIterator] - .map(|x| Some(x)) - .contains(&attr.value_str()) - }, - ); - - requires_note.then(|| { - format!( - "'{}' is included in the prelude starting in Edition 2021", - path_names_to_string(&path) - ) - }) - } else { - None - }; - - candidates.push(ImportSuggestion { - did, - descr: res.descr(), - path, - accessible: child_accessible, - doc_visible: child_doc_visible, - note, - via_import, - }); - } + if candidates.iter().all(|v: &ImportSuggestion| v.did != did) { + // See if we're recommending TryFrom, TryInto, or FromIterator and add + // a note about editions + let note = if let Some(did) = did { + let requires_note = !did.is_local() + && this.tcx.get_attrs(did, sym::rustc_diagnostic_item).any( + |attr| { + [sym::TryInto, sym::TryFrom, sym::FromIterator] + .map(|x| Some(x)) + .contains(&attr.value_str()) + }, + ); + + requires_note.then(|| { + format!( + "'{}' is included in the prelude starting in Edition 2021", + path_names_to_string(&path) + ) + }) + } else { + None + }; + + candidates.push(ImportSuggestion { + did, + descr: res.descr(), + path, + accessible: child_accessible, + doc_visible: child_doc_visible, + note, + via_import, + }); } } diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 87f8e51f28231..7f2bf03bcd162 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -958,12 +958,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }); } - if !restricted_shadowing && binding.expansion != LocalExpnId::ROOT { - if let NameBindingKind::Import { import, .. } = binding.kind - && matches!(import.kind, ImportKind::MacroExport) - { - self.macro_expanded_macro_export_errors.insert((path_span, binding.span)); - } + if !restricted_shadowing + && binding.expansion != LocalExpnId::ROOT + && let NameBindingKind::Import { import, .. } = binding.kind + && matches!(import.kind, ImportKind::MacroExport) + { + self.macro_expanded_macro_export_errors.insert((path_span, binding.span)); } self.record_use(ident, binding, used); diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 917cb81aa511f..3d0771390ed5a 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -4781,16 +4781,14 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { if let Some(res) = res && let Some(def_id) = res.opt_def_id() && !def_id.is_local() + && self.r.tcx.crate_types().contains(&CrateType::ProcMacro) + && matches!( + self.r.tcx.sess.opts.resolve_doc_links, + ResolveDocLinks::ExportedMetadata + ) { - if self.r.tcx.crate_types().contains(&CrateType::ProcMacro) - && matches!( - self.r.tcx.sess.opts.resolve_doc_links, - ResolveDocLinks::ExportedMetadata - ) - { - // Encoding foreign def ids in proc macro crate metadata will ICE. - return None; - } + // Encoding foreign def ids in proc macro crate metadata will ICE. + return None; } res }); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 8f516c2db0900..51102d59bfe3a 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -2255,25 +2255,24 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { fn let_binding_suggestion(&mut self, err: &mut Diag<'_>, ident_span: Span) -> bool { if let Some(Expr { kind: ExprKind::Assign(lhs, ..), .. }) = self.diag_metadata.in_assignment && let ast::ExprKind::Path(None, ref path) = lhs.kind + && !ident_span.from_expansion() { - if !ident_span.from_expansion() { - let (span, text) = match path.segments.first() { - Some(seg) if let Some(name) = seg.ident.as_str().strip_prefix("let") => { - // a special case for #117894 - let name = name.strip_prefix('_').unwrap_or(name); - (ident_span, format!("let {name}")) - } - _ => (ident_span.shrink_to_lo(), "let ".to_string()), - }; + let (span, text) = match path.segments.first() { + Some(seg) if let Some(name) = seg.ident.as_str().strip_prefix("let") => { + // a special case for #117894 + let name = name.strip_prefix('_').unwrap_or(name); + (ident_span, format!("let {name}")) + } + _ => (ident_span.shrink_to_lo(), "let ".to_string()), + }; - err.span_suggestion_verbose( - span, - "you might have meant to introduce a new binding", - text, - Applicability::MaybeIncorrect, - ); - return true; - } + err.span_suggestion_verbose( + span, + "you might have meant to introduce a new binding", + text, + Applicability::MaybeIncorrect, + ); + return true; } false } diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 77efc2fc2dbfd..66dfa283d0763 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -513,10 +513,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // then there's nothing else to check. if let Some(closure_kind) = self_ty.to_opt_closure_kind() && let Some(goal_kind) = target_kind_ty.to_opt_closure_kind() + && closure_kind.extends(goal_kind) { - if closure_kind.extends(goal_kind) { - candidates.vec.push(AsyncFnKindHelperCandidate); - } + candidates.vec.push(AsyncFnKindHelperCandidate); } } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 241c3a3d14122..f5cd7273ca240 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1334,16 +1334,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return; } - if self.can_use_global_caches(param_env) { - if !trait_pred.has_infer() { - debug!(?trait_pred, ?result, "insert_evaluation_cache global"); - // This may overwrite the cache with the same value - // FIXME: Due to #50507 this overwrites the different values - // This should be changed to use HashMapExt::insert_same - // when that is fixed - self.tcx().evaluation_cache.insert((param_env, trait_pred), dep_node, result); - return; - } + if self.can_use_global_caches(param_env) && !trait_pred.has_infer() { + debug!(?trait_pred, ?result, "insert_evaluation_cache global"); + // This may overwrite the cache with the same value + // FIXME: Due to #50507 this overwrites the different values + // This should be changed to use HashMapExt::insert_same + // when that is fixed + self.tcx().evaluation_cache.insert((param_env, trait_pred), dep_node, result); + return; } debug!(?trait_pred, ?result, "insert_evaluation_cache"); @@ -1584,13 +1582,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if self.can_use_global_caches(param_env) { if let Err(Overflow(OverflowError::Canonical)) = candidate { // Don't cache overflow globally; we only produce this in certain modes. - } else if !pred.has_infer() { - if !candidate.has_infer() { - debug!(?pred, ?candidate, "insert_candidate_cache global"); - // This may overwrite the cache with the same value. - tcx.selection_cache.insert((param_env, pred), dep_node, candidate); - return; - } + } else if !pred.has_infer() && !candidate.has_infer() { + debug!(?pred, ?candidate, "insert_candidate_cache global"); + // This may overwrite the cache with the same value. + tcx.selection_cache.insert((param_env, pred), dep_node, candidate); + return; } } @@ -1980,10 +1976,10 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // impls have to be always applicable, meaning that the only allowed // region constraints may be constraints also present on the default impl. let tcx = self.tcx(); - if other.evaluation.must_apply_modulo_regions() { - if tcx.specializes((other_def, victim_def)) { - return DropVictim::Yes; - } + if other.evaluation.must_apply_modulo_regions() + && tcx.specializes((other_def, victim_def)) + { + return DropVictim::Yes; } match tcx.impls_are_allowed_to_overlap(other_def, victim_def) { diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index e899284674c8c..6b24929467be2 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -143,10 +143,8 @@ impl<'tcx> OpaqueTypeCollector<'tcx> { match origin { rustc_hir::OpaqueTyOrigin::FnReturn(_) | rustc_hir::OpaqueTyOrigin::AsyncFn(_) => {} rustc_hir::OpaqueTyOrigin::TyAlias { in_assoc_ty, .. } => { - if !in_assoc_ty { - if !self.check_tait_defining_scope(alias_ty.def_id.expect_local()) { - return; - } + if !in_assoc_ty && !self.check_tait_defining_scope(alias_ty.def_id.expect_local()) { + return; } } } From 3842ea671bfb98b2a7a42edbd31c5bac89078024 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 11 Sep 2024 16:39:07 +0200 Subject: [PATCH 168/189] miri: fix overflow detection for unsigned pointer offset --- .../rustc_const_eval/src/interpret/operator.rs | 9 ++++++++- .../intrinsics/ptr_offset_unsigned_overflow.rs | 7 +++++++ .../ptr_offset_unsigned_overflow.stderr | 15 +++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 src/tools/miri/tests/fail/intrinsics/ptr_offset_unsigned_overflow.rs create mode 100644 src/tools/miri/tests/fail/intrinsics/ptr_offset_unsigned_overflow.stderr diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index e9ba12dbcc4ea..b390bb8778915 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -303,8 +303,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let pointee_layout = self.layout_of(pointee_ty)?; assert!(pointee_layout.abi.is_sized()); - // We cannot overflow i64 as a type's size must be <= isize::MAX. + // The size always fits in `i64` as it can be at most `isize::MAX`. let pointee_size = i64::try_from(pointee_layout.size.bytes()).unwrap(); + // This uses the same type as `right`, which can be `isize` or `usize`. + // `pointee_size` is guaranteed to fit into both types. let pointee_size = ImmTy::from_int(pointee_size, right.layout); // Multiply element size and element count. let (val, overflowed) = self @@ -316,6 +318,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } let offset_bytes = val.to_target_isize(self)?; + if !right.layout.abi.is_signed() && offset_bytes < 0 { + // We were supposed to do an unsigned offset but the result is negative -- this + // can only mean that the cast wrapped around. + throw_ub!(PointerArithOverflow) + } let offset_ptr = self.ptr_offset_inbounds(ptr, offset_bytes)?; Ok(ImmTy::from_scalar(Scalar::from_maybe_pointer(offset_ptr, self), left.layout)) } diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_unsigned_overflow.rs b/src/tools/miri/tests/fail/intrinsics/ptr_offset_unsigned_overflow.rs new file mode 100644 index 0000000000000..a2739842bc135 --- /dev/null +++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_unsigned_overflow.rs @@ -0,0 +1,7 @@ +fn main() { + let x = &[0i32; 2]; + let x = x.as_ptr().wrapping_add(1); + // If the `!0` is interpreted as `isize`, it is just `-1` and hence harmless. + // However, this is unsigned arithmetic, so really this is `usize::MAX` and hence UB. + unsafe { x.byte_add(!0).read() }; //~ERROR: does not fit in an `isize` +} diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_unsigned_overflow.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_offset_unsigned_overflow.stderr new file mode 100644 index 0000000000000..43cd80a6d3e27 --- /dev/null +++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_unsigned_overflow.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: overflowing pointer arithmetic: the total offset in bytes does not fit in an `isize` + --> $DIR/ptr_offset_unsigned_overflow.rs:LL:CC + | +LL | unsafe { x.byte_add(!0).read() }; + | ^^^^^^^^^^^^^^ overflowing pointer arithmetic: the total offset in bytes does not fit in an `isize` + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/ptr_offset_unsigned_overflow.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + From 5527076d84ae874d726f3bf03f83bd1db2cfb199 Mon Sep 17 00:00:00 2001 From: Julius Liu Date: Wed, 11 Sep 2024 12:00:03 -0700 Subject: [PATCH 169/189] chore: remove struct details --- library/std/src/os/windows/fs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/os/windows/fs.rs b/library/std/src/os/windows/fs.rs index c3b91967953ff..9ea33e31f2c58 100644 --- a/library/std/src/os/windows/fs.rs +++ b/library/std/src/os/windows/fs.rs @@ -424,7 +424,7 @@ pub trait MetadataExt { #[stable(feature = "metadata_ext", since = "1.1.0")] fn last_write_time(&self) -> u64; - /// Returns the value of the `nFileSize{High,Low}` fields of this + /// Returns the value of the `nFileSize` fields of this /// metadata. /// /// The returned value does not have meaning for directories. @@ -463,7 +463,7 @@ pub trait MetadataExt { #[unstable(feature = "windows_by_handle", issue = "63010")] fn number_of_links(&self) -> Option; - /// Returns the value of the `nFileIndex{Low,High}` fields of this + /// Returns the value of the `nFileIndex` fields of this /// metadata. /// /// This will return `None` if the `Metadata` instance was created from a From 6ee87ae5944e02342e3d600700b773a1d4303845 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Wed, 11 Sep 2024 20:43:50 +0200 Subject: [PATCH 170/189] Use the same span for attributes and Try expansion of ? This is needed for Clippy to know that the `#[allow(unused)]` attributes added by the expansion of `?` are part of the desugaring, and that they do not come from the user code. rust-lang/rust-clippy#13380 exhibits a manifestation of this problem. --- compiler/rustc_ast_lowering/src/expr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index a6c7714a182bf..b887908f90461 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -1837,7 +1837,7 @@ impl<'hir> LoweringContext<'_, 'hir> { Safety::Default, sym::allow, sym::unreachable_code, - self.lower_span(span), + try_span, ); let attrs: AttrVec = thin_vec![attr]; From 496709356c1edccbdb65c9771b772499dffeb5a4 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sat, 7 Sep 2024 13:34:52 +0300 Subject: [PATCH 171/189] unify `llvm-bitcode-linker`, `wasm-component-ld` and llvm-tools logics Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/compile.rs | 64 ++++------- src/bootstrap/src/core/build_steps/dist.rs | 107 +++++++++++++++++- 2 files changed, 121 insertions(+), 50 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 102c9fd255432..b5e7a2c240dc6 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -29,7 +29,7 @@ use crate::utils::helpers::{ self, exe, get_clang_cl_resource_dir, get_closest_merge_base_commit, is_debug_info, is_dylib, symlink_dir, t, up_to_date, }; -use crate::{CLang, Compiler, DependencyType, GitRepo, Mode, LLVM_TOOLS}; +use crate::{CLang, Compiler, DependencyType, GitRepo, Mode}; #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Std { @@ -1912,52 +1912,26 @@ impl Step for Assemble { // delegates to the `rust-lld` binary for linking and then runs // logic to create the final binary. This is used by the // `wasm32-wasip2` target of Rust. - if builder.tool_enabled("wasm-component-ld") { - let wasm_component_ld_exe = - builder.ensure(crate::core::build_steps::tool::WasmComponentLd { - compiler: build_compiler, - target: target_compiler.host, - }); - builder.copy_link( - &wasm_component_ld_exe, - &libdir_bin.join(wasm_component_ld_exe.file_name().unwrap()), - ); - } + dist::maybe_install_wasm_component_ld( + builder, + build_compiler, + target_compiler.host, + &libdir_bin, + false, + ); - if builder.config.llvm_enabled(target_compiler.host) { - let llvm::LlvmResult { llvm_config, .. } = - builder.ensure(llvm::Llvm { target: target_compiler.host }); - if !builder.config.dry_run() && builder.config.llvm_tools_enabled { - let llvm_bin_dir = - command(llvm_config).arg("--bindir").run_capture_stdout(builder).stdout(); - let llvm_bin_dir = Path::new(llvm_bin_dir.trim()); - - // Since we've already built the LLVM tools, install them to the sysroot. - // This is the equivalent of installing the `llvm-tools-preview` component via - // rustup, and lets developers use a locally built toolchain to - // build projects that expect llvm tools to be present in the sysroot - // (e.g. the `bootimage` crate). - for tool in LLVM_TOOLS { - let tool_exe = exe(tool, target_compiler.host); - let src_path = llvm_bin_dir.join(&tool_exe); - // When using `download-ci-llvm`, some of the tools - // may not exist, so skip trying to copy them. - if src_path.exists() { - builder.copy_link(&src_path, &libdir_bin.join(&tool_exe)); - } - } - } - } + dist::maybe_install_llvm_tools(builder, target_compiler.host, &libdir_bin, false); - if builder.config.llvm_bitcode_linker_enabled { - let src_path = builder.ensure(crate::core::build_steps::tool::LlvmBitcodeLinker { - compiler: build_compiler, - target: target_compiler.host, - extra_features: vec![], - }); - let tool_exe = exe("llvm-bitcode-linker", target_compiler.host); - builder.copy_link(&src_path, &libdir_bin.join(tool_exe)); - } + let self_contained_bin_dir = libdir_bin.join("self-contained"); + t!(fs::create_dir_all(&self_contained_bin_dir)); + + dist::maybe_install_llvm_bitcode_linker( + builder, + build_compiler, + target_compiler.host, + &self_contained_bin_dir, + false, + ); // Ensure that `libLLVM.so` ends up in the newly build compiler directory, // so that it can be found when the newly built `rustc` is run. diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index ccb5656d6716c..4b014fa362b86 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -473,11 +473,29 @@ impl Step for Rustc { ); } } - if builder.tool_enabled("wasm-component-ld") { - let src_dir = builder.sysroot_libdir(compiler, host).parent().unwrap().join("bin"); - let ld = exe("wasm-component-ld", compiler.host); - builder.copy_link(&src_dir.join(&ld), &dst_dir.join(&ld)); - } + + let builder_compiler = + builder.compiler_for(builder.top_stage, builder.config.build, compiler.host); + + maybe_install_wasm_component_ld( + builder, + builder_compiler, + compiler.host, + &dst_dir, + true, + ); + + let self_contained_bin_dir = dst_dir.join("self-contained"); + t!(fs::create_dir_all(&self_contained_bin_dir)); + maybe_install_llvm_bitcode_linker( + builder, + builder_compiler, + compiler.host, + &self_contained_bin_dir, + true, + ); + + maybe_install_llvm_tools(builder, compiler.host, &dst_dir, true); // Man pages t!(fs::create_dir_all(image.join("share/man/man1"))); @@ -2095,6 +2113,85 @@ pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: TargetSelection } } +/// Maybe add LLVM tools to the rustc sysroot. +pub fn maybe_install_llvm_tools( + builder: &Builder<'_>, + target: TargetSelection, + dst_dir: &Path, + dereference_symlinks: bool, +) { + if builder.config.llvm_enabled(target) { + let llvm::LlvmResult { llvm_config, .. } = builder.ensure(llvm::Llvm { target }); + if !builder.config.dry_run() && builder.config.llvm_tools_enabled { + let llvm_bin_dir = + command(llvm_config).arg("--bindir").run_capture_stdout(builder).stdout(); + let llvm_bin_dir = Path::new(llvm_bin_dir.trim()); + + // Since we've already built the LLVM tools, install them to the sysroot. + // This is the equivalent of installing the `llvm-tools-preview` component via + // rustup, and lets developers use a locally built toolchain to + // build projects that expect llvm tools to be present in the sysroot + // (e.g. the `bootimage` crate). + for tool in LLVM_TOOLS { + let tool_exe = exe(tool, target); + let src_path = llvm_bin_dir.join(&tool_exe); + // When using `download-ci-llvm`, some of the tools + // may not exist, so skip trying to copy them. + if src_path.exists() { + builder.copy_link_internal( + &src_path, + &dst_dir.join(&tool_exe), + dereference_symlinks, + ); + } + } + } + } +} + +/// Maybe add `llvm-bitcode-linker` to the rustc sysroot. +pub fn maybe_install_llvm_bitcode_linker( + builder: &Builder<'_>, + builder_compiler: Compiler, + target: TargetSelection, + dst_dir: &Path, + dereference_symlinks: bool, +) { + if builder.config.llvm_bitcode_linker_enabled { + let llvm_bitcode_linker_exe = builder.ensure(tool::LlvmBitcodeLinker { + compiler: builder_compiler, + target, + extra_features: vec![], + }); + + builder.copy_link_internal( + &llvm_bitcode_linker_exe, + &dst_dir.join(llvm_bitcode_linker_exe.file_name().unwrap()), + dereference_symlinks, + ); + } +} + +/// Maybe add `wasm-component-ld` to the rustc sysroot. +pub fn maybe_install_wasm_component_ld( + builder: &Builder<'_>, + builder_compiler: Compiler, + target: TargetSelection, + dst_dir: &Path, + dereference_symlinks: bool, +) { + if builder.tool_enabled("wasm-component-ld") { + let wasm_component_ld_exe = + builder.ensure(tool::WasmComponentLd { compiler: builder_compiler, target }); + + builder.copy_link_internal( + &wasm_component_ld_exe, + &dst_dir.join(wasm_component_ld_exe.file_name().unwrap()), + dereference_symlinks, + ); + } +} + #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct LlvmTools { pub target: TargetSelection, From af8d911d63d6b38ea2da36a330b035dd2e6f89a7 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 11 Sep 2024 17:23:56 -0400 Subject: [PATCH 172/189] Also fix if in else --- compiler/rustc_ast/src/entry.rs | 20 +++--- compiler/rustc_ast_lowering/src/item.rs | 10 ++- .../rustc_borrowck/src/region_infer/values.rs | 12 ++-- compiler/rustc_builtin_macros/src/asm.rs | 10 ++- compiler/rustc_codegen_ssa/src/back/link.rs | 28 +++------ compiler/rustc_codegen_ssa/src/back/linker.rs | 12 ++-- .../src/debuginfo/type_names.rs | 14 ++--- .../rustc_hir_analysis/src/check/check.rs | 62 +++++++++---------- .../src/collect/type_of/opaque.rs | 30 +++++---- .../src/hir_ty_lowering/mod.rs | 10 ++- compiler/rustc_hir_typeck/src/expr.rs | 29 +++++---- .../rustc_hir_typeck/src/gather_locals.rs | 14 ++--- .../src/persist/dirty_clean.rs | 8 +-- compiler/rustc_middle/src/mir/pretty.rs | 8 +-- compiler/rustc_parse/src/parser/expr.rs | 12 ++-- compiler/rustc_parse/src/parser/mod.rs | 10 ++- compiler/rustc_parse/src/parser/pat.rs | 28 ++++----- compiler/rustc_parse/src/validate_attr.rs | 12 ++-- compiler/rustc_passes/src/check_attr.rs | 18 +++--- compiler/rustc_passes/src/liveness.rs | 16 +++-- compiler/rustc_resolve/src/imports.rs | 36 +++++------ compiler/rustc_resolve/src/rustdoc.rs | 8 +-- .../src/cfi/typeid/itanium_cxx_abi/encode.rs | 12 ++-- compiler/rustc_target/src/abi/call/xtensa.rs | 40 ++++++------ .../src/error_reporting/infer/mod.rs | 28 ++++----- .../src/error_reporting/traits/suggestions.rs | 15 ++--- .../src/traits/select/candidate_assembly.rs | 10 ++- 27 files changed, 222 insertions(+), 290 deletions(-) diff --git a/compiler/rustc_ast/src/entry.rs b/compiler/rustc_ast/src/entry.rs index 60a12614f06e8..53276e0847a74 100644 --- a/compiler/rustc_ast/src/entry.rs +++ b/compiler/rustc_ast/src/entry.rs @@ -45,18 +45,16 @@ pub fn entry_point_type( EntryPointType::Start } else if attr::contains_name(attrs, sym::rustc_main) { EntryPointType::RustcMainAttr - } else { - if let Some(name) = name - && name == sym::main - { - if at_root { - // This is a top-level function so it can be `main`. - EntryPointType::MainNamed - } else { - EntryPointType::OtherMain - } + } else if let Some(name) = name + && name == sym::main + { + if at_root { + // This is a top-level function so it can be `main`. + EntryPointType::MainNamed } else { - EntryPointType::None + EntryPointType::OtherMain } + } else { + EntryPointType::None } } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index c8ec8f308a8aa..73c604bf28a40 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -628,13 +628,11 @@ impl<'hir> LoweringContext<'_, 'hir> { .map_or(Const::No, |attr| Const::Yes(attr.span)), _ => Const::No, } + } else if self.tcx.is_const_trait(def_id) { + // FIXME(effects) span + Const::Yes(self.tcx.def_ident_span(def_id).unwrap()) } else { - if self.tcx.is_const_trait(def_id) { - // FIXME(effects) span - Const::Yes(self.tcx.def_ident_span(def_id).unwrap()) - } else { - Const::No - } + Const::No } } else { Const::No diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs index d62f2067729df..30dc062ae7cea 100644 --- a/compiler/rustc_borrowck/src/region_infer/values.rs +++ b/compiler/rustc_borrowck/src/region_infer/values.rs @@ -118,10 +118,8 @@ impl LivenessValues { debug!("LivenessValues::add_location(region={:?}, location={:?})", region, location); if let Some(points) = &mut self.points { points.insert(region, point); - } else { - if self.elements.point_in_range(point) { - self.live_regions.as_mut().unwrap().insert(region); - } + } else if self.elements.point_in_range(point) { + self.live_regions.as_mut().unwrap().insert(region); } // When available, record the loans flowing into this region as live at the given point. @@ -137,10 +135,8 @@ impl LivenessValues { debug!("LivenessValues::add_points(region={:?}, points={:?})", region, points); if let Some(this) = &mut self.points { this.union_row(region, points); - } else { - if points.iter().any(|point| self.elements.point_in_range(point)) { - self.live_regions.as_mut().unwrap().insert(region); - } + } else if points.iter().any(|point| self.elements.point_in_range(point)) { + self.live_regions.as_mut().unwrap().insert(region); } // When available, record the loans flowing into this region as live at the given points. diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index e313016e3d863..974f9d246bff4 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -234,13 +234,11 @@ pub fn parse_asm_args<'a>( continue; } args.named_args.insert(name, slot); - } else { - if !args.named_args.is_empty() || !args.reg_args.is_empty() { - let named = args.named_args.values().map(|p| args.operands[*p].1).collect(); - let explicit = args.reg_args.iter().map(|p| args.operands[p].1).collect(); + } else if !args.named_args.is_empty() || !args.reg_args.is_empty() { + let named = args.named_args.values().map(|p| args.operands[*p].1).collect(); + let explicit = args.reg_args.iter().map(|p| args.operands[p].1).collect(); - dcx.emit_err(errors::AsmPositionalAfter { span, named, explicit }); - } + dcx.emit_err(errors::AsmPositionalAfter { span, named, explicit }); } } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index e8143b9a5f38f..31917b2c27660 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -281,12 +281,10 @@ pub fn each_linked_rlib( let used_crate_source = &info.used_crate_source[&cnum]; if let Some((path, _)) = &used_crate_source.rlib { f(cnum, path); + } else if used_crate_source.rmeta.is_some() { + return Err(errors::LinkRlibError::OnlyRmetaFound { crate_name }); } else { - if used_crate_source.rmeta.is_some() { - return Err(errors::LinkRlibError::OnlyRmetaFound { crate_name }); - } else { - return Err(errors::LinkRlibError::NotFound { crate_name }); - } + return Err(errors::LinkRlibError::NotFound { crate_name }); } } Ok(()) @@ -628,12 +626,10 @@ fn link_staticlib( let used_crate_source = &codegen_results.crate_info.used_crate_source[&cnum]; if let Some((path, _)) = &used_crate_source.dylib { all_rust_dylibs.push(&**path); + } else if used_crate_source.rmeta.is_some() { + sess.dcx().emit_fatal(errors::LinkRlibError::OnlyRmetaFound { crate_name }); } else { - if used_crate_source.rmeta.is_some() { - sess.dcx().emit_fatal(errors::LinkRlibError::OnlyRmetaFound { crate_name }); - } else { - sess.dcx().emit_fatal(errors::LinkRlibError::NotFound { crate_name }); - } + sess.dcx().emit_fatal(errors::LinkRlibError::NotFound { crate_name }); } } @@ -1972,10 +1968,8 @@ fn add_late_link_args( if let Some(args) = sess.target.late_link_args_dynamic.get(&flavor) { cmd.verbatim_args(args.iter().map(Deref::deref)); } - } else { - if let Some(args) = sess.target.late_link_args_static.get(&flavor) { - cmd.verbatim_args(args.iter().map(Deref::deref)); - } + } else if let Some(args) = sess.target.late_link_args_static.get(&flavor) { + cmd.verbatim_args(args.iter().map(Deref::deref)); } if let Some(args) = sess.target.late_link_args.get(&flavor) { cmd.verbatim_args(args.iter().map(Deref::deref)); @@ -2635,10 +2629,8 @@ fn add_native_libs_from_crate( if link_static { cmd.link_staticlib_by_name(name, verbatim, false); } - } else { - if link_dynamic { - cmd.link_dylib_by_name(name, verbatim, true); - } + } else if link_dynamic { + cmd.link_dylib_by_name(name, verbatim, true); } } NativeLibKind::Framework { as_needed } => { diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index cb266247e0dde..06d8c422034db 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -791,14 +791,12 @@ impl<'a> Linker for GccLinker<'a> { self.link_arg("-exported_symbols_list").link_arg(path); } else if self.sess.target.is_like_solaris { self.link_arg("-M").link_arg(path); + } else if is_windows { + self.link_arg(path); } else { - if is_windows { - self.link_arg(path); - } else { - let mut arg = OsString::from("--version-script="); - arg.push(path); - self.link_arg(arg).link_arg("--no-undefined-version"); - } + let mut arg = OsString::from("--version-script="); + arg.push(path); + self.link_arg(arg).link_arg("--no-undefined-version"); } } diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 5103b2f31582b..e34fbfe3f7614 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -236,15 +236,13 @@ fn push_debuginfo_type_name<'tcx>( let has_enclosing_parens = if cpp_like_debuginfo { output.push_str("dyn$<"); false + } else if trait_data.len() > 1 && auto_traits.len() != 0 { + // We need enclosing parens because there is more than one trait + output.push_str("(dyn "); + true } else { - if trait_data.len() > 1 && auto_traits.len() != 0 { - // We need enclosing parens because there is more than one trait - output.push_str("(dyn "); - true - } else { - output.push_str("dyn "); - false - } + output.push_str("dyn "); + false }; if let Some(principal) = trait_data.principal() { diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index d7b2510a1dffa..1d686878eab4b 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -1151,42 +1151,40 @@ pub(super) fn check_packed(tcx: TyCtxt<'_>, sp: Span, def: ty::AdtDef<'_>) { "type has conflicting packed and align representation hints" ) .emit(); - } else { - if let Some(def_spans) = check_packed_inner(tcx, def.did(), &mut vec![]) { - let mut err = struct_span_code_err!( - tcx.dcx(), - sp, - E0588, - "packed type cannot transitively contain a `#[repr(align)]` type" - ); + } else if let Some(def_spans) = check_packed_inner(tcx, def.did(), &mut vec![]) { + let mut err = struct_span_code_err!( + tcx.dcx(), + sp, + E0588, + "packed type cannot transitively contain a `#[repr(align)]` type" + ); - err.span_note( - tcx.def_span(def_spans[0].0), - format!("`{}` has a `#[repr(align)]` attribute", tcx.item_name(def_spans[0].0)), - ); + err.span_note( + tcx.def_span(def_spans[0].0), + format!("`{}` has a `#[repr(align)]` attribute", tcx.item_name(def_spans[0].0)), + ); - if def_spans.len() > 2 { - let mut first = true; - for (adt_def, span) in def_spans.iter().skip(1).rev() { - let ident = tcx.item_name(*adt_def); - err.span_note( - *span, - if first { - format!( - "`{}` contains a field of type `{}`", - tcx.type_of(def.did()).instantiate_identity(), - ident - ) - } else { - format!("...which contains a field of type `{ident}`") - }, - ); - first = false; - } + if def_spans.len() > 2 { + let mut first = true; + for (adt_def, span) in def_spans.iter().skip(1).rev() { + let ident = tcx.item_name(*adt_def); + err.span_note( + *span, + if first { + format!( + "`{}` contains a field of type `{}`", + tcx.type_of(def.did()).instantiate_identity(), + ident + ) + } else { + format!("...which contains a field of type `{ident}`") + }, + ); + first = false; } - - err.emit(); } + + err.emit(); } } } diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs index 7f4a8208faaed..2afb29abd68a6 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs @@ -381,24 +381,22 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>( } mir_opaque_ty.ty + } else if let Some(guar) = tables.tainted_by_errors { + // Some error in the owner fn prevented us from populating + // the `concrete_opaque_types` table. + Ty::new_error(tcx, guar) } else { - if let Some(guar) = tables.tainted_by_errors { - // Some error in the owner fn prevented us from populating - // the `concrete_opaque_types` table. - Ty::new_error(tcx, guar) + // Fall back to the RPIT we inferred during HIR typeck + if let Some(hir_opaque_ty) = hir_opaque_ty { + hir_opaque_ty.ty } else { - // Fall back to the RPIT we inferred during HIR typeck - if let Some(hir_opaque_ty) = hir_opaque_ty { - hir_opaque_ty.ty - } else { - // We failed to resolve the opaque type or it - // resolves to itself. We interpret this as the - // no values of the hidden type ever being constructed, - // so we can just make the hidden type be `!`. - // For backwards compatibility reasons, we fall back to - // `()` until we the diverging default is changed. - Ty::new_diverging_default(tcx) - } + // We failed to resolve the opaque type or it + // resolves to itself. We interpret this as the + // no values of the hidden type ever being constructed, + // so we can just make the hidden type be `!`. + // For backwards compatibility reasons, we fall back to + // `()` until we the diverging default is changed. + Ty::new_diverging_default(tcx) } } } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index ac5bd825b18dd..7163352e8a439 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -562,13 +562,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { tcx.const_param_default(param.def_id) .instantiate(tcx, preceding_args) .into() + } else if infer_args { + self.lowerer.ct_infer(Some(param), self.span).into() } else { - if infer_args { - self.lowerer.ct_infer(Some(param), self.span).into() - } else { - // We've already errored above about the mismatch. - ty::Const::new_misc_error(tcx).into() - } + // We've already errored above about the mismatch. + ty::Const::new_misc_error(tcx).into() } } } diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 197f802960f80..31ea5741ec9ba 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2902,21 +2902,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { candidate_fields.iter().map(|path| format!("{unwrap}{path}")), Applicability::MaybeIncorrect, ); - } else { - if let Some(field_name) = find_best_match_for_name(&field_names, field.name, None) { - err.span_suggestion_verbose( - field.span, - "a field with a similar name exists", - format!("{unwrap}{}", field_name), - Applicability::MaybeIncorrect, - ); - } else if !field_names.is_empty() { - let is = if field_names.len() == 1 { " is" } else { "s are" }; - err.note(format!( - "available field{is}: {}", - self.name_series_display(field_names), - )); - } + } else if let Some(field_name) = + find_best_match_for_name(&field_names, field.name, None) + { + err.span_suggestion_verbose( + field.span, + "a field with a similar name exists", + format!("{unwrap}{}", field_name), + Applicability::MaybeIncorrect, + ); + } else if !field_names.is_empty() { + let is = if field_names.len() == 1 { " is" } else { "s are" }; + err.note( + format!("available field{is}: {}", self.name_series_display(field_names),), + ); } } err diff --git a/compiler/rustc_hir_typeck/src/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs index 4ea22884cf376..2f990de7e31be 100644 --- a/compiler/rustc_hir_typeck/src/gather_locals.rs +++ b/compiler/rustc_hir_typeck/src/gather_locals.rs @@ -158,14 +158,12 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> { ), ); } - } else { - if !self.fcx.tcx.features().unsized_locals { - self.fcx.require_type_is_sized( - var_ty, - p.span, - ObligationCauseCode::VariableType(p.hir_id), - ); - } + } else if !self.fcx.tcx.features().unsized_locals { + self.fcx.require_type_is_sized( + var_ty, + p.span, + ObligationCauseCode::VariableType(p.hir_id), + ); } debug!( diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs index 88cb82f0f37a8..cef0b23143d00 100644 --- a/compiler/rustc_incremental/src/persist/dirty_clean.rs +++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs @@ -417,12 +417,10 @@ fn check_config(tcx: TyCtxt<'_>, attr: &Attribute) -> bool { fn expect_associated_value(tcx: TyCtxt<'_>, item: &NestedMetaItem) -> Symbol { if let Some(value) = item.value_str() { value + } else if let Some(ident) = item.ident() { + tcx.dcx().emit_fatal(errors::AssociatedValueExpectedFor { span: item.span(), ident }); } else { - if let Some(ident) = item.ident() { - tcx.dcx().emit_fatal(errors::AssociatedValueExpectedFor { span: item.span(), ident }); - } else { - tcx.dcx().emit_fatal(errors::AssociatedValueExpected { span: item.span() }); - } + tcx.dcx().emit_fatal(errors::AssociatedValueExpected { span: item.span() }); } } diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index a98e6943d68ee..d66d0be10095f 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -208,12 +208,10 @@ fn dump_path<'tcx>( let pass_num = if tcx.sess.opts.unstable_opts.dump_mir_exclude_pass_number { String::new() + } else if pass_num { + format!(".{:03}-{:03}", body.phase.phase_index(), body.pass_count) } else { - if pass_num { - format!(".{:03}-{:03}", body.phase.phase_index(), body.pass_count) - } else { - ".-------".to_string() - } + ".-------".to_string() }; let crate_name = tcx.crate_name(source.def_id().krate); diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index ecc4cd96fafb0..2d6edad29779a 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2554,13 +2554,12 @@ impl<'a> Parser<'a> { let maybe_fatarrow = self.token.clone(); let block = if self.check(&token::OpenDelim(Delimiter::Brace)) { self.parse_block()? + } else if let Some(block) = recover_block_from_condition(self) { + block } else { - if let Some(block) = recover_block_from_condition(self) { - block - } else { - self.error_on_extra_if(&cond)?; - // Parse block, which will always fail, but we can add a nice note to the error - self.parse_block().map_err(|mut err| { + self.error_on_extra_if(&cond)?; + // Parse block, which will always fail, but we can add a nice note to the error + self.parse_block().map_err(|mut err| { if self.prev_token == token::Semi && self.token == token::AndAnd && let maybe_let = self.look_ahead(1, |t| t.clone()) @@ -2592,7 +2591,6 @@ impl<'a> Parser<'a> { } err })? - } }; self.error_on_if_block_attrs(lo, false, block.span, attrs); block diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 3ee6e742d1b83..9d9265d5318db 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1359,13 +1359,11 @@ impl<'a> Parser<'a> { fn parse_attr_args(&mut self) -> PResult<'a, AttrArgs> { Ok(if let Some(args) = self.parse_delim_args_inner() { AttrArgs::Delimited(args) + } else if self.eat(&token::Eq) { + let eq_span = self.prev_token.span; + AttrArgs::Eq(eq_span, AttrArgsEq::Ast(self.parse_expr_force_collect()?)) } else { - if self.eat(&token::Eq) { - let eq_span = self.prev_token.span; - AttrArgs::Eq(eq_span, AttrArgsEq::Ast(self.parse_expr_force_collect()?)) - } else { - AttrArgs::Empty - } + AttrArgs::Empty }) } diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index cbd35ffdfa982..daced411b8fe2 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -1336,21 +1336,19 @@ impl<'a> Parser<'a> { vec![(first_etc_span, String::new())], Applicability::MachineApplicable, ); - } else { - if let Some(last_non_comma_dotdot_span) = last_non_comma_dotdot_span { - // We have `.., x`. - err.multipart_suggestion( - "move the `..` to the end of the field list", - vec![ - (first_etc_span, String::new()), - ( - self.token.span.to(last_non_comma_dotdot_span.shrink_to_hi()), - format!("{} .. }}", if ate_comma { "" } else { "," }), - ), - ], - Applicability::MachineApplicable, - ); - } + } else if let Some(last_non_comma_dotdot_span) = last_non_comma_dotdot_span { + // We have `.., x`. + err.multipart_suggestion( + "move the `..` to the end of the field list", + vec![ + (first_etc_span, String::new()), + ( + self.token.span.to(last_non_comma_dotdot_span.shrink_to_hi()), + format!("{} .. }}", if ate_comma { "" } else { "," }), + ), + ], + Applicability::MachineApplicable, + ); } } err.emit(); diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index fce41bd90be7b..f2121c3243aa4 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -192,13 +192,11 @@ pub fn check_attribute_safety(psess: &ParseSess, safety: AttributeSafety, attr: ); } } - } else { - if let Safety::Unsafe(unsafe_span) = attr_item.unsafety { - psess.dcx().emit_err(errors::InvalidAttrUnsafe { - span: unsafe_span, - name: attr_item.path.clone(), - }); - } + } else if let Safety::Unsafe(unsafe_span) = attr_item.unsafety { + psess.dcx().emit_err(errors::InvalidAttrUnsafe { + span: unsafe_span, + name: attr_item.path.clone(), + }); } } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index e41f89a3c9da9..57ee55c7866da 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -2172,17 +2172,13 @@ impl<'tcx> CheckAttrVisitor<'tcx> { attr.span, errors::MacroExport::TooManyItems, ); - } else { - if meta_item_list[0].name_or_empty() != sym::local_inner_macros { - self.tcx.emit_node_span_lint( - INVALID_MACRO_EXPORT_ARGUMENTS, - hir_id, - meta_item_list[0].span(), - errors::MacroExport::UnknownItem { - name: meta_item_list[0].name_or_empty(), - }, - ); - } + } else if meta_item_list[0].name_or_empty() != sym::local_inner_macros { + self.tcx.emit_node_span_lint( + INVALID_MACRO_EXPORT_ARGUMENTS, + hir_id, + meta_item_list[0].span(), + errors::MacroExport::UnknownItem { name: meta_item_list[0].name_or_empty() }, + ); } } else { // special case when `#[macro_export]` is applied to a macro 2.0 diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index db3eaea68b5c2..959b7ad147b5f 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -1500,15 +1500,13 @@ impl<'tcx> Liveness<'_, 'tcx> { ); } } - } else { - if let Some(name) = self.should_warn(var) { - self.ir.tcx.emit_node_span_lint( - lint::builtin::UNUSED_VARIABLES, - var_hir_id, - vec![span], - errors::UnusedVarMaybeCaptureRef { name }, - ); - } + } else if let Some(name) = self.should_warn(var) { + self.ir.tcx.emit_node_span_lint( + lint::builtin::UNUSED_VARIABLES, + var_hir_id, + vec![span], + errors::UnusedVarMaybeCaptureRef { name }, + ); } } } diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 42171edf75749..1c8ccd2321f99 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -1256,28 +1256,23 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { extern_crate_span: self.tcx.source_span(self.local_def_id(extern_crate_id)), }, ); + } else if ns == TypeNS { + let err = if crate_private_reexport { + self.dcx() + .create_err(CannotBeReexportedCratePublicNS { span: import.span, ident }) + } else { + self.dcx().create_err(CannotBeReexportedPrivateNS { span: import.span, ident }) + }; + err.emit(); } else { - if ns == TypeNS { - let err = if crate_private_reexport { - self.dcx().create_err(CannotBeReexportedCratePublicNS { - span: import.span, - ident, - }) - } else { - self.dcx() - .create_err(CannotBeReexportedPrivateNS { span: import.span, ident }) - }; - err.emit(); + let mut err = if crate_private_reexport { + self.dcx() + .create_err(CannotBeReexportedCratePublic { span: import.span, ident }) } else { - let mut err = if crate_private_reexport { - self.dcx() - .create_err(CannotBeReexportedCratePublic { span: import.span, ident }) - } else { - self.dcx() - .create_err(CannotBeReexportedPrivate { span: import.span, ident }) - }; + self.dcx().create_err(CannotBeReexportedPrivate { span: import.span, ident }) + }; - match binding.kind { + match binding.kind { NameBindingKind::Res(Res::Def(DefKind::Macro(_), def_id)) // exclude decl_macro if self.get_macro_by_def_id(def_id).macro_rules => @@ -1293,8 +1288,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }); } } - err.emit(); - } + err.emit(); } } diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs index 976c4acb212f5..bed3baa30fb26 100644 --- a/compiler/rustc_resolve/src/rustdoc.rs +++ b/compiler/rustc_resolve/src/rustdoc.rs @@ -270,12 +270,10 @@ fn strip_generics_from_path_segment(segment: Vec) -> Result( if fn_sig.c_variadic { s.push('z'); } + } else if fn_sig.c_variadic { + s.push('z'); } else { - if fn_sig.c_variadic { - s.push('z'); - } else { - // Empty parameter lists, whether declared as () or conventionally as (void), are - // encoded with a void parameter specifier "v". - s.push('v') - } + // Empty parameter lists, whether declared as () or conventionally as (void), are + // encoded with a void parameter specifier "v". + s.push('v') } // Close the "F..E" pair diff --git a/compiler/rustc_target/src/abi/call/xtensa.rs b/compiler/rustc_target/src/abi/call/xtensa.rs index cb61bf2c56bea..d7b5fe9d4cc71 100644 --- a/compiler/rustc_target/src/abi/call/xtensa.rs +++ b/compiler/rustc_target/src/abi/call/xtensa.rs @@ -69,29 +69,27 @@ where if must_use_stack { arg.make_indirect_byval(None); - } else { - if is_xtensa_aggregate(arg) { - // Aggregates which are <= max_size will be passed in - // registers if possible, so coerce to integers. + } else if is_xtensa_aggregate(arg) { + // Aggregates which are <= max_size will be passed in + // registers if possible, so coerce to integers. - // Use a single `xlen` int if possible, 2 * `xlen` if 2 * `xlen` alignment - // is required, and a 2-element `xlen` array if only `xlen` alignment is - // required. - if size <= 32 { - arg.cast_to(Reg::i32()); - } else { - let reg = if needed_align == 2 * 32 { Reg::i64() } else { Reg::i32() }; - let total = Size::from_bits(((size + 32 - 1) / 32) * 32); - arg.cast_to(Uniform::new(reg, total)); - } + // Use a single `xlen` int if possible, 2 * `xlen` if 2 * `xlen` alignment + // is required, and a 2-element `xlen` array if only `xlen` alignment is + // required. + if size <= 32 { + arg.cast_to(Reg::i32()); } else { - // All integral types are promoted to `xlen` - // width. - // - // We let the LLVM backend handle integral types >= xlen. - if size < 32 { - arg.extend_integer_width_to(32); - } + let reg = if needed_align == 2 * 32 { Reg::i64() } else { Reg::i32() }; + let total = Size::from_bits(((size + 32 - 1) / 32) * 32); + arg.cast_to(Uniform::new(reg, total)); + } + } else { + // All integral types are promoted to `xlen` + // width. + // + // We let the LLVM backend handle integral types >= xlen. + if size < 32 { + arg.extend_integer_width_to(32); } } } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index 65d21518491da..d486416f22a30 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -1323,23 +1323,21 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { label_or_note(span, terr.to_string(self.tcx)); label_or_note(sp, msg); } - } else { - if let Some(values) = values - && let Some((e, f)) = values.ty() - && let TypeError::ArgumentSorts(..) | TypeError::Sorts(_) = terr - { - let e = self.tcx.erase_regions(e); - let f = self.tcx.erase_regions(f); - let expected = with_forced_trimmed_paths!(e.sort_string(self.tcx)); - let found = with_forced_trimmed_paths!(f.sort_string(self.tcx)); - if expected == found { - label_or_note(span, terr.to_string(self.tcx)); - } else { - label_or_note(span, Cow::from(format!("expected {expected}, found {found}"))); - } - } else { + } else if let Some(values) = values + && let Some((e, f)) = values.ty() + && let TypeError::ArgumentSorts(..) | TypeError::Sorts(_) = terr + { + let e = self.tcx.erase_regions(e); + let f = self.tcx.erase_regions(f); + let expected = with_forced_trimmed_paths!(e.sort_string(self.tcx)); + let found = with_forced_trimmed_paths!(f.sort_string(self.tcx)); + if expected == found { label_or_note(span, terr.to_string(self.tcx)); + } else { + label_or_note(span, Cow::from(format!("expected {expected}, found {found}"))); } + } else { + label_or_note(span, terr.to_string(self.tcx)); } if let Some((expected, found, path)) = expected_found { diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 45e157b108006..b13aede509a7f 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -3237,16 +3237,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // then the tuple must be the one containing capture types. let is_upvar_tys_infer_tuple = if !matches!(ty.kind(), ty::Tuple(..)) { false + } else if let ObligationCauseCode::BuiltinDerived(data) = &*data.parent_code { + let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred); + let nested_ty = parent_trait_ref.skip_binder().self_ty(); + matches!(nested_ty.kind(), ty::Coroutine(..)) + || matches!(nested_ty.kind(), ty::Closure(..)) } else { - if let ObligationCauseCode::BuiltinDerived(data) = &*data.parent_code { - let parent_trait_ref = - self.resolve_vars_if_possible(data.parent_trait_pred); - let nested_ty = parent_trait_ref.skip_binder().self_ty(); - matches!(nested_ty.kind(), ty::Coroutine(..)) - || matches!(nested_ty.kind(), ty::Closure(..)) - } else { - false - } + false }; if !is_upvar_tys_infer_tuple { diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 66dfa283d0763..3e3589538c710 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -426,13 +426,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } else if kind == ty::ClosureKind::FnOnce { candidates.vec.push(ClosureCandidate { is_const }); } + } else if kind == ty::ClosureKind::FnOnce { + candidates.vec.push(ClosureCandidate { is_const }); } else { - if kind == ty::ClosureKind::FnOnce { - candidates.vec.push(ClosureCandidate { is_const }); - } else { - // This stays ambiguous until kind+upvars are determined. - candidates.ambiguous = true; - } + // This stays ambiguous until kind+upvars are determined. + candidates.ambiguous = true; } } ty::Infer(ty::TyVar(_)) => { From 368231c9954f2a672ba5e484b2de3aee36d911cc Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Wed, 11 Sep 2024 17:35:14 -0400 Subject: [PATCH 173/189] Limit `libc::link` usage to `nto70` target only, not NTO OS It seems QNX 7.0 does not support `linkat` at all (most tests were failing). Limiting to QNX 7.0 only, while using `linkat` for the future versions seems like the right path forward (tested on 7.0). Fixes 129895 --- library/std/src/sys/pal/unix/fs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs index 4ec577a0a01d0..d09cee2e89c5b 100644 --- a/library/std/src/sys/pal/unix/fs.rs +++ b/library/std/src/sys/pal/unix/fs.rs @@ -1731,7 +1731,7 @@ pub fn link(original: &Path, link: &Path) -> io::Result<()> { run_path_with_cstr(original, &|original| { run_path_with_cstr(link, &|link| { cfg_if::cfg_if! { - if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android", target_os = "espidf", target_os = "horizon", target_os = "vita", target_os = "nto"))] { + if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android", target_os = "espidf", target_os = "horizon", target_os = "vita", target_env = "nto70"))] { // VxWorks, Redox and ESP-IDF lack `linkat`, so use `link` instead. POSIX leaves // it implementation-defined whether `link` follows symlinks, so rely on the // `symlink_hard_link` test in library/std/src/fs/tests.rs to check the behavior. From 6d064295c8fb7413cb0500289f922f8d7feb38dc Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 11 Sep 2024 14:58:08 -0400 Subject: [PATCH 174/189] clippy::useless_conversion --- compiler/rustc_ast/src/ast.rs | 6 ++---- .../rustc_const_eval/src/const_eval/eval_queries.rs | 7 +------ compiler/rustc_const_eval/src/interpret/call.rs | 2 +- compiler/rustc_errors/src/diagnostic.rs | 4 ++-- compiler/rustc_hir_analysis/src/check/wfcheck.rs | 4 ++-- compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs | 2 +- compiler/rustc_middle/src/ty/consts.rs | 2 +- compiler/rustc_middle/src/ty/print/pretty.rs | 2 +- .../rustc_next_trait_solver/src/solve/trait_goals.rs | 1 - compiler/rustc_parse/src/parser/attr_wrapper.rs | 2 +- compiler/rustc_parse/src/parser/item.rs | 10 +++++----- compiler/rustc_symbol_mangling/src/v0.rs | 2 +- compiler/rustc_trait_selection/src/traits/project.rs | 4 ++-- 13 files changed, 20 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 85d38a0e28b0f..5d353be67b5de 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -3475,7 +3475,7 @@ impl From for ItemKind { fn from(foreign_item_kind: ForeignItemKind) -> ItemKind { match foreign_item_kind { ForeignItemKind::Static(box static_foreign_item) => { - ItemKind::Static(Box::new(static_foreign_item.into())) + ItemKind::Static(Box::new(static_foreign_item)) } ForeignItemKind::Fn(fn_kind) => ItemKind::Fn(fn_kind), ForeignItemKind::TyAlias(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind), @@ -3489,9 +3489,7 @@ impl TryFrom for ForeignItemKind { fn try_from(item_kind: ItemKind) -> Result { Ok(match item_kind { - ItemKind::Static(box static_item) => { - ForeignItemKind::Static(Box::new(static_item.into())) - } + ItemKind::Static(box static_item) => ForeignItemKind::Static(Box::new(static_item)), ItemKind::Fn(fn_kind) => ForeignItemKind::Fn(fn_kind), ItemKind::TyAlias(ty_alias_kind) => ForeignItemKind::TyAlias(ty_alias_kind), ItemKind::MacCall(a) => ForeignItemKind::MacCall(a), diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 7ccebd83f24f7..da4173f903296 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -75,12 +75,7 @@ fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>( // This can't use `init_stack_frame` since `body` is not a function, // so computing its ABI would fail. It's also not worth it since there are no arguments to pass. - ecx.push_stack_frame_raw( - cid.instance, - body, - &ret.clone().into(), - StackPopCleanup::Root { cleanup: false }, - )?; + ecx.push_stack_frame_raw(cid.instance, body, &ret, StackPopCleanup::Root { cleanup: false })?; ecx.storage_live_for_always_live_locals()?; // The main interpreter loop. diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index 568a9a3a637be..5687e72569f93 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -823,7 +823,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { (Abi::Rust, fn_abi), &[FnArg::Copy(arg.into())], false, - &ret.into(), + &ret, Some(target), unwind, ) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 412a2c17081a9..7a4d8dba179a2 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -681,10 +681,10 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { " ".repeat(expected_padding), expected_label ))]; - msg.extend(expected.0.into_iter()); + msg.extend(expected.0); msg.push(StringPart::normal(format!("`{expected_extra}\n"))); msg.push(StringPart::normal(format!("{}{} `", " ".repeat(found_padding), found_label))); - msg.extend(found.0.into_iter()); + msg.extend(found.0); msg.push(StringPart::normal(format!("`{found_extra}"))); // For now, just attach these as notes. diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 3627faf8dfc57..10b3fe380ab69 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1602,7 +1602,7 @@ fn check_fn_or_method<'tcx>( function: def_id, // Note that the `param_idx` of the output type is // one greater than the index of the last input type. - param_idx: idx.try_into().unwrap(), + param_idx: idx, }), ty, ) @@ -1611,7 +1611,7 @@ fn check_fn_or_method<'tcx>( for (idx, ty) in sig.inputs_and_output.iter().enumerate() { wfcx.register_wf_obligation( arg_span(idx), - Some(WellFormedLoc::Param { function: def_id, param_idx: idx.try_into().unwrap() }), + Some(WellFormedLoc::Param { function: def_id, param_idx: idx }), ty.into(), ); } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index bdf84f332166d..a18ce73a8aad0 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -2565,7 +2565,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { other_generic_param.name.ident() == generic_param.name.ident() }, ) { - idxs_matched.push(other_idx.into()); + idxs_matched.push(other_idx); } if idxs_matched.is_empty() { diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 362ff8e988d36..a5952c65692c1 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -396,7 +396,7 @@ impl<'tcx> Const<'tcx> { Ok((tcx.type_of(unevaluated.def).instantiate(tcx, unevaluated.args), c)) } Ok(Err(bad_ty)) => Err(Either::Left(bad_ty)), - Err(err) => Err(Either::Right(err.into())), + Err(err) => Err(Either::Right(err)), } } ConstKind::Value(ty, val) => Ok((ty, val)), diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index f1ff90831b04f..819c7d3c5b49f 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1526,7 +1526,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { let precedence = |binop: rustc_middle::mir::BinOp| { use rustc_ast::util::parser::AssocOp; - AssocOp::from_ast_binop(binop.to_hir_binop().into()).precedence() + AssocOp::from_ast_binop(binop.to_hir_binop()).precedence() }; let op_precedence = precedence(op); let formatted_op = op.to_hir_binop().as_str(); diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 683d8dab3b2a8..73d9b5e8a4ee7 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -883,7 +883,6 @@ where .into_iter() .chain(a_data.principal_def_id().into_iter().flat_map(|principal_def_id| { elaborate::supertrait_def_ids(self.cx(), principal_def_id) - .into_iter() .filter(|def_id| self.cx().trait_is_auto(*def_id)) })) .collect(); diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs index 205cca830b2e0..6a241be0a1560 100644 --- a/compiler/rustc_parse/src/parser/attr_wrapper.rs +++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs @@ -383,7 +383,7 @@ impl<'a> Parser<'a> { self.capture_state .parser_replacements .drain(parser_replacements_start..parser_replacements_end) - .chain(inner_attr_parser_replacements.into_iter()) + .chain(inner_attr_parser_replacements) .map(|(parser_range, data)| { (NodeRange::new(parser_range, collect_pos.start_pos), data) }) diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index c6a5e1908f704..98ec09356d3dc 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1588,7 +1588,7 @@ impl<'a> Parser<'a> { (thin_vec![], Recovered::Yes(guar)) } }; - VariantData::Struct { fields, recovered: recovered.into() } + VariantData::Struct { fields, recovered } } else if this.check(&token::OpenDelim(Delimiter::Parenthesis)) { let body = match this.parse_tuple_struct_body() { Ok(body) => body, @@ -1672,7 +1672,7 @@ impl<'a> Parser<'a> { class_name.span, generics.where_clause.has_where_token, )?; - VariantData::Struct { fields, recovered: recovered.into() } + VariantData::Struct { fields, recovered } } // No `where` so: `struct Foo;` } else if self.eat(&token::Semi) { @@ -1684,7 +1684,7 @@ impl<'a> Parser<'a> { class_name.span, generics.where_clause.has_where_token, )?; - VariantData::Struct { fields, recovered: recovered.into() } + VariantData::Struct { fields, recovered } // Tuple-style struct definition with optional where-clause. } else if self.token == token::OpenDelim(Delimiter::Parenthesis) { let body = VariantData::Tuple(self.parse_tuple_struct_body()?, DUMMY_NODE_ID); @@ -1713,14 +1713,14 @@ impl<'a> Parser<'a> { class_name.span, generics.where_clause.has_where_token, )?; - VariantData::Struct { fields, recovered: recovered.into() } + VariantData::Struct { fields, recovered } } else if self.token == token::OpenDelim(Delimiter::Brace) { let (fields, recovered) = self.parse_record_struct_body( "union", class_name.span, generics.where_clause.has_where_token, )?; - VariantData::Struct { fields, recovered: recovered.into() } + VariantData::Struct { fields, recovered } } else { let token_str = super::token_descr(&self.token); let msg = format!("expected `where` or `{{` after union name, found {token_str}"); diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 75f4499352b99..ba35a37c32ce1 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -381,7 +381,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { let consts = [ start.unwrap_or(self.tcx.consts.unit), end.unwrap_or(self.tcx.consts.unit), - ty::Const::from_bool(self.tcx, include_end).into(), + ty::Const::from_bool(self.tcx, include_end), ]; // HACK: Represent as tuple until we have something better. // HACK: constants are used in arrays, even if the types don't match. diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 630acc91fbedc..c27a9285b3abe 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -408,7 +408,7 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>( debug!("opt_normalize_projection_type: found error"); let result = normalize_to_error(selcx, param_env, projection_term, cause, depth); obligations.extend(result.obligations); - return Ok(Some(result.value.into())); + return Ok(Some(result.value)); } } @@ -478,7 +478,7 @@ pub(super) fn opt_normalize_projection_term<'a, 'b, 'tcx>( } let result = normalize_to_error(selcx, param_env, projection_term, cause, depth); obligations.extend(result.obligations); - Ok(Some(result.value.into())) + Ok(Some(result.value)) } } } From e866f8a97d1f08e8a187323a1a5838f88fe33d81 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 11 Sep 2024 17:57:04 -0400 Subject: [PATCH 175/189] Revert 'Stabilize -Znext-solver=coherence' --- compiler/rustc_interface/src/tests.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 4 +- compiler/rustc_session/src/config.rs | 5 -- compiler/rustc_session/src/options.rs | 31 ++++--- .../src/traits/engine.rs | 4 +- .../118987-2.rs} | 4 +- tests/crashes/118987.rs | 17 ++++ .../124207.rs} | 4 +- .../74299.rs} | 5 +- .../associated-types-coherence-failure.stderr | 8 +- .../opaque_type_candidate_selection.rs | 30 +++++++ ...e-negative-outlives-lifetimes.stock.stderr | 2 - ...s-lifetimes.with_negative_coherence.stderr | 2 - ...e-overlap-downstream-inherent.next.stderr} | 4 +- ...nce-overlap-downstream-inherent.old.stderr | 23 +++++ .../coherence-overlap-downstream-inherent.rs | 3 + ... coherence-overlap-downstream.next.stderr} | 4 +- .../coherence-overlap-downstream.old.stderr | 21 +++++ .../coherence/coherence-overlap-downstream.rs | 3 + ...-overlap-issue-23516-inherent.next.stderr} | 2 +- ...ce-overlap-issue-23516-inherent.old.stderr | 14 ++++ .../coherence-overlap-issue-23516-inherent.rs | 3 + ...coherence-overlap-issue-23516.next.stderr} | 2 +- .../coherence-overlap-issue-23516.old.stderr | 13 +++ .../coherence-overlap-issue-23516.rs | 3 + ...overlap-negate-not-use-feature-gate.stderr | 2 - ...unnormalizable-projection-0.classic.stderr | 19 +++++ ...p-unnormalizable-projection-0.next.stderr} | 2 +- ...nce-overlap-unnormalizable-projection-0.rs | 3 + ...unnormalizable-projection-1.classic.stderr | 19 +++++ ...p-unnormalizable-projection-1.next.stderr} | 2 +- ...nce-overlap-unnormalizable-projection-1.rs | 3 + tests/ui/coherence/coherent-due-to-fulfill.rs | 2 + .../incoherent-even-though-we-fulfill.rs | 2 + .../incoherent-even-though-we-fulfill.stderr | 2 +- ...-crate-ambiguity-causes-notes.next.stderr} | 2 +- ...er-crate-ambiguity-causes-notes.old.stderr | 17 ++++ .../inter-crate-ambiguity-causes-notes.rs | 3 + ...oherence-check-placeholder-outlives.stderr | 2 - ...oherence-considering-regions.any_lt.stderr | 2 - ...constraints-on-unification.explicit.stderr | 1 - .../normalize-for-errors.current.stderr | 14 ++++ ...tderr => normalize-for-errors.next.stderr} | 2 +- tests/ui/coherence/normalize-for-errors.rs | 6 +- .../occurs-check/associated-type.next.stderr | 4 +- .../occurs-check/associated-type.old.stderr | 10 ++- .../coherence/occurs-check/associated-type.rs | 1 - .../occurs-check/opaques.current.stderr | 12 --- .../occurs-check/opaques.next.stderr | 4 +- tests/ui/coherence/occurs-check/opaques.rs | 8 +- ...-opaque-types-not-covering.classic.stderr} | 4 +- ...heck-opaque-types-not-covering.next.stderr | 21 +++++ .../orphan-check-opaque-types-not-covering.rs | 3 + .../orphan-check-projections-covering.rs | 3 + ...-weak-aliases-not-covering.classic.stderr} | 2 +- ...heck-weak-aliases-not-covering.next.stderr | 12 +++ .../orphan-check-weak-aliases-not-covering.rs | 3 + ...reporting-if-references-err.current.stderr | 27 ++++++ ...p-reporting-if-references-err.next.stderr} | 2 +- .../skip-reporting-if-references-err.rs | 6 ++ .../super-trait-knowable-1.current.stderr | 13 +++ .../super-traits/super-trait-knowable-1.rs | 6 +- .../super-traits/super-trait-knowable-2.rs | 3 + .../super-trait-knowable-3.current.stderr | 13 +++ .../super-traits/super-trait-knowable-3.rs | 6 +- .../unevaluated-const-ice-119731.rs | 1 - .../unevaluated-const-ice-119731.stderr | 23 ++--- ...nown-alias-defkind-anonconst-ice-116710.rs | 1 + ...-alias-defkind-anonconst-ice-116710.stderr | 14 +++- tests/ui/error-codes/e0119/issue-23563.stderr | 2 +- ...eature-gate-with_negative_coherence.stderr | 2 - .../leak-check-in-selection-5-ambig.rs | 6 +- .../structually-relate-aliases.rs | 3 +- .../structually-relate-aliases.stderr | 33 +++++--- .../auto-trait-coherence.old.stderr | 4 +- tests/ui/impl-trait/auto-trait-coherence.rs | 6 +- .../ui/impl-trait/auto-trait-coherence.stderr | 12 --- .../impl-trait/coherence-treats-tait-ambig.rs | 2 +- .../coherence-treats-tait-ambig.stderr | 2 +- tests/ui/impl-trait/negative-reasoning.rs | 2 +- tests/ui/impl-trait/negative-reasoning.stderr | 6 +- tests/ui/impl-unused-tps.rs | 46 +++++----- tests/ui/impl-unused-tps.stderr | 84 +++++++------------ tests/ui/issues/issue-48728.rs | 8 +- .../default-impl-normalization-ambig-2.stderr | 21 ----- .../default-item-normalization-ambig-1.stderr | 21 ----- .../defaultimpl/specialization-no-default.rs | 3 +- ...efault-items-drop-coherence.current.stderr | 12 --- ...n-default-items-drop-coherence.next.stderr | 2 +- ...ialization-default-items-drop-coherence.rs | 8 +- ...lization-overlap-projection.current.stderr | 22 +---- ...cialization-overlap-projection.next.stderr | 6 +- .../specialization-overlap-projection.rs | 13 ++- .../specialization-overlap-projection.stderr | 30 ------- tests/ui/traits/alias/issue-83613.rs | 2 +- tests/ui/traits/alias/issue-83613.stderr | 4 +- tests/ui/traits/issue-105231.rs | 3 +- tests/ui/traits/issue-105231.stderr | 22 +++-- .../cycle-via-builtin-auto-trait-impl.rs | 2 +- .../cycle-via-builtin-auto-trait-impl.stderr | 26 ++++-- .../coherence-bikeshed-intrinsic-from.stderr | 27 ------ .../impl_trait_for_same_tait.stderr | 2 + .../ui/type-alias-impl-trait/issue-104817.rs | 2 +- .../issue-104817.stock.stderr | 4 +- 104 files changed, 578 insertions(+), 392 deletions(-) rename tests/{ui/specialization/coherence/default-impl-normalization-ambig-2.rs => crashes/118987-2.rs} (74%) create mode 100644 tests/crashes/118987.rs rename tests/{ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.rs => crashes/124207.rs} (62%) rename tests/{ui/specialization/coherence/default-item-normalization-ambig-1.rs => crashes/74299.rs} (56%) create mode 100644 tests/ui/auto-traits/opaque_type_candidate_selection.rs rename tests/ui/coherence/{coherence-overlap-downstream-inherent.stderr => coherence-overlap-downstream-inherent.next.stderr} (87%) create mode 100644 tests/ui/coherence/coherence-overlap-downstream-inherent.old.stderr rename tests/ui/coherence/{coherence-overlap-downstream.stderr => coherence-overlap-downstream.next.stderr} (88%) create mode 100644 tests/ui/coherence/coherence-overlap-downstream.old.stderr rename tests/ui/coherence/{coherence-overlap-issue-23516-inherent.stderr => coherence-overlap-issue-23516-inherent.next.stderr} (90%) create mode 100644 tests/ui/coherence/coherence-overlap-issue-23516-inherent.old.stderr rename tests/ui/coherence/{coherence-overlap-issue-23516.stderr => coherence-overlap-issue-23516.next.stderr} (90%) create mode 100644 tests/ui/coherence/coherence-overlap-issue-23516.old.stderr create mode 100644 tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.classic.stderr rename tests/ui/coherence/{coherence-overlap-unnormalizable-projection-0.stderr => coherence-overlap-unnormalizable-projection-0.next.stderr} (91%) create mode 100644 tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.classic.stderr rename tests/ui/coherence/{coherence-overlap-unnormalizable-projection-1.stderr => coherence-overlap-unnormalizable-projection-1.next.stderr} (92%) rename tests/ui/coherence/{inter-crate-ambiguity-causes-notes.stderr => inter-crate-ambiguity-causes-notes.next.stderr} (90%) create mode 100644 tests/ui/coherence/inter-crate-ambiguity-causes-notes.old.stderr create mode 100644 tests/ui/coherence/normalize-for-errors.current.stderr rename tests/ui/coherence/{normalize-for-errors.stderr => normalize-for-errors.next.stderr} (95%) delete mode 100644 tests/ui/coherence/occurs-check/opaques.current.stderr rename tests/ui/coherence/{orphan-check-opaque-types-not-covering.stderr => orphan-check-opaque-types-not-covering.classic.stderr} (92%) create mode 100644 tests/ui/coherence/orphan-check-opaque-types-not-covering.next.stderr rename tests/ui/coherence/{orphan-check-weak-aliases-not-covering.stderr => orphan-check-weak-aliases-not-covering.classic.stderr} (92%) create mode 100644 tests/ui/coherence/orphan-check-weak-aliases-not-covering.next.stderr create mode 100644 tests/ui/coherence/skip-reporting-if-references-err.current.stderr rename tests/ui/coherence/{skip-reporting-if-references-err.stderr => skip-reporting-if-references-err.next.stderr} (87%) create mode 100644 tests/ui/coherence/super-traits/super-trait-knowable-1.current.stderr create mode 100644 tests/ui/coherence/super-traits/super-trait-knowable-3.current.stderr delete mode 100644 tests/ui/impl-trait/auto-trait-coherence.stderr delete mode 100644 tests/ui/specialization/coherence/default-impl-normalization-ambig-2.stderr delete mode 100644 tests/ui/specialization/coherence/default-item-normalization-ambig-1.stderr delete mode 100644 tests/ui/specialization/specialization-default-items-drop-coherence.current.stderr delete mode 100644 tests/ui/specialization/specialization-overlap-projection.stderr delete mode 100644 tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.stderr diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 50422df8ee648..42fed98df0101 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -808,7 +808,7 @@ fn test_unstable_options_tracking_hash() { tracked!(mir_opt_level, Some(4)); tracked!(move_size_limit, Some(4096)); tracked!(mutable_noalias, false); - tracked!(next_solver, NextSolverConfig { coherence: true, globally: true }); + tracked!(next_solver, Some(NextSolverConfig { coherence: true, globally: false })); tracked!(no_generate_arange_section, true); tracked!(no_jump_tables, true); tracked!(no_link, true); diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 56fcfe8e798b1..ff1aeca5a9cb3 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -3132,11 +3132,11 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn next_trait_solver_globally(self) -> bool { - self.sess.opts.unstable_opts.next_solver.globally + self.sess.opts.unstable_opts.next_solver.map_or(false, |c| c.globally) } pub fn next_trait_solver_in_coherence(self) -> bool { - self.sess.opts.unstable_opts.next_solver.coherence + self.sess.opts.unstable_opts.next_solver.map_or(false, |c| c.coherence) } pub fn is_impl_trait_in_trait(self, def_id: DefId) -> bool { diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index f3e3b36111c54..908d50a041ef1 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -842,11 +842,6 @@ pub struct NextSolverConfig { /// This is only `true` if `coherence` is also enabled. pub globally: bool, } -impl Default for NextSolverConfig { - fn default() -> Self { - NextSolverConfig { coherence: true, globally: false } - } -} #[derive(Clone)] pub enum Input { diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index a57dc80b3168d..45339c23ea3ef 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -403,7 +403,7 @@ mod desc { pub(crate) const parse_unpretty: &str = "`string` or `string=string`"; pub(crate) const parse_treat_err_as_bug: &str = "either no value or a non-negative number"; pub(crate) const parse_next_solver_config: &str = - "either `globally` (when used without an argument), `coherence` (default) or `no`"; + "a comma separated list of solver configurations: `globally` (default), and `coherence`"; pub(crate) const parse_lto: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted"; pub(crate) const parse_linker_plugin_lto: &str = @@ -1105,16 +1105,27 @@ mod parse { } } - pub(crate) fn parse_next_solver_config(slot: &mut NextSolverConfig, v: Option<&str>) -> bool { + pub(crate) fn parse_next_solver_config( + slot: &mut Option, + v: Option<&str>, + ) -> bool { if let Some(config) = v { - *slot = match config { - "no" => NextSolverConfig { coherence: false, globally: false }, - "coherence" => NextSolverConfig { coherence: true, globally: false }, - "globally" => NextSolverConfig { coherence: true, globally: true }, - _ => return false, - }; + let mut coherence = false; + let mut globally = true; + for c in config.split(',') { + match c { + "globally" => globally = true, + "coherence" => { + globally = false; + coherence = true; + } + _ => return false, + } + } + + *slot = Some(NextSolverConfig { coherence: coherence || globally, globally }); } else { - *slot = NextSolverConfig { coherence: true, globally: true }; + *slot = Some(NextSolverConfig { coherence: true, globally: true }); } true @@ -1867,7 +1878,7 @@ options! { "the size at which the `large_assignments` lint starts to be emitted"), mutable_noalias: bool = (true, parse_bool, [TRACKED], "emit noalias metadata for mutable references (default: yes)"), - next_solver: NextSolverConfig = (NextSolverConfig::default(), parse_next_solver_config, [TRACKED], + next_solver: Option = (None, parse_next_solver_config, [TRACKED], "enable and configure the next generation trait solver used by rustc"), nll_facts: bool = (false, parse_bool, [UNTRACKED], "dump facts from NLL analysis into side files (default: no)"), diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index c8811bc37b310..de1d4ef15aced 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -35,8 +35,10 @@ where if infcx.next_trait_solver() { Box::new(NextFulfillmentCtxt::new(infcx)) } else { + let new_solver_globally = + infcx.tcx.sess.opts.unstable_opts.next_solver.map_or(false, |c| c.globally); assert!( - !infcx.tcx.next_trait_solver_globally(), + !new_solver_globally, "using old solver even though new solver is enabled globally" ); Box::new(FulfillmentContext::new(infcx)) diff --git a/tests/ui/specialization/coherence/default-impl-normalization-ambig-2.rs b/tests/crashes/118987-2.rs similarity index 74% rename from tests/ui/specialization/coherence/default-impl-normalization-ambig-2.rs rename to tests/crashes/118987-2.rs index 1691530fa0a53..4382a7bcb6397 100644 --- a/tests/ui/specialization/coherence/default-impl-normalization-ambig-2.rs +++ b/tests/crashes/118987-2.rs @@ -1,4 +1,4 @@ -// regression test for #118987 +//@ known-bug: #118987 #![feature(specialization)] //~ WARN the feature `specialization` is incomplete trait Assoc { @@ -15,5 +15,3 @@ trait Foo {} impl Foo for ::Output {} impl Foo for ::Output {} -//~^ ERROR the trait bound `u16: Assoc` is not satisfied -fn main() {} diff --git a/tests/crashes/118987.rs b/tests/crashes/118987.rs new file mode 100644 index 0000000000000..4382a7bcb6397 --- /dev/null +++ b/tests/crashes/118987.rs @@ -0,0 +1,17 @@ +//@ known-bug: #118987 +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete + +trait Assoc { + type Output; +} + +default impl Assoc for T { + type Output = bool; +} + +impl Assoc for u8 {} + +trait Foo {} + +impl Foo for ::Output {} +impl Foo for ::Output {} diff --git a/tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.rs b/tests/crashes/124207.rs similarity index 62% rename from tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.rs rename to tests/crashes/124207.rs index 0cebc99cd4196..a11eedb140a68 100644 --- a/tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.rs +++ b/tests/crashes/124207.rs @@ -1,11 +1,9 @@ +//@ known-bug: #124207 #![feature(transmutability)] #![feature(type_alias_impl_trait)] trait OpaqueTrait {} type OpaqueType = impl OpaqueTrait; -//~^ ERROR unconstrained opaque type trait AnotherTrait {} impl> AnotherTrait for T {} -//~^ ERROR type provided when a constant was expected impl AnotherTrait for OpaqueType {} -//~^ ERROR conflicting implementations of trait `AnotherTrait` pub fn main() {} diff --git a/tests/ui/specialization/coherence/default-item-normalization-ambig-1.rs b/tests/crashes/74299.rs similarity index 56% rename from tests/ui/specialization/coherence/default-item-normalization-ambig-1.rs rename to tests/crashes/74299.rs index af7cf332d5f4f..0e2ddce1c5b11 100644 --- a/tests/ui/specialization/coherence/default-item-normalization-ambig-1.rs +++ b/tests/crashes/74299.rs @@ -1,5 +1,5 @@ -// regression test for #73299. -#![feature(specialization)] //~ WARN the feature `specialization` is incomplete +//@ known-bug: #74299 +#![feature(specialization)] trait X { type U; @@ -18,7 +18,6 @@ trait Y { impl Y for <() as X>::U {} impl Y for ::U {} -//~^ ERROR conflicting implementations of trait `Y` for type `<() as X>::U` fn main() { ().f().g(); diff --git a/tests/ui/associated-types/associated-types-coherence-failure.stderr b/tests/ui/associated-types/associated-types-coherence-failure.stderr index 25c22e5f82ac2..211613b371492 100644 --- a/tests/ui/associated-types/associated-types-coherence-failure.stderr +++ b/tests/ui/associated-types/associated-types-coherence-failure.stderr @@ -1,20 +1,20 @@ -error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `<_ as ToOwned>::Owned` +error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `Cow<'_, _>` --> $DIR/associated-types-coherence-failure.rs:21:1 | LL | impl<'a, B: ?Sized> IntoCow<'a, B> for ::Owned where B: ToOwned { | ----------------------------------------------------------------------------- first implementation here ... LL | impl<'a, B: ?Sized> IntoCow<'a, B> for Cow<'a, B> where B: ToOwned { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `<_ as ToOwned>::Owned` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Cow<'_, _>` -error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `<_ as ToOwned>::Owned` +error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `&_` --> $DIR/associated-types-coherence-failure.rs:28:1 | LL | impl<'a, B: ?Sized> IntoCow<'a, B> for ::Owned where B: ToOwned { | ----------------------------------------------------------------------------- first implementation here ... LL | impl<'a, B: ?Sized> IntoCow<'a, B> for &'a B where B: ToOwned { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `<_ as ToOwned>::Owned` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_` error: aborting due to 2 previous errors diff --git a/tests/ui/auto-traits/opaque_type_candidate_selection.rs b/tests/ui/auto-traits/opaque_type_candidate_selection.rs new file mode 100644 index 0000000000000..d6973b76a6e1e --- /dev/null +++ b/tests/ui/auto-traits/opaque_type_candidate_selection.rs @@ -0,0 +1,30 @@ +//! used to ICE: #119272 + +//@ check-pass + +#![feature(type_alias_impl_trait)] +mod defining_scope { + use super::*; + pub type Alias = impl Sized; + + pub fn cast(x: Container, T>) -> Container { + x + } +} + +struct Container, U> { + x: >::Assoc, +} + +trait Trait { + type Assoc; +} + +impl Trait for T { + type Assoc = Box; +} +impl Trait for defining_scope::Alias { + type Assoc = usize; +} + +fn main() {} diff --git a/tests/ui/coherence/coherence-negative-outlives-lifetimes.stock.stderr b/tests/ui/coherence/coherence-negative-outlives-lifetimes.stock.stderr index 1d28bb46812cf..dbb22d8937d54 100644 --- a/tests/ui/coherence/coherence-negative-outlives-lifetimes.stock.stderr +++ b/tests/ui/coherence/coherence-negative-outlives-lifetimes.stock.stderr @@ -5,8 +5,6 @@ LL | impl<'a, T: MyPredicate<'a>> MyTrait<'a> for T {} | ---------------------------------------------- first implementation here LL | impl<'a, T> MyTrait<'a> for &'a T {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_` - | - = note: downstream crates may implement trait `MyPredicate<'_>` for type `&_` error: aborting due to 1 previous error diff --git a/tests/ui/coherence/coherence-negative-outlives-lifetimes.with_negative_coherence.stderr b/tests/ui/coherence/coherence-negative-outlives-lifetimes.with_negative_coherence.stderr index 1d28bb46812cf..dbb22d8937d54 100644 --- a/tests/ui/coherence/coherence-negative-outlives-lifetimes.with_negative_coherence.stderr +++ b/tests/ui/coherence/coherence-negative-outlives-lifetimes.with_negative_coherence.stderr @@ -5,8 +5,6 @@ LL | impl<'a, T: MyPredicate<'a>> MyTrait<'a> for T {} | ---------------------------------------------- first implementation here LL | impl<'a, T> MyTrait<'a> for &'a T {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_` - | - = note: downstream crates may implement trait `MyPredicate<'_>` for type `&_` error: aborting due to 1 previous error diff --git a/tests/ui/coherence/coherence-overlap-downstream-inherent.stderr b/tests/ui/coherence/coherence-overlap-downstream-inherent.next.stderr similarity index 87% rename from tests/ui/coherence/coherence-overlap-downstream-inherent.stderr rename to tests/ui/coherence/coherence-overlap-downstream-inherent.next.stderr index bbce4b530b4d6..2938bc629b2cc 100644 --- a/tests/ui/coherence/coherence-overlap-downstream-inherent.stderr +++ b/tests/ui/coherence/coherence-overlap-downstream-inherent.next.stderr @@ -1,5 +1,5 @@ error[E0592]: duplicate definitions with name `dummy` - --> $DIR/coherence-overlap-downstream-inherent.rs:7:26 + --> $DIR/coherence-overlap-downstream-inherent.rs:10:26 | LL | impl Sweet { fn dummy(&self) { } } | ^^^^^^^^^^^^^^^ duplicate definitions for `dummy` @@ -8,7 +8,7 @@ LL | impl Sweet { fn dummy(&self) { } } | --------------- other definition for `dummy` error[E0592]: duplicate definitions with name `f` - --> $DIR/coherence-overlap-downstream-inherent.rs:13:38 + --> $DIR/coherence-overlap-downstream-inherent.rs:16:38 | LL | impl A where T: Bar { fn f(&self) {} } | ^^^^^^^^^^^ duplicate definitions for `f` diff --git a/tests/ui/coherence/coherence-overlap-downstream-inherent.old.stderr b/tests/ui/coherence/coherence-overlap-downstream-inherent.old.stderr new file mode 100644 index 0000000000000..2938bc629b2cc --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-downstream-inherent.old.stderr @@ -0,0 +1,23 @@ +error[E0592]: duplicate definitions with name `dummy` + --> $DIR/coherence-overlap-downstream-inherent.rs:10:26 + | +LL | impl Sweet { fn dummy(&self) { } } + | ^^^^^^^^^^^^^^^ duplicate definitions for `dummy` +LL | +LL | impl Sweet { fn dummy(&self) { } } + | --------------- other definition for `dummy` + +error[E0592]: duplicate definitions with name `f` + --> $DIR/coherence-overlap-downstream-inherent.rs:16:38 + | +LL | impl A where T: Bar { fn f(&self) {} } + | ^^^^^^^^^^^ duplicate definitions for `f` +LL | +LL | impl A { fn f(&self) {} } + | ----------- other definition for `f` + | + = note: downstream crates may implement trait `Bar<_>` for type `i32` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0592`. diff --git a/tests/ui/coherence/coherence-overlap-downstream-inherent.rs b/tests/ui/coherence/coherence-overlap-downstream-inherent.rs index 5dea33e330b62..3e90b7c7fdd32 100644 --- a/tests/ui/coherence/coherence-overlap-downstream-inherent.rs +++ b/tests/ui/coherence/coherence-overlap-downstream-inherent.rs @@ -1,3 +1,6 @@ +//@ revisions: old next +//@[next] compile-flags: -Znext-solver + // Tests that we consider `T: Sugar + Fruit` to be ambiguous, even // though no impls are found. diff --git a/tests/ui/coherence/coherence-overlap-downstream.stderr b/tests/ui/coherence/coherence-overlap-downstream.next.stderr similarity index 88% rename from tests/ui/coherence/coherence-overlap-downstream.stderr rename to tests/ui/coherence/coherence-overlap-downstream.next.stderr index 9ab099489d9e5..6c2e9466b4bde 100644 --- a/tests/ui/coherence/coherence-overlap-downstream.stderr +++ b/tests/ui/coherence/coherence-overlap-downstream.next.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Sweet` - --> $DIR/coherence-overlap-downstream.rs:8:1 + --> $DIR/coherence-overlap-downstream.rs:11:1 | LL | impl Sweet for T { } | ------------------------- first implementation here @@ -7,7 +7,7 @@ LL | impl Sweet for T { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation error[E0119]: conflicting implementations of trait `Foo<_>` for type `i32` - --> $DIR/coherence-overlap-downstream.rs:14:1 + --> $DIR/coherence-overlap-downstream.rs:17:1 | LL | impl Foo for T where T: Bar {} | --------------------------------------- first implementation here diff --git a/tests/ui/coherence/coherence-overlap-downstream.old.stderr b/tests/ui/coherence/coherence-overlap-downstream.old.stderr new file mode 100644 index 0000000000000..6c2e9466b4bde --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-downstream.old.stderr @@ -0,0 +1,21 @@ +error[E0119]: conflicting implementations of trait `Sweet` + --> $DIR/coherence-overlap-downstream.rs:11:1 + | +LL | impl Sweet for T { } + | ------------------------- first implementation here +LL | impl Sweet for T { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation + +error[E0119]: conflicting implementations of trait `Foo<_>` for type `i32` + --> $DIR/coherence-overlap-downstream.rs:17:1 + | +LL | impl Foo for T where T: Bar {} + | --------------------------------------- first implementation here +LL | impl Foo for i32 {} + | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `i32` + | + = note: downstream crates may implement trait `Bar<_>` for type `i32` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-overlap-downstream.rs b/tests/ui/coherence/coherence-overlap-downstream.rs index 738ec0e3d4550..8b99296d12a4f 100644 --- a/tests/ui/coherence/coherence-overlap-downstream.rs +++ b/tests/ui/coherence/coherence-overlap-downstream.rs @@ -1,3 +1,6 @@ +//@ revisions: old next +//@[next] compile-flags: -Znext-solver + // Tests that we consider `T: Sugar + Fruit` to be ambiguous, even // though no impls are found. diff --git a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.stderr b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.next.stderr similarity index 90% rename from tests/ui/coherence/coherence-overlap-issue-23516-inherent.stderr rename to tests/ui/coherence/coherence-overlap-issue-23516-inherent.next.stderr index aacdeb5b0f971..2f3ad6278088f 100644 --- a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.stderr +++ b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.next.stderr @@ -1,5 +1,5 @@ error[E0592]: duplicate definitions with name `dummy` - --> $DIR/coherence-overlap-issue-23516-inherent.rs:9:25 + --> $DIR/coherence-overlap-issue-23516-inherent.rs:12:25 | LL | impl Cake { fn dummy(&self) { } } | ^^^^^^^^^^^^^^^ duplicate definitions for `dummy` diff --git a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.old.stderr b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.old.stderr new file mode 100644 index 0000000000000..2f3ad6278088f --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.old.stderr @@ -0,0 +1,14 @@ +error[E0592]: duplicate definitions with name `dummy` + --> $DIR/coherence-overlap-issue-23516-inherent.rs:12:25 + | +LL | impl Cake { fn dummy(&self) { } } + | ^^^^^^^^^^^^^^^ duplicate definitions for `dummy` +LL | +LL | impl Cake> { fn dummy(&self) { } } + | --------------- other definition for `dummy` + | + = note: downstream crates may implement trait `Sugar` for type `std::boxed::Box<_>` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0592`. diff --git a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.rs b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.rs index a272e620fcab3..53b0a40fa6611 100644 --- a/tests/ui/coherence/coherence-overlap-issue-23516-inherent.rs +++ b/tests/ui/coherence/coherence-overlap-issue-23516-inherent.rs @@ -1,3 +1,6 @@ +//@ revisions: old next +//@[next] compile-flags: -Znext-solver + // Tests that we consider `Box: !Sugar` to be ambiguous, even // though we see no impl of `Sugar` for `Box`. Therefore, an overlap // error is reported for the following pair of impls (#23516). diff --git a/tests/ui/coherence/coherence-overlap-issue-23516.stderr b/tests/ui/coherence/coherence-overlap-issue-23516.next.stderr similarity index 90% rename from tests/ui/coherence/coherence-overlap-issue-23516.stderr rename to tests/ui/coherence/coherence-overlap-issue-23516.next.stderr index 7b1b240291a87..b949477402549 100644 --- a/tests/ui/coherence/coherence-overlap-issue-23516.stderr +++ b/tests/ui/coherence/coherence-overlap-issue-23516.next.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Sweet` for type `Box<_>` - --> $DIR/coherence-overlap-issue-23516.rs:8:1 + --> $DIR/coherence-overlap-issue-23516.rs:11:1 | LL | impl Sweet for T { } | ------------------------- first implementation here diff --git a/tests/ui/coherence/coherence-overlap-issue-23516.old.stderr b/tests/ui/coherence/coherence-overlap-issue-23516.old.stderr new file mode 100644 index 0000000000000..b949477402549 --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-issue-23516.old.stderr @@ -0,0 +1,13 @@ +error[E0119]: conflicting implementations of trait `Sweet` for type `Box<_>` + --> $DIR/coherence-overlap-issue-23516.rs:11:1 + | +LL | impl Sweet for T { } + | ------------------------- first implementation here +LL | impl Sweet for Box { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>` + | + = note: downstream crates may implement trait `Sugar` for type `std::boxed::Box<_>` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-overlap-issue-23516.rs b/tests/ui/coherence/coherence-overlap-issue-23516.rs index 63e42e8f412dd..620e00cd0572b 100644 --- a/tests/ui/coherence/coherence-overlap-issue-23516.rs +++ b/tests/ui/coherence/coherence-overlap-issue-23516.rs @@ -1,3 +1,6 @@ +//@ revisions: old next +//@[next] compile-flags: -Znext-solver + // Tests that we consider `Box: !Sugar` to be ambiguous, even // though we see no impl of `Sugar` for `Box`. Therefore, an overlap // error is reported for the following pair of impls (#23516). diff --git a/tests/ui/coherence/coherence-overlap-negate-not-use-feature-gate.stderr b/tests/ui/coherence/coherence-overlap-negate-not-use-feature-gate.stderr index c5bb695eb1882..21c82eedd5df5 100644 --- a/tests/ui/coherence/coherence-overlap-negate-not-use-feature-gate.stderr +++ b/tests/ui/coherence/coherence-overlap-negate-not-use-feature-gate.stderr @@ -5,8 +5,6 @@ LL | impl Foo for T {} | --------------------------- first implementation here LL | impl Foo for &U {} | ^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_` - | - = note: downstream crates may implement trait `std::ops::DerefMut` for type `&_` error: aborting due to 1 previous error diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.classic.stderr b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.classic.stderr new file mode 100644 index 0000000000000..2ffb6000ec822 --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.classic.stderr @@ -0,0 +1,19 @@ +error[E0119]: conflicting implementations of trait `Trait` for type `Box<_>` + --> $DIR/coherence-overlap-unnormalizable-projection-0.rs:27:1 + | +LL | / impl Trait for T +LL | | where +LL | | T: 'static, +LL | | for<'a> T: WithAssoc<'a>, +LL | | for<'a> >::Assoc: WhereBound, + | |____________________________________________________- first implementation here +... +LL | impl Trait for Box {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>` + | + = note: downstream crates may implement trait `WithAssoc<'a>` for type `std::boxed::Box<_>` + = note: downstream crates may implement trait `WhereBound` for type ` as WithAssoc<'a>>::Assoc` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.stderr b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.next.stderr similarity index 91% rename from tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.stderr rename to tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.next.stderr index 57befbe6e68dd..99abdf65abd5f 100644 --- a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.stderr +++ b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.next.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Trait` for type `Box<_>` - --> $DIR/coherence-overlap-unnormalizable-projection-0.rs:24:1 + --> $DIR/coherence-overlap-unnormalizable-projection-0.rs:27:1 | LL | / impl Trait for T LL | | where diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.rs b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.rs index 0695076e221e2..b8b6d8846ef78 100644 --- a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.rs +++ b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-0.rs @@ -2,6 +2,9 @@ // "Coherence incorrectly considers `unnormalizable_projection: Trait` to not hold even if it could" #![crate_type = "lib"] +//@ revisions: classic next +//@[next] compile-flags: -Znext-solver + trait WhereBound {} impl WhereBound for () {} diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.classic.stderr b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.classic.stderr new file mode 100644 index 0000000000000..49b236f9d2aa2 --- /dev/null +++ b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.classic.stderr @@ -0,0 +1,19 @@ +error[E0119]: conflicting implementations of trait `Trait` for type `Box<_>` + --> $DIR/coherence-overlap-unnormalizable-projection-1.rs:26:1 + | +LL | / impl Trait for T +LL | | where +LL | | T: 'static, +LL | | for<'a> T: WithAssoc<'a>, +LL | | for<'a> Box<>::Assoc>: WhereBound, + | |_________________________________________________________- first implementation here +... +LL | impl Trait for Box {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>` + | + = note: downstream crates may implement trait `WithAssoc<'a>` for type `std::boxed::Box<_>` + = note: downstream crates may implement trait `WhereBound` for type `std::boxed::Box< as WithAssoc<'a>>::Assoc>` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.stderr b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.next.stderr similarity index 92% rename from tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.stderr rename to tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.next.stderr index 22673cef64079..781ab0fcbf766 100644 --- a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.stderr +++ b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.next.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Trait` for type `Box<_>` - --> $DIR/coherence-overlap-unnormalizable-projection-1.rs:23:1 + --> $DIR/coherence-overlap-unnormalizable-projection-1.rs:26:1 | LL | / impl Trait for T LL | | where diff --git a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.rs b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.rs index f5fb5aefb5c39..8eeadb3dc7542 100644 --- a/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.rs +++ b/tests/ui/coherence/coherence-overlap-unnormalizable-projection-1.rs @@ -2,6 +2,9 @@ // "Coherence incorrectly considers `unnormalizable_projection: Trait` to not hold even if it could" #![crate_type = "lib"] +//@ revisions: classic next +//@[next] compile-flags: -Znext-solver + pub trait WhereBound {} impl WhereBound for () {} diff --git a/tests/ui/coherence/coherent-due-to-fulfill.rs b/tests/ui/coherence/coherent-due-to-fulfill.rs index f4555ee5171cb..084f9be0a8c3f 100644 --- a/tests/ui/coherence/coherent-due-to-fulfill.rs +++ b/tests/ui/coherence/coherent-due-to-fulfill.rs @@ -1,4 +1,6 @@ +//@ compile-flags: -Znext-solver=coherence //@ check-pass + trait Mirror { type Assoc; } diff --git a/tests/ui/coherence/incoherent-even-though-we-fulfill.rs b/tests/ui/coherence/incoherent-even-though-we-fulfill.rs index 28e5b6d3db09b..b3c9cf328c21c 100644 --- a/tests/ui/coherence/incoherent-even-though-we-fulfill.rs +++ b/tests/ui/coherence/incoherent-even-though-we-fulfill.rs @@ -1,3 +1,5 @@ +//@ compile-flags: -Znext-solver=coherence + trait Mirror { type Assoc; } diff --git a/tests/ui/coherence/incoherent-even-though-we-fulfill.stderr b/tests/ui/coherence/incoherent-even-though-we-fulfill.stderr index 0b15a4e100ed1..b16465d201140 100644 --- a/tests/ui/coherence/incoherent-even-though-we-fulfill.stderr +++ b/tests/ui/coherence/incoherent-even-though-we-fulfill.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Foo` for type `()` - --> $DIR/incoherent-even-though-we-fulfill.rs:15:1 + --> $DIR/incoherent-even-though-we-fulfill.rs:17:1 | LL | impl Foo for T where (): Mirror {} | --------------------------------------------- first implementation here diff --git a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.stderr b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.next.stderr similarity index 90% rename from tests/ui/coherence/inter-crate-ambiguity-causes-notes.stderr rename to tests/ui/coherence/inter-crate-ambiguity-causes-notes.next.stderr index b32283274c699..74be598c44c76 100644 --- a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.stderr +++ b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.next.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `From<()>` for type `S` - --> $DIR/inter-crate-ambiguity-causes-notes.rs:9:1 + --> $DIR/inter-crate-ambiguity-causes-notes.rs:12:1 | LL | impl From<()> for S { | ------------------- first implementation here diff --git a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.old.stderr b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.old.stderr new file mode 100644 index 0000000000000..74be598c44c76 --- /dev/null +++ b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.old.stderr @@ -0,0 +1,17 @@ +error[E0119]: conflicting implementations of trait `From<()>` for type `S` + --> $DIR/inter-crate-ambiguity-causes-notes.rs:12:1 + | +LL | impl From<()> for S { + | ------------------- first implementation here +... +LL | / impl From for S +LL | | +LL | | where +LL | | I: Iterator, + | |___________________________^ conflicting implementation for `S` + | + = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `()` in future versions + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.rs b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.rs index 5b11c78ab2605..3dead2f0d19ce 100644 --- a/tests/ui/coherence/inter-crate-ambiguity-causes-notes.rs +++ b/tests/ui/coherence/inter-crate-ambiguity-causes-notes.rs @@ -1,3 +1,6 @@ +//@ revisions: old next +//@[next] compile-flags: -Znext-solver + struct S; impl From<()> for S { diff --git a/tests/ui/coherence/negative-coherence-check-placeholder-outlives.stderr b/tests/ui/coherence/negative-coherence-check-placeholder-outlives.stderr index bf1ffcb5f0008..f515c39ea8d10 100644 --- a/tests/ui/coherence/negative-coherence-check-placeholder-outlives.stderr +++ b/tests/ui/coherence/negative-coherence-check-placeholder-outlives.stderr @@ -5,8 +5,6 @@ LL | impl Bar for T where T: Foo {} | ------------------------------ first implementation here LL | impl Bar for Box {} | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<_>` - | - = note: downstream crates may implement trait `Foo` for type `std::boxed::Box<_>` error: aborting due to 1 previous error diff --git a/tests/ui/coherence/negative-coherence-considering-regions.any_lt.stderr b/tests/ui/coherence/negative-coherence-considering-regions.any_lt.stderr index 97e2e9759c174..f24de10f6ac48 100644 --- a/tests/ui/coherence/negative-coherence-considering-regions.any_lt.stderr +++ b/tests/ui/coherence/negative-coherence-considering-regions.any_lt.stderr @@ -6,8 +6,6 @@ LL | impl Bar for T where T: Foo {} ... LL | impl Bar for &T {} | ^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_` - | - = note: downstream crates may implement trait `Foo` for type `&_` error: aborting due to 1 previous error diff --git a/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.explicit.stderr b/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.explicit.stderr index 8d59cbc3466ba..832c56a45549b 100644 --- a/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.explicit.stderr +++ b/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.explicit.stderr @@ -8,7 +8,6 @@ LL | impl FnMarker for fn(&T) {} | = warning: the behavior may change in a future release = note: for more information, see issue #56105 - = note: downstream crates may implement trait `Marker` for type `&_` = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details note: the lint level is defined here --> $DIR/negative-coherence-placeholder-region-constraints-on-unification.rs:4:11 diff --git a/tests/ui/coherence/normalize-for-errors.current.stderr b/tests/ui/coherence/normalize-for-errors.current.stderr new file mode 100644 index 0000000000000..dcbb73bd1ff10 --- /dev/null +++ b/tests/ui/coherence/normalize-for-errors.current.stderr @@ -0,0 +1,14 @@ +error[E0119]: conflicting implementations of trait `MyTrait<_>` for type `(Box<(MyType,)>, _)` + --> $DIR/normalize-for-errors.rs:17:1 + | +LL | impl MyTrait for (T, S::Item) {} + | ------------------------------------------------------ first implementation here +LL | +LL | impl MyTrait for (Box<<(MyType,) as Mirror>::Assoc>, S::Item) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(Box<(MyType,)>, _)` + | + = note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/normalize-for-errors.stderr b/tests/ui/coherence/normalize-for-errors.next.stderr similarity index 95% rename from tests/ui/coherence/normalize-for-errors.stderr rename to tests/ui/coherence/normalize-for-errors.next.stderr index 6fbcf5b0e1aca..44952dc194456 100644 --- a/tests/ui/coherence/normalize-for-errors.stderr +++ b/tests/ui/coherence/normalize-for-errors.next.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `MyTrait<_>` for type `(Box<(MyType,)>, <_ as Iterator>::Item)` - --> $DIR/normalize-for-errors.rs:13:1 + --> $DIR/normalize-for-errors.rs:17:1 | LL | impl MyTrait for (T, S::Item) {} | ------------------------------------------------------ first implementation here diff --git a/tests/ui/coherence/normalize-for-errors.rs b/tests/ui/coherence/normalize-for-errors.rs index 3ef91eb0386c0..c17bb766b5bcd 100644 --- a/tests/ui/coherence/normalize-for-errors.rs +++ b/tests/ui/coherence/normalize-for-errors.rs @@ -1,3 +1,7 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + struct MyType; trait MyTrait {} @@ -14,6 +18,6 @@ impl MyTrait for (Box<<(MyType,) as Mirror>::Assoc>, S::Item) {} //~^ ERROR conflicting implementations of trait `MyTrait<_>` for type `(Box<(MyType,)>, //~| NOTE conflicting implementation for `(Box<(MyType,)>, //~| NOTE upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions -//~| NOTE upstream crates may add a new impl of trait `std::clone::Clone` for type `std::boxed::Box<(MyType,)>` in future versions +//[next]~| NOTE upstream crates may add a new impl of trait `std::clone::Clone` for type `std::boxed::Box<(MyType,)>` in future versions fn main() {} diff --git a/tests/ui/coherence/occurs-check/associated-type.next.stderr b/tests/ui/coherence/occurs-check/associated-type.next.stderr index 466b991471ed9..9544bdbb468de 100644 --- a/tests/ui/coherence/occurs-check/associated-type.next.stderr +++ b/tests/ui/coherence/occurs-check/associated-type.next.stderr @@ -3,7 +3,7 @@ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } error[E0119]: conflicting implementations of trait `Overlap fn(&'a (), ())>` for type `for<'a> fn(&'a (), ())` - --> $DIR/associated-type.rs:32:1 + --> $DIR/associated-type.rs:31:1 | LL | impl Overlap for T { | ------------------------ first implementation here @@ -17,7 +17,7 @@ LL | | for<'a> *const T: ToUnit<'a>, = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details error[E0284]: type annotations needed: cannot normalize ` fn(&'a (), ()) as Overlap fn(&'a (), ())>>::Assoc` - --> $DIR/associated-type.rs:45:59 + --> $DIR/associated-type.rs:44:59 | LL | foo:: fn(&'a (), ()), for<'a> fn(&'a (), ())>(3usize); | ^^^^^^ cannot normalize ` fn(&'a (), ()) as Overlap fn(&'a (), ())>>::Assoc` diff --git a/tests/ui/coherence/occurs-check/associated-type.old.stderr b/tests/ui/coherence/occurs-check/associated-type.old.stderr index 1e0345f4ec05b..ccc7f30fa6fdb 100644 --- a/tests/ui/coherence/occurs-check/associated-type.old.stderr +++ b/tests/ui/coherence/occurs-check/associated-type.old.stderr @@ -1,9 +1,13 @@ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, '^0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } -error[E0119]: conflicting implementations of trait `Overlap fn(&'a (), ())>` for type `for<'a> fn(&'a (), ())` - --> $DIR/associated-type.rs:32:1 + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [*const ?1t, !2_0.Named(DefId(0:27 ~ associated_type[f554]::{impl#3}::'a#1), "'a")], def_id: DefId(0:5 ~ associated_type[f554]::ToUnit::Unit), .. } +error[E0119]: conflicting implementations of trait `Overlap fn(&'a (), _)>` for type `for<'a> fn(&'a (), _)` + --> $DIR/associated-type.rs:31:1 | LL | impl Overlap for T { | ------------------------ first implementation here @@ -12,7 +16,7 @@ LL | / impl Overlap fn(&'a (), Assoc<'a, T>)> for T LL | | LL | | where LL | | for<'a> *const T: ToUnit<'a>, - | |_________________________________^ conflicting implementation for `for<'a> fn(&'a (), ())` + | |_________________________________^ conflicting implementation for `for<'a> fn(&'a (), _)` | = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details diff --git a/tests/ui/coherence/occurs-check/associated-type.rs b/tests/ui/coherence/occurs-check/associated-type.rs index e450c33e80934..df03d5f60a028 100644 --- a/tests/ui/coherence/occurs-check/associated-type.rs +++ b/tests/ui/coherence/occurs-check/associated-type.rs @@ -1,5 +1,4 @@ //@ revisions: old next -//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver // A regression test for #105787 diff --git a/tests/ui/coherence/occurs-check/opaques.current.stderr b/tests/ui/coherence/occurs-check/opaques.current.stderr deleted file mode 100644 index f3fc22027c26a..0000000000000 --- a/tests/ui/coherence/occurs-check/opaques.current.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0119]: conflicting implementations of trait `Trait<_>` - --> $DIR/opaques.rs:28:1 - | -LL | impl Trait for T { - | ---------------------- first implementation here -... -LL | impl Trait for defining_scope::Alias { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/occurs-check/opaques.next.stderr b/tests/ui/coherence/occurs-check/opaques.next.stderr index 3de479963bb44..11d1edcca2f91 100644 --- a/tests/ui/coherence/occurs-check/opaques.next.stderr +++ b/tests/ui/coherence/occurs-check/opaques.next.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Trait<_>` - --> $DIR/opaques.rs:28:1 + --> $DIR/opaques.rs:30:1 | LL | impl Trait for T { | ---------------------- first implementation here @@ -8,7 +8,7 @@ LL | impl Trait for defining_scope::Alias { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation error[E0282]: type annotations needed - --> $DIR/opaques.rs:11:20 + --> $DIR/opaques.rs:13:20 | LL | pub fn cast(x: Container, T>) -> Container { | ^ cannot infer type diff --git a/tests/ui/coherence/occurs-check/opaques.rs b/tests/ui/coherence/occurs-check/opaques.rs index e197256c78c77..241a247c84130 100644 --- a/tests/ui/coherence/occurs-check/opaques.rs +++ b/tests/ui/coherence/occurs-check/opaques.rs @@ -1,8 +1,10 @@ -//@ revisions: current next -//@ ignore-compare-mode-next-solver (explicit revisions) +//@revisions: old next //@[next] compile-flags: -Znext-solver // A regression test for #105787 + +//@[old] known-bug: #105787 +//@[old] check-pass #![feature(type_alias_impl_trait)] mod defining_scope { use super::*; @@ -26,7 +28,7 @@ impl Trait for T { type Assoc = Box; } impl Trait for defining_scope::Alias { - //~^ ERROR conflicting implementations of trait + //[next]~^ ERROR conflicting implementations of trait type Assoc = usize; } diff --git a/tests/ui/coherence/orphan-check-opaque-types-not-covering.stderr b/tests/ui/coherence/orphan-check-opaque-types-not-covering.classic.stderr similarity index 92% rename from tests/ui/coherence/orphan-check-opaque-types-not-covering.stderr rename to tests/ui/coherence/orphan-check-opaque-types-not-covering.classic.stderr index 57f5bbd227875..44f76f321cf10 100644 --- a/tests/ui/coherence/orphan-check-opaque-types-not-covering.stderr +++ b/tests/ui/coherence/orphan-check-opaque-types-not-covering.classic.stderr @@ -1,5 +1,5 @@ error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) - --> $DIR/orphan-check-opaque-types-not-covering.rs:14:6 + --> $DIR/orphan-check-opaque-types-not-covering.rs:17:6 | LL | impl foreign::Trait0 for Identity {} | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) @@ -8,7 +8,7 @@ LL | impl foreign::Trait0 for Identity {} = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, where `T0` is the first and `Tn` is the last error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) - --> $DIR/orphan-check-opaque-types-not-covering.rs:23:6 + --> $DIR/orphan-check-opaque-types-not-covering.rs:26:6 | LL | impl foreign::Trait1 for Opaque {} | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) diff --git a/tests/ui/coherence/orphan-check-opaque-types-not-covering.next.stderr b/tests/ui/coherence/orphan-check-opaque-types-not-covering.next.stderr new file mode 100644 index 0000000000000..44f76f321cf10 --- /dev/null +++ b/tests/ui/coherence/orphan-check-opaque-types-not-covering.next.stderr @@ -0,0 +1,21 @@ +error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + --> $DIR/orphan-check-opaque-types-not-covering.rs:17:6 + | +LL | impl foreign::Trait0 for Identity {} + | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type + = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, where `T0` is the first and `Tn` is the last + +error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + --> $DIR/orphan-check-opaque-types-not-covering.rs:26:6 + | +LL | impl foreign::Trait1 for Opaque {} + | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type + = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, where `T0` is the first and `Tn` is the last + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/orphan-check-opaque-types-not-covering.rs b/tests/ui/coherence/orphan-check-opaque-types-not-covering.rs index 02e9eb65570c0..8dc02b081c51d 100644 --- a/tests/ui/coherence/orphan-check-opaque-types-not-covering.rs +++ b/tests/ui/coherence/orphan-check-opaque-types-not-covering.rs @@ -1,5 +1,8 @@ // Opaque types never cover type parameters. +//@ revisions: classic next +//@[next] compile-flags: -Znext-solver + //@ aux-crate:foreign=parametrized-trait.rs //@ edition:2021 diff --git a/tests/ui/coherence/orphan-check-projections-covering.rs b/tests/ui/coherence/orphan-check-projections-covering.rs index 804784463a1b5..ae1917ec161f1 100644 --- a/tests/ui/coherence/orphan-check-projections-covering.rs +++ b/tests/ui/coherence/orphan-check-projections-covering.rs @@ -5,6 +5,9 @@ // first which would've lead to real-word regressions. //@ check-pass +//@ revisions: classic next +//@[next] compile-flags: -Znext-solver + //@ aux-crate:foreign=parametrized-trait.rs //@ edition:2021 diff --git a/tests/ui/coherence/orphan-check-weak-aliases-not-covering.stderr b/tests/ui/coherence/orphan-check-weak-aliases-not-covering.classic.stderr similarity index 92% rename from tests/ui/coherence/orphan-check-weak-aliases-not-covering.stderr rename to tests/ui/coherence/orphan-check-weak-aliases-not-covering.classic.stderr index df915141a769f..276833fa17122 100644 --- a/tests/ui/coherence/orphan-check-weak-aliases-not-covering.stderr +++ b/tests/ui/coherence/orphan-check-weak-aliases-not-covering.classic.stderr @@ -1,5 +1,5 @@ error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) - --> $DIR/orphan-check-weak-aliases-not-covering.rs:13:6 + --> $DIR/orphan-check-weak-aliases-not-covering.rs:16:6 | LL | impl foreign::Trait1 for Identity {} | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) diff --git a/tests/ui/coherence/orphan-check-weak-aliases-not-covering.next.stderr b/tests/ui/coherence/orphan-check-weak-aliases-not-covering.next.stderr new file mode 100644 index 0000000000000..276833fa17122 --- /dev/null +++ b/tests/ui/coherence/orphan-check-weak-aliases-not-covering.next.stderr @@ -0,0 +1,12 @@ +error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + --> $DIR/orphan-check-weak-aliases-not-covering.rs:16:6 + | +LL | impl foreign::Trait1 for Identity {} + | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + | + = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type + = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, where `T0` is the first and `Tn` is the last + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/orphan-check-weak-aliases-not-covering.rs b/tests/ui/coherence/orphan-check-weak-aliases-not-covering.rs index 6d9bccc4c689e..9ebc45a882937 100644 --- a/tests/ui/coherence/orphan-check-weak-aliases-not-covering.rs +++ b/tests/ui/coherence/orphan-check-weak-aliases-not-covering.rs @@ -1,5 +1,8 @@ // Weak aliases might not cover type parameters. +//@ revisions: classic next +//@[next] compile-flags: -Znext-solver + //@ aux-crate:foreign=parametrized-trait.rs //@ edition:2021 diff --git a/tests/ui/coherence/skip-reporting-if-references-err.current.stderr b/tests/ui/coherence/skip-reporting-if-references-err.current.stderr new file mode 100644 index 0000000000000..5eef3256b2c36 --- /dev/null +++ b/tests/ui/coherence/skip-reporting-if-references-err.current.stderr @@ -0,0 +1,27 @@ +error[E0726]: implicit elided lifetime not allowed here + --> $DIR/skip-reporting-if-references-err.rs:10:9 + | +LL | impl ToUnit for T {} + | ^^^^^^ expected lifetime parameter + | +help: indicate the anonymous lifetime + | +LL | impl ToUnit<'_> for T {} + | ++++ + +error[E0277]: the trait bound `for<'a> (): ToUnit<'a>` is not satisfied + --> $DIR/skip-reporting-if-references-err.rs:15:29 + | +LL | impl Overlap for for<'a> fn(<() as ToUnit<'a>>::Unit) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `()` + +error[E0277]: the trait bound `for<'a> (): ToUnit<'a>` is not satisfied + --> $DIR/skip-reporting-if-references-err.rs:15:18 + | +LL | impl Overlap for for<'a> fn(<() as ToUnit<'a>>::Unit) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `()` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0277, E0726. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/coherence/skip-reporting-if-references-err.stderr b/tests/ui/coherence/skip-reporting-if-references-err.next.stderr similarity index 87% rename from tests/ui/coherence/skip-reporting-if-references-err.stderr rename to tests/ui/coherence/skip-reporting-if-references-err.next.stderr index 0ff3e88a0af92..5de4cf626e481 100644 --- a/tests/ui/coherence/skip-reporting-if-references-err.stderr +++ b/tests/ui/coherence/skip-reporting-if-references-err.next.stderr @@ -1,5 +1,5 @@ error[E0726]: implicit elided lifetime not allowed here - --> $DIR/skip-reporting-if-references-err.rs:6:9 + --> $DIR/skip-reporting-if-references-err.rs:10:9 | LL | impl ToUnit for T {} | ^^^^^^ expected lifetime parameter diff --git a/tests/ui/coherence/skip-reporting-if-references-err.rs b/tests/ui/coherence/skip-reporting-if-references-err.rs index dd8a71c4700f4..f9eaa498232da 100644 --- a/tests/ui/coherence/skip-reporting-if-references-err.rs +++ b/tests/ui/coherence/skip-reporting-if-references-err.rs @@ -1,4 +1,8 @@ // Regression test for #121006. +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + trait ToUnit<'a> { type Unit; } @@ -9,5 +13,7 @@ impl ToUnit for T {} trait Overlap {} impl Overlap for fn(U) {} impl Overlap for for<'a> fn(<() as ToUnit<'a>>::Unit) {} +//[current]~^ ERROR the trait bound `for<'a> (): ToUnit<'a>` is not satisfied +//[current]~| ERROR the trait bound `for<'a> (): ToUnit<'a>` is not satisfied fn main() {} diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-1.current.stderr b/tests/ui/coherence/super-traits/super-trait-knowable-1.current.stderr new file mode 100644 index 0000000000000..fb01cf158d980 --- /dev/null +++ b/tests/ui/coherence/super-traits/super-trait-knowable-1.current.stderr @@ -0,0 +1,13 @@ +error[E0119]: conflicting implementations of trait `Overlap<_>` for type `()` + --> $DIR/super-trait-knowable-1.rs:16:1 + | +LL | impl> Overlap for U {} + | ----------------------------------- first implementation here +LL | impl Overlap for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` + | + = note: downstream crates may implement trait `Sub<_>` for type `()` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-1.rs b/tests/ui/coherence/super-traits/super-trait-knowable-1.rs index 77af4d0f2e3a6..80df8c19ee51f 100644 --- a/tests/ui/coherence/super-traits/super-trait-knowable-1.rs +++ b/tests/ui/coherence/super-traits/super-trait-knowable-1.rs @@ -3,7 +3,10 @@ // We therefore elaborate super trait bounds in the implicit negative // overlap check. -//@ check-pass +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] check-pass trait Super {} trait Sub: Super {} @@ -11,5 +14,6 @@ trait Sub: Super {} trait Overlap {} impl> Overlap for U {} impl Overlap for () {} +//[current]~^ ERROR conflicting implementations fn main() {} diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-2.rs b/tests/ui/coherence/super-traits/super-trait-knowable-2.rs index 323ee0b10c9f4..d1f2e8d1c1a15 100644 --- a/tests/ui/coherence/super-traits/super-trait-knowable-2.rs +++ b/tests/ui/coherence/super-traits/super-trait-knowable-2.rs @@ -9,6 +9,9 @@ // which caused the old solver to emit a `Tensor: TensorValue` goal in // `fn normalize_to_error` which then failed, causing this test to pass. +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver //@ check-pass pub trait TensorValue { diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-3.current.stderr b/tests/ui/coherence/super-traits/super-trait-knowable-3.current.stderr new file mode 100644 index 0000000000000..542edb8b7f674 --- /dev/null +++ b/tests/ui/coherence/super-traits/super-trait-knowable-3.current.stderr @@ -0,0 +1,13 @@ +error[E0119]: conflicting implementations of trait `Overlap<_>` for type `()` + --> $DIR/super-trait-knowable-3.rs:19:1 + | +LL | impl>> Overlap for U {} + | ---------------------------------------- first implementation here +LL | impl Overlap for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` + | + = note: downstream crates may implement trait `Sub<_>` for type `()` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-3.rs b/tests/ui/coherence/super-traits/super-trait-knowable-3.rs index 6198d3d303bd1..295d7ac48d8cc 100644 --- a/tests/ui/coherence/super-traits/super-trait-knowable-3.rs +++ b/tests/ui/coherence/super-traits/super-trait-knowable-3.rs @@ -2,7 +2,10 @@ // super trait bound is in a nested goal so this would not // compile if we were to only elaborate root goals. -//@ check-pass +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] check-pass trait Super {} trait Sub: Super {} @@ -14,5 +17,6 @@ impl, U> Bound> for T {} trait Overlap {} impl>> Overlap for U {} impl Overlap for () {} +//[current]~^ ERROR conflicting implementations of trait `Overlap<_>` for type `()` fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs index 42c930f952d16..05a3487ffca51 100644 --- a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs +++ b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs @@ -22,7 +22,6 @@ mod v20 { impl v17<512, v0> { pub const fn v21() -> v18 {} //~^ ERROR cannot find type `v18` in this scope - //~| ERROR duplicate definitions with name `v21` } impl v17 { diff --git a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr index b336f2b3fca59..39f022fbee9db 100644 --- a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr +++ b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr @@ -1,5 +1,5 @@ error[E0432]: unresolved import `v20::v13` - --> $DIR/unevaluated-const-ice-119731.rs:38:15 + --> $DIR/unevaluated-const-ice-119731.rs:37:15 | LL | pub use v20::{v13, v17}; | ^^^ @@ -23,7 +23,7 @@ LL | pub const fn v21() -> v18 {} | ^^^ help: a type alias with a similar name exists: `v11` error[E0412]: cannot find type `v18` in this scope - --> $DIR/unevaluated-const-ice-119731.rs:31:31 + --> $DIR/unevaluated-const-ice-119731.rs:30:31 | LL | pub type v11 = [[usize; v4]; v4]; | --------------------------------- similarly named type alias `v11` defined here @@ -32,7 +32,7 @@ LL | pub const fn v21() -> v18 { | ^^^ help: a type alias with a similar name exists: `v11` error[E0422]: cannot find struct, variant or union type `v18` in this scope - --> $DIR/unevaluated-const-ice-119731.rs:33:13 + --> $DIR/unevaluated-const-ice-119731.rs:32:13 | LL | pub type v11 = [[usize; v4]; v4]; | --------------------------------- similarly named type alias `v11` defined here @@ -73,29 +73,20 @@ LL + #![feature(adt_const_params)] | error: maximum number of nodes exceeded in constant v20::v17::::{constant#1} - --> $DIR/unevaluated-const-ice-119731.rs:28:37 + --> $DIR/unevaluated-const-ice-119731.rs:27:37 | LL | impl v17 { | ^^ error: maximum number of nodes exceeded in constant v20::v17::::{constant#1} - --> $DIR/unevaluated-const-ice-119731.rs:28:37 + --> $DIR/unevaluated-const-ice-119731.rs:27:37 | LL | impl v17 { | ^^ | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0592]: duplicate definitions with name `v21` - --> $DIR/unevaluated-const-ice-119731.rs:23:9 - | -LL | pub const fn v21() -> v18 {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definitions for `v21` -... -LL | pub const fn v21() -> v18 { - | ------------------------- other definition for `v21` - -error: aborting due to 10 previous errors; 2 warnings emitted +error: aborting due to 9 previous errors; 2 warnings emitted -Some errors have detailed explanations: E0412, E0422, E0425, E0432, E0592. +Some errors have detailed explanations: E0412, E0422, E0425, E0432. For more information about an error, try `rustc --explain E0412`. diff --git a/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.rs b/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.rs index 81ac9979bd8c7..dd0b1e8c9f71d 100644 --- a/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.rs +++ b/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.rs @@ -10,5 +10,6 @@ trait Trait {} impl Trait for A {} impl Trait for A {} +//~^ ERROR conflicting implementations of trait `Trait` for type `A<_>` pub fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.stderr b/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.stderr index e29c49ff0422c..80ac96d487000 100644 --- a/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.stderr +++ b/tests/ui/const-generics/generic_const_exprs/unknown-alias-defkind-anonconst-ice-116710.stderr @@ -4,6 +4,16 @@ error[E0423]: expected value, found builtin type `u8` LL | struct A; | ^^ not a value -error: aborting due to 1 previous error +error[E0119]: conflicting implementations of trait `Trait` for type `A<_>` + --> $DIR/unknown-alias-defkind-anonconst-ice-116710.rs:12:1 + | +LL | impl Trait for A {} + | --------------------------------- first implementation here +LL | +LL | impl Trait for A {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `A<_>` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0423`. +Some errors have detailed explanations: E0119, E0423. +For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/error-codes/e0119/issue-23563.stderr b/tests/ui/error-codes/e0119/issue-23563.stderr index a308769af131f..86737742f749b 100644 --- a/tests/ui/error-codes/e0119/issue-23563.stderr +++ b/tests/ui/error-codes/e0119/issue-23563.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `LolFrom<&[u8]>` for type `LocalType` +error[E0119]: conflicting implementations of trait `LolFrom<&[_]>` for type `LocalType<_>` --> $DIR/issue-23563.rs:13:1 | LL | impl<'a, T> LolFrom<&'a [T]> for LocalType { diff --git a/tests/ui/feature-gates/feature-gate-with_negative_coherence.stderr b/tests/ui/feature-gates/feature-gate-with_negative_coherence.stderr index b32f54aaecfa5..ba076568088b2 100644 --- a/tests/ui/feature-gates/feature-gate-with_negative_coherence.stderr +++ b/tests/ui/feature-gates/feature-gate-with_negative_coherence.stderr @@ -6,8 +6,6 @@ LL | impl Foo for T { } LL | LL | impl Foo for &T { } | ^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_` - | - = note: downstream crates may implement trait `std::ops::DerefMut` for type `&_` error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-5-ambig.rs b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-5-ambig.rs index 9a44fd2e64a3e..beda719ac208a 100644 --- a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-5-ambig.rs +++ b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-5-ambig.rs @@ -3,9 +3,9 @@ //@ check-pass // The new trait solver does not return region constraints if the goal -// is still ambiguous. However, the `'!a = 'static` constraint from -// `(): LeakCheckFailure<'!a, V>` is also returned via the canonical -// var values, causing this test to compile. +// is still ambiguous. This causes the following test to fail with ambiguity, +// even though `(): LeakCheckFailure<'!a, V>` would return `'!a: 'static` +// which would have caused a leak check failure. trait Ambig {} impl Ambig for u32 {} diff --git a/tests/ui/higher-ranked/structually-relate-aliases.rs b/tests/ui/higher-ranked/structually-relate-aliases.rs index 6988245096136..8df24702811dd 100644 --- a/tests/ui/higher-ranked/structually-relate-aliases.rs +++ b/tests/ui/higher-ranked/structually-relate-aliases.rs @@ -11,6 +11,7 @@ type Assoc<'a, T> = >::Unit; impl Overlap for T {} impl Overlap fn(&'a (), Assoc<'a, T>)> for T {} -//~^ ERROR conflicting implementations of trait `Overlap fn(&'a (), _)>` +//~^ ERROR 13:17: 13:49: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied [E0277] +//~| ERROR 13:36: 13:48: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied [E0277] fn main() {} diff --git a/tests/ui/higher-ranked/structually-relate-aliases.stderr b/tests/ui/higher-ranked/structually-relate-aliases.stderr index 4ecd5829bc352..7de30efae1cd2 100644 --- a/tests/ui/higher-ranked/structually-relate-aliases.stderr +++ b/tests/ui/higher-ranked/structually-relate-aliases.stderr @@ -1,18 +1,27 @@ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit), .. } - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit), .. } - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit), .. } - WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, '^0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit), .. } -error[E0119]: conflicting implementations of trait `Overlap fn(&'a (), _)>` for type `for<'a> fn(&'a (), _)` - --> $DIR/structually-relate-aliases.rs:13:1 + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: [?1t, !2_0.Named(DefId(0:15 ~ structually_relate_aliases[de75]::{impl#1}::'a), "'a")], def_id: DefId(0:5 ~ structually_relate_aliases[de75]::ToUnit::Unit), .. } +error[E0277]: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied + --> $DIR/structually-relate-aliases.rs:13:36 | -LL | impl Overlap for T {} - | ------------------------ first implementation here -LL | LL | impl Overlap fn(&'a (), Assoc<'a, T>)> for T {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a> fn(&'a (), _)` + | ^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `T` + | +help: consider restricting type parameter `T` + | +LL | impl ToUnit<'a>> Overlap fn(&'a (), Assoc<'a, T>)> for T {} + | ++++++++++++++++++++ + +error[E0277]: the trait bound `for<'a> T: ToUnit<'a>` is not satisfied + --> $DIR/structually-relate-aliases.rs:13:17 + | +LL | impl Overlap fn(&'a (), Assoc<'a, T>)> for T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> ToUnit<'a>` is not implemented for `T` + | +help: consider restricting type parameter `T` | - = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details +LL | impl ToUnit<'a>> Overlap fn(&'a (), Assoc<'a, T>)> for T {} + | ++++++++++++++++++++ -error: aborting due to 1 previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0119`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/auto-trait-coherence.old.stderr b/tests/ui/impl-trait/auto-trait-coherence.old.stderr index cd91bfcb48d73..3f979d1a50b33 100644 --- a/tests/ui/impl-trait/auto-trait-coherence.old.stderr +++ b/tests/ui/impl-trait/auto-trait-coherence.old.stderr @@ -1,11 +1,11 @@ -error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<_>` +error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D` --> $DIR/auto-trait-coherence.rs:24:1 | LL | impl AnotherTrait for T {} | -------------------------------- first implementation here ... LL | impl AnotherTrait for D { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<_>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D` error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/auto-trait-coherence.rs b/tests/ui/impl-trait/auto-trait-coherence.rs index 0d7fef21cc92b..e3036fd0fe2c5 100644 --- a/tests/ui/impl-trait/auto-trait-coherence.rs +++ b/tests/ui/impl-trait/auto-trait-coherence.rs @@ -1,3 +1,6 @@ +//@ revisions: old next +//@[next] compile-flags: -Znext-solver + // Tests that type alias impls traits do not leak auto-traits for // the purposes of coherence checking #![feature(type_alias_impl_trait)] @@ -19,7 +22,8 @@ impl AnotherTrait for T {} // (We treat opaque types as "foreign types" that could grow more impls // in the future.) impl AnotherTrait for D { - //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<_>` + //[old]~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D` + //[next]~^^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<_>` } fn main() {} diff --git a/tests/ui/impl-trait/auto-trait-coherence.stderr b/tests/ui/impl-trait/auto-trait-coherence.stderr deleted file mode 100644 index e0f4c857717cf..0000000000000 --- a/tests/ui/impl-trait/auto-trait-coherence.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<_>` - --> $DIR/auto-trait-coherence.rs:21:1 - | -LL | impl AnotherTrait for T {} - | -------------------------------- first implementation here -... -LL | impl AnotherTrait for D { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<_>` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/impl-trait/coherence-treats-tait-ambig.rs b/tests/ui/impl-trait/coherence-treats-tait-ambig.rs index e8c1fcdd21334..df47208bf3676 100644 --- a/tests/ui/impl-trait/coherence-treats-tait-ambig.rs +++ b/tests/ui/impl-trait/coherence-treats-tait-ambig.rs @@ -5,7 +5,7 @@ type T = impl Sized; struct Foo; impl Into for Foo { -//~^ ERROR conflicting implementations of trait `Into<_>` for type `Foo` +//~^ ERROR conflicting implementations of trait `Into` for type `Foo` fn into(self) -> T { Foo } diff --git a/tests/ui/impl-trait/coherence-treats-tait-ambig.stderr b/tests/ui/impl-trait/coherence-treats-tait-ambig.stderr index 618bef1f2714a..faaad27692716 100644 --- a/tests/ui/impl-trait/coherence-treats-tait-ambig.stderr +++ b/tests/ui/impl-trait/coherence-treats-tait-ambig.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `Into<_>` for type `Foo` +error[E0119]: conflicting implementations of trait `Into` for type `Foo` --> $DIR/coherence-treats-tait-ambig.rs:7:1 | LL | impl Into for Foo { diff --git a/tests/ui/impl-trait/negative-reasoning.rs b/tests/ui/impl-trait/negative-reasoning.rs index 0474dc0beda6d..70e24a3a9d029 100644 --- a/tests/ui/impl-trait/negative-reasoning.rs +++ b/tests/ui/impl-trait/negative-reasoning.rs @@ -17,7 +17,7 @@ impl AnotherTrait for T {} // This is in error, because we cannot assume that `OpaqueType: !Debug` impl AnotherTrait for D { - //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<_>` + //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D` } fn main() {} diff --git a/tests/ui/impl-trait/negative-reasoning.stderr b/tests/ui/impl-trait/negative-reasoning.stderr index 631784c817b87..3cb4be16fc3f1 100644 --- a/tests/ui/impl-trait/negative-reasoning.stderr +++ b/tests/ui/impl-trait/negative-reasoning.stderr @@ -1,11 +1,13 @@ -error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<_>` +error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D` --> $DIR/negative-reasoning.rs:19:1 | LL | impl AnotherTrait for T {} | ------------------------------------------- first implementation here ... LL | impl AnotherTrait for D { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<_>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D` + | + = note: upstream crates may add a new impl of trait `std::marker::FnPtr` for type `OpaqueType` in future versions error: aborting due to 1 previous error diff --git a/tests/ui/impl-unused-tps.rs b/tests/ui/impl-unused-tps.rs index a5836db3c8e66..3eb9daedf76d7 100644 --- a/tests/ui/impl-unused-tps.rs +++ b/tests/ui/impl-unused-tps.rs @@ -1,35 +1,34 @@ +//~ ERROR overflow evaluating the requirement `([isize; 0], _): Sized + trait Foo { - fn get(&self, A: &A) {} + fn get(&self, A: &A) { } } trait Bar { type Out; } -impl Foo for [isize; 0] { +impl Foo for [isize;0] { // OK, T is used in `Foo`. } -impl Foo for [isize; 1] { +impl Foo for [isize;1] { //~^ ERROR the type parameter `U` is not constrained } -impl Foo for [isize; 2] -where - T: Bar, -{ +impl Foo for [isize;2] where T : Bar { // OK, `U` is now constrained by the output type parameter. } -impl, U> Foo for [isize; 3] { +impl,U> Foo for [isize;3] { // OK, same as above but written differently. } -impl Foo for U { +impl Foo for U { //~^ ERROR conflicting implementations of trait `Foo<_>` for type `[isize; 0]` } -impl Bar for T { +impl Bar for T { //~^ ERROR the type parameter `U` is not constrained type Out = U; @@ -37,33 +36,28 @@ impl Bar for T { // Using `U` in an associated type within the impl is not good enough! } -impl Bar for T -where - T: Bar, +impl Bar for T + where T : Bar { - //~^^^^ ERROR the type parameter `U` is not constrained by the impl trait, self type, or predicates - //~| ERROR conflicting implementations of trait `Bar` + //~^^^ ERROR the type parameter `U` is not constrained + // This crafty self-referential attempt is still no good. } -impl Foo for T -where - (T, U): Bar, +impl Foo for T + where (T,U): Bar { - //~^^^^ ERROR the type parameter `U` is not constrained - //~| ERROR the type parameter `V` is not constrained - //~| ERROR conflicting implementations of trait `Foo<[isize; 0]>` for type `[isize; 0]` + //~^^^ ERROR the type parameter `U` is not constrained + //~| ERROR the type parameter `V` is not constrained // Here, `V` is bound by an output type parameter, but the inputs // are not themselves constrained. } -impl Foo<(T, U)> for T -where - (T, U): Bar, +impl Foo<(T,U)> for T + where (T,U): Bar { - //~^^^^ ERROR conflicting implementations of trait `Foo<([isize; 0], _)>` for type `[isize; 0]` // As above, but both T and U ARE constrained. } -fn main() {} +fn main() { } diff --git a/tests/ui/impl-unused-tps.stderr b/tests/ui/impl-unused-tps.stderr index da4589dee8278..af427cb5f3e3c 100644 --- a/tests/ui/impl-unused-tps.stderr +++ b/tests/ui/impl-unused-tps.stderr @@ -1,76 +1,56 @@ error[E0119]: conflicting implementations of trait `Foo<_>` for type `[isize; 0]` - --> $DIR/impl-unused-tps.rs:28:1 + --> $DIR/impl-unused-tps.rs:27:1 | -LL | impl Foo for [isize; 0] { - | ----------------------------- first implementation here +LL | impl Foo for [isize;0] { + | ---------------------------- first implementation here ... -LL | impl Foo for U { - | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `[isize; 0]` +LL | impl Foo for U { + | ^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `[isize; 0]` -error[E0119]: conflicting implementations of trait `Bar` - --> $DIR/impl-unused-tps.rs:40:1 +error[E0275]: overflow evaluating the requirement `([isize; 0], _): Sized` | -LL | impl Bar for T { - | -------------------- first implementation here -... -LL | / impl Bar for T -LL | | where -LL | | T: Bar, - | |____________________^ conflicting implementation - -error[E0119]: conflicting implementations of trait `Foo<[isize; 0]>` for type `[isize; 0]` - --> $DIR/impl-unused-tps.rs:49:1 - | -LL | impl Foo for [isize; 0] { - | ----------------------------- first implementation here -... -LL | / impl Foo for T -LL | | where -LL | | (T, U): Bar, - | |_________________________^ conflicting implementation for `[isize; 0]` - -error[E0119]: conflicting implementations of trait `Foo<([isize; 0], _)>` for type `[isize; 0]` - --> $DIR/impl-unused-tps.rs:61:1 + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`impl_unused_tps`) +note: required for `([isize; 0], _)` to implement `Bar` + --> $DIR/impl-unused-tps.rs:31:11 | -LL | impl Foo for [isize; 0] { - | ----------------------------- first implementation here -... -LL | / impl Foo<(T, U)> for T -LL | | where -LL | | (T, U): Bar, - | |_________________________^ conflicting implementation for `[isize; 0]` +LL | impl Bar for T { + | - ^^^ ^ + | | + | unsatisfied trait bound introduced here + = note: 126 redundant requirements hidden + = note: required for `([isize; 0], _)` to implement `Bar` error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates - --> $DIR/impl-unused-tps.rs:13:9 + --> $DIR/impl-unused-tps.rs:15:8 | -LL | impl Foo for [isize; 1] { - | ^ unconstrained type parameter +LL | impl Foo for [isize;1] { + | ^ unconstrained type parameter error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates - --> $DIR/impl-unused-tps.rs:32:9 + --> $DIR/impl-unused-tps.rs:31:8 | -LL | impl Bar for T { - | ^ unconstrained type parameter +LL | impl Bar for T { + | ^ unconstrained type parameter error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates - --> $DIR/impl-unused-tps.rs:40:9 + --> $DIR/impl-unused-tps.rs:39:8 | -LL | impl Bar for T - | ^ unconstrained type parameter +LL | impl Bar for T + | ^ unconstrained type parameter error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates - --> $DIR/impl-unused-tps.rs:49:9 + --> $DIR/impl-unused-tps.rs:47:8 | -LL | impl Foo for T - | ^ unconstrained type parameter +LL | impl Foo for T + | ^ unconstrained type parameter error[E0207]: the type parameter `V` is not constrained by the impl trait, self type, or predicates - --> $DIR/impl-unused-tps.rs:49:12 + --> $DIR/impl-unused-tps.rs:47:10 | -LL | impl Foo for T - | ^ unconstrained type parameter +LL | impl Foo for T + | ^ unconstrained type parameter -error: aborting due to 9 previous errors +error: aborting due to 7 previous errors -Some errors have detailed explanations: E0119, E0207. +Some errors have detailed explanations: E0119, E0207, E0275. For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/issues/issue-48728.rs b/tests/ui/issues/issue-48728.rs index 8ad9289c65cf2..7ef05f4277b27 100644 --- a/tests/ui/issues/issue-48728.rs +++ b/tests/ui/issues/issue-48728.rs @@ -1,8 +1,12 @@ // Regression test for #48728, an ICE that occurred computing // coherence "help" information. -//@ check-pass -#[derive(Clone)] +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] check-pass + +#[derive(Clone)] //[current]~ ERROR conflicting implementations of trait `Clone` struct Node(Box); impl Clone for Node<[T]> { diff --git a/tests/ui/specialization/coherence/default-impl-normalization-ambig-2.stderr b/tests/ui/specialization/coherence/default-impl-normalization-ambig-2.stderr deleted file mode 100644 index a2fca2ef5b67e..0000000000000 --- a/tests/ui/specialization/coherence/default-impl-normalization-ambig-2.stderr +++ /dev/null @@ -1,21 +0,0 @@ -warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/default-impl-normalization-ambig-2.rs:2:12 - | -LL | #![feature(specialization)] - | ^^^^^^^^^^^^^^ - | - = note: see issue #31844 for more information - = help: consider using `min_specialization` instead, which is more stable and complete - = note: `#[warn(incomplete_features)]` on by default - -error[E0277]: the trait bound `u16: Assoc` is not satisfied - --> $DIR/default-impl-normalization-ambig-2.rs:17:14 - | -LL | impl Foo for ::Output {} - | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Assoc` is not implemented for `u16` - | - = help: the trait `Assoc` is implemented for `u8` - -error: aborting due to 1 previous error; 1 warning emitted - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/specialization/coherence/default-item-normalization-ambig-1.stderr b/tests/ui/specialization/coherence/default-item-normalization-ambig-1.stderr deleted file mode 100644 index a15151cc9c41e..0000000000000 --- a/tests/ui/specialization/coherence/default-item-normalization-ambig-1.stderr +++ /dev/null @@ -1,21 +0,0 @@ -warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/default-item-normalization-ambig-1.rs:2:12 - | -LL | #![feature(specialization)] - | ^^^^^^^^^^^^^^ - | - = note: see issue #31844 for more information - = help: consider using `min_specialization` instead, which is more stable and complete - = note: `#[warn(incomplete_features)]` on by default - -error[E0119]: conflicting implementations of trait `Y` for type `<() as X>::U` - --> $DIR/default-item-normalization-ambig-1.rs:20:1 - | -LL | impl Y for <() as X>::U {} - | ----------------------- first implementation here -LL | impl Y for ::U {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `<() as X>::U` - -error: aborting due to 1 previous error; 1 warning emitted - -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/specialization/defaultimpl/specialization-no-default.rs b/tests/ui/specialization/defaultimpl/specialization-no-default.rs index ddc32337306f3..661724eef8a43 100644 --- a/tests/ui/specialization/defaultimpl/specialization-no-default.rs +++ b/tests/ui/specialization/defaultimpl/specialization-no-default.rs @@ -71,8 +71,7 @@ impl Redundant for T { } default impl Redundant for i32 { - fn redundant(&self) {} - //~^ ERROR `redundant` specializes an item from a parent `impl`, but that item is not marked `default` + fn redundant(&self) {} //~ ERROR E0520 } fn main() {} diff --git a/tests/ui/specialization/specialization-default-items-drop-coherence.current.stderr b/tests/ui/specialization/specialization-default-items-drop-coherence.current.stderr deleted file mode 100644 index 36df6bfd9fc15..0000000000000 --- a/tests/ui/specialization/specialization-default-items-drop-coherence.current.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0119]: conflicting implementations of trait `Overlap` for type `u32` - --> $DIR/specialization-default-items-drop-coherence.rs:26:1 - | -LL | impl Overlap for u32 { - | -------------------- first implementation here -... -LL | impl Overlap for ::Id { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr b/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr index 36df6bfd9fc15..e9498a003179b 100644 --- a/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr +++ b/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Overlap` for type `u32` - --> $DIR/specialization-default-items-drop-coherence.rs:26:1 + --> $DIR/specialization-default-items-drop-coherence.rs:29:1 | LL | impl Overlap for u32 { | -------------------- first implementation here diff --git a/tests/ui/specialization/specialization-default-items-drop-coherence.rs b/tests/ui/specialization/specialization-default-items-drop-coherence.rs index b3c1f72777c4c..6dc012776391b 100644 --- a/tests/ui/specialization/specialization-default-items-drop-coherence.rs +++ b/tests/ui/specialization/specialization-default-items-drop-coherence.rs @@ -1,5 +1,8 @@ -//@ revisions: current next +//@ revisions: classic coherence next //@[next] compile-flags: -Znext-solver +//@[coherence] compile-flags: -Znext-solver=coherence +//@[classic] check-pass +//@[classic] known-bug: #105782 // Should fail. Default items completely drop candidates instead of ambiguity, // which is unsound during coherence, since coherence requires completeness. @@ -24,7 +27,8 @@ impl Overlap for u32 { } impl Overlap for ::Id { - //~^ ERROR conflicting implementations of trait `Overlap` for type `u32` + //[coherence]~^ ERROR conflicting implementations of trait `Overlap` for type `u32` + //[next]~^^ ERROR conflicting implementations of trait `Overlap` for type `u32` type Assoc = Box; } diff --git a/tests/ui/specialization/specialization-overlap-projection.current.stderr b/tests/ui/specialization/specialization-overlap-projection.current.stderr index 4e77cb17fbb0a..a69826fa96b08 100644 --- a/tests/ui/specialization/specialization-overlap-projection.current.stderr +++ b/tests/ui/specialization/specialization-overlap-projection.current.stderr @@ -1,5 +1,5 @@ warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/specialization-overlap-projection.rs:4:12 + --> $DIR/specialization-overlap-projection.rs:10:12 | LL | #![feature(specialization)] | ^^^^^^^^^^^^^^ @@ -8,23 +8,5 @@ LL | #![feature(specialization)] = help: consider using `min_specialization` instead, which is more stable and complete = note: `#[warn(incomplete_features)]` on by default -error[E0119]: conflicting implementations of trait `Foo` for type `u32` - --> $DIR/specialization-overlap-projection.rs:19:1 - | -LL | impl Foo for u32 {} - | ---------------- first implementation here -LL | impl Foo for ::Output {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32` - -error[E0119]: conflicting implementations of trait `Foo` for type `u32` - --> $DIR/specialization-overlap-projection.rs:21:1 - | -LL | impl Foo for u32 {} - | ---------------- first implementation here -... -LL | impl Foo for ::Output {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32` - -error: aborting due to 2 previous errors; 1 warning emitted +warning: 1 warning emitted -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/specialization/specialization-overlap-projection.next.stderr b/tests/ui/specialization/specialization-overlap-projection.next.stderr index 4e77cb17fbb0a..5b17696162ed5 100644 --- a/tests/ui/specialization/specialization-overlap-projection.next.stderr +++ b/tests/ui/specialization/specialization-overlap-projection.next.stderr @@ -1,5 +1,5 @@ warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/specialization-overlap-projection.rs:4:12 + --> $DIR/specialization-overlap-projection.rs:10:12 | LL | #![feature(specialization)] | ^^^^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | #![feature(specialization)] = note: `#[warn(incomplete_features)]` on by default error[E0119]: conflicting implementations of trait `Foo` for type `u32` - --> $DIR/specialization-overlap-projection.rs:19:1 + --> $DIR/specialization-overlap-projection.rs:25:1 | LL | impl Foo for u32 {} | ---------------- first implementation here @@ -17,7 +17,7 @@ LL | impl Foo for ::Output {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32` error[E0119]: conflicting implementations of trait `Foo` for type `u32` - --> $DIR/specialization-overlap-projection.rs:21:1 + --> $DIR/specialization-overlap-projection.rs:27:1 | LL | impl Foo for u32 {} | ---------------- first implementation here diff --git a/tests/ui/specialization/specialization-overlap-projection.rs b/tests/ui/specialization/specialization-overlap-projection.rs index f7a2a79224320..16dccf82dcb98 100644 --- a/tests/ui/specialization/specialization-overlap-projection.rs +++ b/tests/ui/specialization/specialization-overlap-projection.rs @@ -1,8 +1,13 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[current] check-pass + // Test that impls on projected self types can resolve overlap, even when the // projections involve specialization, so long as the associated type is // provided by the most specialized impl. -#![feature(specialization)] -//~^ WARN the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + +#![feature(specialization)] //~ WARN the feature `specialization` is incomplete trait Assoc { type Output; @@ -18,8 +23,8 @@ impl Assoc for u16 { type Output = u16; } trait Foo {} impl Foo for u32 {} impl Foo for ::Output {} -//~^ ERROR conflicting implementations of trait `Foo` for type `u32` +//[next]~^ ERROR conflicting implementations of trait `Foo` for type `u32` impl Foo for ::Output {} -//~^ ERROR conflicting implementations of trait `Foo` for type `u32` +//[next]~^ ERROR conflicting implementations of trait `Foo` for type `u32` fn main() {} diff --git a/tests/ui/specialization/specialization-overlap-projection.stderr b/tests/ui/specialization/specialization-overlap-projection.stderr deleted file mode 100644 index 5f3cd9c66cfe2..0000000000000 --- a/tests/ui/specialization/specialization-overlap-projection.stderr +++ /dev/null @@ -1,30 +0,0 @@ -warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/specialization-overlap-projection.rs:4:12 - | -LL | #![feature(specialization)] - | ^^^^^^^^^^^^^^ - | - = note: see issue #31844 for more information - = help: consider using `min_specialization` instead, which is more stable and complete - = note: `#[warn(incomplete_features)]` on by default - -error[E0119]: conflicting implementations of trait `Foo` for type `u32` - --> $DIR/specialization-overlap-projection.rs:20:1 - | -LL | impl Foo for u32 {} - | ---------------- first implementation here -LL | impl Foo for ::Output {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32` - -error[E0119]: conflicting implementations of trait `Foo` for type `u32` - --> $DIR/specialization-overlap-projection.rs:22:1 - | -LL | impl Foo for u32 {} - | ---------------- first implementation here -... -LL | impl Foo for ::Output {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32` - -error: aborting due to 2 previous errors; 1 warning emitted - -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/alias/issue-83613.rs b/tests/ui/traits/alias/issue-83613.rs index 6f0012bf08967..2462e703a7165 100644 --- a/tests/ui/traits/alias/issue-83613.rs +++ b/tests/ui/traits/alias/issue-83613.rs @@ -8,5 +8,5 @@ fn mk_opaque() -> OpaqueType { trait AnotherTrait {} impl AnotherTrait for T {} impl AnotherTrait for OpaqueType {} -//~^ ERROR conflicting implementations of trait `AnotherTrait` +//~^ ERROR conflicting implementations of trait `AnotherTrait` for type `OpaqueType` fn main() {} diff --git a/tests/ui/traits/alias/issue-83613.stderr b/tests/ui/traits/alias/issue-83613.stderr index 47181c3f33ed6..847fda417766a 100644 --- a/tests/ui/traits/alias/issue-83613.stderr +++ b/tests/ui/traits/alias/issue-83613.stderr @@ -1,10 +1,10 @@ -error[E0119]: conflicting implementations of trait `AnotherTrait` +error[E0119]: conflicting implementations of trait `AnotherTrait` for type `OpaqueType` --> $DIR/issue-83613.rs:10:1 | LL | impl AnotherTrait for T {} | -------------------------------- first implementation here LL | impl AnotherTrait for OpaqueType {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `OpaqueType` error: aborting due to 1 previous error diff --git a/tests/ui/traits/issue-105231.rs b/tests/ui/traits/issue-105231.rs index 83c3158c106b6..7338642beefa6 100644 --- a/tests/ui/traits/issue-105231.rs +++ b/tests/ui/traits/issue-105231.rs @@ -1,3 +1,4 @@ +//~ ERROR overflow evaluating the requirement `A>>>>>>: Send` struct A(B); //~^ ERROR recursive types `A` and `B` have infinite size //~| ERROR `T` is only used recursively @@ -6,5 +7,5 @@ struct B(A>); trait Foo {} impl Foo for T where T: Send {} impl Foo for B {} -//~^ ERROR conflicting implementations of trait `Foo` for type `B` + fn main() {} diff --git a/tests/ui/traits/issue-105231.stderr b/tests/ui/traits/issue-105231.stderr index e113f8382b2f4..d3014a79ad605 100644 --- a/tests/ui/traits/issue-105231.stderr +++ b/tests/ui/traits/issue-105231.stderr @@ -1,5 +1,5 @@ error[E0072]: recursive types `A` and `B` have infinite size - --> $DIR/issue-105231.rs:1:1 + --> $DIR/issue-105231.rs:2:1 | LL | struct A(B); | ^^^^^^^^^^^ ---- recursive without indirection @@ -16,7 +16,7 @@ LL ~ struct B(Box>>); | error: type parameter `T` is only used recursively - --> $DIR/issue-105231.rs:1:15 + --> $DIR/issue-105231.rs:2:15 | LL | struct A(B); | - ^ @@ -27,7 +27,7 @@ LL | struct A(B); = note: all type parameters must be used in a non-recursive way in order to constrain their variance error: type parameter `T` is only used recursively - --> $DIR/issue-105231.rs:4:17 + --> $DIR/issue-105231.rs:5:17 | LL | struct B(A>); | - ^ @@ -37,18 +37,16 @@ LL | struct B(A>); = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` = note: all type parameters must be used in a non-recursive way in order to constrain their variance -error[E0119]: conflicting implementations of trait `Foo` for type `B` - --> $DIR/issue-105231.rs:8:1 +error[E0275]: overflow evaluating the requirement `A>>>>>>: Send` | -LL | impl Foo for T where T: Send {} - | ------------------------------- first implementation here -LL | impl Foo for B {} - | ^^^^^^^^^^^^^^^^^^ conflicting implementation for `B` - | - = note: overflow evaluating the requirement `B: Send` = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_105231`) +note: required because it appears within the type `B>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + --> $DIR/issue-105231.rs:5:8 + | +LL | struct B(A>); + | ^ error: aborting due to 4 previous errors -Some errors have detailed explanations: E0072, E0119. +Some errors have detailed explanations: E0072, E0275. For more information about an error, try `rustc --explain E0072`. diff --git a/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs index 43443be88df73..d37943b929a1f 100644 --- a/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs +++ b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs @@ -1,3 +1,4 @@ +//~ ERROR overflow // A regression test for #111729 checking that we correctly // track recursion depth for obligations returned by confirmation. use std::panic::RefUnwindSafe; @@ -17,7 +18,6 @@ impl Database for T { type Storage = SalsaStorage; } impl Database for RootDatabase { - //~^ ERROR conflicting implementations of trait `Database` for type `RootDatabase` type Storage = SalsaStorage; } diff --git a/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr index 1da7671b45190..2ab150fc0f627 100644 --- a/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr +++ b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr @@ -1,12 +1,24 @@ -error[E0119]: conflicting implementations of trait `Database` for type `RootDatabase` - --> $DIR/cycle-via-builtin-auto-trait-impl.rs:19:1 +error[E0275]: overflow evaluating the requirement `Runtime: RefUnwindSafe` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`cycle_via_builtin_auto_trait_impl`) +note: required because it appears within the type `RootDatabase` + --> $DIR/cycle-via-builtin-auto-trait-impl.rs:13:8 + | +LL | struct RootDatabase { + | ^^^^^^^^^^^^ +note: required for `RootDatabase` to implement `Database` + --> $DIR/cycle-via-builtin-auto-trait-impl.rs:17:24 | LL | impl Database for T { - | ------------------------------------- first implementation here -... -LL | impl Database for RootDatabase { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `RootDatabase` + | ------------- ^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here +note: required because it appears within the type `Runtime` + --> $DIR/cycle-via-builtin-auto-trait-impl.rs:24:8 + | +LL | struct Runtime { + | ^^^^^^^ error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0119`. +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.stderr b/tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.stderr deleted file mode 100644 index 2424541af23ec..0000000000000 --- a/tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.stderr +++ /dev/null @@ -1,27 +0,0 @@ -error: unconstrained opaque type - --> $DIR/coherence-bikeshed-intrinsic-from.rs:4:19 - | -LL | type OpaqueType = impl OpaqueTrait; - | ^^^^^^^^^^^^^^^^ - | - = note: `OpaqueType` must be used in combination with a concrete type within the same module - -error[E0747]: type provided when a constant was expected - --> $DIR/coherence-bikeshed-intrinsic-from.rs:7:37 - | -LL | impl> AnotherTrait for T {} - | ^^ - -error[E0119]: conflicting implementations of trait `AnotherTrait` - --> $DIR/coherence-bikeshed-intrinsic-from.rs:9:1 - | -LL | impl> AnotherTrait for T {} - | ----------------------------------------------------------- first implementation here -LL | -LL | impl AnotherTrait for OpaqueType {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation - -error: aborting due to 3 previous errors - -Some errors have detailed explanations: E0119, E0747. -For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr b/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr index aaf75cc3db97c..e35913be899f4 100644 --- a/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr +++ b/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr @@ -15,6 +15,8 @@ LL | impl Bop for Bar<()> {} ... LL | impl Bop for Barr {} | ^^^^^^^^^^^^^^^^^ conflicting implementation for `Bar<()>` + | + = note: upstream crates may add a new impl of trait `std::marker::FnPtr` for type `Barr` in future versions error[E0119]: conflicting implementations of trait `Bop` for type `Bar<()>` --> $DIR/impl_trait_for_same_tait.rs:30:1 diff --git a/tests/ui/type-alias-impl-trait/issue-104817.rs b/tests/ui/type-alias-impl-trait/issue-104817.rs index 4914632161450..4679d025fce0f 100644 --- a/tests/ui/type-alias-impl-trait/issue-104817.rs +++ b/tests/ui/type-alias-impl-trait/issue-104817.rs @@ -14,6 +14,6 @@ fn mk_opaque() -> OpaqueType { trait AnotherTrait {} impl AnotherTrait for T {} impl AnotherTrait for OpaqueType {} -//[stock]~^ conflicting implementations of trait `AnotherTrait` +//[stock]~^ conflicting implementations of trait `AnotherTrait` for type `OpaqueType` fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-104817.stock.stderr b/tests/ui/type-alias-impl-trait/issue-104817.stock.stderr index df5a6c320a8a7..41c5206d9e88a 100644 --- a/tests/ui/type-alias-impl-trait/issue-104817.stock.stderr +++ b/tests/ui/type-alias-impl-trait/issue-104817.stock.stderr @@ -1,10 +1,10 @@ -error[E0119]: conflicting implementations of trait `AnotherTrait` +error[E0119]: conflicting implementations of trait `AnotherTrait` for type `OpaqueType` --> $DIR/issue-104817.rs:16:1 | LL | impl AnotherTrait for T {} | -------------------------------- first implementation here LL | impl AnotherTrait for OpaqueType {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `OpaqueType` error: aborting due to 1 previous error From 594de02cbacccd3a220c69971e085bfd76a84eac Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 11 Sep 2024 18:22:37 -0400 Subject: [PATCH 176/189] Properly deny const gen/async gen fns --- compiler/rustc_ast/src/ast.rs | 8 ++++++++ compiler/rustc_ast_passes/messages.ftl | 10 +++++----- .../rustc_ast_passes/src/ast_validation.rs | 17 ++++++---------- compiler/rustc_ast_passes/src/errors.rs | 11 +++++----- tests/ui/coroutine/const_gen_fn.rs | 12 +++++++++++ tests/ui/coroutine/const_gen_fn.stderr | 20 +++++++++++++++++++ 6 files changed, 57 insertions(+), 21 deletions(-) create mode 100644 tests/ui/coroutine/const_gen_fn.rs create mode 100644 tests/ui/coroutine/const_gen_fn.stderr diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 42741bdca2295..1fb85abcbfaa2 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2602,6 +2602,14 @@ impl CoroutineKind { } } + pub fn as_str(self) -> &'static str { + match self { + CoroutineKind::Async { .. } => "async", + CoroutineKind::Gen { .. } => "gen", + CoroutineKind::AsyncGen { .. } => "async gen", + } + } + pub fn is_async(self) -> bool { matches!(self, CoroutineKind::Async { .. }) } diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index df5c639382f04..c361c35b723d8 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -40,15 +40,15 @@ ast_passes_body_in_extern = incorrect `{$kind}` inside `extern` block ast_passes_bound_in_context = bounds on `type`s in {$ctx} have no effect -ast_passes_const_and_async = functions cannot be both `const` and `async` - .const = `const` because of this - .async = `async` because of this - .label = {""} - ast_passes_const_and_c_variadic = functions cannot be both `const` and C-variadic .const = `const` because of this .variadic = C-variadic because of this +ast_passes_const_and_coroutine = functions cannot be both `const` and `{$coroutine_kind}` + .const = `const` because of this + .coroutine = `{$coroutine_kind}` because of this + .label = {""} + ast_passes_const_bound_trait_object = const trait bounds are not allowed in trait object types ast_passes_const_without_body = diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index ed9672a9e79b3..f6731c6bd541c 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1418,21 +1418,16 @@ impl<'a> Visitor<'a> for AstValidator<'a> { // Functions cannot both be `const async` or `const gen` if let Some(&FnHeader { - constness: Const::Yes(cspan), + constness: Const::Yes(const_span), coroutine_kind: Some(coroutine_kind), .. }) = fk.header() { - let aspan = match coroutine_kind { - CoroutineKind::Async { span: aspan, .. } - | CoroutineKind::Gen { span: aspan, .. } - | CoroutineKind::AsyncGen { span: aspan, .. } => aspan, - }; - // FIXME(gen_blocks): Report a different error for `const gen` - self.dcx().emit_err(errors::ConstAndAsync { - spans: vec![cspan, aspan], - cspan, - aspan, + self.dcx().emit_err(errors::ConstAndCoroutine { + spans: vec![coroutine_kind.span(), const_span], + const_span, + coroutine_span: coroutine_kind.span(), + coroutine_kind: coroutine_kind.as_str(), span, }); } diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 67c0396333c4b..5cce47ce7bd21 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -657,16 +657,17 @@ pub(crate) enum TildeConstReason { } #[derive(Diagnostic)] -#[diag(ast_passes_const_and_async)] -pub(crate) struct ConstAndAsync { +#[diag(ast_passes_const_and_coroutine)] +pub(crate) struct ConstAndCoroutine { #[primary_span] pub spans: Vec, #[label(ast_passes_const)] - pub cspan: Span, - #[label(ast_passes_async)] - pub aspan: Span, + pub const_span: Span, + #[label(ast_passes_coroutine)] + pub coroutine_span: Span, #[label] pub span: Span, + pub coroutine_kind: &'static str, } #[derive(Diagnostic)] diff --git a/tests/ui/coroutine/const_gen_fn.rs b/tests/ui/coroutine/const_gen_fn.rs new file mode 100644 index 0000000000000..986693f33ab1b --- /dev/null +++ b/tests/ui/coroutine/const_gen_fn.rs @@ -0,0 +1,12 @@ +//@ edition:2024 +//@ compile-flags: -Zunstable-options + +#![feature(gen_blocks)] + +const gen fn a() {} +//~^ ERROR functions cannot be both `const` and `gen` + +const async gen fn b() {} +//~^ ERROR functions cannot be both `const` and `async gen` + +fn main() {} diff --git a/tests/ui/coroutine/const_gen_fn.stderr b/tests/ui/coroutine/const_gen_fn.stderr new file mode 100644 index 0000000000000..b58446ac88fd1 --- /dev/null +++ b/tests/ui/coroutine/const_gen_fn.stderr @@ -0,0 +1,20 @@ +error: functions cannot be both `const` and `gen` + --> $DIR/const_gen_fn.rs:6:1 + | +LL | const gen fn a() {} + | ^^^^^-^^^---------- + | | | + | | `gen` because of this + | `const` because of this + +error: functions cannot be both `const` and `async gen` + --> $DIR/const_gen_fn.rs:9:1 + | +LL | const async gen fn b() {} + | ^^^^^-^^^^^^^^^---------- + | | | + | | `async gen` because of this + | `const` because of this + +error: aborting due to 2 previous errors + From d4fc76cbf386eeeb184bf0411af670912e9bc70d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 10 Sep 2024 16:19:40 +1000 Subject: [PATCH 177/189] Introduce `'ra` lifetime name. `rustc_resolve` allocates many things in `ResolverArenas`. The lifetime used for references into the arena is mostly `'a`, and sometimes `'b`. This commit changes it to `'ra`, which is much more descriptive. The commit also changes the order of lifetimes on a couple of structs so that '`ra` is second last, before `'tcx`, and does other minor renamings such as `'r` to `'a`. --- .../rustc_resolve/src/build_reduced_graph.rs | 92 +++--- compiler/rustc_resolve/src/check_unused.rs | 8 +- compiler/rustc_resolve/src/def_collector.rs | 8 +- compiler/rustc_resolve/src/diagnostics.rs | 52 ++-- .../src/effective_visibilities.rs | 33 +- compiler/rustc_resolve/src/ident.rs | 106 +++---- compiler/rustc_resolve/src/imports.rs | 72 ++--- compiler/rustc_resolve/src/late.rs | 257 ++++++++-------- .../rustc_resolve/src/late/diagnostics.rs | 4 +- compiler/rustc_resolve/src/lib.rs | 287 +++++++++--------- compiler/rustc_resolve/src/macros.rs | 32 +- 11 files changed, 481 insertions(+), 470 deletions(-) diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 3ea782b62f179..f87f3cdde4cf0 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -39,10 +39,10 @@ use crate::{ type Res = def::Res; -impl<'a, Id: Into> ToNameBinding<'a> - for (Module<'a>, ty::Visibility, Span, LocalExpnId) +impl<'ra, Id: Into> ToNameBinding<'ra> + for (Module<'ra>, ty::Visibility, Span, LocalExpnId) { - fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> NameBinding<'a> { + fn to_name_binding(self, arenas: &'ra ResolverArenas<'ra>) -> NameBinding<'ra> { arenas.alloc_name_binding(NameBindingData { kind: NameBindingKind::Module(self.0), ambiguity: None, @@ -54,8 +54,8 @@ impl<'a, Id: Into> ToNameBinding<'a> } } -impl<'a, Id: Into> ToNameBinding<'a> for (Res, ty::Visibility, Span, LocalExpnId) { - fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> NameBinding<'a> { +impl<'ra, Id: Into> ToNameBinding<'ra> for (Res, ty::Visibility, Span, LocalExpnId) { + fn to_name_binding(self, arenas: &'ra ResolverArenas<'ra>) -> NameBinding<'ra> { arenas.alloc_name_binding(NameBindingData { kind: NameBindingKind::Res(self.0), ambiguity: None, @@ -67,12 +67,12 @@ impl<'a, Id: Into> ToNameBinding<'a> for (Res, ty::Visibility, Span, } } -impl<'a, 'tcx> Resolver<'a, 'tcx> { +impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined; /// otherwise, reports an error. - pub(crate) fn define(&mut self, parent: Module<'a>, ident: Ident, ns: Namespace, def: T) + pub(crate) fn define(&mut self, parent: Module<'ra>, ident: Ident, ns: Namespace, def: T) where - T: ToNameBinding<'a>, + T: ToNameBinding<'ra>, { let binding = def.to_name_binding(self.arenas); let key = self.new_disambiguated_key(ident, ns); @@ -97,7 +97,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// Reachable macros with block module parents exist due to `#[macro_export] macro_rules!`, /// but they cannot use def-site hygiene, so the assumption holds /// (). - pub(crate) fn get_nearest_non_block_module(&mut self, mut def_id: DefId) -> Module<'a> { + pub(crate) fn get_nearest_non_block_module(&mut self, mut def_id: DefId) -> Module<'ra> { loop { match self.get_module(def_id) { Some(module) => return module, @@ -106,14 +106,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - pub(crate) fn expect_module(&mut self, def_id: DefId) -> Module<'a> { + pub(crate) fn expect_module(&mut self, def_id: DefId) -> Module<'ra> { self.get_module(def_id).expect("argument `DefId` is not a module") } /// If `def_id` refers to a module (in resolver's sense, i.e. a module item, crate root, enum, /// or trait), then this function returns that module's resolver representation, otherwise it /// returns `None`. - pub(crate) fn get_module(&mut self, def_id: DefId) -> Option> { + pub(crate) fn get_module(&mut self, def_id: DefId) -> Option> { if let module @ Some(..) = self.module_map.get(&def_id) { return module.copied(); } @@ -143,7 +143,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { None } - pub(crate) fn expn_def_scope(&mut self, expn_id: ExpnId) -> Module<'a> { + pub(crate) fn expn_def_scope(&mut self, expn_id: ExpnId) -> Module<'ra> { match expn_id.expn_data().macro_def_id { Some(def_id) => self.macro_def_scope(def_id), None => expn_id @@ -153,7 +153,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - pub(crate) fn macro_def_scope(&mut self, def_id: DefId) -> Module<'a> { + pub(crate) fn macro_def_scope(&mut self, def_id: DefId) -> Module<'ra> { if let Some(id) = def_id.as_local() { self.local_macro_def_scopes[&id] } else { @@ -186,15 +186,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pub(crate) fn build_reduced_graph( &mut self, fragment: &AstFragment, - parent_scope: ParentScope<'a>, - ) -> MacroRulesScopeRef<'a> { + parent_scope: ParentScope<'ra>, + ) -> MacroRulesScopeRef<'ra> { collect_definitions(self, fragment, parent_scope.expansion); let mut visitor = BuildReducedGraphVisitor { r: self, parent_scope }; fragment.visit_with(&mut visitor); visitor.parent_scope.macro_rules } - pub(crate) fn build_reduced_graph_external(&mut self, module: Module<'a>) { + pub(crate) fn build_reduced_graph_external(&mut self, module: Module<'ra>) { for child in self.tcx.module_children(module.def_id()) { let parent_scope = ParentScope::module(module, self); self.build_reduced_graph_for_external_crate_res(child, parent_scope) @@ -205,7 +205,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn build_reduced_graph_for_external_crate_res( &mut self, child: &ModChild, - parent_scope: ParentScope<'a>, + parent_scope: ParentScope<'ra>, ) { let parent = parent_scope.module; let ModChild { ident, res, vis, ref reexport_chain } = *child; @@ -273,18 +273,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } -struct BuildReducedGraphVisitor<'a, 'b, 'tcx> { - r: &'b mut Resolver<'a, 'tcx>, - parent_scope: ParentScope<'a>, +struct BuildReducedGraphVisitor<'a, 'ra, 'tcx> { + r: &'a mut Resolver<'ra, 'tcx>, + parent_scope: ParentScope<'ra>, } -impl<'a, 'tcx> AsMut> for BuildReducedGraphVisitor<'a, '_, 'tcx> { - fn as_mut(&mut self) -> &mut Resolver<'a, 'tcx> { +impl<'ra, 'tcx> AsMut> for BuildReducedGraphVisitor<'_, 'ra, 'tcx> { + fn as_mut(&mut self) -> &mut Resolver<'ra, 'tcx> { self.r } } -impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { +impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { fn res(&self, def_id: impl Into) -> Res { let def_id = def_id.into(); Res::Def(self.r.tcx.def_kind(def_id), def_id) @@ -424,7 +424,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { fn add_import( &mut self, module_path: Vec, - kind: ImportKind<'a>, + kind: ImportKind<'ra>, span: Span, item: &ast::Item, root_span: Span, @@ -752,7 +752,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { } /// Constructs the reduced graph for one item. - fn build_reduced_graph_for_item(&mut self, item: &'b Item) { + fn build_reduced_graph_for_item(&mut self, item: &'a Item) { let parent_scope = &self.parent_scope; let parent = parent_scope.module; let expansion = parent_scope.expansion; @@ -918,7 +918,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { item: &Item, local_def_id: LocalDefId, vis: ty::Visibility, - parent: Module<'a>, + parent: Module<'ra>, ) { let ident = item.ident; let sp = item.span; @@ -1040,7 +1040,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { fn add_macro_use_binding( &mut self, name: Symbol, - binding: NameBinding<'a>, + binding: NameBinding<'ra>, span: Span, allow_shadowing: bool, ) { @@ -1050,7 +1050,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { } /// Returns `true` if we should consider the underlying `extern crate` to be used. - fn process_macro_use_imports(&mut self, item: &Item, module: Module<'a>) -> bool { + fn process_macro_use_imports(&mut self, item: &Item, module: Module<'ra>) -> bool { let mut import_all = None; let mut single_imports = Vec::new(); for attr in &item.attrs { @@ -1188,7 +1188,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { /// Visit invocation in context in which it can emit a named item (possibly `macro_rules`) /// directly into its parent scope's module. - fn visit_invoc_in_module(&mut self, id: NodeId) -> MacroRulesScopeRef<'a> { + fn visit_invoc_in_module(&mut self, id: NodeId) -> MacroRulesScopeRef<'ra> { let invoc_id = self.visit_invoc(id); self.parent_scope.module.unexpanded_invocations.borrow_mut().insert(invoc_id); self.r.arenas.alloc_macro_rules_scope(MacroRulesScope::Invocation(invoc_id)) @@ -1221,7 +1221,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { } } - fn define_macro(&mut self, item: &ast::Item) -> MacroRulesScopeRef<'a> { + fn define_macro(&mut self, item: &ast::Item) -> MacroRulesScopeRef<'ra> { let parent_scope = self.parent_scope; let expansion = parent_scope.expansion; let feed = self.r.feed(item.id); @@ -1308,7 +1308,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { macro_rules! method { ($visit:ident: $ty:ty, $invoc:path, $walk:ident) => { - fn $visit(&mut self, node: &'b $ty) { + fn $visit(&mut self, node: &'a $ty) { if let $invoc(..) = node.kind { self.visit_invoc(node.id); } else { @@ -1318,12 +1318,12 @@ macro_rules! method { }; } -impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { +impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> { method!(visit_expr: ast::Expr, ast::ExprKind::MacCall, walk_expr); method!(visit_pat: ast::Pat, ast::PatKind::MacCall, walk_pat); method!(visit_ty: ast::Ty, ast::TyKind::MacCall, walk_ty); - fn visit_item(&mut self, item: &'b Item) { + fn visit_item(&mut self, item: &'a Item) { let orig_module_scope = self.parent_scope.module; self.parent_scope.macro_rules = match item.kind { ItemKind::MacroDef(..) => { @@ -1357,7 +1357,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { self.parent_scope.module = orig_module_scope; } - fn visit_stmt(&mut self, stmt: &'b ast::Stmt) { + fn visit_stmt(&mut self, stmt: &'a ast::Stmt) { if let ast::StmtKind::MacCall(..) = stmt.kind { self.parent_scope.macro_rules = self.visit_invoc_in_module(stmt.id); } else { @@ -1365,7 +1365,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { } } - fn visit_foreign_item(&mut self, foreign_item: &'b ForeignItem) { + fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) { if let ForeignItemKind::MacCall(_) = foreign_item.kind { self.visit_invoc_in_module(foreign_item.id); return; @@ -1375,7 +1375,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { visit::walk_item(self, foreign_item); } - fn visit_block(&mut self, block: &'b Block) { + fn visit_block(&mut self, block: &'a Block) { let orig_current_module = self.parent_scope.module; let orig_current_macro_rules_scope = self.parent_scope.macro_rules; self.build_reduced_graph_for_block(block); @@ -1384,7 +1384,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { self.parent_scope.macro_rules = orig_current_macro_rules_scope; } - fn visit_assoc_item(&mut self, item: &'b AssocItem, ctxt: AssocCtxt) { + fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) { if let AssocItemKind::MacCall(_) = item.kind { match ctxt { AssocCtxt::Trait => { @@ -1440,7 +1440,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { visit::walk_assoc_item(self, item, ctxt); } - fn visit_attribute(&mut self, attr: &'b ast::Attribute) { + fn visit_attribute(&mut self, attr: &'a ast::Attribute) { if !attr.is_doc_comment() && attr::is_builtin_attr(attr) { self.r .builtin_attrs @@ -1449,7 +1449,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { visit::walk_attribute(self, attr); } - fn visit_arm(&mut self, arm: &'b ast::Arm) { + fn visit_arm(&mut self, arm: &'a ast::Arm) { if arm.is_placeholder { self.visit_invoc(arm.id); } else { @@ -1457,7 +1457,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { } } - fn visit_expr_field(&mut self, f: &'b ast::ExprField) { + fn visit_expr_field(&mut self, f: &'a ast::ExprField) { if f.is_placeholder { self.visit_invoc(f.id); } else { @@ -1465,7 +1465,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { } } - fn visit_pat_field(&mut self, fp: &'b ast::PatField) { + fn visit_pat_field(&mut self, fp: &'a ast::PatField) { if fp.is_placeholder { self.visit_invoc(fp.id); } else { @@ -1473,7 +1473,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { } } - fn visit_generic_param(&mut self, param: &'b ast::GenericParam) { + fn visit_generic_param(&mut self, param: &'a ast::GenericParam) { if param.is_placeholder { self.visit_invoc(param.id); } else { @@ -1481,7 +1481,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { } } - fn visit_param(&mut self, p: &'b ast::Param) { + fn visit_param(&mut self, p: &'a ast::Param) { if p.is_placeholder { self.visit_invoc(p.id); } else { @@ -1489,7 +1489,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { } } - fn visit_field_def(&mut self, sf: &'b ast::FieldDef) { + fn visit_field_def(&mut self, sf: &'a ast::FieldDef) { if sf.is_placeholder { self.visit_invoc(sf.id); } else { @@ -1501,7 +1501,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { // Constructs the reduced graph for one variant. Variants exist in the // type and value namespaces. - fn visit_variant(&mut self, variant: &'b ast::Variant) { + fn visit_variant(&mut self, variant: &'a ast::Variant) { if variant.is_placeholder { self.visit_invoc_in_module(variant.id); return; @@ -1542,7 +1542,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { visit::walk_variant(self, variant); } - fn visit_crate(&mut self, krate: &'b ast::Crate) { + fn visit_crate(&mut self, krate: &'a ast::Crate) { if krate.is_placeholder { self.visit_invoc_in_module(krate.id); } else { diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index 1cee876b80fea..8c434007f2c86 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -52,8 +52,8 @@ impl UnusedImport { } } -struct UnusedImportCheckVisitor<'a, 'b, 'tcx> { - r: &'a mut Resolver<'b, 'tcx>, +struct UnusedImportCheckVisitor<'a, 'ra, 'tcx> { + r: &'a mut Resolver<'ra, 'tcx>, /// All the (so far) unused imports, grouped path list unused_imports: FxIndexMap, extern_crate_items: Vec, @@ -78,7 +78,7 @@ struct ExternCrateToLint { renames: bool, } -impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> { +impl<'a, 'ra, 'tcx> UnusedImportCheckVisitor<'a, 'ra, 'tcx> { // We have information about whether `use` (import) items are actually // used now. If an import is not used at all, we signal a lint error. fn check_import(&mut self, id: ast::NodeId) { @@ -212,7 +212,7 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> { } } -impl<'a, 'b, 'tcx> Visitor<'a> for UnusedImportCheckVisitor<'a, 'b, 'tcx> { +impl<'a, 'ra, 'tcx> Visitor<'a> for UnusedImportCheckVisitor<'a, 'ra, 'tcx> { fn visit_item(&mut self, item: &'a ast::Item) { match item.kind { // Ignore is_public import statements because there's no way to be sure diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 0fedb998463a2..87054dd04f58b 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -25,15 +25,15 @@ pub(crate) fn collect_definitions( } /// Creates `DefId`s for nodes in the AST. -struct DefCollector<'a, 'b, 'tcx> { - resolver: &'a mut Resolver<'b, 'tcx>, +struct DefCollector<'a, 'ra, 'tcx> { + resolver: &'a mut Resolver<'ra, 'tcx>, parent_def: LocalDefId, impl_trait_context: ImplTraitContext, in_attr: bool, expansion: LocalExpnId, } -impl<'a, 'b, 'tcx> DefCollector<'a, 'b, 'tcx> { +impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { fn create_def( &mut self, node_id: NodeId, @@ -119,7 +119,7 @@ impl<'a, 'b, 'tcx> DefCollector<'a, 'b, 'tcx> { } } -impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { +impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { fn visit_item(&mut self, i: &'a Item) { // Pick the def data. This need not be unique, but the more // information we encapsulate into, the better diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index bcbdf627b5662..f349713f22dfc 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -123,7 +123,7 @@ fn reduce_impl_span_to_impl_keyword(sm: &SourceMap, impl_span: Span) -> Span { sm.span_until_whitespace(impl_span) } -impl<'a, 'tcx> Resolver<'a, 'tcx> { +impl<'ra, 'tcx> Resolver<'ra, 'tcx> { pub(crate) fn dcx(&self) -> DiagCtxtHandle<'tcx> { self.tcx.dcx() } @@ -208,8 +208,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { parent: Module<'_>, ident: Ident, ns: Namespace, - new_binding: NameBinding<'a>, - old_binding: NameBinding<'a>, + new_binding: NameBinding<'ra>, + old_binding: NameBinding<'ra>, ) { // Error on the second of two conflicting names if old_binding.span.lo() > new_binding.span.lo() { @@ -531,7 +531,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pub(crate) fn add_module_candidates( &mut self, - module: Module<'a>, + module: Module<'ra>, names: &mut Vec, filter_fn: &impl Fn(Res) -> bool, ctxt: Option, @@ -553,7 +553,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pub(crate) fn report_error( &mut self, span: Span, - resolution_error: ResolutionError<'a>, + resolution_error: ResolutionError<'ra>, ) -> ErrorGuaranteed { self.into_struct_error(span, resolution_error).emit() } @@ -561,7 +561,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pub(crate) fn into_struct_error( &mut self, span: Span, - resolution_error: ResolutionError<'a>, + resolution_error: ResolutionError<'ra>, ) -> Diag<'_> { match resolution_error { ResolutionError::GenericParamsFromOuterItem( @@ -1020,8 +1020,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// Lookup typo candidate in scope for a macro or import. fn early_lookup_typo_candidate( &mut self, - scope_set: ScopeSet<'a>, - parent_scope: &ParentScope<'a>, + scope_set: ScopeSet<'ra>, + parent_scope: &ParentScope<'ra>, ident: Ident, filter_fn: &impl Fn(Res) -> bool, ) -> Option { @@ -1156,8 +1156,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &mut self, lookup_ident: Ident, namespace: Namespace, - parent_scope: &ParentScope<'a>, - start_module: Module<'a>, + parent_scope: &ParentScope<'ra>, + start_module: Module<'ra>, crate_path: ThinVec, filter_fn: FilterFn, ) -> Vec @@ -1343,7 +1343,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &mut self, lookup_ident: Ident, namespace: Namespace, - parent_scope: &ParentScope<'a>, + parent_scope: &ParentScope<'ra>, filter_fn: FilterFn, ) -> Vec where @@ -1421,7 +1421,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &mut self, err: &mut Diag<'_>, macro_kind: MacroKind, - parent_scope: &ParentScope<'a>, + parent_scope: &ParentScope<'ra>, ident: Ident, krate: &Crate, ) { @@ -1749,7 +1749,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { None } - fn report_privacy_error(&mut self, privacy_error: &PrivacyError<'a>) { + fn report_privacy_error(&mut self, privacy_error: &PrivacyError<'ra>) { let PrivacyError { ident, binding, outermost_res, parent_scope, single_nested, dedup_span } = *privacy_error; @@ -1954,7 +1954,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pub(crate) fn find_similarly_named_module_or_crate( &mut self, ident: Symbol, - current_module: Module<'a>, + current_module: Module<'ra>, ) -> Option { let mut candidates = self .extern_prelude @@ -1982,11 +1982,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &mut self, path: &[Segment], opt_ns: Option, // `None` indicates a module path in import - parent_scope: &ParentScope<'a>, - ribs: Option<&PerNS>>>, - ignore_binding: Option>, - ignore_import: Option>, - module: Option>, + parent_scope: &ParentScope<'ra>, + ribs: Option<&PerNS>>>, + ignore_binding: Option>, + ignore_import: Option>, + module: Option>, failed_segment_idx: usize, ident: Ident, ) -> (String, Option) { @@ -2228,7 +2228,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &mut self, span: Span, mut path: Vec, - parent_scope: &ParentScope<'a>, + parent_scope: &ParentScope<'ra>, ) -> Option<(Vec, Option)> { debug!("make_path_suggestion: span={:?} path={:?}", span, path); @@ -2263,7 +2263,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn make_missing_self_suggestion( &mut self, mut path: Vec, - parent_scope: &ParentScope<'a>, + parent_scope: &ParentScope<'ra>, ) -> Option<(Vec, Option)> { // Replace first ident with `self` and check if that is valid. path[0].ident.name = kw::SelfLower; @@ -2282,7 +2282,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn make_missing_crate_suggestion( &mut self, mut path: Vec, - parent_scope: &ParentScope<'a>, + parent_scope: &ParentScope<'ra>, ) -> Option<(Vec, Option)> { // Replace first ident with `crate` and check if that is valid. path[0].ident.name = kw::Crate; @@ -2313,7 +2313,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn make_missing_super_suggestion( &mut self, mut path: Vec, - parent_scope: &ParentScope<'a>, + parent_scope: &ParentScope<'ra>, ) -> Option<(Vec, Option)> { // Replace first ident with `crate` and check if that is valid. path[0].ident.name = kw::Super; @@ -2335,7 +2335,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn make_external_crate_suggestion( &mut self, mut path: Vec, - parent_scope: &ParentScope<'a>, + parent_scope: &ParentScope<'ra>, ) -> Option<(Vec, Option)> { if path[1].ident.span.is_rust_2015() { return None; @@ -2378,8 +2378,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// ``` pub(crate) fn check_for_module_export_macro( &mut self, - import: Import<'a>, - module: ModuleOrUniformRoot<'a>, + import: Import<'ra>, + module: ModuleOrUniformRoot<'ra>, ident: Ident, ) -> Option<(Option, Option)> { let ModuleOrUniformRoot::Module(mut crate_module) = module else { diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs index 5ee495da2d93d..c91eed0e39b36 100644 --- a/compiler/rustc_resolve/src/effective_visibilities.rs +++ b/compiler/rustc_resolve/src/effective_visibilities.rs @@ -11,9 +11,9 @@ use tracing::info; use crate::{NameBinding, NameBindingKind, Resolver}; #[derive(Clone, Copy)] -enum ParentId<'a> { +enum ParentId<'ra> { Def(LocalDefId), - Import(NameBinding<'a>), + Import(NameBinding<'ra>), } impl ParentId<'_> { @@ -25,13 +25,13 @@ impl ParentId<'_> { } } -pub(crate) struct EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> { - r: &'r mut Resolver<'a, 'tcx>, +pub(crate) struct EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> { + r: &'a mut Resolver<'ra, 'tcx>, def_effective_visibilities: EffectiveVisibilities, /// While walking import chains we need to track effective visibilities per-binding, and def id /// keys in `Resolver::effective_visibilities` are not enough for that, because multiple /// bindings can correspond to a single def id in imports. So we keep a separate table. - import_effective_visibilities: EffectiveVisibilities>, + import_effective_visibilities: EffectiveVisibilities>, // It's possible to recalculate this at any point, but it's relatively expensive. current_private_vis: Visibility, changed: bool, @@ -63,14 +63,14 @@ impl Resolver<'_, '_> { } } -impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> { +impl<'a, 'ra, 'tcx> EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> { /// Fills the `Resolver::effective_visibilities` table with public & exported items /// For now, this doesn't resolve macros (FIXME) and cannot resolve Impl, as we /// need access to a TyCtxt for that. Returns the set of ambiguous re-exports. pub(crate) fn compute_effective_visibilities<'c>( - r: &'r mut Resolver<'a, 'tcx>, + r: &'a mut Resolver<'ra, 'tcx>, krate: &'c Crate, - ) -> FxHashSet> { + ) -> FxHashSet> { let mut visitor = EffectiveVisibilitiesVisitor { r, def_effective_visibilities: Default::default(), @@ -127,7 +127,7 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> { // leading to it into the table. They are used by the `ambiguous_glob_reexports` // lint. For all bindings added to the table this way `is_ambiguity` returns true. let is_ambiguity = - |binding: NameBinding<'a>, warn: bool| binding.ambiguity.is_some() && !warn; + |binding: NameBinding<'ra>, warn: bool| binding.ambiguity.is_some() && !warn; let mut parent_id = ParentId::Def(module_id); let mut warn_ambiguity = binding.warn_ambiguity; while let NameBindingKind::Import { binding: nested_binding, .. } = binding.kind { @@ -153,7 +153,7 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> { } } - fn effective_vis_or_private(&mut self, parent_id: ParentId<'a>) -> EffectiveVisibility { + fn effective_vis_or_private(&mut self, parent_id: ParentId<'ra>) -> EffectiveVisibility { // Private nodes are only added to the table for caching, they could be added or removed at // any moment without consequences, so we don't set `changed` to true when adding them. *match parent_id { @@ -190,7 +190,7 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> { } } - fn update_import(&mut self, binding: NameBinding<'a>, parent_id: ParentId<'a>) { + fn update_import(&mut self, binding: NameBinding<'ra>, parent_id: ParentId<'ra>) { let nominal_vis = binding.vis.expect_local(); let Some(cheap_private_vis) = self.may_update(nominal_vis, parent_id) else { return }; let inherited_eff_vis = self.effective_vis_or_private(parent_id); @@ -205,7 +205,12 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> { ); } - fn update_def(&mut self, def_id: LocalDefId, nominal_vis: Visibility, parent_id: ParentId<'a>) { + fn update_def( + &mut self, + def_id: LocalDefId, + nominal_vis: Visibility, + parent_id: ParentId<'ra>, + ) { let Some(cheap_private_vis) = self.may_update(nominal_vis, parent_id) else { return }; let inherited_eff_vis = self.effective_vis_or_private(parent_id); let tcx = self.r.tcx; @@ -224,8 +229,8 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> { } } -impl<'r, 'ast, 'tcx> Visitor<'ast> for EffectiveVisibilitiesVisitor<'ast, 'r, 'tcx> { - fn visit_item(&mut self, item: &'ast ast::Item) { +impl<'a, 'ra, 'tcx> Visitor<'a> for EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> { + fn visit_item(&mut self, item: &'a ast::Item) { let def_id = self.r.local_def_id(item.id); // Update effective visibilities of nested items. // If it's a mod, also make the visitor walk all of its items diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 87f8e51f28231..1602db2f19651 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -38,16 +38,16 @@ impl From for bool { } } -impl<'a, 'tcx> Resolver<'a, 'tcx> { +impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// A generic scope visitor. /// Visits scopes in order to resolve some identifier in them or perform other actions. /// If the callback returns `Some` result, we stop visiting scopes and return it. pub(crate) fn visit_scopes( &mut self, - scope_set: ScopeSet<'a>, - parent_scope: &ParentScope<'a>, + scope_set: ScopeSet<'ra>, + parent_scope: &ParentScope<'ra>, ctxt: SyntaxContext, - mut visitor: impl FnMut(&mut Self, Scope<'a>, UsePrelude, SyntaxContext) -> Option, + mut visitor: impl FnMut(&mut Self, Scope<'ra>, UsePrelude, SyntaxContext) -> Option, ) -> Option { // General principles: // 1. Not controlled (user-defined) names should have higher priority than controlled names @@ -218,10 +218,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn hygienic_lexical_parent( &mut self, - module: Module<'a>, + module: Module<'ra>, ctxt: &mut SyntaxContext, derive_fallback_lint_id: Option, - ) -> Option<(Module<'a>, Option)> { + ) -> Option<(Module<'ra>, Option)> { if !module.expansion.outer_expn_is_descendant_of(*ctxt) { return Some((self.expn_def_scope(ctxt.remove_mark()), None)); } @@ -286,11 +286,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &mut self, mut ident: Ident, ns: Namespace, - parent_scope: &ParentScope<'a>, + parent_scope: &ParentScope<'ra>, finalize: Option, - ribs: &[Rib<'a>], - ignore_binding: Option>, - ) -> Option> { + ribs: &[Rib<'ra>], + ignore_binding: Option>, + ) -> Option> { assert!(ns == TypeNS || ns == ValueNS); let orig_ident = ident; if ident.name == kw::Empty { @@ -381,13 +381,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pub(crate) fn early_resolve_ident_in_lexical_scope( &mut self, orig_ident: Ident, - scope_set: ScopeSet<'a>, - parent_scope: &ParentScope<'a>, + scope_set: ScopeSet<'ra>, + parent_scope: &ParentScope<'ra>, finalize: Option, force: bool, - ignore_binding: Option>, - ignore_import: Option>, - ) -> Result, Determinacy> { + ignore_binding: Option>, + ignore_import: Option>, + ) -> Result, Determinacy> { bitflags::bitflags! { #[derive(Clone, Copy)] struct Flags: u8 { @@ -742,12 +742,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { #[instrument(level = "debug", skip(self))] pub(crate) fn maybe_resolve_ident_in_module( &mut self, - module: ModuleOrUniformRoot<'a>, + module: ModuleOrUniformRoot<'ra>, ident: Ident, ns: Namespace, - parent_scope: &ParentScope<'a>, - ignore_import: Option>, - ) -> Result, Determinacy> { + parent_scope: &ParentScope<'ra>, + ignore_import: Option>, + ) -> Result, Determinacy> { self.resolve_ident_in_module_ext(module, ident, ns, parent_scope, None, None, ignore_import) .map_err(|(determinacy, _)| determinacy) } @@ -755,14 +755,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { #[instrument(level = "debug", skip(self))] pub(crate) fn resolve_ident_in_module( &mut self, - module: ModuleOrUniformRoot<'a>, + module: ModuleOrUniformRoot<'ra>, ident: Ident, ns: Namespace, - parent_scope: &ParentScope<'a>, + parent_scope: &ParentScope<'ra>, finalize: Option, - ignore_binding: Option>, - ignore_import: Option>, - ) -> Result, Determinacy> { + ignore_binding: Option>, + ignore_import: Option>, + ) -> Result, Determinacy> { self.resolve_ident_in_module_ext( module, ident, @@ -778,14 +778,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { #[instrument(level = "debug", skip(self))] fn resolve_ident_in_module_ext( &mut self, - module: ModuleOrUniformRoot<'a>, + module: ModuleOrUniformRoot<'ra>, mut ident: Ident, ns: Namespace, - parent_scope: &ParentScope<'a>, + parent_scope: &ParentScope<'ra>, finalize: Option, - ignore_binding: Option>, - ignore_import: Option>, - ) -> Result, (Determinacy, Weak)> { + ignore_binding: Option>, + ignore_import: Option>, + ) -> Result, (Determinacy, Weak)> { let tmp_parent_scope; let mut adjusted_parent_scope = parent_scope; match module { @@ -818,14 +818,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { #[instrument(level = "debug", skip(self))] fn resolve_ident_in_module_unadjusted( &mut self, - module: ModuleOrUniformRoot<'a>, + module: ModuleOrUniformRoot<'ra>, ident: Ident, ns: Namespace, - parent_scope: &ParentScope<'a>, + parent_scope: &ParentScope<'ra>, finalize: Option, - ignore_binding: Option>, - ignore_import: Option>, - ) -> Result, Determinacy> { + ignore_binding: Option>, + ignore_import: Option>, + ) -> Result, Determinacy> { self.resolve_ident_in_module_unadjusted_ext( module, ident, @@ -844,17 +844,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { #[instrument(level = "debug", skip(self))] fn resolve_ident_in_module_unadjusted_ext( &mut self, - module: ModuleOrUniformRoot<'a>, + module: ModuleOrUniformRoot<'ra>, ident: Ident, ns: Namespace, - parent_scope: &ParentScope<'a>, + parent_scope: &ParentScope<'ra>, restricted_shadowing: bool, finalize: Option, // This binding should be ignored during in-module resolution, so that we don't get // "self-confirming" import resolutions during import validation and checking. - ignore_binding: Option>, - ignore_import: Option>, - ) -> Result, (Determinacy, Weak)> { + ignore_binding: Option>, + ignore_import: Option>, + ) -> Result, (Determinacy, Weak)> { let module = match module { ModuleOrUniformRoot::Module(module) => module, ModuleOrUniformRoot::CrateRootAndExternPrelude => { @@ -970,7 +970,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { return Ok(binding); } - let check_usable = |this: &mut Self, binding: NameBinding<'a>| { + let check_usable = |this: &mut Self, binding: NameBinding<'ra>| { let usable = this.is_accessible_from(binding.vis, parent_scope.module); if usable { Ok(binding) } else { Err((Determined, Weak::No)) } }; @@ -1151,7 +1151,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { mut res: Res, finalize: Option, original_rib_ident_def: Ident, - all_ribs: &[Rib<'a>], + all_ribs: &[Rib<'ra>], ) -> Res { debug!("validate_res_from_ribs({:?})", res); let ribs = &all_ribs[rib_index + 1..]; @@ -1436,9 +1436,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &mut self, path: &[Segment], opt_ns: Option, // `None` indicates a module path in import - parent_scope: &ParentScope<'a>, - ignore_import: Option>, - ) -> PathResult<'a> { + parent_scope: &ParentScope<'ra>, + ignore_import: Option>, + ) -> PathResult<'ra> { self.resolve_path_with_ribs(path, opt_ns, parent_scope, None, None, None, ignore_import) } @@ -1447,11 +1447,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &mut self, path: &[Segment], opt_ns: Option, // `None` indicates a module path in import - parent_scope: &ParentScope<'a>, + parent_scope: &ParentScope<'ra>, finalize: Option, - ignore_binding: Option>, - ignore_import: Option>, - ) -> PathResult<'a> { + ignore_binding: Option>, + ignore_import: Option>, + ) -> PathResult<'ra> { self.resolve_path_with_ribs( path, opt_ns, @@ -1467,12 +1467,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &mut self, path: &[Segment], opt_ns: Option, // `None` indicates a module path in import - parent_scope: &ParentScope<'a>, + parent_scope: &ParentScope<'ra>, finalize: Option, - ribs: Option<&PerNS>>>, - ignore_binding: Option>, - ignore_import: Option>, - ) -> PathResult<'a> { + ribs: Option<&PerNS>>>, + ignore_binding: Option>, + ignore_import: Option>, + ) -> PathResult<'ra> { let mut module = None; let mut allow_super = true; let mut second_binding = None; diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 42171edf75749..2edff67f96a0f 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -43,7 +43,7 @@ type Res = def::Res; /// Contains data for specific kinds of imports. #[derive(Clone)] -pub(crate) enum ImportKind<'a> { +pub(crate) enum ImportKind<'ra> { Single { /// `source` in `use prefix::source as target`. source: Ident, @@ -51,9 +51,9 @@ pub(crate) enum ImportKind<'a> { /// It will directly use `source` when the format is `use prefix::source`. target: Ident, /// Bindings to which `source` refers to. - source_bindings: PerNS, Determinacy>>>, + source_bindings: PerNS, Determinacy>>>, /// Bindings introduced by `target`. - target_bindings: PerNS>>>, + target_bindings: PerNS>>>, /// `true` for `...::{self [as target]}` imports, `false` otherwise. type_ns_only: bool, /// Did this import result from a nested import? ie. `use foo::{bar, baz};` @@ -93,7 +93,7 @@ pub(crate) enum ImportKind<'a> { /// Manually implement `Debug` for `ImportKind` because the `source/target_bindings` /// contain `Cell`s which can introduce infinite loops while printing. -impl<'a> std::fmt::Debug for ImportKind<'a> { +impl<'ra> std::fmt::Debug for ImportKind<'ra> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { use ImportKind::*; match self { @@ -142,8 +142,8 @@ impl<'a> std::fmt::Debug for ImportKind<'a> { /// One import. #[derive(Debug, Clone)] -pub(crate) struct ImportData<'a> { - pub kind: ImportKind<'a>, +pub(crate) struct ImportData<'ra> { + pub kind: ImportKind<'ra>, /// Node ID of the "root" use item -- this is always the same as `ImportKind`'s `id` /// (if it exists) except in the case of "nested" use trees, in which case @@ -171,18 +171,18 @@ pub(crate) struct ImportData<'a> { /// Span of the *root* use tree (see `root_id`). pub root_span: Span, - pub parent_scope: ParentScope<'a>, + pub parent_scope: ParentScope<'ra>, pub module_path: Vec, /// The resolution of `module_path`. - pub imported_module: Cell>>, + pub imported_module: Cell>>, pub vis: ty::Visibility, } /// All imports are unique and allocated on a same arena, /// so we can use referential equality to compare them. -pub(crate) type Import<'a> = Interned<'a, ImportData<'a>>; +pub(crate) type Import<'ra> = Interned<'ra, ImportData<'ra>>; -impl<'a> ImportData<'a> { +impl<'ra> ImportData<'ra> { pub(crate) fn is_glob(&self) -> bool { matches!(self.kind, ImportKind::Glob { .. }) } @@ -217,18 +217,18 @@ impl<'a> ImportData<'a> { /// Records information about the resolution of a name in a namespace of a module. #[derive(Clone, Default, Debug)] -pub(crate) struct NameResolution<'a> { +pub(crate) struct NameResolution<'ra> { /// Single imports that may define the name in the namespace. /// Imports are arena-allocated, so it's ok to use pointers as keys. - pub single_imports: FxHashSet>, + pub single_imports: FxHashSet>, /// The least shadowable known binding for this name, or None if there are no known bindings. - pub binding: Option>, - pub shadowed_glob: Option>, + pub binding: Option>, + pub shadowed_glob: Option>, } -impl<'a> NameResolution<'a> { +impl<'ra> NameResolution<'ra> { /// Returns the binding for the name if it is known or None if it not known. - pub(crate) fn binding(&self) -> Option> { + pub(crate) fn binding(&self) -> Option> { self.binding.and_then(|binding| { if !binding.is_glob_import() || self.single_imports.is_empty() { Some(binding) @@ -270,10 +270,14 @@ fn pub_use_of_private_extern_crate_hack( } } -impl<'a, 'tcx> Resolver<'a, 'tcx> { +impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// Given a binding and an import that resolves to it, /// return the corresponding binding defined by the import. - pub(crate) fn import(&self, binding: NameBinding<'a>, import: Import<'a>) -> NameBinding<'a> { + pub(crate) fn import( + &self, + binding: NameBinding<'ra>, + import: Import<'ra>, + ) -> NameBinding<'ra> { let import_vis = import.vis.to_def_id(); let vis = if binding.vis.is_at_least(import_vis, self.tcx) || pub_use_of_private_extern_crate_hack(import, binding).is_some() @@ -305,11 +309,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// `update` indicates if the definition is a redefinition of an existing binding. pub(crate) fn try_define( &mut self, - module: Module<'a>, + module: Module<'ra>, key: BindingKey, - binding: NameBinding<'a>, + binding: NameBinding<'ra>, warn_ambiguity: bool, - ) -> Result<(), NameBinding<'a>> { + ) -> Result<(), NameBinding<'ra>> { let res = binding.res(); self.check_reserved_macro_name(key.ident, res); self.set_binding_parent_module(binding, module); @@ -394,16 +398,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn new_ambiguity_binding( &self, ambiguity_kind: AmbiguityKind, - primary_binding: NameBinding<'a>, - secondary_binding: NameBinding<'a>, + primary_binding: NameBinding<'ra>, + secondary_binding: NameBinding<'ra>, warn_ambiguity: bool, - ) -> NameBinding<'a> { + ) -> NameBinding<'ra> { let ambiguity = Some((secondary_binding, ambiguity_kind)); let data = NameBindingData { ambiguity, warn_ambiguity, ..*primary_binding }; self.arenas.alloc_name_binding(data) } - fn new_warn_ambiguity_binding(&self, binding: NameBinding<'a>) -> NameBinding<'a> { + fn new_warn_ambiguity_binding(&self, binding: NameBinding<'ra>) -> NameBinding<'ra> { assert!(binding.is_ambiguity_recursive()); self.arenas.alloc_name_binding(NameBindingData { warn_ambiguity: true, ..*binding }) } @@ -412,13 +416,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // If the resolution becomes a success, define it in the module's glob importers. fn update_resolution( &mut self, - module: Module<'a>, + module: Module<'ra>, key: BindingKey, warn_ambiguity: bool, f: F, ) -> T where - F: FnOnce(&mut Resolver<'a, 'tcx>, &mut NameResolution<'a>) -> T, + F: FnOnce(&mut Resolver<'ra, 'tcx>, &mut NameResolution<'ra>) -> T, { // Ensure that `resolution` isn't borrowed when defining in the module's glob importers, // during which the resolution might end up getting re-defined via a glob cycle. @@ -466,7 +470,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Define a dummy resolution containing a `Res::Err` as a placeholder for a failed // or indeterminate resolution, also mark such failed imports as used to avoid duplicate diagnostics. - fn import_dummy_binding(&mut self, import: Import<'a>, is_indeterminate: bool) { + fn import_dummy_binding(&mut self, import: Import<'ra>, is_indeterminate: bool) { if let ImportKind::Single { target, ref target_bindings, .. } = import.kind { if !(is_indeterminate || target_bindings.iter().all(|binding| binding.get().is_none())) { @@ -599,7 +603,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pub(crate) fn check_hidden_glob_reexports( &mut self, - exported_ambiguities: FxHashSet>, + exported_ambiguities: FxHashSet>, ) { for module in self.arenas.local_modules().iter() { for (key, resolution) in self.resolutions(*module).borrow().iter() { @@ -759,7 +763,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// /// Meanwhile, if resolve successful, the resolved bindings are written /// into the module. - fn resolve_import(&mut self, import: Import<'a>) -> usize { + fn resolve_import(&mut self, import: Import<'ra>) -> usize { debug!( "(resolving import for module) resolving import `{}::...` in `{}`", Segment::names_to_string(&import.module_path), @@ -847,7 +851,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// /// Optionally returns an unresolved import error. This error is buffered and used to /// consolidate multiple unresolved import errors into a single diagnostic. - fn finalize_import(&mut self, import: Import<'a>) -> Option { + fn finalize_import(&mut self, import: Import<'ra>) -> Option { let ignore_binding = match &import.kind { ImportKind::Single { target_bindings, .. } => target_bindings[TypeNS].get(), _ => None, @@ -1323,7 +1327,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { None } - pub(crate) fn check_for_redundant_imports(&mut self, import: Import<'a>) -> bool { + pub(crate) fn check_for_redundant_imports(&mut self, import: Import<'ra>) -> bool { // This function is only called for single imports. let ImportKind::Single { source, target, ref source_bindings, ref target_bindings, id, .. @@ -1398,7 +1402,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { false } - fn resolve_glob_import(&mut self, import: Import<'a>) { + fn resolve_glob_import(&mut self, import: Import<'ra>) { // This function is only called for glob imports. let ImportKind::Glob { id, is_prelude, .. } = import.kind else { unreachable!() }; @@ -1458,7 +1462,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Miscellaneous post-processing, including recording re-exports, // reporting conflicts, and reporting unresolved imports. - fn finalize_resolutions_in(&mut self, module: Module<'a>) { + fn finalize_resolutions_in(&mut self, module: Module<'ra>) { // Since import resolution is finished, globs will not define any more names. *module.globs.borrow_mut() = Vec::new(); diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 917cb81aa511f..8ebfe328e3e3d 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -172,7 +172,7 @@ enum RecordPartialRes { /// The rib kind restricts certain accesses, /// e.g. to a `Res::Local` of an outer item. #[derive(Copy, Clone, Debug)] -pub(crate) enum RibKind<'a> { +pub(crate) enum RibKind<'ra> { /// No restriction needs to be applied. Normal, @@ -195,7 +195,7 @@ pub(crate) enum RibKind<'a> { ConstantItem(ConstantHasGenerics, Option<(Ident, ConstantItemKind)>), /// We passed through a module. - Module(Module<'a>), + Module(Module<'ra>), /// We passed through a `macro_rules!` statement MacroDefinition(DefId), @@ -260,13 +260,13 @@ impl RibKind<'_> { /// The resolution keeps a separate stack of ribs as it traverses the AST for each namespace. When /// resolving, the name is looked up from inside out. #[derive(Debug)] -pub(crate) struct Rib<'a, R = Res> { +pub(crate) struct Rib<'ra, R = Res> { pub bindings: IdentMap, - pub kind: RibKind<'a>, + pub kind: RibKind<'ra>, } -impl<'a, R> Rib<'a, R> { - fn new(kind: RibKind<'a>) -> Rib<'a, R> { +impl<'ra, R> Rib<'ra, R> { + fn new(kind: RibKind<'ra>) -> Rib<'ra, R> { Rib { bindings: Default::default(), kind } } } @@ -584,8 +584,8 @@ impl MaybeExported<'_> { /// Used for recording UnnecessaryQualification. #[derive(Debug)] -pub(crate) struct UnnecessaryQualification<'a> { - pub binding: LexicalScopeBinding<'a>, +pub(crate) struct UnnecessaryQualification<'ra> { + pub binding: LexicalScopeBinding<'ra>, pub node_id: NodeId, pub path_span: Span, pub removal_span: Span, @@ -659,20 +659,20 @@ struct DiagMetadata<'ast> { current_elision_failures: Vec, } -struct LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { - r: &'b mut Resolver<'a, 'tcx>, +struct LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { + r: &'a mut Resolver<'ra, 'tcx>, /// The module that represents the current item scope. - parent_scope: ParentScope<'a>, + parent_scope: ParentScope<'ra>, /// The current set of local scopes for types and values. - ribs: PerNS>>, + ribs: PerNS>>, /// Previous popped `rib`, only used for diagnostic. - last_block_rib: Option>, + last_block_rib: Option>, /// The current set of local scopes, for labels. - label_ribs: Vec>, + label_ribs: Vec>, /// The current set of local scopes for lifetimes. lifetime_ribs: Vec, @@ -685,7 +685,7 @@ struct LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { lifetime_elision_candidates: Option>, /// The trait that the current context can refer to. - current_trait_ref: Option<(Module<'a>, TraitRef)>, + current_trait_ref: Option<(Module<'ra>, TraitRef)>, /// Fields used to add information to diagnostic errors. diag_metadata: Box>, @@ -702,7 +702,7 @@ struct LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } /// Walks the whole crate in DFS order, visiting each item, resolving names as it goes. -impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, 'tcx> { +impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { fn visit_attribute(&mut self, _: &'ast Attribute) { // We do not want to resolve expressions that appear in attributes, // as they do not correspond to actual code. @@ -1316,8 +1316,8 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, } } -impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { - fn new(resolver: &'b mut Resolver<'a, 'tcx>) -> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { +impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { + fn new(resolver: &'a mut Resolver<'ra, 'tcx>) -> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // During late resolution we only track the module component of the parent scope, // although it may be useful to track other components as well for diagnostics. let graph_root = resolver.graph_root; @@ -1347,7 +1347,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { &mut self, ident: Ident, ns: Namespace, - ) -> Option> { + ) -> Option> { self.r.resolve_ident_in_lexical_scope( ident, ns, @@ -1363,8 +1363,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ident: Ident, ns: Namespace, finalize: Option, - ignore_binding: Option>, - ) -> Option> { + ignore_binding: Option>, + ) -> Option> { self.r.resolve_ident_in_lexical_scope( ident, ns, @@ -1380,7 +1380,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { path: &[Segment], opt_ns: Option, // `None` indicates a module path in import finalize: Option, - ) -> PathResult<'a> { + ) -> PathResult<'ra> { self.r.resolve_path_with_ribs( path, opt_ns, @@ -1414,7 +1414,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { fn with_rib( &mut self, ns: Namespace, - kind: RibKind<'a>, + kind: RibKind<'ra>, work: impl FnOnce(&mut Self) -> T, ) -> T { self.ribs[ns].push(Rib::new(kind)); @@ -2266,14 +2266,14 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { /// Visits a type to find all the &references, and determines the /// set of lifetimes for all of those references where the referent /// contains Self. - struct FindReferenceVisitor<'r, 'a, 'tcx> { - r: &'r Resolver<'a, 'tcx>, + struct FindReferenceVisitor<'a, 'ra, 'tcx> { + r: &'a Resolver<'ra, 'tcx>, impl_self: Option, lifetime: Set1, } - impl<'a> Visitor<'a> for FindReferenceVisitor<'_, '_, '_> { - fn visit_ty(&mut self, ty: &'a Ty) { + impl<'ra> Visitor<'ra> for FindReferenceVisitor<'_, '_, '_> { + fn visit_ty(&mut self, ty: &'ra Ty) { trace!("FindReferenceVisitor considering ty={:?}", ty); if let TyKind::Ref(lt, _) = ty.kind { // See if anything inside the &thing contains Self @@ -2299,13 +2299,13 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // A type may have an expression as a const generic argument. // We do not want to recurse into those. - fn visit_expr(&mut self, _: &'a Expr) {} + fn visit_expr(&mut self, _: &'ra Expr) {} } /// Visitor which checks the referent of a &Thing to see if the /// Thing contains Self - struct SelfVisitor<'r, 'a, 'tcx> { - r: &'r Resolver<'a, 'tcx>, + struct SelfVisitor<'a, 'ra, 'tcx> { + r: &'a Resolver<'ra, 'tcx>, impl_self: Option, self_found: bool, } @@ -2327,8 +2327,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } } - impl<'a> Visitor<'a> for SelfVisitor<'_, '_, '_> { - fn visit_ty(&mut self, ty: &'a Ty) { + impl<'ra> Visitor<'ra> for SelfVisitor<'_, '_, '_> { + fn visit_ty(&mut self, ty: &'ra Ty) { trace!("SelfVisitor considering ty={:?}", ty); if self.is_self_ty(ty) { trace!("SelfVisitor found Self"); @@ -2339,7 +2339,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // A type may have an expression as a const generic argument. // We do not want to recurse into those. - fn visit_expr(&mut self, _: &'a Expr) {} + fn visit_expr(&mut self, _: &'ra Expr) {} } let impl_self = self @@ -2371,7 +2371,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { /// Searches the current set of local scopes for labels. Returns the `NodeId` of the resolved /// label and reports an error if the label is not found or is unreachable. - fn resolve_label(&mut self, mut label: Ident) -> Result<(NodeId, Span), ResolutionError<'a>> { + fn resolve_label(&mut self, mut label: Ident) -> Result<(NodeId, Span), ResolutionError<'ra>> { let mut suggestion = None; for i in (0..self.label_ribs.len()).rev() { @@ -2712,7 +2712,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { fn with_generic_param_rib<'c, F>( &'c mut self, params: &'c [GenericParam], - kind: RibKind<'a>, + kind: RibKind<'ra>, lifetime_kind: LifetimeRibKind, f: F, ) where @@ -2878,7 +2878,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } } - fn with_label_rib(&mut self, kind: RibKind<'a>, f: impl FnOnce(&mut Self)) { + fn with_label_rib(&mut self, kind: RibKind<'ra>, f: impl FnOnce(&mut Self)) { self.label_ribs.push(Rib::new(kind)); f(self); self.label_ribs.pop(); @@ -3306,7 +3306,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { seen_trait_items: &mut FxHashMap, err: F, ) where - F: FnOnce(Ident, String, Option) -> ResolutionError<'a>, + F: FnOnce(Ident, String, Option) -> ResolutionError<'ra>, { // If there is a TraitRef in scope for an impl, then the method must be in the trait. let Some((module, _)) = self.current_trait_ref else { @@ -4010,101 +4010,102 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // about possible missing imports. // // Similar thing, for types, happens in `report_errors` above. - let report_errors_for_call = |this: &mut Self, parent_err: Spanned>| { - // Before we start looking for candidates, we have to get our hands - // on the type user is trying to perform invocation on; basically: - // we're transforming `HashMap::new` into just `HashMap`. - let (following_seg, prefix_path) = match path.split_last() { - Some((last, path)) if !path.is_empty() => (Some(last), path), - _ => return Some(parent_err), - }; + let report_errors_for_call = + |this: &mut Self, parent_err: Spanned>| { + // Before we start looking for candidates, we have to get our hands + // on the type user is trying to perform invocation on; basically: + // we're transforming `HashMap::new` into just `HashMap`. + let (following_seg, prefix_path) = match path.split_last() { + Some((last, path)) if !path.is_empty() => (Some(last), path), + _ => return Some(parent_err), + }; - let (mut err, candidates) = this.smart_resolve_report_errors( - prefix_path, - following_seg, - path_span, - PathSource::Type, - None, - ); + let (mut err, candidates) = this.smart_resolve_report_errors( + prefix_path, + following_seg, + path_span, + PathSource::Type, + None, + ); - // There are two different error messages user might receive at - // this point: - // - E0412 cannot find type `{}` in this scope - // - E0433 failed to resolve: use of undeclared type or module `{}` - // - // The first one is emitted for paths in type-position, and the - // latter one - for paths in expression-position. - // - // Thus (since we're in expression-position at this point), not to - // confuse the user, we want to keep the *message* from E0433 (so - // `parent_err`), but we want *hints* from E0412 (so `err`). - // - // And that's what happens below - we're just mixing both messages - // into a single one. - let mut parent_err = this.r.into_struct_error(parent_err.span, parent_err.node); - - // overwrite all properties with the parent's error message - err.messages = take(&mut parent_err.messages); - err.code = take(&mut parent_err.code); - swap(&mut err.span, &mut parent_err.span); - err.children = take(&mut parent_err.children); - err.sort_span = parent_err.sort_span; - err.is_lint = parent_err.is_lint.clone(); - - // merge the parent's suggestions with the typo suggestions - fn append_result(res1: &mut Result, E>, res2: Result, E>) { - match res1 { - Ok(vec1) => match res2 { - Ok(mut vec2) => vec1.append(&mut vec2), - Err(e) => *res1 = Err(e), - }, - Err(_) => (), - }; - } - append_result(&mut err.suggestions, parent_err.suggestions.clone()); + // There are two different error messages user might receive at + // this point: + // - E0412 cannot find type `{}` in this scope + // - E0433 failed to resolve: use of undeclared type or module `{}` + // + // The first one is emitted for paths in type-position, and the + // latter one - for paths in expression-position. + // + // Thus (since we're in expression-position at this point), not to + // confuse the user, we want to keep the *message* from E0433 (so + // `parent_err`), but we want *hints* from E0412 (so `err`). + // + // And that's what happens below - we're just mixing both messages + // into a single one. + let mut parent_err = this.r.into_struct_error(parent_err.span, parent_err.node); + + // overwrite all properties with the parent's error message + err.messages = take(&mut parent_err.messages); + err.code = take(&mut parent_err.code); + swap(&mut err.span, &mut parent_err.span); + err.children = take(&mut parent_err.children); + err.sort_span = parent_err.sort_span; + err.is_lint = parent_err.is_lint.clone(); + + // merge the parent's suggestions with the typo suggestions + fn append_result(res1: &mut Result, E>, res2: Result, E>) { + match res1 { + Ok(vec1) => match res2 { + Ok(mut vec2) => vec1.append(&mut vec2), + Err(e) => *res1 = Err(e), + }, + Err(_) => (), + }; + } + append_result(&mut err.suggestions, parent_err.suggestions.clone()); - parent_err.cancel(); + parent_err.cancel(); - let def_id = this.parent_scope.module.nearest_parent_mod(); + let def_id = this.parent_scope.module.nearest_parent_mod(); - if this.should_report_errs() { - if candidates.is_empty() { - if path.len() == 2 - && let [segment] = prefix_path - { - // Delay to check whether methond name is an associated function or not - // ``` - // let foo = Foo {}; - // foo::bar(); // possibly suggest to foo.bar(); - //``` - err.stash(segment.ident.span, rustc_errors::StashKey::CallAssocMethod); + if this.should_report_errs() { + if candidates.is_empty() { + if path.len() == 2 + && let [segment] = prefix_path + { + // Delay to check whether methond name is an associated function or not + // ``` + // let foo = Foo {}; + // foo::bar(); // possibly suggest to foo.bar(); + //``` + err.stash(segment.ident.span, rustc_errors::StashKey::CallAssocMethod); + } else { + // When there is no suggested imports, we can just emit the error + // and suggestions immediately. Note that we bypass the usually error + // reporting routine (ie via `self.r.report_error`) because we need + // to post-process the `ResolutionError` above. + err.emit(); + } } else { - // When there is no suggested imports, we can just emit the error - // and suggestions immediately. Note that we bypass the usually error - // reporting routine (ie via `self.r.report_error`) because we need - // to post-process the `ResolutionError` above. - err.emit(); + // If there are suggested imports, the error reporting is delayed + this.r.use_injections.push(UseError { + err, + candidates, + def_id, + instead: false, + suggestion: None, + path: prefix_path.into(), + is_call: source.is_call(), + }); } } else { - // If there are suggested imports, the error reporting is delayed - this.r.use_injections.push(UseError { - err, - candidates, - def_id, - instead: false, - suggestion: None, - path: prefix_path.into(), - is_call: source.is_call(), - }); + err.cancel(); } - } else { - err.cancel(); - } - // We don't return `Some(parent_err)` here, because the error will - // be already printed either immediately or as part of the `use` injections - None - }; + // We don't return `Some(parent_err)` here, because the error will + // be already printed either immediately or as part of the `use` injections + None + }; let partial_res = match self.resolve_qpath_anywhere( qself, @@ -4205,7 +4206,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { /// A wrapper around [`Resolver::report_error`]. /// /// This doesn't emit errors for function bodies if this is rustdoc. - fn report_error(&mut self, span: Span, resolution_error: ResolutionError<'a>) { + fn report_error(&mut self, span: Span, resolution_error: ResolutionError<'ra>) { if self.should_report_errs() { self.r.report_error(span, resolution_error); } @@ -4229,7 +4230,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { span: Span, defer_to_typeck: bool, finalize: Finalize, - ) -> Result, Spanned>> { + ) -> Result, Spanned>> { let mut fin_res = None; for (i, &ns) in [primary_ns, TypeNS, ValueNS].iter().enumerate() { @@ -4271,7 +4272,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { path: &[Segment], ns: Namespace, finalize: Finalize, - ) -> Result, Spanned>> { + ) -> Result, Spanned>> { debug!( "resolve_qpath(qself={:?}, path={:?}, ns={:?}, finalize={:?})", qself, path, ns, finalize, @@ -4922,8 +4923,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { /// Walks the whole crate in DFS order, visiting each item, counting the declared number of /// lifetime generic parameters and function parameters. -struct ItemInfoCollector<'a, 'b, 'tcx> { - r: &'b mut Resolver<'a, 'tcx>, +struct ItemInfoCollector<'a, 'ra, 'tcx> { + r: &'a mut Resolver<'ra, 'tcx>, } impl ItemInfoCollector<'_, '_, '_> { @@ -4990,7 +4991,7 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { } } -impl<'a, 'tcx> Resolver<'a, 'tcx> { +impl<'ra, 'tcx> Resolver<'ra, 'tcx> { pub(crate) fn late_resolve_crate(&mut self, krate: &Crate) { visit::walk_crate(&mut ItemInfoCollector { r: self }, krate); let mut late_resolution_visitor = LateResolutionVisitor::new(self); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 8f516c2db0900..fb658407f6150 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -170,7 +170,7 @@ impl TypoCandidate { } } -impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { +impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { fn make_base_error( &mut self, path: &[Segment], @@ -2278,7 +2278,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { false } - fn find_module(&mut self, def_id: DefId) -> Option<(Module<'a>, ImportSuggestion)> { + fn find_module(&mut self, def_id: DefId) -> Option<(Module<'ra>, ImportSuggestion)> { let mut result = None; let mut seen_modules = FxHashSet::default(); let root_did = self.r.graph_root.def_id(); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 8ffd00d1b2e60..872535627a56c 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -113,14 +113,14 @@ impl Determinacy { /// This enum is currently used only for early resolution (imports and macros), /// but not for late resolution yet. #[derive(Clone, Copy, Debug)] -enum Scope<'a> { +enum Scope<'ra> { DeriveHelpers(LocalExpnId), DeriveHelpersCompat, - MacroRules(MacroRulesScopeRef<'a>), + MacroRules(MacroRulesScopeRef<'ra>), CrateRoot, // The node ID is for reporting the `PROC_MACRO_DERIVE_RESOLUTION_FALLBACK` // lint if it should be reported. - Module(Module<'a>, Option), + Module(Module<'ra>, Option), MacroUsePrelude, BuiltinAttrs, ExternPrelude, @@ -134,7 +134,7 @@ enum Scope<'a> { /// This enum is currently used only for early resolution (imports and macros), /// but not for late resolution yet. #[derive(Clone, Copy, Debug)] -enum ScopeSet<'a> { +enum ScopeSet<'ra> { /// All scopes with the given namespace. All(Namespace), /// Crate root, then extern prelude (used for mixed 2015-2018 mode in macros). @@ -143,7 +143,7 @@ enum ScopeSet<'a> { Macro(MacroKind), /// All scopes with the given namespace, used for partially performing late resolution. /// The node id enables lints and is used for reporting them. - Late(Namespace, Module<'a>, Option), + Late(Namespace, Module<'ra>, Option), } /// Everything you need to know about a name's location to resolve it. @@ -151,17 +151,17 @@ enum ScopeSet<'a> { /// This struct is currently used only for early resolution (imports and macros), /// but not for late resolution yet. #[derive(Clone, Copy, Debug)] -struct ParentScope<'a> { - module: Module<'a>, +struct ParentScope<'ra> { + module: Module<'ra>, expansion: LocalExpnId, - macro_rules: MacroRulesScopeRef<'a>, - derives: &'a [ast::Path], + macro_rules: MacroRulesScopeRef<'ra>, + derives: &'ra [ast::Path], } -impl<'a> ParentScope<'a> { +impl<'ra> ParentScope<'ra> { /// Creates a parent scope with the passed argument used as the module scope component, /// and other scope components set to default empty values. - fn module(module: Module<'a>, resolver: &Resolver<'a, '_>) -> ParentScope<'a> { + fn module(module: Module<'ra>, resolver: &Resolver<'ra, '_>) -> ParentScope<'ra> { ParentScope { module, expansion: LocalExpnId::ROOT, @@ -203,7 +203,7 @@ struct BindingError { } #[derive(Debug)] -enum ResolutionError<'a> { +enum ResolutionError<'ra> { /// Error E0401: can't use type or const parameters from outer item. GenericParamsFromOuterItem(Res, HasGenericParams, DefKind), /// Error E0403: the name is already used for a type or const parameter in this generic @@ -216,7 +216,7 @@ enum ResolutionError<'a> { /// Error E0438: const is not a member of trait. ConstNotMemberOfTrait(Ident, String, Option), /// Error E0408: variable `{}` is not bound in all patterns. - VariableNotBoundInPattern(BindingError, ParentScope<'a>), + VariableNotBoundInPattern(BindingError, ParentScope<'ra>), /// Error E0409: variable `{}` is bound in inconsistent ways within the same match arm. VariableBoundWithDifferentMode(Symbol, Span), /// Error E0415: identifier is bound more than once in this parameter list. @@ -236,7 +236,7 @@ enum ResolutionError<'a> { segment: Option, label: String, suggestion: Option, - module: Option>, + module: Option>, }, /// Error E0434: can't capture dynamic environment in a fn item. CannotCaptureDynamicEnvironmentInFnItem, @@ -377,12 +377,12 @@ impl<'a> From<&'a ast::PathSegment> for Segment { /// items are visible in their whole block, while `Res`es only from the place they are defined /// forward. #[derive(Debug, Copy, Clone)] -enum LexicalScopeBinding<'a> { - Item(NameBinding<'a>), +enum LexicalScopeBinding<'ra> { + Item(NameBinding<'ra>), Res(Res), } -impl<'a> LexicalScopeBinding<'a> { +impl<'ra> LexicalScopeBinding<'ra> { fn res(self) -> Res { match self { LexicalScopeBinding::Item(binding) => binding.res(), @@ -392,9 +392,9 @@ impl<'a> LexicalScopeBinding<'a> { } #[derive(Copy, Clone, PartialEq, Debug)] -enum ModuleOrUniformRoot<'a> { +enum ModuleOrUniformRoot<'ra> { /// Regular module. - Module(Module<'a>), + Module(Module<'ra>), /// Virtual module that denotes resolution in crate root with fallback to extern prelude. CrateRootAndExternPrelude, @@ -410,8 +410,8 @@ enum ModuleOrUniformRoot<'a> { } #[derive(Debug)] -enum PathResult<'a> { - Module(ModuleOrUniformRoot<'a>), +enum PathResult<'ra> { + Module(ModuleOrUniformRoot<'ra>), NonModule(PartialRes), Indeterminate, Failed { @@ -432,20 +432,20 @@ enum PathResult<'a> { /// ``` /// /// In this case, `module` will point to `a`. - module: Option>, + module: Option>, /// The segment name of target segment_name: Symbol, }, } -impl<'a> PathResult<'a> { +impl<'ra> PathResult<'ra> { fn failed( ident: Ident, is_error_from_last_segment: bool, finalize: bool, - module: Option>, + module: Option>, label_and_suggestion: impl FnOnce() -> (String, Option), - ) -> PathResult<'a> { + ) -> PathResult<'ra> { let (label, suggestion) = if finalize { label_and_suggestion() } else { (String::new(), None) }; PathResult::Failed { @@ -518,7 +518,7 @@ impl BindingKey { } } -type Resolutions<'a> = RefCell>>>; +type Resolutions<'ra> = RefCell>>>; /// One node in the tree of modules. /// @@ -531,15 +531,15 @@ type Resolutions<'a> = RefCell { +struct ModuleData<'ra> { /// The direct parent module (it may not be a `mod`, however). - parent: Option>, + parent: Option>, /// What kind of module this is, because this may not be a `mod`. kind: ModuleKind, /// Mapping between names and their (possibly in-progress) resolutions in this module. /// Resolutions in modules from other crates are not populated until accessed. - lazy_resolutions: Resolutions<'a>, + lazy_resolutions: Resolutions<'ra>, /// True if this is a module from other crate that needs to be populated on access. populate_on_access: Cell, @@ -549,11 +549,11 @@ struct ModuleData<'a> { /// Whether `#[no_implicit_prelude]` is active. no_implicit_prelude: bool, - glob_importers: RefCell>>, - globs: RefCell>>, + glob_importers: RefCell>>, + globs: RefCell>>, /// Used to memoize the traits in this module for faster searches through all traits in scope. - traits: RefCell)]>>>, + traits: RefCell)]>>>, /// Span of the module itself. Used for error reporting. span: Span, @@ -565,11 +565,11 @@ struct ModuleData<'a> { /// so we can use referential equality to compare them. #[derive(Clone, Copy, PartialEq, Eq, Hash)] #[rustc_pass_by_value] -struct Module<'a>(Interned<'a, ModuleData<'a>>); +struct Module<'ra>(Interned<'ra, ModuleData<'ra>>); -impl<'a> ModuleData<'a> { +impl<'ra> ModuleData<'ra> { fn new( - parent: Option>, + parent: Option>, kind: ModuleKind, expansion: ExpnId, span: Span, @@ -595,11 +595,11 @@ impl<'a> ModuleData<'a> { } } -impl<'a> Module<'a> { +impl<'ra> Module<'ra> { fn for_each_child<'tcx, R, F>(self, resolver: &mut R, mut f: F) where - R: AsMut>, - F: FnMut(&mut R, Ident, Namespace, NameBinding<'a>), + R: AsMut>, + F: FnMut(&mut R, Ident, Namespace, NameBinding<'ra>), { for (key, name_resolution) in resolver.as_mut().resolutions(self).borrow().iter() { if let Some(binding) = name_resolution.borrow().binding { @@ -611,7 +611,7 @@ impl<'a> Module<'a> { /// This modifies `self` in place. The traits will be stored in `self.traits`. fn ensure_traits<'tcx, R>(self, resolver: &mut R) where - R: AsMut>, + R: AsMut>, { let mut traits = self.traits.borrow_mut(); if traits.is_none() { @@ -656,7 +656,7 @@ impl<'a> Module<'a> { matches!(self.kind, ModuleKind::Def(DefKind::Trait, _, _)) } - fn nearest_item_scope(self) -> Module<'a> { + fn nearest_item_scope(self) -> Module<'ra> { match self.kind { ModuleKind::Def(DefKind::Enum | DefKind::Trait, ..) => { self.parent.expect("enum or trait module without a parent") @@ -686,15 +686,15 @@ impl<'a> Module<'a> { } } -impl<'a> std::ops::Deref for Module<'a> { - type Target = ModuleData<'a>; +impl<'ra> std::ops::Deref for Module<'ra> { + type Target = ModuleData<'ra>; fn deref(&self) -> &Self::Target { &self.0 } } -impl<'a> fmt::Debug for Module<'a> { +impl<'ra> fmt::Debug for Module<'ra> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}", self.res()) } @@ -702,9 +702,9 @@ impl<'a> fmt::Debug for Module<'a> { /// Records a possibly-private value, type, or module definition. #[derive(Clone, Copy, Debug)] -struct NameBindingData<'a> { - kind: NameBindingKind<'a>, - ambiguity: Option<(NameBinding<'a>, AmbiguityKind)>, +struct NameBindingData<'ra> { + kind: NameBindingKind<'ra>, + ambiguity: Option<(NameBinding<'ra>, AmbiguityKind)>, /// Produce a warning instead of an error when reporting ambiguities inside this binding. /// May apply to indirect ambiguities under imports, so `ambiguity.is_some()` is not required. warn_ambiguity: bool, @@ -715,26 +715,26 @@ struct NameBindingData<'a> { /// All name bindings are unique and allocated on a same arena, /// so we can use referential equality to compare them. -type NameBinding<'a> = Interned<'a, NameBindingData<'a>>; +type NameBinding<'ra> = Interned<'ra, NameBindingData<'ra>>; -trait ToNameBinding<'a> { - fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> NameBinding<'a>; +trait ToNameBinding<'ra> { + fn to_name_binding(self, arenas: &'ra ResolverArenas<'ra>) -> NameBinding<'ra>; } -impl<'a> ToNameBinding<'a> for NameBinding<'a> { - fn to_name_binding(self, _: &'a ResolverArenas<'a>) -> NameBinding<'a> { +impl<'ra> ToNameBinding<'ra> for NameBinding<'ra> { + fn to_name_binding(self, _: &'ra ResolverArenas<'ra>) -> NameBinding<'ra> { self } } #[derive(Clone, Copy, Debug)] -enum NameBindingKind<'a> { +enum NameBindingKind<'ra> { Res(Res), - Module(Module<'a>), - Import { binding: NameBinding<'a>, import: Import<'a> }, + Module(Module<'ra>), + Import { binding: NameBinding<'ra>, import: Import<'ra> }, } -impl<'a> NameBindingKind<'a> { +impl<'ra> NameBindingKind<'ra> { /// Is this a name binding of an import? fn is_import(&self) -> bool { matches!(*self, NameBindingKind::Import { .. }) @@ -742,12 +742,12 @@ impl<'a> NameBindingKind<'a> { } #[derive(Debug)] -struct PrivacyError<'a> { +struct PrivacyError<'ra> { ident: Ident, - binding: NameBinding<'a>, + binding: NameBinding<'ra>, dedup_span: Span, outermost_res: Option<(Res, Ident)>, - parent_scope: ParentScope<'a>, + parent_scope: ParentScope<'ra>, /// Is the format `use a::{b,c}`? single_nested: bool, } @@ -812,18 +812,18 @@ enum AmbiguityErrorMisc { None, } -struct AmbiguityError<'a> { +struct AmbiguityError<'ra> { kind: AmbiguityKind, ident: Ident, - b1: NameBinding<'a>, - b2: NameBinding<'a>, + b1: NameBinding<'ra>, + b2: NameBinding<'ra>, misc1: AmbiguityErrorMisc, misc2: AmbiguityErrorMisc, warning: bool, } -impl<'a> NameBindingData<'a> { - fn module(&self) -> Option> { +impl<'ra> NameBindingData<'ra> { + fn module(&self) -> Option> { match self.kind { NameBindingKind::Module(module) => Some(module), NameBindingKind::Import { binding, .. } => binding.module(), @@ -947,8 +947,8 @@ impl<'a> NameBindingData<'a> { } #[derive(Default, Clone)] -struct ExternPreludeEntry<'a> { - binding: Option>, +struct ExternPreludeEntry<'ra> { + binding: Option>, introduced_by_item: bool, } @@ -985,16 +985,16 @@ impl MacroData { /// The main resolver class. /// /// This is the visitor that walks the whole crate. -pub struct Resolver<'a, 'tcx> { +pub struct Resolver<'ra, 'tcx> { tcx: TyCtxt<'tcx>, /// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`. expn_that_defined: FxHashMap, - graph_root: Module<'a>, + graph_root: Module<'ra>, - prelude: Option>, - extern_prelude: FxHashMap>, + prelude: Option>, + extern_prelude: FxHashMap>, /// N.B., this is used only for better diagnostics, not name resolution itself. field_names: LocalDefIdMap>, @@ -1004,10 +1004,10 @@ pub struct Resolver<'a, 'tcx> { field_visibility_spans: FxHashMap>, /// All imports known to succeed or fail. - determined_imports: Vec>, + determined_imports: Vec>, /// All non-determined imports. - indeterminate_imports: Vec>, + indeterminate_imports: Vec>, // Spans for local variables found during pattern resolution. // Used for suggestions during error reporting. @@ -1018,7 +1018,7 @@ pub struct Resolver<'a, 'tcx> { /// Resolutions for import nodes, which have multiple resolutions in different namespaces. import_res_map: NodeMap>>, /// An import will be inserted into this map if it has been used. - import_use_map: FxHashMap, Used>, + import_use_map: FxHashMap, Used>, /// Resolutions for labels (node IDs of their corresponding blocks or loops). label_res_map: NodeMap, /// Resolutions for lifetimes. @@ -1045,13 +1045,13 @@ pub struct Resolver<'a, 'tcx> { /// /// There will be an anonymous module created around `g` with the ID of the /// entry block for `f`. - block_map: NodeMap>, + block_map: NodeMap>, /// A fake module that contains no definition and no prelude. Used so that /// some AST passes can generate identifiers that only resolve to local or /// lang items. - empty_module: Module<'a>, - module_map: FxHashMap>, - binding_parent_modules: FxHashMap, Module<'a>>, + empty_module: Module<'ra>, + module_map: FxHashMap>, + binding_parent_modules: FxHashMap, Module<'ra>>, underscore_disambiguator: u32, /// Disambiguator for anonymous adts. @@ -1065,57 +1065,57 @@ pub struct Resolver<'a, 'tcx> { maybe_unused_trait_imports: FxIndexSet, /// Privacy errors are delayed until the end in order to deduplicate them. - privacy_errors: Vec>, + privacy_errors: Vec>, /// Ambiguity errors are delayed for deduplication. - ambiguity_errors: Vec>, + ambiguity_errors: Vec>, /// `use` injections are delayed for better placement and deduplication. use_injections: Vec>, /// Crate-local macro expanded `macro_export` referred to by a module-relative path. macro_expanded_macro_export_errors: BTreeSet<(Span, Span)>, - arenas: &'a ResolverArenas<'a>, - dummy_binding: NameBinding<'a>, - builtin_types_bindings: FxHashMap>, - builtin_attrs_bindings: FxHashMap>, - registered_tool_bindings: FxHashMap>, + arenas: &'ra ResolverArenas<'ra>, + dummy_binding: NameBinding<'ra>, + builtin_types_bindings: FxHashMap>, + builtin_attrs_bindings: FxHashMap>, + registered_tool_bindings: FxHashMap>, /// Binding for implicitly declared names that come with a module, /// like `self` (not yet used), or `crate`/`$crate` (for root modules). - module_self_bindings: FxHashMap, NameBinding<'a>>, + module_self_bindings: FxHashMap, NameBinding<'ra>>, used_extern_options: FxHashSet, macro_names: FxHashSet, builtin_macros: FxHashMap, registered_tools: &'tcx RegisteredTools, - macro_use_prelude: FxHashMap>, + macro_use_prelude: FxHashMap>, macro_map: FxHashMap, dummy_ext_bang: Lrc, dummy_ext_derive: Lrc, non_macro_attr: MacroData, - local_macro_def_scopes: FxHashMap>, - ast_transform_scopes: FxHashMap>, + local_macro_def_scopes: FxHashMap>, + ast_transform_scopes: FxHashMap>, unused_macros: FxHashMap, unused_macro_rules: FxHashMap<(LocalDefId, usize), (Ident, Span)>, proc_macro_stubs: FxHashSet, /// Traces collected during macro resolution and validated when it's complete. single_segment_macro_resolutions: - Vec<(Ident, MacroKind, ParentScope<'a>, Option>)>, + Vec<(Ident, MacroKind, ParentScope<'ra>, Option>)>, multi_segment_macro_resolutions: - Vec<(Vec, Span, MacroKind, ParentScope<'a>, Option, Namespace)>, - builtin_attrs: Vec<(Ident, ParentScope<'a>)>, + Vec<(Vec, Span, MacroKind, ParentScope<'ra>, Option, Namespace)>, + builtin_attrs: Vec<(Ident, ParentScope<'ra>)>, /// `derive(Copy)` marks items they are applied to so they are treated specially later. /// Derive macros cannot modify the item themselves and have to store the markers in the global /// context, so they attach the markers to derive container IDs using this resolver table. containers_deriving_copy: FxHashSet, /// Parent scopes in which the macros were invoked. /// FIXME: `derives` are missing in these parent scopes and need to be taken from elsewhere. - invocation_parent_scopes: FxHashMap>, + invocation_parent_scopes: FxHashMap>, /// `macro_rules` scopes *produced* by expanding the macro invocations, /// include all the `macro_rules` items and other invocations generated by them. - output_macro_rules_scopes: FxHashMap>, + output_macro_rules_scopes: FxHashMap>, /// `macro_rules` scopes produced by `macro_rules` item definitions. - macro_rules_scopes: FxHashMap>, + macro_rules_scopes: FxHashMap>, /// Helper attributes that are in scope for the given expansion. - helper_attrs: FxHashMap)>>, + helper_attrs: FxHashMap)>>, /// Ready or in-progress results of resolving paths inside the `#[derive(...)]` attribute /// with the given `ExpnId`. derive_data: FxHashMap, @@ -1123,9 +1123,9 @@ pub struct Resolver<'a, 'tcx> { /// Avoid duplicated errors for "name already defined". name_already_seen: FxHashMap, - potentially_unused_imports: Vec>, + potentially_unused_imports: Vec>, - potentially_unnecessary_qualifications: Vec>, + potentially_unnecessary_qualifications: Vec>, /// Table for mapping struct IDs into struct constructor IDs, /// it's not used during normal resolution, only for better error reporting. @@ -1186,28 +1186,29 @@ pub struct Resolver<'a, 'tcx> { current_crate_outer_attr_insert_span: Span, } -/// Nothing really interesting here; it just provides memory for the rest of the crate. +/// This provides memory for the rest of the crate. The `'ra` lifetime that is +/// used by many types in this crate is an abbreviation of `ResolverArenas`. #[derive(Default)] -pub struct ResolverArenas<'a> { - modules: TypedArena>, - local_modules: RefCell>>, - imports: TypedArena>, - name_resolutions: TypedArena>>, +pub struct ResolverArenas<'ra> { + modules: TypedArena>, + local_modules: RefCell>>, + imports: TypedArena>, + name_resolutions: TypedArena>>, ast_paths: TypedArena, dropless: DroplessArena, } -impl<'a> ResolverArenas<'a> { +impl<'ra> ResolverArenas<'ra> { fn new_module( - &'a self, - parent: Option>, + &'ra self, + parent: Option>, kind: ModuleKind, expn_id: ExpnId, span: Span, no_implicit_prelude: bool, - module_map: &mut FxHashMap>, - module_self_bindings: &mut FxHashMap, NameBinding<'a>>, - ) -> Module<'a> { + module_map: &mut FxHashMap>, + module_self_bindings: &mut FxHashMap, NameBinding<'ra>>, + ) -> Module<'ra> { let module = Module(Interned::new_unchecked(self.modules.alloc(ModuleData::new( parent, kind, @@ -1227,37 +1228,37 @@ impl<'a> ResolverArenas<'a> { } module } - fn local_modules(&'a self) -> std::cell::Ref<'a, Vec>> { + fn local_modules(&'ra self) -> std::cell::Ref<'ra, Vec>> { self.local_modules.borrow() } - fn alloc_name_binding(&'a self, name_binding: NameBindingData<'a>) -> NameBinding<'a> { + fn alloc_name_binding(&'ra self, name_binding: NameBindingData<'ra>) -> NameBinding<'ra> { Interned::new_unchecked(self.dropless.alloc(name_binding)) } - fn alloc_import(&'a self, import: ImportData<'a>) -> Import<'a> { + fn alloc_import(&'ra self, import: ImportData<'ra>) -> Import<'ra> { Interned::new_unchecked(self.imports.alloc(import)) } - fn alloc_name_resolution(&'a self) -> &'a RefCell> { + fn alloc_name_resolution(&'ra self) -> &'ra RefCell> { self.name_resolutions.alloc(Default::default()) } - fn alloc_macro_rules_scope(&'a self, scope: MacroRulesScope<'a>) -> MacroRulesScopeRef<'a> { + fn alloc_macro_rules_scope(&'ra self, scope: MacroRulesScope<'ra>) -> MacroRulesScopeRef<'ra> { Interned::new_unchecked(self.dropless.alloc(Cell::new(scope))) } fn alloc_macro_rules_binding( - &'a self, - binding: MacroRulesBinding<'a>, - ) -> &'a MacroRulesBinding<'a> { + &'ra self, + binding: MacroRulesBinding<'ra>, + ) -> &'ra MacroRulesBinding<'ra> { self.dropless.alloc(binding) } - fn alloc_ast_paths(&'a self, paths: &[ast::Path]) -> &'a [ast::Path] { + fn alloc_ast_paths(&'ra self, paths: &[ast::Path]) -> &'ra [ast::Path] { self.ast_paths.alloc_from_iter(paths.iter().cloned()) } - fn alloc_pattern_spans(&'a self, spans: impl Iterator) -> &'a [Span] { + fn alloc_pattern_spans(&'ra self, spans: impl Iterator) -> &'ra [Span] { self.dropless.alloc_from_iter(spans) } } -impl<'a, 'tcx> AsMut> for Resolver<'a, 'tcx> { - fn as_mut(&mut self) -> &mut Resolver<'a, 'tcx> { +impl<'ra, 'tcx> AsMut> for Resolver<'ra, 'tcx> { + fn as_mut(&mut self) -> &mut Resolver<'ra, 'tcx> { self } } @@ -1341,14 +1342,14 @@ impl<'tcx> Resolver<'_, 'tcx> { } } -impl<'a, 'tcx> Resolver<'a, 'tcx> { +impl<'ra, 'tcx> Resolver<'ra, 'tcx> { pub fn new( tcx: TyCtxt<'tcx>, attrs: &[ast::Attribute], crate_span: Span, current_crate_outer_attr_insert_span: Span, - arenas: &'a ResolverArenas<'a>, - ) -> Resolver<'a, 'tcx> { + arenas: &'ra ResolverArenas<'ra>, + ) -> Resolver<'ra, 'tcx> { let root_def_id = CRATE_DEF_ID.to_def_id(); let mut module_map = FxHashMap::default(); let mut module_self_bindings = FxHashMap::default(); @@ -1541,12 +1542,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn new_module( &mut self, - parent: Option>, + parent: Option>, kind: ModuleKind, expn_id: ExpnId, span: Span, no_implicit_prelude: bool, - ) -> Module<'a> { + ) -> Module<'ra> { let module_map = &mut self.module_map; let module_self_bindings = &mut self.module_self_bindings; self.arenas.new_module( @@ -1578,7 +1579,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &mut self.lint_buffer } - pub fn arenas() -> ResolverArenas<'a> { + pub fn arenas() -> ResolverArenas<'ra> { Default::default() } @@ -1719,8 +1720,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn traits_in_scope( &mut self, - current_trait: Option>, - parent_scope: &ParentScope<'a>, + current_trait: Option>, + parent_scope: &ParentScope<'ra>, ctxt: SyntaxContext, assoc_item: Option<(Symbol, Namespace)>, ) -> Vec { @@ -1754,7 +1755,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn traits_in_module( &mut self, - module: Module<'a>, + module: Module<'ra>, assoc_item: Option<(Symbol, Namespace)>, found_traits: &mut Vec, ) { @@ -1776,7 +1777,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // associated items. fn trait_may_have_item( &mut self, - trait_module: Option>, + trait_module: Option>, assoc_item: Option<(Symbol, Namespace)>, ) -> bool { match (trait_module, assoc_item) { @@ -1822,7 +1823,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { BindingKey { ident, ns, disambiguator } } - fn resolutions(&mut self, module: Module<'a>) -> &'a Resolutions<'a> { + fn resolutions(&mut self, module: Module<'ra>) -> &'ra Resolutions<'ra> { if module.populate_on_access.get() { module.populate_on_access.set(false); self.build_reduced_graph_external(module); @@ -1832,9 +1833,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn resolution( &mut self, - module: Module<'a>, + module: Module<'ra>, key: BindingKey, - ) -> &'a RefCell> { + ) -> &'ra RefCell> { *self .resolutions(module) .borrow_mut() @@ -1860,14 +1861,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { false } - fn record_use(&mut self, ident: Ident, used_binding: NameBinding<'a>, used: Used) { + fn record_use(&mut self, ident: Ident, used_binding: NameBinding<'ra>, used: Used) { self.record_use_inner(ident, used_binding, used, used_binding.warn_ambiguity); } fn record_use_inner( &mut self, ident: Ident, - used_binding: NameBinding<'a>, + used_binding: NameBinding<'ra>, used: Used, warn_ambiguity: bool, ) { @@ -1929,7 +1930,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - fn resolve_crate_root(&mut self, ident: Ident) -> Module<'a> { + fn resolve_crate_root(&mut self, ident: Ident) -> Module<'ra> { debug!("resolve_crate_root({:?})", ident); let mut ctxt = ident.span.ctxt(); let mark = if ident.name == kw::DollarCrate { @@ -2002,7 +2003,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { module } - fn resolve_self(&mut self, ctxt: &mut SyntaxContext, module: Module<'a>) -> Module<'a> { + fn resolve_self(&mut self, ctxt: &mut SyntaxContext, module: Module<'ra>) -> Module<'ra> { let mut module = self.expect_module(module.nearest_parent_mod()); while module.span.ctxt().normalize_to_macros_2_0() != *ctxt { let parent = module.parent.unwrap_or_else(|| self.expn_def_scope(ctxt.remove_mark())); @@ -2026,12 +2027,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn is_accessible_from( &self, vis: ty::Visibility>, - module: Module<'a>, + module: Module<'ra>, ) -> bool { vis.is_accessible_from(module.nearest_parent_mod(), self.tcx) } - fn set_binding_parent_module(&mut self, binding: NameBinding<'a>, module: Module<'a>) { + fn set_binding_parent_module(&mut self, binding: NameBinding<'ra>, module: Module<'ra>) { if let Some(old_module) = self.binding_parent_modules.insert(binding, module) { if module != old_module { span_bug!(binding.span, "parent module is reset for binding"); @@ -2041,8 +2042,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn disambiguate_macro_rules_vs_modularized( &self, - macro_rules: NameBinding<'a>, - modularized: NameBinding<'a>, + macro_rules: NameBinding<'ra>, + modularized: NameBinding<'ra>, ) -> bool { // Some non-controversial subset of ambiguities "modularized macro name" vs "macro_rules" // is disambiguated to mitigate regressions from macro modularization. @@ -2059,7 +2060,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - fn extern_prelude_get(&mut self, ident: Ident, finalize: bool) -> Option> { + fn extern_prelude_get(&mut self, ident: Ident, finalize: bool) -> Option> { if ident.is_path_segment_keyword() { // Make sure `self`, `super` etc produce an error when passed to here. return None; @@ -2108,7 +2109,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &mut self, path_str: &str, ns: Namespace, - parent_scope: ParentScope<'a>, + parent_scope: ParentScope<'ra>, ) -> Option { let mut segments = Vec::from_iter(path_str.split("::").map(Ident::from_str).map(Segment::from_ident)); diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 7203fbe4a0c18..8a81f068a1cc0 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -52,10 +52,10 @@ type Res = def::Res; /// Binding produced by a `macro_rules` item. /// Not modularized, can shadow previous `macro_rules` bindings, etc. #[derive(Debug)] -pub(crate) struct MacroRulesBinding<'a> { - pub(crate) binding: NameBinding<'a>, +pub(crate) struct MacroRulesBinding<'ra> { + pub(crate) binding: NameBinding<'ra>, /// `macro_rules` scope into which the `macro_rules` item was planted. - pub(crate) parent_macro_rules_scope: MacroRulesScopeRef<'a>, + pub(crate) parent_macro_rules_scope: MacroRulesScopeRef<'ra>, pub(crate) ident: Ident, } @@ -65,11 +65,11 @@ pub(crate) struct MacroRulesBinding<'a> { /// Some macro invocations need to introduce `macro_rules` scopes too because they /// can potentially expand into macro definitions. #[derive(Copy, Clone, Debug)] -pub(crate) enum MacroRulesScope<'a> { +pub(crate) enum MacroRulesScope<'ra> { /// Empty "root" scope at the crate start containing no names. Empty, /// The scope introduced by a `macro_rules!` macro definition. - Binding(&'a MacroRulesBinding<'a>), + Binding(&'ra MacroRulesBinding<'ra>), /// The scope introduced by a macro invocation that can potentially /// create a `macro_rules!` macro definition. Invocation(LocalExpnId), @@ -81,7 +81,7 @@ pub(crate) enum MacroRulesScope<'a> { /// This helps to avoid uncontrollable growth of `macro_rules!` scope chains, /// which usually grow linearly with the number of macro invocations /// in a module (including derives) and hurt performance. -pub(crate) type MacroRulesScopeRef<'a> = Interned<'a, Cell>>; +pub(crate) type MacroRulesScopeRef<'ra> = Interned<'ra, Cell>>; /// Macro namespace is separated into two sub-namespaces, one for bang macros and /// one for attribute-like macros (attributes, derives). @@ -177,7 +177,7 @@ fn soft_custom_inner_attributes_gate(path: &ast::Path, invoc: &Invocation) -> bo false } -impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> { +impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { fn next_node_id(&mut self) -> NodeId { self.next_node_id() } @@ -528,7 +528,7 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> { } } -impl<'a, 'tcx> Resolver<'a, 'tcx> { +impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// Resolve macro path with error reporting and recovery. /// Uses dummy syntax extensions for unresolved macros or macros with unexpected resolutions /// for better error recovery. @@ -538,7 +538,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { kind: MacroKind, supports_macro_expansion: SupportsMacroExpansion, inner_attr: bool, - parent_scope: &ParentScope<'a>, + parent_scope: &ParentScope<'ra>, node_id: NodeId, force: bool, soft_custom_inner_attributes_gate: bool, @@ -704,10 +704,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &mut self, path: &ast::Path, kind: Option, - parent_scope: &ParentScope<'a>, + parent_scope: &ParentScope<'ra>, trace: bool, force: bool, - ignore_import: Option>, + ignore_import: Option>, ) -> Result<(Option>, Res), Determinacy> { self.resolve_macro_or_delegation_path( path, @@ -725,12 +725,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &mut self, ast_path: &ast::Path, kind: Option, - parent_scope: &ParentScope<'a>, + parent_scope: &ParentScope<'ra>, trace: bool, force: bool, deleg_impl: Option, invoc_in_mod_inert_attr: Option<(LocalDefId, NodeId)>, - ignore_import: Option>, + ignore_import: Option>, ) -> Result<(Option>, Res), Determinacy> { let path_span = ast_path.span; let mut path = Segment::from_path(ast_path); @@ -1045,7 +1045,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn prohibit_imported_non_macro_attrs( &self, - binding: Option>, + binding: Option>, res: Option, span: Span, ) { @@ -1065,9 +1065,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn report_out_of_scope_macro_calls( &mut self, path: &ast::Path, - parent_scope: &ParentScope<'a>, + parent_scope: &ParentScope<'ra>, invoc_in_mod_inert_attr: Option<(LocalDefId, NodeId)>, - binding: Option>, + binding: Option>, ) { if let Some((mod_def_id, node_id)) = invoc_in_mod_inert_attr && let Some(binding) = binding From 8dc227866fe12879e6a6b518c7a2ad6dbe395ac9 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 11 Sep 2024 18:52:36 -0400 Subject: [PATCH 178/189] Remove unused functions from ast CoroutineKind --- compiler/rustc_ast/src/ast.rs | 8 -------- src/tools/clippy/clippy_utils/src/ast_utils.rs | 12 +++++++++++- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 1fb85abcbfaa2..b7a6746267f53 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2610,14 +2610,6 @@ impl CoroutineKind { } } - pub fn is_async(self) -> bool { - matches!(self, CoroutineKind::Async { .. }) - } - - pub fn is_gen(self) -> bool { - matches!(self, CoroutineKind::Gen { .. }) - } - pub fn closure_id(self) -> NodeId { match self { CoroutineKind::Async { closure_id, .. } diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index 181bbdde8e5f1..de8bbb619f8e4 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -221,7 +221,7 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool { ) => { eq_closure_binder(lb, rb) && lc == rc - && la.map_or(false, CoroutineKind::is_async) == ra.map_or(false, CoroutineKind::is_async) + && eq_coroutine_kind(*la, *ra) && lm == rm && eq_fn_decl(lf, rf) && eq_expr(le, re) @@ -241,6 +241,16 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool { } } +fn eq_coroutine_kind(a: Option, b: Option) -> bool { + match (a, b) { + (Some(CoroutineKind::Async { .. }), Some(CoroutineKind::Async { .. })) + | (Some(CoroutineKind::Gen { .. }), Some(CoroutineKind::Gen { .. })) + | (Some(CoroutineKind::AsyncGen { .. }), Some(CoroutineKind::AsyncGen { .. })) + | (None, None) => true, + _ => false, + } +} + pub fn eq_field(l: &ExprField, r: &ExprField) -> bool { l.is_placeholder == r.is_placeholder && eq_id(l.ident, r.ident) From ed9b2bac36d93cdc8532f6bb86b9b8591f0a79e1 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 12 Sep 2024 12:42:23 +1000 Subject: [PATCH 179/189] Re-run coverage tests if `coverage-dump` was modified --- src/tools/compiletest/src/lib.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 5fe73a0e29729..250b5084d1362 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -647,6 +647,12 @@ fn common_inputs_stamp(config: &Config) -> Stamp { stamp.add_path(&rust_src_dir.join("src/etc/htmldocck.py")); } + // Re-run coverage tests if the `coverage-dump` tool was modified, + // because its output format might have changed. + if let Some(coverage_dump_path) = &config.coverage_dump_path { + stamp.add_path(coverage_dump_path) + } + stamp.add_dir(&rust_src_dir.join("src/tools/run-make-support")); // Compiletest itself. From d6ef1b99e83014122dbd7f4fde8a3487b05ea9b9 Mon Sep 17 00:00:00 2001 From: Chris Jefferson Date: Mon, 13 May 2024 13:35:54 +0800 Subject: [PATCH 180/189] Expand PathBuf documentation Mention that some methods do not sanitize their input fully --- library/std/src/path.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 506ad445b6bed..e7fd2e4ddee22 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -1153,6 +1153,21 @@ impl FusedIterator for Ancestors<'_> {} /// ``` /// /// Which method works best depends on what kind of situation you're in. +/// +/// Note that `PathBuf`` does not always sanitize arguments, for example +/// [`push`] allows paths built from strings which include separators: +/// +/// use std::path::PathBuf; +/// +/// let mut path = PathBuf::new(); +/// +/// path.push(r"C:\"); +/// path.push("windows"); +/// path.push(r"..\otherdir"); +/// path.push("system32"); +/// +/// The behaviour of `PathBuf` may be changed to a panic on such inputs +/// in the future. The [`extend`] method should be used to add multi-part paths. #[cfg_attr(not(test), rustc_diagnostic_item = "PathBuf")] #[stable(feature = "rust1", since = "1.0.0")] pub struct PathBuf { @@ -1391,6 +1406,9 @@ impl PathBuf { /// `file_name`. The new path will be a sibling of the original path. /// (That is, it will have the same parent.) /// + /// The argument is not sanitized, so can include separators. This + /// behaviour may be changed to a panic in the future. + /// /// [`self.file_name`]: Path::file_name /// [`pop`]: PathBuf::pop /// @@ -1411,6 +1429,12 @@ impl PathBuf { /// /// buf.set_file_name("baz"); /// assert!(buf == PathBuf::from("/baz")); + /// + /// buf.set_file_name("../b/c.txt"); + /// assert!(buf == PathBuf::from("/../b/c.txt")); + /// + /// buf.set_file_name("baz"); + /// assert!(buf == PathBuf::from("/../b/baz")); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn set_file_name>(&mut self, file_name: S) { From 45c471b1f3421fff4f29fae80d507831c836f40f Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Wed, 11 Sep 2024 22:46:06 -0700 Subject: [PATCH 181/189] Fixup docs for PathBuf --- library/std/src/path.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/path.rs b/library/std/src/path.rs index e7fd2e4ddee22..c94df9b5366be 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -1154,7 +1154,7 @@ impl FusedIterator for Ancestors<'_> {} /// /// Which method works best depends on what kind of situation you're in. /// -/// Note that `PathBuf`` does not always sanitize arguments, for example +/// Note that `PathBuf` does not always sanitize arguments, for example /// [`push`] allows paths built from strings which include separators: /// /// use std::path::PathBuf; @@ -1167,7 +1167,7 @@ impl FusedIterator for Ancestors<'_> {} /// path.push("system32"); /// /// The behaviour of `PathBuf` may be changed to a panic on such inputs -/// in the future. The [`extend`] method should be used to add multi-part paths. +/// in the future. [`Extend::extend`] should be used to add multi-part paths. #[cfg_attr(not(test), rustc_diagnostic_item = "PathBuf")] #[stable(feature = "rust1", since = "1.0.0")] pub struct PathBuf { From a7a35956687b726f86aa158cb65448fcfd1d6e93 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 11 Sep 2024 17:16:14 +1000 Subject: [PATCH 182/189] coverage: Separate creation of edge counters from building their sum --- .../src/coverage/counters.rs | 54 +++++++++---------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs index 1c240366afa2e..fea615138000f 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters.rs @@ -315,20 +315,20 @@ impl<'a> MakeBcbCounters<'a> { // For each out-edge other than the one that was chosen to get an expression, // ensure that it has a counter (existing counter/expression or a new counter), // and accumulate the corresponding counters into a single sum expression. - let sum_of_all_other_out_edges: BcbCounter = { - let _span = debug_span!("sum_of_all_other_out_edges", ?expression_to_bcb).entered(); - successors - .iter() - .copied() - // Skip the chosen edge, since we'll calculate its count from this sum. - .filter(|&to_bcb| to_bcb != expression_to_bcb) - .fold(None, |accum, to_bcb| { - let _span = debug_span!("to_bcb", ?accum, ?to_bcb).entered(); - let edge_counter = self.get_or_make_edge_counter(from_bcb, to_bcb); - Some(self.coverage_counters.make_sum_expression(accum, edge_counter)) - }) - .expect("there must be at least one other out-edge") - }; + let other_out_edge_counters = successors + .iter() + .copied() + // Skip the chosen edge, since we'll calculate its count from this sum. + .filter(|&to_bcb| to_bcb != expression_to_bcb) + .map(|to_bcb| self.get_or_make_edge_counter(from_bcb, to_bcb)) + .collect::>(); + let sum_of_all_other_out_edges: BcbCounter = other_out_edge_counters + .iter() + .copied() + .fold(None, |accum, edge_counter| { + Some(self.coverage_counters.make_sum_expression(accum, edge_counter)) + }) + .expect("there must be at least one other out-edge"); // Now create an expression for the chosen edge, by taking the counter // for its source node and subtracting the sum of its sibling out-edges. @@ -375,20 +375,18 @@ impl<'a> MakeBcbCounters<'a> { // A BCB with multiple incoming edges can compute its count by ensuring that counters // exist for each of those edges, and then adding them up to get a total count. - let sum_of_in_edges: BcbCounter = { - let _span = debug_span!("sum_of_in_edges", ?bcb).entered(); - // We avoid calling `self.bcb_predecessors` here so that we can - // call methods on `&mut self` inside the fold. - self.basic_coverage_blocks.predecessors[bcb] - .iter() - .copied() - .fold(None, |accum, from_bcb| { - let _span = debug_span!("from_bcb", ?accum, ?from_bcb).entered(); - let edge_counter = self.get_or_make_edge_counter(from_bcb, bcb); - Some(self.coverage_counters.make_sum_expression(accum, edge_counter)) - }) - .expect("there must be at least one in-edge") - }; + let in_edge_counters = self.basic_coverage_blocks.predecessors[bcb] + .iter() + .copied() + .map(|from_bcb| self.get_or_make_edge_counter(from_bcb, bcb)) + .collect::>(); + let sum_of_in_edges: BcbCounter = in_edge_counters + .iter() + .copied() + .fold(None, |accum, edge_counter| { + Some(self.coverage_counters.make_sum_expression(accum, edge_counter)) + }) + .expect("there must be at least one in-edge"); debug!("{bcb:?} gets a new counter (sum of predecessor counters): {sum_of_in_edges:?}"); self.coverage_counters.set_bcb_counter(bcb, sum_of_in_edges) From 2344133ba6abfe54e48cafecca2dff53a9484b07 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 11 Sep 2024 17:24:31 +1000 Subject: [PATCH 183/189] coverage: Simplify creation of sum counters --- .../src/coverage/counters.rs | 30 ++++++++----------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs index fea615138000f..7e3ecad1bce99 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters.rs @@ -155,12 +155,14 @@ impl CoverageCounters { BcbCounter::Expression { id } } - /// Variant of `make_expression` that makes `lhs` optional and assumes [`Op::Add`]. + /// Creates a counter that is the sum of the given counters. /// - /// This is useful when using [`Iterator::fold`] to build an arbitrary-length sum. - fn make_sum_expression(&mut self, lhs: Option, rhs: BcbCounter) -> BcbCounter { - let Some(lhs) = lhs else { return rhs }; - self.make_expression(lhs, Op::Add, rhs) + /// Returns `None` if the given list of counters was empty. + fn make_sum(&mut self, counters: &[BcbCounter]) -> Option { + counters + .iter() + .copied() + .reduce(|accum, counter| self.make_expression(accum, Op::Add, counter)) } pub(super) fn num_counters(&self) -> usize { @@ -322,12 +324,9 @@ impl<'a> MakeBcbCounters<'a> { .filter(|&to_bcb| to_bcb != expression_to_bcb) .map(|to_bcb| self.get_or_make_edge_counter(from_bcb, to_bcb)) .collect::>(); - let sum_of_all_other_out_edges: BcbCounter = other_out_edge_counters - .iter() - .copied() - .fold(None, |accum, edge_counter| { - Some(self.coverage_counters.make_sum_expression(accum, edge_counter)) - }) + let sum_of_all_other_out_edges: BcbCounter = self + .coverage_counters + .make_sum(&other_out_edge_counters) .expect("there must be at least one other out-edge"); // Now create an expression for the chosen edge, by taking the counter @@ -380,12 +379,9 @@ impl<'a> MakeBcbCounters<'a> { .copied() .map(|from_bcb| self.get_or_make_edge_counter(from_bcb, bcb)) .collect::>(); - let sum_of_in_edges: BcbCounter = in_edge_counters - .iter() - .copied() - .fold(None, |accum, edge_counter| { - Some(self.coverage_counters.make_sum_expression(accum, edge_counter)) - }) + let sum_of_in_edges: BcbCounter = self + .coverage_counters + .make_sum(&in_edge_counters) .expect("there must be at least one in-edge"); debug!("{bcb:?} gets a new counter (sum of predecessor counters): {sum_of_in_edges:?}"); From 675c99f4d54693af8c7af162968838d6e75ffbee Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 12 Sep 2024 14:32:44 +0200 Subject: [PATCH 184/189] more eagerly discard constraints on overflow --- .../src/solve/eval_ctxt/canonical.rs | 15 +++++++++ .../src/solve/eval_ctxt/mod.rs | 33 ++++--------------- .../src/solve/fulfill.rs | 2 +- compiler/rustc_type_ir/src/solve/mod.rs | 10 ++---- .../issue-118950-root-region.stderr | 2 ++ 5 files changed, 27 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs index 1c00f5f8b4173..5acfec3dee33c 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs @@ -122,6 +122,21 @@ where (certainty, NestedNormalizationGoals::empty()) }; + if let Certainty::Maybe(cause @ MaybeCause::Overflow { .. }) = certainty { + // If we have overflow, it's probable that we're substituting a type + // into itself infinitely and any partial substitutions in the query + // response are probably not useful anyways, so just return an empty + // query response. + // + // This may prevent us from potentially useful inference, e.g. + // 2 candidates, one ambiguous and one overflow, which both + // have the same inference constraints. + // + // Changing this to retain some constraints in the future + // won't be a breaking change, so this is good enough for now. + return Ok(self.make_ambiguous_response_no_constraints(cause)); + } + let external_constraints = self.compute_external_query_constraints(certainty, normalization_nested_goals); let (var_values, mut external_constraints) = (self.var_values, external_constraints) diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 3f2f34d3255f7..15b123ebdf934 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -17,7 +17,7 @@ use crate::delegate::SolverDelegate; use crate::solve::inspect::{self, ProofTreeBuilder}; use crate::solve::search_graph::SearchGraph; use crate::solve::{ - CanonicalInput, CanonicalResponse, Certainty, Goal, GoalEvaluationKind, GoalSource, MaybeCause, + CanonicalInput, CanonicalResponse, Certainty, Goal, GoalEvaluationKind, GoalSource, NestedNormalizationGoals, NoSolution, PredefinedOpaquesData, QueryResult, SolverMode, FIXPOINT_STEP_LIMIT, }; @@ -370,7 +370,7 @@ where canonical_goal, &mut goal_evaluation, ); - let canonical_response = match canonical_response { + let response = match canonical_response { Err(e) => { self.inspect.goal_evaluation(goal_evaluation); return Err(e); @@ -378,12 +378,11 @@ where Ok(response) => response, }; - let (normalization_nested_goals, certainty, has_changed) = self - .instantiate_response_discarding_overflow( - goal.param_env, - orig_values, - canonical_response, - ); + let has_changed = !response.value.var_values.is_identity_modulo_regions() + || !response.value.external_constraints.opaque_types.is_empty(); + + let (normalization_nested_goals, certainty) = + self.instantiate_and_apply_query_response(goal.param_env, orig_values, response); self.inspect.goal_evaluation(goal_evaluation); // FIXME: We previously had an assert here that checked that recomputing // a goal after applying its constraints did not change its response. @@ -398,24 +397,6 @@ where Ok((normalization_nested_goals, has_changed, certainty)) } - fn instantiate_response_discarding_overflow( - &mut self, - param_env: I::ParamEnv, - original_values: Vec, - response: CanonicalResponse, - ) -> (NestedNormalizationGoals, Certainty, bool) { - if let Certainty::Maybe(MaybeCause::Overflow { .. }) = response.value.certainty { - return (NestedNormalizationGoals::empty(), response.value.certainty, false); - } - - let has_changed = !response.value.var_values.is_identity_modulo_regions() - || !response.value.external_constraints.opaque_types.is_empty(); - - let (normalization_nested_goals, certainty) = - self.instantiate_and_apply_query_response(param_env, original_values, response); - (normalization_nested_goals, certainty, has_changed) - } - fn compute_goal(&mut self, goal: Goal) -> QueryResult { let Goal { param_env, predicate } = goal; let kind = predicate.kind(); diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index f5f36f40f7e6e..cfc73e2e47e87 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -302,7 +302,7 @@ fn fulfillment_error_for_stalled<'tcx>( Ok((_, Certainty::Maybe(MaybeCause::Overflow { suggest_increasing_limit }))) => ( FulfillmentErrorCode::Ambiguity { overflow: Some(suggest_increasing_limit) }, // Don't look into overflows because we treat overflows weirdly anyways. - // In `instantiate_response_discarding_overflow` we set `has_changed = false`, + // We discard the inference constraints from overflowing goals, so // recomputing the goal again during `find_best_leaf_obligation` may apply // inference guidance that makes other goals go from ambig -> pass, for example. // diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs index 96998d2ec9f2c..a0f7658212f4b 100644 --- a/compiler/rustc_type_ir/src/solve/mod.rs +++ b/compiler/rustc_type_ir/src/solve/mod.rs @@ -117,7 +117,8 @@ impl Goal { /// Why a specific goal has to be proven. /// /// This is necessary as we treat nested goals different depending on -/// their source. +/// their source. This is currently mostly used by proof tree visitors +/// but will be used by cycle handling in the future. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] pub enum GoalSource { @@ -126,13 +127,6 @@ pub enum GoalSource { /// /// FIXME(-Znext-solver=coinductive): Explain how and why this /// changes whether cycles are coinductive. - /// - /// This also impacts whether we erase constraints on overflow. - /// Erasing constraints is generally very useful for perf and also - /// results in better error messages by avoiding spurious errors. - /// We do not erase overflow constraints in `normalizes-to` goals unless - /// they are from an impl where-clause. This is necessary due to - /// backwards compatibility, cc trait-system-refactor-initiatitive#70. ImplWhereBound, /// Instantiating a higher-ranked goal and re-proving it. InstantiateHigherRanked, diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.stderr b/tests/ui/traits/next-solver/issue-118950-root-region.stderr index d14b9d217da23..7c3e22fb4014a 100644 --- a/tests/ui/traits/next-solver/issue-118950-root-region.stderr +++ b/tests/ui/traits/next-solver/issue-118950-root-region.stderr @@ -37,6 +37,8 @@ LL | impl Overlap for T {} LL | LL | impl Overlap fn(Assoc<'a, T>)> for T where Missing: Overlap {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `fn(_)` + | + = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details error: aborting due to 3 previous errors; 1 warning emitted From d3ebd232a5f6765373b8b7ef23ed5b87477fbd1e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 12 Sep 2024 09:55:25 -0400 Subject: [PATCH 185/189] Add test for nalgebra hang in coherence --- tests/ui/traits/coherence-alias-hang.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 tests/ui/traits/coherence-alias-hang.rs diff --git a/tests/ui/traits/coherence-alias-hang.rs b/tests/ui/traits/coherence-alias-hang.rs new file mode 100644 index 0000000000000..37b8073958994 --- /dev/null +++ b/tests/ui/traits/coherence-alias-hang.rs @@ -0,0 +1,23 @@ +//@ check-pass + +// Regression test for nalgebra hang . + +#![feature(lazy_type_alias)] +#![allow(incomplete_features)] + +type Id = T; +trait NotImplemented {} + +struct W(*const T, *const U); +trait Trait { + type Assoc: ?Sized; +} +impl Trait for W { + type Assoc = W>; +} + +trait Overlap {} +impl Overlap for W {} +impl Overlap for T {} + +fn main() {} From 8b75004bcad5f25ef31894986945ff75b53d7d94 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Thu, 15 Aug 2024 14:36:10 -0700 Subject: [PATCH 186/189] Fix anon const def-creation when macros are involved Ever since #125915, some `ast::AnonConst`s turn into `hir::ConstArgKind::Path`s, which don't have associated `DefId`s. To deal with the fact that we don't have resolution information in `DefCollector`, we decided to implement a process where if the anon const *appeared* to be trivial (i.e., `N` or `{ N }`), we would avoid creating a def for it in `DefCollector`. If later, in AST lowering, we realized it turned out to be a unit struct literal, or we were lowering it to something that didn't use `hir::ConstArg`, we'd create its def there. However, let's say we have a macro `m!()` that expands to a reference to a free constant `FOO`. If we use `m!()` in the body of an anon const (e.g., `Foo<{ m!() }>`), then in def collection, it appears to be a nontrivial anon const and we create a def. But the macro expands to something that looks like a trivial const arg, but is not, so in AST lowering we "fix" the mistake we assumed def collection made and create a def for it. This causes a duplicate definition ICE. The ideal long-term fix for this is a bit unclear. One option is to delay def creation for all expression-like nodes until AST lowering (see #128844 for an incomplete attempt at this). This would avoid issues like this one that are caused by hacky workarounds. However, this approach has some downsides as well, and the best approach is yet to be determined. In the meantime, this PR fixes the bug by delaying def creation for anon consts whose bodies are macro invocations until after we expand the macro and know what is inside it. This is accomplished by adding information to create the anon const's def to the data in `Resolver.invocation_parents`. --- compiler/rustc_ast/src/ast.rs | 20 ++-- compiler/rustc_resolve/src/def_collector.rs | 110 ++++++++++++++------ compiler/rustc_resolve/src/lib.rs | 28 ++++- compiler/rustc_resolve/src/macros.rs | 16 +-- 4 files changed, 122 insertions(+), 52 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 9dfebfae5ed3d..f433f2eca1a80 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1188,14 +1188,7 @@ impl Expr { /// /// Does not ensure that the path resolves to a const param, the caller should check this. pub fn is_potential_trivial_const_arg(&self) -> bool { - let this = if let ExprKind::Block(block, None) = &self.kind - && let [stmt] = block.stmts.as_slice() - && let StmtKind::Expr(expr) = &stmt.kind - { - expr - } else { - self - }; + let this = self.maybe_unwrap_block(); if let ExprKind::Path(None, path) = &this.kind && path.is_potential_trivial_const_arg() @@ -1206,6 +1199,17 @@ impl Expr { } } + pub fn maybe_unwrap_block(&self) -> &Expr { + if let ExprKind::Block(block, None) = &self.kind + && let [stmt] = block.stmts.as_slice() + && let StmtKind::Expr(expr) = &stmt.kind + { + expr + } else { + self + } + } + pub fn to_bound(&self) -> Option { match &self.kind { ExprKind::Path(None, path) => Some(GenericBound::Trait( diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 0fedb998463a2..dc1aa0a42f8e1 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -12,15 +12,23 @@ use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::Span; use tracing::debug; -use crate::{ImplTraitContext, Resolver}; +use crate::{ImplTraitContext, InvocationParent, PendingAnonConstInfo, Resolver}; pub(crate) fn collect_definitions( resolver: &mut Resolver<'_, '_>, fragment: &AstFragment, expansion: LocalExpnId, ) { - let (parent_def, impl_trait_context, in_attr) = resolver.invocation_parents[&expansion]; - let mut visitor = DefCollector { resolver, parent_def, expansion, impl_trait_context, in_attr }; + let InvocationParent { parent_def, pending_anon_const_info, impl_trait_context, in_attr } = + resolver.invocation_parents[&expansion]; + let mut visitor = DefCollector { + resolver, + parent_def, + pending_anon_const_info, + expansion, + impl_trait_context, + in_attr, + }; fragment.visit_with(&mut visitor); } @@ -28,6 +36,13 @@ pub(crate) fn collect_definitions( struct DefCollector<'a, 'b, 'tcx> { resolver: &'a mut Resolver<'b, 'tcx>, parent_def: LocalDefId, + /// If we have an anon const that consists of a macro invocation, e.g. `Foo<{ m!() }>`, + /// we need to wait until we know what the macro expands to before we create the def for + /// the anon const. That's because we lower some anon consts into `hir::ConstArgKind::Path`, + /// which don't have defs. + /// + /// See `Self::visit_anon_const()`. + pending_anon_const_info: Option, impl_trait_context: ImplTraitContext, in_attr: bool, expansion: LocalExpnId, @@ -111,10 +126,16 @@ impl<'a, 'b, 'tcx> DefCollector<'a, 'b, 'tcx> { fn visit_macro_invoc(&mut self, id: NodeId) { let id = id.placeholder_to_expn_id(); - let old_parent = self - .resolver - .invocation_parents - .insert(id, (self.parent_def, self.impl_trait_context, self.in_attr)); + let pending_anon_const_info = self.pending_anon_const_info.take(); + let old_parent = self.resolver.invocation_parents.insert( + id, + InvocationParent { + parent_def: self.parent_def, + pending_anon_const_info, + impl_trait_context: self.impl_trait_context, + in_attr: self.in_attr, + }, + ); assert!(old_parent.is_none(), "parent `LocalDefId` is reset for an invocation"); } } @@ -326,46 +347,67 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { } fn visit_anon_const(&mut self, constant: &'a AnonConst) { - if self.resolver.tcx.features().const_arg_path - && constant.value.is_potential_trivial_const_arg() - { + if self.resolver.tcx.features().const_arg_path { // HACK(min_generic_const_args): don't create defs for anon consts if we think they will // later be turned into ConstArgKind::Path's. because this is before resolve is done, we // may accidentally identify a construction of a unit struct as a param and not create a // def. we'll then create a def later in ast lowering in this case. the parent of nested // items will be messed up, but that's ok because there can't be any if we're just looking // for bare idents. - visit::walk_anon_const(self, constant) - } else { - let def = - self.create_def(constant.id, kw::Empty, DefKind::AnonConst, constant.value.span); - self.with_parent(def, |this| visit::walk_anon_const(this, constant)); + + if matches!(constant.value.maybe_unwrap_block().kind, ExprKind::MacCall(..)) { + // See self.pending_anon_const_info for explanation + self.pending_anon_const_info = + Some(PendingAnonConstInfo { id: constant.id, span: constant.value.span }); + return visit::walk_anon_const(self, constant); + } else if constant.value.is_potential_trivial_const_arg() { + return visit::walk_anon_const(self, constant); + } } + + let def = self.create_def(constant.id, kw::Empty, DefKind::AnonConst, constant.value.span); + self.with_parent(def, |this| visit::walk_anon_const(this, constant)); } fn visit_expr(&mut self, expr: &'a Expr) { - let parent_def = match expr.kind { - ExprKind::MacCall(..) => return self.visit_macro_invoc(expr.id), - ExprKind::Closure(..) | ExprKind::Gen(..) => { - self.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span) - } - ExprKind::ConstBlock(ref constant) => { - for attr in &expr.attrs { - visit::walk_attribute(self, attr); - } - let def = self.create_def( - constant.id, - kw::Empty, - DefKind::InlineConst, - constant.value.span, - ); - self.with_parent(def, |this| visit::walk_anon_const(this, constant)); - return; + if matches!(expr.kind, ExprKind::MacCall(..)) { + return self.visit_macro_invoc(expr.id); + } + + let grandparent_def = if let Some(pending_anon) = self.pending_anon_const_info.take() { + // See self.pending_anon_const_info for explanation + if !expr.is_potential_trivial_const_arg() { + self.create_def(pending_anon.id, kw::Empty, DefKind::AnonConst, pending_anon.span) + } else { + self.parent_def } - _ => self.parent_def, + } else { + self.parent_def }; - self.with_parent(parent_def, |this| visit::walk_expr(this, expr)); + self.with_parent(grandparent_def, |this| { + let parent_def = match expr.kind { + ExprKind::Closure(..) | ExprKind::Gen(..) => { + this.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span) + } + ExprKind::ConstBlock(ref constant) => { + for attr in &expr.attrs { + visit::walk_attribute(this, attr); + } + let def = this.create_def( + constant.id, + kw::Empty, + DefKind::InlineConst, + constant.value.span, + ); + this.with_parent(def, |this| visit::walk_anon_const(this, constant)); + return; + } + _ => this.parent_def, + }; + + this.with_parent(parent_def, |this| visit::walk_expr(this, expr)) + }) } fn visit_ty(&mut self, ty: &'a Ty) { diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 8ffd00d1b2e60..6ec72649ce32e 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -171,6 +171,29 @@ impl<'a> ParentScope<'a> { } } +#[derive(Copy, Debug, Clone)] +struct InvocationParent { + parent_def: LocalDefId, + pending_anon_const_info: Option, + impl_trait_context: ImplTraitContext, + in_attr: bool, +} + +impl InvocationParent { + const ROOT: Self = Self { + parent_def: CRATE_DEF_ID, + pending_anon_const_info: None, + impl_trait_context: ImplTraitContext::Existential, + in_attr: false, + }; +} + +#[derive(Copy, Debug, Clone)] +struct PendingAnonConstInfo { + id: NodeId, + span: Span, +} + #[derive(Copy, Debug, Clone)] enum ImplTraitContext { Existential, @@ -1144,7 +1167,7 @@ pub struct Resolver<'a, 'tcx> { /// When collecting definitions from an AST fragment produced by a macro invocation `ExpnId` /// we know what parent node that fragment should be attached to thanks to this table, /// and how the `impl Trait` fragments were introduced. - invocation_parents: FxHashMap, + invocation_parents: FxHashMap, /// Some way to know that we are in a *trait* impl in `visit_assoc_item`. /// FIXME: Replace with a more general AST map (together with some other fields). @@ -1381,8 +1404,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { node_id_to_def_id.insert(CRATE_NODE_ID, crate_feed); let mut invocation_parents = FxHashMap::default(); - invocation_parents - .insert(LocalExpnId::ROOT, (CRATE_DEF_ID, ImplTraitContext::Existential, false)); + invocation_parents.insert(LocalExpnId::ROOT, InvocationParent::ROOT); let mut extern_prelude: FxHashMap> = tcx .sess diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 7203fbe4a0c18..d6afd01f48748 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -42,9 +42,9 @@ use crate::errors::{ use crate::imports::Import; use crate::Namespace::*; use crate::{ - BindingKey, BuiltinMacroState, DeriveData, Determinacy, Finalize, MacroData, ModuleKind, - ModuleOrUniformRoot, NameBinding, NameBindingKind, ParentScope, PathResult, ResolutionError, - Resolver, ScopeSet, Segment, ToNameBinding, Used, + BindingKey, BuiltinMacroState, DeriveData, Determinacy, Finalize, InvocationParent, MacroData, + ModuleKind, ModuleOrUniformRoot, NameBinding, NameBindingKind, ParentScope, PathResult, + ResolutionError, Resolver, ScopeSet, Segment, ToNameBinding, Used, }; type Res = def::Res; @@ -183,7 +183,7 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> { } fn invocation_parent(&self, id: LocalExpnId) -> LocalDefId { - self.invocation_parents[&id].0 + self.invocation_parents[&id].parent_def } fn resolve_dollar_crates(&mut self) { @@ -303,12 +303,12 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> { .invocation_parents .get(&invoc_id) .or_else(|| self.invocation_parents.get(&eager_expansion_root)) - .filter(|&&(mod_def_id, _, in_attr)| { + .filter(|&&InvocationParent { parent_def: mod_def_id, in_attr, .. }| { in_attr && invoc.fragment_kind == AstFragmentKind::Expr && self.tcx.def_kind(mod_def_id) == DefKind::Mod }) - .map(|&(mod_def_id, ..)| mod_def_id); + .map(|&InvocationParent { parent_def: mod_def_id, .. }| mod_def_id); let (ext, res) = self.smart_resolve_macro_path( path, kind, @@ -951,7 +951,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let node_id = self .invocation_parents .get(&parent_scope.expansion) - .map_or(ast::CRATE_NODE_ID, |id| self.def_id_to_node_id[id.0]); + .map_or(ast::CRATE_NODE_ID, |parent| { + self.def_id_to_node_id[parent.parent_def] + }); self.lint_buffer.buffer_lint( LEGACY_DERIVE_HELPERS, node_id, From e0bd01167e86d07c03e8ddd2bb0a25f689a2a7f5 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Sun, 8 Sep 2024 01:49:25 -0400 Subject: [PATCH 187/189] Re-enable `ConstArgKind::Path` lowering by default ...and remove the `const_arg_path` feature gate as a result. It was only a stopgap measure to fix the regression that the new lowering introduced (which should now be fixed by this PR). --- compiler/rustc_ast_lowering/src/asm.rs | 4 +- compiler/rustc_ast_lowering/src/expr.rs | 2 +- compiler/rustc_ast_lowering/src/lib.rs | 7 ++-- compiler/rustc_feature/src/unstable.rs | 2 - compiler/rustc_middle/src/ty/consts.rs | 18 +++----- compiler/rustc_resolve/src/def_collector.rs | 30 +++++++------- compiler/rustc_span/src/symbol.rs | 1 - .../ui-fulldeps/stable-mir/check_instance.rs | 2 +- .../generic_const_type_mismatch.rs | 2 - .../generic_const_type_mismatch.stderr | 20 ++------- .../ui/const-generics/bad-subst-const-kind.rs | 1 - .../bad-subst-const-kind.stderr | 11 +---- .../generic_const_exprs/type_mismatch.rs | 1 - .../generic_const_exprs/type_mismatch.stderr | 12 ++---- .../unevaluated-const-ice-119731.rs | 4 +- .../unevaluated-const-ice-119731.stderr | 4 +- tests/ui/const-generics/transmute-fail.rs | 2 - tests/ui/const-generics/transmute-fail.stderr | 41 +++++++------------ tests/ui/const-generics/type_mismatch.rs | 2 - tests/ui/const-generics/type_mismatch.stderr | 20 ++------- tests/ui/consts/issue-36163.stderr | 6 +-- .../feature-gate-const-arg-path.rs | 5 --- tests/ui/lifetimes/issue-95023.rs | 1 - tests/ui/lifetimes/issue-95023.stderr | 10 +---- ...t-proj-ty-as-type-of-const-issue-125757.rs | 1 - ...oj-ty-as-type-of-const-issue-125757.stderr | 14 +------ .../bad-const-wf-doesnt-specialize.rs | 1 - .../bad-const-wf-doesnt-specialize.stderr | 14 ++----- tests/ui/transmutability/issue-101739-1.rs | 1 - .../ui/transmutability/issue-101739-1.stderr | 11 +---- tests/ui/transmutability/issue-101739-2.rs | 2 +- .../ui/transmutability/issue-101739-2.stderr | 11 +---- .../const-in-impl-fn-return-type.rs | 1 - .../const-in-impl-fn-return-type.stderr | 10 +---- 34 files changed, 70 insertions(+), 204 deletions(-) delete mode 100644 tests/ui/feature-gates/feature-gate-const-arg-path.rs diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 4413c259efbf3..a9d1ee5c9c13a 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -220,9 +220,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let parent_def_id = self.current_def_id_parent; let node_id = self.next_node_id(); // HACK(min_generic_const_args): see lower_anon_const - if !self.tcx.features().const_arg_path - || !expr.is_potential_trivial_const_arg() - { + if !expr.is_potential_trivial_const_arg() { self.create_def( parent_def_id, node_id, diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index b887908f90461..e105026ebd19d 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -387,7 +387,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let node_id = self.next_node_id(); // HACK(min_generic_const_args): see lower_anon_const - if !self.tcx.features().const_arg_path || !arg.is_potential_trivial_const_arg() { + if !arg.is_potential_trivial_const_arg() { // Add a definition for the in-band const def. self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, f.span); } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 754fbae4d023f..efd3ae336afb8 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2335,7 +2335,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: Span, ) -> &'hir hir::ConstArg<'hir> { let ct_kind = match res { - Res::Def(DefKind::ConstParam, _) if self.tcx.features().const_arg_path => { + Res::Def(DefKind::ConstParam, _) => { let qpath = self.lower_qpath( ty_id, &None, @@ -2410,8 +2410,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.resolver.get_partial_res(expr.id).and_then(|partial_res| partial_res.full_res()); debug!("res={:?}", maybe_res); // FIXME(min_generic_const_args): for now we only lower params to ConstArgKind::Path - if self.tcx.features().const_arg_path - && let Some(res) = maybe_res + if let Some(res) = maybe_res && let Res::Def(DefKind::ConstParam, _) = res && let ExprKind::Path(qself, path) = &expr.kind { @@ -2442,7 +2441,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// See [`hir::ConstArg`] for when to use this function vs /// [`Self::lower_anon_const_to_const_arg`]. fn lower_anon_const_to_anon_const(&mut self, c: &AnonConst) -> &'hir hir::AnonConst { - if self.tcx.features().const_arg_path && c.value.is_potential_trivial_const_arg() { + if c.value.is_potential_trivial_const_arg() { // HACK(min_generic_const_args): see DefCollector::visit_anon_const // Over there, we guess if this is a bare param and only create a def if // we think it's not. However we may can guess wrong (see there for example) diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 3254dab9a0344..007b8753cfa76 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -193,8 +193,6 @@ declare_features! ( (unstable, anonymous_lifetime_in_impl_trait, "1.63.0", None), /// Allows identifying the `compiler_builtins` crate. (internal, compiler_builtins, "1.13.0", None), - /// Gating for a new desugaring of const arguments of usages of const parameters - (internal, const_arg_path, "1.81.0", None), /// Allows writing custom MIR (internal, custom_mir, "1.65.0", None), /// Outputs useful `assert!` messages diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index a5952c65692c1..6708ae6056284 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -295,20 +295,12 @@ impl<'tcx> Const<'tcx> { _ => expr, }; - if let hir::ExprKind::Path( - qpath @ hir::QPath::Resolved( - _, - &hir::Path { res: Res::Def(DefKind::ConstParam, _), .. }, - ), - ) = expr.kind + if let hir::ExprKind::Path(hir::QPath::Resolved( + _, + &hir::Path { res: Res::Def(DefKind::ConstParam, _), .. }, + )) = expr.kind { - if tcx.features().const_arg_path { - span_bug!( - expr.span, - "try_from_lit: received const param which shouldn't be possible" - ); - } - return Some(Const::from_param(tcx, qpath, expr.hir_id)); + span_bug!(expr.span, "try_from_lit: received const param which shouldn't be possible"); }; let lit_input = match expr.kind { diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index dc1aa0a42f8e1..e479c4b7511f3 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -347,22 +347,20 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { } fn visit_anon_const(&mut self, constant: &'a AnonConst) { - if self.resolver.tcx.features().const_arg_path { - // HACK(min_generic_const_args): don't create defs for anon consts if we think they will - // later be turned into ConstArgKind::Path's. because this is before resolve is done, we - // may accidentally identify a construction of a unit struct as a param and not create a - // def. we'll then create a def later in ast lowering in this case. the parent of nested - // items will be messed up, but that's ok because there can't be any if we're just looking - // for bare idents. - - if matches!(constant.value.maybe_unwrap_block().kind, ExprKind::MacCall(..)) { - // See self.pending_anon_const_info for explanation - self.pending_anon_const_info = - Some(PendingAnonConstInfo { id: constant.id, span: constant.value.span }); - return visit::walk_anon_const(self, constant); - } else if constant.value.is_potential_trivial_const_arg() { - return visit::walk_anon_const(self, constant); - } + // HACK(min_generic_const_args): don't create defs for anon consts if we think they will + // later be turned into ConstArgKind::Path's. because this is before resolve is done, we + // may accidentally identify a construction of a unit struct as a param and not create a + // def. we'll then create a def later in ast lowering in this case. the parent of nested + // items will be messed up, but that's ok because there can't be any if we're just looking + // for bare idents. + + if matches!(constant.value.maybe_unwrap_block().kind, ExprKind::MacCall(..)) { + // See self.pending_anon_const_info for explanation + self.pending_anon_const_info = + Some(PendingAnonConstInfo { id: constant.id, span: constant.value.span }); + return visit::walk_anon_const(self, constant); + } else if constant.value.is_potential_trivial_const_arg() { + return visit::walk_anon_const(self, constant); } let def = self.create_def(constant.id, kw::Empty, DefKind::AnonConst, constant.value.span); diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 28d18f2dfcc15..f1f362ac3e8a0 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -599,7 +599,6 @@ symbols! { conservative_impl_trait, console, const_allocate, - const_arg_path, const_async_blocks, const_closures, const_compare_raw_pointers, diff --git a/tests/ui-fulldeps/stable-mir/check_instance.rs b/tests/ui-fulldeps/stable-mir/check_instance.rs index 5449c09d35ab6..68eb3c54593ea 100644 --- a/tests/ui-fulldeps/stable-mir/check_instance.rs +++ b/tests/ui-fulldeps/stable-mir/check_instance.rs @@ -35,7 +35,7 @@ fn test_stable_mir() -> ControlFlow<()> { // Get all items and split generic vs monomorphic items. let (generic, mono): (Vec<_>, Vec<_>) = items.into_iter().partition(|item| item.requires_monomorphization()); - assert_eq!(mono.len(), 4, "Expected 3 mono functions"); + assert_eq!(mono.len(), 3, "Expected 3 mono functions"); assert_eq!(generic.len(), 2, "Expected 2 generic functions"); // For all monomorphic items, get the correspondent instances. diff --git a/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.rs b/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.rs index cdfeb9c434e6c..e07fa78463c7d 100644 --- a/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.rs +++ b/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.rs @@ -5,9 +5,7 @@ #![feature(with_negative_coherence)] trait Trait {} impl Trait for [(); N] {} -//~^ ERROR: mismatched types impl Trait for [(); N] {} //~^ ERROR: conflicting implementations of trait `Trait` -//~| ERROR: mismatched types fn main() {} diff --git a/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.stderr b/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.stderr index d65450845bc12..2087be8e7115d 100644 --- a/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.stderr +++ b/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.stderr @@ -1,25 +1,11 @@ error[E0119]: conflicting implementations of trait `Trait` for type `[(); _]` - --> $DIR/generic_const_type_mismatch.rs:9:1 + --> $DIR/generic_const_type_mismatch.rs:8:1 | LL | impl Trait for [(); N] {} | ----------------------------------- first implementation here -LL | LL | impl Trait for [(); N] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `[(); _]` -error[E0308]: mismatched types - --> $DIR/generic_const_type_mismatch.rs:7:34 - | -LL | impl Trait for [(); N] {} - | ^ expected `usize`, found `u8` - -error[E0308]: mismatched types - --> $DIR/generic_const_type_mismatch.rs:9:34 - | -LL | impl Trait for [(); N] {} - | ^ expected `usize`, found `i8` - -error: aborting due to 3 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0119, E0308. -For more information about an error, try `rustc --explain E0119`. +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/const-generics/bad-subst-const-kind.rs b/tests/ui/const-generics/bad-subst-const-kind.rs index c4e74596e9fdc..cc2ff9b8dea07 100644 --- a/tests/ui/const-generics/bad-subst-const-kind.rs +++ b/tests/ui/const-generics/bad-subst-const-kind.rs @@ -7,7 +7,6 @@ trait Q { impl Q for [u8; N] { //~^ ERROR: the constant `N` is not of type `usize` - //~| ERROR: mismatched types const ASSOC: usize = 1; } diff --git a/tests/ui/const-generics/bad-subst-const-kind.stderr b/tests/ui/const-generics/bad-subst-const-kind.stderr index 21ec8f0768cf1..5c8d9c9036356 100644 --- a/tests/ui/const-generics/bad-subst-const-kind.stderr +++ b/tests/ui/const-generics/bad-subst-const-kind.stderr @@ -5,7 +5,7 @@ LL | impl Q for [u8; N] { | ^^^^^^^ expected `usize`, found `u64` error: the constant `13` is not of type `u64` - --> $DIR/bad-subst-const-kind.rs:14:24 + --> $DIR/bad-subst-const-kind.rs:13:24 | LL | pub fn test() -> [u8; <[u8; 13] as Q>::ASSOC] { | ^^^^^^^^ expected `u64`, found `usize` @@ -18,12 +18,5 @@ LL | impl Q for [u8; N] { | | | unsatisfied trait bound introduced here -error[E0308]: mismatched types - --> $DIR/bad-subst-const-kind.rs:8:31 - | -LL | impl Q for [u8; N] { - | ^ expected `usize`, found `u64` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/type_mismatch.rs b/tests/ui/const-generics/generic_const_exprs/type_mismatch.rs index a45deabbb0f33..8e5e23b233718 100644 --- a/tests/ui/const-generics/generic_const_exprs/type_mismatch.rs +++ b/tests/ui/const-generics/generic_const_exprs/type_mismatch.rs @@ -8,7 +8,6 @@ trait Q { impl Q for [u8; N] {} //~^ ERROR not all trait items implemented //~| ERROR the constant `N` is not of type `usize` -//~| ERROR mismatched types pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {} //~^ ERROR the constant `13` is not of type `u64` diff --git a/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr b/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr index 68870a8d38da6..e03580ec007ca 100644 --- a/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr +++ b/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr @@ -14,7 +14,7 @@ LL | impl Q for [u8; N] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `ASSOC` in implementation error: the constant `13` is not of type `u64` - --> $DIR/type_mismatch.rs:13:26 + --> $DIR/type_mismatch.rs:12:26 | LL | pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {} | ^^^^^^^^ expected `u64`, found `usize` @@ -28,20 +28,14 @@ LL | impl Q for [u8; N] {} | unsatisfied trait bound introduced here error[E0308]: mismatched types - --> $DIR/type_mismatch.rs:13:20 + --> $DIR/type_mismatch.rs:12:20 | LL | pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {} | ------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `[u8; <[u8; 13] as Q>::ASSOC]`, found `()` | | | implicitly returns `()` as its body has no tail or `return` expression -error[E0308]: mismatched types - --> $DIR/type_mismatch.rs:8:31 - | -LL | impl Q for [u8; N] {} - | ^ expected `usize`, found `u64` - -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0046, E0308. For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs index 05a3487ffca51..d11b457a3f619 100644 --- a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs +++ b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs @@ -25,8 +25,8 @@ mod v20 { } impl v17 { - //~^ ERROR maximum number of nodes exceeded in constant v20::v17::::{constant#1} - //~| ERROR maximum number of nodes exceeded in constant v20::v17::::{constant#1} + //~^ ERROR maximum number of nodes exceeded in constant v20::v17::::{constant#0} + //~| ERROR maximum number of nodes exceeded in constant v20::v17::::{constant#0} pub const fn v21() -> v18 { //~^ ERROR cannot find type `v18` in this scope v18 { _p: () } diff --git a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr index 39f022fbee9db..15d3c47258525 100644 --- a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr +++ b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr @@ -72,13 +72,13 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more LL + #![feature(adt_const_params)] | -error: maximum number of nodes exceeded in constant v20::v17::::{constant#1} +error: maximum number of nodes exceeded in constant v20::v17::::{constant#0} --> $DIR/unevaluated-const-ice-119731.rs:27:37 | LL | impl v17 { | ^^ -error: maximum number of nodes exceeded in constant v20::v17::::{constant#1} +error: maximum number of nodes exceeded in constant v20::v17::::{constant#0} --> $DIR/unevaluated-const-ice-119731.rs:27:37 | LL | impl v17 { diff --git a/tests/ui/const-generics/transmute-fail.rs b/tests/ui/const-generics/transmute-fail.rs index a9b297ffb62a2..7faf670e46819 100644 --- a/tests/ui/const-generics/transmute-fail.rs +++ b/tests/ui/const-generics/transmute-fail.rs @@ -11,8 +11,6 @@ fn foo(v: [[u32; H + 1]; W]) -> [[u32; W + 1]; H fn bar(v: [[u32; H]; W]) -> [[u32; W]; H] { //~^ ERROR: the constant `W` is not of type `usize` - //~| ERROR: mismatched types - //~| ERROR: mismatched types unsafe { std::mem::transmute(v) //~^ ERROR: the constant `W` is not of type `usize` diff --git a/tests/ui/const-generics/transmute-fail.stderr b/tests/ui/const-generics/transmute-fail.stderr index 124fbee885057..4a20034910d10 100644 --- a/tests/ui/const-generics/transmute-fail.stderr +++ b/tests/ui/const-generics/transmute-fail.stderr @@ -14,13 +14,13 @@ LL | std::mem::transmute(v) = note: target type: `[[u32; W + 1]; H]` (size can vary because of [u32; W + 1]) error: the constant `W` is not of type `usize` - --> $DIR/transmute-fail.rs:17:9 + --> $DIR/transmute-fail.rs:15:9 | LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool` error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:24:9 + --> $DIR/transmute-fail.rs:22:9 | LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ @@ -29,7 +29,7 @@ LL | std::mem::transmute(v) = note: target type: `[u32; W * H * H]` (this type does not have a fixed size) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:31:9 + --> $DIR/transmute-fail.rs:29:9 | LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ @@ -38,7 +38,7 @@ LL | std::mem::transmute(v) = note: target type: `[[[u32; 9999999]; 777777777]; 8888888]` (values of the type `[[u32; 9999999]; 777777777]` are too big for the current architecture) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:38:9 + --> $DIR/transmute-fail.rs:36:9 | LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ @@ -47,7 +47,7 @@ LL | std::mem::transmute(v) = note: target type: `[[u32; W]; H]` (size can vary because of [u32; W]) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:49:9 + --> $DIR/transmute-fail.rs:47:9 | LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ @@ -56,7 +56,7 @@ LL | std::mem::transmute(v) = note: target type: `[u32; W * H]` (this type does not have a fixed size) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:56:9 + --> $DIR/transmute-fail.rs:54:9 | LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ @@ -65,7 +65,7 @@ LL | std::mem::transmute(v) = note: target type: `[[u32; W]; H]` (size can vary because of [u32; W]) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:65:9 + --> $DIR/transmute-fail.rs:63:9 | LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ @@ -74,7 +74,7 @@ LL | std::mem::transmute(v) = note: target type: `[u32; D * W * H]` (this type does not have a fixed size) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:74:9 + --> $DIR/transmute-fail.rs:72:9 | LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ @@ -83,7 +83,7 @@ LL | std::mem::transmute(v) = note: target type: `[[u32; D * W]; H]` (size can vary because of [u32; D * W]) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:81:9 + --> $DIR/transmute-fail.rs:79:9 | LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ @@ -92,7 +92,7 @@ LL | std::mem::transmute(v) = note: target type: `[u8; L * 2]` (this type does not have a fixed size) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:88:9 + --> $DIR/transmute-fail.rs:86:9 | LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ @@ -101,7 +101,7 @@ LL | std::mem::transmute(v) = note: target type: `[u16; L]` (this type does not have a fixed size) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:95:9 + --> $DIR/transmute-fail.rs:93:9 | LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ @@ -110,7 +110,7 @@ LL | std::mem::transmute(v) = note: target type: `[[u8; 1]; L]` (this type does not have a fixed size) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:104:9 + --> $DIR/transmute-fail.rs:102:9 | LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ @@ -118,19 +118,6 @@ LL | std::mem::transmute(v) = note: source type: `[[u32; 2 * H]; W + W]` (size can vary because of [u32; 2 * H]) = note: target type: `[[u32; W + W]; 2 * H]` (size can vary because of [u32; W + W]) -error[E0308]: mismatched types - --> $DIR/transmute-fail.rs:12:53 - | -LL | fn bar(v: [[u32; H]; W]) -> [[u32; W]; H] { - | ^ expected `usize`, found `bool` - -error[E0308]: mismatched types - --> $DIR/transmute-fail.rs:12:67 - | -LL | fn bar(v: [[u32; H]; W]) -> [[u32; W]; H] { - | ^ expected `usize`, found `bool` - -error: aborting due to 16 previous errors +error: aborting due to 14 previous errors -Some errors have detailed explanations: E0308, E0512. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0512`. diff --git a/tests/ui/const-generics/type_mismatch.rs b/tests/ui/const-generics/type_mismatch.rs index 9c7217cd83eee..8187c785cd1c7 100644 --- a/tests/ui/const-generics/type_mismatch.rs +++ b/tests/ui/const-generics/type_mismatch.rs @@ -1,12 +1,10 @@ fn foo() -> [u8; N] { bar::() //~^ ERROR the constant `N` is not of type `u8` - //~| ERROR: mismatched types } fn bar() -> [u8; N] {} //~^ ERROR the constant `N` is not of type `usize` -//~| ERROR: mismatched types //~| ERROR mismatched types fn main() {} diff --git a/tests/ui/const-generics/type_mismatch.stderr b/tests/ui/const-generics/type_mismatch.stderr index 77e9f5e2b445e..d1bb5c1242f02 100644 --- a/tests/ui/const-generics/type_mismatch.stderr +++ b/tests/ui/const-generics/type_mismatch.stderr @@ -1,5 +1,5 @@ error: the constant `N` is not of type `usize` - --> $DIR/type_mismatch.rs:7:26 + --> $DIR/type_mismatch.rs:6:26 | LL | fn bar() -> [u8; N] {} | ^^^^^^^ expected `usize`, found `u8` @@ -11,31 +11,19 @@ LL | bar::() | ^ expected `u8`, found `usize` | note: required by a const generic parameter in `bar` - --> $DIR/type_mismatch.rs:7:8 + --> $DIR/type_mismatch.rs:6:8 | LL | fn bar() -> [u8; N] {} | ^^^^^^^^^^^ required by this const generic parameter in `bar` error[E0308]: mismatched types - --> $DIR/type_mismatch.rs:7:26 + --> $DIR/type_mismatch.rs:6:26 | LL | fn bar() -> [u8; N] {} | --- ^^^^^^^ expected `[u8; N]`, found `()` | | | implicitly returns `()` as its body has no tail or `return` expression -error[E0308]: mismatched types - --> $DIR/type_mismatch.rs:2:11 - | -LL | bar::() - | ^ expected `u8`, found `usize` - -error[E0308]: mismatched types - --> $DIR/type_mismatch.rs:7:31 - | -LL | fn bar() -> [u8; N] {} - | ^ expected `usize`, found `u8` - -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/consts/issue-36163.stderr b/tests/ui/consts/issue-36163.stderr index 8a7a0981f4154..52d3e003f0ac9 100644 --- a/tests/ui/consts/issue-36163.stderr +++ b/tests/ui/consts/issue-36163.stderr @@ -1,10 +1,10 @@ -error[E0391]: cycle detected when simplifying constant for the type system `Foo::B::{constant#0}` +error[E0391]: cycle detected when simplifying constant for the type system `Foo::{constant#0}` --> $DIR/issue-36163.rs:4:9 | LL | B = A, | ^ | -note: ...which requires const-evaluating + checking `Foo::B::{constant#0}`... +note: ...which requires const-evaluating + checking `Foo::{constant#0}`... --> $DIR/issue-36163.rs:4:9 | LL | B = A, @@ -19,7 +19,7 @@ note: ...which requires const-evaluating + checking `A`... | LL | const A: isize = Foo::B as isize; | ^^^^^^^^^^^^^^^ - = note: ...which again requires simplifying constant for the type system `Foo::B::{constant#0}`, completing the cycle + = note: ...which again requires simplifying constant for the type system `Foo::{constant#0}`, completing the cycle note: cycle used when checking that `Foo` is well-formed --> $DIR/issue-36163.rs:3:1 | diff --git a/tests/ui/feature-gates/feature-gate-const-arg-path.rs b/tests/ui/feature-gates/feature-gate-const-arg-path.rs deleted file mode 100644 index 0938c5733a297..0000000000000 --- a/tests/ui/feature-gates/feature-gate-const-arg-path.rs +++ /dev/null @@ -1,5 +0,0 @@ -//@ check-pass - -// this doesn't really have any user facing impact.... - -fn main() {} diff --git a/tests/ui/lifetimes/issue-95023.rs b/tests/ui/lifetimes/issue-95023.rs index 8461d92fc33e4..1faae50d9f158 100644 --- a/tests/ui/lifetimes/issue-95023.rs +++ b/tests/ui/lifetimes/issue-95023.rs @@ -9,6 +9,5 @@ impl Fn(&isize) for Error { //~^ ERROR associated function in `impl` without body //~| ERROR method `foo` is not a member of trait `Fn` [E0407] //~| ERROR associated type `B` not found for `Self` [E0220] - //~| ERROR: associated type `B` not found for `Self` } fn main() {} diff --git a/tests/ui/lifetimes/issue-95023.stderr b/tests/ui/lifetimes/issue-95023.stderr index 310dee5140603..cbc0eeebee113 100644 --- a/tests/ui/lifetimes/issue-95023.stderr +++ b/tests/ui/lifetimes/issue-95023.stderr @@ -56,15 +56,7 @@ error[E0220]: associated type `B` not found for `Self` LL | fn foo(&self) -> Self::B<{ N }>; | ^ help: `Self` has the following associated type: `Output` -error[E0220]: associated type `B` not found for `Self` - --> $DIR/issue-95023.rs:8:44 - | -LL | fn foo(&self) -> Self::B<{ N }>; - | ^ help: `Self` has the following associated type: `Output` - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 8 previous errors +error: aborting due to 7 previous errors Some errors have detailed explanations: E0046, E0183, E0220, E0229, E0277, E0407. For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.rs b/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.rs index 858fba2132aae..fb962ad24bf93 100644 --- a/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.rs +++ b/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.rs @@ -14,6 +14,5 @@ struct Wrapper::Type> {} impl Wrapper {} //~^ ERROR the constant `C` is not of type `::Type` -//~| ERROR: mismatched types fn main() {} diff --git a/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.stderr b/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.stderr index 71d4277275fee..7094ee8c67ca0 100644 --- a/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.stderr +++ b/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.stderr @@ -20,17 +20,5 @@ note: required by a const generic parameter in `Wrapper` LL | struct Wrapper::Type> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this const generic parameter in `Wrapper` -error[E0308]: mismatched types - --> $DIR/default-proj-ty-as-type-of-const-issue-125757.rs:15:30 - | -LL | impl Wrapper {} - | ^ expected associated type, found `usize` - | - = note: expected associated type `::Type` - found type `usize` - = help: consider constraining the associated type `::Type` to `usize` - = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs index f89a463bc5805..a0ee771441772 100644 --- a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs +++ b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs @@ -6,7 +6,6 @@ struct S; impl Copy for S {} -//~^ ERROR: mismatched types impl Copy for S {} //~^ ERROR: conflicting implementations of trait `Copy` for type `S<_>` diff --git a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr index 1dac58e1f694e..2953bc95917c9 100644 --- a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr +++ b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr @@ -1,19 +1,11 @@ error[E0119]: conflicting implementations of trait `Copy` for type `S<_>` - --> $DIR/bad-const-wf-doesnt-specialize.rs:10:1 + --> $DIR/bad-const-wf-doesnt-specialize.rs:9:1 | LL | impl Copy for S {} | -------------------------------- first implementation here -LL | LL | impl Copy for S {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `S<_>` -error[E0308]: mismatched types - --> $DIR/bad-const-wf-doesnt-specialize.rs:8:31 - | -LL | impl Copy for S {} - | ^ expected `usize`, found `i32` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0119, E0308. -For more information about an error, try `rustc --explain E0119`. +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/transmutability/issue-101739-1.rs b/tests/ui/transmutability/issue-101739-1.rs index fcc1db073ee0e..4fde120e2be8b 100644 --- a/tests/ui/transmutability/issue-101739-1.rs +++ b/tests/ui/transmutability/issue-101739-1.rs @@ -7,7 +7,6 @@ mod assert { where Dst: TransmuteFrom, //~ ERROR cannot find type `Dst` in this scope //~| the constant `ASSUME_ALIGNMENT` is not of type `Assume` - //~| ERROR: mismatched types { } } diff --git a/tests/ui/transmutability/issue-101739-1.stderr b/tests/ui/transmutability/issue-101739-1.stderr index 3687631dc5119..b3c640a00b4c4 100644 --- a/tests/ui/transmutability/issue-101739-1.stderr +++ b/tests/ui/transmutability/issue-101739-1.stderr @@ -13,13 +13,6 @@ LL | Dst: TransmuteFrom, note: required by a const generic parameter in `TransmuteFrom` --> $SRC_DIR/core/src/mem/transmutability.rs:LL:COL -error[E0308]: mismatched types - --> $DIR/issue-101739-1.rs:8:33 - | -LL | Dst: TransmuteFrom, - | ^^^^^^^^^^^^^^^^ expected `Assume`, found `bool` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0308, E0412. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/transmutability/issue-101739-2.rs b/tests/ui/transmutability/issue-101739-2.rs index 02aa4669e05ef..613626accbb18 100644 --- a/tests/ui/transmutability/issue-101739-2.rs +++ b/tests/ui/transmutability/issue-101739-2.rs @@ -17,7 +17,7 @@ mod assert { Dst: TransmuteFrom< //~^ ERROR trait takes at most 2 generic arguments but 5 generic arguments were supplied Src, - ASSUME_ALIGNMENT, //~ ERROR: mismatched types + ASSUME_ALIGNMENT, ASSUME_LIFETIMES, ASSUME_VALIDITY, ASSUME_VISIBILITY, diff --git a/tests/ui/transmutability/issue-101739-2.stderr b/tests/ui/transmutability/issue-101739-2.stderr index 526fcabe14e9f..b436ab0e2f915 100644 --- a/tests/ui/transmutability/issue-101739-2.stderr +++ b/tests/ui/transmutability/issue-101739-2.stderr @@ -11,13 +11,6 @@ LL | | ASSUME_VALIDITY, LL | | ASSUME_VISIBILITY, | |_________________________________- help: remove the unnecessary generic arguments -error[E0308]: mismatched types - --> $DIR/issue-101739-2.rs:20:17 - | -LL | ASSUME_ALIGNMENT, - | ^^^^^^^^^^^^^^^^ expected `Assume`, found `bool` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0107, E0308. -For more information about an error, try `rustc --explain E0107`. +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.rs b/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.rs index 92c1999e1544b..5eef268872113 100644 --- a/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.rs +++ b/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.rs @@ -6,7 +6,6 @@ trait Trait { fn func() -> [(); N]; //~^ ERROR: the constant `N` is not of type `usize` - //~| ERROR: mismatched types } struct S {} diff --git a/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.stderr b/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.stderr index bb8025d47a18f..8017e5446cc71 100644 --- a/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.stderr +++ b/tests/ui/typeck/issue-114918/const-in-impl-fn-return-type.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/const-in-impl-fn-return-type.rs:16:39 + --> $DIR/const-in-impl-fn-return-type.rs:15:39 | LL | fn func() -> [(); { () }] { | ^^ expected `usize`, found `()` @@ -10,12 +10,6 @@ error: the constant `N` is not of type `usize` LL | fn func() -> [(); N]; | ^^^^^^^ expected `usize`, found `u32` -error[E0308]: mismatched types - --> $DIR/const-in-impl-fn-return-type.rs:7:37 - | -LL | fn func() -> [(); N]; - | ^ expected `usize`, found `u32` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`. From b4b2b356d958664f87c5b12344256c536e9e1b14 Mon Sep 17 00:00:00 2001 From: Ding Xiang Fei Date: Fri, 13 Sep 2024 02:43:49 +0800 Subject: [PATCH 188/189] simplify the suggestion notes --- compiler/rustc_lint/messages.ftl | 4 +- compiler/rustc_lint/src/if_let_rescope.rs | 231 ++++++++++-------- tests/ui/drop/lint-if-let-rescope-gated.rs | 4 +- ...let-rescope-gated.with_feature_gate.stderr | 41 +--- tests/ui/drop/lint-if-let-rescope.fixed | 40 +-- tests/ui/drop/lint-if-let-rescope.rs | 40 +-- tests/ui/drop/lint-if-let-rescope.stderr | 208 ++++------------ 7 files changed, 194 insertions(+), 374 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 2d062465bcfba..4aa86944a0b5c 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -337,9 +337,7 @@ lint_identifier_uncommon_codepoints = identifier contains {$codepoints_len -> lint_if_let_rescope = `if let` assigns a shorter lifetime since Edition 2024 .label = this value has a significant drop implementation which may observe a major change in drop order and requires your discretion .help = the value is now dropped here in Edition 2024 - -lint_if_let_rescope_suggestion = a `match` with a single arm can preserve the drop order up to Edition 2021 - .suggestion = rewrite this `if let` into `match` + .suggestion = a `match` with a single arm can preserve the drop order up to Edition 2021 lint_ignored_unless_crate_specified = {$level}({$name}) is ignored unless specified at crate level diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs index e5bf192d23e31..5b65541bea6e2 100644 --- a/compiler/rustc_lint/src/if_let_rescope.rs +++ b/compiler/rustc_lint/src/if_let_rescope.rs @@ -7,7 +7,7 @@ use rustc_errors::{ Applicability, Diag, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic, SuggestionStyle, }; use rustc_hir::{self as hir, HirIdSet}; -use rustc_macros::{LintDiagnostic, Subdiagnostic}; +use rustc_macros::LintDiagnostic; use rustc_middle::ty::TyCtxt; use rustc_session::lint::{FutureIncompatibilityReason, Level}; use rustc_session::{declare_lint, impl_lint_pass}; @@ -124,103 +124,109 @@ impl IfLetRescope { let source_map = tcx.sess.source_map(); let expr_end = expr.span.shrink_to_hi(); let mut add_bracket_to_match_head = match_head_needs_bracket(tcx, expr); + let mut significant_droppers = vec![]; + let mut lifetime_ends = vec![]; let mut closing_brackets = 0; let mut alt_heads = vec![]; let mut match_heads = vec![]; let mut consequent_heads = vec![]; - let mut first_if_to_rewrite = None; + let mut first_if_to_lint = None; + let mut first_if_to_rewrite = false; let mut empty_alt = false; while let hir::ExprKind::If(cond, conseq, alt) = expr.kind { self.skip.insert(expr.hir_id); - let hir::ExprKind::Let(&hir::LetExpr { + // We are interested in `let` fragment of the condition. + // Otherwise, we probe into the `else` fragment. + if let hir::ExprKind::Let(&hir::LetExpr { span, pat, init, ty: ty_ascription, recovered: Recovered::No, }) = cond.kind - else { - if let Some(alt) = alt { - add_bracket_to_match_head = matches!(alt.kind, hir::ExprKind::If(..)); - expr = alt; - continue; - } else { - // finalize and emit span - break; - } - }; - let if_let_pat = expr.span.shrink_to_lo().between(init.span); - // the consequent fragment is always a block - let before_conseq = conseq.span.shrink_to_lo(); - let lifetime_end = source_map.end_point(conseq.span); - - if let ControlFlow::Break(significant_dropper) = - (FindSignificantDropper { cx }).visit_expr(init) { - tcx.emit_node_span_lint( - IF_LET_RESCOPE, - expr.hir_id, - span, - IfLetRescopeLint { significant_dropper, lifetime_end }, - ); - if ty_ascription.is_some() - || !expr.span.can_be_used_for_suggestions() - || !pat.span.can_be_used_for_suggestions() + let if_let_pat = expr.span.shrink_to_lo().between(init.span); + // The consequent fragment is always a block. + let before_conseq = conseq.span.shrink_to_lo(); + let lifetime_end = source_map.end_point(conseq.span); + + if let ControlFlow::Break(significant_dropper) = + (FindSignificantDropper { cx }).visit_expr(init) { - // Our `match` rewrites does not support type ascription, - // so we just bail. - // Alternatively when the span comes from proc macro expansion, - // we will also bail. - // FIXME(#101728): change this when type ascription syntax is stabilized again - } else if let Ok(pat) = source_map.span_to_snippet(pat.span) { - let emit_suggestion = || { - first_if_to_rewrite = - first_if_to_rewrite.or_else(|| Some((expr.span, expr.hir_id))); - if add_bracket_to_match_head { - closing_brackets += 2; - match_heads.push(SingleArmMatchBegin::WithOpenBracket(if_let_pat)); + first_if_to_lint = first_if_to_lint.or_else(|| Some((span, expr.hir_id))); + significant_droppers.push(significant_dropper); + lifetime_ends.push(lifetime_end); + if ty_ascription.is_some() + || !expr.span.can_be_used_for_suggestions() + || !pat.span.can_be_used_for_suggestions() + { + // Our `match` rewrites does not support type ascription, + // so we just bail. + // Alternatively when the span comes from proc macro expansion, + // we will also bail. + // FIXME(#101728): change this when type ascription syntax is stabilized again + } else if let Ok(pat) = source_map.span_to_snippet(pat.span) { + let emit_suggestion = |alt_span| { + first_if_to_rewrite = true; + if add_bracket_to_match_head { + closing_brackets += 2; + match_heads.push(SingleArmMatchBegin::WithOpenBracket(if_let_pat)); + } else { + // Sometimes, wrapping `match` into a block is undesirable, + // because the scrutinee temporary lifetime is shortened and + // the proposed fix will not work. + closing_brackets += 1; + match_heads + .push(SingleArmMatchBegin::WithoutOpenBracket(if_let_pat)); + } + consequent_heads.push(ConsequentRewrite { span: before_conseq, pat }); + if let Some(alt_span) = alt_span { + alt_heads.push(AltHead(alt_span)); + } + }; + if let Some(alt) = alt { + let alt_head = conseq.span.between(alt.span); + if alt_head.can_be_used_for_suggestions() { + // We lint only when the `else` span is user code, too. + emit_suggestion(Some(alt_head)); + } } else { - // It has to be a block - closing_brackets += 1; - match_heads.push(SingleArmMatchBegin::WithoutOpenBracket(if_let_pat)); + // This is the end of the `if .. else ..` cascade. + // We can stop here. + emit_suggestion(None); + empty_alt = true; + break; } - consequent_heads.push(ConsequentRewrite { span: before_conseq, pat }); - }; - if let Some(alt) = alt { - let alt_head = conseq.span.between(alt.span); - if alt_head.can_be_used_for_suggestions() { - // lint - emit_suggestion(); - alt_heads.push(AltHead(alt_head)); - } - } else { - emit_suggestion(); - empty_alt = true; - break; } } } + // At this point, any `if let` fragment in the cascade is definitely preceeded by `else`, + // so a opening bracket is mandatory before each `match`. + add_bracket_to_match_head = true; if let Some(alt) = alt { - add_bracket_to_match_head = matches!(alt.kind, hir::ExprKind::If(..)); expr = alt; } else { break; } } - if let Some((span, hir_id)) = first_if_to_rewrite { + if let Some((span, hir_id)) = first_if_to_lint { tcx.emit_node_span_lint( IF_LET_RESCOPE, hir_id, span, - IfLetRescopeRewrite { - match_heads, - consequent_heads, - closing_brackets: ClosingBrackets { - span: expr_end, - count: closing_brackets, - empty_alt, - }, - alt_heads, + IfLetRescopeLint { + significant_droppers, + lifetime_ends, + rewrite: first_if_to_rewrite.then_some(IfLetRescopeRewrite { + match_heads, + consequent_heads, + closing_brackets: ClosingBrackets { + span: expr_end, + count: closing_brackets, + empty_alt, + }, + alt_heads, + }), }, ); } @@ -254,71 +260,80 @@ impl<'tcx> LateLintPass<'tcx> for IfLetRescope { #[diag(lint_if_let_rescope)] struct IfLetRescopeLint { #[label] - significant_dropper: Span, + significant_droppers: Vec, #[help] - lifetime_end: Span, + lifetime_ends: Vec, + #[subdiagnostic] + rewrite: Option, } -#[derive(LintDiagnostic)] -#[diag(lint_if_let_rescope_suggestion)] +// #[derive(Subdiagnostic)] struct IfLetRescopeRewrite { - #[subdiagnostic] match_heads: Vec, - #[subdiagnostic] consequent_heads: Vec, - #[subdiagnostic] closing_brackets: ClosingBrackets, - #[subdiagnostic] alt_heads: Vec, } -#[derive(Subdiagnostic)] -#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] -struct AltHead(#[suggestion_part(code = " _ => ")] Span); - -#[derive(Subdiagnostic)] -#[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] -struct ConsequentRewrite { - #[suggestion_part(code = "{{ {pat} => ")] - span: Span, - pat: String, -} - -struct ClosingBrackets { - span: Span, - count: usize, - empty_alt: bool, -} - -impl Subdiagnostic for ClosingBrackets { +impl Subdiagnostic for IfLetRescopeRewrite { fn add_to_diag_with>( self, diag: &mut Diag<'_, G>, f: &F, ) { - let code: String = self - .empty_alt - .then_some(" _ => {}".chars()) - .into_iter() - .flatten() - .chain(repeat('}').take(self.count)) - .collect(); + let mut suggestions = vec![]; + for match_head in self.match_heads { + match match_head { + SingleArmMatchBegin::WithOpenBracket(span) => { + suggestions.push((span, "{ match ".into())) + } + SingleArmMatchBegin::WithoutOpenBracket(span) => { + suggestions.push((span, "match ".into())) + } + } + } + for ConsequentRewrite { span, pat } in self.consequent_heads { + suggestions.push((span, format!("{{ {pat} => "))); + } + for AltHead(span) in self.alt_heads { + suggestions.push((span, " _ => ".into())); + } + let closing_brackets = self.closing_brackets; + suggestions.push(( + closing_brackets.span, + closing_brackets + .empty_alt + .then_some(" _ => {}".chars()) + .into_iter() + .flatten() + .chain(repeat('}').take(closing_brackets.count)) + .collect(), + )); let msg = f(diag, crate::fluent_generated::lint_suggestion.into()); diag.multipart_suggestion_with_style( msg, - vec![(self.span, code)], + suggestions, Applicability::MachineApplicable, SuggestionStyle::ShowCode, ); } } -#[derive(Subdiagnostic)] +struct AltHead(Span); + +struct ConsequentRewrite { + span: Span, + pat: String, +} + +struct ClosingBrackets { + span: Span, + count: usize, + empty_alt: bool, +} enum SingleArmMatchBegin { - #[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] - WithOpenBracket(#[suggestion_part(code = "{{ match ")] Span), - #[multipart_suggestion(lint_suggestion, applicability = "machine-applicable")] - WithoutOpenBracket(#[suggestion_part(code = "match ")] Span), + WithOpenBracket(Span), + WithoutOpenBracket(Span), } struct FindSignificantDropper<'tcx, 'a> { diff --git a/tests/ui/drop/lint-if-let-rescope-gated.rs b/tests/ui/drop/lint-if-let-rescope-gated.rs index 08ded67a51257..cef5de5a8fe56 100644 --- a/tests/ui/drop/lint-if-let-rescope-gated.rs +++ b/tests/ui/drop/lint-if-let-rescope-gated.rs @@ -26,9 +26,9 @@ impl Droppy { fn main() { if let Some(_value) = Droppy.get() { //[with_feature_gate]~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 - //[with_feature_gate]~| ERROR: a `match` with a single arm can preserve the drop order up to Edition 2021 - //[with_feature_gate]~| WARN: this changes meaning in Rust 2024 + //[with_feature_gate]~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 //[with_feature_gate]~| WARN: this changes meaning in Rust 2024 } else { + //[with_feature_gate]~^ HELP: the value is now dropped here in Edition 2024 } } diff --git a/tests/ui/drop/lint-if-let-rescope-gated.with_feature_gate.stderr b/tests/ui/drop/lint-if-let-rescope-gated.with_feature_gate.stderr index e0f2bebdbf1ed..48b7f3e11a682 100644 --- a/tests/ui/drop/lint-if-let-rescope-gated.with_feature_gate.stderr +++ b/tests/ui/drop/lint-if-let-rescope-gated.with_feature_gate.stderr @@ -9,7 +9,7 @@ LL | if let Some(_value) = Droppy.get() { = warning: this changes meaning in Rust 2024 = note: for more information, see issue #124085 help: the value is now dropped here in Edition 2024 - --> $DIR/lint-if-let-rescope-gated.rs:32:5 + --> $DIR/lint-if-let-rescope-gated.rs:31:5 | LL | } else { | ^ @@ -18,37 +18,16 @@ note: the lint level is defined here | LL | #![deny(if_let_rescope)] | ^^^^^^^^^^^^^^ - -error: a `match` with a single arm can preserve the drop order up to Edition 2021 - --> $DIR/lint-if-let-rescope-gated.rs:27:5 - | -LL | / if let Some(_value) = Droppy.get() { -LL | | -LL | | -LL | | -LL | | -LL | | } else { -LL | | } - | |_____^ - | - = warning: this changes meaning in Rust 2024 - = note: for more information, see issue #124085 -help: rewrite this `if let` into `match` - | -LL | match Droppy.get() { - | ~~~~~ -help: rewrite this `if let` into `match` - | -LL | if let Some(_value) = Droppy.get() { Some(_value) => { - | +++++++++++++++++ -help: rewrite this `if let` into `match` +help: a `match` with a single arm can preserve the drop order up to Edition 2021 | -LL | }} - | + -help: rewrite this `if let` into `match` +LL ~ match Droppy.get() { Some(_value) => { +LL | +LL | +LL | +LL ~ } _ => { +LL | +LL ~ }} | -LL | } _ => { - | ~~~~ -error: aborting due to 2 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/drop/lint-if-let-rescope.fixed b/tests/ui/drop/lint-if-let-rescope.fixed index 85ffa320796ad..f228783f88bc5 100644 --- a/tests/ui/drop/lint-if-let-rescope.fixed +++ b/tests/ui/drop/lint-if-let-rescope.fixed @@ -27,73 +27,45 @@ fn main() { match droppy().get() { Some(_value) => { //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 //~| WARN: this changes meaning in Rust 2024 - //~| WARN: this changes meaning in Rust 2024 - //~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021 - //~| HELP: rewrite this `if let` into `match` - //~| HELP: rewrite this `if let` into `match` + //~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 // do something } _ => { //~^ HELP: the value is now dropped here in Edition 2024 - //~| HELP: rewrite this `if let` into `match` // do something else }} - //~^ HELP: rewrite this `if let` into `match` match droppy().get() { Some(_value) => { //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 //~| WARN: this changes meaning in Rust 2024 - //~| WARN: this changes meaning in Rust 2024 - //~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021 - //~| HELP: rewrite this `if let` into `match` - //~| HELP: rewrite this `if let` into `match` + //~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 // do something } _ => { match droppy().get() { Some(_value) => { //~^ HELP: the value is now dropped here in Edition 2024 - //~| ERROR: `if let` assigns a shorter lifetime since Edition 2024 - //~| WARN: this changes meaning in Rust 2024 - //~| HELP: rewrite this `if let` into `match` - //~| HELP: rewrite this `if let` into `match` - //~| HELP: rewrite this `if let` into `match` // do something else } _ => {}}}} - //~^ HELP: rewrite this `if let` into `match` - //~| HELP: the value is now dropped here in Edition 2024 + //~^ HELP: the value is now dropped here in Edition 2024 if droppy().get().is_some() { // Should not lint } else { match droppy().get() { Some(_value) => { //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 - //~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021 //~| WARN: this changes meaning in Rust 2024 - //~| WARN: this changes meaning in Rust 2024 - //~| HELP: rewrite this `if let` into `match` - //~| HELP: rewrite this `if let` into `match` + //~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 } _ => if droppy().get().is_none() { //~^ HELP: the value is now dropped here in Edition 2024 - //~| HELP: rewrite this `if let` into `match` }}} - //~^ HELP: rewrite this `if let` into `match` if let Some(1) = { match Droppy.get() { Some(_value) => { Some(1) } _ => { None }} } { //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 - //~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021 - //~| WARN: this changes meaning in Rust 2024 //~| WARN: this changes meaning in Rust 2024 - //~| HELP: rewrite this `if let` into `match` - //~| HELP: rewrite this `if let` into `match` - //~| HELP: rewrite this `if let` into `match` - //~| HELP: rewrite this `if let` into `match` //~| HELP: the value is now dropped here in Edition 2024 + //~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 } if let () = { match Droppy.get() { Some(_value) => {} _ => {}} } { //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 - //~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021 - //~| WARN: this changes meaning in Rust 2024 //~| WARN: this changes meaning in Rust 2024 - //~| HELP: rewrite this `if let` into `match` - //~| HELP: rewrite this `if let` into `match` - //~| HELP: rewrite this `if let` into `match` //~| HELP: the value is now dropped here in Edition 2024 + //~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 } } diff --git a/tests/ui/drop/lint-if-let-rescope.rs b/tests/ui/drop/lint-if-let-rescope.rs index 776b34fdbeafe..241fb897fce17 100644 --- a/tests/ui/drop/lint-if-let-rescope.rs +++ b/tests/ui/drop/lint-if-let-rescope.rs @@ -27,73 +27,45 @@ fn main() { if let Some(_value) = droppy().get() { //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 //~| WARN: this changes meaning in Rust 2024 - //~| WARN: this changes meaning in Rust 2024 - //~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021 - //~| HELP: rewrite this `if let` into `match` - //~| HELP: rewrite this `if let` into `match` + //~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 // do something } else { //~^ HELP: the value is now dropped here in Edition 2024 - //~| HELP: rewrite this `if let` into `match` // do something else } - //~^ HELP: rewrite this `if let` into `match` if let Some(_value) = droppy().get() { //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 //~| WARN: this changes meaning in Rust 2024 - //~| WARN: this changes meaning in Rust 2024 - //~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021 - //~| HELP: rewrite this `if let` into `match` - //~| HELP: rewrite this `if let` into `match` + //~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 // do something } else if let Some(_value) = droppy().get() { //~^ HELP: the value is now dropped here in Edition 2024 - //~| ERROR: `if let` assigns a shorter lifetime since Edition 2024 - //~| WARN: this changes meaning in Rust 2024 - //~| HELP: rewrite this `if let` into `match` - //~| HELP: rewrite this `if let` into `match` - //~| HELP: rewrite this `if let` into `match` // do something else } - //~^ HELP: rewrite this `if let` into `match` - //~| HELP: the value is now dropped here in Edition 2024 + //~^ HELP: the value is now dropped here in Edition 2024 if droppy().get().is_some() { // Should not lint } else if let Some(_value) = droppy().get() { //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 - //~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021 //~| WARN: this changes meaning in Rust 2024 - //~| WARN: this changes meaning in Rust 2024 - //~| HELP: rewrite this `if let` into `match` - //~| HELP: rewrite this `if let` into `match` + //~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 } else if droppy().get().is_none() { //~^ HELP: the value is now dropped here in Edition 2024 - //~| HELP: rewrite this `if let` into `match` } - //~^ HELP: rewrite this `if let` into `match` if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } else { None } } { //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 - //~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021 - //~| WARN: this changes meaning in Rust 2024 //~| WARN: this changes meaning in Rust 2024 - //~| HELP: rewrite this `if let` into `match` - //~| HELP: rewrite this `if let` into `match` - //~| HELP: rewrite this `if let` into `match` - //~| HELP: rewrite this `if let` into `match` //~| HELP: the value is now dropped here in Edition 2024 + //~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 } if let () = { if let Some(_value) = Droppy.get() {} } { //~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024 - //~| ERROR a `match` with a single arm can preserve the drop order up to Edition 2021 - //~| WARN: this changes meaning in Rust 2024 //~| WARN: this changes meaning in Rust 2024 - //~| HELP: rewrite this `if let` into `match` - //~| HELP: rewrite this `if let` into `match` - //~| HELP: rewrite this `if let` into `match` //~| HELP: the value is now dropped here in Edition 2024 + //~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021 } } diff --git a/tests/ui/drop/lint-if-let-rescope.stderr b/tests/ui/drop/lint-if-let-rescope.stderr index a08d95e113869..25ca3cf1ca873 100644 --- a/tests/ui/drop/lint-if-let-rescope.stderr +++ b/tests/ui/drop/lint-if-let-rescope.stderr @@ -9,7 +9,7 @@ LL | if let Some(_value) = droppy().get() { = warning: this changes meaning in Rust 2024 = note: for more information, see issue #124085 help: the value is now dropped here in Edition 2024 - --> $DIR/lint-if-let-rescope.rs:35:5 + --> $DIR/lint-if-let-rescope.rs:32:5 | LL | } else { | ^ @@ -18,111 +18,55 @@ note: the lint level is defined here | LL | #![deny(if_let_rescope)] | ^^^^^^^^^^^^^^ - -error: a `match` with a single arm can preserve the drop order up to Edition 2021 - --> $DIR/lint-if-let-rescope.rs:27:5 - | -LL | / if let Some(_value) = droppy().get() { -LL | | -LL | | -LL | | -... | -LL | | // do something else -LL | | } - | |_____^ - | - = warning: this changes meaning in Rust 2024 - = note: for more information, see issue #124085 -help: rewrite this `if let` into `match` +help: a `match` with a single arm can preserve the drop order up to Edition 2021 | -LL | match droppy().get() { - | ~~~~~ -help: rewrite this `if let` into `match` +LL ~ match droppy().get() { Some(_value) => { +LL | +... +LL | // do something +LL ~ } _ => { +LL | +LL | // do something else +LL ~ }} | -LL | if let Some(_value) = droppy().get() { Some(_value) => { - | +++++++++++++++++ -help: rewrite this `if let` into `match` - | -LL | }} - | + -help: rewrite this `if let` into `match` - | -LL | } _ => { - | ~~~~ error: `if let` assigns a shorter lifetime since Edition 2024 - --> $DIR/lint-if-let-rescope.rs:42:8 + --> $DIR/lint-if-let-rescope.rs:37:8 | LL | if let Some(_value) = droppy().get() { | ^^^^^^^^^^^^^^^^^^^--------^^^^^^ | | | this value has a significant drop implementation which may observe a major change in drop order and requires your discretion +... +LL | } else if let Some(_value) = droppy().get() { + | -------- this value has a significant drop implementation which may observe a major change in drop order and requires your discretion | = warning: this changes meaning in Rust 2024 = note: for more information, see issue #124085 help: the value is now dropped here in Edition 2024 - --> $DIR/lint-if-let-rescope.rs:50:5 + --> $DIR/lint-if-let-rescope.rs:42:5 | LL | } else if let Some(_value) = droppy().get() { | ^ - -error: `if let` assigns a shorter lifetime since Edition 2024 - --> $DIR/lint-if-let-rescope.rs:50:15 - | -LL | } else if let Some(_value) = droppy().get() { - | ^^^^^^^^^^^^^^^^^^^--------^^^^^^ - | | - | this value has a significant drop implementation which may observe a major change in drop order and requires your discretion - | - = warning: this changes meaning in Rust 2024 - = note: for more information, see issue #124085 help: the value is now dropped here in Edition 2024 - --> $DIR/lint-if-let-rescope.rs:58:5 + --> $DIR/lint-if-let-rescope.rs:45:5 | LL | } | ^ - -error: a `match` with a single arm can preserve the drop order up to Edition 2021 - --> $DIR/lint-if-let-rescope.rs:42:5 - | -LL | / if let Some(_value) = droppy().get() { -LL | | -LL | | -LL | | -... | -LL | | // do something else -LL | | } - | |_____^ - | - = warning: this changes meaning in Rust 2024 - = note: for more information, see issue #124085 -help: rewrite this `if let` into `match` - | -LL | match droppy().get() { - | ~~~~~ -help: rewrite this `if let` into `match` - | -LL | } else { match droppy().get() { - | ~~~~~~~ -help: rewrite this `if let` into `match` +help: a `match` with a single arm can preserve the drop order up to Edition 2021 | -LL | if let Some(_value) = droppy().get() { Some(_value) => { - | +++++++++++++++++ -help: rewrite this `if let` into `match` +LL ~ match droppy().get() { Some(_value) => { +LL | +... +LL | // do something +LL ~ } _ => { match droppy().get() { Some(_value) => { +LL | +LL | // do something else +LL ~ } _ => {}}}} | -LL | } else if let Some(_value) = droppy().get() { Some(_value) => { - | +++++++++++++++++ -help: rewrite this `if let` into `match` - | -LL | } _ => {}}}} - | ++++++++++ -help: rewrite this `if let` into `match` - | -LL | } _ => if let Some(_value) = droppy().get() { - | ~~~~ error: `if let` assigns a shorter lifetime since Edition 2024 - --> $DIR/lint-if-let-rescope.rs:64:15 + --> $DIR/lint-if-let-rescope.rs:50:15 | LL | } else if let Some(_value) = droppy().get() { | ^^^^^^^^^^^^^^^^^^^--------^^^^^^ @@ -132,45 +76,23 @@ LL | } else if let Some(_value) = droppy().get() { = warning: this changes meaning in Rust 2024 = note: for more information, see issue #124085 help: the value is now dropped here in Edition 2024 - --> $DIR/lint-if-let-rescope.rs:71:5 + --> $DIR/lint-if-let-rescope.rs:54:5 | LL | } else if droppy().get().is_none() { | ^ - -error: a `match` with a single arm can preserve the drop order up to Edition 2021 - --> $DIR/lint-if-let-rescope.rs:64:12 - | -LL | } else if let Some(_value) = droppy().get() { - | ____________^ -LL | | -LL | | -LL | | -... | -LL | | -LL | | } - | |_____^ - | - = warning: this changes meaning in Rust 2024 - = note: for more information, see issue #124085 -help: rewrite this `if let` into `match` +help: a `match` with a single arm can preserve the drop order up to Edition 2021 | -LL | } else { match droppy().get() { - | ~~~~~~~ -help: rewrite this `if let` into `match` +LL ~ } else { match droppy().get() { Some(_value) => { +LL | +LL | +LL | +LL ~ } _ => if droppy().get().is_none() { +LL | +LL ~ }}} | -LL | } else if let Some(_value) = droppy().get() { Some(_value) => { - | +++++++++++++++++ -help: rewrite this `if let` into `match` - | -LL | }}} - | ++ -help: rewrite this `if let` into `match` - | -LL | } _ => if droppy().get().is_none() { - | ~~~~ error: `if let` assigns a shorter lifetime since Edition 2024 - --> $DIR/lint-if-let-rescope.rs:77:27 + --> $DIR/lint-if-let-rescope.rs:58:27 | LL | if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } else { None } } { | ^^^^^^^^^^^^^^^^^^^------^^^^^^ @@ -180,38 +102,17 @@ LL | if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } else = warning: this changes meaning in Rust 2024 = note: for more information, see issue #124085 help: the value is now dropped here in Edition 2024 - --> $DIR/lint-if-let-rescope.rs:77:69 + --> $DIR/lint-if-let-rescope.rs:58:69 | LL | if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } else { None } } { | ^ - -error: a `match` with a single arm can preserve the drop order up to Edition 2021 - --> $DIR/lint-if-let-rescope.rs:77:24 - | -LL | if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } else { None } } { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this changes meaning in Rust 2024 - = note: for more information, see issue #124085 -help: rewrite this `if let` into `match` - | -LL | if let Some(1) = { match Droppy.get() { Some(1) } else { None } } { - | ~~~~~ -help: rewrite this `if let` into `match` - | -LL | if let Some(1) = { if let Some(_value) = Droppy.get() { Some(_value) => { Some(1) } else { None } } { - | +++++++++++++++++ -help: rewrite this `if let` into `match` +help: a `match` with a single arm can preserve the drop order up to Edition 2021 | -LL | if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } else { None }} } { - | + -help: rewrite this `if let` into `match` - | -LL | if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } _ => { None } } { - | ~~~~ +LL | if let Some(1) = { match Droppy.get() { Some(_value) => { Some(1) } _ => { None }} } { + | ~~~~~ +++++++++++++++++ ~~~~ + error: `if let` assigns a shorter lifetime since Edition 2024 - --> $DIR/lint-if-let-rescope.rs:89:22 + --> $DIR/lint-if-let-rescope.rs:65:22 | LL | if let () = { if let Some(_value) = Droppy.get() {} } { | ^^^^^^^^^^^^^^^^^^^------^^^^^^ @@ -221,31 +122,14 @@ LL | if let () = { if let Some(_value) = Droppy.get() {} } { = warning: this changes meaning in Rust 2024 = note: for more information, see issue #124085 help: the value is now dropped here in Edition 2024 - --> $DIR/lint-if-let-rescope.rs:89:55 + --> $DIR/lint-if-let-rescope.rs:65:55 | LL | if let () = { if let Some(_value) = Droppy.get() {} } { | ^ - -error: a `match` with a single arm can preserve the drop order up to Edition 2021 - --> $DIR/lint-if-let-rescope.rs:89:19 - | -LL | if let () = { if let Some(_value) = Droppy.get() {} } { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this changes meaning in Rust 2024 - = note: for more information, see issue #124085 -help: rewrite this `if let` into `match` - | -LL | if let () = { match Droppy.get() {} } { - | ~~~~~ -help: rewrite this `if let` into `match` - | -LL | if let () = { if let Some(_value) = Droppy.get() { Some(_value) => {} } { - | +++++++++++++++++ -help: rewrite this `if let` into `match` +help: a `match` with a single arm can preserve the drop order up to Edition 2021 | -LL | if let () = { if let Some(_value) = Droppy.get() {} _ => {}} } { - | ++++++++ +LL | if let () = { match Droppy.get() { Some(_value) => {} _ => {}} } { + | ~~~~~ +++++++++++++++++ ++++++++ -error: aborting due to 11 previous errors +error: aborting due to 5 previous errors From df8e6c343c25afe0011f1675745a9d471c90306d Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 12 Sep 2024 20:18:56 -0700 Subject: [PATCH 189/189] Revert "Auto merge of #130040 - onur-ozkan:llvm-tools-with-ci-rustc, r=Kobzol" This reverts commit adaff5368b0c7b328a0320a218751d65ab1bba97, reversing changes made to 2e8db5e9e39c2bf7729113b3041ef4011d90ac5a. --- src/bootstrap/src/core/build_steps/compile.rs | 64 +++++++---- src/bootstrap/src/core/build_steps/dist.rs | 107 +----------------- 2 files changed, 50 insertions(+), 121 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 3dc1ed5379b5d..bb07d478f71aa 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -29,7 +29,7 @@ use crate::utils::exec::command; use crate::utils::helpers::{ self, exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, symlink_dir, t, up_to_date, }; -use crate::{CLang, Compiler, DependencyType, GitRepo, Mode}; +use crate::{CLang, Compiler, DependencyType, GitRepo, Mode, LLVM_TOOLS}; #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Std { @@ -1908,26 +1908,52 @@ impl Step for Assemble { // delegates to the `rust-lld` binary for linking and then runs // logic to create the final binary. This is used by the // `wasm32-wasip2` target of Rust. - dist::maybe_install_wasm_component_ld( - builder, - build_compiler, - target_compiler.host, - &libdir_bin, - false, - ); - - dist::maybe_install_llvm_tools(builder, target_compiler.host, &libdir_bin, false); + if builder.tool_enabled("wasm-component-ld") { + let wasm_component_ld_exe = + builder.ensure(crate::core::build_steps::tool::WasmComponentLd { + compiler: build_compiler, + target: target_compiler.host, + }); + builder.copy_link( + &wasm_component_ld_exe, + &libdir_bin.join(wasm_component_ld_exe.file_name().unwrap()), + ); + } - let self_contained_bin_dir = libdir_bin.join("self-contained"); - t!(fs::create_dir_all(&self_contained_bin_dir)); + if builder.config.llvm_enabled(target_compiler.host) { + let llvm::LlvmResult { llvm_config, .. } = + builder.ensure(llvm::Llvm { target: target_compiler.host }); + if !builder.config.dry_run() && builder.config.llvm_tools_enabled { + let llvm_bin_dir = + command(llvm_config).arg("--bindir").run_capture_stdout(builder).stdout(); + let llvm_bin_dir = Path::new(llvm_bin_dir.trim()); + + // Since we've already built the LLVM tools, install them to the sysroot. + // This is the equivalent of installing the `llvm-tools-preview` component via + // rustup, and lets developers use a locally built toolchain to + // build projects that expect llvm tools to be present in the sysroot + // (e.g. the `bootimage` crate). + for tool in LLVM_TOOLS { + let tool_exe = exe(tool, target_compiler.host); + let src_path = llvm_bin_dir.join(&tool_exe); + // When using `download-ci-llvm`, some of the tools + // may not exist, so skip trying to copy them. + if src_path.exists() { + builder.copy_link(&src_path, &libdir_bin.join(&tool_exe)); + } + } + } + } - dist::maybe_install_llvm_bitcode_linker( - builder, - build_compiler, - target_compiler.host, - &self_contained_bin_dir, - false, - ); + if builder.config.llvm_bitcode_linker_enabled { + let src_path = builder.ensure(crate::core::build_steps::tool::LlvmBitcodeLinker { + compiler: build_compiler, + target: target_compiler.host, + extra_features: vec![], + }); + let tool_exe = exe("llvm-bitcode-linker", target_compiler.host); + builder.copy_link(&src_path, &libdir_bin.join(tool_exe)); + } // Ensure that `libLLVM.so` ends up in the newly build compiler directory, // so that it can be found when the newly built `rustc` is run. diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index ddf769129491f..b0bd18792beb2 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -473,29 +473,11 @@ impl Step for Rustc { ); } } - - let builder_compiler = - builder.compiler_for(builder.top_stage, builder.config.build, compiler.host); - - maybe_install_wasm_component_ld( - builder, - builder_compiler, - compiler.host, - &dst_dir, - true, - ); - - let self_contained_bin_dir = dst_dir.join("self-contained"); - t!(fs::create_dir_all(&self_contained_bin_dir)); - maybe_install_llvm_bitcode_linker( - builder, - builder_compiler, - compiler.host, - &self_contained_bin_dir, - true, - ); - - maybe_install_llvm_tools(builder, compiler.host, &dst_dir, true); + if builder.tool_enabled("wasm-component-ld") { + let src_dir = builder.sysroot_libdir(compiler, host).parent().unwrap().join("bin"); + let ld = exe("wasm-component-ld", compiler.host); + builder.copy_link(&src_dir.join(&ld), &dst_dir.join(&ld)); + } // Man pages t!(fs::create_dir_all(image.join("share/man/man1"))); @@ -2104,85 +2086,6 @@ pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: TargetSelection } } -/// Maybe add LLVM tools to the rustc sysroot. -pub fn maybe_install_llvm_tools( - builder: &Builder<'_>, - target: TargetSelection, - dst_dir: &Path, - dereference_symlinks: bool, -) { - if builder.config.llvm_enabled(target) { - let llvm::LlvmResult { llvm_config, .. } = builder.ensure(llvm::Llvm { target }); - if !builder.config.dry_run() && builder.config.llvm_tools_enabled { - let llvm_bin_dir = - command(llvm_config).arg("--bindir").run_capture_stdout(builder).stdout(); - let llvm_bin_dir = Path::new(llvm_bin_dir.trim()); - - // Since we've already built the LLVM tools, install them to the sysroot. - // This is the equivalent of installing the `llvm-tools-preview` component via - // rustup, and lets developers use a locally built toolchain to - // build projects that expect llvm tools to be present in the sysroot - // (e.g. the `bootimage` crate). - for tool in LLVM_TOOLS { - let tool_exe = exe(tool, target); - let src_path = llvm_bin_dir.join(&tool_exe); - // When using `download-ci-llvm`, some of the tools - // may not exist, so skip trying to copy them. - if src_path.exists() { - builder.copy_link_internal( - &src_path, - &dst_dir.join(&tool_exe), - dereference_symlinks, - ); - } - } - } - } -} - -/// Maybe add `llvm-bitcode-linker` to the rustc sysroot. -pub fn maybe_install_llvm_bitcode_linker( - builder: &Builder<'_>, - builder_compiler: Compiler, - target: TargetSelection, - dst_dir: &Path, - dereference_symlinks: bool, -) { - if builder.config.llvm_bitcode_linker_enabled { - let llvm_bitcode_linker_exe = builder.ensure(tool::LlvmBitcodeLinker { - compiler: builder_compiler, - target, - extra_features: vec![], - }); - - builder.copy_link_internal( - &llvm_bitcode_linker_exe, - &dst_dir.join(llvm_bitcode_linker_exe.file_name().unwrap()), - dereference_symlinks, - ); - } -} - -/// Maybe add `wasm-component-ld` to the rustc sysroot. -pub fn maybe_install_wasm_component_ld( - builder: &Builder<'_>, - builder_compiler: Compiler, - target: TargetSelection, - dst_dir: &Path, - dereference_symlinks: bool, -) { - if builder.tool_enabled("wasm-component-ld") { - let wasm_component_ld_exe = - builder.ensure(tool::WasmComponentLd { compiler: builder_compiler, target }); - - builder.copy_link_internal( - &wasm_component_ld_exe, - &dst_dir.join(wasm_component_ld_exe.file_name().unwrap()), - dereference_symlinks, - ); - } -} - #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct LlvmTools { pub target: TargetSelection,