From 007c61732677fcd388f9f7887578724d1003f915 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Fri, 24 May 2024 01:33:55 -0700 Subject: [PATCH 001/211] clippy: unnest check_consts --- clippy_utils/src/qualify_min_const_fn.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs index 8ee7d87acb3e..81e94725a70c 100644 --- a/clippy_utils/src/qualify_min_const_fn.rs +++ b/clippy_utils/src/qualify_min_const_fn.rs @@ -6,7 +6,7 @@ use clippy_config::msrvs::{self, Msrv}; use hir::LangItem; use rustc_attr::StableSince; -use rustc_const_eval::transform::check_consts::ConstCx; +use rustc_const_eval::check_consts::ConstCx; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_infer::infer::TyCtxtInferExt; From a456300af569750232afc0e98da28c4786fce19b Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Tue, 20 Feb 2024 20:55:13 -0700 Subject: [PATCH 002/211] Stabilize `LazyCell` and `LazyLock` (`lazy_cell`) --- clippy_dev/src/lib.rs | 1 - src/driver.rs | 1 - tests/compile-test.rs | 1 - tests/dogfood.rs | 1 - tests/lint_message_convention.rs | 1 - tests/workspace.rs | 2 -- 6 files changed, 7 deletions(-) diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 385191e0361b..3aa43dbe23ed 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -1,4 +1,3 @@ -#![feature(lazy_cell)] #![feature(let_chains)] #![feature(rustc_private)] #![cfg_attr(feature = "deny-warnings", deny(warnings))] diff --git a/src/driver.rs b/src/driver.rs index 9e42abbc9aa9..f79da26964f3 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -2,7 +2,6 @@ #![allow(rustc::untranslatable_diagnostic)] #![feature(rustc_private)] #![feature(let_chains)] -#![feature(lazy_cell)] #![feature(lint_reasons)] #![cfg_attr(feature = "deny-warnings", deny(warnings))] // warn on lints, that are included in `rust-lang/rust`s bootstrap diff --git a/tests/compile-test.rs b/tests/compile-test.rs index b06a11702ec8..333a2ab58575 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -1,4 +1,3 @@ -#![feature(lazy_cell)] #![feature(is_sorted)] #![cfg_attr(feature = "deny-warnings", deny(warnings))] #![warn(rust_2018_idioms, unused_lifetimes)] diff --git a/tests/dogfood.rs b/tests/dogfood.rs index 3f16c180ea78..36a7a651c4d2 100644 --- a/tests/dogfood.rs +++ b/tests/dogfood.rs @@ -3,7 +3,6 @@ //! //! See [Eating your own dog food](https://en.wikipedia.org/wiki/Eating_your_own_dog_food) for context -#![feature(lazy_cell)] #![cfg_attr(feature = "deny-warnings", deny(warnings))] #![warn(rust_2018_idioms, unused_lifetimes)] diff --git a/tests/lint_message_convention.rs b/tests/lint_message_convention.rs index 98019c755276..6ce7e44474d8 100644 --- a/tests/lint_message_convention.rs +++ b/tests/lint_message_convention.rs @@ -1,4 +1,3 @@ -#![feature(lazy_cell)] #![cfg_attr(feature = "deny-warnings", deny(warnings))] #![warn(rust_2018_idioms, unused_lifetimes)] diff --git a/tests/workspace.rs b/tests/workspace.rs index 699ab2be199a..19ccc7ae9607 100644 --- a/tests/workspace.rs +++ b/tests/workspace.rs @@ -1,5 +1,3 @@ -#![feature(lazy_cell)] - use std::path::PathBuf; use std::process::Command; use test_utils::{CARGO_CLIPPY_PATH, IS_RUSTC_TEST_SUITE}; From c8390cdbfaccc55aa374222e39cdf9092a1e5ff6 Mon Sep 17 00:00:00 2001 From: Michael Baikov Date: Sat, 6 Apr 2024 11:22:21 -0400 Subject: [PATCH 003/211] Show files produced by --emit foo in json artifact notifications --- .../rustc_codegen_cranelift/src/driver/aot.rs | 23 ++++++++++ compiler/rustc_codegen_ssa/src/back/write.rs | 23 ++++++++++ compiler/rustc_codegen_ssa/src/lib.rs | 18 ++++++++ compiler/rustc_mir_transform/src/dump_mir.rs | 3 ++ src/doc/rustc/src/json.md | 8 +++- .../run-make/notify-all-emit-artifacts/lib.rs | 21 +++++++++ .../notify-all-emit-artifacts/rmake.rs | 45 +++++++++++++++++++ 7 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 tests/run-make/notify-all-emit-artifacts/lib.rs create mode 100644 tests/run-make/notify-all-emit-artifacts/rmake.rs diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index e8c96486041b..aff9448a89c3 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs @@ -287,6 +287,29 @@ fn produce_final_output_artifacts( } } + if sess.opts.json_artifact_notifications { + if codegen_results.modules.len() == 1 { + codegen_results.modules[0].for_each_output(|_path, ty| { + if sess.opts.output_types.contains_key(&ty) { + let descr = ty.shorthand(); + // for single cgu file is renamed to drop cgu specific suffix + // so we regenerate it the same way + let path = crate_output.path(ty); + sess.dcx().emit_artifact_notification(path.as_path(), descr); + } + }); + } else { + for module in &codegen_results.modules { + module.for_each_output(|path, ty| { + if sess.opts.output_types.contains_key(&ty) { + let descr = ty.shorthand(); + sess.dcx().emit_artifact_notification(&path, descr); + } + }); + } + } + } + // We leave the following files around by default: // - #crate#.o // - #crate#.crate.metadata.o diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index c4f062405bb5..72030dcbac54 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -706,6 +706,29 @@ fn produce_final_output_artifacts( } } + if sess.opts.json_artifact_notifications { + if compiled_modules.modules.len() == 1 { + compiled_modules.modules[0].for_each_output(|_path, ty| { + if sess.opts.output_types.contains_key(&ty) { + let descr = ty.shorthand(); + // for single cgu file is renamed to drop cgu specific suffix + // so we regenerate it the same way + let path = crate_output.path(ty); + sess.dcx().emit_artifact_notification(path.as_path(), descr); + } + }); + } else { + for module in &compiled_modules.modules { + module.for_each_output(|path, ty| { + if sess.opts.output_types.contains_key(&ty) { + let descr = ty.shorthand(); + sess.dcx().emit_artifact_notification(&path, descr); + } + }); + } + } + } + // We leave the following files around by default: // - #crate#.o // - #crate#.crate.metadata.o diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 80fe7e0bb786..7e0e5a9e632e 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -113,6 +113,24 @@ pub struct CompiledModule { pub llvm_ir: Option, // --emit=llvm-ir, llvm-bc is in bytecode } +impl CompiledModule { + /// Call `emit` function with every artifact type currently compiled + pub fn for_each_output(&self, mut emit: impl FnMut(&Path, OutputType)) { + if let Some(path) = self.object.as_deref() { + emit(path, OutputType::Object); + } + if let Some(path) = self.bytecode.as_deref() { + emit(path, OutputType::Bitcode); + } + if let Some(path) = self.llvm_ir.as_deref() { + emit(path, OutputType::LlvmAssembly); + } + if let Some(path) = self.assembly.as_deref() { + emit(path, OutputType::Assembly); + } + } +} + pub struct CachedModuleCodegen { pub name: String, pub source: WorkProduct, diff --git a/compiler/rustc_mir_transform/src/dump_mir.rs b/compiler/rustc_mir_transform/src/dump_mir.rs index 13841be494cf..3b71cf02c1a0 100644 --- a/compiler/rustc_mir_transform/src/dump_mir.rs +++ b/compiler/rustc_mir_transform/src/dump_mir.rs @@ -28,6 +28,9 @@ pub fn emit_mir(tcx: TyCtxt<'_>) -> io::Result<()> { OutFileName::Real(path) => { let mut f = io::BufWriter::new(File::create(&path)?); write_mir_pretty(tcx, None, &mut f)?; + if tcx.sess.opts.json_artifact_notifications { + tcx.dcx().emit_artifact_notification(&path, "mir"); + } } } Ok(()) diff --git a/src/doc/rustc/src/json.md b/src/doc/rustc/src/json.md index 32083b2f731d..c853f34ee036 100644 --- a/src/doc/rustc/src/json.md +++ b/src/doc/rustc/src/json.md @@ -217,7 +217,8 @@ Diagnostics have the following format: Artifact notifications are emitted when the [`--json=artifacts` flag][option-json] is used. They indicate that a file artifact has been saved to disk. More information about emit kinds may be found in the [`--emit` -flag][option-emit] documentation. +flag][option-emit] documentation. Notifications can contain more than one file +for each type, for example when using multiple codegen units. ```javascript { @@ -229,6 +230,11 @@ flag][option-emit] documentation. - "link": The generated crate as specified by the crate-type. - "dep-info": The `.d` file with dependency information in a Makefile-like syntax. - "metadata": The Rust `.rmeta` file containing metadata about the crate. + - "asm": The `.s` file with generated assembly + - "llvm-ir": The `.ll` file with generated textual LLVM IR + - "llvm-bc": The `.bc` file with generated LLVM bitcode + - "mir": The `.mir` file with rustc's mid-level intermediate representation. + - "obj": The `.o` file with generated native object code */ "emit": "link" } diff --git a/tests/run-make/notify-all-emit-artifacts/lib.rs b/tests/run-make/notify-all-emit-artifacts/lib.rs new file mode 100644 index 000000000000..6ed194204b45 --- /dev/null +++ b/tests/run-make/notify-all-emit-artifacts/lib.rs @@ -0,0 +1,21 @@ +fn one() -> usize { + 1 +} + +pub mod a { + pub fn two() -> usize { + ::one() + ::one() + } +} + +pub mod b { + pub fn three() -> usize { + ::one() + ::a::two() + } +} + +#[inline(never)] +pub fn main() { + a::two(); + b::three(); +} diff --git a/tests/run-make/notify-all-emit-artifacts/rmake.rs b/tests/run-make/notify-all-emit-artifacts/rmake.rs new file mode 100644 index 000000000000..c866d9179f94 --- /dev/null +++ b/tests/run-make/notify-all-emit-artifacts/rmake.rs @@ -0,0 +1,45 @@ +// rust should produce artifact notifications about files it was asked to --emit. +// +// It should work in incremental mode both on the first pass where files are generated as well +// as on subsequent passes where they are taken from the incremental cache +// +// See +extern crate run_make_support; + +use run_make_support::{rustc, tmp_dir}; + +fn main() { + let inc_dir = tmp_dir(); + + // With single codegen unit files are renamed to match the source file name + for _ in 0..=1 { + let output = rustc() + .input("lib.rs") + .emit("obj,asm,llvm-ir,llvm-bc,mir") + .codegen_units(1) + .json("artifacts") + .error_format("json") + .incremental(&inc_dir) + .run(); + let stderr = String::from_utf8_lossy(&output.stderr); + for file in &["lib.o", "lib.ll", "lib.bc", "lib.s"] { + assert!(stderr.contains(file), "No {:?} in {:?}", file, stderr); + } + } + + // with multiple codegen units files keep codegen unit id part. + for _ in 0..=1 { + let output = rustc() + .input("lib.rs") + .emit("obj,asm,llvm-ir,llvm-bc,mir") + .codegen_units(2) + .json("artifacts") + .error_format("json") + .incremental(&inc_dir) + .run(); + let stderr = String::from_utf8_lossy(&output.stderr); + for file in &["rcgu.o", "rcgu.ll", "rcgu.bc", "rcgu.s"] { + assert!(stderr.contains(file), "No {:?} in {:?}", file, stderr); + } + } +} From 3b2436c1361e03d52b4d5d9a188ea94909bd245a Mon Sep 17 00:00:00 2001 From: Trevor Spiteri Date: Tue, 23 Apr 2024 15:49:00 +0200 Subject: [PATCH 004/211] unroll first iter of checked_ilog loop to save one multiplication --- library/core/src/num/uint_macros.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index c13763243f03..a76b84e7e541 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1093,9 +1093,12 @@ macro_rules! uint_impl { pub const fn checked_ilog(self, base: Self) -> Option { if self <= 0 || base <= 1 { None + } else if self < base { + Some(0) } else { - let mut n = 0; - let mut r = 1; + // Since base >= self, n >= 1 + let mut n = 1; + let mut r = base; // Optimization for 128 bit wide integers. if Self::BITS == 128 { From 245cc23a2f7d55c22437b2482f057fa44cce0624 Mon Sep 17 00:00:00 2001 From: Trevor Spiteri Date: Tue, 23 Apr 2024 18:31:57 +0200 Subject: [PATCH 005/211] add codegen test The test confirms that when val < base, we do not divide or multiply. --- tests/codegen/checked_ilog.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 tests/codegen/checked_ilog.rs diff --git a/tests/codegen/checked_ilog.rs b/tests/codegen/checked_ilog.rs new file mode 100644 index 000000000000..8f3c07119fee --- /dev/null +++ b/tests/codegen/checked_ilog.rs @@ -0,0 +1,20 @@ +//@ compile-flags: -O + +#![crate_type = "lib"] + +// Ensure that when val < base, we do not divide or multiply. + +// CHECK-LABEL: @checked_ilog +// CHECK-SAME: (i16 noundef %val, i16 noundef %base) +#[no_mangle] +pub fn checked_ilog(val: u16, base: u16) -> Option { + // CHECK-NOT: udiv + // CHECK-NOT: mul + // CHECK: %[[IS_LESS:.+]] = icmp ult i16 %val, %base + // CHECK-NEXT: br i1 %[[IS_LESS]], label %[[TRUE:.+]], label %[[FALSE:.+]] + // CHECK: [[TRUE]]: + // CHECK-NOT: udiv + // CHECK-NOT: mul + // CHECK: ret { i32, i32 } + val.checked_ilog(base) +} From fc1e52a1078b7cf983ddf1b1d84c871f26dcb9de Mon Sep 17 00:00:00 2001 From: beetrees Date: Sun, 28 Apr 2024 19:22:51 +0100 Subject: [PATCH 006/211] Add tracking issue and unstable book page for `"vectorcall"` ABI --- compiler/rustc_feature/src/unstable.rs | 4 ++-- .../src/language-features/abi-vectorcall.md | 19 +++++++++++++++++++ .../feature-gate-vectorcall.stderr | 7 +++++++ 3 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 src/doc/unstable-book/src/language-features/abi-vectorcall.md diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 132e2ddee295..ac6b08a40981 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -177,8 +177,6 @@ declare_features! ( /// Allows using the `unadjusted` ABI; perma-unstable. (internal, abi_unadjusted, "1.16.0", None), - /// Allows using the `vectorcall` ABI. - (unstable, abi_vectorcall, "1.7.0", None), /// Allows using `#![needs_allocator]`, an implementation detail of `#[global_allocator]`. (internal, allocator_internals, "1.20.0", None), /// Allows using `#[allow_internal_unsafe]`. This is an @@ -243,6 +241,8 @@ declare_features! ( // feature-group-start: internal feature gates // ------------------------------------------------------------------------- + /// Allows using the `vectorcall` ABI. + (unstable, abi_vectorcall, "1.7.0", Some(124485)), /// Allows features specific to auto traits. /// Renamed from `optin_builtin_traits`. (unstable, auto_traits, "1.50.0", Some(13231)), diff --git a/src/doc/unstable-book/src/language-features/abi-vectorcall.md b/src/doc/unstable-book/src/language-features/abi-vectorcall.md new file mode 100644 index 000000000000..56273bfdb791 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/abi-vectorcall.md @@ -0,0 +1,19 @@ +# `abi_vectorcall` + +The tracking issue for this feature is: [#124485] + +[#124485]: https://github.com/rust-lang/rust/issues/124485 + +------------------------ + +Adds support for the Windows `"vectorcall"` ABI, the equivalent of `__vectorcall` in MSVC. + +```rust,ignore (only-windows-or-x86-or-x86-64) +extern "vectorcall" { + fn add_f64s(x: f64, y: f64) -> f64; +} + +fn main() { + println!("{}", add_f64s(2.0, 4.0)); +} +``` diff --git a/tests/ui/feature-gates/feature-gate-vectorcall.stderr b/tests/ui/feature-gates/feature-gate-vectorcall.stderr index df93e8812c1e..b20e41887b9b 100644 --- a/tests/ui/feature-gates/feature-gate-vectorcall.stderr +++ b/tests/ui/feature-gates/feature-gate-vectorcall.stderr @@ -4,6 +4,7 @@ error[E0658]: vectorcall is experimental and subject to change LL | extern "vectorcall" fn f() {} | ^^^^^^^^^^^^ | + = note: see issue #124485 for more information = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date @@ -13,6 +14,7 @@ error[E0658]: vectorcall is experimental and subject to change LL | extern "vectorcall" fn m(); | ^^^^^^^^^^^^ | + = note: see issue #124485 for more information = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date @@ -22,6 +24,7 @@ error[E0658]: vectorcall is experimental and subject to change LL | extern "vectorcall" fn dm() {} | ^^^^^^^^^^^^ | + = note: see issue #124485 for more information = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date @@ -31,6 +34,7 @@ error[E0658]: vectorcall is experimental and subject to change LL | extern "vectorcall" fn m() {} | ^^^^^^^^^^^^ | + = note: see issue #124485 for more information = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date @@ -40,6 +44,7 @@ error[E0658]: vectorcall is experimental and subject to change LL | extern "vectorcall" fn im() {} | ^^^^^^^^^^^^ | + = note: see issue #124485 for more information = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date @@ -49,6 +54,7 @@ error[E0658]: vectorcall is experimental and subject to change LL | type TA = extern "vectorcall" fn(); | ^^^^^^^^^^^^ | + = note: see issue #124485 for more information = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date @@ -58,6 +64,7 @@ error[E0658]: vectorcall is experimental and subject to change LL | extern "vectorcall" {} | ^^^^^^^^^^^^ | + = note: see issue #124485 for more information = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date From 2f6abd190da3dba44058253cbbfdb900906ef1b6 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 1 May 2024 15:24:32 +0200 Subject: [PATCH 007/211] Stabilize `custom_code_classes_in_docs` feature --- compiler/rustc_feature/src/accepted.rs | 2 + compiler/rustc_feature/src/unstable.rs | 2 - src/doc/rustdoc/src/unstable-features.md | 44 ------ .../documentation-tests.md | 38 ++++++ src/librustdoc/doctest.rs | 1 - src/librustdoc/externalfiles.rs | 4 - src/librustdoc/html/markdown.rs | 125 +++--------------- src/librustdoc/html/markdown/tests.rs | 7 +- src/librustdoc/html/render/mod.rs | 5 - src/librustdoc/markdown.rs | 13 +- .../passes/calculate_doc_coverage.rs | 9 +- .../passes/check_custom_code_classes.rs | 93 ------------- .../passes/check_doc_test_visibility.rs | 9 +- .../passes/lint/check_code_block_syntax.rs | 4 +- src/librustdoc/passes/mod.rs | 5 - .../custom_code_classes_in_docs-warning.rs | 83 ------------ ...custom_code_classes_in_docs-warning.stderr | 97 -------------- .../custom_code_classes_in_docs-warning3.rs | 1 - ...ustom_code_classes_in_docs-warning3.stderr | 6 +- ...eature-gate-custom_code_classes_in_docs.rs | 16 --- ...re-gate-custom_code_classes_in_docs.stderr | 15 --- tests/rustdoc-ui/issues/issue-91713.stdout | 2 - tests/rustdoc/custom_code_classes.rs | 1 - 23 files changed, 67 insertions(+), 515 deletions(-) delete mode 100644 src/librustdoc/passes/check_custom_code_classes.rs delete mode 100644 tests/rustdoc-ui/custom_code_classes_in_docs-warning.rs delete mode 100644 tests/rustdoc-ui/custom_code_classes_in_docs-warning.stderr delete mode 100644 tests/rustdoc-ui/feature-gate-custom_code_classes_in_docs.rs delete mode 100644 tests/rustdoc-ui/feature-gate-custom_code_classes_in_docs.stderr diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index de2bd60ffad8..dfa8b9bb1f49 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -138,6 +138,8 @@ declare_features! ( (accepted, copy_closures, "1.26.0", Some(44490)), /// Allows `crate` in paths. (accepted, crate_in_paths, "1.30.0", Some(45477)), + /// Allows users to provide classes for fenced code block using `class:classname`. + (accepted, custom_code_classes_in_docs, "CURRENT_RUSTC_VERSION", Some(79483)), /// Allows using `#[debugger_visualizer]` attribute. (accepted, debugger_visualizer, "1.71.0", Some(95939)), /// Allows rustc to inject a default alloc_error_handler diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 132e2ddee295..b41eedd17a0a 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -424,8 +424,6 @@ declare_features! ( /// Allows function attribute `#[coverage(on/off)]`, to control coverage /// instrumentation of that function. (unstable, coverage_attribute, "1.74.0", Some(84605)), - /// Allows users to provide classes for fenced code block using `class:classname`. - (unstable, custom_code_classes_in_docs, "1.74.0", Some(79483)), /// Allows non-builtin attributes in inner attribute position. (unstable, custom_inner_attributes, "1.30.0", Some(54726)), /// Allows custom test frameworks with `#![test_runner]` and `#[test_case]`. diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index bdb55de8d634..39f24a13143c 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -624,47 +624,3 @@ add the `--scrape-tests` flag. This flag enables the generation of links in the source code pages which allow the reader to jump to a type definition. - -### Custom CSS classes for code blocks - -```rust -#![feature(custom_code_classes_in_docs)] - -/// ```custom,{class=language-c} -/// int main(void) { return 0; } -/// ``` -pub struct Bar; -``` - -The text `int main(void) { return 0; }` is rendered without highlighting in a code block -with the class `language-c`. This can be used to highlight other languages through JavaScript -libraries for example. - -Without the `custom` attribute, it would be generated as a Rust code example with an additional -`language-C` CSS class. Therefore, if you specifically don't want it to be a Rust code example, -don't forget to add the `custom` attribute. - -To be noted that you can replace `class=` with `.` to achieve the same result: - -```rust -#![feature(custom_code_classes_in_docs)] - -/// ```custom,{.language-c} -/// int main(void) { return 0; } -/// ``` -pub struct Bar; -``` - -To be noted, `rust` and `.rust`/`class=rust` have different effects: `rust` indicates that this is -a Rust code block whereas the two others add a "rust" CSS class on the code block. - -You can also use double quotes: - -```rust -#![feature(custom_code_classes_in_docs)] - -/// ```"not rust" {."hello everyone"} -/// int main(void) { return 0; } -/// ``` -pub struct Bar; -``` diff --git a/src/doc/rustdoc/src/write-documentation/documentation-tests.md b/src/doc/rustdoc/src/write-documentation/documentation-tests.md index a7d3186fb78b..9526f33359e4 100644 --- a/src/doc/rustdoc/src/write-documentation/documentation-tests.md +++ b/src/doc/rustdoc/src/write-documentation/documentation-tests.md @@ -376,6 +376,44 @@ that the code sample should be compiled using the respective edition of Rust. # fn foo() {} ``` +### Custom CSS classes for code blocks + +```rust +/// ```custom,{class=language-c} +/// int main(void) { return 0; } +/// ``` +pub struct Bar; +``` + +The text `int main(void) { return 0; }` is rendered without highlighting in a code block +with the class `language-c`. This can be used to highlight other languages through JavaScript +libraries for example. + +Without the `custom` attribute, it would be generated as a Rust code example with an additional +`language-C` CSS class. Therefore, if you specifically don't want it to be a Rust code example, +don't forget to add the `custom` attribute. + +To be noted that you can replace `class=` with `.` to achieve the same result: + +```rust +/// ```custom,{.language-c} +/// int main(void) { return 0; } +/// ``` +pub struct Bar; +``` + +To be noted, `rust` and `.rust`/`class=rust` have different effects: `rust` indicates that this is +a Rust code block whereas the two others add a "rust" CSS class on the code block. + +You can also use double quotes: + +```rust +/// ```"not rust" {."hello everyone"} +/// int main(void) { return 0; } +/// ``` +pub struct Bar; +``` + ## Syntax reference The *exact* syntax for code blocks, including the edge cases, can be found diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 0ad4c9c23464..ca356db0e540 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -1345,7 +1345,6 @@ impl<'a, 'hir, 'tcx> HirCollector<'a, 'hir, 'tcx> { def_id.to_def_id(), span_of_fragments(&attrs.doc_strings).unwrap_or(sp), )), - self.tcx.features().custom_code_classes_in_docs, ); } diff --git a/src/librustdoc/externalfiles.rs b/src/librustdoc/externalfiles.rs index 57e82b877bf1..f82c77cc9b84 100644 --- a/src/librustdoc/externalfiles.rs +++ b/src/librustdoc/externalfiles.rs @@ -46,8 +46,6 @@ impl ExternalHtml { edition, playground, heading_offset: HeadingOffset::H2, - // For external files, it'll be disabled until the feature is enabled by default. - custom_code_classes_in_docs: false, } .into_string() ); @@ -63,8 +61,6 @@ impl ExternalHtml { edition, playground, heading_offset: HeadingOffset::H2, - // For external files, it'll be disabled until the feature is enabled by default. - custom_code_classes_in_docs: false, } .into_string() ); diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 5c5651f3ef0e..0e38ed79a871 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -20,7 +20,6 @@ //! edition: Edition::Edition2015, //! playground: &None, //! heading_offset: HeadingOffset::H2, -//! custom_code_classes_in_docs: true, //! }; //! let html = md.into_string(); //! // ... something using html @@ -97,8 +96,6 @@ pub struct Markdown<'a> { /// Offset at which we render headings. /// E.g. if `heading_offset: HeadingOffset::H2`, then `# something` renders an `

`. pub heading_offset: HeadingOffset, - /// `true` if the `custom_code_classes_in_docs` feature is enabled. - pub custom_code_classes_in_docs: bool, } /// A struct like `Markdown` that renders the markdown with a table of contents. pub(crate) struct MarkdownWithToc<'a> { @@ -107,8 +104,6 @@ pub(crate) struct MarkdownWithToc<'a> { pub(crate) error_codes: ErrorCodes, pub(crate) edition: Edition, pub(crate) playground: &'a Option, - /// `true` if the `custom_code_classes_in_docs` feature is enabled. - pub(crate) custom_code_classes_in_docs: bool, } /// A tuple struct like `Markdown` that renders the markdown escaping HTML tags /// and includes no paragraph tags. @@ -209,7 +204,6 @@ struct CodeBlocks<'p, 'a, I: Iterator>> { // Information about the playground if a URL has been specified, containing an // optional crate name and the URL. playground: &'p Option, - custom_code_classes_in_docs: bool, } impl<'p, 'a, I: Iterator>> CodeBlocks<'p, 'a, I> { @@ -218,15 +212,8 @@ impl<'p, 'a, I: Iterator>> CodeBlocks<'p, 'a, I> { error_codes: ErrorCodes, edition: Edition, playground: &'p Option, - custom_code_classes_in_docs: bool, ) -> Self { - CodeBlocks { - inner: iter, - check_error_codes: error_codes, - edition, - playground, - custom_code_classes_in_docs, - } + CodeBlocks { inner: iter, check_error_codes: error_codes, edition, playground } } } @@ -253,12 +240,8 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'_, 'a, I> { let LangString { added_classes, compile_fail, should_panic, ignore, edition, .. } = match kind { CodeBlockKind::Fenced(ref lang) => { - let parse_result = LangString::parse_without_check( - lang, - self.check_error_codes, - false, - self.custom_code_classes_in_docs, - ); + let parse_result = + LangString::parse_without_check(lang, self.check_error_codes, false); if !parse_result.rust { let added_classes = parse_result.added_classes; let lang_string = if let Some(lang) = parse_result.unknown.first() { @@ -733,17 +716,8 @@ pub(crate) fn find_testable_code( error_codes: ErrorCodes, enable_per_target_ignores: bool, extra_info: Option<&ExtraInfo<'_>>, - custom_code_classes_in_docs: bool, ) { - find_codes( - doc, - tests, - error_codes, - enable_per_target_ignores, - extra_info, - false, - custom_code_classes_in_docs, - ) + find_codes(doc, tests, error_codes, enable_per_target_ignores, extra_info, false) } pub(crate) fn find_codes( @@ -753,7 +727,6 @@ pub(crate) fn find_codes( enable_per_target_ignores: bool, extra_info: Option<&ExtraInfo<'_>>, include_non_rust: bool, - custom_code_classes_in_docs: bool, ) { let mut parser = Parser::new(doc).into_offset_iter(); let mut prev_offset = 0; @@ -772,7 +745,6 @@ pub(crate) fn find_codes( error_codes, enable_per_target_ignores, extra_info, - custom_code_classes_in_docs, ) } } @@ -1167,29 +1139,6 @@ impl<'a, 'tcx> Iterator for TagIterator<'a, 'tcx> { } } -fn tokens(string: &str) -> impl Iterator> { - // Pandoc, which Rust once used for generating documentation, - // expects lang strings to be surrounded by `{}` and for each token - // to be proceeded by a `.`. Since some of these lang strings are still - // loose in the wild, we strip a pair of surrounding `{}` from the lang - // string and a leading `.` from each token. - - let string = string.trim(); - - let first = string.chars().next(); - let last = string.chars().last(); - - let string = - if first == Some('{') && last == Some('}') { &string[1..string.len() - 1] } else { string }; - - string - .split(|c| c == ',' || c == ' ' || c == '\t') - .map(str::trim) - .map(|token| token.strip_prefix('.').unwrap_or(token)) - .filter(|token| !token.is_empty()) - .map(|token| LangStringToken::LangToken(token)) -} - impl Default for LangString { fn default() -> Self { Self { @@ -1213,15 +1162,8 @@ impl LangString { string: &str, allow_error_code_check: ErrorCodes, enable_per_target_ignores: bool, - custom_code_classes_in_docs: bool, ) -> Self { - Self::parse( - string, - allow_error_code_check, - enable_per_target_ignores, - None, - custom_code_classes_in_docs, - ) + Self::parse(string, allow_error_code_check, enable_per_target_ignores, None) } fn parse( @@ -1229,7 +1171,6 @@ impl LangString { allow_error_code_check: ErrorCodes, enable_per_target_ignores: bool, extra: Option<&ExtraInfo<'_>>, - custom_code_classes_in_docs: bool, ) -> Self { let allow_error_code_check = allow_error_code_check.as_bool(); let mut seen_rust_tags = false; @@ -1266,11 +1207,7 @@ impl LangString { seen_rust_tags = true; } LangStringToken::LangToken("custom") => { - if custom_code_classes_in_docs { - seen_custom_tag = true; - } else { - seen_other_tags = true; - } + seen_custom_tag = true; } LangStringToken::LangToken("test_harness") => { data.test_harness = true; @@ -1361,16 +1298,12 @@ impl LangString { data.unknown.push(x.to_owned()); } LangStringToken::KeyValueAttribute(key, value) => { - if custom_code_classes_in_docs { - if key == "class" { - data.added_classes.push(value.to_owned()); - } else if let Some(extra) = extra { - extra.error_invalid_codeblock_attr(format!( - "unsupported attribute `{key}`" - )); - } - } else { - seen_other_tags = true; + if key == "class" { + data.added_classes.push(value.to_owned()); + } else if let Some(extra) = extra { + extra.error_invalid_codeblock_attr(format!( + "unsupported attribute `{key}`" + )); } } LangStringToken::ClassAttribute(class) => { @@ -1380,11 +1313,7 @@ impl LangString { } }; - if custom_code_classes_in_docs { - call(&mut TagIterator::new(string, extra)) - } else { - call(&mut tokens(string)) - } + call(&mut TagIterator::new(string, extra)); // ignore-foo overrides ignore if !ignores.is_empty() { @@ -1407,7 +1336,6 @@ impl Markdown<'_> { edition, playground, heading_offset, - custom_code_classes_in_docs, } = self; // This is actually common enough to special-case @@ -1430,7 +1358,7 @@ impl Markdown<'_> { let p = Footnotes::new(p); let p = LinkReplacer::new(p.map(|(ev, _)| ev), links); let p = TableWrapper::new(p); - let p = CodeBlocks::new(p, codes, edition, playground, custom_code_classes_in_docs); + let p = CodeBlocks::new(p, codes, edition, playground); html::push_html(&mut s, p); s @@ -1439,14 +1367,7 @@ impl Markdown<'_> { impl MarkdownWithToc<'_> { pub(crate) fn into_string(self) -> String { - let MarkdownWithToc { - content: md, - ids, - error_codes: codes, - edition, - playground, - custom_code_classes_in_docs, - } = self; + let MarkdownWithToc { content: md, ids, error_codes: codes, edition, playground } = self; let p = Parser::new_ext(md, main_body_opts()).into_offset_iter(); @@ -1458,7 +1379,7 @@ impl MarkdownWithToc<'_> { let p = HeadingLinks::new(p, Some(&mut toc), ids, HeadingOffset::H1); let p = Footnotes::new(p); let p = TableWrapper::new(p.map(|(ev, _)| ev)); - let p = CodeBlocks::new(p, codes, edition, playground, custom_code_classes_in_docs); + let p = CodeBlocks::new(p, codes, edition, playground); html::push_html(&mut s, p); } @@ -1899,11 +1820,7 @@ pub(crate) struct RustCodeBlock { /// Returns a range of bytes for each code block in the markdown that is tagged as `rust` or /// untagged (and assumed to be rust). -pub(crate) fn rust_code_blocks( - md: &str, - extra_info: &ExtraInfo<'_>, - custom_code_classes_in_docs: bool, -) -> Vec { +pub(crate) fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_>) -> Vec { let mut code_blocks = vec![]; if md.is_empty() { @@ -1920,13 +1837,7 @@ pub(crate) fn rust_code_blocks( let lang_string = if syntax.is_empty() { Default::default() } else { - LangString::parse( - &*syntax, - ErrorCodes::Yes, - false, - Some(extra_info), - custom_code_classes_in_docs, - ) + LangString::parse(&*syntax, ErrorCodes::Yes, false, Some(extra_info)) }; if !lang_string.rust { continue; diff --git a/src/librustdoc/html/markdown/tests.rs b/src/librustdoc/html/markdown/tests.rs index 1de97e49b830..fb74c079c9a4 100644 --- a/src/librustdoc/html/markdown/tests.rs +++ b/src/librustdoc/html/markdown/tests.rs @@ -49,7 +49,7 @@ fn test_unique_id() { fn test_lang_string_parse() { fn t(lg: LangString) { let s = &lg.original; - assert_eq!(LangString::parse(s, ErrorCodes::Yes, true, None, true), lg) + assert_eq!(LangString::parse(s, ErrorCodes::Yes, true, None), lg) } t(Default::default()); @@ -305,7 +305,6 @@ fn test_header() { edition: DEFAULT_EDITION, playground: &None, heading_offset: HeadingOffset::H2, - custom_code_classes_in_docs: true, } .into_string(); assert_eq!(output, expect, "original: {}", input); @@ -357,7 +356,6 @@ fn test_header_ids_multiple_blocks() { edition: DEFAULT_EDITION, playground: &None, heading_offset: HeadingOffset::H2, - custom_code_classes_in_docs: true, } .into_string(); assert_eq!(output, expect, "original: {}", input); @@ -481,7 +479,7 @@ fn test_markdown_html_escape() { fn test_find_testable_code_line() { fn t(input: &str, expect: &[usize]) { let mut lines = Vec::::new(); - find_testable_code(input, &mut lines, ErrorCodes::No, false, None, true); + find_testable_code(input, &mut lines, ErrorCodes::No, false, None); assert_eq!(lines, expect); } @@ -506,7 +504,6 @@ fn test_ascii_with_prepending_hashtag() { edition: DEFAULT_EDITION, playground: &None, heading_offset: HeadingOffset::H2, - custom_code_classes_in_docs: true, } .into_string(); assert_eq!(output, expect, "original: {}", input); diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 09a53affb14c..716b6b2390a8 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -504,7 +504,6 @@ fn scrape_examples_help(shared: &SharedContext<'_>) -> String { edition: shared.edition(), playground: &shared.playground, heading_offset: HeadingOffset::H1, - custom_code_classes_in_docs: false, } .into_string() ) @@ -538,7 +537,6 @@ fn render_markdown<'a, 'cx: 'a>( heading_offset: HeadingOffset, ) -> impl fmt::Display + 'a + Captures<'cx> { display_fn(move |f| { - let custom_code_classes_in_docs = cx.tcx().features().custom_code_classes_in_docs; write!( f, "
{}
", @@ -550,7 +548,6 @@ fn render_markdown<'a, 'cx: 'a>( edition: cx.shared.edition(), playground: &cx.shared.playground, heading_offset, - custom_code_classes_in_docs, } .into_string() ) @@ -1868,7 +1865,6 @@ fn render_impl( ", ); } - let custom_code_classes_in_docs = cx.tcx().features().custom_code_classes_in_docs; write!( w, "
{}
", @@ -1880,7 +1876,6 @@ fn render_impl( edition: cx.shared.edition(), playground: &cx.shared.playground, heading_offset: HeadingOffset::H4, - custom_code_classes_in_docs, } .into_string() ); diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index dcd2cf02a30a..86b319811969 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -82,8 +82,6 @@ pub(crate) fn render>( error_codes, edition, playground: &playground, - // For markdown files, it'll be disabled until the feature is enabled by default. - custom_code_classes_in_docs: false, } .into_string() } else { @@ -95,8 +93,6 @@ pub(crate) fn render>( edition, playground: &playground, heading_offset: HeadingOffset::H1, - // For markdown files, it'll be disabled until the feature is enabled by default. - custom_code_classes_in_docs: false, } .into_string() }; @@ -168,14 +164,7 @@ pub(crate) fn test(options: Options) -> Result<(), String> { let codes = ErrorCodes::from(options.unstable_features.is_nightly_build()); // For markdown files, custom code classes will be disabled until the feature is enabled by default. - find_testable_code( - &input_str, - &mut collector, - codes, - options.enable_per_target_ignores, - None, - false, - ); + find_testable_code(&input_str, &mut collector, codes, options.enable_per_target_ignores, None); crate::doctest::run_tests(options.test_args, options.nocapture, collector.tests); Ok(()) diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index 60def40588aa..592dd0a145cf 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -208,14 +208,7 @@ impl<'a, 'b> DocVisitor for CoverageCalculator<'a, 'b> { let has_docs = !i.attrs.doc_strings.is_empty(); let mut tests = Tests { found_tests: 0 }; - find_testable_code( - &i.doc_value(), - &mut tests, - ErrorCodes::No, - false, - None, - self.ctx.tcx.features().custom_code_classes_in_docs, - ); + find_testable_code(&i.doc_value(), &mut tests, ErrorCodes::No, false, None); let has_doc_example = tests.found_tests != 0; let hir_id = DocContext::as_local_hir_id(self.ctx.tcx, i.item_id).unwrap(); diff --git a/src/librustdoc/passes/check_custom_code_classes.rs b/src/librustdoc/passes/check_custom_code_classes.rs deleted file mode 100644 index 524795ed77c2..000000000000 --- a/src/librustdoc/passes/check_custom_code_classes.rs +++ /dev/null @@ -1,93 +0,0 @@ -//! NIGHTLY & UNSTABLE CHECK: custom_code_classes_in_docs -//! -//! This pass will produce errors when finding custom classes outside of -//! nightly + relevant feature active. - -use super::Pass; -use crate::clean::{Crate, Item}; -use crate::core::DocContext; -use crate::fold::DocFolder; -use crate::html::markdown::{find_codes, ErrorCodes, LangString}; - -use rustc_errors::StashKey; -use rustc_feature::GateIssue; -use rustc_session::parse::add_feature_diagnostics_for_issue; -use rustc_span::symbol::sym; - -pub(crate) const CHECK_CUSTOM_CODE_CLASSES: Pass = Pass { - name: "check-custom-code-classes", - run: check_custom_code_classes, - description: "check for custom code classes without the feature-gate enabled", -}; - -pub(crate) fn check_custom_code_classes(krate: Crate, cx: &mut DocContext<'_>) -> Crate { - if cx.tcx.features().custom_code_classes_in_docs { - // Nothing to check here if the feature is enabled. - return krate; - } - let mut coll = CustomCodeClassLinter { cx }; - - coll.fold_crate(krate) -} - -struct CustomCodeClassLinter<'a, 'tcx> { - cx: &'a DocContext<'tcx>, -} - -impl<'a, 'tcx> DocFolder for CustomCodeClassLinter<'a, 'tcx> { - fn fold_item(&mut self, item: Item) -> Option { - look_for_custom_classes(&self.cx, &item); - Some(self.fold_item_recur(item)) - } -} - -#[derive(Debug)] -struct TestsWithCustomClasses { - custom_classes_found: Vec, -} - -impl crate::doctest::Tester for TestsWithCustomClasses { - fn add_test(&mut self, _: String, config: LangString, _: usize) { - self.custom_classes_found.extend(config.added_classes); - } -} - -pub(crate) fn look_for_custom_classes<'tcx>(cx: &DocContext<'tcx>, item: &Item) { - if !item.item_id.is_local() { - // If non-local, no need to check anything. - return; - } - - let mut tests = TestsWithCustomClasses { custom_classes_found: vec![] }; - - let dox = item.attrs.doc_value(); - find_codes(&dox, &mut tests, ErrorCodes::No, false, None, true, true); - - if !tests.custom_classes_found.is_empty() { - let span = item.attr_span(cx.tcx); - let sess = &cx.tcx.sess; - let mut err = sess - .dcx() - .struct_span_warn(span, "custom classes in code blocks will change behaviour"); - add_feature_diagnostics_for_issue( - &mut err, - sess, - sym::custom_code_classes_in_docs, - GateIssue::Language, - false, - None, - ); - - err.note( - // This will list the wrong items to make them more easily searchable. - // To ensure the most correct hits, it adds back the 'class:' that was stripped. - format!( - "found these custom classes: class={}", - tests.custom_classes_found.join(",class=") - ), - ); - - // A later feature_err call can steal and cancel this warning. - err.stash(span, StashKey::EarlySyntaxWarning); - } -} diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs index e85b998bfbe1..8055c8a96e35 100644 --- a/src/librustdoc/passes/check_doc_test_visibility.rs +++ b/src/librustdoc/passes/check_doc_test_visibility.rs @@ -112,14 +112,7 @@ pub(crate) fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item let mut tests = Tests { found_tests: 0 }; - find_testable_code( - dox, - &mut tests, - ErrorCodes::No, - false, - None, - cx.tcx.features().custom_code_classes_in_docs, - ); + find_testable_code(dox, &mut tests, ErrorCodes::No, false, None); if tests.found_tests == 0 && cx.tcx.features().rustdoc_missing_doc_code_examples { if should_have_doc_example(cx, item) { diff --git a/src/librustdoc/passes/lint/check_code_block_syntax.rs b/src/librustdoc/passes/lint/check_code_block_syntax.rs index 7b81b5e63be6..7a09baa4ad7f 100644 --- a/src/librustdoc/passes/lint/check_code_block_syntax.rs +++ b/src/librustdoc/passes/lint/check_code_block_syntax.rs @@ -20,9 +20,7 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &clean::Item) { if let Some(dox) = &item.opt_doc_value() { let sp = item.attr_span(cx.tcx); let extra = crate::html::markdown::ExtraInfo::new(cx.tcx, item.item_id.expect_def_id(), sp); - for code_block in - markdown::rust_code_blocks(dox, &extra, cx.tcx.features().custom_code_classes_in_docs) - { + for code_block in markdown::rust_code_blocks(dox, &extra) { check_rust_syntax(cx, item, dox, code_block); } } diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs index 4eeaaa2bb70a..bb678e338888 100644 --- a/src/librustdoc/passes/mod.rs +++ b/src/librustdoc/passes/mod.rs @@ -35,9 +35,6 @@ pub(crate) use self::calculate_doc_coverage::CALCULATE_DOC_COVERAGE; mod lint; pub(crate) use self::lint::RUN_LINTS; -mod check_custom_code_classes; -pub(crate) use self::check_custom_code_classes::CHECK_CUSTOM_CODE_CLASSES; - /// A single pass over the cleaned documentation. /// /// Runs in the compiler context, so it has access to types and traits and the like. @@ -69,7 +66,6 @@ pub(crate) enum Condition { /// The full list of passes. pub(crate) const PASSES: &[Pass] = &[ - CHECK_CUSTOM_CODE_CLASSES, CHECK_DOC_TEST_VISIBILITY, STRIP_HIDDEN, STRIP_PRIVATE, @@ -83,7 +79,6 @@ pub(crate) const PASSES: &[Pass] = &[ /// The list of passes run by default. pub(crate) const DEFAULT_PASSES: &[ConditionalPass] = &[ - ConditionalPass::always(CHECK_CUSTOM_CODE_CLASSES), ConditionalPass::always(COLLECT_TRAIT_IMPLS), ConditionalPass::always(CHECK_DOC_TEST_VISIBILITY), ConditionalPass::new(STRIP_HIDDEN, WhenNotDocumentHidden), diff --git a/tests/rustdoc-ui/custom_code_classes_in_docs-warning.rs b/tests/rustdoc-ui/custom_code_classes_in_docs-warning.rs deleted file mode 100644 index 5398d5833c75..000000000000 --- a/tests/rustdoc-ui/custom_code_classes_in_docs-warning.rs +++ /dev/null @@ -1,83 +0,0 @@ -// This test ensures that warnings are working as expected for "custom_code_classes_in_docs" -// feature. - -#![feature(custom_code_classes_in_docs)] -#![deny(warnings)] -#![feature(no_core)] -#![no_core] - -/// ```{. } -/// main; -/// ``` -//~^^^ ERROR unexpected ` ` character after `.` -pub fn foo() {} - -/// ```{class= a} -/// main; -/// ``` -//~^^^ ERROR unexpected ` ` character after `=` -pub fn foo2() {} - -/// ```{#id} -/// main; -/// ``` -//~^^^ ERROR unexpected character `#` -pub fn foo3() {} - -/// ```{{ -/// main; -/// ``` -//~^^^ ERROR unexpected character `{` -pub fn foo4() {} - -/// ```} -/// main; -/// ``` -//~^^^ ERROR unexpected character `}` -pub fn foo5() {} - -/// ```) -/// main; -/// ``` -//~^^^ ERROR unexpected character `)` -pub fn foo6() {} - -/// ```{class=} -/// main; -/// ``` -//~^^^ ERROR unexpected `}` character after `=` -pub fn foo7() {} - -/// ```( -/// main; -/// ``` -//~^^^ ERROR unclosed comment: missing `)` at the end -pub fn foo8() {} - -/// ```{class=one=two} -/// main; -/// ``` -//~^^^ ERROR unexpected `=` character -pub fn foo9() {} - -/// ```{.one.two} -/// main; -/// ``` -pub fn foo10() {} - -/// ```{class=(one} -/// main; -/// ``` -//~^^^ ERROR unexpected `(` character after `=` -pub fn foo11() {} - -/// ```{class=one.two} -/// main; -/// ``` -pub fn foo12() {} - -/// ```{(comment)} -/// main; -/// ``` -//~^^^ ERROR unexpected character `(` -pub fn foo13() {} diff --git a/tests/rustdoc-ui/custom_code_classes_in_docs-warning.stderr b/tests/rustdoc-ui/custom_code_classes_in_docs-warning.stderr deleted file mode 100644 index 14b4b3bab3fa..000000000000 --- a/tests/rustdoc-ui/custom_code_classes_in_docs-warning.stderr +++ /dev/null @@ -1,97 +0,0 @@ -error: unexpected ` ` character after `.` - --> $DIR/custom_code_classes_in_docs-warning.rs:9:1 - | -LL | / /// ```{. } -LL | | /// main; -LL | | /// ``` - | |_______^ - | -note: the lint level is defined here - --> $DIR/custom_code_classes_in_docs-warning.rs:5:9 - | -LL | #![deny(warnings)] - | ^^^^^^^^ - = note: `#[deny(rustdoc::invalid_codeblock_attributes)]` implied by `#[deny(warnings)]` - -error: unexpected ` ` character after `=` - --> $DIR/custom_code_classes_in_docs-warning.rs:15:1 - | -LL | / /// ```{class= a} -LL | | /// main; -LL | | /// ``` - | |_______^ - -error: unexpected character `#` - --> $DIR/custom_code_classes_in_docs-warning.rs:21:1 - | -LL | / /// ```{#id} -LL | | /// main; -LL | | /// ``` - | |_______^ - -error: unexpected character `{` - --> $DIR/custom_code_classes_in_docs-warning.rs:27:1 - | -LL | / /// ```{{ -LL | | /// main; -LL | | /// ``` - | |_______^ - -error: unexpected character `}` - --> $DIR/custom_code_classes_in_docs-warning.rs:33:1 - | -LL | / /// ```} -LL | | /// main; -LL | | /// ``` - | |_______^ - -error: unexpected character `)` - --> $DIR/custom_code_classes_in_docs-warning.rs:39:1 - | -LL | / /// ```) -LL | | /// main; -LL | | /// ``` - | |_______^ - -error: unexpected `}` character after `=` - --> $DIR/custom_code_classes_in_docs-warning.rs:45:1 - | -LL | / /// ```{class=} -LL | | /// main; -LL | | /// ``` - | |_______^ - -error: unclosed comment: missing `)` at the end - --> $DIR/custom_code_classes_in_docs-warning.rs:51:1 - | -LL | / /// ```( -LL | | /// main; -LL | | /// ``` - | |_______^ - -error: unexpected `=` character - --> $DIR/custom_code_classes_in_docs-warning.rs:57:1 - | -LL | / /// ```{class=one=two} -LL | | /// main; -LL | | /// ``` - | |_______^ - -error: unexpected `(` character after `=` - --> $DIR/custom_code_classes_in_docs-warning.rs:68:1 - | -LL | / /// ```{class=(one} -LL | | /// main; -LL | | /// ``` - | |_______^ - -error: unexpected character `(` - --> $DIR/custom_code_classes_in_docs-warning.rs:79:1 - | -LL | / /// ```{(comment)} -LL | | /// main; -LL | | /// ``` - | |_______^ - -error: aborting due to 11 previous errors - diff --git a/tests/rustdoc-ui/custom_code_classes_in_docs-warning3.rs b/tests/rustdoc-ui/custom_code_classes_in_docs-warning3.rs index 57d9038cb0ce..6b1aa455d981 100644 --- a/tests/rustdoc-ui/custom_code_classes_in_docs-warning3.rs +++ b/tests/rustdoc-ui/custom_code_classes_in_docs-warning3.rs @@ -1,7 +1,6 @@ // This test ensures that warnings are working as expected for "custom_code_classes_in_docs" // feature. -#![feature(custom_code_classes_in_docs)] #![deny(warnings)] #![feature(no_core)] #![no_core] diff --git a/tests/rustdoc-ui/custom_code_classes_in_docs-warning3.stderr b/tests/rustdoc-ui/custom_code_classes_in_docs-warning3.stderr index ad049804213d..fc47404734ee 100644 --- a/tests/rustdoc-ui/custom_code_classes_in_docs-warning3.stderr +++ b/tests/rustdoc-ui/custom_code_classes_in_docs-warning3.stderr @@ -1,5 +1,5 @@ error: unclosed quote string `"` - --> $DIR/custom_code_classes_in_docs-warning3.rs:9:1 + --> $DIR/custom_code_classes_in_docs-warning3.rs:8:1 | LL | / /// ```{class="} LL | | /// main; @@ -11,14 +11,14 @@ LL | | /// ``` | |_______^ | note: the lint level is defined here - --> $DIR/custom_code_classes_in_docs-warning3.rs:5:9 + --> $DIR/custom_code_classes_in_docs-warning3.rs:4:9 | LL | #![deny(warnings)] | ^^^^^^^^ = note: `#[deny(rustdoc::invalid_codeblock_attributes)]` implied by `#[deny(warnings)]` error: unclosed quote string `"` - --> $DIR/custom_code_classes_in_docs-warning3.rs:9:1 + --> $DIR/custom_code_classes_in_docs-warning3.rs:8:1 | LL | / /// ```{class="} LL | | /// main; diff --git a/tests/rustdoc-ui/feature-gate-custom_code_classes_in_docs.rs b/tests/rustdoc-ui/feature-gate-custom_code_classes_in_docs.rs deleted file mode 100644 index e96444039f4c..000000000000 --- a/tests/rustdoc-ui/feature-gate-custom_code_classes_in_docs.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ check-pass - -/// ```{class=language-c} -/// int main(void) { return 0; } -/// ``` -//~^^^ WARNING custom classes in code blocks will change behaviour -//~| NOTE found these custom classes: class=language-c -//~| NOTE see issue #79483 -//~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -//~| HELP add `#![feature(custom_code_classes_in_docs)]` to the crate attributes to enable -pub struct Bar; - -/// ```ASN.1 -/// int main(void) { return 0; } -/// ``` -pub struct Bar2; diff --git a/tests/rustdoc-ui/feature-gate-custom_code_classes_in_docs.stderr b/tests/rustdoc-ui/feature-gate-custom_code_classes_in_docs.stderr deleted file mode 100644 index 822806997c26..000000000000 --- a/tests/rustdoc-ui/feature-gate-custom_code_classes_in_docs.stderr +++ /dev/null @@ -1,15 +0,0 @@ -warning: custom classes in code blocks will change behaviour - --> $DIR/feature-gate-custom_code_classes_in_docs.rs:3:1 - | -LL | / /// ```{class=language-c} -LL | | /// int main(void) { return 0; } -LL | | /// ``` - | |_______^ - | - = note: see issue #79483 for more information - = help: add `#![feature(custom_code_classes_in_docs)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = note: found these custom classes: class=language-c - -warning: 1 warning emitted - diff --git a/tests/rustdoc-ui/issues/issue-91713.stdout b/tests/rustdoc-ui/issues/issue-91713.stdout index bbea7e5c212e..167835243631 100644 --- a/tests/rustdoc-ui/issues/issue-91713.stdout +++ b/tests/rustdoc-ui/issues/issue-91713.stdout @@ -1,5 +1,4 @@ Available passes for running rustdoc: -check-custom-code-classes - check for custom code classes without the feature-gate enabled check_doc_test_visibility - run various visibility-related lints on doctests strip-hidden - strips all `#[doc(hidden)]` items from the output strip-private - strips all private items from a crate which cannot be seen externally, implies strip-priv-imports @@ -11,7 +10,6 @@ calculate-doc-coverage - counts the number of items with and without documentati run-lints - runs some of rustdoc's lints Default passes for rustdoc: -check-custom-code-classes collect-trait-impls check_doc_test_visibility strip-hidden (when not --document-hidden-items) diff --git a/tests/rustdoc/custom_code_classes.rs b/tests/rustdoc/custom_code_classes.rs index cd20d8b7d6c9..569857a09cbe 100644 --- a/tests/rustdoc/custom_code_classes.rs +++ b/tests/rustdoc/custom_code_classes.rs @@ -1,6 +1,5 @@ // Test for `custom_code_classes_in_docs` feature. -#![feature(custom_code_classes_in_docs)] #![crate_name = "foo"] #![feature(no_core)] #![no_core] From fc2f7035c67af9ac44ac7c9186323ac903446c47 Mon Sep 17 00:00:00 2001 From: Jakob Schwarz Date: Wed, 15 May 2024 15:07:34 +0200 Subject: [PATCH 008/211] fulfill expectations in `check_unsafe_derive_deserialize` The utility function `clippy_utils::fulfill_or_allowed` is not used because using it would require to move the check for allowed after the check iterating over all inherent impls of the type, doing possibly unnecessary work. Instead, `is_lint_allowed` is called as before, but additionally, once certain that the lint should be emitted, `span_lint_hir_and_then` is called instead of `span_lint_and_help` to also fulfill expectations. fixes: #12802 changelog: fulfill expectations in `check_unsafe_derive_deserialize` --- clippy_lints/src/derive.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 42cd19fb8eca..b9dd0f638afc 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_sugg, span_lint_and_then, span_lint_hir_and_then}; use clippy_utils::ty::{implements_trait, implements_trait_with_env, is_copy}; use clippy_utils::{has_non_exhaustive_attr, is_lint_allowed, match_def_path, paths}; use rustc_errors::Applicability; @@ -390,13 +390,17 @@ fn check_unsafe_derive_deserialize<'tcx>( .map(|imp_did| cx.tcx.hir().expect_item(imp_did.expect_local())) .any(|imp| has_unsafe(cx, imp)) { - span_lint_and_help( + span_lint_hir_and_then( cx, UNSAFE_DERIVE_DESERIALIZE, + adt_hir_id, item.span, "you are deriving `serde::Deserialize` on a type that has methods using `unsafe`", - None, - "consider implementing `serde::Deserialize` manually. See https://serde.rs/impl-deserialize.html", + |diag| { + diag.help( + "consider implementing `serde::Deserialize` manually. See https://serde.rs/impl-deserialize.html", + ); + }, ); } } From 1b6c91628eb53e6ddf71ca28b43da2a7659d1056 Mon Sep 17 00:00:00 2001 From: Jakob Schwarz Date: Wed, 15 May 2024 18:21:20 +0200 Subject: [PATCH 009/211] add test for `#[expect]`ing `unsafe_derive_deserialize` Adding `#![feature(lint_reasons)]` to the top of the file also changed the line numbers in the expected error output. --- tests/ui/unsafe_derive_deserialize.rs | 11 +++++++++++ tests/ui/unsafe_derive_deserialize.stderr | 8 ++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/tests/ui/unsafe_derive_deserialize.rs b/tests/ui/unsafe_derive_deserialize.rs index 70dcaa3afa45..5187e0790423 100644 --- a/tests/ui/unsafe_derive_deserialize.rs +++ b/tests/ui/unsafe_derive_deserialize.rs @@ -1,3 +1,4 @@ +#![feature(lint_reasons)] #![warn(clippy::unsafe_derive_deserialize)] #![allow(unused, clippy::missing_safety_doc)] @@ -71,4 +72,14 @@ impl G { } } +// Check that we honor the `expect` attribute on the ADT +#[expect(clippy::unsafe_derive_deserialize)] +#[derive(Deserialize)] +pub struct H; +impl H { + pub fn unsafe_block(&self) { + unsafe {} + } +} + fn main() {} diff --git a/tests/ui/unsafe_derive_deserialize.stderr b/tests/ui/unsafe_derive_deserialize.stderr index f2d4429f707a..06719f23d57f 100644 --- a/tests/ui/unsafe_derive_deserialize.stderr +++ b/tests/ui/unsafe_derive_deserialize.stderr @@ -1,5 +1,5 @@ error: you are deriving `serde::Deserialize` on a type that has methods using `unsafe` - --> tests/ui/unsafe_derive_deserialize.rs:8:10 + --> tests/ui/unsafe_derive_deserialize.rs:9:10 | LL | #[derive(Deserialize)] | ^^^^^^^^^^^ @@ -10,7 +10,7 @@ LL | #[derive(Deserialize)] = note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info) error: you are deriving `serde::Deserialize` on a type that has methods using `unsafe` - --> tests/ui/unsafe_derive_deserialize.rs:17:10 + --> tests/ui/unsafe_derive_deserialize.rs:18:10 | LL | #[derive(Deserialize)] | ^^^^^^^^^^^ @@ -19,7 +19,7 @@ LL | #[derive(Deserialize)] = note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info) error: you are deriving `serde::Deserialize` on a type that has methods using `unsafe` - --> tests/ui/unsafe_derive_deserialize.rs:24:10 + --> tests/ui/unsafe_derive_deserialize.rs:25:10 | LL | #[derive(Deserialize)] | ^^^^^^^^^^^ @@ -28,7 +28,7 @@ LL | #[derive(Deserialize)] = note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info) error: you are deriving `serde::Deserialize` on a type that has methods using `unsafe` - --> tests/ui/unsafe_derive_deserialize.rs:33:10 + --> tests/ui/unsafe_derive_deserialize.rs:34:10 | LL | #[derive(Deserialize)] | ^^^^^^^^^^^ From 6b371469bf201a3ff83c9343423bbb8c7d6a79fa Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 15 May 2024 11:51:55 -0400 Subject: [PATCH 010/211] Fix tools --- clippy_lints/src/derive.rs | 4 ++-- clippy_utils/src/ty.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 9662c8f4fe2f..bb6d8b180a0d 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -11,7 +11,7 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; use rustc_middle::traits::Reveal; use rustc_middle::ty::{ - self, ClauseKind, GenericArgKind, GenericParamDefKind, ParamEnv, ToPredicate, TraitPredicate, Ty, TyCtxt, + self, ClauseKind, GenericArgKind, GenericParamDefKind, ParamEnv, Upcast, TraitPredicate, Ty, TyCtxt, }; use rustc_session::declare_lint_pass; use rustc_span::def_id::LocalDefId; @@ -503,7 +503,7 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) -> trait_ref: ty::TraitRef::new(tcx, eq_trait_id, [tcx.mk_param_from_def(param)]), polarity: ty::PredicatePolarity::Positive, }) - .to_predicate(tcx) + .upcast(tcx) }), )), Reveal::UserFacing, diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs index e3ab42c3107c..b604f3ff65fc 100644 --- a/clippy_utils/src/ty.rs +++ b/clippy_utils/src/ty.rs @@ -18,7 +18,7 @@ use rustc_middle::traits::EvaluationResult; use rustc_middle::ty::layout::ValidityRequirement; use rustc_middle::ty::{ self, AdtDef, AliasTy, AssocKind, Binder, BoundRegion, FnSig, GenericArg, GenericArgKind, GenericArgsRef, - GenericParamDefKind, IntTy, ParamEnv, Region, RegionKind, ToPredicate, TraitRef, Ty, TyCtxt, + GenericParamDefKind, IntTy, ParamEnv, Region, RegionKind, Upcast, TraitRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, UintTy, VariantDef, VariantDiscr, }; use rustc_span::symbol::Ident; @@ -311,7 +311,7 @@ pub fn implements_trait_with_env_from_iter<'tcx>( cause: ObligationCause::dummy(), param_env, recursion_depth: 0, - predicate: Binder::dummy(trait_ref).to_predicate(tcx), + predicate: Binder::dummy(trait_ref).upcast(tcx), }; infcx .evaluate_obligation(&obligation) From 4f589e322d20c9ba7cc7e92369faf01d2737825c Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 15 May 2024 12:52:12 -0400 Subject: [PATCH 011/211] Remove trivial Binder::dummy calls --- clippy_utils/src/ty.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs index b604f3ff65fc..50c387bd59ec 100644 --- a/clippy_utils/src/ty.rs +++ b/clippy_utils/src/ty.rs @@ -311,7 +311,7 @@ pub fn implements_trait_with_env_from_iter<'tcx>( cause: ObligationCause::dummy(), param_env, recursion_depth: 0, - predicate: Binder::dummy(trait_ref).upcast(tcx), + predicate: trait_ref.upcast(tcx), }; infcx .evaluate_obligation(&obligation) From 0590d71ce2a0dada4f8970ed024f253552902016 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 17 May 2024 14:17:48 -0300 Subject: [PATCH 012/211] Rename Unsafe to Safety --- clippy_lints/src/derive.rs | 4 ++-- clippy_lints/src/doc/missing_headers.rs | 8 ++++---- clippy_lints/src/doc/mod.rs | 6 +++--- clippy_lints/src/eta_reduction.rs | 12 +++++------- clippy_lints/src/functions/misnamed_getters.rs | 4 ++-- .../src/functions/not_unsafe_ptr_arg_deref.rs | 16 ++++++++-------- clippy_lints/src/inherent_to_string.rs | 4 ++-- clippy_lints/src/methods/mod.rs | 6 ++---- .../src/multiple_unsafe_ops_per_block.rs | 6 +++--- clippy_lints/src/new_without_default.rs | 2 +- clippy_lints/src/ptr.rs | 4 ++-- clippy_lints/src/undocumented_unsafe_blocks.rs | 4 ++-- clippy_utils/src/ast_utils.rs | 16 ++++++++-------- clippy_utils/src/check_proc_macro.rs | 11 +++++------ clippy_utils/src/hir_utils.rs | 2 +- clippy_utils/src/ty.rs | 4 ++-- clippy_utils/src/visitors.rs | 10 +++++----- 17 files changed, 57 insertions(+), 62 deletions(-) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 9662c8f4fe2f..53e0cef361aa 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -5,7 +5,7 @@ use rustc_errors::Applicability; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{walk_expr, walk_fn, walk_item, FnKind, Visitor}; use rustc_hir::{ - self as hir, BlockCheckMode, BodyId, Expr, ExprKind, FnDecl, Impl, Item, ItemKind, UnsafeSource, Unsafety, + self as hir, BlockCheckMode, BodyId, Expr, ExprKind, FnDecl, Safety, Impl, Item, ItemKind, UnsafeSource, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; @@ -415,7 +415,7 @@ impl<'tcx> Visitor<'tcx> for UnsafeVisitor<'_, 'tcx> { } if let Some(header) = kind.header() - && header.unsafety == Unsafety::Unsafe + && header.safety == Safety::Unsafe { self.has_unsafe = true; } diff --git a/clippy_lints/src/doc/missing_headers.rs b/clippy_lints/src/doc/missing_headers.rs index f935ae2e3e48..36ba19698c72 100644 --- a/clippy_lints/src/doc/missing_headers.rs +++ b/clippy_lints/src/doc/missing_headers.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_note}; use clippy_utils::ty::{implements_trait, is_type_diagnostic_item}; use clippy_utils::{is_doc_hidden, return_ty}; -use rustc_hir::{BodyId, FnSig, OwnerId, Unsafety}; +use rustc_hir::{BodyId, FnSig, OwnerId, Safety}; use rustc_lint::LateContext; use rustc_middle::ty; use rustc_span::{sym, Span}; @@ -33,14 +33,14 @@ pub fn check( } let span = cx.tcx.def_span(owner_id); - match (headers.safety, sig.header.unsafety) { - (false, Unsafety::Unsafe) => span_lint( + match (headers.safety, sig.header.safety) { + (false, Safety::Unsafe) => span_lint( cx, MISSING_SAFETY_DOC, span, "unsafe function's docs miss `# Safety` section", ), - (true, Unsafety::Normal) => span_lint( + (true, Safety::Safe) => span_lint( cx, UNNECESSARY_SAFETY_DOC, span, diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs index 4bced104d3bc..7fdb582e6403 100644 --- a/clippy_lints/src/doc/mod.rs +++ b/clippy_lints/src/doc/mod.rs @@ -12,7 +12,7 @@ use pulldown_cmark::{BrokenLink, CodeBlockKind, CowStr, Options}; use rustc_ast::ast::Attribute; use rustc_data_structures::fx::FxHashSet; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{AnonConst, Expr, ImplItemKind, ItemKind, Node, TraitItemKind, Unsafety}; +use rustc_hir::{AnonConst, Expr, ImplItemKind, ItemKind, Node, Safety, TraitItemKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::hir::nested_filter; use rustc_middle::lint::in_external_macro; @@ -415,13 +415,13 @@ impl<'tcx> LateLintPass<'tcx> for Documentation { } }, ItemKind::Trait(_, unsafety, ..) => match (headers.safety, unsafety) { - (false, Unsafety::Unsafe) => span_lint( + (false, Safety::Unsafe) => span_lint( cx, MISSING_SAFETY_DOC, cx.tcx.def_span(item.owner_id), "docs for unsafe trait missing `# Safety` section", ), - (true, Unsafety::Normal) => span_lint( + (true, Safety::Safe) => span_lint( cx, UNNECESSARY_SAFETY_DOC, cx.tcx.def_span(item.owner_id), diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index 306a4a9e55c9..b58018ca0353 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -5,7 +5,7 @@ use clippy_utils::ty::type_diagnostic_name; use clippy_utils::usage::{local_used_after_expr, local_used_in}; use clippy_utils::{get_path_from_caller_to_method_type, is_adjusted, path_to_local, path_to_local_id}; use rustc_errors::Applicability; -use rustc_hir::{BindingMode, Expr, ExprKind, FnRetTy, Param, PatKind, QPath, TyKind, Unsafety}; +use rustc_hir::{BindingMode, Expr, ExprKind, FnRetTy, Param, PatKind, QPath, Safety, TyKind}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{ @@ -146,7 +146,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction { ty::FnPtr(sig) => sig.skip_binder(), ty::Closure(_, subs) => cx .tcx - .signature_unclosure(subs.as_closure().sig(), Unsafety::Normal) + .signature_unclosure(subs.as_closure().sig(), Safety::Safe) .skip_binder(), _ => { if typeck.type_dependent_def_id(body.value.hir_id).is_some() @@ -154,7 +154,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction { && let output = typeck.expr_ty(body.value) && let ty::Tuple(tys) = *subs.type_at(1).kind() { - cx.tcx.mk_fn_sig(tys, output, false, Unsafety::Normal, Abi::Rust) + cx.tcx.mk_fn_sig(tys, output, false, Safety::Safe, Abi::Rust) } else { return; } @@ -241,11 +241,9 @@ fn check_inputs( } fn check_sig<'tcx>(cx: &LateContext<'tcx>, closure: ClosureArgs<'tcx>, call_sig: FnSig<'_>) -> bool { - call_sig.unsafety == Unsafety::Normal + call_sig.safety == Safety::Safe && !has_late_bound_to_non_late_bound_regions( - cx.tcx - .signature_unclosure(closure.sig(), Unsafety::Normal) - .skip_binder(), + cx.tcx.signature_unclosure(closure.sig(), Safety::Safe).skip_binder(), call_sig, ) } diff --git a/clippy_lints/src/functions/misnamed_getters.rs b/clippy_lints/src/functions/misnamed_getters.rs index 8ac17e17688d..7729c556e1fc 100644 --- a/clippy_lints/src/functions/misnamed_getters.rs +++ b/clippy_lints/src/functions/misnamed_getters.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; -use rustc_hir::{Body, ExprKind, FnDecl, ImplicitSelfKind, Unsafety}; +use rustc_hir::{Body, ExprKind, FnDecl, Safety, ImplicitSelfKind}; use rustc_lint::LateContext; use rustc_middle::ty; use rustc_span::Span; @@ -34,7 +34,7 @@ pub fn check_fn(cx: &LateContext<'_>, kind: FnKind<'_>, decl: &FnDecl<'_>, body: ImplicitSelfKind::None => return, }; - let name = if sig.header.unsafety == Unsafety::Unsafe { + let name = if sig.header.safety == Safety::Unsafe { name.strip_suffix("_unchecked").unwrap_or(name) } else { name diff --git a/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs b/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs index 995dd782cbbd..b44a5f20ef68 100644 --- a/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs +++ b/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs @@ -19,30 +19,30 @@ pub(super) fn check_fn<'tcx>( body: &'tcx hir::Body<'tcx>, def_id: LocalDefId, ) { - let unsafety = match kind { - intravisit::FnKind::ItemFn(_, _, hir::FnHeader { unsafety, .. }) => unsafety, - intravisit::FnKind::Method(_, sig) => sig.header.unsafety, + let safety = match kind { + intravisit::FnKind::ItemFn(_, _, hir::FnHeader { safety, .. }) => safety, + intravisit::FnKind::Method(_, sig) => sig.header.safety, intravisit::FnKind::Closure => return, }; - check_raw_ptr(cx, unsafety, decl, body, def_id); + check_raw_ptr(cx, safety, decl, body, def_id); } pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) { if let hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(eid)) = item.kind { let body = cx.tcx.hir().body(eid); - check_raw_ptr(cx, sig.header.unsafety, sig.decl, body, item.owner_id.def_id); + check_raw_ptr(cx, sig.header.safety, sig.decl, body, item.owner_id.def_id); } } fn check_raw_ptr<'tcx>( cx: &LateContext<'tcx>, - unsafety: hir::Unsafety, + safety: hir::Safety, decl: &'tcx hir::FnDecl<'tcx>, body: &'tcx hir::Body<'tcx>, def_id: LocalDefId, ) { - if unsafety == hir::Unsafety::Normal && cx.effective_visibilities.is_exported(def_id) { + if safety == hir::Safety::Safe && cx.effective_visibilities.is_exported(def_id) { let raw_ptrs = iter_input_pats(decl, body) .filter_map(|arg| raw_ptr_arg(cx, arg)) .collect::(); @@ -58,7 +58,7 @@ fn check_raw_ptr<'tcx>( }, hir::ExprKind::MethodCall(_, recv, args, _) => { let def_id = typeck.type_dependent_def_id(e.hir_id).unwrap(); - if cx.tcx.fn_sig(def_id).skip_binder().skip_binder().unsafety == hir::Unsafety::Unsafe { + if cx.tcx.fn_sig(def_id).skip_binder().skip_binder().safety == hir::Safety::Unsafe { check_arg(cx, &raw_ptrs, recv); for arg in args { check_arg(cx, &raw_ptrs, arg); diff --git a/clippy_lints/src/inherent_to_string.rs b/clippy_lints/src/inherent_to_string.rs index 157f61059847..9aedf5ec7e85 100644 --- a/clippy_lints/src/inherent_to_string.rs +++ b/clippy_lints/src/inherent_to_string.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::ty::{implements_trait, is_type_lang_item}; use clippy_utils::{return_ty, trait_ref_of_method}; -use rustc_hir::{GenericParamKind, ImplItem, ImplItemKind, LangItem, Unsafety}; +use rustc_hir::{GenericParamKind, ImplItem, ImplItemKind, LangItem, Safety}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; use rustc_span::sym; @@ -99,7 +99,7 @@ impl<'tcx> LateLintPass<'tcx> for InherentToString { if let ImplItemKind::Fn(ref signature, _) = impl_item.kind // #11201 && let header = signature.header - && header.unsafety == Unsafety::Normal + && header.safety == Safety::Safe && header.abi == Abi::Rust && impl_item.ident.name == sym::to_string && let decl = signature.decl diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 63545d6c5035..2b92bff016db 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -5038,7 +5038,7 @@ fn lint_binary_expr_with_method_call(cx: &LateContext<'_>, info: &mut BinaryExpr } const FN_HEADER: hir::FnHeader = hir::FnHeader { - unsafety: hir::Unsafety::Normal, + safety: hir::Safety::Safe, constness: hir::Constness::NotConst, asyncness: hir::IsAsync::NotAsync, abi: rustc_target::spec::abi::Abi::Rust, @@ -5214,7 +5214,5 @@ impl OutType { } fn fn_header_equals(expected: hir::FnHeader, actual: hir::FnHeader) -> bool { - expected.constness == actual.constness - && expected.unsafety == actual.unsafety - && expected.asyncness == actual.asyncness + expected.constness == actual.constness && expected.safety == actual.safety && expected.asyncness == actual.asyncness } diff --git a/clippy_lints/src/multiple_unsafe_ops_per_block.rs b/clippy_lints/src/multiple_unsafe_ops_per_block.rs index 0e1380667805..5306205aed7e 100644 --- a/clippy_lints/src/multiple_unsafe_ops_per_block.rs +++ b/clippy_lints/src/multiple_unsafe_ops_per_block.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::visitors::{for_each_expr_with_closures, Descend, Visitable}; use core::ops::ControlFlow::Continue; use hir::def::{DefKind, Res}; -use hir::{BlockCheckMode, ExprKind, QPath, UnOp, Unsafety}; +use hir::{BlockCheckMode, ExprKind, Safety, QPath, UnOp}; use rustc_ast::Mutability; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; @@ -133,7 +133,7 @@ fn collect_unsafe_exprs<'tcx>( ty::FnPtr(sig) => sig, _ => return Continue(Descend::Yes), }; - if sig.unsafety() == Unsafety::Unsafe { + if sig.safety() == Safety::Unsafe { unsafe_ops.push(("unsafe function call occurs here", expr.span)); } }, @@ -144,7 +144,7 @@ fn collect_unsafe_exprs<'tcx>( .type_dependent_def_id(expr.hir_id) .map(|def_id| cx.tcx.fn_sig(def_id)) { - if sig.skip_binder().unsafety() == Unsafety::Unsafe { + if sig.skip_binder().safety() == Safety::Unsafe { unsafe_ops.push(("unsafe method call occurs here", expr.span)); } } diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 78dd1e051627..b60fea3f03e0 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -75,7 +75,7 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault { if let hir::ImplItemKind::Fn(ref sig, _) = impl_item.kind { let name = impl_item.ident.name; let id = impl_item.owner_id; - if sig.header.unsafety == hir::Unsafety::Unsafe { + if sig.header.safety == hir::Safety::Unsafe { // can't be implemented for unsafe new return; } diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 2534e3c8468c..65929cd5fea9 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -12,7 +12,7 @@ use rustc_hir::hir_id::{HirId, HirIdMap}; use rustc_hir::intravisit::{walk_expr, Visitor}; use rustc_hir::{ self as hir, AnonConst, BinOpKind, BindingMode, Body, Expr, ExprKind, FnRetTy, FnSig, GenericArg, ImplItemKind, - ItemKind, Lifetime, Mutability, Node, Param, PatKind, QPath, TraitFn, TraitItem, TraitItemKind, TyKind, Unsafety, + ItemKind, Lifetime, Mutability, Node, Param, PatKind, QPath, Safety, TraitFn, TraitItem, TraitItemKind, TyKind, }; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::{Obligation, ObligationCause}; @@ -542,7 +542,7 @@ fn check_mut_from_ref<'tcx>(cx: &LateContext<'tcx>, sig: &FnSig<'_>, body: Optio if let Some(args) = args && !args.is_empty() && body.map_or(true, |body| { - sig.header.unsafety == Unsafety::Unsafe || contains_unsafe_block(cx, body.value) + sig.header.safety == Safety::Unsafe || contains_unsafe_block(cx, body.value) }) { span_lint_and_then( diff --git a/clippy_lints/src/undocumented_unsafe_blocks.rs b/clippy_lints/src/undocumented_unsafe_blocks.rs index cbd161800770..4120bb1331bd 100644 --- a/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -200,7 +200,7 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks { let item_has_safety_comment = item_has_safety_comment(cx, item); match (&item.kind, item_has_safety_comment) { // lint unsafe impl without safety comment - (ItemKind::Impl(impl_), HasSafetyComment::No) if impl_.unsafety == hir::Unsafety::Unsafe => { + (ItemKind::Impl(impl_), HasSafetyComment::No) if impl_.safety == hir::Safety::Unsafe => { if !is_lint_allowed(cx, UNDOCUMENTED_UNSAFE_BLOCKS, item.hir_id()) && !is_unsafe_from_proc_macro(cx, item.span) { @@ -222,7 +222,7 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks { } }, // lint safe impl with unnecessary safety comment - (ItemKind::Impl(impl_), HasSafetyComment::Yes(pos)) if impl_.unsafety == hir::Unsafety::Normal => { + (ItemKind::Impl(impl_), HasSafetyComment::Yes(pos)) if impl_.safety == hir::Safety::Safe => { if !is_lint_allowed(cx, UNNECESSARY_SAFETY_COMMENT, item.hir_id()) { let (span, help_span) = mk_spans(pos); diff --git a/clippy_utils/src/ast_utils.rs b/clippy_utils/src/ast_utils.rs index d3bbc66bcaea..d4a5f547211a 100644 --- a/clippy_utils/src/ast_utils.rs +++ b/clippy_utils/src/ast_utils.rs @@ -386,21 +386,21 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { ( Trait(box ast::Trait { is_auto: la, - unsafety: lu, + safety: lu, generics: lg, bounds: lb, items: li, }), Trait(box ast::Trait { is_auto: ra, - unsafety: ru, + safety: ru, generics: rg, bounds: rb, items: ri, }), ) => { la == ra - && matches!(lu, Unsafe::No) == matches!(ru, Unsafe::No) + && matches!(lu, Safety::Default) == matches!(ru, Safety::Default) && eq_generics(lg, rg) && over(lb, rb, eq_generic_bound) && over(li, ri, |l, r| eq_item(l, r, eq_assoc_item_kind)) @@ -408,7 +408,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { (TraitAlias(lg, lb), TraitAlias(rg, rb)) => eq_generics(lg, rg) && over(lb, rb, eq_generic_bound), ( Impl(box ast::Impl { - unsafety: lu, + safety: lu, polarity: lp, defaultness: ld, constness: lc, @@ -418,7 +418,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { items: li, }), Impl(box ast::Impl { - unsafety: ru, + safety: ru, polarity: rp, defaultness: rd, constness: rc, @@ -428,7 +428,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { items: ri, }), ) => { - matches!(lu, Unsafe::No) == matches!(ru, Unsafe::No) + matches!(lu, Safety::Default) == matches!(ru, Safety::Default) && matches!(lp, ImplPolarity::Positive) == matches!(rp, ImplPolarity::Positive) && eq_defaultness(*ld, *rd) && matches!(lc, ast::Const::No) == matches!(rc, ast::Const::No) @@ -605,7 +605,7 @@ fn eq_opt_coroutine_kind(l: Option, r: Option) -> } pub fn eq_fn_header(l: &FnHeader, r: &FnHeader) -> bool { - matches!(l.unsafety, Unsafe::No) == matches!(r.unsafety, Unsafe::No) + matches!(l.safety, Safety::Default) == matches!(r.safety, Safety::Default) && eq_opt_coroutine_kind(l.coroutine_kind, r.coroutine_kind) && matches!(l.constness, Const::No) == matches!(r.constness, Const::No) && eq_ext(&l.ext, &r.ext) @@ -712,7 +712,7 @@ pub fn eq_ty(l: &Ty, r: &Ty) -> bool { both(ll, rl, |l, r| eq_id(l.ident, r.ident)) && l.mutbl == r.mutbl && eq_ty(&l.ty, &r.ty) }, (BareFn(l), BareFn(r)) => { - l.unsafety == r.unsafety + l.safety == r.safety && eq_ext(&l.ext, &r.ext) && over(&l.generic_params, &r.generic_params, eq_generic_param) && eq_fn_decl(&l.decl, &r.decl) diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs index 422673105136..553e89999750 100644 --- a/clippy_utils/src/check_proc_macro.rs +++ b/clippy_utils/src/check_proc_macro.rs @@ -18,8 +18,8 @@ use rustc_ast::AttrStyle; use rustc_hir::intravisit::FnKind; use rustc_hir::{ Block, BlockCheckMode, Body, Closure, Destination, Expr, ExprKind, FieldDef, FnHeader, FnRetTy, HirId, Impl, - ImplItem, ImplItemKind, IsAuto, Item, ItemKind, LoopSource, MatchSource, MutTy, Node, QPath, TraitItem, - TraitItemKind, Ty, TyKind, UnOp, UnsafeSource, Unsafety, Variant, VariantData, YieldSource, + ImplItem, ImplItemKind, IsAuto, Item, ItemKind, LoopSource, MatchSource, MutTy, Node, QPath, Safety, TraitItem, + TraitItemKind, Ty, TyKind, UnOp, UnsafeSource, Variant, VariantData, YieldSource, }; use rustc_lint::{LateContext, LintContext}; use rustc_middle::ty::TyCtxt; @@ -207,10 +207,9 @@ fn item_search_pat(item: &Item<'_>) -> (Pat, Pat) { ItemKind::Struct(VariantData::Struct { .. }, _) => (Pat::Str("struct"), Pat::Str("}")), ItemKind::Struct(..) => (Pat::Str("struct"), Pat::Str(";")), ItemKind::Union(..) => (Pat::Str("union"), Pat::Str("}")), - ItemKind::Trait(_, Unsafety::Unsafe, ..) + ItemKind::Trait(_, Safety::Unsafe, ..) | ItemKind::Impl(Impl { - unsafety: Unsafety::Unsafe, - .. + safety: Safety::Unsafe, .. }) => (Pat::Str("unsafe"), Pat::Str("}")), ItemKind::Trait(IsAuto::Yes, ..) => (Pat::Str("auto"), Pat::Str("}")), ItemKind::Trait(..) => (Pat::Str("trait"), Pat::Str("}")), @@ -323,7 +322,7 @@ fn ty_search_pat(ty: &Ty<'_>) -> (Pat, Pat) { TyKind::Ptr(MutTy { ty, .. }) => (Pat::Str("*"), ty_search_pat(ty).1), TyKind::Ref(_, MutTy { ty, .. }) => (Pat::Str("&"), ty_search_pat(ty).1), TyKind::BareFn(bare_fn) => ( - if bare_fn.unsafety == Unsafety::Unsafe { + if bare_fn.safety == Safety::Unsafe { Pat::Str("unsafe") } else if bare_fn.abi != Abi::Rust { Pat::Str("extern") diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs index c921168df290..9f285621e0c9 100644 --- a/clippy_utils/src/hir_utils.rs +++ b/clippy_utils/src/hir_utils.rs @@ -1082,7 +1082,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { mut_ty.mutbl.hash(&mut self.s); }, TyKind::BareFn(bfn) => { - bfn.unsafety.hash(&mut self.s); + bfn.safety.hash(&mut self.s); bfn.abi.hash(&mut self.s); for arg in bfn.decl.inputs { self.hash_ty(arg); diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs index e3ab42c3107c..4f71453d8db8 100644 --- a/clippy_utils/src/ty.rs +++ b/clippy_utils/src/ty.rs @@ -9,7 +9,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::{Expr, FnDecl, LangItem, TyKind, Unsafety}; +use rustc_hir::{Expr, FnDecl, Safety, LangItem, TyKind}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::LateContext; use rustc_middle::mir::interpret::Scalar; @@ -562,7 +562,7 @@ pub fn peel_mid_ty_refs_is_mutable(ty: Ty<'_>) -> (Ty<'_>, usize, Mutability) { /// Returns `true` if the given type is an `unsafe` function. pub fn type_is_unsafe_function<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { match ty.kind() { - ty::FnDef(..) | ty::FnPtr(_) => ty.fn_sig(cx.tcx).unsafety() == Unsafety::Unsafe, + ty::FnDef(..) | ty::FnPtr(_) => ty.fn_sig(cx.tcx).safety() == Safety::Unsafe, _ => false, } } diff --git a/clippy_utils/src/visitors.rs b/clippy_utils/src/visitors.rs index a3f3b32ed372..90b56297bb55 100644 --- a/clippy_utils/src/visitors.rs +++ b/clippy_utils/src/visitors.rs @@ -6,7 +6,7 @@ use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::intravisit::{self, walk_block, walk_expr, Visitor}; use rustc_hir::{ AnonConst, Arm, Block, BlockCheckMode, Body, BodyId, Expr, ExprKind, HirId, ItemId, ItemKind, LetExpr, Pat, QPath, - Stmt, UnOp, UnsafeSource, Unsafety, + Safety, Stmt, UnOp, UnsafeSource, }; use rustc_lint::LateContext; use rustc_middle::hir::nested_filter; @@ -421,16 +421,16 @@ pub fn is_expr_unsafe<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> bool { .typeck_results() .type_dependent_def_id(e.hir_id) .map_or(false, |id| { - self.cx.tcx.fn_sig(id).skip_binder().unsafety() == Unsafety::Unsafe + self.cx.tcx.fn_sig(id).skip_binder().safety() == Safety::Unsafe }) => { self.is_unsafe = true; }, ExprKind::Call(func, _) => match *self.cx.typeck_results().expr_ty(func).peel_refs().kind() { - ty::FnDef(id, _) if self.cx.tcx.fn_sig(id).skip_binder().unsafety() == Unsafety::Unsafe => { + ty::FnDef(id, _) if self.cx.tcx.fn_sig(id).skip_binder().safety() == Safety::Unsafe => { self.is_unsafe = true; }, - ty::FnPtr(sig) if sig.unsafety() == Unsafety::Unsafe => self.is_unsafe = true, + ty::FnPtr(sig) if sig.safety() == Safety::Unsafe => self.is_unsafe = true, _ => walk_expr(self, e), }, ExprKind::Path(ref p) @@ -452,7 +452,7 @@ pub fn is_expr_unsafe<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> bool { } fn visit_nested_item(&mut self, id: ItemId) { if let ItemKind::Impl(i) = &self.cx.tcx.hir().item(id).kind { - self.is_unsafe = i.unsafety == Unsafety::Unsafe; + self.is_unsafe = i.safety == Safety::Unsafe; } } } From ab863527897916080e9ec451dbf109aad780ea19 Mon Sep 17 00:00:00 2001 From: Luuk Wester Date: Fri, 17 May 2024 21:54:35 +0200 Subject: [PATCH 013/211] implement assist to switch between doc and normal comments --- .../convert_comment_from_or_to_doc.rs | 645 ++++++++++++++++++ .../crates/ide-assists/src/lib.rs | 2 + .../crates/ide-assists/src/tests/generated.rs | 15 + 3 files changed, 662 insertions(+) create mode 100644 src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs new file mode 100644 index 000000000000..1ac30d71f267 --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs @@ -0,0 +1,645 @@ +use itertools::Itertools; +use syntax::{ + ast::{self, edit::IndentLevel, Comment, CommentPlacement, Whitespace}, + AstToken, Direction, SyntaxElement, TextRange, +}; + +use crate::{AssistContext, AssistId, AssistKind, Assists}; + +// Assist: comment_to_doc +// +// Converts comments to documentation. +// +// ``` +// // Wow what $0a nice function +// // I sure hope this shows up when I hover over it +// ``` +// -> +// ``` +// //! Wow what a nice function +// //! I sure hope this shows up when I hover over it +// ``` +pub(crate) fn convert_comment_from_or_to_doc( + acc: &mut Assists, + ctx: &AssistContext<'_>, +) -> Option<()> { + let comment = ctx.find_token_at_offset::()?; + + match comment.kind().doc { + Some(_) => doc_to_comment(acc, comment), + None => match can_be_doc_comment(&comment) { + Some(doc_comment_style) => comment_to_doc(acc, comment, doc_comment_style), + None => None, + }, + } +} + +fn doc_to_comment(acc: &mut Assists, comment: ast::Comment) -> Option<()> { + let target = if comment.kind().shape.is_line() { + line_comments_text_range(&comment)? + } else { + comment.syntax().text_range() + }; + + acc.add( + AssistId("doc_to_comment", AssistKind::RefactorRewrite), + "Replace a comment with doc comment", + target, + |edit| { + // We need to either replace the first occurrence of /* with /***, or we need to replace + // the occurrences // at the start of each line with /// + let output = match comment.kind().shape { + ast::CommentShape::Line => { + let indentation = IndentLevel::from_token(comment.syntax()); + let line_start = comment.prefix(); + relevant_line_comments(&comment) + .iter() + .map(|comment| comment.text()) + .flat_map(|text| text.lines()) + .map(|line| indentation.to_string() + &line.replacen(line_start, "//", 1)) + .join("\n") + } + ast::CommentShape::Block => { + let block_start = comment.prefix(); + comment + .text() + .lines() + .enumerate() + .map(|(idx, line)| { + if idx == 0 { + line.replacen(block_start, "/*", 1) + } else { + line.replacen("* ", "* ", 1) + } + }) + .join("\n") + } + }; + edit.replace(target, output) + }, + ) +} + +fn comment_to_doc(acc: &mut Assists, comment: ast::Comment, style: CommentPlacement) -> Option<()> { + let target = if comment.kind().shape.is_line() { + line_comments_text_range(&comment)? + } else { + comment.syntax().text_range() + }; + + acc.add( + AssistId("comment_to_doc", AssistKind::RefactorRewrite), + "Replace a doc comment with comment", + target, + |edit| { + // We need to either replace the first occurrence of /* with /***, or we need to replace + // the occurrences // at the start of each line with /// + let output = match comment.kind().shape { + ast::CommentShape::Line => { + let line_start = match style { + CommentPlacement::Inner => "//!", + CommentPlacement::Outer => "///", + }; + let indentation = IndentLevel::from_token(comment.syntax()); + relevant_line_comments(&comment) + .iter() + .map(|comment| comment.text()) + .flat_map(|text| text.lines()) + .map(|line| indentation.to_string() + &line.replacen("//", line_start, 1)) + .join("\n") + } + ast::CommentShape::Block => { + let block_start = match style { + CommentPlacement::Inner => "/*!", + CommentPlacement::Outer => "/**", + }; + comment + .text() + .lines() + .enumerate() + .map(|(idx, line)| { + if idx == 0 { + // On the first line we replace the comment start with a doc comment + // start. + line.replacen("/*", block_start, 1) + } else { + // put one extra space after each * since we moved the first line to + // the right by one column as well. + line.replacen("* ", "* ", 1) + } + }) + .join("\n") + } + }; + edit.replace(target, output) + }, + ) +} + +/// Not all comments are valid candidates for conversion into doc comments. For example, the +/// comments in the code: +/// ```rust +/// // foos the bar +/// fn foo_bar(foo: Foo) -> Bar { +/// // Bar the foo +/// foo.into_bar() +/// } +/// +/// trait A { +/// // The A trait +/// } +/// ``` +/// can be converted to doc comments. However, the comments in this example: +/// ```rust +/// fn foo_bar(foo: Foo /* not bar yet */) -> Bar { +/// foo.into_bar() +/// // Nicely done +/// } +/// // end of function +/// +/// struct S { +/// // The S struct +/// } +/// ``` +/// are not allowed to become doc comments. +fn can_be_doc_comment(comment: &ast::Comment) -> Option { + use syntax::SyntaxKind::*; + + // if the comment is not on its own line, then we do not propose anything. + match comment.syntax().prev_token() { + Some(prev) => { + // There was a previous token, now check if it was a newline + Whitespace::cast(prev).filter(|w| w.text().contains('\n'))?; + } + // There is no previous token, this is the start of the file. + None => return Some(CommentPlacement::Inner), + } + + // check if comment is followed by: `struct`, `trait`, `mod`, `fn`, `type`, `extern crate`, `use`, `const` + let parent = comment.syntax().parent(); + let parent_kind = parent.as_ref().map(|parent| parent.kind()); + if matches!( + parent_kind, + Some(STRUCT | TRAIT | MODULE | FN | TYPE_KW | EXTERN_CRATE | USE | CONST) + ) { + return Some(CommentPlacement::Outer); + } + + // check if comment is preceded by: `fn f() {`, `trait T {`, `mod M {`: + let third_parent_kind = comment + .syntax() + .parent() + .and_then(|p| p.parent()) + .and_then(|p| p.parent()) + .map(|parent| parent.kind()); + let is_first_item_in_parent = comment + .syntax() + .siblings_with_tokens(Direction::Prev) + .filter_map(|not| not.into_node()) + .next() + .is_none(); + + if matches!(parent_kind, Some(STMT_LIST)) + && is_first_item_in_parent + && matches!(third_parent_kind, Some(FN | TRAIT | MODULE)) + { + return Some(CommentPlacement::Inner); + } + + None +} + +/// The line -> block assist can be invoked from anywhere within a sequence of line comments. +/// relevant_line_comments crawls backwards and forwards finding the complete sequence of comments that will +/// be joined. +pub(crate) fn relevant_line_comments(comment: &ast::Comment) -> Vec { + // The prefix identifies the kind of comment we're dealing with + let prefix = comment.prefix(); + let same_prefix = |c: &ast::Comment| c.prefix() == prefix; + + // These tokens are allowed to exist between comments + let skippable = |not: &SyntaxElement| { + not.clone() + .into_token() + .and_then(Whitespace::cast) + .map(|w| !w.spans_multiple_lines()) + .unwrap_or(false) + }; + + // Find all preceding comments (in reverse order) that have the same prefix + let prev_comments = comment + .syntax() + .siblings_with_tokens(Direction::Prev) + .filter(|s| !skippable(s)) + .map(|not| not.into_token().and_then(Comment::cast).filter(same_prefix)) + .take_while(|opt_com| opt_com.is_some()) + .flatten() + .skip(1); // skip the first element so we don't duplicate it in next_comments + + let next_comments = comment + .syntax() + .siblings_with_tokens(Direction::Next) + .filter(|s| !skippable(s)) + .map(|not| not.into_token().and_then(Comment::cast).filter(same_prefix)) + .take_while(|opt_com| opt_com.is_some()) + .flatten(); + + let mut comments: Vec<_> = prev_comments.collect(); + comments.reverse(); + comments.extend(next_comments); + comments +} + +fn line_comments_text_range(comment: &ast::Comment) -> Option { + let comments = relevant_line_comments(comment); + let first = comments.first()?; + let indentation = IndentLevel::from_token(first.syntax()); + let start = + first.syntax().text_range().start().checked_sub((indentation.0 as u32 * 4).into())?; + let end = comments.last()?.syntax().text_range().end(); + Some(TextRange::new(start, end)) +} + +#[cfg(test)] +mod tests { + use crate::tests::{check_assist, check_assist_not_applicable}; + + use super::*; + + #[test] + fn module_comment_to_doc() { + check_assist( + convert_comment_from_or_to_doc, + r#" + // such a nice module$0 + fn main() { + foo(); + } + "#, + r#" + //! such a nice module + fn main() { + foo(); + } + "#, + ); + } + + #[test] + fn single_line_comment_to_doc() { + check_assist( + convert_comment_from_or_to_doc, + r#" + + // unseen$0 docs + fn main() { + foo(); + } + "#, + r#" + + /// unseen docs + fn main() { + foo(); + } + "#, + ); + } + + #[test] + fn multi_line_comment_to_doc() { + check_assist( + convert_comment_from_or_to_doc, + r#" + + // unseen$0 docs + // make me seen! + fn main() { + foo(); + } + "#, + r#" + + /// unseen docs + /// make me seen! + fn main() { + foo(); + } + "#, + ); + } + + #[test] + fn single_line_doc_to_comment() { + check_assist( + convert_comment_from_or_to_doc, + r#" + + /// visible$0 docs + fn main() { + foo(); + } + "#, + r#" + + // visible docs + fn main() { + foo(); + } + "#, + ); + } + + #[test] + fn multi_line_doc_to_comment() { + check_assist( + convert_comment_from_or_to_doc, + r#" + + /// visible$0 docs + /// Hide me! + fn main() { + foo(); + } + "#, + r#" + + // visible docs + // Hide me! + fn main() { + foo(); + } + "#, + ); + } + + #[test] + fn single_line_block_comment_to_doc() { + check_assist( + convert_comment_from_or_to_doc, + r#" + + /* unseen$0 docs */ + fn main() { + foo(); + } + "#, + r#" + + /** unseen docs */ + fn main() { + foo(); + } + "#, + ); + } + + #[test] + fn multi_line_block_comment_to_doc() { + check_assist( + convert_comment_from_or_to_doc, + r#" + + /* unseen$0 docs + * make me seen! + */ + fn main() { + foo(); + } + "#, + r#" + + /** unseen docs + * make me seen! + */ + fn main() { + foo(); + } + "#, + ); + } + + #[test] + fn single_line_block_doc_to_comment() { + check_assist( + convert_comment_from_or_to_doc, + r#" + + /** visible$0 docs */ + fn main() { + foo(); + } + "#, + r#" + + /* visible docs */ + fn main() { + foo(); + } + "#, + ); + } + + #[test] + fn multi_line_block_doc_to_comment() { + check_assist( + convert_comment_from_or_to_doc, + r#" + + /** visible$0 docs + * Hide me! + */ + fn main() { + foo(); + } + "#, + r#" + + /* visible docs + * Hide me! + */ + fn main() { + foo(); + } + "#, + ); + } + + #[test] + fn single_inner_line_comment_to_doc() { + check_assist( + convert_comment_from_or_to_doc, + r#" + fn main() { + // unseen$0 docs + foo(); + } + "#, + r#" + fn main() { + //! unseen docs + foo(); + } + "#, + ); + } + + #[test] + fn multi_inner_line_comment_to_doc() { + check_assist( + convert_comment_from_or_to_doc, + r#" + fn main() { + // unseen$0 docs + // make me seen! + foo(); + } + "#, + r#" + fn main() { + //! unseen docs + //! make me seen! + foo(); + } + "#, + ); + } + + #[test] + fn single_inner_line_doc_to_comment() { + check_assist( + convert_comment_from_or_to_doc, + r#" + fn main() { + //! visible$0 docs + foo(); + } + "#, + r#" + fn main() { + // visible docs + foo(); + } + "#, + ); + } + + #[test] + fn multi_inner_line_doc_to_comment() { + check_assist( + convert_comment_from_or_to_doc, + r#" + fn main() { + //! visible$0 docs + //! Hide me! + foo(); + } + "#, + r#" + fn main() { + // visible docs + // Hide me! + foo(); + } + "#, + ); + } + + #[test] + fn single_inner_line_block_comment_to_doc() { + check_assist( + convert_comment_from_or_to_doc, + r#" + fn main() { + /* unseen$0 docs */ + foo(); + } + "#, + r#" + fn main() { + /*! unseen docs */ + foo(); + } + "#, + ); + } + + #[test] + fn multi_inner_line_block_comment_to_doc() { + check_assist( + convert_comment_from_or_to_doc, + r#" + fn main() { + /* unseen$0 docs + * make me seen! + */ + foo(); + } + "#, + r#" + fn main() { + /*! unseen docs + * make me seen! + */ + foo(); + } + "#, + ); + } + + #[test] + fn single_inner_line_block_doc_to_comment() { + check_assist( + convert_comment_from_or_to_doc, + r#" + fn main() { + /*! visible$0 docs */ + foo(); + } + "#, + r#" + fn main() { + /* visible docs */ + foo(); + } + "#, + ); + } + + #[test] + fn multi_inner_line_block_doc_to_comment() { + check_assist( + convert_comment_from_or_to_doc, + r#" + fn main() { + /*! visible$0 docs + * Hide me! + */ + foo(); + } + "#, + r#" + fn main() { + /* visible docs + * Hide me! + */ + foo(); + } + "#, + ); + } + + #[test] + fn not_overeager() { + check_assist_not_applicable( + convert_comment_from_or_to_doc, + r#" + fn main() { + foo(); + // $0well that settles main + } + // $1 nicely done + "#, + ); + } +} diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs index 0df5e913a573..cbaf03e4d1f0 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs @@ -116,6 +116,7 @@ mod handlers { mod change_visibility; mod convert_bool_then; mod convert_comment_block; + mod convert_comment_from_or_to_doc; mod convert_from_to_tryfrom; mod convert_integer_literal; mod convert_into_to_from; @@ -239,6 +240,7 @@ mod handlers { convert_bool_then::convert_bool_then_to_if, convert_bool_then::convert_if_to_bool_then, convert_comment_block::convert_comment_block, + convert_comment_from_or_to_doc::convert_comment_from_or_to_doc, convert_from_to_tryfrom::convert_from_to_tryfrom, convert_integer_literal::convert_integer_literal, convert_into_to_from::convert_into_to_from, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs index 937e78f8d7d2..bd841d72e6c1 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs @@ -345,6 +345,21 @@ pub(crate) fn frobnicate() {} ) } +#[test] +fn doctest_comment_to_doc() { + check_doc_test( + "comment_to_doc", + r#####" +// Wow what $0a nice function +// I sure hope this shows up when I hover over it +"#####, + r#####" +//! Wow what a nice function +//! I sure hope this shows up when I hover over it +"#####, + ) +} + #[test] fn doctest_convert_bool_then_to_if() { check_doc_test( From 0cd64b5756f6834b266ecfdfede47ac66a6359fa Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Thu, 16 May 2024 03:00:48 -0700 Subject: [PATCH 014/211] Fix clippy --- clippy_utils/src/mir/possible_borrower.rs | 4 ++-- clippy_utils/src/qualify_min_const_fn.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_utils/src/mir/possible_borrower.rs b/clippy_utils/src/mir/possible_borrower.rs index 06229ac938f9..7b4fd8a210ed 100644 --- a/clippy_utils/src/mir/possible_borrower.rs +++ b/clippy_utils/src/mir/possible_borrower.rs @@ -149,7 +149,7 @@ impl TypeVisitor> for ContainsRegion { } fn rvalue_locals(rvalue: &mir::Rvalue<'_>, mut visit: impl FnMut(mir::Local)) { - use rustc_middle::mir::Rvalue::{Aggregate, BinaryOp, Cast, CheckedBinaryOp, Repeat, UnaryOp, Use}; + use rustc_middle::mir::Rvalue::{Aggregate, BinaryOp, Cast, Repeat, UnaryOp, Use}; let mut visit_op = |op: &mir::Operand<'_>| match op { mir::Operand::Copy(p) | mir::Operand::Move(p) => visit(p.local), @@ -159,7 +159,7 @@ fn rvalue_locals(rvalue: &mir::Rvalue<'_>, mut visit: impl FnMut(mir::Local)) { match rvalue { Use(op) | Repeat(op, _) | Cast(_, op, _) | UnaryOp(_, op) => visit_op(op), Aggregate(_, ops) => ops.iter().for_each(visit_op), - BinaryOp(_, box (lhs, rhs)) | CheckedBinaryOp(_, box (lhs, rhs)) => { + BinaryOp(_, box (lhs, rhs)) => { visit_op(lhs); visit_op(rhs); }, diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs index 95851a2eed81..ff9f06531ea1 100644 --- a/clippy_utils/src/qualify_min_const_fn.rs +++ b/clippy_utils/src/qualify_min_const_fn.rs @@ -161,7 +161,7 @@ fn check_rvalue<'tcx>( "transmute can attempt to turn pointers into integers, so is unstable in const fn".into(), )), // binops are fine on integers - Rvalue::BinaryOp(_, box (lhs, rhs)) | Rvalue::CheckedBinaryOp(_, box (lhs, rhs)) => { + Rvalue::BinaryOp(_, box (lhs, rhs)) => { check_operand(tcx, lhs, span, body)?; check_operand(tcx, rhs, span, body)?; let ty = lhs.ty(body, tcx); From ae547e30009635de6f8d6451cf8e355e5d5207b7 Mon Sep 17 00:00:00 2001 From: blyxyas Date: Sat, 18 May 2024 18:08:11 +0200 Subject: [PATCH 015/211] Fix typos (taking into account review comments) --- clippy_lints/src/methods/needless_collect.rs | 2 +- tests/ui/ptr_arg.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/methods/needless_collect.rs b/clippy_lints/src/methods/needless_collect.rs index 1c695655536c..f26f164fa54a 100644 --- a/clippy_lints/src/methods/needless_collect.rs +++ b/clippy_lints/src/methods/needless_collect.rs @@ -127,7 +127,7 @@ pub(super) fn check<'tcx>( } } -/// checks for for collecting into a (generic) method or function argument +/// checks for collecting into a (generic) method or function argument /// taking an `IntoIterator` fn check_collect_into_intoiterator<'tcx>( cx: &LateContext<'tcx>, diff --git a/tests/ui/ptr_arg.rs b/tests/ui/ptr_arg.rs index fcd716f41444..5d6e488972cd 100644 --- a/tests/ui/ptr_arg.rs +++ b/tests/ui/ptr_arg.rs @@ -282,7 +282,7 @@ mod issue_9218 { todo!() } - // These two's return types don't use use 'a so it's not okay + // These two's return types don't use 'a so it's not okay fn cow_bad_ret_ty_1<'a>(input: &'a Cow<'a, str>) -> &'static str { //~^ ERROR: using a reference to `Cow` is not recommended todo!() From 23e8b03f00289643c790bfb618509944f13d6432 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sat, 11 May 2024 11:46:25 +0200 Subject: [PATCH 016/211] Add and use generics.is_empty() and generics.is_own_empty, rather than using generics' attributes --- clippy_lints/src/iter_without_into_iter.rs | 2 +- clippy_utils/src/ty/type_certainty/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/iter_without_into_iter.rs b/clippy_lints/src/iter_without_into_iter.rs index a75dfaf286fd..601d0e151aae 100644 --- a/clippy_lints/src/iter_without_into_iter.rs +++ b/clippy_lints/src/iter_without_into_iter.rs @@ -225,7 +225,7 @@ impl {self_ty_without_ref} {{ && let ImplItemKind::Fn(sig, _) = item.kind && let FnRetTy::Return(ret) = sig.decl.output && is_nameable_in_impl_trait(ret) - && cx.tcx.generics_of(item_did).own_params.is_empty() + && cx.tcx.generics_of(item_did).is_own_empty() && sig.decl.implicit_self == expected_implicit_self && sig.decl.inputs.len() == 1 && let Some(imp) = get_parent_as_impl(cx.tcx, item.hir_id()) diff --git a/clippy_utils/src/ty/type_certainty/mod.rs b/clippy_utils/src/ty/type_certainty/mod.rs index c2ff19931d5c..802193034502 100644 --- a/clippy_utils/src/ty/type_certainty/mod.rs +++ b/clippy_utils/src/ty/type_certainty/mod.rs @@ -176,7 +176,7 @@ fn qpath_certainty(cx: &LateContext<'_>, qpath: &QPath<'_>, resolves_to_type: bo .get(*lang_item) .map_or(Certainty::Uncertain, |def_id| { let generics = cx.tcx.generics_of(def_id); - if generics.parent_count == 0 && generics.own_params.is_empty() { + if generics.is_empty() { Certainty::Certain(if resolves_to_type { Some(def_id) } else { None }) } else { Certainty::Uncertain From 9d311b5c2b29936349acdc9dfddafc8ea919b51e Mon Sep 17 00:00:00 2001 From: schvv31n Date: Sun, 19 May 2024 21:41:13 +0100 Subject: [PATCH 017/211] initial fix --- .../iter_on_single_or_empty_collections.rs | 43 ++++++++++++++++++- tests/ui/iter_on_empty_collections.fixed | 13 ++++++ tests/ui/iter_on_empty_collections.rs | 13 ++++++ tests/ui/iter_on_empty_collections.stderr | 8 +++- 4 files changed, 75 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs b/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs index 6c9bdcff8262..0e929cfe798f 100644 --- a/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs +++ b/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs @@ -1,8 +1,12 @@ +use std::iter::once; + use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet; use clippy_utils::{get_expr_use_or_unification_node, is_res_lang_ctor, path_res, std_or_core}; use rustc_errors::Applicability; +use rustc_hir::def_id::DefId; +use rustc_hir::hir_id::HirId; use rustc_hir::LangItem::{OptionNone, OptionSome}; use rustc_hir::{Expr, ExprKind, Node}; use rustc_lint::LateContext; @@ -25,7 +29,25 @@ impl IterType { } } -pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: &str, recv: &Expr<'_>) { +fn is_arg_ty_unified_in_fn<'tcx>( + cx: &LateContext<'tcx>, + fn_id: DefId, + arg_id: HirId, + args: impl Iterator> + Clone, +) -> bool { + let fn_sig = cx.tcx.fn_sig(fn_id).instantiate_identity(); + let arg_id_in_args = args.clone().position(|e| e.hir_id == arg_id).unwrap(); + let arg_ty_in_args = fn_sig.input(arg_id_in_args); + + cx.tcx.predicates_of(fn_id).predicates.iter().any(|(clause, _)| { + clause + .as_projection_clause() + .and_then(|p| p.map_bound(|p| p.term.ty()).transpose()) + .is_some_and(|ty| ty == arg_ty_in_args) + }) +} + +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, method_name: &str, recv: &'tcx Expr<'tcx>) { let item = match recv.kind { ExprKind::Array([]) => None, ExprKind::Array([e]) => Some(e), @@ -43,6 +65,25 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: &str, re let is_unified = match get_expr_use_or_unification_node(cx.tcx, expr) { Some((Node::Expr(parent), child_id)) => match parent.kind { ExprKind::If(e, _, _) | ExprKind::Match(e, _, _) if e.hir_id == child_id => false, + ExprKind::Call( + Expr { + kind: ExprKind::Path(path), + hir_id, + .. + }, + args, + ) => is_arg_ty_unified_in_fn( + cx, + cx.typeck_results().qpath_res(path, *hir_id).def_id(), + expr.hir_id, + args.iter(), + ), + ExprKind::MethodCall(_name, recv, args, _span) => is_arg_ty_unified_in_fn( + cx, + cx.typeck_results().type_dependent_def_id(parent.hir_id).unwrap(), + expr.hir_id, + once(recv).chain(args.iter()), + ), ExprKind::If(_, _, _) | ExprKind::Match(_, _, _) | ExprKind::Closure(_) diff --git a/tests/ui/iter_on_empty_collections.fixed b/tests/ui/iter_on_empty_collections.fixed index 794629f240eb..871cc18d7c2d 100644 --- a/tests/ui/iter_on_empty_collections.fixed +++ b/tests/ui/iter_on_empty_collections.fixed @@ -20,6 +20,19 @@ fn array() { }; let _ = if false { ["test"].iter() } else { [].iter() }; + + let smth = Some(vec![1, 2, 3]); + + // Don't trigger when the empty collection iter is relied upon for its concrete type + // But do trigger if it is just an iterator, despite being an argument to a method + for i in smth.as_ref().map_or([].iter(), |s| s.iter()).chain(std::iter::empty()) { + println!("{i}"); + } + + // Same as above, but for regular function calls + for i in Option::map_or(smth.as_ref(), [].iter(), |s| s.iter()) { + println!("{i}"); + } } macro_rules! in_macros { diff --git a/tests/ui/iter_on_empty_collections.rs b/tests/ui/iter_on_empty_collections.rs index a6461a702eb2..7e3df49eefcd 100644 --- a/tests/ui/iter_on_empty_collections.rs +++ b/tests/ui/iter_on_empty_collections.rs @@ -20,6 +20,19 @@ fn array() { }; let _ = if false { ["test"].iter() } else { [].iter() }; + + let smth = Some(vec![1, 2, 3]); + + // Don't trigger when the empty collection iter is relied upon for its concrete type + // But do trigger if it is just an iterator, despite being an argument to a method + for i in smth.as_ref().map_or([].iter(), |s| s.iter()).chain([].iter()) { + println!("{i}"); + } + + // Same as above, but for regular function calls + for i in Option::map_or(smth.as_ref(), [].iter(), |s| s.iter()) { + println!("{i}"); + } } macro_rules! in_macros { diff --git a/tests/ui/iter_on_empty_collections.stderr b/tests/ui/iter_on_empty_collections.stderr index ade20ff26a01..da9caa6925bd 100644 --- a/tests/ui/iter_on_empty_collections.stderr +++ b/tests/ui/iter_on_empty_collections.stderr @@ -37,5 +37,11 @@ error: `iter` call on an empty collection LL | assert_eq!(None.iter().next(), Option::<&i32>::None); | ^^^^^^^^^^^ help: try: `std::iter::empty()` -error: aborting due to 6 previous errors +error: `iter` call on an empty collection + --> tests/ui/iter_on_empty_collections.rs:28:66 + | +LL | for i in smth.as_ref().map_or([].iter(), |s| s.iter()).chain([].iter()) { + | ^^^^^^^^^ help: try: `std::iter::empty()` + +error: aborting due to 7 previous errors From 86158f581d20948507bef65e6162e3bbf5f4fa91 Mon Sep 17 00:00:00 2001 From: Caleb Zulawski Date: Mon, 20 May 2024 01:09:29 -0400 Subject: [PATCH 018/211] Make repr(packed) vectors work with SIMD intrinsics --- compiler/rustc_codegen_llvm/src/intrinsic.rs | 49 +++++++++++++++++++- tests/ui/simd/repr_packed.rs | 18 ++----- 2 files changed, 52 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index c0a1208a8c7d..83a71752ffd8 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -480,8 +480,55 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> { } _ if name.as_str().starts_with("simd_") => { + // Unpack non-power-of-2 #[repr(packed)] + let mut loaded_args = Vec::new(); + for (ty, arg) in arg_tys.iter().zip(args) { + loaded_args.push( + if ty.is_simd() + && let OperandValue::Ref(place) = arg.val + { + let (size, elem_ty) = ty.simd_size_and_type(self.tcx()); + let elem_ll_ty = match elem_ty.kind() { + ty::Float(f) => self.type_float_from_ty(*f), + ty::Int(i) => self.type_int_from_ty(*i), + ty::Uint(u) => self.type_uint_from_ty(*u), + ty::RawPtr(_, _) => self.type_ptr(), + _ => unreachable!(), + }; + let loaded = + self.load_from_place(self.type_vector(elem_ll_ty, size), place); + OperandRef::from_immediate_or_packed_pair(self, loaded, arg.layout) + } else { + *arg + }, + ); + } + + let llret_ty = if ret_ty.is_simd() + && let abi::Abi::Aggregate { .. } = self.layout_of(ret_ty).layout.abi + { + let (size, elem_ty) = ret_ty.simd_size_and_type(self.tcx()); + let elem_ll_ty = match elem_ty.kind() { + ty::Float(f) => self.type_float_from_ty(*f), + ty::Int(i) => self.type_int_from_ty(*i), + ty::Uint(u) => self.type_uint_from_ty(*u), + ty::RawPtr(_, _) => self.type_ptr(), + _ => unreachable!(), + }; + self.type_vector(elem_ll_ty, size) + } else { + llret_ty + }; + match generic_simd_intrinsic( - self, name, callee_ty, fn_args, args, ret_ty, llret_ty, span, + self, + name, + callee_ty, + fn_args, + &loaded_args, + ret_ty, + llret_ty, + span, ) { Ok(llval) => llval, Err(()) => return Ok(()), diff --git a/tests/ui/simd/repr_packed.rs b/tests/ui/simd/repr_packed.rs index 411bba3454eb..52c794563de6 100644 --- a/tests/ui/simd/repr_packed.rs +++ b/tests/ui/simd/repr_packed.rs @@ -6,9 +6,6 @@ #[repr(simd, packed)] struct Simd([T; N]); -#[repr(simd)] -struct FullSimd([T; N]); - fn check_size_align() { use std::mem; assert_eq!(mem::size_of::>(), mem::size_of::<[T; N]>()); @@ -44,16 +41,9 @@ fn main() { simd_add(Simd::([0., 1., 2., 3.]), Simd::([2., 2., 2., 2.])); assert_eq!(std::mem::transmute::<_, [f64; 4]>(x), [2., 3., 4., 5.]); - // non-powers-of-two have padding and need to be expanded to full vectors - fn load(v: Simd) -> FullSimd { - unsafe { - let mut tmp = core::mem::MaybeUninit::>::uninit(); - std::ptr::copy_nonoverlapping(&v as *const _, tmp.as_mut_ptr().cast(), 1); - tmp.assume_init() - } - } - let x: FullSimd = - simd_add(load(Simd::([0., 1., 2.])), load(Simd::([2., 2., 2.]))); - assert_eq!(x.0, [2., 3., 4.]); + // non-powers-of-two have padding and lesser alignment, but the intrinsic handles it + let x: Simd = simd_add(Simd::([0., 1., 2.]), Simd::([2., 2., 2.])); + let arr: [f64; 3] = x.0; + assert_eq!(arr, [2., 3., 4.]); } } From 36293727238d2559f594d7019a551853cb0c57b3 Mon Sep 17 00:00:00 2001 From: schvv31n Date: Mon, 20 May 2024 08:05:49 +0100 Subject: [PATCH 019/211] Lint on closure calls, suppress on callable constants calls --- .../iter_on_single_or_empty_collections.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs b/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs index 0e929cfe798f..f16385b5f959 100644 --- a/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs +++ b/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs @@ -33,10 +33,10 @@ fn is_arg_ty_unified_in_fn<'tcx>( cx: &LateContext<'tcx>, fn_id: DefId, arg_id: HirId, - args: impl Iterator> + Clone, + args: impl IntoIterator>, ) -> bool { let fn_sig = cx.tcx.fn_sig(fn_id).instantiate_identity(); - let arg_id_in_args = args.clone().position(|e| e.hir_id == arg_id).unwrap(); + let arg_id_in_args = args.into_iter().position(|e| e.hir_id == arg_id).unwrap(); let arg_ty_in_args = fn_sig.input(arg_id_in_args); cx.tcx.predicates_of(fn_id).predicates.iter().any(|(clause, _)| { @@ -72,12 +72,11 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, method .. }, args, - ) => is_arg_ty_unified_in_fn( - cx, - cx.typeck_results().qpath_res(path, *hir_id).def_id(), - expr.hir_id, - args.iter(), - ), + ) => { + cx.typeck_results().qpath_res(path, *hir_id).opt_def_id() + .filter(|fn_id| cx.tcx.def_kind(fn_id).is_fn_like()) + .is_some_and(|fn_id| is_arg_ty_unified_in_fn(cx, fn_id, expr.hir_id, args)) + } ExprKind::MethodCall(_name, recv, args, _span) => is_arg_ty_unified_in_fn( cx, cx.typeck_results().type_dependent_def_id(parent.hir_id).unwrap(), From 3955bd4c98a61ada7041c028a5d0c749c3c0ee11 Mon Sep 17 00:00:00 2001 From: schvv31n Date: Mon, 20 May 2024 08:07:48 +0100 Subject: [PATCH 020/211] fixed formatting --- .../methods/iter_on_single_or_empty_collections.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs b/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs index f16385b5f959..e8bba0dfe749 100644 --- a/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs +++ b/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs @@ -72,11 +72,12 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, method .. }, args, - ) => { - cx.typeck_results().qpath_res(path, *hir_id).opt_def_id() - .filter(|fn_id| cx.tcx.def_kind(fn_id).is_fn_like()) - .is_some_and(|fn_id| is_arg_ty_unified_in_fn(cx, fn_id, expr.hir_id, args)) - } + ) => cx + .typeck_results() + .qpath_res(path, *hir_id) + .opt_def_id() + .filter(|fn_id| cx.tcx.def_kind(fn_id).is_fn_like()) + .is_some_and(|fn_id| is_arg_ty_unified_in_fn(cx, fn_id, expr.hir_id, args)), ExprKind::MethodCall(_name, recv, args, _span) => is_arg_ty_unified_in_fn( cx, cx.typeck_results().type_dependent_def_id(parent.hir_id).unwrap(), From 20fd7251724a578dae4374e29ac70679ca21974b Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Mon, 20 May 2024 21:21:53 +0200 Subject: [PATCH 021/211] Document platform-specifics for `Read` and `Write` of `File` --- library/std/src/fs.rs | 76 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 77e94365b08e..0dcf554770c5 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -767,11 +767,33 @@ fn buffer_capacity_required(mut file: &File) -> Option { #[stable(feature = "rust1", since = "1.0.0")] impl Read for &File { + /// Read some bytes from the file. + /// + /// See [`Read::read`] docs for more info. + /// + /// # Platform-specific behavior + /// + /// This function currently corresponds to the `read` function on Unix and + /// the `NtReadFile` function on Windows. Note that this [may change in + /// the future][changes]. + /// + /// [changes]: io#platform-specific-behavior #[inline] fn read(&mut self, buf: &mut [u8]) -> io::Result { self.inner.read(buf) } + /// Like `read`, except that it reads into a slice of buffers. + /// + /// See [`Read::read_vectored`] docs for more info. + /// + /// # Platform-specific behavior + /// + /// This function currently corresponds to the `readv` function on Unix and + /// falls back to the `read` implementation on Windows. Note that this + /// [may change in the future][changes]. + /// + /// [changes]: io#platform-specific-behavior #[inline] fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { self.inner.read_vectored(bufs) @@ -782,6 +804,16 @@ impl Read for &File { self.inner.read_buf(cursor) } + /// Determines if `File` has an efficient `read_vectored` implementation. + /// + /// See [`Read::is_read_vectored`] docs for more info. + /// + /// # Platform-specific behavior + /// + /// This function currently returns `true` on Unix an `false` on Windows. + /// Note that this [may change in the future][changes]. + /// + /// [changes]: io#platform-specific-behavior #[inline] fn is_read_vectored(&self) -> bool { self.inner.is_read_vectored() @@ -803,19 +835,63 @@ impl Read for &File { } #[stable(feature = "rust1", since = "1.0.0")] impl Write for &File { + /// Write some bytes from the file. + /// + /// See [`Write::write`] docs for more info. + /// + /// # Platform-specific behavior + /// + /// This function currently corresponds to the `write` function on Unix and + /// the `NtWriteFile` function on Windows. Note that this [may change in + /// the future][changes]. + /// + /// [changes]: io#platform-specific-behavior fn write(&mut self, buf: &[u8]) -> io::Result { self.inner.write(buf) } + /// Like `write`, except that it writes into a slice of buffers. + /// + /// See [`Write::write_vectored`] docs for more info. + /// + /// # Platform-specific behavior + /// + /// This function currently corresponds to the `writev` function on Unix + /// and falls back to the `write` implementation on Windows. Note that this + /// [may change in the future][changes]. + /// + /// [changes]: io#platform-specific-behavior fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result { self.inner.write_vectored(bufs) } + /// Determines if `File` has an efficient `write_vectored` implementation. + /// + /// See [`Write::is_write_vectored`] docs for more info. + /// + /// # Platform-specific behavior + /// + /// This function currently returns `true` on Unix an `false` on Windows. + /// Note that this [may change in the future][changes]. + /// + /// [changes]: io#platform-specific-behavior #[inline] fn is_write_vectored(&self) -> bool { self.inner.is_write_vectored() } + /// Flushes the file, ensuring that all intermediately buffered contents + /// reach their destination. + /// + /// See [`Write::flush`] docs for more info. + /// + /// # Platform-specific behavior + /// + /// Since a `File` structure doesn't contain any buffers, this function is + /// currently a no-op on Unix and Windows. Note that this [may change in + /// the future][changes]. + /// + /// [changes]: io#platform-specific-behavior #[inline] fn flush(&mut self) -> io::Result<()> { self.inner.flush() From b31625cdc7034df5fae32c4d6d6ff0e7d43496d8 Mon Sep 17 00:00:00 2001 From: schvv31n Date: Mon, 20 May 2024 21:27:30 +0100 Subject: [PATCH 022/211] Accounted for possible extra layers before the consuming parent expr --- .../src/methods/iter_on_single_or_empty_collections.rs | 4 ++-- tests/ui/iter_on_empty_collections.fixed | 5 +++++ tests/ui/iter_on_empty_collections.rs | 5 +++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs b/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs index e8bba0dfe749..1bf323cf3c7d 100644 --- a/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs +++ b/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs @@ -77,11 +77,11 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, method .qpath_res(path, *hir_id) .opt_def_id() .filter(|fn_id| cx.tcx.def_kind(fn_id).is_fn_like()) - .is_some_and(|fn_id| is_arg_ty_unified_in_fn(cx, fn_id, expr.hir_id, args)), + .is_some_and(|fn_id| is_arg_ty_unified_in_fn(cx, fn_id, child_id, args)), ExprKind::MethodCall(_name, recv, args, _span) => is_arg_ty_unified_in_fn( cx, cx.typeck_results().type_dependent_def_id(parent.hir_id).unwrap(), - expr.hir_id, + child_id, once(recv).chain(args.iter()), ), ExprKind::If(_, _, _) diff --git a/tests/ui/iter_on_empty_collections.fixed b/tests/ui/iter_on_empty_collections.fixed index 871cc18d7c2d..4b5746c7b6f4 100644 --- a/tests/ui/iter_on_empty_collections.fixed +++ b/tests/ui/iter_on_empty_collections.fixed @@ -29,6 +29,11 @@ fn array() { println!("{i}"); } + // Same as above, but for empty collection iters with extra layers + for i in smth.as_ref().map_or({ [].iter() }, |s| s.iter()) { + println!("{y}", y = i + 1); + } + // Same as above, but for regular function calls for i in Option::map_or(smth.as_ref(), [].iter(), |s| s.iter()) { println!("{i}"); diff --git a/tests/ui/iter_on_empty_collections.rs b/tests/ui/iter_on_empty_collections.rs index 7e3df49eefcd..737192d556d3 100644 --- a/tests/ui/iter_on_empty_collections.rs +++ b/tests/ui/iter_on_empty_collections.rs @@ -29,6 +29,11 @@ fn array() { println!("{i}"); } + // Same as above, but for empty collection iters with extra layers + for i in smth.as_ref().map_or({ [].iter() }, |s| s.iter()) { + println!("{y}", y = i + 1); + } + // Same as above, but for regular function calls for i in Option::map_or(smth.as_ref(), [].iter(), |s| s.iter()) { println!("{i}"); From ca1337a7bc08ab59472a701ee0b843d7ac10a5bc Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 17 Apr 2024 19:54:06 -0400 Subject: [PATCH 023/211] Remove a clippy test that doesn't apply anymore --- tests/ui/into_iter_on_ref.fixed | 1 - tests/ui/into_iter_on_ref.rs | 1 - tests/ui/into_iter_on_ref.stderr | 58 ++++++++++++++------------------ 3 files changed, 26 insertions(+), 34 deletions(-) diff --git a/tests/ui/into_iter_on_ref.fixed b/tests/ui/into_iter_on_ref.fixed index c03d91c797c8..72b39c982bf7 100644 --- a/tests/ui/into_iter_on_ref.fixed +++ b/tests/ui/into_iter_on_ref.fixed @@ -11,7 +11,6 @@ fn main() { let _ = vec![1, 2, 3].into_iter(); let _ = (&vec![1, 2, 3]).iter(); //~ ERROR: equivalent to `.iter() - let _ = vec![1, 2, 3].into_boxed_slice().iter(); //~ ERROR: equivalent to `.iter() let _ = std::rc::Rc::from(&[X][..]).iter(); //~ ERROR: equivalent to `.iter() let _ = std::sync::Arc::from(&[X][..]).iter(); //~ ERROR: equivalent to `.iter() diff --git a/tests/ui/into_iter_on_ref.rs b/tests/ui/into_iter_on_ref.rs index 93c732fd6ccf..5ba224720d34 100644 --- a/tests/ui/into_iter_on_ref.rs +++ b/tests/ui/into_iter_on_ref.rs @@ -11,7 +11,6 @@ fn main() { let _ = vec![1, 2, 3].into_iter(); let _ = (&vec![1, 2, 3]).into_iter(); //~ ERROR: equivalent to `.iter() - let _ = vec![1, 2, 3].into_boxed_slice().into_iter(); //~ ERROR: equivalent to `.iter() let _ = std::rc::Rc::from(&[X][..]).into_iter(); //~ ERROR: equivalent to `.iter() let _ = std::sync::Arc::from(&[X][..]).into_iter(); //~ ERROR: equivalent to `.iter() diff --git a/tests/ui/into_iter_on_ref.stderr b/tests/ui/into_iter_on_ref.stderr index 0e9d485f1a9d..64d814074da4 100644 --- a/tests/ui/into_iter_on_ref.stderr +++ b/tests/ui/into_iter_on_ref.stderr @@ -8,160 +8,154 @@ LL | let _ = (&vec![1, 2, 3]).into_iter(); = help: to override `-D warnings` add `#[allow(clippy::into_iter_on_ref)]` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `slice` - --> tests/ui/into_iter_on_ref.rs:14:46 - | -LL | let _ = vec![1, 2, 3].into_boxed_slice().into_iter(); - | ^^^^^^^^^ help: call directly: `iter` - -error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `slice` - --> tests/ui/into_iter_on_ref.rs:15:41 + --> tests/ui/into_iter_on_ref.rs:14:41 | LL | let _ = std::rc::Rc::from(&[X][..]).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `slice` - --> tests/ui/into_iter_on_ref.rs:16:44 + --> tests/ui/into_iter_on_ref.rs:15:44 | LL | let _ = std::sync::Arc::from(&[X][..]).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `array` - --> tests/ui/into_iter_on_ref.rs:18:32 + --> tests/ui/into_iter_on_ref.rs:17:32 | LL | let _ = (&&&&&&&[1, 2, 3]).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `array` - --> tests/ui/into_iter_on_ref.rs:19:36 + --> tests/ui/into_iter_on_ref.rs:18:36 | LL | let _ = (&&&&mut &&&[1, 2, 3]).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `array` - --> tests/ui/into_iter_on_ref.rs:20:40 + --> tests/ui/into_iter_on_ref.rs:19:40 | LL | let _ = (&mut &mut &mut [1, 2, 3]).into_iter(); | ^^^^^^^^^ help: call directly: `iter_mut` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `Option` - --> tests/ui/into_iter_on_ref.rs:22:24 + --> tests/ui/into_iter_on_ref.rs:21:24 | LL | let _ = (&Some(4)).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `Option` - --> tests/ui/into_iter_on_ref.rs:23:28 + --> tests/ui/into_iter_on_ref.rs:22:28 | LL | let _ = (&mut Some(5)).into_iter(); | ^^^^^^^^^ help: call directly: `iter_mut` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `Result` - --> tests/ui/into_iter_on_ref.rs:24:32 + --> tests/ui/into_iter_on_ref.rs:23:32 | LL | let _ = (&Ok::<_, i32>(6)).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `Result` - --> tests/ui/into_iter_on_ref.rs:25:37 + --> tests/ui/into_iter_on_ref.rs:24:37 | LL | let _ = (&mut Err::(7)).into_iter(); | ^^^^^^^^^ help: call directly: `iter_mut` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `Vec` - --> tests/ui/into_iter_on_ref.rs:26:34 + --> tests/ui/into_iter_on_ref.rs:25:34 | LL | let _ = (&Vec::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `Vec` - --> tests/ui/into_iter_on_ref.rs:27:38 + --> tests/ui/into_iter_on_ref.rs:26:38 | LL | let _ = (&mut Vec::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter_mut` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `BTreeMap` - --> tests/ui/into_iter_on_ref.rs:28:44 + --> tests/ui/into_iter_on_ref.rs:27:44 | LL | let _ = (&BTreeMap::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `BTreeMap` - --> tests/ui/into_iter_on_ref.rs:29:48 + --> tests/ui/into_iter_on_ref.rs:28:48 | LL | let _ = (&mut BTreeMap::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter_mut` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `VecDeque` - --> tests/ui/into_iter_on_ref.rs:30:39 + --> tests/ui/into_iter_on_ref.rs:29:39 | LL | let _ = (&VecDeque::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `VecDeque` - --> tests/ui/into_iter_on_ref.rs:31:43 + --> tests/ui/into_iter_on_ref.rs:30:43 | LL | let _ = (&mut VecDeque::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter_mut` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `LinkedList` - --> tests/ui/into_iter_on_ref.rs:32:41 + --> tests/ui/into_iter_on_ref.rs:31:41 | LL | let _ = (&LinkedList::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `LinkedList` - --> tests/ui/into_iter_on_ref.rs:33:45 + --> tests/ui/into_iter_on_ref.rs:32:45 | LL | let _ = (&mut LinkedList::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter_mut` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `HashMap` - --> tests/ui/into_iter_on_ref.rs:34:43 + --> tests/ui/into_iter_on_ref.rs:33:43 | LL | let _ = (&HashMap::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter_mut()` and will not consume the `HashMap` - --> tests/ui/into_iter_on_ref.rs:35:47 + --> tests/ui/into_iter_on_ref.rs:34:47 | LL | let _ = (&mut HashMap::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter_mut` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `BTreeSet` - --> tests/ui/into_iter_on_ref.rs:37:39 + --> tests/ui/into_iter_on_ref.rs:36:39 | LL | let _ = (&BTreeSet::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `BinaryHeap` - --> tests/ui/into_iter_on_ref.rs:38:41 + --> tests/ui/into_iter_on_ref.rs:37:41 | LL | let _ = (&BinaryHeap::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `HashSet` - --> tests/ui/into_iter_on_ref.rs:39:38 + --> tests/ui/into_iter_on_ref.rs:38:38 | LL | let _ = (&HashSet::::new()).into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `Path` - --> tests/ui/into_iter_on_ref.rs:40:43 + --> tests/ui/into_iter_on_ref.rs:39:43 | LL | let _ = std::path::Path::new("12/34").into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `PathBuf` - --> tests/ui/into_iter_on_ref.rs:41:47 + --> tests/ui/into_iter_on_ref.rs:40:47 | LL | let _ = std::path::PathBuf::from("12/34").into_iter(); | ^^^^^^^^^ help: call directly: `iter` error: this `.into_iter()` call is equivalent to `.iter()` and will not consume the `array` - --> tests/ui/into_iter_on_ref.rs:43:26 + --> tests/ui/into_iter_on_ref.rs:42:26 | LL | let _ = (&[1, 2, 3]).into_iter().next(); | ^^^^^^^^^ help: call directly: `iter` -error: aborting due to 27 previous errors +error: aborting due to 26 previous errors From 4f98cc6d55aa82612fac031a5828f5fc9deee4bc Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 16 May 2024 16:24:58 +0200 Subject: [PATCH 024/211] Correctly handle closing parens in `missing_backticks` doc lint --- clippy_lints/src/doc/markdown.rs | 20 +++++++++++++ tests/ui/doc/issue_12795.fixed | 9 ++++++ tests/ui/doc/issue_12795.rs | 9 ++++++ tests/ui/doc/issue_12795.stderr | 48 ++++++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+) create mode 100644 tests/ui/doc/issue_12795.fixed create mode 100644 tests/ui/doc/issue_12795.rs create mode 100644 tests/ui/doc/issue_12795.stderr diff --git a/clippy_lints/src/doc/markdown.rs b/clippy_lints/src/doc/markdown.rs index 1add02af3101..20ca88f21160 100644 --- a/clippy_lints/src/doc/markdown.rs +++ b/clippy_lints/src/doc/markdown.rs @@ -30,6 +30,7 @@ pub fn check( word = tmp_word; } + let original_len = word.len(); word = word.trim_start_matches(trim_pattern); // Remove leading or trailing single `:` which may be part of a sentence. @@ -44,6 +45,25 @@ pub fn check( continue; } + // Ensure that all reachable matching closing parens are included as well. + let size_diff = original_len - word.len(); + let mut open_parens = 0; + let mut close_parens = 0; + for c in word.chars() { + if c == '(' { + open_parens += 1; + } else if c == ')' { + close_parens += 1; + } + } + while close_parens < open_parens + && let Some(tmp_word) = orig_word.get(size_diff..=(word.len() + size_diff)) + && tmp_word.ends_with(')') + { + word = tmp_word; + close_parens += 1; + } + // Adjust for the current word let offset = word.as_ptr() as usize - text.as_ptr() as usize; let span = Span::new( diff --git a/tests/ui/doc/issue_12795.fixed b/tests/ui/doc/issue_12795.fixed new file mode 100644 index 000000000000..ade23bf975c2 --- /dev/null +++ b/tests/ui/doc/issue_12795.fixed @@ -0,0 +1,9 @@ +#![warn(clippy::doc_markdown)] + +//! A comment with `a_b(x)` and `a_c` in it and (`a_b((c))` ) too and (maybe `a_b((c))`) +//~^ ERROR: item in documentation is missing backticks +//~| ERROR: item in documentation is missing backticks +//~| ERROR: item in documentation is missing backticks +//~| ERROR: item in documentation is missing backticks + +pub fn main() {} diff --git a/tests/ui/doc/issue_12795.rs b/tests/ui/doc/issue_12795.rs new file mode 100644 index 000000000000..6d94a07e3036 --- /dev/null +++ b/tests/ui/doc/issue_12795.rs @@ -0,0 +1,9 @@ +#![warn(clippy::doc_markdown)] + +//! A comment with a_b(x) and a_c in it and (a_b((c)) ) too and (maybe a_b((c))) +//~^ ERROR: item in documentation is missing backticks +//~| ERROR: item in documentation is missing backticks +//~| ERROR: item in documentation is missing backticks +//~| ERROR: item in documentation is missing backticks + +pub fn main() {} diff --git a/tests/ui/doc/issue_12795.stderr b/tests/ui/doc/issue_12795.stderr new file mode 100644 index 000000000000..5700145ec8f7 --- /dev/null +++ b/tests/ui/doc/issue_12795.stderr @@ -0,0 +1,48 @@ +error: item in documentation is missing backticks + --> tests/ui/doc/issue_12795.rs:3:20 + | +LL | //! A comment with a_b(x) and a_c in it and (a_b((c)) ) too and (maybe a_b((c))) + | ^^^^^^ + | + = note: `-D clippy::doc-markdown` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::doc_markdown)]` +help: try + | +LL | //! A comment with `a_b(x)` and a_c in it and (a_b((c)) ) too and (maybe a_b((c))) + | ~~~~~~~~ + +error: item in documentation is missing backticks + --> tests/ui/doc/issue_12795.rs:3:31 + | +LL | //! A comment with a_b(x) and a_c in it and (a_b((c)) ) too and (maybe a_b((c))) + | ^^^ + | +help: try + | +LL | //! A comment with a_b(x) and `a_c` in it and (a_b((c)) ) too and (maybe a_b((c))) + | ~~~~~ + +error: item in documentation is missing backticks + --> tests/ui/doc/issue_12795.rs:3:46 + | +LL | //! A comment with a_b(x) and a_c in it and (a_b((c)) ) too and (maybe a_b((c))) + | ^^^^^^^^ + | +help: try + | +LL | //! A comment with a_b(x) and a_c in it and (`a_b((c))` ) too and (maybe a_b((c))) + | ~~~~~~~~~~ + +error: item in documentation is missing backticks + --> tests/ui/doc/issue_12795.rs:3:72 + | +LL | //! A comment with a_b(x) and a_c in it and (a_b((c)) ) too and (maybe a_b((c))) + | ^^^^^^^^ + | +help: try + | +LL | //! A comment with a_b(x) and a_c in it and (a_b((c)) ) too and (maybe `a_b((c))`) + | ~~~~~~~~~~ + +error: aborting due to 4 previous errors + From a14ca6005c991596a8a0ec2bd9b3ccebdf05942e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 21 May 2024 14:07:02 +0200 Subject: [PATCH 025/211] don't inhibit random field reordering on repr(packed(1)) --- clippy_lints/src/transmute/transmute_undefined_repr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/transmute/transmute_undefined_repr.rs b/clippy_lints/src/transmute/transmute_undefined_repr.rs index 9c8dd37d53dc..3b32e4396b9f 100644 --- a/clippy_lints/src/transmute/transmute_undefined_repr.rs +++ b/clippy_lints/src/transmute/transmute_undefined_repr.rs @@ -278,7 +278,7 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx> ty = sized_ty; continue; } - if def.repr().inhibit_struct_field_reordering_opt() { + if def.repr().inhibit_struct_field_reordering() { ReducedTy::OrderedFields(Some(sized_ty)) } else { ReducedTy::UnorderedFields(ty) From 4363278c73cf506f71215e9e21af90e31c4d74ea Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Tue, 21 May 2024 10:39:30 -0700 Subject: [PATCH 026/211] Merge commit '2efebd2f0c03dabbe5c3ad7b4ebfbd99238d1fb2' into clippy-subtree-update --- .github/driver.sh | 19 +- .github/workflows/clippy.yml | 6 +- .github/workflows/clippy_bors.yml | 4 +- CHANGELOG.md | 7 + book/src/lint_configuration.md | 42 ++ clippy_config/src/conf.rs | 31 + clippy_config/src/msrvs.rs | 3 +- clippy_dev/Cargo.toml | 3 +- clippy_dev/src/main.rs | 578 ++++++++---------- clippy_dev/src/new_lint.rs | 14 +- clippy_dev/src/serve.rs | 2 +- clippy_dev/src/update_lints.rs | 4 +- clippy_lints/src/assigning_clones.rs | 37 +- .../src/attrs/duplicated_attributes.rs | 3 +- clippy_lints/src/attrs/mod.rs | 12 +- clippy_lints/src/attrs/useless_attribute.rs | 49 +- .../src/cargo/lint_groups_priority.rs | 13 +- clippy_lints/src/casts/cast_sign_loss.rs | 4 + clippy_lints/src/declared_lints.rs | 4 + clippy_lints/src/doc/lazy_continuation.rs | 95 +++ clippy_lints/src/doc/missing_headers.rs | 9 +- clippy_lints/src/doc/mod.rs | 129 +++- clippy_lints/src/escape.rs | 4 +- clippy_lints/src/explicit_write.rs | 20 +- clippy_lints/src/format.rs | 19 +- clippy_lints/src/format_args.rs | 13 +- clippy_lints/src/format_impl.rs | 10 +- clippy_lints/src/from_str_radix_10.rs | 5 +- clippy_lints/src/functions/mod.rs | 59 +- .../src/functions/renamed_function_params.rs | 110 ++++ clippy_lints/src/future_not_send.rs | 2 +- clippy_lints/src/lib.rs | 55 +- clippy_lints/src/loops/mod.rs | 36 ++ clippy_lints/src/loops/mut_range_bound.rs | 9 +- clippy_lints/src/loops/while_float.rs | 20 + clippy_lints/src/macro_metavars_in_unsafe.rs | 256 ++++++++ clippy_lints/src/manual_clamp.rs | 7 + clippy_lints/src/matches/match_same_arms.rs | 37 +- .../matches/significant_drop_in_scrutinee.rs | 86 +-- clippy_lints/src/methods/expect_fun_call.rs | 7 +- clippy_lints/src/methods/iter_filter.rs | 8 +- clippy_lints/src/methods/iter_kv_map.rs | 2 + .../src/methods/iter_overeager_cloned.rs | 9 +- clippy_lints/src/methods/mod.rs | 15 +- .../src/methods/unnecessary_iter_cloned.rs | 53 +- clippy_lints/src/methods/utils.rs | 1 + .../src/needless_borrows_for_generic_args.rs | 51 +- clippy_lints/src/needless_continue.rs | 3 +- clippy_lints/src/needless_late_init.rs | 69 +-- clippy_lints/src/needless_pass_by_ref_mut.rs | 8 +- clippy_lints/src/needless_pass_by_value.rs | 4 +- clippy_lints/src/no_effect.rs | 8 +- clippy_lints/src/panic_unimplemented.rs | 14 +- clippy_lints/src/strings.rs | 8 + .../transmute/transmute_int_to_non_zero.rs | 2 +- clippy_lints/src/unwrap.rs | 6 +- .../src/utils/format_args_collector.rs | 27 +- clippy_lints/src/write.rs | 14 +- clippy_utils/src/lib.rs | 18 + clippy_utils/src/macros.rs | 78 ++- clippy_utils/src/qualify_min_const_fn.rs | 82 +-- clippy_utils/src/source.rs | 2 +- clippy_utils/src/sugg.rs | 3 +- clippy_utils/src/ty.rs | 15 +- clippy_utils/src/usage.rs | 10 +- lintcheck/Cargo.toml | 2 +- rust-toolchain | 2 +- .../lint_groups_priority/fail/Cargo.stderr | 30 +- .../lint_groups_priority/fail/Cargo.toml | 8 + .../macro_metavars_in_unsafe/default/test.rs | 260 ++++++++ .../default/test.stderr | 187 ++++++ .../private/clippy.toml | 1 + .../macro_metavars_in_unsafe/private/test.rs | 15 + .../private/test.stderr | 17 + tests/ui-toml/panic/clippy.toml | 1 + tests/ui-toml/panic/panic.rs | 54 ++ tests/ui-toml/panic/panic.stderr | 11 + .../default/clippy.toml | 2 + .../extend/clippy.toml | 2 + .../renamed_function_params.default.stderr | 46 ++ .../renamed_function_params.extend.stderr | 34 ++ .../renamed_function_params.rs | 110 ++++ .../conf_disallowed_types.rs | 6 + .../toml_unknown_key/conf_unknown_key.stderr | 9 + tests/ui/assigning_clones.fixed | 26 + tests/ui/assigning_clones.rs | 26 + tests/ui/assigning_clones.stderr | 46 +- tests/ui/doc/doc_lazy_blockquote.fixed | 47 ++ tests/ui/doc/doc_lazy_blockquote.rs | 47 ++ tests/ui/doc/doc_lazy_blockquote.stderr | 76 +++ tests/ui/doc/doc_lazy_list.fixed | 77 +++ tests/ui/doc/doc_lazy_list.rs | 77 +++ tests/ui/doc/doc_lazy_list.stderr | 136 +++++ tests/ui/duplicated_attributes.rs | 6 +- tests/ui/from_str_radix_10.fixed | 11 + tests/ui/from_str_radix_10.rs | 11 + tests/ui/from_str_radix_10.stderr | 16 +- tests/ui/match_same_arms.stderr | 132 ++-- tests/ui/match_same_arms2.fixed | 241 ++++++++ tests/ui/match_same_arms2.rs | 5 +- tests/ui/match_same_arms2.stderr | 283 +++++---- tests/ui/match_same_arms_non_exhaustive.fixed | 61 ++ tests/ui/match_same_arms_non_exhaustive.rs | 1 - .../ui/match_same_arms_non_exhaustive.stderr | 18 +- .../ui/missing_const_for_fn/cant_be_const.rs | 18 +- .../ui/missing_const_for_fn/could_be_const.rs | 28 + .../could_be_const.stderr | 30 +- tests/ui/missing_panics_doc.rs | 8 + .../needless_borrows_for_generic_args.fixed | 42 +- tests/ui/needless_borrows_for_generic_args.rs | 36 +- .../needless_borrows_for_generic_args.stderr | 32 +- tests/ui/needless_late_init.stderr | 177 +++--- tests/ui/no_effect.rs | 13 - tests/ui/no_effect.stderr | 68 +-- tests/ui/significant_drop_in_scrutinee.rs | 56 ++ tests/ui/significant_drop_in_scrutinee.stderr | 28 +- tests/ui/unnecessary_iter_cloned.fixed | 32 + tests/ui/unnecessary_iter_cloned.rs | 32 + tests/ui/unnecessary_iter_cloned.stderr | 4 +- tests/ui/useless_attribute.fixed | 43 ++ tests/ui/useless_attribute.rs | 43 ++ tests/ui/while_float.rs | 14 + tests/ui/while_float.stderr | 20 + util/gh-pages/script.js | 2 +- 124 files changed, 4052 insertions(+), 1147 deletions(-) create mode 100644 clippy_lints/src/doc/lazy_continuation.rs create mode 100644 clippy_lints/src/functions/renamed_function_params.rs create mode 100644 clippy_lints/src/loops/while_float.rs create mode 100644 clippy_lints/src/macro_metavars_in_unsafe.rs create mode 100644 tests/ui-toml/macro_metavars_in_unsafe/default/test.rs create mode 100644 tests/ui-toml/macro_metavars_in_unsafe/default/test.stderr create mode 100644 tests/ui-toml/macro_metavars_in_unsafe/private/clippy.toml create mode 100644 tests/ui-toml/macro_metavars_in_unsafe/private/test.rs create mode 100644 tests/ui-toml/macro_metavars_in_unsafe/private/test.stderr create mode 100644 tests/ui-toml/panic/clippy.toml create mode 100644 tests/ui-toml/panic/panic.rs create mode 100644 tests/ui-toml/panic/panic.stderr create mode 100644 tests/ui-toml/renamed_function_params/default/clippy.toml create mode 100644 tests/ui-toml/renamed_function_params/extend/clippy.toml create mode 100644 tests/ui-toml/renamed_function_params/renamed_function_params.default.stderr create mode 100644 tests/ui-toml/renamed_function_params/renamed_function_params.extend.stderr create mode 100644 tests/ui-toml/renamed_function_params/renamed_function_params.rs create mode 100644 tests/ui/doc/doc_lazy_blockquote.fixed create mode 100644 tests/ui/doc/doc_lazy_blockquote.rs create mode 100644 tests/ui/doc/doc_lazy_blockquote.stderr create mode 100644 tests/ui/doc/doc_lazy_list.fixed create mode 100644 tests/ui/doc/doc_lazy_list.rs create mode 100644 tests/ui/doc/doc_lazy_list.stderr create mode 100644 tests/ui/match_same_arms2.fixed create mode 100644 tests/ui/match_same_arms_non_exhaustive.fixed create mode 100644 tests/ui/while_float.rs create mode 100644 tests/ui/while_float.stderr diff --git a/.github/driver.sh b/.github/driver.sh index 2eafdd0fbc87..09202b1878b2 100755 --- a/.github/driver.sh +++ b/.github/driver.sh @@ -2,15 +2,18 @@ set -ex -# Check sysroot handling -sysroot=$(./target/debug/clippy-driver --print sysroot) -test "$sysroot" = "$(rustc --print sysroot)" +sysroot="$(rustc --print sysroot)" +case $OS in + Linux) export LD_LIBRARY_PATH="$sysroot/lib" ;; + macOS) export DYLD_FALLBACK_LIBRARY_PATH="$sysroot/lib" ;; + Windows) export PATH="$(cygpath "$sysroot")/bin:$PATH" ;; + *) exit 1 +esac -if [[ ${OS} == "Windows" ]]; then - desired_sysroot=C:/tmp -else - desired_sysroot=/tmp -fi +# Check sysroot handling +test "$(./target/debug/clippy-driver --print sysroot)" = "$sysroot" + +desired_sysroot="target/sysroot" # Set --sysroot in command line sysroot=$(./target/debug/clippy-driver --sysroot $desired_sysroot --print sysroot) test "$sysroot" = $desired_sysroot diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml index 8179e3e65b54..06bf3b6fdbfa 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/clippy.yml @@ -69,6 +69,6 @@ jobs: working-directory: clippy_dev - name: Test clippy-driver - run: | - TOOLCHAIN=$(rustup show active-toolchain | cut -f1 -d' ') - rustup run $TOOLCHAIN bash .github/driver.sh + run: .github/driver.sh + env: + OS: ${{ runner.os }} diff --git a/.github/workflows/clippy_bors.yml b/.github/workflows/clippy_bors.yml index 94515987eba4..1f4bec929182 100644 --- a/.github/workflows/clippy_bors.yml +++ b/.github/workflows/clippy_bors.yml @@ -116,9 +116,7 @@ jobs: working-directory: clippy_dev - name: Test clippy-driver - run: | - TOOLCHAIN=$(rustup show active-toolchain | cut -f1 -d' ') - rustup run $TOOLCHAIN bash .github/driver.sh + run: .github/driver.sh env: OS: ${{ runner.os }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c9ea1140814..d5115f70f662 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5249,6 +5249,7 @@ Released 2018-09-13 [`disallowed_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_type [`disallowed_types`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_types [`diverging_sub_expression`]: https://rust-lang.github.io/rust-clippy/master/index.html#diverging_sub_expression +[`doc_lazy_continuation`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_lazy_continuation [`doc_link_with_quotes`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_link_with_quotes [`doc_markdown`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown [`double_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_comparisons @@ -5447,6 +5448,7 @@ Released 2018-09-13 [`little_endian_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#little_endian_bytes [`logic_bug`]: https://rust-lang.github.io/rust-clippy/master/index.html#logic_bug [`lossy_float_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#lossy_float_literal +[`macro_metavars_in_unsafe`]: https://rust-lang.github.io/rust-clippy/master/index.html#macro_metavars_in_unsafe [`macro_use_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#macro_use_imports [`main_recursion`]: https://rust-lang.github.io/rust-clippy/master/index.html#main_recursion [`manual_assert`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_assert @@ -5702,6 +5704,7 @@ Released 2018-09-13 [`ref_option_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_option_ref [`ref_patterns`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_patterns [`regex_macro`]: https://rust-lang.github.io/rust-clippy/master/index.html#regex_macro +[`renamed_function_params`]: https://rust-lang.github.io/rust-clippy/master/index.html#renamed_function_params [`repeat_once`]: https://rust-lang.github.io/rust-clippy/master/index.html#repeat_once [`repeat_vec_with_capacity`]: https://rust-lang.github.io/rust-clippy/master/index.html#repeat_vec_with_capacity [`replace_consts`]: https://rust-lang.github.io/rust-clippy/master/index.html#replace_consts @@ -5908,6 +5911,7 @@ Released 2018-09-13 [`verbose_file_reads`]: https://rust-lang.github.io/rust-clippy/master/index.html#verbose_file_reads [`vtable_address_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#vtable_address_comparisons [`waker_clone_wake`]: https://rust-lang.github.io/rust-clippy/master/index.html#waker_clone_wake +[`while_float`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_float [`while_immutable_condition`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_immutable_condition [`while_let_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_let_loop [`while_let_on_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_let_on_iterator @@ -5939,8 +5943,10 @@ Released 2018-09-13 [`allow-expect-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-expect-in-tests [`allow-mixed-uninlined-format-args`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-mixed-uninlined-format-args [`allow-one-hash-in-raw-strings`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-one-hash-in-raw-strings +[`allow-panic-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-panic-in-tests [`allow-print-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-print-in-tests [`allow-private-module-inception`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-private-module-inception +[`allow-renamed-params-for`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-renamed-params-for [`allow-unwrap-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-unwrap-in-tests [`allow-useless-vec-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-useless-vec-in-tests [`allowed-dotfiles`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-dotfiles @@ -6002,4 +6008,5 @@ Released 2018-09-13 [`vec-box-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#vec-box-size-threshold [`verbose-bit-mask-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#verbose-bit-mask-threshold [`warn-on-all-wildcard-imports`]: https://doc.rust-lang.org/clippy/lint_configuration.html#warn-on-all-wildcard-imports +[`warn-unsafe-macro-metavars-in-private-macros`]: https://doc.rust-lang.org/clippy/lint_configuration.html#warn-unsafe-macro-metavars-in-private-macros diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index f6af9810ca16..c8223007df7b 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -101,6 +101,16 @@ Whether to allow `r#""#` when `r""` can be used * [`unnecessary_raw_string_hashes`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_raw_string_hashes) +## `allow-panic-in-tests` +Whether `panic` should be allowed in test functions or `#[cfg(test)]` + +**Default Value:** `false` + +--- +**Affected lints:** +* [`panic`](https://rust-lang.github.io/rust-clippy/master/index.html#panic) + + ## `allow-print-in-tests` Whether print macros (ex. `println!`) should be allowed in test functions or `#[cfg(test)]` @@ -122,6 +132,28 @@ Whether to allow module inception if it's not public. * [`module_inception`](https://rust-lang.github.io/rust-clippy/master/index.html#module_inception) +## `allow-renamed-params-for` +List of trait paths to ignore when checking renamed function parameters. + +#### Example + +```toml +allow-renamed-params-for = [ "std::convert::From" ] +``` + +#### Noteworthy + +- By default, the following traits are ignored: `From`, `TryFrom`, `FromStr` +- `".."` can be used as part of the list to indicate that the configured values should be appended to the +default configuration of Clippy. By default, any configuration will replace the default value. + +**Default Value:** `["core::convert::From", "core::convert::TryFrom", "core::str::FromStr"]` + +--- +**Affected lints:** +* [`renamed_function_params`](https://rust-lang.github.io/rust-clippy/master/index.html#renamed_function_params) + + ## `allow-unwrap-in-tests` Whether `unwrap` should be allowed in test functions or `#[cfg(test)]` @@ -900,3 +932,13 @@ Whether to allow certain wildcard imports (prelude, super in tests). * [`wildcard_imports`](https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_imports) +## `warn-unsafe-macro-metavars-in-private-macros` +Whether to also emit warnings for unsafe blocks with metavariable expansions in **private** macros. + +**Default Value:** `false` + +--- +**Affected lints:** +* [`macro_metavars_in_unsafe`](https://rust-lang.github.io/rust-clippy/master/index.html#macro_metavars_in_unsafe) + + diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index 5cfcbdb57d73..cfdf620b7d07 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -40,6 +40,8 @@ const DEFAULT_DOC_VALID_IDENTS: &[&str] = &[ const DEFAULT_DISALLOWED_NAMES: &[&str] = &["foo", "baz", "quux"]; const DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS: &[&str] = &["i", "j", "x", "y", "z", "w", "n"]; const DEFAULT_ALLOWED_PREFIXES: &[&str] = &["to", "as", "into", "from", "try_into", "try_from"]; +const DEFAULT_ALLOWED_TRAITS_WITH_RENAMED_PARAMS: &[&str] = + &["core::convert::From", "core::convert::TryFrom", "core::str::FromStr"]; /// Conf with parse errors #[derive(Default)] @@ -455,6 +457,10 @@ define_Conf! { /// /// Whether `unwrap` should be allowed in test functions or `#[cfg(test)]` (allow_unwrap_in_tests: bool = false), + /// Lint: PANIC. + /// + /// Whether `panic` should be allowed in test functions or `#[cfg(test)]` + (allow_panic_in_tests: bool = false), /// Lint: DBG_MACRO. /// /// Whether `dbg!` should be allowed in test functions or `#[cfg(test)]` @@ -613,6 +619,27 @@ define_Conf! { /// - Use `".."` as part of the list to indicate that the configured values should be appended to the /// default configuration of Clippy. By default, any configuration will replace the default value (allowed_prefixes: Vec = DEFAULT_ALLOWED_PREFIXES.iter().map(ToString::to_string).collect()), + /// Lint: RENAMED_FUNCTION_PARAMS. + /// + /// List of trait paths to ignore when checking renamed function parameters. + /// + /// #### Example + /// + /// ```toml + /// allow-renamed-params-for = [ "std::convert::From" ] + /// ``` + /// + /// #### Noteworthy + /// + /// - By default, the following traits are ignored: `From`, `TryFrom`, `FromStr` + /// - `".."` can be used as part of the list to indicate that the configured values should be appended to the + /// default configuration of Clippy. By default, any configuration will replace the default value. + (allow_renamed_params_for: Vec = + DEFAULT_ALLOWED_TRAITS_WITH_RENAMED_PARAMS.iter().map(ToString::to_string).collect()), + /// Lint: MACRO_METAVARS_IN_UNSAFE. + /// + /// Whether to also emit warnings for unsafe blocks with metavariable expansions in **private** macros. + (warn_unsafe_macro_metavars_in_private_macros: bool = false), } /// Search for the configuration file. @@ -674,6 +701,10 @@ fn deserialize(file: &SourceFile) -> TryConf { extend_vec_if_indicator_present(&mut conf.conf.doc_valid_idents, DEFAULT_DOC_VALID_IDENTS); extend_vec_if_indicator_present(&mut conf.conf.disallowed_names, DEFAULT_DISALLOWED_NAMES); extend_vec_if_indicator_present(&mut conf.conf.allowed_prefixes, DEFAULT_ALLOWED_PREFIXES); + extend_vec_if_indicator_present( + &mut conf.conf.allow_renamed_params_for, + DEFAULT_ALLOWED_TRAITS_WITH_RENAMED_PARAMS, + ); // TODO: THIS SHOULD BE TESTED, this comment will be gone soon if conf.conf.allowed_idents_below_min_chars.contains("..") { conf.conf diff --git a/clippy_config/src/msrvs.rs b/clippy_config/src/msrvs.rs index 14808440d48d..a3e7d0c3fa5f 100644 --- a/clippy_config/src/msrvs.rs +++ b/clippy_config/src/msrvs.rs @@ -26,7 +26,8 @@ msrv_aliases! { 1,63,0 { CLONE_INTO } 1,62,0 { BOOL_THEN_SOME, DEFAULT_ENUM_ATTRIBUTE } 1,59,0 { THREAD_LOCAL_INITIALIZER_CAN_BE_MADE_CONST } - 1,58,0 { FORMAT_ARGS_CAPTURE, PATTERN_TRAIT_CHAR_ARRAY } + 1,58,0 { FORMAT_ARGS_CAPTURE, PATTERN_TRAIT_CHAR_ARRAY, CONST_RAW_PTR_DEREF } + 1,56,0 { CONST_FN_UNION } 1,55,0 { SEEK_REWIND } 1,54,0 { INTO_KEYS } 1,53,0 { OR_PATTERNS, MANUAL_BITS, BTREE_MAP_RETAIN, BTREE_SET_RETAIN, ARRAY_INTO_ITERATOR } diff --git a/clippy_dev/Cargo.toml b/clippy_dev/Cargo.toml index 42a953039b1c..4104e7d94f14 100644 --- a/clippy_dev/Cargo.toml +++ b/clippy_dev/Cargo.toml @@ -1,11 +1,12 @@ [package] name = "clippy_dev" +description = "Clippy developer tooling" version = "0.0.1" edition = "2021" [dependencies] aho-corasick = "1.0" -clap = "4.1.4" +clap = { version = "4.4", features = ["derive"] } indoc = "1.0" itertools = "0.12" opener = "0.6" diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index 397a0e990829..366b52b25dfc 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -2,350 +2,292 @@ // warn on lints, that are included in `rust-lang/rust`s bootstrap #![warn(rust_2018_idioms, unused_lifetimes)] -use clap::{Arg, ArgAction, ArgMatches, Command}; +use clap::{Args, Parser, Subcommand}; use clippy_dev::{dogfood, fmt, lint, new_lint, serve, setup, update_lints}; -use indoc::indoc; use std::convert::Infallible; fn main() { - let matches = get_clap_config(); + let dev = Dev::parse(); - match matches.subcommand() { - Some(("bless", _)) => { + match dev.command { + DevCommand::Bless => { eprintln!("use `cargo bless` to automatically replace `.stderr` and `.fixed` files as tests are being run"); }, - Some(("dogfood", matches)) => { - dogfood::dogfood( - matches.get_flag("fix"), - matches.get_flag("allow-dirty"), - matches.get_flag("allow-staged"), - ); - }, - Some(("fmt", matches)) => { - fmt::run(matches.get_flag("check"), matches.get_flag("verbose")); - }, - Some(("update_lints", matches)) => { - if matches.get_flag("print-only") { + DevCommand::Dogfood { + fix, + allow_dirty, + allow_staged, + } => dogfood::dogfood(fix, allow_dirty, allow_staged), + DevCommand::Fmt { check, verbose } => fmt::run(check, verbose), + DevCommand::UpdateLints { print_only, check } => { + if print_only { update_lints::print_lints(); - } else if matches.get_flag("check") { + } else if check { update_lints::update(update_lints::UpdateMode::Check); } else { update_lints::update(update_lints::UpdateMode::Change); } }, - Some(("new_lint", matches)) => { - match new_lint::create( - matches.get_one::("pass").unwrap(), - matches.get_one::("name"), - matches.get_one::("category").map(String::as_str), - matches.get_one::("type").map(String::as_str), - matches.get_flag("msrv"), - ) { - Ok(()) => update_lints::update(update_lints::UpdateMode::Change), - Err(e) => eprintln!("Unable to create lint: {e}"), - } + DevCommand::NewLint { + pass, + name, + category, + r#type, + msrv, + } => match new_lint::create(&pass, &name, &category, r#type.as_deref(), msrv) { + Ok(()) => update_lints::update(update_lints::UpdateMode::Change), + Err(e) => eprintln!("Unable to create lint: {e}"), }, - Some(("setup", sub_command)) => match sub_command.subcommand() { - Some(("git-hook", matches)) => { - if matches.get_flag("remove") { - setup::git_hook::remove_hook(); - } else { - setup::git_hook::install_hook(matches.get_flag("force-override")); - } - }, - Some(("intellij", matches)) => { - if matches.get_flag("remove") { + DevCommand::Setup(SetupCommand { subcommand }) => match subcommand { + SetupSubcommand::Intellij { remove, repo_path } => { + if remove { setup::intellij::remove_rustc_src(); } else { - setup::intellij::setup_rustc_src( - matches - .get_one::("rustc-repo-path") - .expect("this field is mandatory and therefore always valid"), - ); + setup::intellij::setup_rustc_src(&repo_path); } }, - Some(("toolchain", matches)) => { - setup::toolchain::create( - matches.get_flag("force"), - matches.get_flag("release"), - matches.get_one::("name").unwrap(), - ); + SetupSubcommand::GitHook { remove, force_override } => { + if remove { + setup::git_hook::remove_hook(); + } else { + setup::git_hook::install_hook(force_override); + } }, - Some(("vscode-tasks", matches)) => { - if matches.get_flag("remove") { + SetupSubcommand::Toolchain { force, release, name } => setup::toolchain::create(force, release, &name), + SetupSubcommand::VscodeTasks { remove, force_override } => { + if remove { setup::vscode::remove_tasks(); } else { - setup::vscode::install_tasks(matches.get_flag("force-override")); + setup::vscode::install_tasks(force_override); } }, - _ => {}, }, - Some(("remove", sub_command)) => match sub_command.subcommand() { - Some(("git-hook", _)) => setup::git_hook::remove_hook(), - Some(("intellij", _)) => setup::intellij::remove_rustc_src(), - Some(("vscode-tasks", _)) => setup::vscode::remove_tasks(), - _ => {}, + DevCommand::Remove(RemoveCommand { subcommand }) => match subcommand { + RemoveSubcommand::Intellij => setup::intellij::remove_rustc_src(), + RemoveSubcommand::GitHook => setup::git_hook::remove_hook(), + RemoveSubcommand::VscodeTasks => setup::vscode::remove_tasks(), }, - Some(("serve", matches)) => { - let port = *matches.get_one::("port").unwrap(); - let lint = matches.get_one::("lint"); - serve::run(port, lint); - }, - Some(("lint", matches)) => { - let path = matches.get_one::("path").unwrap(); - let args = matches.get_many::("args").into_iter().flatten(); - lint::run(path, args); - }, - Some(("rename_lint", matches)) => { - let old_name = matches.get_one::("old_name").unwrap(); - let new_name = matches.get_one::("new_name").unwrap_or(old_name); - let uplift = matches.get_flag("uplift"); - update_lints::rename(old_name, new_name, uplift); - }, - Some(("deprecate", matches)) => { - let name = matches.get_one::("name").unwrap(); - let reason = matches.get_one("reason"); - update_lints::deprecate(name, reason); - }, - _ => {}, + DevCommand::Serve { port, lint } => serve::run(port, lint), + DevCommand::Lint { path, args } => lint::run(&path, args.iter()), + DevCommand::RenameLint { + old_name, + new_name, + uplift, + } => update_lints::rename(&old_name, new_name.as_ref().unwrap_or(&old_name), uplift), + DevCommand::Deprecate { name, reason } => update_lints::deprecate(&name, reason.as_deref()), } } -fn get_clap_config() -> ArgMatches { - Command::new("Clippy developer tooling") - .arg_required_else_help(true) - .subcommands([ - Command::new("bless").about("bless the test output changes").arg( - Arg::new("ignore-timestamp") - .long("ignore-timestamp") - .action(ArgAction::SetTrue) - .help("Include files updated before clippy was built"), - ), - Command::new("dogfood").about("Runs the dogfood test").args([ - Arg::new("fix") - .long("fix") - .action(ArgAction::SetTrue) - .help("Apply the suggestions when possible"), - Arg::new("allow-dirty") - .long("allow-dirty") - .action(ArgAction::SetTrue) - .help("Fix code even if the working directory has changes") - .requires("fix"), - Arg::new("allow-staged") - .long("allow-staged") - .action(ArgAction::SetTrue) - .help("Fix code even if the working directory has staged changes") - .requires("fix"), - ]), - Command::new("fmt") - .about("Run rustfmt on all projects and tests") - .args([ - Arg::new("check") - .long("check") - .action(ArgAction::SetTrue) - .help("Use the rustfmt --check option"), - Arg::new("verbose") - .short('v') - .long("verbose") - .action(ArgAction::SetTrue) - .help("Echo commands run"), - ]), - Command::new("update_lints") - .about("Updates lint registration and information from the source code") - .long_about( - "Makes sure that:\n \ - * the lint count in README.md is correct\n \ - * the changelog contains markdown link references at the bottom\n \ - * all lint groups include the correct lints\n \ - * lint modules in `clippy_lints/*` are visible in `src/lib.rs` via `pub mod`\n \ - * all lints are registered in the lint store", - ) - .args([ - Arg::new("print-only") - .long("print-only") - .action(ArgAction::SetTrue) - .help( - "Print a table of lints to STDOUT. \ - This does not include deprecated and internal lints. \ - (Does not modify any files)", - ), - Arg::new("check") - .long("check") - .action(ArgAction::SetTrue) - .help("Checks that `cargo dev update_lints` has been run. Used on CI."), - ]), - Command::new("new_lint") - .about("Create new lint and run `cargo dev update_lints`") - .args([ - Arg::new("pass") - .short('p') - .long("pass") - .help("Specify whether the lint runs during the early or late pass") - .value_parser(["early", "late"]) - .conflicts_with("type") - .default_value("late"), - Arg::new("name") - .short('n') - .long("name") - .help("Name of the new lint in snake case, ex: fn_too_long") - .required(true) - .value_parser(|name: &str| Ok::<_, Infallible>(name.replace('-', "_"))), - Arg::new("category") - .short('c') - .long("category") - .help("What category the lint belongs to") - .default_value("nursery") - .value_parser([ - "style", - "correctness", - "suspicious", - "complexity", - "perf", - "pedantic", - "restriction", - "cargo", - "nursery", - "internal", - ]), - Arg::new("type").long("type").help("What directory the lint belongs in"), - Arg::new("msrv") - .long("msrv") - .action(ArgAction::SetTrue) - .help("Add MSRV config code to the lint"), - ]), - Command::new("setup") - .about("Support for setting up your personal development environment") - .arg_required_else_help(true) - .subcommands([ - Command::new("git-hook") - .about("Add a pre-commit git hook that formats your code to make it look pretty") - .args([ - Arg::new("remove") - .long("remove") - .action(ArgAction::SetTrue) - .help("Remove the pre-commit hook added with 'cargo dev setup git-hook'"), - Arg::new("force-override") - .long("force-override") - .short('f') - .action(ArgAction::SetTrue) - .help("Forces the override of an existing git pre-commit hook"), - ]), - Command::new("intellij") - .about("Alter dependencies so Intellij Rust can find rustc internals") - .args([ - Arg::new("remove") - .long("remove") - .action(ArgAction::SetTrue) - .help("Remove the dependencies added with 'cargo dev setup intellij'"), - Arg::new("rustc-repo-path") - .long("repo-path") - .short('r') - .help("The path to a rustc repo that will be used for setting the dependencies") - .value_name("path") - .conflicts_with("remove") - .required(true), - ]), - Command::new("toolchain") - .about("Install a rustup toolchain pointing to the local clippy build") - .args([ - Arg::new("force") - .long("force") - .short('f') - .action(ArgAction::SetTrue) - .help("Override an existing toolchain"), - Arg::new("release") - .long("release") - .short('r') - .action(ArgAction::SetTrue) - .help("Point to --release clippy binaries"), - Arg::new("name") - .long("name") - .default_value("clippy") - .help("The name of the created toolchain"), - ]), - Command::new("vscode-tasks") - .about("Add several tasks to vscode for formatting, validation and testing") - .args([ - Arg::new("remove") - .long("remove") - .action(ArgAction::SetTrue) - .help("Remove the tasks added with 'cargo dev setup vscode-tasks'"), - Arg::new("force-override") - .long("force-override") - .short('f') - .action(ArgAction::SetTrue) - .help("Forces the override of existing vscode tasks"), - ]), - ]), - Command::new("remove") - .about("Support for undoing changes done by the setup command") - .arg_required_else_help(true) - .subcommands([ - Command::new("git-hook").about("Remove any existing pre-commit git hook"), - Command::new("vscode-tasks").about("Remove any existing vscode tasks"), - Command::new("intellij").about("Removes rustc source paths added via `cargo dev setup intellij`"), - ]), - Command::new("serve") - .about("Launch a local 'ALL the Clippy Lints' website in a browser") - .args([ - Arg::new("port") - .long("port") - .short('p') - .help("Local port for the http server") - .default_value("8000") - .value_parser(clap::value_parser!(u16)), - Arg::new("lint").help("Which lint's page to load initially (optional)"), - ]), - Command::new("lint") - .about("Manually run clippy on a file or package") - .after_help(indoc! {" - EXAMPLES - Lint a single file: - cargo dev lint tests/ui/attrs.rs - - Lint a package directory: - cargo dev lint tests/ui-cargo/wildcard_dependencies/fail - cargo dev lint ~/my-project - - Run rustfix: - cargo dev lint ~/my-project -- --fix - - Set lint levels: - cargo dev lint file.rs -- -W clippy::pedantic - cargo dev lint ~/my-project -- -- -W clippy::pedantic - "}) - .args([ - Arg::new("path") - .required(true) - .help("The path to a file or package directory to lint"), - Arg::new("args") - .action(ArgAction::Append) - .help("Pass extra arguments to cargo/clippy-driver"), - ]), - Command::new("rename_lint").about("Renames the given lint").args([ - Arg::new("old_name") - .index(1) - .required(true) - .help("The name of the lint to rename"), - Arg::new("new_name") - .index(2) - .required_unless_present("uplift") - .help("The new name of the lint"), - Arg::new("uplift") - .long("uplift") - .action(ArgAction::SetTrue) - .help("This lint will be uplifted into rustc"), - ]), - Command::new("deprecate").about("Deprecates the given lint").args([ - Arg::new("name") - .index(1) - .required(true) - .help("The name of the lint to deprecate"), - Arg::new("reason") - .long("reason") - .short('r') - .help("The reason for deprecation"), - ]), - ]) - .get_matches() +#[derive(Parser)] +#[command(name = "dev", about)] +struct Dev { + #[command(subcommand)] + command: DevCommand, +} + +#[derive(Subcommand)] +enum DevCommand { + /// Bless the test output changes + Bless, + /// Runs the dogfood test + Dogfood { + #[arg(long)] + /// Apply the suggestions when possible + fix: bool, + #[arg(long, requires = "fix")] + /// Fix code even if the working directory has changes + allow_dirty: bool, + #[arg(long, requires = "fix")] + /// Fix code even if the working directory has staged changes + allow_staged: bool, + }, + /// Run rustfmt on all projects and tests + Fmt { + #[arg(long)] + /// Use the rustfmt --check option + check: bool, + #[arg(short, long)] + /// Echo commands run + verbose: bool, + }, + #[command(name = "update_lints")] + /// Updates lint registration and information from the source code + /// + /// Makes sure that: {n} + /// * the lint count in README.md is correct {n} + /// * the changelog contains markdown link references at the bottom {n} + /// * all lint groups include the correct lints {n} + /// * lint modules in `clippy_lints/*` are visible in `src/lib.rs` via `pub mod` {n} + /// * all lints are registered in the lint store + UpdateLints { + #[arg(long)] + /// Print a table of lints to STDOUT + /// + /// This does not include deprecated and internal lints. (Does not modify any files) + print_only: bool, + #[arg(long)] + /// Checks that `cargo dev update_lints` has been run. Used on CI. + check: bool, + }, + #[command(name = "new_lint")] + /// Create a new lint and run `cargo dev update_lints` + NewLint { + #[arg(short, long, value_parser = ["early", "late"], conflicts_with = "type", default_value = "late")] + /// Specify whether the lint runs during the early or late pass + pass: String, + #[arg( + short, + long, + value_parser = |name: &str| Ok::<_, Infallible>(name.replace('-', "_")), + )] + /// Name of the new lint in snake case, ex: `fn_too_long` + name: String, + #[arg( + short, + long, + value_parser = [ + "style", + "correctness", + "suspicious", + "complexity", + "perf", + "pedantic", + "restriction", + "cargo", + "nursery", + "internal", + ], + default_value = "nursery", + )] + /// What category the lint belongs to + category: String, + #[arg(long)] + /// What directory the lint belongs in + r#type: Option, + #[arg(long)] + /// Add MSRV config code to the lint + msrv: bool, + }, + /// Support for setting up your personal development environment + Setup(SetupCommand), + /// Support for removing changes done by the setup command + Remove(RemoveCommand), + /// Launch a local 'ALL the Clippy Lints' website in a browser + Serve { + #[arg(short, long, default_value = "8000")] + /// Local port for the http server + port: u16, + #[arg(long)] + /// Which lint's page to load initially (optional) + lint: Option, + }, + #[allow(clippy::doc_markdown)] + /// Manually run clippy on a file or package + /// + /// ## Examples + /// + /// Lint a single file: {n} + /// cargo dev lint tests/ui/attrs.rs + /// + /// Lint a package directory: {n} + /// cargo dev lint tests/ui-cargo/wildcard_dependencies/fail {n} + /// cargo dev lint ~/my-project + /// + /// Run rustfix: {n} + /// cargo dev lint ~/my-project -- --fix + /// + /// Set lint levels: {n} + /// cargo dev lint file.rs -- -W clippy::pedantic {n} + /// cargo dev lint ~/my-project -- -- -W clippy::pedantic + Lint { + /// The path to a file or package directory to lint + path: String, + /// Pass extra arguments to cargo/clippy-driver + args: Vec, + }, + #[command(name = "rename_lint")] + /// Rename a lint + RenameLint { + /// The name of the lint to rename + old_name: String, + #[arg(required_unless_present = "uplift")] + /// The new name of the lint + new_name: Option, + #[arg(long)] + /// This lint will be uplifted into rustc + uplift: bool, + }, + /// Deprecate the given lint + Deprecate { + /// The name of the lint to deprecate + name: String, + #[arg(long, short)] + /// The reason for deprecation + reason: Option, + }, +} + +#[derive(Args)] +struct SetupCommand { + #[command(subcommand)] + subcommand: SetupSubcommand, +} + +#[derive(Subcommand)] +enum SetupSubcommand { + /// Alter dependencies so Intellij Rust can find rustc internals + Intellij { + #[arg(long)] + /// Remove the dependencies added with 'cargo dev setup intellij' + remove: bool, + #[arg(long, short, conflicts_with = "remove")] + /// The path to a rustc repo that will be used for setting the dependencies + repo_path: String, + }, + /// Add a pre-commit git hook that formats your code to make it look pretty + GitHook { + #[arg(long)] + /// Remove the pre-commit hook added with 'cargo dev setup git-hook' + remove: bool, + #[arg(long, short)] + /// Forces the override of an existing git pre-commit hook + force_override: bool, + }, + /// Install a rustup toolchain pointing to the local clippy build + Toolchain { + #[arg(long, short)] + /// Override an existing toolchain + force: bool, + #[arg(long, short)] + /// Point to --release clippy binary + release: bool, + #[arg(long, default_value = "clippy")] + /// Name of the toolchain + name: String, + }, + /// Add several tasks to vscode for formatting, validation and testing + VscodeTasks { + #[arg(long)] + /// Remove the tasks added with 'cargo dev setup vscode-tasks' + remove: bool, + #[arg(long, short)] + /// Forces the override of existing vscode tasks + force_override: bool, + }, +} + +#[derive(Args)] +struct RemoveCommand { + #[command(subcommand)] + subcommand: RemoveSubcommand, +} + +#[derive(Subcommand)] +enum RemoveSubcommand { + /// Remove the dependencies added with 'cargo dev setup intellij' + Intellij, + /// Remove the pre-commit git hook + GitHook, + /// Remove the tasks added with 'cargo dev setup vscode-tasks' + VscodeTasks, } diff --git a/clippy_dev/src/new_lint.rs b/clippy_dev/src/new_lint.rs index 2940d56350f4..b6481dde4dde 100644 --- a/clippy_dev/src/new_lint.rs +++ b/clippy_dev/src/new_lint.rs @@ -36,22 +36,16 @@ impl Context for io::Result { /// # Errors /// /// This function errors out if the files couldn't be created or written to. -pub fn create( - pass: &String, - lint_name: Option<&String>, - category: Option<&str>, - mut ty: Option<&str>, - msrv: bool, -) -> io::Result<()> { - if category == Some("cargo") && ty.is_none() { +pub fn create(pass: &str, name: &str, category: &str, mut ty: Option<&str>, msrv: bool) -> io::Result<()> { + if category == "cargo" && ty.is_none() { // `cargo` is a special category, these lints should always be in `clippy_lints/src/cargo` ty = Some("cargo"); } let lint = LintData { pass, - name: lint_name.expect("`name` argument is validated by clap"), - category: category.expect("`category` argument is validated by clap"), + name, + category, ty, project_root: clippy_project_root(), }; diff --git a/clippy_dev/src/serve.rs b/clippy_dev/src/serve.rs index ea925f6709f9..4a4261d1a1e6 100644 --- a/clippy_dev/src/serve.rs +++ b/clippy_dev/src/serve.rs @@ -8,7 +8,7 @@ use std::{env, thread}; /// # Panics /// /// Panics if the python commands could not be spawned -pub fn run(port: u16, lint: Option<&String>) -> ! { +pub fn run(port: u16, lint: Option) -> ! { let mut url = Some(match lint { None => format!("http://localhost:{port}"), Some(lint) => format!("http://localhost:{port}/#{lint}"), diff --git a/clippy_dev/src/update_lints.rs b/clippy_dev/src/update_lints.rs index 625b13395913..45353901c98f 100644 --- a/clippy_dev/src/update_lints.rs +++ b/clippy_dev/src/update_lints.rs @@ -314,7 +314,7 @@ const DEFAULT_DEPRECATION_REASON: &str = "default deprecation note"; /// # Panics /// /// If a file path could not read from or written to -pub fn deprecate(name: &str, reason: Option<&String>) { +pub fn deprecate(name: &str, reason: Option<&str>) { fn finish( (lints, mut deprecated_lints, renamed_lints): (Vec, Vec, Vec), name: &str, @@ -335,7 +335,7 @@ pub fn deprecate(name: &str, reason: Option<&String>) { println!("note: you must run `cargo uitest` to update the test results"); } - let reason = reason.map_or(DEFAULT_DEPRECATION_REASON, String::as_str); + let reason = reason.unwrap_or(DEFAULT_DEPRECATION_REASON); let name_lower = name.to_lowercase(); let name_upper = name.to_uppercase(); diff --git a/clippy_lints/src/assigning_clones.rs b/clippy_lints/src/assigning_clones.rs index f0dafb1ae0d5..e94a6f3e3fc5 100644 --- a/clippy_lints/src/assigning_clones.rs +++ b/clippy_lints/src/assigning_clones.rs @@ -2,15 +2,15 @@ use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::macros::HirNode; use clippy_utils::sugg::Sugg; -use clippy_utils::{is_trait_method, path_to_local}; +use clippy_utils::{is_trait_method, local_is_initialized, path_to_local}; use rustc_errors::Applicability; -use rustc_hir::{self as hir, Expr, ExprKind, Node}; +use rustc_hir::{self as hir, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, Instance, Mutability}; use rustc_session::impl_lint_pass; use rustc_span::def_id::DefId; use rustc_span::symbol::sym; -use rustc_span::ExpnKind; +use rustc_span::{ExpnKind, SyntaxContext}; declare_clippy_lint! { /// ### What it does @@ -36,6 +36,7 @@ declare_clippy_lint! { /// Use instead: /// ```rust /// struct Thing; + /// /// impl Clone for Thing { /// fn clone(&self) -> Self { todo!() } /// fn clone_from(&mut self, other: &Self) { todo!() } @@ -47,7 +48,7 @@ declare_clippy_lint! { /// ``` #[clippy::version = "1.78.0"] pub ASSIGNING_CLONES, - perf, + pedantic, "assigning the result of cloning may be inefficient" } @@ -67,7 +68,8 @@ impl_lint_pass!(AssigningClones => [ASSIGNING_CLONES]); impl<'tcx> LateLintPass<'tcx> for AssigningClones { fn check_expr(&mut self, cx: &LateContext<'tcx>, assign_expr: &'tcx Expr<'_>) { // Do not fire the lint in macros - let expn_data = assign_expr.span().ctxt().outer_expn_data(); + let ctxt = assign_expr.span().ctxt(); + let expn_data = ctxt.outer_expn_data(); match expn_data.kind { ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) | ExpnKind::Macro(..) => return, ExpnKind::Root => {}, @@ -82,7 +84,7 @@ impl<'tcx> LateLintPass<'tcx> for AssigningClones { }; if is_ok_to_suggest(cx, lhs, &call, &self.msrv) { - suggest(cx, assign_expr, lhs, &call); + suggest(cx, ctxt, assign_expr, lhs, &call); } } @@ -163,9 +165,7 @@ fn is_ok_to_suggest<'tcx>(cx: &LateContext<'tcx>, lhs: &Expr<'tcx>, call: &CallC // TODO: This check currently bails if the local variable has no initializer. // That is overly conservative - the lint should fire even if there was no initializer, // but the variable has been initialized before `lhs` was evaluated. - if let Some(Node::LetStmt(local)) = cx.tcx.hir().parent_id_iter(local).next().map(|p| cx.tcx.hir_node(p)) - && local.init.is_none() - { + if !local_is_initialized(cx, local) { return false; } } @@ -222,14 +222,20 @@ fn is_ok_to_suggest<'tcx>(cx: &LateContext<'tcx>, lhs: &Expr<'tcx>, call: &CallC implemented_fns.contains_key(&provided_fn.def_id) } -fn suggest<'tcx>(cx: &LateContext<'tcx>, assign_expr: &Expr<'tcx>, lhs: &Expr<'tcx>, call: &CallCandidate<'tcx>) { +fn suggest<'tcx>( + cx: &LateContext<'tcx>, + ctxt: SyntaxContext, + assign_expr: &Expr<'tcx>, + lhs: &Expr<'tcx>, + call: &CallCandidate<'tcx>, +) { span_lint_and_then(cx, ASSIGNING_CLONES, assign_expr.span, call.message(), |diag| { let mut applicability = Applicability::Unspecified; diag.span_suggestion( assign_expr.span, call.suggestion_msg(), - call.suggested_replacement(cx, lhs, &mut applicability), + call.suggested_replacement(cx, ctxt, lhs, &mut applicability), applicability, ); }); @@ -275,6 +281,7 @@ impl<'tcx> CallCandidate<'tcx> { fn suggested_replacement( &self, cx: &LateContext<'tcx>, + ctxt: SyntaxContext, lhs: &Expr<'tcx>, applicability: &mut Applicability, ) -> String { @@ -294,7 +301,7 @@ impl<'tcx> CallCandidate<'tcx> { // Determine whether we need to reference the argument to clone_from(). let clone_receiver_type = cx.typeck_results().expr_ty(receiver); let clone_receiver_adj_type = cx.typeck_results().expr_ty_adjusted(receiver); - let mut arg_sugg = Sugg::hir_with_applicability(cx, receiver, "_", applicability); + let mut arg_sugg = Sugg::hir_with_context(cx, receiver, ctxt, "_", applicability); if clone_receiver_type != clone_receiver_adj_type { // The receiver may have been a value type, so we need to add an `&` to // be sure the argument to clone_from will be a reference. @@ -312,7 +319,7 @@ impl<'tcx> CallCandidate<'tcx> { Sugg::hir_with_applicability(cx, lhs, "_", applicability).mut_addr() }; // The RHS had to be exactly correct before the call, there is no auto-deref for function calls. - let rhs_sugg = Sugg::hir_with_applicability(cx, self_arg, "_", applicability); + let rhs_sugg = Sugg::hir_with_context(cx, self_arg, ctxt, "_", applicability); format!("Clone::clone_from({self_sugg}, {rhs_sugg})") }, @@ -341,11 +348,11 @@ impl<'tcx> CallCandidate<'tcx> { match self.kind { CallKind::MethodCall { receiver } => { - let receiver_sugg = Sugg::hir_with_applicability(cx, receiver, "_", applicability); + let receiver_sugg = Sugg::hir_with_context(cx, receiver, ctxt, "_", applicability); format!("{receiver_sugg}.clone_into({rhs_sugg})") }, CallKind::FunctionCall { self_arg, .. } => { - let self_sugg = Sugg::hir_with_applicability(cx, self_arg, "_", applicability); + let self_sugg = Sugg::hir_with_context(cx, self_arg, ctxt, "_", applicability); format!("ToOwned::clone_into({self_sugg}, {rhs_sugg})") }, } diff --git a/clippy_lints/src/attrs/duplicated_attributes.rs b/clippy_lints/src/attrs/duplicated_attributes.rs index 736ee48641d8..40a1c4e28842 100644 --- a/clippy_lints/src/attrs/duplicated_attributes.rs +++ b/clippy_lints/src/attrs/duplicated_attributes.rs @@ -36,9 +36,10 @@ fn check_duplicated_attr( } let Some(ident) = attr.ident() else { return }; let name = ident.name; - if name == sym::doc || name == sym::cfg_attr { + if name == sym::doc || name == sym::cfg_attr || name == sym::rustc_on_unimplemented { // FIXME: Would be nice to handle `cfg_attr` as well. Only problem is to check that cfg // conditions are the same. + // `#[rustc_on_unimplemented]` contains duplicated subattributes, that's expected. return; } if let Some(direct_parent) = parent.last() diff --git a/clippy_lints/src/attrs/mod.rs b/clippy_lints/src/attrs/mod.rs index 8f47bc7653b7..39f406077995 100644 --- a/clippy_lints/src/attrs/mod.rs +++ b/clippy_lints/src/attrs/mod.rs @@ -61,11 +61,21 @@ declare_clippy_lint! { /// /// This lint permits lint attributes for lints emitted on the items themself. /// For `use` items these lints are: + /// * ambiguous_glob_reexports + /// * dead_code /// * deprecated + /// * hidden_glob_reexports /// * unreachable_pub - /// * unused_imports + /// * unused + /// * unused_braces + /// * unused_import_braces + /// * clippy::disallowed_types /// * clippy::enum_glob_use /// * clippy::macro_use_imports + /// * clippy::module_name_repetitions + /// * clippy::redundant_pub_crate + /// * clippy::single_component_path_imports + /// * clippy::unsafe_removed_from_name /// * clippy::wildcard_imports /// /// For `extern crate` items these lints are: diff --git a/clippy_lints/src/attrs/useless_attribute.rs b/clippy_lints/src/attrs/useless_attribute.rs index 7575f502a7c2..f0868231d01a 100644 --- a/clippy_lints/src/attrs/useless_attribute.rs +++ b/clippy_lints/src/attrs/useless_attribute.rs @@ -2,6 +2,7 @@ use super::utils::{extract_clippy_lint, is_lint_level, is_word}; use super::{Attribute, USELESS_ATTRIBUTE}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::{first_line_of_span, snippet_opt}; +use rustc_ast::NestedMetaItem; use rustc_errors::Applicability; use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LintContext}; @@ -20,26 +21,40 @@ pub(super) fn check(cx: &LateContext<'_>, item: &Item<'_>, attrs: &[Attribute]) for lint in lint_list { match item.kind { ItemKind::Use(..) => { - if is_word(lint, sym::unused_imports) - || is_word(lint, sym::deprecated) - || is_word(lint, sym!(unreachable_pub)) - || is_word(lint, sym!(unused)) - || is_word(lint, sym!(unused_import_braces)) - || extract_clippy_lint(lint).map_or(false, |s| { - matches!( - s.as_str(), - "wildcard_imports" - | "enum_glob_use" - | "redundant_pub_crate" - | "macro_use_imports" - | "unsafe_removed_from_name" - | "module_name_repetitions" - | "single_component_path_imports" - ) - }) + if let NestedMetaItem::MetaItem(meta_item) = lint + && meta_item.is_word() + && let Some(ident) = meta_item.ident() + && matches!( + ident.name.as_str(), + "ambiguous_glob_reexports" + | "dead_code" + | "deprecated" + | "hidden_glob_reexports" + | "unreachable_pub" + | "unused" + | "unused_braces" + | "unused_import_braces" + | "unused_imports" + ) { return; } + + if extract_clippy_lint(lint).is_some_and(|symbol| { + matches!( + symbol.as_str(), + "wildcard_imports" + | "enum_glob_use" + | "redundant_pub_crate" + | "macro_use_imports" + | "unsafe_removed_from_name" + | "module_name_repetitions" + | "single_component_path_imports" + | "disallowed_types" + ) + }) { + return; + } }, ItemKind::ExternCrate(..) => { if is_word(lint, sym::unused_imports) && skip_unused_imports { diff --git a/clippy_lints/src/cargo/lint_groups_priority.rs b/clippy_lints/src/cargo/lint_groups_priority.rs index a3291c9da109..0d9eaac882f7 100644 --- a/clippy_lints/src/cargo/lint_groups_priority.rs +++ b/clippy_lints/src/cargo/lint_groups_priority.rs @@ -49,7 +49,7 @@ impl LintConfig { type LintTable = BTreeMap, Spanned>; -#[derive(Deserialize, Debug)] +#[derive(Deserialize, Debug, Default)] struct Lints { #[serde(default)] rust: LintTable, @@ -57,9 +57,18 @@ struct Lints { clippy: LintTable, } +#[derive(Deserialize, Debug, Default)] +struct Workspace { + #[serde(default)] + lints: Lints, +} + #[derive(Deserialize, Debug)] struct CargoToml { + #[serde(default)] lints: Lints, + #[serde(default)] + workspace: Workspace, } #[derive(Default, Debug)] @@ -164,5 +173,7 @@ pub fn check(cx: &LateContext<'_>) { check_table(cx, cargo_toml.lints.rust, &rustc_groups, &file); check_table(cx, cargo_toml.lints.clippy, &clippy_groups, &file); + check_table(cx, cargo_toml.workspace.lints.rust, &rustc_groups, &file); + check_table(cx, cargo_toml.workspace.lints.clippy, &clippy_groups, &file); } } diff --git a/clippy_lints/src/casts/cast_sign_loss.rs b/clippy_lints/src/casts/cast_sign_loss.rs index 2b6e17dc1030..864489ee3fcd 100644 --- a/clippy_lints/src/casts/cast_sign_loss.rs +++ b/clippy_lints/src/casts/cast_sign_loss.rs @@ -255,8 +255,10 @@ fn expr_add_sign(cx: &LateContext<'_>, expr: &Expr<'_>) -> Sign { /// Peels binary operators such as [`BinOpKind::Mul`], [`BinOpKind::Div`] or [`BinOpKind::Rem`], /// where the result depends on: +/// /// - the number of negative values in the entire expression, or /// - the number of negative values on the left hand side of the expression. +/// /// Ignores overflow. /// /// @@ -303,8 +305,10 @@ fn exprs_with_muldiv_binop_peeled<'e>(expr: &'e Expr<'_>) -> Vec<&'e Expr<'e>> { } /// Peels binary operators such as [`BinOpKind::Add`], where the result depends on: +/// /// - all the expressions being positive, or /// - all the expressions being negative. +/// /// Ignores overflow. /// /// Expressions using other operators are preserved, so we can try to evaluate them later. diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 5ff7d8e51343..df2ef465700d 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -140,6 +140,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::disallowed_names::DISALLOWED_NAMES_INFO, crate::disallowed_script_idents::DISALLOWED_SCRIPT_IDENTS_INFO, crate::disallowed_types::DISALLOWED_TYPES_INFO, + crate::doc::DOC_LAZY_CONTINUATION_INFO, crate::doc::DOC_LINK_WITH_QUOTES_INFO, crate::doc::DOC_MARKDOWN_INFO, crate::doc::EMPTY_DOCS_INFO, @@ -205,6 +206,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::functions::MUST_USE_CANDIDATE_INFO, crate::functions::MUST_USE_UNIT_INFO, crate::functions::NOT_UNSAFE_PTR_ARG_DEREF_INFO, + crate::functions::RENAMED_FUNCTION_PARAMS_INFO, crate::functions::RESULT_LARGE_ERR_INFO, crate::functions::RESULT_UNIT_ERR_INFO, crate::functions::TOO_MANY_ARGUMENTS_INFO, @@ -291,9 +293,11 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::loops::SAME_ITEM_PUSH_INFO, crate::loops::SINGLE_ELEMENT_LOOP_INFO, crate::loops::UNUSED_ENUMERATE_INDEX_INFO, + crate::loops::WHILE_FLOAT_INFO, crate::loops::WHILE_IMMUTABLE_CONDITION_INFO, crate::loops::WHILE_LET_LOOP_INFO, crate::loops::WHILE_LET_ON_ITERATOR_INFO, + crate::macro_metavars_in_unsafe::MACRO_METAVARS_IN_UNSAFE_INFO, crate::macro_use::MACRO_USE_IMPORTS_INFO, crate::main_recursion::MAIN_RECURSION_INFO, crate::manual_assert::MANUAL_ASSERT_INFO, diff --git a/clippy_lints/src/doc/lazy_continuation.rs b/clippy_lints/src/doc/lazy_continuation.rs new file mode 100644 index 000000000000..38bc58a55019 --- /dev/null +++ b/clippy_lints/src/doc/lazy_continuation.rs @@ -0,0 +1,95 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use itertools::Itertools; +use rustc_errors::{Applicability, SuggestionStyle}; +use rustc_lint::LateContext; +use rustc_span::{BytePos, Span}; +use std::ops::Range; + +use super::DOC_LAZY_CONTINUATION; + +fn map_container_to_text(c: &super::Container) -> &'static str { + match c { + super::Container::Blockquote => "> ", + // numbered list can have up to nine digits, plus the dot, plus four spaces on either side + super::Container::List(indent) => &" "[0..*indent], + } +} + +// TODO: Adjust the parameters as necessary +pub(super) fn check( + cx: &LateContext<'_>, + doc: &str, + range: Range, + mut span: Span, + containers: &[super::Container], +) { + if doc[range.clone()].contains('\t') { + // We don't do tab stops correctly. + return; + } + + let ccount = doc[range.clone()].chars().filter(|c| *c == '>').count(); + let blockquote_level = containers + .iter() + .filter(|c| matches!(c, super::Container::Blockquote)) + .count(); + let lcount = doc[range.clone()].chars().filter(|c| *c == ' ').count(); + let list_indentation = containers + .iter() + .map(|c| { + if let super::Container::List(indent) = c { + *indent + } else { + 0 + } + }) + .sum(); + if ccount < blockquote_level || lcount < list_indentation { + let msg = if ccount < blockquote_level { + "doc quote missing `>` marker" + } else { + "doc list item missing indentation" + }; + span_lint_and_then(cx, DOC_LAZY_CONTINUATION, span, msg, |diag| { + if ccount == 0 && blockquote_level == 0 { + // simpler suggestion style for indentation + let indent = list_indentation - lcount; + diag.span_suggestion_with_style( + span.shrink_to_hi(), + "indent this line", + std::iter::repeat(" ").take(indent).join(""), + Applicability::MaybeIncorrect, + SuggestionStyle::ShowAlways, + ); + diag.help("if this is supposed to be its own paragraph, add a blank line"); + return; + } + let mut doc_start_range = &doc[range]; + let mut suggested = String::new(); + for c in containers { + let text = map_container_to_text(c); + if doc_start_range.starts_with(text) { + doc_start_range = &doc_start_range[text.len()..]; + span = span + .with_lo(span.lo() + BytePos(u32::try_from(text.len()).expect("text is not 2**32 or bigger"))); + } else if matches!(c, super::Container::Blockquote) + && let Some(i) = doc_start_range.find('>') + { + doc_start_range = &doc_start_range[i + 1..]; + span = + span.with_lo(span.lo() + BytePos(u32::try_from(i).expect("text is not 2**32 or bigger") + 1)); + } else { + suggested.push_str(text); + } + } + diag.span_suggestion_with_style( + span, + "add markers to start of line", + suggested, + Applicability::MachineApplicable, + SuggestionStyle::ShowAlways, + ); + diag.help("if this not intended to be a quote at all, escape it with `\\>`"); + }); + } +} diff --git a/clippy_lints/src/doc/missing_headers.rs b/clippy_lints/src/doc/missing_headers.rs index 36ba19698c72..010fab803d99 100644 --- a/clippy_lints/src/doc/missing_headers.rs +++ b/clippy_lints/src/doc/missing_headers.rs @@ -1,3 +1,4 @@ +use super::{DocHeaders, MISSING_ERRORS_DOC, MISSING_PANICS_DOC, MISSING_SAFETY_DOC, UNNECESSARY_SAFETY_DOC}; use clippy_utils::diagnostics::{span_lint, span_lint_and_note}; use clippy_utils::ty::{implements_trait, is_type_diagnostic_item}; use clippy_utils::{is_doc_hidden, return_ty}; @@ -6,15 +7,13 @@ use rustc_lint::LateContext; use rustc_middle::ty; use rustc_span::{sym, Span}; -use super::{DocHeaders, MISSING_ERRORS_DOC, MISSING_PANICS_DOC, MISSING_SAFETY_DOC, UNNECESSARY_SAFETY_DOC}; - pub fn check( cx: &LateContext<'_>, owner_id: OwnerId, sig: FnSig<'_>, headers: DocHeaders, body_id: Option, - panic_span: Option, + panic_info: Option<(Span, bool)>, check_private_items: bool, ) { if !check_private_items && !cx.effective_visibilities.is_exported(owner_id.def_id) { @@ -48,13 +47,13 @@ pub fn check( ), _ => (), } - if !headers.panics && panic_span.is_some() { + if !headers.panics && panic_info.map_or(false, |el| !el.1) { span_lint_and_note( cx, MISSING_PANICS_DOC, span, "docs for function which may panic missing `# Panics` section", - panic_span, + panic_info.map(|el| el.0), "first possible panic found here", ); } diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs index 7fdb582e6403..9f08973948a3 100644 --- a/clippy_lints/src/doc/mod.rs +++ b/clippy_lints/src/doc/mod.rs @@ -1,13 +1,14 @@ +mod lazy_continuation; use clippy_utils::attrs::is_doc_hidden; use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; use clippy_utils::macros::{is_panic, root_macro_call_first_node}; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::visitors::Visitable; -use clippy_utils::{is_entrypoint_fn, is_trait_impl_item, method_chain_args}; +use clippy_utils::{in_constant, is_entrypoint_fn, is_trait_impl_item, method_chain_args}; use pulldown_cmark::Event::{ Code, End, FootnoteReference, HardBreak, Html, Rule, SoftBreak, Start, TaskListMarker, Text, }; -use pulldown_cmark::Tag::{BlockQuote, CodeBlock, Heading, Item, Link, Paragraph}; +use pulldown_cmark::Tag::{BlockQuote, CodeBlock, FootnoteDefinition, Heading, Item, Link, Paragraph}; use pulldown_cmark::{BrokenLink, CodeBlockKind, CowStr, Options}; use rustc_ast::ast::Attribute; use rustc_data_structures::fx::FxHashSet; @@ -362,6 +363,63 @@ declare_clippy_lint! { "docstrings exist but documentation is empty" } +declare_clippy_lint! { + /// ### What it does + /// + /// In CommonMark Markdown, the language used to write doc comments, a + /// paragraph nested within a list or block quote does not need any line + /// after the first one to be indented or marked. The specification calls + /// this a "lazy paragraph continuation." + /// + /// ### Why is this bad? + /// + /// This is easy to write but hard to read. Lazy continuations makes + /// unintended markers hard to see, and make it harder to deduce the + /// document's intended structure. + /// + /// ### Example + /// + /// This table is probably intended to have two rows, + /// but it does not. It has zero rows, and is followed by + /// a block quote. + /// ```no_run + /// /// Range | Description + /// /// ----- | ----------- + /// /// >= 1 | fully opaque + /// /// < 1 | partially see-through + /// fn set_opacity(opacity: f32) {} + /// ``` + /// + /// Fix it by escaping the marker: + /// ```no_run + /// /// Range | Description + /// /// ----- | ----------- + /// /// \>= 1 | fully opaque + /// /// < 1 | partially see-through + /// fn set_opacity(opacity: f32) {} + /// ``` + /// + /// This example is actually intended to be a list: + /// ```no_run + /// /// * Do nothing. + /// /// * Then do something. Whatever it is needs done, + /// /// it should be done right now. + /// # fn do_stuff() {} + /// ``` + /// + /// Fix it by indenting the list contents: + /// ```no_run + /// /// * Do nothing. + /// /// * Then do something. Whatever it is needs done, + /// /// it should be done right now. + /// # fn do_stuff() {} + /// ``` + #[clippy::version = "1.80.0"] + pub DOC_LAZY_CONTINUATION, + style, + "require every line of a paragraph to be indented and marked" +} + #[derive(Clone)] pub struct Documentation { valid_idents: FxHashSet, @@ -388,6 +446,7 @@ impl_lint_pass!(Documentation => [ UNNECESSARY_SAFETY_DOC, SUSPICIOUS_DOC_COMMENTS, EMPTY_DOCS, + DOC_LAZY_CONTINUATION, ]); impl<'tcx> LateLintPass<'tcx> for Documentation { @@ -402,14 +461,14 @@ impl<'tcx> LateLintPass<'tcx> for Documentation { if !(is_entrypoint_fn(cx, item.owner_id.to_def_id()) || in_external_macro(cx.tcx.sess, item.span)) { let body = cx.tcx.hir().body(body_id); - let panic_span = FindPanicUnwrap::find_span(cx, cx.tcx.typeck(item.owner_id), body.value); + let panic_info = FindPanicUnwrap::find_span(cx, cx.tcx.typeck(item.owner_id), body.value); missing_headers::check( cx, item.owner_id, sig, headers, Some(body_id), - panic_span, + panic_info, self.check_private_items, ); } @@ -551,6 +610,7 @@ fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet, attrs: &[ cx, valid_idents, parser.into_offset_iter(), + &doc, Fragments { fragments: &fragments, doc: &doc, @@ -560,6 +620,11 @@ fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet, attrs: &[ const RUST_CODE: &[&str] = &["rust", "no_run", "should_panic", "compile_fail"]; +enum Container { + Blockquote, + List(usize), +} + /// Checks parsed documentation. /// This walks the "events" (think sections of markdown) produced by `pulldown_cmark`, /// so lints here will generally access that information. @@ -569,6 +634,7 @@ fn check_doc<'a, Events: Iterator, Range, valid_idents: &FxHashSet, events: Events, + doc: &str, fragments: Fragments<'_>, ) -> DocHeaders { // true if a safety header was found @@ -576,6 +642,7 @@ fn check_doc<'a, Events: Iterator, Range, Range { if tag.starts_with(", Range blockquote_level += 1, - End(BlockQuote) => blockquote_level -= 1, + Start(BlockQuote) => { + blockquote_level += 1; + containers.push(Container::Blockquote); + }, + End(BlockQuote) => { + blockquote_level -= 1; + containers.pop(); + }, Start(CodeBlock(ref kind)) => { in_code = true; if let CodeBlockKind::Fenced(lang) = kind { @@ -633,6 +710,13 @@ fn check_doc<'a, Events: Iterator, Range, Range, Range in_footnote_definition = true, + End(FootnoteDefinition(..)) => in_footnote_definition = false, Start(_tag) | End(_tag) => (), // We don't care about other tags - SoftBreak | HardBreak | TaskListMarker(_) | Code(_) | Rule => (), + SoftBreak | HardBreak => { + if !containers.is_empty() + && let Some((next_event, next_range)) = events.peek() + && let Some(next_span) = fragments.span(cx, next_range.clone()) + && let Some(span) = fragments.span(cx, range.clone()) + && !in_footnote_definition + && !matches!(next_event, End(_)) + { + lazy_continuation::check( + cx, + doc, + range.end..next_range.start, + Span::new(span.hi(), next_span.lo(), span.ctxt(), span.parent()), + &containers[..], + ); + } + }, + TaskListMarker(_) | Code(_) | Rule => (), FootnoteReference(text) | Text(text) => { paragraph_range.end = range.end; ticks_unbalanced |= text.contains('`') && !in_code; @@ -701,6 +807,7 @@ fn check_doc<'a, Events: Iterator, Range { cx: &'a LateContext<'tcx>, + is_const: bool, panic_span: Option, typeck_results: &'tcx ty::TypeckResults<'tcx>, } @@ -710,14 +817,15 @@ impl<'a, 'tcx> FindPanicUnwrap<'a, 'tcx> { cx: &'a LateContext<'tcx>, typeck_results: &'tcx ty::TypeckResults<'tcx>, body: impl Visitable<'tcx>, - ) -> Option { + ) -> Option<(Span, bool)> { let mut vis = Self { cx, + is_const: false, panic_span: None, typeck_results, }; body.visit(&mut vis); - vis.panic_span + vis.panic_span.map(|el| (el, vis.is_const)) } } @@ -736,6 +844,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindPanicUnwrap<'a, 'tcx> { "assert" | "assert_eq" | "assert_ne" ) { + self.is_const = in_constant(self.cx, expr.hir_id); self.panic_span = Some(macro_call.span); } } diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index 6715de52649d..8d6e27700d8d 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -104,7 +104,9 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal { too_large_for_stack: self.too_large_for_stack, }; - ExprUseVisitor::for_clippy(cx, fn_def_id, &mut v).consume_body(body).into_ok(); + ExprUseVisitor::for_clippy(cx, fn_def_id, &mut v) + .consume_body(body) + .into_ok(); for node in v.set { span_lint_hir( diff --git a/clippy_lints/src/explicit_write.rs b/clippy_lints/src/explicit_write.rs index 724e1843359b..3c4a043a732b 100644 --- a/clippy_lints/src/explicit_write.rs +++ b/clippy_lints/src/explicit_write.rs @@ -1,12 +1,12 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::macros::{find_format_args, format_args_inputs_span}; +use clippy_utils::macros::{format_args_inputs_span, FormatArgsStorage}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::{is_expn_of, path_def_id}; use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::{BindingMode, Block, BlockCheckMode, Expr, ExprKind, Node, PatKind, QPath, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::declare_lint_pass; +use rustc_session::impl_lint_pass; use rustc_span::{sym, ExpnId}; declare_clippy_lint! { @@ -38,7 +38,17 @@ declare_clippy_lint! { "using the `write!()` family of functions instead of the `print!()` family of functions, when using the latter would work" } -declare_lint_pass!(ExplicitWrite => [EXPLICIT_WRITE]); +pub struct ExplicitWrite { + format_args: FormatArgsStorage, +} + +impl ExplicitWrite { + pub fn new(format_args: FormatArgsStorage) -> Self { + Self { format_args } + } +} + +impl_lint_pass!(ExplicitWrite => [EXPLICIT_WRITE]); impl<'tcx> LateLintPass<'tcx> for ExplicitWrite { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { @@ -57,7 +67,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite { Some(sym::io_stderr) => ("stderr", "e"), _ => return, }; - let Some(format_args) = find_format_args(cx, write_arg, ExpnId::root()) else { + let Some(format_args) = self.format_args.get(cx, write_arg, ExpnId::root()) else { return; }; @@ -83,7 +93,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite { }; let mut applicability = Applicability::MachineApplicable; let inputs_snippet = - snippet_with_applicability(cx, format_args_inputs_span(&format_args), "..", &mut applicability); + snippet_with_applicability(cx, format_args_inputs_span(format_args), "..", &mut applicability); span_lint_and_sugg( cx, EXPLICIT_WRITE, diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index 8a0cd155d211..0b248f784b76 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::macros::{find_format_arg_expr, find_format_args, root_macro_call_first_node}; +use clippy_utils::macros::{find_format_arg_expr, root_macro_call_first_node, FormatArgsStorage}; use clippy_utils::source::{snippet_opt, snippet_with_context}; use clippy_utils::sugg::Sugg; use rustc_ast::{FormatArgsPiece, FormatOptions, FormatTrait}; @@ -7,7 +7,7 @@ use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; -use rustc_session::declare_lint_pass; +use rustc_session::impl_lint_pass; use rustc_span::{sym, Span}; declare_clippy_lint! { @@ -39,13 +39,24 @@ declare_clippy_lint! { "useless use of `format!`" } -declare_lint_pass!(UselessFormat => [USELESS_FORMAT]); +#[allow(clippy::module_name_repetitions)] +pub struct UselessFormat { + format_args: FormatArgsStorage, +} + +impl UselessFormat { + pub fn new(format_args: FormatArgsStorage) -> Self { + Self { format_args } + } +} + +impl_lint_pass!(UselessFormat => [USELESS_FORMAT]); impl<'tcx> LateLintPass<'tcx> for UselessFormat { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if let Some(macro_call) = root_macro_call_first_node(cx, expr) && cx.tcx.is_diagnostic_item(sym::format_macro, macro_call.def_id) - && let Some(format_args) = find_format_args(cx, expr, macro_call.expn) + && let Some(format_args) = self.format_args.get(cx, expr, macro_call.expn) { let mut applicability = Applicability::MachineApplicable; let call_site = macro_call.span; diff --git a/clippy_lints/src/format_args.rs b/clippy_lints/src/format_args.rs index 003a9995c15f..86115807aa4d 100644 --- a/clippy_lints/src/format_args.rs +++ b/clippy_lints/src/format_args.rs @@ -3,8 +3,8 @@ use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::is_diag_trait_item; use clippy_utils::macros::{ - find_format_arg_expr, find_format_args, format_arg_removal_span, format_placeholder_format_span, is_assert_macro, - is_format_macro, is_panic, matching_root_macro_call, root_macro_call_first_node, FormatParamUsage, MacroCall, + find_format_arg_expr, format_arg_removal_span, format_placeholder_format_span, is_assert_macro, is_format_macro, + is_panic, matching_root_macro_call, root_macro_call_first_node, FormatArgsStorage, FormatParamUsage, MacroCall, }; use clippy_utils::source::snippet_opt; use clippy_utils::ty::{implements_trait, is_type_lang_item}; @@ -167,15 +167,18 @@ impl_lint_pass!(FormatArgs => [ UNUSED_FORMAT_SPECS, ]); +#[allow(clippy::struct_field_names)] pub struct FormatArgs { + format_args: FormatArgsStorage, msrv: Msrv, ignore_mixed: bool, } impl FormatArgs { #[must_use] - pub fn new(msrv: Msrv, allow_mixed_uninlined_format_args: bool) -> Self { + pub fn new(format_args: FormatArgsStorage, msrv: Msrv, allow_mixed_uninlined_format_args: bool) -> Self { Self { + format_args, msrv, ignore_mixed: allow_mixed_uninlined_format_args, } @@ -186,13 +189,13 @@ impl<'tcx> LateLintPass<'tcx> for FormatArgs { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { if let Some(macro_call) = root_macro_call_first_node(cx, expr) && is_format_macro(cx, macro_call.def_id) - && let Some(format_args) = find_format_args(cx, expr, macro_call.expn) + && let Some(format_args) = self.format_args.get(cx, expr, macro_call.expn) { let linter = FormatArgsExpr { cx, expr, macro_call: ¯o_call, - format_args: &format_args, + format_args, ignore_mixed: self.ignore_mixed, }; diff --git a/clippy_lints/src/format_impl.rs b/clippy_lints/src/format_impl.rs index 0a52347940ab..09be7237b5ca 100644 --- a/clippy_lints/src/format_impl.rs +++ b/clippy_lints/src/format_impl.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; -use clippy_utils::macros::{find_format_arg_expr, find_format_args, is_format_macro, root_macro_call_first_node}; +use clippy_utils::macros::{find_format_arg_expr, is_format_macro, root_macro_call_first_node, FormatArgsStorage}; use clippy_utils::{get_parent_as_impl, is_diag_trait_item, path_to_local, peel_ref_operators}; use rustc_ast::{FormatArgsPiece, FormatTrait}; use rustc_errors::Applicability; @@ -99,13 +99,15 @@ struct FormatTraitNames { #[derive(Default)] pub struct FormatImpl { + format_args: FormatArgsStorage, // Whether we are inside Display or Debug trait impl - None for neither format_trait_impl: Option, } impl FormatImpl { - pub fn new() -> Self { + pub fn new(format_args: FormatArgsStorage) -> Self { Self { + format_args, format_trait_impl: None, } } @@ -129,6 +131,7 @@ impl<'tcx> LateLintPass<'tcx> for FormatImpl { if let Some(format_trait_impl) = self.format_trait_impl { let linter = FormatImplExpr { cx, + format_args: &self.format_args, expr, format_trait_impl, }; @@ -141,6 +144,7 @@ impl<'tcx> LateLintPass<'tcx> for FormatImpl { struct FormatImplExpr<'a, 'tcx> { cx: &'a LateContext<'tcx>, + format_args: &'a FormatArgsStorage, expr: &'tcx Expr<'tcx>, format_trait_impl: FormatTraitNames, } @@ -175,7 +179,7 @@ impl<'a, 'tcx> FormatImplExpr<'a, 'tcx> { if let Some(outer_macro) = root_macro_call_first_node(self.cx, self.expr) && let macro_def_id = outer_macro.def_id && is_format_macro(self.cx, macro_def_id) - && let Some(format_args) = find_format_args(self.cx, self.expr, outer_macro.expn) + && let Some(format_args) = self.format_args.get(self.cx, self.expr, outer_macro.expn) { for piece in &format_args.template { if let FormatArgsPiece::Placeholder(placeholder) = piece diff --git a/clippy_lints/src/from_str_radix_10.rs b/clippy_lints/src/from_str_radix_10.rs index 633ed96d6a6d..82ce501bac59 100644 --- a/clippy_lints/src/from_str_radix_10.rs +++ b/clippy_lints/src/from_str_radix_10.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::is_integer_literal; use clippy_utils::sugg::Sugg; use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item}; +use clippy_utils::{in_constant, is_integer_literal}; use rustc_errors::Applicability; use rustc_hir::{def, Expr, ExprKind, LangItem, PrimTy, QPath, TyKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -47,6 +47,9 @@ impl<'tcx> LateLintPass<'tcx> for FromStrRadix10 { fn check_expr(&mut self, cx: &LateContext<'tcx>, exp: &Expr<'tcx>) { if let ExprKind::Call(maybe_path, [src, radix]) = &exp.kind && let ExprKind::Path(QPath::TypeRelative(ty, pathseg)) = &maybe_path.kind + // do not lint in constant context, because the suggestion won't work. + // NB: keep this check until a new `const_trait_impl` is available and stablized. + && !in_constant(cx, exp.hir_id) // check if the first part of the path is some integer primitive && let TyKind::Path(ty_qpath) = &ty.kind diff --git a/clippy_lints/src/functions/mod.rs b/clippy_lints/src/functions/mod.rs index 9cc51fa8cd5d..dfcaac9abefc 100644 --- a/clippy_lints/src/functions/mod.rs +++ b/clippy_lints/src/functions/mod.rs @@ -2,15 +2,17 @@ mod impl_trait_in_params; mod misnamed_getters; mod must_use; mod not_unsafe_ptr_arg_deref; +mod renamed_function_params; mod result; mod too_many_arguments; mod too_many_lines; +use clippy_utils::def_path_def_ids; use rustc_hir as hir; use rustc_hir::intravisit; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; -use rustc_span::def_id::LocalDefId; +use rustc_span::def_id::{DefIdSet, LocalDefId}; use rustc_span::Span; declare_clippy_lint! { @@ -359,13 +361,51 @@ declare_clippy_lint! { "`impl Trait` is used in the function's parameters" } -#[derive(Copy, Clone)] -#[allow(clippy::struct_field_names)] +declare_clippy_lint! { + /// ### What it does + /// Lints when the name of function parameters from trait impl is + /// different than its default implementation. + /// + /// ### Why is this bad? + /// Using the default name for parameters of a trait method is often + /// more desirable for consistency's sake. + /// + /// ### Example + /// ```rust + /// struct A(u32); + /// + /// impl PartialEq for A { + /// fn eq(&self, b: &Self) -> bool { + /// self.0 == b.0 + /// } + /// } + /// ``` + /// Use instead: + /// ```rust + /// struct A(u32); + /// + /// impl PartialEq for A { + /// fn eq(&self, other: &Self) -> bool { + /// self.0 == other.0 + /// } + /// } + /// ``` + #[clippy::version = "1.74.0"] + pub RENAMED_FUNCTION_PARAMS, + restriction, + "renamed function parameters in trait implementation" +} + +#[derive(Clone)] pub struct Functions { too_many_arguments_threshold: u64, too_many_lines_threshold: u64, large_error_threshold: u64, avoid_breaking_exported_api: bool, + allow_renamed_params_for: Vec, + /// A set of resolved `def_id` of traits that are configured to allow + /// function params renaming. + trait_ids: DefIdSet, } impl Functions { @@ -374,12 +414,15 @@ impl Functions { too_many_lines_threshold: u64, large_error_threshold: u64, avoid_breaking_exported_api: bool, + allow_renamed_params_for: Vec, ) -> Self { Self { too_many_arguments_threshold, too_many_lines_threshold, large_error_threshold, avoid_breaking_exported_api, + allow_renamed_params_for, + trait_ids: DefIdSet::default(), } } } @@ -395,6 +438,7 @@ impl_lint_pass!(Functions => [ RESULT_LARGE_ERR, MISNAMED_GETTERS, IMPL_TRAIT_IN_PARAMS, + RENAMED_FUNCTION_PARAMS, ]); impl<'tcx> LateLintPass<'tcx> for Functions { @@ -424,6 +468,7 @@ impl<'tcx> LateLintPass<'tcx> for Functions { must_use::check_impl_item(cx, item); result::check_impl_item(cx, item, self.large_error_threshold); impl_trait_in_params::check_impl_item(cx, item); + renamed_function_params::check_impl_item(cx, item, &self.trait_ids); } fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) { @@ -433,4 +478,12 @@ impl<'tcx> LateLintPass<'tcx> for Functions { result::check_trait_item(cx, item, self.large_error_threshold); impl_trait_in_params::check_trait_item(cx, item, self.avoid_breaking_exported_api); } + + fn check_crate(&mut self, cx: &LateContext<'tcx>) { + for path in &self.allow_renamed_params_for { + let path_segments: Vec<&str> = path.split("::").collect(); + let ids = def_path_def_ids(cx, &path_segments); + self.trait_ids.extend(ids); + } + } } diff --git a/clippy_lints/src/functions/renamed_function_params.rs b/clippy_lints/src/functions/renamed_function_params.rs new file mode 100644 index 000000000000..c7de0385c021 --- /dev/null +++ b/clippy_lints/src/functions/renamed_function_params.rs @@ -0,0 +1,110 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use rustc_errors::{Applicability, MultiSpan}; +use rustc_hir::def_id::{DefId, DefIdSet}; +use rustc_hir::hir_id::OwnerId; +use rustc_hir::{Impl, ImplItem, ImplItemKind, ImplItemRef, ItemKind, Node, TraitRef}; +use rustc_lint::LateContext; +use rustc_span::symbol::{kw, Ident, Symbol}; +use rustc_span::Span; + +use super::RENAMED_FUNCTION_PARAMS; + +pub(super) fn check_impl_item(cx: &LateContext<'_>, item: &ImplItem<'_>, ignored_traits: &DefIdSet) { + if !item.span.from_expansion() + && let ImplItemKind::Fn(_, body_id) = item.kind + && let parent_node = cx.tcx.parent_hir_node(item.hir_id()) + && let Node::Item(parent_item) = parent_node + && let ItemKind::Impl(Impl { + items, + of_trait: Some(trait_ref), + .. + }) = &parent_item.kind + && let Some(did) = trait_item_def_id_of_impl(items, item.owner_id) + && !is_from_ignored_trait(trait_ref, ignored_traits) + { + let mut param_idents_iter = cx.tcx.hir().body_param_names(body_id); + let mut default_param_idents_iter = cx.tcx.fn_arg_names(did).iter().copied(); + + let renames = RenamedFnArgs::new(&mut default_param_idents_iter, &mut param_idents_iter); + if !renames.0.is_empty() { + let multi_span = renames.multi_span(); + let plural = if renames.0.len() == 1 { "" } else { "s" }; + span_lint_and_then( + cx, + RENAMED_FUNCTION_PARAMS, + multi_span, + format!("renamed function parameter{plural} of trait impl"), + |diag| { + diag.multipart_suggestion( + format!("consider using the default name{plural}"), + renames.0, + Applicability::Unspecified, + ); + }, + ); + } + } +} + +struct RenamedFnArgs(Vec<(Span, String)>); + +impl RenamedFnArgs { + /// Comparing between an iterator of default names and one with current names, + /// then collect the ones that got renamed. + fn new(default_names: &mut I, current_names: &mut T) -> Self + where + I: Iterator, + T: Iterator, + { + let mut renamed: Vec<(Span, String)> = vec![]; + + debug_assert!(default_names.size_hint() == current_names.size_hint()); + while let (Some(def_name), Some(cur_name)) = (default_names.next(), current_names.next()) { + let current_name = cur_name.name; + let default_name = def_name.name; + if is_unused_or_empty_symbol(current_name) || is_unused_or_empty_symbol(default_name) { + continue; + } + if current_name != default_name { + renamed.push((cur_name.span, default_name.to_string())); + } + } + + Self(renamed) + } + + fn multi_span(&self) -> MultiSpan { + self.0 + .iter() + .map(|(span, _)| span) + .copied() + .collect::>() + .into() + } +} + +fn is_unused_or_empty_symbol(symbol: Symbol) -> bool { + // FIXME: `body_param_names` currently returning empty symbols for `wild` as well, + // so we need to check if the symbol is empty first. + // Therefore the check of whether it's equal to [`kw::Underscore`] has no use for now, + // but it would be nice to keep it here just to be future-proof. + symbol.is_empty() || symbol == kw::Underscore || symbol.as_str().starts_with('_') +} + +/// Get the [`trait_item_def_id`](ImplItemRef::trait_item_def_id) of a relevant impl item. +fn trait_item_def_id_of_impl(items: &[ImplItemRef], target: OwnerId) -> Option { + items.iter().find_map(|item| { + if item.id.owner_id == target { + item.trait_item_def_id + } else { + None + } + }) +} + +fn is_from_ignored_trait(of_trait: &TraitRef<'_>, ignored_traits: &DefIdSet) -> bool { + let Some(trait_did) = of_trait.trait_def_id() else { + return false; + }; + ignored_traits.contains(&trait_did) +} diff --git a/clippy_lints/src/future_not_send.rs b/clippy_lints/src/future_not_send.rs index 2c2daac02349..192fb611c2d4 100644 --- a/clippy_lints/src/future_not_send.rs +++ b/clippy_lints/src/future_not_send.rs @@ -4,8 +4,8 @@ use rustc_hir::intravisit::FnKind; use rustc_hir::{Body, FnDecl}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::{self, AliasTy, ClauseKind, PredicateKind}; use rustc_middle::ty::print::PrintTraitRefExt; +use rustc_middle::ty::{self, AliasTy, ClauseKind, PredicateKind}; use rustc_session::declare_lint_pass; use rustc_span::def_id::LocalDefId; use rustc_span::{sym, Span}; diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index a8bfbbdd9eca..3328d642bd85 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -61,11 +61,6 @@ extern crate clippy_utils; #[macro_use] extern crate declare_clippy_lint; -use std::collections::BTreeMap; - -use rustc_data_structures::fx::FxHashSet; -use rustc_lint::{Lint, LintId}; - #[cfg(feature = "internal")] pub mod deprecated_lints; #[cfg_attr(feature = "internal", allow(clippy::missing_clippy_version_attribute))] @@ -199,6 +194,7 @@ mod lifetimes; mod lines_filter_map_ok; mod literal_representation; mod loops; +mod macro_metavars_in_unsafe; mod macro_use; mod main_recursion; mod manual_assert; @@ -385,6 +381,10 @@ mod zero_sized_map_values; // end lints modules, do not remove this comment, it’s used in `update_lints` use clippy_config::{get_configuration_metadata, Conf}; +use clippy_utils::macros::FormatArgsStorage; +use rustc_data_structures::fx::FxHashSet; +use rustc_lint::{Lint, LintId}; +use std::collections::BTreeMap; /// Register all pre expansion lints /// @@ -533,6 +533,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { allow_expect_in_tests, allow_mixed_uninlined_format_args, allow_one_hash_in_raw_strings, + allow_panic_in_tests, allow_print_in_tests, allow_private_module_inception, allow_unwrap_in_tests, @@ -597,9 +598,11 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { ref allowed_duplicate_crates, allow_comparison_to_zero, ref allowed_prefixes, + ref allow_renamed_params_for, blacklisted_names: _, cyclomatic_complexity_threshold: _, + warn_unsafe_macro_metavars_in_private_macros, } = *conf; let msrv = || msrv.clone(); @@ -616,6 +619,14 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { } } + let format_args_storage = FormatArgsStorage::default(); + let format_args = format_args_storage.clone(); + store.register_early_pass(move || { + Box::new(utils::format_args_collector::FormatArgsCollector::new( + format_args.clone(), + )) + }); + // all the internal lints #[cfg(feature = "internal")] { @@ -656,7 +667,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { .collect(), )) }); - store.register_early_pass(|| Box::::default()); store.register_late_pass(|_| Box::new(utils::dump_hir::DumpHir)); store.register_late_pass(|_| Box::new(utils::author::Author)); store.register_late_pass(move |_| { @@ -698,6 +708,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_late_pass(|_| Box::new(non_octal_unix_permissions::NonOctalUnixPermissions)); store.register_early_pass(|| Box::new(unnecessary_self_imports::UnnecessarySelfImports)); store.register_late_pass(move |_| Box::new(approx_const::ApproxConstant::new(msrv()))); + let format_args = format_args_storage.clone(); store.register_late_pass(move |_| { Box::new(methods::Methods::new( avoid_breaking_exported_api, @@ -705,6 +716,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { allow_expect_in_tests, allow_unwrap_in_tests, allowed_dotfiles.clone(), + format_args.clone(), )) }); store.register_late_pass(move |_| Box::new(matches::Matches::new(msrv()))); @@ -759,7 +771,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { allow_in_test: allow_useless_vec_in_tests, }) }); - store.register_late_pass(|_| Box::new(panic_unimplemented::PanicUnimplemented)); + store.register_late_pass(move |_| Box::new(panic_unimplemented::PanicUnimplemented { allow_panic_in_tests })); store.register_late_pass(|_| Box::new(strings::StringLitAsBytes)); store.register_late_pass(|_| Box::new(derive::Derive)); store.register_late_pass(move |_| Box::new(derivable_impls::DerivableImpls::new(msrv()))); @@ -769,7 +781,8 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_late_pass(|_| Box::::default()); store.register_late_pass(move |_| Box::new(copies::CopyAndPaste::new(ignore_interior_mutability.clone()))); store.register_late_pass(|_| Box::new(copy_iterator::CopyIterator)); - store.register_late_pass(|_| Box::new(format::UselessFormat)); + let format_args = format_args_storage.clone(); + store.register_late_pass(move |_| Box::new(format::UselessFormat::new(format_args.clone()))); store.register_late_pass(|_| Box::new(swap::Swap)); store.register_late_pass(|_| Box::new(overflow_check_conditional::OverflowCheckConditional)); store.register_late_pass(|_| Box::::default()); @@ -780,6 +793,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { too_many_lines_threshold, large_error_threshold, avoid_breaking_exported_api, + allow_renamed_params_for.clone(), )) }); store.register_late_pass(move |_| Box::new(doc::Documentation::new(doc_valid_idents, check_private_items))); @@ -793,7 +807,8 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_late_pass(|_| Box::new(partialeq_ne_impl::PartialEqNeImpl)); store.register_late_pass(|_| Box::new(unused_io_amount::UnusedIoAmount)); store.register_late_pass(move |_| Box::new(large_enum_variant::LargeEnumVariant::new(enum_variant_size_threshold))); - store.register_late_pass(|_| Box::new(explicit_write::ExplicitWrite)); + let format_args = format_args_storage.clone(); + store.register_late_pass(move |_| Box::new(explicit_write::ExplicitWrite::new(format_args.clone()))); store.register_late_pass(|_| Box::new(needless_pass_by_value::NeedlessPassByValue)); store.register_late_pass(move |tcx| { Box::new(pass_by_ref_or_value::PassByRefOrValue::new( @@ -835,7 +850,8 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_late_pass(move |_| Box::new(mut_key::MutableKeyType::new(ignore_interior_mutability.clone()))); store.register_early_pass(|| Box::new(reference::DerefAddrOf)); store.register_early_pass(|| Box::new(double_parens::DoubleParens)); - store.register_late_pass(|_| Box::new(format_impl::FormatImpl::new())); + let format_args = format_args_storage.clone(); + store.register_late_pass(move |_| Box::new(format_impl::FormatImpl::new(format_args.clone()))); store.register_early_pass(|| Box::new(unsafe_removed_from_name::UnsafeNameRemoval)); store.register_early_pass(|| Box::new(else_if_without_else::ElseIfWithoutElse)); store.register_early_pass(|| Box::new(int_plus_one::IntPlusOne)); @@ -961,8 +977,14 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { accept_comment_above_attributes, )) }); - store - .register_late_pass(move |_| Box::new(format_args::FormatArgs::new(msrv(), allow_mixed_uninlined_format_args))); + let format_args = format_args_storage.clone(); + store.register_late_pass(move |_| { + Box::new(format_args::FormatArgs::new( + format_args.clone(), + msrv(), + allow_mixed_uninlined_format_args, + )) + }); store.register_late_pass(|_| Box::new(trailing_empty_array::TrailingEmptyArray)); store.register_early_pass(|| Box::new(octal_escapes::OctalEscapes)); store.register_late_pass(|_| Box::new(needless_late_init::NeedlessLateInit)); @@ -973,7 +995,8 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_late_pass(|_| Box::new(default_union_representation::DefaultUnionRepresentation)); store.register_late_pass(|_| Box::::default()); store.register_late_pass(move |_| Box::new(dbg_macro::DbgMacro::new(allow_dbg_in_tests))); - store.register_late_pass(move |_| Box::new(write::Write::new(allow_print_in_tests))); + let format_args = format_args_storage.clone(); + store.register_late_pass(move |_| Box::new(write::Write::new(format_args.clone(), allow_print_in_tests))); store.register_late_pass(move |_| { Box::new(cargo::Cargo { ignore_publish: cargo_ignore_publish, @@ -1136,6 +1159,12 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_late_pass(|_| Box::new(zero_repeat_side_effects::ZeroRepeatSideEffects)); store.register_late_pass(|_| Box::new(manual_unwrap_or_default::ManualUnwrapOrDefault)); store.register_late_pass(|_| Box::new(integer_division_remainder_used::IntegerDivisionRemainderUsed)); + store.register_late_pass(move |_| { + Box::new(macro_metavars_in_unsafe::ExprMetavarsInUnsafe { + warn_unsafe_macro_metavars_in_private_macros, + ..Default::default() + }) + }); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/loops/mod.rs b/clippy_lints/src/loops/mod.rs index b5e39b33c6a1..3dcb050d77e6 100644 --- a/clippy_lints/src/loops/mod.rs +++ b/clippy_lints/src/loops/mod.rs @@ -17,6 +17,7 @@ mod same_item_push; mod single_element_loop; mod unused_enumerate_index; mod utils; +mod while_float; mod while_immutable_condition; mod while_let_loop; mod while_let_on_iterator; @@ -416,6 +417,39 @@ declare_clippy_lint! { "variables used within while expression are not mutated in the body" } +declare_clippy_lint! { + /// ### What it does + /// Checks for while loops comparing floating point values. + /// + /// ### Why is this bad? + /// If you increment floating point values, errors can compound, + /// so, use integers instead if possible. + /// + /// ### Known problems + /// The lint will catch all while loops comparing floating point + /// values without regarding the increment. + /// + /// ### Example + /// ```no_run + /// let mut x = 0.0; + /// while x < 42.0 { + /// x += 1.0; + /// } + /// ``` + /// + /// Use instead: + /// ```no_run + /// let mut x = 0; + /// while x < 42 { + /// x += 1; + /// } + /// ``` + #[clippy::version = "1.80.0"] + pub WHILE_FLOAT, + nursery, + "while loops comaparing floating point values" +} + declare_clippy_lint! { /// ### What it does /// Checks whether a for loop is being used to push a constant @@ -706,6 +740,7 @@ impl_lint_pass!(Loops => [ NEVER_LOOP, MUT_RANGE_BOUND, WHILE_IMMUTABLE_CONDITION, + WHILE_FLOAT, SAME_ITEM_PUSH, SINGLE_ELEMENT_LOOP, MISSING_SPIN_LOOP, @@ -762,6 +797,7 @@ impl<'tcx> LateLintPass<'tcx> for Loops { if let Some(higher::While { condition, body, span }) = higher::While::hir(expr) { while_immutable_condition::check(cx, condition, body); + while_float::check(cx, condition); missing_spin_loop::check(cx, condition, body); manual_while_let_some::check(cx, condition, body, span); } diff --git a/clippy_lints/src/loops/mut_range_bound.rs b/clippy_lints/src/loops/mut_range_bound.rs index 6b9ecf5f1413..6c6a9a1a2e00 100644 --- a/clippy_lints/src/loops/mut_range_bound.rs +++ b/clippy_lints/src/loops/mut_range_bound.rs @@ -60,12 +60,9 @@ fn check_for_mutation( span_low: None, span_high: None, }; - ExprUseVisitor::for_clippy( - cx, - body.hir_id.owner.def_id, - &mut delegate, - ) - .walk_expr(body).into_ok(); + ExprUseVisitor::for_clippy(cx, body.hir_id.owner.def_id, &mut delegate) + .walk_expr(body) + .into_ok(); delegate.mutation_span() } diff --git a/clippy_lints/src/loops/while_float.rs b/clippy_lints/src/loops/while_float.rs new file mode 100644 index 000000000000..cf62ce29f0c7 --- /dev/null +++ b/clippy_lints/src/loops/while_float.rs @@ -0,0 +1,20 @@ +use clippy_utils::diagnostics::span_lint; +use rustc_hir::ExprKind; + +pub(super) fn check(cx: &rustc_lint::LateContext<'_>, condition: &rustc_hir::Expr<'_>) { + if let ExprKind::Binary(_op, left, right) = condition.kind + && is_float_type(cx, left) + && is_float_type(cx, right) + { + span_lint( + cx, + super::WHILE_FLOAT, + condition.span, + "while condition comparing floats", + ); + } +} + +fn is_float_type(cx: &rustc_lint::LateContext<'_>, expr: &rustc_hir::Expr<'_>) -> bool { + cx.typeck_results().expr_ty(expr).is_floating_point() +} diff --git a/clippy_lints/src/macro_metavars_in_unsafe.rs b/clippy_lints/src/macro_metavars_in_unsafe.rs new file mode 100644 index 000000000000..aea3d26e1878 --- /dev/null +++ b/clippy_lints/src/macro_metavars_in_unsafe.rs @@ -0,0 +1,256 @@ +use std::collections::btree_map::Entry; +use std::collections::BTreeMap; + +use clippy_utils::diagnostics::span_lint_hir_and_then; +use clippy_utils::is_lint_allowed; +use itertools::Itertools; +use rustc_hir::def_id::LocalDefId; +use rustc_hir::intravisit::{walk_block, walk_expr, walk_stmt, Visitor}; +use rustc_hir::{BlockCheckMode, Expr, ExprKind, HirId, Stmt, UnsafeSource}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::impl_lint_pass; +use rustc_span::{sym, Span, SyntaxContext}; + +declare_clippy_lint! { + /// ### What it does + /// Looks for macros that expand metavariables in an unsafe block. + /// + /// ### Why is this bad? + /// This hides an unsafe block and allows the user of the macro to write unsafe code without an explicit + /// unsafe block at callsite, making it possible to perform unsafe operations in seemingly safe code. + /// + /// The macro should be restructured so that these metavariables are referenced outside of unsafe blocks + /// and that the usual unsafety checks apply to the macro argument. + /// + /// This is usually done by binding it to a variable outside of the unsafe block + /// and then using that variable inside of the block as shown in the example, or by referencing it a second time + /// in a safe context, e.g. `if false { $expr }`. + /// + /// ### Known limitations + /// Due to how macros are represented in the compiler at the time Clippy runs its lints, + /// it's not possible to look for metavariables in macro definitions directly. + /// + /// Instead, this lint looks at expansions of macros. + /// This leads to false negatives for macros that are never actually invoked. + /// + /// By default, this lint is rather conservative and will only emit warnings on publicly-exported + /// macros from the same crate, because oftentimes private internal macros are one-off macros where + /// this lint would just be noise (e.g. macros that generate `impl` blocks). + /// The default behavior should help with preventing a high number of such false positives, + /// however it can be configured to also emit warnings in private macros if desired. + /// + /// ### Example + /// ```no_run + /// /// Gets the first element of a slice + /// macro_rules! first { + /// ($slice:expr) => { + /// unsafe { + /// let slice = $slice; // ⚠️ expansion inside of `unsafe {}` + /// + /// assert!(!slice.is_empty()); + /// // SAFETY: slice is checked to have at least one element + /// slice.first().unwrap_unchecked() + /// } + /// } + /// } + /// + /// assert_eq!(*first!(&[1i32]), 1); + /// + /// // This will compile as a consequence (note the lack of `unsafe {}`) + /// assert_eq!(*first!(std::hint::unreachable_unchecked() as &[i32]), 1); + /// ``` + /// Use instead: + /// ```compile_fail + /// macro_rules! first { + /// ($slice:expr) => {{ + /// let slice = $slice; // ✅ outside of `unsafe {}` + /// unsafe { + /// assert!(!slice.is_empty()); + /// // SAFETY: slice is checked to have at least one element + /// slice.first().unwrap_unchecked() + /// } + /// }} + /// } + /// + /// assert_eq!(*first!(&[1]), 1); + /// + /// // This won't compile: + /// assert_eq!(*first!(std::hint::unreachable_unchecked() as &[i32]), 1); + /// ``` + #[clippy::version = "1.80.0"] + pub MACRO_METAVARS_IN_UNSAFE, + suspicious, + "expanding macro metavariables in an unsafe block" +} +impl_lint_pass!(ExprMetavarsInUnsafe => [MACRO_METAVARS_IN_UNSAFE]); + +#[derive(Clone, Debug)] +pub enum MetavarState { + ReferencedInUnsafe { unsafe_blocks: Vec }, + ReferencedInSafe, +} + +#[derive(Default)] +pub struct ExprMetavarsInUnsafe { + pub warn_unsafe_macro_metavars_in_private_macros: bool, + /// A metavariable can be expanded more than once, potentially across multiple bodies, so it + /// requires some state kept across HIR nodes to make it possible to delay a warning + /// and later undo: + /// + /// ```ignore + /// macro_rules! x { + /// ($v:expr) => { + /// unsafe { $v; } // unsafe context, it might be possible to emit a warning here, so add it to the map + /// + /// $v; // `$v` expanded another time but in a safe context, set to ReferencedInSafe to suppress + /// } + /// } + /// ``` + pub metavar_expns: BTreeMap, +} + +struct BodyVisitor<'a, 'tcx> { + /// Stack of unsafe blocks -- the top item always represents the last seen unsafe block from + /// within a relevant macro. + macro_unsafe_blocks: Vec, + /// When this is >0, it means that the node currently being visited is "within" a + /// macro definition. This is not necessary for correctness, it merely helps reduce the number + /// of spans we need to insert into the map, since only spans from macros are relevant. + expn_depth: u32, + cx: &'a LateContext<'tcx>, + lint: &'a mut ExprMetavarsInUnsafe, +} + +fn is_public_macro(cx: &LateContext<'_>, def_id: LocalDefId) -> bool { + (cx.effective_visibilities.is_exported(def_id) || cx.tcx.has_attr(def_id, sym::macro_export)) + && !cx.tcx.is_doc_hidden(def_id) +} + +impl<'a, 'tcx> Visitor<'tcx> for BodyVisitor<'a, 'tcx> { + fn visit_stmt(&mut self, s: &'tcx Stmt<'tcx>) { + let from_expn = s.span.from_expansion(); + if from_expn { + self.expn_depth += 1; + } + walk_stmt(self, s); + if from_expn { + self.expn_depth -= 1; + } + } + + fn visit_expr(&mut self, e: &'tcx Expr<'tcx>) { + let ctxt = e.span.ctxt(); + + if let ExprKind::Block(block, _) = e.kind + && let BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) = block.rules + && !ctxt.is_root() + && let Some(macro_def_id) = ctxt.outer_expn_data().macro_def_id + && let Some(macro_def_id) = macro_def_id.as_local() + && (self.lint.warn_unsafe_macro_metavars_in_private_macros || is_public_macro(self.cx, macro_def_id)) + { + self.macro_unsafe_blocks.push(block.hir_id); + walk_block(self, block); + self.macro_unsafe_blocks.pop(); + } else if ctxt.is_root() && self.expn_depth > 0 { + let unsafe_block = self.macro_unsafe_blocks.last().copied(); + + match (self.lint.metavar_expns.entry(e.span), unsafe_block) { + (Entry::Vacant(e), None) => { + e.insert(MetavarState::ReferencedInSafe); + }, + (Entry::Vacant(e), Some(unsafe_block)) => { + e.insert(MetavarState::ReferencedInUnsafe { + unsafe_blocks: vec![unsafe_block], + }); + }, + (Entry::Occupied(mut e), None) => { + if let MetavarState::ReferencedInUnsafe { .. } = *e.get() { + e.insert(MetavarState::ReferencedInSafe); + } + }, + (Entry::Occupied(mut e), Some(unsafe_block)) => { + if let MetavarState::ReferencedInUnsafe { unsafe_blocks } = e.get_mut() + && !unsafe_blocks.contains(&unsafe_block) + { + unsafe_blocks.push(unsafe_block); + } + }, + } + + // NB: No need to visit descendant nodes. They're guaranteed to represent the same + // metavariable + } else { + walk_expr(self, e); + } + } +} + +impl<'tcx> LateLintPass<'tcx> for ExprMetavarsInUnsafe { + fn check_body(&mut self, cx: &LateContext<'tcx>, body: &'tcx rustc_hir::Body<'tcx>) { + if is_lint_allowed(cx, MACRO_METAVARS_IN_UNSAFE, body.value.hir_id) { + return; + } + + // This BodyVisitor is separate and not part of the lint pass because there is no + // `check_stmt_post` on `(Late)LintPass`, which we'd need to detect when we're leaving a macro span + + let mut vis = BodyVisitor { + #[expect(clippy::bool_to_int_with_if)] // obfuscates the meaning + expn_depth: if body.value.span.from_expansion() { 1 } else { 0 }, + macro_unsafe_blocks: Vec::new(), + lint: self, + cx + }; + vis.visit_body(body); + } + + fn check_crate_post(&mut self, cx: &LateContext<'tcx>) { + // Aggregate all unsafe blocks from all spans: + // ``` + // macro_rules! x { + // ($w:expr, $x:expr, $y:expr) => { $w; unsafe { $w; $x; }; unsafe { $x; $y; }; } + // } + // $w: [] (unsafe#0 is never added because it was referenced in a safe context) + // $x: [unsafe#0, unsafe#1] + // $y: [unsafe#1] + // ``` + // We want to lint unsafe blocks #0 and #1 + let bad_unsafe_blocks = self + .metavar_expns + .iter() + .filter_map(|(_, state)| match state { + MetavarState::ReferencedInUnsafe { unsafe_blocks } => Some(unsafe_blocks.as_slice()), + MetavarState::ReferencedInSafe => None, + }) + .flatten() + .copied() + .map(|id| { + // Remove the syntax context to hide "in this macro invocation" in the diagnostic. + // The invocation doesn't matter. Also we want to dedupe by the unsafe block and not by anything + // related to the callsite. + let span = cx.tcx.hir().span(id); + + (id, Span::new(span.lo(), span.hi(), SyntaxContext::root(), None)) + }) + .dedup_by(|&(_, a), &(_, b)| a == b); + + for (id, span) in bad_unsafe_blocks { + span_lint_hir_and_then( + cx, + MACRO_METAVARS_IN_UNSAFE, + id, + span, + "this macro expands metavariables in an unsafe block", + |diag| { + diag.note("this allows the user of the macro to write unsafe code outside of an unsafe block"); + diag.help( + "consider expanding any metavariables outside of this block, e.g. by storing them in a variable", + ); + diag.help( + "... or also expand referenced metavariables in a safe context to require an unsafe block at callsite", + ); + }, + ); + } + } +} diff --git a/clippy_lints/src/manual_clamp.rs b/clippy_lints/src/manual_clamp.rs index 1eadc200bedc..e2ab44155182 100644 --- a/clippy_lints/src/manual_clamp.rs +++ b/clippy_lints/src/manual_clamp.rs @@ -611,15 +611,22 @@ impl<'tcx> BinaryOp<'tcx> { /// The clamp meta pattern is a pattern shared between many (but not all) patterns. /// In summary, this pattern consists of two if statements that meet many criteria, +/// /// - binary operators that are one of [`>`, `<`, `>=`, `<=`]. +/// /// - Both binary statements must have a shared argument +/// /// - Which can appear on the left or right side of either statement +/// /// - The binary operators must define a finite range for the shared argument. To put this in /// the terms of Rust `std` library, the following ranges are acceptable +/// /// - `Range` /// - `RangeInclusive` +/// /// And all other range types are not accepted. For the purposes of `clamp` it's irrelevant /// whether the range is inclusive or not, the output is the same. +/// /// - The result of each if statement must be equal to the argument unique to that if statement. The /// result can not be the shared argument in either case. fn is_clamp_meta_pattern<'tcx>( diff --git a/clippy_lints/src/matches/match_same_arms.rs b/clippy_lints/src/matches/match_same_arms.rs index cd61e733694b..da8c918a62bb 100644 --- a/clippy_lints/src/matches/match_same_arms.rs +++ b/clippy_lints/src/matches/match_same_arms.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_hir_and_then; -use clippy_utils::source::snippet; +use clippy_utils::source::snippet_with_applicability; use clippy_utils::{is_lint_allowed, path_to_local, search_same, SpanlessEq, SpanlessHash}; use core::cmp::Ordering; use core::{iter, slice}; @@ -9,9 +9,9 @@ use rustc_errors::Applicability; use rustc_hir::def_id::DefId; use rustc_hir::{Arm, Expr, ExprKind, HirId, HirIdMap, HirIdMapEntry, HirIdSet, Pat, PatKind, RangeEnd}; use rustc_lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; -use rustc_lint::LateContext; +use rustc_lint::{LateContext, LintContext}; use rustc_middle::ty; -use rustc_span::{ErrorGuaranteed, Symbol}; +use rustc_span::{ErrorGuaranteed, Span, Symbol}; use super::MATCH_SAME_ARMS; @@ -110,20 +110,22 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) { && check_same_body() }; + let mut appl = Applicability::MaybeIncorrect; let indexed_arms: Vec<(usize, &Arm<'_>)> = arms.iter().enumerate().collect(); for (&(i, arm1), &(j, arm2)) in search_same(&indexed_arms, hash, eq) { if matches!(arm2.pat.kind, PatKind::Wild) { if !cx.tcx.features().non_exhaustive_omitted_patterns_lint || is_lint_allowed(cx, NON_EXHAUSTIVE_OMITTED_PATTERNS, arm2.hir_id) { + let arm_span = adjusted_arm_span(cx, arm1.span); span_lint_hir_and_then( cx, MATCH_SAME_ARMS, arm1.hir_id, - arm1.span, + arm_span, "this match arm has an identical body to the `_` wildcard arm", |diag| { - diag.span_suggestion(arm1.span, "try removing the arm", "", Applicability::MaybeIncorrect) + diag.span_suggestion(arm_span, "try removing the arm", "", appl) .help("or try changing either arm body") .span_note(arm2.span, "`_` wildcard arm here"); }, @@ -144,23 +146,36 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) { keep_arm.span, "this match arm has an identical body to another arm", |diag| { - let move_pat_snip = snippet(cx, move_arm.pat.span, ""); - let keep_pat_snip = snippet(cx, keep_arm.pat.span, ""); + let move_pat_snip = snippet_with_applicability(cx, move_arm.pat.span, "", &mut appl); + let keep_pat_snip = snippet_with_applicability(cx, keep_arm.pat.span, "", &mut appl); diag.span_suggestion( keep_arm.pat.span, - "try merging the arm patterns", + "or try merging the arm patterns", format!("{keep_pat_snip} | {move_pat_snip}"), - Applicability::MaybeIncorrect, + appl, ) - .help("or try changing either arm body") - .span_note(move_arm.span, "other arm here"); + .span_suggestion( + adjusted_arm_span(cx, move_arm.span), + "and remove this obsolete arm", + "", + appl, + ) + .help("try changing either arm body"); }, ); } } } +/// Extend arm's span to include the comma and whitespaces after it. +fn adjusted_arm_span(cx: &LateContext<'_>, span: Span) -> Span { + let source_map = cx.sess().source_map(); + source_map + .span_extend_while(span, |c| c == ',' || c.is_ascii_whitespace()) + .unwrap_or(span) +} + #[derive(Clone, Copy)] enum NormalizedPat<'a> { Wild, diff --git a/clippy_lints/src/matches/significant_drop_in_scrutinee.rs b/clippy_lints/src/matches/significant_drop_in_scrutinee.rs index f775ea072e1f..6ac0705abb21 100644 --- a/clippy_lints/src/matches/significant_drop_in_scrutinee.rs +++ b/clippy_lints/src/matches/significant_drop_in_scrutinee.rs @@ -115,45 +115,60 @@ impl<'a, 'tcx> SigDropChecker<'a, 'tcx> { } } - fn get_type(&self, ex: &'tcx Expr<'_>) -> Ty<'tcx> { - self.cx.typeck_results().expr_ty(ex) + fn is_sig_drop_expr(&mut self, ex: &'tcx Expr<'_>) -> bool { + !ex.is_syntactic_place_expr() && self.has_sig_drop_attr(self.cx.typeck_results().expr_ty(ex)) } - fn has_seen_type(&mut self, ty: Ty<'tcx>) -> bool { - !self.seen_types.insert(ty) + fn has_sig_drop_attr(&mut self, ty: Ty<'tcx>) -> bool { + self.seen_types.clear(); + self.has_sig_drop_attr_impl(ty) } - fn has_sig_drop_attr(&mut self, cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { + fn has_sig_drop_attr_impl(&mut self, ty: Ty<'tcx>) -> bool { if let Some(adt) = ty.ty_adt_def() { - if get_attr(cx.sess(), cx.tcx.get_attrs_unchecked(adt.did()), "has_significant_drop").count() > 0 { + if get_attr( + self.cx.sess(), + self.cx.tcx.get_attrs_unchecked(adt.did()), + "has_significant_drop", + ) + .count() + > 0 + { return true; } } - match ty.kind() { - rustc_middle::ty::Adt(a, b) => { - for f in a.all_fields() { - let ty = f.ty(cx.tcx, b); - if !self.has_seen_type(ty) && self.has_sig_drop_attr(cx, ty) { - return true; - } - } - - for generic_arg in *b { - if let GenericArgKind::Type(ty) = generic_arg.unpack() { - if self.has_sig_drop_attr(cx, ty) { - return true; - } - } - } - false - }, - rustc_middle::ty::Array(ty, _) - | rustc_middle::ty::RawPtr(ty, _) - | rustc_middle::ty::Ref(_, ty, _) - | rustc_middle::ty::Slice(ty) => self.has_sig_drop_attr(cx, *ty), - _ => false, + if !self.seen_types.insert(ty) { + return false; } + + let result = match ty.kind() { + rustc_middle::ty::Adt(adt, args) => { + // if some field has significant drop, + adt.all_fields() + .map(|field| field.ty(self.cx.tcx, args)) + .any(|ty| self.has_sig_drop_attr_impl(ty)) + // or if there is no generic lifetime and.. + // (to avoid false positive on `Ref<'a, MutexGuard>`) + || (args + .iter() + .all(|arg| !matches!(arg.unpack(), GenericArgKind::Lifetime(_))) + // some generic parameter has significant drop + // (to avoid false negative on `Box>`) + && args + .iter() + .filter_map(|arg| match arg.unpack() { + GenericArgKind::Type(ty) => Some(ty), + _ => None, + }) + .any(|ty| self.has_sig_drop_attr_impl(ty))) + }, + rustc_middle::ty::Tuple(tys) => tys.iter().any(|ty| self.has_sig_drop_attr_impl(ty)), + rustc_middle::ty::Array(ty, _) | rustc_middle::ty::Slice(ty) => self.has_sig_drop_attr_impl(*ty), + _ => false, + }; + + result } } @@ -232,7 +247,7 @@ impl<'a, 'tcx> SigDropHelper<'a, 'tcx> { if self.current_sig_drop.is_some() { return; } - let ty = self.sig_drop_checker.get_type(expr); + let ty = self.cx.typeck_results().expr_ty(expr); if ty.is_ref() { // We checked that the type was ref, so builtin_deref will return Some, // but let's avoid any chance of an ICE. @@ -279,11 +294,7 @@ impl<'a, 'tcx> SigDropHelper<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for SigDropHelper<'a, 'tcx> { fn visit_expr(&mut self, ex: &'tcx Expr<'_>) { - if !self.is_chain_end - && self - .sig_drop_checker - .has_sig_drop_attr(self.cx, self.sig_drop_checker.get_type(ex)) - { + if !self.is_chain_end && self.sig_drop_checker.is_sig_drop_expr(ex) { self.has_significant_drop = true; return; } @@ -387,10 +398,7 @@ fn has_significant_drop_in_arms<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<' impl<'a, 'tcx> Visitor<'tcx> for ArmSigDropHelper<'a, 'tcx> { fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) { - if self - .sig_drop_checker - .has_sig_drop_attr(self.sig_drop_checker.cx, self.sig_drop_checker.get_type(ex)) - { + if self.sig_drop_checker.is_sig_drop_expr(ex) { self.found_sig_drop_spans.insert(ex.span); return; } diff --git a/clippy_lints/src/methods/expect_fun_call.rs b/clippy_lints/src/methods/expect_fun_call.rs index fba76852344f..c9f56e1d9809 100644 --- a/clippy_lints/src/methods/expect_fun_call.rs +++ b/clippy_lints/src/methods/expect_fun_call.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::macros::{find_format_args, format_args_inputs_span, root_macro_call_first_node}; +use clippy_utils::macros::{format_args_inputs_span, root_macro_call_first_node, FormatArgsStorage}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item}; use rustc_errors::Applicability; @@ -16,6 +16,7 @@ use super::EXPECT_FUN_CALL; #[allow(clippy::too_many_lines)] pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, + format_args_storage: &FormatArgsStorage, expr: &hir::Expr<'_>, method_span: Span, name: &str, @@ -134,9 +135,9 @@ pub(super) fn check<'tcx>( // Special handling for `format!` as arg_root if let Some(macro_call) = root_macro_call_first_node(cx, arg_root) { if cx.tcx.is_diagnostic_item(sym::format_macro, macro_call.def_id) - && let Some(format_args) = find_format_args(cx, arg_root, macro_call.expn) + && let Some(format_args) = format_args_storage.get(cx, arg_root, macro_call.expn) { - let span = format_args_inputs_span(&format_args); + let span = format_args_inputs_span(format_args); let sugg = snippet_with_applicability(cx, span, "..", &mut applicability); span_lint_and_sugg( cx, diff --git a/clippy_lints/src/methods/iter_filter.rs b/clippy_lints/src/methods/iter_filter.rs index 12647ea1ffcb..b93d51eac647 100644 --- a/clippy_lints/src/methods/iter_filter.rs +++ b/clippy_lints/src/methods/iter_filter.rs @@ -126,15 +126,15 @@ enum FilterType { /// /// How this is done: /// 1. we know that this is invoked in a method call with `filter` as the method name via `mod.rs` -/// 2. we check that we are in a trait method. Therefore we are in an -/// `(x as Iterator).filter({filter_arg})` method call. +/// 2. we check that we are in a trait method. Therefore we are in an `(x as +/// Iterator).filter({filter_arg})` method call. /// 3. we check that the parent expression is not a map. This is because we don't want to lint /// twice, and we already have a specialized lint for that. /// 4. we check that the span of the filter does not contain a comment. /// 5. we get the type of the `Item` in the `Iterator`, and compare against the type of Option and -/// Result. +/// Result. /// 6. we finally check the contents of the filter argument to see if it is a call to `is_some` or -/// `is_ok`. +/// `is_ok`. /// 7. if all of the above are true, then we return the `FilterType` fn expression_type( cx: &LateContext<'_>, diff --git a/clippy_lints/src/methods/iter_kv_map.rs b/clippy_lints/src/methods/iter_kv_map.rs index 7c852a3768d1..05e77386128f 100644 --- a/clippy_lints/src/methods/iter_kv_map.rs +++ b/clippy_lints/src/methods/iter_kv_map.rs @@ -12,8 +12,10 @@ use rustc_middle::ty; use rustc_span::{sym, Span}; /// lint use of: +/// /// - `hashmap.iter().map(|(_, v)| v)` /// - `hashmap.into_iter().map(|(_, v)| v)` +/// /// on `HashMaps` and `BTreeMaps` in std pub(super) fn check<'tcx>( diff --git a/clippy_lints/src/methods/iter_overeager_cloned.rs b/clippy_lints/src/methods/iter_overeager_cloned.rs index a52d38790a2b..5ccb5243e903 100644 --- a/clippy_lints/src/methods/iter_overeager_cloned.rs +++ b/clippy_lints/src/methods/iter_overeager_cloned.rs @@ -69,12 +69,9 @@ pub(super) fn check<'tcx>( used_move: HirIdSet::default(), }; - ExprUseVisitor::for_clippy( - cx, - closure.def_id, - &mut delegate, - ) - .consume_body(body).into_ok(); + ExprUseVisitor::for_clippy(cx, closure.def_id, &mut delegate) + .consume_body(body) + .into_ok(); let mut to_be_discarded = false; diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 2b92bff016db..9d67aa233797 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -133,6 +133,7 @@ use bind_instead_of_map::BindInsteadOfMap; use clippy_config::msrvs::{self, Msrv}; use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; +use clippy_utils::macros::FormatArgsStorage; use clippy_utils::ty::{contains_ty_adt_constructor_opaque, implements_trait, is_copy, is_type_diagnostic_item}; use clippy_utils::{contains_return, is_bool, is_trait_method, iter_input_pats, peel_blocks, return_ty}; pub use path_ends_with_ext::DEFAULT_ALLOWED_DOTFILES; @@ -4087,12 +4088,14 @@ declare_clippy_lint! { suspicious, "is_empty() called on strings known at compile time" } + pub struct Methods { avoid_breaking_exported_api: bool, msrv: Msrv, allow_expect_in_tests: bool, allow_unwrap_in_tests: bool, allowed_dotfiles: FxHashSet, + format_args: FormatArgsStorage, } impl Methods { @@ -4103,6 +4106,7 @@ impl Methods { allow_expect_in_tests: bool, allow_unwrap_in_tests: bool, mut allowed_dotfiles: FxHashSet, + format_args: FormatArgsStorage, ) -> Self { allowed_dotfiles.extend(DEFAULT_ALLOWED_DOTFILES.iter().map(ToString::to_string)); @@ -4112,6 +4116,7 @@ impl Methods { allow_expect_in_tests, allow_unwrap_in_tests, allowed_dotfiles, + format_args, } } } @@ -4281,7 +4286,15 @@ impl<'tcx> LateLintPass<'tcx> for Methods { ExprKind::MethodCall(method_call, receiver, args, _) => { let method_span = method_call.ident.span; or_fun_call::check(cx, expr, method_span, method_call.ident.as_str(), receiver, args); - expect_fun_call::check(cx, expr, method_span, method_call.ident.as_str(), receiver, args); + expect_fun_call::check( + cx, + &self.format_args, + expr, + method_span, + method_call.ident.as_str(), + receiver, + args, + ); clone_on_copy::check(cx, expr, method_call.ident.name, receiver, args); clone_on_ref_ptr::check(cx, expr, method_call.ident.name, receiver, args); inefficient_to_string::check(cx, expr, method_call.ident.name, receiver, args); diff --git a/clippy_lints/src/methods/unnecessary_iter_cloned.rs b/clippy_lints/src/methods/unnecessary_iter_cloned.rs index 520dcb2d52dc..7431dc1cf0b1 100644 --- a/clippy_lints/src/methods/unnecessary_iter_cloned.rs +++ b/clippy_lints/src/methods/unnecessary_iter_cloned.rs @@ -3,10 +3,12 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::higher::ForLoop; use clippy_utils::source::snippet_opt; use clippy_utils::ty::{get_iterator_item_ty, implements_trait}; -use clippy_utils::{fn_def_id, get_parent_expr}; +use clippy_utils::visitors::for_each_expr; +use clippy_utils::{can_mut_borrow_both, fn_def_id, get_parent_expr, path_to_local}; +use core::ops::ControlFlow; use rustc_errors::Applicability; use rustc_hir::def_id::DefId; -use rustc_hir::{Expr, ExprKind}; +use rustc_hir::{BindingMode, Expr, ExprKind, Node, PatKind}; use rustc_lint::LateContext; use rustc_span::{sym, Symbol}; @@ -40,6 +42,53 @@ pub fn check_for_loop_iter( && !clone_or_copy_needed && let Some(receiver_snippet) = snippet_opt(cx, receiver.span) { + // Issue 12098 + // https://github.com/rust-lang/rust-clippy/issues/12098 + // if the assignee have `mut borrow` conflict with the iteratee + // the lint should not execute, former didn't consider the mut case + + // check whether `expr` is mutable + fn is_mutable(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { + if let Some(hir_id) = path_to_local(expr) + && let Node::Pat(pat) = cx.tcx.hir_node(hir_id) + { + matches!(pat.kind, PatKind::Binding(BindingMode::MUT, ..)) + } else { + true + } + } + + fn is_caller_or_fields_change(cx: &LateContext<'_>, body: &Expr<'_>, caller: &Expr<'_>) -> bool { + let mut change = false; + if let ExprKind::Block(block, ..) = body.kind { + for_each_expr(block, |e| { + match e.kind { + ExprKind::Assign(assignee, _, _) | ExprKind::AssignOp(_, assignee, _) => { + change |= !can_mut_borrow_both(cx, caller, assignee); + }, + _ => {}, + } + // the return value has no effect but the function need one return value + ControlFlow::<()>::Continue(()) + }); + } + change + } + + if let ExprKind::Call(_, [child, ..]) = expr.kind { + // filter first layer of iterator + let mut child = child; + // get inner real caller requests for clone + while let ExprKind::MethodCall(_, caller, _, _) = child.kind { + child = caller; + } + if is_mutable(cx, child) && is_caller_or_fields_change(cx, body, child) { + // skip lint + return true; + } + }; + + // the lint should not be executed if no violation happens let snippet = if let ExprKind::MethodCall(maybe_iter_method_name, collection, [], _) = receiver.kind && maybe_iter_method_name.ident.name == sym::iter && let Some(iterator_trait_id) = cx.tcx.get_diagnostic_item(sym::Iterator) diff --git a/clippy_lints/src/methods/utils.rs b/clippy_lints/src/methods/utils.rs index c50f24f824ab..34d7b9acbe4b 100644 --- a/clippy_lints/src/methods/utils.rs +++ b/clippy_lints/src/methods/utils.rs @@ -120,6 +120,7 @@ fn pat_bindings(pat: &Pat<'_>) -> Vec { /// operations performed on `binding_hir_ids` are: /// * to take non-mutable references to them /// * to use them as non-mutable `&self` in method calls +/// /// If any of `binding_hir_ids` is used in any other way, then `clone_or_copy_needed` will be true /// when `CloneOrCopyVisitor` is done visiting. struct CloneOrCopyVisitor<'cx, 'tcx> { diff --git a/clippy_lints/src/needless_borrows_for_generic_args.rs b/clippy_lints/src/needless_borrows_for_generic_args.rs index ae6cf992ef7b..daf166bad90d 100644 --- a/clippy_lints/src/needless_borrows_for_generic_args.rs +++ b/clippy_lints/src/needless_borrows_for_generic_args.rs @@ -1,6 +1,6 @@ use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::mir::{enclosing_mir, expr_local, local_assignments, used_exactly_once, PossibleBorrowerMap}; +use clippy_utils::mir::PossibleBorrowerMap; use clippy_utils::source::snippet_with_context; use clippy_utils::ty::{implements_trait, is_copy}; use clippy_utils::{expr_use_ctxt, peel_n_hir_expr_refs, DefinedTy, ExprUseNode}; @@ -11,7 +11,6 @@ use rustc_hir::{Body, Expr, ExprKind, Mutability, Path, QPath}; use rustc_index::bit_set::BitSet; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::mir::{Rvalue, StatementKind}; use rustc_middle::ty::{ self, ClauseKind, EarlyBinder, FnSig, GenericArg, GenericArgKind, ParamTy, ProjectionPredicate, Ty, }; @@ -106,7 +105,6 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBorrowsForGenericArgs<'tcx> { } && let count = needless_borrow_count( cx, - &mut self.possible_borrowers, fn_id, cx.typeck_results().node_args(hir_id), i, @@ -155,11 +153,9 @@ fn path_has_args(p: &QPath<'_>) -> bool { /// The following constraints will be checked: /// * The borrowed expression meets all the generic type's constraints. /// * The generic type appears only once in the functions signature. -/// * The borrowed value will not be moved if it is used later in the function. -#[expect(clippy::too_many_arguments)] +/// * The borrowed value is Copy itself OR not a variable (created by a function call) fn needless_borrow_count<'tcx>( cx: &LateContext<'tcx>, - possible_borrowers: &mut Vec<(LocalDefId, PossibleBorrowerMap<'tcx, 'tcx>)>, fn_id: DefId, callee_args: ty::GenericArgsRef<'tcx>, arg_index: usize, @@ -234,9 +230,9 @@ fn needless_borrow_count<'tcx>( let referent_ty = cx.typeck_results().expr_ty(referent); - if !is_copy(cx, referent_ty) - && (referent_ty.has_significant_drop(cx.tcx, cx.param_env) - || !referent_used_exactly_once(cx, possible_borrowers, reference)) + if (!is_copy(cx, referent_ty) && !referent_ty.is_ref()) + && let ExprKind::AddrOf(_, _, inner) = reference.kind + && !matches!(inner.kind, ExprKind::Call(..) | ExprKind::MethodCall(..)) { return false; } @@ -339,37 +335,6 @@ fn is_mixed_projection_predicate<'tcx>( } } -fn referent_used_exactly_once<'tcx>( - cx: &LateContext<'tcx>, - possible_borrowers: &mut Vec<(LocalDefId, PossibleBorrowerMap<'tcx, 'tcx>)>, - reference: &Expr<'tcx>, -) -> bool { - if let Some(mir) = enclosing_mir(cx.tcx, reference.hir_id) - && let Some(local) = expr_local(cx.tcx, reference) - && let [location] = *local_assignments(mir, local).as_slice() - && let block_data = &mir.basic_blocks[location.block] - && let Some(statement) = block_data.statements.get(location.statement_index) - && let StatementKind::Assign(box (_, Rvalue::Ref(_, _, place))) = statement.kind - && !place.is_indirect_first_projection() - { - let body_owner_local_def_id = cx.tcx.hir().enclosing_body_owner(reference.hir_id); - if possible_borrowers - .last() - .map_or(true, |&(local_def_id, _)| local_def_id != body_owner_local_def_id) - { - possible_borrowers.push((body_owner_local_def_id, PossibleBorrowerMap::new(cx, mir))); - } - let possible_borrower = &mut possible_borrowers.last_mut().unwrap().1; - // If `only_borrowers` were used here, the `copyable_iterator::warn` test would fail. The reason is - // that `PossibleBorrowerVisitor::visit_terminator` considers `place.local` a possible borrower of - // itself. See the comment in that method for an explanation as to why. - possible_borrower.bounded_borrowers(&[local], &[local, place.local], place.local, location) - && used_exactly_once(mir, place.local).unwrap_or(false) - } else { - false - } -} - // Iteratively replaces `param_ty` with `new_ty` in `args`, and similarly for each resulting // projected type that is a type parameter. Returns `false` if replacing the types would have an // effect on the function signature beyond substituting `new_ty` for `param_ty`. @@ -408,7 +373,11 @@ fn replace_types<'tcx>( && let Some(term_ty) = projection_predicate.term.ty() && let ty::Param(term_param_ty) = term_ty.kind() { - let projection = projection_predicate.projection_term.with_self_ty(cx.tcx, new_ty).expect_ty(cx.tcx).to_ty(cx.tcx); + let projection = projection_predicate + .projection_term + .with_self_ty(cx.tcx, new_ty) + .expect_ty(cx.tcx) + .to_ty(cx.tcx); if let Ok(projected_ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, projection) && args[term_param_ty.index as usize] != GenericArg::from(projected_ty) diff --git a/clippy_lints/src/needless_continue.rs b/clippy_lints/src/needless_continue.rs index 8b4a12bb7664..b97cb4579ca7 100644 --- a/clippy_lints/src/needless_continue.rs +++ b/clippy_lints/src/needless_continue.rs @@ -178,8 +178,7 @@ impl EarlyLintPass for NeedlessContinue { /// Given an expression, returns true if either of the following is true /// /// - The expression is a `continue` node. -/// - The expression node is a block with the first statement being a -/// `continue`. +/// - The expression node is a block with the first statement being a `continue`. fn needless_continue_in_else(else_expr: &ast::Expr, label: Option<&ast::Label>) -> bool { match else_expr.kind { ast::ExprKind::Block(ref else_block, _) => is_first_block_stmt_continue(else_block, label), diff --git a/clippy_lints/src/needless_late_init.rs b/clippy_lints/src/needless_late_init.rs index 6605d1fa51a3..5a0ae1a4d6d2 100644 --- a/clippy_lints/src/needless_late_init.rs +++ b/clippy_lints/src/needless_late_init.rs @@ -273,24 +273,16 @@ fn check<'tcx>( msg_span, "unneeded late initialization", |diag| { - diag.tool_only_span_suggestion( - local_stmt.span, - "remove the local", - "", - Applicability::MachineApplicable, - ); - - diag.span_suggestion( - assign.lhs_span, - format!("declare `{binding_name}` here"), - let_snippet, + diag.multipart_suggestion( + format!("move the declaration `{binding_name}` here"), + vec![(local_stmt.span, String::new()), (assign.lhs_span, let_snippet)], Applicability::MachineApplicable, ); }, ); }, ExprKind::If(cond, then_expr, Some(else_expr)) if !contains_let(cond) => { - let (applicability, suggestions) = assignment_suggestions(cx, binding_id, [then_expr, else_expr])?; + let (applicability, mut suggestions) = assignment_suggestions(cx, binding_id, [then_expr, else_expr])?; span_lint_and_then( cx, @@ -298,30 +290,26 @@ fn check<'tcx>( local_stmt.span, "unneeded late initialization", |diag| { - diag.tool_only_span_suggestion(local_stmt.span, "remove the local", String::new(), applicability); - - diag.span_suggestion_verbose( - usage.stmt.span.shrink_to_lo(), - format!("declare `{binding_name}` here"), - format!("{let_snippet} = "), - applicability, - ); - - diag.multipart_suggestion("remove the assignments from the branches", suggestions, applicability); + suggestions.push((local_stmt.span, String::new())); + suggestions.push((usage.stmt.span.shrink_to_lo(), format!("{let_snippet} = "))); if usage.needs_semi { - diag.span_suggestion( - usage.stmt.span.shrink_to_hi(), - "add a semicolon after the `if` expression", - ";", - applicability, - ); + suggestions.push((usage.stmt.span.shrink_to_hi(), ";".to_owned())); } + + diag.multipart_suggestion( + format!( + "move the declaration `{binding_name}` here and remove the assignments from the branches" + ), + suggestions, + applicability, + ); }, ); }, ExprKind::Match(_, arms, MatchSource::Normal) => { - let (applicability, suggestions) = assignment_suggestions(cx, binding_id, arms.iter().map(|arm| arm.body))?; + let (applicability, mut suggestions) = + assignment_suggestions(cx, binding_id, arms.iter().map(|arm| arm.body))?; span_lint_and_then( cx, @@ -329,29 +317,18 @@ fn check<'tcx>( local_stmt.span, "unneeded late initialization", |diag| { - diag.tool_only_span_suggestion(local_stmt.span, "remove the local", String::new(), applicability); + suggestions.push((local_stmt.span, String::new())); + suggestions.push((usage.stmt.span.shrink_to_lo(), format!("{let_snippet} = "))); - diag.span_suggestion_verbose( - usage.stmt.span.shrink_to_lo(), - format!("declare `{binding_name}` here"), - format!("{let_snippet} = "), - applicability, - ); + if usage.needs_semi { + suggestions.push((usage.stmt.span.shrink_to_hi(), ";".to_owned())); + } diag.multipart_suggestion( - "remove the assignments from the `match` arms", + format!("move the declaration `{binding_name}` here and remove the assignments from the `match` arms"), suggestions, applicability, ); - - if usage.needs_semi { - diag.span_suggestion( - usage.stmt.span.shrink_to_hi(), - "add a semicolon after the `match` expression", - ";", - applicability, - ); - } }, ); }, diff --git a/clippy_lints/src/needless_pass_by_ref_mut.rs b/clippy_lints/src/needless_pass_by_ref_mut.rs index 9b852f52ea1e..da6ed5fb96f1 100644 --- a/clippy_lints/src/needless_pass_by_ref_mut.rs +++ b/clippy_lints/src/needless_pass_by_ref_mut.rs @@ -117,7 +117,9 @@ fn check_closures<'tcx>( .associated_body() .map(|(_, body_id)| hir.body(body_id)) { - euv::ExprUseVisitor::for_clippy(cx, closure, &mut *ctx).consume_body(body).into_ok(); + euv::ExprUseVisitor::for_clippy(cx, closure, &mut *ctx) + .consume_body(body) + .into_ok(); } } } @@ -194,7 +196,9 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> { async_closures: FxHashSet::default(), tcx: cx.tcx, }; - euv::ExprUseVisitor::for_clippy(cx, fn_def_id, &mut ctx).consume_body(body).into_ok(); + euv::ExprUseVisitor::for_clippy(cx, fn_def_id, &mut ctx) + .consume_body(body) + .into_ok(); let mut checked_closures = FxHashSet::default(); diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 0986571d0f28..f2e00cef7e9f 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -133,7 +133,9 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { // function body. let MovedVariablesCtxt { moved_vars } = { let mut ctx = MovedVariablesCtxt::default(); - euv::ExprUseVisitor::for_clippy(cx, fn_def_id, &mut ctx).consume_body(body).into_ok(); + euv::ExprUseVisitor::for_clippy(cx, fn_def_id, &mut ctx) + .consume_body(body) + .into_ok(); ctx }; diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index f915145e794b..87f886b1128d 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -94,7 +94,6 @@ impl<'tcx> LateLintPass<'tcx> for NoEffect { fn check_block_post(&mut self, cx: &LateContext<'tcx>, _: &'tcx rustc_hir::Block<'tcx>) { for hir_id in self.local_bindings.pop().unwrap() { - // FIXME(rust/#120456) - is `swap_remove` correct? if let Some(span) = self.underscore_bindings.swap_remove(&hir_id) { span_lint_hir( cx, @@ -109,7 +108,6 @@ impl<'tcx> LateLintPass<'tcx> for NoEffect { fn check_expr(&mut self, _: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { if let Some(def_id) = path_to_local(expr) { - // FIXME(rust/#120456) - is `swap_remove` correct? self.underscore_bindings.swap_remove(&def_id); } } @@ -118,7 +116,11 @@ impl<'tcx> LateLintPass<'tcx> for NoEffect { impl NoEffect { fn check_no_effect(&mut self, cx: &LateContext<'_>, stmt: &Stmt<'_>) -> bool { if let StmtKind::Semi(expr) = stmt.kind { - // move `expr.span.from_expansion()` ahead + // Covered by rustc `path_statements` lint + if matches!(expr.kind, ExprKind::Path(_)) { + return true; + } + if expr.span.from_expansion() { return false; } diff --git a/clippy_lints/src/panic_unimplemented.rs b/clippy_lints/src/panic_unimplemented.rs index ef51a9a9a1c8..75066c1f0d2e 100644 --- a/clippy_lints/src/panic_unimplemented.rs +++ b/clippy_lints/src/panic_unimplemented.rs @@ -1,8 +1,14 @@ use clippy_utils::diagnostics::span_lint; +use clippy_utils::is_in_test; use clippy_utils::macros::{is_panic, root_macro_call_first_node}; use rustc_hir::Expr; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::declare_lint_pass; +use rustc_session::impl_lint_pass; + +#[derive(Clone)] +pub struct PanicUnimplemented { + pub allow_panic_in_tests: bool, +} declare_clippy_lint! { /// ### What it does @@ -77,7 +83,7 @@ declare_clippy_lint! { "usage of the `unreachable!` macro" } -declare_lint_pass!(PanicUnimplemented => [UNIMPLEMENTED, UNREACHABLE, TODO, PANIC]); +impl_lint_pass!(PanicUnimplemented => [UNIMPLEMENTED, UNREACHABLE, TODO, PANIC]); impl<'tcx> LateLintPass<'tcx> for PanicUnimplemented { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { @@ -85,7 +91,9 @@ impl<'tcx> LateLintPass<'tcx> for PanicUnimplemented { return; }; if is_panic(cx, macro_call.def_id) { - if cx.tcx.hir().is_inside_const_context(expr.hir_id) { + if cx.tcx.hir().is_inside_const_context(expr.hir_id) + || self.allow_panic_in_tests && is_in_test(cx.tcx, expr.hir_id) + { return; } diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index 87a3c3874d77..292124196ff6 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -389,6 +389,10 @@ declare_lint_pass!(StrToString => [STR_TO_STRING]); impl<'tcx> LateLintPass<'tcx> for StrToString { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) { + if expr.span.from_expansion() { + return; + } + if let ExprKind::MethodCall(path, self_arg, ..) = &expr.kind && path.ident.name == sym::to_string && let ty = cx.typeck_results().expr_ty(self_arg) @@ -437,6 +441,10 @@ declare_lint_pass!(StringToString => [STRING_TO_STRING]); impl<'tcx> LateLintPass<'tcx> for StringToString { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) { + if expr.span.from_expansion() { + return; + } + if let ExprKind::MethodCall(path, self_arg, ..) = &expr.kind && path.ident.name == sym::to_string && let ty = cx.typeck_results().expr_ty(self_arg) diff --git a/clippy_lints/src/transmute/transmute_int_to_non_zero.rs b/clippy_lints/src/transmute/transmute_int_to_non_zero.rs index 7d824ef21390..3729dfd3e86f 100644 --- a/clippy_lints/src/transmute/transmute_int_to_non_zero.rs +++ b/clippy_lints/src/transmute/transmute_int_to_non_zero.rs @@ -28,7 +28,7 @@ pub(super) fn check<'tcx>( let int_ty = substs.type_at(0); if from_ty != int_ty { - return false; + return false; } span_lint_and_then( diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index 5b2841dcd833..c0d9bcdd259c 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -251,11 +251,7 @@ impl<'a, 'tcx> UnwrappableVariablesVisitor<'a, 'tcx> { local_id: unwrap_info.local_id, }; - let vis = ExprUseVisitor::for_clippy( - self.cx, - cond.hir_id.owner.def_id, - &mut delegate, - ); + let vis = ExprUseVisitor::for_clippy(self.cx, cond.hir_id.owner.def_id, &mut delegate); vis.walk_expr(cond).into_ok(); vis.walk_expr(branch).into_ok(); diff --git a/clippy_lints/src/utils/format_args_collector.rs b/clippy_lints/src/utils/format_args_collector.rs index 58e66c9f9b95..5acfd35fd6ae 100644 --- a/clippy_lints/src/utils/format_args_collector.rs +++ b/clippy_lints/src/utils/format_args_collector.rs @@ -1,4 +1,4 @@ -use clippy_utils::macros::AST_FORMAT_ARGS; +use clippy_utils::macros::FormatArgsStorage; use clippy_utils::source::snippet_opt; use itertools::Itertools; use rustc_ast::{Crate, Expr, ExprKind, FormatArgs}; @@ -9,13 +9,20 @@ use rustc_session::impl_lint_pass; use rustc_span::{hygiene, Span}; use std::iter::once; use std::mem; -use std::rc::Rc; -/// Collects [`rustc_ast::FormatArgs`] so that future late passes can call -/// [`clippy_utils::macros::find_format_args`] -#[derive(Default)] +/// Populates [`FormatArgsStorage`] with AST [`FormatArgs`] nodes pub struct FormatArgsCollector { - format_args: FxHashMap>, + format_args: FxHashMap, + storage: FormatArgsStorage, +} + +impl FormatArgsCollector { + pub fn new(storage: FormatArgsStorage) -> Self { + Self { + format_args: FxHashMap::default(), + storage, + } + } } impl_lint_pass!(FormatArgsCollector => []); @@ -27,16 +34,12 @@ impl EarlyLintPass for FormatArgsCollector { return; } - self.format_args - .insert(expr.span.with_parent(None), Rc::new((**args).clone())); + self.format_args.insert(expr.span.with_parent(None), (**args).clone()); } } fn check_crate_post(&mut self, _: &EarlyContext<'_>, _: &Crate) { - AST_FORMAT_ARGS.with(|ast_format_args| { - let result = ast_format_args.set(mem::take(&mut self.format_args)); - debug_assert!(result.is_ok()); - }); + self.storage.set(mem::take(&mut self.format_args)); } } diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 26c6859233d5..ff6ee0d10ad5 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; -use clippy_utils::macros::{find_format_args, format_arg_removal_span, root_macro_call_first_node, MacroCall}; +use clippy_utils::macros::{format_arg_removal_span, root_macro_call_first_node, FormatArgsStorage, MacroCall}; use clippy_utils::source::{expand_past_previous_comma, snippet_opt}; use clippy_utils::{is_in_cfg_test, is_in_test_function}; use rustc_ast::token::LitKind; @@ -236,13 +236,15 @@ declare_clippy_lint! { #[derive(Default)] pub struct Write { + format_args: FormatArgsStorage, in_debug_impl: bool, allow_print_in_tests: bool, } impl Write { - pub fn new(allow_print_in_tests: bool) -> Self { + pub fn new(format_args: FormatArgsStorage, allow_print_in_tests: bool) -> Self { Self { + format_args, allow_print_in_tests, ..Default::default() } @@ -307,7 +309,7 @@ impl<'tcx> LateLintPass<'tcx> for Write { _ => return, } - if let Some(format_args) = find_format_args(cx, expr, macro_call.expn) { + if let Some(format_args) = self.format_args.get(cx, expr, macro_call.expn) { // ignore `writeln!(w)` and `write!(v, some_macro!())` if format_args.span.from_expansion() { return; @@ -315,15 +317,15 @@ impl<'tcx> LateLintPass<'tcx> for Write { match diag_name { sym::print_macro | sym::eprint_macro | sym::write_macro => { - check_newline(cx, &format_args, ¯o_call, name); + check_newline(cx, format_args, ¯o_call, name); }, sym::println_macro | sym::eprintln_macro | sym::writeln_macro => { - check_empty_string(cx, &format_args, ¯o_call, name); + check_empty_string(cx, format_args, ¯o_call, name); }, _ => {}, } - check_literal(cx, &format_args, name); + check_literal(cx, format_args, name); if !self.in_debug_impl { for piece in &format_args.template { diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 99d7aba2f7a1..4c603bda770a 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -193,6 +193,21 @@ pub fn find_binding_init<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option< None } +/// Checks if the given local has an initializer or is from something other than a `let` statement +/// +/// e.g. returns true for `x` in `fn f(x: usize) { .. }` and `let x = 1;` but false for `let x;` +pub fn local_is_initialized(cx: &LateContext<'_>, local: HirId) -> bool { + for (_, node) in cx.tcx.hir().parent_iter(local) { + match node { + Node::Pat(..) | Node::PatField(..) => {}, + Node::LetStmt(let_stmt) => return let_stmt.init.is_some(), + _ => return true, + } + } + + false +} + /// Returns `true` if the given `NodeId` is inside a constant context /// /// # Example @@ -1499,15 +1514,18 @@ pub fn is_else_clause_in_let_else(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool { } /// Checks whether the given `Expr` is a range equivalent to a `RangeFull`. +/// /// For the lower bound, this means that: /// - either there is none /// - or it is the smallest value that can be represented by the range's integer type +/// /// For the upper bound, this means that: /// - either there is none /// - or it is the largest value that can be represented by the range's integer type and is /// inclusive /// - or it is a call to some container's `len` method and is exclusive, and the range is passed to /// a method call on that same container (e.g. `v.drain(..v.len())`) +/// /// If the given `Expr` is not some kind of range, the function returns `false`. pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Option<&Path<'_>>) -> bool { let ty = cx.typeck_results().expr_ty(expr); diff --git a/clippy_utils/src/macros.rs b/clippy_utils/src/macros.rs index 257dd76ab15c..8daab9b0d92c 100644 --- a/clippy_utils/src/macros.rs +++ b/clippy_utils/src/macros.rs @@ -5,15 +5,13 @@ use crate::visitors::{for_each_expr, Descend}; use arrayvec::ArrayVec; use rustc_ast::{FormatArgs, FormatArgument, FormatPlaceholder}; use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::sync::{Lrc, OnceLock}; use rustc_hir::{self as hir, Expr, ExprKind, HirId, Node, QPath}; use rustc_lint::LateContext; use rustc_span::def_id::DefId; use rustc_span::hygiene::{self, MacroKind, SyntaxContext}; use rustc_span::{sym, BytePos, ExpnData, ExpnId, ExpnKind, Span, SpanData, Symbol}; -use std::cell::OnceCell; use std::ops::ControlFlow; -use std::rc::Rc; -use std::sync::atomic::{AtomicBool, Ordering}; const FORMAT_MACRO_DIAG_ITEMS: &[Symbol] = &[ sym::assert_eq_macro, @@ -388,50 +386,44 @@ fn is_assert_arg(cx: &LateContext<'_>, expr: &Expr<'_>, assert_expn: ExpnId) -> } } -thread_local! { - /// We preserve the [`FormatArgs`] structs from the early pass for use in the late pass to be - /// able to access the many features of a [`LateContext`]. +/// Stores AST [`FormatArgs`] nodes for use in late lint passes, as they are in a desugared form in +/// the HIR +#[derive(Default, Clone)] +pub struct FormatArgsStorage(Lrc>>); + +impl FormatArgsStorage { + /// Returns an AST [`FormatArgs`] node if a `format_args` expansion is found as a descendant of + /// `expn_id` /// - /// A thread local is used because [`FormatArgs`] is `!Send` and `!Sync`, we are making an - /// assumption that the early pass that populates the map and the later late passes will all be - /// running on the same thread. - #[doc(hidden)] - pub static AST_FORMAT_ARGS: OnceCell>> = { - static CALLED: AtomicBool = AtomicBool::new(false); - debug_assert!( - !CALLED.swap(true, Ordering::SeqCst), - "incorrect assumption: `AST_FORMAT_ARGS` should only be accessed by a single thread", - ); - - OnceCell::new() - }; -} - -/// Returns an AST [`FormatArgs`] node if a `format_args` expansion is found as a descendant of -/// `expn_id` -pub fn find_format_args(cx: &LateContext<'_>, start: &Expr<'_>, expn_id: ExpnId) -> Option> { - let format_args_expr = for_each_expr(start, |expr| { - let ctxt = expr.span.ctxt(); - if ctxt.outer_expn().is_descendant_of(expn_id) { - if macro_backtrace(expr.span) - .map(|macro_call| cx.tcx.item_name(macro_call.def_id)) - .any(|name| matches!(name, sym::const_format_args | sym::format_args | sym::format_args_nl)) - { - ControlFlow::Break(expr) + /// See also [`find_format_arg_expr`] + pub fn get(&self, cx: &LateContext<'_>, start: &Expr<'_>, expn_id: ExpnId) -> Option<&FormatArgs> { + let format_args_expr = for_each_expr(start, |expr| { + let ctxt = expr.span.ctxt(); + if ctxt.outer_expn().is_descendant_of(expn_id) { + if macro_backtrace(expr.span) + .map(|macro_call| cx.tcx.item_name(macro_call.def_id)) + .any(|name| matches!(name, sym::const_format_args | sym::format_args | sym::format_args_nl)) + { + ControlFlow::Break(expr) + } else { + ControlFlow::Continue(Descend::Yes) + } } else { - ControlFlow::Continue(Descend::Yes) + ControlFlow::Continue(Descend::No) } - } else { - ControlFlow::Continue(Descend::No) - } - })?; + })?; - AST_FORMAT_ARGS.with(|ast_format_args| { - ast_format_args - .get()? - .get(&format_args_expr.span.with_parent(None)) - .cloned() - }) + debug_assert!(self.0.get().is_some(), "`FormatArgsStorage` not yet populated"); + + self.0.get()?.get(&format_args_expr.span.with_parent(None)) + } + + /// Should only be called by `FormatArgsCollector` + pub fn set(&self, format_args: FxHashMap) { + self.0 + .set(format_args) + .expect("`FormatArgsStorage::set` should only be called once"); + } } /// Attempt to find the [`rustc_hir::Expr`] that corresponds to the [`FormatArgument`]'s value, if diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs index ff9f06531ea1..8ee7d87acb3e 100644 --- a/clippy_utils/src/qualify_min_const_fn.rs +++ b/clippy_utils/src/qualify_min_const_fn.rs @@ -3,7 +3,7 @@ // of terminologies might not be relevant in the context of Clippy. Note that its behavior might // differ from the time of `rustc` even if the name stays the same. -use clippy_config::msrvs::Msrv; +use clippy_config::msrvs::{self, Msrv}; use hir::LangItem; use rustc_attr::StableSince; use rustc_const_eval::transform::check_consts::ConstCx; @@ -42,7 +42,7 @@ pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: &Msrv) for bb in &*body.basic_blocks { check_terminator(tcx, body, bb.terminator(), msrv)?; for stmt in &bb.statements { - check_statement(tcx, body, def_id, stmt)?; + check_statement(tcx, body, def_id, stmt, msrv)?; } } Ok(()) @@ -102,13 +102,14 @@ fn check_rvalue<'tcx>( def_id: DefId, rvalue: &Rvalue<'tcx>, span: Span, + msrv: &Msrv, ) -> McfResult { match rvalue { Rvalue::ThreadLocalRef(_) => Err((span, "cannot access thread local storage in const fn".into())), Rvalue::Len(place) | Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => { - check_place(tcx, *place, span, body) + check_place(tcx, *place, span, body, msrv) }, - Rvalue::CopyForDeref(place) => check_place(tcx, *place, span, body), + Rvalue::CopyForDeref(place) => check_place(tcx, *place, span, body, msrv), Rvalue::Repeat(operand, _) | Rvalue::Use(operand) | Rvalue::Cast( @@ -122,7 +123,7 @@ fn check_rvalue<'tcx>( | CastKind::PointerCoercion(PointerCoercion::MutToConstPointer | PointerCoercion::ArrayToPointer), operand, _, - ) => check_operand(tcx, operand, span, body), + ) => check_operand(tcx, operand, span, body, msrv), Rvalue::Cast( CastKind::PointerCoercion( PointerCoercion::UnsafeFnPointer @@ -133,15 +134,13 @@ fn check_rvalue<'tcx>( _, ) => Err((span, "function pointer casts are not allowed in const fn".into())), Rvalue::Cast(CastKind::PointerCoercion(PointerCoercion::Unsize), op, cast_ty) => { - let pointee_ty = if let Some(deref_ty) = cast_ty.builtin_deref(true) { - deref_ty - } else { + let Some(pointee_ty) = cast_ty.builtin_deref(true) else { // We cannot allow this for now. return Err((span, "unsizing casts are only allowed for references right now".into())); }; let unsized_ty = tcx.struct_tail_erasing_lifetimes(pointee_ty, tcx.param_env(def_id)); if let ty::Slice(_) | ty::Str = unsized_ty.kind() { - check_operand(tcx, op, span, body)?; + check_operand(tcx, op, span, body, msrv)?; // Casting/coercing things to slices is fine. Ok(()) } else { @@ -162,8 +161,8 @@ fn check_rvalue<'tcx>( )), // binops are fine on integers Rvalue::BinaryOp(_, box (lhs, rhs)) => { - check_operand(tcx, lhs, span, body)?; - check_operand(tcx, rhs, span, body)?; + check_operand(tcx, lhs, span, body, msrv)?; + check_operand(tcx, rhs, span, body, msrv)?; let ty = lhs.ty(body, tcx); if ty.is_integral() || ty.is_bool() || ty.is_char() { Ok(()) @@ -179,14 +178,14 @@ fn check_rvalue<'tcx>( Rvalue::UnaryOp(_, operand) => { let ty = operand.ty(body, tcx); if ty.is_integral() || ty.is_bool() { - check_operand(tcx, operand, span, body) + check_operand(tcx, operand, span, body, msrv) } else { Err((span, "only int and `bool` operations are stable in const fn".into())) } }, Rvalue::Aggregate(_, operands) => { for operand in operands { - check_operand(tcx, operand, span, body)?; + check_operand(tcx, operand, span, body, msrv)?; } Ok(()) }, @@ -198,28 +197,29 @@ fn check_statement<'tcx>( body: &Body<'tcx>, def_id: DefId, statement: &Statement<'tcx>, + msrv: &Msrv, ) -> McfResult { let span = statement.source_info.span; match &statement.kind { StatementKind::Assign(box (place, rval)) => { - check_place(tcx, *place, span, body)?; - check_rvalue(tcx, body, def_id, rval, span) + check_place(tcx, *place, span, body, msrv)?; + check_rvalue(tcx, body, def_id, rval, span, msrv) }, - StatementKind::FakeRead(box (_, place)) => check_place(tcx, *place, span, body), + StatementKind::FakeRead(box (_, place)) => check_place(tcx, *place, span, body, msrv), // just an assignment StatementKind::SetDiscriminant { place, .. } | StatementKind::Deinit(place) => { - check_place(tcx, **place, span, body) + check_place(tcx, **place, span, body, msrv) }, - StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(op)) => check_operand(tcx, op, span, body), + StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(op)) => check_operand(tcx, op, span, body, msrv), StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping( rustc_middle::mir::CopyNonOverlapping { dst, src, count }, )) => { - check_operand(tcx, dst, span, body)?; - check_operand(tcx, src, span, body)?; - check_operand(tcx, count, span, body) + check_operand(tcx, dst, span, body, msrv)?; + check_operand(tcx, src, span, body, msrv)?; + check_operand(tcx, count, span, body, msrv) }, // These are all NOPs StatementKind::StorageLive(_) @@ -233,7 +233,13 @@ fn check_statement<'tcx>( } } -fn check_operand<'tcx>(tcx: TyCtxt<'tcx>, operand: &Operand<'tcx>, span: Span, body: &Body<'tcx>) -> McfResult { +fn check_operand<'tcx>( + tcx: TyCtxt<'tcx>, + operand: &Operand<'tcx>, + span: Span, + body: &Body<'tcx>, + msrv: &Msrv, +) -> McfResult { match operand { Operand::Move(place) => { if !place.projection.as_ref().is_empty() @@ -245,9 +251,9 @@ fn check_operand<'tcx>(tcx: TyCtxt<'tcx>, operand: &Operand<'tcx>, span: Span, b )); } - check_place(tcx, *place, span, body) + check_place(tcx, *place, span, body, msrv) }, - Operand::Copy(place) => check_place(tcx, *place, span, body), + Operand::Copy(place) => check_place(tcx, *place, span, body, msrv), Operand::Constant(c) => match c.check_static_ptr(tcx) { Some(_) => Err((span, "cannot access `static` items in const fn".into())), None => Ok(()), @@ -255,23 +261,27 @@ fn check_operand<'tcx>(tcx: TyCtxt<'tcx>, operand: &Operand<'tcx>, span: Span, b } } -fn check_place<'tcx>(tcx: TyCtxt<'tcx>, place: Place<'tcx>, span: Span, body: &Body<'tcx>) -> McfResult { +fn check_place<'tcx>(tcx: TyCtxt<'tcx>, place: Place<'tcx>, span: Span, body: &Body<'tcx>, msrv: &Msrv) -> McfResult { for (base, elem) in place.as_ref().iter_projections() { match elem { ProjectionElem::Field(..) => { - let base_ty = base.ty(body, tcx).ty; - if let Some(def) = base_ty.ty_adt_def() { - // No union field accesses in `const fn` - if def.is_union() { - return Err((span, "accessing union fields is unstable".into())); - } + if base.ty(body, tcx).ty.is_union() && !msrv.meets(msrvs::CONST_FN_UNION) { + return Err((span, "accessing union fields is unstable".into())); } }, + ProjectionElem::Deref => match base.ty(body, tcx).ty.kind() { + ty::RawPtr(_, hir::Mutability::Mut) => { + return Err((span, "dereferencing raw mut pointer in const fn is unstable".into())); + }, + ty::RawPtr(_, hir::Mutability::Not) if !msrv.meets(msrvs::CONST_RAW_PTR_DEREF) => { + return Err((span, "dereferencing raw const pointer in const fn is unstable".into())); + }, + _ => (), + }, ProjectionElem::ConstantIndex { .. } | ProjectionElem::OpaqueCast(..) | ProjectionElem::Downcast(..) | ProjectionElem::Subslice { .. } - | ProjectionElem::Deref | ProjectionElem::Subtype(_) | ProjectionElem::Index(_) => {}, } @@ -304,7 +314,7 @@ fn check_terminator<'tcx>( } Ok(()) }, - TerminatorKind::SwitchInt { discr, targets: _ } => check_operand(tcx, discr, span, body), + TerminatorKind::SwitchInt { discr, targets: _ } => check_operand(tcx, discr, span, body, msrv), TerminatorKind::CoroutineDrop | TerminatorKind::Yield { .. } => { Err((span, "const fn coroutines are unstable".into())) }, @@ -341,10 +351,10 @@ fn check_terminator<'tcx>( )); } - check_operand(tcx, func, span, body)?; + check_operand(tcx, func, span, body, msrv)?; for arg in args { - check_operand(tcx, &arg.node, span, body)?; + check_operand(tcx, &arg.node, span, body, msrv)?; } Ok(()) } else { @@ -357,7 +367,7 @@ fn check_terminator<'tcx>( msg: _, target: _, unwind: _, - } => check_operand(tcx, cond, span, body), + } => check_operand(tcx, cond, span, body, msrv), TerminatorKind::InlineAsm { .. } => Err((span, "cannot use inline assembly in const fn".into())), } } diff --git a/clippy_utils/src/source.rs b/clippy_utils/src/source.rs index e72467edeeb0..fd67e039c29a 100644 --- a/clippy_utils/src/source.rs +++ b/clippy_utils/src/source.rs @@ -250,7 +250,7 @@ pub fn snippet<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow< /// - Applicability level `Unspecified` will never be changed. /// - If the span is inside a macro, change the applicability level to `MaybeIncorrect`. /// - If the default value is used and the applicability level is `MachineApplicable`, change it to -/// `HasPlaceholders` +/// `HasPlaceholders` pub fn snippet_with_applicability<'a, T: LintContext>( cx: &T, span: Span, diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs index bf03c6c16015..6319c7bfa6b8 100644 --- a/clippy_utils/src/sugg.rs +++ b/clippy_utils/src/sugg.rs @@ -67,8 +67,7 @@ impl<'a> Sugg<'a> { /// - Applicability level `Unspecified` will never be changed. /// - If the span is inside a macro, change the applicability level to `MaybeIncorrect`. /// - If the default value is used and the applicability level is `MachineApplicable`, change it - /// to - /// `HasPlaceholders` + /// to `HasPlaceholders` pub fn hir_with_applicability( cx: &LateContext<'_>, expr: &hir::Expr<'_>, diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs index c29e3feac9ad..2dacc34867f0 100644 --- a/clippy_utils/src/ty.rs +++ b/clippy_utils/src/ty.rs @@ -273,11 +273,7 @@ pub fn implements_trait_with_env_from_iter<'tcx>( let infcx = tcx.infer_ctxt().build(); let args = args .into_iter() - .map(|arg| { - arg.into().unwrap_or_else(|| { - infcx.next_ty_var(DUMMY_SP).into() - }) - }) + .map(|arg| arg.into().unwrap_or_else(|| infcx.next_ty_var(DUMMY_SP).into())) .collect::>(); // If an effect arg was not specified, we need to specify it. @@ -795,7 +791,8 @@ fn sig_from_bounds<'tcx>( inputs = Some(i); }, ty::ClauseKind::Projection(p) - if Some(p.projection_term.def_id) == lang_items.fn_once_output() && p.projection_term.self_ty() == ty => + if Some(p.projection_term.def_id) == lang_items.fn_once_output() + && p.projection_term.self_ty() == ty => { if output.is_some() { // Multiple different fn trait impls. Is this even allowed? @@ -956,11 +953,7 @@ pub struct AdtVariantInfo { impl AdtVariantInfo { /// Returns ADT variants ordered by size - pub fn new<'tcx>( - cx: &LateContext<'tcx>, - adt: AdtDef<'tcx>, - subst: GenericArgsRef<'tcx> - ) -> Vec { + pub fn new<'tcx>(cx: &LateContext<'tcx>, adt: AdtDef<'tcx>, subst: GenericArgsRef<'tcx>) -> Vec { let mut variants_size = adt .variants() .iter() diff --git a/clippy_utils/src/usage.rs b/clippy_utils/src/usage.rs index 9abb4ef9b8d3..2a25d51d8e50 100644 --- a/clippy_utils/src/usage.rs +++ b/clippy_utils/src/usage.rs @@ -16,13 +16,9 @@ pub fn mutated_variables<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) -> used_mutably: HirIdSet::default(), skip: false, }; - ExprUseVisitor::for_clippy( - cx, - expr.hir_id.owner.def_id, - &mut delegate, - ) - .walk_expr(expr) - .into_ok(); + ExprUseVisitor::for_clippy(cx, expr.hir_id.owner.def_id, &mut delegate) + .walk_expr(expr) + .into_ok(); if delegate.skip { return None; diff --git a/lintcheck/Cargo.toml b/lintcheck/Cargo.toml index a828d1237046..8c5a409e25b1 100644 --- a/lintcheck/Cargo.toml +++ b/lintcheck/Cargo.toml @@ -13,7 +13,7 @@ default-run = "lintcheck" [dependencies] anyhow = "1.0.69" cargo_metadata = "0.15.3" -clap = { version = "4.1.8", features = ["derive", "env"] } +clap = { version = "4.4", features = ["derive", "env"] } crates_io_api = "0.8.1" crossbeam-channel = "0.5.6" flate2 = "1.0" diff --git a/rust-toolchain b/rust-toolchain index 055f305eb8e1..a0585ffdb45b 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2024-05-02" +channel = "nightly-2024-05-16" components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] diff --git a/tests/ui-cargo/lint_groups_priority/fail/Cargo.stderr b/tests/ui-cargo/lint_groups_priority/fail/Cargo.stderr index 103e60d84844..9177e99f8e6e 100644 --- a/tests/ui-cargo/lint_groups_priority/fail/Cargo.stderr +++ b/tests/ui-cargo/lint_groups_priority/fail/Cargo.stderr @@ -42,4 +42,32 @@ help: to have lints override the group set `pedantic` to a lower priority 19 | pedantic = { level = "warn", priority = -2 } | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -error: could not compile `fail` (lib) due to 3 previous errors +error: lint group `rust_2018_idioms` has the same priority (0) as a lint + --> Cargo.toml:23:1 + | +23 | rust_2018_idioms = "warn" + | ^^^^^^^^^^^^^^^^ ------ has an implicit priority of 0 +24 | bare_trait_objects = "allow" + | ------------------ has the same priority as this lint + | + = note: the order of the lints in the table is ignored by Cargo +help: to have lints override the group set `rust_2018_idioms` to a lower priority + | +23 | rust_2018_idioms = { level = "warn", priority = -1 } + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: lint group `pedantic` has the same priority (0) as a lint + --> Cargo.toml:27:1 + | +27 | pedantic = "warn" + | ^^^^^^^^ ------ has an implicit priority of 0 +28 | similar_names = "allow" + | ------------- has the same priority as this lint + | + = note: the order of the lints in the table is ignored by Cargo +help: to have lints override the group set `pedantic` to a lower priority + | +27 | pedantic = { level = "warn", priority = -1 } + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: could not compile `fail` (lib) due to 5 previous errors diff --git a/tests/ui-cargo/lint_groups_priority/fail/Cargo.toml b/tests/ui-cargo/lint_groups_priority/fail/Cargo.toml index 4ce41f781711..e4d4af9cd234 100644 --- a/tests/ui-cargo/lint_groups_priority/fail/Cargo.toml +++ b/tests/ui-cargo/lint_groups_priority/fail/Cargo.toml @@ -18,3 +18,11 @@ deprecated = "allow" [lints.clippy] pedantic = { level = "warn", priority = -1 } similar_names = { level = "allow", priority = -1 } + +[workspace.lints.rust] +rust_2018_idioms = "warn" +bare_trait_objects = "allow" + +[workspace.lints.clippy] +pedantic = "warn" +similar_names = "allow" diff --git a/tests/ui-toml/macro_metavars_in_unsafe/default/test.rs b/tests/ui-toml/macro_metavars_in_unsafe/default/test.rs new file mode 100644 index 000000000000..f5e01b431ad9 --- /dev/null +++ b/tests/ui-toml/macro_metavars_in_unsafe/default/test.rs @@ -0,0 +1,260 @@ +//! Tests macro_metavars_in_unsafe with default configuration +#![feature(decl_macro, lint_reasons)] +#![warn(clippy::macro_metavars_in_unsafe)] +#![allow(clippy::no_effect)] + +#[macro_export] +macro_rules! allow_works { + ($v:expr) => { + #[expect(clippy::macro_metavars_in_unsafe)] + unsafe { + $v; + }; + }; +} + +#[macro_export] +macro_rules! simple { + ($v:expr) => { + unsafe { + //~^ ERROR: this macro expands metavariables in an unsafe block + dbg!($v); + } + }; +} + +#[macro_export] +#[rustfmt::skip] // for some reason rustfmt rewrites $r#unsafe to r#u$nsafe, bug? +macro_rules! raw_symbol { + ($r#mod:expr, $r#unsafe:expr) => { + unsafe { + //~^ ERROR: this macro expands metavariables in an unsafe block + $r#mod; + } + $r#unsafe; + }; +} + +#[macro_export] +macro_rules! multilevel_unsafe { + ($v:expr) => { + unsafe { + unsafe { + //~^ ERROR: this macro expands metavariables in an unsafe block + $v; + } + } + }; +} + +#[macro_export] +macro_rules! in_function { + ($v:expr) => { + unsafe { + fn f() { + // function introduces a new body, so don't lint. + $v; + } + } + }; +} + +#[macro_export] +macro_rules! in_function_with_unsafe { + ($v:expr) => { + unsafe { + fn f() { + unsafe { + //~^ ERROR: this macro expands metavariables in an unsafe block + $v; + } + } + } + }; +} + +#[macro_export] +macro_rules! const_static { + ($c:expr, $s:expr) => { + unsafe { + // const and static introduces new body, don't lint + const _X: i32 = $c; + static _Y: i32 = $s; + } + }; +} + +#[macro_export] +macro_rules! const_generic_in_struct { + ($inside_unsafe:expr, $outside_unsafe:expr) => { + unsafe { + struct Ty< + const L: i32 = 1, + const M: i32 = { + 1; + unsafe { $inside_unsafe } + //~^ ERROR: this macro expands metavariables in an unsafe block + }, + const N: i32 = { $outside_unsafe }, + >; + } + }; +} + +#[macro_export] +macro_rules! fn_with_const_generic { + ($inside_unsafe:expr, $outside_unsafe:expr) => { + unsafe { + fn f() { + $outside_unsafe; + unsafe { + //~^ ERROR: this macro expands metavariables in an unsafe block + $inside_unsafe; + } + } + } + }; +} + +#[macro_export] +macro_rules! variables { + ($inside_unsafe:expr, $outside_unsafe:expr) => { + unsafe { + //~^ ERROR: this macro expands metavariables in an unsafe block + $inside_unsafe; + let inside_unsafe = 1; + inside_unsafe; + } + $outside_unsafe; + let outside_unsafe = 1; + outside_unsafe; + }; +} + +#[macro_export] +macro_rules! multiple_matchers { + ($inside_unsafe:expr, $outside_unsafe:expr) => { + unsafe { + //~^ ERROR: this macro expands metavariables in an unsafe block + $inside_unsafe; + } + $outside_unsafe; + }; + ($($v:expr, $x:expr),+) => { + $( + $v; + unsafe { + //~^ ERROR: this macro expands metavariables in an unsafe block + $x; + } + );+ + }; +} + +#[macro_export] +macro_rules! multiple_unsafe_blocks { + ($w:expr, $x:expr, $y:expr) => { + $w; + unsafe { + //~^ ERROR: this macro expands metavariables in an unsafe block + $x; + } + unsafe { + //~^ ERROR: this macro expands metavariables in an unsafe block + $x; + $y; + } + }; +} + +pub macro macro2_0($v:expr) { + unsafe { + //~^ ERROR: this macro expands metavariables in an unsafe block + $v; + } +} + +// don't lint private macros with the default configuration +macro_rules! private_mac { + ($v:expr) => { + unsafe { + $v; + } + }; +} + +// don't lint exported macros that are doc(hidden) because they also aren't part of the public API +#[macro_export] +#[doc(hidden)] +macro_rules! exported_but_hidden { + ($v:expr) => { + unsafe { + $v; + } + }; +} + +// don't lint if the same metavariable is expanded in an unsafe block and then outside of one: +// unsafe {} is still needed at callsite so not problematic +#[macro_export] +macro_rules! does_require_unsafe { + ($v:expr) => { + unsafe { + $v; + } + $v; + }; +} + +#[macro_export] +macro_rules! unsafe_from_root_ctxt { + ($v:expr) => { + // Expands to unsafe { 1 }, but the unsafe block is from the root ctxt and not this macro, + // so no warning. + $v; + }; +} + +// invoked from another macro, should still generate a warning +#[macro_export] +macro_rules! nested_macro_helper { + ($v:expr) => {{ + unsafe { + //~^ ERROR: this macro expands metavariables in an unsafe block + $v; + } + }}; +} + +#[macro_export] +macro_rules! nested_macros { + ($v:expr, $v2:expr) => {{ + unsafe { + //~^ ERROR: this macro expands metavariables in an unsafe block + nested_macro_helper!($v); + $v; + } + }}; +} + +fn main() { + allow_works!(1); + simple!(1); + raw_symbol!(1, 1); + multilevel_unsafe!(1); + in_function!(1); + in_function_with_unsafe!(1); + const_static!(1, 1); + const_generic_in_struct!(1, 1); + fn_with_const_generic!(1, 1); + variables!(1, 1); + multiple_matchers!(1, 1); + multiple_matchers!(1, 1, 1, 1); + macro2_0!(1); + private_mac!(1); + exported_but_hidden!(1); + does_require_unsafe!(1); + multiple_unsafe_blocks!(1, 1, 1); + unsafe_from_root_ctxt!(unsafe { 1 }); + nested_macros!(1, 1); +} diff --git a/tests/ui-toml/macro_metavars_in_unsafe/default/test.stderr b/tests/ui-toml/macro_metavars_in_unsafe/default/test.stderr new file mode 100644 index 000000000000..d6b97f6fde1e --- /dev/null +++ b/tests/ui-toml/macro_metavars_in_unsafe/default/test.stderr @@ -0,0 +1,187 @@ +error: this macro expands metavariables in an unsafe block + --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:19:9 + | +LL | / unsafe { +LL | | +LL | | dbg!($v); +LL | | } + | |_________^ + | + = note: this allows the user of the macro to write unsafe code outside of an unsafe block + = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable + = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite + = note: `-D clippy::macro-metavars-in-unsafe` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::macro_metavars_in_unsafe)]` + +error: this macro expands metavariables in an unsafe block + --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:30:9 + | +LL | / unsafe { +LL | | +LL | | $r#mod; +LL | | } + | |_________^ + | + = note: this allows the user of the macro to write unsafe code outside of an unsafe block + = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable + = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite + +error: this macro expands metavariables in an unsafe block + --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:42:13 + | +LL | / unsafe { +LL | | +LL | | $v; +LL | | } + | |_____________^ + | + = note: this allows the user of the macro to write unsafe code outside of an unsafe block + = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable + = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite + +error: this macro expands metavariables in an unsafe block + --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:67:17 + | +LL | / unsafe { +LL | | +LL | | $v; +LL | | } + | |_________________^ + | + = note: this allows the user of the macro to write unsafe code outside of an unsafe block + = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable + = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite + +error: this macro expands metavariables in an unsafe block + --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:95:21 + | +LL | unsafe { $inside_unsafe } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this allows the user of the macro to write unsafe code outside of an unsafe block + = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable + = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite + +error: this macro expands metavariables in an unsafe block + --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:110:17 + | +LL | / unsafe { +LL | | +LL | | $inside_unsafe; +LL | | } + | |_________________^ + | + = note: this allows the user of the macro to write unsafe code outside of an unsafe block + = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable + = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite + +error: this macro expands metavariables in an unsafe block + --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:122:9 + | +LL | / unsafe { +LL | | +LL | | $inside_unsafe; +LL | | let inside_unsafe = 1; +LL | | inside_unsafe; +LL | | } + | |_________^ + | + = note: this allows the user of the macro to write unsafe code outside of an unsafe block + = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable + = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite + +error: this macro expands metavariables in an unsafe block + --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:137:9 + | +LL | / unsafe { +LL | | +LL | | $inside_unsafe; +LL | | } + | |_________^ + | + = note: this allows the user of the macro to write unsafe code outside of an unsafe block + = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable + = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite + +error: this macro expands metavariables in an unsafe block + --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:146:13 + | +LL | / unsafe { +LL | | +LL | | $x; +LL | | } + | |_____________^ + | + = note: this allows the user of the macro to write unsafe code outside of an unsafe block + = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable + = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite + +error: this macro expands metavariables in an unsafe block + --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:171:5 + | +LL | / unsafe { +LL | | +LL | | $v; +LL | | } + | |_____^ + | + = note: this allows the user of the macro to write unsafe code outside of an unsafe block + = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable + = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite + +error: this macro expands metavariables in an unsafe block + --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:158:9 + | +LL | / unsafe { +LL | | +LL | | $x; +LL | | } + | |_________^ + | + = note: this allows the user of the macro to write unsafe code outside of an unsafe block + = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable + = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite + +error: this macro expands metavariables in an unsafe block + --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:162:9 + | +LL | / unsafe { +LL | | +LL | | $x; +LL | | $y; +LL | | } + | |_________^ + | + = note: this allows the user of the macro to write unsafe code outside of an unsafe block + = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable + = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite + +error: this macro expands metavariables in an unsafe block + --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:222:9 + | +LL | / unsafe { +LL | | +LL | | $v; +LL | | } + | |_________^ + | + = note: this allows the user of the macro to write unsafe code outside of an unsafe block + = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable + = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite + +error: this macro expands metavariables in an unsafe block + --> tests/ui-toml/macro_metavars_in_unsafe/default/test.rs:232:9 + | +LL | / unsafe { +LL | | +LL | | nested_macro_helper!($v); +LL | | $v; +LL | | } + | |_________^ + | + = note: this allows the user of the macro to write unsafe code outside of an unsafe block + = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable + = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite + +error: aborting due to 14 previous errors + diff --git a/tests/ui-toml/macro_metavars_in_unsafe/private/clippy.toml b/tests/ui-toml/macro_metavars_in_unsafe/private/clippy.toml new file mode 100644 index 000000000000..d4bbc2a1be89 --- /dev/null +++ b/tests/ui-toml/macro_metavars_in_unsafe/private/clippy.toml @@ -0,0 +1 @@ +warn-unsafe-macro-metavars-in-private-macros = true diff --git a/tests/ui-toml/macro_metavars_in_unsafe/private/test.rs b/tests/ui-toml/macro_metavars_in_unsafe/private/test.rs new file mode 100644 index 000000000000..2bbe1fa7b7f9 --- /dev/null +++ b/tests/ui-toml/macro_metavars_in_unsafe/private/test.rs @@ -0,0 +1,15 @@ +//! Tests macro_metavars_in_unsafe with private (non-exported) macros +#![warn(clippy::macro_metavars_in_unsafe)] + +macro_rules! mac { + ($v:expr) => { + unsafe { + //~^ ERROR: this macro expands metavariables in an unsafe block + dbg!($v); + } + }; +} + +fn main() { + mac!(1); +} diff --git a/tests/ui-toml/macro_metavars_in_unsafe/private/test.stderr b/tests/ui-toml/macro_metavars_in_unsafe/private/test.stderr new file mode 100644 index 000000000000..f9c418b22188 --- /dev/null +++ b/tests/ui-toml/macro_metavars_in_unsafe/private/test.stderr @@ -0,0 +1,17 @@ +error: this macro expands metavariables in an unsafe block + --> tests/ui-toml/macro_metavars_in_unsafe/private/test.rs:6:9 + | +LL | / unsafe { +LL | | +LL | | dbg!($v); +LL | | } + | |_________^ + | + = note: this allows the user of the macro to write unsafe code outside of an unsafe block + = help: consider expanding any metavariables outside of this block, e.g. by storing them in a variable + = help: ... or also expand referenced metavariables in a safe context to require an unsafe block at callsite + = note: `-D clippy::macro-metavars-in-unsafe` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::macro_metavars_in_unsafe)]` + +error: aborting due to 1 previous error + diff --git a/tests/ui-toml/panic/clippy.toml b/tests/ui-toml/panic/clippy.toml new file mode 100644 index 000000000000..5d6230d092c0 --- /dev/null +++ b/tests/ui-toml/panic/clippy.toml @@ -0,0 +1 @@ +allow-panic-in-tests = true diff --git a/tests/ui-toml/panic/panic.rs b/tests/ui-toml/panic/panic.rs new file mode 100644 index 000000000000..618a37ddfc55 --- /dev/null +++ b/tests/ui-toml/panic/panic.rs @@ -0,0 +1,54 @@ +//@compile-flags: --test +#![warn(clippy::panic)] + +fn main() { + enum Enam { + A, + } + let a = Enam::A; + match a { + Enam::A => {}, + _ => panic!(""), + } +} + +#[test] +fn lonely_test() { + enum Enam { + A, + } + let a = Enam::A; + match a { + Enam::A => {}, + _ => panic!(""), + } +} + +#[cfg(test)] +mod tests { + // should not lint in `#[cfg(test)]` modules + #[test] + fn test_fn() { + enum Enam { + A, + } + let a = Enam::A; + match a { + Enam::A => {}, + _ => panic!(""), + } + + bar(); + } + + fn bar() { + enum Enam { + A, + } + let a = Enam::A; + match a { + Enam::A => {}, + _ => panic!(""), + } + } +} diff --git a/tests/ui-toml/panic/panic.stderr b/tests/ui-toml/panic/panic.stderr new file mode 100644 index 000000000000..bf7503e086c9 --- /dev/null +++ b/tests/ui-toml/panic/panic.stderr @@ -0,0 +1,11 @@ +error: `panic` should not be present in production code + --> tests/ui-toml/panic/panic.rs:11:14 + | +LL | _ => panic!(""), + | ^^^^^^^^^^ + | + = note: `-D clippy::panic` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::panic)]` + +error: aborting due to 1 previous error + diff --git a/tests/ui-toml/renamed_function_params/default/clippy.toml b/tests/ui-toml/renamed_function_params/default/clippy.toml new file mode 100644 index 000000000000..5381e70a9391 --- /dev/null +++ b/tests/ui-toml/renamed_function_params/default/clippy.toml @@ -0,0 +1,2 @@ +# Ignore `From`, `TryFrom`, `FromStr` by default +# allow-renamed-params-for = [] diff --git a/tests/ui-toml/renamed_function_params/extend/clippy.toml b/tests/ui-toml/renamed_function_params/extend/clippy.toml new file mode 100644 index 000000000000..9b3853e76961 --- /dev/null +++ b/tests/ui-toml/renamed_function_params/extend/clippy.toml @@ -0,0 +1,2 @@ +# Ignore `From`, `TryFrom`, `FromStr` by default +allow-renamed-params-for = [ "..", "std::ops::Add", "renamed_function_params::MyTrait" ] diff --git a/tests/ui-toml/renamed_function_params/renamed_function_params.default.stderr b/tests/ui-toml/renamed_function_params/renamed_function_params.default.stderr new file mode 100644 index 000000000000..2d700f607592 --- /dev/null +++ b/tests/ui-toml/renamed_function_params/renamed_function_params.default.stderr @@ -0,0 +1,46 @@ +error: renamed function parameter of trait impl + --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:30:18 + | +LL | fn eq(&self, rhs: &Self) -> bool { + | ^^^ help: consider using the default name: `other` + | + = note: `-D clippy::renamed-function-params` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::renamed_function_params)]` + +error: renamed function parameter of trait impl + --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:34:18 + | +LL | fn ne(&self, rhs: &Self) -> bool { + | ^^^ help: consider using the default name: `other` + +error: renamed function parameter of trait impl + --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:48:19 + | +LL | fn foo(&self, i_dont_wanna_use_your_name: u8) {} // only lint in `extend` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using the default name: `val` + +error: renamed function parameter of trait impl + --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:55:31 + | +LL | fn hash(&self, states: &mut H) { + | ^^^^^^ help: consider using the default name: `state` + +error: renamed function parameters of trait impl + --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:59:30 + | +LL | fn hash_slice(date: &[Self], states: &mut H) { + | ^^^^ ^^^^^^ + | +help: consider using the default names + | +LL | fn hash_slice(data: &[Self], state: &mut H) { + | ~~~~ ~~~~~ + +error: renamed function parameter of trait impl + --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:80:18 + | +LL | fn add(self, b: B) -> C { + | ^ help: consider using the default name: `rhs` + +error: aborting due to 6 previous errors + diff --git a/tests/ui-toml/renamed_function_params/renamed_function_params.extend.stderr b/tests/ui-toml/renamed_function_params/renamed_function_params.extend.stderr new file mode 100644 index 000000000000..e57554fa613a --- /dev/null +++ b/tests/ui-toml/renamed_function_params/renamed_function_params.extend.stderr @@ -0,0 +1,34 @@ +error: renamed function parameter of trait impl + --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:30:18 + | +LL | fn eq(&self, rhs: &Self) -> bool { + | ^^^ help: consider using the default name: `other` + | + = note: `-D clippy::renamed-function-params` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::renamed_function_params)]` + +error: renamed function parameter of trait impl + --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:34:18 + | +LL | fn ne(&self, rhs: &Self) -> bool { + | ^^^ help: consider using the default name: `other` + +error: renamed function parameter of trait impl + --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:55:31 + | +LL | fn hash(&self, states: &mut H) { + | ^^^^^^ help: consider using the default name: `state` + +error: renamed function parameters of trait impl + --> tests/ui-toml/renamed_function_params/renamed_function_params.rs:59:30 + | +LL | fn hash_slice(date: &[Self], states: &mut H) { + | ^^^^ ^^^^^^ + | +help: consider using the default names + | +LL | fn hash_slice(data: &[Self], state: &mut H) { + | ~~~~ ~~~~~ + +error: aborting due to 4 previous errors + diff --git a/tests/ui-toml/renamed_function_params/renamed_function_params.rs b/tests/ui-toml/renamed_function_params/renamed_function_params.rs new file mode 100644 index 000000000000..f3eb910abbd6 --- /dev/null +++ b/tests/ui-toml/renamed_function_params/renamed_function_params.rs @@ -0,0 +1,110 @@ +//@no-rustfix +//@revisions: default extend +//@[default] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/renamed_function_params/default +//@[extend] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/renamed_function_params/extend +#![warn(clippy::renamed_function_params)] +#![allow(clippy::partialeq_ne_impl, clippy::to_string_trait_impl)] +#![allow(unused)] + +use std::hash::{Hash, Hasher}; + +struct A; +impl From for String { + fn from(_value: A) -> Self { + String::new() + } +} +impl ToString for A { + fn to_string(&self) -> String { + String::new() + } +} + +struct B(u32); +impl std::convert::From for String { + fn from(b: B) -> Self { + b.0.to_string() + } +} +impl PartialEq for B { + fn eq(&self, rhs: &Self) -> bool { + //~^ ERROR: renamed function parameter of trait impl + self.0 == rhs.0 + } + fn ne(&self, rhs: &Self) -> bool { + //~^ ERROR: renamed function parameter of trait impl + self.0 != rhs.0 + } +} + +trait MyTrait { + fn foo(&self, val: u8); + fn bar(a: u8, b: u8); + fn baz(self, _val: u8); + fn quz(&self, _: u8); +} + +impl MyTrait for B { + fn foo(&self, i_dont_wanna_use_your_name: u8) {} // only lint in `extend` + fn bar(_a: u8, _: u8) {} + fn baz(self, val: u8) {} + fn quz(&self, val: u8) {} +} + +impl Hash for B { + fn hash(&self, states: &mut H) { + //~^ ERROR: renamed function parameter of trait impl + self.0.hash(states); + } + fn hash_slice(date: &[Self], states: &mut H) { + //~^ ERROR: renamed function parameters of trait impl + for d in date { + d.hash(states); + } + } +} + +impl B { + fn totally_irrelevant(&self, right: bool) {} + fn some_fn(&self, other: impl MyTrait) {} +} + +#[derive(Copy, Clone)] +enum C { + A, + B(u32), +} + +impl std::ops::Add for C { + type Output = C; + fn add(self, b: B) -> C { + // only lint in `extend` + C::B(b.0) + } +} + +impl From for C { + fn from(_: A) -> C { + C::A + } +} + +trait CustomTraitA { + fn foo(&self, other: u32); +} +trait CustomTraitB { + fn bar(&self, value: u8); +} + +macro_rules! impl_trait { + ($impl_for:ident, $tr:ty, $fn_name:ident, $t:ty) => { + impl $tr for $impl_for { + fn $fn_name(&self, v: $t) {} + } + }; +} + +impl_trait!(C, CustomTraitA, foo, u32); +impl_trait!(C, CustomTraitB, bar, u8); + +fn main() {} diff --git a/tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs b/tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs index 7f28efd676f2..f02bd07cfe7b 100644 --- a/tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs +++ b/tests/ui-toml/toml_disallowed_types/conf_disallowed_types.rs @@ -40,3 +40,9 @@ fn main() { let _ = HashMap; let _: usize = 64_usize; } + +mod useless_attribute { + // Regression test for https://github.com/rust-lang/rust-clippy/issues/12753 + #[allow(clippy::disallowed_types)] + use std::collections::HashMap; +} diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr index 722e9b3bc8d4..5cf9c0fb2710 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -8,8 +8,10 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect allow-expect-in-tests allow-mixed-uninlined-format-args allow-one-hash-in-raw-strings + allow-panic-in-tests allow-print-in-tests allow-private-module-inception + allow-renamed-params-for allow-unwrap-in-tests allow-useless-vec-in-tests allowed-dotfiles @@ -74,6 +76,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect vec-box-size-threshold verbose-bit-mask-threshold warn-on-all-wildcard-imports + warn-unsafe-macro-metavars-in-private-macros --> $DIR/tests/ui-toml/toml_unknown_key/clippy.toml:2:1 | LL | foobar = 42 @@ -89,8 +92,10 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect allow-expect-in-tests allow-mixed-uninlined-format-args allow-one-hash-in-raw-strings + allow-panic-in-tests allow-print-in-tests allow-private-module-inception + allow-renamed-params-for allow-unwrap-in-tests allow-useless-vec-in-tests allowed-dotfiles @@ -155,6 +160,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect vec-box-size-threshold verbose-bit-mask-threshold warn-on-all-wildcard-imports + warn-unsafe-macro-metavars-in-private-macros --> $DIR/tests/ui-toml/toml_unknown_key/clippy.toml:4:1 | LL | barfoo = 53 @@ -170,8 +176,10 @@ error: error reading Clippy's configuration file: unknown field `allow_mixed_uni allow-expect-in-tests allow-mixed-uninlined-format-args allow-one-hash-in-raw-strings + allow-panic-in-tests allow-print-in-tests allow-private-module-inception + allow-renamed-params-for allow-unwrap-in-tests allow-useless-vec-in-tests allowed-dotfiles @@ -236,6 +244,7 @@ error: error reading Clippy's configuration file: unknown field `allow_mixed_uni vec-box-size-threshold verbose-bit-mask-threshold warn-on-all-wildcard-imports + warn-unsafe-macro-metavars-in-private-macros --> $DIR/tests/ui-toml/toml_unknown_key/clippy.toml:7:1 | LL | allow_mixed_uninlined_format_args = true diff --git a/tests/ui/assigning_clones.fixed b/tests/ui/assigning_clones.fixed index 8387c7d6156b..70ab43b49b3a 100644 --- a/tests/ui/assigning_clones.fixed +++ b/tests/ui/assigning_clones.fixed @@ -62,6 +62,16 @@ fn clone_method_rhs_complex(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFr mut_thing.clone_from(ref_thing + ref_thing); } +fn clone_method_macro() { + let mut s = String::from(""); + s.clone_from(&format!("{} {}", "hello", "world")); +} + +fn clone_function_macro() { + let mut s = String::from(""); + Clone::clone_from(&mut s, &format!("{} {}", "hello", "world")); +} + fn assign_to_init_mut_var(b: HasCloneFrom) -> HasCloneFrom { let mut a = HasCloneFrom; for _ in 1..10 { @@ -86,6 +96,12 @@ fn assign_to_uninit_mut_var(b: HasCloneFrom) { a = b.clone(); } +fn late_init_let_tuple() { + let (p, q): (String, String); + p = "ghi".to_string(); + q = p.clone(); +} + #[derive(Clone)] pub struct HasDeriveClone; @@ -208,6 +224,16 @@ fn owned_function_val(mut mut_thing: String, ref_str: &str) { ToOwned::clone_into(ref_str, &mut mut_thing); } +fn owned_method_macro() { + let mut s = String::from(""); + format!("{} {}", "hello", "world").clone_into(&mut s); +} + +fn owned_function_macro() { + let mut s = String::from(""); + ToOwned::clone_into(&format!("{} {}", "hello", "world"), &mut s); +} + struct FakeToOwned; impl FakeToOwned { /// This looks just like `ToOwned::to_owned` diff --git a/tests/ui/assigning_clones.rs b/tests/ui/assigning_clones.rs index 6f4da9f652c9..9699fed100c8 100644 --- a/tests/ui/assigning_clones.rs +++ b/tests/ui/assigning_clones.rs @@ -62,6 +62,16 @@ fn clone_method_rhs_complex(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFr *mut_thing = (ref_thing + ref_thing).clone(); } +fn clone_method_macro() { + let mut s = String::from(""); + s = format!("{} {}", "hello", "world").clone(); +} + +fn clone_function_macro() { + let mut s = String::from(""); + s = Clone::clone(&format!("{} {}", "hello", "world")); +} + fn assign_to_init_mut_var(b: HasCloneFrom) -> HasCloneFrom { let mut a = HasCloneFrom; for _ in 1..10 { @@ -86,6 +96,12 @@ fn assign_to_uninit_mut_var(b: HasCloneFrom) { a = b.clone(); } +fn late_init_let_tuple() { + let (p, q): (String, String); + p = "ghi".to_string(); + q = p.clone(); +} + #[derive(Clone)] pub struct HasDeriveClone; @@ -208,6 +224,16 @@ fn owned_function_val(mut mut_thing: String, ref_str: &str) { mut_thing = ToOwned::to_owned(ref_str); } +fn owned_method_macro() { + let mut s = String::from(""); + s = format!("{} {}", "hello", "world").to_owned(); +} + +fn owned_function_macro() { + let mut s = String::from(""); + s = ToOwned::to_owned(&format!("{} {}", "hello", "world")); +} + struct FakeToOwned; impl FakeToOwned { /// This looks just like `ToOwned::to_owned` diff --git a/tests/ui/assigning_clones.stderr b/tests/ui/assigning_clones.stderr index 793927bd1cb1..a68516376abb 100644 --- a/tests/ui/assigning_clones.stderr +++ b/tests/ui/assigning_clones.stderr @@ -62,64 +62,88 @@ LL | *mut_thing = (ref_thing + ref_thing).clone(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `mut_thing.clone_from(ref_thing + ref_thing)` error: assigning the result of `Clone::clone()` may be inefficient - --> tests/ui/assigning_clones.rs:68:9 + --> tests/ui/assigning_clones.rs:67:5 + | +LL | s = format!("{} {}", "hello", "world").clone(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `s.clone_from(&format!("{} {}", "hello", "world"))` + +error: assigning the result of `Clone::clone()` may be inefficient + --> tests/ui/assigning_clones.rs:72:5 + | +LL | s = Clone::clone(&format!("{} {}", "hello", "world")); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `Clone::clone_from(&mut s, &format!("{} {}", "hello", "world"))` + +error: assigning the result of `Clone::clone()` may be inefficient + --> tests/ui/assigning_clones.rs:78:9 | LL | a = b.clone(); | ^^^^^^^^^^^^^ help: use `clone_from()`: `a.clone_from(&b)` error: assigning the result of `Clone::clone()` may be inefficient - --> tests/ui/assigning_clones.rs:133:5 + --> tests/ui/assigning_clones.rs:149:5 | LL | a = b.clone(); | ^^^^^^^^^^^^^ help: use `clone_from()`: `a.clone_from(&b)` error: assigning the result of `Clone::clone()` may be inefficient - --> tests/ui/assigning_clones.rs:140:5 + --> tests/ui/assigning_clones.rs:156:5 | LL | a = b.clone(); | ^^^^^^^^^^^^^ help: use `clone_from()`: `a.clone_from(&b)` error: assigning the result of `ToOwned::to_owned()` may be inefficient - --> tests/ui/assigning_clones.rs:141:5 + --> tests/ui/assigning_clones.rs:157:5 | LL | a = c.to_owned(); | ^^^^^^^^^^^^^^^^ help: use `clone_into()`: `c.clone_into(&mut a)` error: assigning the result of `ToOwned::to_owned()` may be inefficient - --> tests/ui/assigning_clones.rs:171:5 + --> tests/ui/assigning_clones.rs:187:5 | LL | *mut_string = ref_str.to_owned(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(mut_string)` error: assigning the result of `ToOwned::to_owned()` may be inefficient - --> tests/ui/assigning_clones.rs:175:5 + --> tests/ui/assigning_clones.rs:191:5 | LL | mut_string = ref_str.to_owned(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(&mut mut_string)` error: assigning the result of `ToOwned::to_owned()` may be inefficient - --> tests/ui/assigning_clones.rs:196:5 + --> tests/ui/assigning_clones.rs:212:5 | LL | **mut_box_string = ref_str.to_owned(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(&mut (*mut_box_string))` error: assigning the result of `ToOwned::to_owned()` may be inefficient - --> tests/ui/assigning_clones.rs:200:5 + --> tests/ui/assigning_clones.rs:216:5 | LL | **mut_box_string = ref_str.to_owned(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(&mut (*mut_box_string))` error: assigning the result of `ToOwned::to_owned()` may be inefficient - --> tests/ui/assigning_clones.rs:204:5 + --> tests/ui/assigning_clones.rs:220:5 | LL | *mut_thing = ToOwned::to_owned(ref_str); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ToOwned::clone_into(ref_str, mut_thing)` error: assigning the result of `ToOwned::to_owned()` may be inefficient - --> tests/ui/assigning_clones.rs:208:5 + --> tests/ui/assigning_clones.rs:224:5 | LL | mut_thing = ToOwned::to_owned(ref_str); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ToOwned::clone_into(ref_str, &mut mut_thing)` -error: aborting due to 20 previous errors +error: assigning the result of `ToOwned::to_owned()` may be inefficient + --> tests/ui/assigning_clones.rs:229:5 + | +LL | s = format!("{} {}", "hello", "world").to_owned(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `format!("{} {}", "hello", "world").clone_into(&mut s)` + +error: assigning the result of `ToOwned::to_owned()` may be inefficient + --> tests/ui/assigning_clones.rs:234:5 + | +LL | s = ToOwned::to_owned(&format!("{} {}", "hello", "world")); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ToOwned::clone_into(&format!("{} {}", "hello", "world"), &mut s)` + +error: aborting due to 24 previous errors diff --git a/tests/ui/doc/doc_lazy_blockquote.fixed b/tests/ui/doc/doc_lazy_blockquote.fixed new file mode 100644 index 000000000000..9877991f183a --- /dev/null +++ b/tests/ui/doc/doc_lazy_blockquote.fixed @@ -0,0 +1,47 @@ +#![warn(clippy::doc_lazy_continuation)] + +/// > blockquote with +/// > lazy continuation +//~^ ERROR: doc quote missing `>` marker +fn first() {} + +/// > blockquote with no +/// > lazy continuation +fn first_nowarn() {} + +/// > blockquote with no +/// +/// lazy continuation +fn two_nowarn() {} + +/// > nest here +/// > +/// > > nest here +/// > > lazy continuation +//~^ ERROR: doc quote missing `>` marker +fn two() {} + +/// > nest here +/// > +/// > > nest here +/// > > lazy continuation +//~^ ERROR: doc quote missing `>` marker +fn three() {} + +/// > * > nest here +/// > > lazy continuation +//~^ ERROR: doc quote missing `>` marker +fn four() {} + +/// > * > nest here +/// > > lazy continuation +//~^ ERROR: doc quote missing `>` marker +fn four_point_1() {} + +/// * > nest here lazy continuation +fn five() {} + +/// 1. > nest here +/// > lazy continuation (this results in strange indentation, but still works) +//~^ ERROR: doc quote missing `>` marker +fn six() {} diff --git a/tests/ui/doc/doc_lazy_blockquote.rs b/tests/ui/doc/doc_lazy_blockquote.rs new file mode 100644 index 000000000000..587b2fdd533c --- /dev/null +++ b/tests/ui/doc/doc_lazy_blockquote.rs @@ -0,0 +1,47 @@ +#![warn(clippy::doc_lazy_continuation)] + +/// > blockquote with +/// lazy continuation +//~^ ERROR: doc quote missing `>` marker +fn first() {} + +/// > blockquote with no +/// > lazy continuation +fn first_nowarn() {} + +/// > blockquote with no +/// +/// lazy continuation +fn two_nowarn() {} + +/// > nest here +/// > +/// > > nest here +/// > lazy continuation +//~^ ERROR: doc quote missing `>` marker +fn two() {} + +/// > nest here +/// > +/// > > nest here +/// lazy continuation +//~^ ERROR: doc quote missing `>` marker +fn three() {} + +/// > * > nest here +/// lazy continuation +//~^ ERROR: doc quote missing `>` marker +fn four() {} + +/// > * > nest here +/// lazy continuation +//~^ ERROR: doc quote missing `>` marker +fn four_point_1() {} + +/// * > nest here lazy continuation +fn five() {} + +/// 1. > nest here +/// lazy continuation (this results in strange indentation, but still works) +//~^ ERROR: doc quote missing `>` marker +fn six() {} diff --git a/tests/ui/doc/doc_lazy_blockquote.stderr b/tests/ui/doc/doc_lazy_blockquote.stderr new file mode 100644 index 000000000000..975184a01c3f --- /dev/null +++ b/tests/ui/doc/doc_lazy_blockquote.stderr @@ -0,0 +1,76 @@ +error: doc quote missing `>` marker + --> tests/ui/doc/doc_lazy_blockquote.rs:4:5 + | +LL | /// lazy continuation + | ^ + | + = help: if this not intended to be a quote at all, escape it with `\>` + = note: `-D clippy::doc-lazy-continuation` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::doc_lazy_continuation)]` +help: add markers to start of line + | +LL | /// > lazy continuation + | + + +error: doc quote missing `>` marker + --> tests/ui/doc/doc_lazy_blockquote.rs:20:5 + | +LL | /// > lazy continuation + | ^^ + | + = help: if this not intended to be a quote at all, escape it with `\>` +help: add markers to start of line + | +LL | /// > > lazy continuation + | + + +error: doc quote missing `>` marker + --> tests/ui/doc/doc_lazy_blockquote.rs:27:5 + | +LL | /// lazy continuation + | ^ + | + = help: if this not intended to be a quote at all, escape it with `\>` +help: add markers to start of line + | +LL | /// > > lazy continuation + | +++ + +error: doc quote missing `>` marker + --> tests/ui/doc/doc_lazy_blockquote.rs:32:5 + | +LL | /// lazy continuation + | ^ + | + = help: if this not intended to be a quote at all, escape it with `\>` +help: add markers to start of line + | +LL | /// > > lazy continuation + | +++++++ + +error: doc quote missing `>` marker + --> tests/ui/doc/doc_lazy_blockquote.rs:37:5 + | +LL | /// lazy continuation + | ^ + | + = help: if this not intended to be a quote at all, escape it with `\>` +help: add markers to start of line + | +LL | /// > > lazy continuation + | +++++ + +error: doc quote missing `>` marker + --> tests/ui/doc/doc_lazy_blockquote.rs:45:5 + | +LL | /// lazy continuation (this results in strange indentation, but still works) + | ^ + | + = help: if this not intended to be a quote at all, escape it with `\>` +help: add markers to start of line + | +LL | /// > lazy continuation (this results in strange indentation, but still works) + | + + +error: aborting due to 6 previous errors + diff --git a/tests/ui/doc/doc_lazy_list.fixed b/tests/ui/doc/doc_lazy_list.fixed new file mode 100644 index 000000000000..409e6b0bc227 --- /dev/null +++ b/tests/ui/doc/doc_lazy_list.fixed @@ -0,0 +1,77 @@ +#![warn(clippy::doc_lazy_continuation)] + +/// 1. nest here +/// lazy continuation +//~^ ERROR: doc list item missing indentation +fn one() {} + +/// 1. first line +/// lazy list continuations don't make warnings with this lint +//~^ ERROR: doc list item missing indentation +/// because they don't have the +//~^ ERROR: doc list item missing indentation +fn two() {} + +/// - nest here +/// lazy continuation +//~^ ERROR: doc list item missing indentation +fn three() {} + +/// - first line +/// lazy list continuations don't make warnings with this lint +//~^ ERROR: doc list item missing indentation +/// because they don't have the +//~^ ERROR: doc list item missing indentation +fn four() {} + +/// - nest here +/// lazy continuation +//~^ ERROR: doc list item missing indentation +fn five() {} + +/// - - first line +/// this will warn on the lazy continuation +//~^ ERROR: doc list item missing indentation +/// and so should this +//~^ ERROR: doc list item missing indentation +fn six() {} + +/// - - first line +/// +/// this is not a lazy continuation +fn seven() {} + +#[rustfmt::skip] +// https://github.com/rust-lang/rust-clippy/pull/12770#issuecomment-2118601768 +/// Returns a list of ProtocolDescriptors from a Serde JSON input. +/// +/// Defined Protocol Identifiers for the Protocol Descriptor +/// We intentionally omit deprecated profile identifiers. +/// From Bluetooth Assigned Numbers: +/// https://www.bluetooth.com/specifications/assigned-numbers/service-discovery +/// +/// # Arguments +/// * `protocol_descriptors`: A Json Representation of the ProtocolDescriptors +/// to set up. Example: +/// 'protocol_descriptors': [ +//~^ ERROR: doc list item missing indentation +/// { +/// 'protocol': 25, # u64 Representation of ProtocolIdentifier::AVDTP +/// 'params': [ +/// { +/// 'data': 0x0103 # to indicate 1.3 +/// }, +/// { +/// 'data': 0x0105 # to indicate 1.5 +/// } +/// ] +/// }, +/// { +/// 'protocol': 1, # u64 Representation of ProtocolIdentifier::SDP +/// 'params': [{ +/// 'data': 0x0019 +/// }] +/// } +/// ] +//~^ ERROR: doc list item missing indentation +fn eight() {} diff --git a/tests/ui/doc/doc_lazy_list.rs b/tests/ui/doc/doc_lazy_list.rs new file mode 100644 index 000000000000..30ab448a1130 --- /dev/null +++ b/tests/ui/doc/doc_lazy_list.rs @@ -0,0 +1,77 @@ +#![warn(clippy::doc_lazy_continuation)] + +/// 1. nest here +/// lazy continuation +//~^ ERROR: doc list item missing indentation +fn one() {} + +/// 1. first line +/// lazy list continuations don't make warnings with this lint +//~^ ERROR: doc list item missing indentation +/// because they don't have the +//~^ ERROR: doc list item missing indentation +fn two() {} + +/// - nest here +/// lazy continuation +//~^ ERROR: doc list item missing indentation +fn three() {} + +/// - first line +/// lazy list continuations don't make warnings with this lint +//~^ ERROR: doc list item missing indentation +/// because they don't have the +//~^ ERROR: doc list item missing indentation +fn four() {} + +/// - nest here +/// lazy continuation +//~^ ERROR: doc list item missing indentation +fn five() {} + +/// - - first line +/// this will warn on the lazy continuation +//~^ ERROR: doc list item missing indentation +/// and so should this +//~^ ERROR: doc list item missing indentation +fn six() {} + +/// - - first line +/// +/// this is not a lazy continuation +fn seven() {} + +#[rustfmt::skip] +// https://github.com/rust-lang/rust-clippy/pull/12770#issuecomment-2118601768 +/// Returns a list of ProtocolDescriptors from a Serde JSON input. +/// +/// Defined Protocol Identifiers for the Protocol Descriptor +/// We intentionally omit deprecated profile identifiers. +/// From Bluetooth Assigned Numbers: +/// https://www.bluetooth.com/specifications/assigned-numbers/service-discovery +/// +/// # Arguments +/// * `protocol_descriptors`: A Json Representation of the ProtocolDescriptors +/// to set up. Example: +/// 'protocol_descriptors': [ +//~^ ERROR: doc list item missing indentation +/// { +/// 'protocol': 25, # u64 Representation of ProtocolIdentifier::AVDTP +/// 'params': [ +/// { +/// 'data': 0x0103 # to indicate 1.3 +/// }, +/// { +/// 'data': 0x0105 # to indicate 1.5 +/// } +/// ] +/// }, +/// { +/// 'protocol': 1, # u64 Representation of ProtocolIdentifier::SDP +/// 'params': [{ +/// 'data': 0x0019 +/// }] +/// } +/// ] +//~^ ERROR: doc list item missing indentation +fn eight() {} diff --git a/tests/ui/doc/doc_lazy_list.stderr b/tests/ui/doc/doc_lazy_list.stderr new file mode 100644 index 000000000000..ddfdc49340c4 --- /dev/null +++ b/tests/ui/doc/doc_lazy_list.stderr @@ -0,0 +1,136 @@ +error: doc list item missing indentation + --> tests/ui/doc/doc_lazy_list.rs:4:5 + | +LL | /// lazy continuation + | ^ + | + = help: if this is supposed to be its own paragraph, add a blank line + = note: `-D clippy::doc-lazy-continuation` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::doc_lazy_continuation)]` +help: indent this line + | +LL | /// lazy continuation + | +++ + +error: doc list item missing indentation + --> tests/ui/doc/doc_lazy_list.rs:9:5 + | +LL | /// lazy list continuations don't make warnings with this lint + | ^ + | + = help: if this is supposed to be its own paragraph, add a blank line +help: indent this line + | +LL | /// lazy list continuations don't make warnings with this lint + | +++ + +error: doc list item missing indentation + --> tests/ui/doc/doc_lazy_list.rs:11:5 + | +LL | /// because they don't have the + | ^ + | + = help: if this is supposed to be its own paragraph, add a blank line +help: indent this line + | +LL | /// because they don't have the + | +++ + +error: doc list item missing indentation + --> tests/ui/doc/doc_lazy_list.rs:16:5 + | +LL | /// lazy continuation + | ^ + | + = help: if this is supposed to be its own paragraph, add a blank line +help: indent this line + | +LL | /// lazy continuation + | ++++ + +error: doc list item missing indentation + --> tests/ui/doc/doc_lazy_list.rs:21:5 + | +LL | /// lazy list continuations don't make warnings with this lint + | ^ + | + = help: if this is supposed to be its own paragraph, add a blank line +help: indent this line + | +LL | /// lazy list continuations don't make warnings with this lint + | ++++ + +error: doc list item missing indentation + --> tests/ui/doc/doc_lazy_list.rs:23:5 + | +LL | /// because they don't have the + | ^ + | + = help: if this is supposed to be its own paragraph, add a blank line +help: indent this line + | +LL | /// because they don't have the + | ++++ + +error: doc list item missing indentation + --> tests/ui/doc/doc_lazy_list.rs:28:5 + | +LL | /// lazy continuation + | ^ + | + = help: if this is supposed to be its own paragraph, add a blank line +help: indent this line + | +LL | /// lazy continuation + | ++++ + +error: doc list item missing indentation + --> tests/ui/doc/doc_lazy_list.rs:33:5 + | +LL | /// this will warn on the lazy continuation + | ^ + | + = help: if this is supposed to be its own paragraph, add a blank line +help: indent this line + | +LL | /// this will warn on the lazy continuation + | ++++++ + +error: doc list item missing indentation + --> tests/ui/doc/doc_lazy_list.rs:35:5 + | +LL | /// and so should this + | ^^^^ + | + = help: if this is supposed to be its own paragraph, add a blank line +help: indent this line + | +LL | /// and so should this + | ++ + +error: doc list item missing indentation + --> tests/ui/doc/doc_lazy_list.rs:56:5 + | +LL | /// 'protocol_descriptors': [ + | ^ + | + = help: if this is supposed to be its own paragraph, add a blank line +help: indent this line + | +LL | /// 'protocol_descriptors': [ + | + + +error: doc list item missing indentation + --> tests/ui/doc/doc_lazy_list.rs:75:5 + | +LL | /// ] + | ^ + | + = help: if this is supposed to be its own paragraph, add a blank line +help: indent this line + | +LL | /// ] + | + + +error: aborting due to 11 previous errors + diff --git a/tests/ui/duplicated_attributes.rs b/tests/ui/duplicated_attributes.rs index d51e7e37beb6..97cf4a69682d 100644 --- a/tests/ui/duplicated_attributes.rs +++ b/tests/ui/duplicated_attributes.rs @@ -1,5 +1,5 @@ //@aux-build:proc_macro_attr.rs - +#![feature(rustc_attrs)] #![warn(clippy::duplicated_attributes)] #![cfg(any(unix, windows))] #![allow(dead_code)] @@ -20,6 +20,10 @@ fn foo() {} #[cfg(unix)] // cfgs are not handled fn bar() {} +// No warning: +#[rustc_on_unimplemented(on(_Self = "&str", label = "`a"), on(_Self = "alloc::string::String", label = "a"))] +trait Abc {} + #[proc_macro_attr::duplicated_attr()] // Should not warn! fn babar() {} diff --git a/tests/ui/from_str_radix_10.fixed b/tests/ui/from_str_radix_10.fixed index 8c253bfd99a5..f9ce1defda17 100644 --- a/tests/ui/from_str_radix_10.fixed +++ b/tests/ui/from_str_radix_10.fixed @@ -1,3 +1,4 @@ +#![feature(const_int_from_str)] #![warn(clippy::from_str_radix_10)] mod some_mod { @@ -59,3 +60,13 @@ fn main() -> Result<(), Box> { Ok(()) } + +fn issue_12732() { + const A: Result = u32::from_str_radix("123", 10); + const B: () = { + let _ = u32::from_str_radix("123", 10); + }; + const fn foo() { + let _ = u32::from_str_radix("123", 10); + } +} diff --git a/tests/ui/from_str_radix_10.rs b/tests/ui/from_str_radix_10.rs index e9d02215710c..2d5b351f8da3 100644 --- a/tests/ui/from_str_radix_10.rs +++ b/tests/ui/from_str_radix_10.rs @@ -1,3 +1,4 @@ +#![feature(const_int_from_str)] #![warn(clippy::from_str_radix_10)] mod some_mod { @@ -59,3 +60,13 @@ fn main() -> Result<(), Box> { Ok(()) } + +fn issue_12732() { + const A: Result = u32::from_str_radix("123", 10); + const B: () = { + let _ = u32::from_str_radix("123", 10); + }; + const fn foo() { + let _ = u32::from_str_radix("123", 10); + } +} diff --git a/tests/ui/from_str_radix_10.stderr b/tests/ui/from_str_radix_10.stderr index 4aa84eca2612..01a1bf8940a1 100644 --- a/tests/ui/from_str_radix_10.stderr +++ b/tests/ui/from_str_radix_10.stderr @@ -1,5 +1,5 @@ error: this call to `from_str_radix` can be replaced with a call to `str::parse` - --> tests/ui/from_str_radix_10.rs:28:5 + --> tests/ui/from_str_radix_10.rs:29:5 | LL | u32::from_str_radix("30", 10)?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"30".parse::()` @@ -8,43 +8,43 @@ LL | u32::from_str_radix("30", 10)?; = help: to override `-D warnings` add `#[allow(clippy::from_str_radix_10)]` error: this call to `from_str_radix` can be replaced with a call to `str::parse` - --> tests/ui/from_str_radix_10.rs:31:5 + --> tests/ui/from_str_radix_10.rs:32:5 | LL | i64::from_str_radix("24", 10)?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"24".parse::()` error: this call to `from_str_radix` can be replaced with a call to `str::parse` - --> tests/ui/from_str_radix_10.rs:33:5 + --> tests/ui/from_str_radix_10.rs:34:5 | LL | isize::from_str_radix("100", 10)?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"100".parse::()` error: this call to `from_str_radix` can be replaced with a call to `str::parse` - --> tests/ui/from_str_radix_10.rs:35:5 + --> tests/ui/from_str_radix_10.rs:36:5 | LL | u8::from_str_radix("7", 10)?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `"7".parse::()` error: this call to `from_str_radix` can be replaced with a call to `str::parse` - --> tests/ui/from_str_radix_10.rs:37:5 + --> tests/ui/from_str_radix_10.rs:38:5 | LL | u16::from_str_radix(&("10".to_owned() + "5"), 10)?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `("10".to_owned() + "5").parse::()` error: this call to `from_str_radix` can be replaced with a call to `str::parse` - --> tests/ui/from_str_radix_10.rs:39:5 + --> tests/ui/from_str_radix_10.rs:40:5 | LL | i128::from_str_radix(Test + Test, 10)?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(Test + Test).parse::()` error: this call to `from_str_radix` can be replaced with a call to `str::parse` - --> tests/ui/from_str_radix_10.rs:43:5 + --> tests/ui/from_str_radix_10.rs:44:5 | LL | i32::from_str_radix(string, 10)?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `string.parse::()` error: this call to `from_str_radix` can be replaced with a call to `str::parse` - --> tests/ui/from_str_radix_10.rs:47:5 + --> tests/ui/from_str_radix_10.rs:48:5 | LL | i32::from_str_radix(&stringier, 10)?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `stringier.parse::()` diff --git a/tests/ui/match_same_arms.stderr b/tests/ui/match_same_arms.stderr index a926570b60ad..3c0382767c3f 100644 --- a/tests/ui/match_same_arms.stderr +++ b/tests/ui/match_same_arms.stderr @@ -2,7 +2,7 @@ error: this match arm has an identical body to the `_` wildcard arm --> tests/ui/match_same_arms.rs:12:9 | LL | Abc::A => 0, - | ^^^^^^^^^^^ help: try removing the arm + | ^^^^^^^^^^^^^ help: try removing the arm | = help: or try changing either arm body note: `_` wildcard arm here @@ -17,106 +17,114 @@ error: this match arm has an identical body to another arm --> tests/ui/match_same_arms.rs:18:9 | LL | (1, .., 3) => 42, - | ----------^^^^^^ - | | - | help: try merging the arm patterns: `(1, .., 3) | (.., 3)` + | ^^^^^^^^^^^^^^^^ | - = help: or try changing either arm body -note: other arm here - --> tests/ui/match_same_arms.rs:19:9 + = help: try changing either arm body +help: or try merging the arm patterns + | +LL | (1, .., 3) | (.., 3) => 42, + | ~~~~~~~~~~~~~~~~~~~~ +help: and remove this obsolete arm + | +LL - (.., 3) => 42, | -LL | (.., 3) => 42, - | ^^^^^^^^^^^^^ error: this match arm has an identical body to another arm --> tests/ui/match_same_arms.rs:25:9 | LL | 51 => 1, - | --^^^^^ - | | - | help: try merging the arm patterns: `51 | 42` - | - = help: or try changing either arm body -note: other arm here - --> tests/ui/match_same_arms.rs:24:9 - | -LL | 42 => 1, | ^^^^^^^ + | + = help: try changing either arm body +help: or try merging the arm patterns + | +LL | 51 | 42 => 1, + | ~~~~~~~ +help: and remove this obsolete arm + | +LL - 42 => 1, + | error: this match arm has an identical body to another arm --> tests/ui/match_same_arms.rs:26:9 | LL | 41 => 2, - | --^^^^^ - | | - | help: try merging the arm patterns: `41 | 52` - | - = help: or try changing either arm body -note: other arm here - --> tests/ui/match_same_arms.rs:27:9 - | -LL | 52 => 2, | ^^^^^^^ + | + = help: try changing either arm body +help: or try merging the arm patterns + | +LL | 41 | 52 => 2, + | ~~~~~~~ +help: and remove this obsolete arm + | +LL - 52 => 2, + | error: this match arm has an identical body to another arm --> tests/ui/match_same_arms.rs:33:9 | LL | 2 => 2, - | -^^^^^ - | | - | help: try merging the arm patterns: `2 | 1` - | - = help: or try changing either arm body -note: other arm here - --> tests/ui/match_same_arms.rs:32:9 - | -LL | 1 => 2, | ^^^^^^ + | + = help: try changing either arm body +help: or try merging the arm patterns + | +LL | 2 | 1 => 2, + | ~~~~~ +help: and remove this obsolete arm + | +LL - 1 => 2, + | error: this match arm has an identical body to another arm --> tests/ui/match_same_arms.rs:35:9 | LL | 3 => 2, - | -^^^^^ - | | - | help: try merging the arm patterns: `3 | 1` - | - = help: or try changing either arm body -note: other arm here - --> tests/ui/match_same_arms.rs:32:9 - | -LL | 1 => 2, | ^^^^^^ + | + = help: try changing either arm body +help: or try merging the arm patterns + | +LL | 3 | 1 => 2, + | ~~~~~ +help: and remove this obsolete arm + | +LL - 1 => 2, + | error: this match arm has an identical body to another arm --> tests/ui/match_same_arms.rs:33:9 | LL | 2 => 2, - | -^^^^^ - | | - | help: try merging the arm patterns: `2 | 3` - | - = help: or try changing either arm body -note: other arm here - --> tests/ui/match_same_arms.rs:35:9 - | -LL | 3 => 2, | ^^^^^^ + | + = help: try changing either arm body +help: or try merging the arm patterns + | +LL | 2 | 3 => 2, + | ~~~~~ +help: and remove this obsolete arm + | +LL - 3 => 2, +LL + + | error: this match arm has an identical body to another arm --> tests/ui/match_same_arms.rs:52:17 | LL | CommandInfo::External { name, .. } => name.to_string(), - | ----------------------------------^^^^^^^^^^^^^^^^^^^^ - | | - | help: try merging the arm patterns: `CommandInfo::External { name, .. } | CommandInfo::BuiltIn { name, .. }` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: or try changing either arm body -note: other arm here - --> tests/ui/match_same_arms.rs:51:17 + = help: try changing either arm body +help: or try merging the arm patterns + | +LL | CommandInfo::External { name, .. } | CommandInfo::BuiltIn { name, .. } => name.to_string(), + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +help: and remove this obsolete arm + | +LL - CommandInfo::BuiltIn { name, .. } => name.to_string(), | -LL | CommandInfo::BuiltIn { name, .. } => name.to_string(), - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 8 previous errors diff --git a/tests/ui/match_same_arms2.fixed b/tests/ui/match_same_arms2.fixed new file mode 100644 index 000000000000..fba0cf33b3c2 --- /dev/null +++ b/tests/ui/match_same_arms2.fixed @@ -0,0 +1,241 @@ +#![warn(clippy::match_same_arms)] +#![allow( + clippy::disallowed_names, + clippy::diverging_sub_expression, + clippy::uninlined_format_args, + clippy::match_single_binding, + clippy::match_like_matches_macro +)] +fn bar(_: T) {} +fn foo() -> bool { + unimplemented!() +} + +fn match_same_arms() { + let _ = match 42 { + _ => { + foo(); + let mut a = 42 + [23].len() as i32; + if true { + a += 7; + } + a = -31 - a; + a + }, + }; + //~^^^^^^^^^^^^^^^^^^^ ERROR: this match arm has an identical body to the `_` wildcard arm + + let _ = match 42 { + 51 | 42 => foo(), //~ ERROR: this match arm has an identical body to another arm + _ => true, + }; + + let _ = match Some(42) { + None | Some(_) => 24, //~ ERROR: this match arm has an identical body to another arm + }; + + let _ = match Some(42) { + Some(foo) => 24, + None => 24, + }; + + let _ = match Some(42) { + Some(42) => 24, + Some(a) => 24, // bindings are different + None => 0, + }; + + let _ = match Some(42) { + Some(a) if a > 0 => 24, + Some(a) => 24, // one arm has a guard + None => 0, + }; + + match (Some(42), Some(42)) { + (None, Some(a)) | (Some(a), None) => bar(a), //~ ERROR: this match arm has an identical body to another arm + _ => (), + } + + // No warning because guards are different + let _ = match Some(42) { + Some(a) if a == 42 => a, + Some(a) if a == 24 => a, + Some(_) => 24, + None => 0, + }; + + let _ = match (Some(42), Some(42)) { + (None, Some(a)) | (Some(a), None) if a == 42 => a, //~ ERROR: this match arm has an identical body to another arm + _ => 0, + }; + + match (Some(42), Some(42)) { + (Some(a), ..) | (.., Some(a)) => bar(a), //~ ERROR: this match arm has an identical body to another arm + _ => (), + } + + let _ = match Some(()) { + Some(()) => 0.0, + None => -0.0, + }; + + match (Some(42), Some("")) { + (Some(a), None) => bar(a), + (None, Some(a)) => bar(a), // bindings have different types + _ => (), + } + + let x: Result = Ok(3); + + // No warning because of the guard. + match x { + Ok(x) if x * x == 64 => println!("ok"), + Ok(_) => println!("ok"), + Err(_) => println!("err"), + } + + // This used to be a false positive; see issue #1996. + match x { + Ok(3) => println!("ok"), + Ok(x) if x * x == 64 => println!("ok 64"), + Ok(_) => println!("ok"), + Err(_) => println!("err"), + } + + match (x, Some(1i32)) { + (Ok(x), Some(_)) | (Ok(_), Some(x)) => println!("ok {}", x), //~ ERROR: this match arm has an identical body to another arm + _ => println!("err"), + } + + // No warning; different types for `x`. + match (x, Some(1.0f64)) { + (Ok(x), Some(_)) => println!("ok {}", x), + (Ok(_), Some(x)) => println!("ok {}", x), + _ => println!("err"), + } + + // False negative #2251. + match x { + Ok(_tmp) => println!("ok"), + Ok(_) | Ok(3) => println!("ok"), //~ ERROR: this match arm has an identical body to another arm + Err(_) => { + unreachable!(); + }, + } + + // False positive #1390 + macro_rules! empty { + ($e:expr) => {}; + } + match 0 { + 0 => { + empty!(0); + }, + 1 => { + empty!(1); + }, + x => { + empty!(x); + }, + }; + + // still lint if the tokens are the same + match 0 { + 1 | 0 => { + empty!(0); + }, + x => { + empty!(x); + }, + } + //~^^^^^^^ ERROR: this match arm has an identical body to another arm + + match_expr_like_matches_macro_priority(); +} + +fn match_expr_like_matches_macro_priority() { + enum E { + A, + B, + C, + } + let x = E::A; + let _ans = match x { + E::A => false, + E::B => false, + _ => true, + }; +} + +fn main() { + let _ = match Some(0) { + Some(0) => 0, + Some(1) => 1, + #[cfg(feature = "foo")] + Some(2) => 2, + _ => 1, + }; + + enum Foo { + X(u32), + Y(u32), + Z(u32), + } + + // Don't lint. `Foo::X(0)` and `Foo::Z(_)` overlap with the arm in between. + let _ = match Foo::X(0) { + Foo::X(0) => 1, + Foo::X(_) | Foo::Y(_) | Foo::Z(0) => 2, + Foo::Z(_) => 1, + _ => 0, + }; + + // Suggest moving `Foo::Z(_)` up. + let _ = match Foo::X(0) { + Foo::X(0) | Foo::Z(_) => 1, //~ ERROR: this match arm has an identical body to another arm + Foo::X(_) | Foo::Y(_) => 2, + _ => 0, + }; + + // Suggest moving `Foo::X(0)` down. + let _ = match Foo::X(0) { + Foo::Y(_) | Foo::Z(0) => 2, + Foo::Z(_) | Foo::X(0) => 1, //~ ERROR: this match arm has an identical body to another arm + _ => 0, + }; + + // Don't lint. + let _ = match 0 { + -2 => 1, + -5..=50 => 2, + -150..=88 => 1, + _ => 3, + }; + + struct Bar { + x: u32, + y: u32, + z: u32, + } + + // Lint. + let _ = match None { + Some(Bar { y: 10, z: 0, .. }) => 2, + None => 50, + Some(Bar { y: 0, x: 5, .. }) | Some(Bar { x: 0, y: 5, .. }) => 1, //~ ERROR: this match arm has an identical body to another arm + _ => 200, + }; + + let _ = match 0 { + 0 => todo!(), + 1 => todo!(), + 2 => core::convert::identity::(todo!()), + 3 => core::convert::identity::(todo!()), + _ => 5, + }; + + let _ = match 0 { + 1 | 0 => cfg!(not_enable), + _ => false, + }; +} diff --git a/tests/ui/match_same_arms2.rs b/tests/ui/match_same_arms2.rs index 85ad0962eb4b..8a4e3b325bbf 100644 --- a/tests/ui/match_same_arms2.rs +++ b/tests/ui/match_same_arms2.rs @@ -2,9 +2,10 @@ #![allow( clippy::disallowed_names, clippy::diverging_sub_expression, - clippy::uninlined_format_args + clippy::uninlined_format_args, + clippy::match_single_binding, + clippy::match_like_matches_macro )] -//@no-rustfix fn bar(_: T) {} fn foo() -> bool { unimplemented!() diff --git a/tests/ui/match_same_arms2.stderr b/tests/ui/match_same_arms2.stderr index f4c38c1af897..3d15176ccf99 100644 --- a/tests/ui/match_same_arms2.stderr +++ b/tests/ui/match_same_arms2.stderr @@ -1,18 +1,18 @@ error: this match arm has an identical body to the `_` wildcard arm - --> tests/ui/match_same_arms2.rs:15:9 + --> tests/ui/match_same_arms2.rs:16:9 | LL | / 42 => { LL | | foo(); LL | | let mut a = 42 + [23].len() as i32; LL | | if true { ... | -LL | | a LL | | }, - | |_________^ help: try removing the arm +LL | | _ => { + | |________^ help: try removing the arm | = help: or try changing either arm body note: `_` wildcard arm here - --> tests/ui/match_same_arms2.rs:24:9 + --> tests/ui/match_same_arms2.rs:25:9 | LL | / _ => { LL | | foo(); @@ -26,203 +26,200 @@ LL | | }, = help: to override `-D warnings` add `#[allow(clippy::match_same_arms)]` error: this match arm has an identical body to another arm - --> tests/ui/match_same_arms2.rs:38:9 + --> tests/ui/match_same_arms2.rs:39:9 | LL | 51 => foo(), - | --^^^^^^^^^ - | | - | help: try merging the arm patterns: `51 | 42` - | - = help: or try changing either arm body -note: other arm here - --> tests/ui/match_same_arms2.rs:37:9 - | -LL | 42 => foo(), | ^^^^^^^^^^^ + | + = help: try changing either arm body +help: or try merging the arm patterns + | +LL | 51 | 42 => foo(), + | ~~~~~~~ +help: and remove this obsolete arm + | +LL - 42 => foo(), + | error: this match arm has an identical body to another arm - --> tests/ui/match_same_arms2.rs:44:9 + --> tests/ui/match_same_arms2.rs:45:9 | LL | None => 24, - | ----^^^^^^ - | | - | help: try merging the arm patterns: `None | Some(_)` + | ^^^^^^^^^^ | - = help: or try changing either arm body -note: other arm here - --> tests/ui/match_same_arms2.rs:43:9 + = help: try changing either arm body +help: or try merging the arm patterns + | +LL | None | Some(_) => 24, + | ~~~~~~~~~~~~~~ +help: and remove this obsolete arm + | +LL - Some(_) => 24, | -LL | Some(_) => 24, - | ^^^^^^^^^^^^^ error: this match arm has an identical body to another arm - --> tests/ui/match_same_arms2.rs:66:9 + --> tests/ui/match_same_arms2.rs:67:9 | LL | (None, Some(a)) => bar(a), - | ---------------^^^^^^^^^^ - | | - | help: try merging the arm patterns: `(None, Some(a)) | (Some(a), None)` - | - = help: or try changing either arm body -note: other arm here - --> tests/ui/match_same_arms2.rs:65:9 - | -LL | (Some(a), None) => bar(a), | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try changing either arm body +help: or try merging the arm patterns + | +LL | (None, Some(a)) | (Some(a), None) => bar(a), + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +help: and remove this obsolete arm + | +LL - (Some(a), None) => bar(a), + | error: this match arm has an identical body to another arm - --> tests/ui/match_same_arms2.rs:80:9 + --> tests/ui/match_same_arms2.rs:81:9 | LL | (None, Some(a)) if a == 42 => a, - | ---------------^^^^^^^^^^^^^^^^ - | | - | help: try merging the arm patterns: `(None, Some(a)) | (Some(a), None)` - | - = help: or try changing either arm body -note: other arm here - --> tests/ui/match_same_arms2.rs:79:9 - | -LL | (Some(a), None) if a == 42 => a, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try changing either arm body +help: or try merging the arm patterns + | +LL | (None, Some(a)) | (Some(a), None) if a == 42 => a, + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +help: and remove this obsolete arm + | +LL - (Some(a), None) if a == 42 => a, + | error: this match arm has an identical body to another arm - --> tests/ui/match_same_arms2.rs:85:9 - | -LL | (Some(a), ..) => bar(a), - | -------------^^^^^^^^^^ - | | - | help: try merging the arm patterns: `(Some(a), ..) | (.., Some(a))` - | - = help: or try changing either arm body -note: other arm here --> tests/ui/match_same_arms2.rs:86:9 | -LL | (.., Some(a)) => bar(a), +LL | (Some(a), ..) => bar(a), | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try changing either arm body +help: or try merging the arm patterns + | +LL | (Some(a), ..) | (.., Some(a)) => bar(a), + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +help: and remove this obsolete arm + | +LL - (.., Some(a)) => bar(a), + | error: this match arm has an identical body to another arm - --> tests/ui/match_same_arms2.rs:119:9 - | -LL | (Ok(x), Some(_)) => println!("ok {}", x), - | ----------------^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | help: try merging the arm patterns: `(Ok(x), Some(_)) | (Ok(_), Some(x))` - | - = help: or try changing either arm body -note: other arm here --> tests/ui/match_same_arms2.rs:120:9 | -LL | (Ok(_), Some(x)) => println!("ok {}", x), +LL | (Ok(x), Some(_)) => println!("ok {}", x), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try changing either arm body +help: or try merging the arm patterns + | +LL | (Ok(x), Some(_)) | (Ok(_), Some(x)) => println!("ok {}", x), + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +help: and remove this obsolete arm + | +LL - (Ok(_), Some(x)) => println!("ok {}", x), + | error: this match arm has an identical body to another arm - --> tests/ui/match_same_arms2.rs:135:9 + --> tests/ui/match_same_arms2.rs:136:9 | LL | Ok(_) => println!("ok"), - | -----^^^^^^^^^^^^^^^^^^ - | | - | help: try merging the arm patterns: `Ok(_) | Ok(3)` - | - = help: or try changing either arm body -note: other arm here - --> tests/ui/match_same_arms2.rs:134:9 - | -LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try changing either arm body +help: or try merging the arm patterns + | +LL | Ok(_) | Ok(3) => println!("ok"), + | ~~~~~~~~~~~~~ +help: and remove this obsolete arm + | +LL - Ok(3) => println!("ok"), + | error: this match arm has an identical body to another arm - --> tests/ui/match_same_arms2.rs:162:9 + --> tests/ui/match_same_arms2.rs:163:9 | -LL | 1 => { - | ^ help: try merging the arm patterns: `1 | 0` - | _________| - | | +LL | / 1 => { LL | | empty!(0); LL | | }, | |_________^ | - = help: or try changing either arm body -note: other arm here - --> tests/ui/match_same_arms2.rs:159:9 + = help: try changing either arm body +help: or try merging the arm patterns | -LL | / 0 => { -LL | | empty!(0); -LL | | }, - | |_________^ - -error: match expression looks like `matches!` macro - --> tests/ui/match_same_arms2.rs:181:16 +LL | 1 | 0 => { + | ~~~~~ +help: and remove this obsolete arm | -LL | let _ans = match x { - | ________________^ -LL | | E::A => false, -LL | | E::B => false, -LL | | _ => true, -LL | | }; - | |_____^ help: try: `!matches!(x, E::A | E::B)` +LL - 0 => { +LL - empty!(0); +LL - }, | - = note: `-D clippy::match-like-matches-macro` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::match_like_matches_macro)]` error: this match arm has an identical body to another arm - --> tests/ui/match_same_arms2.rs:213:9 - | -LL | Foo::X(0) => 1, - | ---------^^^^^ - | | - | help: try merging the arm patterns: `Foo::X(0) | Foo::Z(_)` - | - = help: or try changing either arm body -note: other arm here - --> tests/ui/match_same_arms2.rs:215:9 - | -LL | Foo::Z(_) => 1, - | ^^^^^^^^^^^^^^ - -error: this match arm has an identical body to another arm - --> tests/ui/match_same_arms2.rs:223:9 - | -LL | Foo::Z(_) => 1, - | ---------^^^^^ - | | - | help: try merging the arm patterns: `Foo::Z(_) | Foo::X(0)` - | - = help: or try changing either arm body -note: other arm here - --> tests/ui/match_same_arms2.rs:221:9 + --> tests/ui/match_same_arms2.rs:214:9 | LL | Foo::X(0) => 1, | ^^^^^^^^^^^^^^ + | + = help: try changing either arm body +help: or try merging the arm patterns + | +LL | Foo::X(0) | Foo::Z(_) => 1, + | ~~~~~~~~~~~~~~~~~~~~~ +help: and remove this obsolete arm + | +LL - Foo::Z(_) => 1, + | error: this match arm has an identical body to another arm - --> tests/ui/match_same_arms2.rs:246:9 + --> tests/ui/match_same_arms2.rs:224:9 + | +LL | Foo::Z(_) => 1, + | ^^^^^^^^^^^^^^ + | + = help: try changing either arm body +help: or try merging the arm patterns + | +LL | Foo::Z(_) | Foo::X(0) => 1, + | ~~~~~~~~~~~~~~~~~~~~~ +help: and remove this obsolete arm + | +LL - Foo::X(0) => 1, + | + +error: this match arm has an identical body to another arm + --> tests/ui/match_same_arms2.rs:247:9 | LL | Some(Bar { y: 0, x: 5, .. }) => 1, - | ----------------------------^^^^^ - | | - | help: try merging the arm patterns: `Some(Bar { y: 0, x: 5, .. }) | Some(Bar { x: 0, y: 5, .. })` - | - = help: or try changing either arm body -note: other arm here - --> tests/ui/match_same_arms2.rs:243:9 - | -LL | Some(Bar { x: 0, y: 5, .. }) => 1, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try changing either arm body +help: or try merging the arm patterns + | +LL | Some(Bar { y: 0, x: 5, .. }) | Some(Bar { x: 0, y: 5, .. }) => 1, + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +help: and remove this obsolete arm + | +LL - Some(Bar { x: 0, y: 5, .. }) => 1, + | error: this match arm has an identical body to another arm - --> tests/ui/match_same_arms2.rs:260:9 + --> tests/ui/match_same_arms2.rs:261:9 | LL | 1 => cfg!(not_enable), - | -^^^^^^^^^^^^^^^^^^^^ - | | - | help: try merging the arm patterns: `1 | 0` - | - = help: or try changing either arm body -note: other arm here - --> tests/ui/match_same_arms2.rs:259:9 - | -LL | 0 => cfg!(not_enable), | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: try changing either arm body +help: or try merging the arm patterns + | +LL | 1 | 0 => cfg!(not_enable), + | ~~~~~ +help: and remove this obsolete arm + | +LL - 0 => cfg!(not_enable), + | -error: aborting due to 14 previous errors +error: aborting due to 13 previous errors diff --git a/tests/ui/match_same_arms_non_exhaustive.fixed b/tests/ui/match_same_arms_non_exhaustive.fixed new file mode 100644 index 000000000000..804c0a869a9f --- /dev/null +++ b/tests/ui/match_same_arms_non_exhaustive.fixed @@ -0,0 +1,61 @@ +#![feature(non_exhaustive_omitted_patterns_lint)] +#![warn(clippy::match_same_arms)] +#![no_main] +use std::sync::atomic::Ordering; // #[non_exhaustive] enum + +fn repeat() -> ! { + panic!() +} + +pub fn f(x: Ordering) { + #[deny(non_exhaustive_omitted_patterns)] + match x { + Ordering::Relaxed => println!("relaxed"), + Ordering::Release => println!("release"), + Ordering::Acquire => println!("acquire"), + Ordering::AcqRel | Ordering::SeqCst => repeat(), + _ => repeat(), + } +} + +mod f { + #![deny(non_exhaustive_omitted_patterns)] + + use super::*; + + pub fn f(x: Ordering) { + match x { + Ordering::Relaxed => println!("relaxed"), + Ordering::Release => println!("release"), + Ordering::Acquire => println!("acquire"), + Ordering::AcqRel | Ordering::SeqCst => repeat(), + _ => repeat(), + } + } +} + +// Below should still lint + +pub fn g(x: Ordering) { + match x { + Ordering::Relaxed => println!("relaxed"), + Ordering::Release => println!("release"), + Ordering::Acquire => println!("acquire"), + //~^ ERROR: this match arm has an identical body to the `_` wildcard arm + _ => repeat(), + } +} + +mod g { + use super::*; + + pub fn g(x: Ordering) { + match x { + Ordering::Relaxed => println!("relaxed"), + Ordering::Release => println!("release"), + Ordering::Acquire => println!("acquire"), + //~^ ERROR: this match arm has an identical body to the `_` wildcard arm + _ => repeat(), + } + } +} diff --git a/tests/ui/match_same_arms_non_exhaustive.rs b/tests/ui/match_same_arms_non_exhaustive.rs index 5c277f925a8f..e50663932a1a 100644 --- a/tests/ui/match_same_arms_non_exhaustive.rs +++ b/tests/ui/match_same_arms_non_exhaustive.rs @@ -1,7 +1,6 @@ #![feature(non_exhaustive_omitted_patterns_lint)] #![warn(clippy::match_same_arms)] #![no_main] -//@no-rustfix use std::sync::atomic::Ordering; // #[non_exhaustive] enum fn repeat() -> ! { diff --git a/tests/ui/match_same_arms_non_exhaustive.stderr b/tests/ui/match_same_arms_non_exhaustive.stderr index cf2a75354e15..aa7f8c95dce8 100644 --- a/tests/ui/match_same_arms_non_exhaustive.stderr +++ b/tests/ui/match_same_arms_non_exhaustive.stderr @@ -1,12 +1,13 @@ error: this match arm has an identical body to the `_` wildcard arm - --> tests/ui/match_same_arms_non_exhaustive.rs:45:9 + --> tests/ui/match_same_arms_non_exhaustive.rs:44:9 | -LL | Ordering::AcqRel | Ordering::SeqCst => repeat(), - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try removing the arm +LL | / Ordering::AcqRel | Ordering::SeqCst => repeat(), +LL | | + | |________^ help: try removing the arm | = help: or try changing either arm body note: `_` wildcard arm here - --> tests/ui/match_same_arms_non_exhaustive.rs:47:9 + --> tests/ui/match_same_arms_non_exhaustive.rs:46:9 | LL | _ => repeat(), | ^^^^^^^^^^^^^ @@ -14,14 +15,15 @@ LL | _ => repeat(), = help: to override `-D warnings` add `#[allow(clippy::match_same_arms)]` error: this match arm has an identical body to the `_` wildcard arm - --> tests/ui/match_same_arms_non_exhaustive.rs:59:13 + --> tests/ui/match_same_arms_non_exhaustive.rs:58:13 | -LL | Ordering::AcqRel | Ordering::SeqCst => repeat(), - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try removing the arm +LL | / Ordering::AcqRel | Ordering::SeqCst => repeat(), +LL | | + | |____________^ help: try removing the arm | = help: or try changing either arm body note: `_` wildcard arm here - --> tests/ui/match_same_arms_non_exhaustive.rs:61:13 + --> tests/ui/match_same_arms_non_exhaustive.rs:60:13 | LL | _ => repeat(), | ^^^^^^^^^^^^^ diff --git a/tests/ui/missing_const_for_fn/cant_be_const.rs b/tests/ui/missing_const_for_fn/cant_be_const.rs index d026e009684a..2750e0cdf3f7 100644 --- a/tests/ui/missing_const_for_fn/cant_be_const.rs +++ b/tests/ui/missing_const_for_fn/cant_be_const.rs @@ -161,7 +161,23 @@ union U { f: u32, } -// Do not lint because accessing union fields from const functions is unstable +// Do not lint because accessing union fields from const functions is unstable in 1.55 +#[clippy::msrv = "1.55"] fn h(u: U) -> u32 { unsafe { u.f } } + +mod msrv { + struct Foo(*const u8, *mut u8); + + impl Foo { + #[clippy::msrv = "1.57"] + fn deref_ptr_cannot_be_const(self) -> usize { + unsafe { *self.0 as usize } + } + #[clippy::msrv = "1.58"] + fn deref_mut_ptr_cannot_be_const(self) -> usize { + unsafe { *self.1 as usize } + } + } +} diff --git a/tests/ui/missing_const_for_fn/could_be_const.rs b/tests/ui/missing_const_for_fn/could_be_const.rs index 12a8320c8f32..06dbbeb31c0d 100644 --- a/tests/ui/missing_const_for_fn/could_be_const.rs +++ b/tests/ui/missing_const_for_fn/could_be_const.rs @@ -113,3 +113,31 @@ impl const Drop for D { // Lint this, since it can be dropped in const contexts // FIXME(effects) fn d(this: D) {} + +mod msrv { + struct Foo(*const u8, &'static u8); + + impl Foo { + #[clippy::msrv = "1.58"] + fn deref_ptr_can_be_const(self) -> usize { + //~^ ERROR: this could be a `const fn` + unsafe { *self.0 as usize } + } + + fn deref_copied_val(self) -> usize { + //~^ ERROR: this could be a `const fn` + *self.1 as usize + } + } + + union Bar { + val: u8, + } + + #[clippy::msrv = "1.56"] + fn union_access_can_be_const() { + //~^ ERROR: this could be a `const fn` + let bar = Bar { val: 1 }; + let _ = unsafe { bar.val }; + } +} diff --git a/tests/ui/missing_const_for_fn/could_be_const.stderr b/tests/ui/missing_const_for_fn/could_be_const.stderr index 082459fd8212..b2cade305637 100644 --- a/tests/ui/missing_const_for_fn/could_be_const.stderr +++ b/tests/ui/missing_const_for_fn/could_be_const.stderr @@ -102,5 +102,33 @@ LL | | 46 LL | | } | |_^ -error: aborting due to 11 previous errors +error: this could be a `const fn` + --> tests/ui/missing_const_for_fn/could_be_const.rs:122:9 + | +LL | / fn deref_ptr_can_be_const(self) -> usize { +LL | | +LL | | unsafe { *self.0 as usize } +LL | | } + | |_________^ + +error: this could be a `const fn` + --> tests/ui/missing_const_for_fn/could_be_const.rs:127:9 + | +LL | / fn deref_copied_val(self) -> usize { +LL | | +LL | | *self.1 as usize +LL | | } + | |_________^ + +error: this could be a `const fn` + --> tests/ui/missing_const_for_fn/could_be_const.rs:138:5 + | +LL | / fn union_access_can_be_const() { +LL | | +LL | | let bar = Bar { val: 1 }; +LL | | let _ = unsafe { bar.val }; +LL | | } + | |_____^ + +error: aborting due to 14 previous errors diff --git a/tests/ui/missing_panics_doc.rs b/tests/ui/missing_panics_doc.rs index 0e1533fc1ab1..b0fa8e988598 100644 --- a/tests/ui/missing_panics_doc.rs +++ b/tests/ui/missing_panics_doc.rs @@ -191,3 +191,11 @@ fn from_declared_macro_should_lint_at_macrosite() { // Not here. some_macro_that_panics!() } + +pub fn issue_12760() { + const { + if N == 0 { + panic!(); + } + } +} diff --git a/tests/ui/needless_borrows_for_generic_args.fixed b/tests/ui/needless_borrows_for_generic_args.fixed index bd7a9a0b9840..5478372cbe00 100644 --- a/tests/ui/needless_borrows_for_generic_args.fixed +++ b/tests/ui/needless_borrows_for_generic_args.fixed @@ -141,8 +141,8 @@ fn main() { let f = |arg| { let loc = "loc".to_owned(); let _ = std::fs::write("x", &env); // Don't lint. In environment - let _ = std::fs::write("x", arg); - let _ = std::fs::write("x", loc); + let _ = std::fs::write("x", &arg); + let _ = std::fs::write("x", &loc); }; let _ = std::fs::write("x", &env); // Don't lint. Borrowed by `f` f(arg); @@ -158,13 +158,13 @@ fn main() { fn f(_: impl Debug) {} let x = X; - f(&x); // Don't lint. Has significant drop + f(&x); // Don't lint, not copy, passed by a reference to a variable } { fn f(_: impl AsRef) {} let x = String::new(); - f(x); + f(&x); } { fn f(_: impl AsRef) {} @@ -299,4 +299,38 @@ fn main() { check_str(&owner.0); // Don't lint. `owner` can't be partially moved because it impl Drop } } + { + #[derive(Debug)] + struct X(Vec); + + fn f(_: impl Debug) {} + + let x = X(vec![]); + f(&x); // Don't lint, makes x unavailable later + } + { + #[derive(Debug)] + struct X; + + impl Drop for X { + fn drop(&mut self) {} + } + + fn f(_: impl Debug) {} + + #[derive(Debug)] + struct Y(X); + + let y = Y(X); + f(&y); // Don't lint. Not copy, passed by a reference to value + } + { + fn f(_: impl AsRef) {} + let x = String::new(); + f(&x); // Don't lint, not a copy, makes it unavailable later + f(String::new()); // Lint, makes no difference + let y = "".to_owned(); + f(&y); // Don't lint + f("".to_owned()); // Lint + } } diff --git a/tests/ui/needless_borrows_for_generic_args.rs b/tests/ui/needless_borrows_for_generic_args.rs index 5cfd4ce30cc5..2643815d939b 100644 --- a/tests/ui/needless_borrows_for_generic_args.rs +++ b/tests/ui/needless_borrows_for_generic_args.rs @@ -158,7 +158,7 @@ fn main() { fn f(_: impl Debug) {} let x = X; - f(&x); // Don't lint. Has significant drop + f(&x); // Don't lint, not copy, passed by a reference to a variable } { fn f(_: impl AsRef) {} @@ -299,4 +299,38 @@ fn main() { check_str(&owner.0); // Don't lint. `owner` can't be partially moved because it impl Drop } } + { + #[derive(Debug)] + struct X(Vec); + + fn f(_: impl Debug) {} + + let x = X(vec![]); + f(&x); // Don't lint, makes x unavailable later + } + { + #[derive(Debug)] + struct X; + + impl Drop for X { + fn drop(&mut self) {} + } + + fn f(_: impl Debug) {} + + #[derive(Debug)] + struct Y(X); + + let y = Y(X); + f(&y); // Don't lint. Not copy, passed by a reference to value + } + { + fn f(_: impl AsRef) {} + let x = String::new(); + f(&x); // Don't lint, not a copy, makes it unavailable later + f(&String::new()); // Lint, makes no difference + let y = "".to_owned(); + f(&y); // Don't lint + f(&"".to_owned()); // Lint + } } diff --git a/tests/ui/needless_borrows_for_generic_args.stderr b/tests/ui/needless_borrows_for_generic_args.stderr index 83c076f8d863..fba0755d14b5 100644 --- a/tests/ui/needless_borrows_for_generic_args.stderr +++ b/tests/ui/needless_borrows_for_generic_args.stderr @@ -49,29 +49,23 @@ error: the borrowed expression implements the required traits LL | let _ = Command::new("ls").args(&["-a", "-l"]).status().unwrap(); | ^^^^^^^^^^^^^ help: change this to: `["-a", "-l"]` -error: the borrowed expression implements the required traits - --> tests/ui/needless_borrows_for_generic_args.rs:144:41 - | -LL | let _ = std::fs::write("x", &arg); - | ^^^^ help: change this to: `arg` - -error: the borrowed expression implements the required traits - --> tests/ui/needless_borrows_for_generic_args.rs:145:41 - | -LL | let _ = std::fs::write("x", &loc); - | ^^^^ help: change this to: `loc` - -error: the borrowed expression implements the required traits - --> tests/ui/needless_borrows_for_generic_args.rs:167:11 - | -LL | f(&x); - | ^^ help: change this to: `x` - error: the borrowed expression implements the required traits --> tests/ui/needless_borrows_for_generic_args.rs:247:13 | LL | foo(&a); | ^^ help: change this to: `a` -error: aborting due to 12 previous errors +error: the borrowed expression implements the required traits + --> tests/ui/needless_borrows_for_generic_args.rs:331:11 + | +LL | f(&String::new()); // Lint, makes no difference + | ^^^^^^^^^^^^^^ help: change this to: `String::new()` + +error: the borrowed expression implements the required traits + --> tests/ui/needless_borrows_for_generic_args.rs:334:11 + | +LL | f(&"".to_owned()); // Lint + | ^^^^^^^^^^^^^^ help: change this to: `"".to_owned()` + +error: aborting due to 11 previous errors diff --git a/tests/ui/needless_late_init.stderr b/tests/ui/needless_late_init.stderr index 1695784030d0..ce64861fa40a 100644 --- a/tests/ui/needless_late_init.stderr +++ b/tests/ui/needless_late_init.stderr @@ -8,10 +8,11 @@ LL | a = "zero"; | = note: `-D clippy::needless-late-init` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::needless_late_init)]` -help: declare `a` here +help: move the declaration `a` here + | +LL ~ +LL ~ let a = "zero"; | -LL | let a = "zero"; - | ~~~~~ error: unneeded late initialization --> tests/ui/needless_late_init.rs:30:5 @@ -22,10 +23,12 @@ LL | let c; LL | b = 1; | ^^^^^ initialised here | -help: declare `b` here +help: move the declaration `b` here + | +LL ~ +LL | let c; +LL ~ let b = 1; | -LL | let b = 1; - | ~~~~~ error: unneeded late initialization --> tests/ui/needless_late_init.rs:31:5 @@ -36,10 +39,12 @@ LL | b = 1; LL | c = 2; | ^^^^^ initialised here | -help: declare `c` here +help: move the declaration `c` here + | +LL ~ +LL | b = 1; +LL ~ let c = 2; | -LL | let c = 2; - | ~~~~~ error: unneeded late initialization --> tests/ui/needless_late_init.rs:35:5 @@ -49,10 +54,11 @@ LL | let d: usize; LL | d = 1; | ^^^^^ initialised here | -help: declare `d` here +help: move the declaration `d` here + | +LL ~ +LL ~ let d: usize = 1; | -LL | let d: usize = 1; - | ~~~~~~~~~~~~ error: unneeded late initialization --> tests/ui/needless_late_init.rs:38:5 @@ -62,10 +68,11 @@ LL | let e; LL | e = format!("{}", d); | ^^^^^^^^^^^^^^^^^^^^ initialised here | -help: declare `e` here +help: move the declaration `e` here + | +LL ~ +LL ~ let e = format!("{}", d); | -LL | let e = format!("{}", d); - | ~~~~~ error: unneeded late initialization --> tests/ui/needless_late_init.rs:43:5 @@ -73,20 +80,17 @@ error: unneeded late initialization LL | let a; | ^^^^^^ | -help: declare `a` here - | -LL | let a = match n { - | +++++++ -help: remove the assignments from the `match` arms +help: move the declaration `a` here and remove the assignments from the `match` arms | +LL ~ +LL | let n = 1; +LL ~ let a = match n { LL ~ 1 => "one", LL | _ => { LL ~ "two" +LL | }, +LL ~ }; | -help: add a semicolon after the `match` expression - | -LL | }; - | + error: unneeded late initialization --> tests/ui/needless_late_init.rs:52:5 @@ -94,20 +98,15 @@ error: unneeded late initialization LL | let b; | ^^^^^^ | -help: declare `b` here - | -LL | let b = if n == 3 { - | +++++++ -help: remove the assignments from the branches +help: move the declaration `b` here and remove the assignments from the branches | +LL ~ +LL ~ let b = if n == 3 { LL ~ "four" LL | } else { LL ~ "five" +LL ~ }; | -help: add a semicolon after the `if` expression - | -LL | }; - | + error: unneeded late initialization --> tests/ui/needless_late_init.rs:59:5 @@ -115,20 +114,16 @@ error: unneeded late initialization LL | let d; | ^^^^^^ | -help: declare `d` here - | -LL | let d = if true { - | +++++++ -help: remove the assignments from the branches +help: move the declaration `d` here and remove the assignments from the branches | +LL ~ +LL ~ let d = if true { +LL | let temp = 5; LL ~ temp LL | } else { LL ~ 15 +LL ~ }; | -help: add a semicolon after the `if` expression - | -LL | }; - | + error: unneeded late initialization --> tests/ui/needless_late_init.rs:67:5 @@ -136,20 +131,15 @@ error: unneeded late initialization LL | let e; | ^^^^^^ | -help: declare `e` here - | -LL | let e = if true { - | +++++++ -help: remove the assignments from the branches +help: move the declaration `e` here and remove the assignments from the branches | +LL ~ +LL ~ let e = if true { LL ~ format!("{} {}", a, b) LL | } else { LL ~ format!("{}", n) +LL ~ }; | -help: add a semicolon after the `if` expression - | -LL | }; - | + error: unneeded late initialization --> tests/ui/needless_late_init.rs:74:5 @@ -157,14 +147,11 @@ error: unneeded late initialization LL | let f; | ^^^^^^ | -help: declare `f` here +help: move the declaration `f` here and remove the assignments from the `match` arms | -LL | let f = match 1 { - | +++++++ -help: remove the assignments from the `match` arms - | -LL - 1 => f = "three", -LL + 1 => "three", +LL ~ +LL ~ let f = match 1 { +LL ~ 1 => "three", | error: unneeded late initialization @@ -173,19 +160,15 @@ error: unneeded late initialization LL | let g: usize; | ^^^^^^^^^^^^^ | -help: declare `g` here +help: move the declaration `g` here and remove the assignments from the branches | -LL | let g: usize = if true { - | ++++++++++++++ -help: remove the assignments from the branches +LL ~ +LL ~ let g: usize = if true { +LL ~ 5 +LL | } else { +LL | panic!(); +LL ~ }; | -LL - g = 5; -LL + 5 - | -help: add a semicolon after the `if` expression - | -LL | }; - | + error: unneeded late initialization --> tests/ui/needless_late_init.rs:88:5 @@ -196,10 +179,12 @@ LL | let y = SignificantDrop; LL | x = 1; | ^^^^^ initialised here | -help: declare `x` here +help: move the declaration `x` here + | +LL ~ +LL | let y = SignificantDrop; +LL ~ let x = 1; | -LL | let x = 1; - | ~~~~~ error: unneeded late initialization --> tests/ui/needless_late_init.rs:92:5 @@ -210,10 +195,12 @@ LL | let y = 1; LL | x = SignificantDrop; | ^^^^^^^^^^^^^^^^^^^ initialised here | -help: declare `x` here +help: move the declaration `x` here + | +LL ~ +LL | let y = 1; +LL ~ let x = SignificantDrop; | -LL | let x = SignificantDrop; - | ~~~~~ error: unneeded late initialization --> tests/ui/needless_late_init.rs:96:5 @@ -224,10 +211,14 @@ LL | let x; LL | x = SignificantDrop; | ^^^^^^^^^^^^^^^^^^^ initialised here | -help: declare `x` here +help: move the declaration `x` here + | +LL ~ +LL | // types that should be considered insignificant + ... +LL | let y = Box::new(4); +LL ~ let x = SignificantDrop; | -LL | let x = SignificantDrop; - | ~~~~~ error: unneeded late initialization --> tests/ui/needless_late_init.rs:115:5 @@ -235,20 +226,17 @@ error: unneeded late initialization LL | let a; | ^^^^^^ | -help: declare `a` here - | -LL | let a = match n { - | +++++++ -help: remove the assignments from the `match` arms +help: move the declaration `a` here and remove the assignments from the `match` arms | +LL ~ +LL | let n = 1; +LL ~ let a = match n { LL ~ 1 => f().await, LL | _ => { LL ~ "two" +LL | }, +LL ~ }; | -help: add a semicolon after the `match` expression - | -LL | }; - | + error: unneeded late initialization --> tests/ui/needless_late_init.rs:132:5 @@ -256,20 +244,17 @@ error: unneeded late initialization LL | let a; | ^^^^^^ | -help: declare `a` here - | -LL | let a = match n { - | +++++++ -help: remove the assignments from the `match` arms +help: move the declaration `a` here and remove the assignments from the `match` arms | +LL ~ +LL | let n = 1; +LL ~ let a = match n { LL ~ 1 => f(), LL | _ => { LL ~ "two" +LL | }, +LL ~ }; | -help: add a semicolon after the `match` expression - | -LL | }; - | + error: aborting due to 16 previous errors diff --git a/tests/ui/no_effect.rs b/tests/ui/no_effect.rs index dabeda72f0c8..0ea911c34348 100644 --- a/tests/ui/no_effect.rs +++ b/tests/ui/no_effect.rs @@ -1,6 +1,5 @@ #![feature(fn_traits, unboxed_closures)] #![warn(clippy::no_effect_underscore_binding)] -#![allow(dead_code, path_statements)] #![allow( clippy::deref_addrof, clippy::redundant_field_names, @@ -33,7 +32,6 @@ impl Neg for Cout { } } -struct Unit; struct Tuple(i32); struct Struct { field: i32, @@ -42,10 +40,6 @@ enum Enum { Tuple(i32), Struct { field: i32 }, } -struct DropUnit; -impl Drop for DropUnit { - fn drop(&mut self) {} -} struct DropStruct { field: i32, } @@ -117,15 +111,9 @@ impl FnOnce<(&str,)> for GreetStruct3 { fn main() { let s = get_struct(); - let s2 = get_struct(); 0; //~^ ERROR: statement with no effect - //~| NOTE: `-D clippy::no-effect` implied by `-D warnings` - s2; - //~^ ERROR: statement with no effect - Unit; - //~^ ERROR: statement with no effect Tuple(0); //~^ ERROR: statement with no effect Struct { field: 0 }; @@ -192,7 +180,6 @@ fn main() { unsafe { unsafe_fn() }; let _used = get_struct(); let _x = vec![1]; - DropUnit; DropStruct { field: 0 }; DropTuple(0); DropEnum::Tuple(0); diff --git a/tests/ui/no_effect.stderr b/tests/ui/no_effect.stderr index c7c8eecd054b..48ec997d938c 100644 --- a/tests/ui/no_effect.stderr +++ b/tests/ui/no_effect.stderr @@ -1,5 +1,5 @@ error: statement with no effect - --> tests/ui/no_effect.rs:122:5 + --> tests/ui/no_effect.rs:115:5 | LL | 0; | ^^ @@ -8,151 +8,139 @@ LL | 0; = help: to override `-D warnings` add `#[allow(clippy::no_effect)]` error: statement with no effect - --> tests/ui/no_effect.rs:125:5 - | -LL | s2; - | ^^^ - -error: statement with no effect - --> tests/ui/no_effect.rs:127:5 - | -LL | Unit; - | ^^^^^ - -error: statement with no effect - --> tests/ui/no_effect.rs:129:5 + --> tests/ui/no_effect.rs:117:5 | LL | Tuple(0); | ^^^^^^^^^ error: statement with no effect - --> tests/ui/no_effect.rs:131:5 + --> tests/ui/no_effect.rs:119:5 | LL | Struct { field: 0 }; | ^^^^^^^^^^^^^^^^^^^^ error: statement with no effect - --> tests/ui/no_effect.rs:133:5 + --> tests/ui/no_effect.rs:121:5 | LL | Struct { ..s }; | ^^^^^^^^^^^^^^^ error: statement with no effect - --> tests/ui/no_effect.rs:135:5 + --> tests/ui/no_effect.rs:123:5 | LL | Union { a: 0 }; | ^^^^^^^^^^^^^^^ error: statement with no effect - --> tests/ui/no_effect.rs:137:5 + --> tests/ui/no_effect.rs:125:5 | LL | Enum::Tuple(0); | ^^^^^^^^^^^^^^^ error: statement with no effect - --> tests/ui/no_effect.rs:139:5 + --> tests/ui/no_effect.rs:127:5 | LL | Enum::Struct { field: 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: statement with no effect - --> tests/ui/no_effect.rs:141:5 + --> tests/ui/no_effect.rs:129:5 | LL | 5 + 6; | ^^^^^^ error: statement with no effect - --> tests/ui/no_effect.rs:143:5 + --> tests/ui/no_effect.rs:131:5 | LL | *&42; | ^^^^^ error: statement with no effect - --> tests/ui/no_effect.rs:145:5 + --> tests/ui/no_effect.rs:133:5 | LL | &6; | ^^^ error: statement with no effect - --> tests/ui/no_effect.rs:147:5 + --> tests/ui/no_effect.rs:135:5 | LL | (5, 6, 7); | ^^^^^^^^^^ error: statement with no effect - --> tests/ui/no_effect.rs:149:5 + --> tests/ui/no_effect.rs:137:5 | LL | ..; | ^^^ error: statement with no effect - --> tests/ui/no_effect.rs:151:5 + --> tests/ui/no_effect.rs:139:5 | LL | 5..; | ^^^^ error: statement with no effect - --> tests/ui/no_effect.rs:153:5 + --> tests/ui/no_effect.rs:141:5 | LL | ..5; | ^^^^ error: statement with no effect - --> tests/ui/no_effect.rs:155:5 + --> tests/ui/no_effect.rs:143:5 | LL | 5..6; | ^^^^^ error: statement with no effect - --> tests/ui/no_effect.rs:157:5 + --> tests/ui/no_effect.rs:145:5 | LL | 5..=6; | ^^^^^^ error: statement with no effect - --> tests/ui/no_effect.rs:159:5 + --> tests/ui/no_effect.rs:147:5 | LL | [42, 55]; | ^^^^^^^^^ error: statement with no effect - --> tests/ui/no_effect.rs:161:5 + --> tests/ui/no_effect.rs:149:5 | LL | [42, 55][1]; | ^^^^^^^^^^^^ error: statement with no effect - --> tests/ui/no_effect.rs:163:5 + --> tests/ui/no_effect.rs:151:5 | LL | (42, 55).1; | ^^^^^^^^^^^ error: statement with no effect - --> tests/ui/no_effect.rs:165:5 + --> tests/ui/no_effect.rs:153:5 | LL | [42; 55]; | ^^^^^^^^^ error: statement with no effect - --> tests/ui/no_effect.rs:167:5 + --> tests/ui/no_effect.rs:155:5 | LL | [42; 55][13]; | ^^^^^^^^^^^^^ error: statement with no effect - --> tests/ui/no_effect.rs:170:5 + --> tests/ui/no_effect.rs:158:5 | LL | || x += 5; | ^^^^^^^^^^ error: statement with no effect - --> tests/ui/no_effect.rs:173:5 + --> tests/ui/no_effect.rs:161:5 | LL | FooString { s: s }; | ^^^^^^^^^^^^^^^^^^^ error: binding to `_` prefixed variable with no side-effect - --> tests/ui/no_effect.rs:175:9 + --> tests/ui/no_effect.rs:163:9 | LL | let _unused = 1; | ^^^^^^^ @@ -161,22 +149,22 @@ LL | let _unused = 1; = help: to override `-D warnings` add `#[allow(clippy::no_effect_underscore_binding)]` error: binding to `_` prefixed variable with no side-effect - --> tests/ui/no_effect.rs:178:9 + --> tests/ui/no_effect.rs:166:9 | LL | let _penguin = || println!("Some helpful closure"); | ^^^^^^^^ error: binding to `_` prefixed variable with no side-effect - --> tests/ui/no_effect.rs:180:9 + --> tests/ui/no_effect.rs:168:9 | LL | let _duck = Struct { field: 0 }; | ^^^^^ error: binding to `_` prefixed variable with no side-effect - --> tests/ui/no_effect.rs:182:9 + --> tests/ui/no_effect.rs:170:9 | LL | let _cat = [2, 4, 6, 8][2]; | ^^^^ -error: aborting due to 29 previous errors +error: aborting due to 27 previous errors diff --git a/tests/ui/significant_drop_in_scrutinee.rs b/tests/ui/significant_drop_in_scrutinee.rs index 0305d895fc58..7fc89bb95380 100644 --- a/tests/ui/significant_drop_in_scrutinee.rs +++ b/tests/ui/significant_drop_in_scrutinee.rs @@ -675,4 +675,60 @@ fn should_not_trigger_on_significant_iterator_drop() { } } +// https://github.com/rust-lang/rust-clippy/issues/9072 +fn should_not_trigger_lint_if_place_expr_has_significant_drop() { + let x = Mutex::new(vec![1, 2, 3]); + let x_guard = x.lock().unwrap(); + + match x_guard[0] { + 1 => println!("1!"), + x => println!("{x}"), + } + + match x_guard.len() { + 1 => println!("1!"), + x => println!("{x}"), + } +} + +struct Guard<'a, T>(MutexGuard<'a, T>); + +struct Ref<'a, T>(&'a T); + +impl<'a, T> Guard<'a, T> { + fn guard(&self) -> &MutexGuard { + &self.0 + } + + fn guard_ref(&self) -> Ref> { + Ref(&self.0) + } + + fn take(self) -> Box> { + Box::new(self.0) + } +} + +fn should_not_trigger_for_significant_drop_ref() { + let mutex = Mutex::new(vec![1, 2]); + let guard = Guard(mutex.lock().unwrap()); + + match guard.guard().len() { + 0 => println!("empty"), + _ => println!("not empty"), + } + + match guard.guard_ref().0.len() { + 0 => println!("empty"), + _ => println!("not empty"), + } + + match guard.take().len() { + //~^ ERROR: temporary with significant `Drop` in `match` scrutinee will live until the + //~| NOTE: this might lead to deadlocks or other unexpected behavior + 0 => println!("empty"), + _ => println!("not empty"), + }; +} + fn main() {} diff --git a/tests/ui/significant_drop_in_scrutinee.stderr b/tests/ui/significant_drop_in_scrutinee.stderr index 7d5b1acc7f00..811bb0655279 100644 --- a/tests/ui/significant_drop_in_scrutinee.stderr +++ b/tests/ui/significant_drop_in_scrutinee.stderr @@ -28,6 +28,9 @@ LL | match s.lock_m().get_the_value() { LL | println!("{}", s.lock_m().get_the_value()); | ---------- another value with significant `Drop` created here ... +LL | println!("{}", s.lock_m().get_the_value()); + | ---------- another value with significant `Drop` created here +... LL | } | - temporary lives until here | @@ -47,6 +50,9 @@ LL | match s.lock_m_m().get_the_value() { LL | println!("{}", s.lock_m().get_the_value()); | ---------- another value with significant `Drop` created here ... +LL | println!("{}", s.lock_m().get_the_value()); + | ---------- another value with significant `Drop` created here +... LL | } | - temporary lives until here | @@ -360,7 +366,7 @@ LL | match s.lock().deref().deref() { | ^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | _ => println!("Value is {}", s.lock().deref()), - | ---------------- another value with significant `Drop` created here + | -------- another value with significant `Drop` created here LL | }; | - temporary lives until here | @@ -378,7 +384,7 @@ LL | match s.lock().deref().deref() { | ^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | matcher => println!("Value is {}", s.lock().deref()), - | ---------------- another value with significant `Drop` created here + | -------- another value with significant `Drop` created here LL | _ => println!("Value was not a match"), LL | }; | - temporary lives until here @@ -499,5 +505,21 @@ LL ~ let value = mutex.lock().unwrap().foo(); LL ~ match value { | -error: aborting due to 26 previous errors +error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression + --> tests/ui/significant_drop_in_scrutinee.rs:726:11 + | +LL | match guard.take().len() { + | ^^^^^^^^^^^^^^^^^^ +... +LL | }; + | - temporary lives until here + | + = note: this might lead to deadlocks or other unexpected behavior +help: try moving the temporary above the match + | +LL ~ let value = guard.take().len(); +LL ~ match value { + | + +error: aborting due to 27 previous errors diff --git a/tests/ui/unnecessary_iter_cloned.fixed b/tests/ui/unnecessary_iter_cloned.fixed index ad0e5fab029e..2c582c90ba8c 100644 --- a/tests/ui/unnecessary_iter_cloned.fixed +++ b/tests/ui/unnecessary_iter_cloned.fixed @@ -21,6 +21,8 @@ fn main() { let _ = check_files_ref_mut(&[(FileType::Account, path)]); let _ = check_files_self_and_arg(&[(FileType::Account, path)]); let _ = check_files_mut_path_buf(&[(FileType::Account, std::path::PathBuf::new())]); + + check_mut_iteratee_and_modify_inner_variable(); } // `check_files` and its variants are based on: @@ -138,3 +140,33 @@ fn check_files_mut_path_buf(files: &[(FileType, std::path::PathBuf)]) -> bool { fn get_file_path(_file_type: &FileType) -> Result { Ok(std::path::PathBuf::new()) } + +// Issue 12098 +// https://github.com/rust-lang/rust-clippy/issues/12098 +// no message emits +fn check_mut_iteratee_and_modify_inner_variable() { + struct Test { + list: Vec, + mut_this: bool, + } + + impl Test { + fn list(&self) -> &[String] { + &self.list + } + } + + let mut test = Test { + list: vec![String::from("foo"), String::from("bar")], + mut_this: false, + }; + + for _item in test.list().to_vec() { + println!("{}", _item); + + test.mut_this = true; + { + test.mut_this = true; + } + } +} diff --git a/tests/ui/unnecessary_iter_cloned.rs b/tests/ui/unnecessary_iter_cloned.rs index d3d59c4c70f5..a28ccd1efef2 100644 --- a/tests/ui/unnecessary_iter_cloned.rs +++ b/tests/ui/unnecessary_iter_cloned.rs @@ -21,6 +21,8 @@ fn main() { let _ = check_files_ref_mut(&[(FileType::Account, path)]); let _ = check_files_self_and_arg(&[(FileType::Account, path)]); let _ = check_files_mut_path_buf(&[(FileType::Account, std::path::PathBuf::new())]); + + check_mut_iteratee_and_modify_inner_variable(); } // `check_files` and its variants are based on: @@ -138,3 +140,33 @@ fn check_files_mut_path_buf(files: &[(FileType, std::path::PathBuf)]) -> bool { fn get_file_path(_file_type: &FileType) -> Result { Ok(std::path::PathBuf::new()) } + +// Issue 12098 +// https://github.com/rust-lang/rust-clippy/issues/12098 +// no message emits +fn check_mut_iteratee_and_modify_inner_variable() { + struct Test { + list: Vec, + mut_this: bool, + } + + impl Test { + fn list(&self) -> &[String] { + &self.list + } + } + + let mut test = Test { + list: vec![String::from("foo"), String::from("bar")], + mut_this: false, + }; + + for _item in test.list().to_vec() { + println!("{}", _item); + + test.mut_this = true; + { + test.mut_this = true; + } + } +} diff --git a/tests/ui/unnecessary_iter_cloned.stderr b/tests/ui/unnecessary_iter_cloned.stderr index 9d3591e0dbfc..fb98cfddc262 100644 --- a/tests/ui/unnecessary_iter_cloned.stderr +++ b/tests/ui/unnecessary_iter_cloned.stderr @@ -1,5 +1,5 @@ error: unnecessary use of `copied` - --> tests/ui/unnecessary_iter_cloned.rs:29:22 + --> tests/ui/unnecessary_iter_cloned.rs:31:22 | LL | for (t, path) in files.iter().copied() { | ^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL + let other = match get_file_path(t) { | error: unnecessary use of `copied` - --> tests/ui/unnecessary_iter_cloned.rs:44:22 + --> tests/ui/unnecessary_iter_cloned.rs:46:22 | LL | for (t, path) in files.iter().copied() { | ^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/useless_attribute.fixed b/tests/ui/useless_attribute.fixed index 81759086f79e..231fc0a892ad 100644 --- a/tests/ui/useless_attribute.fixed +++ b/tests/ui/useless_attribute.fixed @@ -86,8 +86,51 @@ mod module { #[rustfmt::skip] #[allow(unused_import_braces)] +#[allow(unused_braces)] use module::{Struct}; fn main() { test_indented_attr(); } + +// Regression test for https://github.com/rust-lang/rust-clippy/issues/4467 +#[allow(dead_code)] +use std::collections as puppy_doggy; + +// Regression test for https://github.com/rust-lang/rust-clippy/issues/11595 +pub mod hidden_glob_reexports { + #![allow(unreachable_pub)] + + mod my_prelude { + pub struct MyCoolTypeInternal; + pub use MyCoolTypeInternal as MyCoolType; + } + + mod my_uncool_type { + pub(crate) struct MyUncoolType; + } + + // This exports `MyCoolType`. + pub use my_prelude::*; + + // This hides `my_prelude::MyCoolType`. + #[allow(hidden_glob_reexports)] + use my_uncool_type::MyUncoolType as MyCoolType; +} + +// Regression test for https://github.com/rust-lang/rust-clippy/issues/10878 +pub mod ambiguous_glob_exports { + #![allow(unreachable_pub)] + + mod my_prelude { + pub struct MyType; + } + + mod my_type { + pub struct MyType; + } + + #[allow(ambiguous_glob_reexports)] + pub use my_prelude::*; + pub use my_type::*; +} diff --git a/tests/ui/useless_attribute.rs b/tests/ui/useless_attribute.rs index 59a9dcf093bc..8dfcd2110a4b 100644 --- a/tests/ui/useless_attribute.rs +++ b/tests/ui/useless_attribute.rs @@ -86,8 +86,51 @@ mod module { #[rustfmt::skip] #[allow(unused_import_braces)] +#[allow(unused_braces)] use module::{Struct}; fn main() { test_indented_attr(); } + +// Regression test for https://github.com/rust-lang/rust-clippy/issues/4467 +#[allow(dead_code)] +use std::collections as puppy_doggy; + +// Regression test for https://github.com/rust-lang/rust-clippy/issues/11595 +pub mod hidden_glob_reexports { + #![allow(unreachable_pub)] + + mod my_prelude { + pub struct MyCoolTypeInternal; + pub use MyCoolTypeInternal as MyCoolType; + } + + mod my_uncool_type { + pub(crate) struct MyUncoolType; + } + + // This exports `MyCoolType`. + pub use my_prelude::*; + + // This hides `my_prelude::MyCoolType`. + #[allow(hidden_glob_reexports)] + use my_uncool_type::MyUncoolType as MyCoolType; +} + +// Regression test for https://github.com/rust-lang/rust-clippy/issues/10878 +pub mod ambiguous_glob_exports { + #![allow(unreachable_pub)] + + mod my_prelude { + pub struct MyType; + } + + mod my_type { + pub struct MyType; + } + + #[allow(ambiguous_glob_reexports)] + pub use my_prelude::*; + pub use my_type::*; +} diff --git a/tests/ui/while_float.rs b/tests/ui/while_float.rs new file mode 100644 index 000000000000..a3b0618948e6 --- /dev/null +++ b/tests/ui/while_float.rs @@ -0,0 +1,14 @@ +#[deny(clippy::while_float)] +fn main() { + let mut x = 0.0_f32; + while x < 42.0_f32 { + x += 0.5; + } + while x < 42.0 { + x += 1.0; + } + let mut x = 0; + while x < 42 { + x += 1; + } +} diff --git a/tests/ui/while_float.stderr b/tests/ui/while_float.stderr new file mode 100644 index 000000000000..b8e934b97c6c --- /dev/null +++ b/tests/ui/while_float.stderr @@ -0,0 +1,20 @@ +error: while condition comparing floats + --> tests/ui/while_float.rs:4:11 + | +LL | while x < 42.0_f32 { + | ^^^^^^^^^^^^ + | +note: the lint level is defined here + --> tests/ui/while_float.rs:1:8 + | +LL | #[deny(clippy::while_float)] + | ^^^^^^^^^^^^^^^^^^^ + +error: while condition comparing floats + --> tests/ui/while_float.rs:7:11 + | +LL | while x < 42.0 { + | ^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/util/gh-pages/script.js b/util/gh-pages/script.js index c63edd5bf709..7fd779fe9a46 100644 --- a/util/gh-pages/script.js +++ b/util/gh-pages/script.js @@ -406,7 +406,7 @@ } // Search by id - if (lint.id.indexOf(searchStr.replace("-", "_")) !== -1) { + if (lint.id.indexOf(searchStr.replaceAll("-", "_")) !== -1) { return true; } From 7439ecb07c85bcb148b3b62b2de0be746d5beac2 Mon Sep 17 00:00:00 2001 From: schvv31n Date: Tue, 21 May 2024 22:21:33 +0100 Subject: [PATCH 027/211] Added check for type unification with the iter --- .../src/methods/iter_on_single_or_empty_collections.rs | 10 +++++++--- tests/ui/iter_on_empty_collections.fixed | 4 ++++ tests/ui/iter_on_empty_collections.rs | 4 ++++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs b/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs index 1bf323cf3c7d..f4397212cf66 100644 --- a/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs +++ b/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs @@ -37,14 +37,18 @@ fn is_arg_ty_unified_in_fn<'tcx>( ) -> bool { let fn_sig = cx.tcx.fn_sig(fn_id).instantiate_identity(); let arg_id_in_args = args.into_iter().position(|e| e.hir_id == arg_id).unwrap(); - let arg_ty_in_args = fn_sig.input(arg_id_in_args); + let arg_ty_in_args = fn_sig.input(arg_id_in_args).skip_binder(); cx.tcx.predicates_of(fn_id).predicates.iter().any(|(clause, _)| { clause .as_projection_clause() .and_then(|p| p.map_bound(|p| p.term.ty()).transpose()) - .is_some_and(|ty| ty == arg_ty_in_args) - }) + .is_some_and(|ty| ty.skip_binder() == arg_ty_in_args) + }) || fn_sig + .inputs() + .iter() + .enumerate() + .any(|(i, ty)| i != arg_id_in_args && ty.skip_binder().walk().any(|arg| arg.as_type() == Some(arg_ty_in_args))) } pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, method_name: &str, recv: &'tcx Expr<'tcx>) { diff --git a/tests/ui/iter_on_empty_collections.fixed b/tests/ui/iter_on_empty_collections.fixed index 4b5746c7b6f4..0f28b48d9ab8 100644 --- a/tests/ui/iter_on_empty_collections.fixed +++ b/tests/ui/iter_on_empty_collections.fixed @@ -38,6 +38,10 @@ fn array() { for i in Option::map_or(smth.as_ref(), [].iter(), |s| s.iter()) { println!("{i}"); } + + // Same as above, but when there are no predicates that mention the collection iter type. + let mut iter = [34, 228, 35].iter(); + let _ = std::mem::replace(&mut iter, [].iter()); } macro_rules! in_macros { diff --git a/tests/ui/iter_on_empty_collections.rs b/tests/ui/iter_on_empty_collections.rs index 737192d556d3..702da514df7d 100644 --- a/tests/ui/iter_on_empty_collections.rs +++ b/tests/ui/iter_on_empty_collections.rs @@ -38,6 +38,10 @@ fn array() { for i in Option::map_or(smth.as_ref(), [].iter(), |s| s.iter()) { println!("{i}"); } + + // Same as above, but when there are no predicates that mention the collection iter type. + let mut iter = [34, 228, 35].iter(); + let _ = std::mem::replace(&mut iter, [].iter()); } macro_rules! in_macros { From 038f6179d746afb9fe396395ece667d7a0a4052c Mon Sep 17 00:00:00 2001 From: WeiTheShinobi Date: Sat, 2 Mar 2024 16:55:38 +0800 Subject: [PATCH 028/211] bug fix: lint numbered_fields message error --- clippy_lints/src/init_numbered_fields.rs | 4 ++-- tests/ui/numbered_fields.fixed | 5 +++++ tests/ui/numbered_fields.rs | 5 +++++ tests/ui/numbered_fields.stderr | 8 +++++++- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/init_numbered_fields.rs b/clippy_lints/src/init_numbered_fields.rs index e486563808a5..1c8fd0a27f98 100644 --- a/clippy_lints/src/init_numbered_fields.rs +++ b/clippy_lints/src/init_numbered_fields.rs @@ -1,5 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::snippet_with_applicability; +use clippy_utils::source::{snippet_with_applicability, snippet_with_context}; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{Expr, ExprKind}; @@ -62,7 +62,7 @@ impl<'tcx> LateLintPass<'tcx> for NumberedFields { snippet_with_applicability(cx, path.span(), "..", &mut appl), expr_spans .into_iter_sorted() - .map(|(_, span)| snippet_with_applicability(cx, span, "..", &mut appl)) + .map(|(_, span)| snippet_with_context(cx, span, path.span().ctxt(), "..", &mut appl).0) .intersperse(Cow::Borrowed(", ")) .collect::() ); diff --git a/tests/ui/numbered_fields.fixed b/tests/ui/numbered_fields.fixed index dc88081ba0a7..108520eed38d 100644 --- a/tests/ui/numbered_fields.fixed +++ b/tests/ui/numbered_fields.fixed @@ -34,4 +34,9 @@ fn main() { // Aliases can't be tuple constructed #8638 let _ = Alias { 0: 0, 1: 1, 2: 2 }; + + // Issue #12367 + struct TupleStructVec(Vec); + + let _ = TupleStructVec(vec![0, 1, 2, 3]); } diff --git a/tests/ui/numbered_fields.rs b/tests/ui/numbered_fields.rs index e8fa652e3c1d..c718661a6826 100644 --- a/tests/ui/numbered_fields.rs +++ b/tests/ui/numbered_fields.rs @@ -42,4 +42,9 @@ fn main() { // Aliases can't be tuple constructed #8638 let _ = Alias { 0: 0, 1: 1, 2: 2 }; + + // Issue #12367 + struct TupleStructVec(Vec); + + let _ = TupleStructVec { 0: vec![0, 1, 2, 3] }; } diff --git a/tests/ui/numbered_fields.stderr b/tests/ui/numbered_fields.stderr index 96426cab1e62..9d3f59cd3769 100644 --- a/tests/ui/numbered_fields.stderr +++ b/tests/ui/numbered_fields.stderr @@ -23,5 +23,11 @@ LL | | 1: 3u32, LL | | }; | |_____^ help: try: `TupleStruct(1u32, 3u32, 2u8)` -error: aborting due to 2 previous errors +error: used a field initializer for a tuple struct + --> tests/ui/numbered_fields.rs:49:13 + | +LL | let _ = TupleStructVec { 0: vec![0, 1, 2, 3] }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `TupleStructVec(vec![0, 1, 2, 3])` + +error: aborting due to 3 previous errors From 765baba165adb0ce0bef398f5eed54ba97d638f3 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 10 May 2024 17:29:02 +0300 Subject: [PATCH 029/211] rustc: Use `tcx.used_crates(())` more And explain when it should be used. --- clippy_utils/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 4c603bda770a..94d4656377f9 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -647,7 +647,7 @@ fn item_children_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Vec, path: &[&str]) -> Vec { fn find_crates(tcx: TyCtxt<'_>, name: Symbol) -> impl Iterator + '_ { - tcx.crates(()) + tcx.crates_including_speculative(()) .iter() .copied() .filter(move |&num| tcx.crate_name(num) == name) From 6641f9f6e138a3166b06fc27d62e7c349e1f927d Mon Sep 17 00:00:00 2001 From: Ruihan Li Date: Sat, 27 Apr 2024 23:47:11 +0800 Subject: [PATCH 030/211] Track lifetime on values with significant drop --- .../matches/significant_drop_in_scrutinee.rs | 420 ++++++++++-------- tests/ui/significant_drop_in_scrutinee.rs | 98 +++- tests/ui/significant_drop_in_scrutinee.stderr | 220 ++++----- 3 files changed, 434 insertions(+), 304 deletions(-) diff --git a/clippy_lints/src/matches/significant_drop_in_scrutinee.rs b/clippy_lints/src/matches/significant_drop_in_scrutinee.rs index 6ac0705abb21..2f72e59834fa 100644 --- a/clippy_lints/src/matches/significant_drop_in_scrutinee.rs +++ b/clippy_lints/src/matches/significant_drop_in_scrutinee.rs @@ -1,12 +1,17 @@ +use std::ops::ControlFlow; + use crate::FxHashSet; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::{indent_of, snippet}; +use clippy_utils::ty::{for_each_top_level_late_bound_region, is_copy}; use clippy_utils::{get_attr, is_lint_allowed}; +use itertools::Itertools; +use rustc_ast::Mutability; use rustc_errors::{Applicability, Diag}; use rustc_hir::intravisit::{walk_expr, Visitor}; use rustc_hir::{Arm, Expr, ExprKind, MatchSource}; use rustc_lint::{LateContext, LintContext}; -use rustc_middle::ty::{GenericArgKind, Ty}; +use rustc_middle::ty::{GenericArgKind, Region, RegionKind, Ty, TyCtxt, TypeVisitable, TypeVisitor}; use rustc_span::Span; use super::SIGNIFICANT_DROP_IN_SCRUTINEE; @@ -22,43 +27,34 @@ pub(super) fn check<'tcx>( return; } - if let Some((suggestions, message)) = has_significant_drop_in_scrutinee(cx, scrutinee, source) { - for found in suggestions { - span_lint_and_then(cx, SIGNIFICANT_DROP_IN_SCRUTINEE, found.found_span, message, |diag| { - set_diagnostic(diag, cx, expr, found); - let s = Span::new(expr.span.hi(), expr.span.hi(), expr.span.ctxt(), None); - diag.span_label(s, "temporary lives until here"); - for span in has_significant_drop_in_arms(cx, arms) { - diag.span_label(span, "another value with significant `Drop` created here"); - } - diag.note("this might lead to deadlocks or other unexpected behavior"); - }); - } + let (suggestions, message) = has_significant_drop_in_scrutinee(cx, scrutinee, source); + for found in suggestions { + span_lint_and_then(cx, SIGNIFICANT_DROP_IN_SCRUTINEE, found.found_span, message, |diag| { + set_diagnostic(diag, cx, expr, found); + let s = Span::new(expr.span.hi(), expr.span.hi(), expr.span.ctxt(), None); + diag.span_label(s, "temporary lives until here"); + for span in has_significant_drop_in_arms(cx, arms) { + diag.span_label(span, "another value with significant `Drop` created here"); + } + diag.note("this might lead to deadlocks or other unexpected behavior"); + }); } } fn set_diagnostic<'tcx>(diag: &mut Diag<'_, ()>, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, found: FoundSigDrop) { - if found.lint_suggestion == LintSuggestion::MoveAndClone { - // If our suggestion is to move and clone, then we want to leave it to the user to - // decide how to address this lint, since it may be that cloning is inappropriate. - // Therefore, we won't to emit a suggestion. - return; - } - let original = snippet(cx, found.found_span, ".."); let trailing_indent = " ".repeat(indent_of(cx, found.found_span).unwrap_or(0)); - let replacement = if found.lint_suggestion == LintSuggestion::MoveAndDerefToCopy { - format!("let value = *{original};\n{trailing_indent}") - } else if found.is_unit_return_val { - // If the return value of the expression to be moved is unit, then we don't need to - // capture the result in a temporary -- we can just replace it completely with `()`. - format!("{original};\n{trailing_indent}") - } else { - format!("let value = {original};\n{trailing_indent}") + let replacement = { + let (def_part, deref_part) = if found.is_unit_return_val { + ("", String::new()) + } else { + ("let value = ", "*".repeat(found.peel_ref_times)) + }; + format!("{def_part}{deref_part}{original};\n{trailing_indent}") }; - let suggestion_message = if found.lint_suggestion == LintSuggestion::MoveOnly { + let suggestion_message = if found.peel_ref_times == 0 { "try moving the temporary above the match" } else { "try moving the temporary above the match and create a copy" @@ -66,8 +62,11 @@ fn set_diagnostic<'tcx>(diag: &mut Diag<'_, ()>, cx: &LateContext<'tcx>, expr: & let scrutinee_replacement = if found.is_unit_return_val { "()".to_owned() - } else { + } else if found.peel_ref_times == 0 { "value".to_owned() + } else { + let ref_part = "&".repeat(found.peel_ref_times); + format!("({ref_part}value)") }; diag.multipart_suggestion( @@ -86,20 +85,18 @@ fn has_significant_drop_in_scrutinee<'tcx>( cx: &LateContext<'tcx>, scrutinee: &'tcx Expr<'tcx>, source: MatchSource, -) -> Option<(Vec, &'static str)> { +) -> (Vec, &'static str) { let mut helper = SigDropHelper::new(cx); let scrutinee = match (source, &scrutinee.kind) { (MatchSource::ForLoopDesugar, ExprKind::Call(_, [e])) => e, _ => scrutinee, }; - helper.find_sig_drop(scrutinee).map(|drops| { - let message = if source == MatchSource::Normal { - "temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression" - } else { - "temporary with significant `Drop` in `for` loop condition will live until the end of the `for` expression" - }; - (drops, message) - }) + let message = if source == MatchSource::Normal { + "temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression" + } else { + "temporary with significant `Drop` in `for` loop condition will live until the end of the `for` expression" + }; + (helper.find_sig_drop(scrutinee), message) } struct SigDropChecker<'a, 'tcx> { @@ -172,205 +169,248 @@ impl<'a, 'tcx> SigDropChecker<'a, 'tcx> { } } +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)] +enum SigDropHolder { + /// No values with significant drop present in this expression. + /// + /// Expressions that we've emited lints do not count. + None, + /// Some field in this expression references to values with significant drop. + /// + /// Example: `(1, &data.lock().field)`. + PackedRef, + /// The value of this expression references to values with significant drop. + /// + /// Example: `data.lock().field`. + DirectRef, + /// This expression should be moved out to avoid significant drop in scrutinee. + Moved, +} + +impl Default for SigDropHolder { + fn default() -> Self { + Self::None + } +} + struct SigDropHelper<'a, 'tcx> { cx: &'a LateContext<'tcx>, - is_chain_end: bool, - has_significant_drop: bool, - current_sig_drop: Option, - sig_drop_spans: Option>, - special_handling_for_binary_op: bool, + parent_expr: Option<&'tcx Expr<'tcx>>, + sig_drop_holder: SigDropHolder, + sig_drop_spans: Vec, sig_drop_checker: SigDropChecker<'a, 'tcx>, } -#[expect(clippy::enum_variant_names)] -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -enum LintSuggestion { - MoveOnly, - MoveAndDerefToCopy, - MoveAndClone, -} - -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug)] struct FoundSigDrop { found_span: Span, is_unit_return_val: bool, - lint_suggestion: LintSuggestion, + peel_ref_times: usize, } impl<'a, 'tcx> SigDropHelper<'a, 'tcx> { fn new(cx: &'a LateContext<'tcx>) -> SigDropHelper<'a, 'tcx> { SigDropHelper { cx, - is_chain_end: true, - has_significant_drop: false, - current_sig_drop: None, - sig_drop_spans: None, - special_handling_for_binary_op: false, + parent_expr: None, + sig_drop_holder: SigDropHolder::None, + sig_drop_spans: Vec::new(), sig_drop_checker: SigDropChecker::new(cx), } } - fn find_sig_drop(&mut self, match_expr: &'tcx Expr<'_>) -> Option> { + fn find_sig_drop(&mut self, match_expr: &'tcx Expr<'_>) -> Vec { self.visit_expr(match_expr); - // If sig drop spans is empty but we found a significant drop, it means that we didn't find - // a type that was trivially copyable as we moved up the chain after finding a significant - // drop, so move the entire scrutinee. - if self.has_significant_drop && self.sig_drop_spans.is_none() { - self.try_setting_current_suggestion(match_expr, true); - self.move_current_suggestion(); - } - - self.sig_drop_spans.take() + core::mem::take(&mut self.sig_drop_spans) } - fn replace_current_sig_drop( - &mut self, - found_span: Span, - is_unit_return_val: bool, - lint_suggestion: LintSuggestion, - ) { - self.current_sig_drop.replace(FoundSigDrop { + fn replace_current_sig_drop(&mut self, found_span: Span, is_unit_return_val: bool, peel_ref_times: usize) { + self.sig_drop_spans.clear(); + self.sig_drop_spans.push(FoundSigDrop { found_span, is_unit_return_val, - lint_suggestion, + peel_ref_times, }); } - /// This will try to set the current suggestion (so it can be moved into the suggestions vec - /// later). If `allow_move_and_clone` is false, the suggestion *won't* be set -- this gives us - /// an opportunity to look for another type in the chain that will be trivially copyable. - /// However, if we are at the end of the chain, we want to accept whatever is there. (The - /// suggestion won't actually be output, but the diagnostic message will be output, so the user - /// can determine the best way to handle the lint.) - fn try_setting_current_suggestion(&mut self, expr: &'tcx Expr<'_>, allow_move_and_clone: bool) { - if self.current_sig_drop.is_some() { - return; + fn try_move_sig_drop(&mut self, expr: &'tcx Expr<'_>, parent_expr: &'tcx Expr<'_>) { + if self.sig_drop_holder == SigDropHolder::Moved { + self.sig_drop_holder = SigDropHolder::None; } - let ty = self.cx.typeck_results().expr_ty(expr); - if ty.is_ref() { - // We checked that the type was ref, so builtin_deref will return Some, - // but let's avoid any chance of an ICE. - if let Some(ty) = ty.builtin_deref(true) { - if ty.is_trivially_pure_clone_copy() { - self.replace_current_sig_drop(expr.span, false, LintSuggestion::MoveAndDerefToCopy); - } else if allow_move_and_clone { - self.replace_current_sig_drop(expr.span, false, LintSuggestion::MoveAndClone); - } + + if self.sig_drop_holder == SigDropHolder::DirectRef { + self.sig_drop_holder = SigDropHolder::PackedRef; + self.try_move_sig_drop_direct_ref(expr, parent_expr); + } else if self.sig_drop_checker.is_sig_drop_expr(expr) { + // The values with significant drop can be moved to some other functions. For example, consider + // `drop(data.lock())`. We use `SigDropHolder::None` here to avoid emitting lints in such scenarios. + self.sig_drop_holder = SigDropHolder::None; + self.try_move_sig_drop_direct_ref(expr, parent_expr); + } + + if self.sig_drop_holder != SigDropHolder::None { + let parent_ty = self.cx.typeck_results().expr_ty(parent_expr); + if !ty_has_erased_regions(parent_ty) && !parent_expr.is_syntactic_place_expr() { + self.replace_current_sig_drop(parent_expr.span, parent_ty.is_unit(), 0); + self.sig_drop_holder = SigDropHolder::Moved; + } + + let (peel_ref_ty, peel_ref_times) = ty_peel_refs(parent_ty); + if !ty_has_erased_regions(peel_ref_ty) && is_copy(self.cx, peel_ref_ty) { + self.replace_current_sig_drop(parent_expr.span, peel_ref_ty.is_unit(), peel_ref_times); + self.sig_drop_holder = SigDropHolder::Moved; } - } else if ty.is_trivially_pure_clone_copy() { - self.replace_current_sig_drop(expr.span, false, LintSuggestion::MoveOnly); - } else if allow_move_and_clone { - self.replace_current_sig_drop(expr.span, false, LintSuggestion::MoveAndClone); } } - fn move_current_suggestion(&mut self) { - if let Some(current) = self.current_sig_drop.take() { - self.sig_drop_spans.get_or_insert_with(Vec::new).push(current); + fn try_move_sig_drop_direct_ref(&mut self, expr: &'tcx Expr<'_>, parent_expr: &'tcx Expr<'_>) { + let arg_idx = match parent_expr.kind { + ExprKind::MethodCall(_, receiver, exprs, _) => std::iter::once(receiver) + .chain(exprs.iter()) + .find_position(|ex| ex.hir_id == expr.hir_id) + .map(|(idx, _)| idx), + ExprKind::Call(_, exprs) => exprs + .iter() + .find_position(|ex| ex.hir_id == expr.hir_id) + .map(|(idx, _)| idx), + ExprKind::Binary(_, lhs, rhs) | ExprKind::AssignOp(_, lhs, rhs) => [lhs, rhs] + .iter() + .find_position(|ex| ex.hir_id == expr.hir_id) + .map(|(idx, _)| idx), + ExprKind::Unary(_, ex) => (ex.hir_id == expr.hir_id).then_some(0), + _ => { + // Here we assume that all other expressions create or propagate the reference to the value with + // significant drop. + self.sig_drop_holder = SigDropHolder::DirectRef; + return; + }, + }; + let Some(arg_idx) = arg_idx else { + return; + }; + + let fn_sig = if let Some(def_id) = self.cx.typeck_results().type_dependent_def_id(parent_expr.hir_id) { + self.cx.tcx.fn_sig(def_id).instantiate_identity() + } else { + return; + }; + + let input_re = if let Some(input_ty) = fn_sig.skip_binder().inputs().get(arg_idx) + && let rustc_middle::ty::Ref(input_re, _, _) = input_ty.kind() + { + input_re + } else { + return; + }; + + // Late bound lifetime parameters are not related to any constraints, so we can track them in a very + // simple manner. For other lifetime parameters, we give up and update the state to `PackedRef`. + let RegionKind::ReBound(_, input_re_bound) = input_re.kind() else { + self.sig_drop_holder = SigDropHolder::PackedRef; + return; + }; + let contains_input_re = |re_bound| { + if re_bound == input_re_bound { + ControlFlow::Break(()) + } else { + ControlFlow::Continue(()) + } + }; + + let output_ty = fn_sig.skip_binder().output(); + if let rustc_middle::ty::Ref(output_re, peel_ref_ty, _) = output_ty.kind() + && input_re == output_re + && for_each_top_level_late_bound_region(*peel_ref_ty, contains_input_re).is_continue() + { + // We're lucky! The output type is still a direct reference to the value with significant drop. + self.sig_drop_holder = SigDropHolder::DirectRef; + } else if for_each_top_level_late_bound_region(output_ty, contains_input_re).is_continue() { + // The lifetime to the value with significant drop goes away. So we can emit a lint that suggests to + // move the expression out. + self.replace_current_sig_drop(parent_expr.span, output_ty.is_unit(), 0); + self.sig_drop_holder = SigDropHolder::Moved; + } else { + // TODO: The lifetime is still there but it's for a inner type. For instance, consider + // `Some(&mutex.lock().field)`, which has a type of `Option<&u32>`. How to address this scenario? + self.sig_drop_holder = SigDropHolder::PackedRef; + } + } +} + +fn ty_peel_refs(mut ty: Ty<'_>) -> (Ty<'_>, usize) { + let mut n = 0; + while let rustc_middle::ty::Ref(_, new_ty, Mutability::Not) = ty.kind() { + ty = *new_ty; + n += 1; + } + (ty, n) +} + +fn ty_has_erased_regions(ty: Ty<'_>) -> bool { + struct V; + + impl<'tcx> TypeVisitor> for V { + type Result = ControlFlow<()>; + + fn visit_region(&mut self, region: Region<'tcx>) -> Self::Result { + if region.is_erased() { + ControlFlow::Break(()) + } else { + ControlFlow::Continue(()) + } } } - fn visit_exprs_for_binary_ops( - &mut self, - left: &'tcx Expr<'_>, - right: &'tcx Expr<'_>, - is_unit_return_val: bool, - span: Span, - ) { - self.special_handling_for_binary_op = true; - self.visit_expr(left); - self.visit_expr(right); - - // If either side had a significant drop, suggest moving the entire scrutinee to avoid - // unnecessary copies and to simplify cases where both sides have significant drops. - if self.has_significant_drop { - self.replace_current_sig_drop(span, is_unit_return_val, LintSuggestion::MoveOnly); - } - - self.special_handling_for_binary_op = false; - } + ty.visit_with(&mut V).is_break() } impl<'a, 'tcx> Visitor<'tcx> for SigDropHelper<'a, 'tcx> { fn visit_expr(&mut self, ex: &'tcx Expr<'_>) { - if !self.is_chain_end && self.sig_drop_checker.is_sig_drop_expr(ex) { - self.has_significant_drop = true; + // We've emited a lint on some neighborhood expression. That lint will suggest to move out the + // _parent_ expression (not the expression itself). Since we decide to move out the parent + // expression, it is pointless to continue to process the current expression. + if self.sig_drop_holder == SigDropHolder::Moved { return; } - self.is_chain_end = false; + + // These states are of neighborhood expressions. We save and clear them here, and we'll later merge + // the states of the current expression with them at the end of the method. + let sig_drop_holder_before = core::mem::take(&mut self.sig_drop_holder); + let sig_drop_spans_before = core::mem::take(&mut self.sig_drop_spans); + let parent_expr_before = self.parent_expr.replace(ex); match ex.kind { - ExprKind::MethodCall(_, expr, ..) => { - self.visit_expr(expr); - } - ExprKind::Binary(_, left, right) => { - self.visit_exprs_for_binary_ops(left, right, false, ex.span); - } - ExprKind::Assign(left, right, _) | ExprKind::AssignOp(_, left, right) => { - self.visit_exprs_for_binary_ops(left, right, true, ex.span); - } - ExprKind::Tup(exprs) => { - for expr in exprs { - self.visit_expr(expr); - if self.has_significant_drop { - // We may have not have set current_sig_drop if all the suggestions were - // MoveAndClone, so add this tuple item's full expression in that case. - if self.current_sig_drop.is_none() { - self.try_setting_current_suggestion(expr, true); - } + // Skip blocks because values in blocks will be dropped as usual. + ExprKind::Block(..) => (), + _ => walk_expr(self, ex), + } - // Now we are guaranteed to have something, so add it to the final vec. - self.move_current_suggestion(); - } - // Reset `has_significant_drop` after each tuple expression so we can look for - // additional cases. - self.has_significant_drop = false; - } - if self.sig_drop_spans.is_some() { - self.has_significant_drop = true; - } - } - ExprKind::Array(..) | - ExprKind::Call(..) | - ExprKind::Unary(..) | - ExprKind::If(..) | - ExprKind::Match(..) | - ExprKind::Field(..) | - ExprKind::Index(..) | - ExprKind::Ret(..) | - ExprKind::Become(..) | - ExprKind::Repeat(..) | - ExprKind::Yield(..) => walk_expr(self, ex), - ExprKind::AddrOf(_, _, _) | - ExprKind::Block(_, _) | - ExprKind::Break(_, _) | - ExprKind::Cast(_, _) | - // Don't want to check the closure itself, only invocation, which is covered by MethodCall - ExprKind::Closure { .. } | - ExprKind::ConstBlock(_) | - ExprKind::Continue(_) | - ExprKind::DropTemps(_) | - ExprKind::Err(_) | - ExprKind::InlineAsm(_) | - ExprKind::OffsetOf(_, _) | - ExprKind::Let(_) | - ExprKind::Lit(_) | - ExprKind::Loop(_, _, _, _) | - ExprKind::Path(_) | - ExprKind::Struct(_, _, _) | - ExprKind::Type(_, _) => { - return; + if let Some(parent_ex) = parent_expr_before { + match parent_ex.kind { + ExprKind::Assign(lhs, _, _) | ExprKind::AssignOp(_, lhs, _) + if lhs.hir_id == ex.hir_id && self.sig_drop_holder == SigDropHolder::Moved => + { + // Never move out only the assignee. Instead, we should always move out the whole assigment. + self.replace_current_sig_drop(parent_ex.span, true, 0); + }, + _ => { + self.try_move_sig_drop(ex, parent_ex); + }, } } - // Once a significant temporary has been found, we need to go back up at least 1 level to - // find the span to extract for replacement, so the temporary gets dropped. However, for - // binary ops, we want to move the whole scrutinee so we avoid unnecessary copies and to - // simplify cases where both sides have significant drops. - if self.has_significant_drop && !self.special_handling_for_binary_op { - self.try_setting_current_suggestion(ex, false); + self.sig_drop_holder = std::cmp::max(self.sig_drop_holder, sig_drop_holder_before); + + // We do not need those old spans in neighborhood expressions if we emit a lint that suggests to + // move out the _parent_ expression (i.e., `self.sig_drop_holder == SigDropHolder::Moved`). + if self.sig_drop_holder != SigDropHolder::Moved { + let mut sig_drop_spans = sig_drop_spans_before; + sig_drop_spans.append(&mut self.sig_drop_spans); + self.sig_drop_spans = sig_drop_spans; } + + self.parent_expr = parent_expr_before; } } diff --git a/tests/ui/significant_drop_in_scrutinee.rs b/tests/ui/significant_drop_in_scrutinee.rs index 7fc89bb95380..8ee15440ccf0 100644 --- a/tests/ui/significant_drop_in_scrutinee.rs +++ b/tests/ui/significant_drop_in_scrutinee.rs @@ -274,11 +274,20 @@ fn should_trigger_lint_for_tuple_in_scrutinee() { }, (_, _, _) => {}, }; + } +} +// Should not trigger lint since `String::as_str` returns a reference (i.e., `&str`) +// to the locked data (i.e., the `String`) and it is not surprising that matching such +// a reference needs to keep the data locked until the end of the match block. +fn should_not_trigger_lint_for_string_as_str() { + let mutex1 = Mutex::new(StateWithField { s: "one".to_owned() }); + + { + let mutex2 = Mutex::new(StateWithField { s: "two".to_owned() }); let mutex3 = Mutex::new(StateWithField { s: "three".to_owned() }); + match mutex3.lock().unwrap().s.as_str() { - //~^ ERROR: temporary with significant `Drop` in `match` scrutinee will live until - //~| NOTE: this might lead to deadlocks or other unexpected behavior "three" => { println!("started"); mutex1.lock().unwrap().s.len(); @@ -289,8 +298,6 @@ fn should_trigger_lint_for_tuple_in_scrutinee() { }; match (true, mutex3.lock().unwrap().s.as_str()) { - //~^ ERROR: temporary with significant `Drop` in `match` scrutinee will live until - //~| NOTE: this might lead to deadlocks or other unexpected behavior (_, "three") => { println!("started"); mutex1.lock().unwrap().s.len(); @@ -514,16 +521,15 @@ impl StateStringWithBoxedMutexGuard { } } -fn should_trigger_lint_for_boxed_mutex_guard_holding_string() { +fn should_not_trigger_lint_for_string_ref() { let s = StateStringWithBoxedMutexGuard::new(); let matcher = String::from("A String"); - // Should trigger lint because a temporary Box holding a type with a significant drop in a match - // scrutinee may have a potentially surprising lifetime. + // Should not trigger lint because the second `deref` returns a string reference (`&String`). + // So it is not surprising that matching the reference implies that the lock needs to be held + // until the end of the block. match s.lock().deref().deref() { - //~^ ERROR: temporary with significant `Drop` in `match` scrutinee will live until the - //~| NOTE: this might lead to deadlocks or other unexpected behavior matcher => println!("Value is {}", s.lock().deref()), _ => println!("Value was not a match"), }; @@ -639,13 +645,12 @@ fn should_trigger_lint_for_non_ref_move_and_clone_suggestion() { }; } -fn should_trigger_lint_for_read_write_lock_for_loop() { - // For-in loops desugar to match expressions and are prone to the type of deadlock this lint is - // designed to look for. +fn should_not_trigger_lint_for_read_write_lock_for_loop() { let rwlock = RwLock::>::new(vec!["1".to_string()]); + // Should not trigger lint. Since we're iterating over the data, it's obvious that the lock + // has to be held until the iteration finishes. + // https://github.com/rust-lang/rust-clippy/issues/8987 for s in rwlock.read().unwrap().iter() { - //~^ ERROR: temporary with significant `Drop` in `for` loop condition will live until - //~| NOTE: this might lead to deadlocks or other unexpected behavior println!("{}", s); } } @@ -731,4 +736,69 @@ fn should_not_trigger_for_significant_drop_ref() { }; } +struct Foo<'a>(&'a Vec); + +impl<'a> Foo<'a> { + fn copy_old_lifetime(&self) -> &'a Vec { + self.0 + } + + fn reborrow_new_lifetime(&self) -> &Vec { + self.0 + } +} + +fn should_trigger_lint_if_and_only_if_lifetime_is_irrelevant() { + let vec = Vec::new(); + let mutex = Mutex::new(Foo(&vec)); + + // Should trigger lint even if `copy_old_lifetime()` has a lifetime, as the lifetime of + // `&vec` is unrelated to the temporary with significant drop (i.e., the `MutexGuard`). + for val in mutex.lock().unwrap().copy_old_lifetime() { + //~^ ERROR: temporary with significant `Drop` in `for` loop condition will live until the + //~| NOTE: this might lead to deadlocks or other unexpected behavior + println!("{}", val); + } + + // Should not trigger lint because `reborrow_new_lifetime()` has a lifetime and the + // lifetime is related to the temporary with significant drop (i.e., the `MutexGuard`). + for val in mutex.lock().unwrap().reborrow_new_lifetime() { + println!("{}", val); + } +} + +fn should_not_trigger_lint_for_complex_lifetime() { + let mutex = Mutex::new(vec!["hello".to_owned()]); + let string = "world".to_owned(); + + // Should not trigger lint due to the relevant lifetime. + for c in mutex.lock().unwrap().first().unwrap().chars() { + println!("{}", c); + } + + // Should trigger lint due to the irrelevant lifetime. + // + // FIXME: The lifetime is too complex to analyze. In order to avoid false positives, we do not + // trigger lint. + for c in mutex.lock().unwrap().first().map(|_| &string).unwrap().chars() { + println!("{}", c); + } +} + +fn should_not_trigger_lint_with_explicit_drop() { + let mutex = Mutex::new(vec![1]); + + // Should not trigger lint since the drop explicitly happens. + for val in [drop(mutex.lock().unwrap()), ()] { + println!("{:?}", val); + } + + // Should trigger lint if there is no explicit drop. + for val in [mutex.lock().unwrap()[0], 2] { + //~^ ERROR: temporary with significant `Drop` in `for` loop condition will live until the + //~| NOTE: this might lead to deadlocks or other unexpected behavior + println!("{:?}", val); + } +} + fn main() {} diff --git a/tests/ui/significant_drop_in_scrutinee.stderr b/tests/ui/significant_drop_in_scrutinee.stderr index 811bb0655279..4a483e79d8ad 100644 --- a/tests/ui/significant_drop_in_scrutinee.stderr +++ b/tests/ui/significant_drop_in_scrutinee.stderr @@ -160,42 +160,10 @@ LL ~ match (mutex1.lock().unwrap().s.len(), true, value) { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:279:15 - | -LL | match mutex3.lock().unwrap().s.as_str() { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... -LL | mutex1.lock().unwrap().s.len(); - | ---------------------- another value with significant `Drop` created here -LL | mutex2.lock().unwrap().s.len(); - | ---------------------- another value with significant `Drop` created here -... -LL | }; - | - temporary lives until here - | - = note: this might lead to deadlocks or other unexpected behavior - -error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:291:22 - | -LL | match (true, mutex3.lock().unwrap().s.as_str()) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... -LL | mutex1.lock().unwrap().s.len(); - | ---------------------- another value with significant `Drop` created here -LL | mutex2.lock().unwrap().s.len(); - | ---------------------- another value with significant `Drop` created here -... -LL | }; - | - temporary lives until here - | - = note: this might lead to deadlocks or other unexpected behavior - -error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:312:11 + --> tests/ui/significant_drop_in_scrutinee.rs:319:11 | LL | match mutex.lock().unwrap().s.len() > 1 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | mutex.lock().unwrap().s.len(); | --------------------- another value with significant `Drop` created here @@ -206,15 +174,15 @@ LL | }; = note: this might lead to deadlocks or other unexpected behavior help: try moving the temporary above the match | -LL ~ let value = mutex.lock().unwrap().s.len() > 1; -LL ~ match value { +LL ~ let value = mutex.lock().unwrap().s.len(); +LL ~ match value > 1 { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:321:11 + --> tests/ui/significant_drop_in_scrutinee.rs:328:15 | LL | match 1 < mutex.lock().unwrap().s.len() { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | mutex.lock().unwrap().s.len(); | --------------------- another value with significant `Drop` created here @@ -225,15 +193,15 @@ LL | }; = note: this might lead to deadlocks or other unexpected behavior help: try moving the temporary above the match | -LL ~ let value = 1 < mutex.lock().unwrap().s.len(); -LL ~ match value { +LL ~ let value = mutex.lock().unwrap().s.len(); +LL ~ match 1 < value { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:341:11 + --> tests/ui/significant_drop_in_scrutinee.rs:348:11 | LL | match mutex1.lock().unwrap().s.len() < mutex2.lock().unwrap().s.len() { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | mutex1.lock().unwrap().s.len(), | ---------------------- another value with significant `Drop` created here @@ -246,15 +214,36 @@ LL | }; = note: this might lead to deadlocks or other unexpected behavior help: try moving the temporary above the match | -LL ~ let value = mutex1.lock().unwrap().s.len() < mutex2.lock().unwrap().s.len(); -LL ~ match value { +LL ~ let value = mutex1.lock().unwrap().s.len(); +LL ~ match value < mutex2.lock().unwrap().s.len() { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:354:11 + --> tests/ui/significant_drop_in_scrutinee.rs:348:44 + | +LL | match mutex1.lock().unwrap().s.len() < mutex2.lock().unwrap().s.len() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | mutex1.lock().unwrap().s.len(), + | ---------------------- another value with significant `Drop` created here +LL | mutex2.lock().unwrap().s.len() + | ---------------------- another value with significant `Drop` created here +... +LL | }; + | - temporary lives until here + | + = note: this might lead to deadlocks or other unexpected behavior +help: try moving the temporary above the match + | +LL ~ let value = mutex2.lock().unwrap().s.len(); +LL ~ match mutex1.lock().unwrap().s.len() < value { + | + +error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression + --> tests/ui/significant_drop_in_scrutinee.rs:361:11 | LL | match mutex1.lock().unwrap().s.len() >= mutex2.lock().unwrap().s.len() { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | mutex1.lock().unwrap().s.len(), | ---------------------- another value with significant `Drop` created here @@ -267,15 +256,36 @@ LL | }; = note: this might lead to deadlocks or other unexpected behavior help: try moving the temporary above the match | -LL ~ let value = mutex1.lock().unwrap().s.len() >= mutex2.lock().unwrap().s.len(); -LL ~ match value { +LL ~ let value = mutex1.lock().unwrap().s.len(); +LL ~ match value >= mutex2.lock().unwrap().s.len() { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:391:11 + --> tests/ui/significant_drop_in_scrutinee.rs:361:45 + | +LL | match mutex1.lock().unwrap().s.len() >= mutex2.lock().unwrap().s.len() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | mutex1.lock().unwrap().s.len(), + | ---------------------- another value with significant `Drop` created here +LL | mutex2.lock().unwrap().s.len() + | ---------------------- another value with significant `Drop` created here +... +LL | }; + | - temporary lives until here + | + = note: this might lead to deadlocks or other unexpected behavior +help: try moving the temporary above the match + | +LL ~ let value = mutex2.lock().unwrap().s.len(); +LL ~ match mutex1.lock().unwrap().s.len() >= value { + | + +error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression + --> tests/ui/significant_drop_in_scrutinee.rs:398:11 | LL | match get_mutex_guard().s.len() > 1 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | mutex1.lock().unwrap().s.len(); | ---------------------- another value with significant `Drop` created here @@ -286,12 +296,12 @@ LL | }; = note: this might lead to deadlocks or other unexpected behavior help: try moving the temporary above the match | -LL ~ let value = get_mutex_guard().s.len() > 1; -LL ~ match value { +LL ~ let value = get_mutex_guard().s.len(); +LL ~ match value > 1 { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:410:11 + --> tests/ui/significant_drop_in_scrutinee.rs:417:11 | LL | match match i { | ___________^ @@ -299,9 +309,9 @@ LL | | LL | | LL | | 100 => mutex1.lock().unwrap(), ... | +LL | | .s LL | | .len() -LL | | > 1 - | |___________^ + | |__________^ ... LL | mutex1.lock().unwrap().s.len(); | ---------------------- another value with significant `Drop` created here @@ -319,13 +329,12 @@ LL + 100 => mutex1.lock().unwrap(), LL + _ => mutex2.lock().unwrap(), LL + } LL + .s -LL + .len() -LL + > 1; +LL + .len(); LL ~ match value | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:438:11 + --> tests/ui/significant_drop_in_scrutinee.rs:445:11 | LL | match if i > 1 { | ___________^ @@ -333,9 +342,9 @@ LL | | LL | | LL | | mutex1.lock().unwrap() ... | +LL | | .s LL | | .len() -LL | | > 1 - | |___________^ + | |__________^ ... LL | mutex1.lock().unwrap().s.len(); | ---------------------- another value with significant `Drop` created here @@ -354,13 +363,12 @@ LL + } else { LL + mutex2.lock().unwrap() LL + } LL + .s -LL + .len() -LL + > 1; +LL + .len(); LL ~ match value | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:494:11 + --> tests/ui/significant_drop_in_scrutinee.rs:501:11 | LL | match s.lock().deref().deref() { | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -374,25 +382,11 @@ LL | }; help: try moving the temporary above the match and create a copy | LL ~ let value = *s.lock().deref().deref(); -LL ~ match value { +LL ~ match (&value) { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:524:11 - | -LL | match s.lock().deref().deref() { - | ^^^^^^^^^^^^^^^^^^^^^^^^ -... -LL | matcher => println!("Value is {}", s.lock().deref()), - | -------- another value with significant `Drop` created here -LL | _ => println!("Value was not a match"), -LL | }; - | - temporary lives until here - | - = note: this might lead to deadlocks or other unexpected behavior - -error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:545:11 + --> tests/ui/significant_drop_in_scrutinee.rs:551:11 | LL | match mutex.lock().unwrap().i = i { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -411,10 +405,10 @@ LL ~ match () { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:553:11 + --> tests/ui/significant_drop_in_scrutinee.rs:559:15 | LL | match i = mutex.lock().unwrap().i { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^ ... LL | println!("{}", mutex.lock().unwrap().i); | --------------------- another value with significant `Drop` created here @@ -425,12 +419,12 @@ LL | }; = note: this might lead to deadlocks or other unexpected behavior help: try moving the temporary above the match | -LL ~ i = mutex.lock().unwrap().i; -LL ~ match () { +LL ~ let value = mutex.lock().unwrap().i; +LL ~ match i = value { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:561:11 + --> tests/ui/significant_drop_in_scrutinee.rs:567:11 | LL | match mutex.lock().unwrap().i += 1 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -449,10 +443,10 @@ LL ~ match () { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:569:11 + --> tests/ui/significant_drop_in_scrutinee.rs:575:16 | LL | match i += mutex.lock().unwrap().i { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^ ... LL | println!("{}", mutex.lock().unwrap().i); | --------------------- another value with significant `Drop` created here @@ -463,12 +457,12 @@ LL | }; = note: this might lead to deadlocks or other unexpected behavior help: try moving the temporary above the match | -LL ~ i += mutex.lock().unwrap().i; -LL ~ match () { +LL ~ let value = mutex.lock().unwrap().i; +LL ~ match i += value { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:634:11 + --> tests/ui/significant_drop_in_scrutinee.rs:640:11 | LL | match rwlock.read().unwrap().to_number() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -477,20 +471,14 @@ LL | }; | - temporary lives until here | = note: this might lead to deadlocks or other unexpected behavior - -error: temporary with significant `Drop` in `for` loop condition will live until the end of the `for` expression - --> tests/ui/significant_drop_in_scrutinee.rs:646:14 +help: try moving the temporary above the match | -LL | for s in rwlock.read().unwrap().iter() { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... -LL | } - | - temporary lives until here +LL ~ let value = rwlock.read().unwrap().to_number(); +LL ~ match value { | - = note: this might lead to deadlocks or other unexpected behavior error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:663:11 + --> tests/ui/significant_drop_in_scrutinee.rs:668:11 | LL | match mutex.lock().unwrap().foo() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -506,7 +494,7 @@ LL ~ match value { | error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression - --> tests/ui/significant_drop_in_scrutinee.rs:726:11 + --> tests/ui/significant_drop_in_scrutinee.rs:731:11 | LL | match guard.take().len() { | ^^^^^^^^^^^^^^^^^^ @@ -521,5 +509,37 @@ LL ~ let value = guard.take().len(); LL ~ match value { | +error: temporary with significant `Drop` in `for` loop condition will live until the end of the `for` expression + --> tests/ui/significant_drop_in_scrutinee.rs:757:16 + | +LL | for val in mutex.lock().unwrap().copy_old_lifetime() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | } + | - temporary lives until here + | + = note: this might lead to deadlocks or other unexpected behavior +help: try moving the temporary above the match + | +LL ~ let value = mutex.lock().unwrap().copy_old_lifetime(); +LL ~ for val in value { + | + +error: temporary with significant `Drop` in `for` loop condition will live until the end of the `for` expression + --> tests/ui/significant_drop_in_scrutinee.rs:797:17 + | +LL | for val in [mutex.lock().unwrap()[0], 2] { + | ^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | } + | - temporary lives until here + | + = note: this might lead to deadlocks or other unexpected behavior +help: try moving the temporary above the match + | +LL ~ let value = mutex.lock().unwrap()[0]; +LL ~ for val in [value, 2] { + | + error: aborting due to 27 previous errors From 2c9fc62b817783b24312b21f125448abb73ded9b Mon Sep 17 00:00:00 2001 From: Chris Krycho Date: Mon, 20 May 2024 13:29:31 -0600 Subject: [PATCH 031/211] Support mdBook preprocessors for TRPL in rustbook `rust-lang/book` recently added two mdBook preprocessors. Enable `rustbook` to use those preprocessors for books where they are requested by the `book.toml` by adding the preprocessors as path dependencies, and ignoring them where they are not requested, i.e. by all the books other than TRPL at present. --- Cargo.lock | 152 ++++++++++++++++++++++++++++++++- src/doc/book | 2 +- src/tools/rustbook/Cargo.toml | 2 + src/tools/rustbook/src/main.rs | 11 +++ 4 files changed, 164 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3a4f028e695f..66e9a7dcdba7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -275,6 +275,21 @@ dependencies = [ "nom", ] +[[package]] +name = "assert_cmd" +version = "2.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed72493ac66d5804837f480ab3766c72bdfab91a65e565fc54fa9e42db0073a8" +dependencies = [ + "anstyle", + "bstr", + "doc-comment", + "predicates", + "predicates-core", + "predicates-tree", + "wait-timeout", +] + [[package]] name = "autocfg" version = "1.3.0" @@ -1086,6 +1101,12 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" +[[package]] +name = "difflib" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" + [[package]] name = "digest" version = "0.10.7" @@ -1188,6 +1209,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + [[package]] name = "either" version = "1.12.0" @@ -2317,6 +2344,33 @@ dependencies = [ "topological-sort", ] +[[package]] +name = "mdbook-trpl-listing" +version = "0.1.0" +dependencies = [ + "assert_cmd", + "clap", + "mdbook", + "pulldown-cmark 0.10.3", + "pulldown-cmark-to-cmark", + "serde_json", + "thiserror", + "toml 0.8.13", + "xmlparser", +] + +[[package]] +name = "mdbook-trpl-note" +version = "1.0.0" +dependencies = [ + "assert_cmd", + "clap", + "mdbook", + "pulldown-cmark 0.10.3", + "pulldown-cmark-to-cmark", + "serde_json", +] + [[package]] name = "measureme" version = "11.0.1" @@ -2929,6 +2983,33 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" +[[package]] +name = "predicates" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68b87bfd4605926cdfefc1c3b5f8fe560e3feca9d5552cf68c466d3d8236c7e8" +dependencies = [ + "anstyle", + "difflib", + "predicates-core", +] + +[[package]] +name = "predicates-core" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174" + +[[package]] +name = "predicates-tree" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf" +dependencies = [ + "predicates-core", + "termtree", +] + [[package]] name = "prettydiff" version = "0.6.4" @@ -2998,6 +3079,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76979bea66e7875e7509c4ec5300112b316af87fa7a252ca91c448b32dfe3993" dependencies = [ "bitflags 2.5.0", + "getopts", "memchr", "pulldown-cmark-escape", "unicase", @@ -3009,6 +3091,15 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd348ff538bc9caeda7ee8cad2d1d48236a1f443c1fa3913c6a02fe0043b1dd3" +[[package]] +name = "pulldown-cmark-to-cmark" +version = "13.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f609795c8d835f79dcfcf768415b9fb57ef1b74891e99f86e73f43a7a257163b" +dependencies = [ + "pulldown-cmark 0.10.3", +] + [[package]] name = "punycode" version = "0.4.1" @@ -3256,6 +3347,8 @@ dependencies = [ "clap", "env_logger", "mdbook", + "mdbook-trpl-listing", + "mdbook-trpl-note", ] [[package]] @@ -5363,6 +5456,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "termtree" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" + [[package]] name = "test" version = "0.0.0" @@ -5535,7 +5634,19 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit", + "toml_edit 0.19.15", +] + +[[package]] +name = "toml" +version = "0.8.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4e43f8cc456c9704c851ae29c67e17ef65d2c30017c17a9765b89c382dc8bba" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.22.13", ] [[package]] @@ -5557,7 +5668,20 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "winnow", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.22.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c127785850e8c20836d49732ae6abfa47616e60bf9d9f57c43c250361a9db96c" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow 0.6.8", ] [[package]] @@ -5967,6 +6091,15 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + [[package]] name = "walkdir" version = "2.5.0" @@ -6279,6 +6412,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "winnow" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3c52e9c97a68071b23e836c9380edae937f17b9c4667bd021973efc689f618d" +dependencies = [ + "memchr", +] + [[package]] name = "writeable" version = "0.5.4" @@ -6296,6 +6438,12 @@ dependencies = [ "rustix", ] +[[package]] +name = "xmlparser" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4" + [[package]] name = "xz2" version = "0.1.7" diff --git a/src/doc/book b/src/doc/book index 5e9051f71638..85442a608426 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 5e9051f71638aa941cd5dda465e25c61cde9594f +Subproject commit 85442a608426d3667f1c9458ad457b241a36b569 diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml index 2ef9004c476e..2b0dd0062b90 100644 --- a/src/tools/rustbook/Cargo.toml +++ b/src/tools/rustbook/Cargo.toml @@ -7,6 +7,8 @@ edition = "2021" [dependencies] clap = "4.0.32" env_logger = "0.11" +mdbook-trpl-listing = { path = "../../doc/book/packages/mdbook-trpl-listing" } +mdbook-trpl-note = { path = "../../doc/book/packages/mdbook-trpl-note" } [dependencies.mdbook] version = "0.4.37" diff --git a/src/tools/rustbook/src/main.rs b/src/tools/rustbook/src/main.rs index 1368ec653de1..9a06754e4a66 100644 --- a/src/tools/rustbook/src/main.rs +++ b/src/tools/rustbook/src/main.rs @@ -8,6 +8,9 @@ use clap::{arg, ArgMatches, Command}; use mdbook::errors::Result as Result3; use mdbook::MDBook; +use mdbook_trpl_listing::TrplListing; +use mdbook_trpl_note::TrplNote; + fn main() { let crate_version = concat!("v", crate_version!()); env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("warn")).init(); @@ -67,6 +70,14 @@ pub fn build(args: &ArgMatches) -> Result3<()> { book.config.build.build_dir = dest_dir.into(); } + if book.config.get_preprocessor("trpl-note").is_some() { + book.with_preprocessor(TrplNote); + } + + if book.config.get_preprocessor("trpl-listing").is_some() { + book.with_preprocessor(TrplListing); + } + book.build()?; Ok(()) From cfa150b0ddc28ea3723a3b4d0916e729dcea3246 Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Wed, 22 May 2024 18:03:18 -0700 Subject: [PATCH 032/211] Rephrase and expand `empty_enum` documentation. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Remove incorrect claim that “wrappers around it are the conventional way to define an uninhabited type”. * Discuss why one would use `!`, a newtype struct, or keep the enum. * Add links to relevant documentation. --- clippy_lints/src/empty_enum.rs | 45 +++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/clippy_lints/src/empty_enum.rs b/clippy_lints/src/empty_enum.rs index 420888b6ccb3..d16714695cb7 100644 --- a/clippy_lints/src/empty_enum.rs +++ b/clippy_lints/src/empty_enum.rs @@ -7,32 +7,53 @@ use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does - /// Checks for `enum`s with no variants. + /// Checks for `enum`s with no variants, which therefore are uninhabited types + /// (cannot be instantiated). /// - /// As of this writing, the `never_type` is still a - /// nightly-only experimental API. Therefore, this lint is only triggered - /// if the `never_type` is enabled. + /// As of this writing, the `never_type` is still a nightly-only experimental API. + /// Therefore, this lint is only triggered if `#![feature(never_type)]` is enabled. /// /// ### Why is this bad? - /// If you want to introduce a type which - /// can't be instantiated, you should use `!` (the primitive type "never"), - /// or a wrapper around it, because `!` has more extensive - /// compiler support (type inference, etc...) and wrappers - /// around it are the conventional way to define an uninhabited type. - /// For further information visit [never type documentation](https://doc.rust-lang.org/std/primitive.never.html) + /// * If you only want a type which can’t be instantiated, you should use [`!`] + /// (the primitive type "never"), because [`!`] has more extensive compiler support + /// (type inference, etc.) and implementations of common traits. /// + /// * If you need to introduce a distinct type, consider using a [newtype] `struct` + /// containing [`!`] instead (`struct MyType(pub !)`), because it is more idiomatic + /// to use a `struct` rather than an `enum` when an `enum` is unnecessary. + /// + /// If you do this, note that the [visibility] of the [`!`] field determines whether + /// the uninhabitedness is visible in documentation, and whether it can be pattern + /// matched to mark code unreachable. If the field is not visible, then the struct + /// acts like any other struct with private fields. + /// + /// * If the enum has no variants only because all variants happen to be + /// [disabled by conditional compilation][cfg], then it would be appropriate + /// to allow the lint, with `#[allow(empty_enum)]`. + /// + /// For further information, visit + /// [the never type’s documentation][`!`]. /// /// ### Example /// ```no_run - /// enum Test {} + /// enum CannotExist {} /// ``` /// /// Use instead: /// ```no_run /// #![feature(never_type)] /// - /// struct Test(!); + /// /// Use the `!` type directly... + /// type CannotExist = !; + /// + /// /// ...or define a newtype which is distinct. + /// struct CannotExist2(pub !); /// ``` + /// + /// [`!`]: https://doc.rust-lang.org/std/primitive.never.html + /// [cfg]: https://doc.rust-lang.org/reference/conditional-compilation.html + /// [newtype]: https://doc.rust-lang.org/book/ch19-04-advanced-types.html#using-the-newtype-pattern-for-type-safety-and-abstraction + /// [visibility]: https://doc.rust-lang.org/reference/visibility-and-privacy.html #[clippy::version = "pre 1.29.0"] pub EMPTY_ENUM, pedantic, From 273a78b05be72a4609d68740708d27fdeacd29f6 Mon Sep 17 00:00:00 2001 From: Gurinder Singh Date: Thu, 23 May 2024 07:23:59 +0530 Subject: [PATCH 033/211] Do not suggest unresolvable builder methods --- compiler/rustc_hir_typeck/src/expr.rs | 1 + .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 1 + .../rustc_hir_typeck/src/method/suggest.rs | 26 ++++++-- tests/ui/resolve/fn-new-doesnt-exist.rs | 5 -- tests/ui/resolve/fn-new-doesnt-exist.stderr | 14 ---- tests/ui/resolve/suggest-builder-fn.rs | 64 +++++++++++++++++++ tests/ui/resolve/suggest-builder-fn.stderr | 51 +++++++++++++++ tests/ui/suggestions/deref-path-method.stderr | 2 +- tests/ui/suggestions/issue-109291.stderr | 1 - tests/ui/ufcs/bad-builder.stderr | 2 +- 10 files changed, 141 insertions(+), 26 deletions(-) delete mode 100644 tests/ui/resolve/fn-new-doesnt-exist.rs delete mode 100644 tests/ui/resolve/fn-new-doesnt-exist.stderr create mode 100644 tests/ui/resolve/suggest-builder-fn.rs create mode 100644 tests/ui/resolve/suggest-builder-fn.stderr diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index fade943c5ae3..9c3f62e85f58 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1349,6 +1349,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some(rcvr), rcvr_t, segment.ident, + expr.hir_id, SelfSource::MethodCall(rcvr), error, Some(args), diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 77f90c0c1310..3f67f0f5f045 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -837,6 +837,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None, ty.normalized, item_name, + hir_id, SelfSource::QPath(qself), error, args, diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 54af8354c4c7..440dcbf08948 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -191,6 +191,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rcvr_opt: Option<&'tcx hir::Expr<'tcx>>, rcvr_ty: Ty<'tcx>, item_name: Ident, + expr_id: hir::HirId, source: SelfSource<'tcx>, error: MethodError<'tcx>, args: Option<&'tcx [hir::Expr<'tcx>]>, @@ -216,6 +217,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rcvr_opt, rcvr_ty, item_name, + expr_id, source, args, sugg_span, @@ -551,6 +553,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rcvr_opt: Option<&'tcx hir::Expr<'tcx>>, rcvr_ty: Ty<'tcx>, item_name: Ident, + expr_id: hir::HirId, source: SelfSource<'tcx>, args: Option<&'tcx [hir::Expr<'tcx>]>, sugg_span: Span, @@ -683,7 +686,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if matches!(source, SelfSource::QPath(_)) && args.is_some() { - self.find_builder_fn(&mut err, rcvr_ty); + self.find_builder_fn(&mut err, rcvr_ty, expr_id); } if tcx.ty_is_opaque_future(rcvr_ty) && item_name.name == sym::poll { @@ -1944,7 +1947,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Look at all the associated functions without receivers in the type's inherent impls /// to look for builders that return `Self`, `Option` or `Result`. - fn find_builder_fn(&self, err: &mut Diag<'_>, rcvr_ty: Ty<'tcx>) { + fn find_builder_fn(&self, err: &mut Diag<'_>, rcvr_ty: Ty<'tcx>, expr_id: hir::HirId) { let ty::Adt(adt_def, _) = rcvr_ty.kind() else { return; }; @@ -1953,8 +1956,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut items = impls .iter() .flat_map(|i| self.tcx.associated_items(i).in_definition_order()) - // Only assoc fn with no receivers. - .filter(|item| matches!(item.kind, ty::AssocKind::Fn) && !item.fn_has_self_parameter) + // Only assoc fn with no receivers and only if + // they are resolvable + .filter(|item| { + matches!(item.kind, ty::AssocKind::Fn) + && !item.fn_has_self_parameter + && self + .probe_for_name( + Mode::Path, + item.ident(self.tcx), + None, + IsSuggestion(true), + rcvr_ty, + expr_id, + ProbeScope::TraitsInScope, + ) + .is_ok() + }) .filter_map(|item| { // Only assoc fns that return `Self`, `Option` or `Result`. let ret_ty = self diff --git a/tests/ui/resolve/fn-new-doesnt-exist.rs b/tests/ui/resolve/fn-new-doesnt-exist.rs deleted file mode 100644 index 4f6290808fc0..000000000000 --- a/tests/ui/resolve/fn-new-doesnt-exist.rs +++ /dev/null @@ -1,5 +0,0 @@ -use std::net::TcpStream; - -fn main() { - let stream = TcpStream::new(); //~ ERROR no function or associated item named `new` found -} diff --git a/tests/ui/resolve/fn-new-doesnt-exist.stderr b/tests/ui/resolve/fn-new-doesnt-exist.stderr deleted file mode 100644 index 418dd9ea6b84..000000000000 --- a/tests/ui/resolve/fn-new-doesnt-exist.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0599]: no function or associated item named `new` found for struct `TcpStream` in the current scope - --> $DIR/fn-new-doesnt-exist.rs:4:28 - | -LL | let stream = TcpStream::new(); - | ^^^ function or associated item not found in `TcpStream` - | -note: if you're trying to build a new `TcpStream` consider using one of the following associated functions: - TcpStream::connect - TcpStream::connect_timeout - --> $SRC_DIR/std/src/net/tcp.rs:LL:COL - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/resolve/suggest-builder-fn.rs b/tests/ui/resolve/suggest-builder-fn.rs new file mode 100644 index 000000000000..0d9b35549a47 --- /dev/null +++ b/tests/ui/resolve/suggest-builder-fn.rs @@ -0,0 +1,64 @@ +// Tests that we suggest the right alternatives when +// a builder method cannot be resolved + +use std::net::TcpStream; + +trait SomeTrait {} + +struct Foo { + v : T +} + +impl Foo { + // Should not be suggested if constraint on the impl not met + fn new() -> Self { + Self { v: T::default() } + } +} + +struct Bar; + +impl Bar { + // Should be suggested + fn build() -> Self { + Self {} + } + + // Method with self can't be a builder. + // Should not be suggested + fn build_with_self(&self) -> Self { + Self {} + } +} + +mod SomeMod { + use Bar; + + impl Bar { + // Public method. Should be suggested + pub fn build_public() -> Self { + Self {} + } + + // Private method. Should not be suggested + fn build_private() -> Self { + Self {} + } + } +} + +fn main() { + // `new` not found on `TcpStream` and `connect` should be suggested + let _stream = TcpStream::new(); + //~^ ERROR no function or associated item named `new` found + + // Although `new` is found on `>` it should not be + // suggested because `u8` does not meet the `T: SomeTrait` constraint + let _foo = Foo::::new(); + //~^ ERROR the function or associated item `new` exists for struct `Foo`, but its trait bounds were not satisfied + + // Should suggest only `::build()` and `SomeMod::::build_public()`. + // Other methods should not suggested because they are private or are not a builder + let _bar = Bar::new(); + //~^ ERROR no function or associated item named `new` found +} diff --git a/tests/ui/resolve/suggest-builder-fn.stderr b/tests/ui/resolve/suggest-builder-fn.stderr new file mode 100644 index 000000000000..9c5eed35ccff --- /dev/null +++ b/tests/ui/resolve/suggest-builder-fn.stderr @@ -0,0 +1,51 @@ +error[E0599]: no function or associated item named `new` found for struct `TcpStream` in the current scope + --> $DIR/suggest-builder-fn.rs:52:29 + | +LL | let _stream = TcpStream::new(); + | ^^^ function or associated item not found in `TcpStream` + | +note: if you're trying to build a new `TcpStream` consider using one of the following associated functions: + TcpStream::connect + TcpStream::connect_timeout + --> $SRC_DIR/std/src/net/tcp.rs:LL:COL + +error[E0599]: the function or associated item `new` exists for struct `Foo`, but its trait bounds were not satisfied + --> $DIR/suggest-builder-fn.rs:57:27 + | +LL | struct Foo { + | ------------- function or associated item `new` not found for this struct +... +LL | let _foo = Foo::::new(); + | ^^^ function or associated item cannot be called on `Foo` due to unsatisfied trait bounds + | +note: trait bound `u8: SomeTrait` was not satisfied + --> $DIR/suggest-builder-fn.rs:12:9 + | +LL | impl Foo { + | ^^^^^^^^^ ------ + | | + | unsatisfied trait bound introduced here + +error[E0599]: no function or associated item named `new` found for struct `Bar` in the current scope + --> $DIR/suggest-builder-fn.rs:62:21 + | +LL | struct Bar; + | ---------- function or associated item `new` not found for this struct +... +LL | let _bar = Bar::new(); + | ^^^ function or associated item not found in `Bar` + | +note: if you're trying to build a new `Bar` consider using one of the following associated functions: + Bar::build + SomeMod::::build_public + --> $DIR/suggest-builder-fn.rs:23:5 + | +LL | fn build() -> Self { + | ^^^^^^^^^^^^^^^^^^ +... +LL | pub fn build_public() -> Self { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/suggestions/deref-path-method.stderr b/tests/ui/suggestions/deref-path-method.stderr index bfcc2307fd7f..b27d9aef0661 100644 --- a/tests/ui/suggestions/deref-path-method.stderr +++ b/tests/ui/suggestions/deref-path-method.stderr @@ -9,7 +9,7 @@ note: if you're trying to build a new `Vec<_, _>` consider using one of the foll Vec::::with_capacity Vec::::try_with_capacity Vec::::from_raw_parts - and 6 others + and 4 others --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL help: the function `contains` is implemented on `[_]` | diff --git a/tests/ui/suggestions/issue-109291.stderr b/tests/ui/suggestions/issue-109291.stderr index a173bbbb4900..d4a9351af3a8 100644 --- a/tests/ui/suggestions/issue-109291.stderr +++ b/tests/ui/suggestions/issue-109291.stderr @@ -8,7 +8,6 @@ note: if you're trying to build a new `Backtrace` consider using one of the foll Backtrace::capture Backtrace::force_capture Backtrace::disabled - Backtrace::create --> $SRC_DIR/std/src/backtrace.rs:LL:COL help: there is an associated function `force_capture` with a similar name | diff --git a/tests/ui/ufcs/bad-builder.stderr b/tests/ui/ufcs/bad-builder.stderr index e466f94d0d84..9cfeb7a5d09d 100644 --- a/tests/ui/ufcs/bad-builder.stderr +++ b/tests/ui/ufcs/bad-builder.stderr @@ -9,7 +9,7 @@ note: if you're trying to build a new `Vec` consider using one of the followi Vec::::with_capacity Vec::::try_with_capacity Vec::::from_raw_parts - and 6 others + and 4 others --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL help: there is an associated function `new` with a similar name | From 0c653d9f91ad8211701ce685b6cb2a2df1253df2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Wed, 22 May 2024 16:46:05 +0200 Subject: [PATCH 034/211] Remove `LintDiagnostic::msg` * instead simply set the primary message inside the lint decorator functions * it used to be this way before [#]101986 which introduced `msg` to prevent good path delayed bugs (which no longer exist) from firing under certain circumstances when lints were suppressed / silenced * this is no longer necessary for various reasons I presume * it shaves off complexity and makes further changes easier to implement --- clippy_utils/src/diagnostics.rs | 18 ++++++++++++------ tests/ui-internal/disallow_span_lint.rs | 4 ++-- tests/ui-internal/disallow_span_lint.stderr | 8 ++++---- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/clippy_utils/src/diagnostics.rs b/clippy_utils/src/diagnostics.rs index dc0a139e3c78..0641d37cd9a6 100644 --- a/clippy_utils/src/diagnostics.rs +++ b/clippy_utils/src/diagnostics.rs @@ -61,7 +61,8 @@ fn docs_link(diag: &mut Diag<'_, ()>, lint: &'static Lint) { /// ``` pub fn span_lint(cx: &T, lint: &'static Lint, sp: impl Into, msg: impl Into) { #[expect(clippy::disallowed_methods)] - cx.span_lint(lint, sp, msg.into(), |diag| { + cx.span_lint(lint, sp, |diag| { + diag.primary_message(msg); docs_link(diag, lint); }); } @@ -109,7 +110,8 @@ pub fn span_lint_and_help( help: impl Into, ) { #[expect(clippy::disallowed_methods)] - cx.span_lint(lint, span, msg.into(), |diag| { + cx.span_lint(lint, span, |diag| { + diag.primary_message(msg); if let Some(help_span) = help_span { diag.span_help(help_span, help.into()); } else { @@ -165,7 +167,8 @@ pub fn span_lint_and_note( note: impl Into, ) { #[expect(clippy::disallowed_methods)] - cx.span_lint(lint, span, msg.into(), |diag| { + cx.span_lint(lint, span, |diag| { + diag.primary_message(msg); if let Some(note_span) = note_span { diag.span_note(note_span, note.into()); } else { @@ -201,7 +204,8 @@ where F: FnOnce(&mut Diag<'_, ()>), { #[expect(clippy::disallowed_methods)] - cx.span_lint(lint, sp, msg, |diag| { + cx.span_lint(lint, sp, |diag| { + diag.primary_message(msg); f(diag); docs_link(diag, lint); }); @@ -233,7 +237,8 @@ where /// the `#[allow]` will work. pub fn span_lint_hir(cx: &LateContext<'_>, lint: &'static Lint, hir_id: HirId, sp: Span, msg: impl Into) { #[expect(clippy::disallowed_methods)] - cx.tcx.node_span_lint(lint, hir_id, sp, msg.into(), |diag| { + cx.tcx.node_span_lint(lint, hir_id, sp, |diag| { + diag.primary_message(msg); docs_link(diag, lint); }); } @@ -271,7 +276,8 @@ pub fn span_lint_hir_and_then( f: impl FnOnce(&mut Diag<'_, ()>), ) { #[expect(clippy::disallowed_methods)] - cx.tcx.node_span_lint(lint, hir_id, sp, msg.into(), |diag| { + cx.tcx.node_span_lint(lint, hir_id, sp, |diag| { + diag.primary_message(msg); f(diag); docs_link(diag, lint); }); diff --git a/tests/ui-internal/disallow_span_lint.rs b/tests/ui-internal/disallow_span_lint.rs index 5a2a868ed3ec..b91a83308b5f 100644 --- a/tests/ui-internal/disallow_span_lint.rs +++ b/tests/ui-internal/disallow_span_lint.rs @@ -11,11 +11,11 @@ use rustc_lint::{Lint, LintContext}; use rustc_middle::ty::TyCtxt; pub fn a(cx: impl LintContext, lint: &'static Lint, span: impl Into, msg: impl Into) { - cx.span_lint(lint, span, msg, |_| {}); + cx.span_lint(lint, span, |lint| { lint.primary_message(msg); }); } pub fn b(tcx: TyCtxt<'_>, lint: &'static Lint, hir_id: HirId, span: impl Into, msg: impl Into) { - tcx.node_span_lint(lint, hir_id, span, msg, |_| {}); + tcx.node_span_lint(lint, hir_id, span, |lint| { lint.primary_message(msg); }); } fn main() {} diff --git a/tests/ui-internal/disallow_span_lint.stderr b/tests/ui-internal/disallow_span_lint.stderr index cfc590bed369..1cfbc8efc8ed 100644 --- a/tests/ui-internal/disallow_span_lint.stderr +++ b/tests/ui-internal/disallow_span_lint.stderr @@ -1,8 +1,8 @@ error: use of a disallowed method `rustc_lint::context::LintContext::span_lint` --> tests/ui-internal/disallow_span_lint.rs:14:5 | -LL | cx.span_lint(lint, span, msg, |_| {}); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | cx.span_lint(lint, span, |lint| { lint.primary_message(msg); }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this function does not add a link to our documentation, please use the `clippy_utils::diagnostics::span_lint*` functions instead (from clippy.toml) = note: `-D clippy::disallowed-methods` implied by `-D warnings` @@ -11,8 +11,8 @@ LL | cx.span_lint(lint, span, msg, |_| {}); error: use of a disallowed method `rustc_middle::ty::context::TyCtxt::node_span_lint` --> tests/ui-internal/disallow_span_lint.rs:18:5 | -LL | tcx.node_span_lint(lint, hir_id, span, msg, |_| {}); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | tcx.node_span_lint(lint, hir_id, span, |lint| { lint.primary_message(msg); }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this function does not add a link to our documentation, please use the `clippy_utils::diagnostics::span_lint_hir*` functions instead (from clippy.toml) From 9244dbff769f7afc3a0b54d63e2ed0ade06c42cd Mon Sep 17 00:00:00 2001 From: maxwase Date: Sat, 18 May 2024 19:37:04 +0300 Subject: [PATCH 035/211] Add toggle_async_sugar assist code action --- .../src/handlers/toggle_async_sugar.rs | 460 ++++++++++++++++++ .../crates/ide-assists/src/lib.rs | 2 + .../crates/ide-assists/src/tests/generated.rs | 17 + .../crates/ide-db/src/famous_defs.rs | 4 + 4 files changed, 483 insertions(+) create mode 100644 src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_async_sugar.rs diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_async_sugar.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_async_sugar.rs new file mode 100644 index 000000000000..ea127d65e54b --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_async_sugar.rs @@ -0,0 +1,460 @@ +use ide_db::{ + assists::{AssistId, AssistKind}, + famous_defs::FamousDefs, +}; +use syntax::{ + ast::{self, HasVisibility}, + AstNode, NodeOrToken, SyntaxKind, SyntaxNode, SyntaxToken, TextRange, +}; + +use crate::{AssistContext, Assists}; + +// Assist: toggle_async_sugar +// +// Rewrites asynchronous function into `impl Future` and back. +// This action does not touch the function body and therefore `async { 0 }` +// block does not transform to just `0`. +// +// ``` +// pub async f$0n foo() -> usize { +// 0 +// } +// ``` +// -> +// ``` +// pub fn foo() -> impl Future { +// 0 +// } +// ``` +pub(crate) fn toggle_async_sugar(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { + let function: ast::Fn = ctx.find_node_at_offset()?; + match (function.async_token(), function.ret_type()) { + // async function returning futures cannot be flattened + // const async is not yet supported + (None, Some(ret_type)) if function.const_token().is_none() => { + add_async(acc, ctx, function, ret_type) + } + (Some(async_token), ret_type) => remove_async(function, ret_type, acc, async_token), + _ => None, + } +} + +fn add_async( + acc: &mut Assists, + ctx: &AssistContext<'_>, + function: ast::Fn, + ret_type: ast::RetType, +) -> Option<()> { + let ast::Type::ImplTraitType(return_impl_trait) = ret_type.ty()? else { + return None; + }; + + let main_trait_path = return_impl_trait + .type_bound_list()? + .bounds() + .filter_map(|bound| match bound.ty() { + Some(ast::Type::PathType(trait_path)) => trait_path.path(), + _ => None, + }) + .next()?; + + let trait_type = ctx.sema.resolve_trait(&main_trait_path)?; + let scope = ctx.sema.scope(main_trait_path.syntax())?; + if trait_type != FamousDefs(&ctx.sema, scope.krate()).core_future_Future()? { + return None; + } + let future_output = unwrap_future_output(main_trait_path)?; + + acc.add( + AssistId("toggle_async_sugar", AssistKind::RefactorRewrite), + "Convert `impl Future` into async", + function.syntax().text_range(), + |builder| { + match future_output { + ast::Type::TupleType(_) => { + let mut ret_type_range = ret_type.syntax().text_range(); + + // find leftover whitespace + let whitespace_range = function + .param_list() + .as_ref() + .map(|params| NodeOrToken::Node(params.syntax())) + .and_then(following_whitespace); + + if let Some(whitespace_range) = whitespace_range { + ret_type_range = + TextRange::new(whitespace_range.start(), ret_type_range.end()); + } + + builder.delete(ret_type_range); + } + _ => { + builder.replace( + return_impl_trait.syntax().text_range(), + future_output.syntax().text(), + ); + } + } + + let (place_for_async, async_kw) = match function.visibility() { + Some(vis) => (vis.syntax().text_range().end(), " async"), + None => (function.syntax().text_range().start(), "async "), + }; + builder.insert(place_for_async, async_kw); + }, + ) +} + +fn remove_async( + function: ast::Fn, + ret_type: Option, + acc: &mut Assists, + async_token: SyntaxToken, +) -> Option<()> { + let rparen = function.param_list()?.r_paren_token()?; + let return_type = match ret_type { + // unable to get a `ty` makes the action unapplicable + Some(ret_type) => Some(ret_type.ty()?), + // No type means `-> ()` + None => None, + }; + + acc.add( + AssistId("toggle_async_sugar", AssistKind::RefactorRewrite), + "Convert async into `impl Future`", + function.syntax().text_range(), + |builder| { + let mut async_range = async_token.text_range(); + + if let Some(whitespace_range) = following_whitespace(NodeOrToken::Token(async_token)) { + async_range = TextRange::new(async_range.start(), whitespace_range.end()); + } + builder.delete(async_range); + + match return_type { + Some(ret_type) => builder.replace( + ret_type.syntax().text_range(), + format!("impl Future"), + ), + None => builder.insert(rparen.text_range().end(), " -> impl Future"), + } + }, + ) +} + +fn unwrap_future_output(path: ast::Path) -> Option { + let future_trait = path.segments().last()?; + let assoc_list = future_trait.generic_arg_list()?; + let future_assoc = assoc_list.generic_args().next()?; + match future_assoc { + ast::GenericArg::AssocTypeArg(output_type) => output_type.ty(), + _ => None, + } +} + +fn following_whitespace(nt: NodeOrToken<&SyntaxNode, SyntaxToken>) -> Option { + let next_token = match nt { + NodeOrToken::Node(node) => node.next_sibling_or_token(), + NodeOrToken::Token(token) => token.next_sibling_or_token(), + }?; + (next_token.kind() == SyntaxKind::WHITESPACE).then_some(next_token.text_range()) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::tests::{check_assist, check_assist_not_applicable}; + + #[test] + fn sugar_with_use() { + check_assist( + toggle_async_sugar, + r#" + //- minicore: future + use core::future::Future; + f$0n foo() -> impl Future { + todo!() + } + "#, + r#" + use core::future::Future; + async fn foo() { + todo!() + } + "#, + ); + + check_assist( + toggle_async_sugar, + r#" + //- minicore: future + use core::future::Future; + f$0n foo() -> impl Future { + todo!() + } + "#, + r#" + use core::future::Future; + async fn foo() -> usize { + todo!() + } + "#, + ); + } + + #[test] + fn desugar_with_use() { + check_assist( + toggle_async_sugar, + r#" + //- minicore: future + use core::future::Future; + async f$0n foo() { + todo!() + } + "#, + r#" + use core::future::Future; + fn foo() -> impl Future { + todo!() + } + "#, + ); + + check_assist( + toggle_async_sugar, + r#" + //- minicore: future + use core::future::Future; + async f$0n foo() -> usize { + todo!() + } + "#, + r#" + use core::future::Future; + fn foo() -> impl Future { + todo!() + } + "#, + ); + } + + #[test] + fn sugar_without_use() { + check_assist( + toggle_async_sugar, + r#" + //- minicore: future + f$0n foo() -> impl core::future::Future { + todo!() + } + "#, + r#" + async fn foo() { + todo!() + } + "#, + ); + + check_assist( + toggle_async_sugar, + r#" + //- minicore: future + f$0n foo() -> impl core::future::Future { + todo!() + } + "#, + r#" + async fn foo() -> usize { + todo!() + } + "#, + ); + } + + #[test] + fn desugar_without_use() { + check_assist( + toggle_async_sugar, + r#" + //- minicore: future + async f$0n foo() { + todo!() + } + "#, + r#" + fn foo() -> impl Future { + todo!() + } + "#, + ); + + check_assist( + toggle_async_sugar, + r#" + //- minicore: future + async f$0n foo() -> usize { + todo!() + } + "#, + r#" + fn foo() -> impl Future { + todo!() + } + "#, + ); + } + + #[test] + fn sugar_not_applicable() { + check_assist_not_applicable( + toggle_async_sugar, + r#" + //- minicore: future + trait Future { + type Output; + } + f$0n foo() -> impl Future { + todo!() + } + "#, + ); + + check_assist_not_applicable( + toggle_async_sugar, + r#" + //- minicore: future + trait Future { + type Output; + } + f$0n foo() -> impl Future { + todo!() + } + "#, + ); + } + + #[test] + fn sugar_definition_with_use() { + check_assist( + toggle_async_sugar, + r#" + //- minicore: future + use core::future::Future; + f$0n foo() -> impl Future; + "#, + r#" + use core::future::Future; + async fn foo(); + "#, + ); + + check_assist( + toggle_async_sugar, + r#" + //- minicore: future + use core::future::Future; + f$0n foo() -> impl Future; + "#, + r#" + use core::future::Future; + async fn foo() -> usize; + "#, + ); + } + + #[test] + fn sugar_definition_without_use() { + check_assist( + toggle_async_sugar, + r#" + //- minicore: future + f$0n foo() -> impl core::future::Future; + "#, + r#" + async fn foo(); + "#, + ); + + check_assist( + toggle_async_sugar, + r#" + //- minicore: future + f$0n foo() -> impl core::future::Future; + "#, + r#" + async fn foo() -> usize; + "#, + ); + } + + #[test] + fn sugar_with_modifiers() { + check_assist_not_applicable( + toggle_async_sugar, + r#" + //- minicore: future + const f$0n foo() -> impl core::future::Future; + "#, + ); + + check_assist( + toggle_async_sugar, + r#" + //- minicore: future + pub(crate) unsafe f$0n foo() -> impl core::future::Future; + "#, + r#" + pub(crate) async unsafe fn foo() -> usize; + "#, + ); + + check_assist( + toggle_async_sugar, + r#" + //- minicore: future + unsafe f$0n foo() -> impl core::future::Future; + "#, + r#" + async unsafe fn foo(); + "#, + ); + + check_assist( + toggle_async_sugar, + r#" + //- minicore: future + unsafe extern "C" f$0n foo() -> impl core::future::Future; + "#, + r#" + async unsafe extern "C" fn foo(); + "#, + ); + + check_assist( + toggle_async_sugar, + r#" + //- minicore: future + f$0n foo() -> impl core::future::Future; + "#, + r#" + async fn foo() -> T; + "#, + ); + + check_assist( + toggle_async_sugar, + r#" + //- minicore: future + f$0n foo() -> impl core::future::Future + where + T: Sized; + "#, + r#" + async fn foo() -> T + where + T: Sized; + "#, + ); + } +} diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs index 0df5e913a573..d26ac23099a7 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs @@ -209,6 +209,7 @@ mod handlers { mod sort_items; mod split_import; mod term_search; + mod toggle_async_sugar; mod toggle_ignore; mod unmerge_match_arm; mod unmerge_use; @@ -238,6 +239,7 @@ mod handlers { change_visibility::change_visibility, convert_bool_then::convert_bool_then_to_if, convert_bool_then::convert_if_to_bool_then, + toggle_async_sugar::toggle_async_sugar, convert_comment_block::convert_comment_block, convert_from_to_tryfrom::convert_from_to_tryfrom, convert_integer_literal::convert_integer_literal, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs index 937e78f8d7d2..8e0d1bd667a6 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs @@ -3020,6 +3020,23 @@ use std::{collections::HashMap}; ) } +#[test] +fn doctest_toggle_async_sugar() { + check_doc_test( + "toggle_async_sugar", + r#####" +pub async f$0n foo() -> usize { + 0 +} +"#####, + r#####" +pub fn foo() -> impl Future { + 0 +} +"#####, + ) +} + #[test] fn doctest_toggle_ignore() { check_doc_test( diff --git a/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs b/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs index 3106772e63b1..e445e9fb68d6 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs @@ -106,6 +106,10 @@ impl FamousDefs<'_, '_> { self.find_trait("core:marker:Copy") } + pub fn core_future_Future(&self) -> Option { + self.find_trait("core:future:Future") + } + pub fn core_macros_builtin_derive(&self) -> Option { self.find_macro("core:macros:builtin:derive") } From 9cf35f1262c36dcd5c0f25a2875295df9e2ec856 Mon Sep 17 00:00:00 2001 From: maxwase Date: Fri, 24 May 2024 01:10:18 +0300 Subject: [PATCH 036/211] Review fixes: Split into 2, check tuple fields --- .../src/handlers/toggle_async_sugar.rs | 161 ++++++++++++------ .../crates/ide-assists/src/lib.rs | 3 +- .../crates/ide-assists/src/tests/generated.rs | 30 +++- 3 files changed, 137 insertions(+), 57 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_async_sugar.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_async_sugar.rs index ea127d65e54b..356e1d50ae89 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_async_sugar.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_async_sugar.rs @@ -9,42 +9,38 @@ use syntax::{ use crate::{AssistContext, Assists}; -// Assist: toggle_async_sugar +// Assist: sugar_impl_future_into_async // -// Rewrites asynchronous function into `impl Future` and back. +// Rewrites asynchronous function from `impl Future` to `async fn`. // This action does not touch the function body and therefore `async { 0 }` // block does not transform to just `0`. // // ``` -// pub async f$0n foo() -> usize { -// 0 +// # //- minicore: future +// pub f$0n foo() -> impl core::future::Future { +// async { 0 } // } // ``` // -> // ``` -// pub fn foo() -> impl Future { -// 0 +// pub async fn foo() -> usize { +// async { 0 } // } // ``` -pub(crate) fn toggle_async_sugar(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { - let function: ast::Fn = ctx.find_node_at_offset()?; - match (function.async_token(), function.ret_type()) { - // async function returning futures cannot be flattened - // const async is not yet supported - (None, Some(ret_type)) if function.const_token().is_none() => { - add_async(acc, ctx, function, ret_type) - } - (Some(async_token), ret_type) => remove_async(function, ret_type, acc, async_token), - _ => None, - } -} - -fn add_async( +pub(crate) fn sugar_impl_future_into_async( acc: &mut Assists, ctx: &AssistContext<'_>, - function: ast::Fn, - ret_type: ast::RetType, ) -> Option<()> { + let function: ast::Fn = ctx.find_node_at_offset()?; + if function.async_token().is_some() { + return None; + } + + let ret_type = function.ret_type()?; + if function.const_token().is_some() { + return None; + } + let ast::Type::ImplTraitType(return_impl_trait) = ret_type.ty()? else { return None; }; @@ -66,12 +62,12 @@ fn add_async( let future_output = unwrap_future_output(main_trait_path)?; acc.add( - AssistId("toggle_async_sugar", AssistKind::RefactorRewrite), + AssistId("sugar_impl_future_into_async", AssistKind::RefactorRewrite), "Convert `impl Future` into async", function.syntax().text_range(), |builder| { match future_output { - ast::Type::TupleType(_) => { + ast::Type::TupleType(t) if t.fields().next().is_none() => { let mut ret_type_range = ret_type.syntax().text_range(); // find leftover whitespace @@ -105,14 +101,32 @@ fn add_async( ) } -fn remove_async( - function: ast::Fn, - ret_type: Option, +// Assist: desugar_async_into_impl_future +// +// Rewrites asynchronous function from `async fn` to `impl Future`. +// This action does not touch the function body and therefore `0` +// block does not transform to `async { 0 }`. +// +// ``` +// pub async f$0n foo() -> usize { +// 0 +// } +// ``` +// -> +// ``` +// pub fn foo() -> impl Future { +// 0 +// } +// ``` +pub(crate) fn desugar_async_into_impl_future( acc: &mut Assists, - async_token: SyntaxToken, + ctx: &AssistContext<'_>, ) -> Option<()> { + let function: ast::Fn = ctx.find_node_at_offset()?; + let async_token = function.async_token()?; + let rparen = function.param_list()?.r_paren_token()?; - let return_type = match ret_type { + let return_type = match function.ret_type() { // unable to get a `ty` makes the action unapplicable Some(ret_type) => Some(ret_type.ty()?), // No type means `-> ()` @@ -120,7 +134,7 @@ fn remove_async( }; acc.add( - AssistId("toggle_async_sugar", AssistKind::RefactorRewrite), + AssistId("desugar_async_into_impl_future", AssistKind::RefactorRewrite), "Convert async into `impl Future`", function.syntax().text_range(), |builder| { @@ -168,7 +182,7 @@ mod tests { #[test] fn sugar_with_use() { check_assist( - toggle_async_sugar, + sugar_impl_future_into_async, r#" //- minicore: future use core::future::Future; @@ -185,7 +199,7 @@ mod tests { ); check_assist( - toggle_async_sugar, + sugar_impl_future_into_async, r#" //- minicore: future use core::future::Future; @@ -205,7 +219,7 @@ mod tests { #[test] fn desugar_with_use() { check_assist( - toggle_async_sugar, + desugar_async_into_impl_future, r#" //- minicore: future use core::future::Future; @@ -222,7 +236,7 @@ mod tests { ); check_assist( - toggle_async_sugar, + desugar_async_into_impl_future, r#" //- minicore: future use core::future::Future; @@ -242,7 +256,7 @@ mod tests { #[test] fn sugar_without_use() { check_assist( - toggle_async_sugar, + sugar_impl_future_into_async, r#" //- minicore: future f$0n foo() -> impl core::future::Future { @@ -257,7 +271,7 @@ mod tests { ); check_assist( - toggle_async_sugar, + sugar_impl_future_into_async, r#" //- minicore: future f$0n foo() -> impl core::future::Future { @@ -275,7 +289,7 @@ mod tests { #[test] fn desugar_without_use() { check_assist( - toggle_async_sugar, + desugar_async_into_impl_future, r#" //- minicore: future async f$0n foo() { @@ -290,7 +304,7 @@ mod tests { ); check_assist( - toggle_async_sugar, + desugar_async_into_impl_future, r#" //- minicore: future async f$0n foo() -> usize { @@ -308,7 +322,7 @@ mod tests { #[test] fn sugar_not_applicable() { check_assist_not_applicable( - toggle_async_sugar, + sugar_impl_future_into_async, r#" //- minicore: future trait Future { @@ -321,7 +335,7 @@ mod tests { ); check_assist_not_applicable( - toggle_async_sugar, + sugar_impl_future_into_async, r#" //- minicore: future trait Future { @@ -337,7 +351,7 @@ mod tests { #[test] fn sugar_definition_with_use() { check_assist( - toggle_async_sugar, + sugar_impl_future_into_async, r#" //- minicore: future use core::future::Future; @@ -350,7 +364,7 @@ mod tests { ); check_assist( - toggle_async_sugar, + sugar_impl_future_into_async, r#" //- minicore: future use core::future::Future; @@ -366,7 +380,7 @@ mod tests { #[test] fn sugar_definition_without_use() { check_assist( - toggle_async_sugar, + sugar_impl_future_into_async, r#" //- minicore: future f$0n foo() -> impl core::future::Future; @@ -377,7 +391,7 @@ mod tests { ); check_assist( - toggle_async_sugar, + sugar_impl_future_into_async, r#" //- minicore: future f$0n foo() -> impl core::future::Future; @@ -388,10 +402,57 @@ mod tests { ); } + #[test] + fn sugar_more_types() { + check_assist( + sugar_impl_future_into_async, + r#" + //- minicore: future + f$0n foo() -> impl core::future::Future + Send + Sync; + "#, + r#" + async fn foo(); + "#, + ); + + check_assist( + sugar_impl_future_into_async, + r#" + //- minicore: future + f$0n foo() -> impl core::future::Future + Debug; + "#, + r#" + async fn foo() -> usize; + "#, + ); + + check_assist( + sugar_impl_future_into_async, + r#" + //- minicore: future + f$0n foo() -> impl core::future::Future + Debug; + "#, + r#" + async fn foo() -> (usize); + "#, + ); + + check_assist( + sugar_impl_future_into_async, + r#" + //- minicore: future + f$0n foo() -> impl core::future::Future + Debug; + "#, + r#" + async fn foo() -> (usize, usize); + "#, + ); + } + #[test] fn sugar_with_modifiers() { check_assist_not_applicable( - toggle_async_sugar, + sugar_impl_future_into_async, r#" //- minicore: future const f$0n foo() -> impl core::future::Future; @@ -399,7 +460,7 @@ mod tests { ); check_assist( - toggle_async_sugar, + sugar_impl_future_into_async, r#" //- minicore: future pub(crate) unsafe f$0n foo() -> impl core::future::Future; @@ -410,7 +471,7 @@ mod tests { ); check_assist( - toggle_async_sugar, + sugar_impl_future_into_async, r#" //- minicore: future unsafe f$0n foo() -> impl core::future::Future; @@ -421,7 +482,7 @@ mod tests { ); check_assist( - toggle_async_sugar, + sugar_impl_future_into_async, r#" //- minicore: future unsafe extern "C" f$0n foo() -> impl core::future::Future; @@ -432,7 +493,7 @@ mod tests { ); check_assist( - toggle_async_sugar, + sugar_impl_future_into_async, r#" //- minicore: future f$0n foo() -> impl core::future::Future; @@ -443,7 +504,7 @@ mod tests { ); check_assist( - toggle_async_sugar, + sugar_impl_future_into_async, r#" //- minicore: future f$0n foo() -> impl core::future::Future diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs index d26ac23099a7..34ef341c446d 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs @@ -239,7 +239,8 @@ mod handlers { change_visibility::change_visibility, convert_bool_then::convert_bool_then_to_if, convert_bool_then::convert_if_to_bool_then, - toggle_async_sugar::toggle_async_sugar, + toggle_async_sugar::desugar_async_into_impl_future, + toggle_async_sugar::sugar_impl_future_into_async, convert_comment_block::convert_comment_block, convert_from_to_tryfrom::convert_from_to_tryfrom, convert_integer_literal::convert_integer_literal, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs index 8e0d1bd667a6..5f187880b011 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs @@ -800,6 +800,23 @@ fn main() { ) } +#[test] +fn doctest_desugar_async_into_impl_future() { + check_doc_test( + "desugar_async_into_impl_future", + r#####" +pub async f$0n foo() -> usize { + 0 +} +"#####, + r#####" +pub fn foo() -> impl Future { + 0 +} +"#####, + ) +} + #[test] fn doctest_desugar_doc_comment() { check_doc_test( @@ -3021,17 +3038,18 @@ use std::{collections::HashMap}; } #[test] -fn doctest_toggle_async_sugar() { +fn doctest_sugar_impl_future_into_async() { check_doc_test( - "toggle_async_sugar", + "sugar_impl_future_into_async", r#####" -pub async f$0n foo() -> usize { - 0 +//- minicore: future +pub f$0n foo() -> impl core::future::Future { + async { 0 } } "#####, r#####" -pub fn foo() -> impl Future { - 0 +pub async fn foo() -> usize { + async { 0 } } "#####, ) From 0f5338cd903c715d411dee6af95f076177914e42 Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Wed, 22 May 2024 22:21:01 -0700 Subject: [PATCH 037/211] =?UTF-8?q?For=20restriction=20lints,=20replace=20?= =?UTF-8?q?=E2=80=9CWhy=20is=20this=20bad=3F=E2=80=9D=20with=20=E2=80=9CWh?= =?UTF-8?q?y=20restrict=20this=3F=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `restriction` group contains many lints which are not about necessarily “bad” things, but style choices — perhaps even style choices which contradict conventional Rust style — or are otherwise very situational. This results in silly wording like “Why is this bad? It isn't, but ...”, which I’ve seen confuse a newcomer at least once. To improve this situation, this commit replaces the “Why is this bad?” section heading with “Why restrict this?”, for most, but not all, restriction lints. I left alone the ones whose placement in the restriction group is more incidental. In order to make this make sense, I had to remove the “It isn't, but” texts from the contents of the sections. Sometimes further changes were needed, or there were obvious fixes to make, and I went ahead and made those changes without attempting to split them into another commit, even though many of them are not strictly necessary for the “Why restrict this?” project. --- book/src/development/adding_lints.md | 5 ++++ clippy_dev/src/new_lint.rs | 7 ++++- clippy_lints/src/absolute_paths.rs | 2 +- clippy_lints/src/allow_attributes.rs | 7 ++--- clippy_lints/src/as_conversions.rs | 2 +- clippy_lints/src/asm_syntax.rs | 10 +++---- .../src/assertions_on_result_states.rs | 20 ++++++++++---- clippy_lints/src/attrs/mod.rs | 6 ++--- clippy_lints/src/casts/mod.rs | 6 ++--- clippy_lints/src/create_dir.rs | 6 +++-- clippy_lints/src/dbg_macro.rs | 2 +- clippy_lints/src/default_numeric_fallback.rs | 5 ++-- .../src/default_union_representation.rs | 2 +- clippy_lints/src/disallowed_script_idents.rs | 4 +-- clippy_lints/src/doc/mod.rs | 2 +- clippy_lints/src/drop_forget_ref.rs | 7 ++--- clippy_lints/src/else_if_without_else.rs | 2 +- clippy_lints/src/empty_drop.rs | 2 +- clippy_lints/src/empty_with_brackets.rs | 24 +++++++++++++---- clippy_lints/src/endian_bytes.rs | 15 +++++------ clippy_lints/src/error_impl_error.rs | 2 +- clippy_lints/src/exhaustive_items.rs | 16 ++++++------ clippy_lints/src/exit.rs | 12 +++++---- clippy_lints/src/float_literal.rs | 6 ++--- clippy_lints/src/format_push_string.rs | 2 +- clippy_lints/src/functions/mod.rs | 11 ++++---- clippy_lints/src/if_then_some_else_none.rs | 2 +- clippy_lints/src/implicit_return.rs | 13 +++++----- clippy_lints/src/indexing_slicing.rs | 7 ++--- clippy_lints/src/inherent_impl.rs | 2 +- .../src/integer_division_remainder_used.rs | 6 ++--- clippy_lints/src/iter_over_hash_type.rs | 4 +-- clippy_lints/src/large_include_file.rs | 8 +++--- clippy_lints/src/let_underscore.rs | 9 +++---- clippy_lints/src/literal_representation.rs | 4 +-- clippy_lints/src/loops/mod.rs | 6 ++--- clippy_lints/src/matches/mod.rs | 6 ++--- clippy_lints/src/methods/mod.rs | 21 ++++++++------- clippy_lints/src/min_ident_chars.rs | 7 +++-- clippy_lints/src/misc_early/mod.rs | 6 ++--- clippy_lints/src/missing_assert_message.rs | 2 +- .../src/missing_asserts_for_indexing.rs | 2 +- clippy_lints/src/missing_doc.rs | 4 +-- clippy_lints/src/missing_inline.rs | 19 +++++++++----- clippy_lints/src/missing_trait_methods.rs | 10 +++---- .../src/mixed_read_write_in_expression.rs | 9 ++++--- clippy_lints/src/module_style.rs | 6 ++--- .../src/multiple_unsafe_ops_per_block.rs | 2 +- clippy_lints/src/mutex_atomic.rs | 2 +- clippy_lints/src/operators/mod.rs | 12 ++++----- clippy_lints/src/panic_in_result_fn.rs | 4 +-- clippy_lints/src/panic_unimplemented.rs | 18 ++++++------- clippy_lints/src/partial_pub_fields.rs | 9 ++++--- clippy_lints/src/pattern_type_mismatch.rs | 5 ++-- clippy_lints/src/pub_use.rs | 8 +++--- clippy_lints/src/question_mark_used.rs | 2 +- clippy_lints/src/raw_strings.rs | 6 +++-- clippy_lints/src/redundant_slicing.rs | 2 +- .../src/redundant_type_annotations.rs | 2 +- clippy_lints/src/ref_patterns.rs | 4 ++- clippy_lints/src/same_name_method.rs | 2 +- clippy_lints/src/semicolon_block.rs | 6 ++--- clippy_lints/src/shadow.rs | 26 +++++++++++-------- clippy_lints/src/single_call_fn.rs | 19 +++++++++----- .../src/single_char_lifetime_names.rs | 5 ++-- clippy_lints/src/std_instead_of_core.rs | 12 +++------ clippy_lints/src/strings.rs | 19 +++++++------- .../src/suspicious_xor_used_as_pow.rs | 4 ++- clippy_lints/src/tests_outside_test_module.rs | 4 ++- clippy_lints/src/types/mod.rs | 4 +-- .../src/undocumented_unsafe_blocks.rs | 9 +++---- clippy_lints/src/unicode.rs | 2 +- clippy_lints/src/unnecessary_self_imports.rs | 2 +- clippy_lints/src/unwrap_in_result.rs | 6 +++-- clippy_lints/src/visibility.rs | 4 +-- clippy_lints/src/write.rs | 13 ++++++---- 76 files changed, 306 insertions(+), 245 deletions(-) diff --git a/book/src/development/adding_lints.md b/book/src/development/adding_lints.md index 415022612caa..48c00bcbf341 100644 --- a/book/src/development/adding_lints.md +++ b/book/src/development/adding_lints.md @@ -587,6 +587,11 @@ declare_clippy_lint! { } ``` +If the lint is in the `restriction` group because it lints things that are not +necessarily “bad” but are more of a style choice, then replace the +“Why is this bad?” section heading with “Why restrict this?”, to avoid writing +“Why is this bad? It isn't, but ...”. + Once your lint is merged, this documentation will show up in the [lint list][lint_list]. diff --git a/clippy_dev/src/new_lint.rs b/clippy_dev/src/new_lint.rs index b6481dde4dde..2e56eb8ec15f 100644 --- a/clippy_dev/src/new_lint.rs +++ b/clippy_dev/src/new_lint.rs @@ -331,12 +331,17 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String { } fn get_lint_declaration(name_upper: &str, category: &str) -> String { + let justification_heading = if category == "restriction" { + "Why restrict this?" + } else { + "Why is this bad?" + }; formatdoc!( r#" declare_clippy_lint! {{ /// ### What it does /// - /// ### Why is this bad? + /// ### {justification_heading} /// /// ### Example /// ```no_run diff --git a/clippy_lints/src/absolute_paths.rs b/clippy_lints/src/absolute_paths.rs index 8ba661afeeb6..461117cf965d 100644 --- a/clippy_lints/src/absolute_paths.rs +++ b/clippy_lints/src/absolute_paths.rs @@ -12,7 +12,7 @@ declare_clippy_lint! { /// ### What it does /// Checks for usage of items through absolute paths, like `std::env::current_dir`. /// - /// ### Why is this bad? + /// ### Why restrict this? /// Many codebases have their own style when it comes to importing, but one that is seldom used /// is using absolute paths *everywhere*. This is generally considered unidiomatic, and you /// should add a `use` statement. diff --git a/clippy_lints/src/allow_attributes.rs b/clippy_lints/src/allow_attributes.rs index 39fc49dee377..123d0e51eeee 100644 --- a/clippy_lints/src/allow_attributes.rs +++ b/clippy_lints/src/allow_attributes.rs @@ -19,10 +19,11 @@ declare_clippy_lint! { /// This lint only warns outer attributes (`#[allow]`), as inner attributes /// (`#![allow]`) are usually used to enable or disable lints on a global scale. /// - /// ### Why is this bad? - /// `#[expect]` attributes suppress the lint emission, but emit a warning, if + /// ### Why restrict this? + /// `#[allow]` attributes can linger after their reason for existence is gone. + /// `#[expect]` attributes suppress the lint emission, but emit a warning if /// the expectation is unfulfilled. This can be useful to be notified when the - /// lint is no longer triggered. + /// lint is no longer triggered, which may indicate the attribute can be removed. /// /// ### Example /// ```rust,ignore diff --git a/clippy_lints/src/as_conversions.rs b/clippy_lints/src/as_conversions.rs index e3daf75c3eb6..cfa25005a05e 100644 --- a/clippy_lints/src/as_conversions.rs +++ b/clippy_lints/src/as_conversions.rs @@ -17,7 +17,7 @@ declare_clippy_lint! { /// There is a good explanation the reason why this lint should work in this way and how it is useful /// [in this issue](https://github.com/rust-lang/rust-clippy/issues/5122). /// - /// ### Why is this bad? + /// ### Why restrict this? /// `as` conversions will perform many kinds of /// conversions, including silently lossy conversions and dangerous coercions. /// There are cases when it makes sense to use `as`, so the lint is diff --git a/clippy_lints/src/asm_syntax.rs b/clippy_lints/src/asm_syntax.rs index 7c88bfc97ca4..0db1456d40bf 100644 --- a/clippy_lints/src/asm_syntax.rs +++ b/clippy_lints/src/asm_syntax.rs @@ -65,9 +65,8 @@ declare_clippy_lint! { /// ### What it does /// Checks for usage of Intel x86 assembly syntax. /// - /// ### Why is this bad? - /// The lint has been enabled to indicate a preference - /// for AT&T x86 assembly syntax. + /// ### Why restrict this? + /// To enforce consistent use of AT&T x86 assembly syntax. /// /// ### Example /// @@ -114,9 +113,8 @@ declare_clippy_lint! { /// ### What it does /// Checks for usage of AT&T x86 assembly syntax. /// - /// ### Why is this bad? - /// The lint has been enabled to indicate a preference - /// for Intel x86 assembly syntax. + /// ### Why restrict this? + /// To enforce consistent use of Intel x86 assembly syntax. /// /// ### Example /// diff --git a/clippy_lints/src/assertions_on_result_states.rs b/clippy_lints/src/assertions_on_result_states.rs index aec22965b1b0..7217686dcca5 100644 --- a/clippy_lints/src/assertions_on_result_states.rs +++ b/clippy_lints/src/assertions_on_result_states.rs @@ -16,23 +16,33 @@ declare_clippy_lint! { /// ### What it does /// Checks for `assert!(r.is_ok())` or `assert!(r.is_err())` calls. /// - /// ### Why is this bad? - /// An assertion failure cannot output an useful message of the error. + /// ### Why restrict this? + /// This form of assertion does not show any of the information present in the `Result` + /// other than which variant it isn’t. /// /// ### Known problems /// The suggested replacement decreases the readability of code and log output. /// /// ### Example - /// ```rust,ignore + /// ```rust,no_run /// # let r = Ok::<_, ()>(()); /// assert!(r.is_ok()); - /// # let r = Err::<_, ()>(()); + /// # let r = Err::<(), _>(()); /// assert!(r.is_err()); /// ``` + /// + /// Use instead: + /// + /// ```rust,no_run + /// # let r = Ok::<_, ()>(()); + /// r.unwrap(); + /// # let r = Err::<(), _>(()); + /// r.unwrap_err(); + /// ``` #[clippy::version = "1.64.0"] pub ASSERTIONS_ON_RESULT_STATES, restriction, - "`assert!(r.is_ok())`/`assert!(r.is_err())` gives worse error message than directly calling `r.unwrap()`/`r.unwrap_err()`" + "`assert!(r.is_ok())` or `assert!(r.is_err())` gives worse panic messages than directly calling `r.unwrap()` or `r.unwrap_err()`" } declare_lint_pass!(AssertionsOnResultStates => [ASSERTIONS_ON_RESULT_STATES]); diff --git a/clippy_lints/src/attrs/mod.rs b/clippy_lints/src/attrs/mod.rs index 39f406077995..a24bd5ed44be 100644 --- a/clippy_lints/src/attrs/mod.rs +++ b/clippy_lints/src/attrs/mod.rs @@ -309,9 +309,9 @@ declare_clippy_lint! { /// /// (This requires the `lint_reasons` feature) /// - /// ### Why is this bad? - /// Allowing a lint should always have a reason. This reason should be documented to - /// ensure that others understand the reasoning + /// ### Why restrict this? + /// Justifying each `allow` helps readers understand the reasoning, + /// and may allow removing `allow` attributes if their purpose is obsolete. /// /// ### Example /// ```no_run diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs index bd2c96f01f6f..e60c36ced75d 100644 --- a/clippy_lints/src/casts/mod.rs +++ b/clippy_lints/src/casts/mod.rs @@ -303,7 +303,7 @@ declare_clippy_lint! { /// ### What it does /// Checks for casts of a function pointer to any integer type. /// - /// ### Why is this bad? + /// ### Why restrict this? /// Casting a function pointer to an integer can have surprising results and can occur /// accidentally if parentheses are omitted from a function call. If you aren't doing anything /// low-level with function pointers then you can opt-out of casting functions to integers in @@ -535,8 +535,8 @@ declare_clippy_lint! { /// ### What it does /// Checks for the usage of `as _` conversion using inferred type. /// - /// ### Why is this bad? - /// The conversion might include lossy conversion and dangerous cast that might go + /// ### Why restrict this? + /// The conversion might include lossy conversion or a dangerous cast that might go /// undetected due to the type being inferred. /// /// The lint is allowed by default as using `_` is less wordy than always specifying the type. diff --git a/clippy_lints/src/create_dir.rs b/clippy_lints/src/create_dir.rs index 7a3d5a070912..27c00948a8f2 100644 --- a/clippy_lints/src/create_dir.rs +++ b/clippy_lints/src/create_dir.rs @@ -10,8 +10,10 @@ declare_clippy_lint! { /// ### What it does /// Checks usage of `std::fs::create_dir` and suggest using `std::fs::create_dir_all` instead. /// - /// ### Why is this bad? - /// Sometimes `std::fs::create_dir` is mistakenly chosen over `std::fs::create_dir_all`. + /// ### Why restrict this? + /// Sometimes `std::fs::create_dir` is mistakenly chosen over `std::fs::create_dir_all`, + /// resulting in failure when more than one directory needs to be created or when the directory already exists. + /// Crates which never need to specifically create a single directory may wish to prevent this mistake. /// /// ### Example /// ```rust,ignore diff --git a/clippy_lints/src/dbg_macro.rs b/clippy_lints/src/dbg_macro.rs index db5937266047..b0590b0a71cb 100644 --- a/clippy_lints/src/dbg_macro.rs +++ b/clippy_lints/src/dbg_macro.rs @@ -14,7 +14,7 @@ declare_clippy_lint! { /// ### What it does /// Checks for usage of the [`dbg!`](https://doc.rust-lang.org/std/macro.dbg.html) macro. /// - /// ### Why is this bad? + /// ### Why restrict this? /// The `dbg!` macro is intended as a debugging tool. It should not be present in released /// software or committed to a version control system. /// diff --git a/clippy_lints/src/default_numeric_fallback.rs b/clippy_lints/src/default_numeric_fallback.rs index 1d6c4ce72e18..fbc4ede37b1c 100644 --- a/clippy_lints/src/default_numeric_fallback.rs +++ b/clippy_lints/src/default_numeric_fallback.rs @@ -22,9 +22,8 @@ declare_clippy_lint! { /// /// See [RFC0212](https://github.com/rust-lang/rfcs/blob/master/text/0212-restore-int-fallback.md) for more information about the fallback. /// - /// ### Why is this bad? - /// For those who are very careful about types, default numeric fallback - /// can be a pitfall that cause unexpected runtime behavior. + /// ### Why restrict this? + /// To ensure that every numeric type is chosen explicitly rather than implicitly. /// /// ### Known problems /// This lint can only be allowed at the function level or above. diff --git a/clippy_lints/src/default_union_representation.rs b/clippy_lints/src/default_union_representation.rs index b4290b6437f2..3fa9bad0d03d 100644 --- a/clippy_lints/src/default_union_representation.rs +++ b/clippy_lints/src/default_union_representation.rs @@ -10,7 +10,7 @@ declare_clippy_lint! { /// ### What it does /// Displays a warning when a union is declared with the default representation (without a `#[repr(C)]` attribute). /// - /// ### Why is this bad? + /// ### Why restrict this? /// Unions in Rust have unspecified layout by default, despite many people thinking that they /// lay out each field at the start of the union (like C does). That is, there are no guarantees /// about the offset of the fields for unions with multiple non-ZST fields without an explicitly diff --git a/clippy_lints/src/disallowed_script_idents.rs b/clippy_lints/src/disallowed_script_idents.rs index def4b5932b4b..a995f06fb73d 100644 --- a/clippy_lints/src/disallowed_script_idents.rs +++ b/clippy_lints/src/disallowed_script_idents.rs @@ -20,11 +20,11 @@ declare_clippy_lint! { /// [aliases]: http://www.unicode.org/reports/tr24/tr24-31.html#Script_Value_Aliases /// [supported_scripts]: https://www.unicode.org/iso15924/iso15924-codes.html /// - /// ### Why is this bad? + /// ### Why restrict this? /// It may be not desired to have many different scripts for /// identifiers in the codebase. /// - /// Note that if you only want to allow plain English, you might want to use + /// Note that if you only want to allow typical English, you might want to use /// built-in [`non_ascii_idents`] lint instead. /// /// [`non_ascii_idents`]: https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html#non-ascii-idents diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs index 81c47d07c356..e9c4559ff4d2 100644 --- a/clippy_lints/src/doc/mod.rs +++ b/clippy_lints/src/doc/mod.rs @@ -261,7 +261,7 @@ declare_clippy_lint! { /// Checks for the doc comments of publicly visible /// safe functions and traits and warns if there is a `# Safety` section. /// - /// ### Why is this bad? + /// ### Why restrict this? /// Safe functions and traits are safe to implement and therefore do not /// need to describe safety preconditions that users are required to uphold. /// diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index 119473c2454b..4a6ffcd9a788 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -52,9 +52,10 @@ declare_clippy_lint! { /// Checks for usage of `std::mem::forget(t)` where `t` is /// `Drop` or has a field that implements `Drop`. /// - /// ### Why is this bad? - /// `std::mem::forget(t)` prevents `t` from running its - /// destructor, possibly causing leaks. + /// ### Why restrict this? + /// `std::mem::forget(t)` prevents `t` from running its destructor, possibly causing leaks. + /// It is not possible to detect all means of creating leaks, but it may be desirable to + /// prohibit the simple ones. /// /// ### Example /// ```no_run diff --git a/clippy_lints/src/else_if_without_else.rs b/clippy_lints/src/else_if_without_else.rs index a6ca7fe9e0bb..bb6f9aac2236 100644 --- a/clippy_lints/src/else_if_without_else.rs +++ b/clippy_lints/src/else_if_without_else.rs @@ -11,7 +11,7 @@ declare_clippy_lint! { /// Checks for usage of if expressions with an `else if` branch, /// but without a final `else` branch. /// - /// ### Why is this bad? + /// ### Why restrict this? /// Some coding guidelines require this (e.g., MISRA-C:2004 Rule 14.10). /// /// ### Example diff --git a/clippy_lints/src/empty_drop.rs b/clippy_lints/src/empty_drop.rs index 74db250b3ae9..c5fc72b5e2d8 100644 --- a/clippy_lints/src/empty_drop.rs +++ b/clippy_lints/src/empty_drop.rs @@ -9,7 +9,7 @@ declare_clippy_lint! { /// ### What it does /// Checks for empty `Drop` implementations. /// - /// ### Why is this bad? + /// ### Why restrict this? /// Empty `Drop` implementations have no effect when dropping an instance of the type. They are /// most likely useless. However, an empty `Drop` implementation prevents a type from being /// destructured, which might be the intention behind adding the implementation as a marker. diff --git a/clippy_lints/src/empty_with_brackets.rs b/clippy_lints/src/empty_with_brackets.rs index 969df6d85b5a..745599b0e57a 100644 --- a/clippy_lints/src/empty_with_brackets.rs +++ b/clippy_lints/src/empty_with_brackets.rs @@ -11,16 +11,23 @@ declare_clippy_lint! { /// ### What it does /// Finds structs without fields (a so-called "empty struct") that are declared with brackets. /// - /// ### Why is this bad? - /// Empty brackets after a struct declaration can be omitted. + /// ### Why restrict this? + /// Empty brackets after a struct declaration can be omitted, + /// and it may be desirable to do so consistently for style. + /// + /// However, removing the brackets also introduces a public constant named after the struct, + /// so this is not just a syntactic simplification but an an API change, and adding them back + /// is a *breaking* API change. /// /// ### Example /// ```no_run /// struct Cookie {} + /// struct Biscuit(); /// ``` /// Use instead: /// ```no_run /// struct Cookie; + /// struct Biscuit; /// ``` #[clippy::version = "1.62.0"] pub EMPTY_STRUCTS_WITH_BRACKETS, @@ -32,14 +39,20 @@ declare_clippy_lint! { /// ### What it does /// Finds enum variants without fields that are declared with empty brackets. /// - /// ### Why is this bad? - /// Empty brackets while defining enum variants are redundant and can be omitted. + /// ### Why restrict this? + /// Empty brackets after a enum variant declaration are redundant and can be omitted, + /// and it may be desirable to do so consistently for style. + /// + /// However, removing the brackets also introduces a public constant named after the variant, + /// so this is not just a syntactic simplification but an an API change, and adding them back + /// is a *breaking* API change. /// /// ### Example /// ```no_run /// enum MyEnum { /// HasData(u8), - /// HasNoData(), // redundant parentheses + /// HasNoData(), // redundant parentheses + /// NoneHereEither {}, // redundant braces /// } /// ``` /// @@ -48,6 +61,7 @@ declare_clippy_lint! { /// enum MyEnum { /// HasData(u8), /// HasNoData, + /// NoneHereEither, /// } /// ``` #[clippy::version = "1.77.0"] diff --git a/clippy_lints/src/endian_bytes.rs b/clippy_lints/src/endian_bytes.rs index dd03df797de3..bb766e963387 100644 --- a/clippy_lints/src/endian_bytes.rs +++ b/clippy_lints/src/endian_bytes.rs @@ -13,8 +13,9 @@ declare_clippy_lint! { /// ### What it does /// Checks for the usage of the `to_ne_bytes` method and/or the function `from_ne_bytes`. /// - /// ### Why is this bad? - /// It's not, but some may prefer to specify the target endianness explicitly. + /// ### Why restrict this? + /// To ensure use of explicitly chosen endianness rather than the target’s endianness, + /// such as when implementing network protocols or file formats rather than FFI. /// /// ### Example /// ```rust,ignore @@ -31,9 +32,8 @@ declare_clippy_lint! { /// ### What it does /// Checks for the usage of the `to_le_bytes` method and/or the function `from_le_bytes`. /// - /// ### Why is this bad? - /// It's not, but some may wish to lint usage of this method, either to suggest using the host - /// endianness or big endian. + /// ### Why restrict this? + /// To ensure use of big endian or the target’s endianness rather than little endian. /// /// ### Example /// ```rust,ignore @@ -50,9 +50,8 @@ declare_clippy_lint! { /// ### What it does /// Checks for the usage of the `to_be_bytes` method and/or the function `from_be_bytes`. /// - /// ### Why is this bad? - /// It's not, but some may wish to lint usage of this method, either to suggest using the host - /// endianness or little endian. + /// ### Why restrict this? + /// To ensure use of little endian or the target’s endianness rather than big endian. /// /// ### Example /// ```rust,ignore diff --git a/clippy_lints/src/error_impl_error.rs b/clippy_lints/src/error_impl_error.rs index 8dbb47fadc5d..8e49138cd26b 100644 --- a/clippy_lints/src/error_impl_error.rs +++ b/clippy_lints/src/error_impl_error.rs @@ -12,7 +12,7 @@ declare_clippy_lint! { /// ### What it does /// Checks for types named `Error` that implement `Error`. /// - /// ### Why is this bad? + /// ### Why restrict this? /// It can become confusing when a codebase has 20 types all named `Error`, requiring either /// aliasing them in the `use` statement or qualifying them like `my_module::Error`. This /// hinders comprehension, as it requires you to memorize every variation of importing `Error` diff --git a/clippy_lints/src/exhaustive_items.rs b/clippy_lints/src/exhaustive_items.rs index 9ffda6457424..436dc8611bde 100644 --- a/clippy_lints/src/exhaustive_items.rs +++ b/clippy_lints/src/exhaustive_items.rs @@ -10,10 +10,10 @@ declare_clippy_lint! { /// ### What it does /// Warns on any exported `enum`s that are not tagged `#[non_exhaustive]` /// - /// ### Why is this bad? - /// Exhaustive enums are typically fine, but a project which does - /// not wish to make a stability commitment around exported enums may wish to - /// disable them by default. + /// ### Why restrict this? + /// Making an `enum` exhaustive is a stability commitment: adding a variant is a breaking change. + /// A project may wish to ensure that there are no exhaustive enums or that every exhaustive + /// `enum` is explicitly `#[allow]`ed. /// /// ### Example /// ```no_run @@ -40,10 +40,10 @@ declare_clippy_lint! { /// ### What it does /// Warns on any exported `struct`s that are not tagged `#[non_exhaustive]` /// - /// ### Why is this bad? - /// Exhaustive structs are typically fine, but a project which does - /// not wish to make a stability commitment around exported structs may wish to - /// disable them by default. + /// ### Why restrict this? + /// Making a `struct` exhaustive is a stability commitment: adding a field is a breaking change. + /// A project may wish to ensure that there are no exhaustive structs or that every exhaustive + /// `struct` is explicitly `#[allow]`ed. /// /// ### Example /// ```no_run diff --git a/clippy_lints/src/exit.rs b/clippy_lints/src/exit.rs index 106844dd4348..91c94d66458d 100644 --- a/clippy_lints/src/exit.rs +++ b/clippy_lints/src/exit.rs @@ -9,11 +9,13 @@ declare_clippy_lint! { /// ### What it does /// Detects calls to the `exit()` function which terminates the program. /// - /// ### Why is this bad? - /// Exit terminates the program at the location it is called. For unrecoverable - /// errors `panics` should be used to provide a stacktrace and potentially other - /// information. A normal termination or one with an error code should happen in - /// the main function. + /// ### Why restrict this? + /// `exit()` immediately terminates the program with no information other than an exit code. + /// This provides no means to troubleshoot a problem, and may be an unexpected side effect. + /// + /// Codebases may use this lint to require that all exits are performed either by panicking + /// (which produces a message, a code location, and optionally a backtrace) + /// or by returning from `main()` (which is a single place to look). /// /// ### Example /// ```no_run diff --git a/clippy_lints/src/float_literal.rs b/clippy_lints/src/float_literal.rs index 2cd4e9e99a56..4ec9bd757ff4 100644 --- a/clippy_lints/src/float_literal.rs +++ b/clippy_lints/src/float_literal.rs @@ -38,9 +38,9 @@ declare_clippy_lint! { /// Checks for whole number float literals that /// cannot be represented as the underlying type without loss. /// - /// ### Why is this bad? - /// Rust will silently lose precision during - /// conversion to a float. + /// ### Why restrict this? + /// If the value was intended to be exact, it will not be. + /// This may be especially surprising when the lost precision is to the left of the decimal point. /// /// ### Example /// ```no_run diff --git a/clippy_lints/src/format_push_string.rs b/clippy_lints/src/format_push_string.rs index 2b08437d8271..a75538dd329b 100644 --- a/clippy_lints/src/format_push_string.rs +++ b/clippy_lints/src/format_push_string.rs @@ -11,7 +11,7 @@ declare_clippy_lint! { /// Detects cases where the result of a `format!` call is /// appended to an existing `String`. /// - /// ### Why is this bad? + /// ### Why restrict this? /// Introduces an extra, avoidable heap allocation. /// /// ### Known problems diff --git a/clippy_lints/src/functions/mod.rs b/clippy_lints/src/functions/mod.rs index dfcaac9abefc..26534492dddd 100644 --- a/clippy_lints/src/functions/mod.rs +++ b/clippy_lints/src/functions/mod.rs @@ -338,8 +338,10 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does /// Lints when `impl Trait` is being used in a function's parameters. - /// ### Why is this bad? - /// Turbofish syntax (`::<>`) cannot be used when `impl Trait` is being used, making `impl Trait` less powerful. Readability may also be a factor. + /// + /// ### Why restrict this? + /// Turbofish syntax (`::<>`) cannot be used to specify the type of an `impl Trait` parameter, + /// making `impl Trait` less powerful. Readability may also be a factor. /// /// ### Example /// ```no_run @@ -366,9 +368,8 @@ declare_clippy_lint! { /// Lints when the name of function parameters from trait impl is /// different than its default implementation. /// - /// ### Why is this bad? - /// Using the default name for parameters of a trait method is often - /// more desirable for consistency's sake. + /// ### Why restrict this? + /// Using the default name for parameters of a trait method is more consistent. /// /// ### Example /// ```rust diff --git a/clippy_lints/src/if_then_some_else_none.rs b/clippy_lints/src/if_then_some_else_none.rs index f5ba62ae432e..0b2008152198 100644 --- a/clippy_lints/src/if_then_some_else_none.rs +++ b/clippy_lints/src/if_then_some_else_none.rs @@ -15,7 +15,7 @@ declare_clippy_lint! { /// ### What it does /// Checks for if-else that could be written using either `bool::then` or `bool::then_some`. /// - /// ### Why is this bad? + /// ### Why restrict this? /// Looks a little redundant. Using `bool::then` is more concise and incurs no loss of clarity. /// For simple calculations and known values, use `bool::then_some`, which is eagerly evaluated /// in comparison to `bool::then`. diff --git a/clippy_lints/src/implicit_return.rs b/clippy_lints/src/implicit_return.rs index 5288efd8df8c..cc342007ec61 100644 --- a/clippy_lints/src/implicit_return.rs +++ b/clippy_lints/src/implicit_return.rs @@ -16,12 +16,13 @@ declare_clippy_lint! { /// ### What it does /// Checks for missing return statements at the end of a block. /// - /// ### Why is this bad? - /// Actually omitting the return keyword is idiomatic Rust code. Programmers - /// coming from other languages might prefer the expressiveness of `return`. It's possible to miss - /// the last returning statement because the only difference is a missing `;`. Especially in bigger - /// code with multiple return paths having a `return` keyword makes it easier to find the - /// corresponding statements. + /// ### Why restrict this? + /// Omitting the return keyword whenever possible is idiomatic Rust code, but: + /// + /// * Programmers coming from other languages might prefer the expressiveness of `return`. + /// * It's possible to miss the last returning statement because the only difference is a missing `;`. + /// * Especially in bigger code with multiple return paths, having a `return` keyword makes it easier to find the + /// corresponding statements. /// /// ### Example /// ```no_run diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs index 35fcd8cdd354..e3e79749bea6 100644 --- a/clippy_lints/src/indexing_slicing.rs +++ b/clippy_lints/src/indexing_slicing.rs @@ -45,9 +45,10 @@ declare_clippy_lint! { /// does report on arrays if we can tell that slicing operations are in bounds and does not /// lint on constant `usize` indexing on arrays because that is handled by rustc's `const_err` lint. /// - /// ### Why is this bad? - /// Indexing and slicing can panic at runtime and there are - /// safe alternatives. + /// ### Why restrict this? + /// To avoid implicit panics from indexing and slicing. + /// There are “checked” alternatives which do not panic, and can be used with `unwrap()` to make + /// an explicit panic when it is desired. /// /// ### Example /// ```rust,no_run diff --git a/clippy_lints/src/inherent_impl.rs b/clippy_lints/src/inherent_impl.rs index 1127f00abde0..95ae591884bc 100644 --- a/clippy_lints/src/inherent_impl.rs +++ b/clippy_lints/src/inherent_impl.rs @@ -14,7 +14,7 @@ declare_clippy_lint! { /// ### What it does /// Checks for multiple inherent implementations of a struct /// - /// ### Why is this bad? + /// ### Why restrict this? /// Splitting the implementation of a type makes the code harder to navigate. /// /// ### Example diff --git a/clippy_lints/src/integer_division_remainder_used.rs b/clippy_lints/src/integer_division_remainder_used.rs index a3577b765c03..cf598d5045ec 100644 --- a/clippy_lints/src/integer_division_remainder_used.rs +++ b/clippy_lints/src/integer_division_remainder_used.rs @@ -7,10 +7,10 @@ use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does - /// Checks for the usage of division (/) and remainder (%) operations - /// when performed on any integer types using the default Div and Rem trait implementations. + /// Checks for the usage of division (`/`) and remainder (`%`) operations + /// when performed on any integer types using the default `Div` and `Rem` trait implementations. /// - /// ### Why is this bad? + /// ### Why restrict this? /// In cryptographic contexts, division can result in timing sidechannel vulnerabilities, /// and needs to be replaced with constant-time code instead (e.g. Barrett reduction). /// diff --git a/clippy_lints/src/iter_over_hash_type.rs b/clippy_lints/src/iter_over_hash_type.rs index 6c6eff9ba48b..fb29d9824179 100644 --- a/clippy_lints/src/iter_over_hash_type.rs +++ b/clippy_lints/src/iter_over_hash_type.rs @@ -14,8 +14,8 @@ declare_clippy_lint! { /// ### What it does /// This is a restriction lint which prevents the use of hash types (i.e., `HashSet` and `HashMap`) in for loops. /// - /// ### Why is this bad? - /// Because hash types are unordered, when iterated through such as in a for loop, the values are returned in + /// ### Why restrict this? + /// Because hash types are unordered, when iterated through such as in a `for` loop, the values are returned in /// an undefined order. As a result, on redundant systems this may cause inconsistencies and anomalies. /// In addition, the unknown order of the elements may reduce readability or introduce other undesired /// side effects. diff --git a/clippy_lints/src/large_include_file.rs b/clippy_lints/src/large_include_file.rs index 790bed580fd1..07efee159aab 100644 --- a/clippy_lints/src/large_include_file.rs +++ b/clippy_lints/src/large_include_file.rs @@ -10,10 +10,12 @@ use rustc_span::sym; declare_clippy_lint! { /// ### What it does /// Checks for the inclusion of large files via `include_bytes!()` - /// and `include_str!()` + /// or `include_str!()`. /// - /// ### Why is this bad? - /// Including large files can increase the size of the binary + /// ### Why restrict this? + /// Including large files can undesirably increase the size of the binary produced by the compiler. + /// This lint may be used to catch mistakes where an unexpectedly large file is included, or + /// temporarily to obtain a list of all large files. /// /// ### Example /// ```rust,ignore diff --git a/clippy_lints/src/let_underscore.rs b/clippy_lints/src/let_underscore.rs index 619e933b4fff..9fd4f509aa47 100644 --- a/clippy_lints/src/let_underscore.rs +++ b/clippy_lints/src/let_underscore.rs @@ -12,9 +12,8 @@ declare_clippy_lint! { /// ### What it does /// Checks for `let _ = ` where expr is `#[must_use]` /// - /// ### Why is this bad? - /// It's better to explicitly handle the value of a `#[must_use]` - /// expr + /// ### Why restrict this? + /// To ensure that all `#[must_use]` types are used rather than ignored. /// /// ### Example /// ```no_run @@ -96,8 +95,8 @@ declare_clippy_lint! { /// Checks for `let _ = ` without a type annotation, and suggests to either provide one, /// or remove the `let` keyword altogether. /// - /// ### Why is this bad? - /// The `let _ = ` expression ignores the value of `` but will remain doing so even + /// ### Why restrict this? + /// The `let _ = ` expression ignores the value of ``, but will continue to do so even /// if the type were to change, thus potentially introducing subtle bugs. By supplying a type /// annotation, one will be forced to re-visit the decision to ignore the value in such cases. /// diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 2348dd18220f..d2a140a36a83 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -132,8 +132,8 @@ declare_clippy_lint! { /// ### What it does /// Warns if there is a better representation for a numeric literal. /// - /// ### Why is this bad? - /// Especially for big powers of 2 a hexadecimal representation is more + /// ### Why restrict this? + /// Especially for big powers of 2, a hexadecimal representation is usually more /// readable than a decimal representation. /// /// ### Example diff --git a/clippy_lints/src/loops/mod.rs b/clippy_lints/src/loops/mod.rs index 3dcb050d77e6..086829421530 100644 --- a/clippy_lints/src/loops/mod.rs +++ b/clippy_lints/src/loops/mod.rs @@ -675,9 +675,9 @@ declare_clippy_lint! { /// Checks for infinite loops in a function where the return type is not `!` /// and lint accordingly. /// - /// ### Why is this bad? - /// A loop should be gently exited somewhere, or at least mark its parent function as - /// never return (`!`). + /// ### Why restrict this? + /// Making the return type `!` serves as documentation that the function does not return. + /// If the function is not intended to loop infinitely, then this lint may detect a bug. /// /// ### Example /// ```no_run,ignore diff --git a/clippy_lints/src/matches/mod.rs b/clippy_lints/src/matches/mod.rs index ee9f48d71ad8..691ecd57535a 100644 --- a/clippy_lints/src/matches/mod.rs +++ b/clippy_lints/src/matches/mod.rs @@ -260,7 +260,7 @@ declare_clippy_lint! { /// ### What it does /// Checks for wildcard enum matches using `_`. /// - /// ### Why is this bad? + /// ### Why restrict this? /// New enum variants added by library updates can be missed. /// /// ### Known problems @@ -435,7 +435,7 @@ declare_clippy_lint! { /// ### What it does /// Checks for unnecessary '..' pattern binding on struct when all fields are explicitly matched. /// - /// ### Why is this bad? + /// ### Why restrict this? /// Correctness and readability. It's like having a wildcard pattern after /// matching all enum variants explicitly. /// @@ -861,7 +861,7 @@ declare_clippy_lint! { /// ### What it does /// Checks for usage of `Err(x)?`. /// - /// ### Why is this bad? + /// ### Why restrict this? /// The `?` operator is designed to allow calls that /// can fail to be easily chained. For example, `foo()?.bar()` or /// `foo(bar()?)`. Because `Err(x)?` can't be used that way (it will diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 60666445d08b..13c5f537ca40 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -257,7 +257,7 @@ declare_clippy_lint! { /// ### What it does /// Checks for `.unwrap()` or `.unwrap_err()` calls on `Result`s and `.unwrap()` call on `Option`s. /// - /// ### Why is this bad? + /// ### Why restrict this? /// It is better to handle the `None` or `Err` case, /// or at least call `.expect(_)` with a more helpful message. Still, for a lot of /// quick-and-dirty code, `unwrap` is a good choice, which is why this lint is @@ -333,7 +333,7 @@ declare_clippy_lint! { /// ### What it does /// Checks for `.expect()` or `.expect_err()` calls on `Result`s and `.expect()` call on `Option`s. /// - /// ### Why is this bad? + /// ### Why restrict this? /// Usually it is better to handle the `None` or `Err` case. /// Still, for a lot of quick-and-dirty code, `expect` is a good choice, which is why /// this lint is `Allow` by default. @@ -1029,8 +1029,8 @@ declare_clippy_lint! { /// (`Rc`, `Arc`, `rc::Weak`, or `sync::Weak`), and suggests calling Clone via unified /// function syntax instead (e.g., `Rc::clone(foo)`). /// - /// ### Why is this bad? - /// Calling '.clone()' on an Rc, Arc, or Weak + /// ### Why restrict this? + /// Calling `.clone()` on an `Rc`, `Arc`, or `Weak` /// can obscure the fact that only the pointer is being cloned, not the underlying /// data. /// @@ -1051,7 +1051,7 @@ declare_clippy_lint! { #[clippy::version = "pre 1.29.0"] pub CLONE_ON_REF_PTR, restriction, - "using 'clone' on a ref-counted pointer" + "using `clone` on a ref-counted pointer" } declare_clippy_lint! { @@ -1359,7 +1359,7 @@ declare_clippy_lint! { /// Checks for usage of `.get().unwrap()` (or /// `.get_mut().unwrap`) on a standard library type which implements `Index` /// - /// ### Why is this bad? + /// ### Why restrict this? /// Using the Index trait (`[]`) is more clear and more /// concise. /// @@ -1743,7 +1743,7 @@ declare_clippy_lint! { /// ### What it does /// Checks for `FileType::is_file()`. /// - /// ### Why is this bad? + /// ### Why restrict this? /// When people testing a file type with `FileType::is_file` /// they are testing whether a path is something they can get bytes from. But /// `is_file` doesn't cover special file types in unix-like systems, and doesn't cover @@ -2688,8 +2688,9 @@ declare_clippy_lint! { /// ### What it does /// Checks for instances of `map_err(|_| Some::Enum)` /// - /// ### Why is this bad? - /// This `map_err` throws away the original error rather than allowing the enum to contain and report the cause of the error + /// ### Why restrict this? + /// This `map_err` throws away the original error rather than allowing the enum to + /// contain and report the cause of the error. /// /// ### Example /// Before: @@ -3145,7 +3146,7 @@ declare_clippy_lint! { /// ### What it does /// Checks for usage of File::read_to_end and File::read_to_string. /// - /// ### Why is this bad? + /// ### Why restrict this? /// `fs::{read, read_to_string}` provide the same functionality when `buf` is empty with fewer imports and no intermediate values. /// See also: [fs::read docs](https://doc.rust-lang.org/std/fs/fn.read.html), [fs::read_to_string docs](https://doc.rust-lang.org/std/fs/fn.read_to_string.html) /// diff --git a/clippy_lints/src/min_ident_chars.rs b/clippy_lints/src/min_ident_chars.rs index c6b7f5b0ce27..e43b712021ae 100644 --- a/clippy_lints/src/min_ident_chars.rs +++ b/clippy_lints/src/min_ident_chars.rs @@ -12,14 +12,13 @@ use std::borrow::Cow; declare_clippy_lint! { /// ### What it does - /// Checks for idents which comprise of a single letter. + /// Checks for identifiers which consist of a single character (or fewer than the configured threshold). /// /// Note: This lint can be very noisy when enabled; it may be desirable to only enable it /// temporarily. /// - /// ### Why is this bad? - /// In many cases it's not, but at times it can severely hinder readability. Some codebases may - /// wish to disallow this to improve readability. + /// ### Why restrict this? + /// To improve readability by requiring that every variable has a name more specific than a single letter can be. /// /// ### Example /// ```rust,ignore diff --git a/clippy_lints/src/misc_early/mod.rs b/clippy_lints/src/misc_early/mod.rs index 2f5499d7656f..fedcfd11fdcc 100644 --- a/clippy_lints/src/misc_early/mod.rs +++ b/clippy_lints/src/misc_early/mod.rs @@ -23,7 +23,7 @@ declare_clippy_lint! { /// ### What it does /// Checks for structure field patterns bound to wildcards. /// - /// ### Why is this bad? + /// ### Why restrict this? /// Using `..` instead is shorter and leaves the focus on /// the fields that are actually bound. /// @@ -138,7 +138,7 @@ declare_clippy_lint! { /// To enforce unseparated literal suffix style, /// see the `separated_literal_suffix` lint. /// - /// ### Why is this bad? + /// ### Why restrict this? /// Suffix style should be consistent. /// /// ### Example @@ -166,7 +166,7 @@ declare_clippy_lint! { /// To enforce separated literal suffix style, /// see the `unseparated_literal_suffix` lint. /// - /// ### Why is this bad? + /// ### Why restrict this? /// Suffix style should be consistent. /// /// ### Example diff --git a/clippy_lints/src/missing_assert_message.rs b/clippy_lints/src/missing_assert_message.rs index 04df7b7a7e5a..dd98352da860 100644 --- a/clippy_lints/src/missing_assert_message.rs +++ b/clippy_lints/src/missing_assert_message.rs @@ -10,7 +10,7 @@ declare_clippy_lint! { /// ### What it does /// Checks assertions without a custom panic message. /// - /// ### Why is this bad? + /// ### Why restrict this? /// Without a good custom message, it'd be hard to understand what went wrong when the assertion fails. /// A good custom message should be more about why the failure of the assertion is problematic /// and not what is failed because the assertion already conveys that. diff --git a/clippy_lints/src/missing_asserts_for_indexing.rs b/clippy_lints/src/missing_asserts_for_indexing.rs index c29e46b941c6..752723a0c68e 100644 --- a/clippy_lints/src/missing_asserts_for_indexing.rs +++ b/clippy_lints/src/missing_asserts_for_indexing.rs @@ -21,7 +21,7 @@ declare_clippy_lint! { /// Checks for repeated slice indexing without asserting beforehand that the length /// is greater than the largest index used to index into the slice. /// - /// ### Why is this bad? + /// ### Why restrict this? /// In the general case where the compiler does not have a lot of information /// about the length of a slice, indexing it repeatedly will generate a bounds check /// for every single index. diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index 2fb784dae1cd..ca344dc5c810 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -20,9 +20,9 @@ use rustc_span::{sym, Span}; declare_clippy_lint! { /// ### What it does - /// Warns if there is missing doc for any private documentable item + /// Warns if there is missing documentation for any private documentable item. /// - /// ### Why is this bad? + /// ### Why restrict this? /// Doc is good. *rustc* has a `MISSING_DOCS` /// allowed-by-default lint for /// public members, but has no way to enforce documentation of private items. diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index c6a76478806a..33a14d8b7fed 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -10,13 +10,16 @@ declare_clippy_lint! { /// It lints if an exported function, method, trait method with default impl, /// or trait method impl is not `#[inline]`. /// - /// ### Why is this bad? - /// In general, it is not. Functions can be inlined across - /// crates when that's profitable as long as any form of LTO is used. When LTO is disabled, - /// functions that are not `#[inline]` cannot be inlined across crates. Certain types of crates - /// might intend for most of the methods in their public API to be able to be inlined across - /// crates even when LTO is disabled. For these types of crates, enabling this lint might make - /// sense. It allows the crate to require all exported methods to be `#[inline]` by default, and + /// ### Why restrict this? + /// When a function is not marked `#[inline]`, it is not + /// [a “small” candidate for automatic inlining][small], and LTO is not in use, then it is not + /// possible for the function to be inlined into the code of any crate other than the one in + /// which it is defined. Depending on the role of the function and the relationship of the crates, + /// this could significantly reduce performance. + /// + /// Certain types of crates might intend for most of the methods in their public API to be able + /// to be inlined across crates even when LTO is disabled. + /// This lint allows those crates to require all exported methods to be `#[inline]` by default, and /// then opt out for specific methods where this might not make sense. /// /// ### Example @@ -51,6 +54,8 @@ declare_clippy_lint! { /// fn def_bar() {} // missing #[inline] /// } /// ``` + /// + /// [small]: https://github.com/rust-lang/rust/pull/116505 #[clippy::version = "pre 1.29.0"] pub MISSING_INLINE_IN_PUBLIC_ITEMS, restriction, diff --git a/clippy_lints/src/missing_trait_methods.rs b/clippy_lints/src/missing_trait_methods.rs index 6f844bc646a2..85029a5e6a0d 100644 --- a/clippy_lints/src/missing_trait_methods.rs +++ b/clippy_lints/src/missing_trait_methods.rs @@ -10,16 +10,16 @@ use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does /// Checks if a provided method is used implicitly by a trait - /// implementation. A usage example would be a wrapper where every method - /// should perform some operation before delegating to the inner type's /// implementation. /// + /// ### Why restrict this? + /// To ensure that a certain implementation implements every method; for example, + /// a wrapper type where every method should delegate to the corresponding method of + /// the inner type's implementation. + /// /// This lint should typically be enabled on a specific trait `impl` item /// rather than globally. /// - /// ### Why is this bad? - /// Indicates that a method is missing. - /// /// ### Example /// ```no_run /// trait Trait { diff --git a/clippy_lints/src/mixed_read_write_in_expression.rs b/clippy_lints/src/mixed_read_write_in_expression.rs index 181351910db6..9c5a8a0cfcdf 100644 --- a/clippy_lints/src/mixed_read_write_in_expression.rs +++ b/clippy_lints/src/mixed_read_write_in_expression.rs @@ -12,9 +12,10 @@ declare_clippy_lint! { /// whether the read occurs before or after the write depends on the evaluation /// order of sub-expressions. /// - /// ### Why is this bad? - /// It is often confusing to read. As described [here](https://doc.rust-lang.org/reference/expressions.html?highlight=subexpression#evaluation-order-of-operands), - /// the operands of these expressions are evaluated before applying the effects of the expression. + /// ### Why restrict this? + /// While [the evaluation order of sub-expressions] is fully specified in Rust, + /// it still may be confusing to read an expression where the evaluation order + /// affects its behavior. /// /// ### Known problems /// Code which intentionally depends on the evaluation @@ -40,6 +41,8 @@ declare_clippy_lint! { /// }; /// let a = tmp + x; /// ``` + /// + /// [order]: (https://doc.rust-lang.org/reference/expressions.html?highlight=subexpression#evaluation-order-of-operands) #[clippy::version = "pre 1.29.0"] pub MIXED_READ_WRITE_IN_EXPRESSION, restriction, diff --git a/clippy_lints/src/module_style.rs b/clippy_lints/src/module_style.rs index 6c031c081750..305499f9da43 100644 --- a/clippy_lints/src/module_style.rs +++ b/clippy_lints/src/module_style.rs @@ -10,9 +10,9 @@ use std::path::{Component, Path}; declare_clippy_lint! { /// ### What it does - /// Checks that module layout uses only self named module files, bans `mod.rs` files. + /// Checks that module layout uses only self named module files; bans `mod.rs` files. /// - /// ### Why is this bad? + /// ### Why restrict this? /// Having multiple module layout styles in a project can be confusing. /// /// ### Example @@ -41,7 +41,7 @@ declare_clippy_lint! { /// ### What it does /// Checks that module layout uses only `mod.rs` files. /// - /// ### Why is this bad? + /// ### Why restrict this? /// Having multiple module layout styles in a project can be confusing. /// /// ### Example diff --git a/clippy_lints/src/multiple_unsafe_ops_per_block.rs b/clippy_lints/src/multiple_unsafe_ops_per_block.rs index 0e1380667805..6830d48cfd8c 100644 --- a/clippy_lints/src/multiple_unsafe_ops_per_block.rs +++ b/clippy_lints/src/multiple_unsafe_ops_per_block.rs @@ -15,7 +15,7 @@ declare_clippy_lint! { /// ### What it does /// Checks for `unsafe` blocks that contain more than one unsafe operation. /// - /// ### Why is this bad? + /// ### Why restrict this? /// Combined with `undocumented_unsafe_blocks`, /// this lint ensures that each unsafe operation must be independently justified. /// Combined with `unused_unsafe`, this lint also ensures diff --git a/clippy_lints/src/mutex_atomic.rs b/clippy_lints/src/mutex_atomic.rs index 7ecc86176942..853e476a006c 100644 --- a/clippy_lints/src/mutex_atomic.rs +++ b/clippy_lints/src/mutex_atomic.rs @@ -14,7 +14,7 @@ declare_clippy_lint! { /// ### What it does /// Checks for usage of `Mutex` where an atomic will do. /// - /// ### Why is this bad? + /// ### Why restrict this? /// Using a mutex just to make access to a plain bool or /// reference sequential is shooting flies with cannons. /// `std::sync::atomic::AtomicBool` and `std::sync::atomic::AtomicPtr` are leaner and diff --git a/clippy_lints/src/operators/mod.rs b/clippy_lints/src/operators/mod.rs index e002429e3a47..0948973df5a3 100644 --- a/clippy_lints/src/operators/mod.rs +++ b/clippy_lints/src/operators/mod.rs @@ -70,7 +70,7 @@ declare_clippy_lint! { /// Known safe built-in types like `Wrapping` or `Saturating`, floats, operations in constant /// environments, allowed types and non-constant operations that won't overflow are ignored. /// - /// ### Why is this bad? + /// ### Why restrict this? /// For integers, overflow will trigger a panic in debug builds or wrap the result in /// release mode; division by zero will cause a panic in either mode. As a result, it is /// desirable to explicitly call checked, wrapping or saturating arithmetic methods. @@ -100,7 +100,7 @@ declare_clippy_lint! { /// ### What it does /// Checks for float arithmetic. /// - /// ### Why is this bad? + /// ### Why restrict this? /// For some embedded systems or kernel development, it /// can be useful to rule out floating-point numbers. /// @@ -502,7 +502,7 @@ declare_clippy_lint! { /// ### What it does /// Checks for division of integers /// - /// ### Why is this bad? + /// ### Why restrict this? /// When outside of some very specific algorithms, /// integer division is very often a mistake because it discards the /// remainder. @@ -596,7 +596,7 @@ declare_clippy_lint! { /// value and constant, except in functions called `*eq*` (which probably /// implement equality for a type involving floats). /// - /// ### Why is this bad? + /// ### Why restrict this? /// Floating point calculations are usually imprecise, so /// asking if two values are *exactly* equal is asking for trouble. For a good /// guide on what to do, see [the floating point @@ -653,8 +653,8 @@ declare_clippy_lint! { /// ### What it does /// Checks for modulo arithmetic. /// - /// ### Why is this bad? - /// The results of modulo (%) operation might differ + /// ### Why restrict this? + /// The results of modulo (`%`) operation might differ /// depending on the language, when negative numbers are involved. /// If you interop with different languages it might be beneficial /// to double check all places that use modulo arithmetic. diff --git a/clippy_lints/src/panic_in_result_fn.rs b/clippy_lints/src/panic_in_result_fn.rs index f821a4efee7b..806638c0505b 100644 --- a/clippy_lints/src/panic_in_result_fn.rs +++ b/clippy_lints/src/panic_in_result_fn.rs @@ -13,9 +13,9 @@ use rustc_span::{sym, Span}; declare_clippy_lint! { /// ### What it does - /// Checks for usage of `panic!` or assertions in a function of type result. + /// Checks for usage of `panic!` or assertions in a function whose return type is `Result`. /// - /// ### Why is this bad? + /// ### Why restrict this? /// For some codebases, it is desirable for functions of type result to return an error instead of crashing. Hence panicking macros should be avoided. /// /// ### Known problems diff --git a/clippy_lints/src/panic_unimplemented.rs b/clippy_lints/src/panic_unimplemented.rs index 75066c1f0d2e..80ef761906e0 100644 --- a/clippy_lints/src/panic_unimplemented.rs +++ b/clippy_lints/src/panic_unimplemented.rs @@ -14,8 +14,8 @@ declare_clippy_lint! { /// ### What it does /// Checks for usage of `panic!`. /// - /// ### Why is this bad? - /// `panic!` will stop the execution of the executable. + /// ### Why restrict this? + /// This macro, or panics in general, may be unwanted in production code. /// /// ### Example /// ```no_run @@ -31,8 +31,8 @@ declare_clippy_lint! { /// ### What it does /// Checks for usage of `unimplemented!`. /// - /// ### Why is this bad? - /// This macro should not be present in production code. + /// ### Why restrict this? + /// This macro, or panics in general, may be unwanted in production code. /// /// ### Example /// ```no_run @@ -48,9 +48,9 @@ declare_clippy_lint! { /// ### What it does /// Checks for usage of `todo!`. /// - /// ### Why is this bad? - /// The `todo!` macro is often used for unfinished code, and it causes - /// code to panic. It should not be present in production code. + /// ### Why restrict this? + /// The `todo!` macro indicates the presence of unfinished code, + /// so it should not be present in production code. /// /// ### Example /// ```no_run @@ -70,8 +70,8 @@ declare_clippy_lint! { /// ### What it does /// Checks for usage of `unreachable!`. /// - /// ### Why is this bad? - /// This macro can cause code to panic. + /// ### Why restrict this? + /// This macro, or panics in general, may be unwanted in production code. /// /// ### Example /// ```no_run diff --git a/clippy_lints/src/partial_pub_fields.rs b/clippy_lints/src/partial_pub_fields.rs index ffa403e27ca3..2d20cbea698f 100644 --- a/clippy_lints/src/partial_pub_fields.rs +++ b/clippy_lints/src/partial_pub_fields.rs @@ -5,15 +5,16 @@ use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does - /// Checks whether partial fields of a struct are public. + /// Checks whether some but not all fields of a `struct` are public. /// /// Either make all fields of a type public, or make none of them public /// - /// ### Why is this bad? + /// ### Why restrict this? /// Most types should either be: /// * Abstract data types: complex objects with opaque implementation which guard - /// interior invariants and expose intentionally limited API to the outside world. - /// * Data: relatively simple objects which group a bunch of related attributes together. + /// interior invariants and expose intentionally limited API to the outside world. + /// * Data: relatively simple objects which group a bunch of related attributes together, + /// but have no invariants. /// /// ### Example /// ```no_run diff --git a/clippy_lints/src/pattern_type_mismatch.rs b/clippy_lints/src/pattern_type_mismatch.rs index 44db061b8bee..9661a57b8b95 100644 --- a/clippy_lints/src/pattern_type_mismatch.rs +++ b/clippy_lints/src/pattern_type_mismatch.rs @@ -30,9 +30,8 @@ declare_clippy_lint! { /// this lint can still be used to highlight areas of interest and ensure a good understanding /// of ownership semantics. /// - /// ### Why is this bad? - /// It isn't bad in general. But in some contexts it can be desirable - /// because it increases ownership hints in the code, and will guard against some changes + /// ### Why restrict this? + /// It increases ownership hints in the code, and will guard against some changes /// in ownership. /// /// ### Example diff --git a/clippy_lints/src/pub_use.rs b/clippy_lints/src/pub_use.rs index c0e999e76ef2..ab8f8a1689dc 100644 --- a/clippy_lints/src/pub_use.rs +++ b/clippy_lints/src/pub_use.rs @@ -5,13 +5,11 @@ use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does - /// /// Restricts the usage of `pub use ...` /// - /// ### Why is this bad? - /// - /// `pub use` is usually fine, but a project may wish to limit `pub use` instances to prevent - /// unintentional exports or to encourage placing exported items directly in public modules + /// ### Why restrict this? + /// A project may wish to limit `pub use` instances to prevent + /// unintentional exports, or to encourage placing exported items directly in public modules. /// /// ### Example /// ```no_run diff --git a/clippy_lints/src/question_mark_used.rs b/clippy_lints/src/question_mark_used.rs index ddfc53083c46..f5e6cb804da1 100644 --- a/clippy_lints/src/question_mark_used.rs +++ b/clippy_lints/src/question_mark_used.rs @@ -9,7 +9,7 @@ declare_clippy_lint! { /// ### What it does /// Checks for expressions that use the question mark operator and rejects them. /// - /// ### Why is this bad? + /// ### Why restrict this? /// Sometimes code wants to avoid the question mark operator because for instance a local /// block requires a macro to re-throw errors to attach additional information to the /// error. diff --git a/clippy_lints/src/raw_strings.rs b/clippy_lints/src/raw_strings.rs index 7e71f48c6d9a..3a0042454592 100644 --- a/clippy_lints/src/raw_strings.rs +++ b/clippy_lints/src/raw_strings.rs @@ -15,8 +15,10 @@ declare_clippy_lint! { /// ### What it does /// Checks for raw string literals where a string literal can be used instead. /// - /// ### Why is this bad? - /// It's just unnecessary, but there are many cases where using a raw string literal is more + /// ### Why restrict this? + /// For consistent style by using simpler string literals whenever possible. + /// + /// However, there are many cases where using a raw string literal is more /// idiomatic than a string literal, so it's opt-in. /// /// ### Example diff --git a/clippy_lints/src/redundant_slicing.rs b/clippy_lints/src/redundant_slicing.rs index c99b657c23a2..7f87d18e5023 100644 --- a/clippy_lints/src/redundant_slicing.rs +++ b/clippy_lints/src/redundant_slicing.rs @@ -46,7 +46,7 @@ declare_clippy_lint! { /// Checks for slicing expressions which are equivalent to dereferencing the /// value. /// - /// ### Why is this bad? + /// ### Why restrict this? /// Some people may prefer to dereference rather than slice. /// /// ### Example diff --git a/clippy_lints/src/redundant_type_annotations.rs b/clippy_lints/src/redundant_type_annotations.rs index 11b95ee3a54c..81556f396141 100644 --- a/clippy_lints/src/redundant_type_annotations.rs +++ b/clippy_lints/src/redundant_type_annotations.rs @@ -11,7 +11,7 @@ declare_clippy_lint! { /// ### What it does /// Warns about needless / redundant type annotations. /// - /// ### Why is this bad? + /// ### Why restrict this? /// Code without type annotations is shorter and in most cases /// more idiomatic and easier to modify. /// diff --git a/clippy_lints/src/ref_patterns.rs b/clippy_lints/src/ref_patterns.rs index 607a0740b843..467038523b49 100644 --- a/clippy_lints/src/ref_patterns.rs +++ b/clippy_lints/src/ref_patterns.rs @@ -6,9 +6,11 @@ use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does /// Checks for usages of the `ref` keyword. - /// ### Why is this bad? + /// + /// ### Why restrict this? /// The `ref` keyword can be confusing for people unfamiliar with it, and often /// it is more concise to use `&` instead. + /// /// ### Example /// ```no_run /// let opt = Some(5); diff --git a/clippy_lints/src/same_name_method.rs b/clippy_lints/src/same_name_method.rs index 7e27f70bcf94..8fdd19c549f5 100644 --- a/clippy_lints/src/same_name_method.rs +++ b/clippy_lints/src/same_name_method.rs @@ -14,7 +14,7 @@ declare_clippy_lint! { /// It lints if a struct has two methods with the same name: /// one from a trait, another not from trait. /// - /// ### Why is this bad? + /// ### Why restrict this? /// Confusing. /// /// ### Example diff --git a/clippy_lints/src/semicolon_block.rs b/clippy_lints/src/semicolon_block.rs index 0b3adfb7a4b8..0e77acdfd77f 100644 --- a/clippy_lints/src/semicolon_block.rs +++ b/clippy_lints/src/semicolon_block.rs @@ -11,8 +11,7 @@ declare_clippy_lint! { /// Suggests moving the semicolon after a block to the inside of the block, after its last /// expression. /// - /// ### Why is this bad? - /// + /// ### Why restrict this? /// For consistency it's best to have the semicolon inside/outside the block. Either way is fine /// and this lint suggests inside the block. /// Take a look at `semicolon_outside_block` for the other alternative. @@ -40,8 +39,7 @@ declare_clippy_lint! { /// /// Suggests moving the semicolon from a block's final expression outside of the block. /// - /// ### Why is this bad? - /// + /// ### Why restrict this? /// For consistency it's best to have the semicolon inside/outside the block. Either way is fine /// and this lint suggests outside the block. /// Take a look at `semicolon_inside_block` for the other alternative. diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 9db08acb03b2..80f5fd0b4944 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -15,10 +15,10 @@ declare_clippy_lint! { /// Checks for bindings that shadow other bindings already in /// scope, while just changing reference level or mutability. /// - /// ### Why is this bad? - /// Not much, in fact it's a very common pattern in Rust - /// code. Still, some may opt to avoid it in their code base, they can set this - /// lint to `Warn`. + /// ### Why restrict this? + /// To require that what are formally distinct variables be given distinct names. + /// + /// See also `shadow_reuse` and `shadow_unrelated` for other restrictions on shadowing. /// /// ### Example /// ```no_run @@ -42,12 +42,13 @@ declare_clippy_lint! { /// Checks for bindings that shadow other bindings already in /// scope, while reusing the original value. /// - /// ### Why is this bad? - /// Not too much, in fact it's a common pattern in Rust - /// code. Still, some argue that name shadowing like this hurts readability, + /// ### Why restrict this? + /// Some argue that name shadowing like this hurts readability, /// because a value may be bound to different things depending on position in /// the code. /// + /// See also `shadow_same` and `shadow_unrelated` for other restrictions on shadowing. + /// /// ### Example /// ```no_run /// let x = 2; @@ -70,11 +71,14 @@ declare_clippy_lint! { /// scope, either without an initialization or with one that does not even use /// the original value. /// - /// ### Why is this bad? - /// Name shadowing can hurt readability, especially in + /// ### Why restrict this? + /// Shadowing a binding with a closely related one is part of idiomatic Rust, + /// but shadowing a binding by accident with an unrelated one may indicate a mistake. + /// + /// Additionally, name shadowing in general can hurt readability, especially in /// large code bases, because it is easy to lose track of the active binding at - /// any place in the code. This can be alleviated by either giving more specific - /// names to bindings or introducing more scopes to contain the bindings. + /// any place in the code. If linting against all shadowing is desired, you may wish + /// to use the `shadow_same` and `shadow_reuse` lints as well. /// /// ### Example /// ```no_run diff --git a/clippy_lints/src/single_call_fn.rs b/clippy_lints/src/single_call_fn.rs index 2ce7e714c642..c71bc3f7fcde 100644 --- a/clippy_lints/src/single_call_fn.rs +++ b/clippy_lints/src/single_call_fn.rs @@ -13,13 +13,20 @@ declare_clippy_lint! { /// ### What it does /// Checks for functions that are only used once. Does not lint tests. /// - /// ### Why is this bad? - /// It's usually not, splitting a function into multiple parts often improves readability and in - /// the case of generics, can prevent the compiler from duplicating the function dozens of - /// time; instead, only duplicating a thunk. But this can prevent segmentation across a - /// codebase, where many small functions are used only once. + /// ### Why restrict this? + /// If a function is only used once (perhaps because it used to be used more widely), + /// then the code could be simplified by moving that function's code into its caller. /// - /// Note: If this lint is used, prepare to allow this a lot. + /// However, there are reasons not to do this everywhere: + /// + /// * Splitting a large function into multiple parts often improves readability + /// by giving names to its parts. + /// * A function’s signature might serve a necessary purpose, such as constraining + /// the type of a closure passed to it. + /// * Generic functions might call non-generic functions to reduce duplication + /// in the produced machine code. + /// + /// If this lint is used, prepare to `#[allow]` it a lot. /// /// ### Example /// ```no_run diff --git a/clippy_lints/src/single_char_lifetime_names.rs b/clippy_lints/src/single_char_lifetime_names.rs index 42f1564db353..72feb977c310 100644 --- a/clippy_lints/src/single_char_lifetime_names.rs +++ b/clippy_lints/src/single_char_lifetime_names.rs @@ -9,11 +9,10 @@ declare_clippy_lint! { /// Checks for lifetimes with names which are one character /// long. /// - /// ### Why is this bad? + /// ### Why restrict this? /// A single character is likely not enough to express the /// purpose of a lifetime. Using a longer name can make code - /// easier to understand, especially for those who are new to - /// Rust. + /// easier to understand. /// /// ### Known problems /// Rust programmers and learning resources tend to use single diff --git a/clippy_lints/src/std_instead_of_core.rs b/clippy_lints/src/std_instead_of_core.rs index 926c56332cc1..12b70075a3d5 100644 --- a/clippy_lints/src/std_instead_of_core.rs +++ b/clippy_lints/src/std_instead_of_core.rs @@ -12,11 +12,9 @@ use rustc_span::{sym, Span}; declare_clippy_lint! { /// ### What it does - /// /// Finds items imported through `std` when available through `core`. /// - /// ### Why is this bad? - /// + /// ### Why restrict this? /// Crates which have `no_std` compatibility may wish to ensure types are imported from core to ensure /// disabling `std` does not cause the crate to fail to compile. This lint is also useful for crates /// migrating to become `no_std` compatible. @@ -37,11 +35,9 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// /// Finds items imported through `std` when available through `alloc`. /// - /// ### Why is this bad? - /// + /// ### Why restrict this? /// Crates which have `no_std` compatibility and require alloc may wish to ensure types are imported from /// alloc to ensure disabling `std` does not cause the crate to fail to compile. This lint is also useful /// for crates migrating to become `no_std` compatible. @@ -63,11 +59,9 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// /// Finds items imported through `alloc` when available through `core`. /// - /// ### Why is this bad? - /// + /// ### Why restrict this? /// Crates which have `no_std` compatibility and may optionally require alloc may wish to ensure types are /// imported from core to ensure disabling `alloc` does not cause the crate to fail to compile. This lint /// is also useful for crates migrating to become `no_std` compatible. diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index 292124196ff6..f8d36d6b92f6 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -45,10 +45,10 @@ declare_clippy_lint! { /// `String`, but only if [`string_add_assign`](#string_add_assign) does *not* /// match. /// - /// ### Why is this bad? - /// It's not bad in and of itself. However, this particular + /// ### Why restrict this? + /// This particular /// `Add` implementation is asymmetric (the other operand need not be `String`, - /// but `x` does), while addition as mathematically defined is symmetric, also + /// but `x` does), while addition as mathematically defined is symmetric, and /// the `String::push_str(_)` function is a perfectly good replacement. /// Therefore, some dislike it and wish not to have it in their code. /// @@ -123,7 +123,7 @@ declare_clippy_lint! { /// ### What it does /// Checks for slice operations on strings /// - /// ### Why is this bad? + /// ### Why restrict this? /// UTF-8 characters span multiple bytes, and it is easy to inadvertently confuse character /// counts and string indices. This may lead to panics, and should warrant some test cases /// containing wide UTF-8 characters. This lint is most useful in code that should avoid @@ -364,10 +364,10 @@ declare_clippy_lint! { /// ### What it does /// This lint checks for `.to_string()` method calls on values of type `&str`. /// - /// ### Why is this bad? + /// ### Why restrict this? /// The `to_string` method is also used on other types to convert them to a string. - /// When called on a `&str` it turns the `&str` into the owned variant `String`, which can be better - /// expressed with `.to_owned()`. + /// When called on a `&str` it turns the `&str` into the owned variant `String`, which can be + /// more specifically expressed with `.to_owned()`. /// /// ### Example /// ```no_run @@ -415,9 +415,10 @@ declare_clippy_lint! { /// ### What it does /// This lint checks for `.to_string()` method calls on values of type `String`. /// - /// ### Why is this bad? + /// ### Why restrict this? /// The `to_string` method is also used on other types to convert them to a string. - /// When called on a `String` it only clones the `String`, which can be better expressed with `.clone()`. + /// When called on a `String` it only clones the `String`, which can be more specifically + /// expressed with `.clone()`. /// /// ### Example /// ```no_run diff --git a/clippy_lints/src/suspicious_xor_used_as_pow.rs b/clippy_lints/src/suspicious_xor_used_as_pow.rs index 1cc27670fa8b..d150a5f858aa 100644 --- a/clippy_lints/src/suspicious_xor_used_as_pow.rs +++ b/clippy_lints/src/suspicious_xor_used_as_pow.rs @@ -11,8 +11,10 @@ use rustc_session::declare_lint_pass; declare_clippy_lint! { /// ### What it does /// Warns for a Bitwise XOR (`^`) operator being probably confused as a powering. It will not trigger if any of the numbers are not in decimal. - /// ### Why is this bad? + /// + /// ### Why restrict this? /// It's most probably a typo and may lead to unexpected behaviours. + /// /// ### Example /// ```no_run /// let x = 3_i32 ^ 4_i32; diff --git a/clippy_lints/src/tests_outside_test_module.rs b/clippy_lints/src/tests_outside_test_module.rs index da5575826475..58e42892c41d 100644 --- a/clippy_lints/src/tests_outside_test_module.rs +++ b/clippy_lints/src/tests_outside_test_module.rs @@ -11,9 +11,11 @@ declare_clippy_lint! { /// ### What it does /// Triggers when a testing function (marked with the `#[test]` attribute) isn't inside a testing module /// (marked with `#[cfg(test)]`). - /// ### Why is this bad? + /// + /// ### Why restrict this? /// The idiomatic (and more performant) way of writing tests is inside a testing module (flagged with `#[cfg(test)]`), /// having test functions outside of this module is confusing and may lead to them being "hidden". + /// /// ### Example /// ```no_run /// #[test] diff --git a/clippy_lints/src/types/mod.rs b/clippy_lints/src/types/mod.rs index 5e45ab211efd..62ef65ca122f 100644 --- a/clippy_lints/src/types/mod.rs +++ b/clippy_lints/src/types/mod.rs @@ -217,7 +217,7 @@ declare_clippy_lint! { /// ### What it does /// Checks for `Rc` and `Arc` when `T` is a mutable buffer type such as `String` or `Vec`. /// - /// ### Why is this bad? + /// ### Why restrict this? /// Expressions such as `Rc` usually have no advantage over `Rc`, since /// it is larger and involves an extra level of indirection, and doesn't implement `Borrow`. /// @@ -274,7 +274,7 @@ declare_clippy_lint! { /// ### What it does /// Checks for `Rc>`. /// - /// ### Why is this bad? + /// ### Why restrict this? /// `Rc` is used in single thread and `Mutex` is used in multi thread. /// Consider using `Rc>` in single thread or `Arc>` in multi thread. /// diff --git a/clippy_lints/src/undocumented_unsafe_blocks.rs b/clippy_lints/src/undocumented_unsafe_blocks.rs index cbd161800770..7e8c11cf25a3 100644 --- a/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -38,10 +38,9 @@ declare_clippy_lint! { /// ); /// ``` /// - /// ### Why is this bad? - /// Undocumented unsafe blocks and impls can make it difficult to - /// read and maintain code, as well as uncover unsoundness - /// and bugs. + /// ### Why restrict this? + /// Undocumented unsafe blocks and impls can make it difficult to read and maintain code. + /// Writing out the safety justification may help in discovering unsoundness or bugs. /// /// ### Example /// ```no_run @@ -67,7 +66,7 @@ declare_clippy_lint! { /// ### What it does /// Checks for `// SAFETY: ` comments on safe code. /// - /// ### Why is this bad? + /// ### Why restrict this? /// Safe code has no safety requirements, so there is no need to /// describe safety invariants. /// diff --git a/clippy_lints/src/unicode.rs b/clippy_lints/src/unicode.rs index 3d319b9fe767..d42697b31d1f 100644 --- a/clippy_lints/src/unicode.rs +++ b/clippy_lints/src/unicode.rs @@ -31,7 +31,7 @@ declare_clippy_lint! { /// ### What it does /// Checks for non-ASCII characters in string and char literals. /// - /// ### Why is this bad? + /// ### Why restrict this? /// Yeah, we know, the 90's called and wanted their charset /// back. Even so, there still are editors and other programs out there that /// don't work well with Unicode. So if the code is meant to be used diff --git a/clippy_lints/src/unnecessary_self_imports.rs b/clippy_lints/src/unnecessary_self_imports.rs index 528a1dfcfc10..93dff1b85796 100644 --- a/clippy_lints/src/unnecessary_self_imports.rs +++ b/clippy_lints/src/unnecessary_self_imports.rs @@ -9,7 +9,7 @@ declare_clippy_lint! { /// ### What it does /// Checks for imports ending in `::{self}`. /// - /// ### Why is this bad? + /// ### Why restrict this? /// In most cases, this can be written much more cleanly by omitting `::{self}`. /// /// ### Known problems diff --git a/clippy_lints/src/unwrap_in_result.rs b/clippy_lints/src/unwrap_in_result.rs index aca500590cef..197ab0f173bd 100644 --- a/clippy_lints/src/unwrap_in_result.rs +++ b/clippy_lints/src/unwrap_in_result.rs @@ -13,8 +13,10 @@ declare_clippy_lint! { /// ### What it does /// Checks for functions of type `Result` that contain `expect()` or `unwrap()` /// - /// ### Why is this bad? - /// These functions promote recoverable errors to non-recoverable errors which may be undesirable in code bases which wish to avoid panics. + /// ### Why restrict this? + /// These functions promote recoverable errors to non-recoverable errors, + /// which may be undesirable in code bases which wish to avoid panics, + /// or be a bug in the specific function. /// /// ### Known problems /// This can cause false positives in functions that handle both recoverable and non recoverable errors. diff --git a/clippy_lints/src/visibility.rs b/clippy_lints/src/visibility.rs index 9818b98dd5b4..11dcceca7abb 100644 --- a/clippy_lints/src/visibility.rs +++ b/clippy_lints/src/visibility.rs @@ -32,7 +32,7 @@ declare_clippy_lint! { /// ### What it does /// Checks for usage of `pub()` with `in`. /// - /// ### Why is this bad? + /// ### Why restrict this? /// Consistency. Use it or don't, just be consistent about it. /// /// Also see the `pub_without_shorthand` lint for an alternative. @@ -57,7 +57,7 @@ declare_clippy_lint! { /// Note: As you cannot write a module's path in `pub()`, this will only trigger on /// `pub(super)` and the like. /// - /// ### Why is this bad? + /// ### Why restrict this? /// Consistency. Use it or don't, just be consistent about it. /// /// Also see the `pub_with_shorthand` lint for an alternative. diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index ff6ee0d10ad5..652ce88bd951 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -66,7 +66,7 @@ declare_clippy_lint! { /// Checks for printing on *stdout*. The purpose of this lint /// is to catch debugging remnants. /// - /// ### Why is this bad? + /// ### Why restrict this? /// People often print on *stdout* while debugging an /// application and might forget to remove those prints afterward. /// @@ -88,7 +88,7 @@ declare_clippy_lint! { /// Checks for printing on *stderr*. The purpose of this lint /// is to catch debugging remnants. /// - /// ### Why is this bad? + /// ### Why restrict this? /// People often print on *stderr* while debugging an /// application and might forget to remove those prints afterward. /// @@ -110,15 +110,18 @@ declare_clippy_lint! { /// Checks for usage of `Debug` formatting. The purpose of this /// lint is to catch debugging remnants. /// - /// ### Why is this bad? - /// The purpose of the `Debug` trait is to facilitate - /// debugging Rust code. It should not be used in user-facing output. + /// ### Why restrict this? + /// The purpose of the `Debug` trait is to facilitate debugging Rust code, + /// and [no guarantees are made about its output][stability]. + /// It should not be used in user-facing output. /// /// ### Example /// ```no_run /// # let foo = "bar"; /// println!("{:?}", foo); /// ``` + /// + /// [stability]: https://doc.rust-lang.org/stable/std/fmt/trait.Debug.html#stability #[clippy::version = "pre 1.29.0"] pub USE_DEBUG, restriction, From 14dc51c1acfec5f0d01886a1422244f07d20176c Mon Sep 17 00:00:00 2001 From: maxwase Date: Fri, 24 May 2024 01:39:46 +0300 Subject: [PATCH 038/211] Review fixes: Assist scope, trait qualify --- .../src/handlers/toggle_async_sugar.rs | 164 +++++++++++++----- .../crates/ide-assists/src/tests/generated.rs | 7 +- 2 files changed, 126 insertions(+), 45 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_async_sugar.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_async_sugar.rs index 356e1d50ae89..30e09648ea12 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_async_sugar.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_async_sugar.rs @@ -1,3 +1,4 @@ +use hir::{ImportPathConfig, ModuleDef}; use ide_db::{ assists::{AssistId, AssistKind}, famous_defs::FamousDefs, @@ -11,13 +12,13 @@ use crate::{AssistContext, Assists}; // Assist: sugar_impl_future_into_async // -// Rewrites asynchronous function from `impl Future` to `async fn`. +// Rewrites asynchronous function from `-> impl Future` into `async fn`. // This action does not touch the function body and therefore `async { 0 }` // block does not transform to just `0`. // // ``` // # //- minicore: future -// pub f$0n foo() -> impl core::future::Future { +// pub fn foo() -> impl core::future::F$0uture { // async { 0 } // } // ``` @@ -31,13 +32,10 @@ pub(crate) fn sugar_impl_future_into_async( acc: &mut Assists, ctx: &AssistContext<'_>, ) -> Option<()> { - let function: ast::Fn = ctx.find_node_at_offset()?; - if function.async_token().is_some() { - return None; - } + let ret_type: ast::RetType = ctx.find_node_at_offset()?; + let function = ret_type.syntax().parent().and_then(ast::Fn::cast)?; - let ret_type = function.ret_type()?; - if function.const_token().is_some() { + if function.async_token().is_some() || function.const_token().is_some() { return None; } @@ -67,6 +65,7 @@ pub(crate) fn sugar_impl_future_into_async( function.syntax().text_range(), |builder| { match future_output { + // Empty tuple ast::Type::TupleType(t) if t.fields().next().is_none() => { let mut ret_type_range = ret_type.syntax().text_range(); @@ -103,18 +102,19 @@ pub(crate) fn sugar_impl_future_into_async( // Assist: desugar_async_into_impl_future // -// Rewrites asynchronous function from `async fn` to `impl Future`. +// Rewrites asynchronous function from `async fn` into `-> impl Future`. // This action does not touch the function body and therefore `0` // block does not transform to `async { 0 }`. // // ``` -// pub async f$0n foo() -> usize { +// # //- minicore: future +// pub as$0ync fn foo() -> usize { // 0 // } // ``` // -> // ``` -// pub fn foo() -> impl Future { +// pub fn foo() -> impl core::future::Future { // 0 // } // ``` @@ -122,8 +122,8 @@ pub(crate) fn desugar_async_into_impl_future( acc: &mut Assists, ctx: &AssistContext<'_>, ) -> Option<()> { - let function: ast::Fn = ctx.find_node_at_offset()?; - let async_token = function.async_token()?; + let async_token = ctx.find_token_syntax_at_offset(SyntaxKind::ASYNC_KW)?; + let function = async_token.parent().and_then(ast::Fn::cast)?; let rparen = function.param_list()?.r_paren_token()?; let return_type = match function.ret_type() { @@ -133,6 +133,19 @@ pub(crate) fn desugar_async_into_impl_future( None => None, }; + let scope = ctx.sema.scope(function.syntax())?; + let module = scope.module(); + let future_trait = FamousDefs(&ctx.sema, scope.krate()).core_future_Future()?; + let trait_path = module.find_path( + ctx.db(), + ModuleDef::Trait(future_trait), + ImportPathConfig { + prefer_no_std: ctx.config.prefer_no_std, + prefer_prelude: ctx.config.prefer_prelude, + }, + )?; + let trait_path = trait_path.display(ctx.db()); + acc.add( AssistId("desugar_async_into_impl_future", AssistKind::RefactorRewrite), "Convert async into `impl Future`", @@ -148,9 +161,12 @@ pub(crate) fn desugar_async_into_impl_future( match return_type { Some(ret_type) => builder.replace( ret_type.syntax().text_range(), - format!("impl Future"), + format!("impl {trait_path}"), + ), + None => builder.insert( + rparen.text_range().end(), + format!(" -> impl {trait_path}"), ), - None => builder.insert(rparen.text_range().end(), " -> impl Future"), } }, ) @@ -186,7 +202,7 @@ mod tests { r#" //- minicore: future use core::future::Future; - f$0n foo() -> impl Future { + fn foo() -> impl F$0uture { todo!() } "#, @@ -203,7 +219,7 @@ mod tests { r#" //- minicore: future use core::future::Future; - f$0n foo() -> impl Future { + fn foo() -> impl F$0uture { todo!() } "#, @@ -223,7 +239,7 @@ mod tests { r#" //- minicore: future use core::future::Future; - async f$0n foo() { + as$0ync fn foo() { todo!() } "#, @@ -239,8 +255,25 @@ mod tests { desugar_async_into_impl_future, r#" //- minicore: future + use core::future; + as$0ync fn foo() { + todo!() + } + "#, + r#" + use core::future; + fn foo() -> impl future::Future { + todo!() + } + "#, + ); + + check_assist( + desugar_async_into_impl_future, + r#" + //- minicore: future use core::future::Future; - async f$0n foo() -> usize { + as$0ync fn foo() -> usize { todo!() } "#, @@ -249,6 +282,23 @@ mod tests { fn foo() -> impl Future { todo!() } + "#, + ); + + check_assist( + desugar_async_into_impl_future, + r#" + //- minicore: future + use core::future::Future; + as$0ync fn foo() -> impl Future { + todo!() + } + "#, + r#" + use core::future::Future; + fn foo() -> impl Future> { + todo!() + } "#, ); } @@ -259,7 +309,7 @@ mod tests { sugar_impl_future_into_async, r#" //- minicore: future - f$0n foo() -> impl core::future::Future { + fn foo() -> impl core::future::F$0uture { todo!() } "#, @@ -274,7 +324,7 @@ mod tests { sugar_impl_future_into_async, r#" //- minicore: future - f$0n foo() -> impl core::future::Future { + fn foo() -> impl core::future::F$0uture { todo!() } "#, @@ -292,12 +342,12 @@ mod tests { desugar_async_into_impl_future, r#" //- minicore: future - async f$0n foo() { + as$0ync fn foo() { todo!() } "#, r#" - fn foo() -> impl Future { + fn foo() -> impl core::future::Future { todo!() } "#, @@ -307,12 +357,12 @@ mod tests { desugar_async_into_impl_future, r#" //- minicore: future - async f$0n foo() -> usize { + as$0ync fn foo() -> usize { todo!() } "#, r#" - fn foo() -> impl Future { + fn foo() -> impl core::future::Future { todo!() } "#, @@ -320,7 +370,7 @@ mod tests { } #[test] - fn sugar_not_applicable() { + fn not_applicable() { check_assist_not_applicable( sugar_impl_future_into_async, r#" @@ -328,7 +378,7 @@ mod tests { trait Future { type Output; } - f$0n foo() -> impl Future { + fn foo() -> impl F$0uture { todo!() } "#, @@ -341,7 +391,26 @@ mod tests { trait Future { type Output; } - f$0n foo() -> impl Future { + fn foo() -> impl F$0uture { + todo!() + } + "#, + ); + + check_assist_not_applicable( + sugar_impl_future_into_async, + r#" + //- minicore: future + f$0n foo() -> impl core::future::Future { + todo!() + } + "#, + ); + + check_assist_not_applicable( + desugar_async_into_impl_future, + r#" + async f$0n foo() { todo!() } "#, @@ -355,7 +424,7 @@ mod tests { r#" //- minicore: future use core::future::Future; - f$0n foo() -> impl Future; + fn foo() -> impl F$0uture; "#, r#" use core::future::Future; @@ -368,7 +437,7 @@ mod tests { r#" //- minicore: future use core::future::Future; - f$0n foo() -> impl Future; + fn foo() -> impl F$0uture; "#, r#" use core::future::Future; @@ -383,7 +452,7 @@ mod tests { sugar_impl_future_into_async, r#" //- minicore: future - f$0n foo() -> impl core::future::Future; + fn foo() -> impl core::future::F$0uture; "#, r#" async fn foo(); @@ -394,7 +463,7 @@ mod tests { sugar_impl_future_into_async, r#" //- minicore: future - f$0n foo() -> impl core::future::Future; + fn foo() -> impl core::future::F$0uture; "#, r#" async fn foo() -> usize; @@ -408,7 +477,7 @@ mod tests { sugar_impl_future_into_async, r#" //- minicore: future - f$0n foo() -> impl core::future::Future + Send + Sync; + fn foo() -> impl core::future::F$0uture + Send + Sync; "#, r#" async fn foo(); @@ -419,7 +488,7 @@ mod tests { sugar_impl_future_into_async, r#" //- minicore: future - f$0n foo() -> impl core::future::Future + Debug; + fn foo() -> impl core::future::F$0uture + Debug; "#, r#" async fn foo() -> usize; @@ -430,7 +499,7 @@ mod tests { sugar_impl_future_into_async, r#" //- minicore: future - f$0n foo() -> impl core::future::Future + Debug; + fn foo() -> impl core::future::F$0uture + Debug; "#, r#" async fn foo() -> (usize); @@ -441,10 +510,21 @@ mod tests { sugar_impl_future_into_async, r#" //- minicore: future - f$0n foo() -> impl core::future::Future + Debug; + fn foo() -> impl core::future::F$0uture + Debug; "#, r#" async fn foo() -> (usize, usize); + "#, + ); + + check_assist( + sugar_impl_future_into_async, + r#" + //- minicore: future + fn foo() -> impl core::future::Future + Send>; + "#, + r#" + async fn foo() -> impl core::future::Future + Send; "#, ); } @@ -455,7 +535,7 @@ mod tests { sugar_impl_future_into_async, r#" //- minicore: future - const f$0n foo() -> impl core::future::Future; + const fn foo() -> impl core::future::F$0uture; "#, ); @@ -463,7 +543,7 @@ mod tests { sugar_impl_future_into_async, r#" //- minicore: future - pub(crate) unsafe f$0n foo() -> impl core::future::Future; + pub(crate) unsafe fn foo() -> impl core::future::F$0uture; "#, r#" pub(crate) async unsafe fn foo() -> usize; @@ -474,7 +554,7 @@ mod tests { sugar_impl_future_into_async, r#" //- minicore: future - unsafe f$0n foo() -> impl core::future::Future; + unsafe fn foo() -> impl core::future::F$0uture; "#, r#" async unsafe fn foo(); @@ -485,7 +565,7 @@ mod tests { sugar_impl_future_into_async, r#" //- minicore: future - unsafe extern "C" f$0n foo() -> impl core::future::Future; + unsafe extern "C" fn foo() -> impl core::future::F$0uture; "#, r#" async unsafe extern "C" fn foo(); @@ -496,7 +576,7 @@ mod tests { sugar_impl_future_into_async, r#" //- minicore: future - f$0n foo() -> impl core::future::Future; + fn foo() -> impl core::future::F$0uture; "#, r#" async fn foo() -> T; @@ -507,7 +587,7 @@ mod tests { sugar_impl_future_into_async, r#" //- minicore: future - f$0n foo() -> impl core::future::Future + fn foo() -> impl core::future::F$0uture where T: Sized; "#, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs index 5f187880b011..94d9e5edeffb 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs @@ -805,12 +805,13 @@ fn doctest_desugar_async_into_impl_future() { check_doc_test( "desugar_async_into_impl_future", r#####" -pub async f$0n foo() -> usize { +//- minicore: future +pub as$0ync fn foo() -> usize { 0 } "#####, r#####" -pub fn foo() -> impl Future { +pub fn foo() -> impl core::future::Future { 0 } "#####, @@ -3043,7 +3044,7 @@ fn doctest_sugar_impl_future_into_async() { "sugar_impl_future_into_async", r#####" //- minicore: future -pub f$0n foo() -> impl core::future::Future { +pub fn foo() -> impl core::future::F$0uture { async { 0 } } "#####, From 7f30b20b28f44e37df29f4de2c74a86d35b1b72b Mon Sep 17 00:00:00 2001 From: Jakob Schwarz Date: Wed, 22 May 2024 09:01:37 +0200 Subject: [PATCH 039/211] fulfill expectations in `check_partial_eq_without_eq` changelog: fulfill expectations in [derive_partial_eq_without_eq] --- clippy_lints/src/derive.rs | 17 +++++++++---- tests/ui/derive_partial_eq_without_eq.fixed | 17 +++++++++++++ tests/ui/derive_partial_eq_without_eq.rs | 17 +++++++++++++ tests/ui/derive_partial_eq_without_eq.stderr | 26 ++++++++++---------- 4 files changed, 59 insertions(+), 18 deletions(-) diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 19dedceae6d4..ecdef0eee54b 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_sugg, span_lint_and_then, span_lint_hir_and_then}; +use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_then, span_lint_hir_and_then}; use clippy_utils::ty::{implements_trait, implements_trait_with_env, is_copy}; use clippy_utils::{has_non_exhaustive_attr, is_lint_allowed, match_def_path, paths}; use rustc_errors::Applicability; @@ -456,20 +456,27 @@ fn check_partial_eq_without_eq<'tcx>(cx: &LateContext<'tcx>, span: Span, trait_r && !has_non_exhaustive_attr(cx.tcx, *adt) && !ty_implements_eq_trait(cx.tcx, ty, eq_trait_def_id) && let param_env = param_env_for_derived_eq(cx.tcx, adt.did(), eq_trait_def_id) + && let Some(local_def_id) = adt.did().as_local() // If all of our fields implement `Eq`, we can implement `Eq` too && adt .all_fields() .map(|f| f.ty(cx.tcx, args)) .all(|ty| implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, None, &[])) { - span_lint_and_sugg( + span_lint_hir_and_then( cx, DERIVE_PARTIAL_EQ_WITHOUT_EQ, + cx.tcx.local_def_id_to_hir_id(local_def_id), span.ctxt().outer_expn_data().call_site, "you are deriving `PartialEq` and can implement `Eq`", - "consider deriving `Eq` as well", - "PartialEq, Eq".to_string(), - Applicability::MachineApplicable, + |diag| { + diag.span_suggestion( + span.ctxt().outer_expn_data().call_site, + "consider deriving `Eq` as well", + "PartialEq, Eq", + Applicability::MachineApplicable, + ); + }, ); } } diff --git a/tests/ui/derive_partial_eq_without_eq.fixed b/tests/ui/derive_partial_eq_without_eq.fixed index 6f42487bbf49..eb93eb8e8ed4 100644 --- a/tests/ui/derive_partial_eq_without_eq.fixed +++ b/tests/ui/derive_partial_eq_without_eq.fixed @@ -1,3 +1,4 @@ +#![feature(lint_reasons)] #![allow(unused)] #![warn(clippy::derive_partial_eq_without_eq)] @@ -14,6 +15,22 @@ pub struct MissingEq { bar: String, } +// Check that we honor the `allow` attribute +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Debug, PartialEq)] +pub struct AllowedMissingEq { + foo: u32, + bar: String, +} + +// Check that we honor the `expect` attribute +#[expect(clippy::derive_partial_eq_without_eq)] +#[derive(Debug, PartialEq)] +pub struct ExpectedMissingEq { + foo: u32, + bar: String, +} + // Eq is derived #[derive(PartialEq, Eq)] pub struct NotMissingEq { diff --git a/tests/ui/derive_partial_eq_without_eq.rs b/tests/ui/derive_partial_eq_without_eq.rs index 24f687c6c9db..42dc435bdd52 100644 --- a/tests/ui/derive_partial_eq_without_eq.rs +++ b/tests/ui/derive_partial_eq_without_eq.rs @@ -1,3 +1,4 @@ +#![feature(lint_reasons)] #![allow(unused)] #![warn(clippy::derive_partial_eq_without_eq)] @@ -14,6 +15,22 @@ pub struct MissingEq { bar: String, } +// Check that we honor the `allow` attribute +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Debug, PartialEq)] +pub struct AllowedMissingEq { + foo: u32, + bar: String, +} + +// Check that we honor the `expect` attribute +#[expect(clippy::derive_partial_eq_without_eq)] +#[derive(Debug, PartialEq)] +pub struct ExpectedMissingEq { + foo: u32, + bar: String, +} + // Eq is derived #[derive(PartialEq, Eq)] pub struct NotMissingEq { diff --git a/tests/ui/derive_partial_eq_without_eq.stderr b/tests/ui/derive_partial_eq_without_eq.stderr index 3d92112dc36d..29cd7da6b77d 100644 --- a/tests/ui/derive_partial_eq_without_eq.stderr +++ b/tests/ui/derive_partial_eq_without_eq.stderr @@ -1,5 +1,5 @@ error: you are deriving `PartialEq` and can implement `Eq` - --> tests/ui/derive_partial_eq_without_eq.rs:11:17 + --> tests/ui/derive_partial_eq_without_eq.rs:12:17 | LL | #[derive(Debug, PartialEq)] | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` @@ -8,73 +8,73 @@ LL | #[derive(Debug, PartialEq)] = help: to override `-D warnings` add `#[allow(clippy::derive_partial_eq_without_eq)]` error: you are deriving `PartialEq` and can implement `Eq` - --> tests/ui/derive_partial_eq_without_eq.rs:53:10 + --> tests/ui/derive_partial_eq_without_eq.rs:70:10 | LL | #[derive(PartialEq)] | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` error: you are deriving `PartialEq` and can implement `Eq` - --> tests/ui/derive_partial_eq_without_eq.rs:59:10 + --> tests/ui/derive_partial_eq_without_eq.rs:76:10 | LL | #[derive(PartialEq)] | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` error: you are deriving `PartialEq` and can implement `Eq` - --> tests/ui/derive_partial_eq_without_eq.rs:65:10 + --> tests/ui/derive_partial_eq_without_eq.rs:82:10 | LL | #[derive(PartialEq)] | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` error: you are deriving `PartialEq` and can implement `Eq` - --> tests/ui/derive_partial_eq_without_eq.rs:68:10 + --> tests/ui/derive_partial_eq_without_eq.rs:85:10 | LL | #[derive(PartialEq)] | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` error: you are deriving `PartialEq` and can implement `Eq` - --> tests/ui/derive_partial_eq_without_eq.rs:74:10 + --> tests/ui/derive_partial_eq_without_eq.rs:91:10 | LL | #[derive(PartialEq)] | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` error: you are deriving `PartialEq` and can implement `Eq` - --> tests/ui/derive_partial_eq_without_eq.rs:80:10 + --> tests/ui/derive_partial_eq_without_eq.rs:97:10 | LL | #[derive(PartialEq)] | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` error: you are deriving `PartialEq` and can implement `Eq` - --> tests/ui/derive_partial_eq_without_eq.rs:93:17 + --> tests/ui/derive_partial_eq_without_eq.rs:110:17 | LL | #[derive(Debug, PartialEq, Clone)] | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` error: you are deriving `PartialEq` and can implement `Eq` - --> tests/ui/derive_partial_eq_without_eq.rs:96:10 + --> tests/ui/derive_partial_eq_without_eq.rs:113:10 | LL | #[derive(PartialEq)] | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` error: you are deriving `PartialEq` and can implement `Eq` - --> tests/ui/derive_partial_eq_without_eq.rs:103:14 + --> tests/ui/derive_partial_eq_without_eq.rs:120:14 | LL | #[derive(PartialEq)] | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` error: you are deriving `PartialEq` and can implement `Eq` - --> tests/ui/derive_partial_eq_without_eq.rs:106:14 + --> tests/ui/derive_partial_eq_without_eq.rs:123:14 | LL | #[derive(PartialEq)] | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` error: you are deriving `PartialEq` and can implement `Eq` - --> tests/ui/derive_partial_eq_without_eq.rs:166:14 + --> tests/ui/derive_partial_eq_without_eq.rs:183:14 | LL | #[derive(PartialEq)] | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` error: you are deriving `PartialEq` and can implement `Eq` - --> tests/ui/derive_partial_eq_without_eq.rs:174:14 + --> tests/ui/derive_partial_eq_without_eq.rs:191:14 | LL | #[derive(PartialEq)] | ^^^^^^^^^ help: consider deriving `Eq` as well: `PartialEq, Eq` From 714e172ef215f6c57a2449175278f6e0c330a2af Mon Sep 17 00:00:00 2001 From: Boxy Date: Fri, 24 May 2024 17:25:50 +0100 Subject: [PATCH 040/211] Remove `DefId` from `EarlyParamRegion` (clippy/smir) --- clippy_lints/src/ptr.rs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 65929cd5fea9..38580dc58226 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -460,13 +460,19 @@ fn check_fn_args<'cx, 'tcx: 'cx>( } None }) { - if !lifetime.is_anonymous() + if let LifetimeName::Param(param_def_id) = lifetime.res + && !lifetime.is_anonymous() && fn_sig .output() .walk() .filter_map(|arg| { arg.as_region().and_then(|lifetime| match lifetime.kind() { - ty::ReEarlyParam(r) => Some(r.def_id), + ty::ReEarlyParam(r) => Some( + cx.tcx + .generics_of(cx.tcx.parent(param_def_id.to_def_id())) + .region_param(r, cx.tcx) + .def_id, + ), ty::ReBound(_, r) => r.kind.get_id(), ty::ReLateParam(r) => r.bound_region.get_id(), ty::ReStatic @@ -476,14 +482,7 @@ fn check_fn_args<'cx, 'tcx: 'cx>( | ty::ReError(_) => None, }) }) - .any(|def_id| { - matches!( - lifetime.res, - LifetimeName::Param(param_def_id) if def_id - .as_local() - .is_some_and(|def_id| def_id == param_def_id), - ) - }) + .any(|def_id| def_id.as_local().is_some_and(|def_id| def_id == param_def_id)) { // `&Cow<'a, T>` when the return type uses 'a is okay return None; From 65dffc1990f91b470f23175ef243bdd5e0b5313a Mon Sep 17 00:00:00 2001 From: Mahmoud Al-Qudsi Date: Fri, 24 May 2024 12:10:05 -0500 Subject: [PATCH 041/211] Change pedantically incorrect OnceCell/OnceLock wording While the semantic intent of a OnceCell/OnceLock is that it can only be written to once (upon init), the fact of the matter is that both these types offer a `take(&mut self) -> Option` mechanism that, when successful, resets the cell to its initial state, thereby technically allowing it to be written to again. Despite the fact that this can only happen with a mutable reference (generally only used during the construction of the OnceCell/OnceLock), it would be incorrect to say that the type itself as a whole categorically prevents being initialized or written to more than once (since it is possible to imagine an identical type only without the `take()` method that actually fulfills that contract). To clarify, change "that cannot be.." to "that nominally cannot.." and add a note to OnceCell about what can be done with an `&mut Self` reference. --- library/core/src/cell/once.rs | 4 ++-- library/std/src/sync/once_lock.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/library/core/src/cell/once.rs b/library/core/src/cell/once.rs index a7c3dfc982d1..872b4da4dbfd 100644 --- a/library/core/src/cell/once.rs +++ b/library/core/src/cell/once.rs @@ -2,12 +2,12 @@ use crate::cell::UnsafeCell; use crate::fmt; use crate::mem; -/// A cell which can be written to only once. +/// A cell which can nominally be written to only once. /// /// This allows obtaining a shared `&T` reference to its inner value without copying or replacing /// it (unlike [`Cell`]), and without runtime borrow checks (unlike [`RefCell`]). However, /// only immutable references can be obtained unless one has a mutable reference to the cell -/// itself. +/// itself. In the same vein, the cell can only be re-initialized with such a mutable reference. /// /// For a thread-safe version of this struct, see [`std::sync::OnceLock`]. /// diff --git a/library/std/src/sync/once_lock.rs b/library/std/src/sync/once_lock.rs index fc830baccedd..6b9f70da8547 100644 --- a/library/std/src/sync/once_lock.rs +++ b/library/std/src/sync/once_lock.rs @@ -5,7 +5,7 @@ use crate::mem::MaybeUninit; use crate::panic::{RefUnwindSafe, UnwindSafe}; use crate::sync::Once; -/// A synchronization primitive which can be written to only once. +/// A synchronization primitive which can nominally be written to only once. /// /// This type is a thread-safe [`OnceCell`], and can be used in statics. /// From e0d1092d63d80d32685e2aec3fe2fc0e70a106cb Mon Sep 17 00:00:00 2001 From: Luuk Wester Date: Fri, 24 May 2024 21:51:05 +0200 Subject: [PATCH 042/211] cosmetic and performance fixes, and drop support for adding //! comments anywhere, except for at the top of files. --- .../convert_comment_from_or_to_doc.rs | 189 +++++++----------- .../crates/ide-assists/src/tests/generated.rs | 4 +- 2 files changed, 79 insertions(+), 114 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs index 1ac30d71f267..2e738834475c 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs @@ -11,12 +11,12 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; // Converts comments to documentation. // // ``` -// // Wow what $0a nice function +// // Wow what $0a nice module // // I sure hope this shows up when I hover over it // ``` // -> // ``` -// //! Wow what a nice function +// //! Wow what a nice module // //! I sure hope this shows up when I hover over it // ``` pub(crate) fn convert_comment_from_or_to_doc( @@ -43,7 +43,7 @@ fn doc_to_comment(acc: &mut Assists, comment: ast::Comment) -> Option<()> { acc.add( AssistId("doc_to_comment", AssistKind::RefactorRewrite), - "Replace a comment with doc comment", + "Replace comment with doc comment", target, |edit| { // We need to either replace the first occurrence of /* with /***, or we need to replace @@ -52,11 +52,12 @@ fn doc_to_comment(acc: &mut Assists, comment: ast::Comment) -> Option<()> { ast::CommentShape::Line => { let indentation = IndentLevel::from_token(comment.syntax()); let line_start = comment.prefix(); + let prefix = format!("{indentation}//"); relevant_line_comments(&comment) .iter() .map(|comment| comment.text()) .flat_map(|text| text.lines()) - .map(|line| indentation.to_string() + &line.replacen(line_start, "//", 1)) + .map(|line| line.replacen(line_start, &prefix, 1)) .join("\n") } ast::CommentShape::Block => { @@ -89,23 +90,23 @@ fn comment_to_doc(acc: &mut Assists, comment: ast::Comment, style: CommentPlacem acc.add( AssistId("comment_to_doc", AssistKind::RefactorRewrite), - "Replace a doc comment with comment", + "Replace doc comment with comment", target, |edit| { // We need to either replace the first occurrence of /* with /***, or we need to replace // the occurrences // at the start of each line with /// let output = match comment.kind().shape { ast::CommentShape::Line => { - let line_start = match style { - CommentPlacement::Inner => "//!", - CommentPlacement::Outer => "///", - }; let indentation = IndentLevel::from_token(comment.syntax()); + let line_start = match style { + CommentPlacement::Inner => format!("{indentation}//!"), + CommentPlacement::Outer => format!("{indentation}///"), + }; relevant_line_comments(&comment) .iter() .map(|comment| comment.text()) .flat_map(|text| text.lines()) - .map(|line| indentation.to_string() + &line.replacen("//", line_start, 1)) + .map(|line| line.replacen("//", &line_start, 1)) .join("\n") } ast::CommentShape::Block => { @@ -139,21 +140,21 @@ fn comment_to_doc(acc: &mut Assists, comment: ast::Comment, style: CommentPlacem /// Not all comments are valid candidates for conversion into doc comments. For example, the /// comments in the code: /// ```rust -/// // foos the bar -/// fn foo_bar(foo: Foo) -> Bar { -/// // Bar the foo -/// foo.into_bar() +/// // Brilliant module right here +/// +/// // Really good right +/// fn good_function(foo: Foo) -> Bar { +/// foo.into_bar() /// } /// -/// trait A { -/// // The A trait -/// } +/// // So nice +/// mod nice_module {} /// ``` /// can be converted to doc comments. However, the comments in this example: /// ```rust /// fn foo_bar(foo: Foo /* not bar yet */) -> Bar { -/// foo.into_bar() -/// // Nicely done +/// foo.into_bar() +/// // Nicely done /// } /// // end of function /// @@ -161,7 +162,23 @@ fn comment_to_doc(acc: &mut Assists, comment: ast::Comment, style: CommentPlacem /// // The S struct /// } /// ``` -/// are not allowed to become doc comments. +/// are not allowed to become doc comments. Moreover, some comments _are_ allowed, but aren't common +/// style in Rust. For example, the following comments are allowed to be doc comments, but it is not +/// common style for them to be: +/// ```rust +/// fn foo_bar(foo: Foo) -> Bar { +/// // this could be an inner comment with //! +/// foo.into_bar() +/// } +/// +/// trait T { +/// // The T struct could also be documented from within +/// } +/// +/// mod mymod { +/// // Modules only normally get inner documentation when they are defined as a separate file. +/// } +/// ``` fn can_be_doc_comment(comment: &ast::Comment) -> Option { use syntax::SyntaxKind::*; @@ -175,38 +192,12 @@ fn can_be_doc_comment(comment: &ast::Comment) -> Option { None => return Some(CommentPlacement::Inner), } - // check if comment is followed by: `struct`, `trait`, `mod`, `fn`, `type`, `extern crate`, `use`, `const` + // check if comment is followed by: `struct`, `trait`, `mod`, `fn`, `type`, `extern crate`, + // `use` or `const`. let parent = comment.syntax().parent(); let parent_kind = parent.as_ref().map(|parent| parent.kind()); - if matches!( - parent_kind, - Some(STRUCT | TRAIT | MODULE | FN | TYPE_KW | EXTERN_CRATE | USE | CONST) - ) { - return Some(CommentPlacement::Outer); - } - - // check if comment is preceded by: `fn f() {`, `trait T {`, `mod M {`: - let third_parent_kind = comment - .syntax() - .parent() - .and_then(|p| p.parent()) - .and_then(|p| p.parent()) - .map(|parent| parent.kind()); - let is_first_item_in_parent = comment - .syntax() - .siblings_with_tokens(Direction::Prev) - .filter_map(|not| not.into_node()) - .next() - .is_none(); - - if matches!(parent_kind, Some(STMT_LIST)) - && is_first_item_in_parent - && matches!(third_parent_kind, Some(FN | TRAIT | MODULE)) - { - return Some(CommentPlacement::Inner); - } - - None + matches!(parent_kind, Some(STRUCT | TRAIT | MODULE | FN | TYPE_KW | EXTERN_CRATE | USE | CONST)) + .then_some(CommentPlacement::Outer) } /// The line -> block assist can be invoked from anywhere within a sequence of line comments. @@ -467,39 +458,26 @@ mod tests { #[test] fn single_inner_line_comment_to_doc() { - check_assist( + check_assist_not_applicable( convert_comment_from_or_to_doc, r#" - fn main() { + mod mymod { // unseen$0 docs foo(); } "#, - r#" - fn main() { - //! unseen docs - foo(); - } - "#, ); } #[test] fn multi_inner_line_comment_to_doc() { - check_assist( + check_assist_not_applicable( convert_comment_from_or_to_doc, r#" - fn main() { + mod mymod { // unseen$0 docs // make me seen! - foo(); - } - "#, - r#" - fn main() { - //! unseen docs - //! make me seen! - foo(); + type Int = i32; } "#, ); @@ -510,13 +488,13 @@ mod tests { check_assist( convert_comment_from_or_to_doc, r#" - fn main() { + mod mymod { //! visible$0 docs foo(); } "#, r#" - fn main() { + mod mymod { // visible docs foo(); } @@ -529,58 +507,33 @@ mod tests { check_assist( convert_comment_from_or_to_doc, r#" - fn main() { + mod mymod { //! visible$0 docs //! Hide me! foo(); } "#, r#" - fn main() { + mod mymod { // visible docs // Hide me! foo(); } "#, ); - } - - #[test] - fn single_inner_line_block_comment_to_doc() { check_assist( convert_comment_from_or_to_doc, r#" - fn main() { - /* unseen$0 docs */ + mod mymod { + /// visible$0 docs + /// Hide me! foo(); } "#, r#" - fn main() { - /*! unseen docs */ - foo(); - } - "#, - ); - } - - #[test] - fn multi_inner_line_block_comment_to_doc() { - check_assist( - convert_comment_from_or_to_doc, - r#" - fn main() { - /* unseen$0 docs - * make me seen! - */ - foo(); - } - "#, - r#" - fn main() { - /*! unseen docs - * make me seen! - */ + mod mymod { + // visible docs + // Hide me! foo(); } "#, @@ -592,15 +545,15 @@ mod tests { check_assist( convert_comment_from_or_to_doc, r#" - fn main() { + mod mymod { /*! visible$0 docs */ - foo(); + type Int = i32; } "#, r#" - fn main() { + mod mymod { /* visible docs */ - foo(); + type Int = i32; } "#, ); @@ -611,21 +564,21 @@ mod tests { check_assist( convert_comment_from_or_to_doc, r#" - fn main() { + mod mymod { /*! visible$0 docs * Hide me! */ - foo(); + type Int = i32; } "#, r#" - fn main() { + mod mymod { /* visible docs * Hide me! */ - foo(); + type Int = i32; } - "#, + "#, ); } @@ -642,4 +595,16 @@ mod tests { "#, ); } + + #[test] + fn no_inner_comments() { + check_assist_not_applicable( + convert_comment_from_or_to_doc, + r#" + mod mymod { + // aaa$0aa + } + "#, + ); + } } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs index bd841d72e6c1..5ecce3cbb686 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs @@ -350,11 +350,11 @@ fn doctest_comment_to_doc() { check_doc_test( "comment_to_doc", r#####" -// Wow what $0a nice function +// Wow what $0a nice module // I sure hope this shows up when I hover over it "#####, r#####" -//! Wow what a nice function +//! Wow what a nice module //! I sure hope this shows up when I hover over it "#####, ) From 28399f9a80f0f225244618f7fc5169194f9a12b0 Mon Sep 17 00:00:00 2001 From: Luuk Wester Date: Fri, 24 May 2024 22:24:35 +0200 Subject: [PATCH 043/211] add test for every keyword, fix bug --- .../convert_comment_from_or_to_doc.rs | 110 +++++++++++++++--- 1 file changed, 94 insertions(+), 16 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs index 2e738834475c..d714f63f1132 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs @@ -195,8 +195,8 @@ fn can_be_doc_comment(comment: &ast::Comment) -> Option { // check if comment is followed by: `struct`, `trait`, `mod`, `fn`, `type`, `extern crate`, // `use` or `const`. let parent = comment.syntax().parent(); - let parent_kind = parent.as_ref().map(|parent| parent.kind()); - matches!(parent_kind, Some(STRUCT | TRAIT | MODULE | FN | TYPE_KW | EXTERN_CRATE | USE | CONST)) + let par_kind = parent.as_ref().map(|parent| parent.kind()); + matches!(par_kind, Some(STRUCT | TRAIT | MODULE | FN | TYPE_ALIAS | EXTERN_CRATE | USE | CONST)) .then_some(CommentPlacement::Outer) } @@ -469,20 +469,6 @@ mod tests { ); } - #[test] - fn multi_inner_line_comment_to_doc() { - check_assist_not_applicable( - convert_comment_from_or_to_doc, - r#" - mod mymod { - // unseen$0 docs - // make me seen! - type Int = i32; - } - "#, - ); - } - #[test] fn single_inner_line_doc_to_comment() { check_assist( @@ -596,6 +582,98 @@ mod tests { ); } + #[test] + fn all_possible_items() { + check_assist( + convert_comment_from_or_to_doc, + r#"mod m { + /* Nice struct$0 */ + struct S {} + }"#, + r#"mod m { + /** Nice struct */ + struct S {} + }"#, + ); + check_assist( + convert_comment_from_or_to_doc, + r#"mod m { + /* Nice trait$0 */ + trait T {} + }"#, + r#"mod m { + /** Nice trait */ + trait T {} + }"#, + ); + check_assist( + convert_comment_from_or_to_doc, + r#"mod m { + /* Nice module$0 */ + mod module {} + }"#, + r#"mod m { + /** Nice module */ + mod module {} + }"#, + ); + check_assist( + convert_comment_from_or_to_doc, + r#"mod m { + /* Nice function$0 */ + fn function() {} + }"#, + r#"mod m { + /** Nice function */ + fn function() {} + }"#, + ); + check_assist( + convert_comment_from_or_to_doc, + r#"mod m { + /* Nice type$0 */ + type Type Int = i32; + }"#, + r#"mod m { + /** Nice type */ + type Type Int = i32; + }"#, + ); + check_assist( + convert_comment_from_or_to_doc, + r#"mod m { + /* Nice crate$0 */ + extern crate rust_analyzer; + }"#, + r#"mod m { + /** Nice crate */ + extern crate rust_analyzer; + }"#, + ); + check_assist( + convert_comment_from_or_to_doc, + r#"mod m { + /* Nice import$0 */ + use ide_assists::convert_comment_from_or_to_doc::tests + }"#, + r#"mod m { + /** Nice import */ + use ide_assists::convert_comment_from_or_to_doc::tests + }"#, + ); + check_assist( + convert_comment_from_or_to_doc, + r#"mod m { + /* Nice constant$0 */ + const CONST: &str = "very const"; + }"#, + r#"mod m { + /** Nice constant */ + const CONST: &str = "very const"; + }"#, + ); + } + #[test] fn no_inner_comments() { check_assist_not_applicable( From 000713898c6699fdeb5ca14f000bb4467d7812d2 Mon Sep 17 00:00:00 2001 From: Luuk Wester Date: Fri, 24 May 2024 22:57:35 +0200 Subject: [PATCH 044/211] remove nested match with and_then --- .../src/handlers/convert_comment_from_or_to_doc.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs index d714f63f1132..953119fd1ff9 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs @@ -27,10 +27,7 @@ pub(crate) fn convert_comment_from_or_to_doc( match comment.kind().doc { Some(_) => doc_to_comment(acc, comment), - None => match can_be_doc_comment(&comment) { - Some(doc_comment_style) => comment_to_doc(acc, comment, doc_comment_style), - None => None, - }, + None => can_be_doc_comment(&comment).and_then(|style| comment_to_doc(acc, comment, style)), } } From 17cc0a3a7d286b36a5745aafbfff7ac662270b5b Mon Sep 17 00:00:00 2001 From: Hamir Mahal Date: Fri, 24 May 2024 14:30:42 -0700 Subject: [PATCH 045/211] feat: auto-fix for `bare URLs` in doc comments --- clippy_lints/src/doc/markdown.rs | 8 +++++--- tests/ui/doc/doc-fixable.fixed | 3 +++ tests/ui/doc/doc-fixable.rs | 3 +++ tests/ui/doc/doc-fixable.stderr | 8 +++++++- 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/doc/markdown.rs b/clippy_lints/src/doc/markdown.rs index 1add02af3101..8a497b5ab0d9 100644 --- a/clippy_lints/src/doc/markdown.rs +++ b/clippy_lints/src/doc/markdown.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; +use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::source::snippet_with_applicability; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Applicability, SuggestionStyle}; @@ -92,13 +92,15 @@ fn check_word(cx: &LateContext<'_>, word: &str, span: Span, code_level: isize, b if let Ok(url) = Url::parse(word) { // try to get around the fact that `foo::bar` parses as a valid URL if !url.cannot_be_a_base() { - span_lint( + span_lint_and_sugg( cx, DOC_MARKDOWN, span, "you should put bare URLs between `<`/`>` or make a proper Markdown link", + "try", + format!("<{word}>"), + Applicability::MachineApplicable, ); - return; } } diff --git a/tests/ui/doc/doc-fixable.fixed b/tests/ui/doc/doc-fixable.fixed index 7e22c847b1bc..84673f1f43fd 100644 --- a/tests/ui/doc/doc-fixable.fixed +++ b/tests/ui/doc/doc-fixable.fixed @@ -240,3 +240,6 @@ extern { /// `foo()` fn in_extern(); } + +/// +fn check_autofix_for_base_urls() {} diff --git a/tests/ui/doc/doc-fixable.rs b/tests/ui/doc/doc-fixable.rs index 3e2cb0df54b0..4d017a99e0fb 100644 --- a/tests/ui/doc/doc-fixable.rs +++ b/tests/ui/doc/doc-fixable.rs @@ -240,3 +240,6 @@ extern { /// foo() fn in_extern(); } + +/// https://github.com/rust-lang/rust-clippy/pull/12836 +fn check_autofix_for_base_urls() {} diff --git a/tests/ui/doc/doc-fixable.stderr b/tests/ui/doc/doc-fixable.stderr index cd2228c47e35..a9263f62d38d 100644 --- a/tests/ui/doc/doc-fixable.stderr +++ b/tests/ui/doc/doc-fixable.stderr @@ -363,5 +363,11 @@ help: try LL | /// `foo()` | ~~~~~~~ -error: aborting due to 33 previous errors +error: you should put bare URLs between `<`/`>` or make a proper Markdown link + --> tests/ui/doc/doc-fixable.rs:244:5 + | +LL | /// https://github.com/rust-lang/rust-clippy/pull/12836 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `` + +error: aborting due to 34 previous errors From 1052d2931cbc32ffb6e1b648f4d7e248d5fdd889 Mon Sep 17 00:00:00 2001 From: joboet Date: Sat, 25 May 2024 00:19:47 +0200 Subject: [PATCH 046/211] std: make TLS accessors closures that return pointers --- .../src/sys/thread_local/fast_local/eager.rs | 34 +++----- .../src/sys/thread_local/fast_local/lazy.rs | 46 +++------- .../src/sys/thread_local/fast_local/mod.rs | 87 ++++++++----------- library/std/src/sys/thread_local/os_local.rs | 63 ++++++-------- .../std/src/sys/thread_local/static_local.rs | 53 ++++------- library/std/src/thread/local.rs | 12 +-- 6 files changed, 111 insertions(+), 184 deletions(-) diff --git a/library/std/src/sys/thread_local/fast_local/eager.rs b/library/std/src/sys/thread_local/fast_local/eager.rs index c2bc580530ba..b97bd9cc88ce 100644 --- a/library/std/src/sys/thread_local/fast_local/eager.rs +++ b/library/std/src/sys/thread_local/fast_local/eager.rs @@ -21,43 +21,35 @@ impl Storage { Storage { state: Cell::new(State::Initial), val: UnsafeCell::new(val) } } - /// Get a reference to the TLS value. If the TLS variable has been destroyed, - /// `None` is returned. + /// Get a pointer to the TLS value. If the TLS variable has been destroyed, + /// a null pointer is returned. + /// + /// The resulting pointer may not be used after thread destruction has + /// occurred. /// /// # Safety - /// * The `self` reference must remain valid until the TLS destructor has been - /// run. - /// * The returned reference may only be used until thread destruction occurs - /// and may not be used after reentrant initialization has occurred. - /// - // FIXME(#110897): return NonNull instead of lying about the lifetime. + /// The `self` reference must remain valid until the TLS destructor is run. #[inline] - pub unsafe fn get(&self) -> Option<&'static T> { + pub unsafe fn get(&self) -> *const T { match self.state.get() { - // SAFETY: as the state is not `Destroyed`, the value cannot have - // been destroyed yet. The reference fulfills the terms outlined - // above. - State::Alive => unsafe { Some(&*self.val.get()) }, - State::Destroyed => None, + State::Alive => self.val.get(), + State::Destroyed => ptr::null(), State::Initial => unsafe { self.initialize() }, } } #[cold] - unsafe fn initialize(&self) -> Option<&'static T> { + unsafe fn initialize(&self) -> *const T { // Register the destructor // SAFETY: - // * the destructor will be called at thread destruction. - // * the caller guarantees that `self` will be valid until that time. + // The caller guarantees that `self` will be valid until thread destruction. unsafe { register_dtor(ptr::from_ref(self).cast_mut().cast(), destroy::); } + self.state.set(State::Alive); - // SAFETY: as the state is not `Destroyed`, the value cannot have - // been destroyed yet. The reference fulfills the terms outlined - // above. - unsafe { Some(&*self.val.get()) } + self.val.get() } } diff --git a/library/std/src/sys/thread_local/fast_local/lazy.rs b/library/std/src/sys/thread_local/fast_local/lazy.rs index c2e9a1714546..c1ada35d484d 100644 --- a/library/std/src/sys/thread_local/fast_local/lazy.rs +++ b/library/std/src/sys/thread_local/fast_local/lazy.rs @@ -39,49 +39,31 @@ where Storage { state: UnsafeCell::new(State::Initial) } } - /// Get a reference to the TLS value, potentially initializing it with the - /// provided parameters. If the TLS variable has been destroyed, `None` is - /// returned. + /// Get a pointer to the TLS value, potentially initializing it with the + /// provided parameters. If the TLS variable has been destroyed, a null + /// pointer is returned. + /// + /// The resulting pointer may not be used after reentrant inialialization + /// or thread destruction has occurred. /// /// # Safety - /// * The `self` reference must remain valid until the TLS destructor is run, - /// at which point the returned reference is invalidated. - /// * The returned reference may only be used until thread destruction occurs - /// and may not be used after reentrant initialization has occurred. - /// - // FIXME(#110897): return NonNull instead of lying about the lifetime. + /// The `self` reference must remain valid until the TLS destructor is run. #[inline] - pub unsafe fn get_or_init( - &self, - i: Option<&mut Option>, - f: impl FnOnce() -> T, - ) -> Option<&'static T> { - // SAFETY: - // No mutable reference to the inner value exists outside the calls to - // `replace`. The lifetime of the returned reference fulfills the terms - // outlined above. + pub unsafe fn get_or_init(&self, i: Option<&mut Option>, f: impl FnOnce() -> T) -> *const T { let state = unsafe { &*self.state.get() }; match state { - State::Alive(v) => Some(v), - State::Destroyed(_) => None, + State::Alive(v) => v, + State::Destroyed(_) => ptr::null(), State::Initial => unsafe { self.initialize(i, f) }, } } #[cold] - unsafe fn initialize( - &self, - i: Option<&mut Option>, - f: impl FnOnce() -> T, - ) -> Option<&'static T> { + unsafe fn initialize(&self, i: Option<&mut Option>, f: impl FnOnce() -> T) -> *const T { // Perform initialization let v = i.and_then(Option::take).unwrap_or_else(f); - // SAFETY: - // If references to the inner value exist, they were created in `f` - // and are invalidated here. The caller promises to never use them - // after this. let old = unsafe { self.state.get().replace(State::Alive(v)) }; match old { // If the variable is not being recursively initialized, register @@ -92,12 +74,10 @@ where val => drop(val), } - // SAFETY: - // Initialization was completed and the state was set to `Alive`, so the - // reference fulfills the terms outlined above. + // SAFETY: the state was just set to `Alive` unsafe { let State::Alive(v) = &*self.state.get() else { unreachable_unchecked() }; - Some(v) + v } } } diff --git a/library/std/src/sys/thread_local/fast_local/mod.rs b/library/std/src/sys/thread_local/fast_local/mod.rs index 25379071cb7a..5fc8226403d6 100644 --- a/library/std/src/sys/thread_local/fast_local/mod.rs +++ b/library/std/src/sys/thread_local/fast_local/mod.rs @@ -52,32 +52,26 @@ pub macro thread_local_inner { (@key $t:ty, const $init:expr) => {{ const __INIT: $t = $init; - #[inline] - #[deny(unsafe_op_in_unsafe_fn)] - unsafe fn __getit( - _init: $crate::option::Option<&mut $crate::option::Option<$t>>, - ) -> $crate::option::Option<&'static $t> { - use $crate::thread::local_impl::EagerStorage; - use $crate::mem::needs_drop; - use $crate::ptr::addr_of; - - if needs_drop::<$t>() { - #[thread_local] - static VAL: EagerStorage<$t> = EagerStorage::new(__INIT); - unsafe { - VAL.get() - } - } else { - #[thread_local] - static VAL: $t = __INIT; - unsafe { - $crate::option::Option::Some(&*addr_of!(VAL)) - } - } - } - unsafe { - $crate::thread::LocalKey::new(__getit) + use $crate::mem::needs_drop; + use $crate::thread::LocalKey; + use $crate::thread::local_impl::EagerStorage; + + LocalKey::new(const { + if needs_drop::<$t>() { + |_| { + #[thread_local] + static VAL: EagerStorage<$t> = EagerStorage::new(__INIT); + VAL.get() + } + } else { + |_| { + #[thread_local] + static VAL: $t = __INIT; + &VAL + } + } + }) } }}, @@ -88,31 +82,26 @@ pub macro thread_local_inner { $init } - #[inline] - #[deny(unsafe_op_in_unsafe_fn)] - unsafe fn __getit( - init: $crate::option::Option<&mut $crate::option::Option<$t>>, - ) -> $crate::option::Option<&'static $t> { - use $crate::thread::local_impl::LazyStorage; - use $crate::mem::needs_drop; - - if needs_drop::<$t>() { - #[thread_local] - static VAL: LazyStorage<$t, ()> = LazyStorage::new(); - unsafe { - VAL.get_or_init(init, __init) - } - } else { - #[thread_local] - static VAL: LazyStorage<$t, !> = LazyStorage::new(); - unsafe { - VAL.get_or_init(init, __init) - } - } - } - unsafe { - $crate::thread::LocalKey::new(__getit) + use $crate::mem::needs_drop; + use $crate::thread::LocalKey; + use $crate::thread::local_impl::LazyStorage; + + LocalKey::new(const { + if needs_drop::<$t>() { + |init| { + #[thread_local] + static VAL: LazyStorage<$t, ()> = LazyStorage::new(); + VAL.get_or_init(init, __init) + } + } else { + |init| { + #[thread_local] + static VAL: LazyStorage<$t, !> = LazyStorage::new(); + VAL.get_or_init(init, __init) + } + } + }) } }}, ($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $($init:tt)*) => { diff --git a/library/std/src/sys/thread_local/os_local.rs b/library/std/src/sys/thread_local/os_local.rs index d6ddbb78a9c8..ee5adef66eac 100644 --- a/library/std/src/sys/thread_local/os_local.rs +++ b/library/std/src/sys/thread_local/os_local.rs @@ -16,30 +16,22 @@ pub macro thread_local_inner { }, // used to generate the `LocalKey` value for `thread_local!` - (@key $t:ty, $init:expr) => { - { - #[inline] - fn __init() -> $t { $init } + (@key $t:ty, $init:expr) => {{ + #[inline] + fn __init() -> $t { $init } - // `#[inline] does not work on windows-gnu due to linking errors around dllimports. - // See https://github.com/rust-lang/rust/issues/109797. - #[cfg_attr(not(windows), inline)] - unsafe fn __getit( - init: $crate::option::Option<&mut $crate::option::Option<$t>>, - ) -> $crate::option::Option<&'static $t> { - use $crate::thread::local_impl::Key; + unsafe { + use $crate::thread::LocalKey; + use $crate::thread::local_impl::Key; - static __KEY: Key<$t> = Key::new(); - unsafe { - __KEY.get(init, __init) - } - } - - unsafe { - $crate::thread::LocalKey::new(__getit) - } + // Inlining does not work on windows-gnu due to linking errors around + // dllimports. See https://github.com/rust-lang/rust/issues/109797. + LocalKey::new(#[cfg_attr(windows, inline(never))] |init| { + static VAL: Key<$t> = Key::new(); + VAL.get(init, __init) + }) } - }, + }}, ($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $($init:tt)*) => { $(#[$attr])* $vis const $name: $crate::thread::LocalKey<$t> = $crate::thread::local_impl::thread_local_inner!(@key $t, $($init)*); @@ -67,38 +59,33 @@ impl Key { Key { os: OsKey::new(Some(destroy_value::)), marker: PhantomData } } - /// Get the value associated with this key, initializating it if necessary. + /// Get a pointer to the TLS value, potentially initializing it with the + /// provided parameters. If the TLS variable has been destroyed, a null + /// pointer is returned. /// - /// # Safety - /// * the returned reference must not be used after recursive initialization - /// or thread destruction occurs. - pub unsafe fn get( - &'static self, - i: Option<&mut Option>, - f: impl FnOnce() -> T, - ) -> Option<&'static T> { + /// The resulting pointer may not be used after reentrant inialialization + /// or thread destruction has occurred. + pub fn get(&'static self, i: Option<&mut Option>, f: impl FnOnce() -> T) -> *const T { // SAFETY: (FIXME: get should actually be safe) let ptr = unsafe { self.os.get() as *mut Value }; if ptr.addr() > 1 { // SAFETY: the check ensured the pointer is safe (its destructor // is not running) + it is coming from a trusted source (self). - unsafe { Some(&(*ptr).value) } + unsafe { &(*ptr).value } } else { - // SAFETY: At this point we are sure we have no value and so - // initializing (or trying to) is safe. - unsafe { self.try_initialize(ptr, i, f) } + self.try_initialize(ptr, i, f) } } - unsafe fn try_initialize( + fn try_initialize( &'static self, ptr: *mut Value, i: Option<&mut Option>, f: impl FnOnce() -> T, - ) -> Option<&'static T> { + ) -> *const T { if ptr.addr() == 1 { // destructor is running - return None; + return ptr::null(); } let value = i.and_then(Option::take).unwrap_or_else(f); @@ -119,7 +106,7 @@ impl Key { } // SAFETY: We just created this value above. - unsafe { Some(&(*ptr).value) } + unsafe { &(*ptr).value } } } diff --git a/library/std/src/sys/thread_local/static_local.rs b/library/std/src/sys/thread_local/static_local.rs index 6beda2e71880..0f08cab1ae4f 100644 --- a/library/std/src/sys/thread_local/static_local.rs +++ b/library/std/src/sys/thread_local/static_local.rs @@ -13,19 +13,14 @@ pub macro thread_local_inner { (@key $t:ty, const $init:expr) => {{ const __INIT: $t = $init; - #[inline] - #[deny(unsafe_op_in_unsafe_fn)] - unsafe fn __getit( - _init: $crate::option::Option<&mut $crate::option::Option<$t>>, - ) -> $crate::option::Option<&'static $t> { + unsafe { + use $crate::thread::LocalKey; use $crate::thread::local_impl::EagerStorage; - static VAL: EagerStorage<$t> = EagerStorage { value: __INIT }; - $crate::option::Option::Some(&VAL.value) - } - - unsafe { - $crate::thread::LocalKey::new(__getit) + LocalKey::new(|_| { + static VAL: EagerStorage<$t> = EagerStorage { value: __INIT }; + &VAL.value + }) } }}, @@ -34,19 +29,14 @@ pub macro thread_local_inner { #[inline] fn __init() -> $t { $init } - #[inline] - #[deny(unsafe_op_in_unsafe_fn)] - unsafe fn __getit( - init: $crate::option::Option<&mut $crate::option::Option<$t>>, - ) -> $crate::option::Option<&'static $t> { + unsafe { + use $crate::thread::LocalKey; use $crate::thread::local_impl::LazyStorage; - static VAL: LazyStorage<$t> = LazyStorage::new(); - unsafe { $crate::option::Option::Some(VAL.get(init, __init)) } - } - - unsafe { - $crate::thread::LocalKey::new(__getit) + LocalKey::new(|init| { + static VAL: LazyStorage<$t> = LazyStorage::new(); + VAL.get(init, __init) + }) } }}, ($(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $($init:tt)*) => { @@ -73,16 +63,13 @@ impl LazyStorage { LazyStorage { value: UnsafeCell::new(None) } } - /// Gets a reference to the contained value, initializing it if necessary. + /// Get a pointer to the TLS value, potentially initializing it with the + /// provided parameters. /// - /// # Safety - /// The returned reference may not be used after reentrant initialization has occurred. + /// The resulting pointer may not be used after reentrant inialialization + /// has occurred. #[inline] - pub unsafe fn get( - &'static self, - i: Option<&mut Option>, - f: impl FnOnce() -> T, - ) -> &'static T { + pub fn get(&'static self, i: Option<&mut Option>, f: impl FnOnce() -> T) -> *const T { let value = unsafe { &*self.value.get() }; match value { Some(v) => v, @@ -91,11 +78,7 @@ impl LazyStorage { } #[cold] - unsafe fn initialize( - &'static self, - i: Option<&mut Option>, - f: impl FnOnce() -> T, - ) -> &'static T { + fn initialize(&'static self, i: Option<&mut Option>, f: impl FnOnce() -> T) -> *const T { let value = i.and_then(Option::take).unwrap_or_else(f); // Destroy the old value, after updating the TLS variable as the // destructor might reference it. diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index c1b4440e5608..aed185637fd1 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -123,7 +123,7 @@ pub struct LocalKey { // trivially devirtualizable by LLVM because the value of `inner` never // changes and the constant should be readonly within a crate. This mainly // only runs into problems when TLS statics are exported across crates. - inner: unsafe fn(Option<&mut Option>) -> Option<&'static T>, + inner: fn(Option<&mut Option>) -> *const T, } #[stable(feature = "std_debug", since = "1.16.0")] @@ -238,9 +238,7 @@ impl LocalKey { issue = "none" )] #[rustc_const_unstable(feature = "thread_local_internals", issue = "none")] - pub const unsafe fn new( - inner: unsafe fn(Option<&mut Option>) -> Option<&'static T>, - ) -> LocalKey { + pub const unsafe fn new(inner: fn(Option<&mut Option>) -> *const T) -> LocalKey { LocalKey { inner } } @@ -281,8 +279,7 @@ impl LocalKey { where F: FnOnce(&T) -> R, { - // SAFETY: `inner` is safe to call within the lifetime of the thread - let thread_local = unsafe { (self.inner)(None).ok_or(AccessError)? }; + let thread_local = unsafe { (self.inner)(None).as_ref().ok_or(AccessError)? }; Ok(f(thread_local)) } @@ -304,9 +301,8 @@ impl LocalKey { { let mut init = Some(init); - // SAFETY: `inner` is safe to call within the lifetime of the thread let reference = unsafe { - (self.inner)(Some(&mut init)).expect( + (self.inner)(Some(&mut init)).as_ref().expect( "cannot access a Thread Local Storage value \ during or after destruction", ) From 6df8d0dd4e05cd96fbc299fa5fc32f37ad936db0 Mon Sep 17 00:00:00 2001 From: joboet Date: Sat, 25 May 2024 09:37:08 +0200 Subject: [PATCH 047/211] fix UI test --- .../suggestions/missing-lifetime-specifier.rs | 22 ++--- .../missing-lifetime-specifier.stderr | 90 +++---------------- 2 files changed, 21 insertions(+), 91 deletions(-) diff --git a/tests/ui/suggestions/missing-lifetime-specifier.rs b/tests/ui/suggestions/missing-lifetime-specifier.rs index cd7fa0c1d856..dd437fc0c0b8 100644 --- a/tests/ui/suggestions/missing-lifetime-specifier.rs +++ b/tests/ui/suggestions/missing-lifetime-specifier.rs @@ -1,6 +1,11 @@ -// different number of duplicated diagnostics on different targets -//@ only-x86_64 -//@ only-linux +// The specific errors produced depend the thread-local implementation. +// Run only on platforms with "fast" TLS. +//@ ignore-windows FIXME(#84933) +//@ ignore-wasm globals are used instead of thread locals +//@ ignore-emscripten globals are used instead of thread locals +//@ ignore-android does not use #[thread_local] +//@ ignore-nto does not use #[thread_local] +// Different number of duplicated diagnostics on different targets //@ compile-flags: -Zdeduplicate-diagnostics=yes #![allow(bare_trait_objects)] @@ -21,23 +26,19 @@ trait Tar<'t, 'k, I> {} thread_local! { static a: RefCell>>> = RefCell::new(HashMap::new()); - //~^ ERROR missing lifetime specifiers - //~| ERROR missing lifetime specifiers + //~^ ERROR missing lifetime specifiers } thread_local! { static b: RefCell>>> = RefCell::new(HashMap::new()); - //~^ ERROR missing lifetime specifiers - //~| ERROR missing lifetime specifiers + //~^ ERROR missing lifetime specifiers } thread_local! { static c: RefCell>>>> = RefCell::new(HashMap::new()); //~^ ERROR missing lifetime specifiers - //~| ERROR missing lifetime specifiers } thread_local! { static d: RefCell>>>> = RefCell::new(HashMap::new()); //~^ ERROR missing lifetime specifiers - //~| ERROR missing lifetime specifiers } thread_local! { @@ -47,8 +48,7 @@ thread_local! { thread_local! { static f: RefCell>>>> = RefCell::new(HashMap::new()); //~^ ERROR trait takes 2 lifetime arguments but 1 lifetime argument was supplied - //~| ERROR missing lifetime - //~| ERROR missing lifetime + //~| ERROR missing lifetime specifier } fn main() {} diff --git a/tests/ui/suggestions/missing-lifetime-specifier.stderr b/tests/ui/suggestions/missing-lifetime-specifier.stderr index 2b85cfde7b64..e0b6bb872b55 100644 --- a/tests/ui/suggestions/missing-lifetime-specifier.stderr +++ b/tests/ui/suggestions/missing-lifetime-specifier.stderr @@ -1,5 +1,5 @@ error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:23:44 + --> $DIR/missing-lifetime-specifier.rs:28:44 | LL | static a: RefCell>>> = RefCell::new(HashMap::new()); | ^^^ expected 2 lifetime parameters @@ -11,20 +11,7 @@ LL | static a: RefCell>>>> = RefC | ++++++++++++++++++ error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:23:44 - | -LL | / thread_local! { -LL | | static a: RefCell>>> = RefCell::new(HashMap::new()); - | | ^^^ expected 2 lifetime parameters -LL | | -LL | | -LL | | } - | |_- - | - = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 3 lifetimes it is borrowed from - -error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:28:44 + --> $DIR/missing-lifetime-specifier.rs:32:44 | LL | static b: RefCell>>> = RefCell::new(HashMap::new()); | ^^^^ expected 2 lifetime parameters @@ -38,22 +25,7 @@ LL | static b: RefCell>> | +++++++ ++++++++++++++++++ error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:28:44 - | -LL | / thread_local! { -LL | | static b: RefCell>>> = RefCell::new(HashMap::new()); - | | ^^^^ expected 2 lifetime parameters - | | | - | | expected named lifetime parameter -LL | | -LL | | -LL | | } - | |_- - | - = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 4 lifetimes it is borrowed from - -error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:33:47 + --> $DIR/missing-lifetime-specifier.rs:36:47 | LL | static c: RefCell>>>> = RefCell::new(HashMap::new()); | ^ expected 2 lifetime parameters @@ -65,20 +37,7 @@ LL | static c: RefCell>>>> = | +++++++++++++++++ error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:33:47 - | -LL | / thread_local! { -LL | | static c: RefCell>>>> = RefCell::new(HashMap::new()); - | | ^ expected 2 lifetime parameters -LL | | -LL | | -LL | | } - | |_- - | - = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 3 lifetimes it is borrowed from - -error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:38:44 + --> $DIR/missing-lifetime-specifier.rs:40:44 | LL | static d: RefCell>>>> = RefCell::new(HashMap::new()); | ^ ^ expected 2 lifetime parameters @@ -91,23 +50,8 @@ help: consider using the `'static` lifetime, but this is uncommon unless you're LL | static d: RefCell>>>> = RefCell::new(HashMap::new()); | +++++++ +++++++++++++++++ -error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:38:44 - | -LL | / thread_local! { -LL | | static d: RefCell>>>> = RefCell::new(HashMap::new()); - | | ^ ^ expected 2 lifetime parameters - | | | - | | expected named lifetime parameter -LL | | -LL | | -LL | | } - | |_- - | - = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 4 lifetimes it is borrowed from - error[E0106]: missing lifetime specifier - --> $DIR/missing-lifetime-specifier.rs:48:44 + --> $DIR/missing-lifetime-specifier.rs:49:44 | LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); | ^ expected named lifetime parameter @@ -118,22 +62,8 @@ help: consider using the `'static` lifetime, but this is uncommon unless you're LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); | +++++++ -error[E0106]: missing lifetime specifier - --> $DIR/missing-lifetime-specifier.rs:48:44 - | -LL | / thread_local! { -LL | | static f: RefCell>>>> = RefCell::new(HashMap::new()); - | | ^ expected named lifetime parameter -LL | | -LL | | -LL | | -LL | | } - | |_- - | - = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 3 lifetimes it is borrowed from - error[E0107]: union takes 2 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/missing-lifetime-specifier.rs:44:44 + --> $DIR/missing-lifetime-specifier.rs:45:44 | LL | static e: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^ ------- supplied 1 lifetime argument @@ -141,7 +71,7 @@ LL | static e: RefCell>>>> = RefCell: | expected 2 lifetime arguments | note: union defined here, with 2 lifetime parameters: `'t`, `'k` - --> $DIR/missing-lifetime-specifier.rs:16:11 + --> $DIR/missing-lifetime-specifier.rs:21:11 | LL | pub union Qux<'t, 'k, I> { | ^^^ -- -- @@ -151,7 +81,7 @@ LL | static e: RefCell>>>> = | +++++++++ error[E0107]: trait takes 2 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/missing-lifetime-specifier.rs:48:45 + --> $DIR/missing-lifetime-specifier.rs:49:45 | LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^ ------- supplied 1 lifetime argument @@ -159,7 +89,7 @@ LL | static f: RefCell>>>> = RefCell | expected 2 lifetime arguments | note: trait defined here, with 2 lifetime parameters: `'t`, `'k` - --> $DIR/missing-lifetime-specifier.rs:20:7 + --> $DIR/missing-lifetime-specifier.rs:25:7 | LL | trait Tar<'t, 'k, I> {} | ^^^ -- -- @@ -168,7 +98,7 @@ help: add missing lifetime argument LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); | +++++++++ -error: aborting due to 12 previous errors +error: aborting due to 7 previous errors Some errors have detailed explanations: E0106, E0107. For more information about an error, try `rustc --explain E0106`. From 6d6bef0fdf1d58afb2a903e0cf00147df2b5c2ce Mon Sep 17 00:00:00 2001 From: Tavo Annus Date: Sat, 25 May 2024 13:09:26 +0300 Subject: [PATCH 048/211] Fix `data_constructor` ignoring generics for struct --- .../rust-analyzer/crates/hir/src/term_search.rs | 2 +- .../crates/hir/src/term_search/tactics.rs | 10 ++++++---- .../crates/ide-assists/src/handlers/term_search.rs | 12 ++++++++++++ 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir/src/term_search.rs b/src/tools/rust-analyzer/crates/hir/src/term_search.rs index 5c5ddae19e27..7b70cdf45994 100644 --- a/src/tools/rust-analyzer/crates/hir/src/term_search.rs +++ b/src/tools/rust-analyzer/crates/hir/src/term_search.rs @@ -329,7 +329,7 @@ pub fn term_search(ctx: &TermSearchCtx<'_, DB>) -> Vec { while should_continue() { lookup.new_round(); - solutions.extend(tactics::type_constructor(ctx, &defs, &mut lookup, should_continue)); + solutions.extend(tactics::data_constructor(ctx, &defs, &mut lookup, should_continue)); solutions.extend(tactics::free_function(ctx, &defs, &mut lookup, should_continue)); solutions.extend(tactics::impl_method(ctx, &defs, &mut lookup, should_continue)); solutions.extend(tactics::struct_projection(ctx, &defs, &mut lookup, should_continue)); diff --git a/src/tools/rust-analyzer/crates/hir/src/term_search/tactics.rs b/src/tools/rust-analyzer/crates/hir/src/term_search/tactics.rs index a26728272dc6..f95ff1dc0fa1 100644 --- a/src/tools/rust-analyzer/crates/hir/src/term_search/tactics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/term_search/tactics.rs @@ -87,9 +87,9 @@ pub(super) fn trivial<'a, DB: HirDatabase>( }) } -/// # Type constructor tactic +/// # Data constructor tactic /// -/// Attempts different type constructors for enums and structs in scope +/// Attempts different data constructors for enums and structs in scope /// /// Updates lookup by new types reached and returns iterator that yields /// elements that unify with `goal`. @@ -99,7 +99,7 @@ pub(super) fn trivial<'a, DB: HirDatabase>( /// * `defs` - Set of items in scope at term search target location /// * `lookup` - Lookup table for types /// * `should_continue` - Function that indicates when to stop iterating -pub(super) fn type_constructor<'a, DB: HirDatabase>( +pub(super) fn data_constructor<'a, DB: HirDatabase>( ctx: &'a TermSearchCtx<'a, DB>, defs: &'a FxHashSet, lookup: &'a mut LookupTable, @@ -308,7 +308,9 @@ pub(super) fn type_constructor<'a, DB: HirDatabase>( // Early exit if some param cannot be filled from lookup let param_exprs: Vec> = fields .into_iter() - .map(|field| lookup.find(db, &field.ty(db))) + .map(|field| { + lookup.find(db, &field.ty_with_args(db, generics.iter().cloned())) + }) .collect::>()?; // Note that we need special case for 0 param constructors because of multi cartesian diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs index ffd1508ccbdc..94e0519cba0b 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs @@ -278,4 +278,16 @@ fn f() { let a = 1; let b = 0.0; let c: (i32, (i32, f64)) = todo$0!(); }"#, r#"fn f() { let a = 1; let b = 0.0; let c: (i32, (i32, f64)) = (a, (a, b)); }"#, ) } + + #[test] + fn test_tuple_struct_with_generics() { + check_assist( + term_search, + r#"//- minicore: todo, unimplemented +struct Foo(T); +fn f() { let a = 1; let b: Foo = todo$0!(); }"#, + r#"struct Foo(T); +fn f() { let a = 1; let b: Foo = Foo(a); }"#, + ) + } } From e61288cbf053cd313b7539481b3faee1ec351228 Mon Sep 17 00:00:00 2001 From: finga Date: Sat, 25 May 2024 21:36:49 +0200 Subject: [PATCH 049/211] book: Fix example code Fix example code of the "Disabling evaluation of certain code" section in the configuration chapter. --- book/src/configuration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/src/configuration.md b/book/src/configuration.md index 9eb067abd91e..ea549e4df4a5 100644 --- a/book/src/configuration.md +++ b/book/src/configuration.md @@ -133,7 +133,7 @@ Very rarely, you may wish to prevent Clippy from evaluating certain sections of `clippy` cfg is not set. You may need to provide a stub so that the code compiles: ```rust -#[cfg(not(clippy)] +#[cfg(not(clippy))] include!(concat!(env!("OUT_DIR"), "/my_big_function-generated.rs")); #[cfg(clippy)] From 073e5d4a2a5eff241b87bafeb636b0c94f2f3f47 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sun, 26 May 2024 14:35:26 +0000 Subject: [PATCH 050/211] std::pal::unix::thread fetching min stack size on netbsd. PTHREAD_STACK_MIN is not defined however sysconf/_SC_THREAD_STACK_MIN returns it as it can vary from arch to another. --- library/std/src/sys/pal/unix/thread.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs index 853ef8736de2..1ab54ec57c3b 100644 --- a/library/std/src/sys/pal/unix/thread.rs +++ b/library/std/src/sys/pal/unix/thread.rs @@ -717,5 +717,14 @@ unsafe fn min_stack_size(_: *const libc::pthread_attr_t) -> usize { #[cfg(target_os = "netbsd")] unsafe fn min_stack_size(_: *const libc::pthread_attr_t) -> usize { - 2048 // just a guess + static STACK: crate::sync::OnceLock = crate::sync::OnceLock::new(); + + *STACK.get_or_init(|| { + let mut stack = unsafe { libc::sysconf(libc::_SC_THREAD_STACK_MIN) }; + if stack < 0 { + stack = 2048; // just a guess + } + + stack as usize + }) } From 7110f471d305313b0ef12f66c2db3acc3c822851 Mon Sep 17 00:00:00 2001 From: cookie-s Date: Sun, 26 May 2024 22:39:23 -0400 Subject: [PATCH 051/211] [`many_single_char_names`]: Deduplicate diagnostics --- clippy_lints/src/non_expressive_names.rs | 4 ++++ tests/ui/many_single_char_names.rs | 2 -- tests/ui/many_single_char_names.stderr | 10 +++++----- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index 7b26235291a5..eacfe9ff328d 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -98,6 +98,10 @@ struct SimilarNamesLocalVisitor<'a, 'tcx> { impl<'a, 'tcx> SimilarNamesLocalVisitor<'a, 'tcx> { fn check_single_char_names(&self) { + if self.single_char_names.last().map(Vec::len) == Some(0) { + return; + } + let num_single_char_names = self.single_char_names.iter().flatten().count(); let threshold = self.lint.single_char_binding_names_threshold; if num_single_char_names as u64 > threshold { diff --git a/tests/ui/many_single_char_names.rs b/tests/ui/many_single_char_names.rs index 2af45eaab8af..68578340d90e 100644 --- a/tests/ui/many_single_char_names.rs +++ b/tests/ui/many_single_char_names.rs @@ -1,5 +1,3 @@ -//@compile-flags: -Zdeduplicate-diagnostics=yes - #![allow(clippy::too_many_arguments, clippy::diverging_sub_expression)] #![warn(clippy::many_single_char_names)] diff --git a/tests/ui/many_single_char_names.stderr b/tests/ui/many_single_char_names.stderr index 3b2460b5c077..131836ef7c88 100644 --- a/tests/ui/many_single_char_names.stderr +++ b/tests/ui/many_single_char_names.stderr @@ -1,5 +1,5 @@ error: 5 bindings with single-character names in scope - --> tests/ui/many_single_char_names.rs:7:9 + --> tests/ui/many_single_char_names.rs:5:9 | LL | let a: i32; | ^ @@ -14,7 +14,7 @@ LL | let e: i32; = help: to override `-D warnings` add `#[allow(clippy::many_single_char_names)]` error: 6 bindings with single-character names in scope - --> tests/ui/many_single_char_names.rs:7:9 + --> tests/ui/many_single_char_names.rs:5:9 | LL | let a: i32; | ^ @@ -28,7 +28,7 @@ LL | let f: i32; | ^ error: 5 bindings with single-character names in scope - --> tests/ui/many_single_char_names.rs:7:9 + --> tests/ui/many_single_char_names.rs:5:9 | LL | let a: i32; | ^ @@ -40,13 +40,13 @@ LL | e => panic!(), | ^ error: 8 bindings with single-character names in scope - --> tests/ui/many_single_char_names.rs:36:13 + --> tests/ui/many_single_char_names.rs:34:13 | LL | fn bindings(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32, g: i32, h: i32) {} | ^ ^ ^ ^ ^ ^ ^ ^ error: 8 bindings with single-character names in scope - --> tests/ui/many_single_char_names.rs:40:10 + --> tests/ui/many_single_char_names.rs:38:10 | LL | let (a, b, c, d, e, f, g, h): (bool, bool, bool, bool, bool, bool, bool, bool) = unimplemented!(); | ^ ^ ^ ^ ^ ^ ^ ^ From 03306b6ab61bfe5bab6e555caf8ee0ba911cce9a Mon Sep 17 00:00:00 2001 From: J-ZhengLi Date: Mon, 27 May 2024 11:49:10 +0800 Subject: [PATCH 052/211] suggest adding parentheses when linting [`let_and_return`] and [`needless_return`] --- clippy_lints/src/dereference.rs | 14 +++--- clippy_lints/src/needless_bool.rs | 13 ++---- clippy_lints/src/returns.rs | 34 ++++++--------- clippy_utils/src/lib.rs | 22 ++++++++++ tests/ui/let_and_return.fixed | 34 +++++++++++++++ tests/ui/let_and_return.rs | 34 +++++++++++++++ tests/ui/let_and_return.stderr | 72 ++++++++++++++++++++++++++++++- tests/ui/needless_return.fixed | 4 ++ tests/ui/needless_return.rs | 4 ++ tests/ui/needless_return.stderr | 14 +++++- 10 files changed, 203 insertions(+), 42 deletions(-) diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index c6aef9ac2d60..0276c64ef9b7 100644 --- a/clippy_lints/src/dereference.rs +++ b/clippy_lints/src/dereference.rs @@ -2,7 +2,9 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then}; use clippy_utils::source::{snippet_with_applicability, snippet_with_context}; use clippy_utils::sugg::has_enclosing_paren; use clippy_utils::ty::{implements_trait, is_manually_drop, peel_mid_ty_refs}; -use clippy_utils::{expr_use_ctxt, get_parent_expr, is_lint_allowed, path_to_local, DefinedTy, ExprUseNode}; +use clippy_utils::{ + expr_use_ctxt, get_parent_expr, is_block_like, is_lint_allowed, path_to_local, DefinedTy, ExprUseNode, +}; use core::mem; use rustc_ast::util::parser::{PREC_POSTFIX, PREC_PREFIX}; use rustc_data_structures::fx::FxIndexMap; @@ -1038,14 +1040,8 @@ fn report<'tcx>( ); }, State::ExplicitDeref { mutability } => { - if matches!( - expr.kind, - ExprKind::Block(..) - | ExprKind::ConstBlock(_) - | ExprKind::If(..) - | ExprKind::Loop(..) - | ExprKind::Match(..) - ) && let ty::Ref(_, ty, _) = data.adjusted_ty.kind() + if is_block_like(expr) + && let ty::Ref(_, ty, _) = data.adjusted_ty.kind() && ty.is_sized(cx.tcx, cx.param_env) { // Rustc bug: auto deref doesn't work on block expression when targeting sized types. diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index f9ee4a3dc93a..e1866eaa18a7 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -6,8 +6,8 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::sugg::Sugg; use clippy_utils::{ - higher, is_else_clause, is_expn_of, is_parent_stmt, peel_blocks, peel_blocks_with_stmt, span_extract_comment, - SpanlessEq, + higher, is_block_like, is_else_clause, is_expn_of, is_parent_stmt, peel_blocks, peel_blocks_with_stmt, + span_extract_comment, SpanlessEq, }; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; @@ -121,14 +121,7 @@ fn condition_needs_parentheses(e: &Expr<'_>) -> bool { | ExprKind::Type(i, _) | ExprKind::Index(i, _, _) = inner.kind { - if matches!( - i.kind, - ExprKind::Block(..) - | ExprKind::ConstBlock(..) - | ExprKind::If(..) - | ExprKind::Loop(..) - | ExprKind::Match(..) - ) { + if is_block_like(i) { return true; } inner = i; diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index e8f9d4381047..48d6fb3c0378 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -3,8 +3,8 @@ use clippy_utils::source::{snippet_opt, snippet_with_context}; use clippy_utils::sugg::has_enclosing_paren; use clippy_utils::visitors::{for_each_expr_with_closures, Descend}; use clippy_utils::{ - fn_def_id, is_from_proc_macro, is_inside_let_else, is_res_lang_ctor, path_res, path_to_local_id, span_contains_cfg, - span_find_starting_semi, + binary_expr_needs_parentheses, fn_def_id, is_from_proc_macro, is_inside_let_else, is_res_lang_ctor, path_res, + path_to_local_id, span_contains_cfg, span_find_starting_semi, }; use core::ops::ControlFlow; use rustc_errors::Applicability; @@ -129,7 +129,7 @@ enum RetReplacement<'tcx> { Empty, Block, Unit, - IfSequence(Cow<'tcx, str>, Applicability), + NeedsPar(Cow<'tcx, str>, Applicability), Expr(Cow<'tcx, str>, Applicability), } @@ -139,13 +139,13 @@ impl<'tcx> RetReplacement<'tcx> { Self::Empty | Self::Expr(..) => "remove `return`", Self::Block => "replace `return` with an empty block", Self::Unit => "replace `return` with a unit value", - Self::IfSequence(..) => "remove `return` and wrap the sequence with parentheses", + Self::NeedsPar(..) => "remove `return` and wrap the sequence with parentheses", } } fn applicability(&self) -> Applicability { match self { - Self::Expr(_, ap) | Self::IfSequence(_, ap) => *ap, + Self::Expr(_, ap) | Self::NeedsPar(_, ap) => *ap, _ => Applicability::MachineApplicable, } } @@ -157,7 +157,7 @@ impl<'tcx> Display for RetReplacement<'tcx> { Self::Empty => write!(f, ""), Self::Block => write!(f, "{{}}"), Self::Unit => write!(f, "()"), - Self::IfSequence(inner, _) => write!(f, "({inner})"), + Self::NeedsPar(inner, _) => write!(f, "({inner})"), Self::Expr(inner, _) => write!(f, "{inner}"), } } @@ -244,7 +244,11 @@ impl<'tcx> LateLintPass<'tcx> for Return { err.span_label(local.span, "unnecessary `let` binding"); if let Some(mut snippet) = snippet_opt(cx, initexpr.span) { - if !cx.typeck_results().expr_adjustments(retexpr).is_empty() { + if binary_expr_needs_parentheses(initexpr) { + if !has_enclosing_paren(&snippet) { + snippet = format!("({snippet})"); + } + } else if !cx.typeck_results().expr_adjustments(retexpr).is_empty() { if !has_enclosing_paren(&snippet) { snippet = format!("({snippet})"); } @@ -349,8 +353,8 @@ fn check_final_expr<'tcx>( let mut applicability = Applicability::MachineApplicable; let (snippet, _) = snippet_with_context(cx, inner_expr.span, ret_span.ctxt(), "..", &mut applicability); - if expr_contains_conjunctive_ifs(inner_expr) { - RetReplacement::IfSequence(snippet, applicability) + if binary_expr_needs_parentheses(inner_expr) { + RetReplacement::NeedsPar(snippet, applicability) } else { RetReplacement::Expr(snippet, applicability) } @@ -404,18 +408,6 @@ fn check_final_expr<'tcx>( } } -fn expr_contains_conjunctive_ifs<'tcx>(expr: &'tcx Expr<'tcx>) -> bool { - fn contains_if(expr: &Expr<'_>, on_if: bool) -> bool { - match expr.kind { - ExprKind::If(..) => on_if, - ExprKind::Binary(_, left, right) => contains_if(left, true) || contains_if(right, true), - _ => false, - } - } - - contains_if(expr, false) -} - fn emit_return_lint( cx: &LateContext<'_>, ret_span: Span, diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 4c603bda770a..f0870e1b0e49 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -3370,3 +3370,25 @@ pub fn is_parent_stmt(cx: &LateContext<'_>, id: HirId) -> bool { Node::Stmt(..) | Node::Block(Block { stmts: &[], .. }) ) } + +/// Returns true if the given `expr` is a block or resembled as a block, +/// such as `if`, `loop`, `match` expressions etc. +pub fn is_block_like(expr: &Expr<'_>) -> bool { + matches!( + expr.kind, + ExprKind::Block(..) | ExprKind::ConstBlock(..) | ExprKind::If(..) | ExprKind::Loop(..) | ExprKind::Match(..) + ) +} + +/// Returns true if the given `expr` is binary expression that needs to be wrapped in parentheses. +pub fn binary_expr_needs_parentheses(expr: &Expr<'_>) -> bool { + fn contains_block(expr: &Expr<'_>, is_operand: bool) -> bool { + match expr.kind { + ExprKind::Binary(_, lhs, _) => contains_block(lhs, true), + _ if is_block_like(expr) => is_operand, + _ => false, + } + } + + contains_block(expr, false) +} diff --git a/tests/ui/let_and_return.fixed b/tests/ui/let_and_return.fixed index 4187019e5894..b68b41cdca23 100644 --- a/tests/ui/let_and_return.fixed +++ b/tests/ui/let_and_return.fixed @@ -210,4 +210,38 @@ fn issue9150() -> usize { x } +fn issue12801() { + fn left_is_if() -> String { + + (if true { "a".to_string() } else { "b".to_string() } + "c") + //~^ ERROR: returning the result of a `let` binding from a block + } + + fn no_par_needed() -> String { + + "c".to_string() + if true { "a" } else { "b" } + //~^ ERROR: returning the result of a `let` binding from a block + } + + fn conjunctive_blocks() -> String { + + ({ "a".to_string() } + "b" + { "c" } + "d") + //~^ ERROR: returning the result of a `let` binding from a block + } + + #[allow(clippy::overly_complex_bool_expr)] + fn other_ops() { + let _ = || { + + (if true { 2 } else { 3 } << 4) + //~^ ERROR: returning the result of a `let` binding from a block + }; + let _ = || { + + ({ true } || { false } && { 2 <= 3 }) + //~^ ERROR: returning the result of a `let` binding from a block + }; + } +} + fn main() {} diff --git a/tests/ui/let_and_return.rs b/tests/ui/let_and_return.rs index 54444957b7d5..6b9035f94288 100644 --- a/tests/ui/let_and_return.rs +++ b/tests/ui/let_and_return.rs @@ -210,4 +210,38 @@ fn issue9150() -> usize { x } +fn issue12801() { + fn left_is_if() -> String { + let s = if true { "a".to_string() } else { "b".to_string() } + "c"; + s + //~^ ERROR: returning the result of a `let` binding from a block + } + + fn no_par_needed() -> String { + let s = "c".to_string() + if true { "a" } else { "b" }; + s + //~^ ERROR: returning the result of a `let` binding from a block + } + + fn conjunctive_blocks() -> String { + let s = { "a".to_string() } + "b" + { "c" } + "d"; + s + //~^ ERROR: returning the result of a `let` binding from a block + } + + #[allow(clippy::overly_complex_bool_expr)] + fn other_ops() { + let _ = || { + let s = if true { 2 } else { 3 } << 4; + s + //~^ ERROR: returning the result of a `let` binding from a block + }; + let _ = || { + let s = { true } || { false } && { 2 <= 3 }; + s + //~^ ERROR: returning the result of a `let` binding from a block + }; + } +} + fn main() {} diff --git a/tests/ui/let_and_return.stderr b/tests/ui/let_and_return.stderr index ff5962ec196e..75efa05d770a 100644 --- a/tests/ui/let_and_return.stderr +++ b/tests/ui/let_and_return.stderr @@ -78,5 +78,75 @@ LL + E::B(x) => x, LL + }) as _ | -error: aborting due to 5 previous errors +error: returning the result of a `let` binding from a block + --> tests/ui/let_and_return.rs:216:9 + | +LL | let s = if true { "a".to_string() } else { "b".to_string() } + "c"; + | ------------------------------------------------------------------- unnecessary `let` binding +LL | s + | ^ + | +help: return the expression directly + | +LL ~ +LL ~ (if true { "a".to_string() } else { "b".to_string() } + "c") + | + +error: returning the result of a `let` binding from a block + --> tests/ui/let_and_return.rs:222:9 + | +LL | let s = "c".to_string() + if true { "a" } else { "b" }; + | ------------------------------------------------------- unnecessary `let` binding +LL | s + | ^ + | +help: return the expression directly + | +LL ~ +LL ~ "c".to_string() + if true { "a" } else { "b" } + | + +error: returning the result of a `let` binding from a block + --> tests/ui/let_and_return.rs:228:9 + | +LL | let s = { "a".to_string() } + "b" + { "c" } + "d"; + | -------------------------------------------------- unnecessary `let` binding +LL | s + | ^ + | +help: return the expression directly + | +LL ~ +LL ~ ({ "a".to_string() } + "b" + { "c" } + "d") + | + +error: returning the result of a `let` binding from a block + --> tests/ui/let_and_return.rs:236:13 + | +LL | let s = if true { 2 } else { 3 } << 4; + | -------------------------------------- unnecessary `let` binding +LL | s + | ^ + | +help: return the expression directly + | +LL ~ +LL ~ (if true { 2 } else { 3 } << 4) + | + +error: returning the result of a `let` binding from a block + --> tests/ui/let_and_return.rs:241:13 + | +LL | let s = { true } || { false } && { 2 <= 3 }; + | -------------------------------------------- unnecessary `let` binding +LL | s + | ^ + | +help: return the expression directly + | +LL ~ +LL ~ ({ true } || { false } && { 2 <= 3 }) + | + +error: aborting due to 10 previous errors diff --git a/tests/ui/needless_return.fixed b/tests/ui/needless_return.fixed index 2575f2449e18..a9271cb399d8 100644 --- a/tests/ui/needless_return.fixed +++ b/tests/ui/needless_return.fixed @@ -323,4 +323,8 @@ fn allow_works() -> i32 { } } +fn conjunctive_blocks() -> String { + ({ "a".to_string() } + "b" + { "c" }) +} + fn main() {} diff --git a/tests/ui/needless_return.rs b/tests/ui/needless_return.rs index 04f21834d885..dc888bf667f1 100644 --- a/tests/ui/needless_return.rs +++ b/tests/ui/needless_return.rs @@ -333,4 +333,8 @@ fn allow_works() -> i32 { } } +fn conjunctive_blocks() -> String { + return { "a".to_string() } + "b" + { "c" }; +} + fn main() {} diff --git a/tests/ui/needless_return.stderr b/tests/ui/needless_return.stderr index 758ff6d985cd..bf5a89d8b75d 100644 --- a/tests/ui/needless_return.stderr +++ b/tests/ui/needless_return.stderr @@ -653,5 +653,17 @@ LL - return if b1 { 0 } else { 1 } | if b2 { 2 } else { 3 } | if b3 { 4 LL + (if b1 { 0 } else { 1 } | if b2 { 2 } else { 3 } | if b3 { 4 } else { 5 }) | -error: aborting due to 52 previous errors +error: unneeded `return` statement + --> tests/ui/needless_return.rs:337:5 + | +LL | return { "a".to_string() } + "b" + { "c" }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove `return` and wrap the sequence with parentheses + | +LL - return { "a".to_string() } + "b" + { "c" }; +LL + ({ "a".to_string() } + "b" + { "c" }) + | + +error: aborting due to 53 previous errors From 4a64180dd5cc48a26b2af3fbe0ddd3da0cccfb82 Mon Sep 17 00:00:00 2001 From: Marc Dominik Migge Date: Fri, 24 May 2024 17:59:09 +0200 Subject: [PATCH 053/211] `unnecessary_to_owned` should not suggest to remove `&` in macro expansion --- .../src/methods/unnecessary_iter_cloned.rs | 16 +++---- clippy_lints/src/methods/utils.rs | 16 ++++--- tests/ui/unnecessary_iter_cloned.fixed | 29 ++++++++++++ tests/ui/unnecessary_iter_cloned.rs | 29 ++++++++++++ tests/ui/unnecessary_iter_cloned.stderr | 44 +++++++++++++++++-- tests/ui/unnecessary_to_owned.stderr | 2 +- 6 files changed, 117 insertions(+), 19 deletions(-) diff --git a/clippy_lints/src/methods/unnecessary_iter_cloned.rs b/clippy_lints/src/methods/unnecessary_iter_cloned.rs index 7431dc1cf0b1..d1300dd43c28 100644 --- a/clippy_lints/src/methods/unnecessary_iter_cloned.rs +++ b/clippy_lints/src/methods/unnecessary_iter_cloned.rs @@ -38,7 +38,7 @@ pub fn check_for_loop_iter( ) -> bool { if let Some(grandparent) = get_parent_expr(cx, expr).and_then(|parent| get_parent_expr(cx, parent)) && let Some(ForLoop { pat, body, .. }) = ForLoop::hir(grandparent) - && let (clone_or_copy_needed, addr_of_exprs) = clone_or_copy_needed(cx, pat, body) + && let (clone_or_copy_needed, references_to_binding) = clone_or_copy_needed(cx, pat, body) && !clone_or_copy_needed && let Some(receiver_snippet) = snippet_opt(cx, receiver.span) { @@ -123,14 +123,12 @@ pub fn check_for_loop_iter( Applicability::MachineApplicable }; diag.span_suggestion(expr.span, "use", snippet, applicability); - for addr_of_expr in addr_of_exprs { - match addr_of_expr.kind { - ExprKind::AddrOf(_, _, referent) => { - let span = addr_of_expr.span.with_hi(referent.span.lo()); - diag.span_suggestion(span, "remove this `&`", "", applicability); - }, - _ => unreachable!(), - } + if !references_to_binding.is_empty() { + diag.multipart_suggestion( + "remove any references to the binding", + references_to_binding, + applicability, + ); } }, ); diff --git a/clippy_lints/src/methods/utils.rs b/clippy_lints/src/methods/utils.rs index 34d7b9acbe4b..1a55b7160fb1 100644 --- a/clippy_lints/src/methods/utils.rs +++ b/clippy_lints/src/methods/utils.rs @@ -9,6 +9,7 @@ use rustc_lint::LateContext; use rustc_middle::hir::nested_filter; use rustc_middle::ty::{self, Ty}; use rustc_span::symbol::sym; +use rustc_span::Span; pub(super) fn derefs_to_slice<'tcx>( cx: &LateContext<'tcx>, @@ -96,15 +97,15 @@ pub(super) fn clone_or_copy_needed<'tcx>( cx: &LateContext<'tcx>, pat: &Pat<'tcx>, body: &'tcx Expr<'tcx>, -) -> (bool, Vec<&'tcx Expr<'tcx>>) { +) -> (bool, Vec<(Span, String)>) { let mut visitor = CloneOrCopyVisitor { cx, binding_hir_ids: pat_bindings(pat), clone_or_copy_needed: false, - addr_of_exprs: Vec::new(), + references_to_binding: Vec::new(), }; visitor.visit_expr(body); - (visitor.clone_or_copy_needed, visitor.addr_of_exprs) + (visitor.clone_or_copy_needed, visitor.references_to_binding) } /// Returns a vector of all `HirId`s bound by the pattern. @@ -127,7 +128,7 @@ struct CloneOrCopyVisitor<'cx, 'tcx> { cx: &'cx LateContext<'tcx>, binding_hir_ids: Vec, clone_or_copy_needed: bool, - addr_of_exprs: Vec<&'tcx Expr<'tcx>>, + references_to_binding: Vec<(Span, String)>, } impl<'cx, 'tcx> Visitor<'tcx> for CloneOrCopyVisitor<'cx, 'tcx> { @@ -142,8 +143,11 @@ impl<'cx, 'tcx> Visitor<'tcx> for CloneOrCopyVisitor<'cx, 'tcx> { if self.is_binding(expr) { if let Some(parent) = get_parent_expr(self.cx, expr) { match parent.kind { - ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, _) => { - self.addr_of_exprs.push(parent); + ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, referent) => { + if !parent.span.from_expansion() { + self.references_to_binding + .push((parent.span.until(referent.span), String::new())); + } return; }, ExprKind::MethodCall(.., args, _) => { diff --git a/tests/ui/unnecessary_iter_cloned.fixed b/tests/ui/unnecessary_iter_cloned.fixed index 2c582c90ba8c..dc5e163ff04e 100644 --- a/tests/ui/unnecessary_iter_cloned.fixed +++ b/tests/ui/unnecessary_iter_cloned.fixed @@ -170,3 +170,32 @@ fn check_mut_iteratee_and_modify_inner_variable() { } } } + +mod issue_12821 { + fn foo() { + let v: Vec<_> = "hello".chars().collect(); + for c in v.iter() { + //~^ ERROR: unnecessary use of `cloned` + println!("{c}"); // should not suggest to remove `&` + } + } + + fn bar() { + let v: Vec<_> = "hello".chars().collect(); + for c in v.iter() { + //~^ ERROR: unnecessary use of `cloned` + let ref_c = c; //~ HELP: remove any references to the binding + println!("{ref_c}"); + } + } + + fn baz() { + let v: Vec<_> = "hello".chars().enumerate().collect(); + for (i, c) in v.iter() { + //~^ ERROR: unnecessary use of `cloned` + let ref_c = c; //~ HELP: remove any references to the binding + let ref_i = i; + println!("{i} {ref_c}"); // should not suggest to remove `&` from `i` + } + } +} diff --git a/tests/ui/unnecessary_iter_cloned.rs b/tests/ui/unnecessary_iter_cloned.rs index a28ccd1efef2..8f797ac717fb 100644 --- a/tests/ui/unnecessary_iter_cloned.rs +++ b/tests/ui/unnecessary_iter_cloned.rs @@ -170,3 +170,32 @@ fn check_mut_iteratee_and_modify_inner_variable() { } } } + +mod issue_12821 { + fn foo() { + let v: Vec<_> = "hello".chars().collect(); + for c in v.iter().cloned() { + //~^ ERROR: unnecessary use of `cloned` + println!("{c}"); // should not suggest to remove `&` + } + } + + fn bar() { + let v: Vec<_> = "hello".chars().collect(); + for c in v.iter().cloned() { + //~^ ERROR: unnecessary use of `cloned` + let ref_c = &c; //~ HELP: remove any references to the binding + println!("{ref_c}"); + } + } + + fn baz() { + let v: Vec<_> = "hello".chars().enumerate().collect(); + for (i, c) in v.iter().cloned() { + //~^ ERROR: unnecessary use of `cloned` + let ref_c = &c; //~ HELP: remove any references to the binding + let ref_i = &i; + println!("{i} {ref_c}"); // should not suggest to remove `&` from `i` + } + } +} diff --git a/tests/ui/unnecessary_iter_cloned.stderr b/tests/ui/unnecessary_iter_cloned.stderr index fb98cfddc262..0bdb37a521fc 100644 --- a/tests/ui/unnecessary_iter_cloned.stderr +++ b/tests/ui/unnecessary_iter_cloned.stderr @@ -10,7 +10,7 @@ help: use | LL | for (t, path) in files { | ~~~~~ -help: remove this `&` +help: remove any references to the binding | LL - let other = match get_file_path(&t) { LL + let other = match get_file_path(t) { @@ -26,11 +26,49 @@ help: use | LL | for (t, path) in files.iter() { | ~~~~~~~~~~~~ -help: remove this `&` +help: remove any references to the binding | LL - let other = match get_file_path(&t) { LL + let other = match get_file_path(t) { | -error: aborting due to 2 previous errors +error: unnecessary use of `cloned` + --> tests/ui/unnecessary_iter_cloned.rs:177:18 + | +LL | for c in v.iter().cloned() { + | ^^^^^^^^^^^^^^^^^ help: use: `v.iter()` + +error: unnecessary use of `cloned` + --> tests/ui/unnecessary_iter_cloned.rs:185:18 + | +LL | for c in v.iter().cloned() { + | ^^^^^^^^^^^^^^^^^ + | +help: use + | +LL | for c in v.iter() { + | ~~~~~~~~ +help: remove any references to the binding + | +LL - let ref_c = &c; +LL + let ref_c = c; + | + +error: unnecessary use of `cloned` + --> tests/ui/unnecessary_iter_cloned.rs:194:23 + | +LL | for (i, c) in v.iter().cloned() { + | ^^^^^^^^^^^^^^^^^ + | +help: use + | +LL | for (i, c) in v.iter() { + | ~~~~~~~~ +help: remove any references to the binding + | +LL ~ let ref_c = c; +LL ~ let ref_i = i; + | + +error: aborting due to 5 previous errors diff --git a/tests/ui/unnecessary_to_owned.stderr b/tests/ui/unnecessary_to_owned.stderr index 5475df9c7b93..2829f3cd6e98 100644 --- a/tests/ui/unnecessary_to_owned.stderr +++ b/tests/ui/unnecessary_to_owned.stderr @@ -487,7 +487,7 @@ help: use | LL | for t in file_types { | ~~~~~~~~~~ -help: remove this `&` +help: remove any references to the binding | LL - let path = match get_file_path(&t) { LL + let path = match get_file_path(t) { From eeda60ddd878e646417996172d9e004146d8b678 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Ml=C3=A1dek?= Date: Tue, 28 May 2024 11:07:57 +0200 Subject: [PATCH 054/211] fix diagnostics clearing when flychecks run per-workspace --- .../crates/rust-analyzer/src/global_state.rs | 4 ++-- .../rust-analyzer/crates/rust-analyzer/src/main_loop.rs | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs index 79b87ecd58ff..0c2e60fcc912 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs @@ -87,7 +87,7 @@ pub(crate) struct GlobalState { pub(crate) flycheck_sender: Sender, pub(crate) flycheck_receiver: Receiver, pub(crate) last_flycheck_error: Option, - pub(crate) diagnostics_received: bool, + pub(crate) diagnostics_received: FxHashMap, // Test explorer pub(crate) test_run_session: Option>, @@ -225,7 +225,7 @@ impl GlobalState { flycheck_sender, flycheck_receiver, last_flycheck_error: None, - diagnostics_received: false, + diagnostics_received: FxHashMap::default(), test_run_session: None, test_run_sender, diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs index 7acd302867c3..a94ca871bdd8 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs @@ -804,9 +804,9 @@ impl GlobalState { fn handle_flycheck_msg(&mut self, message: flycheck::Message) { match message { flycheck::Message::AddDiagnostic { id, workspace_root, diagnostic } => { - if !self.diagnostics_received { + if !self.diagnostics_received.get(&id).copied().unwrap_or_default() { self.diagnostics.clear_check(id); - self.diagnostics_received = true; + self.diagnostics_received.insert(id, true); } let snap = self.snapshot(); let diagnostics = crate::diagnostics::to_proto::map_rust_diagnostic_to_lsp( @@ -836,7 +836,7 @@ impl GlobalState { flycheck::Message::Progress { id, progress } => { let (state, message) = match progress { flycheck::Progress::DidStart => { - self.diagnostics_received = false; + self.diagnostics_received.insert(id, false); (Progress::Begin, None) } flycheck::Progress::DidCheckCrate(target) => (Progress::Report, Some(target)), @@ -852,7 +852,7 @@ impl GlobalState { flycheck::Progress::DidFinish(result) => { self.last_flycheck_error = result.err().map(|err| format!("cargo check failed to start: {err}")); - if !self.diagnostics_received { + if !self.diagnostics_received.get(&id).copied().unwrap_or_default() { self.diagnostics.clear_check(id); } (Progress::End, None) From 077a8219b07b72d8cd0485ffba32e7147e7f7f7d Mon Sep 17 00:00:00 2001 From: Amanda Stjerna Date: Tue, 28 May 2024 12:57:26 +0200 Subject: [PATCH 055/211] Fix back-porting drop-livess from Polonius to tracing --- .../src/type_check/liveness/polonius.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs index ccfa9f12ef45..808df1d66cb1 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs @@ -14,7 +14,7 @@ struct UseFactsExtractor<'me, 'tcx> { var_defined_at: &'me mut VarPointRelation, var_used_at: &'me mut VarPointRelation, location_table: &'me LocationTable, - var_dropped_at: &'me mut VarPointRelation, + var_dropped_at: &'me mut Vec<(Local, Location)>, move_data: &'me MoveData<'tcx>, path_accessed_at_base: &'me mut PathPointRelation, } @@ -37,7 +37,7 @@ impl<'tcx> UseFactsExtractor<'_, 'tcx> { fn insert_drop_use(&mut self, local: Local, location: Location) { debug!("UseFactsExtractor::insert_drop_use()"); - self.var_dropped_at.push((local, self.location_to_index(location))); + self.var_dropped_at.push((local, location)); } fn insert_path_access(&mut self, path: MovePathIndex, location: Location) { @@ -87,8 +87,12 @@ pub(super) fn populate_access_facts<'a, 'tcx>( body: &Body<'tcx>, location_table: &LocationTable, move_data: &MoveData<'tcx>, - //FIXME: this is not mutated, but expected to be modified as - // out param, bug? + // FIXME: this is an inelegant way of squirreling away a + // copy of `var_dropped_at` in the original `Location` format + // for later use in `trace::trace()`, which updates some liveness- + // internal data based on what Polonius saw. + // Ideally, that part would access the Polonius facts directly, and this + // would be regular facts gathering. dropped_at: &mut Vec<(Local, Location)>, ) { debug!("populate_access_facts()"); @@ -97,7 +101,7 @@ pub(super) fn populate_access_facts<'a, 'tcx>( let mut extractor = UseFactsExtractor { var_defined_at: &mut facts.var_defined_at, var_used_at: &mut facts.var_used_at, - var_dropped_at: &mut facts.var_dropped_at, + var_dropped_at: dropped_at, path_accessed_at_base: &mut facts.path_accessed_at_base, location_table, move_data, From a04ac26a9d059809bee2daf778a9d92770963a81 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 28 May 2024 11:38:30 +0000 Subject: [PATCH 056/211] Allow type_of to return partially non-error types if the type was already tainted --- .../rustc_hir_analysis/src/collect/type_of.rs | 4 +- .../associated-inherent-types/issue-109071.rs | 2 +- .../issue-109071.with_gate.stderr | 17 +----- .../issues/issue-71381.full.stderr | 2 +- .../issues/issue-71381.min.stderr | 20 ++++++- tests/ui/const-generics/issues/issue-71381.rs | 2 + .../issues/issue-71611.min.stderr | 10 +++- tests/ui/const-generics/issues/issue-71611.rs | 1 + .../ice-type-mismatch-when-copying-112824.rs | 1 + ...e-type-mismatch-when-copying-112824.stderr | 8 ++- .../generic-associated-types/issue-71176.rs | 3 + .../issue-71176.stderr | 55 ++++++++++++++++++- tests/ui/layout/issue-84108.rs | 3 + tests/ui/layout/issue-84108.stderr | 36 ++++++++++-- .../ui/lifetimes/unusual-rib-combinations.rs | 6 +- .../lifetimes/unusual-rib-combinations.stderr | 37 +++++++------ .../issues/issue-103748-ICE-wrong-braces.rs | 1 + .../issue-103748-ICE-wrong-braces.stderr | 17 +++++- 18 files changed, 174 insertions(+), 51 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index ed942cc50bb4..bc57b234555d 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -502,7 +502,9 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_ bug!("unexpected sort of node in type_of(): {:?}", x); } }; - if let Err(e) = icx.check_tainted_by_errors() { + if let Err(e) = icx.check_tainted_by_errors() + && !output.references_error() + { ty::EarlyBinder::bind(Ty::new_error(tcx, e)) } else { ty::EarlyBinder::bind(output) diff --git a/tests/ui/associated-inherent-types/issue-109071.rs b/tests/ui/associated-inherent-types/issue-109071.rs index 29eef081a327..97803ae7191e 100644 --- a/tests/ui/associated-inherent-types/issue-109071.rs +++ b/tests/ui/associated-inherent-types/issue-109071.rs @@ -13,7 +13,7 @@ impl Windows { //~ ERROR: missing generics for struct `Windows` impl Windows { fn T() -> Option {} - //~^ ERROR: ambiguous associated type + //[no_gate]~^ ERROR: ambiguous associated type } fn main() {} diff --git a/tests/ui/associated-inherent-types/issue-109071.with_gate.stderr b/tests/ui/associated-inherent-types/issue-109071.with_gate.stderr index a7d17e2d5ebb..1324cb9bb9b5 100644 --- a/tests/ui/associated-inherent-types/issue-109071.with_gate.stderr +++ b/tests/ui/associated-inherent-types/issue-109071.with_gate.stderr @@ -20,20 +20,7 @@ help: add missing generic argument LL | impl Windows { | +++ -error[E0223]: ambiguous associated type - --> $DIR/issue-109071.rs:15:22 - | -LL | fn T() -> Option {} - | ^^^^^^^^^^ - | -help: use fully-qualified syntax - | -LL | fn T() -> Option< as IntoAsyncIterator>::Item> {} - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -LL | fn T() -> Option< as IntoIterator>::Item> {} - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +error: aborting due to 2 previous errors -error: aborting due to 3 previous errors - -Some errors have detailed explanations: E0107, E0223, E0637. +Some errors have detailed explanations: E0107, E0637. For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/const-generics/issues/issue-71381.full.stderr b/tests/ui/const-generics/issues/issue-71381.full.stderr index 5d7800746961..b6460e0017fa 100644 --- a/tests/ui/const-generics/issues/issue-71381.full.stderr +++ b/tests/ui/const-generics/issues/issue-71381.full.stderr @@ -7,7 +7,7 @@ LL | pub fn call_me $DIR/issue-71381.rs:22:40 + --> $DIR/issue-71381.rs:23:40 | LL | const FN: unsafe extern "C" fn(Args), | ^^^^ the type must not depend on the parameter `Args` diff --git a/tests/ui/const-generics/issues/issue-71381.min.stderr b/tests/ui/const-generics/issues/issue-71381.min.stderr index 5d7800746961..e16d3b7a8a46 100644 --- a/tests/ui/const-generics/issues/issue-71381.min.stderr +++ b/tests/ui/const-generics/issues/issue-71381.min.stderr @@ -7,13 +7,29 @@ LL | pub fn call_me $DIR/issue-71381.rs:22:40 + --> $DIR/issue-71381.rs:23:40 | LL | const FN: unsafe extern "C" fn(Args), | ^^^^ the type must not depend on the parameter `Args` | = note: type parameters may not be used in the type of const parameters -error: aborting due to 2 previous errors +error: using function pointers as const generic parameters is forbidden + --> $DIR/issue-71381.rs:14:61 + | +LL | pub fn call_me(&self) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + +error: using function pointers as const generic parameters is forbidden + --> $DIR/issue-71381.rs:23:19 + | +LL | const FN: unsafe extern "C" fn(Args), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0770`. diff --git a/tests/ui/const-generics/issues/issue-71381.rs b/tests/ui/const-generics/issues/issue-71381.rs index 7f2e14944e29..e472ef31fcdd 100644 --- a/tests/ui/const-generics/issues/issue-71381.rs +++ b/tests/ui/const-generics/issues/issue-71381.rs @@ -13,6 +13,7 @@ unsafe extern "C" fn pass(args: PassArg) { impl Test { pub fn call_me(&self) { //~^ ERROR: the type of const parameters must not depend on other generic parameters + //[min]~^^ ERROR: using function pointers as const generic parameters is forbidden self.0 = Self::trampiline:: as _ } @@ -21,6 +22,7 @@ impl Test { const IDX: usize, const FN: unsafe extern "C" fn(Args), //~^ ERROR: the type of const parameters must not depend on other generic parameters + //[min]~^^ ERROR: using function pointers as const generic parameters is forbidden >( args: Args, ) { diff --git a/tests/ui/const-generics/issues/issue-71611.min.stderr b/tests/ui/const-generics/issues/issue-71611.min.stderr index 6f6a9fc21a69..b01936f4d251 100644 --- a/tests/ui/const-generics/issues/issue-71611.min.stderr +++ b/tests/ui/const-generics/issues/issue-71611.min.stderr @@ -6,6 +6,14 @@ LL | fn func(outer: A) { | = note: type parameters may not be used in the type of const parameters -error: aborting due to 1 previous error +error: using function pointers as const generic parameters is forbidden + --> $DIR/issue-71611.rs:5:21 + | +LL | fn func(outer: A) { + | ^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0770`. diff --git a/tests/ui/const-generics/issues/issue-71611.rs b/tests/ui/const-generics/issues/issue-71611.rs index 0e0c08146b2e..c6c1e267171f 100644 --- a/tests/ui/const-generics/issues/issue-71611.rs +++ b/tests/ui/const-generics/issues/issue-71611.rs @@ -4,6 +4,7 @@ fn func(outer: A) { //~^ ERROR: the type of const parameters must not depend on other generic parameters + //[min]~| ERROR: using function pointers as const generic parameters is forbidden F(outer); } diff --git a/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.rs b/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.rs index a41a159c1fd7..09f7e2ba5b1d 100644 --- a/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.rs +++ b/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.rs @@ -13,6 +13,7 @@ impl Opcode2 { pub fn example2(msg_type: Opcode2) -> impl FnMut(&[u8]) { move |i| match msg_type { Opcode2::OP2 => unimplemented!(), + //~^ ERROR: could not evaluate constant pattern } } diff --git a/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.stderr b/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.stderr index d95a8861230e..9442eac0cf54 100644 --- a/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.stderr +++ b/tests/ui/const_prop/ice-type-mismatch-when-copying-112824.stderr @@ -17,7 +17,13 @@ help: you might be missing a type parameter LL | pub struct Opcode2(&'a S); | +++ -error: aborting due to 2 previous errors +error: could not evaluate constant pattern + --> $DIR/ice-type-mismatch-when-copying-112824.rs:15:9 + | +LL | Opcode2::OP2 => unimplemented!(), + | ^^^^^^^^^^^^ + +error: aborting due to 3 previous errors Some errors have detailed explanations: E0261, E0412. For more information about an error, try `rustc --explain E0261`. diff --git a/tests/ui/generic-associated-types/issue-71176.rs b/tests/ui/generic-associated-types/issue-71176.rs index f0e162d825f9..e58b6f6091e7 100644 --- a/tests/ui/generic-associated-types/issue-71176.rs +++ b/tests/ui/generic-associated-types/issue-71176.rs @@ -9,6 +9,9 @@ impl Provider for () { struct Holder { inner: Box>, //~^ ERROR: missing generics for associated type + //~| ERROR: missing generics for associated type + //~| ERROR: missing generics for associated type + //~| ERROR: the trait `Provider` cannot be made into an object } fn main() { diff --git a/tests/ui/generic-associated-types/issue-71176.stderr b/tests/ui/generic-associated-types/issue-71176.stderr index ed837f347533..a1913bb618bc 100644 --- a/tests/ui/generic-associated-types/issue-71176.stderr +++ b/tests/ui/generic-associated-types/issue-71176.stderr @@ -14,6 +14,57 @@ help: add missing lifetime argument LL | inner: Box = B>>, | ++++ -error: aborting due to 1 previous error +error[E0107]: missing generics for associated type `Provider::A` + --> $DIR/issue-71176.rs:10:27 + | +LL | inner: Box>, + | ^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-71176.rs:2:10 + | +LL | type A<'a>; + | ^ -- + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: add missing lifetime argument + | +LL | inner: Box = B>>, + | ++++ -For more information about this error, try `rustc --explain E0107`. +error[E0107]: missing generics for associated type `Provider::A` + --> $DIR/issue-71176.rs:10:27 + | +LL | inner: Box>, + | ^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-71176.rs:2:10 + | +LL | type A<'a>; + | ^ -- + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: add missing lifetime argument + | +LL | inner: Box = B>>, + | ++++ + +error[E0038]: the trait `Provider` cannot be made into an object + --> $DIR/issue-71176.rs:10:14 + | +LL | inner: Box>, + | ^^^^^^^^^^^^^^^^^^^ `Provider` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-71176.rs:2:10 + | +LL | trait Provider { + | -------- this trait cannot be made into an object... +LL | type A<'a>; + | ^ ...because it contains the generic associated type `A` + = help: consider moving `A` to another trait + = help: only type `()` implements the trait, consider using it directly instead + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0038, E0107. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/layout/issue-84108.rs b/tests/ui/layout/issue-84108.rs index 425da65b9905..974d5310f6bb 100644 --- a/tests/ui/layout/issue-84108.rs +++ b/tests/ui/layout/issue-84108.rs @@ -8,6 +8,9 @@ static FOO: (dyn AsRef, u8) = ("hello", 42); const BAR: (&Path, [u8], usize) = ("hello", [], 42); //~^ ERROR cannot find type `Path` in this scope +//~| ERROR the size for values of type `[u8]` cannot be known at compilation time +//~| ERROR the size for values of type `[u8]` cannot be known at compilation time +//~| ERROR mismatched types static BAZ: ([u8], usize) = ([], 0); //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time diff --git a/tests/ui/layout/issue-84108.stderr b/tests/ui/layout/issue-84108.stderr index 6c168cc5fa84..8ddce285e23f 100644 --- a/tests/ui/layout/issue-84108.stderr +++ b/tests/ui/layout/issue-84108.stderr @@ -21,7 +21,35 @@ LL + use std::path::Path; | error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/issue-84108.rs:12:13 + --> $DIR/issue-84108.rs:9:12 + | +LL | const BAR: (&Path, [u8], usize) = ("hello", [], 42); + | ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: only the last element of a tuple may have a dynamically sized type + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/issue-84108.rs:9:12 + | +LL | const BAR: (&Path, [u8], usize) = ("hello", [], 42); + | ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: only the last element of a tuple may have a dynamically sized type + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0308]: mismatched types + --> $DIR/issue-84108.rs:9:45 + | +LL | const BAR: (&Path, [u8], usize) = ("hello", [], 42); + | ^^ expected `[u8]`, found `[_; 0]` + | + = note: expected slice `[u8]` + found array `[_; 0]` + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/issue-84108.rs:15:13 | LL | static BAZ: ([u8], usize) = ([], 0); | ^^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -30,7 +58,7 @@ LL | static BAZ: ([u8], usize) = ([], 0); = note: only the last element of a tuple may have a dynamically sized type error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/issue-84108.rs:12:13 + --> $DIR/issue-84108.rs:15:13 | LL | static BAZ: ([u8], usize) = ([], 0); | ^^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -40,7 +68,7 @@ LL | static BAZ: ([u8], usize) = ([], 0); = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0308]: mismatched types - --> $DIR/issue-84108.rs:12:30 + --> $DIR/issue-84108.rs:15:30 | LL | static BAZ: ([u8], usize) = ([], 0); | ^^ expected `[u8]`, found `[_; 0]` @@ -48,7 +76,7 @@ LL | static BAZ: ([u8], usize) = ([], 0); = note: expected slice `[u8]` found array `[_; 0]` -error: aborting due to 5 previous errors +error: aborting due to 8 previous errors Some errors have detailed explanations: E0277, E0308, E0412. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/lifetimes/unusual-rib-combinations.rs b/tests/ui/lifetimes/unusual-rib-combinations.rs index 3bc87b9d480b..0708a00d3715 100644 --- a/tests/ui/lifetimes/unusual-rib-combinations.rs +++ b/tests/ui/lifetimes/unusual-rib-combinations.rs @@ -2,9 +2,8 @@ struct S<'a>(&'a u8); fn foo() {} // Paren generic args in AnonConst -fn a() -> [u8; foo::()] { -//~^ ERROR parenthesized type parameters may only be used with a `Fn` trait -//~| ERROR mismatched types +fn a() -> [u8; foo()] { + //~^ ERROR mismatched types panic!() } @@ -26,5 +25,6 @@ fn d() {} trait Foo<'a> {} struct Bar Foo<'a>)>; //~^ ERROR the type of const parameters must not depend on other generic parameters +//~| ERROR `&dyn for<'a> Foo<'a>` is forbidden as the type of a const generic parameter fn main() {} diff --git a/tests/ui/lifetimes/unusual-rib-combinations.stderr b/tests/ui/lifetimes/unusual-rib-combinations.stderr index 2857fc72ea14..70f06b4be603 100644 --- a/tests/ui/lifetimes/unusual-rib-combinations.stderr +++ b/tests/ui/lifetimes/unusual-rib-combinations.stderr @@ -1,11 +1,11 @@ error[E0106]: missing lifetime specifier - --> $DIR/unusual-rib-combinations.rs:22:15 + --> $DIR/unusual-rib-combinations.rs:21:15 | LL | fn d() {} | ^ expected named lifetime parameter error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/unusual-rib-combinations.rs:27:22 + --> $DIR/unusual-rib-combinations.rs:26:22 | LL | struct Bar Foo<'a>)>; | ^^ the type must not depend on the parameter `'a` @@ -13,25 +13,19 @@ LL | struct Bar Foo<'a>)>; = note: lifetime parameters may not be used in the type of const parameters error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/unusual-rib-combinations.rs:5:16 - | -LL | fn a() -> [u8; foo::()] { - | ^^^^^^^ only `Fn` traits may use parentheses - -error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/unusual-rib-combinations.rs:12:15 + --> $DIR/unusual-rib-combinations.rs:11:15 | LL | fn b() {} | ^^^^ only `Fn` traits may use parentheses error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/unusual-rib-combinations.rs:16:10 + --> $DIR/unusual-rib-combinations.rs:15:10 | LL | fn c() {} | ^^^^ only `Fn` traits may use parentheses error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions - --> $DIR/unusual-rib-combinations.rs:16:6 + --> $DIR/unusual-rib-combinations.rs:15:6 | LL | fn c() {} | ^^^^^^^^ @@ -43,14 +37,11 @@ LL | fn c() {} error[E0308]: mismatched types --> $DIR/unusual-rib-combinations.rs:5:16 | -LL | fn a() -> [u8; foo::()] { - | ^^^^^^^ expected `usize`, found fn item - | - = note: expected type `usize` - found fn item `fn() {foo}` +LL | fn a() -> [u8; foo()] { + | ^^^^^ expected `usize`, found `()` error: `S<'_>` is forbidden as the type of a const generic parameter - --> $DIR/unusual-rib-combinations.rs:22:15 + --> $DIR/unusual-rib-combinations.rs:21:15 | LL | fn d() {} | ^ @@ -61,6 +52,18 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more LL + #![feature(adt_const_params)] | +error: `&dyn for<'a> Foo<'a>` is forbidden as the type of a const generic parameter + --> $DIR/unusual-rib-combinations.rs:26:21 + | +LL | struct Bar Foo<'a>)>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` +help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types + | +LL + #![feature(adt_const_params)] + | + error: aborting due to 8 previous errors Some errors have detailed explanations: E0106, E0214, E0308, E0770. diff --git a/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.rs b/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.rs index f6aa39df27d8..1c28c0632fa8 100644 --- a/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.rs +++ b/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.rs @@ -5,3 +5,4 @@ struct Apple((Apple, Option(Banana ? Citron))); //~| ERROR expected one of `)` or `,`, found `Citron` //~| ERROR cannot find type `Citron` in this scope [E0412] //~| ERROR parenthesized type parameters may only be used with a `Fn` trait [E0214] +//~| ERROR `Apple` has infinite size diff --git a/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.stderr b/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.stderr index 71d2d7b79758..b0d8b03ae08c 100644 --- a/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.stderr +++ b/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.stderr @@ -34,7 +34,18 @@ help: use angle brackets instead LL | struct Apple((Apple, Option)); | ~ ~ -error: aborting due to 4 previous errors +error[E0072]: recursive type `Apple` has infinite size + --> $DIR/issue-103748-ICE-wrong-braces.rs:3:1 + | +LL | struct Apple((Apple, Option(Banana ? Citron))); + | ^^^^^^^^^^^^ ----- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL | struct Apple((Box, Option(Banana ? Citron))); + | ++++ + -Some errors have detailed explanations: E0214, E0412. -For more information about an error, try `rustc --explain E0214`. +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0072, E0214, E0412. +For more information about an error, try `rustc --explain E0072`. From e3e27ba3dd5a5bd9b36f03527ef9fff82cb17dc4 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 3 May 2024 09:22:55 +0000 Subject: [PATCH 057/211] Create const block DefIds in typeck instead of ast lowering --- clippy_utils/src/consts.rs | 6 ++--- clippy_utils/src/hir_utils.rs | 4 ++-- tests/ui/arithmetic_side_effects.stderr | 32 +++++++++++++++++++++---- 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/clippy_utils/src/consts.rs b/clippy_utils/src/consts.rs index 253ae3aca689..f5d3967d130d 100644 --- a/clippy_utils/src/consts.rs +++ b/clippy_utils/src/consts.rs @@ -6,7 +6,7 @@ use crate::{clip, is_direct_expn_of, sext, unsext}; use rustc_ast::ast::{self, LitFloatType, LitKind}; use rustc_data_structures::sync::Lrc; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::{BinOp, BinOpKind, Block, ConstBlock, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp}; +use rustc_hir::{BinOp, BinOpKind, Block, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp}; use rustc_lexer::tokenize; use rustc_lint::LateContext; use rustc_middle::mir::interpret::{alloc_range, Scalar}; @@ -412,7 +412,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { /// Simple constant folding: Insert an expression, get a constant or none. pub fn expr(&mut self, e: &Expr<'_>) -> Option> { match e.kind { - ExprKind::ConstBlock(ConstBlock { body, .. }) => self.expr(self.lcx.tcx.hir().body(body).value), + ExprKind::ConstBlock(e) | ExprKind::DropTemps(e) => self.expr(e), ExprKind::Path(ref qpath) => { self.fetch_path_and_apply(qpath, e.hir_id, self.typeck_results.expr_ty(e), |this, result| { @@ -491,7 +491,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { /// leaves the local crate. pub fn expr_is_empty(&mut self, e: &Expr<'_>) -> Option { match e.kind { - ExprKind::ConstBlock(ConstBlock { body, .. }) => self.expr_is_empty(self.lcx.tcx.hir().body(body).value), + ExprKind::ConstBlock(e) | ExprKind::DropTemps(e) => self.expr_is_empty(e), ExprKind::Path(ref qpath) => { if !self diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs index 9f285621e0c9..cc5ccd4053a2 100644 --- a/clippy_utils/src/hir_utils.rs +++ b/clippy_utils/src/hir_utils.rs @@ -295,7 +295,7 @@ impl HirEqInterExpr<'_, '_, '_> { self.eq_expr(lx, rx) && self.eq_ty(lt, rt) }, (&ExprKind::Closure(_l), &ExprKind::Closure(_r)) => false, - (&ExprKind::ConstBlock(lb), &ExprKind::ConstBlock(rb)) => self.eq_body(lb.body, rb.body), + (&ExprKind::ConstBlock(lb), &ExprKind::ConstBlock(rb)) => self.eq_expr(lb, rb), (&ExprKind::Continue(li), &ExprKind::Continue(ri)) => { both(&li.label, &ri.label, |l, r| l.ident.name == r.ident.name) }, @@ -770,7 +770,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_expr(self.cx.tcx.hir().body(body).value); }, ExprKind::ConstBlock(ref l_id) => { - self.hash_body(l_id.body); + self.hash_expr(l_id); }, ExprKind::DropTemps(e) | ExprKind::Yield(e, _) => { self.hash_expr(e); diff --git a/tests/ui/arithmetic_side_effects.stderr b/tests/ui/arithmetic_side_effects.stderr index 8039c0bfa248..df14ff396f6c 100644 --- a/tests/ui/arithmetic_side_effects.stderr +++ b/tests/ui/arithmetic_side_effects.stderr @@ -1,11 +1,35 @@ +error: arithmetic operation that can potentially result in unexpected side-effects + --> tests/ui/arithmetic_side_effects.rs:188:36 + | +LL | let _ = const { let mut n = 1; n += 1; n }; + | ^^^^^^ + | + = note: `-D clippy::arithmetic-side-effects` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::arithmetic_side_effects)]` + +error: arithmetic operation that can potentially result in unexpected side-effects + --> tests/ui/arithmetic_side_effects.rs:191:40 + | +LL | let _ = const { let mut n = 1; n = n + 1; n }; + | ^^^^^ + +error: arithmetic operation that can potentially result in unexpected side-effects + --> tests/ui/arithmetic_side_effects.rs:194:40 + | +LL | let _ = const { let mut n = 1; n = 1 + n; n }; + | ^^^^^ + +error: arithmetic operation that can potentially result in unexpected side-effects + --> tests/ui/arithmetic_side_effects.rs:200:59 + | +LL | let _ = const { let mut n = 1; n = -1; n = -(-1); n = -n; n }; + | ^^ + error: arithmetic operation that can potentially result in unexpected side-effects --> tests/ui/arithmetic_side_effects.rs:304:5 | LL | _n += 1; | ^^^^^^^ - | - = note: `-D clippy::arithmetic-side-effects` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::arithmetic_side_effects)]` error: arithmetic operation that can potentially result in unexpected side-effects --> tests/ui/arithmetic_side_effects.rs:305:5 @@ -727,5 +751,5 @@ error: arithmetic operation that can potentially result in unexpected side-effec LL | one.sub_assign(1); | ^^^^^^^^^^^^^^^^^ -error: aborting due to 121 previous errors +error: aborting due to 125 previous errors From e15564672e4e35a8697b717d49db1bfc6579c612 Mon Sep 17 00:00:00 2001 From: Amanda Stjerna Date: Tue, 28 May 2024 15:49:22 +0200 Subject: [PATCH 058/211] Make drop-use fact collection simpler for `polonius` This shunts all the complexity of siphoning off the drop-use facts into `LivenessResults::add_extra_drop_facts()`, which may or may not be a good approach. --- .../src/type_check/liveness/mod.rs | 11 ++---- .../src/type_check/liveness/polonius.rs | 19 +++------- .../src/type_check/liveness/trace.rs | 35 ++++++++++++++----- compiler/rustc_borrowck/src/type_check/mod.rs | 10 +----- 4 files changed, 34 insertions(+), 41 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs index 38ec9f7678eb..8b863efad6ca 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs @@ -14,7 +14,6 @@ use std::rc::Rc; use crate::{ constraints::OutlivesConstraintSet, facts::{AllFacts, AllFactsExt}, - location::LocationTable, region_infer::values::LivenessValues, universal_regions::UniversalRegions, }; @@ -39,7 +38,6 @@ pub(super) fn generate<'mir, 'tcx>( elements: &Rc, flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>, move_data: &MoveData<'tcx>, - location_table: &LocationTable, use_polonius: bool, ) { debug!("liveness::generate"); @@ -53,11 +51,9 @@ pub(super) fn generate<'mir, 'tcx>( compute_relevant_live_locals(typeck.tcx(), &free_regions, body); let facts_enabled = use_polonius || AllFacts::enabled(typeck.tcx()); - let polonius_drop_used = facts_enabled.then(|| { - let mut drop_used = Vec::new(); - polonius::populate_access_facts(typeck, body, location_table, move_data, &mut drop_used); - drop_used - }); + if facts_enabled { + polonius::populate_access_facts(typeck, body, move_data); + }; trace::trace( typeck, @@ -67,7 +63,6 @@ pub(super) fn generate<'mir, 'tcx>( move_data, relevant_live_locals, boring_locals, - polonius_drop_used, ); // Mark regions that should be live where they appear within rvalues or within a call: like diff --git a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs index 808df1d66cb1..d8f03a07a63c 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs @@ -14,7 +14,7 @@ struct UseFactsExtractor<'me, 'tcx> { var_defined_at: &'me mut VarPointRelation, var_used_at: &'me mut VarPointRelation, location_table: &'me LocationTable, - var_dropped_at: &'me mut Vec<(Local, Location)>, + var_dropped_at: &'me mut VarPointRelation, move_data: &'me MoveData<'tcx>, path_accessed_at_base: &'me mut PathPointRelation, } @@ -37,7 +37,7 @@ impl<'tcx> UseFactsExtractor<'_, 'tcx> { fn insert_drop_use(&mut self, local: Local, location: Location) { debug!("UseFactsExtractor::insert_drop_use()"); - self.var_dropped_at.push((local, location)); + self.var_dropped_at.push((local, self.location_to_index(location))); } fn insert_path_access(&mut self, path: MovePathIndex, location: Location) { @@ -85,33 +85,22 @@ impl<'a, 'tcx> Visitor<'tcx> for UseFactsExtractor<'a, 'tcx> { pub(super) fn populate_access_facts<'a, 'tcx>( typeck: &mut TypeChecker<'a, 'tcx>, body: &Body<'tcx>, - location_table: &LocationTable, move_data: &MoveData<'tcx>, - // FIXME: this is an inelegant way of squirreling away a - // copy of `var_dropped_at` in the original `Location` format - // for later use in `trace::trace()`, which updates some liveness- - // internal data based on what Polonius saw. - // Ideally, that part would access the Polonius facts directly, and this - // would be regular facts gathering. - dropped_at: &mut Vec<(Local, Location)>, ) { debug!("populate_access_facts()"); + let location_table = typeck.borrowck_context.location_table; if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() { let mut extractor = UseFactsExtractor { var_defined_at: &mut facts.var_defined_at, var_used_at: &mut facts.var_used_at, - var_dropped_at: dropped_at, + var_dropped_at: &mut facts.var_dropped_at, path_accessed_at_base: &mut facts.path_accessed_at_base, location_table, move_data, }; extractor.visit_body(body); - facts.var_dropped_at.extend( - dropped_at.iter().map(|&(local, location)| (local, location_table.mid_index(location))), - ); - for (local, local_decl) in body.local_decls.iter_enumerated() { debug!( "add use_of_var_derefs_origin facts - local={:?}, type={:?}", diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index 6cc0e67c0f80..92b70a09a885 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -16,6 +16,7 @@ use rustc_mir_dataflow::impls::MaybeInitializedPlaces; use rustc_mir_dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex}; use rustc_mir_dataflow::ResultsCursor; +use crate::location::RichLocation; use crate::{ region_infer::values::{self, LiveLoans}, type_check::liveness::local_use_map::LocalUseMap, @@ -46,7 +47,6 @@ pub(super) fn trace<'mir, 'tcx>( move_data: &MoveData<'tcx>, relevant_live_locals: Vec, boring_locals: Vec, - polonius_drop_used: Option>, ) { let local_use_map = &LocalUseMap::build(&relevant_live_locals, elements, body); @@ -81,6 +81,8 @@ pub(super) fn trace<'mir, 'tcx>( borrowck_context.constraints.liveness_constraints.loans = Some(live_loans); }; + let polonius_facts_gathered = typeck.borrowck_context.all_facts.is_some(); + let cx = LivenessContext { typeck, body, @@ -93,8 +95,8 @@ pub(super) fn trace<'mir, 'tcx>( let mut results = LivenessResults::new(cx); - if let Some(drop_used) = polonius_drop_used { - results.add_extra_drop_facts(drop_used, relevant_live_locals.iter().copied().collect()) + if polonius_facts_gathered { + results.add_extra_drop_facts(relevant_live_locals.iter().copied().collect()); } results.compute_for_all_locals(relevant_live_locals); @@ -218,17 +220,32 @@ impl<'me, 'typeck, 'flow, 'tcx> LivenessResults<'me, 'typeck, 'flow, 'tcx> { /// /// Add facts for all locals with free regions, since regions may outlive /// the function body only at certain nodes in the CFG. - fn add_extra_drop_facts( - &mut self, - drop_used: Vec<(Local, Location)>, - relevant_live_locals: FxIndexSet, - ) { + fn add_extra_drop_facts(&mut self, relevant_live_locals: FxIndexSet) { + let drop_used = self + .cx + .typeck + .borrowck_context + .all_facts + .as_ref() + .map(|facts| facts.var_dropped_at.clone()) + .into_iter() + .flatten(); let locations = IntervalSet::new(self.cx.elements.num_points()); - for (local, location) in drop_used { + for (local, location_index) in drop_used { if !relevant_live_locals.contains(&local) { let local_ty = self.cx.body.local_decls[local].ty; if local_ty.has_free_regions() { + let location = match self + .cx + .typeck + .borrowck_context + .location_table + .to_location(location_index) + { + RichLocation::Start(l) => l, + RichLocation::Mid(l) => l, + }; self.cx.add_drop_live_facts_for(local, local_ty, &[location], &locations); } } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 4e46a0c62c7c..a05fa967af03 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -188,15 +188,7 @@ pub(crate) fn type_check<'mir, 'tcx>( checker.equate_inputs_and_outputs(body, universal_regions, &normalized_inputs_and_output); checker.check_signature_annotation(body); - liveness::generate( - &mut checker, - body, - elements, - flow_inits, - move_data, - location_table, - use_polonius, - ); + liveness::generate(&mut checker, body, elements, flow_inits, move_data, use_polonius); translate_outlives_facts(&mut checker); let opaque_type_values = infcx.take_opaque_types(); From 8066ebc294f110a758fb2b44a68138db10d38ce0 Mon Sep 17 00:00:00 2001 From: Amanda Stjerna Date: Tue, 28 May 2024 16:02:09 +0200 Subject: [PATCH 059/211] Move the rest of the logic into `add_extra_drop_facts()` --- .../src/type_check/liveness/trace.rs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index 92b70a09a885..50843c602cc8 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -81,8 +81,6 @@ pub(super) fn trace<'mir, 'tcx>( borrowck_context.constraints.liveness_constraints.loans = Some(live_loans); }; - let polonius_facts_gathered = typeck.borrowck_context.all_facts.is_some(); - let cx = LivenessContext { typeck, body, @@ -95,9 +93,7 @@ pub(super) fn trace<'mir, 'tcx>( let mut results = LivenessResults::new(cx); - if polonius_facts_gathered { - results.add_extra_drop_facts(relevant_live_locals.iter().copied().collect()); - } + results.add_extra_drop_facts(&relevant_live_locals); results.compute_for_all_locals(relevant_live_locals); @@ -220,16 +216,17 @@ impl<'me, 'typeck, 'flow, 'tcx> LivenessResults<'me, 'typeck, 'flow, 'tcx> { /// /// Add facts for all locals with free regions, since regions may outlive /// the function body only at certain nodes in the CFG. - fn add_extra_drop_facts(&mut self, relevant_live_locals: FxIndexSet) { + fn add_extra_drop_facts(&mut self, relevant_live_locals: &[Local]) -> Option<()> { let drop_used = self .cx .typeck .borrowck_context .all_facts .as_ref() - .map(|facts| facts.var_dropped_at.clone()) - .into_iter() - .flatten(); + .map(|facts| facts.var_dropped_at.clone())?; + + let relevant_live_locals: FxIndexSet<_> = relevant_live_locals.iter().copied().collect(); + let locations = IntervalSet::new(self.cx.elements.num_points()); for (local, location_index) in drop_used { @@ -250,6 +247,7 @@ impl<'me, 'typeck, 'flow, 'tcx> LivenessResults<'me, 'typeck, 'flow, 'tcx> { } } } + Some(()) } /// Clear the value of fields that are "per local variable". From 4be8e5a372791a88b8f18a36155b9d34c9b2492d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Ml=C3=A1dek?= Date: Tue, 28 May 2024 20:34:51 +0200 Subject: [PATCH 060/211] add `FlycheckStatus` to global state --- .../crates/rust-analyzer/src/global_state.rs | 21 +++++++++++++++++-- .../crates/rust-analyzer/src/main_loop.rs | 20 +++++++++++++----- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs index 0c2e60fcc912..1216de2de415 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs @@ -87,7 +87,7 @@ pub(crate) struct GlobalState { pub(crate) flycheck_sender: Sender, pub(crate) flycheck_receiver: Receiver, pub(crate) last_flycheck_error: Option, - pub(crate) diagnostics_received: FxHashMap, + pub(crate) flycheck_status: FxHashMap, // Test explorer pub(crate) test_run_session: Option>, @@ -166,6 +166,14 @@ pub(crate) struct GlobalStateSnapshot { pub(crate) flycheck: Arc<[FlycheckHandle]>, } +#[derive(Debug, Clone)] +pub(crate) enum FlycheckStatus { + Unknown, + Started, + DiagnosticReceived, + Finished, +} + impl std::panic::UnwindSafe for GlobalStateSnapshot {} impl GlobalState { @@ -225,7 +233,7 @@ impl GlobalState { flycheck_sender, flycheck_receiver, last_flycheck_error: None, - diagnostics_received: FxHashMap::default(), + flycheck_status: FxHashMap::default(), test_run_session: None, test_run_sender, @@ -513,3 +521,12 @@ pub(crate) fn url_to_file_id(vfs: &vfs::Vfs, url: &Url) -> anyhow::Result bool { + match self { + FlycheckStatus::Unknown | FlycheckStatus::Started => false, + FlycheckStatus::DiagnosticReceived | FlycheckStatus::Finished => true, + } + } +} diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs index a94ca871bdd8..efedea77fef5 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs @@ -19,7 +19,7 @@ use crate::{ config::Config, diagnostics::fetch_native_diagnostics, dispatch::{NotificationDispatcher, RequestDispatcher}, - global_state::{file_id_to_url, url_to_file_id, GlobalState}, + global_state::{file_id_to_url, url_to_file_id, FlycheckStatus, GlobalState}, hack_recover_crate_name, lsp::{ from_proto, to_proto, @@ -804,10 +804,13 @@ impl GlobalState { fn handle_flycheck_msg(&mut self, message: flycheck::Message) { match message { flycheck::Message::AddDiagnostic { id, workspace_root, diagnostic } => { - if !self.diagnostics_received.get(&id).copied().unwrap_or_default() { + let flycheck_status = + self.flycheck_status.entry(id).or_insert(FlycheckStatus::Unknown); + + if !flycheck_status.should_clear_old_diagnostics() { self.diagnostics.clear_check(id); - self.diagnostics_received.insert(id, true); } + *flycheck_status = FlycheckStatus::DiagnosticReceived; let snap = self.snapshot(); let diagnostics = crate::diagnostics::to_proto::map_rust_diagnostic_to_lsp( &self.config.diagnostics_map(), @@ -836,25 +839,32 @@ impl GlobalState { flycheck::Message::Progress { id, progress } => { let (state, message) = match progress { flycheck::Progress::DidStart => { - self.diagnostics_received.insert(id, false); + self.flycheck_status.insert(id, FlycheckStatus::Started); (Progress::Begin, None) } flycheck::Progress::DidCheckCrate(target) => (Progress::Report, Some(target)), flycheck::Progress::DidCancel => { self.last_flycheck_error = None; + // We do not clear + self.flycheck_status.insert(id, FlycheckStatus::Finished); (Progress::End, None) } flycheck::Progress::DidFailToRestart(err) => { self.last_flycheck_error = Some(format!("cargo check failed to start: {err}")); + self.flycheck_status.insert(id, FlycheckStatus::Finished); return; } flycheck::Progress::DidFinish(result) => { self.last_flycheck_error = result.err().map(|err| format!("cargo check failed to start: {err}")); - if !self.diagnostics_received.get(&id).copied().unwrap_or_default() { + let flycheck_status = + self.flycheck_status.entry(id).or_insert(FlycheckStatus::Unknown); + + if !flycheck_status.should_clear_old_diagnostics() { self.diagnostics.clear_check(id); } + *flycheck_status = FlycheckStatus::Finished; (Progress::End, None) } }; From a126c110d9024fc5e87a4a202918c95df0798ef8 Mon Sep 17 00:00:00 2001 From: Lokathor Date: Tue, 28 May 2024 16:07:48 -0600 Subject: [PATCH 061/211] Reorder the TOC so that targets are put under their meta-group --- src/doc/rustc/src/SUMMARY.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index c9c0ee4067f1..2de13218e495 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -26,10 +26,15 @@ - [aarch64-nintendo-switch-freestanding](platform-support/aarch64-nintendo-switch-freestanding.md) - [armeb-unknown-linux-gnueabi](platform-support/armeb-unknown-linux-gnueabi.md) - [arm-none-eabi](platform-support/arm-none-eabi.md) - - [armv4t-none-eabi](platform-support/armv4t-none-eabi.md) - - [armv5te-none-eabi](platform-support/armv5te-none-eabi.md) - - [armv7r-none-eabi](platform-support/armv7r-none-eabi.md) - - [armv8r-none-eabihf](platform-support/armv8r-none-eabihf.md) + - [armv4t-none-eabi](platform-support/armv4t-none-eabi.md) + - [armv5te-none-eabi](platform-support/armv5te-none-eabi.md) + - [armv7r-none-eabi](platform-support/armv7r-none-eabi.md) + - [armv8r-none-eabihf](platform-support/armv8r-none-eabihf.md) + - [thumbv6m-none-eabi](./platform-support/thumbv6m-none-eabi.md) + - [thumbv7em-none-eabi\*](./platform-support/thumbv7em-none-eabi.md) + - [thumbv7m-none-eabi](./platform-support/thumbv7m-none-eabi.md) + - [thumbv8m.base-none-eabi](./platform-support/thumbv8m.base-none-eabi.md) + - [thumbv8m.main-none-eabi\*](./platform-support/thumbv8m.main-none-eabi.md) - [armv6k-nintendo-3ds](platform-support/armv6k-nintendo-3ds.md) - [armv7-sony-vita-newlibeabihf](platform-support/armv7-sony-vita-newlibeabihf.md) - [armv7-unknown-linux-uclibceabi](platform-support/armv7-unknown-linux-uclibceabi.md) @@ -56,11 +61,6 @@ - [riscv32imac-unknown-xous-elf](platform-support/riscv32imac-unknown-xous-elf.md) - [riscv32*-unknown-none-elf](platform-support/riscv32-unknown-none-elf.md) - [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md) - - [thumbv6m-none-eabi](./platform-support/thumbv6m-none-eabi.md) - - [thumbv7m-none-eabi](./platform-support/thumbv7m-none-eabi.md) - - [thumbv7em-none-eabi\*](./platform-support/thumbv7em-none-eabi.md) - - [thumbv8m.base-none-eabi](./platform-support/thumbv8m.base-none-eabi.md) - - [thumbv8m.main-none-eabi\*](./platform-support/thumbv8m.main-none-eabi.md) - [*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md) - [\*-nto-qnx-\*](platform-support/nto-qnx.md) - [*-unikraft-linux-musl](platform-support/unikraft-linux-musl.md) From f6463142eecb238379e6ca06b81578ab0d8e1d32 Mon Sep 17 00:00:00 2001 From: Lokathor Date: Tue, 28 May 2024 16:15:28 -0600 Subject: [PATCH 062/211] make the fact that arm-none-eabi is a group of targets the first thing you see on the page. --- .../src/platform-support/arm-none-eabi.md | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/doc/rustc/src/platform-support/arm-none-eabi.md b/src/doc/rustc/src/platform-support/arm-none-eabi.md index 0b1b10e4762e..09be74a805d1 100644 --- a/src/doc/rustc/src/platform-support/arm-none-eabi.md +++ b/src/doc/rustc/src/platform-support/arm-none-eabi.md @@ -1,6 +1,15 @@ # `{arm,thumb}*-none-eabi(hf)?` -## Tier 2 Target List +## Common Target Details + +This documentation covers details that apply to a range of bare-metal targets +for 32-bit Arm CPUs. The `arm-none-eabi` flavor of the GNU compiler toolchain is +often used to assist compilation to these targets. + +Details that apply only to only a specific target in this group are covered in +their own document. + +### Tier 2 Target List - Arm A-Profile Architectures - `armv7a-none-eabi` @@ -16,7 +25,7 @@ - *Legacy* Arm Architectures - None -## Tier 3 Target List +### Tier 3 Target List - Arm A-Profile Architectures - `armv7a-none-eabihf` @@ -28,11 +37,7 @@ - [`armv4t-none-eabi` and `thumbv4t-none-eabi`](armv4t-none-eabi.md) - [`armv5te-none-eabi` and `thumbv5te-none-eabi`](armv5te-none-eabi.md) -## Common Target Details - -This documentation covers details that apply to a range of bare-metal targets -for 32-bit Arm CPUs. In addition, target specific details may be covered in -their own document. +## Instruction Sets There are two 32-bit instruction set architectures (ISAs) defined by Arm: @@ -43,9 +48,10 @@ There are two 32-bit instruction set architectures (ISAs) defined by Arm: - The [*T32 ISA*][t32-isa], with a mix of 16-bit and 32-bit width instructions. Note that this term includes both the original 16-bit width *Thumb* ISA introduced with the Armv4T architecture in 1994, and the later 16/32-bit sized - *Thumb-2* ISA introduced with the Armv6T2 architecture in 2003. Again, these - ISAs have been revised by subsequent revisions to the relevant Arm - architecture specifications. + *Thumb-2* ISA introduced with the Armv6T2 architecture in 2003. + +Again, these ISAs have been revised by subsequent revisions to the relevant Arm +architecture specifications. There is also a 64-bit ISA with fixed-width 32-bit instructions called the *A64 ISA*, but targets which implement that instruction set generally start with From 144adf6787bbd25913bfd9b6288acf4d337555a0 Mon Sep 17 00:00:00 2001 From: Lokathor Date: Tue, 28 May 2024 17:08:19 -0600 Subject: [PATCH 063/211] update armv4t docs --- .../src/platform-support/armv4t-none-eabi.md | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/doc/rustc/src/platform-support/armv4t-none-eabi.md b/src/doc/rustc/src/platform-support/armv4t-none-eabi.md index f4c8dd46f1d0..ab8b4caaadff 100644 --- a/src/doc/rustc/src/platform-support/armv4t-none-eabi.md +++ b/src/doc/rustc/src/platform-support/armv4t-none-eabi.md @@ -1,16 +1,13 @@ -# armv4t-none-eabi +# armv4t-none-eabi / thumbv4t-none-eabi Tier 3 -Bare-metal target for any cpu in the Armv4T architecture family, supporting -ARM/Thumb code interworking (aka `A32`/`T32`), with ARM code as the default code -generation. +These two targets are part of the [`arm-none-eabi`](arm-none-eabi.md) target +group, and all the information there applies. -In particular this supports the Game Boy Advance (GBA), but there's nothing -GBA-specific with this target, so any Armv4T device should work fine. - -See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all -`arm-none-eabi` targets. +Both of these targets can be used on the Game Boy Advance (GBA), among other +things. On the GBA, one should usually use the `thumb` target to get the best +overall performance. ## Target Maintainers @@ -23,6 +20,6 @@ This is a cross-compiled target that you will need to emulate during testing. Because this is a device-agnostic target, and the exact emulator that you'll need depends on the specific device you want to run your code on. -For example, when programming for the Gameboy Advance, the -[mgba-test-runner](https://github.com/agbrs/agb) program could be used to make a -normal set of rust tests be run within the `mgba` emulator. +* When building for the GBA, [mgba-test-runner](https://github.com/agbrs/agb) + can be used to make a normal set of rust tests be run within the `mgba` + emulator. From d8704b9ac6e72c68920c08a559ce1eba264bef03 Mon Sep 17 00:00:00 2001 From: Lokathor Date: Tue, 28 May 2024 17:16:36 -0600 Subject: [PATCH 064/211] It's spelled "ARM", in all caps. --- .../src/platform-support/arm-none-eabi.md | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/doc/rustc/src/platform-support/arm-none-eabi.md b/src/doc/rustc/src/platform-support/arm-none-eabi.md index 09be74a805d1..aa8ab296fba5 100644 --- a/src/doc/rustc/src/platform-support/arm-none-eabi.md +++ b/src/doc/rustc/src/platform-support/arm-none-eabi.md @@ -3,7 +3,7 @@ ## Common Target Details This documentation covers details that apply to a range of bare-metal targets -for 32-bit Arm CPUs. The `arm-none-eabi` flavor of the GNU compiler toolchain is +for 32-bit ARM CPUs. The `arm-none-eabi` flavor of the GNU compiler toolchain is often used to assist compilation to these targets. Details that apply only to only a specific target in this group are covered in @@ -11,55 +11,55 @@ their own document. ### Tier 2 Target List -- Arm A-Profile Architectures +- ARM A-Profile Architectures - `armv7a-none-eabi` -- Arm R-Profile Architectures +- ARM R-Profile Architectures - [`armv7r-none-eabi` and `armv7r-none-eabihf`](armv7r-none-eabi.md) - [`armebv7r-none-eabi` and `armebv7r-none-eabihf`](armv7r-none-eabi.md) -- Arm M-Profile Architectures +- ARM M-Profile Architectures - [`thumbv6m-none-eabi`](thumbv6m-none-eabi.md) - [`thumbv7m-none-eabi`](thumbv7m-none-eabi.md) - [`thumbv7em-none-eabi` and `thumbv7em-none-eabihf`](thumbv7em-none-eabi.md) - [`thumbv8m.base-none-eabi`](thumbv8m.base-none-eabi.md) - [`thumbv8m.main-none-eabi` and `thumbv8m.main-none-eabihf`](thumbv8m.main-none-eabi.md) -- *Legacy* Arm Architectures +- *Legacy* ARM Architectures - None ### Tier 3 Target List -- Arm A-Profile Architectures +- ARM A-Profile Architectures - `armv7a-none-eabihf` -- Arm R-Profile Architectures +- ARM R-Profile Architectures - [`armv8r-none-eabihf`](armv8r-none-eabihf.md) -- Arm M-Profile Architectures +- ARM M-Profile Architectures - None -- *Legacy* Arm Architectures +- *Legacy* ARM Architectures - [`armv4t-none-eabi` and `thumbv4t-none-eabi`](armv4t-none-eabi.md) - [`armv5te-none-eabi` and `thumbv5te-none-eabi`](armv5te-none-eabi.md) ## Instruction Sets -There are two 32-bit instruction set architectures (ISAs) defined by Arm: +There are two 32-bit instruction set architectures (ISAs) defined by ARM: - The [*A32 ISA*][a32-isa], with fixed-width 32-bit instructions. Previously - known as the *Arm* ISA, this originated with the original ARM1 of 1985 and has + known as the *ARM* ISA, this originated with the original ARM1 of 1985 and has been updated by various revisions to the architecture specifications ever since. - The [*T32 ISA*][t32-isa], with a mix of 16-bit and 32-bit width instructions. Note that this term includes both the original 16-bit width *Thumb* ISA - introduced with the Armv4T architecture in 1994, and the later 16/32-bit sized - *Thumb-2* ISA introduced with the Armv6T2 architecture in 2003. + introduced with the ARMv4T architecture in 1994, and the later 16/32-bit sized + *Thumb-2* ISA introduced with the ARMv6T2 architecture in 2003. -Again, these ISAs have been revised by subsequent revisions to the relevant Arm +Again, these ISAs have been revised by subsequent revisions to the relevant ARM architecture specifications. There is also a 64-bit ISA with fixed-width 32-bit instructions called the *A64 ISA*, but targets which implement that instruction set generally start with `aarch64*` and are discussed elsewhere. -Rust targets starting with `arm*` generate Arm (A32) code by default, whilst -targets named `thumb*` generate Thumb (T32) code by default. Most Arm chips -support both Thumb mode and Arm mode, with the notable exception that M-profile +Rust targets starting with `arm*` generate ARM (A32) code by default, whilst +targets named `thumb*` generate Thumb (T32) code by default. Most ARM chips +support both Thumb mode and ARM mode, with the notable exception that M-profile processors (`thumbv*m*-none-eabi*` targets) *only* support Thumb-mode. Rust targets ending with `eabi` use the so-called *soft-float ABI*: functions @@ -92,14 +92,14 @@ instructions. ## Target CPU and Target Feature options -It is possible to tell Rust (or LLVM) that you have a specific model of Arm +It is possible to tell Rust (or LLVM) that you have a specific model of ARM processor, using the [`-C target-cpu`][target-cpu] option. You can also control whether Rust (or LLVM) will include instructions that target optional hardware features, e.g. hardware floating-point, or Advanced SIMD operations, using [`-C target-feature`][target-feature]. It is important to note that selecting a *target-cpu* will typically enable -*all* the optional features available from Arm on that model of CPU and your +*all* the optional features available from ARM on that model of CPU and your particular implementation of that CPU may not have those features available. In that case, you can use `-C target-feature=-option` to turn off the specific CPU features you do not have available, leaving you with the optimized instruction @@ -116,7 +116,7 @@ uses (likely linker related ones): ```toml rustflags = [ - # Usual Arm bare-metal linker setup + # Usual ARM bare-metal linker setup "-Clink-arg=-Tlink.x", "-Clink-arg=--nmagic", # tell Rust we have a Cortex-M55 @@ -139,7 +139,7 @@ These targets are cross-compiled and use static linking. By default, the `lld` linker included with Rust will be used; however, you may want to use the GNU linker instead. This can be obtained for Windows/Mac/Linux -from the [Arm Developer Website][arm-gnu-toolchain], or possibly from your OS's +from the [ARM Developer Website][arm-gnu-toolchain], or possibly from your OS's package manager. To use it, add the following to your `.cargo/config.toml`: ```toml @@ -185,7 +185,7 @@ Most of `core` should work as expected, with the following notes: specific kind of FPU) * Integer division is also emulated in software on some targets, depending on the target, `target-cpu` and `target-feature`s. -* Older Arm architectures (e.g. Armv4, Armv5TE and Armv6-M) are limited to basic +* Older ARM architectures (e.g. ARMv4, ARMv5TE and ARMv6-M) are limited to basic [`load`][atomic-load] and [`store`][atomic-store] operations, and not more advanced operations like [`fetch_add`][fetch-add] or [`compare_exchange`][compare-exchange]. From bb1f5c38c053905953e7310f9e2d9e29acfc3ad9 Mon Sep 17 00:00:00 2001 From: Lokathor Date: Tue, 28 May 2024 17:30:30 -0600 Subject: [PATCH 065/211] delete the offending single space. --- src/doc/rustc/src/platform-support/arm-none-eabi.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc/src/platform-support/arm-none-eabi.md b/src/doc/rustc/src/platform-support/arm-none-eabi.md index aa8ab296fba5..09f3461cb980 100644 --- a/src/doc/rustc/src/platform-support/arm-none-eabi.md +++ b/src/doc/rustc/src/platform-support/arm-none-eabi.md @@ -5,7 +5,7 @@ This documentation covers details that apply to a range of bare-metal targets for 32-bit ARM CPUs. The `arm-none-eabi` flavor of the GNU compiler toolchain is often used to assist compilation to these targets. - + Details that apply only to only a specific target in this group are covered in their own document. From 39b39da40beed5e4e555a1465dd0413b04afe91e Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 28 May 2024 16:05:13 +0000 Subject: [PATCH 066/211] Stop proving outlives constraints on regions we already reported errors on --- compiler/rustc_borrowck/src/nll.rs | 14 ++++- .../rustc_borrowck/src/universal_regions.rs | 20 ++++++- tests/rustdoc-ui/unable-fulfill-trait.rs | 13 ++-- tests/rustdoc-ui/unable-fulfill-trait.stderr | 31 +++++++--- .../associated-inherent-types/issue-109299.rs | 1 - .../issue-109299.stderr | 11 +--- .../ui/borrowck/generic_const_early_param.rs | 1 - .../borrowck/generic_const_early_param.stderr | 10 +--- .../gat-trait-path-missing-lifetime.rs | 1 - .../gat-trait-path-missing-lifetime.stderr | 11 +--- .../generic-associated-types/issue-70304.rs | 1 - .../issue-70304.stderr | 18 +----- .../generic-associated-types/issue-80433.rs | 3 +- .../issue-80433.stderr | 28 +-------- .../bad-item-bound-within-rpitit-2.rs | 2 - .../bad-item-bound-within-rpitit-2.stderr | 17 ++---- tests/ui/impl-trait/issues/issue-67830.rs | 7 +-- tests/ui/impl-trait/issues/issue-67830.stderr | 31 ++-------- tests/ui/impl-trait/issues/issue-88236-2.rs | 5 -- .../ui/impl-trait/issues/issue-88236-2.stderr | 60 +------------------ tests/ui/impl-trait/nested-rpit-hrtb.rs | 2 - tests/ui/impl-trait/nested-rpit-hrtb.stderr | 34 +++-------- tests/ui/lifetimes/issue-69314.fixed | 2 +- tests/ui/lifetimes/issue-69314.rs | 2 +- tests/ui/lifetimes/issue-69314.stderr | 18 +----- 25 files changed, 97 insertions(+), 246 deletions(-) diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 49f50babdcb9..5d7ce548469f 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -125,8 +125,8 @@ pub(crate) fn compute_regions<'cx, 'tcx>( placeholder_indices, placeholder_index_to_region: _, liveness_constraints, - outlives_constraints, - member_constraints, + mut outlives_constraints, + mut member_constraints, universe_causes, type_tests, } = constraints; @@ -144,6 +144,16 @@ pub(crate) fn compute_regions<'cx, 'tcx>( &universal_region_relations, ); + if let Some(guar) = universal_regions.tainted_by_errors() { + // Suppress unhelpful extra errors in `infer_opaque_types` by clearing out all + // outlives bounds that we may end up checking. + outlives_constraints = Default::default(); + member_constraints = Default::default(); + + // Also taint the entire scope. + infcx.set_tainted_by_errors(guar); + } + let mut regioncx = RegionInferenceContext::new( infcx, var_origins, diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index f8123535e2d0..9f5fb59e46c5 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -29,7 +29,8 @@ use rustc_middle::ty::{self, InlineConstArgs, InlineConstArgsParts, RegionVid, T use rustc_middle::ty::{GenericArgs, GenericArgsRef}; use rustc_middle::{bug, span_bug}; use rustc_span::symbol::{kw, sym}; -use rustc_span::Symbol; +use rustc_span::{ErrorGuaranteed, Symbol}; +use std::cell::Cell; use std::iter; use crate::renumber::RegionCtxt; @@ -186,6 +187,10 @@ struct UniversalRegionIndices<'tcx> { /// The vid assigned to `'static`. Used only for diagnostics. pub fr_static: RegionVid, + + /// Whether we've encountered an error region. If we have, cancel all + /// outlives errors, as they are likely bogus. + pub tainted_by_errors: Cell>, } #[derive(Debug, PartialEq)] @@ -408,6 +413,10 @@ impl<'tcx> UniversalRegions<'tcx> { } } } + + pub fn tainted_by_errors(&self) -> Option { + self.indices.tainted_by_errors.get() + } } struct UniversalRegionsBuilder<'cx, 'tcx> { @@ -663,7 +672,11 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { let global_mapping = iter::once((tcx.lifetimes.re_static, fr_static)); let arg_mapping = iter::zip(identity_args.regions(), fr_args.regions().map(|r| r.as_var())); - UniversalRegionIndices { indices: global_mapping.chain(arg_mapping).collect(), fr_static } + UniversalRegionIndices { + indices: global_mapping.chain(arg_mapping).collect(), + fr_static, + tainted_by_errors: Cell::new(None), + } } fn compute_inputs_and_output( @@ -868,7 +881,8 @@ impl<'tcx> UniversalRegionIndices<'tcx> { pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid { if let ty::ReVar(..) = *r { r.as_var() - } else if r.is_error() { + } else if let ty::ReError(guar) = *r { + self.tainted_by_errors.set(Some(guar)); // We use the `'static` `RegionVid` because `ReError` doesn't actually exist in the // `UniversalRegionIndices`. This is fine because 1) it is a fallback only used if // errors are being emitted and 2) it leaves the happy path unaffected. diff --git a/tests/rustdoc-ui/unable-fulfill-trait.rs b/tests/rustdoc-ui/unable-fulfill-trait.rs index a69f74b09ac0..f3b6256346f0 100644 --- a/tests/rustdoc-ui/unable-fulfill-trait.rs +++ b/tests/rustdoc-ui/unable-fulfill-trait.rs @@ -1,13 +1,16 @@ // This test ensures that it's not crashing rustdoc. pub struct Foo<'a, 'b, T> { - field1: dyn Bar<'a, 'b,>, + field1: dyn Bar<'a, 'b>, //~^ ERROR //~| ERROR + //~| ERROR } pub trait Bar<'x, 's, U> - where U: 'x, - Self:'x, - Self:'s -{} +where + U: 'x, + Self: 'x, + Self: 's, +{ +} diff --git a/tests/rustdoc-ui/unable-fulfill-trait.stderr b/tests/rustdoc-ui/unable-fulfill-trait.stderr index 72f35cb92244..40d103f2a62e 100644 --- a/tests/rustdoc-ui/unable-fulfill-trait.stderr +++ b/tests/rustdoc-ui/unable-fulfill-trait.stderr @@ -1,26 +1,43 @@ error[E0107]: trait takes 1 generic argument but 0 generic arguments were supplied --> $DIR/unable-fulfill-trait.rs:4:17 | -LL | field1: dyn Bar<'a, 'b,>, +LL | field1: dyn Bar<'a, 'b>, | ^^^ expected 1 generic argument | note: trait defined here, with 1 generic parameter: `U` - --> $DIR/unable-fulfill-trait.rs:9:11 + --> $DIR/unable-fulfill-trait.rs:10:11 | LL | pub trait Bar<'x, 's, U> | ^^^ - help: add missing generic argument | -LL | field1: dyn Bar<'a, 'b, U,>, +LL | field1: dyn Bar<'a, 'b, U>, | +++ error[E0227]: ambiguous lifetime bound, explicit lifetime bound required --> $DIR/unable-fulfill-trait.rs:4:13 | -LL | field1: dyn Bar<'a, 'b,>, - | ^^^^^^^^^^^^^^^^ +LL | field1: dyn Bar<'a, 'b>, + | ^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error[E0478]: lifetime bound not satisfied + --> $DIR/unable-fulfill-trait.rs:4:13 + | +LL | field1: dyn Bar<'a, 'b>, + | ^^^^^^^^^^^^^^^ + | +note: lifetime parameter instantiated with the lifetime `'b` as defined here + --> $DIR/unable-fulfill-trait.rs:3:20 + | +LL | pub struct Foo<'a, 'b, T> { + | ^^ +note: but lifetime parameter must outlive the lifetime `'a` as defined here + --> $DIR/unable-fulfill-trait.rs:3:16 + | +LL | pub struct Foo<'a, 'b, T> { + | ^^ -Some errors have detailed explanations: E0107, E0227. +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0107, E0227, E0478. For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/associated-inherent-types/issue-109299.rs b/tests/ui/associated-inherent-types/issue-109299.rs index b6c010c34e44..84e4f9e72527 100644 --- a/tests/ui/associated-inherent-types/issue-109299.rs +++ b/tests/ui/associated-inherent-types/issue-109299.rs @@ -8,6 +8,5 @@ impl Lexer<'d> { //~ ERROR use of undeclared lifetime name `'d` } fn test(_: Lexer::Cursor) {} -//~^ ERROR: lifetime may not live long enough fn main() {} diff --git a/tests/ui/associated-inherent-types/issue-109299.stderr b/tests/ui/associated-inherent-types/issue-109299.stderr index f108a52b92c0..1e11c0e8c2af 100644 --- a/tests/ui/associated-inherent-types/issue-109299.stderr +++ b/tests/ui/associated-inherent-types/issue-109299.stderr @@ -6,15 +6,6 @@ LL | impl Lexer<'d> { | | | help: consider introducing lifetime `'d` here: `<'d>` -error: lifetime may not live long enough - --> $DIR/issue-109299.rs:10:1 - | -LL | fn test(_: Lexer::Cursor) {} - | ^^^^^^^^-^^^^^^^^^^^^^^^^ - | | | - | | has type `Lexer<'1>::Cursor` - | requires that `'1` must outlive `'static` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0261`. diff --git a/tests/ui/borrowck/generic_const_early_param.rs b/tests/ui/borrowck/generic_const_early_param.rs index f601e45d21fe..0d07b6869f12 100644 --- a/tests/ui/borrowck/generic_const_early_param.rs +++ b/tests/ui/borrowck/generic_const_early_param.rs @@ -5,7 +5,6 @@ struct DataWrapper<'static> { //~^ ERROR invalid lifetime parameter name: `'static` data: &'a [u8; Self::SIZE], //~^ ERROR use of undeclared lifetime name `'a` - //~^^ ERROR lifetime may not live long enough } impl DataWrapper<'a> { diff --git a/tests/ui/borrowck/generic_const_early_param.stderr b/tests/ui/borrowck/generic_const_early_param.stderr index a71ab09396e7..3f56d6a33251 100644 --- a/tests/ui/borrowck/generic_const_early_param.stderr +++ b/tests/ui/borrowck/generic_const_early_param.stderr @@ -14,7 +14,7 @@ LL | data: &'a [u8; Self::SIZE], | ^^ undeclared lifetime error[E0261]: use of undeclared lifetime name `'a` - --> $DIR/generic_const_early_param.rs:11:18 + --> $DIR/generic_const_early_param.rs:10:18 | LL | impl DataWrapper<'a> { | - ^^ undeclared lifetime @@ -30,13 +30,7 @@ LL | #![feature(generic_const_exprs)] = note: see issue #76560 for more information = note: `#[warn(incomplete_features)]` on by default -error: lifetime may not live long enough - --> $DIR/generic_const_early_param.rs:6:20 - | -LL | data: &'a [u8; Self::SIZE], - | ^^^^^^^^^^ requires that `'_` must outlive `'static` - -error: aborting due to 4 previous errors; 1 warning emitted +error: aborting due to 3 previous errors; 1 warning emitted Some errors have detailed explanations: E0261, E0262. For more information about an error, try `rustc --explain E0261`. diff --git a/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.rs b/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.rs index 671d17f36f13..285493132b64 100644 --- a/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.rs +++ b/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.rs @@ -9,7 +9,6 @@ impl X for T { //~ ERROR: not all trait items implemented //~^ ERROR missing generics for associated type //~^^ ERROR missing generics for associated type //~| ERROR method `foo` has 1 type parameter but its trait declaration has 0 type parameters - //~| ERROR may not live long enough t } } diff --git a/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr b/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr index 65854ed71587..6a600aee11f2 100644 --- a/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr +++ b/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr @@ -51,16 +51,7 @@ help: add missing lifetime argument LL | fn foo<'a, T1: X = T1>>(t : T1) -> T1::Y<'a> { | ++++ -error: lifetime may not live long enough - --> $DIR/gat-trait-path-missing-lifetime.rs:8:3 - | -LL | fn foo<'a, T1: X>(t : T1) -> T1::Y<'a> { - | ^^^^^^^--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | | - | | lifetime `'a` defined here - | requires that `'a` must outlive `'static` - -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0046, E0049, E0107. For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/generic-associated-types/issue-70304.rs b/tests/ui/generic-associated-types/issue-70304.rs index 935d3f7a4ba8..8898d4c7d135 100644 --- a/tests/ui/generic-associated-types/issue-70304.rs +++ b/tests/ui/generic-associated-types/issue-70304.rs @@ -52,5 +52,4 @@ fn create_doc() -> impl Document = DocCursorImpl<'_>> { pub fn main() { let doc = create_doc(); let lexer: Lexer<'_, DocCursorImpl<'_>> = Lexer::from(&doc); - //~^ ERROR: `doc` does not live long enough } diff --git a/tests/ui/generic-associated-types/issue-70304.stderr b/tests/ui/generic-associated-types/issue-70304.stderr index 8e012cc6d936..9b02c1b07683 100644 --- a/tests/ui/generic-associated-types/issue-70304.stderr +++ b/tests/ui/generic-associated-types/issue-70304.stderr @@ -27,21 +27,7 @@ LL | type Cursor<'a>: DocCursor<'a>; = note: this bound is currently required to ensure that impls have maximum flexibility = note: we are soliciting feedback, see issue #87479 for more information -error[E0597]: `doc` does not live long enough - --> $DIR/issue-70304.rs:54:59 - | -LL | let doc = create_doc(); - | --- binding `doc` declared here -LL | let lexer: Lexer<'_, DocCursorImpl<'_>> = Lexer::from(&doc); - | ------------^^^^- - | | | - | | borrowed value does not live long enough - | argument requires that `doc` is borrowed for `'static` -LL | -LL | } - | - `doc` dropped here while still borrowed +error: aborting due to 3 previous errors -error: aborting due to 4 previous errors - -Some errors have detailed explanations: E0106, E0597, E0637. +Some errors have detailed explanations: E0106, E0637. For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/generic-associated-types/issue-80433.rs b/tests/ui/generic-associated-types/issue-80433.rs index 530575424402..bdba78c2ccd2 100644 --- a/tests/ui/generic-associated-types/issue-80433.rs +++ b/tests/ui/generic-associated-types/issue-80433.rs @@ -22,8 +22,7 @@ fn test_simpler<'a>(dst: &'a mut impl TestMut) //~^ ERROR missing generics for associated type { for n in 0i16..100 { - *dst.test_mut() = n.into(); //~ ERROR: cannot borrow - //~^ ERROR: borrowed data escapes outside of function + *dst.test_mut() = n.into(); } } diff --git a/tests/ui/generic-associated-types/issue-80433.stderr b/tests/ui/generic-associated-types/issue-80433.stderr index a9a14d3f51ce..8ab6fdcb8157 100644 --- a/tests/ui/generic-associated-types/issue-80433.stderr +++ b/tests/ui/generic-associated-types/issue-80433.stderr @@ -25,30 +25,6 @@ help: add missing lifetime argument LL | fn test_simpler<'a>(dst: &'a mut impl TestMut = &'a mut f32>) | ++++ -error[E0499]: cannot borrow `*dst` as mutable more than once at a time - --> $DIR/issue-80433.rs:25:10 - | -LL | *dst.test_mut() = n.into(); - | ^^^----------- - | | - | `*dst` was mutably borrowed here in the previous iteration of the loop - | argument requires that `*dst` is borrowed for `'static` +error: aborting due to 2 previous errors -error[E0521]: borrowed data escapes outside of function - --> $DIR/issue-80433.rs:25:10 - | -LL | fn test_simpler<'a>(dst: &'a mut impl TestMut) - | -- --- `dst` is a reference that is only valid in the function body - | | - | lifetime `'a` defined here -... -LL | *dst.test_mut() = n.into(); - | ^^^^^^^^^^^^^^ - | | - | `dst` escapes the function body here - | argument requires that `'a` must outlive `'static` - -error: aborting due to 4 previous errors - -Some errors have detailed explanations: E0107, E0499, E0521. -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/impl-trait/in-trait/bad-item-bound-within-rpitit-2.rs b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.rs index 5b3a4eb53ff1..14b1ebea8db2 100644 --- a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.rs +++ b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.rs @@ -1,11 +1,9 @@ // issue: 114146 - trait Foo { fn bar<'other: 'a>() -> impl Sized + 'a {} //~^ ERROR use of undeclared lifetime name `'a` //~| ERROR use of undeclared lifetime name `'a` - //~| ERROR expected generic lifetime parameter, found `'static` } fn main() {} diff --git a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.stderr b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.stderr index 8975578dabd8..f1b006da1db5 100644 --- a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.stderr +++ b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.stderr @@ -1,5 +1,5 @@ error[E0261]: use of undeclared lifetime name `'a` - --> $DIR/bad-item-bound-within-rpitit-2.rs:5:20 + --> $DIR/bad-item-bound-within-rpitit-2.rs:4:20 | LL | fn bar<'other: 'a>() -> impl Sized + 'a {} | ^^ undeclared lifetime @@ -14,7 +14,7 @@ LL | trait Foo<'a> { | ++++ error[E0261]: use of undeclared lifetime name `'a` - --> $DIR/bad-item-bound-within-rpitit-2.rs:5:42 + --> $DIR/bad-item-bound-within-rpitit-2.rs:4:42 | LL | fn bar<'other: 'a>() -> impl Sized + 'a {} | ^^ undeclared lifetime @@ -28,15 +28,6 @@ help: consider introducing lifetime `'a` here LL | trait Foo<'a> { | ++++ -error[E0792]: expected generic lifetime parameter, found `'static` - --> $DIR/bad-item-bound-within-rpitit-2.rs:5:45 - | -LL | fn bar<'other: 'a>() -> impl Sized + 'a {} - | ------ ^^ - | | - | cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type +error: aborting due to 2 previous errors -error: aborting due to 3 previous errors - -Some errors have detailed explanations: E0261, E0792. -For more information about an error, try `rustc --explain E0261`. +For more information about this error, try `rustc --explain E0261`. diff --git a/tests/ui/impl-trait/issues/issue-67830.rs b/tests/ui/impl-trait/issues/issue-67830.rs index 939eca82a8f6..28772fa52720 100644 --- a/tests/ui/impl-trait/issues/issue-67830.rs +++ b/tests/ui/impl-trait/issues/issue-67830.rs @@ -7,7 +7,7 @@ struct Wrap(F); impl MyFn for Wrap where - F: Fn(A) -> B + F: Fn(A) -> B, { type Output = B; @@ -16,13 +16,10 @@ where } } - struct A; -fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> { +fn test() -> impl for<'a> MyFn<&'a A, Output = impl Iterator + 'a> { //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` Wrap(|a| Some(a).into_iter()) - //~^ ERROR implementation of `FnOnce` is not general enough - //~| ERROR implementation of `FnOnce` is not general enough } fn main() {} diff --git a/tests/ui/impl-trait/issues/issue-67830.stderr b/tests/ui/impl-trait/issues/issue-67830.stderr index ef513a40cf39..a7633c7f20b6 100644 --- a/tests/ui/impl-trait/issues/issue-67830.stderr +++ b/tests/ui/impl-trait/issues/issue-67830.stderr @@ -1,34 +1,15 @@ error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` - --> $DIR/issue-67830.rs:21:62 + --> $DIR/issue-67830.rs:20:64 | -LL | fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> { - | ^^ +LL | fn test() -> impl for<'a> MyFn<&'a A, Output = impl Iterator + 'a> { + | ^^ | note: lifetime declared here - --> $DIR/issue-67830.rs:21:23 + --> $DIR/issue-67830.rs:20:23 | -LL | fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> { +LL | fn test() -> impl for<'a> MyFn<&'a A, Output = impl Iterator + 'a> { | ^^ -error: implementation of `FnOnce` is not general enough - --> $DIR/issue-67830.rs:23:5 - | -LL | Wrap(|a| Some(a).into_iter()) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough - | - = note: closure with signature `fn(&'2 A) -> std::option::IntoIter<&A>` must implement `FnOnce<(&'1 A,)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&'2 A,)>`, for some specific lifetime `'2` - -error: implementation of `FnOnce` is not general enough - --> $DIR/issue-67830.rs:23:5 - | -LL | Wrap(|a| Some(a).into_iter()) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough - | - = note: closure with signature `fn(&'2 A) -> std::option::IntoIter<&A>` must implement `FnOnce<(&'1 A,)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&'2 A,)>`, for some specific lifetime `'2` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 3 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0657`. diff --git a/tests/ui/impl-trait/issues/issue-88236-2.rs b/tests/ui/impl-trait/issues/issue-88236-2.rs index 7ff08d8174f8..5005af46ee18 100644 --- a/tests/ui/impl-trait/issues/issue-88236-2.rs +++ b/tests/ui/impl-trait/issues/issue-88236-2.rs @@ -18,16 +18,11 @@ fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {} fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> { //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` &() - //~^ ERROR implementation of `Hrtb` is not general enough - //~| ERROR implementation of `Hrtb` is not general enough } fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> { //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` x - //~^ ERROR implementation of `Hrtb` is not general enough - //~| ERROR implementation of `Hrtb` is not general enough - //~| ERROR lifetime may not live long enough } fn main() {} diff --git a/tests/ui/impl-trait/issues/issue-88236-2.stderr b/tests/ui/impl-trait/issues/issue-88236-2.stderr index 09fd58056a56..4ded9ed386fa 100644 --- a/tests/ui/impl-trait/issues/issue-88236-2.stderr +++ b/tests/ui/impl-trait/issues/issue-88236-2.stderr @@ -22,72 +22,18 @@ note: lifetime declared here LL | fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> { | ^^ -error: implementation of `Hrtb` is not general enough - --> $DIR/issue-88236-2.rs:20:5 - | -LL | &() - | ^^^ implementation of `Hrtb` is not general enough - | - = note: `Hrtb<'0>` would have to be implemented for the type `&()`, for any lifetime `'0`... - = note: ...but `Hrtb<'1>` is actually implemented for the type `&'1 ()`, for some specific lifetime `'1` - -error: implementation of `Hrtb` is not general enough - --> $DIR/issue-88236-2.rs:20:5 - | -LL | &() - | ^^^ implementation of `Hrtb` is not general enough - | - = note: `Hrtb<'a>` would have to be implemented for the type `&()` - = note: ...but `Hrtb<'0>` is actually implemented for the type `&'0 ()`, for some specific lifetime `'0` - error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` - --> $DIR/issue-88236-2.rs:25:78 + --> $DIR/issue-88236-2.rs:23:78 | LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> { | ^^ | note: lifetime declared here - --> $DIR/issue-88236-2.rs:25:45 + --> $DIR/issue-88236-2.rs:23:45 | LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> { | ^^ -error: lifetime may not live long enough - --> $DIR/issue-88236-2.rs:27:5 - | -LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> { - | -- lifetime `'b` defined here -LL | -LL | x - | ^ returning this value requires that `'b` must outlive `'static` - | -help: to declare that `impl for<'a> Hrtb<'a, Assoc = impl Send + '_>` captures data from argument `x`, you can add an explicit `'b` lifetime bound - | -LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> + 'b { - | ++++ -help: to declare that `impl Send + 'a` captures data from argument `x`, you can add an explicit `'b` lifetime bound - | -LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a + 'b> { - | ++++ - -error: implementation of `Hrtb` is not general enough - --> $DIR/issue-88236-2.rs:27:5 - | -LL | x - | ^ implementation of `Hrtb` is not general enough - | - = note: `Hrtb<'0>` would have to be implemented for the type `&()`, for any lifetime `'0`... - = note: ...but `Hrtb<'1>` is actually implemented for the type `&'1 ()`, for some specific lifetime `'1` - -error: implementation of `Hrtb` is not general enough - --> $DIR/issue-88236-2.rs:27:5 - | -LL | x - | ^ implementation of `Hrtb` is not general enough - | - = note: `Hrtb<'a>` would have to be implemented for the type `&()` - = note: ...but `Hrtb<'0>` is actually implemented for the type `&'0 ()`, for some specific lifetime `'0` - -error: aborting due to 8 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0657`. diff --git a/tests/ui/impl-trait/nested-rpit-hrtb.rs b/tests/ui/impl-trait/nested-rpit-hrtb.rs index 9b18aceb4a73..11d79bcff737 100644 --- a/tests/ui/impl-trait/nested-rpit-hrtb.rs +++ b/tests/ui/impl-trait/nested-rpit-hrtb.rs @@ -31,7 +31,6 @@ fn one_hrtb_trait_param() -> impl for<'a> Foo<'a, Assoc = impl Qux<'a>> {} fn one_hrtb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'a> {} //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` -//~| ERROR implementation of `Bar` is not general enough fn one_hrtb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl Qux<'a>> {} //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` @@ -64,6 +63,5 @@ fn two_htrb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Qux< // `'b` is not in scope for the outlives bound. fn two_htrb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Sized + 'b> {} //~^ ERROR use of undeclared lifetime name `'b` [E0261] -//~| ERROR implementation of `Bar` is not general enough fn main() {} diff --git a/tests/ui/impl-trait/nested-rpit-hrtb.stderr b/tests/ui/impl-trait/nested-rpit-hrtb.stderr index 2fa036f35fab..d98de650d0d8 100644 --- a/tests/ui/impl-trait/nested-rpit-hrtb.stderr +++ b/tests/ui/impl-trait/nested-rpit-hrtb.stderr @@ -1,5 +1,5 @@ error[E0261]: use of undeclared lifetime name `'b` - --> $DIR/nested-rpit-hrtb.rs:57:77 + --> $DIR/nested-rpit-hrtb.rs:56:77 | LL | fn two_htrb_outlives() -> impl for<'a> Foo<'a, Assoc = impl for<'b> Sized + 'b> {} | ^^ undeclared lifetime @@ -15,7 +15,7 @@ LL | fn two_htrb_outlives<'b>() -> impl for<'a> Foo<'a, Assoc = impl for<'b> Siz | ++++ error[E0261]: use of undeclared lifetime name `'b` - --> $DIR/nested-rpit-hrtb.rs:65:82 + --> $DIR/nested-rpit-hrtb.rs:64:82 | LL | fn two_htrb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Sized + 'b> {} | ^^ undeclared lifetime @@ -65,29 +65,20 @@ note: lifetime declared here LL | fn one_hrtb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'a> {} | ^^ -error: implementation of `Bar` is not general enough - --> $DIR/nested-rpit-hrtb.rs:32:78 - | -LL | fn one_hrtb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'a> {} - | ^^ implementation of `Bar` is not general enough - | - = note: `()` must implement `Bar<'a>` - = note: ...but it actually implements `Bar<'0>`, for some specific lifetime `'0` - error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` - --> $DIR/nested-rpit-hrtb.rs:36:73 + --> $DIR/nested-rpit-hrtb.rs:35:73 | LL | fn one_hrtb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl Qux<'a>> {} | ^^ | note: lifetime declared here - --> $DIR/nested-rpit-hrtb.rs:36:44 + --> $DIR/nested-rpit-hrtb.rs:35:44 | LL | fn one_hrtb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl Qux<'a>> {} | ^^ error[E0277]: the trait bound `for<'a> &'a (): Qux<'b>` is not satisfied - --> $DIR/nested-rpit-hrtb.rs:46:79 + --> $DIR/nested-rpit-hrtb.rs:45:79 | LL | fn one_hrtb_mention_fn_trait_param_uses<'b>() -> impl for<'a> Bar<'a, Assoc = impl Qux<'b>> {} | ^^^^^^^^^^^^ the trait `for<'a> Qux<'b>` is not implemented for `&'a ()` @@ -96,7 +87,7 @@ LL | fn one_hrtb_mention_fn_trait_param_uses<'b>() -> impl for<'a> Bar<'a, Assoc = help: for that trait implementation, expected `()`, found `&'a ()` error: implementation of `Bar` is not general enough - --> $DIR/nested-rpit-hrtb.rs:50:93 + --> $DIR/nested-rpit-hrtb.rs:49:93 | LL | fn one_hrtb_mention_fn_outlives_uses<'b>() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'b> {} | ^^ implementation of `Bar` is not general enough @@ -105,7 +96,7 @@ LL | fn one_hrtb_mention_fn_outlives_uses<'b>() -> impl for<'a> Bar<'a, Assoc = = note: ...but it actually implements `Bar<'0>`, for some specific lifetime `'0` error[E0277]: the trait bound `for<'a, 'b> &'a (): Qux<'b>` is not satisfied - --> $DIR/nested-rpit-hrtb.rs:61:64 + --> $DIR/nested-rpit-hrtb.rs:60:64 | LL | fn two_htrb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Qux<'b>> {} | ^^^^^^^^^^^^^^^^^^^^ the trait `for<'a, 'b> Qux<'b>` is not implemented for `&'a ()` @@ -113,16 +104,7 @@ LL | fn two_htrb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> = help: the trait `Qux<'_>` is implemented for `()` = help: for that trait implementation, expected `()`, found `&'a ()` -error: implementation of `Bar` is not general enough - --> $DIR/nested-rpit-hrtb.rs:65:86 - | -LL | fn two_htrb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Sized + 'b> {} - | ^^ implementation of `Bar` is not general enough - | - = note: `()` must implement `Bar<'a>` - = note: ...but it actually implements `Bar<'0>`, for some specific lifetime `'0` - -error: aborting due to 11 previous errors +error: aborting due to 9 previous errors Some errors have detailed explanations: E0261, E0277, E0657. For more information about an error, try `rustc --explain E0261`. diff --git a/tests/ui/lifetimes/issue-69314.fixed b/tests/ui/lifetimes/issue-69314.fixed index 285d192b44c7..ee1675724fb1 100644 --- a/tests/ui/lifetimes/issue-69314.fixed +++ b/tests/ui/lifetimes/issue-69314.fixed @@ -11,7 +11,7 @@ impl A { } async fn f() { let mut buf = [0; 512]; - let m2 = &buf[..]; //~ ERROR `buf` does not live long enough + let m2 = &buf[..]; let m = Self::g(m2).await; Self::f2(m).await; } diff --git a/tests/ui/lifetimes/issue-69314.rs b/tests/ui/lifetimes/issue-69314.rs index 345f77850608..f9e5196b2c74 100644 --- a/tests/ui/lifetimes/issue-69314.rs +++ b/tests/ui/lifetimes/issue-69314.rs @@ -11,7 +11,7 @@ impl A { } async fn f() { let mut buf = [0; 512]; - let m2 = &buf[..]; //~ ERROR `buf` does not live long enough + let m2 = &buf[..]; let m = Self::g(m2).await; Self::f2(m).await; } diff --git a/tests/ui/lifetimes/issue-69314.stderr b/tests/ui/lifetimes/issue-69314.stderr index 3879f35505c2..67da54e8dcd7 100644 --- a/tests/ui/lifetimes/issue-69314.stderr +++ b/tests/ui/lifetimes/issue-69314.stderr @@ -9,20 +9,6 @@ help: indicate the anonymous lifetime LL | async fn f2(m: Msg<'_>) {} | ++++ -error[E0597]: `buf` does not live long enough - --> $DIR/issue-69314.rs:14:19 - | -LL | let mut buf = [0; 512]; - | ------- binding `buf` declared here -LL | let m2 = &buf[..]; - | ^^^ borrowed value does not live long enough -LL | let m = Self::g(m2).await; - | ----------- argument requires that `buf` is borrowed for `'static` -LL | Self::f2(m).await; -LL | } - | - `buf` dropped here while still borrowed +error: aborting due to 1 previous error -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0597, E0726. -For more information about an error, try `rustc --explain E0597`. +For more information about this error, try `rustc --explain E0726`. From e0904cd6a96e76f89112ea83b45e4c507e3e31df Mon Sep 17 00:00:00 2001 From: Daria Sukhonina Date: Fri, 24 May 2024 17:20:49 +0300 Subject: [PATCH 067/211] Add size check inside of the async drop tests --- src/tools/miri/tests/pass/async-drop.rs | 79 ++++++++++++++--------- tests/ui/async-await/async-drop.rs | 85 +++++++++++++++---------- 2 files changed, 102 insertions(+), 62 deletions(-) diff --git a/src/tools/miri/tests/pass/async-drop.rs b/src/tools/miri/tests/pass/async-drop.rs index f16206f3db62..744ffdeebdaf 100644 --- a/src/tools/miri/tests/pass/async-drop.rs +++ b/src/tools/miri/tests/pass/async-drop.rs @@ -11,9 +11,21 @@ use core::mem::{self, ManuallyDrop}; use core::pin::{pin, Pin}; use core::task::{Context, Poll, Waker}; -async fn test_async_drop(x: T) { +async fn test_async_drop(x: T, _size: usize) { let mut x = mem::MaybeUninit::new(x); let dtor = pin!(unsafe { async_drop_in_place(x.as_mut_ptr()) }); + + // FIXME(zetanumbers): This check fully depends on the layout of + // the coroutine state, since async destructor combinators are just + // async functions. + #[cfg(target_pointer_width = "64")] + assert_eq!( + mem::size_of_val(&*dtor), + _size, + "sizes did not match for async destructor of type {}", + core::any::type_name::(), + ); + test_idempotency(dtor).await; } @@ -34,49 +46,58 @@ fn main() { let i = 13; let fut = pin!(async { - test_async_drop(Int(0)).await; - test_async_drop(AsyncInt(0)).await; - test_async_drop([AsyncInt(1), AsyncInt(2)]).await; - test_async_drop((AsyncInt(3), AsyncInt(4))).await; - test_async_drop(5).await; + test_async_drop(Int(0), 16).await; + test_async_drop(AsyncInt(0), 104).await; + test_async_drop([AsyncInt(1), AsyncInt(2)], 152).await; + test_async_drop((AsyncInt(3), AsyncInt(4)), 488).await; + test_async_drop(5, 0).await; let j = 42; - test_async_drop(&i).await; - test_async_drop(&j).await; - test_async_drop(AsyncStruct { b: AsyncInt(8), a: AsyncInt(7), i: 6 }).await; - test_async_drop(ManuallyDrop::new(AsyncInt(9))).await; + test_async_drop(&i, 0).await; + test_async_drop(&j, 0).await; + test_async_drop(AsyncStruct { b: AsyncInt(8), a: AsyncInt(7), i: 6 }, 1688).await; + test_async_drop(ManuallyDrop::new(AsyncInt(9)), 0).await; let foo = AsyncInt(10); - test_async_drop(AsyncReference { foo: &foo }).await; + test_async_drop(AsyncReference { foo: &foo }, 104).await; let foo = AsyncInt(11); - test_async_drop(|| { - black_box(foo); - let foo = AsyncInt(10); - foo - }) + test_async_drop( + || { + black_box(foo); + let foo = AsyncInt(10); + foo + }, + 120, + ) .await; - test_async_drop(AsyncEnum::A(AsyncInt(12))).await; - test_async_drop(AsyncEnum::B(SyncInt(13))).await; + test_async_drop(AsyncEnum::A(AsyncInt(12)), 792).await; + test_async_drop(AsyncEnum::B(SyncInt(13)), 792).await; - test_async_drop(SyncInt(14)).await; - test_async_drop(SyncThenAsync { i: 15, a: AsyncInt(16), b: SyncInt(17), c: AsyncInt(18) }) - .await; + test_async_drop(SyncInt(14), 72).await; + test_async_drop( + SyncThenAsync { i: 15, a: AsyncInt(16), b: SyncInt(17), c: AsyncInt(18) }, + 3512, + ) + .await; let async_drop_fut = pin!(core::future::async_drop(AsyncInt(19))); test_idempotency(async_drop_fut).await; let foo = AsyncInt(20); - test_async_drop(async || { - black_box(foo); - let foo = AsyncInt(19); - // Await point there, but this is async closure so it's fine - black_box(core::future::ready(())).await; - foo - }) + test_async_drop( + async || { + black_box(foo); + let foo = AsyncInt(19); + // Await point there, but this is async closure so it's fine + black_box(core::future::ready(())).await; + foo + }, + 120, + ) .await; - test_async_drop(AsyncUnion { signed: 21 }).await; + test_async_drop(AsyncUnion { signed: 21 }, 32).await; }); let res = fut.poll(&mut cx); assert_eq!(res, Poll::Ready(())); diff --git a/tests/ui/async-await/async-drop.rs b/tests/ui/async-await/async-drop.rs index 6d02dcebc0b6..d1222cd740c3 100644 --- a/tests/ui/async-await/async-drop.rs +++ b/tests/ui/async-await/async-drop.rs @@ -13,9 +13,21 @@ use core::mem::{self, ManuallyDrop}; use core::pin::{pin, Pin}; use core::task::{Context, Poll, Waker}; -async fn test_async_drop(x: T) { +async fn test_async_drop(x: T, _size: usize) { let mut x = mem::MaybeUninit::new(x); let dtor = pin!(unsafe { async_drop_in_place(x.as_mut_ptr()) }); + + // FIXME(zetanumbers): This check fully depends on the layout of + // the coroutine state, since async destructor combinators are just + // async functions. + #[cfg(target_pointer_width = "64")] + assert_eq!( + mem::size_of_val(&*dtor), + _size, + "sizes did not match for async destructor of type {}", + core::any::type_name::(), + ); + test_idempotency(dtor).await; } @@ -36,51 +48,58 @@ fn main() { let i = 13; let fut = pin!(async { - test_async_drop(Int(0)).await; - test_async_drop(AsyncInt(0)).await; - test_async_drop([AsyncInt(1), AsyncInt(2)]).await; - test_async_drop((AsyncInt(3), AsyncInt(4))).await; - test_async_drop(5).await; + test_async_drop(Int(0), 16).await; + test_async_drop(AsyncInt(0), 104).await; + test_async_drop([AsyncInt(1), AsyncInt(2)], 152).await; + test_async_drop((AsyncInt(3), AsyncInt(4)), 488).await; + test_async_drop(5, 0).await; let j = 42; - test_async_drop(&i).await; - test_async_drop(&j).await; - test_async_drop(AsyncStruct { b: AsyncInt(8), a: AsyncInt(7), i: 6 }).await; - test_async_drop(ManuallyDrop::new(AsyncInt(9))).await; + test_async_drop(&i, 0).await; + test_async_drop(&j, 0).await; + test_async_drop(AsyncStruct { b: AsyncInt(8), a: AsyncInt(7), i: 6 }, 1688).await; + test_async_drop(ManuallyDrop::new(AsyncInt(9)), 0).await; let foo = AsyncInt(10); - test_async_drop(AsyncReference { foo: &foo }).await; + test_async_drop(AsyncReference { foo: &foo }, 104).await; let foo = AsyncInt(11); - test_async_drop(|| { - black_box(foo); - let foo = AsyncInt(10); - foo - }).await; + test_async_drop( + || { + black_box(foo); + let foo = AsyncInt(10); + foo + }, + 120, + ) + .await; - test_async_drop(AsyncEnum::A(AsyncInt(12))).await; - test_async_drop(AsyncEnum::B(SyncInt(13))).await; + test_async_drop(AsyncEnum::A(AsyncInt(12)), 792).await; + test_async_drop(AsyncEnum::B(SyncInt(13)), 792).await; - test_async_drop(SyncInt(14)).await; - test_async_drop(SyncThenAsync { - i: 15, - a: AsyncInt(16), - b: SyncInt(17), - c: AsyncInt(18), - }).await; + test_async_drop(SyncInt(14), 72).await; + test_async_drop( + SyncThenAsync { i: 15, a: AsyncInt(16), b: SyncInt(17), c: AsyncInt(18) }, + 3512, + ) + .await; let async_drop_fut = pin!(core::future::async_drop(AsyncInt(19))); test_idempotency(async_drop_fut).await; let foo = AsyncInt(20); - test_async_drop(async || { - black_box(foo); - let foo = AsyncInt(19); - // Await point there, but this is async closure so it's fine - black_box(core::future::ready(())).await; - foo - }).await; + test_async_drop( + async || { + black_box(foo); + let foo = AsyncInt(19); + // Await point there, but this is async closure so it's fine + black_box(core::future::ready(())).await; + foo + }, + 120, + ) + .await; - test_async_drop(AsyncUnion { signed: 21 }).await; + test_async_drop(AsyncUnion { signed: 21 }, 32).await; }); let res = fut.poll(&mut cx); assert_eq!(res, Poll::Ready(())); From a47173c4f77b5e7c960ffe178eba2bc00bb91e31 Mon Sep 17 00:00:00 2001 From: Daria Sukhonina Date: Thu, 2 May 2024 17:59:02 +0300 Subject: [PATCH 068/211] Start implementing needs_async_drop and related --- compiler/rustc_hir_analysis/src/check/mod.rs | 5 + .../src/rmeta/decoder/cstore_impl.rs | 4 + compiler/rustc_middle/src/query/erase.rs | 2 + compiler/rustc_middle/src/query/mod.rs | 17 +- compiler/rustc_middle/src/ty/adt.rs | 10 +- compiler/rustc_middle/src/ty/mod.rs | 9 + compiler/rustc_middle/src/ty/sty.rs | 26 +-- compiler/rustc_middle/src/ty/util.rs | 196 ++++++++++++------ compiler/rustc_ty_utils/src/common_traits.rs | 21 +- compiler/rustc_ty_utils/src/needs_drop.rs | 16 ++ 10 files changed, 196 insertions(+), 110 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 0083da2a1e44..149e7737e309 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -112,6 +112,7 @@ pub fn provide(providers: &mut Providers) { wfcheck::provide(providers); *providers = Providers { adt_destructor, + adt_async_destructor, region_scope_tree, collect_return_position_impl_trait_in_trait_tys, compare_impl_const: compare_impl_item::compare_impl_const_raw, @@ -124,6 +125,10 @@ fn adt_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option tcx.calculate_dtor(def_id.to_def_id(), dropck::check_drop_impl) } +fn adt_async_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option { + tcx.calculate_async_dtor(def_id.to_def_id(), dropck::check_drop_impl) +} + /// Given a `DefId` for an opaque type in return position, find its parent item's return /// expressions. fn get_owner_return_paths( diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 4cad317ce80c..f6b9c7ed9926 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -287,6 +287,10 @@ provide! { tcx, def_id, other, cdata, let _ = cdata; tcx.calculate_dtor(def_id, |_,_| Ok(())) } + adt_async_destructor => { + let _ = cdata; + tcx.calculate_async_dtor(def_id, |_,_| Ok(())) + } associated_item_def_ids => { tcx.arena.alloc_from_iter(cdata.get_associated_item_or_field_def_ids(def_id.index)) } diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 1e36f034cc22..f98dbf8a0bd4 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -238,6 +238,7 @@ trivial! { Option, Option, Option, + Option, Option, Option, Option, @@ -295,6 +296,7 @@ trivial! { rustc_middle::ty::AssocItem, rustc_middle::ty::AssocItemContainer, rustc_middle::ty::Asyncness, + rustc_middle::ty::AsyncDestructor, rustc_middle::ty::BoundVariableKind, rustc_middle::ty::DeducedParamAttrs, rustc_middle::ty::Destructor, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 6ad4b7c40fb2..d72ad09f9548 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -703,6 +703,11 @@ rustc_queries! { cache_on_disk_if { key.is_local() } separate_provide_extern } + query adt_async_destructor(key: DefId) -> Option { + desc { |tcx| "computing `AsyncDrop` impl for `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + separate_provide_extern + } query adt_sized_constraint(key: DefId) -> Option>> { desc { |tcx| "computing the `Sized` constraint for `{}`", tcx.def_path_str(key) } @@ -1343,18 +1348,14 @@ rustc_queries! { query is_unpin_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` is `Unpin`", env.value } } - /// Query backing `Ty::has_surface_async_drop`. - query has_surface_async_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { - desc { "computing whether `{}` has `AsyncDrop` implementation", env.value } - } - /// Query backing `Ty::has_surface_drop`. - query has_surface_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { - desc { "computing whether `{}` has `Drop` implementation", env.value } - } /// Query backing `Ty::needs_drop`. query needs_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` needs drop", env.value } } + /// Query backing `Ty::needs_async_drop`. + query needs_async_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { + desc { "computing whether `{}` needs async drop", env.value } + } /// Query backing `Ty::has_significant_drop_raw`. query has_significant_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` has a significant drop", env.value } diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index 8e946bc8b314..988ce35484d5 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -24,7 +24,9 @@ use std::hash::{Hash, Hasher}; use std::ops::Range; use std::str; -use super::{Destructor, FieldDef, GenericPredicates, Ty, TyCtxt, VariantDef, VariantDiscr}; +use super::{ + AsyncDestructor, Destructor, FieldDef, GenericPredicates, Ty, TyCtxt, VariantDef, VariantDiscr, +}; #[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)] pub struct AdtFlags(u16); @@ -577,6 +579,12 @@ impl<'tcx> AdtDef<'tcx> { tcx.adt_destructor(self.did()) } + // FIXME(zetanumbers): consider supporting this method in same places where + // `destructor` is referenced + pub fn async_destructor(self, tcx: TyCtxt<'tcx>) -> Option { + tcx.adt_async_destructor(self.did()) + } + /// Returns a type such that `Self: Sized` if and only if that type is `Sized`, /// or `None` if the type is always sized. pub fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> Option>> { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index f24074cb472d..90c154233dab 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1172,6 +1172,15 @@ pub struct Destructor { pub constness: hir::Constness, } +// FIXME: consider combining this definition with regular `Destructor` +#[derive(Copy, Clone, Debug, HashStable, Encodable, Decodable)] +pub struct AsyncDestructor { + /// The `DefId` of the async destructor future constructor + pub ctor: DefId, + /// The `DefId` of the async destructor future type + pub future: DefId, +} + #[derive(Clone, Copy, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] pub struct VariantFlags(u8); bitflags::bitflags! { diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 5cf96d298375..00f603a88189 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1991,7 +1991,7 @@ impl<'tcx> Ty<'tcx> { ty::Adt(adt_def, _) => { assert!(adt_def.is_union()); - let surface_drop = self.surface_async_dropper_ty(tcx, param_env).unwrap(); + let surface_drop = self.surface_async_dropper_ty(tcx).unwrap(); Ty::async_destructor_combinator(tcx, LangItem::AsyncDropFuse) .instantiate(tcx, &[surface_drop.into()]) @@ -2041,7 +2041,7 @@ impl<'tcx> Ty<'tcx> { }) .unwrap(); - let dtor = if let Some(dropper_ty) = self.surface_async_dropper_ty(tcx, param_env) { + let dtor = if let Some(dropper_ty) = self.surface_async_dropper_ty(tcx) { Ty::async_destructor_combinator(tcx, LangItem::AsyncDropChain) .instantiate(tcx, &[dropper_ty.into(), variants_dtor.into()]) } else { @@ -2052,21 +2052,13 @@ impl<'tcx> Ty<'tcx> { .instantiate(tcx, &[dtor.into()]) } - fn surface_async_dropper_ty( - self, - tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, - ) -> Option> { - if self.has_surface_async_drop(tcx, param_env) { - Some(LangItem::SurfaceAsyncDropInPlace) - } else if self.has_surface_drop(tcx, param_env) { - Some(LangItem::AsyncDropSurfaceDropInPlace) - } else { - None - } - .map(|dropper| { - Ty::async_destructor_combinator(tcx, dropper).instantiate(tcx, &[self.into()]) - }) + fn surface_async_dropper_ty(self, tcx: TyCtxt<'tcx>) -> Option> { + let adt_def = self.ty_adt_def()?; + let dropper = adt_def + .async_destructor(tcx) + .map(|_| LangItem::SurfaceAsyncDropInPlace) + .or_else(|| adt_def.destructor(tcx).map(|_| LangItem::AsyncDropSurfaceDropInPlace))?; + Some(Ty::async_destructor_combinator(tcx, dropper).instantiate(tcx, &[self.into()])) } fn async_destructor_combinator( diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index cacaa859d526..905ada3832d5 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -4,8 +4,8 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::query::{IntoQueryParam, Providers}; use crate::ty::layout::{FloatExt, IntegerExt}; use crate::ty::{ - self, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, - TypeVisitableExt, Upcast, + self, Asyncness, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, + TypeSuperFoldable, TypeVisitableExt, Upcast, }; use crate::ty::{GenericArgKind, GenericArgsRef}; use rustc_apfloat::Float as _; @@ -382,6 +382,45 @@ impl<'tcx> TyCtxt<'tcx> { Some(ty::Destructor { did, constness }) } + /// Calculate the async destructor of a given type. + pub fn calculate_async_dtor( + self, + adt_did: DefId, + validate: impl Fn(Self, DefId) -> Result<(), ErrorGuaranteed>, + ) -> Option { + let async_drop_trait = self.lang_items().async_drop_trait()?; + self.ensure().coherent_trait(async_drop_trait).ok()?; + + let ty = self.type_of(adt_did).instantiate_identity(); + let mut dtor_candidate = None; + self.for_each_relevant_impl(async_drop_trait, ty, |impl_did| { + if validate(self, impl_did).is_err() { + // Already `ErrorGuaranteed`, no need to delay a span bug here. + return; + } + + let [future, ctor] = self.associated_item_def_ids(impl_did) else { + self.dcx().span_delayed_bug( + self.def_span(impl_did), + "AsyncDrop impl without async_drop function or Dropper type", + ); + return; + }; + + if let Some((_, _, old_impl_did)) = dtor_candidate { + self.dcx() + .struct_span_err(self.def_span(impl_did), "multiple async drop impls found") + .with_span_note(self.def_span(old_impl_did), "other impl here") + .delay_as_bug(); + } + + dtor_candidate = Some((*future, *ctor, impl_did)); + }); + + let (future, ctor, _) = dtor_candidate?; + Some(ty::AsyncDestructor { future, ctor }) + } + /// Returns the set of types that are required to be alive in /// order to run the destructor of `def` (see RFCs 769 and /// 1238). @@ -1303,72 +1342,19 @@ impl<'tcx> Ty<'tcx> { } } - /// Checks whether values of this type `T` implements the `AsyncDrop` - /// trait. - pub fn has_surface_async_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { - self.could_have_surface_async_drop() && tcx.has_surface_async_drop_raw(param_env.and(self)) - } - - /// Fast path helper for testing if a type has `AsyncDrop` - /// implementation. - /// - /// Returning `false` means the type is known to not have `AsyncDrop` - /// implementation. Returning `true` means nothing -- could be - /// `AsyncDrop`, might not be. - fn could_have_surface_async_drop(self) -> bool { - !self.is_async_destructor_trivially_noop() - && !matches!( - self.kind(), - ty::Tuple(_) - | ty::Slice(_) - | ty::Array(_, _) - | ty::Closure(..) - | ty::CoroutineClosure(..) - | ty::Coroutine(..) - ) - } - - /// Checks whether values of this type `T` implements the `Drop` - /// trait. - pub fn has_surface_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { - self.could_have_surface_drop() && tcx.has_surface_drop_raw(param_env.and(self)) - } - - /// Fast path helper for testing if a type has `Drop` implementation. - /// - /// Returning `false` means the type is known to not have `Drop` - /// implementation. Returning `true` means nothing -- could be - /// `Drop`, might not be. - fn could_have_surface_drop(self) -> bool { - !self.is_async_destructor_trivially_noop() - && !matches!( - self.kind(), - ty::Tuple(_) - | ty::Slice(_) - | ty::Array(_, _) - | ty::Closure(..) - | ty::CoroutineClosure(..) - | ty::Coroutine(..) - ) - } - /// Checks whether values of this type `T` implement has noop async destructor. // // FIXME: implement optimization to make ADTs, which do not need drop, - // to skip fields or to have noop async destructor. + // to skip fields or to have noop async destructor, use `needs_(async_)drop` pub fn is_async_destructor_noop( self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> bool { + // TODO: check on the most generic version of your type self.is_async_destructor_trivially_noop() - || if let ty::Adt(adt_def, _) = self.kind() { - (adt_def.is_union() || adt_def.is_payloadfree()) - && !self.has_surface_async_drop(tcx, param_env) - && !self.has_surface_drop(tcx, param_env) - } else { - false - } + || self.needs_async_drop(tcx, param_env) + || self.needs_drop(tcx, param_env) } /// Fast path helper for testing if a type has noop async destructor. @@ -1391,7 +1377,34 @@ impl<'tcx> Ty<'tcx> { | ty::FnPtr(_) => true, ty::Tuple(tys) => tys.is_empty(), ty::Adt(adt_def, _) => adt_def.is_manually_drop(), - _ => false, + ty::Bool => todo!(), + ty::Char => todo!(), + ty::Int(_) => todo!(), + ty::Uint(_) => todo!(), + ty::Float(_) => todo!(), + ty::Adt(_, _) => todo!(), + ty::Foreign(_) => todo!(), + ty::Str => todo!(), + ty::Array(_, _) => todo!(), + ty::Pat(_, _) => todo!(), + ty::Slice(_) => todo!(), + ty::RawPtr(_, _) => todo!(), + ty::Ref(_, _, _) => todo!(), + ty::FnDef(_, _) => todo!(), + ty::FnPtr(_) => todo!(), + ty::Dynamic(_, _, _) => todo!(), + ty::Closure(_, _) => todo!(), + ty::CoroutineClosure(_, _) => todo!(), + ty::Coroutine(_, _) => todo!(), + ty::CoroutineWitness(_, _) => todo!(), + ty::Never => todo!(), + ty::Tuple(_) => todo!(), + ty::Alias(_, _) => todo!(), + ty::Param(_) => todo!(), + ty::Bound(_, _) => todo!(), + ty::Placeholder(_) => todo!(), + ty::Infer(_) => todo!(), + ty::Error(_) => todo!(), } } @@ -1430,6 +1443,42 @@ impl<'tcx> Ty<'tcx> { } } + /// If `ty.needs_async_drop(...)` returns `true`, then `ty` is definitely + /// non-copy and *might* have a async destructor attached; if it returns + /// `false`, then `ty` definitely has no async destructor (i.e., no async + /// drop glue). + /// + /// (Note that this implies that if `ty` has an async destructor attached, + /// then `needs_async_drop` will definitely return `true` for `ty`.) + /// + /// Note that this method is used to check eligible types in unions. + #[inline] + pub fn needs_async_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { + // Avoid querying in simple cases. + match needs_drop_components(tcx, self) { + Err(AlwaysRequiresDrop) => true, + Ok(components) => { + let query_ty = match *components { + [] => return false, + // If we've got a single component, call the query with that + // to increase the chance that we hit the query cache. + [component_ty] => component_ty, + _ => self, + }; + + // This doesn't depend on regions, so try to minimize distinct + // query keys used. + // If normalization fails, we just use `query_ty`. + debug_assert!(!param_env.has_infer()); + let query_ty = tcx + .try_normalize_erasing_regions(param_env, query_ty) + .unwrap_or_else(|_| tcx.erase_regions(query_ty)); + + tcx.needs_async_drop_raw(param_env.and(query_ty)) + } + } + } + /// Checks if `ty` has a significant drop. /// /// Note that this method can return false even if `ty` has a destructor @@ -1598,12 +1647,24 @@ impl<'tcx> ExplicitSelf<'tcx> { } } +// FIXME(zetanumbers): make specifying asyncness explicit /// Returns a list of types such that the given type needs drop if and only if /// *any* of the returned types need drop. Returns `Err(AlwaysRequiresDrop)` if /// this type always needs drop. pub fn needs_drop_components<'tcx>( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, +) -> Result; 2]>, AlwaysRequiresDrop> { + needs_drop_components_with_async(tcx, ty, Asyncness::No) +} + +/// Returns a list of types such that the given type needs drop if and only if +/// *any* of the returned types need drop. Returns `Err(AlwaysRequiresDrop)` if +/// this type always needs drop. +pub fn needs_drop_components_with_async<'tcx>( + tcx: TyCtxt<'tcx>, + ty: Ty<'tcx>, + asyncness: Asyncness, ) -> Result; 2]>, AlwaysRequiresDrop> { match *ty.kind() { ty::Infer(ty::FreshIntTy(_)) @@ -1623,11 +1684,18 @@ pub fn needs_drop_components<'tcx>( // Foreign types can never have destructors. ty::Foreign(..) => Ok(SmallVec::new()), - ty::Dynamic(..) | ty::Error(_) => Err(AlwaysRequiresDrop), + // FIXME(zetanumbers): Temporary workaround for async drop of dynamic types + ty::Dynamic(..) | ty::Error(_) => { + if asyncness.is_async() { + Ok(SmallVec::new()) + } else { + Err(AlwaysRequiresDrop) + } + } - ty::Pat(ty, _) | ty::Slice(ty) => needs_drop_components(tcx, ty), + ty::Pat(ty, _) | ty::Slice(ty) => needs_drop_components_with_async(tcx, ty, asyncness), ty::Array(elem_ty, size) => { - match needs_drop_components(tcx, elem_ty) { + match needs_drop_components_with_async(tcx, elem_ty, asyncness) { Ok(v) if v.is_empty() => Ok(v), res => match size.try_to_target_usize(tcx) { // Arrays of size zero don't need drop, even if their element @@ -1643,7 +1711,7 @@ pub fn needs_drop_components<'tcx>( } // If any field needs drop, then the whole tuple does. ty::Tuple(fields) => fields.iter().try_fold(SmallVec::new(), move |mut acc, elem| { - acc.extend(needs_drop_components(tcx, elem)?); + acc.extend(needs_drop_components_with_async(tcx, elem, asyncness)?); Ok(acc) }), diff --git a/compiler/rustc_ty_utils/src/common_traits.rs b/compiler/rustc_ty_utils/src/common_traits.rs index cb95239e9919..51b908881eb4 100644 --- a/compiler/rustc_ty_utils/src/common_traits.rs +++ b/compiler/rustc_ty_utils/src/common_traits.rs @@ -22,17 +22,6 @@ fn is_unpin_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) is_item_raw(tcx, query, LangItem::Unpin) } -fn has_surface_async_drop_raw<'tcx>( - tcx: TyCtxt<'tcx>, - query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, -) -> bool { - is_item_raw(tcx, query, LangItem::AsyncDrop) -} - -fn has_surface_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { - is_item_raw(tcx, query, LangItem::Drop) -} - fn is_item_raw<'tcx>( tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, @@ -45,13 +34,5 @@ fn is_item_raw<'tcx>( } pub(crate) fn provide(providers: &mut Providers) { - *providers = Providers { - is_copy_raw, - is_sized_raw, - is_freeze_raw, - is_unpin_raw, - has_surface_async_drop_raw, - has_surface_drop_raw, - ..*providers - }; + *providers = Providers { is_copy_raw, is_sized_raw, is_freeze_raw, is_unpin_raw, ..*providers }; } diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index 72ee1a482495..7fc3543ff66a 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -30,6 +30,21 @@ fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx> res } +fn needs_async_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { + // If we don't know a type doesn't need async drop, for example if it's a + // type parameter without a `Copy` bound, then we conservatively return that + // it needs async drop. + let adt_has_async_dtor = + |adt_def: ty::AdtDef<'tcx>| adt_def.async_destructor(tcx).map(|_| DtorType::Significant); + let res = drop_tys_helper(tcx, query.value, query.param_env, adt_has_dtor, false) + .filter(filter_array_elements(tcx, query.param_env)) + .next() + .is_some(); + + debug!("needs_drop_raw({:?}) = {:?}", query, res); + res +} + /// HACK: in order to not mistakenly assume that `[PhantomData; N]` requires drop glue /// we check the element type for drop glue. The correct fix would be looking at the /// entirety of the code around `needs_drop_components` and this file and come up with @@ -389,6 +404,7 @@ fn adt_significant_drop_tys( pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { needs_drop_raw, + needs_async_drop_raw, has_significant_drop_raw, adt_drop_tys, adt_significant_drop_tys, From 7cdd95e1a683c89baff762a6c7755951bcd32717 Mon Sep 17 00:00:00 2001 From: Daria Sukhonina Date: Fri, 3 May 2024 15:47:23 +0300 Subject: [PATCH 069/211] Optimize async drop glue for some old types --- compiler/rustc_hir/src/lang_items.rs | 1 + compiler/rustc_middle/src/ty/adt.rs | 4 +- compiler/rustc_middle/src/ty/sty.rs | 48 +++--- compiler/rustc_middle/src/ty/util.rs | 139 +++++++++++------- .../src/shim/async_destructor_ctor.rs | 37 ++++- compiler/rustc_span/src/symbol.rs | 1 + .../src/solve/normalizes_to/mod.rs | 2 +- .../src/traits/project.rs | 2 +- compiler/rustc_ty_utils/src/instance.rs | 3 +- compiler/rustc_ty_utils/src/needs_drop.rs | 2 +- library/core/src/future/async_drop.rs | 11 ++ 11 files changed, 161 insertions(+), 89 deletions(-) diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index c4be67cdd887..4c9d143a63b9 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -176,6 +176,7 @@ language_item_table! { AsyncDropSlice, sym::async_drop_slice, async_drop_slice_fn, Target::Fn, GenericRequirement::Exact(1); AsyncDropChain, sym::async_drop_chain, async_drop_chain_fn, Target::Fn, GenericRequirement::Exact(2); AsyncDropNoop, sym::async_drop_noop, async_drop_noop_fn, Target::Fn, GenericRequirement::Exact(0); + AsyncDropDeferredDropInPlace, sym::async_drop_deferred_drop_in_place, async_drop_deferred_drop_in_place_fn, Target::Fn, GenericRequirement::Exact(1); AsyncDropFuse, sym::async_drop_fuse, async_drop_fuse_fn, Target::Fn, GenericRequirement::Exact(1); AsyncDropDefer, sym::async_drop_defer, async_drop_defer_fn, Target::Fn, GenericRequirement::Exact(1); AsyncDropEither, sym::async_drop_either, async_drop_either_fn, Target::Fn, GenericRequirement::Exact(3); diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index 988ce35484d5..5f9b870331c9 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -579,8 +579,8 @@ impl<'tcx> AdtDef<'tcx> { tcx.adt_destructor(self.did()) } - // FIXME(zetanumbers): consider supporting this method in same places where - // `destructor` is referenced + // FIXME: consider combining this method with `AdtDef::destructor` and removing + // this version pub fn async_destructor(self, tcx: TyCtxt<'tcx>) -> Option { tcx.adt_async_destructor(self.did()) } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 00f603a88189..5f7385fccc98 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -25,7 +25,7 @@ use std::assert_matches::debug_assert_matches; use std::borrow::Cow; use std::iter; use std::ops::{ControlFlow, Range}; -use ty::util::IntTypeExt; +use ty::util::{AsyncDropGlueMorphology, IntTypeExt}; use rustc_type_ir::TyKind::*; use rustc_type_ir::{self as ir, BoundVar, CollectAndApply, DynKind}; @@ -1951,11 +1951,22 @@ impl<'tcx> Ty<'tcx> { } /// Returns the type of the async destructor of this type. - pub fn async_destructor_ty(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Ty<'tcx> { - if self.is_async_destructor_noop(tcx, param_env) || matches!(self.kind(), ty::Error(_)) { - return Ty::async_destructor_combinator(tcx, LangItem::AsyncDropNoop) - .instantiate_identity(); + pub fn async_destructor_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + match self.async_drop_glue_morphology(tcx) { + AsyncDropGlueMorphology::Noop => { + return Ty::async_destructor_combinator(tcx, LangItem::AsyncDropNoop) + .instantiate_identity(); + } + AsyncDropGlueMorphology::DeferredDropInPlace => { + let drop_in_place = + Ty::async_destructor_combinator(tcx, LangItem::AsyncDropDeferredDropInPlace) + .instantiate(tcx, &[self.into()]); + return Ty::async_destructor_combinator(tcx, LangItem::AsyncDropFuse) + .instantiate(tcx, &[drop_in_place.into()]); + } + AsyncDropGlueMorphology::Custom => (), } + match *self.kind() { ty::Param(_) | ty::Alias(..) | ty::Infer(ty::TyVar(_)) => { let assoc_items = tcx @@ -1974,19 +1985,13 @@ impl<'tcx> Ty<'tcx> { .adt_async_destructor_ty( tcx, adt_def.variants().iter().map(|v| v.fields.iter().map(|f| f.ty(tcx, args))), - param_env, ), - ty::Tuple(tys) => self.adt_async_destructor_ty(tcx, iter::once(tys), param_env), - ty::Closure(_, args) => self.adt_async_destructor_ty( - tcx, - iter::once(args.as_closure().upvar_tys()), - param_env, - ), - ty::CoroutineClosure(_, args) => self.adt_async_destructor_ty( - tcx, - iter::once(args.as_coroutine_closure().upvar_tys()), - param_env, - ), + ty::Tuple(tys) => self.adt_async_destructor_ty(tcx, iter::once(tys)), + ty::Closure(_, args) => { + self.adt_async_destructor_ty(tcx, iter::once(args.as_closure().upvar_tys())) + } + ty::CoroutineClosure(_, args) => self + .adt_async_destructor_ty(tcx, iter::once(args.as_coroutine_closure().upvar_tys())), ty::Adt(adt_def, _) => { assert!(adt_def.is_union()); @@ -2008,17 +2013,12 @@ impl<'tcx> Ty<'tcx> { } } - fn adt_async_destructor_ty( - self, - tcx: TyCtxt<'tcx>, - variants: I, - param_env: ParamEnv<'tcx>, - ) -> Ty<'tcx> + fn adt_async_destructor_ty(self, tcx: TyCtxt<'tcx>, variants: I) -> Ty<'tcx> where I: Iterator + ExactSizeIterator, I::Item: IntoIterator>, { - debug_assert!(!self.is_async_destructor_noop(tcx, param_env)); + debug_assert_eq!(self.async_drop_glue_morphology(tcx), AsyncDropGlueMorphology::Custom); let defer = Ty::async_destructor_combinator(tcx, LangItem::AsyncDropDefer); let chain = Ty::async_destructor_combinator(tcx, LangItem::AsyncDropChain); diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 905ada3832d5..2f2d03e9ec84 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -421,6 +421,25 @@ impl<'tcx> TyCtxt<'tcx> { Some(ty::AsyncDestructor { future, ctor }) } + /// Returns async drop glue morphology for a definition. To get async drop + /// glue morphology for a type see [`Ty::async_drop_glue_morphology`]. + // + // FIXME: consider making this a query + pub fn async_drop_glue_morphology(self, did: DefId) -> AsyncDropGlueMorphology { + let ty: Ty<'tcx> = self.type_of(did).instantiate_identity(); + + // Async drop glue morphology is an internal detail, so reveal_all probably + // should be fine + let param_env = ty::ParamEnv::reveal_all(); + if ty.needs_async_drop(self, param_env) { + AsyncDropGlueMorphology::Custom + } else if ty.needs_drop(self, param_env) { + AsyncDropGlueMorphology::DeferredDropInPlace + } else { + AsyncDropGlueMorphology::Noop + } + } + /// Returns the set of types that are required to be alive in /// order to run the destructor of `def` (see RFCs 769 and /// 1238). @@ -1177,6 +1196,18 @@ impl<'tcx> TypeFolder> for WeakAliasTypeExpander<'tcx> { } } +/// Indicates the form of `AsyncDestruct::Destructor`. Used to simplify async +/// drop glue for types not using async drop. +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub enum AsyncDropGlueMorphology { + /// Async destructor simply does nothing + Noop, + /// Async destructor simply runs `drop_in_place` + DeferredDropInPlace, + /// Async destructor has custom logic + Custom, +} + impl<'tcx> Ty<'tcx> { /// Returns the `Size` for primitive types (bool, uint, int, char, float). pub fn primitive_size(self, tcx: TyCtxt<'tcx>) -> Size { @@ -1342,27 +1373,16 @@ impl<'tcx> Ty<'tcx> { } } - /// Checks whether values of this type `T` implement has noop async destructor. + /// Get morphology of the async drop glue, needed for types which do not + /// use async drop. To get async drop glue morphology for a definition see + /// [`TyCtxt::async_drop_glue_morphology`]. Used for `AsyncDestruct::Destructor` + /// type construction. // - // FIXME: implement optimization to make ADTs, which do not need drop, - // to skip fields or to have noop async destructor, use `needs_(async_)drop` - pub fn is_async_destructor_noop( - self, - tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, - ) -> bool { - // TODO: check on the most generic version of your type - self.is_async_destructor_trivially_noop() - || self.needs_async_drop(tcx, param_env) - || self.needs_drop(tcx, param_env) - } - - /// Fast path helper for testing if a type has noop async destructor. - /// - /// Returning `true` means the type is known to have noop async destructor - /// implementation. Returning `true` means nothing -- could be - /// `Drop`, might not be. - fn is_async_destructor_trivially_noop(self) -> bool { + // FIXME: implement optimization to not instantiate a certain morphology of + // async drop glue too soon to allow per type optimizations, see array case + // for more info. Perhaps then remove this method and use `needs_(async_)drop` + // instead. + pub fn async_drop_glue_morphology(self, tcx: TyCtxt<'tcx>) -> AsyncDropGlueMorphology { match self.kind() { ty::Int(_) | ty::Uint(_) @@ -1374,37 +1394,43 @@ impl<'tcx> Ty<'tcx> { | ty::Ref(..) | ty::RawPtr(..) | ty::FnDef(..) - | ty::FnPtr(_) => true, - ty::Tuple(tys) => tys.is_empty(), - ty::Adt(adt_def, _) => adt_def.is_manually_drop(), - ty::Bool => todo!(), - ty::Char => todo!(), - ty::Int(_) => todo!(), - ty::Uint(_) => todo!(), - ty::Float(_) => todo!(), - ty::Adt(_, _) => todo!(), - ty::Foreign(_) => todo!(), - ty::Str => todo!(), - ty::Array(_, _) => todo!(), - ty::Pat(_, _) => todo!(), - ty::Slice(_) => todo!(), - ty::RawPtr(_, _) => todo!(), - ty::Ref(_, _, _) => todo!(), - ty::FnDef(_, _) => todo!(), - ty::FnPtr(_) => todo!(), - ty::Dynamic(_, _, _) => todo!(), - ty::Closure(_, _) => todo!(), - ty::CoroutineClosure(_, _) => todo!(), - ty::Coroutine(_, _) => todo!(), - ty::CoroutineWitness(_, _) => todo!(), - ty::Never => todo!(), - ty::Tuple(_) => todo!(), - ty::Alias(_, _) => todo!(), - ty::Param(_) => todo!(), - ty::Bound(_, _) => todo!(), - ty::Placeholder(_) => todo!(), - ty::Infer(_) => todo!(), - ty::Error(_) => todo!(), + | ty::FnPtr(_) + | ty::Infer(ty::FreshIntTy(_)) + | ty::Infer(ty::FreshFloatTy(_)) => AsyncDropGlueMorphology::Noop, + + ty::Tuple(tys) if tys.is_empty() => AsyncDropGlueMorphology::Noop, + ty::Adt(adt_def, _) if adt_def.is_manually_drop() => AsyncDropGlueMorphology::Noop, + + // Foreign types can never have destructors. + ty::Foreign(_) => AsyncDropGlueMorphology::Noop, + + // FIXME: implement dynamic types async drops + ty::Error(_) | ty::Dynamic(..) => AsyncDropGlueMorphology::DeferredDropInPlace, + + ty::Tuple(_) | ty::Array(_, _) | ty::Slice(_) => { + // Assume worst-case scenario, because we can instantiate async + // destructors in different orders: + // + // 1. Instantiate [T; N] with T = String and N = 0 + // 2. Instantiate <[String; 0] as AsyncDestruct>::Destructor + // + // And viceversa, thus we cannot rely on String not using async + // drop or array having zero (0) elements + AsyncDropGlueMorphology::Custom + } + ty::Pat(ty, _) => ty.async_drop_glue_morphology(tcx), + + ty::Adt(adt_def, _) => tcx.async_drop_glue_morphology(adt_def.did()), + + ty::Closure(did, _) + | ty::CoroutineClosure(did, _) + | ty::Coroutine(did, _) + | ty::CoroutineWitness(did, _) => tcx.async_drop_glue_morphology(*did), + + ty::Alias(..) | ty::Param(_) | ty::Bound(..) | ty::Placeholder(..) | ty::Infer(_) => { + // No specifics, but would usually mean forwarding async drop glue + AsyncDropGlueMorphology::Custom + } } } @@ -1451,7 +1477,11 @@ impl<'tcx> Ty<'tcx> { /// (Note that this implies that if `ty` has an async destructor attached, /// then `needs_async_drop` will definitely return `true` for `ty`.) /// - /// Note that this method is used to check eligible types in unions. + /// When constructing `AsyncDestruct::Destructor` type, use + /// [`Ty::async_drop_glue_morphology`] instead. + // + // FIXME(zetanumbers): Note that this method is used to check eligible types + // in unions. #[inline] pub fn needs_async_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { // Avoid querying in simple cases. @@ -1647,10 +1677,13 @@ impl<'tcx> ExplicitSelf<'tcx> { } } -// FIXME(zetanumbers): make specifying asyncness explicit /// Returns a list of types such that the given type needs drop if and only if /// *any* of the returned types need drop. Returns `Err(AlwaysRequiresDrop)` if /// this type always needs drop. +// +// FIXME(zetanumbers): consider replacing this with only +// `needs_drop_components_with_async` +#[inline] pub fn needs_drop_components<'tcx>( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, 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 f4481c22fc1f..aa9c87d8f80d 100644 --- a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs +++ b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs @@ -12,7 +12,7 @@ use rustc_middle::mir::{ Terminator, TerminatorKind, UnwindAction, UnwindTerminateReason, RETURN_PLACE, }; use rustc_middle::ty::adjustment::PointerCoercion; -use rustc_middle::ty::util::Discr; +use rustc_middle::ty::util::{AsyncDropGlueMorphology, Discr}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_span::source_map::respan; @@ -116,15 +116,25 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> { } fn build(self) -> Body<'tcx> { - let (tcx, def_id, Some(self_ty)) = (self.tcx, self.def_id, self.self_ty) else { + let (tcx, Some(self_ty)) = (self.tcx, self.self_ty) else { return self.build_zst_output(); }; + match self_ty.async_drop_glue_morphology(tcx) { + AsyncDropGlueMorphology::Noop => span_bug!( + self.span, + "async drop glue shim generator encountered type with noop async drop glue morphology" + ), + AsyncDropGlueMorphology::DeferredDropInPlace => { + return self.build_deferred_drop_in_place(); + } + AsyncDropGlueMorphology::Custom => (), + } let surface_drop_kind = || { - let param_env = tcx.param_env_reveal_all_normalized(def_id); - if self_ty.has_surface_async_drop(tcx, param_env) { + let adt_def = self_ty.ty_adt_def()?; + if adt_def.async_destructor(tcx).is_some() { Some(SurfaceDropKind::Async) - } else if self_ty.has_surface_drop(tcx, param_env) { + } else if adt_def.destructor(tcx).is_some() { Some(SurfaceDropKind::Sync) } else { None @@ -267,6 +277,13 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> { self.return_() } + fn build_deferred_drop_in_place(mut self) -> Body<'tcx> { + self.put_self(); + let deferred = self.combine_deferred_drop_in_place(); + self.combine_fuse(deferred); + self.return_() + } + fn build_fused_async_surface(mut self) -> Body<'tcx> { self.put_self(); let surface = self.combine_async_surface(); @@ -441,6 +458,14 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> { ) } + fn combine_deferred_drop_in_place(&mut self) -> Ty<'tcx> { + self.apply_combinator( + 1, + LangItem::AsyncDropDeferredDropInPlace, + &[self.self_ty.unwrap().into()], + ) + } + fn combine_fuse(&mut self, inner_future_ty: Ty<'tcx>) -> Ty<'tcx> { self.apply_combinator(1, LangItem::AsyncDropFuse, &[inner_future_ty.into()]) } @@ -481,7 +506,7 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> { if let Some(ty) = self.self_ty { debug_assert_eq!( output.ty(&self.locals, self.tcx), - ty.async_destructor_ty(self.tcx, self.param_env), + ty.async_destructor_ty(self.tcx), "output async destructor types did not match for type: {ty:?}", ); } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 90da220b3f54..f771b4686902 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -430,6 +430,7 @@ symbols! { async_drop, async_drop_chain, async_drop_defer, + async_drop_deferred_drop_in_place, async_drop_either, async_drop_fuse, async_drop_in_place, diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs index 7fd2a3801cc4..9d4c03375fe8 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs @@ -839,7 +839,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { | ty::Str | ty::Slice(_) | ty::Tuple(_) - | ty::Error(_) => self_ty.async_destructor_ty(ecx.interner(), goal.param_env), + | ty::Error(_) => self_ty.async_destructor_ty(ecx.interner()), // We do not call `Ty::async_destructor_ty` on alias, param, or placeholder // types, which return `::AsyncDestructor` diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 87c8b1cda504..0f8b003c0778 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1560,7 +1560,7 @@ fn confirm_builtin_candidate<'cx, 'tcx>( let destructor_def_id = tcx.associated_item_def_ids(trait_def_id)[0]; assert_eq!(destructor_def_id, item_def_id); - (self_ty.async_destructor_ty(tcx, obligation.param_env).into(), Vec::new()) + (self_ty.async_destructor_ty(tcx).into(), Vec::new()) } else if lang_items.pointee_trait() == Some(trait_def_id) { let metadata_def_id = tcx.require_lang_item(LangItem::Metadata, None); assert_eq!(metadata_def_id, item_def_id); diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 0d089205c1ec..e4dcea785d41 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -4,6 +4,7 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::bug; use rustc_middle::query::Providers; use rustc_middle::traits::{BuiltinImplSource, CodegenObligationError}; +use rustc_middle::ty::util::AsyncDropGlueMorphology; use rustc_middle::ty::GenericArgsRef; use rustc_middle::ty::{self, Instance, TyCtxt, TypeVisitableExt}; use rustc_span::sym; @@ -59,7 +60,7 @@ fn resolve_instance<'tcx>( } else if Some(def_id) == tcx.lang_items().async_drop_in_place_fn() { let ty = args.type_at(0); - if !ty.is_async_destructor_noop(tcx, param_env) { + if ty.async_drop_glue_morphology(tcx) != AsyncDropGlueMorphology::Noop { match *ty.kind() { ty::Closure(..) | ty::CoroutineClosure(..) diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index 7fc3543ff66a..205b3f2760f3 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -36,7 +36,7 @@ fn needs_async_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty // it needs async drop. let adt_has_async_dtor = |adt_def: ty::AdtDef<'tcx>| adt_def.async_destructor(tcx).map(|_| DtorType::Significant); - let res = drop_tys_helper(tcx, query.value, query.param_env, adt_has_dtor, false) + let res = drop_tys_helper(tcx, query.value, query.param_env, adt_has_async_dtor, false) .filter(filter_array_elements(tcx, query.param_env)) .next() .is_some(); diff --git a/library/core/src/future/async_drop.rs b/library/core/src/future/async_drop.rs index 0eb8d7bb3289..ea7e2f52ba1d 100644 --- a/library/core/src/future/async_drop.rs +++ b/library/core/src/future/async_drop.rs @@ -161,6 +161,11 @@ async unsafe fn surface_drop_in_place(ptr: *mut T) { /// wrapped future completes by returning `Poll::Ready(())` on poll. This /// is useful for constructing async destructors to guarantee this /// "fuse" property +// +// FIXME: Consider optimizing combinators to not have to use fuse in majority +// of cases, perhaps by adding `#[(rustc_)idempotent(_future)]` attribute for +// async functions and blocks with the unit return type. However current layout +// optimizations currently encode `None` case into the async block's discriminant. struct Fuse { inner: Option, } @@ -251,6 +256,12 @@ async unsafe fn either, M: IntoFuture, T } } +#[cfg(not(bootstrap))] +#[lang = "async_drop_deferred_drop_in_place"] +async unsafe fn deferred_drop_in_place(to_drop: *mut T) { + unsafe { crate::ptr::drop_in_place(to_drop) } +} + /// Used for noop async destructors. We don't use [`core::future::Ready`] /// because it panics after its second poll, which could be potentially /// bad if that would happen during the cleanup. From 2892302aef73715678f604ccbbf8e371bdf0ab4e Mon Sep 17 00:00:00 2001 From: Daria Sukhonina Date: Fri, 3 May 2024 17:02:26 +0300 Subject: [PATCH 070/211] Add safety comment to fix tidy --- library/core/src/future/async_drop.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/core/src/future/async_drop.rs b/library/core/src/future/async_drop.rs index ea7e2f52ba1d..25138c445c43 100644 --- a/library/core/src/future/async_drop.rs +++ b/library/core/src/future/async_drop.rs @@ -259,6 +259,8 @@ async unsafe fn either, M: IntoFuture, T #[cfg(not(bootstrap))] #[lang = "async_drop_deferred_drop_in_place"] async unsafe fn deferred_drop_in_place(to_drop: *mut T) { + // SAFETY: same safety requirements as with drop_in_place (implied by + // function's name) unsafe { crate::ptr::drop_in_place(to_drop) } } From 39e193964e6b35e57b1e04f81831c625bd9e0c4c Mon Sep 17 00:00:00 2001 From: Daria Sukhonina Date: Mon, 20 May 2024 16:22:02 +0300 Subject: [PATCH 071/211] fix non-existing ToPredicate trait error --- compiler/rustc_middle/src/ty/util.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 2f2d03e9ec84..52a0e72e17e2 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -4,8 +4,8 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::query::{IntoQueryParam, Providers}; use crate::ty::layout::{FloatExt, IntegerExt}; use crate::ty::{ - self, Asyncness, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, - TypeSuperFoldable, TypeVisitableExt, Upcast, + self, Asyncness, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, + TypeVisitableExt, Upcast, }; use crate::ty::{GenericArgKind, GenericArgsRef}; use rustc_apfloat::Float as _; From 57a44b21197a7156608ec2d15cf6967e64f04db9 Mon Sep 17 00:00:00 2001 From: Daria Sukhonina Date: Fri, 24 May 2024 18:03:36 +0300 Subject: [PATCH 072/211] Bless new async destructor sizes in async drop tests --- src/tools/miri/tests/pass/async-drop.rs | 10 +++++----- tests/ui/async-await/async-drop.rs | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/tools/miri/tests/pass/async-drop.rs b/src/tools/miri/tests/pass/async-drop.rs index 744ffdeebdaf..c289c9410b25 100644 --- a/src/tools/miri/tests/pass/async-drop.rs +++ b/src/tools/miri/tests/pass/async-drop.rs @@ -46,7 +46,7 @@ fn main() { let i = 13; let fut = pin!(async { - test_async_drop(Int(0), 16).await; + test_async_drop(Int(0), 0).await; test_async_drop(AsyncInt(0), 104).await; test_async_drop([AsyncInt(1), AsyncInt(2)], 152).await; test_async_drop((AsyncInt(3), AsyncInt(4)), 488).await; @@ -71,13 +71,13 @@ fn main() { ) .await; - test_async_drop(AsyncEnum::A(AsyncInt(12)), 792).await; - test_async_drop(AsyncEnum::B(SyncInt(13)), 792).await; + test_async_drop(AsyncEnum::A(AsyncInt(12)), 680).await; + test_async_drop(AsyncEnum::B(SyncInt(13)), 680).await; - test_async_drop(SyncInt(14), 72).await; + test_async_drop(SyncInt(14), 16).await; test_async_drop( SyncThenAsync { i: 15, a: AsyncInt(16), b: SyncInt(17), c: AsyncInt(18) }, - 3512, + 3064, ) .await; diff --git a/tests/ui/async-await/async-drop.rs b/tests/ui/async-await/async-drop.rs index d1222cd740c3..97b5a602bc37 100644 --- a/tests/ui/async-await/async-drop.rs +++ b/tests/ui/async-await/async-drop.rs @@ -48,7 +48,7 @@ fn main() { let i = 13; let fut = pin!(async { - test_async_drop(Int(0), 16).await; + test_async_drop(Int(0), 0).await; test_async_drop(AsyncInt(0), 104).await; test_async_drop([AsyncInt(1), AsyncInt(2)], 152).await; test_async_drop((AsyncInt(3), AsyncInt(4)), 488).await; @@ -73,13 +73,13 @@ fn main() { ) .await; - test_async_drop(AsyncEnum::A(AsyncInt(12)), 792).await; - test_async_drop(AsyncEnum::B(SyncInt(13)), 792).await; + test_async_drop(AsyncEnum::A(AsyncInt(12)), 680).await; + test_async_drop(AsyncEnum::B(SyncInt(13)), 680).await; - test_async_drop(SyncInt(14), 72).await; + test_async_drop(SyncInt(14), 16).await; test_async_drop( SyncThenAsync { i: 15, a: AsyncInt(16), b: SyncInt(17), c: AsyncInt(18) }, - 3512, + 3064, ) .await; From 4903cf4df6f6647177f1645ab17ebab933564949 Mon Sep 17 00:00:00 2001 From: Daria Sukhonina Date: Mon, 27 May 2024 15:53:25 +0300 Subject: [PATCH 073/211] Revert miri async drop test but add warnings to each async drop test --- src/tools/miri/tests/pass/async-drop.rs | 84 ++++++++++--------------- tests/ui/async-await/async-drop.rs | 4 ++ 2 files changed, 38 insertions(+), 50 deletions(-) diff --git a/src/tools/miri/tests/pass/async-drop.rs b/src/tools/miri/tests/pass/async-drop.rs index c289c9410b25..92ecbdd29fdb 100644 --- a/src/tools/miri/tests/pass/async-drop.rs +++ b/src/tools/miri/tests/pass/async-drop.rs @@ -1,6 +1,11 @@ //@revisions: stack tree //@compile-flags: -Zmiri-strict-provenance //@[tree]compile-flags: -Zmiri-tree-borrows + +// WARNING: If you would ever want to modify this test, +// please consider modifying rustc's async drop test at +// `tests/ui/async-await/async-drop.rs`. + #![feature(async_drop, impl_trait_in_assoc_type, noop_waker, async_closure)] #![allow(incomplete_features, dead_code)] @@ -11,21 +16,9 @@ use core::mem::{self, ManuallyDrop}; use core::pin::{pin, Pin}; use core::task::{Context, Poll, Waker}; -async fn test_async_drop(x: T, _size: usize) { +async fn test_async_drop(x: T) { let mut x = mem::MaybeUninit::new(x); let dtor = pin!(unsafe { async_drop_in_place(x.as_mut_ptr()) }); - - // FIXME(zetanumbers): This check fully depends on the layout of - // the coroutine state, since async destructor combinators are just - // async functions. - #[cfg(target_pointer_width = "64")] - assert_eq!( - mem::size_of_val(&*dtor), - _size, - "sizes did not match for async destructor of type {}", - core::any::type_name::(), - ); - test_idempotency(dtor).await; } @@ -46,58 +39,49 @@ fn main() { let i = 13; let fut = pin!(async { - test_async_drop(Int(0), 0).await; - test_async_drop(AsyncInt(0), 104).await; - test_async_drop([AsyncInt(1), AsyncInt(2)], 152).await; - test_async_drop((AsyncInt(3), AsyncInt(4)), 488).await; - test_async_drop(5, 0).await; + test_async_drop(Int(0)).await; + test_async_drop(AsyncInt(0)).await; + test_async_drop([AsyncInt(1), AsyncInt(2)]).await; + test_async_drop((AsyncInt(3), AsyncInt(4))).await; + test_async_drop(5).await; let j = 42; - test_async_drop(&i, 0).await; - test_async_drop(&j, 0).await; - test_async_drop(AsyncStruct { b: AsyncInt(8), a: AsyncInt(7), i: 6 }, 1688).await; - test_async_drop(ManuallyDrop::new(AsyncInt(9)), 0).await; + test_async_drop(&i).await; + test_async_drop(&j).await; + test_async_drop(AsyncStruct { b: AsyncInt(8), a: AsyncInt(7), i: 6 }).await; + test_async_drop(ManuallyDrop::new(AsyncInt(9))).await; let foo = AsyncInt(10); - test_async_drop(AsyncReference { foo: &foo }, 104).await; + test_async_drop(AsyncReference { foo: &foo }).await; let foo = AsyncInt(11); - test_async_drop( - || { - black_box(foo); - let foo = AsyncInt(10); - foo - }, - 120, - ) + test_async_drop(|| { + black_box(foo); + let foo = AsyncInt(10); + foo + }) .await; - test_async_drop(AsyncEnum::A(AsyncInt(12)), 680).await; - test_async_drop(AsyncEnum::B(SyncInt(13)), 680).await; + test_async_drop(AsyncEnum::A(AsyncInt(12))).await; + test_async_drop(AsyncEnum::B(SyncInt(13))).await; - test_async_drop(SyncInt(14), 16).await; - test_async_drop( - SyncThenAsync { i: 15, a: AsyncInt(16), b: SyncInt(17), c: AsyncInt(18) }, - 3064, - ) - .await; + test_async_drop(SyncInt(14)).await; + test_async_drop(SyncThenAsync { i: 15, a: AsyncInt(16), b: SyncInt(17), c: AsyncInt(18) }) + .await; let async_drop_fut = pin!(core::future::async_drop(AsyncInt(19))); test_idempotency(async_drop_fut).await; let foo = AsyncInt(20); - test_async_drop( - async || { - black_box(foo); - let foo = AsyncInt(19); - // Await point there, but this is async closure so it's fine - black_box(core::future::ready(())).await; - foo - }, - 120, - ) + test_async_drop(async || { + black_box(foo); + let foo = AsyncInt(19); + // Await point there, but this is async closure so it's fine + black_box(core::future::ready(())).await; + foo + }) .await; - test_async_drop(AsyncUnion { signed: 21 }, 32).await; + test_async_drop(AsyncUnion { signed: 21 }).await; }); let res = fut.poll(&mut cx); assert_eq!(res, Poll::Ready(())); diff --git a/tests/ui/async-await/async-drop.rs b/tests/ui/async-await/async-drop.rs index 97b5a602bc37..12f120a0b121 100644 --- a/tests/ui/async-await/async-drop.rs +++ b/tests/ui/async-await/async-drop.rs @@ -1,6 +1,10 @@ //@ run-pass //@ check-run-results +// WARNING: If you would ever want to modify this test, +// please consider modifying miri's async drop test at +// `src/tools/miri/tests/pass/async-drop.rs`. + #![feature(async_drop, impl_trait_in_assoc_type, noop_waker, async_closure)] #![allow(incomplete_features, dead_code)] From ceb45d55190eb00d30b8762bc4c34cf71c53b637 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 29 May 2024 09:08:22 +0000 Subject: [PATCH 074/211] Don't require `visit_body` to take a lifetime that must outlive the function call --- compiler/rustc_hir/src/intravisit.rs | 4 ++-- compiler/rustc_hir_analysis/src/check/region.rs | 2 +- .../rustc_infer/src/infer/error_reporting/need_type_info.rs | 2 +- compiler/rustc_infer/src/infer/error_reporting/suggest.rs | 4 ---- compiler/rustc_lint/src/late.rs | 2 +- compiler/rustc_lint/src/non_local_def.rs | 4 ++-- compiler/rustc_lint/src/passes.rs | 4 ++-- compiler/rustc_passes/src/check_const.rs | 2 +- compiler/rustc_passes/src/hir_stats.rs | 2 +- .../src/traits/error_reporting/suggestions.rs | 2 +- src/librustdoc/visit_ast.rs | 2 +- .../clippy/clippy_lints/src/default_numeric_fallback.rs | 2 +- src/tools/clippy/clippy_lints/src/dereference.rs | 2 +- src/tools/clippy/clippy_lints/src/implicit_hasher.rs | 2 +- .../clippy/clippy_lints/src/macro_metavars_in_unsafe.rs | 2 +- .../clippy_lints/src/needless_borrows_for_generic_args.rs | 2 +- src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs | 4 ++-- src/tools/clippy/clippy_lints/src/operators/mod.rs | 4 ++-- src/tools/clippy/clippy_lints/src/ptr.rs | 6 +++--- src/tools/clippy/clippy_lints/src/question_mark.rs | 4 ++-- 20 files changed, 27 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index aba0532f0d1e..63ddb22c5abc 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -299,7 +299,7 @@ pub trait Visitor<'v>: Sized { walk_item(self, i) } - fn visit_body(&mut self, b: &'v Body<'v>) -> Self::Result { + fn visit_body(&mut self, b: &Body<'v>) -> Self::Result { walk_body(self, b) } @@ -578,7 +578,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V:: V::Result::output() } -pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &'v Body<'v>) -> V::Result { +pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &Body<'v>) -> V::Result { walk_list!(visitor, visit_param, body.params); visitor.visit_expr(body.value) } diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 8b0adebfaf46..dcddb2662088 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -818,7 +818,7 @@ impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> { resolve_block(self, b); } - fn visit_body(&mut self, body: &'tcx hir::Body<'tcx>) { + fn visit_body(&mut self, body: &hir::Body<'tcx>) { let body_id = body.id(); let owner_id = self.tcx.hir().body_owner_def_id(body_id); diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index 98fd7906e700..63d41a1faf3f 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -1163,7 +1163,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> { /// For closures, we first visit the parameters and then the content, /// as we prefer those. - fn visit_body(&mut self, body: &'tcx Body<'tcx>) { + fn visit_body(&mut self, body: &Body<'tcx>) { for param in body.params { debug!( "param: span {:?}, ty_span {:?}, pat.span {:?}", diff --git a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs index 75479decebcd..c333f024ad12 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs @@ -578,10 +578,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { walk_stmt(self, ex) } } - - fn visit_body(&mut self, body: &'v hir::Body<'v>) -> Self::Result { - hir::intravisit::walk_body(self, body) - } } self.tcx.hir().maybe_body_owned_by(cause.body_id).and_then(|body_id| { diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index b638ab10e11e..aa328fb87b27 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -125,7 +125,7 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas }); } - fn visit_body(&mut self, body: &'tcx hir::Body<'tcx>) { + fn visit_body(&mut self, body: &hir::Body<'tcx>) { lint_callback!(self, check_body, body); hir_visit::walk_body(self, body); lint_callback!(self, check_body_post, body); diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index 42b03f47a5bc..5135996186a7 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -68,11 +68,11 @@ impl_lint_pass!(NonLocalDefinitions => [NON_LOCAL_DEFINITIONS]); // instead check_mod is called after every body has been handled. impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { - fn check_body(&mut self, _cx: &LateContext<'tcx>, _body: &'tcx Body<'tcx>) { + fn check_body(&mut self, _cx: &LateContext<'tcx>, _body: &Body<'tcx>) { self.body_depth += 1; } - fn check_body_post(&mut self, _cx: &LateContext<'tcx>, _body: &'tcx Body<'tcx>) { + fn check_body_post(&mut self, _cx: &LateContext<'tcx>, _body: &Body<'tcx>) { self.body_depth -= 1; } diff --git a/compiler/rustc_lint/src/passes.rs b/compiler/rustc_lint/src/passes.rs index d8ba84eb7a1a..c4f5f152de52 100644 --- a/compiler/rustc_lint/src/passes.rs +++ b/compiler/rustc_lint/src/passes.rs @@ -7,8 +7,8 @@ use rustc_session::lint::LintPass; macro_rules! late_lint_methods { ($macro:path, $args:tt) => ( $macro!($args, [ - fn check_body(a: &'tcx rustc_hir::Body<'tcx>); - fn check_body_post(a: &'tcx rustc_hir::Body<'tcx>); + fn check_body(a: &rustc_hir::Body<'tcx>); + fn check_body_post(a: &rustc_hir::Body<'tcx>); fn check_crate(); fn check_crate_post(); fn check_mod(a: &'tcx rustc_hir::Mod<'tcx>, b: rustc_hir::HirId); diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs index fa2c8f69c71d..71f3e8b7b5d9 100644 --- a/compiler/rustc_passes/src/check_const.rs +++ b/compiler/rustc_passes/src/check_const.rs @@ -196,7 +196,7 @@ impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> { self.recurse_into(kind, None, |this| intravisit::walk_anon_const(this, anon)); } - fn visit_body(&mut self, body: &'tcx hir::Body<'tcx>) { + fn visit_body(&mut self, body: &hir::Body<'tcx>) { let owner = self.tcx.hir().body_owner_def_id(body.id()); let kind = self.tcx.hir().body_const_context(owner); self.recurse_into(kind, Some(owner), |this| intravisit::walk_body(this, body)); diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index a980d5dcaba4..6bb9cff53193 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -246,7 +246,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { hir_visit::walk_item(self, i) } - fn visit_body(&mut self, b: &'v hir::Body<'v>) { + fn visit_body(&mut self, b: &hir::Body<'v>) { self.record("Body", Id::None, b); hir_visit::walk_body(self, b); } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 6c56ebb62aed..18d91a5b9a89 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -4748,7 +4748,7 @@ impl<'v> Visitor<'v> for ReturnsVisitor<'v> { } } - fn visit_body(&mut self, body: &'v hir::Body<'v>) { + fn visit_body(&mut self, body: &hir::Body<'v>) { assert!(!self.in_block_tail); self.in_block_tail = true; hir::intravisit::walk_body(self, body); diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 907ea6d309c9..886df82e5b69 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -614,7 +614,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RustdocVisitor<'a, 'tcx> { // Unneeded. } - fn visit_body(&mut self, b: &'tcx hir::Body<'tcx>) { + fn visit_body(&mut self, b: &hir::Body<'tcx>) { let prev = mem::replace(&mut self.inside_body, true); walk_body(self, b); self.inside_body = prev; diff --git a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs index 1d6c4ce72e18..4d8c066fea54 100644 --- a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs +++ b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs @@ -49,7 +49,7 @@ declare_clippy_lint! { declare_lint_pass!(DefaultNumericFallback => [DEFAULT_NUMERIC_FALLBACK]); impl<'tcx> LateLintPass<'tcx> for DefaultNumericFallback { - fn check_body(&mut self, cx: &LateContext<'tcx>, body: &'tcx Body<'_>) { + fn check_body(&mut self, cx: &LateContext<'tcx>, body: &Body<'tcx>) { let hir = cx.tcx.hir(); let is_parent_const = matches!( hir.body_const_context(hir.body_owner_def_id(body.id())), diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index c6aef9ac2d60..297082354ff1 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -641,7 +641,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> { } } - fn check_body_post(&mut self, cx: &LateContext<'tcx>, body: &'tcx Body<'_>) { + fn check_body_post(&mut self, cx: &LateContext<'tcx>, body: &Body<'_>) { if Some(body.id()) == self.current_body { for pat in self.ref_locals.drain(..).filter_map(|(_, x)| x) { let replacements = pat.replacements; diff --git a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs index a46aae36d5c5..ca830af3b2f3 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs @@ -328,7 +328,7 @@ impl<'a, 'b, 'tcx> ImplicitHasherConstructorVisitor<'a, 'b, 'tcx> { impl<'a, 'b, 'tcx> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'a, 'b, 'tcx> { type NestedFilter = nested_filter::OnlyBodies; - fn visit_body(&mut self, body: &'tcx Body<'_>) { + fn visit_body(&mut self, body: &Body<'tcx>) { let old_maybe_typeck_results = self.maybe_typeck_results.replace(self.cx.tcx.typeck_body(body.id())); walk_body(self, body); self.maybe_typeck_results = old_maybe_typeck_results; diff --git a/src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs b/src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs index aea3d26e1878..d1ae243877d7 100644 --- a/src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs +++ b/src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs @@ -186,7 +186,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BodyVisitor<'a, 'tcx> { } impl<'tcx> LateLintPass<'tcx> for ExprMetavarsInUnsafe { - fn check_body(&mut self, cx: &LateContext<'tcx>, body: &'tcx rustc_hir::Body<'tcx>) { + fn check_body(&mut self, cx: &LateContext<'tcx>, body: &rustc_hir::Body<'tcx>) { if is_lint_allowed(cx, MACRO_METAVARS_IN_UNSAFE, body.value.hir_id) { return; } diff --git a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs index daf166bad90d..5b5e1c234245 100644 --- a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs +++ b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs @@ -129,7 +129,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBorrowsForGenericArgs<'tcx> { } } - fn check_body_post(&mut self, cx: &LateContext<'tcx>, body: &'tcx Body<'_>) { + fn check_body_post(&mut self, cx: &LateContext<'tcx>, body: &Body<'_>) { if self.possible_borrowers.last().map_or(false, |&(local_def_id, _)| { local_def_id == cx.tcx.hir().body_owner_def_id(body.id()) }) { diff --git a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs index b3ff5ecae862..8b8aabe7accc 100644 --- a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs +++ b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs @@ -221,7 +221,7 @@ pub struct OnlyUsedInRecursion { } impl<'tcx> LateLintPass<'tcx> for OnlyUsedInRecursion { - fn check_body(&mut self, cx: &LateContext<'tcx>, body: &'tcx Body<'tcx>) { + fn check_body(&mut self, cx: &LateContext<'tcx>, body: &Body<'tcx>) { if body.value.span.from_expansion() { return; } @@ -350,7 +350,7 @@ impl<'tcx> LateLintPass<'tcx> for OnlyUsedInRecursion { } } - fn check_body_post(&mut self, cx: &LateContext<'tcx>, body: &'tcx Body<'tcx>) { + fn check_body_post(&mut self, cx: &LateContext<'tcx>, body: &Body<'tcx>) { if self.entered_body == Some(body.value.hir_id) { self.entered_body = None; self.params.flag_for_linting(); diff --git a/src/tools/clippy/clippy_lints/src/operators/mod.rs b/src/tools/clippy/clippy_lints/src/operators/mod.rs index e002429e3a47..9e77d0e09c48 100644 --- a/src/tools/clippy/clippy_lints/src/operators/mod.rs +++ b/src/tools/clippy/clippy_lints/src/operators/mod.rs @@ -868,11 +868,11 @@ impl<'tcx> LateLintPass<'tcx> for Operators { self.arithmetic_context.expr_post(e.hir_id); } - fn check_body(&mut self, cx: &LateContext<'tcx>, b: &'tcx Body<'_>) { + fn check_body(&mut self, cx: &LateContext<'tcx>, b: &Body<'_>) { self.arithmetic_context.enter_body(cx, b); } - fn check_body_post(&mut self, cx: &LateContext<'tcx>, b: &'tcx Body<'_>) { + fn check_body_post(&mut self, cx: &LateContext<'tcx>, b: &Body<'_>) { self.arithmetic_context.body_post(cx, b); } } diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs index 38580dc58226..02c05e0aaf9c 100644 --- a/src/tools/clippy/clippy_lints/src/ptr.rs +++ b/src/tools/clippy/clippy_lints/src/ptr.rs @@ -188,7 +188,7 @@ impl<'tcx> LateLintPass<'tcx> for Ptr { } } - fn check_body(&mut self, cx: &LateContext<'tcx>, body: &'tcx Body<'_>) { + fn check_body(&mut self, cx: &LateContext<'tcx>, body: &Body<'tcx>) { let hir = cx.tcx.hir(); let mut parents = hir.parent_iter(body.value.hir_id); let (item_id, sig, is_trait_item) = match parents.next() { @@ -525,7 +525,7 @@ fn check_fn_args<'cx, 'tcx: 'cx>( }) } -fn check_mut_from_ref<'tcx>(cx: &LateContext<'tcx>, sig: &FnSig<'_>, body: Option<&'tcx Body<'_>>) { +fn check_mut_from_ref<'tcx>(cx: &LateContext<'tcx>, sig: &FnSig<'_>, body: Option<&Body<'tcx>>) { if let FnRetTy::Return(ty) = sig.decl.output && let Some((out, Mutability::Mut, _)) = get_ref_lm(ty) { @@ -559,7 +559,7 @@ fn check_mut_from_ref<'tcx>(cx: &LateContext<'tcx>, sig: &FnSig<'_>, body: Optio } #[expect(clippy::too_many_lines)] -fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &'tcx Body<'_>, args: &[PtrArg<'tcx>]) -> Vec { +fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &Body<'tcx>, args: &[PtrArg<'tcx>]) -> Vec { struct V<'cx, 'tcx> { cx: &'cx LateContext<'tcx>, /// Map from a local id to which argument it came from (index into `Self::args` and diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs index 1f1ce147ca24..7cf98ad9e09a 100644 --- a/src/tools/clippy/clippy_lints/src/question_mark.rs +++ b/src/tools/clippy/clippy_lints/src/question_mark.rs @@ -370,11 +370,11 @@ impl<'tcx> LateLintPass<'tcx> for QuestionMark { } } - fn check_body(&mut self, _: &LateContext<'tcx>, _: &'tcx Body<'tcx>) { + fn check_body(&mut self, _: &LateContext<'tcx>, _: &Body<'tcx>) { self.try_block_depth_stack.push(0); } - fn check_body_post(&mut self, _: &LateContext<'tcx>, _: &'tcx Body<'tcx>) { + fn check_body_post(&mut self, _: &LateContext<'tcx>, _: &Body<'tcx>) { self.try_block_depth_stack.pop(); } From a34c26e7ecfbfe3f4fd5fbd4868a0cba5676e6a5 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 29 May 2024 10:03:40 +0000 Subject: [PATCH 075/211] Make `body_owned_by` return the body directly. Almost all callers want this anyway, and now we can use it to also return fed bodies --- .../src/diagnostics/conflict_errors.rs | 11 +++++----- .../src/diagnostics/mutability_errors.rs | 19 +++++++---------- .../src/diagnostics/region_errors.rs | 4 ++-- compiler/rustc_driver_impl/src/pretty.rs | 2 +- .../rustc_hir_analysis/src/check/region.rs | 5 ++--- compiler/rustc_hir_typeck/src/_match.rs | 3 +-- compiler/rustc_hir_typeck/src/demand.rs | 3 +-- compiler/rustc_hir_typeck/src/expr.rs | 3 +-- compiler/rustc_hir_typeck/src/fallback.rs | 3 +-- .../src/fn_ctxt/suggestions.rs | 3 +-- .../rustc_hir_typeck/src/method/suggest.rs | 12 ++++------- .../infer/error_reporting/need_type_info.rs | 4 ++-- .../error_reporting/nice_region_error/util.rs | 5 ++--- .../src/infer/error_reporting/suggest.rs | 5 ++--- compiler/rustc_metadata/src/rmeta/encoder.rs | 14 ++++++------- compiler/rustc_middle/src/hir/map/mod.rs | 21 ++++++++++++++++--- compiler/rustc_middle/src/hir/mod.rs | 11 ++++++---- compiler/rustc_mir_build/src/build/mod.rs | 6 +++--- compiler/rustc_mir_build/src/thir/cx/mod.rs | 21 +++---------------- compiler/rustc_mir_transform/src/lib.rs | 3 ++- compiler/rustc_passes/src/liveness.rs | 15 +++++++------ compiler/rustc_passes/src/upvars.rs | 6 +++--- compiler/rustc_privacy/src/lib.rs | 2 +- .../src/traits/error_reporting/suggestions.rs | 21 +++++++------------ .../error_reporting/type_err_ctxt_ext.rs | 5 ++--- compiler/rustc_ty_utils/src/opaque_types.rs | 2 +- src/librustdoc/clean/types.rs | 6 ++++-- src/librustdoc/clean/utils.rs | 2 +- src/librustdoc/core.rs | 4 ++-- src/librustdoc/html/render/span_map.rs | 4 +--- src/librustdoc/json/conversions.rs | 5 ++++- .../src/methods/option_map_unwrap_or.rs | 4 ++-- .../clippy/clippy_lints/src/single_call_fn.rs | 1 - .../missing_transmute_annotations.rs | 4 ++-- .../src/unconditional_recursion.rs | 2 +- .../clippy/clippy_lints/src/utils/author.rs | 4 ++-- tests/ui/inline-const/uninit_local.rs | 6 ++++++ tests/ui/inline-const/uninit_local.stderr | 16 ++++++++++++++ 38 files changed, 136 insertions(+), 131 deletions(-) create mode 100644 tests/ui/inline-const/uninit_local.rs create mode 100644 tests/ui/inline-const/uninit_local.stderr diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 2f1b2ce9c4c7..7c60d3b4bd87 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -399,8 +399,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } let hir = self.infcx.tcx.hir(); - if let Some(body_id) = hir.maybe_body_owned_by(self.mir_def_id()) { - let expr = hir.body(body_id).value; + if let Some(body) = hir.maybe_body_owned_by(self.mir_def_id()) { + let expr = body.value; let place = &self.move_data.move_paths[mpi].place; let span = place.as_local().map(|local| self.body.local_decls[local].source_info.span); let mut finder = ExpressionFinder { @@ -556,11 +556,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // We use the statements were the binding was initialized, and inspect the HIR to look // for the branching codepaths that aren't covered, to point at them. let map = self.infcx.tcx.hir(); - let body_id = map.body_owned_by(self.mir_def_id()); - let body = map.body(body_id); + let body = map.body_owned_by(self.mir_def_id()); let mut visitor = ConditionVisitor { spans: &spans, name: &name, errors: vec![] }; - visitor.visit_body(body); + visitor.visit_body(&body); let mut show_assign_sugg = false; let isnt_initialized = if let InitializationRequiringAction::PartialAssignment @@ -665,7 +664,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } let mut visitor = LetVisitor { decl_span, sugg_span: None }; - visitor.visit_body(body); + visitor.visit_body(&body); if let Some(span) = visitor.sugg_span { self.suggest_assign_value(&mut err, moved_place, span); } diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 79b485085852..78798545c26f 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -647,8 +647,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let hir_map = self.infcx.tcx.hir(); let def_id = self.body.source.def_id(); let Some(local_def_id) = def_id.as_local() else { return }; - let Some(body_id) = hir_map.maybe_body_owned_by(local_def_id) else { return }; - let body = self.infcx.tcx.hir().body(body_id); + let Some(body) = hir_map.maybe_body_owned_by(local_def_id) else { return }; let mut v = SuggestIndexOperatorAlternativeVisitor { assign_span: span, @@ -656,7 +655,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { ty, suggested: false, }; - v.visit_body(body); + v.visit_body(&body); if !v.suggested { err.help(format!( "to modify a `{ty}`, use `.get_mut()`, `.insert()` or the entry API", @@ -746,9 +745,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // `fn foo(&x: &i32)` -> `fn foo(&(mut x): &i32)` let def_id = self.body.source.def_id(); if let Some(local_def_id) = def_id.as_local() - && let Some(body_id) = self.infcx.tcx.hir().maybe_body_owned_by(local_def_id) - && let body = self.infcx.tcx.hir().body(body_id) - && let Some(hir_id) = (BindingFinder { span: pat_span }).visit_body(body).break_value() + && let Some(body) = self.infcx.tcx.hir().maybe_body_owned_by(local_def_id) + && let Some(hir_id) = (BindingFinder { span: pat_span }).visit_body(&body).break_value() && let node = self.infcx.tcx.hir_node(hir_id) && let hir::Node::LetStmt(hir::LetStmt { pat: hir::Pat { kind: hir::PatKind::Ref(_, _), .. }, @@ -867,8 +865,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } } } - if let Some(body_id) = hir_map.maybe_body_owned_by(self.mir_def_id()) - && let Block(block, _) = hir_map.body(body_id).value.kind + if let Some(body) = hir_map.maybe_body_owned_by(self.mir_def_id()) + && let Block(block, _) = body.value.kind { // `span` corresponds to the expression being iterated, find the `for`-loop desugared // expression with that span in order to identify potential fixes when encountering a @@ -1189,10 +1187,9 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { Some((false, err_label_span, message, _)) => { let def_id = self.body.source.def_id(); let hir_id = if let Some(local_def_id) = def_id.as_local() - && let Some(body_id) = self.infcx.tcx.hir().maybe_body_owned_by(local_def_id) + && let Some(body) = self.infcx.tcx.hir().maybe_body_owned_by(local_def_id) { - let body = self.infcx.tcx.hir().body(body_id); - BindingFinder { span: err_label_span }.visit_body(body).break_value() + BindingFinder { span: err_label_span }.visit_body(&body).break_value() } else { None }; diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index e11e4a7247c2..15a8764aab3c 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -1183,8 +1183,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn suggest_move_on_borrowing_closure(&self, diag: &mut Diag<'_>) { let map = self.infcx.tcx.hir(); - let body_id = map.body_owned_by(self.mir_def_id()); - let expr = &map.body(body_id).value.peel_blocks(); + let body = map.body_owned_by(self.mir_def_id()); + let expr = &body.value.peel_blocks(); let mut closure_span = None::; match expr.kind { hir::ExprKind::MethodCall(.., args, _) => { diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs index fe426b8111cc..8acba57b7a65 100644 --- a/compiler/rustc_driver_impl/src/pretty.rs +++ b/compiler/rustc_driver_impl/src/pretty.rs @@ -169,7 +169,7 @@ impl<'tcx> pprust_hir::PpAnn for HirTypedAnn<'tcx> { self.tcx .hir() .maybe_body_owned_by(expr.hir_id.owner.def_id) - .map(|body_id| self.tcx.typeck_body(body_id)) + .map(|body_id| self.tcx.typeck_body(body_id.id())) }); if let Some(typeck_results) = typeck_results { diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index dcddb2662088..30b03b43872a 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -896,7 +896,7 @@ pub fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> &ScopeTree { return tcx.region_scope_tree(typeck_root_def_id); } - let scope_tree = if let Some(body_id) = tcx.hir().maybe_body_owned_by(def_id.expect_local()) { + let scope_tree = if let Some(body) = tcx.hir().maybe_body_owned_by(def_id.expect_local()) { let mut visitor = RegionResolutionVisitor { tcx, scope_tree: ScopeTree::default(), @@ -907,9 +907,8 @@ pub fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> &ScopeTree { fixup_scopes: vec![], }; - let body = tcx.hir().body(body_id); visitor.scope_tree.root_body = Some(body.value.hir_id); - visitor.visit_body(body); + visitor.visit_body(&body); visitor.scope_tree } else { ScopeTree::default() diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index c2e62e4c0035..a599e8d05fd3 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -207,10 +207,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let hir = self.tcx.hir(); // First, check that we're actually in the tail of a function. - let Some(body_id) = hir.maybe_body_owned_by(self.body_id) else { + let Some(body) = hir.maybe_body_owned_by(self.body_id) else { return; }; - let body = hir.body(body_id); let hir::ExprKind::Block(block, _) = body.value.kind else { return; }; diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 7916366ef089..fa147f9bfcfe 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -327,8 +327,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let mut expr_finder = FindExprs { hir_id: local_hir_id, uses: init.into_iter().collect() }; - let body = - hir.body(hir.maybe_body_owned_by(self.body_id).expect("expected item to have body")); + let body = hir.body_owned_by(self.body_id); expr_finder.visit_expr(body.value); // Replaces all of the variables in the given type with a fresh inference variable. diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 364f0fec202a..061d9507a35c 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -909,8 +909,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // the first place. assert_ne!(encl_item_id.def_id, encl_body_owner_id); - let encl_body_id = self.tcx.hir().body_owned_by(encl_body_owner_id); - let encl_body = self.tcx.hir().body(encl_body_id); + let encl_body = self.tcx.hir().body_owned_by(encl_body_owner_id); err.encl_body_span = Some(encl_body.value.span); err.encl_fn_span = Some(*encl_fn_span); diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index e8533c68c793..7d6fdc9392ea 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -544,9 +544,8 @@ fn compute_unsafe_infer_vars<'a, 'tcx>( root_ctxt: &'a TypeckRootCtxt<'tcx>, body_id: LocalDefId, ) -> UnordMap { - let body_id = + let body = root_ctxt.tcx.hir().maybe_body_owned_by(body_id).expect("body id must have an owner"); - let body = root_ctxt.tcx.hir().body(body_id); let mut res = UnordMap::default(); struct UnsafeInferVarsVisitor<'a, 'tcx, 'r> { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 0d7f59c48715..7cefe189bd6b 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1973,8 +1973,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { *expr } else { let body_def_id = hir.enclosing_body_owner(expr.hir_id); - let body_id = hir.body_owned_by(body_def_id); - let body = hir.body(body_id); + let body = hir.body_owned_by(body_def_id); // Get tail expr of the body match body.value.kind { diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 54af8354c4c7..af7b68bc36b7 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -505,9 +505,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && let hir::def::Res::Local(recv_id) = path.res && let Some(segment) = path.segments.first() { - let map = self.infcx.tcx.hir(); - let body_id = self.tcx.hir().body_owned_by(self.body_id); - let body = map.body(body_id); + let body = self.tcx.hir().body_owned_by(self.body_id); if let Node::Expr(call_expr) = self.tcx.parent_hir_node(rcvr.hir_id) { let mut let_visitor = LetVisitor { @@ -518,7 +516,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { method_name, sugg_let: None, }; - let_visitor.visit_body(body); + let_visitor.visit_body(&body); if let Some(sugg_let) = let_visitor.sugg_let && let Some(self_ty) = self.node_ty_opt(sugg_let.init_hir_id) { @@ -2429,9 +2427,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { seg1.ident.span, StashKey::CallAssocMethod, |err| { - let map = self.infcx.tcx.hir(); - let body_id = self.tcx.hir().body_owned_by(self.body_id); - let body = map.body(body_id); + let body = self.tcx.hir().body_owned_by(self.body_id); struct LetVisitor { ident_name: Symbol, } @@ -2453,7 +2449,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Node::Expr(call_expr) = self.tcx.parent_hir_node(seg1.hir_id) && let ControlFlow::Break(Some(expr)) = - (LetVisitor { ident_name: seg1.ident.name }).visit_body(body) + (LetVisitor { ident_name: seg1.ident.name }).visit_body(&body) && let Some(self_ty) = self.node_ty_opt(expr.hir_id) { let probe = self.lookup_probe_for_diagnostic( diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index 63d41a1faf3f..fb8c843f3095 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -457,10 +457,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { }; let mut local_visitor = FindInferSourceVisitor::new(self, typeck_results, arg); - if let Some(body_id) = self.tcx.hir().maybe_body_owned_by( + if let Some(body) = self.tcx.hir().maybe_body_owned_by( self.tcx.typeck_root_def_id(body_def_id.to_def_id()).expect_local(), ) { - let expr = self.tcx.hir().body(body_id).value; + let expr = body.value; local_visitor.visit_expr(expr); } diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs index 5f3f1081ca8f..83145e4f7b27 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs @@ -62,14 +62,13 @@ pub fn find_param_with_region<'tcx>( _ => {} } - let body_id = hir.maybe_body_owned_by(def_id)?; + let body = hir.maybe_body_owned_by(def_id)?; - let owner_id = hir.body_owner(body_id); + let owner_id = hir.body_owner(body.id()); let fn_decl = hir.fn_decl_by_hir_id(owner_id)?; let poly_fn_sig = tcx.fn_sig(id).instantiate_identity(); let fn_sig = tcx.liberate_late_bound_regions(id, poly_fn_sig); - let body = hir.body(body_id); body.params .iter() .take(if fn_sig.c_variadic { diff --git a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs index c333f024ad12..17fb760295ae 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs @@ -580,10 +580,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } } - self.tcx.hir().maybe_body_owned_by(cause.body_id).and_then(|body_id| { - let body = self.tcx.hir().body(body_id); + self.tcx.hir().maybe_body_owned_by(cause.body_id).and_then(|body| { IfVisitor { err_span: span, found_if: false } - .visit_body(body) + .visit_body(&body) .is_break() .then(|| TypeErrorAdditionalDiags::AddLetForLetChains { span: span.shrink_to_lo() }) }) diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 4587a4315e3c..4f186981a76f 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1677,9 +1677,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if should_encode_const(tcx.def_kind(def_id)) { let qualifs = tcx.mir_const_qualif(def_id); record!(self.tables.mir_const_qualif[def_id.to_def_id()] <- qualifs); - let body_id = tcx.hir().maybe_body_owned_by(def_id); - if let Some(body_id) = body_id { - let const_data = rendered_const(self.tcx, body_id); + let body = tcx.hir().maybe_body_owned_by(def_id); + if let Some(body) = body { + let const_data = rendered_const(self.tcx, &body, def_id); record!(self.tables.rendered_const[def_id.to_def_id()] <- const_data); } } @@ -2368,9 +2368,9 @@ pub fn provide(providers: &mut Providers) { /// Whenever possible, prefer to evaluate the constant first and try to /// use a different method for pretty-printing. Ideally this function /// should only ever be used as a fallback. -pub fn rendered_const<'tcx>(tcx: TyCtxt<'tcx>, body: hir::BodyId) -> String { +pub fn rendered_const<'tcx>(tcx: TyCtxt<'tcx>, body: &hir::Body<'_>, def_id: LocalDefId) -> String { let hir = tcx.hir(); - let value = &hir.body(body).value; + let value = body.value; #[derive(PartialEq, Eq)] enum Classification { @@ -2426,13 +2426,13 @@ pub fn rendered_const<'tcx>(tcx: TyCtxt<'tcx>, body: hir::BodyId) -> String { // Otherwise we prefer pretty-printing to get rid of extraneous whitespace, comments and // other formatting artifacts. - Literal | Simple => id_to_string(&hir, body.hir_id), + Literal | Simple => id_to_string(&hir, body.id().hir_id), // FIXME: Omit the curly braces if the enclosing expression is an array literal // with a repeated element (an `ExprKind::Repeat`) as in such case it // would not actually need any disambiguation. Complex => { - if tcx.def_kind(hir.body_owner_def_id(body).to_def_id()) == DefKind::AnonConst { + if tcx.def_kind(def_id) == DefKind::AnonConst { "{ _ }".to_owned() } else { "_".to_owned() diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index ff8d29197055..665cd883d44a 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -1,3 +1,5 @@ +use std::borrow::Cow; + use crate::hir::ModuleItems; use crate::middle::debugger_visualizer::DebuggerVisualizerFile; use crate::query::LocalCrate; @@ -254,13 +256,26 @@ impl<'hir> Map<'hir> { /// Given a `LocalDefId`, returns the `BodyId` associated with it, /// if the node is a body owner, otherwise returns `None`. - pub fn maybe_body_owned_by(self, id: LocalDefId) -> Option { - self.tcx.hir_node_by_def_id(id).body_id() + pub fn maybe_body_owned_by(self, id: LocalDefId) -> Option>> { + Some(match self.tcx.def_kind(id) { + // Inline consts do not have bodies of their own, so create one to make the follow-up logic simpler. + DefKind::InlineConst => { + let e = self.expect_expr(self.tcx.local_def_id_to_hir_id(id)); + Cow::Owned(Body { + params: &[], + value: match e.kind { + ExprKind::ConstBlock(body) => body, + _ => span_bug!(e.span, "InlineConst was not a ConstBlock: {e:#?}"), + }, + }) + } + _ => Cow::Borrowed(self.body(self.tcx.hir_node_by_def_id(id).body_id()?)), + }) } /// Given a body owner's id, returns the `BodyId` associated with it. #[track_caller] - pub fn body_owned_by(self, id: LocalDefId) -> BodyId { + pub fn body_owned_by(self, id: LocalDefId) -> Cow<'hir, Body<'hir>> { self.maybe_body_owned_by(id).unwrap_or_else(|| { let hir_id = self.tcx.local_def_id_to_hir_id(id); span_bug!( diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index d39422b2b04d..b0c14cdfec93 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -194,8 +194,7 @@ pub fn provide(providers: &mut Providers) { }; providers.fn_arg_names = |tcx, def_id| { let hir = tcx.hir(); - let hir_id = tcx.local_def_id_to_hir_id(def_id); - if let Some(body_id) = hir.maybe_body_owned_by(def_id) { + if let Some(body_id) = tcx.hir_node_by_def_id(def_id).body_id() { tcx.arena.alloc_from_iter(hir.body_param_names(body_id)) } else if let Node::TraitItem(&TraitItem { kind: TraitItemKind::Fn(_, TraitFn::Required(idents)), @@ -204,11 +203,15 @@ pub fn provide(providers: &mut Providers) { | Node::ForeignItem(&ForeignItem { kind: ForeignItemKind::Fn(_, idents, _), .. - }) = tcx.hir_node(hir_id) + }) = tcx.hir_node(tcx.local_def_id_to_hir_id(def_id)) { idents } else { - span_bug!(hir.span(hir_id), "fn_arg_names: unexpected item {:?}", def_id); + span_bug!( + hir.span(tcx.local_def_id_to_hir_id(def_id)), + "fn_arg_names: unexpected item {:?}", + def_id + ); } }; providers.all_local_trait_impls = |tcx, ()| &tcx.resolutions(()).trait_impls; diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 13112f2b12c8..14d1b502474f 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -452,7 +452,7 @@ fn construct_fn<'tcx>( assert_eq!(expr.as_usize(), thir.exprs.len() - 1); // Figure out what primary body this item has. - let body_id = tcx.hir().body_owned_by(fn_def); + let body = tcx.hir().body_owned_by(fn_def); let span_with_body = tcx.hir().span_with_body(fn_id); let return_ty_span = tcx .hir() @@ -512,9 +512,9 @@ fn construct_fn<'tcx>( ); let call_site_scope = - region::Scope { id: body_id.hir_id.local_id, data: region::ScopeData::CallSite }; + region::Scope { id: body.id().hir_id.local_id, data: region::ScopeData::CallSite }; let arg_scope = - region::Scope { id: body_id.hir_id.local_id, data: region::ScopeData::Arguments }; + region::Scope { id: body.id().hir_id.local_id, data: region::ScopeData::Arguments }; let source_info = builder.source_info(span); let call_site_s = (call_site_scope, source_info); unpack!(builder.in_scope(call_site_s, LintLevel::Inherited, |builder| { diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index bd72ef28cb37..bd9e34ae80fc 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -13,10 +13,10 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::lang_items::LangItem; use rustc_hir::HirId; use rustc_hir::Node; +use rustc_middle::bug; use rustc_middle::middle::region; use rustc_middle::thir::*; use rustc_middle::ty::{self, RvalueScopes, TyCtxt}; -use rustc_middle::{bug, span_bug}; use tracing::instrument; pub(crate) fn thir_body( @@ -24,22 +24,7 @@ pub(crate) fn thir_body( owner_def: LocalDefId, ) -> Result<(&Steal>, ExprId), ErrorGuaranteed> { let hir = tcx.hir(); - let body; - let body = match tcx.def_kind(owner_def) { - // Inline consts do not have bodies of their own, so create one to make the follow-up logic simpler. - DefKind::InlineConst => { - let e = hir.expect_expr(tcx.local_def_id_to_hir_id(owner_def)); - body = hir::Body { - params: &[], - value: match e.kind { - hir::ExprKind::ConstBlock(body) => body, - _ => span_bug!(e.span, "InlineConst was not a ConstBlock: {e:#?}"), - }, - }; - &body - } - _ => hir.body(hir.body_owned_by(owner_def)), - }; + let body = hir.body_owned_by(owner_def); let mut cx = Cx::new(tcx, owner_def); if let Some(reported) = cx.typeck_results.tainted_by_errors { return Err(reported); @@ -49,7 +34,7 @@ pub(crate) fn thir_body( let owner_id = tcx.local_def_id_to_hir_id(owner_def); if let Some(fn_decl) = hir.fn_decl_by_hir_id(owner_id) { let closure_env_param = cx.closure_env_param(owner_def, owner_id); - let explicit_params = cx.explicit_params(owner_id, fn_decl, body); + let explicit_params = cx.explicit_params(owner_id, fn_decl, &body); cx.thir.params = closure_env_param.into_iter().chain(explicit_params).collect(); // The resume argument may be missing, in that case we need to provide it here. diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 93ae105150cc..a8741254ffbf 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -226,7 +226,8 @@ fn mir_keys(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet { // typeck instead of during ast lowering, like all other bodies so far. for def_id in tcx.hir().body_owners() { // Incremental performance optimization: only load typeck results for things that actually have inline consts - if tcx.hir_owner_nodes(tcx.hir().body_owned_by(def_id).hir_id.owner).has_inline_consts { + if tcx.hir_owner_nodes(tcx.hir().body_owned_by(def_id).id().hir_id.owner).has_inline_consts + { set.extend(tcx.typeck(def_id).inline_consts.values()) } } diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 1f966be26ff4..698f15015c48 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -158,9 +158,8 @@ fn check_liveness(tcx: TyCtxt<'_>, def_id: LocalDefId) { } let mut maps = IrMaps::new(tcx); - let body_id = tcx.hir().body_owned_by(def_id); - let hir_id = tcx.hir().body_owner(body_id); - let body = tcx.hir().body(body_id); + let body = tcx.hir().body_owned_by(def_id); + let hir_id = tcx.hir().body_owner(body.id()); if let Some(upvars) = tcx.upvars_mentioned(def_id) { for &var_hir_id in upvars.keys() { @@ -171,17 +170,17 @@ fn check_liveness(tcx: TyCtxt<'_>, def_id: LocalDefId) { // gather up the various local variables, significant expressions, // and so forth: - maps.visit_body(body); + maps.visit_body(&body); // compute liveness let mut lsets = Liveness::new(&mut maps, def_id); - let entry_ln = lsets.compute(body, hir_id); - lsets.log_liveness(entry_ln, body_id.hir_id); + let entry_ln = lsets.compute(&body, hir_id); + lsets.log_liveness(entry_ln, body.id().hir_id); // check for various error conditions - lsets.visit_body(body); + lsets.visit_body(&body); lsets.warn_about_unused_upvars(entry_ln); - lsets.warn_about_unused_args(body, entry_ln); + lsets.warn_about_unused_args(&body, entry_ln); } pub fn provide(providers: &mut Providers) { diff --git a/compiler/rustc_passes/src/upvars.rs b/compiler/rustc_passes/src/upvars.rs index 2eed58d10bb7..f2454514e4d3 100644 --- a/compiler/rustc_passes/src/upvars.rs +++ b/compiler/rustc_passes/src/upvars.rs @@ -16,17 +16,17 @@ pub fn provide(providers: &mut Providers) { } let local_def_id = def_id.expect_local(); - let body = tcx.hir().body(tcx.hir().maybe_body_owned_by(local_def_id)?); + let body = tcx.hir().maybe_body_owned_by(local_def_id)?; let mut local_collector = LocalCollector::default(); - local_collector.visit_body(body); + local_collector.visit_body(&body); let mut capture_collector = CaptureCollector { tcx, locals: &local_collector.locals, upvars: FxIndexMap::default(), }; - capture_collector.visit_body(body); + capture_collector.visit_body(&body); if !capture_collector.upvars.is_empty() { Some(tcx.arena.alloc(capture_collector.upvars)) diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index f631ae76de50..698b28c626d0 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -1695,7 +1695,7 @@ fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { rustc_ty_utils::sig_types::walk_types(tcx, def_id, &mut visitor); if let Some(body_id) = tcx.hir().maybe_body_owned_by(def_id) { - visitor.visit_nested_body(body_id); + visitor.visit_nested_body(body_id.id()); } } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 18d91a5b9a89..9336148fd672 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -907,10 +907,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { span.remove_mark(); } let mut expr_finder = FindExprBySpan::new(span, self.tcx); - let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) else { + let Some(body) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) else { return; }; - let body = self.tcx.hir().body(body_id); expr_finder.visit_expr(body.value); let Some(expr) = expr_finder.result else { return; @@ -1369,12 +1368,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { // Issue #104961, we need to add parentheses properly for compound expressions // for example, `x.starts_with("hi".to_string() + "you")` // should be `x.starts_with(&("hi".to_string() + "you"))` - let Some(body_id) = + let Some(body) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) else { return false; }; - let body = self.tcx.hir().body(body_id); let mut expr_finder = FindExprBySpan::new(span, self.tcx); expr_finder.visit_expr(body.value); let Some(expr) = expr_finder.result else { @@ -1476,10 +1474,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { span.remove_mark(); } let mut expr_finder = super::FindExprBySpan::new(span, self.tcx); - let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) else { + let Some(body) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) else { return false; }; - let body = self.tcx.hir().body(body_id); expr_finder.visit_expr(body.value); let mut maybe_suggest = |suggested_ty, count, suggestions| { // Remapping bound vars here @@ -1805,10 +1802,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ); } - let body = self.tcx.hir().body(self.tcx.hir().body_owned_by(obligation.cause.body_id)); + let body = self.tcx.hir().body_owned_by(obligation.cause.body_id); let mut visitor = ReturnsVisitor::default(); - visitor.visit_body(body); + visitor.visit_body(&body); let mut sugg = vec![(span.shrink_to_lo(), "Box<".to_string()), (span.shrink_to_hi(), ">".to_string())]; @@ -2348,13 +2345,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ?span, ); - let coroutine_body = coroutine_did - .as_local() - .and_then(|def_id| hir.maybe_body_owned_by(def_id)) - .map(|body_id| hir.body(body_id)); + let coroutine_body = + coroutine_did.as_local().and_then(|def_id| hir.maybe_body_owned_by(def_id)); let mut visitor = AwaitsVisitor::default(); if let Some(body) = coroutine_body { - visitor.visit_body(body); + visitor.visit_body(&body); } debug!(awaits = ?visitor.awaits); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 46953a61296a..8101f6cf295a 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -2451,11 +2451,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } if let Some(ty::GenericArgKind::Type(_)) = arg.map(|arg| arg.unpack()) - && let Some(body_id) = - self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) + && let Some(body) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) { let mut expr_finder = FindExprBySpan::new(span, self.tcx); - expr_finder.visit_expr(self.tcx.hir().body(body_id).value); + expr_finder.visit_expr(&body.value); if let Some(hir::Expr { kind: diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index ccc522053a65..686f2f04ad9a 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -109,7 +109,7 @@ impl<'tcx> OpaqueTypeCollector<'tcx> { #[instrument(level = "trace", skip(self))] fn collect_taits_declared_in_body(&mut self) { - let body = self.tcx.hir().body(self.tcx.hir().body_owned_by(self.item)).value; + let body = self.tcx.hir().body_owned_by(self.item).value; struct TaitInBodyFinder<'a, 'tcx> { collector: &'a mut OpaqueTypeCollector<'tcx>, } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 7490688e36c5..711aef34c27e 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -2133,7 +2133,9 @@ impl Discriminant { /// Will be `None` in the case of cross-crate reexports, and may be /// simplified pub(crate) fn expr(&self, tcx: TyCtxt<'_>) -> Option { - self.expr.map(|body| rendered_const(tcx, body)) + self.expr.map(|body| { + rendered_const(tcx, tcx.hir().body(body), tcx.hir().body_owner_def_id(body)) + }) } pub(crate) fn value(&self, tcx: TyCtxt<'_>, with_underscores: bool) -> String { print_evaluated_const(tcx, self.value, with_underscores, false).unwrap() @@ -2419,7 +2421,7 @@ impl ConstantKind { ConstantKind::TyConst { ref expr } => expr.to_string(), ConstantKind::Extern { def_id } => print_inlined_const(tcx, def_id), ConstantKind::Local { body, .. } | ConstantKind::Anonymous { body } => { - rendered_const(tcx, body) + rendered_const(tcx, tcx.hir().body(body), tcx.hir().body_owner_def_id(body)) } } } diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index aa923cc61173..803650beaf67 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -342,7 +342,7 @@ pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String { match n.kind() { ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args: _ }) => { let s = if let Some(def) = def.as_local() { - rendered_const(cx.tcx, cx.tcx.hir().body_owned_by(def)) + rendered_const(cx.tcx, &cx.tcx.hir().body_owned_by(def), def) } else { inline::print_inlined_const(cx.tcx, def) }; diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 932295270765..ccd5dadb20a0 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -284,9 +284,9 @@ pub(crate) fn create_config( } let hir = tcx.hir(); - let body = hir.body(hir.body_owned_by(def_id)); + let body = hir.body_owned_by(def_id); debug!("visiting body for {def_id:?}"); - EmitIgnoredResolutionErrors::new(tcx).visit_body(body); + EmitIgnoredResolutionErrors::new(tcx).visit_body(&body); (rustc_interface::DEFAULT_QUERY_PROVIDERS.typeck)(tcx, def_id) }; }), diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs index 8ee35db56f8d..0535246ae10f 100644 --- a/src/librustdoc/html/render/span_map.rs +++ b/src/librustdoc/html/render/span_map.rs @@ -162,9 +162,7 @@ impl<'tcx> SpanMapVisitor<'tcx> { // compiled (because of cfg)! // // See discussion in https://github.com/rust-lang/rust/issues/69426#issuecomment-1019412352 - let typeck_results = self - .tcx - .typeck_body(hir.maybe_body_owned_by(body_id).expect("a body which isn't a body")); + let typeck_results = self.tcx.typeck_body(hir.body_owned_by(body_id).id()); // Interestingly enough, for method calls, we need the whole expression whereas for static // method/function calls, we need the call expression specifically. if let Some(def_id) = typeck_results.type_dependent_def_id(expr_hir_id.unwrap_or(hir_id)) { diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index f856b4e9f16c..7f5c12219b87 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -820,7 +820,10 @@ impl FromWithTcx for Static { Static { type_: stat.type_.into_tcx(tcx), mutable: stat.mutability == ast::Mutability::Mut, - expr: stat.expr.map(|e| rendered_const(tcx, e)).unwrap_or_default(), + expr: stat + .expr + .map(|e| rendered_const(tcx, tcx.hir().body(e), tcx.hir().body_owner_def_id(e))) + .unwrap_or_default(), } } } diff --git a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs index efec9dd716dc..ca331f3e7568 100644 --- a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs +++ b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs @@ -59,8 +59,8 @@ pub(super) fn check<'tcx>( }; let map = cx.tcx.hir(); - let body = map.body(map.body_owned_by(map.enclosing_body_owner(expr.hir_id))); - reference_visitor.visit_body(body); + let body = map.body_owned_by(map.enclosing_body_owner(expr.hir_id)); + reference_visitor.visit_body(&body); if reference_visitor.found_reference { return; diff --git a/src/tools/clippy/clippy_lints/src/single_call_fn.rs b/src/tools/clippy/clippy_lints/src/single_call_fn.rs index 2ce7e714c642..f8e09d517f57 100644 --- a/src/tools/clippy/clippy_lints/src/single_call_fn.rs +++ b/src/tools/clippy/clippy_lints/src/single_call_fn.rs @@ -79,7 +79,6 @@ impl SingleCallFn { .tcx .hir() .maybe_body_owned_by(fn_def_id) - .map(|body| cx.tcx.hir().body(body)) .map_or(true, |body| is_in_test_function(cx.tcx, body.value.hir_id)) || match cx.tcx.hir_node(fn_hir_id) { Node::Item(item) => is_from_proc_macro(cx, item), diff --git a/src/tools/clippy/clippy_lints/src/transmute/missing_transmute_annotations.rs b/src/tools/clippy/clippy_lints/src/transmute/missing_transmute_annotations.rs index cc6ff1cf3b42..f98ea59a15d8 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/missing_transmute_annotations.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/missing_transmute_annotations.rs @@ -30,8 +30,8 @@ fn get_parent_local_binding_ty<'tcx>(cx: &LateContext<'tcx>, expr_hir_id: HirId) fn is_function_block(cx: &LateContext<'_>, expr_hir_id: HirId) -> bool { let def_id = cx.tcx.hir().enclosing_body_owner(expr_hir_id); - if let Some(body_id) = cx.tcx.hir().maybe_body_owned_by(def_id) { - let body = cx.tcx.hir().body(body_id); + if let Some(body) = cx.tcx.hir().maybe_body_owned_by(def_id) { + let body = cx.tcx.hir().body(body.id()); return body.value.peel_blocks().hir_id == expr_hir_id; } false diff --git a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs index 0c4e2c91aec5..5e41b3f4914f 100644 --- a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs +++ b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs @@ -336,7 +336,7 @@ impl UnconditionalRecursion { // We need to use typeck here to infer the actual function being called. && let body_def_id = cx.tcx.hir().enclosing_body_owner(call_expr.hir_id) && let Some(body_owner) = cx.tcx.hir().maybe_body_owned_by(body_def_id) - && let typeck = cx.tcx.typeck_body(body_owner) + && let typeck = cx.tcx.typeck_body(body_owner.id()) && let Some(call_def_id) = typeck.type_dependent_def_id(call_expr.hir_id) { self.default_impl_for_type.insert(self_def_id, call_def_id); diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index 4448c9ae3df7..18a31abddd0a 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -137,9 +137,9 @@ impl<'tcx> LateLintPass<'tcx> for Author { fn check_item(cx: &LateContext<'_>, hir_id: HirId) { let hir = cx.tcx.hir(); - if let Some(body_id) = hir.maybe_body_owned_by(hir_id.expect_owner().def_id) { + if let Some(body) = hir.maybe_body_owned_by(hir_id.expect_owner().def_id) { check_node(cx, hir_id, |v| { - v.expr(&v.bind("expr", hir.body(body_id).value)); + v.expr(&v.bind("expr", body.value)); }); } } diff --git a/tests/ui/inline-const/uninit_local.rs b/tests/ui/inline-const/uninit_local.rs new file mode 100644 index 000000000000..548c053affc7 --- /dev/null +++ b/tests/ui/inline-const/uninit_local.rs @@ -0,0 +1,6 @@ +fn main() { + let _my_usize = const { + let x: bool; + while x {} //~ ERROR: `x` isn't initialized + }; +} diff --git a/tests/ui/inline-const/uninit_local.stderr b/tests/ui/inline-const/uninit_local.stderr new file mode 100644 index 000000000000..37b78e337e7b --- /dev/null +++ b/tests/ui/inline-const/uninit_local.stderr @@ -0,0 +1,16 @@ +error[E0381]: used binding `x` isn't initialized + --> $DIR/uninit_local.rs:4:15 + | +LL | let x: bool; + | - binding declared here but left uninitialized +LL | while x {} + | ^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: bool = false; + | +++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0381`. From d5bd4e233d2bb4415138e384e66379eedbc7e76e Mon Sep 17 00:00:00 2001 From: Boxy Date: Wed, 29 May 2024 17:06:50 +0100 Subject: [PATCH 076/211] Partially implement `ConstArgHasType` --- .../rustc_infer/src/infer/relate/combine.rs | 9 +- .../rustc_trait_selection/src/solve/mod.rs | 26 +++- .../error_reporting/type_err_ctxt_ext.rs | 16 +++ .../src/traits/fulfill.rs | 41 ++++-- .../src/traits/select/mod.rs | 19 ++- .../121858.rs} | 7 +- tests/crashes/122638.rs | 12 -- tests/crashes/123141-2.rs | 23 ---- tests/crashes/123141.rs | 27 ++-- .../generic_const_type_mismatch.rs | 1 + .../generic_const_type_mismatch.stderr | 14 +- .../alias_const_param_ty-1.rs} | 4 +- .../alias_const_param_ty-1.stderr | 19 +++ .../alias_const_param_ty-2.rs} | 11 +- .../alias_const_param_ty-2.stderr | 11 ++ .../ui/const-generics/bad-subst-const-kind.rs | 6 +- .../bad-subst-const-kind.stderr | 17 ++- .../const-generics/defaults/doesnt_infer.rs | 4 +- .../defaults/doesnt_infer.stderr | 2 +- .../generic_arg_infer/issue-91614.rs | 2 +- ...-125520-layout-mismatch-mulwithoverflow.rs | 27 ---- ...520-layout-mismatch-mulwithoverflow.stderr | 125 ------------------ .../generic_const_exprs/type_mismatch.rs | 2 +- .../generic_const_exprs/type_mismatch.stderr | 14 +- .../ui/const-generics/issues/issue-105821.rs | 11 +- .../const-generics/issues/issue-105821.stderr | 8 -- tests/ui/consts/eval_type_mismatch.stderr | 34 ----- tests/ui/inference/issue-83606.rs | 2 +- .../bad-const-wf-doesnt-specialize.rs | 3 +- .../bad-const-wf-doesnt-specialize.stderr | 36 ++--- 30 files changed, 206 insertions(+), 327 deletions(-) rename tests/{ui/consts/eval_type_mismatch.rs => crashes/121858.rs} (53%) delete mode 100644 tests/crashes/122638.rs delete mode 100644 tests/crashes/123141-2.rs rename tests/{crashes/114456.rs => ui/const-generics/adt_const_params/alias_const_param_ty-1.rs} (69%) create mode 100644 tests/ui/const-generics/adt_const_params/alias_const_param_ty-1.stderr rename tests/{crashes/114456-2.rs => ui/const-generics/adt_const_params/alias_const_param_ty-2.rs} (64%) create mode 100644 tests/ui/const-generics/adt_const_params/alias_const_param_ty-2.stderr delete mode 100644 tests/ui/const-generics/generic_const_exprs/ice-125520-layout-mismatch-mulwithoverflow.rs delete mode 100644 tests/ui/const-generics/generic_const_exprs/ice-125520-layout-mismatch-mulwithoverflow.stderr delete mode 100644 tests/ui/const-generics/issues/issue-105821.stderr delete mode 100644 tests/ui/consts/eval_type_mismatch.stderr diff --git a/compiler/rustc_infer/src/infer/relate/combine.rs b/compiler/rustc_infer/src/infer/relate/combine.rs index 7e7d4f43c7cc..e721c36dec3d 100644 --- a/compiler/rustc_infer/src/infer/relate/combine.rs +++ b/compiler/rustc_infer/src/infer/relate/combine.rs @@ -22,11 +22,10 @@ use super::glb::Glb; use super::lub::Lub; use super::type_relating::TypeRelating; use super::StructurallyRelateAliases; -use crate::infer::{DefineOpaqueTypes, InferCtxt, InferOk, TypeTrace}; +use crate::infer::{DefineOpaqueTypes, InferCtxt, TypeTrace}; use crate::traits::{Obligation, PredicateObligations}; use rustc_middle::bug; use rustc_middle::infer::unify_key::EffectVarValue; -use rustc_middle::traits::ObligationCause; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::relate::{RelateResult, TypeRelation}; use rustc_middle::ty::{self, InferConst, Ty, TyCtxt, TypeVisitableExt, Upcast}; @@ -159,12 +158,6 @@ impl<'tcx> InferCtxt<'tcx> { let a = self.shallow_resolve_const(a); let b = self.shallow_resolve_const(b); - // It is always an error if the types of two constants that are related are not equal. - let InferOk { value: (), obligations } = self - .at(&ObligationCause::dummy_with_span(relation.span()), relation.param_env()) - .eq(DefineOpaqueTypes::No, a.ty(), b.ty())?; - relation.register_obligations(obligations); - match (a.kind(), b.kind()) { ( ty::ConstKind::Infer(InferConst::Var(a_vid)), diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index a432090f78cd..f9febd290fe7 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -197,8 +197,30 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> { goal: Goal<'tcx, (ty::Const<'tcx>, Ty<'tcx>)>, ) -> QueryResult<'tcx> { let (ct, ty) = goal.predicate; - self.eq(goal.param_env, ct.ty(), ty)?; - self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + + // FIXME(BoxyUwU): Really we should not be calling `ct.ty()` for any variant + // other than `ConstKind::Value`. Unfortunately this would require looking in the + // env for any `ConstArgHasType` assumptions for parameters and placeholders. I + // have not yet gotten around to implementing this though. + // + // We do still stall on infer vars though as otherwise a goal like: + // `ConstArgHasType(?x: usize, usize)` can succeed even though it might later + // get unified with some const that is not of type `usize`. + match ct.kind() { + // FIXME: Ignore effect vars because canonicalization doesn't handle them correctly + // and if we stall on the var then we wind up creating ambiguity errors in a probe + // for this goal which contains an effect var. Which then ends up ICEing. + ty::ConstKind::Infer(ty::InferConst::Var(_)) => { + self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) + } + ty::ConstKind::Error(_) => { + self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + } + _ => { + self.eq(goal.param_env, ct.ty(), ty)?; + self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + } + } } } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 46953a61296a..7f995b315f74 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -2685,6 +2685,22 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { .with_span_label(span, format!("cannot satisfy `{predicate}`")) } } + + // Given some `ConstArgHasType(?x, usize)`, we should not emit an error such as + // "type annotations needed: cannot satisfy the constant `_` has type `usize`" + // Instead we should emit a normal error suggesting the user to turbofish the + // const parameter that is currently being inferred. Unfortunately we cannot + // nicely emit such an error so we delay an ICE incase nobody else reports it + // for us. + ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => { + return self.tcx.sess.dcx().span_delayed_bug( + span, + format!( + "`ambiguous ConstArgHasType({:?}, {:?}) unaccompanied by inference error`", + ct, ty + ), + ); + } _ => { if let Some(e) = self.tainted_by_errors() { return e; diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 07fcf109fdaa..c64d1be751cb 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -429,16 +429,37 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { // This is because this is not ever a useful obligation to report // as the cause of an overflow. ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => { - match self.selcx.infcx.at(&obligation.cause, obligation.param_env).eq( - // Only really excercised by generic_const_exprs - DefineOpaqueTypes::Yes, - ct.ty(), - ty, - ) { - Ok(inf_ok) => ProcessResult::Changed(mk_pending(inf_ok.into_obligations())), - Err(_) => ProcessResult::Error(FulfillmentErrorCode::Select( - SelectionError::Unimplemented, - )), + // FIXME(BoxyUwU): Really we should not be calling `ct.ty()` for any variant + // other than `ConstKind::Value`. Unfortunately this would require looking in the + // env for any `ConstArgHasType` assumptions for parameters and placeholders. I + // don't really want to implement this in the old solver so I haven't. + // + // We do still stall on infer vars though as otherwise a goal like: + // `ConstArgHasType(?x: usize, usize)` can succeed even though it might later + // get unified with some const that is not of type `usize`. + let ct = self.selcx.infcx.shallow_resolve_const(ct); + match ct.kind() { + ty::ConstKind::Infer(ty::InferConst::Var(vid)) => { + pending_obligation.stalled_on.clear(); + pending_obligation.stalled_on.extend([TyOrConstInferVar::Const(vid)]); + ProcessResult::Unchanged + } + ty::ConstKind::Error(_) => return ProcessResult::Changed(vec![]), + _ => { + match self.selcx.infcx.at(&obligation.cause, obligation.param_env).eq( + // Only really excercised by generic_const_exprs + DefineOpaqueTypes::Yes, + ct.ty(), + ty, + ) { + Ok(inf_ok) => { + ProcessResult::Changed(mk_pending(inf_ok.into_obligations())) + } + Err(_) => ProcessResult::Error(FulfillmentErrorCode::Select( + SelectionError::Unimplemented, + )), + } + } } } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 696b1c151153..1f53e8cc671d 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -992,10 +992,27 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } ty::PredicateKind::Ambiguous => Ok(EvaluatedToAmbig), ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => { + // FIXME(BoxyUwU): Really we should not be calling `ct.ty()` for any variant + // other than `ConstKind::Value`. Unfortunately this would require looking in the + // env for any `ConstArgHasType` assumptions for parameters and placeholders. I + // don't really want to implement this in the old solver so I haven't. + // + // We do still stall on infer vars though as otherwise a goal like: + // `ConstArgHasType(?x: usize, usize)` can succeed even though it might later + // get unified with some const that is not of type `usize`. + let ct = self.infcx.shallow_resolve_const(ct); + let ct_ty = match ct.kind() { + ty::ConstKind::Infer(ty::InferConst::Var(_)) => { + return Ok(EvaluatedToAmbig); + } + ty::ConstKind::Error(_) => return Ok(EvaluatedToOk), + _ => ct.ty(), + }; + match self.infcx.at(&obligation.cause, obligation.param_env).eq( // Only really excercised by generic_const_exprs DefineOpaqueTypes::Yes, - ct.ty(), + ct_ty, ty, ) { Ok(inf_ok) => self.evaluate_predicates_recursively( diff --git a/tests/ui/consts/eval_type_mismatch.rs b/tests/crashes/121858.rs similarity index 53% rename from tests/ui/consts/eval_type_mismatch.rs rename to tests/crashes/121858.rs index 3d821ab538ec..7d5bae37f846 100644 --- a/tests/ui/consts/eval_type_mismatch.rs +++ b/tests/crashes/121858.rs @@ -1,17 +1,14 @@ +//@ known-bug: #121858 #![feature(generic_const_exprs)] -#![allow(incomplete_features)] struct Outer(); impl Outer -//~^ ERROR: `A` is not of type `i64` -//~| ERROR: mismatched types where [(); A + (B * 2)]:, { - fn o() {} + fn o() -> Union {} } fn main() { Outer::<1, 1>::o(); - //~^ ERROR: no function or associated item named `o` found } diff --git a/tests/crashes/122638.rs b/tests/crashes/122638.rs deleted file mode 100644 index af0fc5bbd503..000000000000 --- a/tests/crashes/122638.rs +++ /dev/null @@ -1,12 +0,0 @@ -//@ known-bug: #122638 -#![feature(min_specialization)] - -impl<'a, T: std::fmt::Debug, const N: usize> Iterator for ConstChunksExact<'a, T, { N }> { - fn next(&mut self) -> Option {} -} - -struct ConstChunksExact<'a, T: '_, const assert: usize> {} - -impl<'a, T: std::fmt::Debug, const N: usize> Iterator for ConstChunksExact<'a, T, {}> { - type Item = &'a [T; N]; -} diff --git a/tests/crashes/123141-2.rs b/tests/crashes/123141-2.rs deleted file mode 100644 index 74f961c2a337..000000000000 --- a/tests/crashes/123141-2.rs +++ /dev/null @@ -1,23 +0,0 @@ -//@ known-bug: #123141 - -trait ConstChunksExactTrait { - fn const_chunks_exact(&self) -> ConstChunksExact<'_, T, {N}>; -} - -impl ConstChunksExactTrait for [T] {} - -struct ConstChunksExact<'a, T: 'a, const N: usize> {} - -impl <'a, T: , const N: usize> Iterator for ConstChunksExact<'a, T, {rem}> { - type Item = &'a [T; N]; -} - -fn main() { - let slice = &[1i32, 2, 3, 4, 5, 6, 7, 7, 9, 1i32]; - - let mut iter = [[1, 2, 3], [4, 5, 6], [7, 8 ,9]].iter(); - - for a in slice.const_chunks_exact::<3>() { - assert_eq!(a, iter.next().unwrap()); - } -} diff --git a/tests/crashes/123141.rs b/tests/crashes/123141.rs index 99dfee7670ef..07181387e045 100644 --- a/tests/crashes/123141.rs +++ b/tests/crashes/123141.rs @@ -1,22 +1,23 @@ //@ known-bug: #123141 -trait ConstChunksExactTrait { - fn const_chunks_exact(&self) -> ConstChunksExact<'_, T, { N }>; + +trait Trait { + fn next(self) -> Self::Item; + type Item; } -impl ConstChunksExactTrait for [T] {} +struct Foo(T); -struct ConstChunksExact<'a, T: 'a, const N: usize> {} +impl Trait for Foo { + type Item = Foo; + fn next(self) -> Self::Item { + loop {} + } +} -impl<'a, T, const N: usize> Iterator for ConstChunksExact<'a, T, { rem }> { - type Item = &'a [T; N]; +fn opaque() -> impl Trait { + Foo::<_>(10_u32) } fn main() { - let slice = &[1i32, 2, 3, 4, 5, 6, 7, 7, 9, 1i32]; - - let mut iter = [[1, 2, 3], [4, 5, 6], [7, 8, 9]].iter(); - - for a in slice.const_chunks_exact::<3>() { - assert_eq!(a, iter.next().unwrap()); - } + opaque().next(); } 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 89d0b74d4030..fa0b0fdc136a 100644 --- a/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.rs +++ b/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.rs @@ -8,5 +8,6 @@ impl Trait for [(); N] {} //~^ ERROR: mismatched types impl Trait for [(); N] {} //~^ ERROR: mismatched types +//~| ERROR: conflicting implementations of trait `Trait` 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 d19502546602..d65450845bc1 100644 --- a/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.stderr +++ b/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.stderr @@ -1,3 +1,12 @@ +error[E0119]: conflicting implementations of trait `Trait` for type `[(); _]` + --> $DIR/generic_const_type_mismatch.rs:9: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 | @@ -10,6 +19,7 @@ error[E0308]: mismatched types LL | impl Trait for [(); N] {} | ^ expected `usize`, found `i8` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0119, E0308. +For more information about an error, try `rustc --explain E0119`. diff --git a/tests/crashes/114456.rs b/tests/ui/const-generics/adt_const_params/alias_const_param_ty-1.rs similarity index 69% rename from tests/crashes/114456.rs rename to tests/ui/const-generics/adt_const_params/alias_const_param_ty-1.rs index e347327e7386..8035fce09147 100644 --- a/tests/crashes/114456.rs +++ b/tests/ui/const-generics/adt_const_params/alias_const_param_ty-1.rs @@ -1,5 +1,7 @@ -//@ known-bug: #114456 +//@ check-pass #![feature(adt_const_params, lazy_type_alias)] +//~^ WARN: the feature `adt_const_params` is incomplete +//~| WARN: the feature `lazy_type_alias` is incomplete pub type Matrix = [usize; 1]; const EMPTY_MATRIX: Matrix = [0; 1]; diff --git a/tests/ui/const-generics/adt_const_params/alias_const_param_ty-1.stderr b/tests/ui/const-generics/adt_const_params/alias_const_param_ty-1.stderr new file mode 100644 index 000000000000..5c6981077b2d --- /dev/null +++ b/tests/ui/const-generics/adt_const_params/alias_const_param_ty-1.stderr @@ -0,0 +1,19 @@ +warning: the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/alias_const_param_ty-1.rs:2:12 + | +LL | #![feature(adt_const_params, lazy_type_alias)] + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #95174 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: the feature `lazy_type_alias` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/alias_const_param_ty-1.rs:2:30 + | +LL | #![feature(adt_const_params, lazy_type_alias)] + | ^^^^^^^^^^^^^^^ + | + = note: see issue #112792 for more information + +warning: 2 warnings emitted + diff --git a/tests/crashes/114456-2.rs b/tests/ui/const-generics/adt_const_params/alias_const_param_ty-2.rs similarity index 64% rename from tests/crashes/114456-2.rs rename to tests/ui/const-generics/adt_const_params/alias_const_param_ty-2.rs index eca27febb968..a576b75341cf 100644 --- a/tests/crashes/114456-2.rs +++ b/tests/ui/const-generics/adt_const_params/alias_const_param_ty-2.rs @@ -1,5 +1,6 @@ -//@ known-bug: #114456 +//@ check-pass #![feature(adt_const_params)] +//~^ WARN: the feature `adt_const_params` is incomplete const EMPTY_MATRIX: ::Matrix = [0; 1]; @@ -12,8 +13,12 @@ impl Walk { } pub enum Type {} -pub trait Trait { type Matrix; } -impl Trait for Type { type Matrix = [usize; 1]; } +pub trait Trait { + type Matrix; +} +impl Trait for Type { + type Matrix = [usize; 1]; +} fn main() { let _ = Walk::new(); diff --git a/tests/ui/const-generics/adt_const_params/alias_const_param_ty-2.stderr b/tests/ui/const-generics/adt_const_params/alias_const_param_ty-2.stderr new file mode 100644 index 000000000000..dbc8ab716365 --- /dev/null +++ b/tests/ui/const-generics/adt_const_params/alias_const_param_ty-2.stderr @@ -0,0 +1,11 @@ +warning: the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/alias_const_param_ty-2.rs:2:12 + | +LL | #![feature(adt_const_params)] + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #95174 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/const-generics/bad-subst-const-kind.rs b/tests/ui/const-generics/bad-subst-const-kind.rs index 88f98a54b6e6..d5913879191e 100644 --- a/tests/ui/const-generics/bad-subst-const-kind.rs +++ b/tests/ui/const-generics/bad-subst-const-kind.rs @@ -10,5 +10,7 @@ impl Q for [u8; N] { const ASSOC: usize = 1; } -pub fn test() -> [u8; <[u8; 13] as Q>::ASSOC] { todo!() } -//~^ ERROR: `[u8; 13]: Q` is not satisfied +pub fn test() -> [u8; <[u8; 13] as Q>::ASSOC] { + //~^ ERROR: the constant `13` is not of type `u64` + todo!() +} diff --git a/tests/ui/const-generics/bad-subst-const-kind.stderr b/tests/ui/const-generics/bad-subst-const-kind.stderr index 6cf9fa743b34..6725f6762e45 100644 --- a/tests/ui/const-generics/bad-subst-const-kind.stderr +++ b/tests/ui/const-generics/bad-subst-const-kind.stderr @@ -1,10 +1,16 @@ -error[E0277]: the trait bound `[u8; 13]: Q` is not satisfied +error: the constant `13` is not of type `u64` --> $DIR/bad-subst-const-kind.rs:13:24 | -LL | pub fn test() -> [u8; <[u8; 13] as Q>::ASSOC] { todo!() } - | ^^^^^^^^ the trait `Q` is not implemented for `[u8; 13]` +LL | pub fn test() -> [u8; <[u8; 13] as Q>::ASSOC] { + | ^^^^^^^^ expected `u64`, found `usize` | - = help: the trait `Q` is implemented for `[u8; N]` +note: required for `[u8; 13]` to implement `Q` + --> $DIR/bad-subst-const-kind.rs:8:20 + | +LL | impl Q for [u8; N] { + | ------------ ^ ^^^^^^^ + | | + | unsatisfied trait bound introduced here error[E0308]: mismatched types --> $DIR/bad-subst-const-kind.rs:8:31 @@ -14,5 +20,4 @@ LL | impl Q for [u8; N] { error: aborting due to 2 previous errors -Some errors have detailed explanations: E0277, E0308. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/defaults/doesnt_infer.rs b/tests/ui/const-generics/defaults/doesnt_infer.rs index e14c08fc1487..016685eee9df 100644 --- a/tests/ui/const-generics/defaults/doesnt_infer.rs +++ b/tests/ui/const-generics/defaults/doesnt_infer.rs @@ -3,7 +3,9 @@ struct Foo; impl Foo { - fn foo() -> Self { loop {} } + fn foo() -> Self { + loop {} + } } fn main() { diff --git a/tests/ui/const-generics/defaults/doesnt_infer.stderr b/tests/ui/const-generics/defaults/doesnt_infer.stderr index 93d586033971..1e779f75ce08 100644 --- a/tests/ui/const-generics/defaults/doesnt_infer.stderr +++ b/tests/ui/const-generics/defaults/doesnt_infer.stderr @@ -1,5 +1,5 @@ error[E0282]: type annotations needed for `Foo<_>` - --> $DIR/doesnt_infer.rs:11:9 + --> $DIR/doesnt_infer.rs:13:9 | LL | let foo = Foo::foo(); | ^^^ diff --git a/tests/ui/const-generics/generic_arg_infer/issue-91614.rs b/tests/ui/const-generics/generic_arg_infer/issue-91614.rs index b45e2cbc7372..cfbc5faecd9c 100644 --- a/tests/ui/const-generics/generic_arg_infer/issue-91614.rs +++ b/tests/ui/const-generics/generic_arg_infer/issue-91614.rs @@ -4,5 +4,5 @@ use std::simd::Mask; fn main() { let y = Mask::<_, _>::splat(false); - //~^ ERROR: type annotations needed for + //~^ ERROR: type annotations needed } diff --git a/tests/ui/const-generics/generic_const_exprs/ice-125520-layout-mismatch-mulwithoverflow.rs b/tests/ui/const-generics/generic_const_exprs/ice-125520-layout-mismatch-mulwithoverflow.rs deleted file mode 100644 index cd2dc3f4fe85..000000000000 --- a/tests/ui/const-generics/generic_const_exprs/ice-125520-layout-mismatch-mulwithoverflow.rs +++ /dev/null @@ -1,27 +0,0 @@ -// issue: rust-lang/rust#125520 -#![feature(generic_const_exprs)] -//~^ WARN the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes - -struct Outer(); -impl Outer -//~^ ERROR the constant `A` is not of type `i64` -//~| ERROR the constant `B` is not of type `i64` -//~| ERROR mismatched types -//~| ERROR mismatched types -where - [(); A + (B * 2)]:, -{ - fn i() -> Self { - //~^ ERROR the constant `A` is not of type `i64` - //~| ERROR the constant `B` is not of type `i64` - Self - //~^ ERROR mismatched types - //~| ERROR the constant `A` is not of type `i64` - //~| ERROR the constant `B` is not of type `i64` - } -} - -fn main() { - Outer::<1, 1>::o(); - //~^ ERROR no function or associated item named `o` found for struct `Outer` in the current scope -} diff --git a/tests/ui/const-generics/generic_const_exprs/ice-125520-layout-mismatch-mulwithoverflow.stderr b/tests/ui/const-generics/generic_const_exprs/ice-125520-layout-mismatch-mulwithoverflow.stderr deleted file mode 100644 index 2dbd69fd3bc1..000000000000 --- a/tests/ui/const-generics/generic_const_exprs/ice-125520-layout-mismatch-mulwithoverflow.stderr +++ /dev/null @@ -1,125 +0,0 @@ -warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/ice-125520-layout-mismatch-mulwithoverflow.rs:2:12 - | -LL | #![feature(generic_const_exprs)] - | ^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #76560 for more information - = note: `#[warn(incomplete_features)]` on by default - -error: the constant `A` is not of type `i64` - --> $DIR/ice-125520-layout-mismatch-mulwithoverflow.rs:6:38 - | -LL | impl Outer - | ^^^^^^^^^^^ expected `i64`, found `usize` - | -note: required by a bound in `Outer` - --> $DIR/ice-125520-layout-mismatch-mulwithoverflow.rs:5:14 - | -LL | struct Outer(); - | ^^^^^^^^^^^^ required by this bound in `Outer` - -error: the constant `B` is not of type `i64` - --> $DIR/ice-125520-layout-mismatch-mulwithoverflow.rs:6:38 - | -LL | impl Outer - | ^^^^^^^^^^^ expected `i64`, found `usize` - | -note: required by a bound in `Outer` - --> $DIR/ice-125520-layout-mismatch-mulwithoverflow.rs:5:28 - | -LL | struct Outer(); - | ^^^^^^^^^^^^ required by this bound in `Outer` - -error: the constant `A` is not of type `i64` - --> $DIR/ice-125520-layout-mismatch-mulwithoverflow.rs:14:15 - | -LL | fn i() -> Self { - | ^^^^ expected `i64`, found `usize` - | -note: required by a bound in `Outer` - --> $DIR/ice-125520-layout-mismatch-mulwithoverflow.rs:5:14 - | -LL | struct Outer(); - | ^^^^^^^^^^^^ required by this bound in `Outer` - -error: the constant `B` is not of type `i64` - --> $DIR/ice-125520-layout-mismatch-mulwithoverflow.rs:14:15 - | -LL | fn i() -> Self { - | ^^^^ expected `i64`, found `usize` - | -note: required by a bound in `Outer` - --> $DIR/ice-125520-layout-mismatch-mulwithoverflow.rs:5:28 - | -LL | struct Outer(); - | ^^^^^^^^^^^^ required by this bound in `Outer` - -error[E0308]: mismatched types - --> $DIR/ice-125520-layout-mismatch-mulwithoverflow.rs:17:9 - | -LL | struct Outer(); - | ---------------------------------------- `Outer` defines a struct constructor here, which should be called -... -LL | fn i() -> Self { - | ---- expected `Outer` because of return type -... -LL | Self - | ^^^^ expected `Outer`, found struct constructor - | - = note: expected struct `Outer` - found struct constructor `fn() -> Outer {Outer::}` -help: use parentheses to construct this tuple struct - | -LL | Self() - | ++ - -error: the constant `A` is not of type `i64` - --> $DIR/ice-125520-layout-mismatch-mulwithoverflow.rs:17:9 - | -LL | Self - | ^^^^ expected `i64`, found `usize` - | -note: required by a bound in `Outer` - --> $DIR/ice-125520-layout-mismatch-mulwithoverflow.rs:5:14 - | -LL | struct Outer(); - | ^^^^^^^^^^^^ required by this bound in `Outer` - -error: the constant `B` is not of type `i64` - --> $DIR/ice-125520-layout-mismatch-mulwithoverflow.rs:17:9 - | -LL | Self - | ^^^^ expected `i64`, found `usize` - | -note: required by a bound in `Outer` - --> $DIR/ice-125520-layout-mismatch-mulwithoverflow.rs:5:28 - | -LL | struct Outer(); - | ^^^^^^^^^^^^ required by this bound in `Outer` - -error[E0599]: no function or associated item named `o` found for struct `Outer` in the current scope - --> $DIR/ice-125520-layout-mismatch-mulwithoverflow.rs:25:20 - | -LL | struct Outer(); - | ---------------------------------------- function or associated item `o` not found for this struct -... -LL | Outer::<1, 1>::o(); - | ^ function or associated item not found in `Outer<1, 1>` - -error[E0308]: mismatched types - --> $DIR/ice-125520-layout-mismatch-mulwithoverflow.rs:6:44 - | -LL | impl Outer - | ^ expected `i64`, found `usize` - -error[E0308]: mismatched types - --> $DIR/ice-125520-layout-mismatch-mulwithoverflow.rs:6:47 - | -LL | impl Outer - | ^ expected `i64`, found `usize` - -error: aborting due to 10 previous errors; 1 warning emitted - -Some errors have detailed explanations: E0308, E0599. -For more information about an 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 285f9dee6c27..6b0d9e047dbc 100644 --- a/tests/ui/const-generics/generic_const_exprs/type_mismatch.rs +++ b/tests/ui/const-generics/generic_const_exprs/type_mismatch.rs @@ -10,7 +10,7 @@ impl Q for [u8; N] {} //~| ERROR mismatched types pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {} -//~^ ERROR `[u8; 13]: Q` is not satisfied +//~^ ERROR the constant `13` is not of type `u64` //~| ERROR mismatched types pub fn main() {} 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 a63a56dd6753..bb6d650b7ab2 100644 --- a/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr +++ b/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr @@ -7,13 +7,19 @@ LL | const ASSOC: usize; LL | impl Q for [u8; N] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `ASSOC` in implementation -error[E0277]: the trait bound `[u8; 13]: Q` is not satisfied +error: the constant `13` is not of type `u64` --> $DIR/type_mismatch.rs:12:26 | LL | pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {} - | ^^^^^^^^ the trait `Q` is not implemented for `[u8; 13]` + | ^^^^^^^^ expected `u64`, found `usize` | - = help: the trait `Q` is implemented for `[u8; N]` +note: required for `[u8; 13]` to implement `Q` + --> $DIR/type_mismatch.rs:8:20 + | +LL | impl Q for [u8; N] {} + | ------------ ^ ^^^^^^^ + | | + | unsatisfied trait bound introduced here error[E0308]: mismatched types --> $DIR/type_mismatch.rs:12:20 @@ -31,5 +37,5 @@ LL | impl Q for [u8; N] {} error: aborting due to 4 previous errors -Some errors have detailed explanations: E0046, E0277, E0308. +Some errors have detailed explanations: E0046, E0308. For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/const-generics/issues/issue-105821.rs b/tests/ui/const-generics/issues/issue-105821.rs index e55da461605e..ecbae4d9f35c 100644 --- a/tests/ui/const-generics/issues/issue-105821.rs +++ b/tests/ui/const-generics/issues/issue-105821.rs @@ -1,10 +1,7 @@ -//@ failure-status: 101 -//@ known-bug: rust-lang/rust#125451 -//@ normalize-stderr-test "note: .*\n\n" -> "" -//@ normalize-stderr-test "thread 'rustc' panicked.*\n.*\n" -> "" -//@ normalize-stderr-test "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: " -//@ normalize-stderr-test "delayed at .*" -> "" -//@ rustc-env:RUST_BACKTRACE=0 +//@ check-pass +// If this test starts failing because it ICEs due to not being able to convert a `ReErased` to +// something then feel free to just convert this to a known-bug. I'm pretty sure this is still +// a failing test, we just started masking the bug. #![allow(incomplete_features)] #![feature(adt_const_params, generic_const_exprs)] diff --git a/tests/ui/const-generics/issues/issue-105821.stderr b/tests/ui/const-generics/issues/issue-105821.stderr deleted file mode 100644 index 1f0fc0f33ce4..000000000000 --- a/tests/ui/const-generics/issues/issue-105821.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: internal compiler error: compiler/rustc_borrowck/src/universal_regions.rs:LL:CC: cannot convert `'{erased}` to a region vid - -query stack during panic: -#0 [mir_borrowck] borrow-checking `::R` -#1 [analysis] running analysis passes on this crate -end of query stack -error: aborting due to 1 previous error - diff --git a/tests/ui/consts/eval_type_mismatch.stderr b/tests/ui/consts/eval_type_mismatch.stderr deleted file mode 100644 index 38d6e33d4067..000000000000 --- a/tests/ui/consts/eval_type_mismatch.stderr +++ /dev/null @@ -1,34 +0,0 @@ -error: the constant `A` is not of type `i64` - --> $DIR/eval_type_mismatch.rs:5:38 - | -LL | impl Outer - | ^^^^^^^^^^^ expected `i64`, found `usize` - | -note: required by a bound in `Outer` - --> $DIR/eval_type_mismatch.rs:4:14 - | -LL | struct Outer(); - | ^^^^^^^^^^^^ required by this bound in `Outer` - -error[E0599]: no function or associated item named `o` found for struct `Outer<1, 1>` in the current scope - --> $DIR/eval_type_mismatch.rs:15:20 - | -LL | struct Outer(); - | ------------------------------------------ function or associated item `o` not found for this struct -... -LL | Outer::<1, 1>::o(); - | ^ function or associated item not found in `Outer<1, 1>` - | - = note: the function or associated item was found for - - `Outer` - -error[E0308]: mismatched types - --> $DIR/eval_type_mismatch.rs:5:44 - | -LL | impl Outer - | ^ expected `i64`, found `usize` - -error: aborting due to 3 previous errors - -Some errors have detailed explanations: E0308, E0599. -For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/inference/issue-83606.rs b/tests/ui/inference/issue-83606.rs index 4454b5e60f06..e6e291c3a920 100644 --- a/tests/ui/inference/issue-83606.rs +++ b/tests/ui/inference/issue-83606.rs @@ -6,5 +6,5 @@ fn foo(_: impl std::fmt::Display) -> [usize; N] { fn main() { let _ = foo("foo"); - //~^ ERROR type annotations needed for `[usize; _]` + //~^ ERROR type annotations needed } 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 4d1cd4332fee..f89a463bc580 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 @@ -7,8 +7,7 @@ struct S; impl Copy for S {} //~^ ERROR: mismatched types -//~| ERROR: the trait bound `S: Clone` is not satisfied -//~| ERROR: the constant `N` is not of type `usize` impl Copy for S {} +//~^ ERROR: conflicting implementations of trait `Copy` for type `S<_>` fn main() {} 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 716a47879482..1dac58e1f694 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,29 +1,11 @@ -error[E0277]: the trait bound `S: Clone` is not satisfied - --> $DIR/bad-const-wf-doesnt-specialize.rs:8:29 +error[E0119]: conflicting implementations of trait `Copy` for type `S<_>` + --> $DIR/bad-const-wf-doesnt-specialize.rs:10:1 | LL | impl Copy for S {} - | ^^^^ the trait `Clone` is not implemented for `S` - | - = help: the trait `Clone` is implemented for `S` -note: required by a bound in `Copy` - --> $SRC_DIR/core/src/marker.rs:LL:COL -help: consider annotating `S` with `#[derive(Clone)]` - | -LL + #[derive(Clone)] -LL | struct S; - | - -error: the constant `N` is not of type `usize` - --> $DIR/bad-const-wf-doesnt-specialize.rs:8:29 - | -LL | impl Copy for S {} - | ^^^^ expected `usize`, found `i32` - | -note: required by a bound in `S` - --> $DIR/bad-const-wf-doesnt-specialize.rs:6:10 - | -LL | struct S; - | ^^^^^^^^^^^^^^ required by this bound in `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 @@ -31,7 +13,7 @@ error[E0308]: mismatched types LL | impl Copy for S {} | ^ expected `usize`, found `i32` -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0277, E0308. -For more information about an error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0119, E0308. +For more information about an error, try `rustc --explain E0119`. From 5c497cb3f08d729206726e659d17ce1168327949 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 29 May 2024 21:53:44 +0200 Subject: [PATCH 077/211] drop_in_place: weaken the claim of equivalence with drop(ptr.read()) --- library/core/src/ptr/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index d2bbdc84d4dd..51eb2bb4f0e0 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -450,7 +450,7 @@ mod mut_ptr; /// Executes the destructor (if any) of the pointed-to value. /// -/// This is semantically equivalent to calling [`ptr::read`] and discarding +/// This is almost the same as calling [`ptr::read`] and discarding /// the result, but has the following advantages: /// /// * It is *required* to use `drop_in_place` to drop unsized types like From f9adc1ee9d5b94d4ccb744cf686091c16849a4ee Mon Sep 17 00:00:00 2001 From: Georg Semmler Date: Wed, 29 May 2024 08:59:06 +0200 Subject: [PATCH 078/211] Refactor `#[diagnostic::do_not_recommend]` support This commit refactors the `#[do_not_recommend]` support in the old parser to also apply to projection errors and not only to selection errors. This allows the attribute to be used more widely. --- .../error_reporting/type_err_ctxt_ext.rs | 26 ++++++++++++------ .../type_mismatch.current.stderr | 15 +++++++++++ .../type_mismatch.next.stderr | 15 +++++++++++ .../do_not_recommend/type_mismatch.rs | 27 +++++++++++++++++++ 4 files changed, 75 insertions(+), 8 deletions(-) create mode 100644 tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.current.stderr create mode 100644 tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.next.stderr create mode 100644 tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.rs diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 46953a61296a..642bb3a6e1be 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -414,7 +414,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => { let trait_predicate = bound_predicate.rebind(trait_predicate); let trait_predicate = self.resolve_vars_if_possible(trait_predicate); - let trait_predicate = self.apply_do_not_recommend(trait_predicate, &mut obligation); // Let's use the root obligation as the main message, when we care about the // most general case ("X doesn't implement Pattern<'_>") over the case that @@ -996,12 +995,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { err.emit() } - fn apply_do_not_recommend( - &self, - mut trait_predicate: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>, - obligation: &'_ mut PredicateObligation<'tcx>, - ) -> ty::Binder<'tcx, ty::TraitPredicate<'tcx>> { + fn apply_do_not_recommend(&self, obligation: &mut PredicateObligation<'tcx>) -> bool { let mut base_cause = obligation.cause.code().clone(); + let mut applied_do_not_recommend = false; loop { if let ObligationCauseCode::ImplDerived(ref c) = base_cause { if self.tcx.has_attrs_with_path( @@ -1011,7 +1007,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let code = (*c.derived.parent_code).clone(); obligation.cause.map_code(|_| code); obligation.predicate = c.derived.parent_trait_pred.upcast(self.tcx); - trait_predicate = c.derived.parent_trait_pred.clone(); + applied_do_not_recommend = true; } } if let Some((parent_cause, _parent_pred)) = base_cause.parent() { @@ -1021,7 +1017,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } } - trait_predicate + applied_do_not_recommend } fn emit_specialized_closure_kind_error( @@ -1521,6 +1517,20 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { #[instrument(skip(self), level = "debug")] fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) -> ErrorGuaranteed { + let mut error = FulfillmentError { + obligation: error.obligation.clone(), + code: error.code.clone(), + root_obligation: error.root_obligation.clone(), + }; + if matches!( + error.code, + FulfillmentErrorCode::Select(crate::traits::SelectionError::Unimplemented) + | FulfillmentErrorCode::Project(_) + ) && self.apply_do_not_recommend(&mut error.obligation) + { + error.code = FulfillmentErrorCode::Select(SelectionError::Unimplemented); + } + match error.code { FulfillmentErrorCode::Select(ref selection_error) => self.report_selection_error( error.obligation.clone(), diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.current.stderr new file mode 100644 index 000000000000..bcede8a255f2 --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.current.stderr @@ -0,0 +1,15 @@ +error[E0277]: Very important message! + --> $DIR/type_mismatch.rs:25:14 + | +LL | verify::(); + | ^^ the trait `TheImportantOne` is not implemented for `u8` + | +note: required by a bound in `verify` + --> $DIR/type_mismatch.rs:22:14 + | +LL | fn verify() {} + | ^^^^^^^^^^^^^^^ required by this bound in `verify` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.next.stderr new file mode 100644 index 000000000000..bcede8a255f2 --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.next.stderr @@ -0,0 +1,15 @@ +error[E0277]: Very important message! + --> $DIR/type_mismatch.rs:25:14 + | +LL | verify::(); + | ^^ the trait `TheImportantOne` is not implemented for `u8` + | +note: required by a bound in `verify` + --> $DIR/type_mismatch.rs:22:14 + | +LL | fn verify() {} + | ^^^^^^^^^^^^^^^ required by this bound in `verify` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.rs b/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.rs new file mode 100644 index 000000000000..d6721ccc848f --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/type_mismatch.rs @@ -0,0 +1,27 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +#![feature(do_not_recommend)] + +#[diagnostic::on_unimplemented(message = "Very important message!")] +trait TheImportantOne {} + +trait ImplementationDetail { + type Restriction; +} + +#[diagnostic::do_not_recommend] +impl> TheImportantOne for T {} + +// Comment out this `impl` to show the expected error message. +impl ImplementationDetail for u8 { + type Restriction = u8; +} + +fn verify() {} + +pub fn main() { + verify::(); + //~^ERROR: Very important message! [E0277] +} From 5d8f9b4dc1c913e62387e10762f018f182a34582 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Mon, 13 May 2024 09:05:34 +0200 Subject: [PATCH 079/211] Make `std::env::{set_var, remove_var}` unsafe in edition 2024 Allow calling these functions without `unsafe` blocks in editions up until 2021, but don't trigger the `unused_unsafe` lint for `unsafe` blocks containing these functions. Fixes #27970. Fixes #90308. CC #124866. --- compiler/rustc_feature/src/builtin_attrs.rs | 6 +++ .../rustc_mir_build/src/check_unsafety.rs | 13 +++-- compiler/rustc_span/src/symbol.rs | 1 + library/std/src/env.rs | 54 ++++++++++++------- library/std/src/sys/pal/hermit/os.rs | 14 ++--- library/std/src/sys/pal/sgx/os.rs | 4 +- library/std/src/sys/pal/solid/os.rs | 4 +- library/std/src/sys/pal/teeos/os.rs | 4 +- library/std/src/sys/pal/uefi/os.rs | 4 +- library/std/src/sys/pal/unix/os.rs | 8 +-- library/std/src/sys/pal/unsupported/os.rs | 4 +- library/std/src/sys/pal/wasi/os.rs | 4 +- library/std/src/sys/pal/windows/os.rs | 8 +-- library/std/src/sys/pal/xous/os.rs | 4 +- library/std/src/sys/pal/zkvm/os.rs | 4 +- tests/ui/rust-2024/unsafe-env.e2021.stderr | 23 ++++++++ tests/ui/rust-2024/unsafe-env.e2024.stderr | 39 ++++++++++++++ tests/ui/rust-2024/unsafe-env.rs | 31 +++++++++++ 18 files changed, 172 insertions(+), 57 deletions(-) create mode 100644 tests/ui/rust-2024/unsafe-env.e2021.stderr create mode 100644 tests/ui/rust-2024/unsafe-env.e2024.stderr create mode 100644 tests/ui/rust-2024/unsafe-env.rs diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 0b4a871dd50c..8b7e93fd5558 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -578,6 +578,12 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ "rustc_allowed_through_unstable_modules special cases accidental stabilizations of stable items \ through unstable paths" ), + rustc_attr!( + rustc_deprecated_safe_2024, Normal, template!(Word), WarnFollowing, + EncodeCrossCrate::Yes, + "rustc_deprecated_safe_2024 is supposed to be used in libstd only", + ), + // ========================================================================== // Internal attributes: Type system related: diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index b5f7ffbd2afb..403b7b31f1e5 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -110,14 +110,19 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { ); self.suggest_unsafe_block = false; } - SafetyContext::Safe => { - kind.emit_requires_unsafe_err( + SafetyContext::Safe => match kind { + // Allow calls to deprecated-safe unsafe functions if the + // caller is from an edition before 2024. + UnsafeOpKind::CallToUnsafeFunction(Some(id)) + if !span.at_least_rust_2024() + && self.tcx.has_attr(id, sym::rustc_deprecated_safe_2024) => {} + _ => kind.emit_requires_unsafe_err( self.tcx, span, self.hir_context, unsafe_op_in_unsafe_fn_allowed, - ); - } + ), + }, } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 90da220b3f54..c86701241692 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1575,6 +1575,7 @@ symbols! { rustc_def_path, rustc_default_body_unstable, rustc_deny_explicit_impl, + rustc_deprecated_safe_2024, rustc_diagnostic_item, rustc_diagnostic_macros, rustc_dirty, diff --git a/library/std/src/env.rs b/library/std/src/env.rs index 6f8ac17f12c7..95ee2a91d159 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -318,11 +318,6 @@ impl Error for VarError { /// /// # Safety /// -/// Even though this function is currently not marked as `unsafe`, it needs to -/// be because invoking it can cause undefined behaviour. The function will be -/// marked `unsafe` in a future version of Rust. This is tracked in -/// [rust#27970](https://github.com/rust-lang/rust/issues/27970). -/// /// This function is safe to call in a single-threaded program. /// /// In multi-threaded programs, you must ensure that are no other threads @@ -331,7 +326,7 @@ impl Error for VarError { /// how to achieve this, but we strongly suggest not using `set_var` or /// `remove_var` in multi-threaded programs at all. /// -/// Most C libraries, including libc itself do not advertise which functions +/// Most C libraries, including libc itself, do not advertise which functions /// read from the environment. Even functions from the Rust standard library do /// that, e.g. for DNS lookups from [`std::net::ToSocketAddrs`]. /// @@ -353,15 +348,26 @@ impl Error for VarError { /// use std::env; /// /// let key = "KEY"; -/// env::set_var(key, "VALUE"); +/// unsafe { +/// env::set_var(key, "VALUE"); +/// } /// assert_eq!(env::var(key), Ok("VALUE".to_string())); /// ``` +#[cfg(not(bootstrap))] +#[rustc_deprecated_safe_2024] #[stable(feature = "env", since = "1.0.0")] -pub fn set_var, V: AsRef>(key: K, value: V) { +pub unsafe fn set_var, V: AsRef>(key: K, value: V) { _set_var(key.as_ref(), value.as_ref()) } -fn _set_var(key: &OsStr, value: &OsStr) { +#[cfg(bootstrap)] +#[allow(missing_docs)] +#[stable(feature = "env", since = "1.0.0")] +pub fn set_var, V: AsRef>(key: K, value: V) { + unsafe { _set_var(key.as_ref(), value.as_ref()) } +} + +unsafe fn _set_var(key: &OsStr, value: &OsStr) { os_imp::setenv(key, value).unwrap_or_else(|e| { panic!("failed to set environment variable `{key:?}` to `{value:?}`: {e}") }) @@ -371,11 +377,6 @@ fn _set_var(key: &OsStr, value: &OsStr) { /// /// # Safety /// -/// Even though this function is currently not marked as `unsafe`, it needs to -/// be because invoking it can cause undefined behaviour. The function will be -/// marked `unsafe` in a future version of Rust. This is tracked in -/// [rust#27970](https://github.com/rust-lang/rust/issues/27970). -/// /// This function is safe to call in a single-threaded program. /// /// In multi-threaded programs, you must ensure that are no other threads @@ -384,7 +385,7 @@ fn _set_var(key: &OsStr, value: &OsStr) { /// how to achieve this, but we strongly suggest not using `set_var` or /// `remove_var` in multi-threaded programs at all. /// -/// Most C libraries, including libc itself do not advertise which functions +/// Most C libraries, including libc itself, do not advertise which functions /// read from the environment. Even functions from the Rust standard library do /// that, e.g. for DNS lookups from [`std::net::ToSocketAddrs`]. /// @@ -403,22 +404,35 @@ fn _set_var(key: &OsStr, value: &OsStr) { /// /// # Examples /// -/// ``` +/// ```no_run /// use std::env; /// /// let key = "KEY"; -/// env::set_var(key, "VALUE"); +/// unsafe { +/// env::set_var(key, "VALUE"); +/// } /// assert_eq!(env::var(key), Ok("VALUE".to_string())); /// -/// env::remove_var(key); +/// unsafe { +/// env::remove_var(key); +/// } /// assert!(env::var(key).is_err()); /// ``` +#[cfg(not(bootstrap))] +#[rustc_deprecated_safe_2024] #[stable(feature = "env", since = "1.0.0")] -pub fn remove_var>(key: K) { +pub unsafe fn remove_var>(key: K) { _remove_var(key.as_ref()) } -fn _remove_var(key: &OsStr) { +#[cfg(bootstrap)] +#[allow(missing_docs)] +#[stable(feature = "env", since = "1.0.0")] +pub fn remove_var>(key: K) { + unsafe { _remove_var(key.as_ref()) } +} + +unsafe fn _remove_var(key: &OsStr) { os_imp::unsetenv(key) .unwrap_or_else(|e| panic!("failed to remove environment variable `{key:?}`: {e}")) } diff --git a/library/std/src/sys/pal/hermit/os.rs b/library/std/src/sys/pal/hermit/os.rs index cc6781238319..91247d30462f 100644 --- a/library/std/src/sys/pal/hermit/os.rs +++ b/library/std/src/sys/pal/hermit/os.rs @@ -172,18 +172,14 @@ pub fn getenv(k: &OsStr) -> Option { unsafe { ENV.as_ref().unwrap().lock().unwrap().get_mut(k).cloned() } } -pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { - unsafe { - let (k, v) = (k.to_owned(), v.to_owned()); - ENV.as_ref().unwrap().lock().unwrap().insert(k, v); - } +pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { + let (k, v) = (k.to_owned(), v.to_owned()); + ENV.as_ref().unwrap().lock().unwrap().insert(k, v); Ok(()) } -pub fn unsetenv(k: &OsStr) -> io::Result<()> { - unsafe { - ENV.as_ref().unwrap().lock().unwrap().remove(k); - } +pub unsafe fn unsetenv(k: &OsStr) -> io::Result<()> { + ENV.as_ref().unwrap().lock().unwrap().remove(k); Ok(()) } diff --git a/library/std/src/sys/pal/sgx/os.rs b/library/std/src/sys/pal/sgx/os.rs index 86f4c7d3d56d..c021300d4ae3 100644 --- a/library/std/src/sys/pal/sgx/os.rs +++ b/library/std/src/sys/pal/sgx/os.rs @@ -157,13 +157,13 @@ pub fn getenv(k: &OsStr) -> Option { get_env_store().and_then(|s| s.lock().unwrap().get(k).cloned()) } -pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { +pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { let (k, v) = (k.to_owned(), v.to_owned()); create_env_store().lock().unwrap().insert(k, v); Ok(()) } -pub fn unsetenv(k: &OsStr) -> io::Result<()> { +pub unsafe fn unsetenv(k: &OsStr) -> io::Result<()> { if let Some(env) = get_env_store() { env.lock().unwrap().remove(k); } diff --git a/library/std/src/sys/pal/solid/os.rs b/library/std/src/sys/pal/solid/os.rs index ef35d8788a23..ac90aae4ebe4 100644 --- a/library/std/src/sys/pal/solid/os.rs +++ b/library/std/src/sys/pal/solid/os.rs @@ -191,7 +191,7 @@ pub fn getenv(k: &OsStr) -> Option { .flatten() } -pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { +pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { run_with_cstr(k.as_bytes(), &|k| { run_with_cstr(v.as_bytes(), &|v| { let _guard = ENV_LOCK.write(); @@ -200,7 +200,7 @@ pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { }) } -pub fn unsetenv(n: &OsStr) -> io::Result<()> { +pub unsafe fn unsetenv(n: &OsStr) -> io::Result<()> { run_with_cstr(n.as_bytes(), &|nbuf| { let _guard = ENV_LOCK.write(); cvt_env(unsafe { libc::unsetenv(nbuf.as_ptr()) }).map(drop) diff --git a/library/std/src/sys/pal/teeos/os.rs b/library/std/src/sys/pal/teeos/os.rs index e54a92f01f86..3be0846a6dd4 100644 --- a/library/std/src/sys/pal/teeos/os.rs +++ b/library/std/src/sys/pal/teeos/os.rs @@ -109,11 +109,11 @@ pub fn getenv(_: &OsStr) -> Option { None } -pub fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> { +pub unsafe fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> { Err(io::Error::new(io::ErrorKind::Unsupported, "cannot set env vars on this platform")) } -pub fn unsetenv(_: &OsStr) -> io::Result<()> { +pub unsafe fn unsetenv(_: &OsStr) -> io::Result<()> { Err(io::Error::new(io::ErrorKind::Unsupported, "cannot unset env vars on this platform")) } diff --git a/library/std/src/sys/pal/uefi/os.rs b/library/std/src/sys/pal/uefi/os.rs index 58838c5876eb..0b27977df2fd 100644 --- a/library/std/src/sys/pal/uefi/os.rs +++ b/library/std/src/sys/pal/uefi/os.rs @@ -203,11 +203,11 @@ pub fn getenv(_: &OsStr) -> Option { None } -pub fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> { +pub unsafe fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> { Err(io::const_io_error!(io::ErrorKind::Unsupported, "cannot set env vars on this platform")) } -pub fn unsetenv(_: &OsStr) -> io::Result<()> { +pub unsafe fn unsetenv(_: &OsStr) -> io::Result<()> { Err(io::const_io_error!(io::ErrorKind::Unsupported, "cannot unset env vars on this platform")) } diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs index 8afc49f52274..b5c7d30da7bc 100644 --- a/library/std/src/sys/pal/unix/os.rs +++ b/library/std/src/sys/pal/unix/os.rs @@ -675,19 +675,19 @@ pub fn getenv(k: &OsStr) -> Option { .flatten() } -pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { +pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { run_with_cstr(k.as_bytes(), &|k| { run_with_cstr(v.as_bytes(), &|v| { let _guard = ENV_LOCK.write(); - cvt(unsafe { libc::setenv(k.as_ptr(), v.as_ptr(), 1) }).map(drop) + cvt(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(drop) }) }) } -pub fn unsetenv(n: &OsStr) -> io::Result<()> { +pub unsafe fn unsetenv(n: &OsStr) -> io::Result<()> { run_with_cstr(n.as_bytes(), &|nbuf| { let _guard = ENV_LOCK.write(); - cvt(unsafe { libc::unsetenv(nbuf.as_ptr()) }).map(drop) + cvt(libc::unsetenv(nbuf.as_ptr())).map(drop) }) } diff --git a/library/std/src/sys/pal/unsupported/os.rs b/library/std/src/sys/pal/unsupported/os.rs index 248b34829f2e..3be98898bbeb 100644 --- a/library/std/src/sys/pal/unsupported/os.rs +++ b/library/std/src/sys/pal/unsupported/os.rs @@ -96,11 +96,11 @@ pub fn getenv(_: &OsStr) -> Option { None } -pub fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> { +pub unsafe fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> { Err(io::const_io_error!(io::ErrorKind::Unsupported, "cannot set env vars on this platform")) } -pub fn unsetenv(_: &OsStr) -> io::Result<()> { +pub unsafe fn unsetenv(_: &OsStr) -> io::Result<()> { Err(io::const_io_error!(io::ErrorKind::Unsupported, "cannot unset env vars on this platform")) } diff --git a/library/std/src/sys/pal/wasi/os.rs b/library/std/src/sys/pal/wasi/os.rs index ee377b6ef791..e96296997e6a 100644 --- a/library/std/src/sys/pal/wasi/os.rs +++ b/library/std/src/sys/pal/wasi/os.rs @@ -244,7 +244,7 @@ pub fn getenv(k: &OsStr) -> Option { .flatten() } -pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { +pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { run_with_cstr(k.as_bytes(), &|k| { run_with_cstr(v.as_bytes(), &|v| unsafe { let _guard = env_write_lock(); @@ -253,7 +253,7 @@ pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { }) } -pub fn unsetenv(n: &OsStr) -> io::Result<()> { +pub unsafe fn unsetenv(n: &OsStr) -> io::Result<()> { run_with_cstr(n.as_bytes(), &|nbuf| unsafe { let _guard = env_write_lock(); cvt(libc::unsetenv(nbuf.as_ptr())).map(drop) diff --git a/library/std/src/sys/pal/windows/os.rs b/library/std/src/sys/pal/windows/os.rs index 64d8b72aed28..483b8b0072c8 100644 --- a/library/std/src/sys/pal/windows/os.rs +++ b/library/std/src/sys/pal/windows/os.rs @@ -302,16 +302,16 @@ pub fn getenv(k: &OsStr) -> Option { .ok() } -pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { +pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { let k = to_u16s(k)?; let v = to_u16s(v)?; - cvt(unsafe { c::SetEnvironmentVariableW(k.as_ptr(), v.as_ptr()) }).map(drop) + cvt(c::SetEnvironmentVariableW(k.as_ptr(), v.as_ptr())).map(drop) } -pub fn unsetenv(n: &OsStr) -> io::Result<()> { +pub unsafe fn unsetenv(n: &OsStr) -> io::Result<()> { let v = to_u16s(n)?; - cvt(unsafe { c::SetEnvironmentVariableW(v.as_ptr(), ptr::null()) }).map(drop) + cvt(c::SetEnvironmentVariableW(v.as_ptr(), ptr::null())).map(drop) } pub fn temp_dir() -> PathBuf { diff --git a/library/std/src/sys/pal/xous/os.rs b/library/std/src/sys/pal/xous/os.rs index 8d2eaee8aa61..9be09eed6298 100644 --- a/library/std/src/sys/pal/xous/os.rs +++ b/library/std/src/sys/pal/xous/os.rs @@ -149,11 +149,11 @@ pub fn getenv(_: &OsStr) -> Option { None } -pub fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> { +pub unsafe fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> { Err(io::const_io_error!(io::ErrorKind::Unsupported, "cannot set env vars on this platform")) } -pub fn unsetenv(_: &OsStr) -> io::Result<()> { +pub unsafe fn unsetenv(_: &OsStr) -> io::Result<()> { Err(io::const_io_error!(io::ErrorKind::Unsupported, "cannot unset env vars on this platform")) } diff --git a/library/std/src/sys/pal/zkvm/os.rs b/library/std/src/sys/pal/zkvm/os.rs index 759beb2d306b..e7d6cd52a258 100644 --- a/library/std/src/sys/pal/zkvm/os.rs +++ b/library/std/src/sys/pal/zkvm/os.rs @@ -115,11 +115,11 @@ pub fn getenv(varname: &OsStr) -> Option { Some(OsString::from_inner(os_str::Buf { inner: u8s.to_vec() })) } -pub fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> { +pub unsafe fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> { Err(io::const_io_error!(io::ErrorKind::Unsupported, "cannot set env vars on this platform")) } -pub fn unsetenv(_: &OsStr) -> io::Result<()> { +pub unsafe fn unsetenv(_: &OsStr) -> io::Result<()> { Err(io::const_io_error!(io::ErrorKind::Unsupported, "cannot unset env vars on this platform")) } diff --git a/tests/ui/rust-2024/unsafe-env.e2021.stderr b/tests/ui/rust-2024/unsafe-env.e2021.stderr new file mode 100644 index 000000000000..ebca04d348a3 --- /dev/null +++ b/tests/ui/rust-2024/unsafe-env.e2021.stderr @@ -0,0 +1,23 @@ +error[E0133]: call to unsafe function `unsafe_fn` is unsafe and requires unsafe function or block + --> $DIR/unsafe-env.rs:24:5 + | +LL | unsafe_fn(); + | ^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: unnecessary `unsafe` block + --> $DIR/unsafe-env.rs:27:5 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/unsafe-env.rs:12:8 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/rust-2024/unsafe-env.e2024.stderr b/tests/ui/rust-2024/unsafe-env.e2024.stderr new file mode 100644 index 000000000000..212ff1fca009 --- /dev/null +++ b/tests/ui/rust-2024/unsafe-env.e2024.stderr @@ -0,0 +1,39 @@ +error[E0133]: call to unsafe function `set_var` is unsafe and requires unsafe block + --> $DIR/unsafe-env.rs:14:5 + | +LL | env::set_var("FOO", "BAR"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error[E0133]: call to unsafe function `remove_var` is unsafe and requires unsafe block + --> $DIR/unsafe-env.rs:16:5 + | +LL | env::remove_var("FOO"); + | ^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error[E0133]: call to unsafe function `unsafe_fn` is unsafe and requires unsafe block + --> $DIR/unsafe-env.rs:24:5 + | +LL | unsafe_fn(); + | ^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: unnecessary `unsafe` block + --> $DIR/unsafe-env.rs:27:5 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/unsafe-env.rs:12:8 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/rust-2024/unsafe-env.rs b/tests/ui/rust-2024/unsafe-env.rs new file mode 100644 index 000000000000..e5c1d5778fd2 --- /dev/null +++ b/tests/ui/rust-2024/unsafe-env.rs @@ -0,0 +1,31 @@ +//@ revisions: e2021 e2024 +//@[e2021] edition: 2021 +//@[e2024] edition: 2024 +//@[e2024] compile-flags: -Zunstable-options + +use std::env; +use std::mem; + +unsafe fn unsafe_fn() {} +fn safe_fn() {} + +#[deny(unused_unsafe)] +fn main() { + env::set_var("FOO", "BAR"); + //[e2024]~^ ERROR call to unsafe function `set_var` is unsafe + env::remove_var("FOO"); + //[e2024]~^ ERROR call to unsafe function `remove_var` is unsafe + + unsafe { + env::set_var("FOO", "BAR"); + env::remove_var("FOO"); + } + + unsafe_fn(); + //~^ ERROR call to unsafe function `unsafe_fn` is unsafe + + unsafe { + //~^ ERROR unnecessary `unsafe` block + safe_fn(); + } +} From 8cf49806486133a1fae72ca22c732ed2800eb879 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Fri, 24 May 2024 10:04:44 +0200 Subject: [PATCH 080/211] Add note about safety of `std::env::set_var` on Windows --- library/std/src/env.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/library/std/src/env.rs b/library/std/src/env.rs index 95ee2a91d159..d433caa9d2a4 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -320,11 +320,14 @@ impl Error for VarError { /// /// This function is safe to call in a single-threaded program. /// -/// In multi-threaded programs, you must ensure that are no other threads -/// concurrently writing or *reading*(!) from the environment through functions -/// other than the ones in this module. You are responsible for figuring out -/// how to achieve this, but we strongly suggest not using `set_var` or -/// `remove_var` in multi-threaded programs at all. +/// This function is also always safe to call on Windows, in single-threaded +/// and multi-threaded programs. +/// +/// In multi-threaded programs on other operating systems, you must ensure that +/// are no other threads concurrently writing or *reading*(!) from the +/// environment through functions other than the ones in this module. You are +/// responsible for figuring out how to achieve this, but we strongly suggest +/// not using `set_var` or `remove_var` in multi-threaded programs at all. /// /// Most C libraries, including libc itself, do not advertise which functions /// read from the environment. Even functions from the Rust standard library do @@ -379,6 +382,9 @@ unsafe fn _set_var(key: &OsStr, value: &OsStr) { /// /// This function is safe to call in a single-threaded program. /// +/// This function is also always safe to call on Windows, in single-threaded +/// and multi-threaded programs. +/// /// In multi-threaded programs, you must ensure that are no other threads /// concurrently writing or *reading*(!) from the environment through functions /// other than the ones in this module. You are responsible for figuring out From d7680e355617f409db3cda62afe35fffbb52e70c Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Fri, 24 May 2024 10:26:04 +0200 Subject: [PATCH 081/211] Elaborate about modifying env vars in multi-threaded programs --- library/std/src/env.rs | 46 +++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/library/std/src/env.rs b/library/std/src/env.rs index d433caa9d2a4..4d649f8a6f13 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -323,15 +323,20 @@ impl Error for VarError { /// This function is also always safe to call on Windows, in single-threaded /// and multi-threaded programs. /// -/// In multi-threaded programs on other operating systems, you must ensure that -/// are no other threads concurrently writing or *reading*(!) from the -/// environment through functions other than the ones in this module. You are -/// responsible for figuring out how to achieve this, but we strongly suggest -/// not using `set_var` or `remove_var` in multi-threaded programs at all. -/// -/// Most C libraries, including libc itself, do not advertise which functions -/// read from the environment. Even functions from the Rust standard library do -/// that, e.g. for DNS lookups from [`std::net::ToSocketAddrs`]. +/// In multi-threaded programs on other operating systems, we strongly suggest +/// not using `set_var` or `remove_var` at all. The exact requirement is: you +/// must ensure that there are no other threads concurrently writing or +/// *reading*(!) the environment through functions or global variables other +/// than the ones in this module. The problem is that these operating systems +/// do not provide a thread-safe way to read the environment, and most C +/// libraries, including libc itself, do not advertise which functions read +/// from the environment. Even functions from the Rust standard library may +/// read the environment without going through this module, e.g. for DNS +/// lookups from [`std::net::ToSocketAddrs`]. No stable guarantee is made about +/// which functions may read from the environment in future versions of a +/// library. All this makes it not practically possible for you to guarantee +/// that no other thread will read the environment, so the only safe option is +/// to not use `set_var` or `remove_var` in multi-threaded programs at all. /// /// Discussion of this unsafety on Unix may be found in: /// @@ -385,15 +390,20 @@ unsafe fn _set_var(key: &OsStr, value: &OsStr) { /// This function is also always safe to call on Windows, in single-threaded /// and multi-threaded programs. /// -/// In multi-threaded programs, you must ensure that are no other threads -/// concurrently writing or *reading*(!) from the environment through functions -/// other than the ones in this module. You are responsible for figuring out -/// how to achieve this, but we strongly suggest not using `set_var` or -/// `remove_var` in multi-threaded programs at all. -/// -/// Most C libraries, including libc itself, do not advertise which functions -/// read from the environment. Even functions from the Rust standard library do -/// that, e.g. for DNS lookups from [`std::net::ToSocketAddrs`]. +/// In multi-threaded programs on other operating systems, we strongly suggest +/// not using `set_var` or `remove_var` at all. The exact requirement is: you +/// must ensure that there are no other threads concurrently writing or +/// *reading*(!) the environment through functions or global variables other +/// than the ones in this module. The problem is that these operating systems +/// do not provide a thread-safe way to read the environment, and most C +/// libraries, including libc itself, do not advertise which functions read +/// from the environment. Even functions from the Rust standard library may +/// read the environment without going through this module, e.g. for DNS +/// lookups from [`std::net::ToSocketAddrs`]. No stable guarantee is made about +/// which functions may read from the environment in future versions of a +/// library. All this makes it not practically possible for you to guarantee +/// that no other thread will read the environment, so the only safe option is +/// to not use `set_var` or `remove_var` in multi-threaded programs at all. /// /// Discussion of this unsafety on Unix may be found in: /// From 44f9f8bc33c0b5537c52c9e18697b83f12f19604 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Tue, 28 May 2024 15:16:25 +0200 Subject: [PATCH 082/211] Add `deprecated_safe` lint It warns about usages of `std::env::{set_var, remove_var}` with an automatic fix wrapping the call in an `unsafe` block. --- compiler/rustc_lint_defs/src/builtin.rs | 49 +++++++++++++++++++ compiler/rustc_mir_build/messages.ftl | 6 +++ .../rustc_mir_build/src/check_unsafety.rs | 19 ++++++- compiler/rustc_mir_build/src/errors.rs | 19 +++++++ .../ui/rust-2024/unsafe-env-suggestion.fixed | 20 ++++++++ tests/ui/rust-2024/unsafe-env-suggestion.rs | 20 ++++++++ .../ui/rust-2024/unsafe-env-suggestion.stderr | 33 +++++++++++++ tests/ui/rust-2024/unsafe-env.e2021.stderr | 6 +-- tests/ui/rust-2024/unsafe-env.e2024.stderr | 10 ++-- tests/ui/rust-2024/unsafe-env.rs | 1 - 10 files changed, 172 insertions(+), 11 deletions(-) create mode 100644 tests/ui/rust-2024/unsafe-env-suggestion.fixed create mode 100644 tests/ui/rust-2024/unsafe-env-suggestion.rs create mode 100644 tests/ui/rust-2024/unsafe-env-suggestion.stderr diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 13867319e5cd..93995fe60a36 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -37,6 +37,7 @@ declare_lint_pass! { DEPRECATED, DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME, DEPRECATED_IN_FUTURE, + DEPRECATED_SAFE, DEPRECATED_WHERE_CLAUSE_LOCATION, DUPLICATE_MACRO_ATTRIBUTES, ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT, @@ -4844,3 +4845,51 @@ declare_lint! { reference: "issue #124559 ", }; } + +declare_lint! { + /// The `deprecated_safe` lint detects unsafe functions being used as safe + /// functions. + /// + /// ### Example + /// + /// ```rust,edition2021,compile_fail + /// #![deny(deprecated_safe)] + /// // edition 2021 + /// use std::env; + /// fn enable_backtrace() { + /// env::set_var("RUST_BACKTRACE", "1"); + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Rust [editions] allow the language to evolve without breaking backward + /// compatibility. This lint catches code that uses `unsafe` functions that + /// were declared as safe (non-`unsafe`) in earlier editions. If you switch + /// the compiler to a new edition without updating the code, then it + /// will fail to compile if you are using a function previously marked as + /// safe. + /// + /// You can audit the code to see if it suffices the preconditions of the + /// `unsafe` code, and if it does, you can wrap it in an `unsafe` block. If + /// you can't fulfill the preconditions, you probably need to switch to a + /// different way of doing what you want to achieve. + /// + /// This lint can automatically wrap the calls in `unsafe` blocks, but this + /// obviously cannot verify that the preconditions of the `unsafe` + /// functions are fulfilled, so that is still up to the user. + /// + /// The lint is currently "allow" by default, but that might change in the + /// future. + /// + /// [editions]: https://doc.rust-lang.org/edition-guide/ + pub DEPRECATED_SAFE, + Allow, + "detects unsafe functions being used as safe functions", + @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::EditionError(Edition::Edition2024), + reference: "issue #27970 ", + }; +} diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index 4ba61226a3fd..40a84a599afb 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -28,6 +28,12 @@ mir_build_borrow_of_moved_value = borrow of moved value .value_borrowed_label = value borrowed here after move .suggestion = borrow this binding in the pattern to avoid moving the value +mir_build_call_to_deprecated_safe_fn_requires_unsafe = + call to deprecated safe function `{$function}` is unsafe and requires unsafe block + .note = consult the function's documentation for information on how to avoid undefined behavior + .label = call to unsafe function + .suggestion = you can wrap the call in an `unsafe` block if you can guarantee the code is only ever called from single-threaded code + mir_build_call_to_fn_with_requires_unsafe = call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block .help = in order for the call to be safe, the context requires the following additional target {$missing_target_features_count -> diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 403b7b31f1e5..24098282d93b 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -9,7 +9,7 @@ use rustc_middle::thir::visit::Visitor; use rustc_middle::thir::*; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt}; -use rustc_session::lint::builtin::{UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE}; +use rustc_session::lint::builtin::{DEPRECATED_SAFE, UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE}; use rustc_session::lint::Level; use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::symbol::Symbol; @@ -115,7 +115,22 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { // caller is from an edition before 2024. UnsafeOpKind::CallToUnsafeFunction(Some(id)) if !span.at_least_rust_2024() - && self.tcx.has_attr(id, sym::rustc_deprecated_safe_2024) => {} + && self.tcx.has_attr(id, sym::rustc_deprecated_safe_2024) => + { + self.tcx.emit_node_span_lint( + DEPRECATED_SAFE, + self.hir_context, + span, + CallToDeprecatedSafeFnRequiresUnsafe { + span, + function: with_no_trimmed_paths!(self.tcx.def_path_str(id)), + sub: CallToDeprecatedSafeFnRequiresUnsafeSub { + left: span.shrink_to_lo(), + right: span.shrink_to_hi(), + }, + }, + ) + } _ => kind.emit_requires_unsafe_err( self.tcx, span, diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index ae6e126a4e2c..b29cc24cff81 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -20,6 +20,25 @@ pub struct UnconditionalRecursion { pub call_sites: Vec, } +#[derive(LintDiagnostic)] +#[diag(mir_build_call_to_deprecated_safe_fn_requires_unsafe)] +pub struct CallToDeprecatedSafeFnRequiresUnsafe { + #[label] + pub span: Span, + pub function: String, + #[subdiagnostic] + pub sub: CallToDeprecatedSafeFnRequiresUnsafeSub, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(mir_build_suggestion, applicability = "machine-applicable")] +pub struct CallToDeprecatedSafeFnRequiresUnsafeSub { + #[suggestion_part(code = "unsafe {{ ")] + pub left: Span, + #[suggestion_part(code = " }}")] + pub right: Span, +} + #[derive(LintDiagnostic)] #[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe, code = E0133)] #[note] diff --git a/tests/ui/rust-2024/unsafe-env-suggestion.fixed b/tests/ui/rust-2024/unsafe-env-suggestion.fixed new file mode 100644 index 000000000000..d9c738edfacb --- /dev/null +++ b/tests/ui/rust-2024/unsafe-env-suggestion.fixed @@ -0,0 +1,20 @@ +//@ run-rustfix + +#![deny(deprecated_safe)] + +use std::env; + +#[deny(unused_unsafe)] +fn main() { + unsafe { env::set_var("FOO", "BAR") }; + //~^ ERROR call to deprecated safe function + //~| WARN this is accepted in the current edition + unsafe { env::remove_var("FOO") }; + //~^ ERROR call to deprecated safe function + //~| WARN this is accepted in the current edition + + unsafe { + env::set_var("FOO", "BAR"); + env::remove_var("FOO"); + } +} diff --git a/tests/ui/rust-2024/unsafe-env-suggestion.rs b/tests/ui/rust-2024/unsafe-env-suggestion.rs new file mode 100644 index 000000000000..3bd169973e38 --- /dev/null +++ b/tests/ui/rust-2024/unsafe-env-suggestion.rs @@ -0,0 +1,20 @@ +//@ run-rustfix + +#![deny(deprecated_safe)] + +use std::env; + +#[deny(unused_unsafe)] +fn main() { + env::set_var("FOO", "BAR"); + //~^ ERROR call to deprecated safe function + //~| WARN this is accepted in the current edition + env::remove_var("FOO"); + //~^ ERROR call to deprecated safe function + //~| WARN this is accepted in the current edition + + unsafe { + env::set_var("FOO", "BAR"); + env::remove_var("FOO"); + } +} diff --git a/tests/ui/rust-2024/unsafe-env-suggestion.stderr b/tests/ui/rust-2024/unsafe-env-suggestion.stderr new file mode 100644 index 000000000000..90c91c2a474a --- /dev/null +++ b/tests/ui/rust-2024/unsafe-env-suggestion.stderr @@ -0,0 +1,33 @@ +error: call to deprecated safe function `std::env::set_var` is unsafe and requires unsafe block + --> $DIR/unsafe-env-suggestion.rs:9:5 + | +LL | env::set_var("FOO", "BAR"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! + = note: for more information, see issue #27970 +note: the lint level is defined here + --> $DIR/unsafe-env-suggestion.rs:3:9 + | +LL | #![deny(deprecated_safe)] + | ^^^^^^^^^^^^^^^ +help: you can wrap the call in an `unsafe` block if you can guarantee the code is only ever called from single-threaded code + | +LL | unsafe { env::set_var("FOO", "BAR") }; + | ++++++++ + + +error: call to deprecated safe function `std::env::remove_var` is unsafe and requires unsafe block + --> $DIR/unsafe-env-suggestion.rs:12:5 + | +LL | env::remove_var("FOO"); + | ^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! + = note: for more information, see issue #27970 +help: you can wrap the call in an `unsafe` block if you can guarantee the code is only ever called from single-threaded code + | +LL | unsafe { env::remove_var("FOO") }; + | ++++++++ + + +error: aborting due to 2 previous errors + diff --git a/tests/ui/rust-2024/unsafe-env.e2021.stderr b/tests/ui/rust-2024/unsafe-env.e2021.stderr index ebca04d348a3..cc40ec2e466b 100644 --- a/tests/ui/rust-2024/unsafe-env.e2021.stderr +++ b/tests/ui/rust-2024/unsafe-env.e2021.stderr @@ -1,5 +1,5 @@ error[E0133]: call to unsafe function `unsafe_fn` is unsafe and requires unsafe function or block - --> $DIR/unsafe-env.rs:24:5 + --> $DIR/unsafe-env.rs:23:5 | LL | unsafe_fn(); | ^^^^^^^^^^^ call to unsafe function @@ -7,13 +7,13 @@ LL | unsafe_fn(); = note: consult the function's documentation for information on how to avoid undefined behavior error: unnecessary `unsafe` block - --> $DIR/unsafe-env.rs:27:5 + --> $DIR/unsafe-env.rs:26:5 | LL | unsafe { | ^^^^^^ unnecessary `unsafe` block | note: the lint level is defined here - --> $DIR/unsafe-env.rs:12:8 + --> $DIR/unsafe-env.rs:11:8 | LL | #[deny(unused_unsafe)] | ^^^^^^^^^^^^^ diff --git a/tests/ui/rust-2024/unsafe-env.e2024.stderr b/tests/ui/rust-2024/unsafe-env.e2024.stderr index 212ff1fca009..b43f817cf72a 100644 --- a/tests/ui/rust-2024/unsafe-env.e2024.stderr +++ b/tests/ui/rust-2024/unsafe-env.e2024.stderr @@ -1,5 +1,5 @@ error[E0133]: call to unsafe function `set_var` is unsafe and requires unsafe block - --> $DIR/unsafe-env.rs:14:5 + --> $DIR/unsafe-env.rs:13:5 | LL | env::set_var("FOO", "BAR"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function @@ -7,7 +7,7 @@ LL | env::set_var("FOO", "BAR"); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: call to unsafe function `remove_var` is unsafe and requires unsafe block - --> $DIR/unsafe-env.rs:16:5 + --> $DIR/unsafe-env.rs:15:5 | LL | env::remove_var("FOO"); | ^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function @@ -15,7 +15,7 @@ LL | env::remove_var("FOO"); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: call to unsafe function `unsafe_fn` is unsafe and requires unsafe block - --> $DIR/unsafe-env.rs:24:5 + --> $DIR/unsafe-env.rs:23:5 | LL | unsafe_fn(); | ^^^^^^^^^^^ call to unsafe function @@ -23,13 +23,13 @@ LL | unsafe_fn(); = note: consult the function's documentation for information on how to avoid undefined behavior error: unnecessary `unsafe` block - --> $DIR/unsafe-env.rs:27:5 + --> $DIR/unsafe-env.rs:26:5 | LL | unsafe { | ^^^^^^ unnecessary `unsafe` block | note: the lint level is defined here - --> $DIR/unsafe-env.rs:12:8 + --> $DIR/unsafe-env.rs:11:8 | LL | #[deny(unused_unsafe)] | ^^^^^^^^^^^^^ diff --git a/tests/ui/rust-2024/unsafe-env.rs b/tests/ui/rust-2024/unsafe-env.rs index e5c1d5778fd2..a882f077b9bb 100644 --- a/tests/ui/rust-2024/unsafe-env.rs +++ b/tests/ui/rust-2024/unsafe-env.rs @@ -4,7 +4,6 @@ //@[e2024] compile-flags: -Zunstable-options use std::env; -use std::mem; unsafe fn unsafe_fn() {} fn safe_fn() {} From e6bd6c2044352d842afb827f1fe0fd6f43c38413 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 29 May 2024 21:42:40 +0000 Subject: [PATCH 083/211] Use parenthetical notation for `Fn` traits Always use the `Fn(T) -> R` format when printing closure traits instead of `Fn<(T,), Output = R>`. Fix #67100: ``` error[E0277]: expected a `Fn()` closure, found `F` --> file.rs:6:13 | 6 | call_fn(f) | ------- ^ expected an `Fn()` closure, found `F` | | | required by a bound introduced by this call | = note: wrap the `F` in a closure with no arguments: `|| { /* code */ }` note: required by a bound in `call_fn` --> file.rs:1:15 | 1 | fn call_fn ()>(f: &F) { | ^^^^^^^^^^ required by this bound in `call_fn` help: consider further restricting this bound | 5 | fn call_any(f: &F) { | ++++++ ``` --- .../src/diagnostics/conflict_errors.rs | 2 +- compiler/rustc_const_eval/src/check_consts/ops.rs | 2 +- compiler/rustc_hir_analysis/src/coherence/builtin.rs | 2 +- compiler/rustc_middle/src/ty/print/pretty.rs | 2 +- .../src/traits/error_reporting/suggestions.rs | 11 ++++++----- tests/ui/async-await/async-fn/impl-header.stderr | 2 +- tests/ui/closures/closure-expected.stderr | 2 +- tests/ui/closures/coerce-unsafe-to-closure.stderr | 2 +- tests/ui/consts/fn_trait_refs.stderr | 12 ++++++------ tests/ui/consts/unstable-const-fn-in-libcore.stderr | 4 ++-- .../block_instead_of_closure_in_arg.stderr | 2 +- .../ruby_style_closure_successful_parse.stderr | 2 +- tests/ui/extern/extern-wrong-value-type.stderr | 2 +- ...feature-gate-unboxed-closures-manual-impls.stderr | 4 ++-- tests/ui/fn/fn-trait-formatting.stderr | 2 +- tests/ui/fn/issue-39259.stderr | 2 +- .../issue-68642-broken-llvm-ir.stderr | 4 ++-- .../issue-68643-broken-mir.stderr | 4 ++-- .../issue-68644-codegen-selection.stderr | 4 ++-- .../issue-68645-codegen-fulfillment.stderr | 4 ++-- tests/ui/impl-trait/normalize-tait-in-const.stderr | 4 ++-- tests/ui/intrinsics/const-eval-select-bad.stderr | 4 ++-- tests/ui/issues/issue-22034.stderr | 2 +- tests/ui/issues/issue-23966.stderr | 2 +- tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr | 10 +++++----- tests/ui/lifetimes/issue-95023.stderr | 2 +- .../suggest-option-asderef-unfixable.stderr | 4 ++-- .../rfcs/rfc-2396-target_feature-11/fn-traits.stderr | 12 ++++++------ .../const-closure-trait-method-fail.stderr | 4 ++-- .../const-closure-trait-method.stderr | 4 ++-- .../rfc-2632-const-trait-impl/const-closures.stderr | 12 ++++++------ .../check-trait-object-bounds-2.stderr | 2 +- .../traits/bound/assoc-fn-bound-root-obligation.rs | 2 +- .../bound/assoc-fn-bound-root-obligation.stderr | 2 +- tests/ui/traits/issue-87558.stderr | 2 +- tests/ui/traits/next-solver/fn-trait.stderr | 8 ++++---- .../suggest-dereferences/root-obligation.stderr | 4 ++-- tests/ui/type-alias-impl-trait/issue-63279.stderr | 4 ++-- .../unboxed-closures-fnmut-as-fn.stderr | 2 +- .../unboxed-closures-unsafe-extern-fn.stderr | 6 +++--- .../unboxed-closures-wrong-abi.stderr | 6 +++--- .../unboxed-closures-wrong-arg-type-extern-fn.stderr | 6 +++--- tests/ui/unsafe/initializing-ranged-via-ctor.stderr | 2 +- 43 files changed, 89 insertions(+), 88 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 2f1b2ce9c4c7..5d5a1d76a3c0 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1362,7 +1362,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { match *predicate.self_ty().kind() { ty::Param(param_ty) => Ok(( generics.type_param(param_ty, tcx), - predicate.trait_ref.print_only_trait_path().to_string(), + predicate.trait_ref.print_trait_sugared().to_string(), )), _ => Err(()), } diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index 90b622cae656..feab5b929acb 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -113,7 +113,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { if let Some(generics) = tcx.hir_node_by_def_id(caller).generics() { let constraint = with_no_trimmed_paths!(format!( "~const {}", - trait_ref.print_only_trait_path() + trait_ref.print_trait_sugared(), )); suggest_constraining_type_param( tcx, diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 8f0aba1c38c1..84771978a46c 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -554,7 +554,7 @@ fn infringing_fields_error( if let ty::Param(_) = ty.kind() { bounds.push(( format!("{ty}"), - trait_ref.print_only_trait_path().to_string(), + trait_ref.print_trait_sugared().to_string(), Some(trait_ref.def_id), )); } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 3c0f2578284a..1da074373c78 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -3197,7 +3197,7 @@ define_print_and_forward_display! { if let ty::PredicatePolarity::Negative = self.0.polarity { p!("!") } - p!(print(self.0.trait_ref.print_only_trait_path())); + p!(print(self.0.trait_ref.print_trait_sugared())); } PrintClosureAsImpl<'tcx> { diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 6c56ebb62aed..0483789d3663 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -29,10 +29,11 @@ use rustc_macros::extension; use rustc_middle::hir::map; use rustc_middle::traits::IsConstable; use rustc_middle::ty::error::TypeError::{self, Sorts}; +use rustc_middle::ty::print::PrintPolyTraitRefExt; use rustc_middle::ty::{ self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, GenericArgs, - InferTy, IsSuggestable, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, - TypeVisitableExt, TypeckResults, Upcast, + InferTy, IsSuggestable, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable, TypeFolder, + TypeSuperFoldable, TypeVisitableExt, TypeckResults, Upcast, }; use rustc_middle::{bug, span_bug}; use rustc_span::def_id::LocalDefId; @@ -219,15 +220,15 @@ pub fn suggest_restriction<'tcx, G: EmissionGuarantee>( (_, None) => predicate_constraint(hir_generics, trait_pred.upcast(tcx)), (None, Some((ident, []))) => ( ident.span.shrink_to_hi(), - format!(": {}", trait_pred.print_modifiers_and_trait_path()), + format!(": {}", trait_pred.to_poly_trait_ref().print_trait_sugared()), ), (_, Some((_, [.., bounds]))) => ( bounds.span().shrink_to_hi(), - format!(" + {}", trait_pred.print_modifiers_and_trait_path()), + format!(" + {}", trait_pred.to_poly_trait_ref().print_trait_sugared()), ), (Some(_), Some((_, []))) => ( hir_generics.span.shrink_to_hi(), - format!(": {}", trait_pred.print_modifiers_and_trait_path()), + format!(": {}", trait_pred.to_poly_trait_ref().print_trait_sugared()), ), }; diff --git a/tests/ui/async-await/async-fn/impl-header.stderr b/tests/ui/async-await/async-fn/impl-header.stderr index 2fb862af04e4..64a98aab17b2 100644 --- a/tests/ui/async-await/async-fn/impl-header.stderr +++ b/tests/ui/async-await/async-fn/impl-header.stderr @@ -28,7 +28,7 @@ error[E0277]: expected a `FnMut()` closure, found `F` LL | impl async Fn<()> for F {} | ^ expected an `FnMut()` closure, found `F` | - = help: the trait `FnMut<()>` is not implemented for `F` + = help: the trait `FnMut()` is not implemented for `F` = note: wrap the `F` in a closure with no arguments: `|| { /* code */ }` note: required by a bound in `Fn` --> $SRC_DIR/core/src/ops/function.rs:LL:COL diff --git a/tests/ui/closures/closure-expected.stderr b/tests/ui/closures/closure-expected.stderr index 6b309d70bdf1..53a93e1e84dd 100644 --- a/tests/ui/closures/closure-expected.stderr +++ b/tests/ui/closures/closure-expected.stderr @@ -6,7 +6,7 @@ LL | let y = x.or_else(4); | | | required by a bound introduced by this call | - = help: the trait `FnOnce<()>` is not implemented for `{integer}` + = help: the trait `FnOnce()` is not implemented for `{integer}` = note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }` note: required by a bound in `Option::::or_else` --> $SRC_DIR/core/src/option.rs:LL:COL diff --git a/tests/ui/closures/coerce-unsafe-to-closure.stderr b/tests/ui/closures/coerce-unsafe-to-closure.stderr index 4841ff32e701..cb718ca160f8 100644 --- a/tests/ui/closures/coerce-unsafe-to-closure.stderr +++ b/tests/ui/closures/coerce-unsafe-to-closure.stderr @@ -6,7 +6,7 @@ LL | let x: Option<&[u8]> = Some("foo").map(std::mem::transmute); | | | required by a bound introduced by this call | - = help: the trait `FnOnce<(&str,)>` is not implemented for fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}` + = help: the trait `FnOnce(&str)` is not implemented for fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}` = note: unsafe function cannot be called generically without an unsafe block note: required by a bound in `Option::::map` --> $SRC_DIR/core/src/option.rs:LL:COL diff --git a/tests/ui/consts/fn_trait_refs.stderr b/tests/ui/consts/fn_trait_refs.stderr index aad0ae64e858..4fb82c0683dc 100644 --- a/tests/ui/consts/fn_trait_refs.stderr +++ b/tests/ui/consts/fn_trait_refs.stderr @@ -107,8 +107,8 @@ LL | f() = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants help: consider further restricting this bound | -LL | T: ~const Fn<()> + ~const Destruct + ~const std::ops::Fn<()>, - | +++++++++++++++++++++++++ +LL | T: ~const Fn<()> + ~const Destruct + ~const Fn(), + | +++++++++++++ help: add `#![feature(effects)]` to the crate attributes to enable | LL + #![feature(effects)] @@ -132,8 +132,8 @@ LL | f() = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants help: consider further restricting this bound | -LL | T: ~const FnMut<()> + ~const Destruct + ~const std::ops::FnMut<()>, - | ++++++++++++++++++++++++++++ +LL | T: ~const FnMut<()> + ~const Destruct + ~const FnMut(), + | ++++++++++++++++ help: add `#![feature(effects)]` to the crate attributes to enable | LL + #![feature(effects)] @@ -157,8 +157,8 @@ LL | f() = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants help: consider further restricting this bound | -LL | T: ~const FnOnce<()> + ~const std::ops::FnOnce<()>, - | +++++++++++++++++++++++++++++ +LL | T: ~const FnOnce<()> + ~const FnOnce(), + | +++++++++++++++++ help: add `#![feature(effects)]` to the crate attributes to enable | LL + #![feature(effects)] diff --git a/tests/ui/consts/unstable-const-fn-in-libcore.stderr b/tests/ui/consts/unstable-const-fn-in-libcore.stderr index 9590b3372e32..6c83eff4de01 100644 --- a/tests/ui/consts/unstable-const-fn-in-libcore.stderr +++ b/tests/ui/consts/unstable-const-fn-in-libcore.stderr @@ -13,8 +13,8 @@ LL | Opt::None => f(), = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants help: consider further restricting this bound | -LL | const fn unwrap_or_else T + ~const std::ops::FnOnce<()>>(self, f: F) -> T { - | +++++++++++++++++++++++++++++ +LL | const fn unwrap_or_else T + ~const FnOnce()>(self, f: F) -> T { + | +++++++++++++++++ help: add `#![feature(effects)]` to the crate attributes to enable | LL + #![feature(effects)] diff --git a/tests/ui/expr/malformed_closure/block_instead_of_closure_in_arg.stderr b/tests/ui/expr/malformed_closure/block_instead_of_closure_in_arg.stderr index 1264d9693425..c4c1c830afa6 100644 --- a/tests/ui/expr/malformed_closure/block_instead_of_closure_in_arg.stderr +++ b/tests/ui/expr/malformed_closure/block_instead_of_closure_in_arg.stderr @@ -14,7 +14,7 @@ LL | || } LL | | }); | |______^ expected an `FnOnce(&bool)` closure, found `bool` | - = help: the trait `for<'a> FnOnce<(&'a bool,)>` is not implemented for `bool` + = help: the trait `for<'a> FnOnce(&'a bool)` is not implemented for `bool` note: required by a bound in `Option::::filter` --> $SRC_DIR/core/src/option.rs:LL:COL help: you might have meant to create the closure instead of a block diff --git a/tests/ui/expr/malformed_closure/ruby_style_closure_successful_parse.stderr b/tests/ui/expr/malformed_closure/ruby_style_closure_successful_parse.stderr index a7ed9f5880b6..54d3c6727f77 100644 --- a/tests/ui/expr/malformed_closure/ruby_style_closure_successful_parse.stderr +++ b/tests/ui/expr/malformed_closure/ruby_style_closure_successful_parse.stderr @@ -11,7 +11,7 @@ LL | | Some(x * 2) LL | | }); | |_____^ expected an `FnOnce({integer})` closure, found `Option` | - = help: the trait `FnOnce<({integer},)>` is not implemented for `Option` + = help: the trait `FnOnce({integer})` is not implemented for `Option` note: required by a bound in `Option::::and_then` --> $SRC_DIR/core/src/option.rs:LL:COL help: you might have meant to open the closure body instead of placing a closure within a block diff --git a/tests/ui/extern/extern-wrong-value-type.stderr b/tests/ui/extern/extern-wrong-value-type.stderr index 1c08aa1717f4..692a66011711 100644 --- a/tests/ui/extern/extern-wrong-value-type.stderr +++ b/tests/ui/extern/extern-wrong-value-type.stderr @@ -6,7 +6,7 @@ LL | is_fn(f); | | | required by a bound introduced by this call | - = help: the trait `Fn<()>` is not implemented for fn item `extern "C" fn() {f}` + = help: the trait `Fn()` is not implemented for fn item `extern "C" fn() {f}` = note: wrap the `extern "C" fn() {f}` in a closure with no arguments: `|| { /* code */ }` note: required by a bound in `is_fn` --> $DIR/extern-wrong-value-type.rs:4:28 diff --git a/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr b/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr index c3f161469e30..71c320422bc8 100644 --- a/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr +++ b/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr @@ -80,7 +80,7 @@ error[E0277]: expected a `FnMut()` closure, found `Foo` LL | impl Fn<()> for Foo { | ^^^ expected an `FnMut()` closure, found `Foo` | - = help: the trait `FnMut<()>` is not implemented for `Foo` + = help: the trait `FnMut()` is not implemented for `Foo` = note: wrap the `Foo` in a closure with no arguments: `|| { /* code */ }` note: required by a bound in `Fn` --> $SRC_DIR/core/src/ops/function.rs:LL:COL @@ -149,7 +149,7 @@ error[E0277]: expected a `FnOnce()` closure, found `Bar` LL | impl FnMut<()> for Bar { | ^^^ expected an `FnOnce()` closure, found `Bar` | - = help: the trait `FnOnce<()>` is not implemented for `Bar` + = help: the trait `FnOnce()` is not implemented for `Bar` = note: wrap the `Bar` in a closure with no arguments: `|| { /* code */ }` note: required by a bound in `FnMut` --> $SRC_DIR/core/src/ops/function.rs:LL:COL diff --git a/tests/ui/fn/fn-trait-formatting.stderr b/tests/ui/fn/fn-trait-formatting.stderr index c5e2f41691fa..9fdef49c5ef9 100644 --- a/tests/ui/fn/fn-trait-formatting.stderr +++ b/tests/ui/fn/fn-trait-formatting.stderr @@ -47,7 +47,7 @@ LL | needs_fn(1); | | | required by a bound introduced by this call | - = help: the trait `Fn<(isize,)>` is not implemented for `{integer}` + = help: the trait `Fn(isize)` is not implemented for `{integer}` note: required by a bound in `needs_fn` --> $DIR/fn-trait-formatting.rs:1:31 | diff --git a/tests/ui/fn/issue-39259.stderr b/tests/ui/fn/issue-39259.stderr index 47150a3c155c..e9d311029a71 100644 --- a/tests/ui/fn/issue-39259.stderr +++ b/tests/ui/fn/issue-39259.stderr @@ -16,7 +16,7 @@ error[E0277]: expected a `FnMut(u32)` closure, found `S` LL | impl Fn(u32) -> u32 for S { | ^ expected an `FnMut(u32)` closure, found `S` | - = help: the trait `FnMut<(u32,)>` is not implemented for `S` + = help: the trait `FnMut(u32)` is not implemented for `S` note: required by a bound in `Fn` --> $SRC_DIR/core/src/ops/function.rs:LL:COL diff --git a/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr b/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr index 6bf832bb9e2a..3929e66a25a3 100644 --- a/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr +++ b/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr @@ -12,8 +12,8 @@ LL | type F<'a>: Fn() -> u32; | ^^^^^^^^^^^ required by this bound in `Fun::F` help: consider restricting type parameter `T` | -LL | impl> Fun for T { - | ++++++++++++++++++ +LL | impl Fun for T { + | ++++++ error: aborting due to 1 previous error diff --git a/tests/ui/generic-associated-types/issue-68643-broken-mir.stderr b/tests/ui/generic-associated-types/issue-68643-broken-mir.stderr index d9f26ee6c291..662726b89935 100644 --- a/tests/ui/generic-associated-types/issue-68643-broken-mir.stderr +++ b/tests/ui/generic-associated-types/issue-68643-broken-mir.stderr @@ -12,8 +12,8 @@ LL | type F<'a>: Fn() -> u32; | ^^^^^^^^^^^ required by this bound in `Fun::F` help: consider restricting type parameter `T` | -LL | impl> Fun for T { - | ++++++++++++++++++ +LL | impl Fun for T { + | ++++++ error: aborting due to 1 previous error diff --git a/tests/ui/generic-associated-types/issue-68644-codegen-selection.stderr b/tests/ui/generic-associated-types/issue-68644-codegen-selection.stderr index 3dc9ff10243f..34278249e35d 100644 --- a/tests/ui/generic-associated-types/issue-68644-codegen-selection.stderr +++ b/tests/ui/generic-associated-types/issue-68644-codegen-selection.stderr @@ -12,8 +12,8 @@ LL | type F<'a>: Fn() -> u32; | ^^^^^^^^^^^ required by this bound in `Fun::F` help: consider restricting type parameter `T` | -LL | impl> Fun for T { - | ++++++++++++++++++ +LL | impl Fun for T { + | ++++++ error: aborting due to 1 previous error diff --git a/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr b/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr index 45fb65f6cf1e..dafe1c1d3950 100644 --- a/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr +++ b/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr @@ -12,8 +12,8 @@ LL | type F<'a>: Fn() -> u32; | ^^^^^^^^^^^ required by this bound in `Fun::F` help: consider restricting type parameter `T` | -LL | impl> Fun for T { - | ++++++++++++++++++ +LL | impl Fun for T { + | ++++++ error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/normalize-tait-in-const.stderr b/tests/ui/impl-trait/normalize-tait-in-const.stderr index fbd41b61730e..9ea4ff7cc70a 100644 --- a/tests/ui/impl-trait/normalize-tait-in-const.stderr +++ b/tests/ui/impl-trait/normalize-tait-in-const.stderr @@ -13,8 +13,8 @@ LL | fun(filter_positive()); = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants help: consider further restricting this bound | -LL | const fn with_positive Fn(&'a Alias<'a>) + ~const Destruct + ~const std::ops::Fn<(&Alias<'_>,)>>(fun: F) { - | ++++++++++++++++++++++++++++++++++++ +LL | const fn with_positive Fn(&'a Alias<'a>) + ~const Destruct + ~const Fn(&Alias<'_>)>(fun: F) { + | +++++++++++++++++++++++ help: add `#![feature(effects)]` to the crate attributes to enable | LL + #![feature(effects)] diff --git a/tests/ui/intrinsics/const-eval-select-bad.stderr b/tests/ui/intrinsics/const-eval-select-bad.stderr index 85e22178c4a6..50092edda4f7 100644 --- a/tests/ui/intrinsics/const-eval-select-bad.stderr +++ b/tests/ui/intrinsics/const-eval-select-bad.stderr @@ -24,7 +24,7 @@ LL | const_eval_select((), 42, 0xDEADBEEF); | | | required by a bound introduced by this call | - = help: the trait `FnOnce<()>` is not implemented for `{integer}` + = help: the trait `FnOnce()` is not implemented for `{integer}` = note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }` note: required by a bound in `const_eval_select` --> $SRC_DIR/core/src/intrinsics.rs:LL:COL @@ -37,7 +37,7 @@ LL | const_eval_select((), 42, 0xDEADBEEF); | | | required by a bound introduced by this call | - = help: the trait `FnOnce<()>` is not implemented for `{integer}` + = help: the trait `FnOnce()` is not implemented for `{integer}` = note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }` note: required by a bound in `const_eval_select` --> $SRC_DIR/core/src/intrinsics.rs:LL:COL diff --git a/tests/ui/issues/issue-22034.stderr b/tests/ui/issues/issue-22034.stderr index 75ddcd478992..68202085e77d 100644 --- a/tests/ui/issues/issue-22034.stderr +++ b/tests/ui/issues/issue-22034.stderr @@ -4,7 +4,7 @@ error[E0277]: expected a `Fn()` closure, found `()` LL | &mut *(ptr as *mut dyn Fn()) | ^^^ expected an `Fn()` closure, found `()` | - = help: the trait `Fn<()>` is not implemented for `()` + = help: the trait `Fn()` is not implemented for `()` = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }` = note: required for the cast from `*mut ()` to `*mut dyn Fn()` diff --git a/tests/ui/issues/issue-23966.stderr b/tests/ui/issues/issue-23966.stderr index c29e88614442..3f7a4fa312f1 100644 --- a/tests/ui/issues/issue-23966.stderr +++ b/tests/ui/issues/issue-23966.stderr @@ -6,7 +6,7 @@ LL | "".chars().fold(|_, _| (), ()); | | | required by a bound introduced by this call | - = help: the trait `FnMut<(_, char)>` is not implemented for `()` + = help: the trait `FnMut(_, char)` is not implemented for `()` note: required by a bound in `fold` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL diff --git a/tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr b/tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr index e9f97d1d93bd..e8c3ab00226e 100644 --- a/tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr +++ b/tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr @@ -10,7 +10,7 @@ LL | | F:, LL | | for<'a> >::Output: Future + 'a, | |__________________________________________________________________________^ expected an `FnOnce(&'a mut i32)` closure, found `i32` | - = help: the trait `for<'a> FnOnce<(&'a mut i32,)>` is not implemented for `i32` + = help: the trait `for<'a> FnOnce(&'a mut i32)` is not implemented for `i32` error[E0277]: expected a `FnOnce(&'a mut i32)` closure, found `i32` --> $DIR/issue-76168-hr-outlives-3.rs:6:10 @@ -18,7 +18,7 @@ error[E0277]: expected a `FnOnce(&'a mut i32)` closure, found `i32` LL | async fn wrapper(f: F) | ^^^^^^^ expected an `FnOnce(&'a mut i32)` closure, found `i32` | - = help: the trait `for<'a> FnOnce<(&'a mut i32,)>` is not implemented for `i32` + = help: the trait `for<'a> FnOnce(&'a mut i32)` is not implemented for `i32` error[E0277]: expected a `FnOnce(&'a mut i32)` closure, found `i32` --> $DIR/issue-76168-hr-outlives-3.rs:6:1 @@ -32,7 +32,7 @@ LL | | F:, LL | | for<'a> >::Output: Future + 'a, | |__________________________________________________________________________^ expected an `FnOnce(&'a mut i32)` closure, found `i32` | - = help: the trait `for<'a> FnOnce<(&'a mut i32,)>` is not implemented for `i32` + = help: the trait `for<'a> FnOnce(&'a mut i32)` is not implemented for `i32` error[E0277]: expected a `FnOnce(&'a mut i32)` closure, found `i32` --> $DIR/issue-76168-hr-outlives-3.rs:6:1 @@ -46,7 +46,7 @@ LL | | F:, LL | | for<'a> >::Output: Future + 'a, | |__________________________________________________________________________^ expected an `FnOnce(&'a mut i32)` closure, found `i32` | - = help: the trait `for<'a> FnOnce<(&'a mut i32,)>` is not implemented for `i32` + = help: the trait `for<'a> FnOnce(&'a mut i32)` is not implemented for `i32` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: expected a `FnOnce(&'a mut i32)` closure, found `i32` @@ -59,7 +59,7 @@ LL | | &mut i; LL | | } | |_^ expected an `FnOnce(&'a mut i32)` closure, found `i32` | - = help: the trait `for<'a> FnOnce<(&'a mut i32,)>` is not implemented for `i32` + = help: the trait `for<'a> FnOnce(&'a mut i32)` is not implemented for `i32` error: aborting due to 5 previous errors diff --git a/tests/ui/lifetimes/issue-95023.stderr b/tests/ui/lifetimes/issue-95023.stderr index c4285dbf4bdb..5ff59cccd890 100644 --- a/tests/ui/lifetimes/issue-95023.stderr +++ b/tests/ui/lifetimes/issue-95023.stderr @@ -38,7 +38,7 @@ error[E0277]: expected a `FnMut(&isize)` closure, found `Error` LL | impl Fn(&isize) for Error { | ^^^^^ expected an `FnMut(&isize)` closure, found `Error` | - = help: the trait `FnMut<(&isize,)>` is not implemented for `Error` + = help: the trait `FnMut(&isize)` is not implemented for `Error` note: required by a bound in `Fn` --> $SRC_DIR/core/src/ops/function.rs:LL:COL diff --git a/tests/ui/mismatched_types/suggest-option-asderef-unfixable.stderr b/tests/ui/mismatched_types/suggest-option-asderef-unfixable.stderr index 99c9028ae1ef..a657a65c426d 100644 --- a/tests/ui/mismatched_types/suggest-option-asderef-unfixable.stderr +++ b/tests/ui/mismatched_types/suggest-option-asderef-unfixable.stderr @@ -26,7 +26,7 @@ LL | let _ = produces_string().and_then(takes_str_but_wrong_abi); | | | required by a bound introduced by this call | - = help: the trait `FnOnce<(String,)>` is not implemented for fn item `for<'a> extern "C" fn(&'a str) -> Option<()> {takes_str_but_wrong_abi}` + = help: the trait `FnOnce(String)` is not implemented for fn item `for<'a> extern "C" fn(&'a str) -> Option<()> {takes_str_but_wrong_abi}` note: required by a bound in `Option::::and_then` --> $SRC_DIR/core/src/option.rs:LL:COL @@ -38,7 +38,7 @@ LL | let _ = produces_string().and_then(takes_str_but_unsafe); | | | required by a bound introduced by this call | - = help: the trait `FnOnce<(String,)>` is not implemented for fn item `for<'a> unsafe fn(&'a str) -> Option<()> {takes_str_but_unsafe}` + = help: the trait `FnOnce(String)` is not implemented for fn item `for<'a> unsafe fn(&'a str) -> Option<()> {takes_str_but_unsafe}` = note: unsafe function cannot be called generically without an unsafe block note: required by a bound in `Option::::and_then` --> $SRC_DIR/core/src/option.rs:LL:COL diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr index 67bfaa4c98c7..4c07f4d6b990 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr @@ -6,7 +6,7 @@ LL | call(foo); | | | required by a bound introduced by this call | - = help: the trait `Fn<()>` is not implemented for fn item `fn() {foo}` + = help: the trait `Fn()` is not implemented for fn item `fn() {foo}` = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }` = note: `#[target_feature]` functions do not implement the `Fn` traits note: required by a bound in `call` @@ -23,7 +23,7 @@ LL | call_mut(foo); | | | required by a bound introduced by this call | - = help: the trait `FnMut<()>` is not implemented for fn item `fn() {foo}` + = help: the trait `FnMut()` is not implemented for fn item `fn() {foo}` = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }` = note: `#[target_feature]` functions do not implement the `Fn` traits note: required by a bound in `call_mut` @@ -40,7 +40,7 @@ LL | call_once(foo); | | | required by a bound introduced by this call | - = help: the trait `FnOnce<()>` is not implemented for fn item `fn() {foo}` + = help: the trait `FnOnce()` is not implemented for fn item `fn() {foo}` = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }` = note: `#[target_feature]` functions do not implement the `Fn` traits note: required by a bound in `call_once` @@ -57,7 +57,7 @@ LL | call(foo_unsafe); | | | required by a bound introduced by this call | - = help: the trait `Fn<()>` is not implemented for fn item `unsafe fn() {foo_unsafe}` + = help: the trait `Fn()` is not implemented for fn item `unsafe fn() {foo_unsafe}` = note: unsafe function cannot be called generically without an unsafe block = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }` = note: `#[target_feature]` functions do not implement the `Fn` traits @@ -75,7 +75,7 @@ LL | call_mut(foo_unsafe); | | | required by a bound introduced by this call | - = help: the trait `FnMut<()>` is not implemented for fn item `unsafe fn() {foo_unsafe}` + = help: the trait `FnMut()` is not implemented for fn item `unsafe fn() {foo_unsafe}` = note: unsafe function cannot be called generically without an unsafe block = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }` = note: `#[target_feature]` functions do not implement the `Fn` traits @@ -93,7 +93,7 @@ LL | call_once(foo_unsafe); | | | required by a bound introduced by this call | - = help: the trait `FnOnce<()>` is not implemented for fn item `unsafe fn() {foo_unsafe}` + = help: the trait `FnOnce()` is not implemented for fn item `unsafe fn() {foo_unsafe}` = note: unsafe function cannot be called generically without an unsafe block = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }` = note: `#[target_feature]` functions do not implement the `Fn` traits diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr index 151bd6facf72..fb2e66db1d48 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr @@ -13,8 +13,8 @@ LL | x(()) = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants help: consider further restricting this bound | -LL | const fn need_const_closure i32 + ~const std::ops::FnOnce<((),)>>(x: T) -> i32 { - | ++++++++++++++++++++++++++++++++ +LL | const fn need_const_closure i32 + ~const FnOnce(())>(x: T) -> i32 { + | +++++++++++++++++++ help: add `#![feature(effects)]` to the crate attributes to enable | LL + #![feature(effects)] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr index e2b3e3527012..dede411e69c7 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr @@ -13,8 +13,8 @@ LL | x(()) = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants help: consider further restricting this bound | -LL | const fn need_const_closure i32 + ~const std::ops::FnOnce<((),)>>(x: T) -> i32 { - | ++++++++++++++++++++++++++++++++ +LL | const fn need_const_closure i32 + ~const FnOnce(())>(x: T) -> i32 { + | +++++++++++++++++++ help: add `#![feature(effects)]` to the crate attributes to enable | LL + #![feature(effects)] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.stderr index e5a773123e90..a0f053253892 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.stderr @@ -31,8 +31,8 @@ LL | f() + f() = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants help: consider further restricting this bound | -LL | const fn answer u8 + ~const std::ops::Fn<()>>(f: &F) -> u8 { - | +++++++++++++++++++++++++ +LL | const fn answer u8 + ~const Fn()>(f: &F) -> u8 { + | +++++++++++++ help: add `#![feature(effects)]` to the crate attributes to enable | LL + #![feature(effects)] @@ -47,8 +47,8 @@ LL | f() + f() = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants help: consider further restricting this bound | -LL | const fn answer u8 + ~const std::ops::Fn<()>>(f: &F) -> u8 { - | +++++++++++++++++++++++++ +LL | const fn answer u8 + ~const Fn()>(f: &F) -> u8 { + | +++++++++++++ help: add `#![feature(effects)]` to the crate attributes to enable | LL + #![feature(effects)] @@ -63,8 +63,8 @@ LL | f() * 7 = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants help: consider further restricting this bound | -LL | F: ~const FnOnce() -> u8 + ~const std::ops::Fn<()>, - | +++++++++++++++++++++++++ +LL | F: ~const FnOnce() -> u8 + ~const Fn(), + | +++++++++++++ help: add `#![feature(effects)]` to the crate attributes to enable | LL + #![feature(effects)] diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr index b7a7784755ec..ebd45b9dd963 100644 --- a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr @@ -4,7 +4,7 @@ error[E0277]: expected a `FnOnce(&i32)` closure, found `i32` LL | f:: X<'x, F = i32>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnOnce(&i32)` closure, found `i32` | - = help: the trait `for<'a> FnOnce<(&'a i32,)>` is not implemented for `i32` + = help: the trait `for<'a> FnOnce(&'a i32)` is not implemented for `i32` note: required by a bound in `f` --> $DIR/check-trait-object-bounds-2.rs:8:9 | diff --git a/tests/ui/traits/bound/assoc-fn-bound-root-obligation.rs b/tests/ui/traits/bound/assoc-fn-bound-root-obligation.rs index f8e3f8e968e1..98825bd536e0 100644 --- a/tests/ui/traits/bound/assoc-fn-bound-root-obligation.rs +++ b/tests/ui/traits/bound/assoc-fn-bound-root-obligation.rs @@ -2,7 +2,7 @@ fn strip_lf(s: &str) -> &str { s.strip_suffix(b'\n').unwrap_or(s) //~^ ERROR expected a `FnMut(char)` closure, found `u8` //~| NOTE expected an `FnMut(char)` closure, found `u8` - //~| HELP the trait `FnMut<(char,)>` is not implemented for `u8` + //~| HELP the trait `FnMut(char)` is not implemented for `u8` //~| HELP the following other types implement trait `Pattern<'a>`: //~| NOTE required for `u8` to implement `Pattern<'_>` diff --git a/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr b/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr index 27006f59b902..49272e7d357b 100644 --- a/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr +++ b/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr @@ -4,7 +4,7 @@ error[E0277]: expected a `FnMut(char)` closure, found `u8` LL | s.strip_suffix(b'\n').unwrap_or(s) | ^^^^^^^^^^^^ expected an `FnMut(char)` closure, found `u8` | - = help: the trait `FnMut<(char,)>` is not implemented for `u8`, which is required by `u8: Pattern<'_>` + = help: the trait `FnMut(char)` is not implemented for `u8`, which is required by `u8: Pattern<'_>` = help: the following other types implement trait `Pattern<'a>`: &'b String &'b [char; N] diff --git a/tests/ui/traits/issue-87558.stderr b/tests/ui/traits/issue-87558.stderr index 1ce273a9f25e..dd589cfc3d38 100644 --- a/tests/ui/traits/issue-87558.stderr +++ b/tests/ui/traits/issue-87558.stderr @@ -30,7 +30,7 @@ error[E0277]: expected a `FnMut(&isize)` closure, found `Error` LL | impl Fn(&isize) for Error { | ^^^^^ expected an `FnMut(&isize)` closure, found `Error` | - = help: the trait `FnMut<(&isize,)>` is not implemented for `Error` + = help: the trait `FnMut(&isize)` is not implemented for `Error` note: required by a bound in `Fn` --> $SRC_DIR/core/src/ops/function.rs:LL:COL diff --git a/tests/ui/traits/next-solver/fn-trait.stderr b/tests/ui/traits/next-solver/fn-trait.stderr index e33487235e66..86d97cb16b32 100644 --- a/tests/ui/traits/next-solver/fn-trait.stderr +++ b/tests/ui/traits/next-solver/fn-trait.stderr @@ -6,7 +6,7 @@ LL | require_fn(f as unsafe fn() -> i32); | | | required by a bound introduced by this call | - = help: the trait `Fn<()>` is not implemented for `unsafe fn() -> i32` + = help: the trait `Fn()` is not implemented for `unsafe fn() -> i32` = note: unsafe function cannot be called generically without an unsafe block = note: wrap the `unsafe fn() -> i32` in a closure with no arguments: `|| { /* code */ }` note: required by a bound in `require_fn` @@ -37,7 +37,7 @@ LL | require_fn(g); | | | required by a bound introduced by this call | - = help: the trait `Fn<()>` is not implemented for fn item `extern "C" fn() -> i32 {g}` + = help: the trait `Fn()` is not implemented for fn item `extern "C" fn() -> i32 {g}` = note: wrap the `extern "C" fn() -> i32 {g}` in a closure with no arguments: `|| { /* code */ }` note: required by a bound in `require_fn` --> $DIR/fn-trait.rs:3:23 @@ -67,7 +67,7 @@ LL | require_fn(g as extern "C" fn() -> i32); | | | required by a bound introduced by this call | - = help: the trait `Fn<()>` is not implemented for `extern "C" fn() -> i32` + = help: the trait `Fn()` is not implemented for `extern "C" fn() -> i32` = note: wrap the `extern "C" fn() -> i32` in a closure with no arguments: `|| { /* code */ }` note: required by a bound in `require_fn` --> $DIR/fn-trait.rs:3:23 @@ -97,7 +97,7 @@ LL | require_fn(h); | | | required by a bound introduced by this call | - = help: the trait `Fn<()>` is not implemented for fn item `unsafe fn() -> i32 {h}` + = help: the trait `Fn()` is not implemented for fn item `unsafe fn() -> i32 {h}` = note: unsafe function cannot be called generically without an unsafe block = note: wrap the `unsafe fn() -> i32 {h}` in a closure with no arguments: `|| { /* code */ }` note: required by a bound in `require_fn` diff --git a/tests/ui/traits/suggest-dereferences/root-obligation.stderr b/tests/ui/traits/suggest-dereferences/root-obligation.stderr index 56f95e207158..14b2ecbb9f2d 100644 --- a/tests/ui/traits/suggest-dereferences/root-obligation.stderr +++ b/tests/ui/traits/suggest-dereferences/root-obligation.stderr @@ -2,11 +2,11 @@ error[E0277]: the trait bound `&char: Pattern<'_>` is not satisfied --> $DIR/root-obligation.rs:6:38 | LL | .filter(|c| "aeiou".contains(c)) - | -------- ^ the trait `Fn<(char,)>` is not implemented for `&char`, which is required by `&char: Pattern<'_>` + | -------- ^ the trait `Fn(char)` is not implemented for `&char`, which is required by `&char: Pattern<'_>` | | | required by a bound introduced by this call | - = note: required for `&char` to implement `FnOnce<(char,)>` + = note: required for `&char` to implement `FnOnce(char)` = note: required for `&char` to implement `Pattern<'_>` note: required by a bound in `core::str::::contains` --> $SRC_DIR/core/src/str/mod.rs:LL:COL diff --git a/tests/ui/type-alias-impl-trait/issue-63279.stderr b/tests/ui/type-alias-impl-trait/issue-63279.stderr index 58cafd21ca87..97158ee297da 100644 --- a/tests/ui/type-alias-impl-trait/issue-63279.stderr +++ b/tests/ui/type-alias-impl-trait/issue-63279.stderr @@ -4,7 +4,7 @@ error[E0277]: expected a `FnOnce()` closure, found `()` LL | fn c() -> Closure { | ^^^^^^^ expected an `FnOnce()` closure, found `()` | - = help: the trait `FnOnce<()>` is not implemented for `()` + = help: the trait `FnOnce()` is not implemented for `()` = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }` error[E0277]: expected a `FnOnce()` closure, found `()` @@ -13,7 +13,7 @@ error[E0277]: expected a `FnOnce()` closure, found `()` LL | || -> Closure { || () } | ^^^^^^^ expected an `FnOnce()` closure, found `()` | - = help: the trait `FnOnce<()>` is not implemented for `()` + = help: the trait `FnOnce()` is not implemented for `()` = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }` error[E0308]: mismatched types diff --git a/tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr b/tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr index 795bd0a0d180..9c5d824185b8 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr +++ b/tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr @@ -6,7 +6,7 @@ LL | let x = call_it(&S, 22); | | | required by a bound introduced by this call | - = help: the trait `Fn<(isize,)>` is not implemented for `S` + = help: the trait `Fn(isize)` is not implemented for `S` = note: `S` implements `FnMut`, but it must implement `Fn`, which is more general note: required by a bound in `call_it` --> $DIR/unboxed-closures-fnmut-as-fn.rs:22:14 diff --git a/tests/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr b/tests/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr index d836af2b0149..dfdb3ea19c3f 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr +++ b/tests/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr @@ -6,7 +6,7 @@ LL | let x = call_it(&square, 22); | | | required by a bound introduced by this call | - = help: the trait `for<'a> Fn<(&'a isize,)>` is not implemented for fn item `for<'a> unsafe fn(&'a isize) -> isize {square}` + = help: the trait `for<'a> Fn(&'a isize)` is not implemented for fn item `for<'a> unsafe fn(&'a isize) -> isize {square}` = note: unsafe function cannot be called generically without an unsafe block note: required by a bound in `call_it` --> $DIR/unboxed-closures-unsafe-extern-fn.rs:9:15 @@ -22,7 +22,7 @@ LL | let y = call_it_mut(&mut square, 22); | | | required by a bound introduced by this call | - = help: the trait `for<'a> FnMut<(&'a isize,)>` is not implemented for fn item `for<'a> unsafe fn(&'a isize) -> isize {square}` + = help: the trait `for<'a> FnMut(&'a isize)` is not implemented for fn item `for<'a> unsafe fn(&'a isize) -> isize {square}` = note: unsafe function cannot be called generically without an unsafe block note: required by a bound in `call_it_mut` --> $DIR/unboxed-closures-unsafe-extern-fn.rs:12:19 @@ -38,7 +38,7 @@ LL | let z = call_it_once(square, 22); | | | required by a bound introduced by this call | - = help: the trait `for<'a> FnOnce<(&'a isize,)>` is not implemented for fn item `for<'a> unsafe fn(&'a isize) -> isize {square}` + = help: the trait `for<'a> FnOnce(&'a isize)` is not implemented for fn item `for<'a> unsafe fn(&'a isize) -> isize {square}` = note: unsafe function cannot be called generically without an unsafe block note: required by a bound in `call_it_once` --> $DIR/unboxed-closures-unsafe-extern-fn.rs:15:20 diff --git a/tests/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr b/tests/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr index c0dcf83a5bb0..b4521cc6890d 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr +++ b/tests/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr @@ -6,7 +6,7 @@ LL | let x = call_it(&square, 22); | | | required by a bound introduced by this call | - = help: the trait `for<'a> Fn<(&'a isize,)>` is not implemented for fn item `for<'a> extern "C" fn(&'a isize) -> isize {square}` + = help: the trait `for<'a> Fn(&'a isize)` is not implemented for fn item `for<'a> extern "C" fn(&'a isize) -> isize {square}` note: required by a bound in `call_it` --> $DIR/unboxed-closures-wrong-abi.rs:9:15 | @@ -21,7 +21,7 @@ LL | let y = call_it_mut(&mut square, 22); | | | required by a bound introduced by this call | - = help: the trait `for<'a> FnMut<(&'a isize,)>` is not implemented for fn item `for<'a> extern "C" fn(&'a isize) -> isize {square}` + = help: the trait `for<'a> FnMut(&'a isize)` is not implemented for fn item `for<'a> extern "C" fn(&'a isize) -> isize {square}` note: required by a bound in `call_it_mut` --> $DIR/unboxed-closures-wrong-abi.rs:12:19 | @@ -36,7 +36,7 @@ LL | let z = call_it_once(square, 22); | | | required by a bound introduced by this call | - = help: the trait `for<'a> FnOnce<(&'a isize,)>` is not implemented for fn item `for<'a> extern "C" fn(&'a isize) -> isize {square}` + = help: the trait `for<'a> FnOnce(&'a isize)` is not implemented for fn item `for<'a> extern "C" fn(&'a isize) -> isize {square}` note: required by a bound in `call_it_once` --> $DIR/unboxed-closures-wrong-abi.rs:15:20 | diff --git a/tests/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr b/tests/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr index d261c38f50c2..5519bb33ebc2 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr +++ b/tests/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr @@ -6,7 +6,7 @@ LL | let x = call_it(&square, 22); | | | required by a bound introduced by this call | - = help: the trait `for<'a> Fn<(&'a isize,)>` is not implemented for fn item `unsafe fn(isize) -> isize {square}` + = help: the trait `for<'a> Fn(&'a isize)` is not implemented for fn item `unsafe fn(isize) -> isize {square}` = note: unsafe function cannot be called generically without an unsafe block note: required by a bound in `call_it` --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:10:15 @@ -22,7 +22,7 @@ LL | let y = call_it_mut(&mut square, 22); | | | required by a bound introduced by this call | - = help: the trait `for<'a> FnMut<(&'a isize,)>` is not implemented for fn item `unsafe fn(isize) -> isize {square}` + = help: the trait `for<'a> FnMut(&'a isize)` is not implemented for fn item `unsafe fn(isize) -> isize {square}` = note: unsafe function cannot be called generically without an unsafe block note: required by a bound in `call_it_mut` --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:13:19 @@ -38,7 +38,7 @@ LL | let z = call_it_once(square, 22); | | | required by a bound introduced by this call | - = help: the trait `for<'a> FnOnce<(&'a isize,)>` is not implemented for fn item `unsafe fn(isize) -> isize {square}` + = help: the trait `for<'a> FnOnce(&'a isize)` is not implemented for fn item `unsafe fn(isize) -> isize {square}` = note: unsafe function cannot be called generically without an unsafe block note: required by a bound in `call_it_once` --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:16:20 diff --git a/tests/ui/unsafe/initializing-ranged-via-ctor.stderr b/tests/ui/unsafe/initializing-ranged-via-ctor.stderr index 56b112867cf0..040c1d5bcbee 100644 --- a/tests/ui/unsafe/initializing-ranged-via-ctor.stderr +++ b/tests/ui/unsafe/initializing-ranged-via-ctor.stderr @@ -6,7 +6,7 @@ LL | println!("{:?}", Some(1).map(NonZeroAndOneU8).unwrap()); | | | required by a bound introduced by this call | - = help: the trait `FnOnce<({integer},)>` is not implemented for fn item `unsafe fn(u8) -> NonZeroAndOneU8 {NonZeroAndOneU8}` + = help: the trait `FnOnce({integer})` is not implemented for fn item `unsafe fn(u8) -> NonZeroAndOneU8 {NonZeroAndOneU8}` = note: unsafe function cannot be called generically without an unsafe block note: required by a bound in `Option::::map` --> $SRC_DIR/core/src/option.rs:LL:COL From 2f35cfd87a6b1e4917b462447cb5b1ec1835866f Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Wed, 29 May 2024 19:30:51 -0400 Subject: [PATCH 084/211] Bump the stage0 compiler to beta.7 (2024-05-25) --- src/stage0 | 856 ++++++++++++++++++++++++++--------------------------- 1 file changed, 428 insertions(+), 428 deletions(-) diff --git a/src/stage0 b/src/stage0 index 72f50b787a7a..ed88549e6982 100644 --- a/src/stage0 +++ b/src/stage0 @@ -14,434 +14,434 @@ nightly_branch=master # All changes below this comment will be overridden the next time the # tool is executed. -compiler_date=2024-05-24 +compiler_date=2024-05-26 compiler_version=beta -rustfmt_date=2024-05-24 +rustfmt_date=2024-05-29 rustfmt_version=nightly -dist/2024-05-24/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz=502e7f1a05acd503079654dca24a1a9945452580d835d0b6a2cc21155837a4c7 -dist/2024-05-24/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz=0bcf49fe166183955a27a0be2e83aa6d6ee9820a475323d8f61c6b159960d3f8 -dist/2024-05-24/rustc-beta-aarch64-pc-windows-msvc.tar.gz=234d90368b765cbe8824068eb2d21ca4c9d7f5cd401f686ef5b338a1781d1468 -dist/2024-05-24/rustc-beta-aarch64-pc-windows-msvc.tar.xz=085cc56230431db4c6088e0f9c4d63fb5af2a7064a5a7e21d5d19be1d3026d18 -dist/2024-05-24/rustc-beta-i686-unknown-linux-gnu.tar.gz=790bcf8e2fe47efc4a0071093df383d70c3383ba3290aaa2f6b5eade8e2f35f0 -dist/2024-05-24/rustc-beta-i686-unknown-linux-gnu.tar.xz=7f8df95a04a6e57db99fb84d60baeddef4a69f13f026f5cc5719a8b6c231d4b8 -dist/2024-05-24/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz=939759a91a408b4ecd8921e0cf07676cc473d1c23a2021a57f0f8b04465e9ed4 -dist/2024-05-24/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz=5ac62bb9f5d7e7e499598f5579156e593d07c91eadfd1326b29f2bea29122164 -dist/2024-05-24/rustc-beta-aarch64-apple-darwin.tar.gz=134d09a9f7c51f1862f1b361da5608bdae02bef2fdb994e30404a8b0e309b7d6 -dist/2024-05-24/rustc-beta-aarch64-apple-darwin.tar.xz=c3eae7e3583a6f4e68d388a73d2414ca355ef98215417f908ac81e1ea90b2d51 -dist/2024-05-24/rustc-beta-aarch64-unknown-linux-gnu.tar.gz=0f9aa17c2a8748cdf06bbd77bb948ba65794b89587744839db503bb0988e0824 -dist/2024-05-24/rustc-beta-aarch64-unknown-linux-gnu.tar.xz=390c430ffe5f237d547ae2c93a058122d3b8fbf4ea71b20018f0f8bf83858398 -dist/2024-05-24/rustc-beta-powerpc-unknown-linux-gnu.tar.gz=bf6a18c4f54921c46d90fe2a53f6e3044a32f327d6cd13e8308db683a428aef7 -dist/2024-05-24/rustc-beta-powerpc-unknown-linux-gnu.tar.xz=27dcf104f3ca958f0ef3bed47c26e3318e545d1de06f27bf9b25aac97a21c06b -dist/2024-05-24/rustc-beta-x86_64-unknown-linux-musl.tar.gz=07c74d5cc87fba304d33ac7844a1e762225f9ec8ca5a5c6b7bab4c427ffed80a -dist/2024-05-24/rustc-beta-x86_64-unknown-linux-musl.tar.xz=08b6c39e9315c0eee5174d540851c6530e6b1c900db4396fdf8a967b88d69a75 -dist/2024-05-24/rustc-beta-aarch64-unknown-linux-musl.tar.gz=c3aa3cead301f7081c88b5bbd0c0b5a24eab203cbdb2d772ed0ddba8e3034928 -dist/2024-05-24/rustc-beta-aarch64-unknown-linux-musl.tar.xz=943a3fd053657bce6cafb589665c5ad98d5c453ab7c594650ed8c3cd15356647 -dist/2024-05-24/rustc-beta-s390x-unknown-linux-gnu.tar.gz=b8db693c04ad41d1e90b7a3bec7f41a0a21872a220342742402dcd0cb4f28799 -dist/2024-05-24/rustc-beta-s390x-unknown-linux-gnu.tar.xz=ec509af079e002d181b092f1a9e768744656b93fc78466efad8fac567d2184f1 -dist/2024-05-24/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz=50f60b246b50778720557f16e87cc19373dd44a77e423bc1e2db1e504557cb58 -dist/2024-05-24/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz=ed2a36058a7f0a2393309fbbe435a0c498ab682e91d757f6d70d9c16091dd646 -dist/2024-05-24/rustc-beta-x86_64-unknown-illumos.tar.gz=9b931dc596fd980a66507ca9c83b17c4e6d376a9741361a41dfb176f41b4bd2c -dist/2024-05-24/rustc-beta-x86_64-unknown-illumos.tar.xz=e1bb3f44adf89ff9900ed3bdabb7ab386018c8894d6d92c68f3881077f777a1c -dist/2024-05-24/rustc-beta-x86_64-pc-windows-msvc.tar.gz=c5427a8ba5dc41aa00b8194c49b711685a6c6bd0674ab93ec44b953897def2f4 -dist/2024-05-24/rustc-beta-x86_64-pc-windows-msvc.tar.xz=274545121eb6003eb52fddf030f8893ad63cebee564648dbef312aa28853cb54 -dist/2024-05-24/rustc-beta-i686-pc-windows-msvc.tar.gz=36185524fe00de47a92cb0fb766a4a7afadee469cd5f1ef1345ac24364499425 -dist/2024-05-24/rustc-beta-i686-pc-windows-msvc.tar.xz=7681b6695ac56c50277318fb9deec495fcadcb266a763f1ad3d19b88c9a520fb -dist/2024-05-24/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz=d1115327b8cfb23e60a70510f78e39329f2092a0a99763b2cbd25929c41cb24f -dist/2024-05-24/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz=7bb0b5b15e5218d9e4554ff2eec03cbe2fde2e957f954fa08aa7079b334bad05 -dist/2024-05-24/rustc-beta-x86_64-unknown-netbsd.tar.gz=6a46a111e30efc6f8f090b2c9e547465e6fcf836b9433fc1f8c53276a0ef63fb -dist/2024-05-24/rustc-beta-x86_64-unknown-netbsd.tar.xz=9516471cb5d3377e1430e64171b7a289bd8a8674032d73c739e0cffa85e87e92 -dist/2024-05-24/rustc-beta-x86_64-apple-darwin.tar.gz=63331eea78233ec4ee4d9390a509a587bbb6e07ce0748fca36cf93a0f4ecb216 -dist/2024-05-24/rustc-beta-x86_64-apple-darwin.tar.xz=b668abe9cb4c5366ee866f8e399ced6c9a8b560f5e5adbe7d6c07058762be21d -dist/2024-05-24/rustc-beta-x86_64-pc-windows-gnu.tar.gz=076e95ca2413fc3f07257ce0b94212db0331e797679a60695929cb588c6047cf -dist/2024-05-24/rustc-beta-x86_64-pc-windows-gnu.tar.xz=d1d006a216c2358a33000e400b5a2c223ee0ab875cfd57eca95b9bd230494d62 -dist/2024-05-24/rustc-beta-x86_64-unknown-freebsd.tar.gz=48ccaab8b59f8bb3e1e0fb82368b79d317e66e4b6a2c6d18d0d49b32e96b2e95 -dist/2024-05-24/rustc-beta-x86_64-unknown-freebsd.tar.xz=a050b10d6f67c1f1d2cdb2425ffb51445ade293328ec3e235400c151a447beb9 -dist/2024-05-24/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz=21f26e3028f1174184be66ce88597e1551d2dbf7d9458f528f15366c6cf52c30 -dist/2024-05-24/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz=fe504571f52c9eaba68fcc07398db049e3dd6131daa14c2b999540b84cec4885 -dist/2024-05-24/rustc-beta-x86_64-unknown-linux-gnu.tar.gz=082828da023201d2b8f84e686d727f77b76a71c929c5588098d8c4609ffca336 -dist/2024-05-24/rustc-beta-x86_64-unknown-linux-gnu.tar.xz=13bf4a5f012b29334dececacfe16ab6755f7b97165229cff7c27d37b6acb455f -dist/2024-05-24/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz=f4584c00af06eb05e6f238f3ce8cbb39ace84e3aad7a3b158b5bb591e522eab8 -dist/2024-05-24/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz=8fe01de1853880df20e355ba3925eb1cc537a6fb6aca53b638ee74f689f15cdf -dist/2024-05-24/rustc-beta-arm-unknown-linux-gnueabi.tar.gz=7a24b865db48708120ad670811238fccfd054bba0a92d6b436237c0726678413 -dist/2024-05-24/rustc-beta-arm-unknown-linux-gnueabi.tar.xz=3716d2a3896a2f3cb774c265e58d29e4f8ea35228261f499b96887cb40ff5cd9 -dist/2024-05-24/rustc-beta-i686-pc-windows-gnu.tar.gz=336dd7b17d5ea546f359fff5e7697f82022b0710e1d6ab513370f21741d6f737 -dist/2024-05-24/rustc-beta-i686-pc-windows-gnu.tar.xz=829a078f5d4126d90e117c2c5d31f259b3ba4960b834830c0e49a23ce3bb339f -dist/2024-05-24/rust-std-beta-x86_64-unknown-uefi.tar.gz=3522e09c17465ceda12ad69adc341cda01171cc7275623ea55cc0a56611fcff9 -dist/2024-05-24/rust-std-beta-x86_64-unknown-uefi.tar.xz=d71dac0e0316928d2e5c83c092fab2605b3e46b75a0de867e838067a5134851d -dist/2024-05-24/rust-std-beta-armv7r-none-eabihf.tar.gz=d9fe62eafe589b5223097d35104c5d32b623e98a0e60284254770dc5a760ded8 -dist/2024-05-24/rust-std-beta-armv7r-none-eabihf.tar.xz=0ed3d3b74882594f08be828a491bad42c5b73914c461346e634a38dbf609de0e -dist/2024-05-24/rust-std-beta-wasm32-wasip1-threads.tar.gz=850236f8f00bfdf0f032a2f4b2c3ee1c71ddd7fe11a87648066eb63801d302ff -dist/2024-05-24/rust-std-beta-wasm32-wasip1-threads.tar.xz=db1c182ddbb3276752c16d4d9c9ee94f97b426349fb44a456c276268c4aa8be4 -dist/2024-05-24/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz=ce22565ddab95e2f43abc8a864787820f3b1dd0a0f174639b90c26726da667ab -dist/2024-05-24/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz=214c16191cc3a3623a7b8d3a995c50132c03f90b3fad0d08927a5e449ea13923 -dist/2024-05-24/rust-std-beta-i686-unknown-freebsd.tar.gz=478c1de19c252d581b4438af70b37b36c0bd240e5bf5ca5ba4e752438e80707b -dist/2024-05-24/rust-std-beta-i686-unknown-freebsd.tar.xz=0948aa34ea060445ca2a410df33622a9228f3fe0f24a94442799568b251c1e10 -dist/2024-05-24/rust-std-beta-thumbv8m.main-none-eabi.tar.gz=e139b5a0151a1a3ff8e6bc94ff856522be558cffbf51fd76a434591e30d51ccd -dist/2024-05-24/rust-std-beta-thumbv8m.main-none-eabi.tar.xz=dccf2fcff4e0980b3e0edd30a565c6bc3f994812f2acce9c7a07eb6ea8ad84ab -dist/2024-05-24/rust-std-beta-wasm32-unknown-unknown.tar.gz=2f6aff225189a507b79e84388b69fdcfe12ac29a6a955cd60d34298bb7435c79 -dist/2024-05-24/rust-std-beta-wasm32-unknown-unknown.tar.xz=2b623f3318ff77aada72d0ca8ce46e807f8e4833dd74717d1a4102f1ee3bef78 -dist/2024-05-24/rust-std-beta-i686-unknown-linux-musl.tar.gz=85e016d2c36da363618b184576e35263034ef0291e8a36f9380879917e757f67 -dist/2024-05-24/rust-std-beta-i686-unknown-linux-musl.tar.xz=fb0be15c71068cdec7e8b75f6ebcf1094d610c0e41d1cec08c2031d8583d10c5 -dist/2024-05-24/rust-std-beta-thumbv6m-none-eabi.tar.gz=96c68111c9a491f816f56ae8f1f552ce31738fa9b9d9d00e42c2d1f0a3628ef0 -dist/2024-05-24/rust-std-beta-thumbv6m-none-eabi.tar.xz=a6e20d5c434cbe9b86e406c6132d1986489fe76168be7a60b6459b0f2691877b -dist/2024-05-24/rust-std-beta-i686-pc-windows-gnullvm.tar.gz=933e7b14c199d36f6eb51ae6527c9af2d094ec13bb1299bcf8c72ba9b0d69515 -dist/2024-05-24/rust-std-beta-i686-pc-windows-gnullvm.tar.xz=ade7325d0787ade9c3122a042baf7238ba5d493a6b7b7ea311421e11a15586cb -dist/2024-05-24/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz=8816d3c9fbe0dfadfab0ba7db858bfd32546161f6460b4c9160a4e77ab54ac8f -dist/2024-05-24/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz=da52d6feb060edada6fb0f747ef1c1ea658f2070c024a873c69ba909ade175b2 -dist/2024-05-24/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz=b699e48e19a1860132719487bf287a3a3f014257182a53b4ed95f1316f401fec -dist/2024-05-24/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz=402cad3c14a356f7345bb8cc93ef7186fd09b4ae1abdd13bc020c7e424a941d3 -dist/2024-05-24/rust-std-beta-aarch64-unknown-none.tar.gz=d875d0e34057c77c34e2020310f33a56f08f3b063b202f513be8de96319e9e4b -dist/2024-05-24/rust-std-beta-aarch64-unknown-none.tar.xz=3f489181280332f0d7169f656d03252f7de43b84a6fd6de9fb9c6906c09f7b72 -dist/2024-05-24/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz=072503fd29be4101f8e1f75bad03a5b2486fd2e8e2f217f651d6cee2e0b2f032 -dist/2024-05-24/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz=b96a542616a05b2ccaad49d9e22273341df7000ca63e4eb91ee219e8b931f4b0 -dist/2024-05-24/rust-std-beta-wasm32-wasip1.tar.gz=ccae6a247c76bbe08216faad0faff0d2052982baa1cba8d403f3182bd3d92e46 -dist/2024-05-24/rust-std-beta-wasm32-wasip1.tar.xz=ceb781289ab079bbab947f366eeb4087b04082326c4f935c78b3887351fe6c89 -dist/2024-05-24/rust-std-beta-i686-unknown-uefi.tar.gz=ed888cc3847b8616d50e80d6c3c0116c8c0e73c6b7fc3b39bb04bced9fb8d9fa -dist/2024-05-24/rust-std-beta-i686-unknown-uefi.tar.xz=51ef73968d5e9ae2b7d857befa8827aac37c490f2051f526ad1b5089ee9fa550 -dist/2024-05-24/rust-std-beta-x86_64-unknown-fuchsia.tar.gz=226d46a2cf4e5c58f1ad1357bfc607d23c195122c7a74a5ddb6636ed35d295a4 -dist/2024-05-24/rust-std-beta-x86_64-unknown-fuchsia.tar.xz=27e68d85bfbc8302e68aea58bc57d1d8ff038a0eee7629f17f479d0ea1a6acaa -dist/2024-05-24/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz=132be65f60c5d0b7d6293495acf51559b8855c80498befe98d6cef752deb1a71 -dist/2024-05-24/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz=7f938a1bfcea115c99e7e813c9737f86788d78af8f97265ce8f7ebde52dca54b -dist/2024-05-24/rust-std-beta-x86_64-pc-windows-msvc.tar.gz=186c252edf1497a5f559dabbd8245491e3fef7caa6a80b5dc989275caeed95af -dist/2024-05-24/rust-std-beta-x86_64-pc-windows-msvc.tar.xz=3be2944eee2ec57d7ae3d2eb87b7b1881590adaa68c5c6851fa7c027b4f7c4a1 -dist/2024-05-24/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz=ae9bfb56c1be153d29371a75141471f676cdf5ec6e8b6af252f4a6f3a1054712 -dist/2024-05-24/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz=1387267e76f332fdfaea426468a45ad5d967f1ee9a211b9b72c6cace0b746ad1 -dist/2024-05-24/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz=ef44a8ad9b1e07d240a00a2bec592d4f19a099ddfd8b2398f4ea2d50216548e0 -dist/2024-05-24/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz=25d0da3cc4616bf6778af8277341b3e436300865245d016a370892d1afcfef31 -dist/2024-05-24/rust-std-beta-x86_64-unknown-freebsd.tar.gz=d5da4fed34f7c008e6365475e2c9a8ac6b74468839fe017827e3c884fca95b1c -dist/2024-05-24/rust-std-beta-x86_64-unknown-freebsd.tar.xz=7aeade644917bfb22fe68f427a46e21834d45fcc626755b0af806ae28d018518 -dist/2024-05-24/rust-std-beta-wasm32-wasi.tar.gz=3c5d32303ca72eb469730421945f2d2216f8f96aa160d11d6b2e38c6350763dd -dist/2024-05-24/rust-std-beta-wasm32-wasi.tar.xz=9705313b0e7d696b4e7c4ae6201e1dd2a02c51b5d0caac730591419322462f0a -dist/2024-05-24/rust-std-beta-armv7a-none-eabi.tar.gz=afc32902cd96bfd1c72e5d2cda240a2275f8b8262a0f952e53b39bdf267ffe18 -dist/2024-05-24/rust-std-beta-armv7a-none-eabi.tar.xz=8a34c9025601a2ee0dabce89ec195fa3bf990986517955768409f3620ae90efa -dist/2024-05-24/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz=dddbace8cce3233b6a906ea75032e21c7f2a07be131ff7c356f9d7d59bf90fee -dist/2024-05-24/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz=b833758c5555d8805191527f676a20ba6e902fb4da538df8795c5282f495ab65 -dist/2024-05-24/rust-std-beta-aarch64-unknown-uefi.tar.gz=2750fc63254bdb773423483808363048126f20246d8d1a26800d06dc7489807c -dist/2024-05-24/rust-std-beta-aarch64-unknown-uefi.tar.xz=ccef9823e93948996965f9ed2e73f9dd1638a840c57ef96e5c8df525ac241af3 -dist/2024-05-24/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz=47ebc0eb1bbfa824df620a73d1253f22dda9a2f0810c9b6c542e4a3ed545e899 -dist/2024-05-24/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz=6b5d87a1de21c15352121a9380449ae1df9e49b983ffa2431e3e2767a1b36501 -dist/2024-05-24/rust-std-beta-nvptx64-nvidia-cuda.tar.gz=6e3adc75a553a2d97214d2147340ce23a09a2cad1f5e411048b17f74cc735128 -dist/2024-05-24/rust-std-beta-nvptx64-nvidia-cuda.tar.xz=473c1a57e19527a5a710b5ee59692a1f9d0759d5163de0337e061b006765f197 -dist/2024-05-24/rust-std-beta-i586-pc-windows-msvc.tar.gz=eebbea699b2cd32d14123af5ce49ed2fc81f8b2b8de8a83048bdaaae3d0ddbd9 -dist/2024-05-24/rust-std-beta-i586-pc-windows-msvc.tar.xz=2a9591eeebfa1ebb4af31ec8c0929b9bdb353ed92c1f22f4a5651d0578a6a5fb -dist/2024-05-24/rust-std-beta-arm-unknown-linux-musleabi.tar.gz=036a0bea6dbf65183a3d772fe2cf79c9ad86100274680b639e23683b5a29aa6a -dist/2024-05-24/rust-std-beta-arm-unknown-linux-musleabi.tar.xz=ebb328a83ad6cdee2e2b26fce63e6ad57293726a59352eb7bb9ac2d022504c33 -dist/2024-05-24/rust-std-beta-i586-unknown-linux-gnu.tar.gz=254ba6539d9c7b3b7d1b7ef92056c8c4dc7a9378da7da2575b4010cdbf9ca718 -dist/2024-05-24/rust-std-beta-i586-unknown-linux-gnu.tar.xz=9dfb77901799850f50ae983d05aa9467fbf50d0995b3dd1de880dcb48663706c -dist/2024-05-24/rust-std-beta-arm-linux-androideabi.tar.gz=d99a69e9dd172506a73412c5d3b338a0df798ef77e20e5d8376989d74ada2289 -dist/2024-05-24/rust-std-beta-arm-linux-androideabi.tar.xz=35f9022e3aff144157a504e73107cdc4fd7aab4e175eb193d240cdbc539d587f -dist/2024-05-24/rust-std-beta-x86_64-unknown-linux-musl.tar.gz=aca1d6e2bafd7a446a52bd5a6b6daddb36a2e76f29ffac3ba17cc47f80c2af9c -dist/2024-05-24/rust-std-beta-x86_64-unknown-linux-musl.tar.xz=f967c44f7ed974abf292f4b77ddf1e875f08eecb9f8ad930f7d22ca49253b59e -dist/2024-05-24/rust-std-beta-i686-pc-windows-gnu.tar.gz=61da28d58e15c845d96ae5c1aa93710c47cc3f1903e001bac55e208ea76693a5 -dist/2024-05-24/rust-std-beta-i686-pc-windows-gnu.tar.xz=6aae3ee172ed6ea5c4f547841c70bfbf26879698c984c4b94f295846282a8643 -dist/2024-05-24/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz=aa7cd934f8d17ed79c1d5e37acd67e3f988a0b727a72960b7d9858f965694c19 -dist/2024-05-24/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz=2ab9fe2d4e6679ab880ff27addee27c9efa6c851e4781f20971ce035b5037b86 -dist/2024-05-24/rust-std-beta-thumbv7em-none-eabi.tar.gz=96281c576bbf4a1eb9ce814517040189be4529050af2fbce9d20cdf0549154e1 -dist/2024-05-24/rust-std-beta-thumbv7em-none-eabi.tar.xz=1f37734d1987dd0c58f03ee1374a214ef3d35244d455908ca9b346d5945e3aaa -dist/2024-05-24/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz=515f28e48b0237144bb4110b15c1dfa9dbbd23167b3798a32cd8cf28e741e2d6 -dist/2024-05-24/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz=469ee9ef8ec15d8203f07630d72ac32ac262a0708617b712f139f1f3adfc7e62 -dist/2024-05-24/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz=066b9b8550ad7960bf6653bdc762ad5264f697ce2122b6789175d270ed0ff9ae -dist/2024-05-24/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz=7dcde7ccfd02c980ddc33ebb980b1fc364aab099ffd7698a758a375102d48ed0 -dist/2024-05-24/rust-std-beta-aarch64-apple-ios.tar.gz=b54b1fe276bf44c39f55678aa4b5c8d50c44332d8ba515d94d057da2e1e036c1 -dist/2024-05-24/rust-std-beta-aarch64-apple-ios.tar.xz=1ed8171e1e957aec55be7410f5f9fd7e1b48473f4bc85d1f81360502ddf562a2 -dist/2024-05-24/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz=b85f3e30dada40bc826daa9f02883924cabcf25dd0738e9f783b4185e5bcd6fb -dist/2024-05-24/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz=4a5642069ce14b53a0ebedf808e9580cf145e30f0e8e61400a27ed14956ed295 -dist/2024-05-24/rust-std-beta-i686-pc-windows-msvc.tar.gz=3296a8cbcbbc8296a28d1f97bf24f0c47142c7524ca83d1e215adc6cf1ae459e -dist/2024-05-24/rust-std-beta-i686-pc-windows-msvc.tar.xz=5ff405dfdbc42805f8fadd06323066e2a0aa238517871c65198e0c7eb8f6c210 -dist/2024-05-24/rust-std-beta-thumbv7em-none-eabihf.tar.gz=01893bc682d37aa38bff5d41e8b61d23ece07f64f950b2efefa2e67efeb47081 -dist/2024-05-24/rust-std-beta-thumbv7em-none-eabihf.tar.xz=fcf60f22fab4d53f0352f98c1def023ec174d4d930b7ec0eef71e4ca6a1315de -dist/2024-05-24/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz=39feeb9da7f9901db336af32543785fd3b0a587684aabf42254efd763461c820 -dist/2024-05-24/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz=f14b77154f905166c769012e600321f1ff9cf79155f9031d7a05eb7469353569 -dist/2024-05-24/rust-std-beta-armv7-linux-androideabi.tar.gz=49c2f372740848e34c8a60256ffde8c578be529087855e517af27a3f4f440428 -dist/2024-05-24/rust-std-beta-armv7-linux-androideabi.tar.xz=5dfc8fdffd7f502ff05f50b8834424f7129b0f7be80647eac466e9fa19660e12 -dist/2024-05-24/rust-std-beta-i586-unknown-linux-musl.tar.gz=7dcdd118d7f862b7bb532fdbfa94a92d88a035a22310c4c2f6c9fc2230467d6c -dist/2024-05-24/rust-std-beta-i586-unknown-linux-musl.tar.xz=dbccad2e2b705f2b38ad2b0a8da9bdd3ab58849818051674c26cf516ad7fb37b -dist/2024-05-24/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz=06ad4618876e3c9413fde9763b93271e15451ab91c65b56ad6f8be958d2651ff -dist/2024-05-24/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz=079120eec04d3940aa4f96627fd6d9ef8f74662eb132f52f4e5c797f5dd16678 -dist/2024-05-24/rust-std-beta-thumbv7m-none-eabi.tar.gz=2b0c040d29177a6a1829b3f4e5f5be9313c70205366707d586f4290e80c081d2 -dist/2024-05-24/rust-std-beta-thumbv7m-none-eabi.tar.xz=7487ecd436a99fbea0a968c082b42c6036ea0a7f66e8175e61aa0139ff2f80bd -dist/2024-05-24/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz=041e08179dd50bf95ca4f66bc5b1a10b958bc696774997139fa6754587c45336 -dist/2024-05-24/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz=4a7e06b730d3e35318690fc2927e4084062754c2256e5ea2bb37014e3c66101b -dist/2024-05-24/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz=e0cbee59a29d119616e60766eb68b581e27a661498c6af8b7e3cb8279078ba49 -dist/2024-05-24/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz=7a21de0bf78aa43cba18f560bf2668c902ee4755fc74f7fee7128f0fa9ded5f3 -dist/2024-05-24/rust-std-beta-aarch64-apple-darwin.tar.gz=dfd520844463a19cb99dc9c33849d646970166e3424c5dd96fb69c4483bd14f7 -dist/2024-05-24/rust-std-beta-aarch64-apple-darwin.tar.xz=7aa566be6a31bc5ebe6f588f521933d2d30514a3caa29332c91a9bba2f41f37d -dist/2024-05-24/rust-std-beta-wasm32-unknown-emscripten.tar.gz=70efc840eb8b45f0c4f527165ca87a913d18661cf4996766448c03bacc5ac429 -dist/2024-05-24/rust-std-beta-wasm32-unknown-emscripten.tar.xz=b19493c7894240666496a4cde38cda7dbcce3977c0014cc531f27fedfaabeb6b -dist/2024-05-24/rust-std-beta-loongarch64-unknown-none.tar.gz=ae808e787aa5997f2f6ab0fa4bcd65c3c3724d909738b9f78998796c939c6d83 -dist/2024-05-24/rust-std-beta-loongarch64-unknown-none.tar.xz=2bb6da4f902a8f1d6725705c16d513478c027cbf82c8ab9948feeeed028f60e3 -dist/2024-05-24/rust-std-beta-x86_64-linux-android.tar.gz=f29b6c9b9f507858c08a560569bea2a65a749f3f906caa92a2f78998e3530d25 -dist/2024-05-24/rust-std-beta-x86_64-linux-android.tar.xz=7b79450216d0e11e6c3cf241cd57b5064388a8d6d7c0b0e52d29f8373ff97da1 -dist/2024-05-24/rust-std-beta-x86_64-unknown-none.tar.gz=37b03d9f74ec899fde6ae56eb6af8e6b04c2bf8fdf2de08f14fd576569c7f78f -dist/2024-05-24/rust-std-beta-x86_64-unknown-none.tar.xz=6d212f421ff3b67ed0c0b205a1c3af1df6c5210d21127faf53f906ddc46f1758 -dist/2024-05-24/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz=53d0a088e7e70b333a72a83bd42f57c81c24520bad9ae89ef710bc2ad658984b -dist/2024-05-24/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz=f26ac1c83990634235b44e14884307a8cc35ab730747b6e4fc90542a985d164d -dist/2024-05-24/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz=d8385e3c27433ca0898344dad62a91a5bc29b5cbacc5660cef82db0475ce9a04 -dist/2024-05-24/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz=4478fe4b44978f4000708014802365ff25dde402acdf1546101fa07fef329c9e -dist/2024-05-24/rust-std-beta-x86_64-unknown-netbsd.tar.gz=ebeb2599218420288ea2b95dc5c1a30f4482a37ff28b06bfc945569f60c8b914 -dist/2024-05-24/rust-std-beta-x86_64-unknown-netbsd.tar.xz=5610b2b28f534eec0003b848621881d3b0addbefdfd69666dc555124aa6dd600 -dist/2024-05-24/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz=5bed751da30f4ec0d76613ab04b5e7687b0928539215241988ae792e93fc1ac6 -dist/2024-05-24/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz=a46f5557facf0e7fe88cb70a52afe1bf7329836ea3379e9eb3d2823884806f35 -dist/2024-05-24/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz=ae040d65d4a52e5369c212f3f3e8986eb92e903d2661734831d253d24efd9f57 -dist/2024-05-24/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz=5bfc44c33c26cba4d381b3a4ec0821ed6fe7597ba1ea33f53f4ed5b9e883aa88 -dist/2024-05-24/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz=7a85f404f581debe2802c64da4e421eab591a47ca40518249c3293d5f3fa109e -dist/2024-05-24/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz=02b85ff8b77947f53e0bd70c9a40c5bc55fb820f86efb40c2e985266153553ec -dist/2024-05-24/rust-std-beta-x86_64-apple-ios.tar.gz=db60e79cb4497d46467de9e2e808ae58ee329e2cfc7a114f97d7455c756ced38 -dist/2024-05-24/rust-std-beta-x86_64-apple-ios.tar.xz=fd7c3fac452faaadf1f907a270daf4e6b09063d9023d0a00bcfbbeffa66aaba5 -dist/2024-05-24/rust-std-beta-armv7-unknown-linux-ohos.tar.gz=6ef5201b5b5ddc2c8ea7fb20186f086e0ebba77992b86ee9517973063dde8393 -dist/2024-05-24/rust-std-beta-armv7-unknown-linux-ohos.tar.xz=32744f5af908ff5c925f5b6fe9f2ddb985b23b3a707aa61c5bfbbc4754838d52 -dist/2024-05-24/rust-std-beta-aarch64-pc-windows-msvc.tar.gz=857d39bbcd5b8ea6ecefbbbf5a082b11e0e96e51e85c06b33aebc0b96bc48a5f -dist/2024-05-24/rust-std-beta-aarch64-pc-windows-msvc.tar.xz=d51e77d6fc82bdbae84d4bb787e4df4167a3bdea6ab211d9b8ddf79c285547c9 -dist/2024-05-24/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz=8b5578ab21645fd5ae11dd8e1c6bcd6ff8f402da94345a5a5c462ebddacdf733 -dist/2024-05-24/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz=d3f1f2821af7ec976fc5f68cdcea77b3b36d0e1f54ca17e86fd92b0083d113fa -dist/2024-05-24/rust-std-beta-aarch64-linux-android.tar.gz=09095551ce4bca6bb872b07c4a5d62cf96915fcdb95f6e36884b2f6758464e5c -dist/2024-05-24/rust-std-beta-aarch64-linux-android.tar.xz=5ab50b5e63d10c1a2edcb7c60cddb081f2779dfcdb6ddfd1785c282c775c4128 -dist/2024-05-24/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz=85633e33d5c82d99cb59d9ac2cf6811b871db12ca3530293ffdd73870a3ee758 -dist/2024-05-24/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz=cfabeb1cecc122b16ff8c63a09e25c15b4855ae30fb71d631ae106150fa10595 -dist/2024-05-24/rust-std-beta-armebv7r-none-eabihf.tar.gz=79532507392a67355c649f92c575ccacce0c73e5c3bec969b0f501e82c3ed291 -dist/2024-05-24/rust-std-beta-armebv7r-none-eabihf.tar.xz=c47637bcf4a3b031f43c5225daa76bd29bb747104ce34d3020328f677b186246 -dist/2024-05-24/rust-std-beta-sparcv9-sun-solaris.tar.gz=b64d6b7272689d68074fc15779bb2dd625a897b2afdcc400d6b21f3d64aea45d -dist/2024-05-24/rust-std-beta-sparcv9-sun-solaris.tar.xz=54688000828eda67b5761e405f3318f97f58616ecc0fd4b67a3da1ad5fe24471 -dist/2024-05-24/rust-std-beta-x86_64-unknown-redox.tar.gz=6ba9d6456afab0e61593e12a34bb50cbdb8bd78def16eece0f0c79703fd31499 -dist/2024-05-24/rust-std-beta-x86_64-unknown-redox.tar.xz=4b88c220a125af0d7c3a8b50c2edb3acbac9f5a3d54630e5aa926a898c8c5ee4 -dist/2024-05-24/rust-std-beta-aarch64-pc-windows-gnullvm.tar.gz=194780953225139f9c3ca0ed92106a34fd7466aeae3b92aece0fbed31c22ae7c -dist/2024-05-24/rust-std-beta-aarch64-pc-windows-gnullvm.tar.xz=7907a4234a8cd358df1ef1e462136d1c31435461806b7581e621698afce8f1a4 -dist/2024-05-24/rust-std-beta-aarch64-apple-ios-sim.tar.gz=faa185048776def01bd11870e2d1d0bde2fca0654ffe01614f36a2602523f261 -dist/2024-05-24/rust-std-beta-aarch64-apple-ios-sim.tar.xz=07a424016f695d47ceacb6966983a2fec1414caa9ef5bf84d72540283686c639 -dist/2024-05-24/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz=c083674853c3412de578f469e50a367bff77f5f3f8e85bff082200f769150bb4 -dist/2024-05-24/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz=2e29b73c2942fad3f2a79ad294e16b124c7c271ce26c6e2b65d5cfadb9709c3e -dist/2024-05-24/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz=f5e0be0aa0ce467db0bf18fb9d306f88efa36786ea28539fec841300f13fc926 -dist/2024-05-24/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz=e7c5d53eeb250006c2ff5c90bdc3a31fd19edde7f9022b96f86655889a2ffe43 -dist/2024-05-24/rust-std-beta-armebv7r-none-eabi.tar.gz=d78c22fb8862dd3bd258e7982dcce54b859756b8f3bede42097873dd7239e14b -dist/2024-05-24/rust-std-beta-armebv7r-none-eabi.tar.xz=bb1ca2a1bf420f5feb10133ac208f1be8fe54927af236855202758959d933019 -dist/2024-05-24/rust-std-beta-riscv32i-unknown-none-elf.tar.gz=3bc49069aaba38a7ac627181b73f6249d707be590d77bd410a90a59c9ae98378 -dist/2024-05-24/rust-std-beta-riscv32i-unknown-none-elf.tar.xz=a66a7b99c95b600abba03330e9f26fdcf87860259f81d41ab629643663c188e3 -dist/2024-05-24/rust-std-beta-thumbv8m.base-none-eabi.tar.gz=c17554b2eeaf0af3115fbf3659ca22be0ca1ef7b4c64c831a18466db04cc8d02 -dist/2024-05-24/rust-std-beta-thumbv8m.base-none-eabi.tar.xz=f4b21bf361ffcab4abc8ecbcc0c671788f4f2df058a24334d0aa0c2567c86fbc -dist/2024-05-24/rust-std-beta-s390x-unknown-linux-gnu.tar.gz=1e99b060eb7686203e8b49a2ead224ae3a28456b14a7db89585fe547673ab0c2 -dist/2024-05-24/rust-std-beta-s390x-unknown-linux-gnu.tar.xz=dca7426cdc98b799cade30c8adb4386c4fd0be2d1e6fd055615a0d0350dfe396 -dist/2024-05-24/rust-std-beta-x86_64-apple-darwin.tar.gz=2d683687edd6df5f650979fe8d4ded9c813a695033f11be7444fec7599f58225 -dist/2024-05-24/rust-std-beta-x86_64-apple-darwin.tar.xz=f14f1f132b28d67737fd7d2eaa740a74bce2f19443f0e938c26e182be97404c0 -dist/2024-05-24/rust-std-beta-i686-linux-android.tar.gz=3b812e866ad74e542fe32c625ffac712ee1bf3d101f73828cd938bdbc688b7dd -dist/2024-05-24/rust-std-beta-i686-linux-android.tar.xz=6cd72f9ae6b0459f57e8cc7c5161efb0b0477bbac33339951c9b4ca4f4512de0 -dist/2024-05-24/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz=cf0436b2a84bdb83af01a9383dadb2d0bdb43edbcb959c28d20d8874a4b6bc3c -dist/2024-05-24/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz=afd01da46d82692d8bea9eefa31000ca10372ee7bdc5a9d8c6b5c4bcecd930cd -dist/2024-05-24/rust-std-beta-riscv32im-unknown-none-elf.tar.gz=3f90c703dd67cee0972536caccc6641dbe5bf38eb8dc822937ff3c98abc97710 -dist/2024-05-24/rust-std-beta-riscv32im-unknown-none-elf.tar.xz=a79012cb247484db2df607a63e451cb6748be1a103d6e368883d95e92fd5ee8f -dist/2024-05-24/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz=8df8df9a6eb55bc9b63dbb4b1fbf3e15ba6f95b0ae1e901d4f3d2e594d4fbaef -dist/2024-05-24/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz=f110b657611fd530af1fdb20b06384a41db126832ff9a0b8e3e53b508addf1ff -dist/2024-05-24/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz=f89ad7191d2eb0c5d8b01892e61e68747e66d18214152cdef5c5b191a1606981 -dist/2024-05-24/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz=729057537bb4494e3d060c26867bd6695f62a096eaf33582010d583c7234a313 -dist/2024-05-24/rust-std-beta-aarch64-unknown-fuchsia.tar.gz=ea83d20d4dc99b7e9eeef69eeba2224015fc1bd0b0ad4695ca6dcb537a5f610b -dist/2024-05-24/rust-std-beta-aarch64-unknown-fuchsia.tar.xz=b3615738d1c067d22327b62e416e06cc57c08c2141c0a478f265fd888ce6f655 -dist/2024-05-24/rust-std-beta-x86_64-pc-windows-gnu.tar.gz=7915fd0662c2cc9724395745bb23d6589e48b74c11151b5674fdd7834483c54a -dist/2024-05-24/rust-std-beta-x86_64-pc-windows-gnu.tar.xz=d868ffc4f8b60bd61d862e83f445c783b9b98b11041ba9d284354d1c7c5c81b3 -dist/2024-05-24/rust-std-beta-x86_64-unknown-illumos.tar.gz=9d4ec9d659228b86780d29f183b7b1d8d9087290d9602659d985b5a4adaefe52 -dist/2024-05-24/rust-std-beta-x86_64-unknown-illumos.tar.xz=315ef515146f4de92935fd02a458bf71cbfa967d426b7d781b361f650752fb0d -dist/2024-05-24/rust-std-beta-i686-unknown-linux-gnu.tar.gz=c3cfe615737af46a5de0c0c71cd530d8f1b8fe5d8c9c89865ba5d127c71ebbed -dist/2024-05-24/rust-std-beta-i686-unknown-linux-gnu.tar.xz=fb375bcafb3d35146ee387772440921cf1ec737f48e035bb34a6772ed6f98435 -dist/2024-05-24/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz=0b5253ef9d9d1298423e6fbc1170e3a7173717ebfc57653debdeceb80df74d8f -dist/2024-05-24/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz=f1ca8bde4ca0621bba03e94de67167c01a2cc5b37f5b77e600986c67cb477ad8 -dist/2024-05-24/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz=9eaa5a78691b16244bb8d2d4f1e22b3548243967b49572a276a66997a04733a1 -dist/2024-05-24/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz=f4919dd99711b1b0c7c533a2301423a3c6b01534fb8dfb7811356ea827b43b3e -dist/2024-05-24/rust-std-beta-aarch64-unknown-linux-musl.tar.gz=9c5156e544557ba6cdc366407cac81b90255b0759c7e9ecf19d15560f8da0338 -dist/2024-05-24/rust-std-beta-aarch64-unknown-linux-musl.tar.xz=8f9841d0d6bf623330e497304efed6bffb96f081208be5b5952c493884d803f7 -dist/2024-05-24/rust-std-beta-armv7r-none-eabi.tar.gz=6fbf1ea31e37333c52e2c28d92baadac89bdb2c53fabe18b3977c2a837f69606 -dist/2024-05-24/rust-std-beta-armv7r-none-eabi.tar.xz=e1b656df5f54c6317ebbe660ca9488a6c93e1516e4d8cd13d4d601d98e18cc71 -dist/2024-05-24/rust-std-beta-x86_64-pc-solaris.tar.gz=d5831bd26c24ee90134178a0877944ebfc5fa743e4b6644308f2e6f9480cbb94 -dist/2024-05-24/rust-std-beta-x86_64-pc-solaris.tar.xz=3441e45c78e670b2cbb5becd10fb1a20232adfba8a3b27534b364fad47a8b14f -dist/2024-05-24/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz=3ca6068a2b62dc715fba00c8f8c231465a8cb918bcc0ec28ba5eefd6322509ae -dist/2024-05-24/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz=3674d1fb506ee0237f8dc359ebce38aaa1f302e0cfda1a23ca083596aa6ed1cc -dist/2024-05-24/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz=6150c318589db8d2243619b85e0bdbf4433dedd1f6bdaf8ab5a0c48d0fd9a62f -dist/2024-05-24/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz=3a03e4ee500596e03335f7d01e666727ca35f861a82dad214ca06c09c11246a0 -dist/2024-05-24/cargo-beta-aarch64-apple-darwin.tar.gz=39998995295e1c03bf81c2f384d871a0270e3b87ca87b23c61642e6455c83287 -dist/2024-05-24/cargo-beta-aarch64-apple-darwin.tar.xz=4a837a5313c2b7c340c1df32f37679975abb7263966d90f755e87c4925262065 -dist/2024-05-24/cargo-beta-x86_64-unknown-illumos.tar.gz=6f6b434451c5e08e89feaab897d6d70445b380e12ad398453ec36425954c1d09 -dist/2024-05-24/cargo-beta-x86_64-unknown-illumos.tar.xz=183082bd9b3ecb97831d22a1f88820a9622cef480db113695907fd00eac25602 -dist/2024-05-24/cargo-beta-aarch64-unknown-linux-musl.tar.gz=7d500984773dea88db82653b5565f6d73a622cbaf9da2db942b3453f0b965296 -dist/2024-05-24/cargo-beta-aarch64-unknown-linux-musl.tar.xz=9e9a890b7314a731ce63d57c325cd6476c6fa50e0364b4c7b8e2e5620c83ae05 -dist/2024-05-24/cargo-beta-s390x-unknown-linux-gnu.tar.gz=5a3bd87bf129c826ec705b94f0ebca06fc2b3629d191b76fafc09cff8c59adc3 -dist/2024-05-24/cargo-beta-s390x-unknown-linux-gnu.tar.xz=24fcbcea1863cf45eadef4fa575d3ec1faded48ddd9aa02f45d199a4b09c136c -dist/2024-05-24/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz=6a844b4584ea5c89556518ad063ff6298e6c47853d23f7d8f96a07774b0329e3 -dist/2024-05-24/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz=4f20df4cd9832304e4a5963b27f7caa3d5cf7d1d8ca7a203db3c3f30552bf2e5 -dist/2024-05-24/cargo-beta-aarch64-unknown-linux-gnu.tar.gz=d986028f54153318e862d42bc6f6858b88dfb32089d1039e7cf1bba384ccae1e -dist/2024-05-24/cargo-beta-aarch64-unknown-linux-gnu.tar.xz=a6ecc5e601620ce896f4371487a7cd9ae529dd20f760d44c498fd705fc4140d0 -dist/2024-05-24/cargo-beta-aarch64-pc-windows-msvc.tar.gz=59f6d05082f4feb8d1fdedc513c27f4d1680280daa40889aeada106c8d363678 -dist/2024-05-24/cargo-beta-aarch64-pc-windows-msvc.tar.xz=820c078d60cf6530f1c67111c99ecfc492b564e4f48113770c684677a553864a -dist/2024-05-24/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz=8c89e03e9c8f41f2efc8c0c05397051dc67505b634d9b9b7a076471b334a6b8c -dist/2024-05-24/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz=592c740d96a1d78711c8a861b3ea17c36a806ca2dc1d869d51dc6e5de456ee60 -dist/2024-05-24/cargo-beta-i686-pc-windows-gnu.tar.gz=9db89655fecd5169d7cfe6869bd901abd621f6f5ccc9c2928ca52a666ef11eb8 -dist/2024-05-24/cargo-beta-i686-pc-windows-gnu.tar.xz=9a37c1efbc17ee392784109db3d5674d95b68829ef87895c2f7dcdedc2271952 -dist/2024-05-24/cargo-beta-i686-unknown-linux-gnu.tar.gz=0b6e0cde1312e5294efd1f9ff94a7448e8025b755d02fb36b0e15b2642069cde -dist/2024-05-24/cargo-beta-i686-unknown-linux-gnu.tar.xz=5b96820f5ef0f04afeda2fc4052788a0a5c17f24a73680abe265d4a52a27d266 -dist/2024-05-24/cargo-beta-x86_64-unknown-freebsd.tar.gz=42a56ca6639895afcc379daa674270aafed270ed3698ac7a16d2180b67d78da3 -dist/2024-05-24/cargo-beta-x86_64-unknown-freebsd.tar.xz=9dc792621d33faaf4c5b779df0b72eeb87ff2756bd7347517f50ae0a41d067ac -dist/2024-05-24/cargo-beta-x86_64-pc-windows-msvc.tar.gz=e30d1feb140198a1cccba94f1f4f12a1e5446c6925c4bc35a82dd8fed54be079 -dist/2024-05-24/cargo-beta-x86_64-pc-windows-msvc.tar.xz=b754bb31b01483bbb92b14f1fb7de241295223c58a84059f36b2237c93963bad -dist/2024-05-24/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz=de99b7e5b35a756f4d3ae4f780a154310c6062dbcb9c9ab0083d061976634d0e -dist/2024-05-24/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz=224f4a46d4cc3ea797fd7cf70f80e2c16ee758cec23aa1816964d9128264928e -dist/2024-05-24/cargo-beta-powerpc-unknown-linux-gnu.tar.gz=0e3907c9e2d11bcf9ae9739c01608f66048a63c343cb006374ddec08d6ea7c78 -dist/2024-05-24/cargo-beta-powerpc-unknown-linux-gnu.tar.xz=981ce940535a7684952299c1be88378c6763ee91d3765b014330aca0fbc65ce9 -dist/2024-05-24/cargo-beta-x86_64-pc-windows-gnu.tar.gz=ae0074711a8ee88061859789dbe7c7ba9f4f306d5d99fbcdf1a4fb0aef7ec2a8 -dist/2024-05-24/cargo-beta-x86_64-pc-windows-gnu.tar.xz=40de1cd1454bb99a8c3ff18bbf2950fcf480152536dba1bc20576e3cb42b62e2 -dist/2024-05-24/cargo-beta-x86_64-unknown-linux-musl.tar.gz=1f849b69e086fde12e342aa935bdde649cc3b18ab9f372c1decdc6ab52ecae77 -dist/2024-05-24/cargo-beta-x86_64-unknown-linux-musl.tar.xz=75e6ca1b2b75de206ae4c6c8b98f36872e00cb92151c064e29bbb9a5bf47d441 -dist/2024-05-24/cargo-beta-x86_64-unknown-netbsd.tar.gz=fb6a694dc1dd5c0f8e0749354b54ec213ae62977d2293b76806da8cf6b4db18a -dist/2024-05-24/cargo-beta-x86_64-unknown-netbsd.tar.xz=5d2bdce7e5ee3be7a46bc55614ff6b35c996eb95cc6348fe982207f183237b47 -dist/2024-05-24/cargo-beta-arm-unknown-linux-gnueabi.tar.gz=551b70fc54e177ee31a33d79ea7c8ae19b81cf3bbbc767e23455f3da4d1d440a -dist/2024-05-24/cargo-beta-arm-unknown-linux-gnueabi.tar.xz=3ceac72674b7ebc33ed3b73057ff93c4569f9bb47d15c743a9ed2775a51d9eb3 -dist/2024-05-24/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz=b38fdb21440650b6cbecd6c2e049b95519f60e37af48d1a98d38ea82fe27d908 -dist/2024-05-24/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz=74be24ebefc943be201b114d9eb49e15fda0880eb03c0df60ee382f2a48dd0d0 -dist/2024-05-24/cargo-beta-i686-pc-windows-msvc.tar.gz=70d1d27a68f084c133fa0b3c110d43be37de2446a81e27e92fac5678283fa26f -dist/2024-05-24/cargo-beta-i686-pc-windows-msvc.tar.xz=d02feba93e984c5d5aba5018499c830954f3b49f68c9885f11bd04b48b277f0b -dist/2024-05-24/cargo-beta-x86_64-unknown-linux-gnu.tar.gz=f4eab6af2e369b32879a97446c962c67b8733aaccfbfdc60e04f72e2baf6ab82 -dist/2024-05-24/cargo-beta-x86_64-unknown-linux-gnu.tar.xz=a34c6b4298c5b8fdd266b6035b6a3c5b0458fbb64a853830fc6f9df2c1a0bca3 -dist/2024-05-24/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz=b6fac94136e6fab6c0b6425890060f20481bffaa98bebde52f99564afe8e2c3e -dist/2024-05-24/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz=6dc5ebd5e03441015655d5929825364b9bebe0659df42ddef09fc489fe22155e -dist/2024-05-24/cargo-beta-x86_64-apple-darwin.tar.gz=f08d91646163be427447b11fe7e1214df4444c98c99070d5f154ba79e47cafa1 -dist/2024-05-24/cargo-beta-x86_64-apple-darwin.tar.xz=ac86b164e6a95388510c6cd5ef6fc82cf9794d5f3ebd12f1bc94f16ca2c85ff4 -dist/2024-05-24/clippy-beta-x86_64-unknown-freebsd.tar.gz=07e962b44908356b427c350f1208a9c017ebdbf4bb6d5f952b1625833b552068 -dist/2024-05-24/clippy-beta-x86_64-unknown-freebsd.tar.xz=6e0173c30b8087e9ff2a4d7b46d178d380ec4a1443034d5706dcfeb8dcd8ecfc -dist/2024-05-24/clippy-beta-aarch64-apple-darwin.tar.gz=ebaa62ae3e7191bc5be56f93b47493641e705ea312071e723a9e03bf9fb487ab -dist/2024-05-24/clippy-beta-aarch64-apple-darwin.tar.xz=3d9c9ecbbbfd2d475d4bec4141e5da4559f092d5167127fd4eb13f5397abc693 -dist/2024-05-24/clippy-beta-arm-unknown-linux-gnueabi.tar.gz=ea1d746dfe195065e8d387ee06db4f0d2615814b9c6ef6246f85d1073c471b06 -dist/2024-05-24/clippy-beta-arm-unknown-linux-gnueabi.tar.xz=86387463578f29dbdbb79257ea973a247df4c6774e88df6b38fcf52b79c99e02 -dist/2024-05-24/clippy-beta-x86_64-unknown-linux-musl.tar.gz=383a5528ac4ac0524fadad6e2bb7fef0b3a03d795250057cc816533728fbb4a7 -dist/2024-05-24/clippy-beta-x86_64-unknown-linux-musl.tar.xz=6f796fc9a9039815692dc5e127fe83c5fb71f208f0876a5c6324bfa9953899bb -dist/2024-05-24/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz=4538a4c73464791275fb0eb49ef96356966521131a33ed74c5de1ff587b57e3e -dist/2024-05-24/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz=e16fd33e2788bfe6d7dfdaf2692b21bf61edf3d34197cd7d32b1ea998ae03000 -dist/2024-05-24/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz=61e5c68a5eb0b7ec35b2353dcf19a54e8fd63a4cc8be1e1651138aa8193cd0d6 -dist/2024-05-24/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz=6e2a98ffecd48aae032540eaa0c9573317ffa920d6a21e2e2f2e512d8eb3b991 -dist/2024-05-24/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz=ae6406baa95d37a95afec6c3cfde8b1fc5b811fa824785ebd6b17d5f1f31d329 -dist/2024-05-24/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz=fe98fd0b83763a2b73622ec3ba849ef2e0e31656010b2be3b2ee31875b19a826 -dist/2024-05-24/clippy-beta-x86_64-unknown-illumos.tar.gz=3a4eba33496cf3c1b116524b3f5466426148b5bf84bce2d1b3865c4429277ba6 -dist/2024-05-24/clippy-beta-x86_64-unknown-illumos.tar.xz=17a5a7e10a8821c12a5930fd1ed85e3a545d16471d7948d09fcfe536fb6556a9 -dist/2024-05-24/clippy-beta-aarch64-pc-windows-msvc.tar.gz=176239e95b1efaa8d12a41792d008ffc4919ce49a86cecc1b5a83fbd94983c9c -dist/2024-05-24/clippy-beta-aarch64-pc-windows-msvc.tar.xz=0e4abffe1c361b54572572633cdb57ba4b5e43aba01b1af9298532de8201a2bd -dist/2024-05-24/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz=1b36ea0173144992dbef9bfbe7117454b7d4bc3a717bd04c6b8470f9f3feb38d -dist/2024-05-24/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz=43371fd91a35451213a5b082190bb18178ad712627f7243feb1acbdcf5b01c21 -dist/2024-05-24/clippy-beta-aarch64-unknown-linux-musl.tar.gz=9ae71ea9dfe0b56882b949321e4a2820bec4883614bb052cd71d9cce3b203ecd -dist/2024-05-24/clippy-beta-aarch64-unknown-linux-musl.tar.xz=92e23034c6287754a5c7d49c3e53313a614addb220fe0eac36d39b2883b445b6 -dist/2024-05-24/clippy-beta-x86_64-pc-windows-gnu.tar.gz=2076ed6ef91cd8febcf7daa894d110a2acb8a5b48a60f050c5e126c9378624a2 -dist/2024-05-24/clippy-beta-x86_64-pc-windows-gnu.tar.xz=e32790707ddd05624a7066c6185283476aafd7a304fe7528587765102d0fb63e -dist/2024-05-24/clippy-beta-powerpc-unknown-linux-gnu.tar.gz=f47378feae7c5b4d15693ce8b170152237e5adfe027e53e4f017dece19da9f68 -dist/2024-05-24/clippy-beta-powerpc-unknown-linux-gnu.tar.xz=af17738279b4acc3c75974b070c63de6385a62e7cb2ced3d445cb2c7d9928653 -dist/2024-05-24/clippy-beta-aarch64-unknown-linux-gnu.tar.gz=1fa14738518c68f24668fe42ed6653b4a80ac12ac121f36b488215901ea49349 -dist/2024-05-24/clippy-beta-aarch64-unknown-linux-gnu.tar.xz=f636b9d9628b5be5cc873b0698bc8d1a8487ca81309e359e60d6065c3771f8c0 -dist/2024-05-24/clippy-beta-x86_64-apple-darwin.tar.gz=14084cadcf4e71259a3a7e2189e648bcc8f8f044b5abf027079ebc140f3593ae -dist/2024-05-24/clippy-beta-x86_64-apple-darwin.tar.xz=6226dbc6d0e180eb7e946606cd7a5879ce558846334bfd79105ae23cfb7eee63 -dist/2024-05-24/clippy-beta-x86_64-unknown-linux-gnu.tar.gz=6c58a39182997f07a7391e069ae6f141af8a2964f8c5583bedd70039a759c52f -dist/2024-05-24/clippy-beta-x86_64-unknown-linux-gnu.tar.xz=a4c33cdb8711b784f533a685c3a6491f4c841fffcf573b1832315360788833d0 -dist/2024-05-24/clippy-beta-x86_64-pc-windows-msvc.tar.gz=f12a529b11e68e8dcbaeefc13e98935171bab78d5aaca0e6ea6d5fccc71b23ab -dist/2024-05-24/clippy-beta-x86_64-pc-windows-msvc.tar.xz=b060a3285527311eda126adc0f70aa6f361718ef397e89d488a58be7ff70d316 -dist/2024-05-24/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz=a7a455d8a0f102d83c07987045beae1a9f633adcbb1752a6c338a0056183cf06 -dist/2024-05-24/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz=47869852cf4b215d71ffbb67decee05aa4627041353daa9acd36dd6f2cc8ca71 -dist/2024-05-24/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz=99c4401de28a11dc31d868d01d8de661f45f6238ab7fa36bc203868bf9977efd -dist/2024-05-24/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz=828ffcd6fae6e48d9af7eca3017eec88b5d79ad5f892dc72ec598d908c23a7d8 -dist/2024-05-24/clippy-beta-i686-unknown-linux-gnu.tar.gz=dfe75e08d07df8e2d2f8b7e1d7840a505e42b2267b0f3b63c4cc8356dc3f4519 -dist/2024-05-24/clippy-beta-i686-unknown-linux-gnu.tar.xz=83270728dc14957c00a8801a5a187b9247b7c7bac7347f71eaec5e2fc59e17fa -dist/2024-05-24/clippy-beta-i686-pc-windows-gnu.tar.gz=7bef578957e857cb38b6cdc126bd055b95b5dff54d11d73f68413425cb4cae3e -dist/2024-05-24/clippy-beta-i686-pc-windows-gnu.tar.xz=9492aa7f12aa1f38afaab16f4c1ef4d3fc45169e25575a3c691ef13b0389c2d0 -dist/2024-05-24/clippy-beta-x86_64-unknown-netbsd.tar.gz=e325ee40a680aba2e413ea314e15fd4f9b5394705f72d652d9914b4fbb16e253 -dist/2024-05-24/clippy-beta-x86_64-unknown-netbsd.tar.xz=c499d0bdc755156a058c32d4d9be8e2b358197aa89a161804ccf87b0ce8c90f1 -dist/2024-05-24/clippy-beta-s390x-unknown-linux-gnu.tar.gz=ef245e8ebc4e598ab68b5bd8fbbeaa311e4b4e0471bab961b39c4d5218655712 -dist/2024-05-24/clippy-beta-s390x-unknown-linux-gnu.tar.xz=55ce153227cecea3a6f05807a156bfbea3c7d7aee72fdfa055fb9ddcbabd041f -dist/2024-05-24/clippy-beta-i686-pc-windows-msvc.tar.gz=d2378b267bf3d0e58300d21dd302161eaea8f8e38b7439731a054597970f7195 -dist/2024-05-24/clippy-beta-i686-pc-windows-msvc.tar.xz=87e337e9a584908d6397987b89756a30e6cd4b537fbe5dfe9d4752d9ae17dd51 -dist/2024-05-24/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=9ce0c27f91a3d3a99a0b32d72284827add678b4e6b1377e2fc978397dc897bbd -dist/2024-05-24/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=2c314fcfeed780a18fef9835266a50a8bfd4c63f66033c7a2cb589243d0dea8d -dist/2024-05-24/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=a1691b9a1629b0ab09505c80ef510fba462f41296b45b04bea52aa66e0314cef -dist/2024-05-24/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=6d36402ae66f53c24db57f37e3f78a2bd5a07a238d59d4b4b8c000202e6e6714 -dist/2024-05-24/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=e54ac8103de0de2c4166da6149c0f3da1db29cbf3909844b5fab43e1f56d943f -dist/2024-05-24/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=986bc361afa619b299f1c6674651aa56a344374ab8731c9cb702a651132841bc -dist/2024-05-24/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=0ee19412859c424304a8e2d66798896ab3be24057a6f12383fadd9c8283e5825 -dist/2024-05-24/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=01ff0f61731da21c55618fff0aca2f900c8b1473b7efc12cd8f1d1e49b51ba8a -dist/2024-05-24/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=9d29a9809633b98851a5de84d37cb0b37b4f9e9223b42841ee11e4288dfafd90 -dist/2024-05-24/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=122e2f607f59dbbd82693ece7610d9f9a92c1640e3501921d0f6069d0eaf4ac0 -dist/2024-05-24/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=5d8d0ed9f63eb0f2b8eb43c47f0a6858702cd5e9c8f1b308b570981f54a45ba9 -dist/2024-05-24/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=203c63f477369ce5a6464d0e11a10c5ed11b2e510e6190d6e0ac9993c43f3ffe -dist/2024-05-24/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=cee4cab103bf4c2b244a91c1d7578d5c807307a3367291ef1efd072f975e27ca -dist/2024-05-24/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=813a55dba22fea0203e43339f95ed1ce8b7406d57b5d75cb0d11ed2638402280 -dist/2024-05-24/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=c9a941b5c05972c0fc875b052728dd5a83dbdcc8437c5509fbc4ca82cefd5866 -dist/2024-05-24/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=3bb87c7cdfd0b942d8051de34d068d3fe6b4d5c8b52534ff43d6ffd802112d99 -dist/2024-05-24/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=2bc18cd1444098b36ba3eb0648944caccac1515495c7180d2258bb29c4dbba71 -dist/2024-05-24/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=a5e49cd58fbe857a2e99dbd9b68aec300dea92a9f840dc564f6f61d71a291cbe -dist/2024-05-24/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=7b270dfdcc65d11d0741adf11f62fff5839b4262ca87a84c273c4f54ccdcf404 -dist/2024-05-24/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=3cfb7ff6d106ee2ca996a7e5790981648e4bca92ae424c780e6d6831dbe5d521 -dist/2024-05-24/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=82ef339de90bd1eb99bdee0ed4ff0431358706cb826c0810c6a05aa7432c56fe -dist/2024-05-24/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=d4332d61ca86a3c561bef17474110dd96fe73789c1fa43ba216be9a0c3690192 -dist/2024-05-24/rustfmt-nightly-aarch64-apple-darwin.tar.gz=5505cd69abfb7cf00ddd32936067088cc4448cfa09e5571516fa2e61d6593e51 -dist/2024-05-24/rustfmt-nightly-aarch64-apple-darwin.tar.xz=0c7cc98f9534c691dcba913b5d40fded47b33ca549ac75098c84d900d8452f01 -dist/2024-05-24/rustfmt-nightly-x86_64-apple-darwin.tar.gz=734c21a4018bf0e5ab561e8e485fd15f9ee38c01685aaf620808edb9a218b476 -dist/2024-05-24/rustfmt-nightly-x86_64-apple-darwin.tar.xz=69e6408ba329925f38522050f84adb20a299960c04ed3012bf075a10c4ad60c0 -dist/2024-05-24/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=d759046124506b761f0d628681e7f5ac73fc23a04f1bab5097e0796b7197097d -dist/2024-05-24/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=fb07a6adc006753ce09457b032d6e1ce06934aa8c009f5d586d3b317dde6ce21 -dist/2024-05-24/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=c7f7195f7c80e9d6afac4fd6cb6f54b4f1c53116cfbbaa06d185bbca4ef2b4d6 -dist/2024-05-24/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=5acb271b43e1f1c186666c33f322b9d3c253b929710eb73000e2eb61b3978dc9 -dist/2024-05-24/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=7aea051dfd13311ef4a95845b6cfb390c6f502ac2bf46fea335abdbcda05a2e4 -dist/2024-05-24/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=832f664b6508735fc91491fef9eca137ea6707cec000ae483d4c8b5ce9abadb4 -dist/2024-05-24/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=a5f79e10a34ad8d02645d1e6ae758812ff16e1c74b63c775c5f840fce5569ed0 -dist/2024-05-24/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=837e8d335322a4d0efb86bf6d6dd65b815548faa9e40135e8cf3b197f6e03960 -dist/2024-05-24/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=c0d3c4786cf4b4c4cf0b8c26d89d6009e3e9d9c1e69092f4b55f0087b08204f2 -dist/2024-05-24/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=0d8a1f390b09f8550c38cd1b74e4e8f7cccc496b86e6f2d6f74291c34cc31bd8 -dist/2024-05-24/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=56ccaaba20445959702503d1aedac87b8a9995bcd8619dd120273d0795859705 -dist/2024-05-24/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=201932eba6521c04367eb682f96a54fec10830fe954bc271ce2766db2afe30a1 -dist/2024-05-24/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=e8c2324aca7fe35e47088d8c317c7f97d88830629e871987faa197d545ef644f -dist/2024-05-24/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=51985f7c0530eb59dce830e1508bc270e1bb3fe7b33a95eb93142611e651a7d5 -dist/2024-05-24/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=a4fa6bcf4c4b9c446236d710c1878efaf1dfdb95a2f5f3c4c374d8fbf49b792e -dist/2024-05-24/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=af0f2443e34c9d6f5d85ff8cb0c0c52fa46b64275c26b57528c1e815edb8f59e -dist/2024-05-24/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=59bd9ccde4722b24b5b746d7e3dfdd48ae8f9c8b142b8c175750b8bdb2c05411 -dist/2024-05-24/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=91dcec67d9382548f89dcaf7c2c6dcaa47f9e04b777f7b8cf047ca0895fd7958 -dist/2024-05-24/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=d16ac0c789f0c79867ca74161214a902f97647d2b448ec510d48b254092ea05b -dist/2024-05-24/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=065d796ed384f07116903ae75dcb4accabb3cd81849a0083fa26b42e5ee3027a -dist/2024-05-24/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=bd673c6d23377af5158565bcc48048d5a8febf346d200920e8ca8e661149f600 -dist/2024-05-24/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=7f630e63ea697c95bdd2ea2edd678e8cf999c5ed9e7760c2b631ed6ecc4f112d -dist/2024-05-24/rustc-nightly-aarch64-apple-darwin.tar.gz=1f418de895c28fb684035c38f5f1ad45993ccab9bdbd247958083043ec2904ff -dist/2024-05-24/rustc-nightly-aarch64-apple-darwin.tar.xz=a762ad9b084a4221f5e24ba7cc99bfa20dfba935d267efd36ecf371de5fa6261 -dist/2024-05-24/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=6fc6f1ee02ac5562da863213924a43b8cc914b54b7a7df7c0fa65b51c0cec2ec -dist/2024-05-24/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=3e4343551874ebd6a41912937784938572706896f7b64b246b7630eb2de81e32 -dist/2024-05-24/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=225dfdb7af532a1de12c04bfb4ad41756db6b0c342e3e974a1587b74ac942cc4 -dist/2024-05-24/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=ef45d12cf6c0a00bd62bde5143bace4b9f4dc3d27d0e66274698fd4c12aa644e -dist/2024-05-24/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=cd5c25154d3a24f9fa14bea66c149c8547179e28307989276b3450411db94f1a -dist/2024-05-24/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=07473937fbe50012d4472e283bedb8fa239a02fedc880e8d3cdf96e449a7a237 -dist/2024-05-24/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=3c96788305ae61feba692d7c254c68486e6caa0a7851dc6ee545338260e195bb -dist/2024-05-24/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=f5789e53bd82a6e7593f51248342bea26014770d86b171d1e6182039e96cd008 -dist/2024-05-24/rustc-nightly-x86_64-unknown-netbsd.tar.gz=c7960546ecaf8e190e0e0a6bf21d3259b6098b440e9f8efd455c0e207db14100 -dist/2024-05-24/rustc-nightly-x86_64-unknown-netbsd.tar.xz=dcbd4e5a41496ec3a76a492b6f48a0913f3174f192b0dce38886580fe5866806 -dist/2024-05-24/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=201d715fc46c3b97c6ba56ed89b45870089ead21b5dbe107fc9c11d4e409b594 -dist/2024-05-24/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=5660fc1ea7228b156b070766d568bd27222245f4a8bbd3fa55d53646320594ac -dist/2024-05-24/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=ba5a31b8f6fe6b55976ce3fb7075cf0c539b83b86c029e1dee9259e76eee90c7 -dist/2024-05-24/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=1494876804a4eae08e22a586295d5c75fe611e90e35e98e9d4fd4ce7f08e1648 -dist/2024-05-24/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=e83d8ad735b0c2213613882affea611db0453f2d83dddcdc325100d94ecb8be4 -dist/2024-05-24/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=c41af42429b2322b140d99049fef6a2bfc6950847601ce5daf5e789939ef8383 -dist/2024-05-24/rustc-nightly-i686-unknown-linux-gnu.tar.gz=4fd2063d10fb4ea166c684edb9b790a0decdc602c600208cad2c378cb5b5f04a -dist/2024-05-24/rustc-nightly-i686-unknown-linux-gnu.tar.xz=522f49079f90b469a7580f3cbc8f7ec88f2267a5df9cb0fc06a40fa21a778b1d -dist/2024-05-24/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=622d58678e2aeca83bfa7172c9cd0fc21128917067b6492fc6a966f0715843e0 -dist/2024-05-24/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=2e021443798286eb5bdc855112970862b58bd12ea3b1a3ef7aad178f757004ef -dist/2024-05-24/rustc-nightly-i686-pc-windows-gnu.tar.gz=a14a5f1c16f8ac231083b11075aae0970370f29b7f8a6b952c945c8b4a99a1c4 -dist/2024-05-24/rustc-nightly-i686-pc-windows-gnu.tar.xz=5a389561f37d446433dc4e4d0ac1259fdfa4bb5728863a0b2e00b6575acc8851 -dist/2024-05-24/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=95e73ffa458449089b753f85aaf71581d6229d1fef10f57aa6ac0a9a15f5e2dc -dist/2024-05-24/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=b678c5d611324ced9ec61e36cb2ac53d595ed0d9024e987b658d3708714137d0 -dist/2024-05-24/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=07d9e8f300835045ae9bc9350aaebb0c7994398e92e43ca0baf4d491d5e06a51 -dist/2024-05-24/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=7d40e53082177294ee09d59730526586ee973b9d0aac24b4c9116db306a926e1 -dist/2024-05-24/rustc-nightly-i686-pc-windows-msvc.tar.gz=e88718e456cfc8892fcdafc1c522b67c53ba5faedf80f43f007222a8bec00a01 -dist/2024-05-24/rustc-nightly-i686-pc-windows-msvc.tar.xz=b8320cdfa66421593610eb7299d57ba20381f10bb6f2f82ef5475f86c454c2c7 -dist/2024-05-24/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=65ddf18ce7489b1bcc0d110fbd645326b960230702f6c9ad45680e44e0c1890e -dist/2024-05-24/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=f64735396de921f8b65fd74a3f2c179094770e39549d057e5222085b17976832 -dist/2024-05-24/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=cdacc2d990089859fe21fd779d24b186101bcd03f91b8f9c595ddf26af9ced5b -dist/2024-05-24/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=74c673001e8794afbf085bde1b5e010420458230fa9eadf7f5f76e5ad11f1c8d -dist/2024-05-24/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=76c0a333525099ec78351d29deb0f0c7b72d8a48860c1595442e574bc454ac5a -dist/2024-05-24/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=5ff07cf9292c0ba7e3860e9ec2c1de9810e932dc12d9711ba6f1795a5c90875f -dist/2024-05-24/rustc-nightly-x86_64-unknown-illumos.tar.gz=32e4afe3e4dd9f64c69da73af0c4a1e6e4c8264640b142de6bb9494c567fdfe4 -dist/2024-05-24/rustc-nightly-x86_64-unknown-illumos.tar.xz=f6d8be59445080cc278a152387e47a98d3b371758bc7f36932343d0caa5896e0 -dist/2024-05-24/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=caeefbab1a93f119669078ba91aa821e5aaff5811fb3d0a6b0ec482d7bc1a404 -dist/2024-05-24/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=7032353ac8ba628f8a2648c106c7a3248ebb1f03bc9036cfca61007f9acc3a0b -dist/2024-05-24/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=ca53d272b136d5fa112ede10627880a58f51d99a40a490b2c9fff6c996f9aabf -dist/2024-05-24/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=d24dcd68c9426f1463c60d5075a9a0ecbc494cdc34a434f377a0b09fdeabf914 -dist/2024-05-24/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=c6a05ee622261a0f4b41b1cf26b5461e1247c00376ac61a0fc4faa16ce478140 -dist/2024-05-24/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=c317af1e4bb1551edc046c426da84ad122379e5829b5e97033c94b6844b18e2c -dist/2024-05-24/rustc-nightly-x86_64-unknown-freebsd.tar.gz=3efbcc6e74d9cd4ff86803410bbdce0f1e64741870c32f33e28c660c68155851 -dist/2024-05-24/rustc-nightly-x86_64-unknown-freebsd.tar.xz=3cb7acb1bf66ba39becc6df1cf2727de424ca3ba90e74f0fd7c76f586f868a89 -dist/2024-05-24/rustc-nightly-x86_64-apple-darwin.tar.gz=427b795b94eb4e4e2bd150e98055c5a9a414937ebef7e586bcaf8a1988eb5214 -dist/2024-05-24/rustc-nightly-x86_64-apple-darwin.tar.xz=405b2a99f9a34c1d1195ab88bf6fb696fadb6c2988a3d83555e2ac4de80ba4e5 \ No newline at end of file +dist/2024-05-26/rustc-beta-aarch64-apple-darwin.tar.gz=b899079e4c3541762db909b2ec2fd73ca10c26874308831346770c35be29d6e4 +dist/2024-05-26/rustc-beta-aarch64-apple-darwin.tar.xz=2370613f7b60baee5dfccb0adf1586ec960d8590863e2be1571e5efe10f7eaf2 +dist/2024-05-26/rustc-beta-i686-pc-windows-msvc.tar.gz=d8976f398b8fdc3a43894cdd783c83bf0d7db33d6d059dd5387dd7a2840c70b6 +dist/2024-05-26/rustc-beta-i686-pc-windows-msvc.tar.xz=1eeb53dfc82b902e5f9e11bb631b0c2812c7f81a84c1023c69903debb6fff4da +dist/2024-05-26/rustc-beta-x86_64-unknown-linux-gnu.tar.gz=512c74d27fc57bddaf8ec8865afc1ec3dc37106e07a9ef60921b2f852c16ef88 +dist/2024-05-26/rustc-beta-x86_64-unknown-linux-gnu.tar.xz=48b01607a0316817505d4286ce075dacdb38fc170aae7e8b4daa7b75272916f9 +dist/2024-05-26/rustc-beta-aarch64-pc-windows-msvc.tar.gz=f9c8260ce005ffb02213b23530abc8bda5f74104ede11202a6b379e1cead640c +dist/2024-05-26/rustc-beta-aarch64-pc-windows-msvc.tar.xz=567989038185ddbf00d5ef5f7bde9934cce7c8d932db81c3c635283512d8983c +dist/2024-05-26/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz=9fe58cd58e0f758d338d1ee427186f2ac0b644ef9decf457d4b6c0f67df475e4 +dist/2024-05-26/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz=c589495fc21e7bfe3ff19736ba79ff78bc8899bc95f714e93ae4d410a704b0c8 +dist/2024-05-26/rustc-beta-x86_64-unknown-freebsd.tar.gz=4d9206a4361ed0d400decc68b2d908447de0390801bb5ef49885b42e31fc8b07 +dist/2024-05-26/rustc-beta-x86_64-unknown-freebsd.tar.xz=215b0f6ce7885bc2fa8c5d8352e4c5b9bfddb6d92f398ece00ede1bb693c92bc +dist/2024-05-26/rustc-beta-arm-unknown-linux-gnueabi.tar.gz=a7f32c585c191b194a271c3baec3e81d8daac6a107ab5fada0b94e6c31dc295a +dist/2024-05-26/rustc-beta-arm-unknown-linux-gnueabi.tar.xz=ea7a5b798e251fea669265bb66d8e20889e1fa0dd71c5cbb7caf9eb187462fa4 +dist/2024-05-26/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz=44cb994404abeb3b9f873cacae90a208b3243a98d6c7366a7f211a81180eb3af +dist/2024-05-26/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz=49cdde9184c78d03a3fc1af955c0cb37ab290f6d4f0f3a71ce37903df389f804 +dist/2024-05-26/rustc-beta-x86_64-pc-windows-gnu.tar.gz=fe9aebf5129393a8525c9be7fb3120b61a346028d23a19727dac37bb282d4731 +dist/2024-05-26/rustc-beta-x86_64-pc-windows-gnu.tar.xz=760ea53130788d624e3cbee11ade75b38abeaa10701e8205ae5cd8781f54d5f4 +dist/2024-05-26/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz=0a7412f1c722cf74736120b9fce90e4f432da4a51f2d7a53320362e7e829f661 +dist/2024-05-26/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz=e82df323b5544ca55a23db09fd23dff72cacc575dd25e7e056033ff2ca5ba3e3 +dist/2024-05-26/rustc-beta-aarch64-unknown-linux-musl.tar.gz=9b9e7fe38a6e1fe44e629a8523d6b3acdf199b2bb94e7cb2bc9dc4858faf2022 +dist/2024-05-26/rustc-beta-aarch64-unknown-linux-musl.tar.xz=cf1c8a2e68d22d078b69fcffa64dafa9d3b54ad4983b485368dc297c4109645e +dist/2024-05-26/rustc-beta-x86_64-pc-windows-msvc.tar.gz=9069c6b50e3842e03ed13cdd39513a17ae4251fb47893c02c58b5f4704b4c9ff +dist/2024-05-26/rustc-beta-x86_64-pc-windows-msvc.tar.xz=6a315e496629f9b57fa9b82e6cb705cc7aacde690b3619c81dfa57382bdb64ac +dist/2024-05-26/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz=c31a1bf28a4d2c4470032e893b043c25c349ff07facda18587a2eb76cff648e4 +dist/2024-05-26/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz=36da69f87daec24b9810ece65d51abc41128ee1874be14bbc46f74c09a3b20f2 +dist/2024-05-26/rustc-beta-powerpc-unknown-linux-gnu.tar.gz=6b9aab90326c804aeb88bcfbc8055438bae0fb721b9d8b1a64b062836ba9efa4 +dist/2024-05-26/rustc-beta-powerpc-unknown-linux-gnu.tar.xz=d0aeed09775c58a17649c42e0b641f20c44479056db43116ad452e771a88ddfc +dist/2024-05-26/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz=4b1293f35b04a2f9e01e9752b3e8a5b61aa2375930fa72a8c3d04f52f4fbcad3 +dist/2024-05-26/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz=06a653d79b84399798df9f3e636160f56c774a1593e7ad9a57f6e35a3d54fa77 +dist/2024-05-26/rustc-beta-x86_64-unknown-illumos.tar.gz=827865d233d702017b592d6c46954b54f18ffb758f79bfedf59fb535168b9b18 +dist/2024-05-26/rustc-beta-x86_64-unknown-illumos.tar.xz=4258e58b103e5a579e57059bdb1f61fa8e54854c80340888a11a2e81040bfc32 +dist/2024-05-26/rustc-beta-x86_64-unknown-linux-musl.tar.gz=be7f3f7485cfb378e105f8ea09b4a1fb6b78cd68e2a5b7e1cc354c6abfa55953 +dist/2024-05-26/rustc-beta-x86_64-unknown-linux-musl.tar.xz=ee6c02cdf6baa8cbadf8dc53a075582db428a0b149dec7c0f70bb182f49df79a +dist/2024-05-26/rustc-beta-s390x-unknown-linux-gnu.tar.gz=cbf5cc045498ade9d1051de75b127e78d7986f5dee9ca39586e9e9e3bfe066d2 +dist/2024-05-26/rustc-beta-s390x-unknown-linux-gnu.tar.xz=8803daf2ffadd1c76f7591dd765bccb8630336c00a9419f4e9e9a2fc882cd1c7 +dist/2024-05-26/rustc-beta-aarch64-unknown-linux-gnu.tar.gz=9546048a0d5022d19770398f27e8c51cee4fd5879ec012709b8683a5ea9acd62 +dist/2024-05-26/rustc-beta-aarch64-unknown-linux-gnu.tar.xz=5da5076d933127e616a289f6ba9bdea41f0f8f2604436c440a12f7007e5bee79 +dist/2024-05-26/rustc-beta-i686-unknown-linux-gnu.tar.gz=2f20e8666a768b32913a61e49f1774ad0fd616af874eab37b8fcff5344479806 +dist/2024-05-26/rustc-beta-i686-unknown-linux-gnu.tar.xz=1ac7c922764f406db986050f526f5b4490d789978cafad00db668cb4128d64da +dist/2024-05-26/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz=d685e5d7efd8f312f22c0d1c132618f6112e528a51e451fa3279e71d66b46a4d +dist/2024-05-26/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz=bb378be1b0bd6187cca16f5142f6d516790b8acc330f64af4371dd15751aff4f +dist/2024-05-26/rustc-beta-i686-pc-windows-gnu.tar.gz=5a628010b3fd859aae9b75086ad299fdee3159c6f7b8c5b93b24f56f392af0c6 +dist/2024-05-26/rustc-beta-i686-pc-windows-gnu.tar.xz=7546c4cbbc9c33dbed8895608116393855d73b99987e5e1fb2e6a8e88b0ed3cf +dist/2024-05-26/rustc-beta-x86_64-unknown-netbsd.tar.gz=5c10adf9a0d2b917d05e285b8754925d324a43335639d6caeae6bc815f70a852 +dist/2024-05-26/rustc-beta-x86_64-unknown-netbsd.tar.xz=49015adf19be4847dc5de824718a07f741b921a6c4f5565ae9d57b2ff24977c3 +dist/2024-05-26/rustc-beta-x86_64-apple-darwin.tar.gz=399a4751cf0f1015cd67b312f89a3b57f1a2e0b2b7052aa943dd87ff88e10e2c +dist/2024-05-26/rustc-beta-x86_64-apple-darwin.tar.xz=214178058be3e0d305838e1cc0c4de7d7a6aaeb3df1c8de451aa598bab46bc13 +dist/2024-05-26/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz=fc8ba79857b1f1d8d27049e3322db0e9dd8e8f55e9899a7651826d29d18ccbd8 +dist/2024-05-26/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz=d83f291dd371fec862e71e382db853d3547c1f8fc5cf475765e91054ffe4b40d +dist/2024-05-26/rust-std-beta-i686-pc-windows-msvc.tar.gz=4e831a551c6903d6995162c7e4ca35dcb421e50659a52e33b5d82a071ffc9c6d +dist/2024-05-26/rust-std-beta-i686-pc-windows-msvc.tar.xz=4944a6c8bd5716811eaa34d932899cb7a7b1ef16def784663867921357b98b89 +dist/2024-05-26/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz=25cf208ccd2bfd922d43f7d5e6000daf523fdea3c436795a641af43ca5af3c3e +dist/2024-05-26/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz=846bcd9b52a0c267bc0f5870dde2b672f002df8397d31ec4d55ef407ac9f7097 +dist/2024-05-26/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz=2043dc32a5df5da4c289119d70896b88ec527ca72509eafbe39592bf18451c2d +dist/2024-05-26/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz=20bffebf6414d6c5eb357280a301a7d7b6e2fe778423403aaa9106ce16ead498 +dist/2024-05-26/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz=a67464ceea45dd3bfd20156091e1ac070ad1f921f70cb8c11c0a5945e857cc40 +dist/2024-05-26/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz=b8518464ed51eb07fe9874dd38eb81004a58a994e95f1062ec5ab01db0d7cbd1 +dist/2024-05-26/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz=398e2a8c2c1ff8e19f810513f1d4105c57b509290393d346ff56a78c58419c54 +dist/2024-05-26/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz=3cb98ea534755f69a050df188c4b0b4282e5778609a8df6bd7dc9a467966344b +dist/2024-05-26/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz=aaf44990f5ea7055c911d414e7ba74ec6457d347648b13eba087ef87030fef34 +dist/2024-05-26/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz=32aa99692fe79711fa637b4f222fc5bcce3673845fee99692ef2cdc94acd033a +dist/2024-05-26/rust-std-beta-wasm32-wasip1.tar.gz=7711323738d70039ac2dcc39812610464b5d06f4a24db127143964424f07692c +dist/2024-05-26/rust-std-beta-wasm32-wasip1.tar.xz=413fc4b5480274ede6fc389d2563655cea0d438baee6b4f6c0d8757a4179d8e3 +dist/2024-05-26/rust-std-beta-x86_64-pc-windows-gnu.tar.gz=b46cc9fab639276eb86be72746f3e484020014041cadff276da79f2c62b16376 +dist/2024-05-26/rust-std-beta-x86_64-pc-windows-gnu.tar.xz=f4241afe5137e9a28fefd20115154dedfdd0db6d62e70e8b447a9999d238bf98 +dist/2024-05-26/rust-std-beta-x86_64-unknown-illumos.tar.gz=7b963148cf41ec6c918448d71929190474ac18b4770581e8ca41c9aa06d0d548 +dist/2024-05-26/rust-std-beta-x86_64-unknown-illumos.tar.xz=11d363e7e1325daa6161206f659b2da1cb64e1a6a49bedea2afd0993692e0110 +dist/2024-05-26/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz=2846fb587bc1e04ebcc15c4401eca652ec4a9a3ee07c4c8901ba8f0dec8bd307 +dist/2024-05-26/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz=c9aba9b367861d861b7c21969c64ed7c56db27b295b79498f817d28afe6258d6 +dist/2024-05-26/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz=dccd96c4f24fd935c04f29b1ac10f936ee92b9c8ecc71ca494d60555a3541a80 +dist/2024-05-26/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz=6b22b9c8526b4c5e25e7b6583df7c626388d3ff177e1f7b22c57ffec07bdcde2 +dist/2024-05-26/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz=d85b7dc13e34927030b76f0578dfa8da22025b914e8f024e611a05f55f2ff60c +dist/2024-05-26/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz=327beab489c253a802259760afc82ac337fe2addd2f26877610e1a2ca8a20c47 +dist/2024-05-26/rust-std-beta-thumbv7m-none-eabi.tar.gz=3b78f640fbc54016515b15fe5eba6c3d3f679582f33fbbd7656a9514bf04de25 +dist/2024-05-26/rust-std-beta-thumbv7m-none-eabi.tar.xz=f8fa181333351d8673b938b0395be2632110cdc6ad40f2b2bbc254643f5047df +dist/2024-05-26/rust-std-beta-wasm32-wasi.tar.gz=fa1f7cbf6784e9d1487a88f1942a223056315d45968d1f23ac262d81e6a3a1ca +dist/2024-05-26/rust-std-beta-wasm32-wasi.tar.xz=e13ce9734bebabf39839b27310c4a97c1553a34988bb2de69c9f4ad38592da48 +dist/2024-05-26/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz=93c06f87883dd3b8abc504ee10c0d46ad702ec7266f13996a8e8dbbdcc6adfb8 +dist/2024-05-26/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz=f785f3f53f47cd70cb3b1e04f46ae56f937814a895d132db470e21d9eb3f0eba +dist/2024-05-26/rust-std-beta-s390x-unknown-linux-gnu.tar.gz=7bdb39efb763f3272550f229d97145515e73c9510b54c53246436c068fa4b98e +dist/2024-05-26/rust-std-beta-s390x-unknown-linux-gnu.tar.xz=33960973887d3e4dc5f72550dd636c28bf6d5a9319c23c2ea1a14bb4c33eccf3 +dist/2024-05-26/rust-std-beta-x86_64-unknown-redox.tar.gz=16194e687a77d25e67d575f4e8a202d070771b6e51fb261d3a4673978b4c2a76 +dist/2024-05-26/rust-std-beta-x86_64-unknown-redox.tar.xz=0ce66624b0d2c1e476c730fc96718e8ff52780f8d5d6968e39a30cb9bd906b22 +dist/2024-05-26/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz=01555fb03930106ae6be0c4bbc185a5f8cbec27375aedf4201529ed6856ac02d +dist/2024-05-26/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz=3fa3ec9e478370a2874e7a47dcd84f714612b0eb05a8cbb6ff9379250e750278 +dist/2024-05-26/rust-std-beta-nvptx64-nvidia-cuda.tar.gz=b84dc461e790fdcbf8084d2adb42398e51f162416522f2901f1d82d07915ee70 +dist/2024-05-26/rust-std-beta-nvptx64-nvidia-cuda.tar.xz=8792ac895cd373b3fa8f4913e5a1b098d97ca1ca8f71beb15ca614111ea9bbbc +dist/2024-05-26/rust-std-beta-i686-unknown-linux-musl.tar.gz=5133f49db7ba73e900d8431838cbc12a5a276ff0f95fcd10a5791d5b4ef9b714 +dist/2024-05-26/rust-std-beta-i686-unknown-linux-musl.tar.xz=607131ca6ed1feab6289035445be404060281d3b1f720f40eb985b0341d2f2cd +dist/2024-05-26/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz=aa8ba338e80abadf4383c34a686b1fa331e31a4cf0bb067576288f265a86aac3 +dist/2024-05-26/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz=46fdbdffd351933cc1bebeaee3e2b26bee28c2356a9b337a4472346ee6cac9c9 +dist/2024-05-26/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz=dbbd9d0f3b4ecd1cac5d9c6ee62e5e099fd5f05dd8703c9035d5280b38e3a601 +dist/2024-05-26/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz=60edbb54ab8f1b982057a79063e6cf0fe5e4041c6306251e54cfca7014de84c9 +dist/2024-05-26/rust-std-beta-aarch64-unknown-fuchsia.tar.gz=7ab82e3ae01242203d9d72b7d3c01c3bd70ef4d9ddcc86feaf025ae120558dad +dist/2024-05-26/rust-std-beta-aarch64-unknown-fuchsia.tar.xz=148500507545bc8addedd8fe2f1df836c9aba894afb06bcb6f8a1258d9590999 +dist/2024-05-26/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz=5b9d7ca3c0b76a23ac412aae8421750b144c9e9fdacdb34a637a6f5f353d9bc9 +dist/2024-05-26/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz=7c856cc68e7d0b972258cc8f37731e72b9dd7eb88fc143fdea5220f4f60f6db0 +dist/2024-05-26/rust-std-beta-x86_64-unknown-uefi.tar.gz=5ddf07fcfd6e2cf17104f26fdfbaed3fa9055708b0ca63b1b0e675df8690b04f +dist/2024-05-26/rust-std-beta-x86_64-unknown-uefi.tar.xz=bbe32665b93efc6cf2fc5c28af448f85efa3810734a121033a92eac06b8414b1 +dist/2024-05-26/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz=cde6a9cfb0aeced8be963fd7faa0456d506b6d693e84afd6a5423ac37a69d944 +dist/2024-05-26/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz=026bdb53279ebb5f6a50f581b12ca2aa2c4de9655e786a3a17a606b2db4ff49d +dist/2024-05-26/rust-std-beta-i686-linux-android.tar.gz=8a21fb5147985941fc9eb8581e9970997240d8af19d6348e8b1b4296ecbea47c +dist/2024-05-26/rust-std-beta-i686-linux-android.tar.xz=ac5fd73f5a6ddc8c0644b32626c0bc53c885788e3e9fe331e2b598b86f0daebd +dist/2024-05-26/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz=1f791a99dbed0179a1ea7b36fd13128c5c05d08489c8baa0ce660b6bbaf42a05 +dist/2024-05-26/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz=92f8573bb786beb5cc74f3842a57d2725409ca7c2b12ed64f7ee543bb3ee477a +dist/2024-05-26/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz=faf08553004fda1e2215116221cf35c7ea4a9f9c51b5bbe4bf16c99235d571de +dist/2024-05-26/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz=81a5f8c273f7403091781bd7ad110fe7103392bef4350bba0e029385bc0ce0a7 +dist/2024-05-26/rust-std-beta-x86_64-apple-darwin.tar.gz=2a2bf00ca629cd0c7bdcc7333456f5766db2a805cba1c88a1a89cfe76a0f5d09 +dist/2024-05-26/rust-std-beta-x86_64-apple-darwin.tar.xz=b3ac3042484e972962a3e67b4f9251380135d6cf07b9589c5e3e94b0dbdb70fb +dist/2024-05-26/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz=c1953526bed228077dd42be2e570d1276fcf04868e4c8d426d23e00037178617 +dist/2024-05-26/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz=71310bef84016c25c949826121b8bf78eabac6d7c34b3397961ad39493df49c2 +dist/2024-05-26/rust-std-beta-thumbv8m.main-none-eabi.tar.gz=d8fa9332e29f19b8b06dbafa2b6b13eb3479b9b28601372dabcee0cbb2a4d0ab +dist/2024-05-26/rust-std-beta-thumbv8m.main-none-eabi.tar.xz=84daea4b14a3eb2712120652ebb2c342e6a37f984f1512dfa3cbd3531fb5cf53 +dist/2024-05-26/rust-std-beta-armebv7r-none-eabihf.tar.gz=348822ddf1f918cf56e6b76cdcfd3c4d4f50fb8e45c8b8c803e639910150b044 +dist/2024-05-26/rust-std-beta-armebv7r-none-eabihf.tar.xz=0f26d6888811e8ce6f0324bc5b4cbd667fbd8771e3e42192410d15e1d45033d5 +dist/2024-05-26/rust-std-beta-aarch64-unknown-linux-musl.tar.gz=42b49ef649da71c425b9de48812c23470638ac876f489f4c1c35ac116ba0d078 +dist/2024-05-26/rust-std-beta-aarch64-unknown-linux-musl.tar.xz=1111d46b2f5ef019cfb894b1a330721ee6fa1cf19b6f3c1abd8f866f8a208b3c +dist/2024-05-26/rust-std-beta-thumbv7em-none-eabi.tar.gz=4a41109968645be22ef1540037ac0a73789583eb250381d8431dfa6c8dd3a652 +dist/2024-05-26/rust-std-beta-thumbv7em-none-eabi.tar.xz=10007bd59e6cd60e924e472c19df1bda10bf6c60887ed91fb9874a7e596f9e72 +dist/2024-05-26/rust-std-beta-thumbv8m.base-none-eabi.tar.gz=09d74fb8bd049910c60f585193af33fa51eab82dd2211030d71f3dcfba128a96 +dist/2024-05-26/rust-std-beta-thumbv8m.base-none-eabi.tar.xz=2cdabc7be85304a7675fcebd53b8dd0e4183007fe0f81db3811df0d8bc712120 +dist/2024-05-26/rust-std-beta-x86_64-apple-ios.tar.gz=2061188c2361ce7b3a62a5bf45012aed708a8a86c2e5d1035a8c82b2ce868aa9 +dist/2024-05-26/rust-std-beta-x86_64-apple-ios.tar.xz=b6fd849acd590c2b853783b12b7b559395cc6698c6ab60d3b58a8475c809b9c6 +dist/2024-05-26/rust-std-beta-armv7r-none-eabihf.tar.gz=1915d8b728f8e37d7ede0da8cf2281676b970281c486d683f58d9bccfac2868e +dist/2024-05-26/rust-std-beta-armv7r-none-eabihf.tar.xz=21323f2a4eb7d46924438d0cc341b5d4e35b1ddb5abb02604980b5b055449e40 +dist/2024-05-26/rust-std-beta-riscv32im-unknown-none-elf.tar.gz=2f6ff815e3f4ed2913a27bb30c51c3992e60fa4d7d00a6ea8c648f19c9fd56bd +dist/2024-05-26/rust-std-beta-riscv32im-unknown-none-elf.tar.xz=ae6d85a4ee1a98084f3b95befb923ccb57eb42a05ef1fc9f4e5d6736a63edc09 +dist/2024-05-26/rust-std-beta-x86_64-linux-android.tar.gz=580b1f05fc5530fe0078e958b8740ac538ba1b2589e2c893a6b25f12fa4609f5 +dist/2024-05-26/rust-std-beta-x86_64-linux-android.tar.xz=8eccdb906d4f28404172d6e09dbe8a33a89cdf4dea168c446a3f38d719b63ec7 +dist/2024-05-26/rust-std-beta-aarch64-pc-windows-msvc.tar.gz=91c10648eaa115ebb2436cf78031d86704a917c2641090c2fc30d3234f2ed316 +dist/2024-05-26/rust-std-beta-aarch64-pc-windows-msvc.tar.xz=376e28b76c9b0fb590b7a7b3700debb4bd5878d861c144aa69502a0aaba2c9ba +dist/2024-05-26/rust-std-beta-armv7-unknown-linux-ohos.tar.gz=9a02c999175b39b1ae4a99a5556f42c89ce02b9c6e25688cfe573833256f9a0b +dist/2024-05-26/rust-std-beta-armv7-unknown-linux-ohos.tar.xz=5dbcb9a42313fcbec57d26877175320bde265a1c1c1f8a3415bb742b86810153 +dist/2024-05-26/rust-std-beta-i686-pc-windows-gnullvm.tar.gz=df780a07a1322e981da7083938d755dbefe0a2fa00c6acbe5658469400b79d32 +dist/2024-05-26/rust-std-beta-i686-pc-windows-gnullvm.tar.xz=611fe18a51c4d84b231d3cf9a2dc47913071698634b7b3c4c066b1e92ef5adee +dist/2024-05-26/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz=0f30d5e28ed599888e8125b3614070ef3da7d9b52442fd11e15993a84b678432 +dist/2024-05-26/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz=7118728e4dfb3283f4f6ffdf0cb92e4f1dbee7a8d9ee79c2cb4cad99e90507f5 +dist/2024-05-26/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz=f1f1a976de6ad212370887bc8079a0ce6b491ca9bad3e4e8d2ba06e4eafae2d3 +dist/2024-05-26/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz=034a5cebd66cf8f6d9379a26744e14d7d7e681b9203589a090a0fa205296d58d +dist/2024-05-26/rust-std-beta-x86_64-unknown-linux-musl.tar.gz=900ac2af2799139ea704e192f6709f364b736e31ce682e12ce2ba0471b01afa1 +dist/2024-05-26/rust-std-beta-x86_64-unknown-linux-musl.tar.xz=5883309a473fb227ed5c71b7f341fc6f5ff22657d089ba790fc80ac9afeb065b +dist/2024-05-26/rust-std-beta-i586-unknown-linux-musl.tar.gz=da1637ebab43f0a7b6e64ba42d8e2d06f04c7c8eda4e8f80a6fa520832288dde +dist/2024-05-26/rust-std-beta-i586-unknown-linux-musl.tar.xz=c80f46b0b5b4cd2e3ea67f4ab3df1ad4124fa6b425d598ca0b6656451a74ba44 +dist/2024-05-26/rust-std-beta-aarch64-unknown-uefi.tar.gz=f7d0413c0882917fd041704c692cf5cc5030660aa9f04ada91e5c3c3fe007c6c +dist/2024-05-26/rust-std-beta-aarch64-unknown-uefi.tar.xz=ad84c695a7eb2dccee3d3560e2140fe19c6aee116fc5fc953ac944d630d3fd64 +dist/2024-05-26/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz=d42f482f7c262cc9cd6f9bb5bc64019cc348c0ec552ac5b518bd92548018411a +dist/2024-05-26/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz=7589cab1072cecc50a9481e025e2f62f42975e60ba3e50fa6074e57e80c97257 +dist/2024-05-26/rust-std-beta-i686-unknown-uefi.tar.gz=85392042843c9653f1f6f643c0ba1af98ab0fd5a81cf1ddb7736415238cd5fa1 +dist/2024-05-26/rust-std-beta-i686-unknown-uefi.tar.xz=9cac1dafe8fc420c163fdb0ec089443dd4632077eaef73c459f3e8a9648fc6e5 +dist/2024-05-26/rust-std-beta-arm-unknown-linux-musleabi.tar.gz=a2c33177e3a1d48542bd376eac44d4fc6320e58ed5b5ee1c5f58980301d7df49 +dist/2024-05-26/rust-std-beta-arm-unknown-linux-musleabi.tar.xz=7183769937af0c9501b8fb71ce84a41562d9d773f4647d0d76d692fc0a623994 +dist/2024-05-26/rust-std-beta-armv7a-none-eabi.tar.gz=48e17ac14232f015425b46e1cfea19eea664cd224e0ec3e5b2ff58b82174b67a +dist/2024-05-26/rust-std-beta-armv7a-none-eabi.tar.xz=e04323b38171e9c63a4cd1673a5d69a9faf6e415d69ba11e7da7f30bd77077ac +dist/2024-05-26/rust-std-beta-x86_64-pc-windows-msvc.tar.gz=2bc38de25271bd34c74a97b2f09133b4d3518911bd2d32deceab3e91f7554aed +dist/2024-05-26/rust-std-beta-x86_64-pc-windows-msvc.tar.xz=2aad6d3b0b86847dfb1e57394de95dcbfe799630b388933d09939d1e309df911 +dist/2024-05-26/rust-std-beta-x86_64-unknown-none.tar.gz=9de88c179553ec42bdf5e036a44318a442778396380c44387cac94658ae7a294 +dist/2024-05-26/rust-std-beta-x86_64-unknown-none.tar.xz=f526dabd3d11858320129ccabfb3e5d14249ea6db30ac882ab26ae628d91f81e +dist/2024-05-26/rust-std-beta-armv7r-none-eabi.tar.gz=fa439d79673ad7a467dda9aa40524299880378d2a44a3338d038a6c6e6ec164c +dist/2024-05-26/rust-std-beta-armv7r-none-eabi.tar.xz=e07e26bcb5bd8dc93a877d122568aa78d09f77e81a3c85538872ddea47f3b319 +dist/2024-05-26/rust-std-beta-i586-pc-windows-msvc.tar.gz=f703880c171e14a6748beadb64477e85716e1cf45f98c5342600ee850518ba60 +dist/2024-05-26/rust-std-beta-i586-pc-windows-msvc.tar.xz=17dbd60169c3f47aa031d58dcd4898032d1e4991df86ff64e684e833c717d453 +dist/2024-05-26/rust-std-beta-armebv7r-none-eabi.tar.gz=5e53e25483594947af7a2aa5f14b06d44e0eaa16a464a004cfe7b079da9d7847 +dist/2024-05-26/rust-std-beta-armebv7r-none-eabi.tar.xz=81da84696b4250ad653b29aa73e8dd70fb0db6b469d8895a1f6c587ef38b47eb +dist/2024-05-26/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz=d93918290043ba801c78f1d662ab847cd19002560fa6832176bb549cc51b0e8b +dist/2024-05-26/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz=46b81807b463ef523a2e522199b4cdff70b817ab45bac56d17b7cf40c2bdb908 +dist/2024-05-26/rust-std-beta-i686-unknown-linux-gnu.tar.gz=adc0fa2c9a8cc8b4204fbd0455ccb2f914ae5335d8f8f96dc3df2791cf85e625 +dist/2024-05-26/rust-std-beta-i686-unknown-linux-gnu.tar.xz=8d5531693ba346d36f89fa969826434a1583c60dd1bf61b055aff026cadcb82d +dist/2024-05-26/rust-std-beta-aarch64-pc-windows-gnullvm.tar.gz=01bd0ccbae4a301cd39eb92afda2f3a4d81276c17f8a3f48f9226a36fe4b6d31 +dist/2024-05-26/rust-std-beta-aarch64-pc-windows-gnullvm.tar.xz=a07afdb285f1744ea75082d0a92f07333d5fd26ab84818a1bbb91ffab047998f +dist/2024-05-26/rust-std-beta-aarch64-apple-darwin.tar.gz=333fb310bf7749b0fb81a4f0930d0db738e24098fd3b4b38d037686c713f7243 +dist/2024-05-26/rust-std-beta-aarch64-apple-darwin.tar.xz=aa720a70e396e872045fe5934444b0e1b1e4633f371dc781397192c42a970c22 +dist/2024-05-26/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz=4949dc875777c799d1fa74db866d6492b25bf15a9383867f8272c3751b1bfd99 +dist/2024-05-26/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz=40eb3bffd0ca0db7dcd330e01f28ba777807f0e2e514f65e3c2aedf19b72d61c +dist/2024-05-26/rust-std-beta-loongarch64-unknown-none.tar.gz=0b719a0748343cea4f6e3fcd0dffc567de0e45eef6b8067259c5d8b61c7b8040 +dist/2024-05-26/rust-std-beta-loongarch64-unknown-none.tar.xz=e7cb82769b71b100a8453df764a231d1967e5ae41a39a0b974a31ecd6c348568 +dist/2024-05-26/rust-std-beta-aarch64-linux-android.tar.gz=9b85abd7488b16f323396e5158059104281319971933a0702055b1e508418395 +dist/2024-05-26/rust-std-beta-aarch64-linux-android.tar.xz=2164c9dd13043e16b5144670a3032adfe0e439b18a193ca22c4c6b6bab678577 +dist/2024-05-26/rust-std-beta-sparcv9-sun-solaris.tar.gz=ab9d4db4abb8057fa0e9d8cfe0d01921da5499d082402f6277e1f8ed75c32f23 +dist/2024-05-26/rust-std-beta-sparcv9-sun-solaris.tar.xz=43254c65450dde6de4ce2538b80100db01ca15632989a6ba7173b01f4acc89bc +dist/2024-05-26/rust-std-beta-x86_64-unknown-netbsd.tar.gz=07c76a68e44cb9d6ba527d17dafdc0b51c9e2b51ab1c5dbbe8784d137609a4b5 +dist/2024-05-26/rust-std-beta-x86_64-unknown-netbsd.tar.xz=caf5dc8356c9fd34f13983f338e0d44fbec83358309a60b1d7520aaaddc4ff57 +dist/2024-05-26/rust-std-beta-i686-pc-windows-gnu.tar.gz=ca3561531a6054f2236a820c77b5ce109118f720a0e1ef850cb5dc8abfd1c8ce +dist/2024-05-26/rust-std-beta-i686-pc-windows-gnu.tar.xz=955681b4b4f5b3bebee11c381b8c12a73ca7fedf4f4d80213be9035cfad722f1 +dist/2024-05-26/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz=035483e893dc4e28689c8ddba80b0e12d4b6ff8c8075c8fbb72612edfb830d1a +dist/2024-05-26/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz=e6d4f6d00972fdf6f9c9faf4e8608d7f6eca23094623ddd9c6a08237f0721825 +dist/2024-05-26/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz=02f9bb16b62f6b1a02787ad30877fe5b1676524ec868789044b82cb762cd96d3 +dist/2024-05-26/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz=c54719d0e78d063c1aabc9253a3cb0bb5bc9a9b88bdd02829f004c183ef225ae +dist/2024-05-26/rust-std-beta-arm-linux-androideabi.tar.gz=ab579d41fa31499c9ae0574194961d64065bbded4595c9809504826151d7ffb9 +dist/2024-05-26/rust-std-beta-arm-linux-androideabi.tar.xz=41f0ac3317212f46df64b0907487ced9b5c8e390f2d8a49f284ddf95a89c04b1 +dist/2024-05-26/rust-std-beta-i686-unknown-freebsd.tar.gz=cad37ef490a691de7b1649b94aea62af61a79d93e3f859fffaf5ccf63ca238f5 +dist/2024-05-26/rust-std-beta-i686-unknown-freebsd.tar.xz=f20be5c8c379fe9d2445eaf83fdb9b1df77117a93fa6ec0b97fbd0e5449f75bc +dist/2024-05-26/rust-std-beta-armv7-linux-androideabi.tar.gz=58eb5e6155e8f4e598f7201ad46633afda0fbc3221fdf07c57ab7c644eed4140 +dist/2024-05-26/rust-std-beta-armv7-linux-androideabi.tar.xz=c2ee165302f135710ea2158d9592731cfdbb1c2d7f529ac1557b190826aae24d +dist/2024-05-26/rust-std-beta-wasm32-unknown-emscripten.tar.gz=6268910518871d87012f8e77e31c3b525cb573f6697787b03c516e2a43846e45 +dist/2024-05-26/rust-std-beta-wasm32-unknown-emscripten.tar.xz=01cf5cd68bcd9a7f706ff1b266bc5bfb61b8b1230488b3352359ce1c604c5d36 +dist/2024-05-26/rust-std-beta-x86_64-unknown-freebsd.tar.gz=c3baafd66056b93943bde313b84b00f719fbb006045a7af869d1c0b77927ffc4 +dist/2024-05-26/rust-std-beta-x86_64-unknown-freebsd.tar.xz=7d846e6840553986ebe3f2a8dd526af5daeaad566f3b241e94c2d18dedabed85 +dist/2024-05-26/rust-std-beta-wasm32-wasip1-threads.tar.gz=b4de80001c585b3644116c7a4cc7ee6a00476058f84637c3ff49e8dfc5edcf1d +dist/2024-05-26/rust-std-beta-wasm32-wasip1-threads.tar.xz=8facfbeb32902b094512c89dac44b94f437163a8b630adc485383045ec4bfd0d +dist/2024-05-26/rust-std-beta-riscv32i-unknown-none-elf.tar.gz=0b8a82fa80653cbd2c27237b7b696f4ddd37e0a2575fca29655fd36883193659 +dist/2024-05-26/rust-std-beta-riscv32i-unknown-none-elf.tar.xz=ea9b3e6984605bd2606aa0456e5a9ecc4addd2880104cf5ddbb7fdb81673818f +dist/2024-05-26/rust-std-beta-x86_64-pc-solaris.tar.gz=b4234ad1e817f65a7a2ecdfabfb1437ce98fd580c0bff61037ec917fd6e3c88b +dist/2024-05-26/rust-std-beta-x86_64-pc-solaris.tar.xz=b7ee8e567aa1341d76be78eccd2c5857f4757b295b32a14d4054766c41cd126c +dist/2024-05-26/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz=145a8427c01b038b9bc79aed2e0ff46af87789555bd486885b3592c4bb62fe9b +dist/2024-05-26/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz=d84f020657dd466ba4f45d50fe1a8c316d03291c8845c443e2c68c4b40e590c4 +dist/2024-05-26/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz=96b2278c15a6f83cb37ad6af34d9c5f364198a19cedac937d5cbaafbaca63fa7 +dist/2024-05-26/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz=edbe125808cfcc69189c59f7b7614e056d34b23d121f9f165a93498eb775f92f +dist/2024-05-26/rust-std-beta-thumbv7em-none-eabihf.tar.gz=dbbc72ede43591cfddb55ceb4aeb38d641a7ea7d7c0f5f4415a3c2e3a07e916a +dist/2024-05-26/rust-std-beta-thumbv7em-none-eabihf.tar.xz=6b80df5802d08d6653fea474366bf1d4c892a87738a7a9f7156ae7ef916b5de6 +dist/2024-05-26/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz=2e9c56810053a067bf91df0bf3d2c5c08c823e25fbe7267a6633ad33876ab0bb +dist/2024-05-26/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz=494963c721fb8d1e0d44ab9ad4212aa086af2363289d7b0d8b08c1e82f71efc7 +dist/2024-05-26/rust-std-beta-x86_64-unknown-fuchsia.tar.gz=9901fb8f28e2334b31cb594afb1a91f22fa019b13808b650d940bd2d89a1315d +dist/2024-05-26/rust-std-beta-x86_64-unknown-fuchsia.tar.xz=583b0336f3f501eda441cdb5fbae87c4457a0bdcf896cca808111a181549b786 +dist/2024-05-26/rust-std-beta-i586-unknown-linux-gnu.tar.gz=e4fd222c2ed08e0fc1da161a23183ee222fa8755e70f4a352ae854b2cb798663 +dist/2024-05-26/rust-std-beta-i586-unknown-linux-gnu.tar.xz=81bf3475805e8af9a6297868ce9c1893c22d901fc7d16f0482c28a4655608de6 +dist/2024-05-26/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz=c1d015599bc48664b01507da30bf152d730eaf0bd61cd907caa353b223d7adb9 +dist/2024-05-26/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz=fdea1b1280e2fa5b14ef8998408557ecad0954b2502fe073e65e3ec3cacd1d22 +dist/2024-05-26/rust-std-beta-aarch64-apple-ios.tar.gz=be8fc41bb262be74ad73d375db76cc8ba277e8313a911aaabf17b02c52909b2f +dist/2024-05-26/rust-std-beta-aarch64-apple-ios.tar.xz=7ae7187a9e85b58b740cf778df6d4442e388236501d6eeee76bcef0f9f378533 +dist/2024-05-26/rust-std-beta-wasm32-unknown-unknown.tar.gz=f5d863504c8b6b3fd42123dc09ad5e2cef978d8887a8ed62a125c125a7022b32 +dist/2024-05-26/rust-std-beta-wasm32-unknown-unknown.tar.xz=a36d65ab13f0da73e38f5e034d041dbdb1dc6577508734af332b2cbda5122ad6 +dist/2024-05-26/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz=f9c9684b948b09d658689ca70b84515b3533c41edab0e25bcd8aef5e40c621f5 +dist/2024-05-26/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz=e595f26a2b49d2f5b36e5a7333ac6bd0b54fd1c05122d160e5c1a4708ed6d488 +dist/2024-05-26/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz=2c140b89014321f7827ce3e0b2d6cfdc84e871f05b3a0908716174719689498a +dist/2024-05-26/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz=bfed676e39a67671f3256edb6b9e20e8ed4421d4b777627c1484afd8c0d68d85 +dist/2024-05-26/rust-std-beta-aarch64-apple-ios-sim.tar.gz=8297677d667a637cb298e9e7453ba68190a9ad314a52015bc4124817e6586ece +dist/2024-05-26/rust-std-beta-aarch64-apple-ios-sim.tar.xz=f2763a0f3a59b6c87ad1dc390cd7715587cf2b41fb58f58849243c69524905ac +dist/2024-05-26/rust-std-beta-thumbv6m-none-eabi.tar.gz=447a1c4e502b0deef96183af40f32ef3f0d011f833621d7b0a6d972c8859e986 +dist/2024-05-26/rust-std-beta-thumbv6m-none-eabi.tar.xz=5d21d53fdcbdcae5dedf1e8cf2742d05b95198c984cf42322b72e98636214364 +dist/2024-05-26/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz=f1ea6387ea140cce37c4708bbd5135d74f2861309b907b58458f2a4bb34dff13 +dist/2024-05-26/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz=464f09ab8fe2fb8cda1d194d1178e025f092c13984680fcfc55f60f0f3b7f757 +dist/2024-05-26/rust-std-beta-aarch64-unknown-none.tar.gz=17b2d567838919513d8b998819f0367cee1b030882bff2be1116fcc4d3b95b1e +dist/2024-05-26/rust-std-beta-aarch64-unknown-none.tar.xz=a0571520b61b28a64055b6420ce5cbd49ebb8aaaefc73ab40df73b0ebeb142e8 +dist/2024-05-26/cargo-beta-aarch64-unknown-linux-musl.tar.gz=61a51a1409249cb99d168d88805d678f042b0cebae06f0f2be3ec3ffe507e59a +dist/2024-05-26/cargo-beta-aarch64-unknown-linux-musl.tar.xz=ea1e0fa7859596502b1b270e58599ca0d71c17060dc504a8cc801dc63a60de30 +dist/2024-05-26/cargo-beta-x86_64-pc-windows-gnu.tar.gz=ed791a607b85ed30666cf25de886892bcdab38bb2194bb5969637c4bf5700dcf +dist/2024-05-26/cargo-beta-x86_64-pc-windows-gnu.tar.xz=3cd4887501f35f9d608c25e5306b3e20473820d194e014902f1ba7e2baf365d7 +dist/2024-05-26/cargo-beta-i686-pc-windows-msvc.tar.gz=c531faa0b9af65f9987897dab8ef32d32c53d14437a76541fb7e477d73a778ca +dist/2024-05-26/cargo-beta-i686-pc-windows-msvc.tar.xz=f624fd704ee17023fe568a5f7165fd310170610b62fcfe0be374fbd53ba5e5fa +dist/2024-05-26/cargo-beta-s390x-unknown-linux-gnu.tar.gz=e4de592c9e6e58556ee56ca395838259cd239cd88be27fe27141181981ebac4f +dist/2024-05-26/cargo-beta-s390x-unknown-linux-gnu.tar.xz=b34dedc4c0312d40c7923f7fda9491ec6969002d641cff31889b96ba9becec08 +dist/2024-05-26/cargo-beta-x86_64-unknown-linux-gnu.tar.gz=3c60bd3a7623e4a6f8691256ebdbd5b7441a13cc291803cd7e1e3a9af600def6 +dist/2024-05-26/cargo-beta-x86_64-unknown-linux-gnu.tar.xz=07c4043b8da23bc161e8df2924c96f21c3d613e07b6d78c57c57908eeff50feb +dist/2024-05-26/cargo-beta-x86_64-unknown-freebsd.tar.gz=9e8e5e7e2725c680eef7ac4c9b962f04f31d2f59a33a4ff2025aa035f0ef9f80 +dist/2024-05-26/cargo-beta-x86_64-unknown-freebsd.tar.xz=c5e194b6bd6494101ac163902943437b3b0b1e78cfe50900fa80eda96bf37a4a +dist/2024-05-26/cargo-beta-i686-unknown-linux-gnu.tar.gz=20931f1b365f6f39fa473393ffade8bca346d00483673253a75f5718728e934f +dist/2024-05-26/cargo-beta-i686-unknown-linux-gnu.tar.xz=7ce7c900c333f79170d28fcc85603822c39b14b687db22618ae11bfd3d6d274e +dist/2024-05-26/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz=152b2d0c9d1b79ef75cf5d86b880aff2e675e74d1f3456d156f782692df9062a +dist/2024-05-26/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz=29852ddbc3e91ef2524a267f4037a901a5dcef4182138dc85f946b13f2defe2d +dist/2024-05-26/cargo-beta-arm-unknown-linux-gnueabi.tar.gz=084be6c65205744138bb4b32c8c64acfcd62eec48de06dce24904d7dc92d5d08 +dist/2024-05-26/cargo-beta-arm-unknown-linux-gnueabi.tar.xz=40139b0b78e8bf8b6ced7bd45675be174b51e99b0e09d5029aa2810f4ecd1850 +dist/2024-05-26/cargo-beta-x86_64-unknown-illumos.tar.gz=92448a4b52d02cc7e33c4304542f3514c1dfdd48a10a15c085caf24eae1ac955 +dist/2024-05-26/cargo-beta-x86_64-unknown-illumos.tar.xz=54757ba4bfc4ee87161dab91d3406570eae3f95f9022742b7096359e532a46bf +dist/2024-05-26/cargo-beta-aarch64-pc-windows-msvc.tar.gz=c8d3cd13d4a2f3932b3804bfd18a11f847b5c2bb5ae32f4eb04c75f882c23471 +dist/2024-05-26/cargo-beta-aarch64-pc-windows-msvc.tar.xz=ff5b389e3645d58fd7cad66881554537d36319d84add1d897382b6ca3ca406f2 +dist/2024-05-26/cargo-beta-powerpc-unknown-linux-gnu.tar.gz=31ea12902d3179266af423f4534881a9b2ea0131c0ee292a46e4db35efed6063 +dist/2024-05-26/cargo-beta-powerpc-unknown-linux-gnu.tar.xz=1b467f77feaadd5d37d6faeca1f4001e7d5d1b29c4d40465c78f4d556ae23b1a +dist/2024-05-26/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz=a32d5142d32f64f3adc18d9949c63e4582caac446daf8809626f3edc04dcc2ee +dist/2024-05-26/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz=facf0eb79d61967126c5c49698aea3603790c13f467e40475ba4ba80d2937ee8 +dist/2024-05-26/cargo-beta-x86_64-pc-windows-msvc.tar.gz=bbc183a2ffa90e9771c1db7ae1bb260d6c5ecc86933e9d60026d5ff4975c76ac +dist/2024-05-26/cargo-beta-x86_64-pc-windows-msvc.tar.xz=154e72625aa847777464b1aa8d885f8de0f16138362ec3725f96b434d6ec3a1d +dist/2024-05-26/cargo-beta-x86_64-unknown-linux-musl.tar.gz=b45ea7d288797a7da04b71b665dca721899df248887e35b1d6903077a7f3a363 +dist/2024-05-26/cargo-beta-x86_64-unknown-linux-musl.tar.xz=cf654640589ad3326d5072be882270c8e16694400668a2b1be1feea6cd623636 +dist/2024-05-26/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz=0c57f4972f64d8a418d4821492d2f069b7dd8f7b1e9626bdf59c4763ee85e06c +dist/2024-05-26/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz=2ddb32aec0863593472f47c90fe9e8f008fdf69f3e33679d808383e56e5acaae +dist/2024-05-26/cargo-beta-aarch64-unknown-linux-gnu.tar.gz=f304394966cea648c66faadc1f04d46a39e7532b913ae6f170b67eca1c03cfbf +dist/2024-05-26/cargo-beta-aarch64-unknown-linux-gnu.tar.xz=0625fe16550bd1a1aac9699560e168836d6a31f24c2bd5f49007029684991c05 +dist/2024-05-26/cargo-beta-aarch64-apple-darwin.tar.gz=8159a07acc11cd1c1b7d0c0dcf8be269325033922c21a85ec38a9a1b11166cbf +dist/2024-05-26/cargo-beta-aarch64-apple-darwin.tar.xz=e4e935be5e89a405c06dcc77a76929a7c5fda2e576bde183a6854254720e053e +dist/2024-05-26/cargo-beta-i686-pc-windows-gnu.tar.gz=6a5c34fd6a762df06c7b25d3a25f93f8dcd9071789528365350b20ac4a0cf08b +dist/2024-05-26/cargo-beta-i686-pc-windows-gnu.tar.xz=3b0784e1ada13f88c1b3d130135406ab1b12ace88e2f296b292071ec35d15b50 +dist/2024-05-26/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz=8dee7954f81238d7be66538f70cce670b724e919fcd7f2eeeef8ee492a808a8d +dist/2024-05-26/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz=dd2445c26ea2c151b93bff68c164ed69a313f87fbf1f90e8024317b4a66a6185 +dist/2024-05-26/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz=bdcc649bb6f425ab32caa2cc385fa3b99cbe86cc3ea7a5780788c35c029fb099 +dist/2024-05-26/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz=8fb0a771f69f3d6849129a1ebf5026e256010775e8bb9befd52325243b8f188e +dist/2024-05-26/cargo-beta-x86_64-apple-darwin.tar.gz=2f4cefcb58f0ff51eef25680c926313e9b5e4a2c3beb710e7bb8eadde50c9313 +dist/2024-05-26/cargo-beta-x86_64-apple-darwin.tar.xz=5d53afb9ca5fe65a56e1d64e4746b13f9c586f81603553c0556eb02ad95df4c2 +dist/2024-05-26/cargo-beta-x86_64-unknown-netbsd.tar.gz=35c5b04d84d85c43f0c5a3bdc2aa8b8fb848961e3c4daf276704f85e47ae3fb2 +dist/2024-05-26/cargo-beta-x86_64-unknown-netbsd.tar.xz=3b0296264bd63a2d40c9d5e3a663756a5bdf442635ee8b6f54438a2767a2d04d +dist/2024-05-26/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz=a8c3a909f50a5de7f78672942d87aed939ee60ed6d5e50f308460a942a632545 +dist/2024-05-26/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz=2ca4cb39879eba33da970197d45de82df898cf5a5bd4f4614b083fe999fac575 +dist/2024-05-26/clippy-beta-aarch64-apple-darwin.tar.gz=04c563beabcaefe80eda700ab26e975b30b5264c6202e04c9577f6c2b41bd6a9 +dist/2024-05-26/clippy-beta-aarch64-apple-darwin.tar.xz=19846f743872fd899ad66ce4820eef3f7ac056834856fe1d86c963f2e8acf2e5 +dist/2024-05-26/clippy-beta-s390x-unknown-linux-gnu.tar.gz=911554e8139df5c5b61fc85aaee2119cf36f3ec0f0e8741a7c8d92b1205bcff6 +dist/2024-05-26/clippy-beta-s390x-unknown-linux-gnu.tar.xz=1b108110da176b81daaadbc8c0a65950761fca243eb6cbf5ae0991d2bc3c89ec +dist/2024-05-26/clippy-beta-x86_64-unknown-illumos.tar.gz=264150fbe3d369f18b61f2d607b694519c2b4b50f93c8c03f7109064bea79ad7 +dist/2024-05-26/clippy-beta-x86_64-unknown-illumos.tar.xz=89a044938cf7734caaf39c98c6e2a036e544bc474a0af3a3d92e47f39534e6cc +dist/2024-05-26/clippy-beta-x86_64-unknown-linux-musl.tar.gz=f3a99c3a05280706cc042d67cec7162088cd2f62f2174bce8f074eda3d43cb8c +dist/2024-05-26/clippy-beta-x86_64-unknown-linux-musl.tar.xz=0da48481695a90c1857bc0f8ff39223b3791b8b7102143e44bcca7bcea6fcb42 +dist/2024-05-26/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz=5ba8b0e2162c574dc73121a69e43fd6629df9c656d96d95e9d269c3bc6e62add +dist/2024-05-26/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz=778eaf706993f617d40c22084f06d4ec8fa7455a22bcb699bd7b376d1194bd58 +dist/2024-05-26/clippy-beta-arm-unknown-linux-gnueabi.tar.gz=cdf9711390230edab20cf0552d55ebbef87263b3353fd51bf232c12d1dd131d4 +dist/2024-05-26/clippy-beta-arm-unknown-linux-gnueabi.tar.xz=5aa9b052cd0c7452ad08a1523c6fcad7df0a69f62a0a222b6a57d003d1881a6a +dist/2024-05-26/clippy-beta-aarch64-unknown-linux-gnu.tar.gz=3d7276560656e51826e3033dcc45fd2c78c2d872951c7e3434fd5f693a37fb45 +dist/2024-05-26/clippy-beta-aarch64-unknown-linux-gnu.tar.xz=9aa885565bf7691ed028b8838a4108313cb2e7eda4b2f96381e8d80655ff4ce8 +dist/2024-05-26/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz=29bcb622529f9e13b6aff7597e4c9d474f8127259f9efa96fa928eb3ba49b157 +dist/2024-05-26/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz=14c7a9664a635479391eb33b90d8af80188cd38069799bb5b851b935e1848473 +dist/2024-05-26/clippy-beta-x86_64-pc-windows-msvc.tar.gz=3491ca3ce04812559abe45455e468625791aa6fc648ddc229d429159ce2b639f +dist/2024-05-26/clippy-beta-x86_64-pc-windows-msvc.tar.xz=85eca1d8659dd6c171295b0aea160eff1410bc60e15889952998460b30df03ab +dist/2024-05-26/clippy-beta-aarch64-unknown-linux-musl.tar.gz=aed3c4e45f47fd0bd6ca299f5883132e6d8b3c3f06d6bede71bb664bb0b04c10 +dist/2024-05-26/clippy-beta-aarch64-unknown-linux-musl.tar.xz=b8c475ac163435bad15fada68c29733d96f23f87cd92f5aa13ca99df21b93323 +dist/2024-05-26/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz=3b42f9ffedd1b4074e7831fbf0809987866021b095eaa5f2d9481ca2765a7f85 +dist/2024-05-26/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz=d71a3e5ae13c46f68f95f8fca7a3c6f8795faebf7602f8d1206e355c6d9bec08 +dist/2024-05-26/clippy-beta-x86_64-unknown-linux-gnu.tar.gz=ce12948ba13e8f0556255a65657e9b92b996c2f96966cfefb895a6ffb8b08d47 +dist/2024-05-26/clippy-beta-x86_64-unknown-linux-gnu.tar.xz=d1d23de591053c469fccc8ae6edeae3a2a8502ea5feb95272ab90f6651c52dc1 +dist/2024-05-26/clippy-beta-powerpc-unknown-linux-gnu.tar.gz=31ae7b2c3af5ca9b47a9eb6ff53d1717df49e3a834584659a7108a72739799bc +dist/2024-05-26/clippy-beta-powerpc-unknown-linux-gnu.tar.xz=576332e47d5cd862581be587f03aa3a3e6abfc982fda6d26c7dcef0e2742b537 +dist/2024-05-26/clippy-beta-aarch64-pc-windows-msvc.tar.gz=8bd2c213b1dd6eea58a7896203962e9928ba9a39b0cbed5c5737b2d35c707a44 +dist/2024-05-26/clippy-beta-aarch64-pc-windows-msvc.tar.xz=dd530cb08114f28323c740e453f25b553376f0f4df977ebc79a87d09ac8e2b25 +dist/2024-05-26/clippy-beta-i686-unknown-linux-gnu.tar.gz=d8aa70bb4711bb985592632f88b2499b1fceedc294adcdb6e37f234dff0081f9 +dist/2024-05-26/clippy-beta-i686-unknown-linux-gnu.tar.xz=26349efee4513b0c37b9a963f3f6fcdeabc6857554bf3f28efa7c76c5c5b54b3 +dist/2024-05-26/clippy-beta-x86_64-apple-darwin.tar.gz=e6283756c66ff219a879799b6237df25755ac6a590e2015750bc3ac79eee322b +dist/2024-05-26/clippy-beta-x86_64-apple-darwin.tar.xz=474a5bacc986404ebdca454c28254e6af3a7865db1daf26da56497e6dd8db248 +dist/2024-05-26/clippy-beta-x86_64-pc-windows-gnu.tar.gz=2fab393b9f0fae2c087067dc42758f914d74eff81c6e87da134520b1e4bcfb97 +dist/2024-05-26/clippy-beta-x86_64-pc-windows-gnu.tar.xz=23f46cea5a99191908e79f6f145b6577ce328aa4a435c8fb84a3c5afba8b9476 +dist/2024-05-26/clippy-beta-i686-pc-windows-gnu.tar.gz=5d0b5a07967828f9d2180ecda420433962532721fcd6b5b1dcf7fd273c8ee1bb +dist/2024-05-26/clippy-beta-i686-pc-windows-gnu.tar.xz=34e36c25a1f385161d352f4d0fd03c332b9ad70c8bd96cd7928010f367d9ed07 +dist/2024-05-26/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz=6bb0b231319507013f6556b88c7b32e640e182249935935796b33063f77d8c5f +dist/2024-05-26/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz=e029f9e9176d0562d6729ad87ba9dbaf474c003854f140da0a57ca52b2794a68 +dist/2024-05-26/clippy-beta-x86_64-unknown-netbsd.tar.gz=5aff0b8818b2639d2bb792288464b042aa2987e63e4b8d885ceed14fbd2425a6 +dist/2024-05-26/clippy-beta-x86_64-unknown-netbsd.tar.xz=6edd1afcf6bf4d9118a1dfbd8fc7f862026d179277b465da51b6b455957bc30b +dist/2024-05-26/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz=8969bae5fee4a30591b55d57b06d03d7d2be08ee20d2e5d04f055f916a8e248a +dist/2024-05-26/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz=7dfddd258c8cfa4f6b26f739fe52bb0519543472476595d901486b53ab22ebe5 +dist/2024-05-26/clippy-beta-x86_64-unknown-freebsd.tar.gz=2462c2fdc6215312ec7a12e98f74f9cfb06c0bed30812441268bb91feb2e4a8a +dist/2024-05-26/clippy-beta-x86_64-unknown-freebsd.tar.xz=154d43b7db31cf9c25f6379c6bc0bb828fcaba99d9313e8267f705bdf810655d +dist/2024-05-26/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz=ed50a1f702e574c754a0c6eabfe120b5b3286bfe004dcc58b6a857684ae44033 +dist/2024-05-26/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz=c7431985caefaa2d995483b0af592f828157d517828e6792c8abec0a52e2e600 +dist/2024-05-26/clippy-beta-i686-pc-windows-msvc.tar.gz=870b60708cb7fb9bd76d6c1ec2572502bbb7a86152d7e2ffb0e3d023674193a7 +dist/2024-05-26/clippy-beta-i686-pc-windows-msvc.tar.xz=292183dc34bbc648564ef99230efdb8749d3d2e34a190b62b318ef1b8f4546fc +dist/2024-05-29/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=c28d6ba3d8319ca2a3c810ef13637dc67df6ab5c6d3e67e085009b296a4e87d3 +dist/2024-05-29/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=ba1e59c352e3e10696f3b1e5516af1d7b9fc480f4b9b45f313234a9151f4db57 +dist/2024-05-29/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=2efadde71b4bfbd6713b381f4e2df77a51be47818c4d7a0a9000d4f31502d50a +dist/2024-05-29/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=82347bd970ad3a6e6d9565d9e6bfa994e23f849591ae6fda109f876928033952 +dist/2024-05-29/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=c3deeda6061109a09b123df68fd83a9c11c30419b91fc73be7653e4650b1b544 +dist/2024-05-29/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=a93bab60e6133734771ccbc807b44263c368bdb66b05491359897a23803d31be +dist/2024-05-29/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=e71d212b7e25d7bbd0bdc4d04de8fa9c896239f1063f5e33067baf5278134cc5 +dist/2024-05-29/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=467191e0463a1f465304ffa37724da8199a112691147ae0c49fc311007fce410 +dist/2024-05-29/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=e2be1ffefa6c19b2682d8ac219ad88956485c99d41bcdd76fe78c80ce214f331 +dist/2024-05-29/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=7c801202c1c575c2522782f4346b4fc08abfc7f952a0cf3ad36a184e8e3c59ce +dist/2024-05-29/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=cbc04f5efa7849c51944612974aeadef63479202f2c0426d9301f38a54f3e023 +dist/2024-05-29/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=e0deed883ba554d9b863bad8f9903b5952813439469282673fcd322ab7692751 +dist/2024-05-29/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=d3c4d54c15e8dbc45e2182354510cb705068fd32e604d289c0c612a6942ae82c +dist/2024-05-29/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=a112b66030fc6d861ac988fbdb9496040a702d84409e41936c192af21d0ac7e2 +dist/2024-05-29/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=633f765dfa420b35aead7f8e0be99d28c90dd8d76dc452321e0b1102563f9f5e +dist/2024-05-29/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=5db0f26d1705666dd1b6aa9c00bd24679698c7afc5b9a5df7d5588dd8be4dbd8 +dist/2024-05-29/rustfmt-nightly-x86_64-apple-darwin.tar.gz=a919f09c70fb61986dc0b4a52a75641edf18d7a4a9396fb0aae1009510bfdef1 +dist/2024-05-29/rustfmt-nightly-x86_64-apple-darwin.tar.xz=1d5781a9e6c705dd0a14ae75d4a49e5b0bf149d5d157ee19afc4fcbf6c31de29 +dist/2024-05-29/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=866667cc443b61ada4e25b816ee3d8e9de0d3114a9f5ce26fa36f311731f5726 +dist/2024-05-29/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=66cfae5d45a256b8d838a93e49a1cab0263418158ea238e07ba673dc7b3df6f1 +dist/2024-05-29/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=57b29a2e3bd7d5aad05d6ac6ec8acd3f0b747ce679ea0fb53a203c5383895765 +dist/2024-05-29/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=b8a5f95ab75b9a645934adb9a76513e0ff85f98de7b82aba494bd74289597d43 +dist/2024-05-29/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=d1ec7e5e6c8b13ef47359b1e64b972be0c4f740d18d341190db347cd89a868e7 +dist/2024-05-29/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=84f60a1fb717916a03c8f054610f543efd687bbfeee3b58bf8e99fa976bc7faf +dist/2024-05-29/rustfmt-nightly-aarch64-apple-darwin.tar.gz=3016ced168060e3e2ba6147d3f4d13b18c76338ca80a827557b7882f168bb5ef +dist/2024-05-29/rustfmt-nightly-aarch64-apple-darwin.tar.xz=cd45818ace482132afef6b6d59d892d002a476fbad00f28182b865b56687d239 +dist/2024-05-29/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=d49c9b195f063d2268074ecf9366380a968700a007f71593b1fcd8e5324b3a28 +dist/2024-05-29/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=66209a3abe1d64c7b00d55f526045d553e782ae994520da3a0ebdcef72142eda +dist/2024-05-29/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=40f9c57aaa01f165604e47a967c2ce2af83a8c1d79f7cfa5cb737dc1513c12a0 +dist/2024-05-29/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=b5e067643239ef064de01776806de26a3d728aa9a3e2b88fb619400a6a2cf4ad +dist/2024-05-29/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=2a860e5b10568f388252eb531913aad8aa0389d37cd2af49480802773a596be2 +dist/2024-05-29/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=6587860267c67a64977275f5d16b856d934f2a683ee1a6155dbf4bc9e52dc841 +dist/2024-05-29/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=979abfded9f0758334c867f2f493ac4741f9321c8321d9f5425adba51e19e5cf +dist/2024-05-29/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=392924fe23bbe9df2723e67af3cd5aba27b176c04878c62904e97fbed9bc946d +dist/2024-05-29/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=9e809bab970bad03e9fc2bbae8302498053115a8db46a8bd617014d751d153be +dist/2024-05-29/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=8abee908fa9bfcf6e48b3e62581875ae65cc2b79b31c8df0976aa680c58e0ca8 +dist/2024-05-29/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=48a98383da0741207106ccf93414739d7dcc37b83bfbd79b3789acd1481ca7e0 +dist/2024-05-29/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=9706e65357de932a3325ed03153f455cc9af1d551a41327049c72a7a7cfd811b +dist/2024-05-29/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=eb328f79f4fa5afa2ecef6869555b5303761ef0b8fe5d69ef6eb03a01c93af9d +dist/2024-05-29/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=d5e7f54a4b972f8f6192a85e0185307406cfbcc50465a21c22d2fe64bbccc03c +dist/2024-05-29/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=b3964c1199d4cf6ed8926a5442ad95eb6c5bca8639576b5a423df0afaddf2353 +dist/2024-05-29/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=3b3711a87366e42348321efcb87b232f0cb9c68f8fef9f651893d599bbd03bf6 +dist/2024-05-29/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=2900e5fff29a5bff6bdbcd4205dd8bf5992df44534f04c1279a7cd47d050a15b +dist/2024-05-29/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=e5269da876cfbb5d0eb0ac24b34cf38e950a6904188fb4a7171f0504cbce654c +dist/2024-05-29/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=4ccb7a272765c9c59776922f0e034f2ffdc236e959d4500df9d928078016ec9c +dist/2024-05-29/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=5da7e0f39a0bb8c527f1db46c24713265ea7a3c9fb1bfaf84be6c6268ce68893 +dist/2024-05-29/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=de475ba7e107a5c144a417bb6b482b779ff954e0210c181a71a960c091a71532 +dist/2024-05-29/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=431c7d2d5a0c7bdb27dc15079c92cf71ce496978f1f2922e444da49e1b12affc +dist/2024-05-29/rustc-nightly-i686-pc-windows-gnu.tar.gz=5e08f7be71e0ba29abcc3486a727df8444b818d6e4deac4728108c25382a4cc1 +dist/2024-05-29/rustc-nightly-i686-pc-windows-gnu.tar.xz=df5b548d795cf89bc6bd6bc5608cca377e46e5829485a4f3b7d43e294e2b48d4 +dist/2024-05-29/rustc-nightly-i686-unknown-linux-gnu.tar.gz=2f2f62d57833250c2b36509e820d7d4860bfdd297f46af5eacecb6c0f27430b9 +dist/2024-05-29/rustc-nightly-i686-unknown-linux-gnu.tar.xz=d819323b185b9cb9b5fb2f1521d9f71408c026ffe345cd6b76f7ffca0917b054 +dist/2024-05-29/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=af87663dc3677d7a697192cd9f7e2e73f6825cd86109a3a1af424e39c2e20f5f +dist/2024-05-29/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=fdd0b838ff62feebfec9a7b8d516cab45568141a751641654b6ebd63165cd023 +dist/2024-05-29/rustc-nightly-aarch64-apple-darwin.tar.gz=9c328c9692688ee51fff66e43d92155752fdd67128c0f2fa3e5a642f43d7dd08 +dist/2024-05-29/rustc-nightly-aarch64-apple-darwin.tar.xz=d4f17356232fd136d2844d5888cc1425c0b942aa5ccaaf877fb8a8b357b6d4f1 +dist/2024-05-29/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=fe6533f08d7ce2e06e9fb337cdc32d865e8e00b8f91908737bc6354d3206eaf2 +dist/2024-05-29/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=dcec47a722fde1ec2eb61523a3a0efb06deed29f33e64ed1b11a01abccd20c2b +dist/2024-05-29/rustc-nightly-x86_64-unknown-netbsd.tar.gz=82f159b866d58fc7183ff923d714183f319459d9e47719551d17c8c2345ca138 +dist/2024-05-29/rustc-nightly-x86_64-unknown-netbsd.tar.xz=6bf7bcd9ba441e35bb2cc6ca2b91c8fa9dbaf72e11d57bb3371b0303701aa66c +dist/2024-05-29/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=e205ebc20e54660c7698f589f367dbed50bdbe46380b4505f96e8a90f9620c52 +dist/2024-05-29/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=8c2f2f53a77d638f36014b294dfc30d30b44899af92837d54237e7035e365d44 +dist/2024-05-29/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=dafb95b4125eb098fac7cbbf775f82247705f4ae39081966f1cc6530e47ab9eb +dist/2024-05-29/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=e450864ba5db1035016100e83e36574a50bd1037f5613abe9fb2171506458069 +dist/2024-05-29/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=79d563c9dbf525955da2f0e666b8e1d8aaed2beccf8ed400ce0ee0916892bbb1 +dist/2024-05-29/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=886cabea80578d4bddad4fd9eaeada7b7295c1a26f9d65a7466b078ce8f455e2 +dist/2024-05-29/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=96c7e311c97e0739bdb27d114e2c70b4f0300695dea7b17867b17f87609d75f4 +dist/2024-05-29/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=e59464ace28065d7b3ebc21bcde836c5cf6d7e442cb69dfb9751cf08f597958f +dist/2024-05-29/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=43016ec0b5b33c7f16cf4f4c486b0d4e3554cc7fef139a78558c177856f047ea +dist/2024-05-29/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=e74571f5b4dfb498aef90454b12ea33e927a86cc31fbfb83ab33b3e0439afa09 +dist/2024-05-29/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=7a7479cd717019f2e18cb022d96deb5d27c554cf411920d04229f940fbc7226c +dist/2024-05-29/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=bbd708d94f94da90010eb574aac0fed82490989a3f4b3b66e51d65526e0b3629 +dist/2024-05-29/rustc-nightly-x86_64-unknown-illumos.tar.gz=f60e5f253ce5f17631620a5ed99873e6067d65a547dfbb0ea751e7b151cdf971 +dist/2024-05-29/rustc-nightly-x86_64-unknown-illumos.tar.xz=71448313016bd45a7bbf083207a5f334c1a921b8a68bc9618cb4644c7e134716 +dist/2024-05-29/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=69c481a820c25d7b59d3d63081e93f9784c00cc4efd301fb5b9680b3166e2d9b +dist/2024-05-29/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=3a33c45bce9fcc91730bfed44db0c1781f9a6c8c0a4382af775f4c9b638ee5a7 +dist/2024-05-29/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=d8d12e8b1f70353fd9b84ebea1ccb3a0f4bb561e99283c77ccb970ad6838cd19 +dist/2024-05-29/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=2890c1e4eb5eb0cfb57cf947088c43efd11e5e071bdb6191609639d541244394 +dist/2024-05-29/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=0ba52772ae17e47cabd816980f0cb22bd25254ccc213da6a968bd8e635607c4c +dist/2024-05-29/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=4da826ffedd6468d336d97722b20f8ba49cbe7d77c7667addab19c39f731dd69 +dist/2024-05-29/rustc-nightly-x86_64-unknown-freebsd.tar.gz=463bd6103900d486e874195bd65646265449333dd5dd5f007cc57120289a5553 +dist/2024-05-29/rustc-nightly-x86_64-unknown-freebsd.tar.xz=0f4b1b482056ca489e9e74c634b733d1903ac0e6196506e635cc7edd6dc8f4d0 +dist/2024-05-29/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=42b41b32eceec839cedf88ffea93c99b04ee4bc9ce095e0872bfe3a67a6f6421 +dist/2024-05-29/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=644896626ec0177c21ab549eff85fcf28d307848454055b4e43909455df51b01 +dist/2024-05-29/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=43698606a91a090ebdcd6ab5f40f8d62fc0d653eaec74ab851438abe7da8a89e +dist/2024-05-29/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=19b759811b9193c7b0d710b18427d7324c7ca4dafeca5d7cfebb6686761f9e67 +dist/2024-05-29/rustc-nightly-i686-pc-windows-msvc.tar.gz=c52226e19cff041f23552589f872399723d4c6d6514db93c2d6201f70f36e013 +dist/2024-05-29/rustc-nightly-i686-pc-windows-msvc.tar.xz=49c5b9d7551462e29ef4a036b3a6dd8905455256aff636b4fd4defc516d62e3f +dist/2024-05-29/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=b04be4f9b1eaf4bb5e9a2a544614ac99f466d5925108633fb8c5b700e7aece7b +dist/2024-05-29/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=8638b2106fbf7e5dc6837caaf07af1750b6aa24dc845e22a35d8e8e53584b2d6 +dist/2024-05-29/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=99710480631e11119640f6955257838648db572c4ed0d8d1b0081bace32313b0 +dist/2024-05-29/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=daab5b6364ad2afe80c96e8d905160e75c0783192296e88fd2b639c49b09d829 +dist/2024-05-29/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=0f6e0e64bbe42aae577cc0cb87d81ecb64a21c745277872177025611993c47a0 +dist/2024-05-29/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=fd45d7b870257bce91a33f5b971b11e0c6743e1c03eaa3c26bd201fe9be0c083 +dist/2024-05-29/rustc-nightly-x86_64-apple-darwin.tar.gz=29c34129ce3fef647140a0302fa1699af5460dab518b56d6a2257c7d7c288487 +dist/2024-05-29/rustc-nightly-x86_64-apple-darwin.tar.xz=fdf25c965c5218fad6e2949da8df88eeb9f886a8f5b9c72ec9d79a993c4829c6 \ No newline at end of file From a8234d5f8729fd78a76641bc341519941bfb14aa Mon Sep 17 00:00:00 2001 From: John Millikin Date: Thu, 30 May 2024 08:40:48 +0900 Subject: [PATCH 085/211] Fix copy-paste error in `Duration::from_weeks` panic message. --- library/core/src/time.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/time.rs b/library/core/src/time.rs index 89202e7bb8dd..dfa58e4f46d0 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -348,7 +348,7 @@ impl Duration { #[inline] pub const fn from_weeks(weeks: u64) -> Duration { if weeks > u64::MAX / (SECS_PER_MINUTE * MINS_PER_HOUR * HOURS_PER_DAY * DAYS_PER_WEEK) { - panic!("overflow in Duration::from_days"); + panic!("overflow in Duration::from_weeks"); } Duration::from_secs(weeks * MINS_PER_HOUR * SECS_PER_MINUTE * HOURS_PER_DAY * DAYS_PER_WEEK) From 5fa0ec6ad17cd002e9359345bbeae4601c03fd53 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 30 Apr 2023 20:48:29 +0000 Subject: [PATCH 086/211] Enable DestinationPropagation by default. --- compiler/rustc_mir_transform/src/dest_prop.rs | 2 +- compiler/rustc_mir_transform/src/lib.rs | 4 +- compiler/rustc_mir_transform/src/nrvo.rs | 235 ------------------ ...o.DestinationPropagation.panic-abort.diff} | 31 +-- ....DestinationPropagation.panic-unwind.diff} | 31 +-- .../nrvo_borrowed.rs} | 4 +- .../{ => dest-prop}/nrvo_miscompile_111005.rs | 4 +- ..._111005.wrong.DestinationPropagation.diff} | 7 +- ...in.DestinationPropagation.panic-abort.diff | 2 +- ...n.DestinationPropagation.panic-unwind.diff | 2 +- ....{impl#0}-partial_cmp.PreCodegen.after.mir | 32 ++- ...ward_loop.PreCodegen.after.panic-abort.mir | 64 +++-- ...ard_loop.PreCodegen.after.panic-unwind.mir | 64 +++-- ...ated_loop.PreCodegen.after.panic-abort.mir | 80 +++--- ...ted_loop.PreCodegen.after.panic-unwind.mir | 80 +++--- ...ward_loop.PreCodegen.after.panic-abort.mir | 66 +++-- ...ard_loop.PreCodegen.after.panic-unwind.mir | 66 +++-- ...ange_loop.PreCodegen.after.panic-abort.mir | 56 ++--- ...nge_loop.PreCodegen.after.panic-unwind.mir | 56 ++--- ...erse_loop.PreCodegen.after.panic-abort.mir | 74 +++--- ...rse_loop.PreCodegen.after.panic-unwind.mir | 74 +++--- 21 files changed, 373 insertions(+), 661 deletions(-) delete mode 100644 compiler/rustc_mir_transform/src/nrvo.rs rename tests/mir-opt/{nrvo_simple.nrvo.RenameReturnPlace.panic-abort.diff => dest-prop/nrvo_borrowed.nrvo.DestinationPropagation.panic-abort.diff} (53%) rename tests/mir-opt/{nrvo_simple.nrvo.RenameReturnPlace.panic-unwind.diff => dest-prop/nrvo_borrowed.nrvo.DestinationPropagation.panic-unwind.diff} (53%) rename tests/mir-opt/{nrvo_simple.rs => dest-prop/nrvo_borrowed.rs} (68%) rename tests/mir-opt/{ => dest-prop}/nrvo_miscompile_111005.rs (78%) rename tests/mir-opt/{nrvo_miscompile_111005.wrong.RenameReturnPlace.diff => dest-prop/nrvo_miscompile_111005.wrong.DestinationPropagation.diff} (60%) diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index b1016c0867c6..f0778594353d 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -160,7 +160,7 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation { // 2. Despite being an overall perf improvement, this still causes a 30% regression in // keccak. We can temporarily fix this by bounding function size, but in the long term // we should fix this by being smarter about invalidating analysis results. - sess.mir_opt_level() >= 3 + sess.mir_opt_level() >= 2 } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 93ae105150cc..ea033b70df8d 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -88,7 +88,6 @@ mod match_branches; mod mentioned_items; mod multiple_return_terminators; mod normalize_array_len; -mod nrvo; mod prettify; mod promote_consts; mod ref_prop; @@ -607,13 +606,12 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { &jump_threading::JumpThreading, &early_otherwise_branch::EarlyOtherwiseBranch, &simplify_comparison_integral::SimplifyComparisonIntegral, - &dest_prop::DestinationPropagation, &o1(simplify_branches::SimplifyConstCondition::Final), &o1(remove_noop_landing_pads::RemoveNoopLandingPads), &o1(simplify::SimplifyCfg::Final), ©_prop::CopyProp, &dead_store_elimination::DeadStoreElimination::Final, - &nrvo::RenameReturnPlace, + &dest_prop::DestinationPropagation, &simplify::SimplifyLocals::Final, &multiple_return_terminators::MultipleReturnTerminators, &deduplicate_blocks::DeduplicateBlocks, diff --git a/compiler/rustc_mir_transform/src/nrvo.rs b/compiler/rustc_mir_transform/src/nrvo.rs deleted file mode 100644 index 885dbd5f3393..000000000000 --- a/compiler/rustc_mir_transform/src/nrvo.rs +++ /dev/null @@ -1,235 +0,0 @@ -//! See the docs for [`RenameReturnPlace`]. - -use rustc_hir::Mutability; -use rustc_index::bit_set::BitSet; -use rustc_middle::bug; -use rustc_middle::mir::visit::{MutVisitor, NonUseContext, PlaceContext, Visitor}; -use rustc_middle::mir::{self, BasicBlock, Local, Location}; -use rustc_middle::ty::TyCtxt; - -use crate::MirPass; - -/// This pass looks for MIR that always copies the same local into the return place and eliminates -/// the copy by renaming all uses of that local to `_0`. -/// -/// This allows LLVM to perform an optimization similar to the named return value optimization -/// (NRVO) that is guaranteed in C++. This avoids a stack allocation and `memcpy` for the -/// relatively common pattern of allocating a buffer on the stack, mutating it, and returning it by -/// value like so: -/// -/// ```rust -/// fn foo(init: fn(&mut [u8; 1024])) -> [u8; 1024] { -/// let mut buf = [0; 1024]; -/// init(&mut buf); -/// buf -/// } -/// ``` -/// -/// For now, this pass is very simple and only capable of eliminating a single copy. A more general -/// version of copy propagation, such as the one based on non-overlapping live ranges in [#47954] and -/// [#71003], could yield even more benefits. -/// -/// [#47954]: https://github.com/rust-lang/rust/pull/47954 -/// [#71003]: https://github.com/rust-lang/rust/pull/71003 -pub struct RenameReturnPlace; - -impl<'tcx> MirPass<'tcx> for RenameReturnPlace { - fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - // unsound: #111005 - sess.mir_opt_level() > 0 && sess.opts.unstable_opts.unsound_mir_opts - } - - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut mir::Body<'tcx>) { - let def_id = body.source.def_id(); - let Some(returned_local) = local_eligible_for_nrvo(body) else { - debug!("`{:?}` was ineligible for NRVO", def_id); - return; - }; - - if !tcx.consider_optimizing(|| format!("RenameReturnPlace {def_id:?}")) { - return; - } - - debug!( - "`{:?}` was eligible for NRVO, making {:?} the return place", - def_id, returned_local - ); - - RenameToReturnPlace { tcx, to_rename: returned_local }.visit_body_preserves_cfg(body); - - // Clean up the `NOP`s we inserted for statements made useless by our renaming. - for block_data in body.basic_blocks.as_mut_preserves_cfg() { - block_data.statements.retain(|stmt| stmt.kind != mir::StatementKind::Nop); - } - - // Overwrite the debuginfo of `_0` with that of the renamed local. - let (renamed_decl, ret_decl) = - body.local_decls.pick2_mut(returned_local, mir::RETURN_PLACE); - - // Sometimes, the return place is assigned a local of a different but coercible type, for - // example `&mut T` instead of `&T`. Overwriting the `LocalInfo` for the return place means - // its type may no longer match the return type of its function. This doesn't cause a - // problem in codegen because these two types are layout-compatible, but may be unexpected. - debug!("_0: {:?} = {:?}: {:?}", ret_decl.ty, returned_local, renamed_decl.ty); - ret_decl.clone_from(renamed_decl); - - // The return place is always mutable. - ret_decl.mutability = Mutability::Mut; - } -} - -/// MIR that is eligible for the NRVO must fulfill two conditions: -/// 1. The return place must not be read prior to the `Return` terminator. -/// 2. A simple assignment of a whole local to the return place (e.g., `_0 = _1`) must be the -/// only definition of the return place reaching the `Return` terminator. -/// -/// If the MIR fulfills both these conditions, this function returns the `Local` that is assigned -/// to the return place along all possible paths through the control-flow graph. -fn local_eligible_for_nrvo(body: &mir::Body<'_>) -> Option { - if IsReturnPlaceRead::run(body) { - return None; - } - - let mut copied_to_return_place = None; - for block in body.basic_blocks.indices() { - // Look for blocks with a `Return` terminator. - if !matches!(body[block].terminator().kind, mir::TerminatorKind::Return) { - continue; - } - - // Look for an assignment of a single local to the return place prior to the `Return`. - let returned_local = find_local_assigned_to_return_place(block, body)?; - match body.local_kind(returned_local) { - // FIXME: Can we do this for arguments as well? - mir::LocalKind::Arg => return None, - - mir::LocalKind::ReturnPointer => bug!("Return place was assigned to itself?"), - mir::LocalKind::Temp => {} - } - - // If multiple different locals are copied to the return place. We can't pick a - // single one to rename. - if copied_to_return_place.is_some_and(|old| old != returned_local) { - return None; - } - - copied_to_return_place = Some(returned_local); - } - - copied_to_return_place -} - -fn find_local_assigned_to_return_place(start: BasicBlock, body: &mir::Body<'_>) -> Option { - let mut block = start; - let mut seen = BitSet::new_empty(body.basic_blocks.len()); - - // Iterate as long as `block` has exactly one predecessor that we have not yet visited. - while seen.insert(block) { - trace!("Looking for assignments to `_0` in {:?}", block); - - let local = body[block].statements.iter().rev().find_map(as_local_assigned_to_return_place); - if local.is_some() { - return local; - } - - match body.basic_blocks.predecessors()[block].as_slice() { - &[pred] => block = pred, - _ => return None, - } - } - - None -} - -// If this statement is an assignment of an unprojected local to the return place, -// return that local. -fn as_local_assigned_to_return_place(stmt: &mir::Statement<'_>) -> Option { - if let mir::StatementKind::Assign(box (lhs, rhs)) = &stmt.kind { - if lhs.as_local() == Some(mir::RETURN_PLACE) { - if let mir::Rvalue::Use(mir::Operand::Copy(rhs) | mir::Operand::Move(rhs)) = rhs { - return rhs.as_local(); - } - } - } - - None -} - -struct RenameToReturnPlace<'tcx> { - to_rename: Local, - tcx: TyCtxt<'tcx>, -} - -/// Replaces all uses of `self.to_rename` with `_0`. -impl<'tcx> MutVisitor<'tcx> for RenameToReturnPlace<'tcx> { - fn tcx(&self) -> TyCtxt<'tcx> { - self.tcx - } - - fn visit_statement(&mut self, stmt: &mut mir::Statement<'tcx>, loc: Location) { - // Remove assignments of the local being replaced to the return place, since it is now the - // return place: - // _0 = _1 - if as_local_assigned_to_return_place(stmt) == Some(self.to_rename) { - stmt.kind = mir::StatementKind::Nop; - return; - } - - // Remove storage annotations for the local being replaced: - // StorageLive(_1) - if let mir::StatementKind::StorageLive(local) | mir::StatementKind::StorageDead(local) = - stmt.kind - { - if local == self.to_rename { - stmt.kind = mir::StatementKind::Nop; - return; - } - } - - self.super_statement(stmt, loc) - } - - fn visit_terminator(&mut self, terminator: &mut mir::Terminator<'tcx>, loc: Location) { - // Ignore the implicit "use" of the return place in a `Return` statement. - if let mir::TerminatorKind::Return = terminator.kind { - return; - } - - self.super_terminator(terminator, loc); - } - - fn visit_local(&mut self, l: &mut Local, ctxt: PlaceContext, _: Location) { - if *l == mir::RETURN_PLACE { - assert_eq!(ctxt, PlaceContext::NonUse(NonUseContext::VarDebugInfo)); - } else if *l == self.to_rename { - *l = mir::RETURN_PLACE; - } - } -} - -struct IsReturnPlaceRead(bool); - -impl IsReturnPlaceRead { - fn run(body: &mir::Body<'_>) -> bool { - let mut vis = IsReturnPlaceRead(false); - vis.visit_body(body); - vis.0 - } -} - -impl<'tcx> Visitor<'tcx> for IsReturnPlaceRead { - fn visit_local(&mut self, l: Local, ctxt: PlaceContext, _: Location) { - if l == mir::RETURN_PLACE && ctxt.is_use() && !ctxt.is_place_assignment() { - self.0 = true; - } - } - - fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, loc: Location) { - // Ignore the implicit "use" of the return place in a `Return` statement. - if let mir::TerminatorKind::Return = terminator.kind { - return; - } - - self.super_terminator(terminator, loc); - } -} diff --git a/tests/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.panic-abort.diff b/tests/mir-opt/dest-prop/nrvo_borrowed.nrvo.DestinationPropagation.panic-abort.diff similarity index 53% rename from tests/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.panic-abort.diff rename to tests/mir-opt/dest-prop/nrvo_borrowed.nrvo.DestinationPropagation.panic-abort.diff index f7bc5559ab7b..4d34f43fd5ce 100644 --- a/tests/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.panic-abort.diff +++ b/tests/mir-opt/dest-prop/nrvo_borrowed.nrvo.DestinationPropagation.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `nrvo` before RenameReturnPlace -+ // MIR for `nrvo` after RenameReturnPlace +- // MIR for `nrvo` before DestinationPropagation ++ // MIR for `nrvo` after DestinationPropagation fn nrvo(_1: for<'a> fn(&'a mut [u8; 1024])) -> [u8; 1024] { debug init => _1; @@ -10,32 +10,33 @@ let mut _5: &mut [u8; 1024]; let mut _6: &mut [u8; 1024]; scope 1 { -- debug buf => _2; -+ debug buf => _0; + debug buf => _2; } bb0: { -- StorageLive(_2); -- _2 = [const 0_u8; 1024]; -+ _0 = [const 0_u8; 1024]; + StorageLive(_2); + _2 = [const 0_u8; 1024]; StorageLive(_3); - StorageLive(_4); - _4 = _1; +- StorageLive(_4); +- _4 = _1; ++ nop; ++ nop; StorageLive(_5); StorageLive(_6); -- _6 = &mut _2; -+ _6 = &mut _0; + _6 = &mut _2; _5 = &mut (*_6); - _3 = move _4(move _5) -> [return: bb1, unwind unreachable]; +- _3 = move _4(move _5) -> [return: bb1, unwind unreachable]; ++ _3 = move _1(move _5) -> [return: bb1, unwind unreachable]; } bb1: { StorageDead(_5); - StorageDead(_4); +- StorageDead(_4); ++ nop; StorageDead(_6); StorageDead(_3); -- _0 = _2; -- StorageDead(_2); + _0 = _2; + StorageDead(_2); return; } } diff --git a/tests/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.panic-unwind.diff b/tests/mir-opt/dest-prop/nrvo_borrowed.nrvo.DestinationPropagation.panic-unwind.diff similarity index 53% rename from tests/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.panic-unwind.diff rename to tests/mir-opt/dest-prop/nrvo_borrowed.nrvo.DestinationPropagation.panic-unwind.diff index 3df8e567f1fe..9c3cbef38d69 100644 --- a/tests/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.panic-unwind.diff +++ b/tests/mir-opt/dest-prop/nrvo_borrowed.nrvo.DestinationPropagation.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `nrvo` before RenameReturnPlace -+ // MIR for `nrvo` after RenameReturnPlace +- // MIR for `nrvo` before DestinationPropagation ++ // MIR for `nrvo` after DestinationPropagation fn nrvo(_1: for<'a> fn(&'a mut [u8; 1024])) -> [u8; 1024] { debug init => _1; @@ -10,32 +10,33 @@ let mut _5: &mut [u8; 1024]; let mut _6: &mut [u8; 1024]; scope 1 { -- debug buf => _2; -+ debug buf => _0; + debug buf => _2; } bb0: { -- StorageLive(_2); -- _2 = [const 0_u8; 1024]; -+ _0 = [const 0_u8; 1024]; + StorageLive(_2); + _2 = [const 0_u8; 1024]; StorageLive(_3); - StorageLive(_4); - _4 = _1; +- StorageLive(_4); +- _4 = _1; ++ nop; ++ nop; StorageLive(_5); StorageLive(_6); -- _6 = &mut _2; -+ _6 = &mut _0; + _6 = &mut _2; _5 = &mut (*_6); - _3 = move _4(move _5) -> [return: bb1, unwind continue]; +- _3 = move _4(move _5) -> [return: bb1, unwind continue]; ++ _3 = move _1(move _5) -> [return: bb1, unwind continue]; } bb1: { StorageDead(_5); - StorageDead(_4); +- StorageDead(_4); ++ nop; StorageDead(_6); StorageDead(_3); -- _0 = _2; -- StorageDead(_2); + _0 = _2; + StorageDead(_2); return; } } diff --git a/tests/mir-opt/nrvo_simple.rs b/tests/mir-opt/dest-prop/nrvo_borrowed.rs similarity index 68% rename from tests/mir-opt/nrvo_simple.rs rename to tests/mir-opt/dest-prop/nrvo_borrowed.rs index 5d2894a704a5..405423f24624 100644 --- a/tests/mir-opt/nrvo_simple.rs +++ b/tests/mir-opt/dest-prop/nrvo_borrowed.rs @@ -1,8 +1,8 @@ // skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY -//@ test-mir-pass: RenameReturnPlace +//@ test-mir-pass: DestinationPropagation -// EMIT_MIR nrvo_simple.nrvo.RenameReturnPlace.diff +// EMIT_MIR nrvo_borrowed.nrvo.DestinationPropagation.diff fn nrvo(init: fn(&mut [u8; 1024])) -> [u8; 1024] { let mut buf = [0; 1024]; init(&mut buf); diff --git a/tests/mir-opt/nrvo_miscompile_111005.rs b/tests/mir-opt/dest-prop/nrvo_miscompile_111005.rs similarity index 78% rename from tests/mir-opt/nrvo_miscompile_111005.rs rename to tests/mir-opt/dest-prop/nrvo_miscompile_111005.rs index 18814b0678fe..faf30cfd1b01 100644 --- a/tests/mir-opt/nrvo_miscompile_111005.rs +++ b/tests/mir-opt/dest-prop/nrvo_miscompile_111005.rs @@ -1,13 +1,13 @@ // skip-filecheck // This is a miscompilation, #111005 to track -//@ test-mir-pass: RenameReturnPlace +//@ test-mir-pass: DestinationPropagation #![feature(custom_mir, core_intrinsics)] extern crate core; use core::intrinsics::mir::*; -// EMIT_MIR nrvo_miscompile_111005.wrong.RenameReturnPlace.diff +// EMIT_MIR nrvo_miscompile_111005.wrong.DestinationPropagation.diff #[custom_mir(dialect = "runtime", phase = "initial")] pub fn wrong(arg: char) -> char { mir!({ diff --git a/tests/mir-opt/nrvo_miscompile_111005.wrong.RenameReturnPlace.diff b/tests/mir-opt/dest-prop/nrvo_miscompile_111005.wrong.DestinationPropagation.diff similarity index 60% rename from tests/mir-opt/nrvo_miscompile_111005.wrong.RenameReturnPlace.diff rename to tests/mir-opt/dest-prop/nrvo_miscompile_111005.wrong.DestinationPropagation.diff index 260b472daa92..afacf5c14966 100644 --- a/tests/mir-opt/nrvo_miscompile_111005.wrong.RenameReturnPlace.diff +++ b/tests/mir-opt/dest-prop/nrvo_miscompile_111005.wrong.DestinationPropagation.diff @@ -1,5 +1,5 @@ -- // MIR for `wrong` before RenameReturnPlace -+ // MIR for `wrong` after RenameReturnPlace +- // MIR for `wrong` before DestinationPropagation ++ // MIR for `wrong` after DestinationPropagation fn wrong(_1: char) -> char { let mut _0: char; @@ -9,8 +9,9 @@ - _2 = _1; - _0 = _2; - _2 = const 'b'; ++ nop; + _0 = _1; -+ _0 = const 'b'; ++ _1 = const 'b'; return; } } diff --git a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff index 570ec129f06e..b596e25ddfdf 100644 --- a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff +++ b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff @@ -18,7 +18,7 @@ bb0: { StorageLive(_1); StorageLive(_2); - _2 = const 1_u32; + nop; _1 = Un { us: const 1_u32 }; StorageDead(_2); StorageLive(_3); diff --git a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff index 570ec129f06e..b596e25ddfdf 100644 --- a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff +++ b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff @@ -18,7 +18,7 @@ bb0: { StorageLive(_1); StorageLive(_2); - _2 = const 1_u32; + nop; _1 = Un { us: const 1_u32 }; StorageDead(_2); StorageLive(_3); diff --git a/tests/mir-opt/pre-codegen/derived_ord.{impl#0}-partial_cmp.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/derived_ord.{impl#0}-partial_cmp.PreCodegen.after.mir index 47f10451b057..b58e05f93688 100644 --- a/tests/mir-opt/pre-codegen/derived_ord.{impl#0}-partial_cmp.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/derived_ord.{impl#0}-partial_cmp.PreCodegen.after.mir @@ -4,10 +4,9 @@ fn ::partial_cmp(_1: &MultiField, _2: &M debug self => _1; debug other => _2; let mut _0: std::option::Option; - let mut _6: std::option::Option; - let mut _7: i8; + let mut _6: i8; scope 1 { - debug cmp => _6; + debug cmp => _0; } scope 2 (inlined std::cmp::impls::::partial_cmp) { let mut _3: char; @@ -15,9 +14,9 @@ fn ::partial_cmp(_1: &MultiField, _2: &M let mut _5: std::cmp::Ordering; } scope 3 (inlined std::cmp::impls::::partial_cmp) { + let mut _7: i16; let mut _8: i16; - let mut _9: i16; - let mut _10: std::cmp::Ordering; + let mut _9: std::cmp::Ordering; } bb0: { @@ -28,27 +27,26 @@ fn ::partial_cmp(_1: &MultiField, _2: &M _5 = Cmp(move _3, move _4); StorageDead(_4); StorageDead(_3); - _6 = Option::::Some(_5); - _7 = discriminant(_5); - switchInt(move _7) -> [0: bb1, otherwise: bb2]; + _0 = Option::::Some(_5); + _6 = discriminant(_5); + switchInt(move _6) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_10); - StorageLive(_8); - _8 = ((*_1).1: i16); StorageLive(_9); - _9 = ((*_2).1: i16); - _10 = Cmp(move _8, move _9); - StorageDead(_9); + StorageLive(_7); + _7 = ((*_1).1: i16); + StorageLive(_8); + _8 = ((*_2).1: i16); + _9 = Cmp(move _7, move _8); StorageDead(_8); - _0 = Option::::Some(move _10); - StorageDead(_10); + StorageDead(_7); + _0 = Option::::Some(move _9); + StorageDead(_9); goto -> bb3; } bb2: { - _0 = _6; goto -> bb3; } diff --git a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir index 96b4962854de..163279c1c334 100644 --- a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir @@ -5,27 +5,25 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { debug end => _2; debug f => _3; let mut _0: (); - let mut _4: u32; - let mut _9: std::option::Option; - let mut _11: &impl Fn(u32); - let mut _12: (u32,); - let _13: (); + let mut _7: std::option::Option; + let mut _9: &impl Fn(u32); + let mut _10: (u32,); + let _11: (); scope 1 { - debug ((iter: std::ops::Range).0: u32) => _4; + debug ((iter: std::ops::Range).0: u32) => _1; debug ((iter: std::ops::Range).1: u32) => _2; - let _10: u32; + let _8: u32; scope 2 { - debug x => _10; + debug x => _8; } scope 4 (inlined iter::range::>::next) { scope 5 (inlined as iter::range::RangeIteratorImpl>::spec_next) { - let mut _6: bool; - let _7: u32; - let mut _8: u32; + let mut _5: bool; + let _6: u32; scope 6 { } scope 7 (inlined std::cmp::impls::::lt) { - let mut _5: u32; + let mut _4: u32; } } } @@ -34,27 +32,24 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { } bb0: { - StorageLive(_4); - _4 = _1; goto -> bb1; } bb1: { - StorageLive(_9); StorageLive(_7); StorageLive(_6); StorageLive(_5); - _5 = _4; - _6 = Lt(move _5, _2); - StorageDead(_5); - switchInt(move _6) -> [0: bb2, otherwise: bb4]; + StorageLive(_4); + _4 = _1; + _5 = Lt(move _4, _2); + StorageDead(_4); + switchInt(move _5) -> [0: bb2, otherwise: bb4]; } bb2: { + StorageDead(_5); StorageDead(_6); StorageDead(_7); - StorageDead(_9); - StorageDead(_4); drop(_3) -> [return: bb3, unwind unreachable]; } @@ -63,29 +58,26 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { } bb4: { - _7 = _4; - StorageLive(_8); - _8 = ::forward_unchecked(_7, const 1_usize) -> [return: bb5, unwind unreachable]; + _6 = _1; + _1 = ::forward_unchecked(_6, const 1_usize) -> [return: bb5, unwind unreachable]; } bb5: { - _4 = move _8; - StorageDead(_8); - _9 = Option::::Some(_7); + _7 = Option::::Some(_6); + StorageDead(_5); StorageDead(_6); - StorageDead(_7); - _10 = ((_9 as Some).0: u32); - StorageLive(_11); - _11 = &_3; - StorageLive(_12); - _12 = (_10,); - _13 = >::call(move _11, move _12) -> [return: bb6, unwind unreachable]; + _8 = ((_7 as Some).0: u32); + StorageLive(_9); + _9 = &_3; + StorageLive(_10); + _10 = (_8,); + _11 = >::call(move _9, move _10) -> [return: bb6, unwind unreachable]; } bb6: { - StorageDead(_12); - StorageDead(_11); + StorageDead(_10); StorageDead(_9); + StorageDead(_7); goto -> bb1; } } diff --git a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir index ce8e2bd083ed..05f72ade9249 100644 --- a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir @@ -5,27 +5,25 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { debug end => _2; debug f => _3; let mut _0: (); - let mut _4: u32; - let mut _9: std::option::Option; - let mut _11: &impl Fn(u32); - let mut _12: (u32,); - let _13: (); + let mut _7: std::option::Option; + let mut _9: &impl Fn(u32); + let mut _10: (u32,); + let _11: (); scope 1 { - debug ((iter: std::ops::Range).0: u32) => _4; + debug ((iter: std::ops::Range).0: u32) => _1; debug ((iter: std::ops::Range).1: u32) => _2; - let _10: u32; + let _8: u32; scope 2 { - debug x => _10; + debug x => _8; } scope 4 (inlined iter::range::>::next) { scope 5 (inlined as iter::range::RangeIteratorImpl>::spec_next) { - let mut _6: bool; - let _7: u32; - let mut _8: u32; + let mut _5: bool; + let _6: u32; scope 6 { } scope 7 (inlined std::cmp::impls::::lt) { - let mut _5: u32; + let mut _4: u32; } } } @@ -34,27 +32,24 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { } bb0: { - StorageLive(_4); - _4 = _1; goto -> bb1; } bb1: { - StorageLive(_9); StorageLive(_7); StorageLive(_6); StorageLive(_5); - _5 = _4; - _6 = Lt(move _5, _2); - StorageDead(_5); - switchInt(move _6) -> [0: bb2, otherwise: bb4]; + StorageLive(_4); + _4 = _1; + _5 = Lt(move _4, _2); + StorageDead(_4); + switchInt(move _5) -> [0: bb2, otherwise: bb4]; } bb2: { + StorageDead(_5); StorageDead(_6); StorageDead(_7); - StorageDead(_9); - StorageDead(_4); drop(_3) -> [return: bb3, unwind continue]; } @@ -63,29 +58,26 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { } bb4: { - _7 = _4; - StorageLive(_8); - _8 = ::forward_unchecked(_7, const 1_usize) -> [return: bb5, unwind: bb7]; + _6 = _1; + _1 = ::forward_unchecked(_6, const 1_usize) -> [return: bb5, unwind: bb7]; } bb5: { - _4 = move _8; - StorageDead(_8); - _9 = Option::::Some(_7); + _7 = Option::::Some(_6); + StorageDead(_5); StorageDead(_6); - StorageDead(_7); - _10 = ((_9 as Some).0: u32); - StorageLive(_11); - _11 = &_3; - StorageLive(_12); - _12 = (_10,); - _13 = >::call(move _11, move _12) -> [return: bb6, unwind: bb7]; + _8 = ((_7 as Some).0: u32); + StorageLive(_9); + _9 = &_3; + StorageLive(_10); + _10 = (_8,); + _11 = >::call(move _9, move _10) -> [return: bb6, unwind: bb7]; } bb6: { - StorageDead(_12); - StorageDead(_11); + StorageDead(_10); StorageDead(_9); + StorageDead(_7); goto -> bb1; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir index d979c5ec1d5a..e761dc1e8b83 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir @@ -4,22 +4,22 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _12: std::slice::Iter<'_, T>; + let mut _11: std::slice::Iter<'_, T>; + let mut _12: std::iter::Enumerate>; let mut _13: std::iter::Enumerate>; - let mut _14: std::iter::Enumerate>; - let mut _15: &mut std::iter::Enumerate>; - let mut _16: std::option::Option<(usize, &T)>; - let mut _17: isize; - let mut _20: &impl Fn(usize, &T); - let mut _21: (usize, &T); - let _22: (); + let mut _14: &mut std::iter::Enumerate>; + let mut _15: std::option::Option<(usize, &T)>; + let mut _16: isize; + let mut _19: &impl Fn(usize, &T); + let mut _20: (usize, &T); + let _21: (); scope 1 { - debug iter => _14; - let _18: usize; - let _19: &T; + debug iter => _13; + let _17: usize; + let _18: &T; scope 2 { - debug i => _18; - debug x => _19; + debug i => _17; + debug x => _18; } } scope 3 (inlined core::slice::::iter) { @@ -28,11 +28,10 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { let mut _7: bool; let mut _8: *mut T; let mut _9: *mut T; - let mut _11: *const T; + let mut _10: *const T; scope 5 { let _6: std::ptr::NonNull; scope 6 { - let _10: *const T; scope 7 { } scope 11 (inlined without_provenance::) { @@ -61,16 +60,16 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb0: { - StorageLive(_12); + StorageLive(_11); StorageLive(_3); StorageLive(_6); + StorageLive(_10); StorageLive(_4); StorageLive(_5); _3 = Len((*_1)); _4 = &raw const (*_1); _5 = _4 as *const T (PtrToPtr); _6 = NonNull:: { pointer: _5 }; - StorageLive(_10); StorageLive(_7); _7 = const ::IS_ZST; switchInt(move _7) -> [0: bb1, otherwise: bb2]; @@ -94,38 +93,35 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { bb3: { StorageDead(_7); - StorageLive(_11); - _11 = _10; - _12 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _11, _marker: const ZeroSized: PhantomData<&T> }; - StorageDead(_11); - StorageDead(_10); + _11 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> }; StorageDead(_5); StorageDead(_4); + StorageDead(_10); StorageDead(_6); StorageDead(_3); - _13 = Enumerate::> { iter: _12, count: const 0_usize }; - StorageDead(_12); - StorageLive(_14); - _14 = _13; + _12 = Enumerate::> { iter: _11, count: const 0_usize }; + StorageDead(_11); + StorageLive(_13); + _13 = _12; goto -> bb4; } bb4: { - StorageLive(_16); StorageLive(_15); - _15 = &mut _14; - _16 = > as Iterator>::next(move _15) -> [return: bb5, unwind unreachable]; + StorageLive(_14); + _14 = &mut _13; + _15 = > as Iterator>::next(move _14) -> [return: bb5, unwind unreachable]; } bb5: { - StorageDead(_15); - _17 = discriminant(_16); - switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_14); + _16 = discriminant(_15); + switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_16); - StorageDead(_14); + StorageDead(_15); + StorageDead(_13); drop(_2) -> [return: bb7, unwind unreachable]; } @@ -134,19 +130,19 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb8: { - _18 = (((_16 as Some).0: (usize, &T)).0: usize); - _19 = (((_16 as Some).0: (usize, &T)).1: &T); + _17 = (((_15 as Some).0: (usize, &T)).0: usize); + _18 = (((_15 as Some).0: (usize, &T)).1: &T); + StorageLive(_19); + _19 = &_2; StorageLive(_20); - _20 = &_2; - StorageLive(_21); - _21 = (_18, _19); - _22 = >::call(move _20, move _21) -> [return: bb9, unwind unreachable]; + _20 = (_17, _18); + _21 = >::call(move _19, move _20) -> [return: bb9, unwind unreachable]; } bb9: { - StorageDead(_21); StorageDead(_20); - StorageDead(_16); + StorageDead(_19); + StorageDead(_15); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir index 8491c49f7673..da293cdb5a17 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir @@ -4,22 +4,22 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _12: std::slice::Iter<'_, T>; + let mut _11: std::slice::Iter<'_, T>; + let mut _12: std::iter::Enumerate>; let mut _13: std::iter::Enumerate>; - let mut _14: std::iter::Enumerate>; - let mut _15: &mut std::iter::Enumerate>; - let mut _16: std::option::Option<(usize, &T)>; - let mut _17: isize; - let mut _20: &impl Fn(usize, &T); - let mut _21: (usize, &T); - let _22: (); + let mut _14: &mut std::iter::Enumerate>; + let mut _15: std::option::Option<(usize, &T)>; + let mut _16: isize; + let mut _19: &impl Fn(usize, &T); + let mut _20: (usize, &T); + let _21: (); scope 1 { - debug iter => _14; - let _18: usize; - let _19: &T; + debug iter => _13; + let _17: usize; + let _18: &T; scope 2 { - debug i => _18; - debug x => _19; + debug i => _17; + debug x => _18; } } scope 3 (inlined core::slice::::iter) { @@ -28,11 +28,10 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { let mut _7: bool; let mut _8: *mut T; let mut _9: *mut T; - let mut _11: *const T; + let mut _10: *const T; scope 5 { let _6: std::ptr::NonNull; scope 6 { - let _10: *const T; scope 7 { } scope 11 (inlined without_provenance::) { @@ -61,16 +60,16 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb0: { - StorageLive(_12); + StorageLive(_11); StorageLive(_3); StorageLive(_6); + StorageLive(_10); StorageLive(_4); StorageLive(_5); _3 = Len((*_1)); _4 = &raw const (*_1); _5 = _4 as *const T (PtrToPtr); _6 = NonNull:: { pointer: _5 }; - StorageLive(_10); StorageLive(_7); _7 = const ::IS_ZST; switchInt(move _7) -> [0: bb1, otherwise: bb2]; @@ -94,38 +93,35 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { bb3: { StorageDead(_7); - StorageLive(_11); - _11 = _10; - _12 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _11, _marker: const ZeroSized: PhantomData<&T> }; - StorageDead(_11); - StorageDead(_10); + _11 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> }; StorageDead(_5); StorageDead(_4); + StorageDead(_10); StorageDead(_6); StorageDead(_3); - _13 = Enumerate::> { iter: _12, count: const 0_usize }; - StorageDead(_12); - StorageLive(_14); - _14 = _13; + _12 = Enumerate::> { iter: _11, count: const 0_usize }; + StorageDead(_11); + StorageLive(_13); + _13 = _12; goto -> bb4; } bb4: { - StorageLive(_16); StorageLive(_15); - _15 = &mut _14; - _16 = > as Iterator>::next(move _15) -> [return: bb5, unwind: bb11]; + StorageLive(_14); + _14 = &mut _13; + _15 = > as Iterator>::next(move _14) -> [return: bb5, unwind: bb11]; } bb5: { - StorageDead(_15); - _17 = discriminant(_16); - switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_14); + _16 = discriminant(_15); + switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_16); - StorageDead(_14); + StorageDead(_15); + StorageDead(_13); drop(_2) -> [return: bb7, unwind continue]; } @@ -134,19 +130,19 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb8: { - _18 = (((_16 as Some).0: (usize, &T)).0: usize); - _19 = (((_16 as Some).0: (usize, &T)).1: &T); + _17 = (((_15 as Some).0: (usize, &T)).0: usize); + _18 = (((_15 as Some).0: (usize, &T)).1: &T); + StorageLive(_19); + _19 = &_2; StorageLive(_20); - _20 = &_2; - StorageLive(_21); - _21 = (_18, _19); - _22 = >::call(move _20, move _21) -> [return: bb9, unwind: bb11]; + _20 = (_17, _18); + _21 = >::call(move _19, move _20) -> [return: bb9, unwind: bb11]; } bb9: { - StorageDead(_21); StorageDead(_20); - StorageDead(_16); + StorageDead(_19); + StorageDead(_15); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir index 67dd0c85ea1d..d824857ac5d9 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir @@ -4,19 +4,19 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); + let mut _11: std::slice::Iter<'_, T>; let mut _12: std::slice::Iter<'_, T>; - let mut _13: std::slice::Iter<'_, T>; - let mut _14: &mut std::slice::Iter<'_, T>; - let mut _15: std::option::Option<&T>; - let mut _16: isize; - let mut _18: &impl Fn(&T); - let mut _19: (&T,); - let _20: (); + let mut _13: &mut std::slice::Iter<'_, T>; + let mut _14: std::option::Option<&T>; + let mut _15: isize; + let mut _17: &impl Fn(&T); + let mut _18: (&T,); + let _19: (); scope 1 { - debug iter => _13; - let _17: &T; + debug iter => _12; + let _16: &T; scope 2 { - debug x => _17; + debug x => _16; } } scope 3 (inlined core::slice::::iter) { @@ -25,11 +25,10 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { let mut _7: bool; let mut _8: *mut T; let mut _9: *mut T; - let mut _11: *const T; + let mut _10: *const T; scope 5 { let _6: std::ptr::NonNull; scope 6 { - let _10: *const T; scope 7 { } scope 11 (inlined without_provenance::) { @@ -56,13 +55,13 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { bb0: { StorageLive(_3); StorageLive(_6); + StorageLive(_10); StorageLive(_4); StorageLive(_5); _3 = Len((*_1)); _4 = &raw const (*_1); _5 = _4 as *const T (PtrToPtr); _6 = NonNull:: { pointer: _5 }; - StorageLive(_10); StorageLive(_7); _7 = const ::IS_ZST; switchInt(move _7) -> [0: bb1, otherwise: bb2]; @@ -86,36 +85,33 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { bb3: { StorageDead(_7); - StorageLive(_11); - _11 = _10; - _12 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _11, _marker: const ZeroSized: PhantomData<&T> }; - StorageDead(_11); - StorageDead(_10); + _11 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> }; StorageDead(_5); StorageDead(_4); + StorageDead(_10); StorageDead(_6); StorageDead(_3); - StorageLive(_13); - _13 = _12; + StorageLive(_12); + _12 = _11; goto -> bb4; } bb4: { - StorageLive(_15); StorageLive(_14); - _14 = &mut _13; - _15 = as Iterator>::next(move _14) -> [return: bb5, unwind unreachable]; + StorageLive(_13); + _13 = &mut _12; + _14 = as Iterator>::next(move _13) -> [return: bb5, unwind unreachable]; } bb5: { - StorageDead(_14); - _16 = discriminant(_15); - switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_13); + _15 = discriminant(_14); + switchInt(move _15) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_15); - StorageDead(_13); + StorageDead(_14); + StorageDead(_12); drop(_2) -> [return: bb7, unwind unreachable]; } @@ -124,18 +120,18 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _17 = ((_15 as Some).0: &T); + _16 = ((_14 as Some).0: &T); + StorageLive(_17); + _17 = &_2; StorageLive(_18); - _18 = &_2; - StorageLive(_19); - _19 = (_17,); - _20 = >::call(move _18, move _19) -> [return: bb9, unwind unreachable]; + _18 = (_16,); + _19 = >::call(move _17, move _18) -> [return: bb9, unwind unreachable]; } bb9: { - StorageDead(_19); StorageDead(_18); - StorageDead(_15); + StorageDead(_17); + StorageDead(_14); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir index 7c41e9e1f1b7..75437119aa60 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir @@ -4,19 +4,19 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); + let mut _11: std::slice::Iter<'_, T>; let mut _12: std::slice::Iter<'_, T>; - let mut _13: std::slice::Iter<'_, T>; - let mut _14: &mut std::slice::Iter<'_, T>; - let mut _15: std::option::Option<&T>; - let mut _16: isize; - let mut _18: &impl Fn(&T); - let mut _19: (&T,); - let _20: (); + let mut _13: &mut std::slice::Iter<'_, T>; + let mut _14: std::option::Option<&T>; + let mut _15: isize; + let mut _17: &impl Fn(&T); + let mut _18: (&T,); + let _19: (); scope 1 { - debug iter => _13; - let _17: &T; + debug iter => _12; + let _16: &T; scope 2 { - debug x => _17; + debug x => _16; } } scope 3 (inlined core::slice::::iter) { @@ -25,11 +25,10 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { let mut _7: bool; let mut _8: *mut T; let mut _9: *mut T; - let mut _11: *const T; + let mut _10: *const T; scope 5 { let _6: std::ptr::NonNull; scope 6 { - let _10: *const T; scope 7 { } scope 11 (inlined without_provenance::) { @@ -56,13 +55,13 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { bb0: { StorageLive(_3); StorageLive(_6); + StorageLive(_10); StorageLive(_4); StorageLive(_5); _3 = Len((*_1)); _4 = &raw const (*_1); _5 = _4 as *const T (PtrToPtr); _6 = NonNull:: { pointer: _5 }; - StorageLive(_10); StorageLive(_7); _7 = const ::IS_ZST; switchInt(move _7) -> [0: bb1, otherwise: bb2]; @@ -86,36 +85,33 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { bb3: { StorageDead(_7); - StorageLive(_11); - _11 = _10; - _12 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _11, _marker: const ZeroSized: PhantomData<&T> }; - StorageDead(_11); - StorageDead(_10); + _11 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> }; StorageDead(_5); StorageDead(_4); + StorageDead(_10); StorageDead(_6); StorageDead(_3); - StorageLive(_13); - _13 = _12; + StorageLive(_12); + _12 = _11; goto -> bb4; } bb4: { - StorageLive(_15); StorageLive(_14); - _14 = &mut _13; - _15 = as Iterator>::next(move _14) -> [return: bb5, unwind: bb11]; + StorageLive(_13); + _13 = &mut _12; + _14 = as Iterator>::next(move _13) -> [return: bb5, unwind: bb11]; } bb5: { - StorageDead(_14); - _16 = discriminant(_15); - switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_13); + _15 = discriminant(_14); + switchInt(move _15) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_15); - StorageDead(_13); + StorageDead(_14); + StorageDead(_12); drop(_2) -> [return: bb7, unwind continue]; } @@ -124,18 +120,18 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _17 = ((_15 as Some).0: &T); + _16 = ((_14 as Some).0: &T); + StorageLive(_17); + _17 = &_2; StorageLive(_18); - _18 = &_2; - StorageLive(_19); - _19 = (_17,); - _20 = >::call(move _18, move _19) -> [return: bb9, unwind: bb11]; + _18 = (_16,); + _19 = >::call(move _17, move _18) -> [return: bb9, unwind: bb11]; } bb9: { - StorageDead(_19); StorageDead(_18); - StorageDead(_15); + StorageDead(_17); + StorageDead(_14); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir index dbe6f39548c8..dc370911d8a9 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir @@ -6,28 +6,27 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { let mut _0: (); let mut _3: usize; let mut _4: usize; - let mut _9: std::option::Option; - let mut _11: usize; - let mut _12: bool; - let mut _14: &impl Fn(usize, &T); - let mut _15: (usize, &T); - let _16: (); + let mut _8: std::option::Option; + let mut _10: usize; + let mut _11: bool; + let mut _13: &impl Fn(usize, &T); + let mut _14: (usize, &T); + let _15: (); scope 1 { debug ((iter: std::ops::Range).0: usize) => _4; debug ((iter: std::ops::Range).1: usize) => _3; - let _10: usize; + let _9: usize; scope 2 { - debug i => _10; - let _13: &T; + debug i => _9; + let _12: &T; scope 3 { - debug x => _13; + debug x => _12; } } scope 5 (inlined iter::range::>::next) { scope 6 (inlined as iter::range::RangeIteratorImpl>::spec_next) { let mut _6: bool; let _7: usize; - let mut _8: usize; scope 7 { } scope 8 (inlined std::cmp::impls::::lt) { @@ -41,13 +40,12 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { bb0: { _3 = Len((*_1)); - StorageLive(_4); _4 = const 0_usize; goto -> bb1; } bb1: { - StorageLive(_9); + StorageLive(_8); StorageLive(_7); StorageLive(_6); StorageLive(_5); @@ -60,8 +58,7 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { bb2: { StorageDead(_6); StorageDead(_7); - StorageDead(_9); - StorageDead(_4); + StorageDead(_8); drop(_2) -> [return: bb3, unwind unreachable]; } @@ -71,35 +68,32 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { bb4: { _7 = _4; - StorageLive(_8); - _8 = ::forward_unchecked(_7, const 1_usize) -> [return: bb5, unwind unreachable]; + _4 = ::forward_unchecked(_7, const 1_usize) -> [return: bb5, unwind unreachable]; } bb5: { - _4 = move _8; - StorageDead(_8); - _9 = Option::::Some(_7); + _8 = Option::::Some(_7); StorageDead(_6); StorageDead(_7); - _10 = ((_9 as Some).0: usize); - _11 = Len((*_1)); - _12 = Lt(_10, _11); - assert(move _12, "index out of bounds: the length is {} but the index is {}", move _11, _10) -> [success: bb6, unwind unreachable]; + _9 = ((_8 as Some).0: usize); + _10 = Len((*_1)); + _11 = Lt(_9, _10); + assert(move _11, "index out of bounds: the length is {} but the index is {}", move _10, _9) -> [success: bb6, unwind unreachable]; } bb6: { - _13 = &(*_1)[_10]; + _12 = &(*_1)[_9]; + StorageLive(_13); + _13 = &_2; StorageLive(_14); - _14 = &_2; - StorageLive(_15); - _15 = (_10, _13); - _16 = >::call(move _14, move _15) -> [return: bb7, unwind unreachable]; + _14 = (_9, _12); + _15 = >::call(move _13, move _14) -> [return: bb7, unwind unreachable]; } bb7: { - StorageDead(_15); StorageDead(_14); - StorageDead(_9); + StorageDead(_13); + StorageDead(_8); goto -> bb1; } } diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir index 5b6441cfb3b2..751e14441d43 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir @@ -6,28 +6,27 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { let mut _0: (); let mut _3: usize; let mut _4: usize; - let mut _9: std::option::Option; - let mut _11: usize; - let mut _12: bool; - let mut _14: &impl Fn(usize, &T); - let mut _15: (usize, &T); - let _16: (); + let mut _8: std::option::Option; + let mut _10: usize; + let mut _11: bool; + let mut _13: &impl Fn(usize, &T); + let mut _14: (usize, &T); + let _15: (); scope 1 { debug ((iter: std::ops::Range).0: usize) => _4; debug ((iter: std::ops::Range).1: usize) => _3; - let _10: usize; + let _9: usize; scope 2 { - debug i => _10; - let _13: &T; + debug i => _9; + let _12: &T; scope 3 { - debug x => _13; + debug x => _12; } } scope 5 (inlined iter::range::>::next) { scope 6 (inlined as iter::range::RangeIteratorImpl>::spec_next) { let mut _6: bool; let _7: usize; - let mut _8: usize; scope 7 { } scope 8 (inlined std::cmp::impls::::lt) { @@ -41,13 +40,12 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { bb0: { _3 = Len((*_1)); - StorageLive(_4); _4 = const 0_usize; goto -> bb1; } bb1: { - StorageLive(_9); + StorageLive(_8); StorageLive(_7); StorageLive(_6); StorageLive(_5); @@ -60,8 +58,7 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { bb2: { StorageDead(_6); StorageDead(_7); - StorageDead(_9); - StorageDead(_4); + StorageDead(_8); drop(_2) -> [return: bb3, unwind continue]; } @@ -71,35 +68,32 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { bb4: { _7 = _4; - StorageLive(_8); - _8 = ::forward_unchecked(_7, const 1_usize) -> [return: bb5, unwind: bb8]; + _4 = ::forward_unchecked(_7, const 1_usize) -> [return: bb5, unwind: bb8]; } bb5: { - _4 = move _8; - StorageDead(_8); - _9 = Option::::Some(_7); + _8 = Option::::Some(_7); StorageDead(_6); StorageDead(_7); - _10 = ((_9 as Some).0: usize); - _11 = Len((*_1)); - _12 = Lt(_10, _11); - assert(move _12, "index out of bounds: the length is {} but the index is {}", move _11, _10) -> [success: bb6, unwind: bb8]; + _9 = ((_8 as Some).0: usize); + _10 = Len((*_1)); + _11 = Lt(_9, _10); + assert(move _11, "index out of bounds: the length is {} but the index is {}", move _10, _9) -> [success: bb6, unwind: bb8]; } bb6: { - _13 = &(*_1)[_10]; + _12 = &(*_1)[_9]; + StorageLive(_13); + _13 = &_2; StorageLive(_14); - _14 = &_2; - StorageLive(_15); - _15 = (_10, _13); - _16 = >::call(move _14, move _15) -> [return: bb7, unwind: bb8]; + _14 = (_9, _12); + _15 = >::call(move _13, move _14) -> [return: bb7, unwind: bb8]; } bb7: { - StorageDead(_15); StorageDead(_14); - StorageDead(_9); + StorageDead(_13); + StorageDead(_8); goto -> bb1; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir index ffeef1e04a15..9200d311d6d7 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir @@ -4,22 +4,22 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _12: std::slice::Iter<'_, T>; + let mut _11: std::slice::Iter<'_, T>; + let mut _12: std::iter::Rev>; let mut _13: std::iter::Rev>; - let mut _14: std::iter::Rev>; - let mut _16: std::option::Option<&T>; - let mut _17: isize; - let mut _19: &impl Fn(&T); - let mut _20: (&T,); - let _21: (); + let mut _15: std::option::Option<&T>; + let mut _16: isize; + let mut _18: &impl Fn(&T); + let mut _19: (&T,); + let _20: (); scope 1 { - debug iter => _14; - let _18: &T; + debug iter => _13; + let _17: &T; scope 2 { - debug x => _18; + debug x => _17; } scope 17 (inlined > as Iterator>::next) { - let mut _15: &mut std::slice::Iter<'_, T>; + let mut _14: &mut std::slice::Iter<'_, T>; } } scope 3 (inlined core::slice::::iter) { @@ -28,11 +28,10 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { let mut _7: bool; let mut _8: *mut T; let mut _9: *mut T; - let mut _11: *const T; + let mut _10: *const T; scope 5 { let _6: std::ptr::NonNull; scope 6 { - let _10: *const T; scope 7 { } scope 11 (inlined without_provenance::) { @@ -61,16 +60,16 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb0: { - StorageLive(_12); + StorageLive(_11); StorageLive(_3); StorageLive(_6); + StorageLive(_10); StorageLive(_4); StorageLive(_5); _3 = Len((*_1)); _4 = &raw const (*_1); _5 = _4 as *const T (PtrToPtr); _6 = NonNull:: { pointer: _5 }; - StorageLive(_10); StorageLive(_7); _7 = const ::IS_ZST; switchInt(move _7) -> [0: bb1, otherwise: bb2]; @@ -94,38 +93,35 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { bb3: { StorageDead(_7); - StorageLive(_11); - _11 = _10; - _12 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _11, _marker: const ZeroSized: PhantomData<&T> }; - StorageDead(_11); - StorageDead(_10); + _11 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> }; StorageDead(_5); StorageDead(_4); + StorageDead(_10); StorageDead(_6); StorageDead(_3); - _13 = Rev::> { iter: _12 }; - StorageDead(_12); - StorageLive(_14); - _14 = _13; + _12 = Rev::> { iter: _11 }; + StorageDead(_11); + StorageLive(_13); + _13 = _12; goto -> bb4; } bb4: { - StorageLive(_16); StorageLive(_15); - _15 = &mut (_14.0: std::slice::Iter<'_, T>); - _16 = as DoubleEndedIterator>::next_back(move _15) -> [return: bb5, unwind unreachable]; + StorageLive(_14); + _14 = &mut (_13.0: std::slice::Iter<'_, T>); + _15 = as DoubleEndedIterator>::next_back(move _14) -> [return: bb5, unwind unreachable]; } bb5: { - StorageDead(_15); - _17 = discriminant(_16); - switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_14); + _16 = discriminant(_15); + switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_16); - StorageDead(_14); + StorageDead(_15); + StorageDead(_13); drop(_2) -> [return: bb7, unwind unreachable]; } @@ -134,18 +130,18 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _18 = ((_16 as Some).0: &T); + _17 = ((_15 as Some).0: &T); + StorageLive(_18); + _18 = &_2; StorageLive(_19); - _19 = &_2; - StorageLive(_20); - _20 = (_18,); - _21 = >::call(move _19, move _20) -> [return: bb9, unwind unreachable]; + _19 = (_17,); + _20 = >::call(move _18, move _19) -> [return: bb9, unwind unreachable]; } bb9: { - StorageDead(_20); StorageDead(_19); - StorageDead(_16); + StorageDead(_18); + StorageDead(_15); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir index c7cd37afd866..5a2d9d2a6814 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir @@ -4,22 +4,22 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _12: std::slice::Iter<'_, T>; + let mut _11: std::slice::Iter<'_, T>; + let mut _12: std::iter::Rev>; let mut _13: std::iter::Rev>; - let mut _14: std::iter::Rev>; - let mut _16: std::option::Option<&T>; - let mut _17: isize; - let mut _19: &impl Fn(&T); - let mut _20: (&T,); - let _21: (); + let mut _15: std::option::Option<&T>; + let mut _16: isize; + let mut _18: &impl Fn(&T); + let mut _19: (&T,); + let _20: (); scope 1 { - debug iter => _14; - let _18: &T; + debug iter => _13; + let _17: &T; scope 2 { - debug x => _18; + debug x => _17; } scope 17 (inlined > as Iterator>::next) { - let mut _15: &mut std::slice::Iter<'_, T>; + let mut _14: &mut std::slice::Iter<'_, T>; } } scope 3 (inlined core::slice::::iter) { @@ -28,11 +28,10 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { let mut _7: bool; let mut _8: *mut T; let mut _9: *mut T; - let mut _11: *const T; + let mut _10: *const T; scope 5 { let _6: std::ptr::NonNull; scope 6 { - let _10: *const T; scope 7 { } scope 11 (inlined without_provenance::) { @@ -61,16 +60,16 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb0: { - StorageLive(_12); + StorageLive(_11); StorageLive(_3); StorageLive(_6); + StorageLive(_10); StorageLive(_4); StorageLive(_5); _3 = Len((*_1)); _4 = &raw const (*_1); _5 = _4 as *const T (PtrToPtr); _6 = NonNull:: { pointer: _5 }; - StorageLive(_10); StorageLive(_7); _7 = const ::IS_ZST; switchInt(move _7) -> [0: bb1, otherwise: bb2]; @@ -94,38 +93,35 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { bb3: { StorageDead(_7); - StorageLive(_11); - _11 = _10; - _12 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _11, _marker: const ZeroSized: PhantomData<&T> }; - StorageDead(_11); - StorageDead(_10); + _11 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> }; StorageDead(_5); StorageDead(_4); + StorageDead(_10); StorageDead(_6); StorageDead(_3); - _13 = Rev::> { iter: _12 }; - StorageDead(_12); - StorageLive(_14); - _14 = _13; + _12 = Rev::> { iter: _11 }; + StorageDead(_11); + StorageLive(_13); + _13 = _12; goto -> bb4; } bb4: { - StorageLive(_16); StorageLive(_15); - _15 = &mut (_14.0: std::slice::Iter<'_, T>); - _16 = as DoubleEndedIterator>::next_back(move _15) -> [return: bb5, unwind: bb11]; + StorageLive(_14); + _14 = &mut (_13.0: std::slice::Iter<'_, T>); + _15 = as DoubleEndedIterator>::next_back(move _14) -> [return: bb5, unwind: bb11]; } bb5: { - StorageDead(_15); - _17 = discriminant(_16); - switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_14); + _16 = discriminant(_15); + switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_16); - StorageDead(_14); + StorageDead(_15); + StorageDead(_13); drop(_2) -> [return: bb7, unwind continue]; } @@ -134,18 +130,18 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _18 = ((_16 as Some).0: &T); + _17 = ((_15 as Some).0: &T); + StorageLive(_18); + _18 = &_2; StorageLive(_19); - _19 = &_2; - StorageLive(_20); - _20 = (_18,); - _21 = >::call(move _19, move _20) -> [return: bb9, unwind: bb11]; + _19 = (_17,); + _20 = >::call(move _18, move _19) -> [return: bb9, unwind: bb11]; } bb9: { - StorageDead(_20); StorageDead(_19); - StorageDead(_16); + StorageDead(_18); + StorageDead(_15); goto -> bb4; } From dabd05bbab9df465a580858c3e03dc1797b12deb Mon Sep 17 00:00:00 2001 From: r0cky Date: Thu, 30 May 2024 09:51:27 +0800 Subject: [PATCH 087/211] Apply x clippy --fix and x fmt --- .../src/graph/dominators/mod.rs | 2 +- .../src/graph/iterate/mod.rs | 4 ++-- .../rustc_data_structures/src/graph/scc/mod.rs | 2 +- .../rustc_data_structures/src/profiling.rs | 2 +- .../rustc_data_structures/src/sorted_map.rs | 4 ++-- .../rustc_data_structures/src/sync/lock.rs | 2 +- compiler/rustc_parse_format/src/lib.rs | 18 ++++++++---------- compiler/rustc_serialize/src/serialize.rs | 2 +- compiler/stable_mir/src/mir/pretty.rs | 4 ++-- compiler/stable_mir/src/ty.rs | 6 +++--- library/proc_macro/src/bridge/fxhash.rs | 2 +- library/proc_macro/src/bridge/rpc.rs | 6 +++--- library/test/src/cli.rs | 2 +- library/test/src/term/terminfo/parm.rs | 2 +- 14 files changed, 28 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_data_structures/src/graph/dominators/mod.rs b/compiler/rustc_data_structures/src/graph/dominators/mod.rs index 30e240cf85b8..d1d2de670b82 100644 --- a/compiler/rustc_data_structures/src/graph/dominators/mod.rs +++ b/compiler/rustc_data_structures/src/graph/dominators/mod.rs @@ -93,7 +93,7 @@ fn dominators_impl(graph: &G) -> Inner { // These are all done here rather than through one of the 'standard' // graph traversals to help make this fast. 'recurse: while let Some(frame) = stack.last_mut() { - while let Some(successor) = frame.iter.next() { + for successor in frame.iter.by_ref() { if real_to_pre_order[successor].is_none() { let pre_order_idx = pre_order_to_real.push(successor); real_to_pre_order[successor] = Some(pre_order_idx); diff --git a/compiler/rustc_data_structures/src/graph/iterate/mod.rs b/compiler/rustc_data_structures/src/graph/iterate/mod.rs index 78d05a6e1951..6fca57d32f77 100644 --- a/compiler/rustc_data_structures/src/graph/iterate/mod.rs +++ b/compiler/rustc_data_structures/src/graph/iterate/mod.rs @@ -48,7 +48,7 @@ fn post_order_walk( let node = frame.node; visited[node] = true; - while let Some(successor) = frame.iter.next() { + for successor in frame.iter.by_ref() { if !visited[successor] { stack.push(PostOrderFrame { node: successor, iter: graph.successors(successor) }); continue 'recurse; @@ -112,7 +112,7 @@ where /// This is equivalent to just invoke `next` repeatedly until /// you get a `None` result. pub fn complete_search(&mut self) { - while let Some(_) = self.next() {} + for _ in self.by_ref() {} } /// Returns true if node has been visited thus far. diff --git a/compiler/rustc_data_structures/src/graph/scc/mod.rs b/compiler/rustc_data_structures/src/graph/scc/mod.rs index 914a6a16348c..7f36e4ca16df 100644 --- a/compiler/rustc_data_structures/src/graph/scc/mod.rs +++ b/compiler/rustc_data_structures/src/graph/scc/mod.rs @@ -40,7 +40,7 @@ pub struct SccData { } impl Sccs { - pub fn new(graph: &(impl DirectedGraph + Successors)) -> Self { + pub fn new(graph: &impl Successors) -> Self { SccsConstruction::construct(graph) } diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs index c6d51a5d6b4f..240f2671c3b2 100644 --- a/compiler/rustc_data_structures/src/profiling.rs +++ b/compiler/rustc_data_structures/src/profiling.rs @@ -562,7 +562,7 @@ impl SelfProfiler { // ASLR is disabled and the heap is otherwise deterministic. let pid: u32 = process::id(); let filename = format!("{crate_name}-{pid:07}.rustc_profile"); - let path = output_directory.join(&filename); + let path = output_directory.join(filename); let profiler = Profiler::with_counter(&path, measureme::counters::Counter::by_name(counter_name)?)?; diff --git a/compiler/rustc_data_structures/src/sorted_map.rs b/compiler/rustc_data_structures/src/sorted_map.rs index 21d7c91ec482..885f023122ab 100644 --- a/compiler/rustc_data_structures/src/sorted_map.rs +++ b/compiler/rustc_data_structures/src/sorted_map.rs @@ -125,13 +125,13 @@ impl SortedMap { /// Iterate over the keys, sorted #[inline] - pub fn keys(&self) -> impl Iterator + ExactSizeIterator + DoubleEndedIterator { + pub fn keys(&self) -> impl ExactSizeIterator + DoubleEndedIterator { self.data.iter().map(|(k, _)| k) } /// Iterate over values, sorted by key #[inline] - pub fn values(&self) -> impl Iterator + ExactSizeIterator + DoubleEndedIterator { + pub fn values(&self) -> impl ExactSizeIterator + DoubleEndedIterator { self.data.iter().map(|(_, v)| v) } diff --git a/compiler/rustc_data_structures/src/sync/lock.rs b/compiler/rustc_data_structures/src/sync/lock.rs index 756984642c74..780be7739458 100644 --- a/compiler/rustc_data_structures/src/sync/lock.rs +++ b/compiler/rustc_data_structures/src/sync/lock.rs @@ -69,7 +69,7 @@ mod maybe_sync { match self.mode { Mode::NoSync => { let cell = unsafe { &self.lock.mode_union.no_sync }; - debug_assert_eq!(cell.get(), true); + debug_assert!(cell.get()); cell.set(false); } // SAFETY (unlock): We know that the lock is locked as this type is a proof of that. diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index faf6ca784670..ef71333d1c39 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -286,13 +286,11 @@ impl<'a> Iterator for Parser<'a> { lbrace_byte_pos.to(InnerOffset(rbrace_byte_pos.0 + width)), ); } - } else { - if let Some(&(_, maybe)) = self.cur.peek() { - match maybe { - '?' => self.suggest_format_debug(), - '<' | '^' | '>' => self.suggest_format_align(maybe), - _ => self.suggest_positional_arg_instead_of_captured_arg(arg), - } + } else if let Some(&(_, maybe)) = self.cur.peek() { + match maybe { + '?' => self.suggest_format_debug(), + '<' | '^' | '>' => self.suggest_format_align(maybe), + _ => self.suggest_positional_arg_instead_of_captured_arg(arg), } } Some(NextArgument(Box::new(arg))) @@ -1028,7 +1026,7 @@ fn find_width_map_from_snippet( if next_c == '{' { // consume up to 6 hexanumeric chars let digits_len = - s.clone().take(6).take_while(|(_, c)| c.is_digit(16)).count(); + s.clone().take(6).take_while(|(_, c)| c.is_ascii_hexdigit()).count(); let len_utf8 = s .as_str() @@ -1047,14 +1045,14 @@ fn find_width_map_from_snippet( width += required_skips + 2; s.nth(digits_len); - } else if next_c.is_digit(16) { + } else if next_c.is_ascii_hexdigit() { width += 1; // We suggest adding `{` and `}` when appropriate, accept it here as if // it were correct let mut i = 0; // consume up to 6 hexanumeric chars while let (Some((_, c)), _) = (s.next(), i < 6) { - if c.is_digit(16) { + if c.is_ascii_hexdigit() { width += 1; } else { break; diff --git a/compiler/rustc_serialize/src/serialize.rs b/compiler/rustc_serialize/src/serialize.rs index 412f7eced433..c84bb26735c5 100644 --- a/compiler/rustc_serialize/src/serialize.rs +++ b/compiler/rustc_serialize/src/serialize.rs @@ -252,7 +252,7 @@ impl Encodable for () { } impl Decodable for () { - fn decode(_: &mut D) -> () {} + fn decode(_: &mut D) {} } impl Encodable for PhantomData { diff --git a/compiler/stable_mir/src/mir/pretty.rs b/compiler/stable_mir/src/mir/pretty.rs index bbca3965852a..580dc1a2b88f 100644 --- a/compiler/stable_mir/src/mir/pretty.rs +++ b/compiler/stable_mir/src/mir/pretty.rs @@ -156,7 +156,7 @@ fn pretty_terminator(writer: &mut W, terminator: &TerminatorKind) -> i fn pretty_terminator_head(writer: &mut W, terminator: &TerminatorKind) -> io::Result<()> { use self::TerminatorKind::*; - const INDENT: &'static str = " "; + const INDENT: &str = " "; match terminator { Goto { .. } => write!(writer, "{INDENT}goto"), SwitchInt { discr, .. } => { @@ -315,7 +315,7 @@ fn pretty_operand(operand: &Operand) -> String { } fn pretty_const(literal: &Const) -> String { - with(|cx| cx.const_pretty(&literal)) + with(|cx| cx.const_pretty(literal)) } fn pretty_rvalue(writer: &mut W, rval: &Rvalue) -> io::Result<()> { diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs index d62054eff609..50bf0a5d74ef 100644 --- a/compiler/stable_mir/src/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -526,7 +526,7 @@ pub enum IntTy { impl IntTy { pub fn num_bytes(self) -> usize { match self { - IntTy::Isize => crate::target::MachineInfo::target_pointer_width().bytes().into(), + IntTy::Isize => crate::target::MachineInfo::target_pointer_width().bytes(), IntTy::I8 => 1, IntTy::I16 => 2, IntTy::I32 => 4, @@ -549,7 +549,7 @@ pub enum UintTy { impl UintTy { pub fn num_bytes(self) -> usize { match self { - UintTy::Usize => crate::target::MachineInfo::target_pointer_width().bytes().into(), + UintTy::Usize => crate::target::MachineInfo::target_pointer_width().bytes(), UintTy::U8 => 1, UintTy::U16 => 2, UintTy::U32 => 4, @@ -1185,7 +1185,7 @@ impl Allocation { match self.read_int()? { 0 => Ok(false), 1 => Ok(true), - val @ _ => Err(error!("Unexpected value for bool: `{val}`")), + val => Err(error!("Unexpected value for bool: `{val}`")), } } diff --git a/library/proc_macro/src/bridge/fxhash.rs b/library/proc_macro/src/bridge/fxhash.rs index f4e905441972..f9f74c63fc4f 100644 --- a/library/proc_macro/src/bridge/fxhash.rs +++ b/library/proc_macro/src/bridge/fxhash.rs @@ -69,7 +69,7 @@ impl Hasher for FxHasher { hash.add_to_hash(u16::from_ne_bytes(bytes[..2].try_into().unwrap()) as usize); bytes = &bytes[2..]; } - if (size_of::() > 1) && bytes.len() >= 1 { + if (size_of::() > 1) && !bytes.is_empty() { hash.add_to_hash(bytes[0] as usize); } self.hash = hash.hash; diff --git a/library/proc_macro/src/bridge/rpc.rs b/library/proc_macro/src/bridge/rpc.rs index 6d75a5a627c8..202a8e04543b 100644 --- a/library/proc_macro/src/bridge/rpc.rs +++ b/library/proc_macro/src/bridge/rpc.rs @@ -264,9 +264,9 @@ impl From> for PanicMessage { } } -impl Into> for PanicMessage { - fn into(self) -> Box { - match self { +impl From for Box { + fn from(val: PanicMessage) -> Self { + match val { PanicMessage::StaticStr(s) => Box::new(s), PanicMessage::String(s) => Box::new(s), PanicMessage::Unknown => { diff --git a/library/test/src/cli.rs b/library/test/src/cli.rs index 6ac3b3eaa797..b7d24405b775 100644 --- a/library/test/src/cli.rs +++ b/library/test/src/cli.rs @@ -200,7 +200,7 @@ Test Attributes: pub fn parse_opts(args: &[String]) -> Option { // Parse matches. let opts = optgroups(); - let binary = args.get(0).map(|c| &**c).unwrap_or("..."); + let binary = args.first().map(|c| &**c).unwrap_or("..."); let args = args.get(1..).unwrap_or(args); let matches = match opts.parse(args) { Ok(m) => m, diff --git a/library/test/src/term/terminfo/parm.rs b/library/test/src/term/terminfo/parm.rs index 2815f6cfc77f..c5b4ef01893c 100644 --- a/library/test/src/term/terminfo/parm.rs +++ b/library/test/src/term/terminfo/parm.rs @@ -524,7 +524,7 @@ fn format(val: Param, op: FormatOp, flags: Flags) -> Result, String> { } else { let mut s_ = Vec::with_capacity(flags.width); s_.extend(repeat(b' ').take(n)); - s_.extend(s.into_iter()); + s_.extend(s); s = s_; } } From 31043656fe03325745777e27e1716f7af202bc7c Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 29 May 2024 20:53:48 +1000 Subject: [PATCH 088/211] compiletest: Unify `cmd2procres` with `run_command_to_procres` --- src/tools/compiletest/src/runtest.rs | 48 +++++++++++----------------- 1 file changed, 19 insertions(+), 29 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 910a829fbea1..4ea12a0f9e48 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -506,8 +506,20 @@ impl<'test> TestCx<'test> { } } + /// Runs a [`Command`] and waits for it to finish, then converts its exit + /// status and output streams into a [`ProcRes`]. + /// + /// The command might have succeeded or failed; it is the caller's + /// responsibility to check the exit status and take appropriate action. + /// + /// # Panics + /// Panics if the command couldn't be executed at all + /// (e.g. because the executable could not be found). + #[must_use = "caller should check whether the command succeeded"] fn run_command_to_procres(&self, cmd: &mut Command) -> ProcRes { - let output = cmd.output().unwrap_or_else(|e| panic!("failed to exec `{cmd:?}`: {e:?}")); + let output = cmd + .output() + .unwrap_or_else(|e| self.fatal(&format!("failed to exec `{cmd:?}` because: {e}"))); let proc_res = ProcRes { status: output.status, @@ -1232,7 +1244,7 @@ impl<'test> TestCx<'test> { } else { self.config.lldb_python_dir.as_ref().unwrap().to_string() }; - self.cmd2procres( + self.run_command_to_procres( Command::new(&self.config.python) .arg(&lldb_script_path) .arg(test_executable) @@ -1242,28 +1254,6 @@ impl<'test> TestCx<'test> { ) } - fn cmd2procres(&self, cmd: &mut Command) -> ProcRes { - let (status, out, err) = match cmd.output() { - Ok(Output { status, stdout, stderr }) => { - (status, String::from_utf8(stdout).unwrap(), String::from_utf8(stderr).unwrap()) - } - Err(e) => self.fatal(&format!( - "Failed to setup Python process for \ - LLDB script: {}", - e - )), - }; - - self.dump_output(&out, &err); - ProcRes { - status, - stdout: out, - stderr: err, - truncated: Truncated::No, - cmdline: format!("{:?}", cmd), - } - } - fn cleanup_debug_info_options(&self, options: &Vec) -> Vec { // Remove options that are either unwanted (-O) or may lead to duplicates due to RUSTFLAGS. let options_to_remove = ["-O".to_owned(), "-g".to_owned(), "--debuginfo".to_owned()]; @@ -2683,7 +2673,7 @@ impl<'test> TestCx<'test> { if self.config.bless { cmd.arg("--bless"); } - let res = self.cmd2procres(&mut cmd); + let res = self.run_command_to_procres(&mut cmd); if !res.status.success() { self.fatal_proc_rec_with_ctx("htmldocck failed!", &res, |mut this| { this.compare_to_default_rustdoc(&out_dir) @@ -2860,7 +2850,7 @@ impl<'test> TestCx<'test> { let root = self.config.find_rust_src_root().unwrap(); let mut json_out = out_dir.join(self.testpaths.file.file_stem().unwrap()); json_out.set_extension("json"); - let res = self.cmd2procres( + let res = self.run_command_to_procres( Command::new(self.config.jsondocck_path.as_ref().unwrap()) .arg("--doc-dir") .arg(root.join(&out_dir)) @@ -2878,7 +2868,7 @@ impl<'test> TestCx<'test> { let mut json_out = out_dir.join(self.testpaths.file.file_stem().unwrap()); json_out.set_extension("json"); - let res = self.cmd2procres( + let res = self.run_command_to_procres( Command::new(self.config.jsondoclint_path.as_ref().unwrap()).arg(&json_out), ); @@ -3526,7 +3516,7 @@ impl<'test> TestCx<'test> { cmd.arg("--sysroot").arg(&stage0_sysroot); } - let res = self.cmd2procres(&mut cmd); + let res = self.run_command_to_procres(&mut cmd); if !res.status.success() { self.fatal_proc_rec("run-make test failed: could not build `rmake.rs` recipe", &res); } @@ -3687,7 +3677,7 @@ impl<'test> TestCx<'test> { let root = self.config.find_rust_src_root().unwrap(); let file_stem = self.testpaths.file.file_stem().and_then(|f| f.to_str()).expect("no file stem"); - let res = self.cmd2procres( + let res = self.run_command_to_procres( Command::new(&nodejs) .arg(root.join("src/tools/rustdoc-js/tester.js")) .arg("--doc-folder") From c671eaaaffcd4204573d96cb6085863bb83dcfbe Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 30 May 2024 13:16:07 +1000 Subject: [PATCH 089/211] coverage: Rename MC/DC `conditions_num` to `num_conditions` This value represents a quantity of conditions, not an ID, so the new spelling is more appropriate. --- .../src/coverageinfo/ffi.rs | 7 ++--- compiler/rustc_middle/src/mir/coverage.rs | 4 +-- compiler/rustc_middle/src/mir/pretty.rs | 4 +-- compiler/rustc_mir_build/messages.ftl | 2 +- .../src/build/coverageinfo/mcdc.rs | 26 +++++++++---------- compiler/rustc_mir_build/src/errors.rs | 8 +++--- .../src/coverage/mappings.rs | 6 ++--- .../rustc_mir_transform/src/coverage/mod.rs | 6 ++--- .../mcdc-condition-limit.bad.stderr | 2 +- .../mcdc-condition-limit.rs | 2 +- 10 files changed, 34 insertions(+), 33 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs index 12a846a49ec1..584d033d6bdd 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs @@ -118,7 +118,7 @@ pub mod mcdc { #[derive(Clone, Copy, Debug, Default)] pub struct DecisionParameters { bitmap_idx: u32, - conditions_num: u16, + num_conditions: u16, } // ConditionId in llvm is `unsigned int` at 18 while `int16_t` at [19](https://github.com/llvm/llvm-project/pull/81257) @@ -177,8 +177,9 @@ pub mod mcdc { } impl From for DecisionParameters { - fn from(value: DecisionInfo) -> Self { - Self { bitmap_idx: value.bitmap_idx, conditions_num: value.conditions_num } + fn from(info: DecisionInfo) -> Self { + let DecisionInfo { bitmap_idx, num_conditions } = info; + Self { bitmap_idx, num_conditions } } } } diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index 4155c61e96d0..da25fbb0a82b 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -329,14 +329,14 @@ pub struct MCDCBranchSpan { #[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] pub struct DecisionInfo { pub bitmap_idx: u32, - pub conditions_num: u16, + pub num_conditions: u16, } #[derive(Clone, Debug)] #[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] pub struct MCDCDecisionSpan { pub span: Span, - pub conditions_num: usize, + pub num_conditions: usize, pub end_markers: Vec, pub decision_depth: u16, } diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 7bfb4ac867aa..f1c79c0b0391 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -512,12 +512,12 @@ fn write_coverage_branch_info( )?; } - for coverage::MCDCDecisionSpan { span, conditions_num, end_markers, decision_depth } in + for coverage::MCDCDecisionSpan { span, num_conditions, end_markers, decision_depth } in mcdc_decision_spans { writeln!( w, - "{INDENT}coverage mcdc decision {{ conditions_num: {conditions_num:?}, end: {end_markers:?}, depth: {decision_depth:?} }} => {span:?}" + "{INDENT}coverage mcdc decision {{ num_conditions: {num_conditions:?}, end: {end_markers:?}, depth: {decision_depth:?} }} => {span:?}" )?; } diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index 4ba61226a3fd..e3362429a6d9 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -97,7 +97,7 @@ mir_build_deref_raw_pointer_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = .note = raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior .label = dereference of raw pointer -mir_build_exceeds_mcdc_condition_num_limit = Conditions number of the decision ({$conditions_num}) exceeds limit ({$max_conditions_num}). MCDC analysis will not count this expression. +mir_build_exceeds_mcdc_condition_limit = Number of conditions in decision ({$num_conditions}) exceeds limit ({$max_conditions}). MC/DC analysis will not count this expression. mir_build_extern_static_requires_unsafe = use of extern static is unsafe and requires unsafe block diff --git a/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs b/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs index 728b63d5b21b..7d7b7caf9ef9 100644 --- a/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs +++ b/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs @@ -10,12 +10,12 @@ use rustc_middle::ty::TyCtxt; use rustc_span::Span; use crate::build::Builder; -use crate::errors::MCDCExceedsConditionNumLimit; +use crate::errors::MCDCExceedsConditionLimit; /// The MCDC bitmap scales exponentially (2^n) based on the number of conditions seen, /// So llvm sets a maximum value prevents the bitmap footprint from growing too large without the user's knowledge. /// This limit may be relaxed if the [upstream change](https://github.com/llvm/llvm-project/pull/82448) is merged. -const MAX_CONDITIONS_NUM_IN_DECISION: usize = 6; +const MAX_CONDITIONS_IN_DECISION: usize = 6; #[derive(Default)] struct MCDCDecisionCtx { @@ -100,7 +100,7 @@ impl MCDCState { } None => decision_ctx.processing_decision.insert(MCDCDecisionSpan { span, - conditions_num: 0, + num_conditions: 0, end_markers: vec![], decision_depth, }), @@ -108,14 +108,14 @@ impl MCDCState { let parent_condition = decision_ctx.decision_stack.pop_back().unwrap_or_default(); let lhs_id = if parent_condition.condition_id == ConditionId::NONE { - decision.conditions_num += 1; - ConditionId::from(decision.conditions_num) + decision.num_conditions += 1; + ConditionId::from(decision.num_conditions) } else { parent_condition.condition_id }; - decision.conditions_num += 1; - let rhs_condition_id = ConditionId::from(decision.conditions_num); + decision.num_conditions += 1; + let rhs_condition_id = ConditionId::from(decision.num_conditions); let (lhs, rhs) = match op { LogicalOp::And => { @@ -208,17 +208,17 @@ impl MCDCInfoBuilder { // is empty, i.e. when all the conditions of the decision were instrumented, // and the decision is "complete". if let Some(decision) = decision_result { - match decision.conditions_num { + match decision.num_conditions { 0 => { unreachable!("Decision with no condition is not expected"); } - 1..=MAX_CONDITIONS_NUM_IN_DECISION => { + 1..=MAX_CONDITIONS_IN_DECISION => { self.decision_spans.push(decision); } _ => { // Do not generate mcdc mappings and statements for decisions with too many conditions. // Therefore, first erase the condition info of the (N-1) previous branch spans. - let rebase_idx = self.branch_spans.len() - (decision.conditions_num - 1); + let rebase_idx = self.branch_spans.len() - (decision.num_conditions - 1); for branch in &mut self.branch_spans[rebase_idx..] { branch.condition_info = None; } @@ -226,10 +226,10 @@ impl MCDCInfoBuilder { // Then, erase this last branch span's info too, for a total of N. condition_info = None; - tcx.dcx().emit_warn(MCDCExceedsConditionNumLimit { + tcx.dcx().emit_warn(MCDCExceedsConditionLimit { span: decision.span, - conditions_num: decision.conditions_num, - max_conditions_num: MAX_CONDITIONS_NUM_IN_DECISION, + num_conditions: decision.num_conditions, + max_conditions: MAX_CONDITIONS_IN_DECISION, }); } } diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index ae6e126a4e2c..19616cc0a1e1 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -812,12 +812,12 @@ pub struct NonEmptyNeverPattern<'tcx> { } #[derive(Diagnostic)] -#[diag(mir_build_exceeds_mcdc_condition_num_limit)] -pub(crate) struct MCDCExceedsConditionNumLimit { +#[diag(mir_build_exceeds_mcdc_condition_limit)] +pub(crate) struct MCDCExceedsConditionLimit { #[primary_span] pub span: Span, - pub conditions_num: usize, - pub max_conditions_num: usize, + pub num_conditions: usize, + pub max_conditions: usize, } #[derive(Diagnostic)] diff --git a/compiler/rustc_mir_transform/src/coverage/mappings.rs b/compiler/rustc_mir_transform/src/coverage/mappings.rs index 61aabea1d8b3..0e209757100c 100644 --- a/compiler/rustc_mir_transform/src/coverage/mappings.rs +++ b/compiler/rustc_mir_transform/src/coverage/mappings.rs @@ -48,7 +48,7 @@ pub(super) struct MCDCDecision { pub(super) span: Span, pub(super) end_bcbs: BTreeSet, pub(super) bitmap_idx: u32, - pub(super) conditions_num: u16, + pub(super) num_conditions: u16, pub(super) decision_depth: u16, } @@ -268,13 +268,13 @@ pub(super) fn extract_mcdc_mappings( // the bitmap, rounded up to a whole number of bytes. // The decision's "bitmap index" points to its first byte in the bitmap. let bitmap_idx = *mcdc_bitmap_bytes; - *mcdc_bitmap_bytes += (1_u32 << decision.conditions_num).div_ceil(8); + *mcdc_bitmap_bytes += (1_u32 << decision.num_conditions).div_ceil(8); Some(MCDCDecision { span, end_bcbs, bitmap_idx, - conditions_num: decision.conditions_num as u16, + num_conditions: decision.num_conditions as u16, decision_depth: decision.decision_depth, }) }, diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 28e0c633d5aa..419e39bc3867 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -195,9 +195,9 @@ fn create_mappings<'tcx>( )); mappings.extend(mcdc_decisions.iter().filter_map( - |&mappings::MCDCDecision { span, bitmap_idx, conditions_num, .. }| { + |&mappings::MCDCDecision { span, bitmap_idx, num_conditions, .. }| { let code_region = region_for_span(span)?; - let kind = MappingKind::MCDCDecision(DecisionInfo { bitmap_idx, conditions_num }); + let kind = MappingKind::MCDCDecision(DecisionInfo { bitmap_idx, num_conditions }); Some(Mapping { kind, code_region }) }, )); @@ -269,7 +269,7 @@ fn inject_mcdc_statements<'tcx>( span: _, ref end_bcbs, bitmap_idx, - conditions_num: _, + num_conditions: _, decision_depth, } in &extracted_mappings.mcdc_decisions { diff --git a/tests/ui/instrument-coverage/mcdc-condition-limit.bad.stderr b/tests/ui/instrument-coverage/mcdc-condition-limit.bad.stderr index 4d8d7e1560d0..5df6aaf98041 100644 --- a/tests/ui/instrument-coverage/mcdc-condition-limit.bad.stderr +++ b/tests/ui/instrument-coverage/mcdc-condition-limit.bad.stderr @@ -1,4 +1,4 @@ -warning: Conditions number of the decision (7) exceeds limit (6). MCDC analysis will not count this expression. +warning: Number of conditions in decision (7) exceeds limit (6). MC/DC analysis will not count this expression. --> $DIR/mcdc-condition-limit.rs:29:8 | LL | if a && b && c && d && e && f && g { diff --git a/tests/ui/instrument-coverage/mcdc-condition-limit.rs b/tests/ui/instrument-coverage/mcdc-condition-limit.rs index 64c5f8e9b779..de3770b5709d 100644 --- a/tests/ui/instrument-coverage/mcdc-condition-limit.rs +++ b/tests/ui/instrument-coverage/mcdc-condition-limit.rs @@ -26,7 +26,7 @@ fn main() { fn main() { // 7 conditions is too many, so issue a diagnostic. let [a, b, c, d, e, f, g] = <[bool; 7]>::default(); - if a && b && c && d && e && f && g { //[bad]~ WARNING Conditions number of the decision + if a && b && c && d && e && f && g { //[bad]~ WARNING Number of conditions in decision core::hint::black_box("hello"); } } From 4ce7e094ae9d226535a404075efc92898f79793a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 29 May 2024 11:33:13 +0200 Subject: [PATCH 090/211] compiletest: clarify COMPILETEST_NEEDS_ALL_LLVM_COMPONENTS error also improve wording for an ignore reason --- src/ci/run.sh | 2 +- src/tools/compiletest/src/header.rs | 9 ++++++--- src/tools/tidy/src/target_specific_tests.rs | 3 +++ 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/ci/run.sh b/src/ci/run.sh index 2e36b7e5962e..efaf70078c4a 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -90,7 +90,7 @@ RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --dist-compression-formats=xz" if [ "$EXTERNAL_LLVM" = "" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.optimized-compiler-builtins" # Likewise, only demand we test all LLVM components if we know we built LLVM with them - export COMPILETEST_NEEDS_ALL_LLVM_COMPONENTS=1 + export COMPILETEST_REQUIRE_ALL_LLVM_COMPONENTS=1 elif [ "$DEPLOY$DEPLOY_ALT" = "1" ]; then echo "error: dist builds should always use optimized compiler-rt!" >&2 exit 1 diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index dc5818201b6d..a2cdf800a971 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -1436,7 +1436,7 @@ pub fn make_test_description( if config.target == "wasm32-unknown-unknown" { if config.parse_name_directive(ln, directives::CHECK_RUN_RESULTS) { decision!(IgnoreDecision::Ignore { - reason: "ignored when checking the run results on WASM".into(), + reason: "ignored on WASM as the run results cannot be checked there".into(), }); } } @@ -1577,8 +1577,11 @@ fn ignore_llvm(config: &Config, line: &str) -> IgnoreDecision { .split_whitespace() .find(|needed_component| !components.contains(needed_component)) { - if env::var_os("COMPILETEST_NEEDS_ALL_LLVM_COMPONENTS").is_some() { - panic!("missing LLVM component: {}", missing_component); + if env::var_os("COMPILETEST_REQUIRE_ALL_LLVM_COMPONENTS").is_some() { + panic!( + "missing LLVM component {}, and COMPILETEST_REQUIRE_ALL_LLVM_COMPONENTS is set", + missing_component + ); } return IgnoreDecision::Ignore { reason: format!("ignored when the {missing_component} LLVM component is missing"), diff --git a/src/tools/tidy/src/target_specific_tests.rs b/src/tools/tidy/src/target_specific_tests.rs index 6fd2148ef678..f3a64b38e8c6 100644 --- a/src/tools/tidy/src/target_specific_tests.rs +++ b/src/tools/tidy/src/target_specific_tests.rs @@ -90,6 +90,9 @@ pub fn check(path: &Path, bad: &mut bool) { } if let Some(llvm_components) = llvm_components { for component in llvm_components { + // Ensure the given component even exists. + // This is somewhat redundant with COMPILETEST_REQUIRE_ALL_LLVM_COMPONENTS, + // but helps detect such problems earlier (PR CI rather than bors CI). if !KNOWN_LLVM_COMPONENTS.contains(component) { eprintln!( "{}: revision {} specifies unknown LLVM component `{}`", From 4af4ba2391c81eb1db6290e6197a4a91478abfac Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 29 May 2024 13:49:23 +1000 Subject: [PATCH 091/211] List all `tests/` subdirs explicitly in `rustfmt.toml`. So we can gradually remove the ones where rustfmt can be used. --- rustfmt.toml | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/rustfmt.toml b/rustfmt.toml index b78e96d5872f..90de42072d78 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -10,9 +10,32 @@ ignore = [ "/build-*/", "/vendor/", - # Tests for now are not formatted, as they are sometimes pretty-printing constrained - # (and generally rustfmt can move around comments in UI-testing incompatible ways). - "/tests/", + # Some tests are not formatted, for multiple reasons: + # - some contain syntax errors that cause rustfmt to give an error + # - some UI tests are broken by different formatting + # - some require special comments in a particular position (e.g. `EMIT_MIR` comments) + "/tests/assembly/", + "/tests/auxiliary/", + "/tests/codegen/", + "/tests/codegen-units/", + "/tests/coverage/", + "/tests/coverage-run-rustdoc/", + "/tests/crashes/", + "/tests/debuginfo/", + "/tests/incremental/", + "/tests/mir-opt/", + "/tests/pretty/", + "/tests/run-make/", + "/tests/run-make-fulldeps/", + "/tests/run-pass-valgrind/", + "/tests/rustdoc/", + "/tests/rustdoc-gui/", + "/tests/rustdoc-js/", + "/tests/rustdoc-json/", + "/tests/rustdoc-js-std/", + "/tests/rustdoc-ui/", + "/tests/ui/", + "/tests/ui-fulldeps/", # Do not format submodules. # FIXME: sync submodule list with tidy/bootstrap/etc From d063c7b6c8548b88323378c9890c67233755f831 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 29 May 2024 13:57:23 +1000 Subject: [PATCH 092/211] Run rustfmt on `tests/assembly/`. --- rustfmt.toml | 1 - tests/assembly/align_offset.rs | 2 +- tests/assembly/asm/inline-asm-avx.rs | 2 +- .../closure-inherit-target-feature.rs | 13 +++++----- tests/assembly/is_aligned.rs | 7 ++--- tests/assembly/pic-relocation-model.rs | 15 +++++------ tests/assembly/pie-relocation-model.rs | 15 +++++------ ...otector-heuristics-effect-windows-32bit.rs | 11 +------- ...otector-heuristics-effect-windows-64bit.rs | 11 +------- .../stack-protector-heuristics-effect.rs | 7 +---- tests/assembly/static-relocation-model.rs | 20 +++++--------- tests/assembly/thin-lto.rs | 3 +-- tests/assembly/wasm_exceptions.rs | 26 ++++++++++++------- ...4-fortanix-unknown-sgx-lvi-generic-load.rs | 2 +- ...64-fortanix-unknown-sgx-lvi-generic-ret.rs | 2 +- 15 files changed, 52 insertions(+), 85 deletions(-) diff --git a/rustfmt.toml b/rustfmt.toml index 90de42072d78..70d7332aafa9 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -14,7 +14,6 @@ ignore = [ # - some contain syntax errors that cause rustfmt to give an error # - some UI tests are broken by different formatting # - some require special comments in a particular position (e.g. `EMIT_MIR` comments) - "/tests/assembly/", "/tests/auxiliary/", "/tests/codegen/", "/tests/codegen-units/", diff --git a/tests/assembly/align_offset.rs b/tests/assembly/align_offset.rs index dbf599a741fd..d9902ce336b0 100644 --- a/tests/assembly/align_offset.rs +++ b/tests/assembly/align_offset.rs @@ -1,7 +1,7 @@ //@ assembly-output: emit-asm //@ compile-flags: -Copt-level=1 //@ only-x86_64 -#![crate_type="rlib"] +#![crate_type = "rlib"] // CHECK-LABEL: align_offset_byte_ptr // CHECK: leaq 31 diff --git a/tests/assembly/asm/inline-asm-avx.rs b/tests/assembly/asm/inline-asm-avx.rs index 7e52a798dedb..630acbb971a8 100644 --- a/tests/assembly/asm/inline-asm-avx.rs +++ b/tests/assembly/asm/inline-asm-avx.rs @@ -5,8 +5,8 @@ #![feature(portable_simd)] -use std::simd::Simd; use std::arch::asm; +use std::simd::Simd; #[target_feature(enable = "avx")] #[no_mangle] diff --git a/tests/assembly/closure-inherit-target-feature.rs b/tests/assembly/closure-inherit-target-feature.rs index cafe9e7ca6fa..4692653d91fc 100644 --- a/tests/assembly/closure-inherit-target-feature.rs +++ b/tests/assembly/closure-inherit-target-feature.rs @@ -18,7 +18,8 @@ pub unsafe fn sse41_blend_nofeature(x: __m128, y: __m128) -> __m128 { // CHECK: {{call .*_mm_blend_ps.*}} // CHECK-NOT: blendps // CHECK: ret - #[inline(never)] |x, y| _mm_blend_ps(x, y, 0b0101) + #[inline(never)] + |x, y| _mm_blend_ps(x, y, 0b0101) }; f(x, y) } @@ -33,9 +34,8 @@ pub fn sse41_blend_noinline(x: __m128, y: __m128) -> __m128 { // CHECK: blendps // CHECK-NOT: _mm_blend_ps // CHECK: ret - #[inline(never)] |x, y| unsafe { - _mm_blend_ps(x, y, 0b0101) - } + #[inline(never)] + |x, y| unsafe { _mm_blend_ps(x, y, 0b0101) } }; f(x, y) } @@ -52,9 +52,8 @@ pub fn sse41_blend_doinline(x: __m128, y: __m128) -> __m128 { // CHECK-NOT: _mm_blend_ps // CHECK: ret let f = { - #[inline] |x, y| unsafe { - _mm_blend_ps(x, y, 0b0101) - } + #[inline] + |x, y| unsafe { _mm_blend_ps(x, y, 0b0101) } }; f(x, y) } diff --git a/tests/assembly/is_aligned.rs b/tests/assembly/is_aligned.rs index 14423a52064a..ab8f7dea808d 100644 --- a/tests/assembly/is_aligned.rs +++ b/tests/assembly/is_aligned.rs @@ -4,8 +4,7 @@ //@ revisions: opt-speed opt-size //@ [opt-speed] compile-flags: -Copt-level=2 -Cdebug-assertions=no //@ [opt-size] compile-flags: -Copt-level=s -Cdebug-assertions=no -#![crate_type="rlib"] - +#![crate_type = "rlib"] #![feature(core_intrinsics)] #![feature(pointer_is_aligned_to)] @@ -16,9 +15,7 @@ // CHECK: retq #[no_mangle] pub unsafe fn is_aligned_to_unchecked(ptr: *const u8, align: usize) -> bool { - unsafe { - std::intrinsics::assume(align.is_power_of_two()) - } + unsafe { std::intrinsics::assume(align.is_power_of_two()) } ptr.is_aligned_to(align) } diff --git a/tests/assembly/pic-relocation-model.rs b/tests/assembly/pic-relocation-model.rs index 453fd6a70476..73db94791ec6 100644 --- a/tests/assembly/pic-relocation-model.rs +++ b/tests/assembly/pic-relocation-model.rs @@ -3,10 +3,9 @@ //@ [x64] compile-flags: --target x86_64-unknown-linux-gnu -Crelocation-model=pic //@ [x64] needs-llvm-components: x86 - #![feature(no_core, lang_items)] #![no_core] -#![crate_type="rlib"] +#![crate_type = "rlib"] #[lang = "sized"] trait Sized {} @@ -17,9 +16,7 @@ trait Copy {} // CHECK: {{(jmpq|callq)}} *other_fn@GOTPCREL(%rip) #[no_mangle] pub fn call_other_fn() -> u8 { - unsafe { - other_fn() - } + unsafe { other_fn() } } // CHECK-LABEL: other_fn: @@ -27,9 +24,9 @@ pub fn call_other_fn() -> u8 { #[no_mangle] #[inline(never)] pub fn other_fn() -> u8 { - unsafe { - foreign_fn() - } + unsafe { foreign_fn() } } -extern "C" {fn foreign_fn() -> u8;} +extern "C" { + fn foreign_fn() -> u8; +} diff --git a/tests/assembly/pie-relocation-model.rs b/tests/assembly/pie-relocation-model.rs index 6ff6b7708bbf..e632b4dd5823 100644 --- a/tests/assembly/pie-relocation-model.rs +++ b/tests/assembly/pie-relocation-model.rs @@ -3,10 +3,9 @@ //@ [x64] compile-flags: --target x86_64-unknown-linux-gnu -Crelocation-model=pie //@ [x64] needs-llvm-components: x86 - #![feature(no_core, lang_items)] #![no_core] -#![crate_type="rlib"] +#![crate_type = "rlib"] #[lang = "sized"] trait Sized {} @@ -18,9 +17,7 @@ trait Copy {} // CHECK: {{(jmp|callq)}} other_fn #[no_mangle] pub fn call_other_fn() -> u8 { - unsafe { - other_fn() - } + unsafe { other_fn() } } // CHECK-LABEL: other_fn: @@ -30,9 +27,9 @@ pub fn call_other_fn() -> u8 { #[no_mangle] #[inline(never)] pub fn other_fn() -> u8 { - unsafe { - foreign_fn() - } + unsafe { foreign_fn() } } -extern "C" {fn foreign_fn() -> u8;} +extern "C" { + fn foreign_fn() -> u8; +} diff --git a/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs b/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs index 51b4dc4e1699..2a8251785e77 100644 --- a/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs +++ b/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs @@ -10,12 +10,9 @@ //@ compile-flags: -C opt-level=2 -Z merge-functions=disabled #![crate_type = "lib"] - #![allow(incomplete_features)] - #![feature(unsized_locals, unsized_fn_params)] - // CHECK-LABEL: emptyfn: #[no_mangle] pub fn emptyfn() { @@ -139,7 +136,6 @@ pub fn local_var_addr_used_indirectly(f: fn(bool)) { // missing-NOT: __security_check_cookie } - // CHECK-LABEL: local_string_addr_taken #[no_mangle] pub fn local_string_addr_taken(f: fn(&String)) { @@ -205,7 +201,7 @@ pub struct Gigastruct { not: u64, have: u64, array: u64, - members: u64 + members: u64, } // CHECK-LABEL: local_large_var_moved @@ -259,7 +255,6 @@ pub fn local_large_var_cloned(f: fn(Gigastruct)) { // EOF // ``` - // all: __security_check_cookie // strong: __security_check_cookie // basic: __security_check_cookie @@ -267,7 +262,6 @@ pub fn local_large_var_cloned(f: fn(Gigastruct)) { // missing-NOT: __security_check_cookie } - extern "C" { // A call to an external `alloca` function is *not* recognized as an // `alloca(3)` operation. This function is a compiler built-in, as the @@ -320,7 +314,6 @@ pub fn alloca_large_compile_time_constant_arg(f: fn(*mut ())) { // missing-NOT: __security_check_cookie } - // CHECK-LABEL: alloca_dynamic_arg #[no_mangle] pub fn alloca_dynamic_arg(f: fn(*mut ()), n: usize) { @@ -340,7 +333,6 @@ pub fn alloca_dynamic_arg(f: fn(*mut ()), n: usize) { // this is support for the "unsized locals" unstable feature: // https://doc.rust-lang.org/unstable-book/language-features/unsized-locals.html. - // CHECK-LABEL: unsized_fn_param #[no_mangle] pub fn unsized_fn_param(s: [u8], l: bool, f: fn([u8])) { @@ -354,7 +346,6 @@ pub fn unsized_fn_param(s: [u8], l: bool, f: fn([u8])) { // alloca, and is therefore not protected by the `strong` or `basic` // heuristics. - // We should have a __security_check_cookie call in `all` and `strong` modes but // LLVM does not support generating stack protectors in functions with funclet // based EH personalities. diff --git a/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs b/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs index c5915262c093..9729da4e5d25 100644 --- a/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs +++ b/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs @@ -10,12 +10,9 @@ //@ compile-flags: -C opt-level=2 -Z merge-functions=disabled #![crate_type = "lib"] - #![allow(incomplete_features)] - #![feature(unsized_locals, unsized_fn_params)] - // CHECK-LABEL: emptyfn: #[no_mangle] pub fn emptyfn() { @@ -139,7 +136,6 @@ pub fn local_var_addr_used_indirectly(f: fn(bool)) { // missing-NOT: __security_check_cookie } - // CHECK-LABEL: local_string_addr_taken #[no_mangle] pub fn local_string_addr_taken(f: fn(&String)) { @@ -213,7 +209,7 @@ pub struct Gigastruct { not: u64, have: u64, array: u64, - members: u64 + members: u64, } // CHECK-LABEL: local_large_var_moved @@ -267,7 +263,6 @@ pub fn local_large_var_cloned(f: fn(Gigastruct)) { // EOF // ``` - // all: __security_check_cookie // strong: __security_check_cookie // basic: __security_check_cookie @@ -275,7 +270,6 @@ pub fn local_large_var_cloned(f: fn(Gigastruct)) { // missing-NOT: __security_check_cookie } - extern "C" { // A call to an external `alloca` function is *not* recognized as an // `alloca(3)` operation. This function is a compiler built-in, as the @@ -328,7 +322,6 @@ pub fn alloca_large_compile_time_constant_arg(f: fn(*mut ())) { // missing-NOT: __security_check_cookie } - // CHECK-LABEL: alloca_dynamic_arg #[no_mangle] pub fn alloca_dynamic_arg(f: fn(*mut ()), n: usize) { @@ -348,7 +341,6 @@ pub fn alloca_dynamic_arg(f: fn(*mut ()), n: usize) { // this is support for the "unsized locals" unstable feature: // https://doc.rust-lang.org/unstable-book/language-features/unsized-locals.html. - // CHECK-LABEL: unsized_fn_param #[no_mangle] pub fn unsized_fn_param(s: [u8], l: bool, f: fn([u8])) { @@ -362,7 +354,6 @@ pub fn unsized_fn_param(s: [u8], l: bool, f: fn([u8])) { // alloca, and is therefore not protected by the `strong` or `basic` // heuristics. - // We should have a __security_check_cookie call in `all` and `strong` modes but // LLVM does not support generating stack protectors in functions with funclet // based EH personalities. diff --git a/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs b/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs index 1f15f1a318a6..5ed0b6c50a73 100644 --- a/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs +++ b/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs @@ -143,7 +143,6 @@ pub fn local_var_addr_used_indirectly(f: fn(bool)) { // missing-NOT: __stack_chk_fail } - // CHECK-LABEL: local_string_addr_taken #[no_mangle] pub fn local_string_addr_taken(f: fn(&String)) { @@ -194,7 +193,7 @@ pub struct Gigastruct { not: u64, have: u64, array: u64, - members: u64 + members: u64, } // CHECK-LABEL: local_large_var_moved @@ -255,7 +254,6 @@ pub fn local_large_var_cloned(f: fn(Gigastruct)) { // missing-NOT: __stack_chk_fail } - extern "C" { // A call to an external `alloca` function is *not* recognized as an // `alloca(3)` operation. This function is a compiler built-in, as the @@ -308,7 +306,6 @@ pub fn alloca_large_compile_time_constant_arg(f: fn(*mut ())) { // missing-NOT: __stack_chk_fail } - // CHECK-LABEL: alloca_dynamic_arg #[no_mangle] pub fn alloca_dynamic_arg(f: fn(*mut ()), n: usize) { @@ -328,7 +325,6 @@ pub fn alloca_dynamic_arg(f: fn(*mut ()), n: usize) { // this is support for the "unsized locals" unstable feature: // https://doc.rust-lang.org/unstable-book/language-features/unsized-locals.html. - // CHECK-LABEL: unsized_fn_param #[no_mangle] pub fn unsized_fn_param(s: [u8], l: bool, f: fn([u8])) { @@ -342,7 +338,6 @@ pub fn unsized_fn_param(s: [u8], l: bool, f: fn([u8])) { // alloca, and is therefore not protected by the `strong` or `basic` // heuristics. - // all: __stack_chk_fail // strong-NOT: __stack_chk_fail // basic-NOT: __stack_chk_fail diff --git a/tests/assembly/static-relocation-model.rs b/tests/assembly/static-relocation-model.rs index 50527b853451..eafdfd485baa 100644 --- a/tests/assembly/static-relocation-model.rs +++ b/tests/assembly/static-relocation-model.rs @@ -9,15 +9,15 @@ #![feature(no_core, lang_items)] #![no_core] -#![crate_type="rlib"] +#![crate_type = "rlib"] -#[lang="sized"] +#[lang = "sized"] trait Sized {} -#[lang="copy"] +#[lang = "copy"] trait Copy {} -#[lang="sync"] +#[lang = "sync"] trait Sync {} #[lang = "drop_in_place"] @@ -42,9 +42,7 @@ extern "C" { // A64-NEXT: ldrb {{[a-z0-9]+}}, {{\[}}[[REG]], :lo12:chaenomeles] #[no_mangle] pub fn banana() -> u8 { - unsafe { - *(chaenomeles as *mut u8) - } + unsafe { *(chaenomeles as *mut u8) } } // CHECK-LABEL: peach: @@ -53,9 +51,7 @@ pub fn banana() -> u8 { // A64-NEXT: ldrb {{[a-z0-9]+}}, {{\[}}[[REG2]], :lo12:banana] #[no_mangle] pub fn peach() -> u8 { - unsafe { - *(banana as *mut u8) - } + unsafe { *(banana as *mut u8) } } // CHECK-LABEL: mango: @@ -65,9 +61,7 @@ pub fn peach() -> u8 { // A64-NEXT: ldr {{[a-z0-9]+}}, {{\[}}[[REG2]], :lo12:EXOCHORDA] #[no_mangle] pub fn mango() -> u8 { - unsafe { - *EXOCHORDA - } + unsafe { *EXOCHORDA } } // CHECK-LABEL: orange: diff --git a/tests/assembly/thin-lto.rs b/tests/assembly/thin-lto.rs index 182115662bfd..7b67b2de1e63 100644 --- a/tests/assembly/thin-lto.rs +++ b/tests/assembly/thin-lto.rs @@ -4,5 +4,4 @@ // CHECK: main -pub fn main() { -} +pub fn main() {} diff --git a/tests/assembly/wasm_exceptions.rs b/tests/assembly/wasm_exceptions.rs index 3d3b13ff32b7..7bdf7f1287c2 100644 --- a/tests/assembly/wasm_exceptions.rs +++ b/tests/assembly/wasm_exceptions.rs @@ -8,7 +8,7 @@ #![feature(core_intrinsics)] #![feature(rustc_attrs)] -extern { +extern "C" { fn may_panic(); #[rustc_nounwind] @@ -19,7 +19,9 @@ struct LogOnDrop; impl Drop for LogOnDrop { fn drop(&mut self) { - unsafe { log_number(0); } + unsafe { + log_number(0); + } } } @@ -27,7 +29,9 @@ impl Drop for LogOnDrop { #[no_mangle] pub fn test_cleanup() { let _log_on_drop = LogOnDrop; - unsafe { may_panic(); } + unsafe { + may_panic(); + } // CHECK-NOT: call // CHECK: try @@ -41,12 +45,16 @@ pub fn test_cleanup() { #[no_mangle] pub fn test_rtry() { unsafe { - core::intrinsics::catch_unwind(|_| { - may_panic(); - }, core::ptr::null_mut(), |data, exception| { - log_number(data as usize); - log_number(exception as usize); - }); + core::intrinsics::catch_unwind( + |_| { + may_panic(); + }, + core::ptr::null_mut(), + |data, exception| { + log_number(data as usize); + log_number(exception as usize); + }, + ); } // CHECK-NOT: call diff --git a/tests/assembly/x86_64-fortanix-unknown-sgx-lvi-generic-load.rs b/tests/assembly/x86_64-fortanix-unknown-sgx-lvi-generic-load.rs index 7215e354d0dc..f5e2f18e68e4 100644 --- a/tests/assembly/x86_64-fortanix-unknown-sgx-lvi-generic-load.rs +++ b/tests/assembly/x86_64-fortanix-unknown-sgx-lvi-generic-load.rs @@ -5,7 +5,7 @@ //@ only-x86_64-fortanix-unknown-sgx #[no_mangle] -pub extern fn plus_one(r: &mut u64) { +pub extern "C" fn plus_one(r: &mut u64) { *r = *r + 1; } diff --git a/tests/assembly/x86_64-fortanix-unknown-sgx-lvi-generic-ret.rs b/tests/assembly/x86_64-fortanix-unknown-sgx-lvi-generic-ret.rs index 5ae9dd11859e..f16d68fa2554 100644 --- a/tests/assembly/x86_64-fortanix-unknown-sgx-lvi-generic-ret.rs +++ b/tests/assembly/x86_64-fortanix-unknown-sgx-lvi-generic-ret.rs @@ -5,7 +5,7 @@ //@ only-x86_64-fortanix-unknown-sgx #[no_mangle] -pub extern fn myret() {} +pub extern "C" fn myret() {} // CHECK: myret: // CHECK: popq [[REGISTER:%[a-z]+]] // CHECK-NEXT: lfence From b1b18e6031cb31b8c1a07e455e65b52eccc6305b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 29 May 2024 13:59:52 +1000 Subject: [PATCH 093/211] Run rustfmt on `tests/auxiliary/`. That directory doesn't contain any Rust files, so it's a trivial change. --- rustfmt.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/rustfmt.toml b/rustfmt.toml index 70d7332aafa9..f17c038899cb 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -14,7 +14,6 @@ ignore = [ # - some contain syntax errors that cause rustfmt to give an error # - some UI tests are broken by different formatting # - some require special comments in a particular position (e.g. `EMIT_MIR` comments) - "/tests/auxiliary/", "/tests/codegen/", "/tests/codegen-units/", "/tests/coverage/", From 5c68a15e41a4e2fe792508ec130c3659b198db3d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 30 May 2024 09:07:06 +0200 Subject: [PATCH 094/211] explain what the open questions are, and add a Miri test for that --- library/core/src/ptr/mod.rs | 5 +++++ src/tools/miri/tests/pass/drop_in_place.rs | 12 ++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 src/tools/miri/tests/pass/drop_in_place.rs diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 51eb2bb4f0e0..335fc861ae86 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -452,6 +452,11 @@ mod mut_ptr; /// /// This is almost the same as calling [`ptr::read`] and discarding /// the result, but has the following advantages: +// FIXME: say something more useful than "almost the same"? +// There are open questions here: `read` requires the value to be fully valid, e.g. if `T` is a +// `bool` it must be 0 or 1, if it is a reference then it must be dereferenceable. `drop_in_place` +// only requires that `*to_drop` be "valid for dropping" and we have not defined what that means. In +// Miri it currently (May 2024) requires nothing at all for types without drop glue. /// /// * It is *required* to use `drop_in_place` to drop unsized types like /// trait objects, because they can't be read out onto the stack and diff --git a/src/tools/miri/tests/pass/drop_in_place.rs b/src/tools/miri/tests/pass/drop_in_place.rs new file mode 100644 index 000000000000..0615a43c8000 --- /dev/null +++ b/src/tools/miri/tests/pass/drop_in_place.rs @@ -0,0 +1,12 @@ +// Miri currently doesn't require types without drop glue to be +// valid when dropped. This test confirms that behavior. +// This is not a stable guarantee! + +use std::ptr; + +fn main() { + let mut not_a_bool = 13u8; + unsafe { + ptr::drop_in_place(&mut not_a_bool as *mut u8 as *mut bool) + }; +} From 280ed2b594783a3c5fc91722eb37830ab78f1f5a Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Thu, 30 May 2024 09:44:33 +0200 Subject: [PATCH 095/211] Bump nightly version -> 2024-05-30 --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index a0585ffdb45b..dd8b9ece773e 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2024-05-16" +channel = "nightly-2024-05-30" components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] From 97d2c3a6a738c019ba59d884a7233ca53ee4f28c Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 21 May 2024 18:01:16 +0000 Subject: [PATCH 096/211] remove tracing tree indent lines --- compiler/rustc_log/src/lib.rs | 1 - compiler/rustc_pattern_analysis/tests/common/mod.rs | 1 - src/librustdoc/lib.rs | 1 - 3 files changed, 3 deletions(-) diff --git a/compiler/rustc_log/src/lib.rs b/compiler/rustc_log/src/lib.rs index e11c45b66e6d..41b26ecce3c5 100644 --- a/compiler/rustc_log/src/lib.rs +++ b/compiler/rustc_log/src/lib.rs @@ -103,7 +103,6 @@ pub fn init_logger(cfg: LoggerConfig) -> Result<(), Error> { let mut layer = tracing_tree::HierarchicalLayer::default() .with_writer(io::stderr) - .with_indent_lines(true) .with_ansi(color_logs) .with_targets(true) .with_verbose_exit(verbose_entry_exit) diff --git a/compiler/rustc_pattern_analysis/tests/common/mod.rs b/compiler/rustc_pattern_analysis/tests/common/mod.rs index e72fddb9e9a8..6e8bb5050055 100644 --- a/compiler/rustc_pattern_analysis/tests/common/mod.rs +++ b/compiler/rustc_pattern_analysis/tests/common/mod.rs @@ -13,7 +13,6 @@ pub fn init_tracing() { use tracing_subscriber::Layer; let _ = tracing_tree::HierarchicalLayer::default() .with_writer(std::io::stderr) - .with_indent_lines(true) .with_ansi(true) .with_targets(true) .with_indent_amount(2) diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 55346c768b66..c0d2f9cfaf95 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -200,7 +200,6 @@ fn init_logging(early_dcx: &EarlyDiagCtxt) { let filter = tracing_subscriber::EnvFilter::from_env("RUSTDOC_LOG"); let layer = tracing_tree::HierarchicalLayer::default() .with_writer(io::stderr) - .with_indent_lines(true) .with_ansi(color_logs) .with_targets(true) .with_wraparound(10) From f7d14b741e0be6a2ca49e34bd1e6bf827647e30f Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 21 May 2024 18:16:33 +0000 Subject: [PATCH 097/211] update UI tests --- .../occurs-check/associated-type.next.stderr | 8 ++++---- .../occurs-check/associated-type.old.stderr | 16 ++++++++-------- .../structually-relate-aliases.stderr | 4 ++-- ...itrary-self-from-method-substs.default.stderr | 2 +- .../next-solver/issue-118950-root-region.stderr | 8 ++++---- 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/tests/ui/coherence/occurs-check/associated-type.next.stderr b/tests/ui/coherence/occurs-check/associated-type.next.stderr index 7443459b8300..d809a6948f3e 100644 --- a/tests/ui/coherence/occurs-check/associated-type.next.stderr +++ b/tests/ui/coherence/occurs-check/associated-type.next.stderr @@ -1,7 +1,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) } -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) } + 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) } + 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:31:1 | diff --git a/tests/ui/coherence/occurs-check/associated-type.old.stderr b/tests/ui/coherence/occurs-check/associated-type.old.stderr index 38a02c906d4f..329086ab7dfd 100644 --- a/tests/ui/coherence/occurs-check/associated-type.old.stderr +++ b/tests/ui/coherence/occurs-check/associated-type.old.stderr @@ -1,11 +1,11 @@ -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) } -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) } + 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) } error[E0119]: conflicting implementations of trait `Overlap fn(&'a (), _)>` for type `for<'a> fn(&'a (), _)` --> $DIR/associated-type.rs:31:1 | diff --git a/tests/ui/higher-ranked/structually-relate-aliases.stderr b/tests/ui/higher-ranked/structually-relate-aliases.stderr index 59fab52b221e..2f1dfd19c483 100644 --- a/tests/ui/higher-ranked/structually-relate-aliases.stderr +++ b/tests/ui/higher-ranked/structually-relate-aliases.stderr @@ -1,5 +1,5 @@ -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, !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) } + 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, !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 | diff --git a/tests/ui/self/arbitrary-self-from-method-substs.default.stderr b/tests/ui/self/arbitrary-self-from-method-substs.default.stderr index bd0519f66c0d..6fff086a89c2 100644 --- a/tests/ui/self/arbitrary-self-from-method-substs.default.stderr +++ b/tests/ui/self/arbitrary-self-from-method-substs.default.stderr @@ -9,7 +9,7 @@ LL | fn get>(self: R) -> u32 { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) +error[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion between structures + --> $DIR/issue-78372.rs:3:1 + | +LL | impl DispatchFromDyn> for T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error: aborting due to 8 previous errors Some errors have detailed explanations: E0038, E0307, E0378, E0412, E0658. From 4dec6bbcb3b8cae2e35de8b23652be75ac320be1 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 3 Jun 2024 12:56:47 +0000 Subject: [PATCH 177/211] Avoid an `Option` that is always `Some` --- .../src/hir_ty_lowering/generics.rs | 2 +- .../src/hir_ty_lowering/mod.rs | 18 ++++++------- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 25 +++++++++++-------- 3 files changed, 22 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs index d641e33b299e..ea6841f9a823 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs @@ -610,7 +610,7 @@ pub(crate) fn check_generic_arg_count( explicit_late_bound, correct: lifetimes_correct .and(args_correct) - .map_err(|reported| GenericArgCountMismatch { reported: Some(reported), invalid_args }), + .map_err(|reported| GenericArgCountMismatch { reported, invalid_args }), } } 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 54b7f7f36ed2..4ffc8e5abd86 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -215,10 +215,9 @@ pub(crate) enum GenericArgPosition { /// A marker denoting that the generic arguments that were /// provided did not match the respective generic parameters. -#[derive(Clone, Default, Debug)] +#[derive(Clone, Debug)] pub struct GenericArgCountMismatch { - /// Indicates whether a fatal error was reported (`Some`), or just a lint (`None`). - pub reported: Option, + pub reported: ErrorGuaranteed, /// A list of spans of arguments provided that were not valid. pub invalid_args: Vec, } @@ -404,10 +403,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { self_ty.is_some(), ); - if let Err(err) = &arg_count.correct - && let Some(reported) = err.reported - { - self.set_tainted_by_errors(reported); + if let Err(err) = &arg_count.correct { + self.set_tainted_by_errors(err.reported); } // Skip processing if type has no generic parameters. @@ -584,13 +581,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { && generics.has_self && !tcx.has_attr(def_id, sym::const_trait) { - let e = tcx.dcx().emit_err(crate::errors::ConstBoundForNonConstTrait { + let reported = tcx.dcx().emit_err(crate::errors::ConstBoundForNonConstTrait { span, modifier: constness.as_str(), }); - self.set_tainted_by_errors(e); - arg_count.correct = - Err(GenericArgCountMismatch { reported: Some(e), invalid_args: vec![] }); + self.set_tainted_by_errors(reported); + arg_count.correct = Err(GenericArgCountMismatch { reported, invalid_args: vec![] }); } let args = lower_generic_args( tcx, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 0c10c67db8c3..bae99fe79773 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1118,7 +1118,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // to add defaults. If the user provided *too many* types, that's // a problem. - let mut infer_args_for_err = FxHashSet::default(); + let mut infer_args_for_err = None; let mut explicit_late_bound = ExplicitLateBound::No; for &GenericPathSegment(def_id, index) in &generic_segments { @@ -1136,9 +1136,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { explicit_late_bound = ExplicitLateBound::Yes; } - if let Err(GenericArgCountMismatch { reported: Some(e), .. }) = arg_count.correct { - infer_args_for_err.insert(index); - self.set_tainted_by_errors(e); // See issue #53251. + if let Err(GenericArgCountMismatch { reported, .. }) = arg_count.correct { + infer_args_for_err + .get_or_insert_with(|| (reported, FxHashSet::default())) + .1 + .insert(index); + self.set_tainted_by_errors(reported); // See issue #53251. } } @@ -1232,15 +1235,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let def_id = res.def_id(); - let arg_count = GenericArgCountResult { - explicit_late_bound, - correct: if infer_args_for_err.is_empty() { - Ok(()) - } else { - Err(GenericArgCountMismatch::default()) - }, + let (correct, infer_args_for_err) = match infer_args_for_err { + Some((reported, args)) => { + (Err(GenericArgCountMismatch { reported, invalid_args: vec![] }), args) + } + None => (Ok(()), Default::default()), }; + let arg_count = GenericArgCountResult { explicit_late_bound, correct }; + struct CtorGenericArgsCtxt<'a, 'tcx> { fcx: &'a FnCtxt<'a, 'tcx>, span: Span, From 24af952ef7bf02501bf7a991c1c2feb110c77a7f Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 3 Jun 2024 13:06:59 +0000 Subject: [PATCH 178/211] Store indices of generic args instead of spans, as the actual entries are unused, just the number of entries is checked. The indices will be used in a follow-up commit --- .../src/hir_ty_lowering/errors.rs | 2 +- .../src/hir_ty_lowering/generics.rs | 15 ++------------- .../rustc_hir_analysis/src/hir_ty_lowering/mod.rs | 4 ++-- 3 files changed, 5 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 821c56530407..8ea27d0947d5 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -702,7 +702,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { pub(crate) fn complain_about_missing_assoc_tys( &self, associated_types: FxIndexMap>, - potential_assoc_types: Vec, + potential_assoc_types: Vec, trait_bounds: &[hir::PolyTraitRef<'_>], ) { if associated_types.values().all(|v| v.is_empty()) { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs index ea6841f9a823..4ec2aa6c6262 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs @@ -474,16 +474,9 @@ pub(crate) fn check_generic_arg_count( return Ok(()); } - if provided_args > max_expected_args { - invalid_args.extend( - gen_args.args[max_expected_args..provided_args].iter().map(|arg| arg.span()), - ); - }; + invalid_args.extend(min_expected_args..provided_args); let gen_args_info = if provided_args > min_expected_args { - invalid_args.extend( - gen_args.args[min_expected_args..provided_args].iter().map(|arg| arg.span()), - ); let num_redundant_args = provided_args - min_expected_args; GenericArgsInfo::ExcessLifetimes { num_redundant_args } } else { @@ -538,11 +531,7 @@ pub(crate) fn check_generic_arg_count( let num_default_params = expected_max - expected_min; let gen_args_info = if provided > expected_max { - invalid_args.extend( - gen_args.args[args_offset + expected_max..args_offset + provided] - .iter() - .map(|arg| arg.span()), - ); + invalid_args.extend((expected_max..provided).map(|i| i + args_offset)); let num_redundant_args = provided - expected_max; // Provide extra note if synthetic arguments like `impl Trait` are specified. 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 4ffc8e5abd86..7aa01b85028c 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -218,8 +218,8 @@ pub(crate) enum GenericArgPosition { #[derive(Clone, Debug)] pub struct GenericArgCountMismatch { pub reported: ErrorGuaranteed, - /// A list of spans of arguments provided that were not valid. - pub invalid_args: Vec, + /// A list of indices of arguments provided that were not valid. + pub invalid_args: Vec, } /// Decorates the result of a generic argument count mismatch From 2e3842b6d024943dfb06c73dd15e980f6e69fcb7 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 3 Jun 2024 13:16:56 +0000 Subject: [PATCH 179/211] Mark all missing generic args as errors --- .../src/hir_ty_lowering/mod.rs | 39 ++++++++++++++---- tests/crashes/123917.rs | 41 ------------------- .../transmutable-ice-110969.rs | 1 - .../transmutable-ice-110969.stderr | 19 +-------- tests/ui/polymorphization/abi_mismatch.rs | 20 +++++++++ tests/ui/polymorphization/abi_mismatch.stderr | 11 +++++ 6 files changed, 63 insertions(+), 68 deletions(-) delete mode 100644 tests/crashes/123917.rs create mode 100644 tests/ui/polymorphization/abi_mismatch.rs create mode 100644 tests/ui/polymorphization/abi_mismatch.stderr 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 7aa01b85028c..a18164ec7405 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -422,6 +422,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { span: Span, inferred_params: Vec, infer_args: bool, + incorrect_args: &'a Result<(), GenericArgCountMismatch>, } impl<'a, 'tcx> GenericArgsLowerer<'a, 'tcx> for GenericArgsCtxt<'a, 'tcx> { @@ -508,6 +509,25 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { infer_args: bool, ) -> ty::GenericArg<'tcx> { let tcx = self.lowerer.tcx(); + + if let Err(incorrect) = self.incorrect_args { + if incorrect.invalid_args.contains(&(param.index as usize)) { + return match param.kind { + GenericParamDefKind::Lifetime => { + ty::Region::new_error(tcx, incorrect.reported).into() + } + GenericParamDefKind::Type { .. } => { + Ty::new_error(tcx, incorrect.reported).into() + } + GenericParamDefKind::Const { .. } => ty::Const::new_error( + tcx, + incorrect.reported, + Ty::new_error(tcx, incorrect.reported), + ) + .into(), + }; + } + } match param.kind { GenericParamDefKind::Lifetime => self .lowerer @@ -568,15 +588,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } } - - let mut args_ctx = GenericArgsCtxt { - lowerer: self, - def_id, - span, - generic_args: segment.args(), - inferred_params: vec![], - infer_args: segment.infer_args, - }; if let ty::BoundConstness::Const | ty::BoundConstness::ConstIfConst = constness && generics.has_self && !tcx.has_attr(def_id, sym::const_trait) @@ -588,6 +599,16 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { self.set_tainted_by_errors(reported); arg_count.correct = Err(GenericArgCountMismatch { reported, invalid_args: vec![] }); } + + let mut args_ctx = GenericArgsCtxt { + lowerer: self, + def_id, + span, + generic_args: segment.args(), + inferred_params: vec![], + infer_args: segment.infer_args, + incorrect_args: &arg_count.correct, + }; let args = lower_generic_args( tcx, def_id, diff --git a/tests/crashes/123917.rs b/tests/crashes/123917.rs deleted file mode 100644 index 66e754606622..000000000000 --- a/tests/crashes/123917.rs +++ /dev/null @@ -1,41 +0,0 @@ -//@ known-bug: #123917 -//@ compile-flags: -Zmir-opt-level=5 -Zpolymorphize=on - -use std::marker::PhantomData; - -pub struct Id<'id>(); - -pub struct Item<'life, T> { - data: T, -} - -pub struct Token<'life, 'borrow, 'compact, 'reborrow, T> -where - 'life: 'reborrow, - T: Tokenize, -{ - ptr: *mut ::Tokenized, - ptr: core::ptr::NonNull, - _phantom: PhantomData>, -} - -impl<'life> Arena<'life> { - pub fn tokenize<'before, 'compact, 'borrow, 'reborrow, T, U>( - item: Item<'life, &'before mut T>, - ) -> Token<'life, 'borrow, 'compact, 'reborrow, U> - where - T: Tokenize<'life, 'borrow, 'compact, 'reborrow, Untokenized = U>, - T::Untokenized: Tokenize<'life, 'borrow, 'compact, 'reborrow>, - { - let dst = item.data as *mut T as *mut T::Tokenized; - Token { - ptr: core::ptr::NonNull::new(dst as *mut _).unwrap(), - _phantom: PhantomData, - } - } -} - -pub trait Tokenize { - type Tokenized; - type Untokenized; -} diff --git a/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.rs b/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.rs index 68b8b4898168..569e57fa3262 100644 --- a/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.rs +++ b/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.rs @@ -24,7 +24,6 @@ fn via_associated_const() { trait Trait { const FALSE: bool = assert::is_transmutable::(); //~^ ERROR mismatched types - //~| ERROR `Src` cannot be safely transmuted into `Dst` //~| ERROR mismatched types } } diff --git a/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.stderr b/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.stderr index 1dbacaee3c2d..a8fc742e89f5 100644 --- a/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.stderr +++ b/tests/ui/const-generics/adt_const_params/transmutable-ice-110969.stderr @@ -12,28 +12,13 @@ error[E0308]: mismatched types LL | const FALSE: bool = assert::is_transmutable::(); | ^^ expected `Assume`, found `()` -error[E0277]: `Src` cannot be safely transmuted into `Dst` - --> $DIR/transmutable-ice-110969.rs:25:60 - | -LL | const FALSE: bool = assert::is_transmutable::(); - | ^^^ `Dst` may carry safety invariants - | -note: required by a bound in `is_transmutable` - --> $DIR/transmutable-ice-110969.rs:11:14 - | -LL | pub fn is_transmutable() - | --------------- required by a bound in this function -LL | where -LL | Dst: BikeshedIntrinsicFrom, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` - error[E0308]: mismatched types --> $DIR/transmutable-ice-110969.rs:25:29 | LL | const FALSE: bool = assert::is_transmutable::(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()` -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0107, E0277, E0308. +Some errors have detailed explanations: E0107, E0308. For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/polymorphization/abi_mismatch.rs b/tests/ui/polymorphization/abi_mismatch.rs new file mode 100644 index 000000000000..22c2c162d1c1 --- /dev/null +++ b/tests/ui/polymorphization/abi_mismatch.rs @@ -0,0 +1,20 @@ +//! This test used to ICE: #123917 +//! The reason was that while the AST knows about two fields +//! named `ptr`, only one exists at the layout level, so accessing +//! `_extra_field` would use an oob index +//@ compile-flags: -Zmir-opt-level=5 -Zpolymorphize=on + +struct NonNull(*mut T); + +struct Token { + ptr: *mut T, + ptr: NonNull, + //~^ ERROR: `ptr` is already declared + _extra_field: (), +} + +fn tokenize(item: *mut T) -> Token { + Token { ptr: NonNull(item), _extra_field: () } +} + +fn main() {} diff --git a/tests/ui/polymorphization/abi_mismatch.stderr b/tests/ui/polymorphization/abi_mismatch.stderr new file mode 100644 index 000000000000..e96c737f7773 --- /dev/null +++ b/tests/ui/polymorphization/abi_mismatch.stderr @@ -0,0 +1,11 @@ +error[E0124]: field `ptr` is already declared + --> $DIR/abi_mismatch.rs:11:5 + | +LL | ptr: *mut T, + | ----------- `ptr` first declared here +LL | ptr: NonNull, + | ^^^^^^^^^^^^^^^ field already declared + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0124`. From adb2ac01657d8c0e972d641b6d22cc9b98ae217a Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 3 Jun 2024 13:21:17 +0000 Subject: [PATCH 180/211] Mark all extraneous generic args as errors --- .../src/hir_ty_lowering/mod.rs | 19 +++++++++++ tests/crashes/121134.rs | 20 ------------ ...lid-assoc-type-suggestion-in-trait-impl.rs | 2 -- ...assoc-type-suggestion-in-trait-impl.stderr | 32 ++++++------------- ...aram_mismatch_in_unsatisfied_projection.rs | 27 ++++++++++++++++ ..._mismatch_in_unsatisfied_projection.stderr | 19 +++++++++++ tests/ui/transmutability/issue-101739-2.rs | 1 - .../ui/transmutability/issue-101739-2.stderr | 20 ++---------- 8 files changed, 77 insertions(+), 63 deletions(-) delete mode 100644 tests/crashes/121134.rs create mode 100644 tests/ui/traits/generic_param_mismatch_in_unsatisfied_projection.rs create mode 100644 tests/ui/traits/generic_param_mismatch_in_unsatisfied_projection.stderr 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 a18164ec7405..d26ebe9881b8 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -442,6 +442,25 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) -> ty::GenericArg<'tcx> { let tcx = self.lowerer.tcx(); + if let Err(incorrect) = self.incorrect_args { + if incorrect.invalid_args.contains(&(param.index as usize)) { + return match param.kind { + GenericParamDefKind::Lifetime => { + ty::Region::new_error(tcx, incorrect.reported).into() + } + GenericParamDefKind::Type { .. } => { + Ty::new_error(tcx, incorrect.reported).into() + } + GenericParamDefKind::Const { .. } => ty::Const::new_error( + tcx, + incorrect.reported, + Ty::new_error(tcx, incorrect.reported), + ) + .into(), + }; + } + } + let mut handle_ty_args = |has_default, ty: &hir::Ty<'tcx>| { if has_default { tcx.check_optional_stability( diff --git a/tests/crashes/121134.rs b/tests/crashes/121134.rs deleted file mode 100644 index 36397d4ec3c0..000000000000 --- a/tests/crashes/121134.rs +++ /dev/null @@ -1,20 +0,0 @@ -//@ known-bug: #121134 -trait Output<'a> { - type Type; -} - -struct Wrapper; - -impl Wrapper { - fn do_something_wrapper(&mut self, do_something_wrapper: F) - where - FnOnce:, - F: for<'a> FnOnce(>::Type), - { - } -} - -fn main() { - let mut wrapper = Wrapper; - wrapper.do_something_wrapper::(|value| ()); -} diff --git a/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.rs b/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.rs index cab484a120c3..445ea2de610f 100644 --- a/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.rs +++ b/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.rs @@ -14,14 +14,12 @@ impl Trait for i32 { // Should not not trigger suggestion here... impl Trait for () {} //~^ ERROR trait takes 1 generic argument but 2 generic arguments were supplied -//~| ERROR `S` is not constrained //... but should do so in all of the below cases except the last one fn func>(t: T) -> impl Trait<(), i32> { //~^ ERROR trait takes 1 generic argument but 2 generic arguments were supplied //~| ERROR trait takes 1 generic argument but 2 generic arguments were supplied //~| ERROR trait takes 1 generic argument but 2 generic arguments were supplied -//~| ERROR type annotations needed 3 } diff --git a/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.stderr b/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.stderr index 99e81a9039e7..06e2fa5d4d1f 100644 --- a/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.stderr +++ b/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.stderr @@ -16,14 +16,8 @@ note: trait defined here, with 1 generic parameter: `T` LL | pub trait Trait { | ^^^^^ - -error[E0207]: the type parameter `S` is not constrained by the impl trait, self type, or predicates - --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:15:9 - | -LL | impl Trait for () {} - | ^ unconstrained type parameter - error[E0107]: trait takes 1 generic argument but 2 generic arguments were supplied - --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:20:12 + --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:19:12 | LL | fn func>(t: T) -> impl Trait<(), i32> { | ^^^^^ expected 1 generic argument @@ -39,7 +33,7 @@ LL | fn func>(t: T) -> impl Trait<(), i32> { | +++++++ error[E0107]: trait takes 1 generic argument but 2 generic arguments were supplied - --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:20:46 + --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:19:46 | LL | fn func>(t: T) -> impl Trait<(), i32> { | ^^^^^ expected 1 generic argument @@ -55,7 +49,7 @@ LL | fn func>(t: T) -> impl Trait<(), Assoc = i32> { | +++++++ error[E0107]: trait takes 1 generic argument but 2 generic arguments were supplied - --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:20:46 + --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:19:46 | LL | fn func>(t: T) -> impl Trait<(), i32> { | ^^^^^ expected 1 generic argument @@ -71,14 +65,8 @@ help: replace the generic bound with the associated type LL | fn func>(t: T) -> impl Trait<(), Assoc = i32> { | +++++++ -error[E0282]: type annotations needed - --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:20:41 - | -LL | fn func>(t: T) -> impl Trait<(), i32> { - | ^^^^^^^^^^^^^^^^^^^ cannot infer type - error[E0107]: trait takes 1 generic argument but 2 generic arguments were supplied - --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:28:18 + --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:26:18 | LL | struct Struct> { | ^^^^^ expected 1 generic argument @@ -94,7 +82,7 @@ LL | struct Struct> { | +++++++ error[E0107]: trait takes 1 generic argument but 2 generic arguments were supplied - --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:33:23 + --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:31:23 | LL | trait AnotherTrait> {} | ^^^^^ expected 1 generic argument @@ -110,7 +98,7 @@ LL | trait AnotherTrait> {} | +++++++ error[E0107]: trait takes 1 generic argument but 2 generic arguments were supplied - --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:36:9 + --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:34:9 | LL | impl> Struct {} | ^^^^^ expected 1 generic argument @@ -126,7 +114,7 @@ LL | impl> Struct {} | +++++++ error[E0107]: struct takes 1 generic argument but 2 generic arguments were supplied - --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:42:58 + --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:40:58 | LL | impl, U> YetAnotherTrait for Struct {} | ^^^^^^ - help: remove this generic argument @@ -134,12 +122,12 @@ LL | impl, U> YetAnotherTrait for Struct {} | expected 1 generic argument | note: struct defined here, with 1 generic parameter: `T` - --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:28:8 + --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:26:8 | LL | struct Struct> { | ^^^^^^ - -error: aborting due to 11 previous errors +error: aborting due to 9 previous errors -Some errors have detailed explanations: E0107, E0207, E0282. +Some errors have detailed explanations: E0107, E0207. For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/traits/generic_param_mismatch_in_unsatisfied_projection.rs b/tests/ui/traits/generic_param_mismatch_in_unsatisfied_projection.rs new file mode 100644 index 000000000000..bf1278f992b6 --- /dev/null +++ b/tests/ui/traits/generic_param_mismatch_in_unsatisfied_projection.rs @@ -0,0 +1,27 @@ +//! This test used to ICE: #121134 +//! The issue is that we're trying to prove a projection, but there's +//! no bound for the projection's trait, and the projection has the wrong +//! kind of generic parameter (lifetime vs type). +//! When actually calling the function with those broken bounds, trying to +//! instantiate the bounds with inference vars would ICE. +#![feature(unboxed_closures)] + +trait Output<'a> { + type Type; +} + +struct Wrapper; + +impl Wrapper { + fn do_something_wrapper(&mut self, _: F) + where + F: for<'a> FnOnce(>::Type), + //~^ ERROR: trait takes 0 generic arguments but 1 generic argument was supplied + { + } +} + +fn main() { + let mut wrapper = Wrapper; + wrapper.do_something_wrapper(|value| ()); +} diff --git a/tests/ui/traits/generic_param_mismatch_in_unsatisfied_projection.stderr b/tests/ui/traits/generic_param_mismatch_in_unsatisfied_projection.stderr new file mode 100644 index 000000000000..acda3418894d --- /dev/null +++ b/tests/ui/traits/generic_param_mismatch_in_unsatisfied_projection.stderr @@ -0,0 +1,19 @@ +error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/generic_param_mismatch_in_unsatisfied_projection.rs:18:33 + | +LL | F: for<'a> FnOnce(>::Type), + | ^^^^^^ expected 0 generic arguments + | +note: trait defined here, with 0 generic parameters + --> $DIR/generic_param_mismatch_in_unsatisfied_projection.rs:9:7 + | +LL | trait Output<'a> { + | ^^^^^^ +help: replace the generic bound with the associated type + | +LL | F: for<'a> FnOnce(>::Type), + | ++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/transmutability/issue-101739-2.rs b/tests/ui/transmutability/issue-101739-2.rs index e2cec24aac14..1c0bd29d7079 100644 --- a/tests/ui/transmutability/issue-101739-2.rs +++ b/tests/ui/transmutability/issue-101739-2.rs @@ -15,7 +15,6 @@ mod assert { >() where Dst: BikeshedIntrinsicFrom< //~ ERROR trait takes at most 2 generic arguments but 5 generic arguments were supplied - //~^ ERROR: the constant `ASSUME_ALIGNMENT` is not of type `Assume` Src, ASSUME_ALIGNMENT, //~ ERROR: mismatched types ASSUME_LIFETIMES, diff --git a/tests/ui/transmutability/issue-101739-2.stderr b/tests/ui/transmutability/issue-101739-2.stderr index 639b44608924..38912696c18e 100644 --- a/tests/ui/transmutability/issue-101739-2.stderr +++ b/tests/ui/transmutability/issue-101739-2.stderr @@ -9,29 +9,13 @@ LL | | ASSUME_VALIDITY, LL | | ASSUME_VISIBILITY, | |_____________________________- help: remove these generic arguments -error: the constant `ASSUME_ALIGNMENT` is not of type `Assume` - --> $DIR/issue-101739-2.rs:17:14 - | -LL | Dst: BikeshedIntrinsicFrom< - | ______________^ -LL | | -LL | | Src, -LL | | ASSUME_ALIGNMENT, -... | -LL | | ASSUME_VISIBILITY, -LL | | >, - | |_________^ expected `Assume`, found `bool` - | -note: required by a bound in `BikeshedIntrinsicFrom` - --> $SRC_DIR/core/src/mem/transmutability.rs:LL:COL - error[E0308]: mismatched types - --> $DIR/issue-101739-2.rs:20:13 + --> $DIR/issue-101739-2.rs:19:13 | LL | ASSUME_ALIGNMENT, | ^^^^^^^^^^^^^^^^ expected `Assume`, found `bool` -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors Some errors have detailed explanations: E0107, E0308. For more information about an error, try `rustc --explain E0107`. From 084ccd23901366cef0b2921ae3cd069a74295ad9 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 1 Jun 2024 13:22:35 -0400 Subject: [PATCH 181/211] Remove unnecessary extension trait --- .../src/infer/canonical/query_response.rs | 2 +- compiler/rustc_infer/src/infer/mod.rs | 2 +- compiler/rustc_infer/src/traits/engine.rs | 44 +++++++++---------- compiler/rustc_infer/src/traits/mod.rs | 2 +- .../src/solve/normalize.rs | 1 - .../src/traits/engine.rs | 4 +- 6 files changed, 24 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 1732913e1915..1dbc1ae7ddd2 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -15,8 +15,8 @@ use crate::infer::canonical::{ use crate::infer::region_constraints::{Constraint, RegionConstraintData}; use crate::infer::{DefineOpaqueTypes, InferCtxt, InferOk, InferResult}; use crate::traits::query::NoSolution; +use crate::traits::TraitEngine; use crate::traits::{Obligation, ObligationCause, PredicateObligation}; -use crate::traits::{TraitEngine, TraitEngineExt}; use rustc_data_structures::captures::Captures; use rustc_index::Idx; use rustc_index::IndexVec; diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index c8bb6cf5f9b4..617e6a245ed7 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -12,7 +12,7 @@ pub use SubregionOrigin::*; pub use ValuePairs::*; use crate::traits::{ - self, ObligationCause, ObligationInspector, PredicateObligations, TraitEngine, TraitEngineExt, + self, ObligationCause, ObligationInspector, PredicateObligations, TraitEngine, }; use error_reporting::TypeErrCtxt; use free_regions::RegionRelations; diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs index e27e6a0a4a15..a4bcd9d2c8a4 100644 --- a/compiler/rustc_infer/src/traits/engine.rs +++ b/compiler/rustc_infer/src/traits/engine.rs @@ -1,7 +1,6 @@ use crate::infer::InferCtxt; use crate::traits::Obligation; use rustc_hir::def_id::DefId; -use rustc_macros::extension; use rustc_middle::ty::{self, Ty, Upcast}; use super::FulfillmentError; @@ -37,11 +36,31 @@ pub trait TraitEngine<'tcx>: 'tcx { obligation: PredicateObligation<'tcx>, ); + fn register_predicate_obligations( + &mut self, + infcx: &InferCtxt<'tcx>, + obligations: Vec>, + ) { + for obligation in obligations { + self.register_predicate_obligation(infcx, obligation); + } + } + #[must_use] fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec>; fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec>; + #[must_use] + fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec> { + let errors = self.select_where_possible(infcx); + if !errors.is_empty() { + return errors; + } + + self.collect_remaining_errors(infcx) + } + fn pending_obligations(&self) -> Vec>; /// Among all pending obligations, collect those are stalled on a inference variable which has @@ -52,26 +71,3 @@ pub trait TraitEngine<'tcx>: 'tcx { infcx: &InferCtxt<'tcx>, ) -> Vec>; } - -#[extension(pub trait TraitEngineExt<'tcx>)] -impl<'tcx, T: ?Sized + TraitEngine<'tcx>> T { - fn register_predicate_obligations( - &mut self, - infcx: &InferCtxt<'tcx>, - obligations: impl IntoIterator>, - ) { - for obligation in obligations { - self.register_predicate_obligation(infcx, obligation); - } - } - - #[must_use] - fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec> { - let errors = self.select_where_possible(infcx); - if !errors.is_empty() { - return errors; - } - - self.collect_remaining_errors(infcx) - } -} diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index 0ae4340098bc..8304fa3c8a2f 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -23,7 +23,7 @@ pub use self::ImplSource::*; pub use self::SelectionError::*; use crate::infer::InferCtxt; -pub use self::engine::{TraitEngine, TraitEngineExt}; +pub use self::engine::TraitEngine; pub use self::project::MismatchedProjectionTypes; pub(crate) use self::project::UndoLog; pub use self::project::{ diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs index 5d5161e092e3..970848544c5a 100644 --- a/compiler/rustc_trait_selection/src/solve/normalize.rs +++ b/compiler/rustc_trait_selection/src/solve/normalize.rs @@ -4,7 +4,6 @@ use crate::traits::{BoundVarReplacer, PlaceholderReplacer}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_infer::infer::at::At; use rustc_infer::infer::InferCtxt; -use rustc_infer::traits::TraitEngineExt; use rustc_infer::traits::{FulfillmentError, Obligation, TraitEngine}; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{self, Ty, TyCtxt, UniverseIndex}; diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index 4684c7171d82..6fed24c49e0b 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -18,9 +18,7 @@ use rustc_infer::infer::canonical::{ use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::RegionResolutionError; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk}; -use rustc_infer::traits::{ - FulfillmentError, Obligation, ObligationCause, PredicateObligation, TraitEngineExt as _, -}; +use rustc_infer::traits::{FulfillmentError, Obligation, ObligationCause, PredicateObligation}; use rustc_macros::extension; use rustc_middle::arena::ArenaAllocatable; use rustc_middle::traits::query::NoSolution; From 54b2b7d460fd0847508b781219d380231c4fee72 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 1 Jun 2024 14:12:34 -0400 Subject: [PATCH 182/211] Make TraitEngines generic over error --- .../src/type_check/constraint_conversion.rs | 3 +- .../src/check/compare_impl_item.rs | 4 +- .../src/coherence/orphan.rs | 5 +- .../src/hir_ty_lowering/errors.rs | 2 +- .../rustc_hir_typeck/src/typeck_root_ctxt.rs | 8 +- .../src/infer/canonical/query_response.rs | 25 ++---- compiler/rustc_infer/src/infer/mod.rs | 7 +- compiler/rustc_infer/src/traits/engine.rs | 19 +++-- compiler/rustc_infer/src/traits/mod.rs | 34 +------- .../src/traits/structural_impls.rs | 6 -- compiler/rustc_trait_selection/src/regions.rs | 4 +- .../src/solve/fulfill.rs | 84 ++++++++++++++----- .../rustc_trait_selection/src/solve/mod.rs | 2 +- .../src/solve/normalize.rs | 53 +++++++----- .../src/traits/coherence.rs | 2 +- .../src/traits/engine.rs | 22 +++-- .../src/traits/fulfill.rs | 51 ++++++----- .../rustc_trait_selection/src/traits/misc.rs | 4 +- .../rustc_trait_selection/src/traits/mod.rs | 43 ++++++++++ .../src/traits/normalize.rs | 13 ++- .../src/traits/query/normalize.rs | 7 +- .../query/type_op/implied_outlives_bounds.rs | 4 +- .../src/traits/structural_normalize.rs | 8 +- 23 files changed, 253 insertions(+), 157 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index b23ad2e15842..4037f04d0bce 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -13,6 +13,7 @@ use rustc_span::Span; use rustc_trait_selection::solve::deeply_normalize; use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp; use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput}; +use rustc_trait_selection::traits::FulfillmentError; use crate::{ constraints::OutlivesConstraint, @@ -286,7 +287,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { ocx.infcx.at(&ObligationCause::dummy_with_span(self.span), self.param_env), ty, ) - .map_err(|_| NoSolution) + .map_err(|_: Vec>| NoSolution) }, "normalize type outlives obligation", ) 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 db749ef3f81b..17db1c07383f 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -10,7 +10,7 @@ use rustc_hir::intravisit; use rustc_hir::{GenericParamKind, ImplItemKind}; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; -use rustc_infer::traits::{util, FulfillmentError}; +use rustc_infer::traits::util; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::util::ExplicitSelf; @@ -25,7 +25,7 @@ use rustc_trait_selection::regions::InferCtxtRegionExt; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _; use rustc_trait_selection::traits::{ - self, ObligationCause, ObligationCauseCode, ObligationCtxt, Reveal, + self, FulfillmentError, ObligationCause, ObligationCauseCode, ObligationCtxt, Reveal, }; use std::borrow::Cow; use std::iter; diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index bdac0d9b0b40..a4818b25f98c 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -13,8 +13,8 @@ use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, Type use rustc_middle::{bug, span_bug}; use rustc_span::def_id::{DefId, LocalDefId}; use rustc_trait_selection::traits::{self, IsFirstInputType, UncoveredTyParams}; +use rustc_trait_selection::traits::{FulfillmentError, StructurallyNormalizeExt, TraitEngineExt}; use rustc_trait_selection::traits::{OrphanCheckErr, OrphanCheckMode}; -use rustc_trait_selection::traits::{StructurallyNormalizeExt, TraitEngineExt}; #[instrument(level = "debug", skip(tcx))] pub(crate) fn orphan_check_impl( @@ -317,7 +317,8 @@ fn orphan_check<'tcx>( } let ty = if infcx.next_trait_solver() { - let mut fulfill_cx = >::new(&infcx); + let mut fulfill_cx = + >>::new(&infcx); infcx .at(&cause, ty::ParamEnv::empty()) .structurally_normalize(ty, &mut *fulfill_cx) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 821c56530407..f646e7de26b9 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -15,7 +15,6 @@ use rustc_errors::{ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_infer::traits::FulfillmentError; use rustc_middle::bug; use rustc_middle::query::Key; use rustc_middle::ty::print::{PrintPolyTraitRefExt as _, PrintTraitRefExt as _}; @@ -28,6 +27,7 @@ use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::BytePos; use rustc_span::{Span, Symbol, DUMMY_SP}; +use rustc_trait_selection::traits::FulfillmentError; use rustc_trait_selection::traits::{ object_safety_violations_for_assoc_item, TraitAliasExpansionInfo, }; diff --git a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs index 19d6481cc1b8..0dfc5408f306 100644 --- a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs +++ b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs @@ -11,7 +11,9 @@ use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::def_id::LocalDefIdMap; use rustc_span::Span; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; -use rustc_trait_selection::traits::{self, PredicateObligation, TraitEngine, TraitEngineExt as _}; +use rustc_trait_selection::traits::{ + self, FulfillmentError, PredicateObligation, TraitEngine, TraitEngineExt as _, +}; use std::cell::RefCell; use std::ops::Deref; @@ -34,7 +36,7 @@ pub(crate) struct TypeckRootCtxt<'tcx> { pub(super) locals: RefCell>>, - pub(super) fulfillment_cx: RefCell>>, + pub(super) fulfillment_cx: RefCell>>>, /// Some additional `Sized` obligations badly affect type inference. /// These obligations are added in a later stage of typeck. @@ -83,7 +85,7 @@ impl<'tcx> TypeckRootCtxt<'tcx> { TypeckRootCtxt { typeck_results, - fulfillment_cx: RefCell::new(>::new(&infcx)), + fulfillment_cx: RefCell::new(>::new(&infcx)), infcx, locals: RefCell::new(Default::default()), deferred_sized_obligations: RefCell::new(Vec::new()), diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 1dbc1ae7ddd2..4917f936f4e1 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -15,7 +15,7 @@ use crate::infer::canonical::{ use crate::infer::region_constraints::{Constraint, RegionConstraintData}; use crate::infer::{DefineOpaqueTypes, InferCtxt, InferOk, InferResult}; use crate::traits::query::NoSolution; -use crate::traits::TraitEngine; +use crate::traits::{FulfillmentErrorLike, TraitEngine}; use crate::traits::{Obligation, ObligationCause, PredicateObligation}; use rustc_data_structures::captures::Captures; use rustc_index::Idx; @@ -50,11 +50,11 @@ impl<'tcx> InferCtxt<'tcx> { /// - Finally, if any of the obligations result in a hard error, /// then `Err(NoSolution)` is returned. #[instrument(skip(self, inference_vars, answer, fulfill_cx), level = "trace")] - pub fn make_canonicalized_query_response( + pub fn make_canonicalized_query_response>( &self, inference_vars: CanonicalVarValues<'tcx>, answer: T, - fulfill_cx: &mut dyn TraitEngine<'tcx>, + fulfill_cx: &mut dyn TraitEngine<'tcx, E>, ) -> Result, NoSolution> where T: Debug + TypeFoldable>, @@ -97,11 +97,11 @@ impl<'tcx> InferCtxt<'tcx> { /// Helper for `make_canonicalized_query_response` that does /// everything up until the final canonicalization. #[instrument(skip(self, fulfill_cx), level = "debug")] - fn make_query_response( + fn make_query_response>( &self, inference_vars: CanonicalVarValues<'tcx>, answer: T, - fulfill_cx: &mut dyn TraitEngine<'tcx>, + fulfill_cx: &mut dyn TraitEngine<'tcx, E>, ) -> Result, NoSolution> where T: Debug + TypeFoldable>, @@ -109,19 +109,13 @@ impl<'tcx> InferCtxt<'tcx> { let tcx = self.tcx; // Select everything, returning errors. - let true_errors = fulfill_cx.select_where_possible(self); - debug!("true_errors = {:#?}", true_errors); + let errors = fulfill_cx.select_all_or_error(self); - if !true_errors.is_empty() { - // FIXME -- we don't indicate *why* we failed to solve - debug!("make_query_response: true_errors={:#?}", true_errors); + // True error! + if errors.iter().any(|e| e.is_true_error()) { return Err(NoSolution); } - // Anything left unselected *now* must be an ambiguity. - let ambig_errors = fulfill_cx.select_all_or_error(self); - debug!("ambig_errors = {:#?}", ambig_errors); - let region_obligations = self.take_registered_region_obligations(); debug!(?region_obligations); let region_constraints = self.with_region_constraints(|region_constraints| { @@ -135,8 +129,7 @@ impl<'tcx> InferCtxt<'tcx> { }); debug!(?region_constraints); - let certainty = - if ambig_errors.is_empty() { Certainty::Proven } else { Certainty::Ambiguous }; + let certainty = if errors.is_empty() { Certainty::Proven } else { Certainty::Ambiguous }; let opaque_types = self.take_opaque_types_for_query_response(); diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 617e6a245ed7..5183d9e2d6eb 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -12,7 +12,8 @@ pub use SubregionOrigin::*; pub use ValuePairs::*; use crate::traits::{ - self, ObligationCause, ObligationInspector, PredicateObligations, TraitEngine, + self, FulfillmentErrorLike, ObligationCause, ObligationInspector, PredicateObligations, + TraitEngine, }; use error_reporting::TypeErrCtxt; use free_regions::RegionRelations; @@ -737,10 +738,10 @@ impl<'tcx> InferCtxtBuilder<'tcx> { impl<'tcx, T> InferOk<'tcx, T> { /// Extracts `value`, registering any obligations into `fulfill_cx`. - pub fn into_value_registering_obligations( + pub fn into_value_registering_obligations>( self, infcx: &InferCtxt<'tcx>, - fulfill_cx: &mut dyn TraitEngine<'tcx>, + fulfill_cx: &mut dyn TraitEngine<'tcx, E>, ) -> T { let InferOk { value, obligations } = self; fulfill_cx.register_predicate_obligations(infcx, obligations); diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs index a4bcd9d2c8a4..1d6875d0f8ed 100644 --- a/compiler/rustc_infer/src/traits/engine.rs +++ b/compiler/rustc_infer/src/traits/engine.rs @@ -1,12 +1,13 @@ +use std::fmt::Debug; + use crate::infer::InferCtxt; use crate::traits::Obligation; use rustc_hir::def_id::DefId; use rustc_middle::ty::{self, Ty, Upcast}; -use super::FulfillmentError; use super::{ObligationCause, PredicateObligation}; -pub trait TraitEngine<'tcx>: 'tcx { +pub trait TraitEngine<'tcx, E: FulfillmentErrorLike<'tcx>>: 'tcx { /// Requires that `ty` must implement the trait with `def_id` in /// the given environment. This trait must not have any type /// parameters (except for `Self`). @@ -47,12 +48,12 @@ pub trait TraitEngine<'tcx>: 'tcx { } #[must_use] - fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec>; + fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec; - fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec>; + fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec; #[must_use] - fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec> { + fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec { let errors = self.select_where_possible(infcx); if !errors.is_empty() { return errors; @@ -71,3 +72,11 @@ pub trait TraitEngine<'tcx>: 'tcx { infcx: &InferCtxt<'tcx>, ) -> Vec>; } + +pub trait FulfillmentErrorLike<'tcx>: Debug + 'tcx { + fn is_true_error(&self) -> bool; +} + +pub trait FromSolverError<'tcx, E>: FulfillmentErrorLike<'tcx> { + fn from_solver_error(infcx: &InferCtxt<'tcx>, error: E) -> Self; +} diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index 8304fa3c8a2f..26c931876dbd 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -23,7 +23,7 @@ pub use self::ImplSource::*; pub use self::SelectionError::*; use crate::infer::InferCtxt; -pub use self::engine::TraitEngine; +pub use self::engine::{FromSolverError, FulfillmentErrorLike, TraitEngine}; pub use self::project::MismatchedProjectionTypes; pub(crate) use self::project::UndoLog; pub use self::project::{ @@ -124,15 +124,7 @@ pub type Selection<'tcx> = ImplSource<'tcx, PredicateObligation<'tcx>>; pub type ObligationInspector<'tcx> = fn(&InferCtxt<'tcx>, &PredicateObligation<'tcx>, Result); -pub struct FulfillmentError<'tcx> { - pub obligation: PredicateObligation<'tcx>, - pub code: FulfillmentErrorCode<'tcx>, - /// Diagnostics only: the 'root' obligation which resulted in - /// the failure to process `obligation`. This is the obligation - /// that was initially passed to `register_predicate_obligation` - pub root_obligation: PredicateObligation<'tcx>, -} - +// TODO: Pull this down too #[derive(Clone)] pub enum FulfillmentErrorCode<'tcx> { /// Inherently impossible to fulfill; this trait is implemented if and only @@ -198,28 +190,6 @@ impl<'tcx, O> Obligation<'tcx, O> { } } -impl<'tcx> FulfillmentError<'tcx> { - pub fn new( - obligation: PredicateObligation<'tcx>, - code: FulfillmentErrorCode<'tcx>, - root_obligation: PredicateObligation<'tcx>, - ) -> FulfillmentError<'tcx> { - FulfillmentError { obligation, code, root_obligation } - } - - pub fn is_true_error(&self) -> bool { - match self.code { - FulfillmentErrorCode::Select(_) - | FulfillmentErrorCode::Project(_) - | FulfillmentErrorCode::Subtype(_, _) - | FulfillmentErrorCode::ConstEquate(_, _) => true, - FulfillmentErrorCode::Cycle(_) | FulfillmentErrorCode::Ambiguity { overflow: _ } => { - false - } - } - } -} - impl<'tcx> PolyTraitObligation<'tcx> { pub fn polarity(&self) -> ty::PredicatePolarity { self.predicate.skip_binder().polarity diff --git a/compiler/rustc_infer/src/traits/structural_impls.rs b/compiler/rustc_infer/src/traits/structural_impls.rs index b616d37e5b5e..00abf939807a 100644 --- a/compiler/rustc_infer/src/traits/structural_impls.rs +++ b/compiler/rustc_infer/src/traits/structural_impls.rs @@ -29,12 +29,6 @@ impl<'tcx, O: fmt::Debug> fmt::Debug for traits::Obligation<'tcx, O> { } } -impl<'tcx> fmt::Debug for traits::FulfillmentError<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "FulfillmentError({:?},{:?})", self.obligation, self.code) - } -} - impl<'tcx> fmt::Debug for traits::FulfillmentErrorCode<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use traits::FulfillmentErrorCode::*; diff --git a/compiler/rustc_trait_selection/src/regions.rs b/compiler/rustc_trait_selection/src/regions.rs index 5e0d7da4f06b..cca5bce03e19 100644 --- a/compiler/rustc_trait_selection/src/regions.rs +++ b/compiler/rustc_trait_selection/src/regions.rs @@ -1,3 +1,4 @@ +use crate::traits::FulfillmentError; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{InferCtxt, RegionResolutionError}; use rustc_macros::extension; @@ -27,7 +28,8 @@ impl<'tcx> InferCtxt<'tcx> { ), ty, ) - .map_err(|_| NoSolution) + // TODO: + .map_err(|_: Vec>| NoSolution) } else { Ok(ty) } diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index d28cf834032d..040bab1dfae2 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -1,3 +1,4 @@ +use std::marker::PhantomData; use std::mem; use std::ops::ControlFlow; @@ -5,14 +6,17 @@ use rustc_infer::infer::InferCtxt; use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::solve::{CandidateSource, GoalSource, MaybeCause}; use rustc_infer::traits::{ - self, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, Obligation, - ObligationCause, ObligationCauseCode, PredicateObligation, SelectionError, TraitEngine, + self, FromSolverError, FulfillmentErrorCode, FulfillmentErrorLike, MismatchedProjectionTypes, + Obligation, ObligationCause, ObligationCauseCode, PredicateObligation, SelectionError, + TraitEngine, }; use rustc_middle::bug; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::symbol::sym; +use crate::traits::FulfillmentError; + use super::eval_ctxt::GenerateProofTree; use super::inspect::{self, ProofTreeInferCtxtExt, ProofTreeVisitor}; use super::{Certainty, InferCtxtEvalExt}; @@ -28,7 +32,7 @@ use super::{Certainty, InferCtxtEvalExt}; /// /// It is also likely that we want to use slightly different datastructures /// here as this will have to deal with far more root goals than `evaluate_all`. -pub struct FulfillmentCtxt<'tcx> { +pub struct FulfillmentCtxt<'tcx, E: FulfillmentErrorLike<'tcx>> { obligations: ObligationStorage<'tcx>, /// The snapshot in which this context was created. Using the context @@ -36,6 +40,7 @@ pub struct FulfillmentCtxt<'tcx> { /// gets rolled back. Because of this we explicitly check that we only /// use the context in exactly this snapshot. usable_in_snapshot: usize, + _errors: PhantomData, } #[derive(Default)] @@ -89,8 +94,8 @@ impl<'tcx> ObligationStorage<'tcx> { } } -impl<'tcx> FulfillmentCtxt<'tcx> { - pub fn new(infcx: &InferCtxt<'tcx>) -> FulfillmentCtxt<'tcx> { +impl<'tcx, E: FulfillmentErrorLike<'tcx>> FulfillmentCtxt<'tcx, E> { + pub fn new(infcx: &InferCtxt<'tcx>) -> FulfillmentCtxt<'tcx, E> { assert!( infcx.next_trait_solver(), "new trait solver fulfillment context created when \ @@ -99,6 +104,7 @@ impl<'tcx> FulfillmentCtxt<'tcx> { FulfillmentCtxt { obligations: Default::default(), usable_in_snapshot: infcx.num_open_snapshots(), + _errors: PhantomData, } } @@ -118,7 +124,9 @@ impl<'tcx> FulfillmentCtxt<'tcx> { } } -impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { +impl<'tcx, E: FromSolverError<'tcx, NextSolverError<'tcx>>> TraitEngine<'tcx, E> + for FulfillmentCtxt<'tcx, E> +{ #[instrument(level = "trace", skip(self, infcx))] fn register_predicate_obligation( &mut self, @@ -129,24 +137,22 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { self.obligations.register(obligation); } - fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec> { - let mut errors: Vec<_> = self - .obligations + fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec { + self.obligations .pending .drain(..) - .map(|obligation| fulfillment_error_for_stalled(infcx, obligation)) - .collect(); - - errors.extend(self.obligations.overflowed.drain(..).map(|obligation| FulfillmentError { - obligation: find_best_leaf_obligation(infcx, &obligation, true), - code: FulfillmentErrorCode::Ambiguity { overflow: Some(true) }, - root_obligation: obligation, - })); - - errors + .map(|obligation| NextSolverError::Ambiguity(obligation)) + .chain( + self.obligations + .overflowed + .drain(..) + .map(|obligation| NextSolverError::Overflow(obligation)), + ) + .map(|e| E::from_solver_error(infcx, e)) + .collect() } - fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec> { + fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec { assert_eq!(self.usable_in_snapshot, infcx.num_open_snapshots()); let mut errors = Vec::new(); for i in 0.. { @@ -164,7 +170,10 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { let (changed, certainty) = match result { Ok(result) => result, Err(NoSolution) => { - errors.push(fulfillment_error_for_no_solution(infcx, obligation)); + errors.push(E::from_solver_error( + infcx, + NextSolverError::TrueError(obligation), + )); continue; } }; @@ -195,6 +204,28 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { } } +pub enum NextSolverError<'tcx> { + TrueError(PredicateObligation<'tcx>), + Ambiguity(PredicateObligation<'tcx>), + Overflow(PredicateObligation<'tcx>), +} + +impl<'tcx> FromSolverError<'tcx, NextSolverError<'tcx>> for FulfillmentError<'tcx> { + fn from_solver_error(infcx: &InferCtxt<'tcx>, error: NextSolverError<'tcx>) -> Self { + match error { + NextSolverError::TrueError(obligation) => { + fulfillment_error_for_no_solution(infcx, obligation) + } + NextSolverError::Ambiguity(obligation) => { + fulfillment_error_for_stalled(infcx, obligation) + } + NextSolverError::Overflow(obligation) => { + fulfillment_error_for_overflow(infcx, obligation) + } + } + } +} + fn fulfillment_error_for_no_solution<'tcx>( infcx: &InferCtxt<'tcx>, root_obligation: PredicateObligation<'tcx>, @@ -280,6 +311,17 @@ fn fulfillment_error_for_stalled<'tcx>( } } +fn fulfillment_error_for_overflow<'tcx>( + infcx: &InferCtxt<'tcx>, + root_obligation: PredicateObligation<'tcx>, +) -> FulfillmentError<'tcx> { + FulfillmentError { + obligation: find_best_leaf_obligation(infcx, &root_obligation, true), + code: FulfillmentErrorCode::Ambiguity { overflow: Some(true) }, + root_obligation, + } +} + fn find_best_leaf_obligation<'tcx>( infcx: &InferCtxt<'tcx>, obligation: &PredicateObligation<'tcx>, diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index f9febd290fe7..ffeafd0e89f6 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -40,7 +40,7 @@ mod search_graph; mod trait_goals; pub use eval_ctxt::{EvalCtxt, GenerateProofTree, InferCtxtEvalExt, InferCtxtSelectExt}; -pub use fulfill::FulfillmentCtxt; +pub use fulfill::{FulfillmentCtxt, NextSolverError}; pub(crate) use normalize::deeply_normalize_for_diagnostics; pub use normalize::{deeply_normalize, deeply_normalize_with_skipped_universes}; diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs index 970848544c5a..f85e5d8746fd 100644 --- a/compiler/rustc_trait_selection/src/solve/normalize.rs +++ b/compiler/rustc_trait_selection/src/solve/normalize.rs @@ -1,23 +1,29 @@ +use std::marker::PhantomData; + use crate::traits::error_reporting::{OverflowCause, TypeErrCtxtExt}; use crate::traits::query::evaluate_obligation::InferCtxtExt; -use crate::traits::{BoundVarReplacer, PlaceholderReplacer}; +use crate::traits::{BoundVarReplacer, FulfillmentError, PlaceholderReplacer}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_infer::infer::at::At; use rustc_infer::infer::InferCtxt; -use rustc_infer::traits::{FulfillmentError, Obligation, TraitEngine}; +use rustc_infer::traits::{FromSolverError, FulfillmentErrorLike, Obligation, TraitEngine}; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{self, Ty, TyCtxt, UniverseIndex}; use rustc_middle::ty::{FallibleTypeFolder, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::{TypeFoldable, TypeVisitableExt}; -use super::FulfillmentCtxt; +use super::{FulfillmentCtxt, NextSolverError}; /// Deeply normalize all aliases in `value`. This does not handle inference and expects /// its input to be already fully resolved. -pub fn deeply_normalize<'tcx, T: TypeFoldable>>( +pub fn deeply_normalize< + 'tcx, + T: TypeFoldable>, + E: FromSolverError<'tcx, NextSolverError<'tcx>>, +>( at: At<'_, 'tcx>, value: T, -) -> Result>> { +) -> Result> { assert!(!value.has_escaping_bound_vars()); deeply_normalize_with_skipped_universes(at, value, vec![]) } @@ -28,29 +34,32 @@ pub fn deeply_normalize<'tcx, T: TypeFoldable>>( /// Additionally takes a list of universes which represents the binders which have been /// entered before passing `value` to the function. This is currently needed for /// `normalize_erasing_regions`, which skips binders as it walks through a type. -pub fn deeply_normalize_with_skipped_universes<'tcx, T: TypeFoldable>>( +pub fn deeply_normalize_with_skipped_universes< + 'tcx, + T: TypeFoldable>, + E: FromSolverError<'tcx, NextSolverError<'tcx>>, +>( at: At<'_, 'tcx>, value: T, universes: Vec>, -) -> Result>> { +) -> Result> { let fulfill_cx = FulfillmentCtxt::new(at.infcx); - let mut folder = NormalizationFolder { at, fulfill_cx, depth: 0, universes }; + let mut folder = + NormalizationFolder { at, fulfill_cx, depth: 0, universes, _errors: PhantomData }; value.try_fold_with(&mut folder) } -struct NormalizationFolder<'me, 'tcx> { +struct NormalizationFolder<'me, 'tcx, E: FulfillmentErrorLike<'tcx>> { at: At<'me, 'tcx>, - fulfill_cx: FulfillmentCtxt<'tcx>, + fulfill_cx: FulfillmentCtxt<'tcx, E>, depth: usize, universes: Vec>, + _errors: PhantomData, } -impl<'tcx> NormalizationFolder<'_, 'tcx> { - fn normalize_alias_ty( - &mut self, - alias_ty: Ty<'tcx>, - ) -> Result, Vec>> { +impl<'tcx, E: FromSolverError<'tcx, NextSolverError<'tcx>>> NormalizationFolder<'_, 'tcx, E> { + fn normalize_alias_ty(&mut self, alias_ty: Ty<'tcx>) -> Result, Vec> { assert!(matches!(alias_ty.kind(), ty::Alias(..))); let infcx = self.at.infcx; @@ -101,7 +110,7 @@ impl<'tcx> NormalizationFolder<'_, 'tcx> { &mut self, ty: Ty<'tcx>, uv: ty::UnevaluatedConst<'tcx>, - ) -> Result, Vec>> { + ) -> Result, Vec> { let infcx = self.at.infcx; let tcx = infcx.tcx; let recursion_limit = tcx.recursion_limit(); @@ -141,8 +150,10 @@ impl<'tcx> NormalizationFolder<'_, 'tcx> { } } -impl<'tcx> FallibleTypeFolder> for NormalizationFolder<'_, 'tcx> { - type Error = Vec>; +impl<'tcx, E: FromSolverError<'tcx, NextSolverError<'tcx>>> FallibleTypeFolder> + for NormalizationFolder<'_, 'tcx, E> +{ + type Error = Vec; fn interner(&self) -> TyCtxt<'tcx> { self.at.infcx.tcx @@ -242,7 +253,8 @@ impl<'tcx> TypeFolder> for DeeplyNormalizeForDiagnosticsFolder<'_, ty, vec![None; ty.outer_exclusive_binder().as_usize()], ) - .unwrap_or_else(|_| ty.super_fold_with(self)) + // TODO: + .unwrap_or_else(|_: Vec>| ty.super_fold_with(self)) } fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { @@ -251,6 +263,7 @@ impl<'tcx> TypeFolder> for DeeplyNormalizeForDiagnosticsFolder<'_, ct, vec![None; ct.outer_exclusive_binder().as_usize()], ) - .unwrap_or_else(|_| ct.super_fold_with(self)) + // TODO: + .unwrap_or_else(|_: Vec>| ct.super_fold_with(self)) } } diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index ebdb032dc0e2..33eca1599121 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -11,6 +11,7 @@ use crate::solve::{deeply_normalize_for_diagnostics, inspect}; use crate::traits::select::IntercrateAmbiguityCause; use crate::traits::NormalizeExt; use crate::traits::SkipLeakCheck; +use crate::traits::{util, FulfillmentErrorCode}; use crate::traits::{ Obligation, ObligationCause, PredicateObligation, PredicateObligations, SelectionContext, }; @@ -19,7 +20,6 @@ use rustc_errors::{Diag, EmissionGuarantee}; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, TyCtxtInferExt}; -use rustc_infer::traits::{util, FulfillmentErrorCode}; use rustc_middle::bug; use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::solve::{CandidateSource, Certainty, Goal}; diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index 6fed24c49e0b..b62cd345e510 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -2,12 +2,15 @@ use std::cell::RefCell; use std::fmt::Debug; use super::FulfillmentContext; -use super::TraitEngine; +use super::{FromSolverError, TraitEngine}; use crate::regions::InferCtxtRegionExt; use crate::solve::FulfillmentCtxt as NextFulfillmentCtxt; +use crate::solve::NextSolverError; use crate::traits::error_reporting::TypeErrCtxtExt; +use crate::traits::fulfill::OldSolverError; use crate::traits::NormalizeExt; use crate::traits::StructurallyNormalizeExt; +use crate::traits::{FulfillmentError, Obligation, ObligationCause, PredicateObligation}; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -18,7 +21,6 @@ use rustc_infer::infer::canonical::{ use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::RegionResolutionError; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk}; -use rustc_infer::traits::{FulfillmentError, Obligation, ObligationCause, PredicateObligation}; use rustc_macros::extension; use rustc_middle::arena::ArenaAllocatable; use rustc_middle::traits::query::NoSolution; @@ -28,8 +30,12 @@ use rustc_middle::ty::Upcast; use rustc_middle::ty::Variance; use rustc_middle::ty::{self, Ty, TyCtxt}; -#[extension(pub trait TraitEngineExt<'tcx>)] -impl<'tcx> dyn TraitEngine<'tcx> { +#[extension(pub trait TraitEngineExt<'tcx, E>)] +impl< + 'tcx, + E: FromSolverError<'tcx, NextSolverError<'tcx>> + FromSolverError<'tcx, OldSolverError<'tcx>>, +> dyn TraitEngine<'tcx, E> +{ fn new(infcx: &InferCtxt<'tcx>) -> Box { if infcx.next_trait_solver() { Box::new(NextFulfillmentCtxt::new(infcx)) @@ -49,12 +55,16 @@ impl<'tcx> dyn TraitEngine<'tcx> { /// with obligations outside of hir or mir typeck. pub struct ObligationCtxt<'a, 'tcx> { pub infcx: &'a InferCtxt<'tcx>, - engine: RefCell>>, + engine: RefCell>>>, } impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self { - Self { infcx, engine: RefCell::new(>::new(infcx)) } + // TODO: + Self { + infcx, + engine: RefCell::new(>>::new(infcx)), + } } pub fn register_obligation(&self, obligation: PredicateObligation<'tcx>) { diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index e1afc2a35293..09fe0196fcfc 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -6,7 +6,7 @@ use rustc_data_structures::obligation_forest::ProcessResult; use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome}; use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor}; use rustc_infer::infer::DefineOpaqueTypes; -use rustc_infer::traits::ProjectionCacheKey; +use rustc_infer::traits::{FromSolverError, FulfillmentErrorLike, ProjectionCacheKey}; use rustc_infer::traits::{PolyTraitObligation, SelectionError, TraitEngine}; use rustc_middle::bug; use rustc_middle::mir::interpret::ErrorHandled; @@ -50,7 +50,7 @@ impl<'tcx> ForestObligation for PendingPredicateObligation<'tcx> { /// along. Once all type inference constraints have been generated, the /// method `select_all_or_error` can be used to report any remaining /// ambiguous cases as errors. -pub struct FulfillmentContext<'tcx> { +pub struct FulfillmentContext<'tcx, E: FulfillmentErrorLike<'tcx>> { /// A list of all obligations that have been registered with this /// fulfillment context. predicates: ObligationForest>, @@ -60,6 +60,8 @@ pub struct FulfillmentContext<'tcx> { /// gets rolled back. Because of this we explicitly check that we only /// use the context in exactly this snapshot. usable_in_snapshot: usize, + + _errors: PhantomData, } #[derive(Clone, Debug)] @@ -76,9 +78,9 @@ pub struct PendingPredicateObligation<'tcx> { #[cfg(target_pointer_width = "64")] rustc_data_structures::static_assert_size!(PendingPredicateObligation<'_>, 72); -impl<'tcx> FulfillmentContext<'tcx> { +impl<'tcx, E: FromSolverError<'tcx, OldSolverError<'tcx>>> FulfillmentContext<'tcx, E> { /// Creates a new fulfillment context. - pub(super) fn new(infcx: &InferCtxt<'tcx>) -> FulfillmentContext<'tcx> { + pub(super) fn new(infcx: &InferCtxt<'tcx>) -> FulfillmentContext<'tcx, E> { assert!( !infcx.next_trait_solver(), "old trait solver fulfillment context created when \ @@ -87,13 +89,15 @@ impl<'tcx> FulfillmentContext<'tcx> { FulfillmentContext { predicates: ObligationForest::new(), usable_in_snapshot: infcx.num_open_snapshots(), + _errors: PhantomData, } } /// Attempts to select obligations using `selcx`. - fn select(&mut self, selcx: SelectionContext<'_, 'tcx>) -> Vec> { + fn select(&mut self, selcx: SelectionContext<'_, 'tcx>) -> Vec { let span = debug_span!("select", obligation_forest_size = ?self.predicates.len()); let _enter = span.enter(); + let infcx = selcx.infcx; // Process pending obligations. let outcome: Outcome<_, _> = @@ -102,8 +106,8 @@ impl<'tcx> FulfillmentContext<'tcx> { // FIXME: if we kept the original cache key, we could mark projection // obligations as complete for the projection cache here. - let errors: Vec> = - outcome.errors.into_iter().map(to_fulfillment_error).collect(); + let errors: Vec = + outcome.errors.into_iter().map(|err| E::from_solver_error(infcx, err)).collect(); debug!( "select({} predicates remaining, {} errors) done", @@ -115,7 +119,9 @@ impl<'tcx> FulfillmentContext<'tcx> { } } -impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { +impl<'tcx, E: FromSolverError<'tcx, OldSolverError<'tcx>>> TraitEngine<'tcx, E> + for FulfillmentContext<'tcx, E> +{ #[inline] fn register_predicate_obligation( &mut self, @@ -134,18 +140,15 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { .register_obligation(PendingPredicateObligation { obligation, stalled_on: vec![] }); } - fn collect_remaining_errors( - &mut self, - _infcx: &InferCtxt<'tcx>, - ) -> Vec> { + fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec { self.predicates .to_errors(FulfillmentErrorCode::Ambiguity { overflow: None }) .into_iter() - .map(to_fulfillment_error) + .map(|err| E::from_solver_error(infcx, err)) .collect() } - fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec> { + fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec { let selcx = SelectionContext::new(infcx); self.select(selcx) } @@ -840,13 +843,15 @@ fn args_infer_vars<'a, 'tcx>( .filter_map(TyOrConstInferVar::maybe_from_generic_arg) } -fn to_fulfillment_error<'tcx>( - error: Error, FulfillmentErrorCode<'tcx>>, -) -> FulfillmentError<'tcx> { - let mut iter = error.backtrace.into_iter(); - let obligation = iter.next().unwrap().obligation; - // The root obligation is the last item in the backtrace - if there's only - // one item, then it's the same as the main obligation - let root_obligation = iter.next_back().map_or_else(|| obligation.clone(), |e| e.obligation); - FulfillmentError::new(obligation, error.error, root_obligation) +pub type OldSolverError<'tcx> = Error, FulfillmentErrorCode<'tcx>>; + +impl<'tcx> FromSolverError<'tcx, OldSolverError<'tcx>> for FulfillmentError<'tcx> { + fn from_solver_error(_infcx: &InferCtxt<'tcx>, error: OldSolverError<'tcx>) -> Self { + let mut iter = error.backtrace.into_iter(); + let obligation = iter.next().unwrap().obligation; + // The root obligation is the last item in the backtrace - if there's only + // one item, then it's the same as the main obligation + let root_obligation = iter.next_back().map_or_else(|| obligation.clone(), |e| e.obligation); + FulfillmentError::new(obligation, error.error, root_obligation) + } } diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs index a1094d982768..8b4594926474 100644 --- a/compiler/rustc_trait_selection/src/traits/misc.rs +++ b/compiler/rustc_trait_selection/src/traits/misc.rs @@ -1,13 +1,13 @@ //! Miscellaneous type-system utilities that are too small to deserve their own modules. use crate::regions::InferCtxtRegionExt; -use crate::traits::{self, ObligationCause}; +use crate::traits::{self, FulfillmentError, ObligationCause}; use hir::LangItem; use rustc_data_structures::fx::FxIndexSet; use rustc_hir as hir; +use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt}; -use rustc_infer::{infer::outlives::env::OutlivesEnvironment, traits::FulfillmentError}; use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeVisitableExt}; use super::outlives_bounds::InferCtxtExt; diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 786ab091e915..990a88f748e6 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -70,6 +70,49 @@ pub use self::util::{with_replaced_escaping_bound_vars, BoundVarReplacer, Placeh pub use rustc_infer::traits::*; +pub struct FulfillmentError<'tcx> { + pub obligation: PredicateObligation<'tcx>, + pub code: FulfillmentErrorCode<'tcx>, + /// Diagnostics only: the 'root' obligation which resulted in + /// the failure to process `obligation`. This is the obligation + /// that was initially passed to `register_predicate_obligation` + pub root_obligation: PredicateObligation<'tcx>, +} + +impl<'tcx> FulfillmentError<'tcx> { + pub fn new( + obligation: PredicateObligation<'tcx>, + code: FulfillmentErrorCode<'tcx>, + root_obligation: PredicateObligation<'tcx>, + ) -> FulfillmentError<'tcx> { + FulfillmentError { obligation, code, root_obligation } + } + + pub fn is_true_error(&self) -> bool { + match self.code { + FulfillmentErrorCode::Select(_) + | FulfillmentErrorCode::Project(_) + | FulfillmentErrorCode::Subtype(_, _) + | FulfillmentErrorCode::ConstEquate(_, _) => true, + FulfillmentErrorCode::Cycle(_) | FulfillmentErrorCode::Ambiguity { overflow: _ } => { + false + } + } + } +} + +impl<'tcx> FulfillmentErrorLike<'tcx> for FulfillmentError<'tcx> { + fn is_true_error(&self) -> bool { + self.is_true_error() + } +} + +impl<'tcx> Debug for FulfillmentError<'tcx> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "FulfillmentError({:?},{:?})", self.obligation, self.code) + } +} + /// Whether to skip the leak check, as part of a future compatibility warning step. /// /// The "default" for skip-leak-check corresponds to the current diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index d10aee2d4e29..4e5ca2ee92e1 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -3,11 +3,13 @@ use super::error_reporting::OverflowCause; use super::error_reporting::TypeErrCtxtExt; use super::SelectionContext; use super::{project, with_replaced_escaping_bound_vars, BoundVarReplacer, PlaceholderReplacer}; +use crate::solve::NextSolverError; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_infer::infer::at::At; use rustc_infer::infer::InferOk; +use rustc_infer::traits::FromSolverError; use rustc_infer::traits::PredicateObligation; -use rustc_infer::traits::{FulfillmentError, Normalized, Obligation, TraitEngine}; +use rustc_infer::traits::{Normalized, Obligation, TraitEngine}; use rustc_macros::extension; use rustc_middle::traits::{ObligationCause, ObligationCauseCode, Reveal}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFolder}; @@ -44,11 +46,14 @@ impl<'tcx> At<'_, 'tcx> { /// existing fulfillment context in the old solver. Once we also eagerly prove goals with /// the old solver or have removed the old solver, remove `traits::fully_normalize` and /// rename this function to `At::fully_normalize`. - fn deeply_normalize>>( + fn deeply_normalize< + T: TypeFoldable>, + E: FromSolverError<'tcx, NextSolverError<'tcx>>, + >( self, value: T, - fulfill_cx: &mut dyn TraitEngine<'tcx>, - ) -> Result>> { + fulfill_cx: &mut dyn TraitEngine<'tcx, E>, + ) -> Result> { if self.infcx.next_trait_solver() { crate::solve::deeply_normalize(self, value) } else { diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 1b5ffeebc01f..2c0103e40dff 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -9,10 +9,10 @@ use crate::traits::error_reporting::OverflowCause; use crate::traits::error_reporting::TypeErrCtxtExt; use crate::traits::normalize::needs_normalization; use crate::traits::{BoundVarReplacer, PlaceholderReplacer}; +use crate::traits::{FulfillmentError, Normalized}; use crate::traits::{ObligationCause, PredicateObligation, Reveal}; use rustc_data_structures::sso::SsoHashMap; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_infer::traits::Normalized; use rustc_macros::extension; use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable}; use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt}; @@ -76,7 +76,10 @@ impl<'cx, 'tcx> At<'cx, 'tcx> { }; if self.infcx.next_trait_solver() { - match crate::solve::deeply_normalize_with_skipped_universes(self, value, universes) { + // TODO: + match crate::solve::deeply_normalize_with_skipped_universes::<_, FulfillmentError<'tcx>>( + self, value, universes, + ) { Ok(value) => return Ok(Normalized { value, obligations: vec![] }), Err(_errors) => { return Err(NoSolution); diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs index 00cc77e71e72..a1bbd21f8296 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs @@ -1,6 +1,7 @@ use crate::solve; use crate::traits::query::NoSolution; use crate::traits::wf; +use crate::traits::FulfillmentError; use crate::traits::ObligationCtxt; use rustc_infer::infer::canonical::Canonical; @@ -266,7 +267,8 @@ pub fn compute_implied_outlives_bounds_compat_inner<'tcx>( ocx.infcx.at(&ObligationCause::dummy(), param_env), ty_a, ) - .map_err(|_errs| NoSolution)?; + // TODO: + .map_err(|_errs: Vec>| NoSolution)?; } let mut components = smallvec![]; push_outlives_components(tcx, ty_a, &mut components); diff --git a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs index 96a06e0c1691..a160fc033a2c 100644 --- a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs @@ -1,5 +1,5 @@ use rustc_infer::infer::at::At; -use rustc_infer::traits::{FulfillmentError, TraitEngine}; +use rustc_infer::traits::{FulfillmentErrorLike, TraitEngine}; use rustc_macros::extension; use rustc_middle::ty::{self, Ty}; @@ -7,11 +7,11 @@ use crate::traits::{NormalizeExt, Obligation}; #[extension(pub trait StructurallyNormalizeExt<'tcx>)] impl<'tcx> At<'_, 'tcx> { - fn structurally_normalize( + fn structurally_normalize>( &self, ty: Ty<'tcx>, - fulfill_cx: &mut dyn TraitEngine<'tcx>, - ) -> Result, Vec>> { + fulfill_cx: &mut dyn TraitEngine<'tcx, E>, + ) -> Result, Vec> { assert!(!ty.is_ty_var(), "should have resolved vars before calling"); if self.infcx.next_trait_solver() { From eb0a70a5578be0ae164cb802898ea98d41e95f13 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 1 Jun 2024 14:51:31 -0400 Subject: [PATCH 183/211] Opt-in diagnostics reporting to avoid doing extra work in the new solver --- .../src/diagnostics/conflict_errors.rs | 2 +- .../src/region_infer/opaque_types.rs | 2 +- .../src/check_consts/check.rs | 2 +- .../rustc_hir_analysis/src/check/check.rs | 4 +- .../src/check/compare_impl_item.rs | 31 +++-- .../rustc_hir_analysis/src/check/dropck.rs | 2 +- .../rustc_hir_analysis/src/check/entry.rs | 2 +- compiler/rustc_hir_analysis/src/check/mod.rs | 2 +- .../rustc_hir_analysis/src/check/wfcheck.rs | 8 +- .../src/coherence/builtin.rs | 4 +- .../src/hir_ty_lowering/mod.rs | 2 +- .../rustc_hir_analysis/src/hir_wf_check.rs | 2 +- .../src/impl_wf_check/min_specialization.rs | 2 +- compiler/rustc_hir_typeck/src/expr.rs | 2 +- compiler/rustc_hir_typeck/src/method/probe.rs | 2 +- compiler/rustc_hir_typeck/src/op.rs | 2 +- compiler/rustc_mir_transform/src/coroutine.rs | 2 +- compiler/rustc_passes/src/check_attr.rs | 2 +- compiler/rustc_passes/src/layout_test.rs | 2 +- compiler/rustc_trait_selection/src/infer.rs | 18 +-- .../src/solve/fulfill.rs | 13 +- .../src/solve/inspect/analyse.rs | 1 + .../src/traits/coherence.rs | 2 +- .../src/traits/engine.rs | 116 +++++++++++------- .../src/traits/fulfill.rs | 16 ++- .../rustc_trait_selection/src/traits/misc.rs | 2 +- .../rustc_trait_selection/src/traits/mod.rs | 26 +++- compiler/rustc_traits/src/codegen.rs | 3 +- .../src/normalize_projection_ty.rs | 9 +- compiler/rustc_traits/src/type_op.rs | 22 ++-- .../clippy_lints/src/future_not_send.rs | 2 +- 31 files changed, 200 insertions(+), 107 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index cde7ac94e357..821a90366547 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1347,7 +1347,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { return; }; // Try to find predicates on *generic params* that would allow copying `ty` - let ocx = ObligationCtxt::new(self.infcx); + let ocx = ObligationCtxt::new_with_diagnostics(self.infcx); let cause = ObligationCause::misc(span, self.mir_def_id()); ocx.register_bound(cause, self.param_env, ty, def_id); diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index f601a9d70739..06adb686ed48 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -340,7 +340,7 @@ fn check_opaque_type_well_formed<'tcx>( .with_next_trait_solver(next_trait_solver) .with_opaque_type_inference(parent_def_id) .build(); - let ocx = ObligationCtxt::new(&infcx); + let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let identity_args = GenericArgs::identity_for_item(tcx, def_id); // Require that the hidden type actually fulfills all the bounds of the opaque type, even without diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index 5fbf5b41109f..9e01c59a96f9 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -735,7 +735,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { // which path expressions are getting called on and which path expressions are only used // as function pointers. This is required for correctness. let infcx = tcx.infer_ctxt().build(); - let ocx = ObligationCtxt::new(&infcx); + let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let predicates = tcx.predicates_of(callee).instantiate(tcx, fn_args); let cause = ObligationCause::new( diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 3904f14b0f6e..76b6cbd6e531 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -342,7 +342,7 @@ fn check_opaque_meets_bounds<'tcx>( let param_env = tcx.param_env(defining_use_anchor); let infcx = tcx.infer_ctxt().with_opaque_type_inference(defining_use_anchor).build(); - let ocx = ObligationCtxt::new(&infcx); + let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let args = match *origin { hir::OpaqueTyOrigin::FnReturn(parent) @@ -1727,7 +1727,7 @@ pub(super) fn check_coroutine_obligations( .with_opaque_type_inference(def_id) .build(); - let ocx = ObligationCtxt::new(&infcx); + let ocx = ObligationCtxt::new_with_diagnostics(&infcx); for (predicate, cause) in &typeck_results.coroutine_stalled_predicates { ocx.register_obligation(Obligation::new(tcx, cause.clone(), param_env, *predicate)); } 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 17db1c07383f..594d28eda7ac 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -10,7 +10,7 @@ use rustc_hir::intravisit; use rustc_hir::{GenericParamKind, ImplItemKind}; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; -use rustc_infer::traits::util; +use rustc_infer::traits::{util, FulfillmentErrorLike}; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::util::ExplicitSelf; @@ -225,7 +225,7 @@ fn compare_method_predicate_entailment<'tcx>( let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause); let infcx = &tcx.infer_ctxt().build(); - let ocx = ObligationCtxt::new(infcx); + let ocx = ObligationCtxt::new_with_diagnostics(infcx); debug!("compare_impl_method: caller_bounds={:?}", param_env.caller_bounds()); @@ -493,7 +493,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( ); let infcx = &tcx.infer_ctxt().build(); - let ocx = ObligationCtxt::new(infcx); + let ocx = ObligationCtxt::new_with_diagnostics(infcx); // Normalize the impl signature with fresh variables for lifetime inference. let misc_cause = ObligationCause::misc(return_span, impl_m_def_id); @@ -764,17 +764,23 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( Ok(&*tcx.arena.alloc(remapped_types)) } -struct ImplTraitInTraitCollector<'a, 'tcx> { - ocx: &'a ObligationCtxt<'a, 'tcx>, +struct ImplTraitInTraitCollector<'a, 'tcx, E> +where + E: FulfillmentErrorLike<'tcx>, +{ + ocx: &'a ObligationCtxt<'a, 'tcx, E>, types: FxIndexMap, ty::GenericArgsRef<'tcx>)>, span: Span, param_env: ty::ParamEnv<'tcx>, body_id: LocalDefId, } -impl<'a, 'tcx> ImplTraitInTraitCollector<'a, 'tcx> { +impl<'a, 'tcx, E> ImplTraitInTraitCollector<'a, 'tcx, E> +where + E: FulfillmentErrorLike<'tcx>, +{ fn new( - ocx: &'a ObligationCtxt<'a, 'tcx>, + ocx: &'a ObligationCtxt<'a, 'tcx, E>, span: Span, param_env: ty::ParamEnv<'tcx>, body_id: LocalDefId, @@ -783,7 +789,10 @@ impl<'a, 'tcx> ImplTraitInTraitCollector<'a, 'tcx> { } } -impl<'tcx> TypeFolder> for ImplTraitInTraitCollector<'_, 'tcx> { +impl<'tcx, E> TypeFolder> for ImplTraitInTraitCollector<'_, 'tcx, E> +where + E: FulfillmentErrorLike<'tcx>, +{ fn interner(&self) -> TyCtxt<'tcx> { self.ocx.infcx.tcx } @@ -1777,7 +1786,7 @@ fn compare_const_predicate_entailment<'tcx>( ); let infcx = tcx.infer_ctxt().build(); - let ocx = ObligationCtxt::new(&infcx); + let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let impl_ct_own_bounds = impl_ct_predicates.instantiate_own(tcx, impl_args); for (predicate, span) in impl_ct_own_bounds { @@ -1910,7 +1919,7 @@ fn compare_type_predicate_entailment<'tcx>( let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds.predicates), Reveal::UserFacing); let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause); let infcx = tcx.infer_ctxt().build(); - let ocx = ObligationCtxt::new(&infcx); + let ocx = ObligationCtxt::new_with_diagnostics(&infcx); debug!("compare_type_predicate_entailment: caller_bounds={:?}", param_env.caller_bounds()); @@ -1977,7 +1986,7 @@ pub(super) fn check_type_bounds<'tcx>( let rebased_args = impl_ty_args.rebase_onto(tcx, container_id, impl_trait_ref.args); let infcx = tcx.infer_ctxt().build(); - let ocx = ObligationCtxt::new(&infcx); + let ocx = ObligationCtxt::new_with_diagnostics(&infcx); // A synthetic impl Trait for RPITIT desugaring has no HIR, which we currently use to get the // span for an impl's associated type. Instead, for these, use the def_span for the synthesized diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs index be412dde9680..8ec6dd12a78d 100644 --- a/compiler/rustc_hir_analysis/src/check/dropck.rs +++ b/compiler/rustc_hir_analysis/src/check/dropck.rs @@ -123,7 +123,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( adt_to_impl_args: GenericArgsRef<'tcx>, ) -> Result<(), ErrorGuaranteed> { let infcx = tcx.infer_ctxt().build(); - let ocx = ObligationCtxt::new(&infcx); + let ocx = ObligationCtxt::new_with_diagnostics(&infcx); // Take the param-env of the adt and instantiate the args that show up in // the implementation's self type. This gives us the assumptions that the diff --git a/compiler/rustc_hir_analysis/src/check/entry.rs b/compiler/rustc_hir_analysis/src/check/entry.rs index 25ac31c16c7c..cc52a7658020 100644 --- a/compiler/rustc_hir_analysis/src/check/entry.rs +++ b/compiler/rustc_hir_analysis/src/check/entry.rs @@ -133,7 +133,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { main_diagnostics_def_id, ObligationCauseCode::MainFunctionType, ); - let ocx = traits::ObligationCtxt::new(&infcx); + let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx); let norm_return_ty = ocx.normalize(&cause, param_env, return_ty); ocx.register_bound(cause, param_env, norm_return_ty, term_did); let errors = ocx.select_all_or_error(); diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 149e7737e309..da66e1f34fd9 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -599,7 +599,7 @@ pub fn check_function_signature<'tcx>( let param_env = ty::ParamEnv::empty(); let infcx = &tcx.infer_ctxt().build(); - let ocx = ObligationCtxt::new(infcx); + let ocx = ObligationCtxt::new_with_diagnostics(infcx); let actual_sig = tcx.fn_sig(fn_id).instantiate_identity(); diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 81e3d8c7ece2..750e558be7c9 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -37,7 +37,7 @@ use rustc_trait_selection::traits::misc::{ use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; use rustc_trait_selection::traits::{ - self, ObligationCause, ObligationCauseCode, ObligationCtxt, WellFormedLoc, + self, FulfillmentError, ObligationCause, ObligationCauseCode, ObligationCtxt, WellFormedLoc, }; use rustc_type_ir::TypeFlags; @@ -45,13 +45,13 @@ use std::cell::LazyCell; use std::ops::{ControlFlow, Deref}; pub(super) struct WfCheckingCtxt<'a, 'tcx> { - pub(super) ocx: ObligationCtxt<'a, 'tcx>, + pub(super) ocx: ObligationCtxt<'a, 'tcx, FulfillmentError<'tcx>>, span: Span, body_def_id: LocalDefId, param_env: ty::ParamEnv<'tcx>, } impl<'a, 'tcx> Deref for WfCheckingCtxt<'a, 'tcx> { - type Target = ObligationCtxt<'a, 'tcx>; + type Target = ObligationCtxt<'a, 'tcx, FulfillmentError<'tcx>>; fn deref(&self) -> &Self::Target { &self.ocx } @@ -106,7 +106,7 @@ where { let param_env = tcx.param_env(body_def_id); let infcx = &tcx.infer_ctxt().build(); - let ocx = ObligationCtxt::new(infcx); + let ocx = ObligationCtxt::new_with_diagnostics(infcx); let mut wfcx = WfCheckingCtxt { ocx, span, body_def_id, param_env }; diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 84771978a46c..61adb7a3cbae 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -267,7 +267,7 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<() .join(", "), })); } else { - let ocx = ObligationCtxt::new(&infcx); + let ocx = ObligationCtxt::new_with_diagnostics(&infcx); for field in coerced_fields { ocx.register_obligation(Obligation::new( tcx, @@ -480,7 +480,7 @@ pub fn coerce_unsized_info<'tcx>( }; // Register an obligation for `A: Trait`. - let ocx = ObligationCtxt::new(&infcx); + let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let cause = traits::ObligationCause::misc(span, impl_did); let obligation = Obligation::new( 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 54b7f7f36ed2..e385716fbfb0 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -1298,7 +1298,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .copied() .filter(|&(impl_, _)| { infcx.probe(|_| { - let ocx = ObligationCtxt::new(infcx); + let ocx = ObligationCtxt::new_with_diagnostics(infcx); let self_ty = ocx.normalize(&ObligationCause::dummy(), param_env, self_ty); let impl_args = infcx.fresh_args_for_item(span, impl_); diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index 10101aa046e5..3e15fddf559f 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -67,7 +67,7 @@ fn diagnostic_hir_wf_check<'tcx>( impl<'tcx> Visitor<'tcx> for HirWfCheck<'tcx> { fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) { let infcx = self.tcx.infer_ctxt().build(); - let ocx = ObligationCtxt::new(&infcx); + let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let tcx_ty = self.icx.lower_ty(ty); // This visitor can walk into binders, resulting in the `tcx_ty` to diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index 6967cb4d9d0b..f3ce3ab66553 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -196,7 +196,7 @@ fn get_impl_args( impl2_node: Node, ) -> Result<(GenericArgsRef<'_>, GenericArgsRef<'_>), ErrorGuaranteed> { let infcx = &tcx.infer_ctxt().build(); - let ocx = ObligationCtxt::new(infcx); + let ocx = ObligationCtxt::new_with_diagnostics(infcx); let param_env = tcx.param_env(impl1_def_id); let impl1_span = tcx.def_span(impl1_def_id); let assumed_wf_types = ocx.assumed_wf_types_and_report_errors(param_env, impl1_def_id)?; diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 2f92a304bf03..3d88c4255245 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -3049,7 +3049,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.commit_if_ok(|snapshot| { let outer_universe = self.universe(); - let ocx = ObligationCtxt::new(self); + let ocx = ObligationCtxt::new_with_diagnostics(self); let impl_args = self.fresh_args_for_item(base_expr.span, impl_def_id); let impl_trait_ref = self.tcx.impl_trait_ref(impl_def_id).unwrap().instantiate(self.tcx, impl_args); diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 97a74b55c535..12ced49f92ff 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -1390,7 +1390,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let mut result = ProbeResult::Match; let cause = &self.misc(self.span); - let ocx = ObligationCtxt::new(self); + let ocx = ObligationCtxt::new_with_diagnostics(self); let mut trait_predicate = None; let (mut xform_self_ty, mut xform_ret_ty); diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index 25b74dca12fc..d774ae2146aa 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -928,7 +928,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (obligation, _) = self.obligation_for_method(cause, trait_did, lhs_ty, Some(input_types)); // FIXME: This should potentially just add the obligation to the `FnCtxt` - let ocx = ObligationCtxt::new(&self.infcx); + let ocx = ObligationCtxt::new_with_diagnostics(&self.infcx); ocx.register_obligation(obligation); Err(ocx.select_all_or_error()) } diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index ade2ac0080e5..84512e81637e 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -1608,7 +1608,7 @@ fn check_field_tys_sized<'tcx>( let infcx = tcx.infer_ctxt().ignoring_regions().build(); let param_env = tcx.param_env(def_id); - let ocx = ObligationCtxt::new(&infcx); + let ocx = ObligationCtxt::new_with_diagnostics(&infcx); for field_ty in &coroutine_layout.field_tys { ocx.register_bound( ObligationCause::new( diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 4fe84b91b8b1..39cb48c1af3a 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -2321,7 +2321,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { let param_env = ty::ParamEnv::empty(); let infcx = tcx.infer_ctxt().build(); - let ocx = ObligationCtxt::new(&infcx); + let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let span = tcx.def_span(def_id); let fresh_args = infcx.fresh_args_for_item(span, def_id.to_def_id()); diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs index 82d43f078ee2..c9a476504562 100644 --- a/compiler/rustc_passes/src/layout_test.rs +++ b/compiler/rustc_passes/src/layout_test.rs @@ -54,7 +54,7 @@ pub fn ensure_wf<'tcx>( pred, ); let infcx = tcx.infer_ctxt().build(); - let ocx = traits::ObligationCtxt::new(&infcx); + let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx); ocx.register_obligation(obligation); let errors = ocx.select_all_or_error(); if !errors.is_empty() { diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index fc852293dff0..f5d78430c978 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -1,14 +1,16 @@ +use crate::solve::NextSolverError; use crate::traits::query::evaluate_obligation::InferCtxtExt as _; -use crate::traits::{self, ObligationCtxt, SelectionContext}; +use crate::traits::{ + self, FromSolverError, Obligation, ObligationCause, ObligationCtxt, OldSolverError, + SelectionContext, +}; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; -use rustc_infer::traits::Obligation; use rustc_macros::extension; use rustc_middle::arena::ArenaAllocatable; use rustc_middle::infer::canonical::{Canonical, CanonicalQueryResponse, QueryResponse}; use rustc_middle::traits::query::NoSolution; -use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_middle::ty::{GenericArg, Upcast}; use rustc_span::DUMMY_SP; @@ -94,7 +96,7 @@ impl<'tcx> InferCtxt<'tcx> { ty::TraitRef::new(self.tcx, trait_def_id, [ty]), )) { Ok(Some(selection)) => { - let ocx = ObligationCtxt::new(self); + let ocx = ObligationCtxt::new_with_diagnostics(self); ocx.register_obligations(selection.nested_obligations()); Some(ocx.select_all_or_error()) } @@ -122,19 +124,21 @@ impl<'tcx> InferCtxtBuilder<'tcx> { /// bound for the closure and in part because it is convenient to /// have `'tcx` be free on this function so that we can talk about /// `K: TypeFoldable>`.) - fn enter_canonical_trait_query( + fn enter_canonical_trait_query( self, canonical_key: &Canonical<'tcx, K>, - operation: impl FnOnce(&ObligationCtxt<'_, 'tcx>, K) -> Result, + operation: impl FnOnce(&ObligationCtxt<'_, 'tcx, E>, K) -> Result, ) -> Result, NoSolution> where K: TypeFoldable>, R: Debug + TypeFoldable>, Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>, + E: FromSolverError<'tcx, NextSolverError<'tcx>> + + FromSolverError<'tcx, OldSolverError<'tcx>>, { let (infcx, key, canonical_inference_vars) = self.build_with_canonical(DUMMY_SP, canonical_key); - let ocx = ObligationCtxt::new(&infcx); + let ocx = ObligationCtxt::new_generic(&infcx); let value = operation(&ocx, key)?; ocx.make_canonicalized_query_response(canonical_inference_vars, value) } diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 040bab1dfae2..d92c903a76ed 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -15,7 +15,7 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::symbol::sym; -use crate::traits::FulfillmentError; +use crate::traits::{FulfillmentError, ScrubbedTraitError}; use super::eval_ctxt::GenerateProofTree; use super::inspect::{self, ProofTreeInferCtxtExt, ProofTreeVisitor}; @@ -226,6 +226,17 @@ impl<'tcx> FromSolverError<'tcx, NextSolverError<'tcx>> for FulfillmentError<'tc } } +impl<'tcx> FromSolverError<'tcx, NextSolverError<'tcx>> for ScrubbedTraitError { + fn from_solver_error(_infcx: &InferCtxt<'tcx>, error: NextSolverError<'tcx>) -> Self { + match error { + NextSolverError::TrueError(_) => ScrubbedTraitError::TrueError, + NextSolverError::Ambiguity(_) | NextSolverError::Overflow(_) => { + ScrubbedTraitError::Ambiguity + } + } + } +} + fn fulfillment_error_for_no_solution<'tcx>( infcx: &InferCtxt<'tcx>, root_obligation: PredicateObligation<'tcx>, diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index 1f27978e5a62..dca14e20fb31 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -12,6 +12,7 @@ use rustc_ast_ir::try_visit; use rustc_ast_ir::visit::VisitorResult; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk}; +use rustc_infer::traits::FulfillmentErrorLike as _; use rustc_macros::extension; use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::solve::{inspect, QueryResult}; diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 33eca1599121..7723f2229bf9 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -360,7 +360,7 @@ fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>( let infcx = selcx.infcx; if infcx.next_trait_solver() { - let ocx = ObligationCtxt::new(infcx); + let ocx = ObligationCtxt::new_with_diagnostics(infcx); ocx.register_obligations(obligations.iter().cloned()); let errors_and_ambiguities = ocx.select_all_or_error(); // We only care about the obligations that are *definitely* true errors. diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index b62cd345e510..333fd4556e3d 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -1,8 +1,8 @@ use std::cell::RefCell; use std::fmt::Debug; -use super::FulfillmentContext; use super::{FromSolverError, TraitEngine}; +use super::{FulfillmentContext, ScrubbedTraitError}; use crate::regions::InferCtxtRegionExt; use crate::solve::FulfillmentCtxt as NextFulfillmentCtxt; use crate::solve::NextSolverError; @@ -21,6 +21,7 @@ use rustc_infer::infer::canonical::{ use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::RegionResolutionError; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk}; +use rustc_infer::traits::FulfillmentErrorLike; use rustc_macros::extension; use rustc_middle::arena::ArenaAllocatable; use rustc_middle::traits::query::NoSolution; @@ -53,20 +54,36 @@ impl< /// Used if you want to have pleasant experience when dealing /// with obligations outside of hir or mir typeck. -pub struct ObligationCtxt<'a, 'tcx> { +pub struct ObligationCtxt<'a, 'tcx, E = ScrubbedTraitError> { pub infcx: &'a InferCtxt<'tcx>, - engine: RefCell>>>, + engine: RefCell>>, } -impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { - pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self { - // TODO: - Self { - infcx, - engine: RefCell::new(>>::new(infcx)), - } +impl<'a, 'tcx> ObligationCtxt<'a, 'tcx, FulfillmentError<'tcx>> { + pub fn new_with_diagnostics(infcx: &'a InferCtxt<'tcx>) -> Self { + Self { infcx, engine: RefCell::new(>::new(infcx)) } } +} +impl<'a, 'tcx> ObligationCtxt<'a, 'tcx, ScrubbedTraitError> { + pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self { + Self { infcx, engine: RefCell::new(>::new(infcx)) } + } +} + +impl<'a, 'tcx, E> ObligationCtxt<'a, 'tcx, E> +where + E: FromSolverError<'tcx, NextSolverError<'tcx>> + FromSolverError<'tcx, OldSolverError<'tcx>>, +{ + pub fn new_generic(infcx: &'a InferCtxt<'tcx>) -> Self { + Self { infcx, engine: RefCell::new(>::new(infcx)) } + } +} + +impl<'a, 'tcx, E> ObligationCtxt<'a, 'tcx, E> +where + E: FulfillmentErrorLike<'tcx>, +{ pub fn register_obligation(&self, obligation: PredicateObligation<'tcx>) { self.engine.borrow_mut().register_predicate_obligation(self.infcx, obligation); } @@ -118,26 +135,6 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { self.register_infer_ok_obligations(infer_ok) } - pub fn deeply_normalize>>( - &self, - cause: &ObligationCause<'tcx>, - param_env: ty::ParamEnv<'tcx>, - value: T, - ) -> Result>> { - self.infcx.at(cause, param_env).deeply_normalize(value, &mut **self.engine.borrow_mut()) - } - - pub fn structurally_normalize( - &self, - cause: &ObligationCause<'tcx>, - param_env: ty::ParamEnv<'tcx>, - value: Ty<'tcx>, - ) -> Result, Vec>> { - self.infcx - .at(cause, param_env) - .structurally_normalize(value, &mut **self.engine.borrow_mut()) - } - pub fn eq>( &self, cause: &ObligationCause<'tcx>, @@ -194,12 +191,12 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { } #[must_use] - pub fn select_where_possible(&self) -> Vec> { + pub fn select_where_possible(&self) -> Vec { self.engine.borrow_mut().select_where_possible(self.infcx) } #[must_use] - pub fn select_all_or_error(&self) -> Vec> { + pub fn select_all_or_error(&self) -> Vec { self.engine.borrow_mut().select_all_or_error(self.infcx) } @@ -244,6 +241,24 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { self.infcx.resolve_regions(outlives_env) } + pub fn make_canonicalized_query_response( + &self, + inference_vars: CanonicalVarValues<'tcx>, + answer: T, + ) -> Result, NoSolution> + where + T: Debug + TypeFoldable>, + Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable<'tcx>, + { + self.infcx.make_canonicalized_query_response( + inference_vars, + answer, + &mut **self.engine.borrow_mut(), + ) + } +} + +impl<'tcx> ObligationCtxt<'_, 'tcx, FulfillmentError<'tcx>> { pub fn assumed_wf_types_and_report_errors( &self, param_env: ty::ParamEnv<'tcx>, @@ -252,12 +267,17 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { self.assumed_wf_types(param_env, def_id) .map_err(|errors| self.infcx.err_ctxt().report_fulfillment_errors(errors)) } +} +impl<'tcx, E> ObligationCtxt<'_, 'tcx, E> +where + E: FromSolverError<'tcx, NextSolverError<'tcx>>, +{ pub fn assumed_wf_types( &self, param_env: ty::ParamEnv<'tcx>, def_id: LocalDefId, - ) -> Result>, Vec>> { + ) -> Result>, Vec> { let tcx = self.infcx.tcx; let mut implied_bounds = FxIndexSet::default(); let mut errors = Vec::new(); @@ -289,19 +309,23 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { if errors.is_empty() { Ok(implied_bounds) } else { Err(errors) } } - pub fn make_canonicalized_query_response( + pub fn deeply_normalize>>( &self, - inference_vars: CanonicalVarValues<'tcx>, - answer: T, - ) -> Result, NoSolution> - where - T: Debug + TypeFoldable>, - Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable<'tcx>, - { - self.infcx.make_canonicalized_query_response( - inference_vars, - answer, - &mut **self.engine.borrow_mut(), - ) + cause: &ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, + value: T, + ) -> Result> { + self.infcx.at(cause, param_env).deeply_normalize(value, &mut **self.engine.borrow_mut()) + } + + pub fn structurally_normalize( + &self, + cause: &ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, + value: Ty<'tcx>, + ) -> Result, Vec> { + self.infcx + .at(cause, param_env) + .structurally_normalize(value, &mut **self.engine.borrow_mut()) } } diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 09fe0196fcfc..8746cfa37e2e 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -16,13 +16,13 @@ use rustc_middle::ty::GenericArgsRef; use rustc_middle::ty::{self, Binder, Const, TypeVisitableExt}; use std::marker::PhantomData; -use super::const_evaluatable; use super::project::{self, ProjectAndUnifyResult}; use super::select::SelectionContext; use super::wf; use super::EvaluationResult; use super::PredicateObligation; use super::Unimplemented; +use super::{const_evaluatable, ScrubbedTraitError}; use super::{FulfillmentError, FulfillmentErrorCode}; use crate::traits::project::PolyProjectionObligation; @@ -855,3 +855,17 @@ impl<'tcx> FromSolverError<'tcx, OldSolverError<'tcx>> for FulfillmentError<'tcx FulfillmentError::new(obligation, error.error, root_obligation) } } + +impl<'tcx> FromSolverError<'tcx, OldSolverError<'tcx>> for ScrubbedTraitError { + fn from_solver_error(_infcx: &InferCtxt<'tcx>, error: OldSolverError<'tcx>) -> Self { + match error.error { + FulfillmentErrorCode::Select(_) + | FulfillmentErrorCode::Project(_) + | FulfillmentErrorCode::Subtype(_, _) + | FulfillmentErrorCode::ConstEquate(_, _) => ScrubbedTraitError::TrueError, + FulfillmentErrorCode::Cycle(_) | FulfillmentErrorCode::Ambiguity { overflow: _ } => { + ScrubbedTraitError::Ambiguity + } + } + } +} diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs index 8b4594926474..baec2268629d 100644 --- a/compiler/rustc_trait_selection/src/traits/misc.rs +++ b/compiler/rustc_trait_selection/src/traits/misc.rs @@ -137,7 +137,7 @@ pub fn all_fields_implement_trait<'tcx>( for field in &variant.fields { // Do this per-field to get better error messages. let infcx = tcx.infer_ctxt().build(); - let ocx = traits::ObligationCtxt::new(&infcx); + let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx); let unnormalized_ty = field.ty(tcx, args); if unnormalized_ty.references_error() { diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 990a88f748e6..aabd687f0a54 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -46,7 +46,7 @@ pub use self::coherence::{add_placeholder_note, orphan_check_trait_ref, overlapp pub use self::coherence::{InCrate, IsFirstInputType, UncoveredTyParams}; pub use self::coherence::{OrphanCheckErr, OrphanCheckMode, OverlapResult}; pub use self::engine::{ObligationCtxt, TraitEngineExt}; -pub use self::fulfill::{FulfillmentContext, PendingPredicateObligation}; +pub use self::fulfill::{FulfillmentContext, OldSolverError, PendingPredicateObligation}; pub use self::normalize::NormalizeExt; pub use self::object_safety::hir_ty_lowering_object_safety_violations; pub use self::object_safety::is_vtable_safe_method; @@ -70,6 +70,28 @@ pub use self::util::{with_replaced_escaping_bound_vars, BoundVarReplacer, Placeh pub use rustc_infer::traits::*; +// A trait error without any information in it. You likely want to alternately use [`ObligationCtxt::new_with_diagnostics`] to get a [`FulfillmentError`]. +#[derive(Copy, Clone, Debug)] +pub enum ScrubbedTraitError { + TrueError, + Ambiguity, +} + +impl ScrubbedTraitError { + fn is_true_error(&self) -> bool { + match self { + ScrubbedTraitError::TrueError => true, + ScrubbedTraitError::Ambiguity => false, + } + } +} + +impl<'tcx> FulfillmentErrorLike<'tcx> for ScrubbedTraitError { + fn is_true_error(&self) -> bool { + self.is_true_error() + } +} + pub struct FulfillmentError<'tcx> { pub obligation: PredicateObligation<'tcx>, pub code: FulfillmentErrorCode<'tcx>, @@ -450,7 +472,7 @@ pub fn fully_normalize<'tcx, T>( where T: TypeFoldable>, { - let ocx = ObligationCtxt::new(infcx); + let ocx = ObligationCtxt::new_with_diagnostics(infcx); debug!(?value); let normalized_value = ocx.normalize(&cause, param_env, value); debug!(?normalized_value); diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs index b96b1b67a740..41f607fb3a8a 100644 --- a/compiler/rustc_traits/src/codegen.rs +++ b/compiler/rustc_traits/src/codegen.rs @@ -50,7 +50,8 @@ pub fn codegen_select_candidate<'tcx>( // Currently, we use a fulfillment context to completely resolve // all nested obligations. This is because they can inform the // inference of the impl's type parameters. - let ocx = ObligationCtxt::new(&infcx); + // FIXME(-Znext-solver): Doesn't need diagnostics if new solver. + let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let impl_source = selection.map(|obligation| { ocx.register_obligation(obligation); }); diff --git a/compiler/rustc_traits/src/normalize_projection_ty.rs b/compiler/rustc_traits/src/normalize_projection_ty.rs index fee13078250f..712abf6fcb32 100644 --- a/compiler/rustc_traits/src/normalize_projection_ty.rs +++ b/compiler/rustc_traits/src/normalize_projection_ty.rs @@ -8,7 +8,7 @@ use rustc_trait_selection::traits::query::{ normalize::NormalizationResult, CanonicalAliasGoal, NoSolution, }; use rustc_trait_selection::traits::{ - self, FulfillmentErrorCode, ObligationCause, SelectionContext, + self, FulfillmentError, FulfillmentErrorCode, ObligationCause, ObligationCtxt, SelectionContext, }; use tracing::debug; @@ -29,7 +29,8 @@ fn normalize_canonicalized_projection_ty<'tcx>( tcx.infer_ctxt().enter_canonical_trait_query( &goal, - |ocx, ParamEnvAnd { param_env, value: goal }| { + |ocx: &ObligationCtxt<'_, 'tcx, FulfillmentError<'tcx>>, + ParamEnvAnd { param_env, value: goal }| { debug_assert!(!ocx.infcx.next_trait_solver()); let selcx = &mut SelectionContext::new(ocx.infcx); let cause = ObligationCause::dummy(); @@ -73,7 +74,7 @@ fn normalize_canonicalized_weak_ty<'tcx>( tcx.infer_ctxt().enter_canonical_trait_query( &goal, - |ocx, ParamEnvAnd { param_env, value: goal }| { + |ocx: &ObligationCtxt<'_, 'tcx>, ParamEnvAnd { param_env, value: goal }| { let obligations = tcx.predicates_of(goal.def_id).instantiate_own(tcx, goal.args).map( |(predicate, span)| { traits::Obligation::new( @@ -99,7 +100,7 @@ fn normalize_canonicalized_inherent_projection_ty<'tcx>( tcx.infer_ctxt().enter_canonical_trait_query( &goal, - |ocx, ParamEnvAnd { param_env, value: goal }| { + |ocx: &ObligationCtxt<'_, 'tcx>, ParamEnvAnd { param_env, value: goal }| { let selcx = &mut SelectionContext::new(ocx.infcx); let cause = ObligationCause::dummy(); let mut obligations = vec![]; diff --git a/compiler/rustc_traits/src/type_op.rs b/compiler/rustc_traits/src/type_op.rs index b6a59a4ad3a4..35b0ede9a2e5 100644 --- a/compiler/rustc_traits/src/type_op.rs +++ b/compiler/rustc_traits/src/type_op.rs @@ -43,10 +43,13 @@ fn type_op_eq<'tcx>( tcx: TyCtxt<'tcx>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Eq<'tcx>>>, ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> { - tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |ocx, key| { - let (param_env, Eq { a, b }) = key.into_parts(); - Ok(ocx.eq(&ObligationCause::dummy(), param_env, a, b)?) - }) + tcx.infer_ctxt().enter_canonical_trait_query( + &canonicalized, + |ocx: &ObligationCtxt<'_, 'tcx>, key| { + let (param_env, Eq { a, b }) = key.into_parts(); + Ok(ocx.eq(&ObligationCause::dummy(), param_env, a, b)?) + }, + ) } fn type_op_normalize<'tcx, T>( @@ -95,10 +98,13 @@ fn type_op_subtype<'tcx>( tcx: TyCtxt<'tcx>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Subtype<'tcx>>>, ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> { - tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |ocx, key| { - let (param_env, Subtype { sub, sup }) = key.into_parts(); - Ok(ocx.sup(&ObligationCause::dummy(), param_env, sup, sub)?) - }) + tcx.infer_ctxt().enter_canonical_trait_query( + &canonicalized, + |ocx: &ObligationCtxt<'_, 'tcx>, key| { + let (param_env, Subtype { sub, sup }) = key.into_parts(); + Ok(ocx.sup(&ObligationCause::dummy(), param_env, sup, sub)?) + }, + ) } fn type_op_prove_predicate<'tcx>( diff --git a/src/tools/clippy/clippy_lints/src/future_not_send.rs b/src/tools/clippy/clippy_lints/src/future_not_send.rs index 192fb611c2d4..cb1d0de1edff 100644 --- a/src/tools/clippy/clippy_lints/src/future_not_send.rs +++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs @@ -79,7 +79,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend { let send_trait = cx.tcx.get_diagnostic_item(sym::Send).unwrap(); let span = decl.output.span(); let infcx = cx.tcx.infer_ctxt().build(); - let ocx = ObligationCtxt::new(&infcx); + let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let cause = traits::ObligationCause::misc(span, fn_def_id); ocx.register_bound(cause, cx.param_env, ret_ty, send_trait); let send_errors = ocx.select_all_or_error(); From 94a524ed1163f4876544366586dc1b87deb13e95 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 1 Jun 2024 15:00:02 -0400 Subject: [PATCH 184/211] Use ScrubbedTraitError in more places --- .../src/type_check/constraint_conversion.rs | 4 ++-- compiler/rustc_hir_analysis/src/coherence/orphan.rs | 9 +++++---- compiler/rustc_trait_selection/src/regions.rs | 5 ++--- compiler/rustc_trait_selection/src/solve/normalize.rs | 8 +++----- compiler/rustc_trait_selection/src/traits/mod.rs | 9 ++++++++- .../rustc_trait_selection/src/traits/query/normalize.rs | 7 +++---- .../src/traits/query/type_op/implied_outlives_bounds.rs | 5 ++--- 7 files changed, 25 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index 4037f04d0bce..210532e56a5b 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -13,7 +13,7 @@ use rustc_span::Span; use rustc_trait_selection::solve::deeply_normalize; use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp; use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput}; -use rustc_trait_selection::traits::FulfillmentError; +use rustc_trait_selection::traits::ScrubbedTraitError; use crate::{ constraints::OutlivesConstraint, @@ -287,7 +287,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { ocx.infcx.at(&ObligationCause::dummy_with_span(self.span), self.param_env), ty, ) - .map_err(|_: Vec>| NoSolution) + .map_err(|_: Vec| NoSolution) }, "normalize type outlives obligation", ) diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index a4818b25f98c..d2eb0cb5a7bc 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -12,9 +12,11 @@ use rustc_middle::ty::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; use rustc_middle::{bug, span_bug}; use rustc_span::def_id::{DefId, LocalDefId}; -use rustc_trait_selection::traits::{self, IsFirstInputType, UncoveredTyParams}; -use rustc_trait_selection::traits::{FulfillmentError, StructurallyNormalizeExt, TraitEngineExt}; +use rustc_trait_selection::traits::{ + self, IsFirstInputType, ScrubbedTraitError, UncoveredTyParams, +}; use rustc_trait_selection::traits::{OrphanCheckErr, OrphanCheckMode}; +use rustc_trait_selection::traits::{StructurallyNormalizeExt, TraitEngineExt}; #[instrument(level = "debug", skip(tcx))] pub(crate) fn orphan_check_impl( @@ -317,8 +319,7 @@ fn orphan_check<'tcx>( } let ty = if infcx.next_trait_solver() { - let mut fulfill_cx = - >>::new(&infcx); + let mut fulfill_cx = >::new(&infcx); infcx .at(&cause, ty::ParamEnv::empty()) .structurally_normalize(ty, &mut *fulfill_cx) diff --git a/compiler/rustc_trait_selection/src/regions.rs b/compiler/rustc_trait_selection/src/regions.rs index cca5bce03e19..3ef3f9ef3585 100644 --- a/compiler/rustc_trait_selection/src/regions.rs +++ b/compiler/rustc_trait_selection/src/regions.rs @@ -1,4 +1,4 @@ -use crate::traits::FulfillmentError; +use crate::traits::ScrubbedTraitError; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{InferCtxt, RegionResolutionError}; use rustc_macros::extension; @@ -28,8 +28,7 @@ impl<'tcx> InferCtxt<'tcx> { ), ty, ) - // TODO: - .map_err(|_: Vec>| NoSolution) + .map_err(|_: Vec| NoSolution) } else { Ok(ty) } diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs index f85e5d8746fd..5e41e8e8ba92 100644 --- a/compiler/rustc_trait_selection/src/solve/normalize.rs +++ b/compiler/rustc_trait_selection/src/solve/normalize.rs @@ -2,7 +2,7 @@ use std::marker::PhantomData; use crate::traits::error_reporting::{OverflowCause, TypeErrCtxtExt}; use crate::traits::query::evaluate_obligation::InferCtxtExt; -use crate::traits::{BoundVarReplacer, FulfillmentError, PlaceholderReplacer}; +use crate::traits::{BoundVarReplacer, PlaceholderReplacer, ScrubbedTraitError}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_infer::infer::at::At; use rustc_infer::infer::InferCtxt; @@ -253,8 +253,7 @@ impl<'tcx> TypeFolder> for DeeplyNormalizeForDiagnosticsFolder<'_, ty, vec![None; ty.outer_exclusive_binder().as_usize()], ) - // TODO: - .unwrap_or_else(|_: Vec>| ty.super_fold_with(self)) + .unwrap_or_else(|_: Vec| ty.super_fold_with(self)) } fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { @@ -263,7 +262,6 @@ impl<'tcx> TypeFolder> for DeeplyNormalizeForDiagnosticsFolder<'_, ct, vec![None; ct.outer_exclusive_binder().as_usize()], ) - // TODO: - .unwrap_or_else(|_: Vec>| ct.super_fold_with(self)) + .unwrap_or_else(|_: Vec| ct.super_fold_with(self)) } } diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index aabd687f0a54..cab743987c65 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -70,10 +70,17 @@ pub use self::util::{with_replaced_escaping_bound_vars, BoundVarReplacer, Placeh pub use rustc_infer::traits::*; -// A trait error without any information in it. You likely want to alternately use [`ObligationCtxt::new_with_diagnostics`] to get a [`FulfillmentError`]. +/// A trait error without most of its information removed. This is the error +/// returned by an [`ObligationCtxt`] by default, and suitable if you just +/// want to see if a predicate holds, and don't particularly care about the +/// error itself (except for if it's an ambiguity or true error). +/// +/// use [`ObligationCtxt::new_with_diagnostics`] to get a [`FulfillmentError`]. #[derive(Copy, Clone, Debug)] pub enum ScrubbedTraitError { + /// A real error. This goal definitely does not hold. TrueError, + /// An ambiguity. This goal may hold if further inference is done. Ambiguity, } diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 2c0103e40dff..860f50888a59 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -8,8 +8,8 @@ use crate::infer::{InferCtxt, InferOk}; use crate::traits::error_reporting::OverflowCause; use crate::traits::error_reporting::TypeErrCtxtExt; use crate::traits::normalize::needs_normalization; -use crate::traits::{BoundVarReplacer, PlaceholderReplacer}; -use crate::traits::{FulfillmentError, Normalized}; +use crate::traits::Normalized; +use crate::traits::{BoundVarReplacer, PlaceholderReplacer, ScrubbedTraitError}; use crate::traits::{ObligationCause, PredicateObligation, Reveal}; use rustc_data_structures::sso::SsoHashMap; use rustc_data_structures::stack::ensure_sufficient_stack; @@ -76,8 +76,7 @@ impl<'cx, 'tcx> At<'cx, 'tcx> { }; if self.infcx.next_trait_solver() { - // TODO: - match crate::solve::deeply_normalize_with_skipped_universes::<_, FulfillmentError<'tcx>>( + match crate::solve::deeply_normalize_with_skipped_universes::<_, ScrubbedTraitError>( self, value, universes, ) { Ok(value) => return Ok(Normalized { value, obligations: vec![] }), diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs index a1bbd21f8296..e4d0a5412192 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs @@ -1,8 +1,8 @@ use crate::solve; use crate::traits::query::NoSolution; use crate::traits::wf; -use crate::traits::FulfillmentError; use crate::traits::ObligationCtxt; +use crate::traits::ScrubbedTraitError; use rustc_infer::infer::canonical::Canonical; use rustc_infer::infer::outlives::components::{push_outlives_components, Component}; @@ -267,8 +267,7 @@ pub fn compute_implied_outlives_bounds_compat_inner<'tcx>( ocx.infcx.at(&ObligationCause::dummy(), param_env), ty_a, ) - // TODO: - .map_err(|_errs: Vec>| NoSolution)?; + .map_err(|_errs: Vec| NoSolution)?; } let mut components = smallvec![]; push_outlives_components(tcx, ty_a, &mut components); From 27f5eccd1f433c9455d1a0d3e402c1fa2a2ce334 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 1 Jun 2024 15:08:44 -0400 Subject: [PATCH 185/211] Move FulfillmentErrorCode to rustc_trait_selection too --- .../rustc_borrowck/src/diagnostics/mod.rs | 6 ++- .../src/diagnostics/mutability_errors.rs | 2 +- .../src/fn_ctxt/suggestions.rs | 2 +- compiler/rustc_infer/src/traits/mod.rs | 21 +--------- .../src/traits/structural_impls.rs | 21 ---------- .../src/solve/fulfill.rs | 7 ++-- .../rustc_trait_selection/src/traits/mod.rs | 40 ++++++++++++++++++- compiler/rustc_traits/src/codegen.rs | 4 +- 8 files changed, 51 insertions(+), 52 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 88172c62a3b2..1eb67ea367c2 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -11,7 +11,7 @@ use rustc_hir::def::{CtorKind, Namespace}; use rustc_hir::CoroutineKind; use rustc_index::IndexSlice; use rustc_infer::infer::BoundRegionConversionTime; -use rustc_infer::traits::{FulfillmentErrorCode, SelectionError}; +use rustc_infer::traits::SelectionError; use rustc_middle::bug; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::{ @@ -29,7 +29,9 @@ use rustc_span::{symbol::sym, Span, Symbol, DUMMY_SP}; use rustc_target::abi::{FieldIdx, VariantIdx}; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt as _; -use rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions; +use rustc_trait_selection::traits::{ + type_known_to_meet_bound_modulo_regions, FulfillmentErrorCode, +}; use crate::fluent_generated as fluent; diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 78798545c26f..df1a1411cf5f 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -6,7 +6,6 @@ use hir::{ExprKind, Param}; use rustc_errors::{Applicability, Diag}; use rustc_hir::intravisit::Visitor; use rustc_hir::{self as hir, BindingMode, ByRef, Node}; -use rustc_infer::traits; use rustc_middle::bug; use rustc_middle::mir::{Mutability, Place, PlaceRef, ProjectionElem}; use rustc_middle::ty::{self, InstanceDef, Ty, TyCtxt, Upcast}; @@ -18,6 +17,7 @@ use rustc_span::symbol::{kw, Symbol}; use rustc_span::{sym, BytePos, DesugaringKind, Span}; use rustc_target::abi::FieldIdx; use rustc_trait_selection::infer::InferCtxtExt; +use rustc_trait_selection::traits; use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt; use crate::diagnostics::BorrowedContentSource; diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 5723b73a328a..caaf4142f7d1 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -22,7 +22,6 @@ use rustc_hir::{ }; use rustc_hir_analysis::collect::suggest_impl_trait; use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer; -use rustc_infer::traits; use rustc_middle::lint::in_external_macro; use rustc_middle::middle::stability::EvalResult; use rustc_middle::span_bug; @@ -36,6 +35,7 @@ use rustc_span::source_map::Spanned; use rustc_span::symbol::{sym, Ident}; use rustc_span::{Span, Symbol}; use rustc_trait_selection::infer::InferCtxtExt; +use rustc_trait_selection::traits; use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt; use rustc_trait_selection::traits::error_reporting::DefIdOrName; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index 26c931876dbd..e9c2d81aa0af 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -15,8 +15,7 @@ use hir::def_id::LocalDefId; use rustc_hir as hir; use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::solve::Certainty; -use rustc_middle::ty::error::{ExpectedFound, TypeError}; -use rustc_middle::ty::{self, Const, Ty, TyCtxt, Upcast}; +use rustc_middle::ty::{self, Ty, TyCtxt, Upcast}; use rustc_span::Span; pub use self::ImplSource::*; @@ -124,24 +123,6 @@ pub type Selection<'tcx> = ImplSource<'tcx, PredicateObligation<'tcx>>; pub type ObligationInspector<'tcx> = fn(&InferCtxt<'tcx>, &PredicateObligation<'tcx>, Result); -// TODO: Pull this down too -#[derive(Clone)] -pub enum FulfillmentErrorCode<'tcx> { - /// Inherently impossible to fulfill; this trait is implemented if and only - /// if it is already implemented. - Cycle(Vec>), - Select(SelectionError<'tcx>), - Project(MismatchedProjectionTypes<'tcx>), - Subtype(ExpectedFound>, TypeError<'tcx>), // always comes from a SubtypePredicate - ConstEquate(ExpectedFound>, TypeError<'tcx>), - Ambiguity { - /// Overflow is only `Some(suggest_recursion_limit)` when using the next generation - /// trait solver `-Znext-solver`. With the old solver overflow is eagerly handled by - /// emitting a fatal error instead. - overflow: Option, - }, -} - impl<'tcx, O> Obligation<'tcx, O> { pub fn new( tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_infer/src/traits/structural_impls.rs b/compiler/rustc_infer/src/traits/structural_impls.rs index 00abf939807a..b26734a296fd 100644 --- a/compiler/rustc_infer/src/traits/structural_impls.rs +++ b/compiler/rustc_infer/src/traits/structural_impls.rs @@ -29,27 +29,6 @@ impl<'tcx, O: fmt::Debug> fmt::Debug for traits::Obligation<'tcx, O> { } } -impl<'tcx> fmt::Debug for traits::FulfillmentErrorCode<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - use traits::FulfillmentErrorCode::*; - match *self { - Select(ref e) => write!(f, "{e:?}"), - Project(ref e) => write!(f, "{e:?}"), - Subtype(ref a, ref b) => { - write!(f, "CodeSubtypeError({a:?}, {b:?})") - } - ConstEquate(ref a, ref b) => { - write!(f, "CodeConstEquateError({a:?}, {b:?})") - } - Ambiguity { overflow: None } => write!(f, "Ambiguity"), - Ambiguity { overflow: Some(suggest_increasing_limit) } => { - write!(f, "Overflow({suggest_increasing_limit})") - } - Cycle(ref cycle) => write!(f, "Cycle({cycle:?})"), - } - } -} - impl<'tcx> fmt::Debug for traits::MismatchedProjectionTypes<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "MismatchedProjectionTypes({:?})", self.err) diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index d92c903a76ed..b644f70eee42 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -6,16 +6,15 @@ use rustc_infer::infer::InferCtxt; use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::solve::{CandidateSource, GoalSource, MaybeCause}; use rustc_infer::traits::{ - self, FromSolverError, FulfillmentErrorCode, FulfillmentErrorLike, MismatchedProjectionTypes, - Obligation, ObligationCause, ObligationCauseCode, PredicateObligation, SelectionError, - TraitEngine, + self, FromSolverError, FulfillmentErrorLike, MismatchedProjectionTypes, Obligation, + ObligationCause, ObligationCauseCode, PredicateObligation, SelectionError, TraitEngine, }; use rustc_middle::bug; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::symbol::sym; -use crate::traits::{FulfillmentError, ScrubbedTraitError}; +use crate::traits::{FulfillmentError, FulfillmentErrorCode, ScrubbedTraitError}; use super::eval_ctxt::GenerateProofTree; use super::inspect::{self, ProofTreeInferCtxtExt, ProofTreeVisitor}; diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index cab743987c65..8fdf9c61c496 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -32,6 +32,7 @@ use crate::traits::query::evaluate_obligation::InferCtxtExt as _; use rustc_errors::ErrorGuaranteed; use rustc_middle::query::Providers; use rustc_middle::span_bug; +use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFolder, TypeSuperVisitable, Upcast}; @@ -70,7 +71,7 @@ pub use self::util::{with_replaced_escaping_bound_vars, BoundVarReplacer, Placeh pub use rustc_infer::traits::*; -/// A trait error without most of its information removed. This is the error +/// A trait error with most of its information removed. This is the error /// returned by an [`ObligationCtxt`] by default, and suitable if you just /// want to see if a predicate holds, and don't particularly care about the /// error itself (except for if it's an ambiguity or true error). @@ -142,6 +143,43 @@ impl<'tcx> Debug for FulfillmentError<'tcx> { } } +#[derive(Clone)] +pub enum FulfillmentErrorCode<'tcx> { + /// Inherently impossible to fulfill; this trait is implemented if and only + /// if it is already implemented. + Cycle(Vec>), + Select(SelectionError<'tcx>), + Project(MismatchedProjectionTypes<'tcx>), + Subtype(ExpectedFound>, TypeError<'tcx>), // always comes from a SubtypePredicate + ConstEquate(ExpectedFound>, TypeError<'tcx>), + Ambiguity { + /// Overflow is only `Some(suggest_recursion_limit)` when using the next generation + /// trait solver `-Znext-solver`. With the old solver overflow is eagerly handled by + /// emitting a fatal error instead. + overflow: Option, + }, +} + +impl<'tcx> Debug for FulfillmentErrorCode<'tcx> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match *self { + FulfillmentErrorCode::Select(ref e) => write!(f, "{e:?}"), + FulfillmentErrorCode::Project(ref e) => write!(f, "{e:?}"), + FulfillmentErrorCode::Subtype(ref a, ref b) => { + write!(f, "CodeSubtypeError({a:?}, {b:?})") + } + FulfillmentErrorCode::ConstEquate(ref a, ref b) => { + write!(f, "CodeConstEquateError({a:?}, {b:?})") + } + FulfillmentErrorCode::Ambiguity { overflow: None } => write!(f, "Ambiguity"), + FulfillmentErrorCode::Ambiguity { overflow: Some(suggest_increasing_limit) } => { + write!(f, "Overflow({suggest_increasing_limit})") + } + FulfillmentErrorCode::Cycle(ref cycle) => write!(f, "Cycle({cycle:?})"), + } + } +} + /// Whether to skip the leak check, as part of a future compatibility warning step. /// /// The "default" for skip-leak-check corresponds to the current diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs index 41f607fb3a8a..5defb8172716 100644 --- a/compiler/rustc_traits/src/codegen.rs +++ b/compiler/rustc_traits/src/codegen.rs @@ -4,13 +4,13 @@ // general routines. use rustc_infer::infer::TyCtxtInferExt; -use rustc_infer::traits::FulfillmentErrorCode; use rustc_middle::bug; use rustc_middle::traits::CodegenObligationError; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; use rustc_trait_selection::traits::{ - ImplSource, Obligation, ObligationCause, ObligationCtxt, SelectionContext, Unimplemented, + FulfillmentErrorCode, ImplSource, Obligation, ObligationCause, ObligationCtxt, + SelectionContext, Unimplemented, }; use tracing::debug; From 1e72c7f536bbdf3ed8a0071d28824c071c3722b5 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 2 Jun 2024 18:36:11 -0400 Subject: [PATCH 186/211] Add cycle errors to ScrubbedTraitError to remove a couple more calls to new_with_diagnostics --- .../src/type_check/constraint_conversion.rs | 2 +- .../src/coherence/orphan.rs | 3 ++- compiler/rustc_trait_selection/src/infer.rs | 14 ++++-------- compiler/rustc_trait_selection/src/regions.rs | 2 +- .../src/solve/fulfill.rs | 2 +- .../src/solve/normalize.rs | 4 ++-- .../src/traits/engine.rs | 13 ++--------- .../src/traits/fulfill.rs | 7 +++--- .../rustc_trait_selection/src/traits/mod.rs | 12 +++++----- .../src/traits/query/normalize.rs | 2 +- .../query/type_op/implied_outlives_bounds.rs | 2 +- compiler/rustc_traits/src/codegen.rs | 8 +++---- .../src/normalize_projection_ty.rs | 13 +++++------ compiler/rustc_traits/src/type_op.rs | 22 +++++++------------ 14 files changed, 42 insertions(+), 64 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index 210532e56a5b..266a80187c54 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -287,7 +287,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { ocx.infcx.at(&ObligationCause::dummy_with_span(self.span), self.param_env), ty, ) - .map_err(|_: Vec| NoSolution) + .map_err(|_: Vec>| NoSolution) }, "normalize type outlives obligation", ) diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index d2eb0cb5a7bc..1e7bb63e6ea4 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -319,7 +319,8 @@ fn orphan_check<'tcx>( } let ty = if infcx.next_trait_solver() { - let mut fulfill_cx = >::new(&infcx); + let mut fulfill_cx = + >>::new(&infcx); infcx .at(&cause, ty::ParamEnv::empty()) .structurally_normalize(ty, &mut *fulfill_cx) diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index f5d78430c978..c95649e2ffb8 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -1,9 +1,5 @@ -use crate::solve::NextSolverError; use crate::traits::query::evaluate_obligation::InferCtxtExt as _; -use crate::traits::{ - self, FromSolverError, Obligation, ObligationCause, ObligationCtxt, OldSolverError, - SelectionContext, -}; +use crate::traits::{self, Obligation, ObligationCause, ObligationCtxt, SelectionContext}; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; @@ -124,21 +120,19 @@ impl<'tcx> InferCtxtBuilder<'tcx> { /// bound for the closure and in part because it is convenient to /// have `'tcx` be free on this function so that we can talk about /// `K: TypeFoldable>`.) - fn enter_canonical_trait_query( + fn enter_canonical_trait_query( self, canonical_key: &Canonical<'tcx, K>, - operation: impl FnOnce(&ObligationCtxt<'_, 'tcx, E>, K) -> Result, + operation: impl FnOnce(&ObligationCtxt<'_, 'tcx>, K) -> Result, ) -> Result, NoSolution> where K: TypeFoldable>, R: Debug + TypeFoldable>, Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>, - E: FromSolverError<'tcx, NextSolverError<'tcx>> - + FromSolverError<'tcx, OldSolverError<'tcx>>, { let (infcx, key, canonical_inference_vars) = self.build_with_canonical(DUMMY_SP, canonical_key); - let ocx = ObligationCtxt::new_generic(&infcx); + let ocx = ObligationCtxt::new(&infcx); let value = operation(&ocx, key)?; ocx.make_canonicalized_query_response(canonical_inference_vars, value) } diff --git a/compiler/rustc_trait_selection/src/regions.rs b/compiler/rustc_trait_selection/src/regions.rs index 3ef3f9ef3585..5f986e22f513 100644 --- a/compiler/rustc_trait_selection/src/regions.rs +++ b/compiler/rustc_trait_selection/src/regions.rs @@ -28,7 +28,7 @@ impl<'tcx> InferCtxt<'tcx> { ), ty, ) - .map_err(|_: Vec| NoSolution) + .map_err(|_: Vec>| NoSolution) } else { Ok(ty) } diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index b644f70eee42..3de4aee0927b 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -225,7 +225,7 @@ impl<'tcx> FromSolverError<'tcx, NextSolverError<'tcx>> for FulfillmentError<'tc } } -impl<'tcx> FromSolverError<'tcx, NextSolverError<'tcx>> for ScrubbedTraitError { +impl<'tcx> FromSolverError<'tcx, NextSolverError<'tcx>> for ScrubbedTraitError<'tcx> { fn from_solver_error(_infcx: &InferCtxt<'tcx>, error: NextSolverError<'tcx>) -> Self { match error { NextSolverError::TrueError(_) => ScrubbedTraitError::TrueError, diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs index 5e41e8e8ba92..4211129a4e15 100644 --- a/compiler/rustc_trait_selection/src/solve/normalize.rs +++ b/compiler/rustc_trait_selection/src/solve/normalize.rs @@ -253,7 +253,7 @@ impl<'tcx> TypeFolder> for DeeplyNormalizeForDiagnosticsFolder<'_, ty, vec![None; ty.outer_exclusive_binder().as_usize()], ) - .unwrap_or_else(|_: Vec| ty.super_fold_with(self)) + .unwrap_or_else(|_: Vec>| ty.super_fold_with(self)) } fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { @@ -262,6 +262,6 @@ impl<'tcx> TypeFolder> for DeeplyNormalizeForDiagnosticsFolder<'_, ct, vec![None; ct.outer_exclusive_binder().as_usize()], ) - .unwrap_or_else(|_: Vec| ct.super_fold_with(self)) + .unwrap_or_else(|_: Vec>| ct.super_fold_with(self)) } } diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index 333fd4556e3d..397f9cf2638e 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -54,7 +54,7 @@ impl< /// Used if you want to have pleasant experience when dealing /// with obligations outside of hir or mir typeck. -pub struct ObligationCtxt<'a, 'tcx, E = ScrubbedTraitError> { +pub struct ObligationCtxt<'a, 'tcx, E = ScrubbedTraitError<'tcx>> { pub infcx: &'a InferCtxt<'tcx>, engine: RefCell>>, } @@ -65,21 +65,12 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx, FulfillmentError<'tcx>> { } } -impl<'a, 'tcx> ObligationCtxt<'a, 'tcx, ScrubbedTraitError> { +impl<'a, 'tcx> ObligationCtxt<'a, 'tcx, ScrubbedTraitError<'tcx>> { pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self { Self { infcx, engine: RefCell::new(>::new(infcx)) } } } -impl<'a, 'tcx, E> ObligationCtxt<'a, 'tcx, E> -where - E: FromSolverError<'tcx, NextSolverError<'tcx>> + FromSolverError<'tcx, OldSolverError<'tcx>>, -{ - pub fn new_generic(infcx: &'a InferCtxt<'tcx>) -> Self { - Self { infcx, engine: RefCell::new(>::new(infcx)) } - } -} - impl<'a, 'tcx, E> ObligationCtxt<'a, 'tcx, E> where E: FulfillmentErrorLike<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 8746cfa37e2e..59802a260435 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -856,16 +856,15 @@ impl<'tcx> FromSolverError<'tcx, OldSolverError<'tcx>> for FulfillmentError<'tcx } } -impl<'tcx> FromSolverError<'tcx, OldSolverError<'tcx>> for ScrubbedTraitError { +impl<'tcx> FromSolverError<'tcx, OldSolverError<'tcx>> for ScrubbedTraitError<'tcx> { fn from_solver_error(_infcx: &InferCtxt<'tcx>, error: OldSolverError<'tcx>) -> Self { match error.error { FulfillmentErrorCode::Select(_) | FulfillmentErrorCode::Project(_) | FulfillmentErrorCode::Subtype(_, _) | FulfillmentErrorCode::ConstEquate(_, _) => ScrubbedTraitError::TrueError, - FulfillmentErrorCode::Cycle(_) | FulfillmentErrorCode::Ambiguity { overflow: _ } => { - ScrubbedTraitError::Ambiguity - } + FulfillmentErrorCode::Ambiguity { overflow: _ } => ScrubbedTraitError::Ambiguity, + FulfillmentErrorCode::Cycle(cycle) => ScrubbedTraitError::Cycle(cycle), } } } diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 8fdf9c61c496..9aaa8adbd671 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -77,24 +77,26 @@ pub use rustc_infer::traits::*; /// error itself (except for if it's an ambiguity or true error). /// /// use [`ObligationCtxt::new_with_diagnostics`] to get a [`FulfillmentError`]. -#[derive(Copy, Clone, Debug)] -pub enum ScrubbedTraitError { +#[derive(Clone, Debug)] +pub enum ScrubbedTraitError<'tcx> { /// A real error. This goal definitely does not hold. TrueError, /// An ambiguity. This goal may hold if further inference is done. Ambiguity, + /// An old-solver-style cycle error, which will fatal. + Cycle(Vec>), } -impl ScrubbedTraitError { +impl<'tcx> ScrubbedTraitError<'tcx> { fn is_true_error(&self) -> bool { match self { ScrubbedTraitError::TrueError => true, - ScrubbedTraitError::Ambiguity => false, + ScrubbedTraitError::Ambiguity | ScrubbedTraitError::Cycle(_) => false, } } } -impl<'tcx> FulfillmentErrorLike<'tcx> for ScrubbedTraitError { +impl<'tcx> FulfillmentErrorLike<'tcx> for ScrubbedTraitError<'tcx> { fn is_true_error(&self) -> bool { self.is_true_error() } diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 860f50888a59..e170d7cae937 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -76,7 +76,7 @@ impl<'cx, 'tcx> At<'cx, 'tcx> { }; if self.infcx.next_trait_solver() { - match crate::solve::deeply_normalize_with_skipped_universes::<_, ScrubbedTraitError>( + match crate::solve::deeply_normalize_with_skipped_universes::<_, ScrubbedTraitError<'tcx>>( self, value, universes, ) { Ok(value) => return Ok(Normalized { value, obligations: vec![] }), diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs index e4d0a5412192..54fa07496181 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs @@ -267,7 +267,7 @@ pub fn compute_implied_outlives_bounds_compat_inner<'tcx>( ocx.infcx.at(&ObligationCause::dummy(), param_env), ty_a, ) - .map_err(|_errs: Vec| NoSolution)?; + .map_err(|_errs: Vec>| NoSolution)?; } let mut components = smallvec![]; push_outlives_components(tcx, ty_a, &mut components); diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs index 5defb8172716..c73ececd1d15 100644 --- a/compiler/rustc_traits/src/codegen.rs +++ b/compiler/rustc_traits/src/codegen.rs @@ -9,8 +9,8 @@ use rustc_middle::traits::CodegenObligationError; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; use rustc_trait_selection::traits::{ - FulfillmentErrorCode, ImplSource, Obligation, ObligationCause, ObligationCtxt, - SelectionContext, Unimplemented, + ImplSource, Obligation, ObligationCause, ObligationCtxt, ScrubbedTraitError, SelectionContext, + Unimplemented, }; use tracing::debug; @@ -51,7 +51,7 @@ pub fn codegen_select_candidate<'tcx>( // all nested obligations. This is because they can inform the // inference of the impl's type parameters. // FIXME(-Znext-solver): Doesn't need diagnostics if new solver. - let ocx = ObligationCtxt::new_with_diagnostics(&infcx); + let ocx = ObligationCtxt::new(&infcx); let impl_source = selection.map(|obligation| { ocx.register_obligation(obligation); }); @@ -65,7 +65,7 @@ pub fn codegen_select_candidate<'tcx>( // Cycle errors are the only post-monomorphization errors possible; emit them now so // `rustc_ty_utils::resolve_associated_item` doesn't return `None` post-monomorphization. for err in errors { - if let FulfillmentErrorCode::Cycle(cycle) = err.code { + if let ScrubbedTraitError::Cycle(cycle) = err { infcx.err_ctxt().report_overflow_obligation_cycle(&cycle); } } diff --git a/compiler/rustc_traits/src/normalize_projection_ty.rs b/compiler/rustc_traits/src/normalize_projection_ty.rs index 712abf6fcb32..b0a93b62dbf3 100644 --- a/compiler/rustc_traits/src/normalize_projection_ty.rs +++ b/compiler/rustc_traits/src/normalize_projection_ty.rs @@ -7,9 +7,7 @@ use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; use rustc_trait_selection::traits::query::{ normalize::NormalizationResult, CanonicalAliasGoal, NoSolution, }; -use rustc_trait_selection::traits::{ - self, FulfillmentError, FulfillmentErrorCode, ObligationCause, ObligationCtxt, SelectionContext, -}; +use rustc_trait_selection::traits::{self, ObligationCause, ScrubbedTraitError, SelectionContext}; use tracing::debug; pub(crate) fn provide(p: &mut Providers) { @@ -29,8 +27,7 @@ fn normalize_canonicalized_projection_ty<'tcx>( tcx.infer_ctxt().enter_canonical_trait_query( &goal, - |ocx: &ObligationCtxt<'_, 'tcx, FulfillmentError<'tcx>>, - ParamEnvAnd { param_env, value: goal }| { + |ocx, ParamEnvAnd { param_env, value: goal }| { debug_assert!(!ocx.infcx.next_trait_solver()); let selcx = &mut SelectionContext::new(ocx.infcx); let cause = ObligationCause::dummy(); @@ -50,7 +47,7 @@ fn normalize_canonicalized_projection_ty<'tcx>( // that impl vars are constrained by the signature, for example). if !tcx.sess.opts.actually_rustdoc { for error in &errors { - if let FulfillmentErrorCode::Cycle(cycle) = &error.code { + if let ScrubbedTraitError::Cycle(cycle) = &error { ocx.infcx.err_ctxt().report_overflow_obligation_cycle(cycle); } } @@ -74,7 +71,7 @@ fn normalize_canonicalized_weak_ty<'tcx>( tcx.infer_ctxt().enter_canonical_trait_query( &goal, - |ocx: &ObligationCtxt<'_, 'tcx>, ParamEnvAnd { param_env, value: goal }| { + |ocx, ParamEnvAnd { param_env, value: goal }| { let obligations = tcx.predicates_of(goal.def_id).instantiate_own(tcx, goal.args).map( |(predicate, span)| { traits::Obligation::new( @@ -100,7 +97,7 @@ fn normalize_canonicalized_inherent_projection_ty<'tcx>( tcx.infer_ctxt().enter_canonical_trait_query( &goal, - |ocx: &ObligationCtxt<'_, 'tcx>, ParamEnvAnd { param_env, value: goal }| { + |ocx, ParamEnvAnd { param_env, value: goal }| { let selcx = &mut SelectionContext::new(ocx.infcx); let cause = ObligationCause::dummy(); let mut obligations = vec![]; diff --git a/compiler/rustc_traits/src/type_op.rs b/compiler/rustc_traits/src/type_op.rs index 35b0ede9a2e5..b6a59a4ad3a4 100644 --- a/compiler/rustc_traits/src/type_op.rs +++ b/compiler/rustc_traits/src/type_op.rs @@ -43,13 +43,10 @@ fn type_op_eq<'tcx>( tcx: TyCtxt<'tcx>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Eq<'tcx>>>, ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> { - tcx.infer_ctxt().enter_canonical_trait_query( - &canonicalized, - |ocx: &ObligationCtxt<'_, 'tcx>, key| { - let (param_env, Eq { a, b }) = key.into_parts(); - Ok(ocx.eq(&ObligationCause::dummy(), param_env, a, b)?) - }, - ) + tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |ocx, key| { + let (param_env, Eq { a, b }) = key.into_parts(); + Ok(ocx.eq(&ObligationCause::dummy(), param_env, a, b)?) + }) } fn type_op_normalize<'tcx, T>( @@ -98,13 +95,10 @@ fn type_op_subtype<'tcx>( tcx: TyCtxt<'tcx>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Subtype<'tcx>>>, ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> { - tcx.infer_ctxt().enter_canonical_trait_query( - &canonicalized, - |ocx: &ObligationCtxt<'_, 'tcx>, key| { - let (param_env, Subtype { sub, sup }) = key.into_parts(); - Ok(ocx.sup(&ObligationCause::dummy(), param_env, sup, sub)?) - }, - ) + tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |ocx, key| { + let (param_env, Subtype { sub, sup }) = key.into_parts(); + Ok(ocx.sup(&ObligationCause::dummy(), param_env, sup, sub)?) + }) } fn type_op_prove_predicate<'tcx>( From 063b26af6bf7973768d2616eb4f79fc9b91ee11c Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 3 Jun 2024 13:28:49 +0000 Subject: [PATCH 187/211] Explain some code duplication --- compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs | 4 ++++ 1 file changed, 4 insertions(+) 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 d26ebe9881b8..4b8e12a489c5 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -444,6 +444,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { if let Err(incorrect) = self.incorrect_args { if incorrect.invalid_args.contains(&(param.index as usize)) { + // FIXME: use `param.to_error` once `provided_kind` is supplied a list of + // all previous generic args. return match param.kind { GenericParamDefKind::Lifetime => { ty::Region::new_error(tcx, incorrect.reported).into() @@ -531,6 +533,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { if let Err(incorrect) = self.incorrect_args { if incorrect.invalid_args.contains(&(param.index as usize)) { + // FIXME: use `param.to_error` once `inferred_kind` is supplied a list of + // all previous generic args. return match param.kind { GenericParamDefKind::Lifetime => { ty::Region::new_error(tcx, incorrect.reported).into() From 108a1e5f4be6a9184dee6957bdaa81c0454fb4fd Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 3 Jun 2024 13:45:36 +0000 Subject: [PATCH 188/211] Always provide previous generic arguments --- .../src/hir_ty_lowering/generics.rs | 9 ++-- .../src/hir_ty_lowering/mod.rs | 41 +++++++------------ .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 6 +-- .../rustc_hir_typeck/src/method/confirm.rs | 2 +- 4 files changed, 24 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs index 4ec2aa6c6262..72e03ead76b0 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs @@ -214,10 +214,11 @@ pub fn lower_generic_args<'tcx: 'a, 'a>( if let Some(¶m) = params.peek() { if param.index == 0 { if let GenericParamDefKind::Type { .. } = param.kind { + assert_eq!(&args[..], &[]); args.push( self_ty .map(|ty| ty.into()) - .unwrap_or_else(|| ctx.inferred_kind(None, param, true)), + .unwrap_or_else(|| ctx.inferred_kind(&args, param, true)), ); params.next(); } @@ -267,7 +268,7 @@ pub fn lower_generic_args<'tcx: 'a, 'a>( // Since this is a const impl, we need to insert a host arg at the end of // `PartialEq`'s generics, but this errors since `Rhs` isn't specified. // To work around this, we infer all arguments until we reach the host param. - args.push(ctx.inferred_kind(Some(&args), param, infer_args)); + args.push(ctx.inferred_kind(&args, param, infer_args)); params.next(); } (GenericArg::Lifetime(_), GenericParamDefKind::Lifetime, _) @@ -292,7 +293,7 @@ pub fn lower_generic_args<'tcx: 'a, 'a>( ) => { // We expected a lifetime argument, but got a type or const // argument. That means we're inferring the lifetimes. - args.push(ctx.inferred_kind(None, param, infer_args)); + args.push(ctx.inferred_kind(&args, param, infer_args)); force_infer_lt = Some((arg, param)); params.next(); } @@ -388,7 +389,7 @@ pub fn lower_generic_args<'tcx: 'a, 'a>( (None, Some(¶m)) => { // If there are fewer arguments than parameters, it means // we're inferring the remaining arguments. - args.push(ctx.inferred_kind(Some(&args), param, infer_args)); + args.push(ctx.inferred_kind(&args, param, infer_args)); params.next(); } 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 4b8e12a489c5..f073d92a1b91 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -245,7 +245,7 @@ pub trait GenericArgsLowerer<'a, 'tcx> { fn inferred_kind( &mut self, - args: Option<&[ty::GenericArg<'tcx>]>, + preceding_args: &[ty::GenericArg<'tcx>], param: &ty::GenericParamDef, infer_args: bool, ) -> ty::GenericArg<'tcx>; @@ -525,7 +525,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { fn inferred_kind( &mut self, - args: Option<&[ty::GenericArg<'tcx>]>, + preceding_args: &[ty::GenericArg<'tcx>], param: &ty::GenericParamDef, infer_args: bool, ) -> ty::GenericArg<'tcx> { @@ -533,22 +533,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { if let Err(incorrect) = self.incorrect_args { if incorrect.invalid_args.contains(&(param.index as usize)) { - // FIXME: use `param.to_error` once `inferred_kind` is supplied a list of - // all previous generic args. - return match param.kind { - GenericParamDefKind::Lifetime => { - ty::Region::new_error(tcx, incorrect.reported).into() - } - GenericParamDefKind::Type { .. } => { - Ty::new_error(tcx, incorrect.reported).into() - } - GenericParamDefKind::Const { .. } => ty::Const::new_error( - tcx, - incorrect.reported, - Ty::new_error(tcx, incorrect.reported), - ) - .into(), - }; + return param.to_error(tcx, preceding_args); } } match param.kind { @@ -569,15 +554,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { GenericParamDefKind::Type { has_default, .. } => { if !infer_args && has_default { // No type parameter provided, but a default exists. - let args = args.unwrap(); - if args.iter().any(|arg| match arg.unpack() { - GenericArgKind::Type(ty) => ty.references_error(), - _ => false, - }) { + if let Some(prev) = + preceding_args.iter().find_map(|arg| match arg.unpack() { + GenericArgKind::Type(ty) => ty.error_reported().err(), + _ => None, + }) + { // Avoid ICE #86756 when type error recovery goes awry. - return Ty::new_misc_error(tcx).into(); + return Ty::new_error(tcx, prev).into(); } - tcx.at(self.span).type_of(param.def_id).instantiate(tcx, args).into() + tcx.at(self.span) + .type_of(param.def_id) + .instantiate(tcx, preceding_args) + .into() } else if infer_args { self.lowerer.ty_infer(Some(param), self.span).into() } else { @@ -597,7 +586,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // FIXME(effects) see if we should special case effect params here if !infer_args && has_default { tcx.const_param_default(param.def_id) - .instantiate(tcx, args.unwrap()) + .instantiate(tcx, preceding_args) .into() } else { if infer_args { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index bae99fe79773..5edbf584b2e2 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1317,7 +1317,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn inferred_kind( &mut self, - args: Option<&[ty::GenericArg<'tcx>]>, + preceding_args: &[ty::GenericArg<'tcx>], param: &ty::GenericParamDef, infer_args: bool, ) -> ty::GenericArg<'tcx> { @@ -1331,7 +1331,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If we have a default, then it doesn't matter that we're not // inferring the type arguments: we provide the default where any // is missing. - tcx.type_of(param.def_id).instantiate(tcx, args.unwrap()).into() + tcx.type_of(param.def_id).instantiate(tcx, preceding_args).into() } else { // If no type arguments were provided, we have to infer them. // This case also occurs as a result of some malformed input, e.g. @@ -1356,7 +1356,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else if !infer_args { return tcx .const_param_default(param.def_id) - .instantiate(tcx, args.unwrap()) + .instantiate(tcx, preceding_args) .into(); } } diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 9c64f9475cf1..cde5c71966cd 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -419,7 +419,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { fn inferred_kind( &mut self, - _args: Option<&[ty::GenericArg<'tcx>]>, + _preceding_args: &[ty::GenericArg<'tcx>], param: &ty::GenericParamDef, _infer_args: bool, ) -> ty::GenericArg<'tcx> { From d498eb59373a71a166f31b1a9b70a7d8ac9cd4a3 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 3 Jun 2024 13:48:54 +0000 Subject: [PATCH 189/211] Provide previous generic arguments to `provided_kind` --- .../src/hir_ty_lowering/generics.rs | 2 +- .../src/hir_ty_lowering/mod.rs | 19 +++---------------- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 1 + .../rustc_hir_typeck/src/method/confirm.rs | 1 + 4 files changed, 6 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs index 72e03ead76b0..26cabb69d25c 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs @@ -282,7 +282,7 @@ pub fn lower_generic_args<'tcx: 'a, 'a>( GenericParamDefKind::Const { .. }, _, ) => { - args.push(ctx.provided_kind(param, arg)); + args.push(ctx.provided_kind(&args, param, arg)); args_iter.next(); params.next(); } 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 f073d92a1b91..56e2a05214ea 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -239,6 +239,7 @@ pub trait GenericArgsLowerer<'a, 'tcx> { fn provided_kind( &mut self, + preceding_args: &[ty::GenericArg<'tcx>], param: &ty::GenericParamDef, arg: &GenericArg<'tcx>, ) -> ty::GenericArg<'tcx>; @@ -437,6 +438,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { fn provided_kind( &mut self, + preceding_args: &[ty::GenericArg<'tcx>], param: &ty::GenericParamDef, arg: &GenericArg<'tcx>, ) -> ty::GenericArg<'tcx> { @@ -444,22 +446,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { if let Err(incorrect) = self.incorrect_args { if incorrect.invalid_args.contains(&(param.index as usize)) { - // FIXME: use `param.to_error` once `provided_kind` is supplied a list of - // all previous generic args. - return match param.kind { - GenericParamDefKind::Lifetime => { - ty::Region::new_error(tcx, incorrect.reported).into() - } - GenericParamDefKind::Type { .. } => { - Ty::new_error(tcx, incorrect.reported).into() - } - GenericParamDefKind::Const { .. } => ty::Const::new_error( - tcx, - incorrect.reported, - Ty::new_error(tcx, incorrect.reported), - ) - .into(), - }; + return param.to_error(tcx, preceding_args); } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 5edbf584b2e2..58eb0c281798 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1275,6 +1275,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn provided_kind( &mut self, + _preceding_args: &[ty::GenericArg<'tcx>], param: &ty::GenericParamDef, arg: &GenericArg<'tcx>, ) -> ty::GenericArg<'tcx> { diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index cde5c71966cd..0825e6613730 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -383,6 +383,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { fn provided_kind( &mut self, + _preceding_args: &[ty::GenericArg<'tcx>], param: &ty::GenericParamDef, arg: &GenericArg<'tcx>, ) -> ty::GenericArg<'tcx> { From de6b219803421da9f50a85c108847c51abf2e74a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 23 Apr 2024 14:52:54 -0400 Subject: [PATCH 190/211] Make WHERE_CLAUSES_OBJECT_SAFETY a regular object safety violation --- compiler/rustc_lint_defs/src/builtin.rs | 42 ---------- .../src/traits/object_safety.rs | 81 +------------------ src/tools/miri/tests/fail/issue-miri-2432.rs | 19 ----- .../miri/tests/fail/issue-miri-2432.stderr | 15 ---- .../object-safety-err-where-bounds.rs | 5 +- .../object-safety-err-where-bounds.stderr | 35 +++++--- tests/ui/issues/issue-50781.rs | 8 +- tests/ui/issues/issue-50781.stderr | 52 +++++++++--- tests/ui/object-safety/issue-106247.rs | 2 - tests/ui/traits/vtable/vtable-vacant.rs | 1 - tests/ui/traits/vtable/vtable-vacant.stderr | 2 +- .../self-in-where-clause-allowed.rs | 1 - .../self-in-where-clause-allowed.stderr | 4 +- 13 files changed, 75 insertions(+), 192 deletions(-) delete mode 100644 src/tools/miri/tests/fail/issue-miri-2432.rs delete mode 100644 src/tools/miri/tests/fail/issue-miri-2432.stderr diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 93995fe60a36..a3044489fdce 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -136,7 +136,6 @@ declare_lint_pass! { USELESS_DEPRECATED, WARNINGS, WASM_C_ABI, - WHERE_CLAUSES_OBJECT_SAFETY, WRITES_THROUGH_IMMUTABLE_POINTER, // tidy-alphabetical-end ] @@ -2093,47 +2092,6 @@ declare_lint! { "detects labels that are never used" } -declare_lint! { - /// The `where_clauses_object_safety` lint detects for [object safety] of - /// [where clauses]. - /// - /// [object safety]: https://doc.rust-lang.org/reference/items/traits.html#object-safety - /// [where clauses]: https://doc.rust-lang.org/reference/items/generics.html#where-clauses - /// - /// ### Example - /// - /// ```rust,no_run - /// trait Trait {} - /// - /// trait X { fn foo(&self) where Self: Trait; } - /// - /// impl X for () { fn foo(&self) {} } - /// - /// impl Trait for dyn X {} - /// - /// // Segfault at opt-level 0, SIGILL otherwise. - /// pub fn main() { ::foo(&()); } - /// ``` - /// - /// {{produces}} - /// - /// ### Explanation - /// - /// The compiler previously allowed these object-unsafe bounds, which was - /// incorrect. This is a [future-incompatible] lint to transition this to - /// a hard error in the future. See [issue #51443] for more details. - /// - /// [issue #51443]: https://github.com/rust-lang/rust/issues/51443 - /// [future-incompatible]: ../index.md#future-incompatible-lints - pub WHERE_CLAUSES_OBJECT_SAFETY, - Warn, - "checks the object safety of where clauses", - @future_incompatible = FutureIncompatibleInfo { - reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, - reference: "issue #51443 ", - }; -} - declare_lint! { /// The `proc_macro_derive_resolution_fallback` lint detects proc macro /// derives using inaccessible names from parent modules. diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 0f32b6ef9e39..201f71b079b5 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -13,7 +13,7 @@ use super::elaborate; use crate::infer::TyCtxtInferExt; use crate::traits::query::evaluate_obligation::InferCtxtExt; use crate::traits::{self, Obligation, ObligationCause}; -use rustc_errors::{FatalError, MultiSpan}; +use rustc_errors::FatalError; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_middle::query::Providers; @@ -23,7 +23,6 @@ use rustc_middle::ty::{ }; use rustc_middle::ty::{GenericArg, GenericArgs}; use rustc_middle::ty::{TypeVisitableExt, Upcast}; -use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY; use rustc_span::symbol::Symbol; use rustc_span::Span; use rustc_target::abi::Abi; @@ -66,44 +65,13 @@ fn object_safety_violations(tcx: TyCtxt<'_>, trait_def_id: DefId) -> &'_ [Object } fn check_is_object_safe(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool { - let violations = tcx.object_safety_violations(trait_def_id); - - if violations.is_empty() { - return true; - } - - // If the trait contains any other violations, then let the error reporting path - // report it instead of emitting a warning here. - if violations.iter().all(|violation| { - matches!( - violation, - ObjectSafetyViolation::Method(_, MethodViolationCode::WhereClauseReferencesSelf, _) - ) - }) { - for violation in violations { - if let ObjectSafetyViolation::Method( - _, - MethodViolationCode::WhereClauseReferencesSelf, - span, - ) = violation - { - lint_object_unsafe_trait(tcx, *span, trait_def_id, violation); - } - } - return true; - } - - false + tcx.object_safety_violations(trait_def_id).is_empty() } /// We say a method is *vtable safe* if it can be invoked on a trait /// object. Note that object-safe traits can have some /// non-vtable-safe methods, so long as they require `Self: Sized` or /// otherwise ensure that they cannot be used when `Self = Trait`. -/// -/// [`MethodViolationCode::WhereClauseReferencesSelf`] is considered object safe due to backwards -/// compatibility, see and -/// [`WHERE_CLAUSES_OBJECT_SAFETY`]. pub fn is_vtable_safe_method(tcx: TyCtxt<'_>, trait_def_id: DefId, method: ty::AssocItem) -> bool { debug_assert!(tcx.generics_of(trait_def_id).has_self); debug!("is_vtable_safe_method({:?}, {:?})", trait_def_id, method); @@ -112,9 +80,7 @@ pub fn is_vtable_safe_method(tcx: TyCtxt<'_>, trait_def_id: DefId, method: ty::A return false; } - virtual_call_violations_for_method(tcx, trait_def_id, method) - .iter() - .all(|v| matches!(v, MethodViolationCode::WhereClauseReferencesSelf)) + virtual_call_violations_for_method(tcx, trait_def_id, method).is_empty() } fn object_safety_violations_for_trait( @@ -163,47 +129,6 @@ fn object_safety_violations_for_trait( violations } -/// Lint object-unsafe trait. -fn lint_object_unsafe_trait( - tcx: TyCtxt<'_>, - span: Span, - trait_def_id: DefId, - violation: &ObjectSafetyViolation, -) { - // Using `CRATE_NODE_ID` is wrong, but it's hard to get a more precise id. - // It's also hard to get a use site span, so we use the method definition span. - tcx.node_span_lint(WHERE_CLAUSES_OBJECT_SAFETY, hir::CRATE_HIR_ID, span, |err| { - err.primary_message(format!( - "the trait `{}` cannot be made into an object", - tcx.def_path_str(trait_def_id) - )); - let node = tcx.hir().get_if_local(trait_def_id); - let mut spans = MultiSpan::from_span(span); - if let Some(hir::Node::Item(item)) = node { - spans.push_span_label(item.ident.span, "this trait cannot be made into an object..."); - spans.push_span_label(span, format!("...because {}", violation.error_msg())); - } else { - spans.push_span_label( - span, - format!( - "the trait cannot be made into an object because {}", - violation.error_msg() - ), - ); - }; - err.span_note( - spans, - "for a trait to be \"object safe\" it needs to allow building a vtable to allow the \ - call to be resolvable dynamically; for more information visit \ - ", - ); - if node.is_some() { - // Only provide the help if its a local trait, otherwise it's not - violation.solution().add_to(err); - } - }); -} - fn sized_trait_bound_spans<'tcx>( tcx: TyCtxt<'tcx>, bounds: hir::GenericBounds<'tcx>, diff --git a/src/tools/miri/tests/fail/issue-miri-2432.rs b/src/tools/miri/tests/fail/issue-miri-2432.rs deleted file mode 100644 index f822479c4368..000000000000 --- a/src/tools/miri/tests/fail/issue-miri-2432.rs +++ /dev/null @@ -1,19 +0,0 @@ -#![allow(where_clauses_object_safety)] - -trait Trait {} - -trait X { - fn foo(&self) - where - Self: Trait; -} - -impl X for () { - fn foo(&self) {} -} - -impl Trait for dyn X {} - -pub fn main() { - ::foo(&()); //~ERROR: trying to call something that is not a method -} diff --git a/src/tools/miri/tests/fail/issue-miri-2432.stderr b/src/tools/miri/tests/fail/issue-miri-2432.stderr deleted file mode 100644 index 3befe31dc5a0..000000000000 --- a/src/tools/miri/tests/fail/issue-miri-2432.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error: Undefined Behavior: `dyn` call trying to call something that is not a method - --> $DIR/issue-miri-2432.rs:LL:CC - | -LL | ::foo(&()); - | ^^^^^^^^^^^^^^^^^^^^^^ `dyn` call trying to call something that is not a method - | - = 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/issue-miri-2432.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/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.rs b/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.rs index 42c1cc507b5c..b3bbb8426386 100644 --- a/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.rs +++ b/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.rs @@ -1,14 +1,11 @@ #![feature(generic_const_exprs)] #![allow(incomplete_features)] -#![deny(where_clauses_object_safety)] const fn bar() -> usize { 7 } trait Foo { fn test(&self) where [u8; bar::()]: Sized; - //~^ ERROR the trait `Foo` cannot be made into an object - //~| WARN this was previously accepted by the compiler but is being phased out } impl Foo for () { @@ -16,7 +13,9 @@ impl Foo for () { } fn use_dyn(v: &dyn Foo) { + //~^ ERROR the trait `Foo` cannot be made into an object v.test(); + //~^ ERROR the trait `Foo` cannot be made into an object } fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.stderr b/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.stderr index 9e480ce9b856..fde5d3ce7725 100644 --- a/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.stderr +++ b/tests/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.stderr @@ -1,24 +1,35 @@ -error: the trait `Foo` cannot be made into an object - --> $DIR/object-safety-err-where-bounds.rs:9:8 +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/object-safety-err-where-bounds.rs:15:16 | -LL | fn test(&self) where [u8; bar::()]: Sized; - | ^^^^ +LL | fn use_dyn(v: &dyn Foo) { + | ^^^^^^^ `Foo` cannot be made into an object | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #51443 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety-err-where-bounds.rs:9:8 + --> $DIR/object-safety-err-where-bounds.rs:8:8 | LL | trait Foo { | --- this trait cannot be made into an object... LL | fn test(&self) where [u8; bar::()]: Sized; | ^^^^ ...because method `test` references the `Self` type in its `where` clause = help: consider moving `test` to another trait -note: the lint level is defined here - --> $DIR/object-safety-err-where-bounds.rs:3:9 + = help: only type `()` implements the trait, consider using it directly instead + +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/object-safety-err-where-bounds.rs:17:5 | -LL | #![deny(where_clauses_object_safety)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | v.test(); + | ^^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety-err-where-bounds.rs:8:8 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | fn test(&self) where [u8; bar::()]: Sized; + | ^^^^ ...because method `test` references the `Self` type in its `where` clause + = help: consider moving `test` to another trait + = help: only type `()` implements the trait, consider using it directly instead -error: aborting due to 1 previous error +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/issues/issue-50781.rs b/tests/ui/issues/issue-50781.rs index 3c5e5a9f69af..32253c3c2360 100644 --- a/tests/ui/issues/issue-50781.rs +++ b/tests/ui/issues/issue-50781.rs @@ -1,10 +1,7 @@ -#![deny(where_clauses_object_safety)] - trait Trait {} trait X { - fn foo(&self) where Self: Trait; //~ ERROR the trait `X` cannot be made into an object - //~^ WARN this was previously accepted by the compiler but is being phased out + fn foo(&self) where Self: Trait; } impl X for () { @@ -12,8 +9,11 @@ impl X for () { } impl Trait for dyn X {} +//~^ ERROR the trait `X` cannot be made into an object pub fn main() { // Check that this does not segfault. ::foo(&()); + //~^ ERROR the trait `X` cannot be made into an object + //~| ERROR the trait `X` cannot be made into an object } diff --git a/tests/ui/issues/issue-50781.stderr b/tests/ui/issues/issue-50781.stderr index beaea1e634ce..6b0b42ca53a6 100644 --- a/tests/ui/issues/issue-50781.stderr +++ b/tests/ui/issues/issue-50781.stderr @@ -1,24 +1,52 @@ -error: the trait `X` cannot be made into an object - --> $DIR/issue-50781.rs:6:8 +error[E0038]: the trait `X` cannot be made into an object + --> $DIR/issue-50781.rs:11:16 | -LL | fn foo(&self) where Self: Trait; - | ^^^ +LL | impl Trait for dyn X {} + | ^^^^^ `X` cannot be made into an object | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #51443 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/issue-50781.rs:6:8 + --> $DIR/issue-50781.rs:4:8 | LL | trait X { | - this trait cannot be made into an object... LL | fn foo(&self) where Self: Trait; | ^^^ ...because method `foo` references the `Self` type in its `where` clause = help: consider moving `foo` to another trait -note: the lint level is defined here - --> $DIR/issue-50781.rs:1:9 + = help: only type `()` implements the trait, consider using it directly instead + +error[E0038]: the trait `X` cannot be made into an object + --> $DIR/issue-50781.rs:16:23 | -LL | #![deny(where_clauses_object_safety)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | ::foo(&()); + | ^^^ `X` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-50781.rs:4:8 + | +LL | trait X { + | - this trait cannot be made into an object... +LL | fn foo(&self) where Self: Trait; + | ^^^ ...because method `foo` references the `Self` type in its `where` clause + = help: consider moving `foo` to another trait + = help: only type `()` implements the trait, consider using it directly instead + = note: required for the cast from `&()` to `&dyn X` -error: aborting due to 1 previous error +error[E0038]: the trait `X` cannot be made into an object + --> $DIR/issue-50781.rs:16:6 + | +LL | ::foo(&()); + | ^^^^^ `X` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-50781.rs:4:8 + | +LL | trait X { + | - this trait cannot be made into an object... +LL | fn foo(&self) where Self: Trait; + | ^^^ ...because method `foo` references the `Self` type in its `where` clause + = help: consider moving `foo` to another trait + = help: only type `()` implements the trait, consider using it directly instead +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/issue-106247.rs b/tests/ui/object-safety/issue-106247.rs index 78bae5681619..20a451a59a16 100644 --- a/tests/ui/object-safety/issue-106247.rs +++ b/tests/ui/object-safety/issue-106247.rs @@ -1,7 +1,5 @@ //@ check-pass -#![deny(where_clauses_object_safety)] - pub trait Trait { fn method(&self) where Self: Sync; } diff --git a/tests/ui/traits/vtable/vtable-vacant.rs b/tests/ui/traits/vtable/vtable-vacant.rs index 26de3f606210..b3c768157036 100644 --- a/tests/ui/traits/vtable/vtable-vacant.rs +++ b/tests/ui/traits/vtable/vtable-vacant.rs @@ -1,7 +1,6 @@ //@ build-fail #![feature(rustc_attrs)] #![feature(negative_impls)] -#![allow(where_clauses_object_safety)] // B --> A diff --git a/tests/ui/traits/vtable/vtable-vacant.stderr b/tests/ui/traits/vtable/vtable-vacant.stderr index 9ce1d0b76328..f6961ca010ed 100644 --- a/tests/ui/traits/vtable/vtable-vacant.stderr +++ b/tests/ui/traits/vtable/vtable-vacant.stderr @@ -7,7 +7,7 @@ error: vtable entries for ``: [ Method(::foo_b1), Vacant, ] - --> $DIR/vtable-vacant.rs:15:1 + --> $DIR/vtable-vacant.rs:14:1 | LL | trait B: A { | ^^^^^^^^^^ diff --git a/tests/ui/where-clauses/self-in-where-clause-allowed.rs b/tests/ui/where-clauses/self-in-where-clause-allowed.rs index fd2cfe2bf65e..a4c2d82b4837 100644 --- a/tests/ui/where-clauses/self-in-where-clause-allowed.rs +++ b/tests/ui/where-clauses/self-in-where-clause-allowed.rs @@ -1,7 +1,6 @@ //@ check-fail #![feature(auto_traits)] -#![deny(where_clauses_object_safety)] auto trait AutoTrait {} diff --git a/tests/ui/where-clauses/self-in-where-clause-allowed.stderr b/tests/ui/where-clauses/self-in-where-clause-allowed.stderr index 7f92ac102f01..5d23c4bee00f 100644 --- a/tests/ui/where-clauses/self-in-where-clause-allowed.stderr +++ b/tests/ui/where-clauses/self-in-where-clause-allowed.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `dyn Trait: AutoTrait` is not satisfied - --> $DIR/self-in-where-clause-allowed.rs:22:18 + --> $DIR/self-in-where-clause-allowed.rs:21:18 | LL | trait_object.autotrait_bound(); | ^^^^^^^^^^^^^^^ the trait `AutoTrait` is not implemented for `dyn Trait` | note: required by a bound in `Trait::autotrait_bound` - --> $DIR/self-in-where-clause-allowed.rs:13:43 + --> $DIR/self-in-where-clause-allowed.rs:12:43 | LL | fn autotrait_bound(&self) where Self: AutoTrait {} | ^^^^^^^^^ required by this bound in `Trait::autotrait_bound` From 511f1cf7c8e96c2350dac7b4870e92c99ee08b92 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 21 May 2024 14:39:30 -0400 Subject: [PATCH 191/211] check_is_object_safe -> is_object_safe --- compiler/rustc_hir_analysis/src/check/wfcheck.rs | 2 +- compiler/rustc_hir_analysis/src/coherence/mod.rs | 2 +- compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs | 2 +- compiler/rustc_interface/src/passes.rs | 2 +- compiler/rustc_lint/src/multiple_supertrait_upcastable.rs | 4 ++-- compiler/rustc_middle/src/query/mod.rs | 2 +- .../src/cfi/typeid/itanium_cxx_abi/transform.rs | 2 +- compiler/rustc_trait_selection/src/solve/assembly/mod.rs | 2 +- compiler/rustc_trait_selection/src/solve/mod.rs | 2 +- compiler/rustc_trait_selection/src/solve/trait_goals.rs | 2 +- compiler/rustc_trait_selection/src/traits/fulfill.rs | 2 +- compiler/rustc_trait_selection/src/traits/object_safety.rs | 4 ++-- .../src/traits/select/candidate_assembly.rs | 2 +- .../rustc_trait_selection/src/traits/select/confirmation.rs | 2 +- compiler/rustc_trait_selection/src/traits/select/mod.rs | 2 +- src/librustdoc/clean/types.rs | 2 +- 16 files changed, 18 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 81e3d8c7ece2..68304e683248 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -881,7 +881,7 @@ fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem _ => {} } if !trait_should_be_self.is_empty() { - if tcx.check_is_object_safe(trait_def_id) { + if tcx.is_object_safe(trait_def_id) { return; } let sugg = trait_should_be_self.iter().map(|span| (*span, "Self".to_string())).collect(); diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index 480318acca8e..eae41d28e897 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -191,7 +191,7 @@ fn check_object_overlap<'tcx>( }); for component_def_id in component_def_ids { - if !tcx.check_is_object_safe(component_def_id) { + if !tcx.is_object_safe(component_def_id) { // Without the 'object_safe_for_dispatch' feature this is an error // which will be reported by wfcheck. Ignore it here. // This is tested by `coherence-impl-trait-for-trait-object-safe.rs`. diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs index b4305f6efb9a..240a749de96a 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs @@ -182,7 +182,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // For recursive traits, don't downgrade the error. (#119652) is_downgradable = false; } - tcx.check_is_object_safe(id) + tcx.is_object_safe(id) } _ => false, }) diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 33995f80162e..b678582766d5 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -832,7 +832,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { let traits = tcx.traits(LOCAL_CRATE); for &tr in traits { - if !tcx.check_is_object_safe(tr) { + if !tcx.is_object_safe(tr) { continue; } diff --git a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs index 48d140c6b7f3..aa1d94228ea2 100644 --- a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs +++ b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs @@ -38,10 +38,10 @@ declare_lint_pass!(MultipleSupertraitUpcastable => [MULTIPLE_SUPERTRAIT_UPCASTAB impl<'tcx> LateLintPass<'tcx> for MultipleSupertraitUpcastable { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) { let def_id = item.owner_id.to_def_id(); - // NOTE(nbdd0121): use `object_safety_violations` instead of `check_is_object_safe` because + // NOTE(nbdd0121): use `object_safety_violations` instead of `is_object_safe` because // the latter will report `where_clause_object_safety` lint. if let hir::ItemKind::Trait(_, _, _, _, _) = item.kind - && cx.tcx.object_safety_violations(def_id).is_empty() + && cx.tcx.is_object_safe(def_id) { let direct_super_traits_iter = cx .tcx diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index d72ad09f9548..3c4aae73bc49 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1309,7 +1309,7 @@ rustc_queries! { query object_safety_violations(trait_id: DefId) -> &'tcx [ObjectSafetyViolation] { desc { |tcx| "determining object safety of trait `{}`", tcx.def_path_str(trait_id) } } - query check_is_object_safe(trait_id: DefId) -> bool { + query is_object_safe(trait_id: DefId) -> bool { desc { |tcx| "checking if trait `{}` is object safe", tcx.def_path_str(trait_id) } } diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs index 62eb07e82871..2fbfb93150e7 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs @@ -367,7 +367,7 @@ pub fn transform_instance<'tcx>( let trait_method = tcx.associated_item(method_id); let trait_id = trait_ref.skip_binder().def_id; if traits::is_vtable_safe_method(tcx, trait_id, trait_method) - && tcx.object_safety_violations(trait_id).is_empty() + && tcx.is_object_safe(trait_id) { // Trait methods will have a Self polymorphic parameter, where the concreteized // implementatation will not. We need to walk back to the more general trait method diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index aae6fa9f635b..b51efd339c4d 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -714,7 +714,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { }; // Do not consider built-in object impls for non-object-safe types. - if bounds.principal_def_id().is_some_and(|def_id| !tcx.check_is_object_safe(def_id)) { + if bounds.principal_def_id().is_some_and(|def_id| !tcx.is_object_safe(def_id)) { return; } diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index f9febd290fe7..b0edbf3cbef8 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -133,7 +133,7 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> { } fn compute_object_safe_goal(&mut self, trait_def_id: DefId) -> QueryResult<'tcx> { - if self.interner().check_is_object_safe(trait_def_id) { + if self.interner().is_object_safe(trait_def_id) { self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } else { Err(NoSolution) diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index e93d5c96b880..a741f488901e 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -789,7 +789,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { let Goal { predicate: (a_ty, _), .. } = goal; // Can only unsize to an object-safe trait. - if b_data.principal_def_id().is_some_and(|def_id| !tcx.check_is_object_safe(def_id)) { + if b_data.principal_def_id().is_some_and(|def_id| !tcx.is_object_safe(def_id)) { return Err(NoSolution); } diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index e1afc2a35293..12aef87cb66f 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -411,7 +411,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { } ty::PredicateKind::ObjectSafe(trait_def_id) => { - if !self.selcx.tcx().check_is_object_safe(trait_def_id) { + if !self.selcx.tcx().is_object_safe(trait_def_id) { ProcessResult::Error(FulfillmentErrorCode::Select(Unimplemented)) } else { ProcessResult::Changed(vec![]) diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 201f71b079b5..08355ef55c49 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -64,7 +64,7 @@ fn object_safety_violations(tcx: TyCtxt<'_>, trait_def_id: DefId) -> &'_ [Object ) } -fn check_is_object_safe(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool { +fn is_object_safe(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool { tcx.object_safety_violations(trait_def_id).is_empty() } @@ -854,7 +854,7 @@ pub fn contains_illegal_impl_trait_in_trait<'tcx>( pub fn provide(providers: &mut Providers) { *providers = Providers { object_safety_violations, - check_is_object_safe, + is_object_safe, generics_require_sized_self, ..*providers }; 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 d513a5d2996c..bb44be7799be 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -870,7 +870,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if let Some(principal) = data.principal() { if !self.infcx.tcx.features().object_safe_for_dispatch { principal.with_self_ty(self.tcx(), self_ty) - } else if self.tcx().check_is_object_safe(principal.def_id()) { + } else if self.tcx().is_object_safe(principal.def_id()) { principal.with_self_ty(self.tcx(), self_ty) } else { return; diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index c684f087d321..ef0d8735d35f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -1222,7 +1222,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // `T` -> `Trait` (_, &ty::Dynamic(data, r, ty::Dyn)) => { let mut object_dids = data.auto_traits().chain(data.principal_def_id()); - if let Some(did) = object_dids.find(|did| !tcx.check_is_object_safe(*did)) { + if let Some(did) = object_dids.find(|did| !tcx.is_object_safe(*did)) { return Err(TraitNotObjectSafe(did)); } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index dcb0875639fc..2489b8916d18 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -798,7 +798,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } ty::PredicateKind::ObjectSafe(trait_def_id) => { - if self.tcx().check_is_object_safe(trait_def_id) { + if self.tcx().is_object_safe(trait_def_id) { Ok(EvaluatedToOk) } else { Ok(EvaluatedToErr) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 3f84da310ddc..b387809cc717 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1451,7 +1451,7 @@ impl Trait { tcx.trait_def(self.def_id).safety } pub(crate) fn is_object_safe(&self, tcx: TyCtxt<'_>) -> bool { - tcx.check_is_object_safe(self.def_id) + tcx.is_object_safe(self.def_id) } } From a41c44f21c1a6fd96eb8d68fbdb298610443cff5 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 3 Jun 2024 09:27:48 -0400 Subject: [PATCH 192/211] Nits and formatting --- .../src/type_check/constraint_conversion.rs | 6 +-- .../src/check/compare_impl_item.rs | 11 ++---- .../src/coherence/orphan.rs | 18 ++++----- .../src/infer/canonical/query_response.rs | 10 ++--- compiler/rustc_infer/src/infer/mod.rs | 5 +-- compiler/rustc_infer/src/traits/engine.rs | 33 ++++++++++++++--- compiler/rustc_infer/src/traits/mod.rs | 2 +- compiler/rustc_macros/src/extension.rs | 9 +++-- .../src/solve/fulfill.rs | 13 ++++--- .../src/solve/inspect/analyse.rs | 1 - .../src/solve/normalize.rs | 36 +++++++++--------- .../src/traits/engine.rs | 32 ++++++++-------- .../src/traits/fulfill.rs | 34 +++++++++++------ .../rustc_trait_selection/src/traits/mod.rs | 37 ------------------- .../src/traits/normalize.rs | 11 +++--- .../query/type_op/implied_outlives_bounds.rs | 10 ++--- .../src/traits/structural_normalize.rs | 4 +- 17 files changed, 130 insertions(+), 142 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index 266a80187c54..0cb4b15b1271 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -10,7 +10,6 @@ use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_span::Span; -use rustc_trait_selection::solve::deeply_normalize; use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp; use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput}; use rustc_trait_selection::traits::ScrubbedTraitError; @@ -283,8 +282,9 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { ) -> Ty<'tcx> { let result = CustomTypeOp::new( |ocx| { - deeply_normalize( - ocx.infcx.at(&ObligationCause::dummy_with_span(self.span), self.param_env), + ocx.deeply_normalize( + &ObligationCause::dummy_with_span(self.span), + self.param_env, ty, ) .map_err(|_: Vec>| NoSolution) 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 594d28eda7ac..f7bebc2697d7 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -10,7 +10,7 @@ use rustc_hir::intravisit; use rustc_hir::{GenericParamKind, ImplItemKind}; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; -use rustc_infer::traits::{util, FulfillmentErrorLike}; +use rustc_infer::traits::util; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::util::ExplicitSelf; @@ -764,10 +764,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( Ok(&*tcx.arena.alloc(remapped_types)) } -struct ImplTraitInTraitCollector<'a, 'tcx, E> -where - E: FulfillmentErrorLike<'tcx>, -{ +struct ImplTraitInTraitCollector<'a, 'tcx, E> { ocx: &'a ObligationCtxt<'a, 'tcx, E>, types: FxIndexMap, ty::GenericArgsRef<'tcx>)>, span: Span, @@ -777,7 +774,7 @@ where impl<'a, 'tcx, E> ImplTraitInTraitCollector<'a, 'tcx, E> where - E: FulfillmentErrorLike<'tcx>, + E: 'tcx, { fn new( ocx: &'a ObligationCtxt<'a, 'tcx, E>, @@ -791,7 +788,7 @@ where impl<'tcx, E> TypeFolder> for ImplTraitInTraitCollector<'_, 'tcx, E> where - E: FulfillmentErrorLike<'tcx>, + E: 'tcx, { fn interner(&self) -> TyCtxt<'tcx> { self.ocx.infcx.tcx diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index 1e7bb63e6ea4..61ac4af01519 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -12,11 +12,8 @@ use rustc_middle::ty::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; use rustc_middle::{bug, span_bug}; use rustc_span::def_id::{DefId, LocalDefId}; -use rustc_trait_selection::traits::{ - self, IsFirstInputType, ScrubbedTraitError, UncoveredTyParams, -}; +use rustc_trait_selection::traits::{self, IsFirstInputType, UncoveredTyParams}; use rustc_trait_selection::traits::{OrphanCheckErr, OrphanCheckMode}; -use rustc_trait_selection::traits::{StructurallyNormalizeExt, TraitEngineExt}; #[instrument(level = "debug", skip(tcx))] pub(crate) fn orphan_check_impl( @@ -319,13 +316,12 @@ fn orphan_check<'tcx>( } let ty = if infcx.next_trait_solver() { - let mut fulfill_cx = - >>::new(&infcx); - infcx - .at(&cause, ty::ParamEnv::empty()) - .structurally_normalize(ty, &mut *fulfill_cx) - .map(|ty| infcx.resolve_vars_if_possible(ty)) - .unwrap_or(ty) + ocx.structurally_normalize( + &cause, + ty::ParamEnv::empty(), + infcx.resolve_vars_if_possible(ty), + ) + .unwrap_or(ty) } else { ty }; diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 4917f936f4e1..d7dd6a1e7cf5 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -15,8 +15,8 @@ use crate::infer::canonical::{ use crate::infer::region_constraints::{Constraint, RegionConstraintData}; use crate::infer::{DefineOpaqueTypes, InferCtxt, InferOk, InferResult}; use crate::traits::query::NoSolution; -use crate::traits::{FulfillmentErrorLike, TraitEngine}; use crate::traits::{Obligation, ObligationCause, PredicateObligation}; +use crate::traits::{ScrubbedTraitError, TraitEngine}; use rustc_data_structures::captures::Captures; use rustc_index::Idx; use rustc_index::IndexVec; @@ -50,11 +50,11 @@ impl<'tcx> InferCtxt<'tcx> { /// - Finally, if any of the obligations result in a hard error, /// then `Err(NoSolution)` is returned. #[instrument(skip(self, inference_vars, answer, fulfill_cx), level = "trace")] - pub fn make_canonicalized_query_response>( + pub fn make_canonicalized_query_response( &self, inference_vars: CanonicalVarValues<'tcx>, answer: T, - fulfill_cx: &mut dyn TraitEngine<'tcx, E>, + fulfill_cx: &mut dyn TraitEngine<'tcx, ScrubbedTraitError<'tcx>>, ) -> Result, NoSolution> where T: Debug + TypeFoldable>, @@ -97,11 +97,11 @@ impl<'tcx> InferCtxt<'tcx> { /// Helper for `make_canonicalized_query_response` that does /// everything up until the final canonicalization. #[instrument(skip(self, fulfill_cx), level = "debug")] - fn make_query_response>( + fn make_query_response( &self, inference_vars: CanonicalVarValues<'tcx>, answer: T, - fulfill_cx: &mut dyn TraitEngine<'tcx, E>, + fulfill_cx: &mut dyn TraitEngine<'tcx, ScrubbedTraitError<'tcx>>, ) -> Result, NoSolution> where T: Debug + TypeFoldable>, diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 5183d9e2d6eb..72c4e1b511e6 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -12,8 +12,7 @@ pub use SubregionOrigin::*; pub use ValuePairs::*; use crate::traits::{ - self, FulfillmentErrorLike, ObligationCause, ObligationInspector, PredicateObligations, - TraitEngine, + self, ObligationCause, ObligationInspector, PredicateObligations, TraitEngine, }; use error_reporting::TypeErrCtxt; use free_regions::RegionRelations; @@ -738,7 +737,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> { impl<'tcx, T> InferOk<'tcx, T> { /// Extracts `value`, registering any obligations into `fulfill_cx`. - pub fn into_value_registering_obligations>( + pub fn into_value_registering_obligations( self, infcx: &InferCtxt<'tcx>, fulfill_cx: &mut dyn TraitEngine<'tcx, E>, diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs index 1d6875d0f8ed..026b2c1b905e 100644 --- a/compiler/rustc_infer/src/traits/engine.rs +++ b/compiler/rustc_infer/src/traits/engine.rs @@ -7,7 +7,32 @@ use rustc_middle::ty::{self, Ty, Upcast}; use super::{ObligationCause, PredicateObligation}; -pub trait TraitEngine<'tcx, E: FulfillmentErrorLike<'tcx>>: 'tcx { +/// A trait error with most of its information removed. This is the error +/// returned by an `ObligationCtxt` by default, and suitable if you just +/// want to see if a predicate holds, and don't particularly care about the +/// error itself (except for if it's an ambiguity or true error). +/// +/// use `ObligationCtxt::new_with_diagnostics` to get a `FulfillmentError`. +#[derive(Clone, Debug)] +pub enum ScrubbedTraitError<'tcx> { + /// A real error. This goal definitely does not hold. + TrueError, + /// An ambiguity. This goal may hold if further inference is done. + Ambiguity, + /// An old-solver-style cycle error, which will fatal. + Cycle(Vec>), +} + +impl<'tcx> ScrubbedTraitError<'tcx> { + pub fn is_true_error(&self) -> bool { + match self { + ScrubbedTraitError::TrueError => true, + ScrubbedTraitError::Ambiguity | ScrubbedTraitError::Cycle(_) => false, + } + } +} + +pub trait TraitEngine<'tcx, E: 'tcx>: 'tcx { /// Requires that `ty` must implement the trait with `def_id` in /// the given environment. This trait must not have any type /// parameters (except for `Self`). @@ -73,10 +98,6 @@ pub trait TraitEngine<'tcx, E: FulfillmentErrorLike<'tcx>>: 'tcx { ) -> Vec>; } -pub trait FulfillmentErrorLike<'tcx>: Debug + 'tcx { - fn is_true_error(&self) -> bool; -} - -pub trait FromSolverError<'tcx, E>: FulfillmentErrorLike<'tcx> { +pub trait FromSolverError<'tcx, E>: Debug + 'tcx { fn from_solver_error(infcx: &InferCtxt<'tcx>, error: E) -> Self; } diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index e9c2d81aa0af..ca6c6570e072 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -22,7 +22,7 @@ pub use self::ImplSource::*; pub use self::SelectionError::*; use crate::infer::InferCtxt; -pub use self::engine::{FromSolverError, FulfillmentErrorLike, TraitEngine}; +pub use self::engine::{FromSolverError, ScrubbedTraitError, TraitEngine}; pub use self::project::MismatchedProjectionTypes; pub(crate) use self::project::UndoLog; pub use self::project::{ diff --git a/compiler/rustc_macros/src/extension.rs b/compiler/rustc_macros/src/extension.rs index 5377bbdfeabd..bbaa477237b1 100644 --- a/compiler/rustc_macros/src/extension.rs +++ b/compiler/rustc_macros/src/extension.rs @@ -6,6 +6,7 @@ use syn::spanned::Spanned; use syn::{ braced, parse_macro_input, Attribute, Generics, ImplItem, Pat, PatIdent, Path, Signature, Token, TraitItem, TraitItemConst, TraitItemFn, TraitItemMacro, TraitItemType, Type, Visibility, + WhereClause, }; pub(crate) fn extension( @@ -13,7 +14,7 @@ pub(crate) fn extension( input: proc_macro::TokenStream, ) -> proc_macro::TokenStream { let ExtensionAttr { vis, trait_ } = parse_macro_input!(attr as ExtensionAttr); - let Impl { attrs, generics, self_ty, items } = parse_macro_input!(input as Impl); + let Impl { attrs, generics, self_ty, items, wc } = parse_macro_input!(input as Impl); let headers: Vec<_> = items .iter() .map(|item| match item { @@ -59,7 +60,7 @@ pub(crate) fn extension( #(#headers)* } - impl #generics #trait_ for #self_ty { + impl #generics #trait_ for #self_ty #wc { #(#items)* } } @@ -133,6 +134,7 @@ struct Impl { generics: Generics, self_ty: Type, items: Vec, + wc: Option, } impl Parse for Impl { @@ -141,6 +143,7 @@ impl Parse for Impl { let _: Token![impl] = input.parse()?; let generics = input.parse()?; let self_ty = input.parse()?; + let wc = input.parse()?; let content; let _brace_token = braced!(content in input); @@ -149,6 +152,6 @@ impl Parse for Impl { items.push(content.parse()?); } - Ok(Impl { attrs, generics, self_ty, items }) + Ok(Impl { attrs, generics, self_ty, items, wc }) } } diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 3de4aee0927b..dc13941e5d7b 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -6,8 +6,8 @@ use rustc_infer::infer::InferCtxt; use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::solve::{CandidateSource, GoalSource, MaybeCause}; use rustc_infer::traits::{ - self, FromSolverError, FulfillmentErrorLike, MismatchedProjectionTypes, Obligation, - ObligationCause, ObligationCauseCode, PredicateObligation, SelectionError, TraitEngine, + self, FromSolverError, MismatchedProjectionTypes, Obligation, ObligationCause, + ObligationCauseCode, PredicateObligation, SelectionError, TraitEngine, }; use rustc_middle::bug; use rustc_middle::ty::error::{ExpectedFound, TypeError}; @@ -31,7 +31,7 @@ use super::{Certainty, InferCtxtEvalExt}; /// /// It is also likely that we want to use slightly different datastructures /// here as this will have to deal with far more root goals than `evaluate_all`. -pub struct FulfillmentCtxt<'tcx, E: FulfillmentErrorLike<'tcx>> { +pub struct FulfillmentCtxt<'tcx, E: 'tcx> { obligations: ObligationStorage<'tcx>, /// The snapshot in which this context was created. Using the context @@ -93,7 +93,7 @@ impl<'tcx> ObligationStorage<'tcx> { } } -impl<'tcx, E: FulfillmentErrorLike<'tcx>> FulfillmentCtxt<'tcx, E> { +impl<'tcx, E: 'tcx> FulfillmentCtxt<'tcx, E> { pub fn new(infcx: &InferCtxt<'tcx>) -> FulfillmentCtxt<'tcx, E> { assert!( infcx.next_trait_solver(), @@ -123,8 +123,9 @@ impl<'tcx, E: FulfillmentErrorLike<'tcx>> FulfillmentCtxt<'tcx, E> { } } -impl<'tcx, E: FromSolverError<'tcx, NextSolverError<'tcx>>> TraitEngine<'tcx, E> - for FulfillmentCtxt<'tcx, E> +impl<'tcx, E> TraitEngine<'tcx, E> for FulfillmentCtxt<'tcx, E> +where + E: FromSolverError<'tcx, NextSolverError<'tcx>>, { #[instrument(level = "trace", skip(self, infcx))] fn register_predicate_obligation( diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index dca14e20fb31..1f27978e5a62 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -12,7 +12,6 @@ use rustc_ast_ir::try_visit; use rustc_ast_ir::visit::VisitorResult; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk}; -use rustc_infer::traits::FulfillmentErrorLike as _; use rustc_macros::extension; use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::solve::{inspect, QueryResult}; diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs index 4211129a4e15..c60d1aed415a 100644 --- a/compiler/rustc_trait_selection/src/solve/normalize.rs +++ b/compiler/rustc_trait_selection/src/solve/normalize.rs @@ -1,3 +1,4 @@ +use std::fmt::Debug; use std::marker::PhantomData; use crate::traits::error_reporting::{OverflowCause, TypeErrCtxtExt}; @@ -6,7 +7,7 @@ use crate::traits::{BoundVarReplacer, PlaceholderReplacer, ScrubbedTraitError}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_infer::infer::at::At; use rustc_infer::infer::InferCtxt; -use rustc_infer::traits::{FromSolverError, FulfillmentErrorLike, Obligation, TraitEngine}; +use rustc_infer::traits::{FromSolverError, Obligation, TraitEngine}; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{self, Ty, TyCtxt, UniverseIndex}; use rustc_middle::ty::{FallibleTypeFolder, TypeFolder, TypeSuperFoldable}; @@ -16,14 +17,11 @@ use super::{FulfillmentCtxt, NextSolverError}; /// Deeply normalize all aliases in `value`. This does not handle inference and expects /// its input to be already fully resolved. -pub fn deeply_normalize< - 'tcx, +pub fn deeply_normalize<'tcx, T, E>(at: At<'_, 'tcx>, value: T) -> Result> +where T: TypeFoldable>, E: FromSolverError<'tcx, NextSolverError<'tcx>>, ->( - at: At<'_, 'tcx>, - value: T, -) -> Result> { +{ assert!(!value.has_escaping_bound_vars()); deeply_normalize_with_skipped_universes(at, value, vec![]) } @@ -34,15 +32,15 @@ pub fn deeply_normalize< /// Additionally takes a list of universes which represents the binders which have been /// entered before passing `value` to the function. This is currently needed for /// `normalize_erasing_regions`, which skips binders as it walks through a type. -pub fn deeply_normalize_with_skipped_universes< - 'tcx, - T: TypeFoldable>, - E: FromSolverError<'tcx, NextSolverError<'tcx>>, ->( +pub fn deeply_normalize_with_skipped_universes<'tcx, T, E>( at: At<'_, 'tcx>, value: T, universes: Vec>, -) -> Result> { +) -> Result> +where + T: TypeFoldable>, + E: FromSolverError<'tcx, NextSolverError<'tcx>>, +{ let fulfill_cx = FulfillmentCtxt::new(at.infcx); let mut folder = NormalizationFolder { at, fulfill_cx, depth: 0, universes, _errors: PhantomData }; @@ -50,7 +48,7 @@ pub fn deeply_normalize_with_skipped_universes< value.try_fold_with(&mut folder) } -struct NormalizationFolder<'me, 'tcx, E: FulfillmentErrorLike<'tcx>> { +struct NormalizationFolder<'me, 'tcx, E> { at: At<'me, 'tcx>, fulfill_cx: FulfillmentCtxt<'tcx, E>, depth: usize, @@ -58,7 +56,10 @@ struct NormalizationFolder<'me, 'tcx, E: FulfillmentErrorLike<'tcx>> { _errors: PhantomData, } -impl<'tcx, E: FromSolverError<'tcx, NextSolverError<'tcx>>> NormalizationFolder<'_, 'tcx, E> { +impl<'tcx, E> NormalizationFolder<'_, 'tcx, E> +where + E: FromSolverError<'tcx, NextSolverError<'tcx>>, +{ fn normalize_alias_ty(&mut self, alias_ty: Ty<'tcx>) -> Result, Vec> { assert!(matches!(alias_ty.kind(), ty::Alias(..))); @@ -150,8 +151,9 @@ impl<'tcx, E: FromSolverError<'tcx, NextSolverError<'tcx>>> NormalizationFolder< } } -impl<'tcx, E: FromSolverError<'tcx, NextSolverError<'tcx>>> FallibleTypeFolder> - for NormalizationFolder<'_, 'tcx, E> +impl<'tcx, E> FallibleTypeFolder> for NormalizationFolder<'_, 'tcx, E> +where + E: FromSolverError<'tcx, NextSolverError<'tcx>> + Debug, { type Error = Vec; diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index 397f9cf2638e..811f61d2bf37 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -21,7 +21,6 @@ use rustc_infer::infer::canonical::{ use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::RegionResolutionError; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk}; -use rustc_infer::traits::FulfillmentErrorLike; use rustc_macros::extension; use rustc_middle::arena::ArenaAllocatable; use rustc_middle::traits::query::NoSolution; @@ -32,10 +31,9 @@ use rustc_middle::ty::Variance; use rustc_middle::ty::{self, Ty, TyCtxt}; #[extension(pub trait TraitEngineExt<'tcx, E>)] -impl< - 'tcx, +impl<'tcx, E> dyn TraitEngine<'tcx, E> +where E: FromSolverError<'tcx, NextSolverError<'tcx>> + FromSolverError<'tcx, OldSolverError<'tcx>>, -> dyn TraitEngine<'tcx, E> { fn new(infcx: &InferCtxt<'tcx>) -> Box { if infcx.next_trait_solver() { @@ -73,7 +71,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx, ScrubbedTraitError<'tcx>> { impl<'a, 'tcx, E> ObligationCtxt<'a, 'tcx, E> where - E: FulfillmentErrorLike<'tcx>, + E: 'tcx, { pub fn register_obligation(&self, obligation: PredicateObligation<'tcx>) { self.engine.borrow_mut().register_predicate_obligation(self.infcx, obligation); @@ -231,7 +229,20 @@ where ) -> Vec> { self.infcx.resolve_regions(outlives_env) } +} +impl<'tcx> ObligationCtxt<'_, 'tcx, FulfillmentError<'tcx>> { + pub fn assumed_wf_types_and_report_errors( + &self, + param_env: ty::ParamEnv<'tcx>, + def_id: LocalDefId, + ) -> Result>, ErrorGuaranteed> { + self.assumed_wf_types(param_env, def_id) + .map_err(|errors| self.infcx.err_ctxt().report_fulfillment_errors(errors)) + } +} + +impl<'tcx> ObligationCtxt<'_, 'tcx, ScrubbedTraitError<'tcx>> { pub fn make_canonicalized_query_response( &self, inference_vars: CanonicalVarValues<'tcx>, @@ -249,17 +260,6 @@ where } } -impl<'tcx> ObligationCtxt<'_, 'tcx, FulfillmentError<'tcx>> { - pub fn assumed_wf_types_and_report_errors( - &self, - param_env: ty::ParamEnv<'tcx>, - def_id: LocalDefId, - ) -> Result>, ErrorGuaranteed> { - self.assumed_wf_types(param_env, def_id) - .map_err(|errors| self.infcx.err_ctxt().report_fulfillment_errors(errors)) - } -} - impl<'tcx, E> ObligationCtxt<'_, 'tcx, E> where E: FromSolverError<'tcx, NextSolverError<'tcx>>, diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 59802a260435..8ab9d5754c03 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -6,7 +6,7 @@ use rustc_data_structures::obligation_forest::ProcessResult; use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome}; use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor}; use rustc_infer::infer::DefineOpaqueTypes; -use rustc_infer::traits::{FromSolverError, FulfillmentErrorLike, ProjectionCacheKey}; +use rustc_infer::traits::{FromSolverError, ProjectionCacheKey}; use rustc_infer::traits::{PolyTraitObligation, SelectionError, TraitEngine}; use rustc_middle::bug; use rustc_middle::mir::interpret::ErrorHandled; @@ -50,7 +50,7 @@ impl<'tcx> ForestObligation for PendingPredicateObligation<'tcx> { /// along. Once all type inference constraints have been generated, the /// method `select_all_or_error` can be used to report any remaining /// ambiguous cases as errors. -pub struct FulfillmentContext<'tcx, E: FulfillmentErrorLike<'tcx>> { +pub struct FulfillmentContext<'tcx, E: 'tcx> { /// A list of all obligations that have been registered with this /// fulfillment context. predicates: ObligationForest>, @@ -78,7 +78,10 @@ pub struct PendingPredicateObligation<'tcx> { #[cfg(target_pointer_width = "64")] rustc_data_structures::static_assert_size!(PendingPredicateObligation<'_>, 72); -impl<'tcx, E: FromSolverError<'tcx, OldSolverError<'tcx>>> FulfillmentContext<'tcx, E> { +impl<'tcx, E> FulfillmentContext<'tcx, E> +where + E: FromSolverError<'tcx, OldSolverError<'tcx>>, +{ /// Creates a new fulfillment context. pub(super) fn new(infcx: &InferCtxt<'tcx>) -> FulfillmentContext<'tcx, E> { assert!( @@ -106,8 +109,11 @@ impl<'tcx, E: FromSolverError<'tcx, OldSolverError<'tcx>>> FulfillmentContext<'t // FIXME: if we kept the original cache key, we could mark projection // obligations as complete for the projection cache here. - let errors: Vec = - outcome.errors.into_iter().map(|err| E::from_solver_error(infcx, err)).collect(); + let errors: Vec = outcome + .errors + .into_iter() + .map(|err| E::from_solver_error(infcx, OldSolverError(err))) + .collect(); debug!( "select({} predicates remaining, {} errors) done", @@ -119,8 +125,9 @@ impl<'tcx, E: FromSolverError<'tcx, OldSolverError<'tcx>>> FulfillmentContext<'t } } -impl<'tcx, E: FromSolverError<'tcx, OldSolverError<'tcx>>> TraitEngine<'tcx, E> - for FulfillmentContext<'tcx, E> +impl<'tcx, E> TraitEngine<'tcx, E> for FulfillmentContext<'tcx, E> +where + E: FromSolverError<'tcx, OldSolverError<'tcx>>, { #[inline] fn register_predicate_obligation( @@ -144,7 +151,7 @@ impl<'tcx, E: FromSolverError<'tcx, OldSolverError<'tcx>>> TraitEngine<'tcx, E> self.predicates .to_errors(FulfillmentErrorCode::Ambiguity { overflow: None }) .into_iter() - .map(|err| E::from_solver_error(infcx, err)) + .map(|err| E::from_solver_error(infcx, OldSolverError(err))) .collect() } @@ -843,22 +850,25 @@ fn args_infer_vars<'a, 'tcx>( .filter_map(TyOrConstInferVar::maybe_from_generic_arg) } -pub type OldSolverError<'tcx> = Error, FulfillmentErrorCode<'tcx>>; +#[derive(Debug)] +pub struct OldSolverError<'tcx>( + Error, FulfillmentErrorCode<'tcx>>, +); impl<'tcx> FromSolverError<'tcx, OldSolverError<'tcx>> for FulfillmentError<'tcx> { fn from_solver_error(_infcx: &InferCtxt<'tcx>, error: OldSolverError<'tcx>) -> Self { - let mut iter = error.backtrace.into_iter(); + let mut iter = error.0.backtrace.into_iter(); let obligation = iter.next().unwrap().obligation; // The root obligation is the last item in the backtrace - if there's only // one item, then it's the same as the main obligation let root_obligation = iter.next_back().map_or_else(|| obligation.clone(), |e| e.obligation); - FulfillmentError::new(obligation, error.error, root_obligation) + FulfillmentError::new(obligation, error.0.error, root_obligation) } } impl<'tcx> FromSolverError<'tcx, OldSolverError<'tcx>> for ScrubbedTraitError<'tcx> { fn from_solver_error(_infcx: &InferCtxt<'tcx>, error: OldSolverError<'tcx>) -> Self { - match error.error { + match error.0.error { FulfillmentErrorCode::Select(_) | FulfillmentErrorCode::Project(_) | FulfillmentErrorCode::Subtype(_, _) diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 9aaa8adbd671..d918945dbed9 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -71,37 +71,6 @@ pub use self::util::{with_replaced_escaping_bound_vars, BoundVarReplacer, Placeh pub use rustc_infer::traits::*; -/// A trait error with most of its information removed. This is the error -/// returned by an [`ObligationCtxt`] by default, and suitable if you just -/// want to see if a predicate holds, and don't particularly care about the -/// error itself (except for if it's an ambiguity or true error). -/// -/// use [`ObligationCtxt::new_with_diagnostics`] to get a [`FulfillmentError`]. -#[derive(Clone, Debug)] -pub enum ScrubbedTraitError<'tcx> { - /// A real error. This goal definitely does not hold. - TrueError, - /// An ambiguity. This goal may hold if further inference is done. - Ambiguity, - /// An old-solver-style cycle error, which will fatal. - Cycle(Vec>), -} - -impl<'tcx> ScrubbedTraitError<'tcx> { - fn is_true_error(&self) -> bool { - match self { - ScrubbedTraitError::TrueError => true, - ScrubbedTraitError::Ambiguity | ScrubbedTraitError::Cycle(_) => false, - } - } -} - -impl<'tcx> FulfillmentErrorLike<'tcx> for ScrubbedTraitError<'tcx> { - fn is_true_error(&self) -> bool { - self.is_true_error() - } -} - pub struct FulfillmentError<'tcx> { pub obligation: PredicateObligation<'tcx>, pub code: FulfillmentErrorCode<'tcx>, @@ -133,12 +102,6 @@ impl<'tcx> FulfillmentError<'tcx> { } } -impl<'tcx> FulfillmentErrorLike<'tcx> for FulfillmentError<'tcx> { - fn is_true_error(&self) -> bool { - self.is_true_error() - } -} - impl<'tcx> Debug for FulfillmentError<'tcx> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "FulfillmentError({:?},{:?})", self.obligation, self.code) diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index 4e5ca2ee92e1..db30521d776a 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -46,14 +46,15 @@ impl<'tcx> At<'_, 'tcx> { /// existing fulfillment context in the old solver. Once we also eagerly prove goals with /// the old solver or have removed the old solver, remove `traits::fully_normalize` and /// rename this function to `At::fully_normalize`. - fn deeply_normalize< - T: TypeFoldable>, - E: FromSolverError<'tcx, NextSolverError<'tcx>>, - >( + fn deeply_normalize( self, value: T, fulfill_cx: &mut dyn TraitEngine<'tcx, E>, - ) -> Result> { + ) -> Result> + where + T: TypeFoldable>, + E: FromSolverError<'tcx, NextSolverError<'tcx>>, + { if self.infcx.next_trait_solver() { crate::solve::deeply_normalize(self, value) } else { diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs index 54fa07496181..b38841db9233 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs @@ -1,8 +1,6 @@ -use crate::solve; use crate::traits::query::NoSolution; use crate::traits::wf; use crate::traits::ObligationCtxt; -use crate::traits::ScrubbedTraitError; use rustc_infer::infer::canonical::Canonical; use rustc_infer::infer::outlives::components::{push_outlives_components, Component}; @@ -263,11 +261,9 @@ pub fn compute_implied_outlives_bounds_compat_inner<'tcx>( let mut ty_a = ocx.infcx.resolve_vars_if_possible(ty_a); // Need to manually normalize in the new solver as `wf::obligations` does not. if ocx.infcx.next_trait_solver() { - ty_a = solve::deeply_normalize( - ocx.infcx.at(&ObligationCause::dummy(), param_env), - ty_a, - ) - .map_err(|_errs: Vec>| NoSolution)?; + ty_a = ocx + .deeply_normalize(&ObligationCause::dummy(), param_env, ty_a) + .map_err(|_| NoSolution)?; } let mut components = smallvec![]; push_outlives_components(tcx, ty_a, &mut components); diff --git a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs index a160fc033a2c..9d657ade86bf 100644 --- a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs @@ -1,5 +1,5 @@ use rustc_infer::infer::at::At; -use rustc_infer::traits::{FulfillmentErrorLike, TraitEngine}; +use rustc_infer::traits::TraitEngine; use rustc_macros::extension; use rustc_middle::ty::{self, Ty}; @@ -7,7 +7,7 @@ use crate::traits::{NormalizeExt, Obligation}; #[extension(pub trait StructurallyNormalizeExt<'tcx>)] impl<'tcx> At<'_, 'tcx> { - fn structurally_normalize>( + fn structurally_normalize( &self, ty: Ty<'tcx>, fulfill_cx: &mut dyn TraitEngine<'tcx, E>, From 5875f3fff39055f7e99b891bd18576f4edee4c92 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 3 Jun 2024 15:59:31 +1000 Subject: [PATCH 193/211] Explain why `tests/pretty/` is unformatted. --- rustfmt.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rustfmt.toml b/rustfmt.toml index 998bcb983540..7cc029d2776d 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -15,7 +15,7 @@ ignore = [ "/tests/crashes/", # Many of these tests contain syntax errors. "/tests/debuginfo/", # These tests are somewhat sensitive to source code layout. "/tests/incremental/", # These tests are somewhat sensitive to source code layout. - "/tests/pretty/", + "/tests/pretty/", # These tests are very sensitive to source code layout. "/tests/run-make/translation/test.rs", # This test contains syntax errors. "/tests/run-make-fulldeps/", "/tests/run-pass-valgrind/", From d161d06241af26d13ee22bddbfbd4e0e9c562757 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 3 Jun 2024 16:03:45 +1000 Subject: [PATCH 194/211] rustfmt `tests/run-make-fulldeps/`. Note: I inserted blank lines between the items in `pretty-expanded/input.rs` because it looked better that way. --- rustfmt.toml | 1 - .../hotplug_codegen_backend/the_backend.rs | 9 ++++-- .../pretty-expanded/input.rs | 29 +++++++++++++++---- 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/rustfmt.toml b/rustfmt.toml index 7cc029d2776d..91abd35d7483 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -17,7 +17,6 @@ ignore = [ "/tests/incremental/", # These tests are somewhat sensitive to source code layout. "/tests/pretty/", # These tests are very sensitive to source code layout. "/tests/run-make/translation/test.rs", # This test contains syntax errors. - "/tests/run-make-fulldeps/", "/tests/run-pass-valgrind/", "/tests/rustdoc/", "/tests/rustdoc-gui/", diff --git a/tests/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs b/tests/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs index 28a1e27ccccc..07466440aabf 100644 --- a/tests/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs +++ b/tests/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs @@ -27,7 +27,9 @@ use std::any::Any; struct TheBackend; impl CodegenBackend for TheBackend { - fn locale_resource(&self) -> &'static str { "" } + fn locale_resource(&self) -> &'static str { + "" + } fn codegen_crate<'a, 'tcx>( &self, @@ -62,7 +64,10 @@ impl CodegenBackend for TheBackend { codegen_results: CodegenResults, outputs: &OutputFilenames, ) -> Result<(), ErrorGuaranteed> { - use rustc_session::{config::{CrateType, OutFileName}, output::out_filename}; + use rustc_session::{ + config::{CrateType, OutFileName}, + output::out_filename, + }; use std::io::Write; let crate_name = codegen_results.crate_info.local_crate_name; for &crate_type in sess.opts.crate_types.iter() { diff --git a/tests/run-make-fulldeps/pretty-expanded/input.rs b/tests/run-make-fulldeps/pretty-expanded/input.rs index 02b235068a1d..64ed97572ee9 100644 --- a/tests/run-make-fulldeps/pretty-expanded/input.rs +++ b/tests/run-make-fulldeps/pretty-expanded/input.rs @@ -1,8 +1,25 @@ // #13544 -#[derive(Debug)] pub struct A; -#[derive(Debug)] pub struct B(isize); -#[derive(Debug)] pub struct C { x: isize } -#[derive(Debug)] pub enum D {} -#[derive(Debug)] pub enum E { y } -#[derive(Debug)] pub enum F { z(isize) } +#[derive(Debug)] +pub struct A; + +#[derive(Debug)] +pub struct B(isize); + +#[derive(Debug)] +pub struct C { + x: isize, +} + +#[derive(Debug)] +pub enum D {} + +#[derive(Debug)] +pub enum E { + y, +} + +#[derive(Debug)] +pub enum F { + z(isize), +} From a78e1202dd4096e95f118fae833949d0b028c753 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 3 Jun 2024 16:06:52 +1000 Subject: [PATCH 195/211] rustfmt `tests/run-pass-valgrind/`. --- rustfmt.toml | 1 - tests/run-pass-valgrind/cast-enum-with-dtor.rs | 6 +++--- .../run-pass-valgrind/cleanup-auto-borrow-obj.rs | 9 ++++++--- tests/run-pass-valgrind/coerce-match-calls.rs | 10 ++++++++-- tests/run-pass-valgrind/coerce-match.rs | 15 ++++++++++++--- tests/run-pass-valgrind/down-with-thread-dtors.rs | 8 ++++++-- tests/run-pass-valgrind/dst-dtor-1.rs | 10 +++++++--- tests/run-pass-valgrind/dst-dtor-2.rs | 6 ++++-- tests/run-pass-valgrind/dst-dtor-3.rs | 8 ++++++-- tests/run-pass-valgrind/dst-dtor-4.rs | 4 +++- .../by-value-trait-objects-rust-call.rs | 1 - .../by-value-trait-objects-rust-call2.rs | 5 ++--- .../unsized-locals/by-value-trait-objects.rs | 1 - 13 files changed, 57 insertions(+), 27 deletions(-) diff --git a/rustfmt.toml b/rustfmt.toml index 91abd35d7483..0e788e92455f 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -17,7 +17,6 @@ ignore = [ "/tests/incremental/", # These tests are somewhat sensitive to source code layout. "/tests/pretty/", # These tests are very sensitive to source code layout. "/tests/run-make/translation/test.rs", # This test contains syntax errors. - "/tests/run-pass-valgrind/", "/tests/rustdoc/", "/tests/rustdoc-gui/", "/tests/rustdoc-js/", diff --git a/tests/run-pass-valgrind/cast-enum-with-dtor.rs b/tests/run-pass-valgrind/cast-enum-with-dtor.rs index f7ef92df8fbe..a57dc3734789 100644 --- a/tests/run-pass-valgrind/cast-enum-with-dtor.rs +++ b/tests/run-pass-valgrind/cast-enum-with-dtor.rs @@ -2,14 +2,14 @@ // check dtor calling order when casting enums. +use std::mem; use std::sync::atomic; use std::sync::atomic::Ordering; -use std::mem; enum E { A = 0, B = 1, - C = 2 + C = 2, } static FLAG: atomic::AtomicUsize = atomic::AtomicUsize::new(0); @@ -19,7 +19,7 @@ impl Drop for E { // avoid dtor loop unsafe { mem::forget(mem::replace(self, E::B)) }; - FLAG.store(FLAG.load(Ordering::SeqCst)+1, Ordering::SeqCst); + FLAG.store(FLAG.load(Ordering::SeqCst) + 1, Ordering::SeqCst); } } diff --git a/tests/run-pass-valgrind/cleanup-auto-borrow-obj.rs b/tests/run-pass-valgrind/cleanup-auto-borrow-obj.rs index dfc094abeb9b..e4ce80b33059 100644 --- a/tests/run-pass-valgrind/cleanup-auto-borrow-obj.rs +++ b/tests/run-pass-valgrind/cleanup-auto-borrow-obj.rs @@ -7,12 +7,15 @@ static mut DROP_RAN: bool = false; struct Foo; impl Drop for Foo { fn drop(&mut self) { - unsafe { DROP_RAN = true; } + unsafe { + DROP_RAN = true; + } } } - -trait Trait { fn dummy(&self) { } } +trait Trait { + fn dummy(&self) {} +} impl Trait for Foo {} pub fn main() { diff --git a/tests/run-pass-valgrind/coerce-match-calls.rs b/tests/run-pass-valgrind/coerce-match-calls.rs index f6c7151ff103..8c7375610dd7 100644 --- a/tests/run-pass-valgrind/coerce-match-calls.rs +++ b/tests/run-pass-valgrind/coerce-match-calls.rs @@ -7,9 +7,15 @@ use std::boxed::Box; pub fn main() { let _: Box<[isize]> = if true { Box::new([1, 2, 3]) } else { Box::new([1]) }; - let _: Box<[isize]> = match true { true => Box::new([1, 2, 3]), false => Box::new([1]) }; + let _: Box<[isize]> = match true { + true => Box::new([1, 2, 3]), + false => Box::new([1]), + }; // Check we don't get over-keen at propagating coercions in the case of casts. let x = if true { 42 } else { 42u8 } as u16; - let x = match true { true => 42, false => 42u8 } as u16; + let x = match true { + true => 42, + false => 42u8, + } as u16; } diff --git a/tests/run-pass-valgrind/coerce-match.rs b/tests/run-pass-valgrind/coerce-match.rs index 3f33264c5a80..95f16a8cc896 100644 --- a/tests/run-pass-valgrind/coerce-match.rs +++ b/tests/run-pass-valgrind/coerce-match.rs @@ -12,11 +12,20 @@ pub fn main() { }; let _: Box<[isize]> = match true { - true => { let b: Box<_> = Box::new([1, 2, 3]); b } - false => { let b: Box<_> = Box::new([1]); b } + true => { + let b: Box<_> = Box::new([1, 2, 3]); + b + } + false => { + let b: Box<_> = Box::new([1]); + b + } }; // Check we don't get over-keen at propagating coercions in the case of casts. let x = if true { 42 } else { 42u8 } as u16; - let x = match true { true => 42, false => 42u8 } as u16; + let x = match true { + true => 42, + false => 42u8, + } as u16; } diff --git a/tests/run-pass-valgrind/down-with-thread-dtors.rs b/tests/run-pass-valgrind/down-with-thread-dtors.rs index 15aeac98c667..0d3745bba5ba 100644 --- a/tests/run-pass-valgrind/down-with-thread-dtors.rs +++ b/tests/run-pass-valgrind/down-with-thread-dtors.rs @@ -27,13 +27,17 @@ impl Drop for Bar { impl Drop for Baz { fn drop(&mut self) { - unsafe { HIT = true; } + unsafe { + HIT = true; + } } } fn main() { std::thread::spawn(|| { FOO.with(|_| {}); - }).join().unwrap(); + }) + .join() + .unwrap(); assert!(unsafe { HIT }); } diff --git a/tests/run-pass-valgrind/dst-dtor-1.rs b/tests/run-pass-valgrind/dst-dtor-1.rs index 5b8433f61456..47065151a037 100644 --- a/tests/run-pass-valgrind/dst-dtor-1.rs +++ b/tests/run-pass-valgrind/dst-dtor-1.rs @@ -3,15 +3,19 @@ static mut DROP_RAN: bool = false; struct Foo; impl Drop for Foo { fn drop(&mut self) { - unsafe { DROP_RAN = true; } + unsafe { + DROP_RAN = true; + } } } -trait Trait { fn dummy(&self) { } } +trait Trait { + fn dummy(&self) {} +} impl Trait for Foo {} struct Fat { - f: T + f: T, } pub fn main() { diff --git a/tests/run-pass-valgrind/dst-dtor-2.rs b/tests/run-pass-valgrind/dst-dtor-2.rs index 991fe00950bb..d8abebfb4473 100644 --- a/tests/run-pass-valgrind/dst-dtor-2.rs +++ b/tests/run-pass-valgrind/dst-dtor-2.rs @@ -3,12 +3,14 @@ static mut DROP_RAN: isize = 0; struct Foo; impl Drop for Foo { fn drop(&mut self) { - unsafe { DROP_RAN += 1; } + unsafe { + DROP_RAN += 1; + } } } struct Fat { - f: T + f: T, } pub fn main() { diff --git a/tests/run-pass-valgrind/dst-dtor-3.rs b/tests/run-pass-valgrind/dst-dtor-3.rs index f0c2dda5ab05..09adaca21c71 100644 --- a/tests/run-pass-valgrind/dst-dtor-3.rs +++ b/tests/run-pass-valgrind/dst-dtor-3.rs @@ -5,11 +5,15 @@ static mut DROP_RAN: bool = false; struct Foo; impl Drop for Foo { fn drop(&mut self) { - unsafe { DROP_RAN = true; } + unsafe { + DROP_RAN = true; + } } } -trait Trait { fn dummy(&self) { } } +trait Trait { + fn dummy(&self) {} +} impl Trait for Foo {} pub fn main() { diff --git a/tests/run-pass-valgrind/dst-dtor-4.rs b/tests/run-pass-valgrind/dst-dtor-4.rs index ad6d46f7c088..a66ac8e3cfca 100644 --- a/tests/run-pass-valgrind/dst-dtor-4.rs +++ b/tests/run-pass-valgrind/dst-dtor-4.rs @@ -5,7 +5,9 @@ static mut DROP_RAN: isize = 0; struct Foo; impl Drop for Foo { fn drop(&mut self) { - unsafe { DROP_RAN += 1; } + unsafe { + DROP_RAN += 1; + } } } diff --git a/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call.rs b/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call.rs index ece4dea9aaf6..5d3f558a63a9 100644 --- a/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call.rs +++ b/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call.rs @@ -43,7 +43,6 @@ impl FnOnce<()> for D { } } - fn main() { let x = *(Box::new(A) as Box>); assert_eq!(x.call_once(()), format!("hello")); diff --git a/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call2.rs b/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call2.rs index 94df2b0b83f0..9b6648f2e27a 100644 --- a/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call2.rs +++ b/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call2.rs @@ -51,7 +51,6 @@ impl FnOnce<(String, Box)> for D { } } - fn main() { let (s1, s2) = (format!("s1"), format!("s2").into_boxed_str()); let x = *(Box::new(A) as Box), Output = String>>); @@ -61,10 +60,10 @@ fn main() { assert_eq!(x.call_once((s1, s2)), format!("42")); let (s1, s2) = (format!("s1"), format!("s2").into_boxed_str()); let x = *(Box::new(C(format!("jumping fox"))) - as Box), Output = String>>); + as Box), Output = String>>); assert_eq!(x.call_once((s1, s2)), format!("jumping fox")); let (s1, s2) = (format!("s1"), format!("s2").into_boxed_str()); let x = *(Box::new(D(Box::new(format!("lazy dog")))) - as Box), Output = String>>); + as Box), Output = String>>); assert_eq!(x.call_once((s1, s2)), format!("lazy dog")); } diff --git a/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects.rs b/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects.rs index 3d67101e734c..3f6b6d262b5d 100644 --- a/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects.rs +++ b/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects.rs @@ -36,7 +36,6 @@ impl Foo for D { } } - fn main() { let x = *(Box::new(A) as Box); assert_eq!(x.foo(), format!("hello")); From e372bf8e337b3b30431adff7279711debf07ca7d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 3 Jun 2024 17:30:09 +1000 Subject: [PATCH 196/211] Explain why `tests/rustdoc/` is unformatted. --- rustfmt.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rustfmt.toml b/rustfmt.toml index 0e788e92455f..dffb7bb67f3c 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -17,7 +17,7 @@ ignore = [ "/tests/incremental/", # These tests are somewhat sensitive to source code layout. "/tests/pretty/", # These tests are very sensitive to source code layout. "/tests/run-make/translation/test.rs", # This test contains syntax errors. - "/tests/rustdoc/", + "/tests/rustdoc/", # Some have syntax errors, some are whitespace-sensitive. "/tests/rustdoc-gui/", "/tests/rustdoc-js/", "/tests/rustdoc-json/", From 273b990554fa2a7efdd975ccf2ef490c6c90cbaf Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 29 May 2024 22:23:49 -0400 Subject: [PATCH 197/211] Align Term methods with GenericArg methods --- .../rustc_codegen_ssa/src/debuginfo/type_names.rs | 2 +- .../src/check/compare_impl_item.rs | 2 +- .../src/check/compare_impl_item/refine.rs | 2 +- compiler/rustc_hir_analysis/src/check/mod.rs | 4 +++- compiler/rustc_hir_typeck/src/closure.rs | 4 ++-- compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs | 2 +- .../rustc_infer/src/infer/error_reporting/mod.rs | 2 +- compiler/rustc_infer/src/infer/mod.rs | 4 ++-- .../rustc_lint/src/opaque_hidden_inferred_bound.rs | 2 +- compiler/rustc_middle/src/ty/mod.rs | 12 ++++++++++-- compiler/rustc_middle/src/ty/print/pretty.rs | 6 +++--- .../src/solve/assembly/structural_traits.rs | 2 +- .../src/solve/normalizes_to/opaque_types.rs | 2 +- .../rustc_trait_selection/src/traits/auto_trait.rs | 2 +- .../src/traits/error_reporting/suggestions.rs | 8 ++++---- .../rustc_trait_selection/src/traits/normalize.rs | 4 ++-- .../src/traits/select/candidate_assembly.rs | 2 +- compiler/rustc_trait_selection/src/traits/wf.rs | 2 +- compiler/rustc_traits/src/normalize_projection_ty.rs | 2 +- .../methods/iter_on_single_or_empty_collections.rs | 2 +- .../src/needless_borrows_for_generic_args.rs | 4 ++-- .../clippy_lints/src/unit_return_expecting_ord.rs | 4 ++-- src/tools/clippy/clippy_utils/src/ty.rs | 6 +++--- 23 files changed, 46 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 07473ee476ba..2360cce55a99 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -263,7 +263,7 @@ fn push_debuginfo_type_name<'tcx>( let ExistentialProjection { def_id: item_def_id, term, .. } = tcx.instantiate_bound_regions_with_erased(bound); // FIXME(associated_const_equality): allow for consts here - (item_def_id, term.ty().unwrap()) + (item_def_id, term.expect_type()) }) .collect(); 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 f7bebc2697d7..74dcd672578e 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -2281,7 +2281,7 @@ fn try_report_async_mismatch<'tcx>( && let Some(proj) = proj.no_bound_vars() && infcx.can_eq( error.root_obligation.param_env, - proj.term.ty().unwrap(), + proj.term.expect_type(), impl_sig.output(), ) { diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs index ca08eeea2275..10b097a1060f 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs @@ -267,7 +267,7 @@ fn report_mismatched_rpitit_signature<'tcx>( .explicit_item_bounds(future_ty.def_id) .iter_instantiated_copied(tcx, future_ty.args) .find_map(|(clause, _)| match clause.kind().no_bound_vars()? { - ty::ClauseKind::Projection(proj) => proj.term.ty(), + ty::ClauseKind::Projection(proj) => proj.term.as_type(), _ => None, }) else { diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index da66e1f34fd9..4d1b96d9c1ba 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -441,7 +441,9 @@ fn fn_sig_suggestion<'tcx>( output = if let ty::Alias(_, alias_ty) = *output.kind() { tcx.explicit_item_super_predicates(alias_ty.def_id) .iter_instantiated_copied(tcx, alias_ty.args) - .find_map(|(bound, _)| bound.as_projection_clause()?.no_bound_vars()?.term.ty()) + .find_map(|(bound, _)| { + bound.as_projection_clause()?.no_bound_vars()?.term.as_type() + }) .unwrap_or_else(|| { span_bug!( ident.span, diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 14a6177141c9..ac7ed3e26f97 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -485,7 +485,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; // Since this is a return parameter type it is safe to unwrap. - let ret_param_ty = projection.skip_binder().term.ty().unwrap(); + let ret_param_ty = projection.skip_binder().term.expect_type(); let ret_param_ty = self.resolve_vars_if_possible(ret_param_ty); debug!(?ret_param_ty); @@ -956,7 +956,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let output_ty = self.resolve_vars_if_possible(predicate.term); debug!("deduce_future_output_from_projection: output_ty={:?}", output_ty); // This is a projection on a Fn trait so will always be a type. - Some(output_ty.ty().unwrap()) + Some(output_ty.expect_type()) } /// Converts the types that the user supplied, in case that doing diff --git a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs index 0dfc5408f306..28745af3a530 100644 --- a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs +++ b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs @@ -160,7 +160,7 @@ impl<'tcx> TypeckRootCtxt<'tcx> { { // If the projection predicate (Foo::Bar == X) has X as a non-TyVid, // we need to make it into one. - if let Some(vid) = predicate.term.ty().and_then(|ty| ty.ty_vid()) { + if let Some(vid) = predicate.term.as_type().and_then(|ty| ty.ty_vid()) { debug!("infer_var_info: {:?}.output = true", vid); infer_var_info.entry(vid).or_default().output = true; } diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 95fbc1e66cea..fe0a246abbc6 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -425,7 +425,7 @@ impl<'tcx> InferCtxt<'tcx> { ty::ClauseKind::Projection(projection_predicate) if projection_predicate.projection_term.def_id == item_def_id => { - projection_predicate.term.ty() + projection_predicate.term.as_type() } _ => None, }) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 72c4e1b511e6..f46c596425be 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -424,8 +424,8 @@ pub enum ValuePairs<'tcx> { impl<'tcx> ValuePairs<'tcx> { pub fn ty(&self) -> Option<(Ty<'tcx>, Ty<'tcx>)> { if let ValuePairs::Terms(ExpectedFound { expected, found }) = self - && let Some(expected) = expected.ty() - && let Some(found) = found.ty() + && let Some(expected) = expected.as_type() + && let Some(found) = found.as_type() { Some((expected, found)) } else { diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index eda40e4a011a..6098da990c04 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -83,7 +83,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { }; // Only check types, since those are the only things that may // have opaques in them anyways. - let Some(proj_term) = proj.term.ty() else { return }; + let Some(proj_term) = proj.term.as_type() else { return }; // HACK: `impl Trait` from an RPIT is "ok"... if let ty::Alias(ty::Opaque, opaque_ty) = *proj_term.kind() diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 2643ce976ded..3fdcb9669602 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -624,14 +624,22 @@ impl<'tcx> Term<'tcx> { } } - pub fn ty(&self) -> Option> { + pub fn as_type(&self) -> Option> { if let TermKind::Ty(ty) = self.unpack() { Some(ty) } else { None } } - pub fn ct(&self) -> Option> { + pub fn expect_type(&self) -> Ty<'tcx> { + self.as_type().expect("expected a type, but found a const") + } + + pub fn as_const(&self) -> Option> { if let TermKind::Const(c) = self.unpack() { Some(c) } else { None } } + pub fn expect_const(&self) -> Const<'tcx> { + self.as_const().expect("expected a const, but found a type") + } + pub fn into_arg(self) -> GenericArg<'tcx> { match self.unpack() { TermKind::Ty(ty) => ty.into(), diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 8fb4367d3b58..af7784d6b8ed 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1077,7 +1077,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { } p!(")"); - if let Some(ty) = return_ty.skip_binder().ty() { + if let Some(ty) = return_ty.skip_binder().as_type() { if !ty.is_unit() { p!(" -> ", print(return_ty)); } @@ -1144,7 +1144,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { for (assoc_item_def_id, term) in assoc_items { // Skip printing `<{coroutine@} as Coroutine<_>>::Return` from async blocks, // unless we can find out what coroutine return type it comes from. - let term = if let Some(ty) = term.skip_binder().ty() + let term = if let Some(ty) = term.skip_binder().as_type() && let ty::Alias(ty::Projection, proj) = ty.kind() && let Some(assoc) = tcx.opt_associated_item(proj.def_id) && assoc.trait_container(tcx) == tcx.lang_items().coroutine_trait() @@ -1322,7 +1322,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { p!(pretty_fn_sig( tys, false, - proj.skip_binder().term.ty().expect("Return type was a const") + proj.skip_binder().term.as_type().expect("Return type was a const") )); resugared = true; } diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index 48acf2a4e996..98f98d9992d3 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -726,7 +726,7 @@ impl<'tcx> TypeFolder> for ReplaceProjectionWith<'_, 'tcx> { ) .expect("expected to be able to unify goal projection with dyn's projection"), ); - proj.term.ty().unwrap() + proj.term.expect_type() } else { ty.super_fold_with(self) } diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs index 67ec2f3be481..82464470b2a2 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs @@ -17,7 +17,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { ) -> QueryResult<'tcx> { let tcx = self.interner(); let opaque_ty = goal.predicate.alias; - let expected = goal.predicate.term.ty().expect("no such thing as an opaque const"); + let expected = goal.predicate.term.as_type().expect("no such thing as an opaque const"); match (goal.param_env.reveal(), self.solver_mode()) { (Reveal::UserFacing, SolverMode::Normal) => { diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 1ea207cc375f..6623a86e69ff 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -553,7 +553,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { } fn is_self_referential_projection(&self, p: ty::PolyProjectionPredicate<'tcx>) -> bool { - if let Some(ty) = p.term().skip_binder().ty() { + if let Some(ty) = p.term().skip_binder().as_type() { matches!(ty.kind(), ty::Alias(ty::Projection, proj) if proj == &p.skip_binder().projection_term.expect_ty(self.tcx)) } else { false diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 3ee332951761..6a96a03e047f 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1112,7 +1112,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { { Some(( DefIdOrName::DefId(def_id), - pred.kind().rebind(proj.term.ty().unwrap()), + pred.kind().rebind(proj.term.expect_type()), pred.kind().rebind(args.as_slice()), )) } else { @@ -1129,7 +1129,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { { Some(( DefIdOrName::Name("trait object"), - pred.rebind(proj.term.ty().unwrap()), + pred.rebind(proj.term.expect_type()), pred.rebind(args.as_slice()), )) } else { @@ -1157,7 +1157,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { { Some(( name, - pred.kind().rebind(proj.term.ty().unwrap()), + pred.kind().rebind(proj.term.expect_type()), pred.kind().rebind(args.as_slice()), )) } else { @@ -3840,7 +3840,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { }) } else if let Some(where_pred) = where_pred.as_projection_clause() && let Some(failed_pred) = failed_pred.as_projection_clause() - && let Some(found) = failed_pred.skip_binder().term.ty() + && let Some(found) = failed_pred.skip_binder().term.as_type() { type_diffs = vec![Sorts(ty::error::ExpectedFound { expected: where_pred diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index db30521d776a..e7ab0b7791c4 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -259,7 +259,7 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx obligations.len = ?self.obligations.len(), "AssocTypeNormalizer: normalized type" ); - normalized_ty.ty().unwrap() + normalized_ty.expect_type() } ty::Projection => { @@ -289,7 +289,7 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx ) .ok() .flatten() - .map(|term| term.ty().unwrap()) + .map(|term| term.expect_type()) .map(|normalized_ty| { PlaceholderReplacer::replace_placeholders( infcx, 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 d513a5d2996c..2b9c577e9894 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -946,7 +946,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // since we don't actually use them. &mut vec![], ) - .ty() + .as_type() .unwrap(); if let ty::Dynamic(data, ..) = ty.kind() { data.principal() } else { None } diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index f4189ff09020..066755f7b3e7 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -286,7 +286,7 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>( // implemented, but rather from a "second order" obligation, where an associated // type has a projection coming from another associated type. // See `tests/ui/traits/assoc-type-in-superbad.rs` for an example. - if let Some(term_ty) = proj.term.ty() + if let Some(term_ty) = proj.term.as_type() && let Some(impl_item_span) = ty_to_impl_span(term_ty) { cause.span = impl_item_span; diff --git a/compiler/rustc_traits/src/normalize_projection_ty.rs b/compiler/rustc_traits/src/normalize_projection_ty.rs index b0a93b62dbf3..0430e0bb70eb 100644 --- a/compiler/rustc_traits/src/normalize_projection_ty.rs +++ b/compiler/rustc_traits/src/normalize_projection_ty.rs @@ -58,7 +58,7 @@ fn normalize_canonicalized_projection_ty<'tcx>( // FIXME(associated_const_equality): All users of normalize_canonicalized_projection_ty // expected a type, but there is the possibility it could've been a const now. // Maybe change it to a Term later? - Ok(NormalizationResult { normalized_ty: answer.ty().unwrap() }) + Ok(NormalizationResult { normalized_ty: answer.expect_type() }) }, ) } diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs b/src/tools/clippy/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs index f4397212cf66..7f6b666e434e 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs @@ -42,7 +42,7 @@ fn is_arg_ty_unified_in_fn<'tcx>( cx.tcx.predicates_of(fn_id).predicates.iter().any(|(clause, _)| { clause .as_projection_clause() - .and_then(|p| p.map_bound(|p| p.term.ty()).transpose()) + .and_then(|p| p.map_bound(|p| p.term.as_type()).transpose()) .is_some_and(|ty| ty.skip_binder() == arg_ty_in_args) }) || fn_sig .inputs() diff --git a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs index 5b5e1c234245..4f99eaa40c29 100644 --- a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs +++ b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs @@ -311,7 +311,7 @@ fn is_mixed_projection_predicate<'tcx>( ) -> bool { let generics = cx.tcx.generics_of(callee_def_id); // The predicate requires the projected type to equal a type parameter from the parent context. - if let Some(term_ty) = projection_predicate.term.ty() + if let Some(term_ty) = projection_predicate.term.as_type() && let ty::Param(term_param_ty) = term_ty.kind() && (term_param_ty.index as usize) < generics.parent_count { @@ -370,7 +370,7 @@ fn replace_types<'tcx>( if replaced.insert(param_ty.index) { for projection_predicate in projection_predicates { if projection_predicate.projection_term.self_ty() == param_ty.to_ty(cx.tcx) - && let Some(term_ty) = projection_predicate.term.ty() + && let Some(term_ty) = projection_predicate.term.as_type() && let ty::Param(term_param_ty) = term_ty.kind() { let projection = projection_predicate diff --git a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs index f0d1458a59b2..a8cc2f979633 100644 --- a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs +++ b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs @@ -100,12 +100,12 @@ fn get_args_to_check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Ve { if ord_preds .iter() - .any(|ord| Some(ord.self_ty()) == return_ty_pred.term.ty()) + .any(|ord| Some(ord.self_ty()) == return_ty_pred.term.as_type()) { args_to_check.push((i, "Ord".to_string())); } else if partial_ord_preds .iter() - .any(|pord| pord.self_ty() == return_ty_pred.term.ty().unwrap()) + .any(|pord| pord.self_ty() == return_ty_pred.term.expect_type()) { args_to_check.push((i, "PartialOrd".to_string())); } diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 3414b5ef680c..f0dac6f5d9c4 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -750,7 +750,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option None, @@ -798,7 +798,7 @@ fn sig_from_bounds<'tcx>( // Multiple different fn trait impls. Is this even allowed? return None; } - output = Some(pred.kind().rebind(p.term.ty().unwrap())); + output = Some(pred.kind().rebind(p.term.expect_type())); }, _ => (), } @@ -836,7 +836,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: AliasTy<'tcx>) -> Option // Multiple different fn trait impls. Is this even allowed? return None; } - output = pred.kind().rebind(p.term.ty()).transpose(); + output = pred.kind().rebind(p.term.as_type()).transpose(); }, _ => (), } From 98d65d62c511777d6372ae0115d40f82d0a42857 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 3 Jun 2024 17:34:39 +1000 Subject: [PATCH 198/211] Explain why `tests/rustdoc-gui/` is unformatted. --- rustfmt.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rustfmt.toml b/rustfmt.toml index dffb7bb67f3c..cc032bfe0237 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -18,7 +18,7 @@ ignore = [ "/tests/pretty/", # These tests are very sensitive to source code layout. "/tests/run-make/translation/test.rs", # This test contains syntax errors. "/tests/rustdoc/", # Some have syntax errors, some are whitespace-sensitive. - "/tests/rustdoc-gui/", + "/tests/rustdoc-gui/", # Some tests are sensitive to source code layout. "/tests/rustdoc-js/", "/tests/rustdoc-json/", "/tests/rustdoc-js-std/", From c6fb703c05a47a7f20c59c5315fe704c536084d0 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 3 Jun 2024 17:35:56 +1000 Subject: [PATCH 199/211] rustfmt `tests/rustdoc-js/`. --- rustfmt.toml | 1 - tests/rustdoc-js/assoc-type-backtrack.rs | 21 ++++--- tests/rustdoc-js/assoc-type-loop.rs | 9 +-- tests/rustdoc-js/auxiliary/interner.rs | 67 +++++++++-------------- tests/rustdoc-js/doc-alias.rs | 6 +- tests/rustdoc-js/enum-variant-not-type.rs | 10 +++- tests/rustdoc-js/foreign-type-path.rs | 3 +- tests/rustdoc-js/full-path-function.rs | 20 +++++-- tests/rustdoc-js/gat.rs | 16 ++++-- tests/rustdoc-js/generics-impl.rs | 7 ++- tests/rustdoc-js/generics-trait.rs | 16 ++++-- tests/rustdoc-js/generics.rs | 37 +++++++++---- tests/rustdoc-js/hof.rs | 8 +-- tests/rustdoc-js/macro-search.rs | 4 +- tests/rustdoc-js/never-search.rs | 28 ++++++++-- tests/rustdoc-js/path-maxeditdistance.rs | 2 +- tests/rustdoc-js/prototype.rs | 2 +- tests/rustdoc-js/reexport-dedup-macro.rs | 2 +- tests/rustdoc-js/reexport-dedup-method.rs | 4 +- tests/rustdoc-js/reexport-dedup.rs | 4 +- tests/rustdoc-js/reexport.rs | 2 +- tests/rustdoc-js/reference.rs | 16 ++++-- tests/rustdoc-js/slice-array.rs | 16 ++++-- tests/rustdoc-js/struct-like-variant.rs | 4 +- tests/rustdoc-js/summaries.rs | 1 - tests/rustdoc-js/tuple-unit.rs | 18 ++++-- tests/rustdoc-js/type-parameters.rs | 20 +++++-- tests/rustdoc-js/where-clause.rs | 29 ++++++++-- 28 files changed, 240 insertions(+), 133 deletions(-) diff --git a/rustfmt.toml b/rustfmt.toml index cc032bfe0237..79f197b27b17 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -19,7 +19,6 @@ ignore = [ "/tests/run-make/translation/test.rs", # This test contains syntax errors. "/tests/rustdoc/", # Some have syntax errors, some are whitespace-sensitive. "/tests/rustdoc-gui/", # Some tests are sensitive to source code layout. - "/tests/rustdoc-js/", "/tests/rustdoc-json/", "/tests/rustdoc-js-std/", "/tests/rustdoc-ui/", diff --git a/tests/rustdoc-js/assoc-type-backtrack.rs b/tests/rustdoc-js/assoc-type-backtrack.rs index c3cdd78c6e1c..2dfede9dc383 100644 --- a/tests/rustdoc-js/assoc-type-backtrack.rs +++ b/tests/rustdoc-js/assoc-type-backtrack.rs @@ -5,22 +5,27 @@ pub trait MyTrait2 { pub trait MyTrait { type Item; fn next(&mut self) -> Option; - fn fold(self, init: B, f: F) -> B where + fn fold(self, init: B, f: F) -> B + where Self: Sized, - F: MyTrait2<(B, Self::Item), Output=B>; + F: MyTrait2<(B, Self::Item), Output = B>; } pub struct Cloned(I); -impl<'a, T, I> MyTrait for Cloned where +impl<'a, T, I> MyTrait for Cloned +where T: 'a + Clone, - I: MyTrait + I: MyTrait, { type Item = T; - fn next(&mut self) -> Option { loop {} } - fn fold(self, init: B, f: F) -> B where + fn next(&mut self) -> Option { + loop {} + } + fn fold(self, init: B, f: F) -> B + where Self: Sized, - F: MyTrait2<(B, Self::Item), Output=B> + F: MyTrait2<(B, Self::Item), Output = B>, { loop {} } @@ -32,7 +37,7 @@ pub trait MyFuture { pub trait MyIntoFuture { type Output; - type Fut: MyFuture; + type Fut: MyFuture; fn into_future(self) -> Self::Fut; fn into_future_2(self, other: Self) -> Self::Fut; } diff --git a/tests/rustdoc-js/assoc-type-loop.rs b/tests/rustdoc-js/assoc-type-loop.rs index f123c83f50fd..09efe8c7be5c 100644 --- a/tests/rustdoc-js/assoc-type-loop.rs +++ b/tests/rustdoc-js/assoc-type-loop.rs @@ -1,9 +1,9 @@ -#![crate_name="foo"] +#![crate_name = "foo"] // reduced from sqlx 0.7.3 use std::future::Future; -use std::pin::Pin; use std::ops::{Deref, DerefMut}; +use std::pin::Pin; pub enum Error {} pub trait Acquire<'c> { type Database: Database; @@ -16,7 +16,7 @@ pub trait Connection { type Database: Database; type Options: ConnectionOptions; fn begin( - &mut self + &mut self, ) -> Pin, Error>> + Send + '_>> where Self: Sized; @@ -28,7 +28,8 @@ pub struct Transaction<'c, DB: Database> { _db: &'c DB, } impl<'t, 'c, DB: Database> Acquire<'t> for &'t mut Transaction<'c, DB> - where ::Connection: Send +where + ::Connection: Send, { type Database = DB; type Connection = &'t mut ::Connection; diff --git a/tests/rustdoc-js/auxiliary/interner.rs b/tests/rustdoc-js/auxiliary/interner.rs index c95029be9f0f..e4e4ff6276d6 100644 --- a/tests/rustdoc-js/auxiliary/interner.rs +++ b/tests/rustdoc-js/auxiliary/interner.rs @@ -77,17 +77,14 @@ pub trait Interner: Sized { type ClosureKind: Copy + Debug + Hash + Eq; // Required method - fn mk_canonical_var_infos( - self, - infos: &[CanonicalVarInfo] - ) -> Self::CanonicalVars; + fn mk_canonical_var_infos(self, infos: &[CanonicalVarInfo]) -> Self::CanonicalVars; } pub trait DebugWithInfcx: Debug { // Required method fn fmt>( this: WithInfcx<'_, Infcx, &Self>, - f: &mut Formatter<'_> + f: &mut Formatter<'_>, ) -> std::fmt::Result; } @@ -130,11 +127,7 @@ pub struct TypeFlags; pub trait Ty> { // Required method - fn new_anon_bound( - interner: I, - debruijn: DebruijnIndex, - var: BoundVar - ) -> Self; + fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar) -> Self; } pub trait PlaceholderLike { @@ -152,12 +145,7 @@ pub struct BoundVar; pub struct ConstKind(std::marker::PhantomData); pub trait Const> { // Required method - fn new_anon_bound( - interner: I, - debruijn: DebruijnIndex, - var: BoundVar, - ty: I::Ty - ) -> Self; + fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar, ty: I::Ty) -> Self; } pub trait ConstTy { @@ -170,25 +158,28 @@ pub struct DebruijnIndex; pub struct RegionKind(std::marker::PhantomData); pub trait Region> { // Required method - fn new_anon_bound( - interner: I, - debruijn: DebruijnIndex, - var: BoundVar - ) -> Self; + fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar) -> Self; } pub trait TypeVisitor: Sized { type Result: VisitorResult = (); // Provided methods - fn visit_binder>( - &mut self, - t: &I::Binder - ) -> Self::Result { unimplemented!() } - fn visit_ty(&mut self, t: I::Ty) -> Self::Result { unimplemented!() } - fn visit_region(&mut self, _r: I::Region) -> Self::Result { unimplemented!() } - fn visit_const(&mut self, c: I::Const) -> Self::Result { unimplemented!() } - fn visit_predicate(&mut self, p: I::Predicate) -> Self::Result { unimplemented!() } + fn visit_binder>(&mut self, t: &I::Binder) -> Self::Result { + unimplemented!() + } + fn visit_ty(&mut self, t: I::Ty) -> Self::Result { + unimplemented!() + } + fn visit_region(&mut self, _r: I::Region) -> Self::Result { + unimplemented!() + } + fn visit_const(&mut self, c: I::Const) -> Self::Result { + unimplemented!() + } + fn visit_predicate(&mut self, p: I::Predicate) -> Self::Result { + unimplemented!() + } } pub trait VisitorResult { @@ -206,7 +197,9 @@ impl VisitorResult for () { fn output() -> Self {} fn from_residual(_: Self::Residual) -> Self {} fn from_branch(_: ControlFlow) -> Self {} - fn branch(self) -> ControlFlow { ControlFlow::Continue(()) } + fn branch(self) -> ControlFlow { + ControlFlow::Continue(()) + } } pub struct WithInfcx<'a, Infcx: InferCtxtLike, T> { @@ -221,24 +214,18 @@ pub trait InferCtxtLike { fn interner(&self) -> Self::Interner; fn universe_of_ty(&self, ty: TyVid) -> Option; fn root_ty_var(&self, vid: TyVid) -> TyVid; - fn probe_ty_var( - &self, - vid: TyVid - ) -> Option<::Ty>; + fn probe_ty_var(&self, vid: TyVid) -> Option<::Ty>; fn universe_of_lt( &self, - lt: ::InferRegion + lt: ::InferRegion, ) -> Option; fn opportunistic_resolve_lt_var( &self, - vid: ::InferRegion + vid: ::InferRegion, ) -> Option<::Region>; fn universe_of_ct(&self, ct: ConstVid) -> Option; fn root_ct_var(&self, vid: ConstVid) -> ConstVid; - fn probe_ct_var( - &self, - vid: ConstVid - ) -> Option<::Const>; + fn probe_ct_var(&self, vid: ConstVid) -> Option<::Const>; } pub struct TyVid; diff --git a/tests/rustdoc-js/doc-alias.rs b/tests/rustdoc-js/doc-alias.rs index 750b7b757bc3..453b55c956c7 100644 --- a/tests/rustdoc-js/doc-alias.rs +++ b/tests/rustdoc-js/doc-alias.rs @@ -16,7 +16,9 @@ impl Trait for Struct { const AssociatedConst: i32 = 12; #[doc(alias = "ImplTraitFunction")] - fn function() -> Self::Target { 0 } + fn function() -> Self::Target { + 0 + } } #[doc(alias = "EnumItem")] @@ -71,5 +73,5 @@ impl Union { #[doc(alias = "MacroItem")] #[macro_export] macro_rules! Macro { - () => {} + () => {}; } diff --git a/tests/rustdoc-js/enum-variant-not-type.rs b/tests/rustdoc-js/enum-variant-not-type.rs index 421bddf62894..f0facd63cfcd 100644 --- a/tests/rustdoc-js/enum-variant-not-type.rs +++ b/tests/rustdoc-js/enum-variant-not-type.rs @@ -5,10 +5,14 @@ pub trait MyTrait { fn not_appearing(&self) -> Option<&Self::T>; } -pub fn my_fn(t: X) -> X { t } +pub fn my_fn(t: X) -> X { + t +} pub trait AutoCorrectConfounder { type InsertUnnecessarilyLongTypeNameHere; - fn assoc_type_acts_like_generic(&self, x: &Self::InsertUnnecessarilyLongTypeNameHere) - -> Option<&Self::InsertUnnecessarilyLongTypeNameHere>; + fn assoc_type_acts_like_generic( + &self, + x: &Self::InsertUnnecessarilyLongTypeNameHere, + ) -> Option<&Self::InsertUnnecessarilyLongTypeNameHere>; } diff --git a/tests/rustdoc-js/foreign-type-path.rs b/tests/rustdoc-js/foreign-type-path.rs index 83400104ea77..f9228c7b9ac3 100644 --- a/tests/rustdoc-js/foreign-type-path.rs +++ b/tests/rustdoc-js/foreign-type-path.rs @@ -2,12 +2,11 @@ pub mod aaaaaaa { - extern { + extern "C" { pub type MyForeignType; } impl MyForeignType { pub fn my_method() {} } - } diff --git a/tests/rustdoc-js/full-path-function.rs b/tests/rustdoc-js/full-path-function.rs index 8dcc3f2b69d8..a1a9220654d0 100644 --- a/tests/rustdoc-js/full-path-function.rs +++ b/tests/rustdoc-js/full-path-function.rs @@ -2,16 +2,26 @@ pub mod sac { pub struct Sac; impl Sac { - pub fn len(&self) -> usize { 0 } + pub fn len(&self) -> usize { + 0 + } } } pub mod b { pub struct Sac; impl Sac { - pub fn len(&self) -> usize { 0 } - pub fn bar(&self, w: u32) -> usize { 0 } - pub fn bar2(&self, w: u32) -> u32 { 0 } - pub fn string(w: String) -> u32 { 0 } + pub fn len(&self) -> usize { + 0 + } + pub fn bar(&self, w: u32) -> usize { + 0 + } + pub fn bar2(&self, w: u32) -> u32 { + 0 + } + pub fn string(w: String) -> u32 { + 0 + } } } diff --git a/tests/rustdoc-js/gat.rs b/tests/rustdoc-js/gat.rs index b4861cc683ff..7a2b5551114c 100644 --- a/tests/rustdoc-js/gat.rs +++ b/tests/rustdoc-js/gat.rs @@ -2,7 +2,15 @@ pub trait Foo { type Assoc; } -pub fn sample = u8>>(_: X) -> u32 { loop {} } -pub fn synergy(_: impl Foo = u8>) -> ! { loop {} } -pub fn consider(_: impl Foo = u32>) -> bool { loop {} } -pub fn integrate(_: impl Foo = T>) -> T { loop {} } +pub fn sample = u8>>(_: X) -> u32 { + loop {} +} +pub fn synergy(_: impl Foo = u8>) -> ! { + loop {} +} +pub fn consider(_: impl Foo = u32>) -> bool { + loop {} +} +pub fn integrate(_: impl Foo = T>) -> T { + loop {} +} diff --git a/tests/rustdoc-js/generics-impl.rs b/tests/rustdoc-js/generics-impl.rs index 696218021d5a..27d44fdd7e92 100644 --- a/tests/rustdoc-js/generics-impl.rs +++ b/tests/rustdoc-js/generics-impl.rs @@ -1,4 +1,4 @@ -use std::io::{Result as IoResult, Read}; +use std::io::{Read, Result as IoResult}; pub struct Aaaaaaa; @@ -29,7 +29,10 @@ impl Ddddddd { pub fn ggggggg(self) -> u64 { 1 } - pub fn hhhhhhh() -> Self where T: Default { + pub fn hhhhhhh() -> Self + where + T: Default, + { Ddddddd(T::default()) } } diff --git a/tests/rustdoc-js/generics-trait.rs b/tests/rustdoc-js/generics-trait.rs index 20db117ccd5c..58c86361e419 100644 --- a/tests/rustdoc-js/generics-trait.rs +++ b/tests/rustdoc-js/generics-trait.rs @@ -1,8 +1,16 @@ pub trait SomeTrait {} pub trait OtherThingxxxxxxxx {} -pub fn alef() -> Result { loop {} } -pub fn bet() -> Result { loop {} } +pub fn alef() -> Result { + loop {} +} +pub fn bet() -> Result { + loop {} +} -pub fn alpha(_param: Result) { loop {} } -pub fn beta(_param: Result) { loop {} } +pub fn alpha(_param: Result) { + loop {} +} +pub fn beta(_param: Result) { + loop {} +} diff --git a/tests/rustdoc-js/generics.rs b/tests/rustdoc-js/generics.rs index 055c51c7ec57..c3ca13666141 100644 --- a/tests/rustdoc-js/generics.rs +++ b/tests/rustdoc-js/generics.rs @@ -3,26 +3,41 @@ pub struct Q; pub struct R(T); // returns test -pub fn alef() -> R

{ loop {} } -pub fn bet() -> R { loop {} } +pub fn alef() -> R

{ + loop {} +} +pub fn bet() -> R { + loop {} +} // in_args test -pub fn alpha(_x: R

) { loop {} } -pub fn beta(_x: R) { loop {} } +pub fn alpha(_x: R

) { + loop {} +} +pub fn beta(_x: R) { + loop {} +} // test case with multiple appearances of the same type -pub struct ExtraCreditStructMulti { t: T, u: U } +pub struct ExtraCreditStructMulti { + t: T, + u: U, +} pub struct ExtraCreditInnerMulti {} pub fn extracreditlabhomework( - _param: ExtraCreditStructMulti -) { loop {} } -pub fn redherringmatchforextracredit( - _param: ExtraCreditStructMulti -) { loop {} } + _param: ExtraCreditStructMulti, +) { + loop {} +} +pub fn redherringmatchforextracredit(_param: ExtraCreditStructMulti) { + loop {} +} pub trait TraitCat {} pub trait TraitDog {} pub fn gamma(t: T) {} -pub fn super_soup(s: Result) -> Result { s } +pub fn super_soup(s: Result) -> Result { + s +} diff --git a/tests/rustdoc-js/hof.rs b/tests/rustdoc-js/hof.rs index 4d2c6e331cac..e4d550250e8a 100644 --- a/tests/rustdoc-js/hof.rs +++ b/tests/rustdoc-js/hof.rs @@ -4,9 +4,9 @@ pub struct First(T); pub struct Second(T); pub struct Third(T); -pub fn fn_ptr(_: fn (First) -> !, _: bool) {} -pub fn fn_once(_: impl FnOnce (Second) -> !, _: u8) {} -pub fn fn_mut(_: impl FnMut (Third) -> !, _: i8) {} -pub fn fn_(_: impl Fn (u32) -> !, _: char) {} +pub fn fn_ptr(_: fn(First) -> !, _: bool) {} +pub fn fn_once(_: impl FnOnce(Second) -> !, _: u8) {} +pub fn fn_mut(_: impl FnMut(Third) -> !, _: i8) {} +pub fn fn_(_: impl Fn(u32) -> !, _: char) {} pub fn multiple(_: impl Fn(&'static str, &'static str) -> i8) {} diff --git a/tests/rustdoc-js/macro-search.rs b/tests/rustdoc-js/macro-search.rs index dc397490cf58..7fa9cbc4ab23 100644 --- a/tests/rustdoc-js/macro-search.rs +++ b/tests/rustdoc-js/macro-search.rs @@ -1,10 +1,10 @@ #[macro_export] macro_rules! abracadabra { - () => {} + () => {}; } #[macro_export] macro_rules! abracadabra_b { - () => {} + () => {}; } pub fn abracadabra() {} pub fn abracadabra_c() {} diff --git a/tests/rustdoc-js/never-search.rs b/tests/rustdoc-js/never-search.rs index 299b4660dae9..800f9ead8b35 100644 --- a/tests/rustdoc-js/never-search.rs +++ b/tests/rustdoc-js/never-search.rs @@ -3,11 +3,27 @@ #[allow(nonstandard_style)] pub struct never; -pub fn loops() -> ! { loop {} } -pub fn returns() -> never { never } +pub fn loops() -> ! { + loop {} +} +pub fn returns() -> never { + never +} -pub fn impossible(x: !) { match x {} } -pub fn uninteresting(x: never) { match x { never => {} } } +pub fn impossible(x: !) { + match x {} +} +pub fn uninteresting(x: never) { + match x { + never => {} + } +} -pub fn box_impossible(x: Box) { match *x {} } -pub fn box_uninteresting(x: Box) { match *x { never => {} } } +pub fn box_impossible(x: Box) { + match *x {} +} +pub fn box_uninteresting(x: Box) { + match *x { + never => {} + } +} diff --git a/tests/rustdoc-js/path-maxeditdistance.rs b/tests/rustdoc-js/path-maxeditdistance.rs index 3861280d59bf..88af4f487741 100644 --- a/tests/rustdoc-js/path-maxeditdistance.rs +++ b/tests/rustdoc-js/path-maxeditdistance.rs @@ -1,3 +1,3 @@ -#![crate_name="abracadabra"] +#![crate_name = "abracadabra"] pub struct HocusPocusPrestidigitation; diff --git a/tests/rustdoc-js/prototype.rs b/tests/rustdoc-js/prototype.rs index 5f6d73cc1962..77553561238c 100644 --- a/tests/rustdoc-js/prototype.rs +++ b/tests/rustdoc-js/prototype.rs @@ -1,4 +1,4 @@ // The alias needed to be there to reproduce the bug // that used to be here. -#[doc(alias="other_alias")] +#[doc(alias = "other_alias")] pub fn something_else() {} diff --git a/tests/rustdoc-js/reexport-dedup-macro.rs b/tests/rustdoc-js/reexport-dedup-macro.rs index 3d18da3951c7..f70b9c3d7338 100644 --- a/tests/rustdoc-js/reexport-dedup-macro.rs +++ b/tests/rustdoc-js/reexport-dedup-macro.rs @@ -1,5 +1,5 @@ //@ aux-crate: macro_in_module=macro-in-module.rs -#![crate_name="foo"] +#![crate_name = "foo"] extern crate macro_in_module; // Test case based on the relationship between alloc and std. diff --git a/tests/rustdoc-js/reexport-dedup-method.rs b/tests/rustdoc-js/reexport-dedup-method.rs index 5dbd66e9c8ed..c00df094d7ac 100644 --- a/tests/rustdoc-js/reexport-dedup-method.rs +++ b/tests/rustdoc-js/reexport-dedup-method.rs @@ -1,5 +1,5 @@ // This test enforces that the (renamed) reexports are present in the search results. -#![crate_name="foo"] +#![crate_name = "foo"] pub mod fmt { pub struct Subscriber; @@ -14,5 +14,5 @@ mod foo { } } -pub use foo::AnotherOne; pub use fmt::Subscriber; +pub use foo::AnotherOne; diff --git a/tests/rustdoc-js/reexport-dedup.rs b/tests/rustdoc-js/reexport-dedup.rs index 40aea9633036..83c23d5c3664 100644 --- a/tests/rustdoc-js/reexport-dedup.rs +++ b/tests/rustdoc-js/reexport-dedup.rs @@ -1,5 +1,5 @@ // This test enforces that the (renamed) reexports are present in the search results. -#![crate_name="foo"] +#![crate_name = "foo"] pub mod fmt { pub struct Subscriber; @@ -8,5 +8,5 @@ mod foo { pub struct AnotherOne; } -pub use foo::AnotherOne; pub use fmt::Subscriber; +pub use foo::AnotherOne; diff --git a/tests/rustdoc-js/reexport.rs b/tests/rustdoc-js/reexport.rs index d51b7fb369c2..0b3718cd9a3e 100644 --- a/tests/rustdoc-js/reexport.rs +++ b/tests/rustdoc-js/reexport.rs @@ -9,5 +9,5 @@ mod foo { pub struct AnotherOne; } -pub use foo::AnotherOne; pub use fmt::Subscriber as FmtSubscriber; +pub use foo::AnotherOne; diff --git a/tests/rustdoc-js/reference.rs b/tests/rustdoc-js/reference.rs index 3a0a23c65d5b..93b2a6df8e6c 100644 --- a/tests/rustdoc-js/reference.rs +++ b/tests/rustdoc-js/reference.rs @@ -7,13 +7,17 @@ pub fn pinky(input: &usize, manage: usize) { pub struct Thumb; impl Thumb { - pub fn up(&self, finger: Thumb) { unimplemented!() } + pub fn up(&self, finger: Thumb) { + unimplemented!() + } } pub enum Index {} impl Index { - pub fn point(self, data: &Index) { unimplemented!() } + pub fn point(self, data: &Index) { + unimplemented!() + } } pub union Ring { @@ -22,11 +26,15 @@ pub union Ring { } impl Ring { - pub fn wear(&mut self, extra: &Ring) { unimplemented!() } + pub fn wear(&mut self, extra: &Ring) { + unimplemented!() + } } extern "C" { pub type Middle; } -pub fn show(left: &&mut Middle, right: &mut &Middle) { unimplemented!() } +pub fn show(left: &&mut Middle, right: &mut &Middle) { + unimplemented!() +} diff --git a/tests/rustdoc-js/slice-array.rs b/tests/rustdoc-js/slice-array.rs index 15ac4294f3d7..e4e34a26fa25 100644 --- a/tests/rustdoc-js/slice-array.rs +++ b/tests/rustdoc-js/slice-array.rs @@ -3,12 +3,20 @@ pub struct Q; pub struct R(T); // returns test -pub fn alef() -> &'static [R

] { loop {} } -pub fn bet() -> R<[Q; 32]> { loop {} } +pub fn alef() -> &'static [R

] { + loop {} +} +pub fn bet() -> R<[Q; 32]> { + loop {} +} // in_args test -pub fn alpha(_x: R<&'static [P]>) { loop {} } -pub fn beta(_x: [R; 32]) { loop {} } +pub fn alpha(_x: R<&'static [P]>) { + loop {} +} +pub fn beta(_x: [R; 32]) { + loop {} +} pub trait TraitCat {} pub trait TraitDog {} diff --git a/tests/rustdoc-js/struct-like-variant.rs b/tests/rustdoc-js/struct-like-variant.rs index 2f52a319ab9a..aafde9957ff8 100644 --- a/tests/rustdoc-js/struct-like-variant.rs +++ b/tests/rustdoc-js/struct-like-variant.rs @@ -3,6 +3,6 @@ pub enum Enum { Bar { /// This is a name. - name: String - } + name: String, + }, } diff --git a/tests/rustdoc-js/summaries.rs b/tests/rustdoc-js/summaries.rs index 1ee1c34aa156..9e8fc820245e 100644 --- a/tests/rustdoc-js/summaries.rs +++ b/tests/rustdoc-js/summaries.rs @@ -1,6 +1,5 @@ #![crate_type = "lib"] #![crate_name = "summaries"] - #![allow(rustdoc::broken_intra_doc_links)] //! This *summary* has a [link], [`code`], and [`Sidebar2`] intra-doc. diff --git a/tests/rustdoc-js/tuple-unit.rs b/tests/rustdoc-js/tuple-unit.rs index 93f9a671cbc3..4531545cf6c5 100644 --- a/tests/rustdoc-js/tuple-unit.rs +++ b/tests/rustdoc-js/tuple-unit.rs @@ -3,16 +3,24 @@ pub struct Q; pub struct R(T); // Checks that tuple and unit both work -pub fn side_effect() { } +pub fn side_effect() {} // Check a non-tuple -pub fn not_tuple() -> P { loop {} } +pub fn not_tuple() -> P { + loop {} +} // Check a 1-tuple -pub fn one() -> (P,) { loop {} } +pub fn one() -> (P,) { + loop {} +} // Check a 2-tuple -pub fn two() -> (P,P) { loop {} } +pub fn two() -> (P, P) { + loop {} +} // Check a nested tuple -pub fn nest() -> (Q, R<(u32,)>) { loop {} } +pub fn nest() -> (Q, R<(u32,)>) { + loop {} +} diff --git a/tests/rustdoc-js/type-parameters.rs b/tests/rustdoc-js/type-parameters.rs index cda5e26171fc..0edbfbea178b 100644 --- a/tests/rustdoc-js/type-parameters.rs +++ b/tests/rustdoc-js/type-parameters.rs @@ -1,15 +1,23 @@ -#![crate_name="foo"] +#![crate_name = "foo"] pub trait Some {} impl Some for () {} pub trait Other {} impl Other for () {} -pub fn alef() -> T { loop {} } -pub fn alpha() -> impl Some { } +pub fn alef() -> T { + loop {} +} +pub fn alpha() -> impl Some {} -pub fn bet(t: T) -> U { loop {} } +pub fn bet(t: T) -> U { + loop {} +} pub fn beta(t: T) -> T {} -pub fn other(t: T, u: U) { loop {} } -pub fn alternate(t: T, u: T) { loop {} } +pub fn other(t: T, u: U) { + loop {} +} +pub fn alternate(t: T, u: T) { + loop {} +} diff --git a/tests/rustdoc-js/where-clause.rs b/tests/rustdoc-js/where-clause.rs index 56c01019fb69..c0fede1cfd59 100644 --- a/tests/rustdoc-js/where-clause.rs +++ b/tests/rustdoc-js/where-clause.rs @@ -4,27 +4,46 @@ pub trait Trait { fn thank_you(x: T); } -pub fn abracadabra(_: X) where X: Trait {} +pub fn abracadabra(_: X) +where + X: Trait, +{ +} -pub fn alacazam() -> X where X: Trait {} +pub fn alacazam() -> X +where + X: Trait, +{ +} pub trait T1 {} pub trait T2<'a, T> { fn please(_: &'a T); } -pub fn presto(_: A, _: B) where A: T1, B: for <'b> T2<'b, Nested> {} +pub fn presto(_: A, _: B) +where + A: T1, + B: for<'b> T2<'b, Nested>, +{ +} pub trait Shazam {} -pub fn bippety() -> &'static X where X: Shazam { +pub fn bippety() -> &'static X +where + X: Shazam, +{ panic!() } pub struct Drizzel(T); impl Drizzel { - pub fn boppety(&self) -> &T where T: Shazam { + pub fn boppety(&self) -> &T + where + T: Shazam, + { panic!(); } } From 9f16362ab4c584aa737b68326c9859a07293113a Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 4 Jun 2024 10:03:40 +1000 Subject: [PATCH 200/211] rustfmt `tests/rustdoc-json/`. --- rustfmt.toml | 1 - tests/rustdoc-json/lifetime/longest.rs | 6 +----- tests/rustdoc-json/non_lifetime_binders.rs | 6 +++++- tests/rustdoc-json/output_generics.rs | 13 ++++++++++--- tests/rustdoc-json/type/extern.rs | 2 +- tests/rustdoc-json/unions/impl.rs | 2 +- tests/rustdoc-json/unions/union.rs | 1 - 7 files changed, 18 insertions(+), 13 deletions(-) diff --git a/rustfmt.toml b/rustfmt.toml index 79f197b27b17..9f2dcec6f060 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -19,7 +19,6 @@ ignore = [ "/tests/run-make/translation/test.rs", # This test contains syntax errors. "/tests/rustdoc/", # Some have syntax errors, some are whitespace-sensitive. "/tests/rustdoc-gui/", # Some tests are sensitive to source code layout. - "/tests/rustdoc-json/", "/tests/rustdoc-js-std/", "/tests/rustdoc-ui/", "/tests/ui/", diff --git a/tests/rustdoc-json/lifetime/longest.rs b/tests/rustdoc-json/lifetime/longest.rs index 419b0b4fcab1..dccad41a861b 100644 --- a/tests/rustdoc-json/lifetime/longest.rs +++ b/tests/rustdoc-json/lifetime/longest.rs @@ -23,9 +23,5 @@ // @is "$.index[*][?(@.name=='longest')].inner.function.decl.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 - } + if l.len() > r.len() { l } else { r } } diff --git a/tests/rustdoc-json/non_lifetime_binders.rs b/tests/rustdoc-json/non_lifetime_binders.rs index d925fcd52215..6f0732646ca1 100644 --- a/tests/rustdoc-json/non_lifetime_binders.rs +++ b/tests/rustdoc-json/non_lifetime_binders.rs @@ -12,4 +12,8 @@ pub struct Wrapper(std::marker::PhantomData); // @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 } }' -pub fn foo() where for<'a, T> &'a Wrapper: Trait {} +pub fn foo() +where + for<'a, T> &'a Wrapper: Trait, +{ +} diff --git a/tests/rustdoc-json/output_generics.rs b/tests/rustdoc-json/output_generics.rs index d421eafbb47b..e9df64b79e30 100644 --- a/tests/rustdoc-json/output_generics.rs +++ b/tests/rustdoc-json/output_generics.rs @@ -16,12 +16,19 @@ pub trait Trait { fn handle(value: T) -> Self; } -impl Trait for T where T: From { - fn handle(_: U) -> Self { unimplemented!() } +impl Trait for T +where + T: From, +{ + fn handle(_: U) -> Self { + unimplemented!() + } } impl<'a, R> Trait<&'a mut Events> for Other { - fn handle(_: &'a mut Events) -> Self { unimplemented!() } + fn handle(_: &'a mut Events) -> Self { + unimplemented!() + } } fn this_compiles<'a, R>(value: &'a mut Events) { diff --git a/tests/rustdoc-json/type/extern.rs b/tests/rustdoc-json/type/extern.rs index c30146ce9e03..59e099ec9fce 100644 --- a/tests/rustdoc-json/type/extern.rs +++ b/tests/rustdoc-json/type/extern.rs @@ -1,6 +1,6 @@ #![feature(extern_types)] -extern { +extern "C" { /// No inner information pub type Foo; } diff --git a/tests/rustdoc-json/unions/impl.rs b/tests/rustdoc-json/unions/impl.rs index 7456892df1bb..1515f7d93971 100644 --- a/tests/rustdoc-json/unions/impl.rs +++ b/tests/rustdoc-json/unions/impl.rs @@ -4,7 +4,7 @@ // @has "$.index[*][?(@.name=='Ux')].inner.union" pub union Ux { a: u32, - b: u64 + b: u64, } // @is "$.index[*][?(@.name=='Num')].visibility" \"public\" diff --git a/tests/rustdoc-json/unions/union.rs b/tests/rustdoc-json/unions/union.rs index 22b70e1ce8c5..1089d9c45585 100644 --- a/tests/rustdoc-json/unions/union.rs +++ b/tests/rustdoc-json/unions/union.rs @@ -7,7 +7,6 @@ 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 pub fn make_int_union(int: i32) -> Union { From 50185807d723363f5070165f514969cd675ec39a Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 4 Jun 2024 10:05:25 +1000 Subject: [PATCH 201/211] rustfmt `tests/rustdoc-js-std/`. This is trivial, because the directory contains no `.rs` files. --- rustfmt.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/rustfmt.toml b/rustfmt.toml index 9f2dcec6f060..6966de6ce7ea 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -19,7 +19,6 @@ ignore = [ "/tests/run-make/translation/test.rs", # This test contains syntax errors. "/tests/rustdoc/", # Some have syntax errors, some are whitespace-sensitive. "/tests/rustdoc-gui/", # Some tests are sensitive to source code layout. - "/tests/rustdoc-js-std/", "/tests/rustdoc-ui/", "/tests/ui/", "/tests/ui-fulldeps/", From 1be65925d70de48b077c91046dd2910e13577a35 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 4 Jun 2024 10:17:58 +1000 Subject: [PATCH 202/211] Explain why `tests/rustdoc-ui/` is unformatted. --- rustfmt.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rustfmt.toml b/rustfmt.toml index 6966de6ce7ea..135dd29ad7ca 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -19,7 +19,7 @@ ignore = [ "/tests/run-make/translation/test.rs", # This test contains syntax errors. "/tests/rustdoc/", # Some have syntax errors, some are whitespace-sensitive. "/tests/rustdoc-gui/", # Some tests are sensitive to source code layout. - "/tests/rustdoc-ui/", + "/tests/rustdoc-ui/", # Some have syntax errors, some are whitespace-sensitive. "/tests/ui/", "/tests/ui-fulldeps/", From 758d49e5c80989186ae65df0a5d045fb546b977e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 4 Jun 2024 10:22:43 +1000 Subject: [PATCH 203/211] Explain why `tests/ui/` is unformatted. --- rustfmt.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rustfmt.toml b/rustfmt.toml index 135dd29ad7ca..31d1e9b50e54 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -20,7 +20,7 @@ ignore = [ "/tests/rustdoc/", # Some have syntax errors, some are whitespace-sensitive. "/tests/rustdoc-gui/", # Some tests are sensitive to source code layout. "/tests/rustdoc-ui/", # Some have syntax errors, some are whitespace-sensitive. - "/tests/ui/", + "/tests/ui/", # Some have syntax errors, some are whitespace-sensitive. "/tests/ui-fulldeps/", # Do not format submodules. From d2ea692e2d4f11b0a91b14570172fde9151b06c5 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 4 Jun 2024 10:27:30 +1000 Subject: [PATCH 204/211] Explain why `tests/ui-fulldeps/` is unformatted. --- rustfmt.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rustfmt.toml b/rustfmt.toml index 31d1e9b50e54..b15ffdca38a0 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -21,7 +21,7 @@ ignore = [ "/tests/rustdoc-gui/", # Some tests are sensitive to source code layout. "/tests/rustdoc-ui/", # Some have syntax errors, some are whitespace-sensitive. "/tests/ui/", # Some have syntax errors, some are whitespace-sensitive. - "/tests/ui-fulldeps/", + "/tests/ui-fulldeps/", # Some are whitespace-sensitive (e.g. `// ~ERROR` comments). # Do not format submodules. # FIXME: sync submodule list with tidy/bootstrap/etc From 4798c20d31843b49bf3a5e891c1a3534f007ce61 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 30 May 2024 10:51:11 +1000 Subject: [PATCH 205/211] Streamline `nested` calls. `TyCtxt` impls `PpAnn` in `compiler/rustc_middle/src/hir/map/mod.rs`. We can call that impl, which then calls the one on `intravisit::Map`, instead of calling the one on `intravisit::Map` directly, avoiding a cast and extra references. --- compiler/rustc_driver_impl/src/pretty.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs index 8acba57b7a65..31de0a747b24 100644 --- a/compiler/rustc_driver_impl/src/pretty.rs +++ b/compiler/rustc_driver_impl/src/pretty.rs @@ -3,7 +3,6 @@ use rustc_ast as ast; use rustc_ast_pretty::pprust as pprust_ast; use rustc_errors::FatalError; -use rustc_hir as hir; use rustc_hir_pretty as pprust_hir; use rustc_middle::bug; use rustc_middle::mir::{write_mir_graphviz, write_mir_pretty}; @@ -70,11 +69,7 @@ struct HirIdentifiedAnn<'tcx> { impl<'tcx> pprust_hir::PpAnn for HirIdentifiedAnn<'tcx> { fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) { - pprust_hir::PpAnn::nested( - &(&self.tcx.hir() as &dyn hir::intravisit::Map<'_>), - state, - nested, - ) + self.tcx.nested(state, nested) } fn pre(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) { @@ -152,8 +147,7 @@ impl<'tcx> pprust_hir::PpAnn for HirTypedAnn<'tcx> { if let pprust_hir::Nested::Body(id) = nested { self.maybe_typeck_results.set(Some(self.tcx.typeck_body(id))); } - let pp_ann = &(&self.tcx.hir() as &dyn hir::intravisit::Map<'_>); - pprust_hir::PpAnn::nested(pp_ann, state, nested); + self.tcx.nested(state, nested); self.maybe_typeck_results.set(old_maybe_typeck_results); } From 6b47c5e24d7403e7587a3aad16bcc8aed2cbbd0a Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 4 Jun 2024 15:18:35 +1000 Subject: [PATCH 206/211] Remove out-of-date comment. Exhaustiveness and usefulness checking are now in `rustc_pattern_analysis`. --- compiler/rustc_mir_build/src/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs index 74600c6b12eb..a1b8b5783491 100644 --- a/compiler/rustc_mir_build/src/lib.rs +++ b/compiler/rustc_mir_build/src/lib.rs @@ -1,6 +1,4 @@ //! Construction of MIR from HIR. -//! -//! This crate also contains the match exhaustiveness and usefulness checking. #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] From 5a5e2489c5143f9b1bea608bb10309994e6c091a Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 4 Jun 2024 15:28:09 +1000 Subject: [PATCH 207/211] Reduce `pub` exposure. A lot of errors don't need to be visible outside the crate, and some other things as well. --- .../src/build/coverageinfo/mcdc.rs | 8 +- .../rustc_mir_build/src/build/custom/parse.rs | 4 +- .../src/build/custom/parse/instruction.rs | 6 +- .../src/build/expr/as_constant.rs | 2 +- .../rustc_mir_build/src/build/expr/mod.rs | 4 +- .../rustc_mir_build/src/build/matches/util.rs | 2 +- compiler/rustc_mir_build/src/build/scope.rs | 2 +- .../rustc_mir_build/src/check_unsafety.rs | 4 +- compiler/rustc_mir_build/src/errors.rs | 518 +++++++++--------- 9 files changed, 275 insertions(+), 275 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs b/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs index 7d7b7caf9ef9..f97e9ef60a29 100644 --- a/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs +++ b/compiler/rustc_mir_build/src/build/coverageinfo/mcdc.rs @@ -179,18 +179,18 @@ impl MCDCState { } } -pub struct MCDCInfoBuilder { +pub(crate) struct MCDCInfoBuilder { branch_spans: Vec, decision_spans: Vec, state: MCDCState, } impl MCDCInfoBuilder { - pub fn new() -> Self { + pub(crate) fn new() -> Self { Self { branch_spans: vec![], decision_spans: vec![], state: MCDCState::new() } } - pub fn visit_evaluated_condition( + pub(crate) fn visit_evaluated_condition( &mut self, tcx: TyCtxt<'_>, source_info: SourceInfo, @@ -243,7 +243,7 @@ impl MCDCInfoBuilder { }); } - pub fn into_done(self) -> (Vec, Vec) { + pub(crate) fn into_done(self) -> (Vec, Vec) { (self.decision_spans, self.branch_spans) } } diff --git a/compiler/rustc_mir_build/src/build/custom/parse.rs b/compiler/rustc_mir_build/src/build/custom/parse.rs index 8bcd429b67eb..9607022c6df0 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse.rs @@ -91,7 +91,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { } } - pub fn parse_args(&mut self, params: &IndexSlice>) -> PResult<()> { + pub(crate) fn parse_args(&mut self, params: &IndexSlice>) -> PResult<()> { for param in params.iter() { let (var, span) = { let pat = param.pat.as_ref().unwrap(); @@ -149,7 +149,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { /// /// This allows us to easily parse the basic blocks declarations, local declarations, and /// basic block definitions in order. - pub fn parse_body(&mut self, expr_id: ExprId) -> PResult<()> { + pub(crate) fn parse_body(&mut self, expr_id: ExprId) -> PResult<()> { let body = parse_by_kind!(self, expr_id, _, "whole body", ExprKind::Block { block } => self.thir[*block].expr.unwrap(), ); diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs index de748b9c85d1..b1a305efa4c6 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs @@ -12,7 +12,7 @@ use crate::build::expr::as_constant::as_constant_inner; use super::{parse_by_kind, PResult, ParseCtxt}; impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { - pub fn parse_statement(&self, expr_id: ExprId) -> PResult> { + pub(crate) fn parse_statement(&self, expr_id: ExprId) -> PResult> { parse_by_kind!(self, expr_id, _, "statement", @call(mir_storage_live, args) => { Ok(StatementKind::StorageLive(self.parse_local(args[0])?)) @@ -46,7 +46,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { ) } - pub fn parse_terminator(&self, expr_id: ExprId) -> PResult> { + pub(crate) fn parse_terminator(&self, expr_id: ExprId) -> PResult> { parse_by_kind!(self, expr_id, expr, "terminator", @call(mir_return, _args) => { Ok(TerminatorKind::Return) @@ -261,7 +261,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { ) } - pub fn parse_operand(&self, expr_id: ExprId) -> PResult> { + pub(crate) fn parse_operand(&self, expr_id: ExprId) -> PResult> { parse_by_kind!(self, expr_id, expr, "operand", @call(mir_move, args) => self.parse_place(args[0]).map(Operand::Move), @call(mir_static, args) => self.parse_static(args[0]), diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs index b4dd423f344a..f7229326c541 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs @@ -39,7 +39,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } -pub fn as_constant_inner<'tcx>( +pub(crate) fn as_constant_inner<'tcx>( expr: &Expr<'tcx>, push_cuta: impl FnMut(&Box>) -> Option, tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_mir_build/src/build/expr/mod.rs b/compiler/rustc_mir_build/src/build/expr/mod.rs index dfe85b858cd0..3de43a3370f3 100644 --- a/compiler/rustc_mir_build/src/build/expr/mod.rs +++ b/compiler/rustc_mir_build/src/build/expr/mod.rs @@ -62,9 +62,9 @@ pub(crate) mod as_constant; mod as_operand; -pub mod as_place; +pub(crate) mod as_place; mod as_rvalue; mod as_temp; -pub mod category; +pub(crate) mod category; mod into; mod stmt; diff --git a/compiler/rustc_mir_build/src/build/matches/util.rs b/compiler/rustc_mir_build/src/build/matches/util.rs index 770f689724af..50f4ca2d819d 100644 --- a/compiler/rustc_mir_build/src/build/matches/util.rs +++ b/compiler/rustc_mir_build/src/build/matches/util.rs @@ -456,7 +456,7 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> { } #[must_use] -pub fn ref_pat_borrow_kind(ref_mutability: Mutability) -> BorrowKind { +pub(crate) fn ref_pat_borrow_kind(ref_mutability: Mutability) -> BorrowKind { match ref_mutability { Mutability::Mut => BorrowKind::Mut { kind: MutBorrowKind::Default }, Mutability::Not => BorrowKind::Shared, diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index c7850c7aea87..5b6de39bb2e7 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -97,7 +97,7 @@ use rustc_span::{Span, DUMMY_SP}; use tracing::{debug, instrument}; #[derive(Debug)] -pub struct Scopes<'tcx> { +pub(crate) struct Scopes<'tcx> { scopes: Vec, /// The current set of breakable scopes. See module comment for more details. diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 24098282d93b..659ae1724603 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -597,7 +597,7 @@ enum UnsafeOpKind { use UnsafeOpKind::*; impl UnsafeOpKind { - pub fn emit_unsafe_op_in_unsafe_fn_lint( + fn emit_unsafe_op_in_unsafe_fn_lint( &self, tcx: TyCtxt<'_>, hir_id: HirId, @@ -737,7 +737,7 @@ impl UnsafeOpKind { } } - pub fn emit_requires_unsafe_err( + fn emit_requires_unsafe_err( &self, tcx: TyCtxt<'_>, span: Span, diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index d7ed4f57e596..cf324c03dc9f 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -13,111 +13,111 @@ use rustc_span::Span; #[derive(LintDiagnostic)] #[diag(mir_build_unconditional_recursion)] #[help] -pub struct UnconditionalRecursion { +pub(crate) struct UnconditionalRecursion { #[label] - pub span: Span, + pub(crate) span: Span, #[label(mir_build_unconditional_recursion_call_site_label)] - pub call_sites: Vec, + pub(crate) call_sites: Vec, } #[derive(LintDiagnostic)] #[diag(mir_build_call_to_deprecated_safe_fn_requires_unsafe)] -pub struct CallToDeprecatedSafeFnRequiresUnsafe { +pub(crate) struct CallToDeprecatedSafeFnRequiresUnsafe { #[label] - pub span: Span, - pub function: String, + pub(crate) span: Span, + pub(crate) function: String, #[subdiagnostic] - pub sub: CallToDeprecatedSafeFnRequiresUnsafeSub, + pub(crate) sub: CallToDeprecatedSafeFnRequiresUnsafeSub, } #[derive(Subdiagnostic)] #[multipart_suggestion(mir_build_suggestion, applicability = "machine-applicable")] -pub struct CallToDeprecatedSafeFnRequiresUnsafeSub { +pub(crate) struct CallToDeprecatedSafeFnRequiresUnsafeSub { #[suggestion_part(code = "unsafe {{ ")] - pub left: Span, + pub(crate) left: Span, #[suggestion_part(code = " }}")] - pub right: Span, + pub(crate) right: Span, } #[derive(LintDiagnostic)] #[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe, code = E0133)] #[note] -pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe { +pub(crate) struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe { #[label] - pub span: Span, - pub function: String, + pub(crate) span: Span, + pub(crate) function: String, #[subdiagnostic] - pub unsafe_not_inherited_note: Option, + pub(crate) unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] #[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_unsafe_fn_requires_unsafe_nameless, code = E0133)] #[note] -pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless { +pub(crate) struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless { #[label] - pub span: Span, + pub(crate) span: Span, #[subdiagnostic] - pub unsafe_not_inherited_note: Option, + pub(crate) unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] #[diag(mir_build_unsafe_op_in_unsafe_fn_inline_assembly_requires_unsafe, code = E0133)] #[note] -pub struct UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe { +pub(crate) struct UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe { #[label] - pub span: Span, + pub(crate) span: Span, #[subdiagnostic] - pub unsafe_not_inherited_note: Option, + pub(crate) unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] #[diag(mir_build_unsafe_op_in_unsafe_fn_initializing_type_with_requires_unsafe, code = E0133)] #[note] -pub struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { +pub(crate) struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { #[label] - pub span: Span, + pub(crate) span: Span, #[subdiagnostic] - pub unsafe_not_inherited_note: Option, + pub(crate) unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] #[diag(mir_build_unsafe_op_in_unsafe_fn_mutable_static_requires_unsafe, code = E0133)] #[note] -pub struct UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { +pub(crate) struct UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { #[label] - pub span: Span, + pub(crate) span: Span, #[subdiagnostic] - pub unsafe_not_inherited_note: Option, + pub(crate) unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] #[diag(mir_build_unsafe_op_in_unsafe_fn_extern_static_requires_unsafe, code = E0133)] #[note] -pub struct UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe { +pub(crate) struct UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe { #[label] - pub span: Span, + pub(crate) span: Span, #[subdiagnostic] - pub unsafe_not_inherited_note: Option, + pub(crate) unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] #[diag(mir_build_unsafe_op_in_unsafe_fn_deref_raw_pointer_requires_unsafe, code = E0133)] #[note] -pub struct UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe { +pub(crate) struct UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe { #[label] - pub span: Span, + pub(crate) span: Span, #[subdiagnostic] - pub unsafe_not_inherited_note: Option, + pub(crate) unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] #[diag(mir_build_unsafe_op_in_unsafe_fn_union_field_requires_unsafe, code = E0133)] #[note] -pub struct UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { +pub(crate) struct UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { #[label] - pub span: Span, + pub(crate) span: Span, #[subdiagnostic] - pub unsafe_not_inherited_note: Option, + pub(crate) unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] @@ -126,11 +126,11 @@ pub struct UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { code = E0133 )] #[note] -pub struct UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe { +pub(crate) struct UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe { #[label] - pub span: Span, + pub(crate) span: Span, #[subdiagnostic] - pub unsafe_not_inherited_note: Option, + pub(crate) unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] @@ -138,63 +138,63 @@ pub struct UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe { mir_build_unsafe_op_in_unsafe_fn_borrow_of_layout_constrained_field_requires_unsafe, code = E0133, )] -pub struct UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe { +pub(crate) struct UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe { #[label] - pub span: Span, + pub(crate) span: Span, #[subdiagnostic] - pub unsafe_not_inherited_note: Option, + pub(crate) unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] #[diag(mir_build_unsafe_op_in_unsafe_fn_call_to_fn_with_requires_unsafe, code = E0133)] #[help] -pub struct UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe { +pub(crate) struct UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe { #[label] - pub span: Span, - pub function: String, - pub missing_target_features: DiagArgValue, - pub missing_target_features_count: usize, + pub(crate) span: Span, + pub(crate) function: String, + pub(crate) missing_target_features: DiagArgValue, + pub(crate) missing_target_features_count: usize, #[note] - pub note: Option<()>, - pub build_target_features: DiagArgValue, - pub build_target_features_count: usize, + pub(crate) note: Option<()>, + pub(crate) build_target_features: DiagArgValue, + pub(crate) build_target_features_count: usize, #[subdiagnostic] - pub unsafe_not_inherited_note: Option, + pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] #[diag(mir_build_call_to_unsafe_fn_requires_unsafe, code = E0133)] #[note] -pub struct CallToUnsafeFunctionRequiresUnsafe { +pub(crate) struct CallToUnsafeFunctionRequiresUnsafe { #[primary_span] #[label] - pub span: Span, - pub function: String, + pub(crate) span: Span, + pub(crate) function: String, #[subdiagnostic] - pub unsafe_not_inherited_note: Option, + pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] #[diag(mir_build_call_to_unsafe_fn_requires_unsafe_nameless, code = E0133)] #[note] -pub struct CallToUnsafeFunctionRequiresUnsafeNameless { +pub(crate) struct CallToUnsafeFunctionRequiresUnsafeNameless { #[primary_span] #[label] - pub span: Span, + pub(crate) span: Span, #[subdiagnostic] - pub unsafe_not_inherited_note: Option, + pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] #[diag(mir_build_call_to_unsafe_fn_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)] #[note] -pub struct CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed { +pub(crate) struct CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] #[label] - pub span: Span, - pub function: String, + pub(crate) span: Span, + pub(crate) function: String, #[subdiagnostic] - pub unsafe_not_inherited_note: Option, + pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] @@ -203,45 +203,45 @@ pub struct CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed { code = E0133 )] #[note] -pub struct CallToUnsafeFunctionRequiresUnsafeNamelessUnsafeOpInUnsafeFnAllowed { +pub(crate) struct CallToUnsafeFunctionRequiresUnsafeNamelessUnsafeOpInUnsafeFnAllowed { #[primary_span] #[label] - pub span: Span, + pub(crate) span: Span, #[subdiagnostic] - pub unsafe_not_inherited_note: Option, + pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] #[diag(mir_build_inline_assembly_requires_unsafe, code = E0133)] #[note] -pub struct UseOfInlineAssemblyRequiresUnsafe { +pub(crate) struct UseOfInlineAssemblyRequiresUnsafe { #[primary_span] #[label] - pub span: Span, + pub(crate) span: Span, #[subdiagnostic] - pub unsafe_not_inherited_note: Option, + pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] #[diag(mir_build_inline_assembly_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)] #[note] -pub struct UseOfInlineAssemblyRequiresUnsafeUnsafeOpInUnsafeFnAllowed { +pub(crate) struct UseOfInlineAssemblyRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] #[label] - pub span: Span, + pub(crate) span: Span, #[subdiagnostic] - pub unsafe_not_inherited_note: Option, + pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] #[diag(mir_build_initializing_type_with_requires_unsafe, code = E0133)] #[note] -pub struct InitializingTypeWithRequiresUnsafe { +pub(crate) struct InitializingTypeWithRequiresUnsafe { #[primary_span] #[label] - pub span: Span, + pub(crate) span: Span, #[subdiagnostic] - pub unsafe_not_inherited_note: Option, + pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] @@ -250,111 +250,111 @@ pub struct InitializingTypeWithRequiresUnsafe { code = E0133 )] #[note] -pub struct InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { +pub(crate) struct InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] #[label] - pub span: Span, + pub(crate) span: Span, #[subdiagnostic] - pub unsafe_not_inherited_note: Option, + pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] #[diag(mir_build_mutable_static_requires_unsafe, code = E0133)] #[note] -pub struct UseOfMutableStaticRequiresUnsafe { +pub(crate) struct UseOfMutableStaticRequiresUnsafe { #[primary_span] #[label] - pub span: Span, + pub(crate) span: Span, #[subdiagnostic] - pub unsafe_not_inherited_note: Option, + pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] #[diag(mir_build_mutable_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)] #[note] -pub struct UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { +pub(crate) struct UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] #[label] - pub span: Span, + pub(crate) span: Span, #[subdiagnostic] - pub unsafe_not_inherited_note: Option, + pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] #[diag(mir_build_extern_static_requires_unsafe, code = E0133)] #[note] -pub struct UseOfExternStaticRequiresUnsafe { +pub(crate) struct UseOfExternStaticRequiresUnsafe { #[primary_span] #[label] - pub span: Span, + pub(crate) span: Span, #[subdiagnostic] - pub unsafe_not_inherited_note: Option, + pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] #[diag(mir_build_extern_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)] #[note] -pub struct UseOfExternStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { +pub(crate) struct UseOfExternStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] #[label] - pub span: Span, + pub(crate) span: Span, #[subdiagnostic] - pub unsafe_not_inherited_note: Option, + pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] #[diag(mir_build_deref_raw_pointer_requires_unsafe, code = E0133)] #[note] -pub struct DerefOfRawPointerRequiresUnsafe { +pub(crate) struct DerefOfRawPointerRequiresUnsafe { #[primary_span] #[label] - pub span: Span, + pub(crate) span: Span, #[subdiagnostic] - pub unsafe_not_inherited_note: Option, + pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] #[diag(mir_build_deref_raw_pointer_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)] #[note] -pub struct DerefOfRawPointerRequiresUnsafeUnsafeOpInUnsafeFnAllowed { +pub(crate) struct DerefOfRawPointerRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] #[label] - pub span: Span, + pub(crate) span: Span, #[subdiagnostic] - pub unsafe_not_inherited_note: Option, + pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] #[diag(mir_build_union_field_requires_unsafe, code = E0133)] #[note] -pub struct AccessToUnionFieldRequiresUnsafe { +pub(crate) struct AccessToUnionFieldRequiresUnsafe { #[primary_span] #[label] - pub span: Span, + pub(crate) span: Span, #[subdiagnostic] - pub unsafe_not_inherited_note: Option, + pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] #[diag(mir_build_union_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)] #[note] -pub struct AccessToUnionFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { +pub(crate) struct AccessToUnionFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] #[label] - pub span: Span, + pub(crate) span: Span, #[subdiagnostic] - pub unsafe_not_inherited_note: Option, + pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] #[diag(mir_build_mutation_of_layout_constrained_field_requires_unsafe, code = E0133)] #[note] -pub struct MutationOfLayoutConstrainedFieldRequiresUnsafe { +pub(crate) struct MutationOfLayoutConstrainedFieldRequiresUnsafe { #[primary_span] #[label] - pub span: Span, + pub(crate) span: Span, #[subdiagnostic] - pub unsafe_not_inherited_note: Option, + pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] @@ -363,23 +363,23 @@ pub struct MutationOfLayoutConstrainedFieldRequiresUnsafe { code = E0133 )] #[note] -pub struct MutationOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { +pub(crate) struct MutationOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] #[label] - pub span: Span, + pub(crate) span: Span, #[subdiagnostic] - pub unsafe_not_inherited_note: Option, + pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] #[diag(mir_build_borrow_of_layout_constrained_field_requires_unsafe, code = E0133)] #[note] -pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafe { +pub(crate) struct BorrowOfLayoutConstrainedFieldRequiresUnsafe { #[primary_span] #[label] - pub span: Span, + pub(crate) span: Span, #[subdiagnostic] - pub unsafe_not_inherited_note: Option, + pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] @@ -388,60 +388,60 @@ pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafe { code = E0133 )] #[note] -pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { +pub(crate) struct BorrowOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] #[label] - pub span: Span, + pub(crate) span: Span, #[subdiagnostic] - pub unsafe_not_inherited_note: Option, + pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] #[diag(mir_build_call_to_fn_with_requires_unsafe, code = E0133)] #[help] -pub struct CallToFunctionWithRequiresUnsafe { +pub(crate) struct CallToFunctionWithRequiresUnsafe { #[primary_span] #[label] - pub span: Span, - pub function: String, - pub missing_target_features: DiagArgValue, - pub missing_target_features_count: usize, + pub(crate) span: Span, + pub(crate) function: String, + pub(crate) missing_target_features: DiagArgValue, + pub(crate) missing_target_features_count: usize, #[note] - pub note: Option<()>, - pub build_target_features: DiagArgValue, - pub build_target_features_count: usize, + pub(crate) note: Option<()>, + pub(crate) build_target_features: DiagArgValue, + pub(crate) build_target_features_count: usize, #[subdiagnostic] - pub unsafe_not_inherited_note: Option, + pub(crate) unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] #[diag(mir_build_call_to_fn_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)] #[help] -pub struct CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { +pub(crate) struct CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] #[label] - pub span: Span, - pub function: String, - pub missing_target_features: DiagArgValue, - pub missing_target_features_count: usize, + pub(crate) span: Span, + pub(crate) function: String, + pub(crate) missing_target_features: DiagArgValue, + pub(crate) missing_target_features_count: usize, #[note] - pub note: Option<()>, - pub build_target_features: DiagArgValue, - pub build_target_features_count: usize, + pub(crate) note: Option<()>, + pub(crate) build_target_features: DiagArgValue, + pub(crate) build_target_features_count: usize, #[subdiagnostic] - pub unsafe_not_inherited_note: Option, + pub(crate) unsafe_not_inherited_note: Option, } #[derive(Subdiagnostic)] #[label(mir_build_unsafe_not_inherited)] -pub struct UnsafeNotInheritedNote { +pub(crate) struct UnsafeNotInheritedNote { #[primary_span] - pub span: Span, + pub(crate) span: Span, } -pub struct UnsafeNotInheritedLintNote { - pub signature_span: Span, - pub body_span: Span, +pub(crate) struct UnsafeNotInheritedLintNote { + pub(crate) signature_span: Span, + pub(crate) body_span: Span, } impl Subdiagnostic for UnsafeNotInheritedLintNote { @@ -463,15 +463,15 @@ impl Subdiagnostic for UnsafeNotInheritedLintNote { #[derive(LintDiagnostic)] #[diag(mir_build_unused_unsafe)] -pub struct UnusedUnsafe { +pub(crate) struct UnusedUnsafe { #[label] - pub span: Span, + pub(crate) span: Span, #[subdiagnostic] - pub enclosing: Option, + pub(crate) enclosing: Option, } #[derive(Subdiagnostic)] -pub enum UnusedUnsafeEnclosing { +pub(crate) enum UnusedUnsafeEnclosing { #[label(mir_build_unused_unsafe_enclosing_block_label)] Block { #[primary_span] @@ -480,10 +480,10 @@ pub enum UnusedUnsafeEnclosing { } pub(crate) struct NonExhaustivePatternsTypeNotEmpty<'p, 'tcx, 'm> { - pub cx: &'m RustcPatCtxt<'p, 'tcx>, - pub scrut_span: Span, - pub braces_span: Option, - pub ty: Ty<'tcx>, + pub(crate) cx: &'m RustcPatCtxt<'p, 'tcx>, + pub(crate) scrut_span: Span, + pub(crate) braces_span: Option, + pub(crate) ty: Ty<'tcx>, } impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_> { @@ -552,197 +552,197 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NonExhaustivePatternsTypeNo #[derive(Subdiagnostic)] #[note(mir_build_non_exhaustive_match_all_arms_guarded)] -pub struct NonExhaustiveMatchAllArmsGuarded; +pub(crate) struct NonExhaustiveMatchAllArmsGuarded; #[derive(Diagnostic)] #[diag(mir_build_static_in_pattern, code = E0158)] -pub struct StaticInPattern { +pub(crate) struct StaticInPattern { #[primary_span] - pub span: Span, + pub(crate) span: Span, } #[derive(Diagnostic)] #[diag(mir_build_assoc_const_in_pattern, code = E0158)] -pub struct AssocConstInPattern { +pub(crate) struct AssocConstInPattern { #[primary_span] - pub span: Span, + pub(crate) span: Span, } #[derive(Diagnostic)] #[diag(mir_build_const_param_in_pattern, code = E0158)] -pub struct ConstParamInPattern { +pub(crate) struct ConstParamInPattern { #[primary_span] - pub span: Span, + pub(crate) span: Span, } #[derive(Diagnostic)] #[diag(mir_build_non_const_path, code = E0080)] -pub struct NonConstPath { +pub(crate) struct NonConstPath { #[primary_span] - pub span: Span, + pub(crate) span: Span, } #[derive(LintDiagnostic)] #[diag(mir_build_unreachable_pattern)] -pub struct UnreachablePattern { +pub(crate) struct UnreachablePattern { #[label] - pub span: Option, + pub(crate) span: Option, #[label(mir_build_catchall_label)] - pub catchall: Option, + pub(crate) catchall: Option, } #[derive(Diagnostic)] #[diag(mir_build_const_pattern_depends_on_generic_parameter)] -pub struct ConstPatternDependsOnGenericParameter { +pub(crate) struct ConstPatternDependsOnGenericParameter { #[primary_span] - pub span: Span, + pub(crate) span: Span, } #[derive(Diagnostic)] #[diag(mir_build_could_not_eval_const_pattern)] -pub struct CouldNotEvalConstPattern { +pub(crate) struct CouldNotEvalConstPattern { #[primary_span] - pub span: Span, + pub(crate) span: Span, } #[derive(Diagnostic)] #[diag(mir_build_lower_range_bound_must_be_less_than_or_equal_to_upper, code = E0030)] -pub struct LowerRangeBoundMustBeLessThanOrEqualToUpper { +pub(crate) struct LowerRangeBoundMustBeLessThanOrEqualToUpper { #[primary_span] #[label] - pub span: Span, + pub(crate) span: Span, #[note(mir_build_teach_note)] - pub teach: Option<()>, + pub(crate) teach: Option<()>, } #[derive(Diagnostic)] #[diag(mir_build_literal_in_range_out_of_bounds)] -pub struct LiteralOutOfRange<'tcx> { +pub(crate) struct LiteralOutOfRange<'tcx> { #[primary_span] #[label] - pub span: Span, - pub ty: Ty<'tcx>, - pub min: i128, - pub max: u128, + pub(crate) span: Span, + pub(crate) ty: Ty<'tcx>, + pub(crate) min: i128, + pub(crate) max: u128, } #[derive(Diagnostic)] #[diag(mir_build_lower_range_bound_must_be_less_than_upper, code = E0579)] -pub struct LowerRangeBoundMustBeLessThanUpper { +pub(crate) struct LowerRangeBoundMustBeLessThanUpper { #[primary_span] - pub span: Span, + pub(crate) span: Span, } #[derive(LintDiagnostic)] #[diag(mir_build_leading_irrefutable_let_patterns)] #[note] #[help] -pub struct LeadingIrrefutableLetPatterns { - pub count: usize, +pub(crate) struct LeadingIrrefutableLetPatterns { + pub(crate) count: usize, } #[derive(LintDiagnostic)] #[diag(mir_build_trailing_irrefutable_let_patterns)] #[note] #[help] -pub struct TrailingIrrefutableLetPatterns { - pub count: usize, +pub(crate) struct TrailingIrrefutableLetPatterns { + pub(crate) count: usize, } #[derive(LintDiagnostic)] #[diag(mir_build_bindings_with_variant_name, code = E0170)] -pub struct BindingsWithVariantName { +pub(crate) struct BindingsWithVariantName { #[suggestion(code = "{ty_path}::{name}", applicability = "machine-applicable")] - pub suggestion: Option, - pub ty_path: String, - pub name: Symbol, + pub(crate) suggestion: Option, + pub(crate) ty_path: String, + pub(crate) name: Symbol, } #[derive(LintDiagnostic)] #[diag(mir_build_irrefutable_let_patterns_if_let)] #[note] #[help] -pub struct IrrefutableLetPatternsIfLet { - pub count: usize, +pub(crate) struct IrrefutableLetPatternsIfLet { + pub(crate) count: usize, } #[derive(LintDiagnostic)] #[diag(mir_build_irrefutable_let_patterns_if_let_guard)] #[note] #[help] -pub struct IrrefutableLetPatternsIfLetGuard { - pub count: usize, +pub(crate) struct IrrefutableLetPatternsIfLetGuard { + pub(crate) count: usize, } #[derive(LintDiagnostic)] #[diag(mir_build_irrefutable_let_patterns_let_else)] #[note] #[help] -pub struct IrrefutableLetPatternsLetElse { - pub count: usize, +pub(crate) struct IrrefutableLetPatternsLetElse { + pub(crate) count: usize, } #[derive(LintDiagnostic)] #[diag(mir_build_irrefutable_let_patterns_while_let)] #[note] #[help] -pub struct IrrefutableLetPatternsWhileLet { - pub count: usize, +pub(crate) struct IrrefutableLetPatternsWhileLet { + pub(crate) count: usize, } #[derive(Diagnostic)] #[diag(mir_build_borrow_of_moved_value)] -pub struct BorrowOfMovedValue<'tcx> { +pub(crate) struct BorrowOfMovedValue<'tcx> { #[primary_span] #[label] #[label(mir_build_occurs_because_label)] - pub binding_span: Span, + pub(crate) binding_span: Span, #[label(mir_build_value_borrowed_label)] - pub conflicts_ref: Vec, - pub name: Symbol, - pub ty: Ty<'tcx>, + pub(crate) conflicts_ref: Vec, + pub(crate) name: Symbol, + pub(crate) ty: Ty<'tcx>, #[suggestion(code = "ref ", applicability = "machine-applicable")] - pub suggest_borrowing: Option, + pub(crate) suggest_borrowing: Option, } #[derive(Diagnostic)] #[diag(mir_build_multiple_mut_borrows)] -pub struct MultipleMutBorrows { +pub(crate) struct MultipleMutBorrows { #[primary_span] - pub span: Span, + pub(crate) span: Span, #[subdiagnostic] - pub occurrences: Vec, + pub(crate) occurrences: Vec, } #[derive(Diagnostic)] #[diag(mir_build_already_borrowed)] -pub struct AlreadyBorrowed { +pub(crate) struct AlreadyBorrowed { #[primary_span] - pub span: Span, + pub(crate) span: Span, #[subdiagnostic] - pub occurrences: Vec, + pub(crate) occurrences: Vec, } #[derive(Diagnostic)] #[diag(mir_build_already_mut_borrowed)] -pub struct AlreadyMutBorrowed { +pub(crate) struct AlreadyMutBorrowed { #[primary_span] - pub span: Span, + pub(crate) span: Span, #[subdiagnostic] - pub occurrences: Vec, + pub(crate) occurrences: Vec, } #[derive(Diagnostic)] #[diag(mir_build_moved_while_borrowed)] -pub struct MovedWhileBorrowed { +pub(crate) struct MovedWhileBorrowed { #[primary_span] - pub span: Span, + pub(crate) span: Span, #[subdiagnostic] - pub occurrences: Vec, + pub(crate) occurrences: Vec, } #[derive(Subdiagnostic)] -pub enum Conflict { +pub(crate) enum Conflict { #[label(mir_build_mutable_borrow)] Mut { #[primary_span] @@ -765,118 +765,118 @@ pub enum Conflict { #[derive(Diagnostic)] #[diag(mir_build_union_pattern)] -pub struct UnionPattern { +pub(crate) struct UnionPattern { #[primary_span] - pub span: Span, + pub(crate) span: Span, } #[derive(Diagnostic)] #[diag(mir_build_type_not_structural)] #[note(mir_build_type_not_structural_tip)] #[note(mir_build_type_not_structural_more_info)] -pub struct TypeNotStructural<'tcx> { +pub(crate) struct TypeNotStructural<'tcx> { #[primary_span] - pub span: Span, - pub non_sm_ty: Ty<'tcx>, + pub(crate) span: Span, + pub(crate) non_sm_ty: Ty<'tcx>, } #[derive(Diagnostic)] #[diag(mir_build_non_partial_eq_match)] -pub struct TypeNotPartialEq<'tcx> { +pub(crate) struct TypeNotPartialEq<'tcx> { #[primary_span] - pub span: Span, - pub non_peq_ty: Ty<'tcx>, + pub(crate) span: Span, + pub(crate) non_peq_ty: Ty<'tcx>, } #[derive(Diagnostic)] #[diag(mir_build_invalid_pattern)] -pub struct InvalidPattern<'tcx> { +pub(crate) struct InvalidPattern<'tcx> { #[primary_span] - pub span: Span, - pub non_sm_ty: Ty<'tcx>, + pub(crate) span: Span, + pub(crate) non_sm_ty: Ty<'tcx>, } #[derive(Diagnostic)] #[diag(mir_build_unsized_pattern)] -pub struct UnsizedPattern<'tcx> { +pub(crate) struct UnsizedPattern<'tcx> { #[primary_span] - pub span: Span, - pub non_sm_ty: Ty<'tcx>, + pub(crate) span: Span, + pub(crate) non_sm_ty: Ty<'tcx>, } #[derive(Diagnostic)] #[diag(mir_build_nan_pattern)] #[note] #[help] -pub struct NaNPattern { +pub(crate) struct NaNPattern { #[primary_span] - pub span: Span, + pub(crate) span: Span, } #[derive(Diagnostic)] #[diag(mir_build_pointer_pattern)] -pub struct PointerPattern { +pub(crate) struct PointerPattern { #[primary_span] - pub span: Span, + pub(crate) span: Span, } #[derive(Diagnostic)] #[diag(mir_build_non_empty_never_pattern)] #[note] -pub struct NonEmptyNeverPattern<'tcx> { +pub(crate) struct NonEmptyNeverPattern<'tcx> { #[primary_span] #[label] - pub span: Span, - pub ty: Ty<'tcx>, + pub(crate) span: Span, + pub(crate) ty: Ty<'tcx>, } #[derive(Diagnostic)] #[diag(mir_build_exceeds_mcdc_condition_limit)] pub(crate) struct MCDCExceedsConditionLimit { #[primary_span] - pub span: Span, - pub num_conditions: usize, - pub max_conditions: usize, + pub(crate) span: Span, + pub(crate) num_conditions: usize, + pub(crate) max_conditions: usize, } #[derive(Diagnostic)] #[diag(mir_build_pattern_not_covered, code = E0005)] pub(crate) struct PatternNotCovered<'s, 'tcx> { #[primary_span] - pub span: Span, - pub origin: &'s str, + pub(crate) span: Span, + pub(crate) origin: &'s str, #[subdiagnostic] - pub uncovered: Uncovered<'tcx>, + pub(crate) uncovered: Uncovered<'tcx>, #[subdiagnostic] - pub inform: Option, + pub(crate) inform: Option, #[subdiagnostic] - pub interpreted_as_const: Option, + pub(crate) interpreted_as_const: Option, #[subdiagnostic] - pub adt_defined_here: Option>, + pub(crate) adt_defined_here: Option>, #[note(mir_build_privately_uninhabited)] - pub witness_1_is_privately_uninhabited: Option<()>, + pub(crate) witness_1_is_privately_uninhabited: Option<()>, #[note(mir_build_pattern_ty)] - pub _p: (), - pub pattern_ty: Ty<'tcx>, + pub(crate) _p: (), + pub(crate) pattern_ty: Ty<'tcx>, #[subdiagnostic] - pub let_suggestion: Option, + pub(crate) let_suggestion: Option, #[subdiagnostic] - pub misc_suggestion: Option, + pub(crate) misc_suggestion: Option, } #[derive(Subdiagnostic)] #[note(mir_build_inform_irrefutable)] #[note(mir_build_more_information)] -pub struct Inform; +pub(crate) struct Inform; -pub struct AdtDefinedHere<'tcx> { - pub adt_def_span: Span, - pub ty: Ty<'tcx>, - pub variants: Vec, +pub(crate) struct AdtDefinedHere<'tcx> { + pub(crate) adt_def_span: Span, + pub(crate) ty: Ty<'tcx>, + pub(crate) variants: Vec, } -pub struct Variant { - pub span: Span, +pub(crate) struct Variant { + pub(crate) span: Span, } impl<'tcx> Subdiagnostic for AdtDefinedHere<'tcx> { @@ -903,14 +903,14 @@ impl<'tcx> Subdiagnostic for AdtDefinedHere<'tcx> { applicability = "maybe-incorrect" )] #[label(mir_build_confused)] -pub struct InterpretedAsConst { +pub(crate) struct InterpretedAsConst { #[primary_span] - pub span: Span, - pub variable: String, + pub(crate) span: Span, + pub(crate) variable: String, } #[derive(Subdiagnostic)] -pub enum SuggestLet { +pub(crate) enum SuggestLet { #[multipart_suggestion(mir_build_suggest_if_let, applicability = "has-placeholders")] If { #[suggestion_part(code = "if ")] @@ -932,7 +932,7 @@ pub enum SuggestLet { } #[derive(Subdiagnostic)] -pub enum MiscPatternSuggestion { +pub(crate) enum MiscPatternSuggestion { #[suggestion( mir_build_suggest_attempted_int_lit, code = "_", @@ -946,15 +946,15 @@ pub enum MiscPatternSuggestion { #[derive(Diagnostic)] #[diag(mir_build_rustc_box_attribute_error)] -pub struct RustcBoxAttributeError { +pub(crate) struct RustcBoxAttributeError { #[primary_span] - pub span: Span, + pub(crate) span: Span, #[subdiagnostic] - pub reason: RustcBoxAttrReason, + pub(crate) reason: RustcBoxAttrReason, } #[derive(Subdiagnostic)] -pub enum RustcBoxAttrReason { +pub(crate) enum RustcBoxAttrReason { #[note(mir_build_attributes)] Attributes, #[note(mir_build_not_box)] @@ -965,13 +965,13 @@ pub enum RustcBoxAttrReason { #[derive(LintDiagnostic)] #[diag(mir_build_rust_2024_incompatible_pat)] -pub struct Rust2024IncompatiblePat { +pub(crate) struct Rust2024IncompatiblePat { #[subdiagnostic] - pub sugg: Rust2024IncompatiblePatSugg, + pub(crate) sugg: Rust2024IncompatiblePatSugg, } -pub struct Rust2024IncompatiblePatSugg { - pub suggestion: Vec<(Span, String)>, +pub(crate) struct Rust2024IncompatiblePatSugg { + pub(crate) suggestion: Vec<(Span, String)>, } impl Subdiagnostic for Rust2024IncompatiblePatSugg { From f076dec33622904821b7829ba759da9c610d1451 Mon Sep 17 00:00:00 2001 From: Boxy Date: Tue, 4 Jun 2024 02:24:57 +0100 Subject: [PATCH 208/211] Downsize `ty::Expr` --- compiler/rustc_middle/src/ty/consts.rs | 4 +- compiler/rustc_middle/src/ty/consts/kind.rs | 125 +++++++++++++++++- compiler/rustc_middle/src/ty/flags.rs | 21 +-- compiler/rustc_middle/src/ty/mod.rs | 2 +- compiler/rustc_middle/src/ty/print/pretty.rs | 100 ++++++-------- compiler/rustc_middle/src/ty/relate.rs | 52 ++------ .../rustc_middle/src/ty/structural_impls.rs | 38 ++++-- compiler/rustc_middle/src/ty/walk.rs | 19 +-- compiler/rustc_ty_utils/src/consts.rs | 33 +++-- 9 files changed, 232 insertions(+), 162 deletions(-) diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 6416bbbe889c..384a4e7009d8 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -24,7 +24,7 @@ pub type ConstKind<'tcx> = ir::ConstKind>; pub type UnevaluatedConst<'tcx> = ir::UnevaluatedConst>; #[cfg(target_pointer_width = "64")] -rustc_data_structures::static_assert_size!(ConstKind<'_>, 32); +rustc_data_structures::static_assert_size!(ConstKind<'_>, 24); /// Use this rather than `ConstData`, whenever possible. #[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable)] @@ -58,7 +58,7 @@ pub struct ConstData<'tcx> { } #[cfg(target_pointer_width = "64")] -rustc_data_structures::static_assert_size!(ConstData<'_>, 40); +rustc_data_structures::static_assert_size!(ConstData<'_>, 32); impl<'tcx> Const<'tcx> { #[inline] diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index d7ae050ed4d0..5f29acf5ed27 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -1,7 +1,7 @@ use super::Const; use crate::mir; use crate::ty::abstract_const::CastKind; -use crate::ty::{self, visit::TypeVisitableExt as _, List, Ty, TyCtxt}; +use crate::ty::{self, visit::TypeVisitableExt as _, Ty, TyCtxt}; use rustc_macros::{extension, HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; #[extension(pub(crate) trait UnevaluatedConstEvalExt<'tcx>)] @@ -40,14 +40,125 @@ impl<'tcx> ty::UnevaluatedConst<'tcx> { } } +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +#[derive(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)] +pub enum ExprKind { + Binop(mir::BinOp), + UnOp(mir::UnOp), + FunctionCall, + Cast(CastKind), +} #[derive(Copy, Clone, Eq, PartialEq, Hash)] #[derive(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)] -pub enum Expr<'tcx> { - Binop(mir::BinOp, Const<'tcx>, Const<'tcx>), - UnOp(mir::UnOp, Const<'tcx>), - FunctionCall(Const<'tcx>, &'tcx List>), - Cast(CastKind, Const<'tcx>, Ty<'tcx>), +pub struct Expr<'tcx> { + pub kind: ExprKind, + args: ty::GenericArgsRef<'tcx>, +} +impl<'tcx> Expr<'tcx> { + pub fn new_binop( + tcx: TyCtxt<'tcx>, + binop: mir::BinOp, + lhs_ty: Ty<'tcx>, + rhs_ty: Ty<'tcx>, + lhs_ct: Const<'tcx>, + rhs_ct: Const<'tcx>, + ) -> Self { + let args = tcx.mk_args_from_iter::<_, ty::GenericArg<'tcx>>( + [lhs_ty.into(), rhs_ty.into(), lhs_ct.into(), rhs_ct.into()].into_iter(), + ); + + Self { kind: ExprKind::Binop(binop), args } + } + + pub fn binop_args(self) -> (Ty<'tcx>, Ty<'tcx>, Const<'tcx>, Const<'tcx>) { + assert!(matches!(self.kind, ExprKind::Binop(_))); + + match self.args().as_slice() { + [lhs_ty, rhs_ty, lhs_ct, rhs_ct] => ( + lhs_ty.expect_ty(), + rhs_ty.expect_ty(), + lhs_ct.expect_const(), + rhs_ct.expect_const(), + ), + _ => bug!("Invalid args for `Binop` expr {self:?}"), + } + } + + pub fn new_unop(tcx: TyCtxt<'tcx>, unop: mir::UnOp, ty: Ty<'tcx>, ct: Const<'tcx>) -> Self { + let args = + tcx.mk_args_from_iter::<_, ty::GenericArg<'tcx>>([ty.into(), ct.into()].into_iter()); + + Self { kind: ExprKind::UnOp(unop), args } + } + + pub fn unop_args(self) -> (Ty<'tcx>, Const<'tcx>) { + assert!(matches!(self.kind, ExprKind::UnOp(_))); + + match self.args().as_slice() { + [ty, ct] => (ty.expect_ty(), ct.expect_const()), + _ => bug!("Invalid args for `UnOp` expr {self:?}"), + } + } + + pub fn new_call( + tcx: TyCtxt<'tcx>, + func_ty: Ty<'tcx>, + func_expr: Const<'tcx>, + arguments: impl Iterator>, + ) -> Self { + let args = tcx.mk_args_from_iter::<_, ty::GenericArg<'tcx>>( + [func_ty.into(), func_expr.into()].into_iter().chain(arguments.map(|ct| ct.into())), + ); + + Self { kind: ExprKind::FunctionCall, args } + } + + pub fn call_args(self) -> (Ty<'tcx>, Const<'tcx>, impl Iterator>) { + assert!(matches!(self.kind, ExprKind::FunctionCall)); + + match self.args().as_slice() { + [func_ty, func, rest @ ..] => ( + func_ty.expect_ty(), + func.expect_const(), + rest.iter().map(|arg| arg.expect_const()), + ), + _ => bug!("Invalid args for `Call` expr {self:?}"), + } + } + + pub fn new_cast( + tcx: TyCtxt<'tcx>, + cast: CastKind, + value_ty: Ty<'tcx>, + value: Const<'tcx>, + to_ty: Ty<'tcx>, + ) -> Self { + let args = tcx.mk_args_from_iter::<_, ty::GenericArg<'tcx>>( + [value_ty.into(), value.into(), to_ty.into()].into_iter(), + ); + + Self { kind: ExprKind::Cast(cast), args } + } + + pub fn cast_args(self) -> (Ty<'tcx>, Const<'tcx>, Ty<'tcx>) { + assert!(matches!(self.kind, ExprKind::Cast(_))); + + match self.args().as_slice() { + [value_ty, value, to_ty] => { + (value_ty.expect_ty(), value.expect_const(), to_ty.expect_ty()) + } + _ => bug!("Invalid args for `Cast` expr {self:?}"), + } + } + + pub fn new(kind: ExprKind, args: ty::GenericArgsRef<'tcx>) -> Self { + Self { kind, args } + } + + pub fn args(&self) -> ty::GenericArgsRef<'tcx> { + self.args + } } #[cfg(target_pointer_width = "64")] -rustc_data_structures::static_assert_size!(Expr<'_>, 24); +rustc_data_structures::static_assert_size!(Expr<'_>, 16); diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 4de7d532c967..93a51d3a3340 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -374,26 +374,7 @@ impl FlagComputation { self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); } ty::ConstKind::Value(_) => {} - ty::ConstKind::Expr(e) => { - use ty::Expr; - match e { - Expr::Binop(_, l, r) => { - self.add_const(l); - self.add_const(r); - } - Expr::UnOp(_, v) => self.add_const(v), - Expr::FunctionCall(f, args) => { - self.add_const(f); - for arg in args { - self.add_const(arg); - } - } - Expr::Cast(_, c, t) => { - self.add_ty(t); - self.add_const(c); - } - } - } + ty::ConstKind::Expr(e) => self.add_args(e.args()), ty::ConstKind::Error(_) => self.add_flags(TypeFlags::HAS_ERROR), } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 2643ce976ded..714224fc9654 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -87,7 +87,7 @@ pub use self::closure::{ CAPTURE_STRUCT_LOCAL, }; pub use self::consts::{ - Const, ConstData, ConstInt, ConstKind, Expr, ScalarInt, UnevaluatedConst, ValTree, + Const, ConstData, ConstInt, ConstKind, Expr, ExprKind, ScalarInt, UnevaluatedConst, ValTree, }; pub use self::context::{ tls, CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift, diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 8fb4367d3b58..80d5b7445d09 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1533,8 +1533,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { print_ty: bool, ) -> Result<(), PrintError> { define_scoped_cx!(self); - match expr { - Expr::Binop(op, c1, c2) => { + match expr.kind { + ty::ExprKind::Binop(op) => { + let (_, _, c1, c2) = expr.binop_args(); + let precedence = |binop: rustc_middle::mir::BinOp| { use rustc_ast::util::parser::AssocOp; AssocOp::from_ast_binop(binop.to_hir_binop().into()).precedence() @@ -1543,22 +1545,26 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { let formatted_op = op.to_hir_binop().as_str(); let (lhs_parenthesized, rhs_parenthesized) = match (c1.kind(), c2.kind()) { ( - ty::ConstKind::Expr(Expr::Binop(lhs_op, _, _)), - ty::ConstKind::Expr(Expr::Binop(rhs_op, _, _)), + ty::ConstKind::Expr(ty::Expr { kind: ty::ExprKind::Binop(lhs_op), .. }), + ty::ConstKind::Expr(ty::Expr { kind: ty::ExprKind::Binop(rhs_op), .. }), ) => (precedence(lhs_op) < op_precedence, precedence(rhs_op) < op_precedence), - (ty::ConstKind::Expr(Expr::Binop(lhs_op, ..)), ty::ConstKind::Expr(_)) => { - (precedence(lhs_op) < op_precedence, true) - } - (ty::ConstKind::Expr(_), ty::ConstKind::Expr(Expr::Binop(rhs_op, ..))) => { - (true, precedence(rhs_op) < op_precedence) - } + ( + ty::ConstKind::Expr(ty::Expr { kind: ty::ExprKind::Binop(lhs_op), .. }), + ty::ConstKind::Expr(_), + ) => (precedence(lhs_op) < op_precedence, true), + ( + ty::ConstKind::Expr(_), + ty::ConstKind::Expr(ty::Expr { kind: ty::ExprKind::Binop(rhs_op), .. }), + ) => (true, precedence(rhs_op) < op_precedence), (ty::ConstKind::Expr(_), ty::ConstKind::Expr(_)) => (true, true), - (ty::ConstKind::Expr(Expr::Binop(lhs_op, ..)), _) => { - (precedence(lhs_op) < op_precedence, false) - } - (_, ty::ConstKind::Expr(Expr::Binop(rhs_op, ..))) => { - (false, precedence(rhs_op) < op_precedence) - } + ( + ty::ConstKind::Expr(ty::Expr { kind: ty::ExprKind::Binop(lhs_op), .. }), + _, + ) => (precedence(lhs_op) < op_precedence, false), + ( + _, + ty::ConstKind::Expr(ty::Expr { kind: ty::ExprKind::Binop(rhs_op), .. }), + ) => (false, precedence(rhs_op) < op_precedence), (ty::ConstKind::Expr(_), _) => (true, false), (_, ty::ConstKind::Expr(_)) => (false, true), _ => (false, false), @@ -1574,7 +1580,9 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { rhs_parenthesized, )?; } - Expr::UnOp(op, ct) => { + ty::ExprKind::UnOp(op) => { + let (_, ct) = expr.unop_args(); + use rustc_middle::mir::UnOp; let formatted_op = match op { UnOp::Not => "!", @@ -1583,7 +1591,9 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { }; let parenthesized = match ct.kind() { _ if op == UnOp::PtrMetadata => true, - ty::ConstKind::Expr(Expr::UnOp(c_op, ..)) => c_op != op, + ty::ConstKind::Expr(ty::Expr { kind: ty::ExprKind::UnOp(c_op), .. }) => { + c_op != op + } ty::ConstKind::Expr(_) => true, _ => false, }; @@ -1593,61 +1603,37 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { parenthesized, )? } - Expr::FunctionCall(fn_def, fn_args) => { - use ty::TyKind; - match fn_def.ty().kind() { - TyKind::FnDef(def_id, gen_args) => { - p!(print_value_path(*def_id, gen_args), "("); - if print_ty { - let tcx = self.tcx(); - let sig = tcx.fn_sig(def_id).instantiate(tcx, gen_args).skip_binder(); + ty::ExprKind::FunctionCall => { + let (_, fn_def, fn_args) = expr.call_args(); - let mut args_with_ty = fn_args.iter().map(|ct| (ct, ct.ty())); - let output_ty = sig.output(); - - if let Some((ct, ty)) = args_with_ty.next() { - self.typed_value( - |this| this.pretty_print_const(ct, print_ty), - |this| this.pretty_print_type(ty), - ": ", - )?; - for (ct, ty) in args_with_ty { - p!(", "); - self.typed_value( - |this| this.pretty_print_const(ct, print_ty), - |this| this.pretty_print_type(ty), - ": ", - )?; - } - } - p!(write(") -> {output_ty}")); - } else { - p!(comma_sep(fn_args.iter()), ")"); - } - } - _ => bug!("unexpected type of fn def"), - } + write!(self, "(")?; + self.pretty_print_const(fn_def, print_ty)?; + p!(")(", comma_sep(fn_args), ")"); } - Expr::Cast(kind, ct, ty) => { + ty::ExprKind::Cast(kind) => { + let (_, value, to_ty) = expr.cast_args(); + use ty::abstract_const::CastKind; if kind == CastKind::As || (kind == CastKind::Use && self.should_print_verbose()) { - let parenthesized = match ct.kind() { - ty::ConstKind::Expr(Expr::Cast(_, _, _)) => false, + let parenthesized = match value.kind() { + ty::ConstKind::Expr(ty::Expr { + kind: ty::ExprKind::Cast { .. }, .. + }) => false, ty::ConstKind::Expr(_) => true, _ => false, }; self.maybe_parenthesized( |this| { this.typed_value( - |this| this.pretty_print_const(ct, print_ty), - |this| this.pretty_print_type(ty), + |this| this.pretty_print_const(value, print_ty), + |this| this.pretty_print_type(to_ty), " as ", ) }, parenthesized, )?; } else { - self.pretty_print_const(ct, print_ty)? + self.pretty_print_const(value, print_ty)? } } } diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index b41798588909..a621d255a03e 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -6,8 +6,8 @@ use crate::ty::error::{ExpectedFound, TypeError}; use crate::ty::{ - self, ExistentialPredicate, ExistentialPredicateStableCmpExt as _, Expr, GenericArg, - GenericArgKind, GenericArgsRef, ImplSubject, Term, TermKind, Ty, TyCtxt, TypeFoldable, + self, ExistentialPredicate, ExistentialPredicateStableCmpExt as _, GenericArg, GenericArgKind, + GenericArgsRef, ImplSubject, Term, TermKind, Ty, TyCtxt, TypeFoldable, }; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -665,46 +665,18 @@ pub fn structurally_relate_consts<'tcx, R: TypeRelation<'tcx>>( a.ty(), )); } - // Before calling relate on exprs, it is necessary to ensure that the nested consts - // have identical types. (ty::ConstKind::Expr(ae), ty::ConstKind::Expr(be)) => { - let r = relation; - - // FIXME(generic_const_exprs): is it possible to relate two consts which are not identical - // exprs? Should we care about that? - // FIXME(generic_const_exprs): relating the `ty()`s is a little weird since it is supposed to - // ICE If they mismatch. Unfortunately `ConstKind::Expr` is a little special and can be thought - // of as being generic over the argument types, however this is implicit so these types don't get - // related when we relate the args of the item this const arg is for. - let expr = match (ae, be) { - (Expr::Binop(a_op, al, ar), Expr::Binop(b_op, bl, br)) if a_op == b_op => { - r.relate(al.ty(), bl.ty())?; - r.relate(ar.ty(), br.ty())?; - Expr::Binop(a_op, r.consts(al, bl)?, r.consts(ar, br)?) - } - (Expr::UnOp(a_op, av), Expr::UnOp(b_op, bv)) if a_op == b_op => { - r.relate(av.ty(), bv.ty())?; - Expr::UnOp(a_op, r.consts(av, bv)?) - } - (Expr::Cast(ak, av, at), Expr::Cast(bk, bv, bt)) if ak == bk => { - r.relate(av.ty(), bv.ty())?; - Expr::Cast(ak, r.consts(av, bv)?, r.tys(at, bt)?) - } - (Expr::FunctionCall(af, aa), Expr::FunctionCall(bf, ba)) - if aa.len() == ba.len() => - { - r.relate(af.ty(), bf.ty())?; - let func = r.consts(af, bf)?; - let mut related_args = Vec::with_capacity(aa.len()); - for (a_arg, b_arg) in aa.iter().zip(ba.iter()) { - related_args.push(r.consts(a_arg, b_arg)?); - } - let related_args = tcx.mk_const_list(&related_args); - Expr::FunctionCall(func, related_args) - } + match (ae.kind, be.kind) { + (ty::ExprKind::Binop(a_binop), ty::ExprKind::Binop(b_binop)) + if a_binop == b_binop => {} + (ty::ExprKind::UnOp(a_unop), ty::ExprKind::UnOp(b_unop)) if a_unop == b_unop => {} + (ty::ExprKind::FunctionCall, ty::ExprKind::FunctionCall) => {} + (ty::ExprKind::Cast(a_kind), ty::ExprKind::Cast(b_kind)) if a_kind == b_kind => {} _ => return Err(TypeError::ConstMismatch(expected_found(a, b))), - }; - return Ok(ty::Const::new_expr(tcx, expr, a.ty())); + } + + let args = relation.relate(ae.args(), be.args())?; + return Ok(ty::Const::new_expr(tcx, ty::Expr::new(ae.kind, args), a.ty())); } _ => false, }; diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 90791bdd20dc..7a291b4dbff6 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -147,14 +147,27 @@ impl<'tcx> DebugWithInfcx> for ty::consts::Expr<'tcx> { this: WithInfcx<'_, Infcx, &Self>, f: &mut core::fmt::Formatter<'_>, ) -> core::fmt::Result { - match this.data { - ty::Expr::Binop(op, lhs, rhs) => { - write!(f, "({op:?}: {:?}, {:?})", &this.wrap(lhs), &this.wrap(rhs)) + match this.data.kind { + ty::ExprKind::Binop(op) => { + let (lhs_ty, rhs_ty, lhs, rhs) = this.data.binop_args(); + write!( + f, + "({op:?}: ({:?}: {:?}), ({:?}: {:?}))", + &this.wrap(lhs), + &this.wrap(lhs_ty), + &this.wrap(rhs), + &this.wrap(rhs_ty), + ) } - ty::Expr::UnOp(op, rhs) => write!(f, "({op:?}: {:?})", &this.wrap(rhs)), - ty::Expr::FunctionCall(func, args) => { - write!(f, "{:?}(", &this.wrap(func))?; - for arg in args.as_slice().iter().rev().skip(1).rev() { + ty::ExprKind::UnOp(op) => { + let (rhs_ty, rhs) = this.data.unop_args(); + write!(f, "({op:?}: ({:?}: {:?}))", &this.wrap(rhs), &this.wrap(rhs_ty)) + } + ty::ExprKind::FunctionCall => { + let (func_ty, func, args) = this.data.call_args(); + let args = args.collect::>(); + write!(f, "({:?}: {:?})(", &this.wrap(func), &this.wrap(func_ty))?; + for arg in args.iter().rev().skip(1).rev() { write!(f, "{:?}, ", &this.wrap(arg))?; } if let Some(arg) = args.last() { @@ -163,8 +176,15 @@ impl<'tcx> DebugWithInfcx> for ty::consts::Expr<'tcx> { write!(f, ")") } - ty::Expr::Cast(cast_kind, lhs, rhs) => { - write!(f, "({cast_kind:?}: {:?}, {:?})", &this.wrap(lhs), &this.wrap(rhs)) + ty::ExprKind::Cast(kind) => { + let (value_ty, value, to_ty) = this.data.cast_args(); + write!( + f, + "({kind:?}: ({:?}: {:?}), {:?})", + &this.wrap(value), + &this.wrap(value_ty), + &this.wrap(to_ty) + ) } } } diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs index a9421aacff83..58f69d772ecb 100644 --- a/compiler/rustc_middle/src/ty/walk.rs +++ b/compiler/rustc_middle/src/ty/walk.rs @@ -222,24 +222,7 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) | ty::ConstKind::Value(_) | ty::ConstKind::Error(_) => {} - ty::ConstKind::Expr(expr) => match expr { - ty::Expr::UnOp(_, v) => push_inner(stack, v.into()), - ty::Expr::Binop(_, l, r) => { - push_inner(stack, r.into()); - push_inner(stack, l.into()) - } - ty::Expr::FunctionCall(func, args) => { - for a in args.iter().rev() { - push_inner(stack, a.into()); - } - push_inner(stack, func.into()); - } - ty::Expr::Cast(_, c, t) => { - push_inner(stack, t.into()); - push_inner(stack, c.into()); - } - }, - + ty::ConstKind::Expr(expr) => stack.extend(expr.args().iter().rev()), ty::ConstKind::Unevaluated(ct) => { stack.extend(ct.args.iter().rev()); } diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs index e9112d232cbd..8a42298f2164 100644 --- a/compiler/rustc_ty_utils/src/consts.rs +++ b/compiler/rustc_ty_utils/src/consts.rs @@ -148,17 +148,24 @@ fn recurse_build<'tcx>( for &id in args.iter() { new_args.push(recurse_build(tcx, body, id, root_span)?); } - let new_args = tcx.mk_const_list(&new_args); - ty::Const::new_expr(tcx, Expr::FunctionCall(fun, new_args), node.ty) + ty::Const::new_expr( + tcx, + Expr::new_call(tcx, fun.ty(), fun, new_args.into_iter()), + node.ty, + ) } &ExprKind::Binary { op, lhs, rhs } if check_binop(op) => { let lhs = recurse_build(tcx, body, lhs, root_span)?; let rhs = recurse_build(tcx, body, rhs, root_span)?; - ty::Const::new_expr(tcx, Expr::Binop(op, lhs, rhs), node.ty) + ty::Const::new_expr( + tcx, + Expr::new_binop(tcx, op, lhs.ty(), rhs.ty(), lhs, rhs), + node.ty, + ) } &ExprKind::Unary { op, arg } if check_unop(op) => { let arg = recurse_build(tcx, body, arg, root_span)?; - ty::Const::new_expr(tcx, Expr::UnOp(op, arg), node.ty) + ty::Const::new_expr(tcx, Expr::new_unop(tcx, op, arg.ty(), arg), node.ty) } // This is necessary so that the following compiles: // @@ -178,12 +185,22 @@ fn recurse_build<'tcx>( // "coercion cast" i.e. using a coercion or is a no-op. // This is important so that `N as usize as usize` doesn't unify with `N as usize`. (untested) &ExprKind::Use { source } => { - let arg = recurse_build(tcx, body, source, root_span)?; - ty::Const::new_expr(tcx, Expr::Cast(CastKind::Use, arg, node.ty), node.ty) + let value_ty = body.exprs[source].ty; + let value = recurse_build(tcx, body, source, root_span)?; + ty::Const::new_expr( + tcx, + Expr::new_cast(tcx, CastKind::Use, value_ty, value, node.ty), + node.ty, + ) } &ExprKind::Cast { source } => { - let arg = recurse_build(tcx, body, source, root_span)?; - ty::Const::new_expr(tcx, Expr::Cast(CastKind::As, arg, node.ty), node.ty) + let value_ty = body.exprs[source].ty; + let value = recurse_build(tcx, body, source, root_span)?; + ty::Const::new_expr( + tcx, + Expr::new_cast(tcx, CastKind::As, value_ty, value, node.ty), + node.ty, + ) } ExprKind::Borrow { arg, .. } => { let arg_node = &body.exprs[*arg]; From 7e08f80b34608e4aac2fcce1d9e85735b02034fe Mon Sep 17 00:00:00 2001 From: Boxy Date: Tue, 4 Jun 2024 00:39:35 +0100 Subject: [PATCH 209/211] Split smir `Const` into `TyConst` and `MirConst` --- .../rustc_smir/src/rustc_internal/internal.rs | 44 ++++----- compiler/rustc_smir/src/rustc_internal/mod.rs | 3 +- compiler/rustc_smir/src/rustc_smir/context.rs | 59 +++++++++--- .../rustc_smir/src/rustc_smir/convert/mir.rs | 20 ++-- .../rustc_smir/src/rustc_smir/convert/mod.rs | 2 + .../rustc_smir/src/rustc_smir/convert/ty.rs | 74 +++++++++++---- compiler/rustc_smir/src/rustc_smir/mod.rs | 13 ++- compiler/stable_mir/src/compiler_interface.rs | 22 +++-- compiler/stable_mir/src/mir/body.rs | 10 +- compiler/stable_mir/src/mir/pretty.rs | 16 ++-- compiler/stable_mir/src/mir/visit.rs | 25 +++-- compiler/stable_mir/src/ty.rs | 95 +++++++++++++------ compiler/stable_mir/src/visitor.rs | 30 +++++- .../ui-fulldeps/stable-mir/check_transform.rs | 6 +- 14 files changed, 285 insertions(+), 134 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs index 6ec710f97d16..edfd48ed43b1 100644 --- a/compiler/rustc_smir/src/rustc_internal/internal.rs +++ b/compiler/rustc_smir/src/rustc_internal/internal.rs @@ -5,17 +5,17 @@ // Prefer importing stable_mir over internal rustc constructs to make this file more readable. use crate::rustc_smir::Tables; -use rustc_middle::ty::{self as rustc_ty, Ty as InternalTy, TyCtxt}; +use rustc_middle::ty::{self as rustc_ty, Const as InternalConst, Ty as InternalTy, TyCtxt}; use rustc_span::Symbol; use stable_mir::abi::Layout; use stable_mir::mir::alloc::AllocId; use stable_mir::mir::mono::{Instance, MonoItem, StaticDef}; use stable_mir::mir::{BinOp, Mutability, Place, ProjectionElem, Safety, UnOp}; use stable_mir::ty::{ - Abi, AdtDef, Binder, BoundRegionKind, BoundTyKind, BoundVariableKind, ClosureKind, Const, - DynKind, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FloatTy, FnSig, - GenericArgKind, GenericArgs, IndexedVal, IntTy, Movability, Pattern, Region, RigidTy, Span, - TermKind, TraitRef, Ty, UintTy, VariantDef, VariantIdx, + Abi, AdtDef, Binder, BoundRegionKind, BoundTyKind, BoundVariableKind, ClosureKind, DynKind, + ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FloatTy, FnSig, + GenericArgKind, GenericArgs, IndexedVal, IntTy, MirConst, Movability, Pattern, Region, RigidTy, + Span, TermKind, TraitRef, Ty, TyConst, UintTy, VariantDef, VariantIdx, }; use stable_mir::{CrateItem, CrateNum, DefId}; @@ -55,7 +55,7 @@ impl RustcInternal for GenericArgKind { let arg: rustc_ty::GenericArg<'tcx> = match self { GenericArgKind::Lifetime(reg) => reg.internal(tables, tcx).into(), GenericArgKind::Type(ty) => ty.internal(tables, tcx).into(), - GenericArgKind::Const(cnst) => ty_const(cnst, tables, tcx).into(), + GenericArgKind::Const(cnst) => cnst.internal(tables, tcx).into(), }; tcx.lift(arg).unwrap() } @@ -76,13 +76,20 @@ impl RustcInternal for Ty { } } +impl RustcInternal for TyConst { + type T<'tcx> = InternalConst<'tcx>; + fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> { + tcx.lift(tables.ty_consts[self.id]).unwrap() + } +} + impl RustcInternal for Pattern { type T<'tcx> = rustc_ty::Pattern<'tcx>; fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> { tcx.mk_pat(match self { Pattern::Range { start, end, include_end } => rustc_ty::PatternKind::Range { - start: start.as_ref().map(|c| ty_const(c, tables, tcx)), - end: end.as_ref().map(|c| ty_const(c, tables, tcx)), + start: start.as_ref().map(|c| c.internal(tables, tcx)), + end: end.as_ref().map(|c| c.internal(tables, tcx)), include_end: *include_end, }, }) @@ -101,7 +108,7 @@ impl RustcInternal for RigidTy { RigidTy::Float(float_ty) => rustc_ty::TyKind::Float(float_ty.internal(tables, tcx)), RigidTy::Never => rustc_ty::TyKind::Never, RigidTy::Array(ty, cnst) => { - rustc_ty::TyKind::Array(ty.internal(tables, tcx), ty_const(cnst, tables, tcx)) + rustc_ty::TyKind::Array(ty.internal(tables, tcx), cnst.internal(tables, tcx)) } RigidTy::Pat(ty, pat) => { rustc_ty::TyKind::Pat(ty.internal(tables, tcx), pat.internal(tables, tcx)) @@ -239,23 +246,10 @@ impl RustcInternal for VariantDef { } } -fn ty_const<'tcx>( - constant: &Const, - tables: &mut Tables<'_>, - tcx: TyCtxt<'tcx>, -) -> rustc_ty::Const<'tcx> { - match constant.internal(tables, tcx) { - rustc_middle::mir::Const::Ty(c) => c, - cnst => { - panic!("Trying to convert constant `{constant:?}` to type constant, but found {cnst:?}") - } - } -} - -impl RustcInternal for Const { +impl RustcInternal for MirConst { type T<'tcx> = rustc_middle::mir::Const<'tcx>; fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> { - let constant = tables.constants[self.id]; + let constant = tables.mir_consts[self.id]; match constant { rustc_middle::mir::Const::Ty(ty) => rustc_middle::mir::Const::Ty(tcx.lift(ty).unwrap()), rustc_middle::mir::Const::Unevaluated(uneval, ty) => { @@ -392,7 +386,7 @@ impl RustcInternal for TermKind { fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> { match self { TermKind::Type(ty) => ty.internal(tables, tcx).into(), - TermKind::Const(const_) => ty_const(const_, tables, tcx).into(), + TermKind::Const(cnst) => cnst.internal(tables, tcx).into(), } } } diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index 6e870728bafc..810ffc142a09 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -214,7 +214,8 @@ where spans: IndexMap::default(), types: IndexMap::default(), instances: IndexMap::default(), - constants: IndexMap::default(), + ty_consts: IndexMap::default(), + mir_consts: IndexMap::default(), layouts: IndexMap::default(), })); stable_mir::compiler_interface::run(&tables, || init(&tables, f)) diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index fa7b2a30ba6c..9822ed79e2bd 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -6,7 +6,6 @@ #![allow(rustc::usage_of_qualified_ty)] use rustc_abi::HasDataLayout; -use rustc_middle::ty; use rustc_middle::ty::layout::{ FnAbiOf, FnAbiOfHelpers, HasParamEnv, HasTyCtxt, LayoutOf, LayoutOfHelpers, }; @@ -14,6 +13,7 @@ use rustc_middle::ty::print::{with_forced_trimmed_paths, with_no_trimmed_paths}; use rustc_middle::ty::{ GenericPredicates, Instance, List, ParamEnv, ScalarInt, TyCtxt, TypeVisitableExt, ValTree, }; +use rustc_middle::{mir, ty}; use rustc_span::def_id::LOCAL_CRATE; use stable_mir::abi::{FnAbi, Layout, LayoutShape}; use stable_mir::compiler_interface::Context; @@ -22,9 +22,9 @@ use stable_mir::mir::mono::{InstanceDef, StaticDef}; use stable_mir::mir::{BinOp, Body, Place, UnOp}; use stable_mir::target::{MachineInfo, MachineSize}; use stable_mir::ty::{ - AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FieldDef, FnDef, ForeignDef, - ForeignItemKind, GenericArgs, IntrinsicDef, LineInfo, PolyFnSig, RigidTy, Span, Ty, TyKind, - UintTy, VariantDef, + AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, FieldDef, FnDef, ForeignDef, + ForeignItemKind, GenericArgs, IntrinsicDef, LineInfo, MirConst, PolyFnSig, RigidTy, Span, Ty, + TyConst, TyKind, UintTy, VariantDef, }; use stable_mir::{Crate, CrateDef, CrateItem, CrateNum, DefId, Error, Filename, ItemKind, Symbol}; use std::cell::RefCell; @@ -360,7 +360,15 @@ impl<'tcx> Context for TablesWrapper<'tcx> { def.internal(&mut *tables, tcx).fields.iter().map(|f| f.stable(&mut *tables)).collect() } - fn eval_target_usize(&self, cnst: &Const) -> Result { + fn eval_target_usize(&self, cnst: &MirConst) -> Result { + let mut tables = self.0.borrow_mut(); + let tcx = tables.tcx; + let mir_const = cnst.internal(&mut *tables, tcx); + mir_const + .try_eval_target_usize(tables.tcx, ParamEnv::empty()) + .ok_or_else(|| Error::new(format!("Const `{cnst:?}` cannot be encoded as u64"))) + } + fn eval_target_usize_ty(&self, cnst: &TyConst) -> Result { let mut tables = self.0.borrow_mut(); let tcx = tables.tcx; let mir_const = cnst.internal(&mut *tables, tcx); @@ -369,7 +377,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> { .ok_or_else(|| Error::new(format!("Const `{cnst:?}` cannot be encoded as u64"))) } - fn try_new_const_zst(&self, ty: Ty) -> Result { + fn try_new_const_zst(&self, ty: Ty) -> Result { let mut tables = self.0.borrow_mut(); let tcx = tables.tcx; let ty_internal = ty.internal(&mut *tables, tcx); @@ -390,25 +398,45 @@ impl<'tcx> Context for TablesWrapper<'tcx> { ))); } - Ok(ty::Const::zero_sized(tables.tcx, ty_internal).stable(&mut *tables)) + Ok(mir::Const::Ty(ty::Const::zero_sized(tables.tcx, ty_internal)).stable(&mut *tables)) } - fn new_const_str(&self, value: &str) -> Const { + fn new_const_str(&self, value: &str) -> MirConst { let mut tables = self.0.borrow_mut(); let tcx = tables.tcx; let ty = ty::Ty::new_static_str(tcx); let bytes = value.as_bytes(); let val_tree = ty::ValTree::from_raw_bytes(tcx, bytes); - ty::Const::new_value(tcx, val_tree, ty).stable(&mut *tables) + let ct = ty::Const::new_value(tcx, val_tree, ty); + super::convert::mir_const_from_ty_const(&mut *tables, ct, ty) } - fn new_const_bool(&self, value: bool) -> Const { + fn new_const_bool(&self, value: bool) -> MirConst { let mut tables = self.0.borrow_mut(); - ty::Const::from_bool(tables.tcx, value).stable(&mut *tables) + let ct = ty::Const::from_bool(tables.tcx, value); + let ty = tables.tcx.types.bool; + super::convert::mir_const_from_ty_const(&mut *tables, ct, ty) } - fn try_new_const_uint(&self, value: u128, uint_ty: UintTy) -> Result { + fn try_new_const_uint(&self, value: u128, uint_ty: UintTy) -> Result { + let mut tables = self.0.borrow_mut(); + let tcx = tables.tcx; + let ty = ty::Ty::new_uint(tcx, uint_ty.internal(&mut *tables, tcx)); + let size = tables.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap().size; + + // We don't use Const::from_bits since it doesn't have any error checking. + let scalar = ScalarInt::try_from_uint(value, size).ok_or_else(|| { + Error::new(format!("Value overflow: cannot convert `{value}` to `{ty}`.")) + })?; + let ct = ty::Const::new_value(tables.tcx, ValTree::from_scalar_int(scalar), ty); + Ok(super::convert::mir_const_from_ty_const(&mut *tables, ct, ty)) + } + fn try_new_ty_const_uint( + &self, + value: u128, + uint_ty: UintTy, + ) -> Result { let mut tables = self.0.borrow_mut(); let tcx = tables.tcx; let ty = ty::Ty::new_uint(tcx, uint_ty.internal(&mut *tables, tcx)); @@ -453,7 +481,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> { .stable(&mut *tables) } - fn const_pretty(&self, cnst: &stable_mir::ty::Const) -> String { + fn mir_const_pretty(&self, cnst: &stable_mir::ty::MirConst) -> String { let mut tables = self.0.borrow_mut(); let tcx = tables.tcx; cnst.internal(&mut *tables, tcx).to_string() @@ -474,6 +502,11 @@ impl<'tcx> Context for TablesWrapper<'tcx> { tables.types[ty].kind().stable(&mut *tables) } + fn ty_const_pretty(&self, ct: stable_mir::ty::TyConstId) -> String { + let tables = self.0.borrow_mut(); + tables.ty_consts[ct].to_string() + } + fn rigid_ty_discriminant_ty(&self, ty: &RigidTy) -> stable_mir::ty::Ty { let mut tables = self.0.borrow_mut(); let tcx = tables.tcx; diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs index a1a5c09ef0af..1c87293209c6 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs @@ -6,7 +6,7 @@ use rustc_middle::mir::interpret::alloc_range; use rustc_middle::mir::mono::MonoItem; use stable_mir::mir::alloc::GlobalAlloc; use stable_mir::mir::{ConstOperand, Statement, UserTypeProjection, VarDebugInfoFragment}; -use stable_mir::ty::{Allocation, Const, ConstantKind}; +use stable_mir::ty::{Allocation, ConstantKind, MirConst}; use stable_mir::{opaque, Error}; use crate::rustc_smir::{alloc, Stable, Tables}; @@ -724,11 +724,16 @@ impl<'tcx> Stable<'tcx> for mir::interpret::GlobalAlloc<'tcx> { } impl<'tcx> Stable<'tcx> for rustc_middle::mir::Const<'tcx> { - type T = stable_mir::ty::Const; + type T = stable_mir::ty::MirConst; fn stable(&self, tables: &mut Tables<'_>) -> Self::T { + let id = tables.intern_mir_const(tables.tcx.lift(*self).unwrap()); match *self { - mir::Const::Ty(c) => c.stable(tables), + mir::Const::Ty(c) => MirConst::new( + stable_mir::ty::ConstantKind::Ty(c.stable(tables)), + c.ty().stable(tables), + id, + ), mir::Const::Unevaluated(unev_const, ty) => { let kind = stable_mir::ty::ConstantKind::Unevaluated(stable_mir::ty::UnevaluatedConst { @@ -737,21 +742,18 @@ impl<'tcx> Stable<'tcx> for rustc_middle::mir::Const<'tcx> { promoted: unev_const.promoted.map(|u| u.as_u32()), }); let ty = ty.stable(tables); - let id = tables.intern_const(tables.tcx.lift(*self).unwrap()); - Const::new(kind, ty, id) + MirConst::new(kind, ty, id) } mir::Const::Val(mir::ConstValue::ZeroSized, ty) => { let ty = ty.stable(tables); - let id = tables.intern_const(tables.tcx.lift(*self).unwrap()); - Const::new(ConstantKind::ZeroSized, ty, id) + MirConst::new(ConstantKind::ZeroSized, ty, id) } mir::Const::Val(val, ty) => { let ty = tables.tcx.lift(ty).unwrap(); let val = tables.tcx.lift(val).unwrap(); let kind = ConstantKind::Allocated(alloc::new_allocation(ty, val, tables)); let ty = ty.stable(tables); - let id = tables.intern_const(tables.tcx.lift(*self).unwrap()); - Const::new(kind, ty, id) + MirConst::new(kind, ty, id) } } } diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mod.rs b/compiler/rustc_smir/src/rustc_smir/convert/mod.rs index 736378a530f0..50687935473a 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mod.rs @@ -9,6 +9,8 @@ mod error; mod mir; mod ty; +pub use ty::mir_const_from_ty_const; + impl<'tcx> Stable<'tcx> for rustc_hir::Safety { type T = stable_mir::mir::Safety; fn stable(&self, _: &mut Tables<'_>) -> Self::T { diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index 66708def00f1..1f3356f579fe 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -3,8 +3,7 @@ use rustc_middle::ty::Ty; use rustc_middle::{mir, ty}; use stable_mir::ty::{ - AdtKind, Const, ConstantKind, FloatTy, GenericArgs, GenericParamDef, IntTy, Region, RigidTy, - TyKind, UintTy, + AdtKind, FloatTy, GenericArgs, GenericParamDef, IntTy, Region, RigidTy, TyKind, UintTy, }; use crate::rustc_smir::{alloc, Stable, Tables}; @@ -410,8 +409,50 @@ impl<'tcx> Stable<'tcx> for ty::Pattern<'tcx> { } } +pub fn mir_const_from_ty_const<'tcx>( + tables: &mut Tables<'tcx>, + ty_const: ty::Const<'tcx>, + ty: Ty<'tcx>, +) -> stable_mir::ty::MirConst { + let kind = match ty_const.kind() { + ty::Value(val) => { + let val = match val { + ty::ValTree::Leaf(scalar) => ty::ValTree::Leaf(scalar), + ty::ValTree::Branch(branch) => { + ty::ValTree::Branch(tables.tcx.lift(branch).unwrap()) + } + }; + let ty = tables.tcx.lift(ty).unwrap(); + let const_val = tables.tcx.valtree_to_const_val((ty, val)); + if matches!(const_val, mir::ConstValue::ZeroSized) { + stable_mir::ty::ConstantKind::ZeroSized + } else { + stable_mir::ty::ConstantKind::Allocated(alloc::new_allocation( + ty, const_val, tables, + )) + } + } + ty::ParamCt(param) => stable_mir::ty::ConstantKind::Param(param.stable(tables)), + ty::ErrorCt(_) => unreachable!(), + ty::InferCt(_) => unreachable!(), + ty::BoundCt(_, _) => unimplemented!(), + ty::PlaceholderCt(_) => unimplemented!(), + ty::Unevaluated(uv) => { + stable_mir::ty::ConstantKind::Unevaluated(stable_mir::ty::UnevaluatedConst { + def: tables.const_def(uv.def), + args: uv.args.stable(tables), + promoted: None, + }) + } + ty::ExprCt(_) => unimplemented!(), + }; + let stable_ty = tables.intern_ty(ty); + let id = tables.intern_mir_const(mir::Const::Ty(ty_const)); + stable_mir::ty::MirConst::new(kind, stable_ty, id) +} + impl<'tcx> Stable<'tcx> for ty::Const<'tcx> { - type T = stable_mir::ty::Const; + type T = stable_mir::ty::TyConst; fn stable(&self, tables: &mut Tables<'_>) -> Self::T { let kind = match self.kind() { @@ -425,30 +466,27 @@ impl<'tcx> Stable<'tcx> for ty::Const<'tcx> { let ty = tables.tcx.lift(self.ty()).unwrap(); let const_val = tables.tcx.valtree_to_const_val((ty, val)); if matches!(const_val, mir::ConstValue::ZeroSized) { - ConstantKind::ZeroSized + stable_mir::ty::TyConstKind::ZSTValue(ty.stable(tables)) } else { - stable_mir::ty::ConstantKind::Allocated(alloc::new_allocation( - ty, const_val, tables, - )) + stable_mir::ty::TyConstKind::Value( + ty.stable(tables), + alloc::new_allocation(ty, const_val, tables), + ) } } - ty::ParamCt(param) => stable_mir::ty::ConstantKind::Param(param.stable(tables)), + ty::ParamCt(param) => stable_mir::ty::TyConstKind::Param(param.stable(tables)), + ty::Unevaluated(uv) => stable_mir::ty::TyConstKind::Unevaluated( + tables.const_def(uv.def), + uv.args.stable(tables), + ), ty::ErrorCt(_) => unreachable!(), ty::InferCt(_) => unreachable!(), ty::BoundCt(_, _) => unimplemented!(), ty::PlaceholderCt(_) => unimplemented!(), - ty::Unevaluated(uv) => { - stable_mir::ty::ConstantKind::Unevaluated(stable_mir::ty::UnevaluatedConst { - def: tables.const_def(uv.def), - args: uv.args.stable(tables), - promoted: None, - }) - } ty::ExprCt(_) => unimplemented!(), }; - let ty = self.ty().stable(tables); - let id = tables.intern_const(mir::Const::Ty(tables.tcx.lift(*self).unwrap())); - Const::new(kind, ty, id) + let id = tables.intern_ty_const(tables.tcx.lift(*self).unwrap()); + stable_mir::ty::TyConst::new(kind, id) } } diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index aba7e7dc9c21..d13e78033263 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -14,7 +14,7 @@ use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE}; use stable_mir::abi::Layout; use stable_mir::mir::mono::InstanceDef; -use stable_mir::ty::{ConstId, Span}; +use stable_mir::ty::{MirConstId, Span, TyConstId}; use stable_mir::{CtorKind, ItemKind}; use std::ops::RangeInclusive; use tracing::debug; @@ -33,7 +33,8 @@ pub struct Tables<'tcx> { pub(crate) spans: IndexMap, pub(crate) types: IndexMap, stable_mir::ty::Ty>, pub(crate) instances: IndexMap, InstanceDef>, - pub(crate) constants: IndexMap, ConstId>, + pub(crate) ty_consts: IndexMap, TyConstId>, + pub(crate) mir_consts: IndexMap, MirConstId>, pub(crate) layouts: IndexMap, Layout>, } @@ -42,8 +43,12 @@ impl<'tcx> Tables<'tcx> { self.types.create_or_fetch(ty) } - pub(crate) fn intern_const(&mut self, constant: mir::Const<'tcx>) -> ConstId { - self.constants.create_or_fetch(constant) + pub(crate) fn intern_ty_const(&mut self, ct: ty::Const<'tcx>) -> TyConstId { + self.ty_consts.create_or_fetch(ct) + } + + pub(crate) fn intern_mir_const(&mut self, constant: mir::Const<'tcx>) -> MirConstId { + self.mir_consts.create_or_fetch(constant) } pub(crate) fn has_body(&self, instance: Instance<'tcx>) -> bool { diff --git a/compiler/stable_mir/src/compiler_interface.rs b/compiler/stable_mir/src/compiler_interface.rs index 858ce5301d84..085dfd9ea890 100644 --- a/compiler/stable_mir/src/compiler_interface.rs +++ b/compiler/stable_mir/src/compiler_interface.rs @@ -11,10 +11,10 @@ use crate::mir::mono::{Instance, InstanceDef, StaticDef}; use crate::mir::{BinOp, Body, Place, UnOp}; use crate::target::MachineInfo; use crate::ty::{ - AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FieldDef, FnDef, ForeignDef, + AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, FieldDef, FnDef, ForeignDef, ForeignItemKind, ForeignModule, ForeignModuleDef, GenericArgs, GenericPredicates, Generics, - ImplDef, ImplTrait, IntrinsicDef, LineInfo, PolyFnSig, RigidTy, Span, TraitDecl, TraitDef, Ty, - TyKind, UintTy, VariantDef, + ImplDef, ImplTrait, IntrinsicDef, LineInfo, MirConst, PolyFnSig, RigidTy, Span, TraitDecl, + TraitDef, Ty, TyConst, TyConstId, TyKind, UintTy, VariantDef, }; use crate::{ mir, Crate, CrateItem, CrateItems, CrateNum, DefId, Error, Filename, ImplTraitDecls, ItemKind, @@ -109,19 +109,21 @@ pub trait Context { fn variant_fields(&self, def: VariantDef) -> Vec; /// Evaluate constant as a target usize. - fn eval_target_usize(&self, cnst: &Const) -> Result; + fn eval_target_usize(&self, cnst: &MirConst) -> Result; + fn eval_target_usize_ty(&self, cnst: &TyConst) -> Result; /// Create a new zero-sized constant. - fn try_new_const_zst(&self, ty: Ty) -> Result; + fn try_new_const_zst(&self, ty: Ty) -> Result; /// Create a new constant that represents the given string value. - fn new_const_str(&self, value: &str) -> Const; + fn new_const_str(&self, value: &str) -> MirConst; /// Create a new constant that represents the given boolean value. - fn new_const_bool(&self, value: bool) -> Const; + fn new_const_bool(&self, value: bool) -> MirConst; /// Create a new constant that represents the given value. - fn try_new_const_uint(&self, value: u128, uint_ty: UintTy) -> Result; + fn try_new_const_uint(&self, value: u128, uint_ty: UintTy) -> Result; + fn try_new_ty_const_uint(&self, value: u128, uint_ty: UintTy) -> Result; /// Create a new type from the given kind. fn new_rigid_ty(&self, kind: RigidTy) -> Ty; @@ -136,11 +138,13 @@ pub trait Context { fn def_ty_with_args(&self, item: DefId, args: &GenericArgs) -> Ty; /// Returns literal value of a const as a string. - fn const_pretty(&self, cnst: &Const) -> String; + fn mir_const_pretty(&self, cnst: &MirConst) -> String; /// `Span` of an item fn span_of_an_item(&self, def_id: DefId) -> Span; + fn ty_const_pretty(&self, ct: TyConstId) -> String; + /// Obtain the representation of a type. fn ty_pretty(&self, ty: Ty) -> String; diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs index 4c779ae96a81..43e4682dc100 100644 --- a/compiler/stable_mir/src/mir/body.rs +++ b/compiler/stable_mir/src/mir/body.rs @@ -1,8 +1,8 @@ use crate::compiler_interface::with; use crate::mir::pretty::function_body; use crate::ty::{ - AdtDef, ClosureDef, Const, CoroutineDef, GenericArgs, Movability, Region, RigidTy, Ty, TyKind, - VariantIdx, + AdtDef, ClosureDef, CoroutineDef, GenericArgs, MirConst, Movability, Region, RigidTy, Ty, + TyConst, TyKind, VariantIdx, }; use crate::{Error, Opaque, Span, Symbol}; use std::io; @@ -524,7 +524,7 @@ pub enum Rvalue { /// Corresponds to source code like `[x; 32]`. /// /// [#74836]: https://github.com/rust-lang/rust/issues/74836 - Repeat(Operand, Const), + Repeat(Operand, TyConst), /// Transmutes a `*mut u8` into shallow-initialized `Box`. /// @@ -718,7 +718,7 @@ pub enum VarDebugInfoContents { pub struct ConstOperand { pub span: Span, pub user_ty: Option, - pub const_: Const, + pub const_: MirConst, } // In MIR ProjectionElem is parameterized on the second Field argument and the Index argument. This @@ -833,7 +833,7 @@ type UserTypeAnnotationIndex = usize; pub struct Constant { pub span: Span, pub user_ty: Option, - pub literal: Const, + pub literal: MirConst, } /// The possible branch sites of a [TerminatorKind::SwitchInt]. diff --git a/compiler/stable_mir/src/mir/pretty.rs b/compiler/stable_mir/src/mir/pretty.rs index 580dc1a2b88f..2fb180b84c7c 100644 --- a/compiler/stable_mir/src/mir/pretty.rs +++ b/compiler/stable_mir/src/mir/pretty.rs @@ -1,5 +1,5 @@ use crate::mir::{Operand, Place, Rvalue, StatementKind, UnwindAction, VarDebugInfoContents}; -use crate::ty::{Const, IndexedVal, Ty}; +use crate::ty::{IndexedVal, MirConst, Ty, TyConst}; use crate::{with, Body, Mutability}; use fmt::{Display, Formatter}; use std::fmt::Debug; @@ -46,7 +46,7 @@ pub(crate) fn function_body(writer: &mut W, body: &Body, name: &str) - VarDebugInfoContents::Place(place) => { format!("{place:?}") } - VarDebugInfoContents::Const(constant) => pretty_const(&constant.const_), + VarDebugInfoContents::Const(constant) => pretty_mir_const(&constant.const_), }; writeln!(writer, " debug {} => {};", info.name, content) })?; @@ -310,12 +310,16 @@ fn pretty_operand(operand: &Operand) -> String { Operand::Move(mv) => { format!("move {:?}", mv) } - Operand::Constant(cnst) => pretty_const(&cnst.literal), + Operand::Constant(cnst) => pretty_mir_const(&cnst.literal), } } -fn pretty_const(literal: &Const) -> String { - with(|cx| cx.const_pretty(literal)) +fn pretty_mir_const(literal: &MirConst) -> String { + with(|cx| cx.mir_const_pretty(literal)) +} + +fn pretty_ty_const(ct: &TyConst) -> String { + with(|cx| cx.ty_const_pretty(ct.id)) } fn pretty_rvalue(writer: &mut W, rval: &Rvalue) -> io::Result<()> { @@ -359,7 +363,7 @@ fn pretty_rvalue(writer: &mut W, rval: &Rvalue) -> io::Result<()> { write!(writer, "{kind}{:?}", place) } Rvalue::Repeat(op, cnst) => { - write!(writer, "{} \" \" {}", &pretty_operand(op), cnst.ty()) + write!(writer, "{} \" \" {}", &pretty_operand(op), &pretty_ty_const(cnst)) } Rvalue::ShallowInitBox(_, _) => Ok(()), Rvalue::ThreadLocalRef(item) => { diff --git a/compiler/stable_mir/src/mir/visit.rs b/compiler/stable_mir/src/mir/visit.rs index 24296e9e8778..10f30083dc2d 100644 --- a/compiler/stable_mir/src/mir/visit.rs +++ b/compiler/stable_mir/src/mir/visit.rs @@ -36,7 +36,7 @@ //! variant argument) that does not require visiting. use crate::mir::*; -use crate::ty::{Const, GenericArgs, Region, Ty}; +use crate::ty::{GenericArgs, MirConst, Region, Ty, TyConst}; use crate::{Error, Opaque, Span}; pub trait MirVisitor { @@ -112,8 +112,13 @@ pub trait MirVisitor { self.super_constant(constant, location) } - fn visit_const(&mut self, constant: &Const, location: Location) { - self.super_const(constant, location) + fn visit_mir_const(&mut self, constant: &MirConst, location: Location) { + self.super_mir_const(constant, location) + } + + fn visit_ty_const(&mut self, constant: &TyConst, location: Location) { + let _ = location; + self.super_ty_const(constant) } fn visit_region(&mut self, region: &Region, location: Location) { @@ -339,7 +344,7 @@ pub trait MirVisitor { } Rvalue::Repeat(op, constant) => { self.visit_operand(op, location); - self.visit_const(constant, location); + self.visit_ty_const(constant, location); } Rvalue::ShallowInitBox(op, ty) => { self.visit_ty(ty, location); @@ -378,14 +383,18 @@ pub trait MirVisitor { fn super_constant(&mut self, constant: &Constant, location: Location) { let Constant { span, user_ty: _, literal } = constant; self.visit_span(span); - self.visit_const(literal, location); + self.visit_mir_const(literal, location); } - fn super_const(&mut self, constant: &Const, location: Location) { - let Const { kind: _, ty, id: _ } = constant; + fn super_mir_const(&mut self, constant: &MirConst, location: Location) { + let MirConst { kind: _, ty, id: _ } = constant; self.visit_ty(ty, location); } + fn super_ty_const(&mut self, constant: &TyConst) { + let _ = constant; + } + fn super_region(&mut self, region: &Region) { let _ = region; } @@ -407,7 +416,7 @@ pub trait MirVisitor { self.visit_place(place, PlaceContext::NON_USE, location); } VarDebugInfoContents::Const(constant) => { - self.visit_const(&constant.const_, location); + self.visit_mir_const(&constant.const_, location); } } } diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs index 50bf0a5d74ef..bcbe87f7303b 100644 --- a/compiler/stable_mir/src/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -28,11 +28,11 @@ impl Ty { /// Create a new array type. pub fn try_new_array(elem_ty: Ty, size: u64) -> Result { - Ok(Ty::from_rigid_kind(RigidTy::Array(elem_ty, Const::try_from_target_usize(size)?))) + Ok(Ty::from_rigid_kind(RigidTy::Array(elem_ty, TyConst::try_from_target_usize(size)?))) } /// Create a new array type from Const length. - pub fn new_array_with_const_len(elem_ty: Ty, len: Const) -> Ty { + pub fn new_array_with_const_len(elem_ty: Ty, len: TyConst) -> Ty { Ty::from_rigid_kind(RigidTy::Array(elem_ty, len)) } @@ -101,24 +101,66 @@ impl Ty { /// Represents a pattern in the type system #[derive(Clone, Debug, Eq, PartialEq)] pub enum Pattern { - Range { start: Option, end: Option, include_end: bool }, + Range { start: Option, end: Option, include_end: bool }, } -/// Represents a constant in MIR or from the Type system. +/// Represents a constant in the type system #[derive(Clone, Debug, Eq, PartialEq)] -pub struct Const { +pub struct TyConst { + pub(crate) kind: TyConstKind, + pub id: TyConstId, +} + +impl TyConst { + pub fn new(kind: TyConstKind, id: TyConstId) -> TyConst { + Self { kind, id } + } + + /// Retrieve the constant kind. + pub fn kind(&self) -> &TyConstKind { + &self.kind + } + + /// Creates an interned usize constant. + fn try_from_target_usize(val: u64) -> Result { + with(|cx| cx.try_new_ty_const_uint(val.into(), UintTy::Usize)) + } + + /// Try to evaluate to a target `usize`. + pub fn eval_target_usize(&self) -> Result { + with(|cx| cx.eval_target_usize_ty(self)) + } +} + +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum TyConstKind { + Param(ParamConst), + Bound(DebruijnIndex, BoundVar), + Unevaluated(ConstDef, GenericArgs), + + // FIXME: These should be a valtree + Value(Ty, Allocation), + ZSTValue(Ty), +} + +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub struct TyConstId(usize); + +/// Represents a constant in MIR +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct MirConst { /// The constant kind. pub(crate) kind: ConstantKind, /// The constant type. pub(crate) ty: Ty, /// Used for internal tracking of the internal constant. - pub id: ConstId, + pub id: MirConstId, } -impl Const { +impl MirConst { /// Build a constant. Note that this should only be used by the compiler. - pub fn new(kind: ConstantKind, ty: Ty, id: ConstId) -> Const { - Const { kind, ty, id } + pub fn new(kind: ConstantKind, ty: Ty, id: MirConstId) -> MirConst { + MirConst { kind, ty, id } } /// Retrieve the constant kind. @@ -131,11 +173,6 @@ impl Const { self.ty } - /// Creates an interned usize constant. - fn try_from_target_usize(val: u64) -> Result { - with(|cx| cx.try_new_const_uint(val.into(), UintTy::Usize)) - } - /// Try to evaluate to a target `usize`. pub fn eval_target_usize(&self) -> Result { with(|cx| cx.eval_target_usize(self)) @@ -143,7 +180,7 @@ impl Const { /// Create a constant that represents a new zero-sized constant of type T. /// Fails if the type is not a ZST or if it doesn't have a known size. - pub fn try_new_zero_sized(ty: Ty) -> Result { + pub fn try_new_zero_sized(ty: Ty) -> Result { with(|cx| cx.try_new_const_zst(ty)) } @@ -152,23 +189,23 @@ impl Const { /// Note that there is no guarantee today about duplication of the same constant. /// I.e.: Calling this function multiple times with the same argument may or may not return /// the same allocation. - pub fn from_str(value: &str) -> Const { + pub fn from_str(value: &str) -> MirConst { with(|cx| cx.new_const_str(value)) } /// Build a new constant that represents the given boolean value. - pub fn from_bool(value: bool) -> Const { + pub fn from_bool(value: bool) -> MirConst { with(|cx| cx.new_const_bool(value)) } /// Build a new constant that represents the given unsigned integer. - pub fn try_from_uint(value: u128, uint_ty: UintTy) -> Result { + pub fn try_from_uint(value: u128, uint_ty: UintTy) -> Result { with(|cx| cx.try_new_const_uint(value, uint_ty)) } } #[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub struct ConstId(usize); +pub struct MirConstId(usize); type Ident = Opaque; @@ -484,7 +521,7 @@ pub enum RigidTy { Adt(AdtDef, GenericArgs), Foreign(ForeignDef), Str, - Array(Ty, Const), + Array(Ty, TyConst), Pat(Ty, Pattern), Slice(Ty), RawPtr(Ty, Mutability), @@ -866,7 +903,7 @@ impl std::ops::Index for GenericArgs { } impl std::ops::Index for GenericArgs { - type Output = Const; + type Output = TyConst; fn index(&self, index: ParamConst) -> &Self::Output { self.0[index.index as usize].expect_const() @@ -877,7 +914,7 @@ impl std::ops::Index for GenericArgs { pub enum GenericArgKind { Lifetime(Region), Type(Ty), - Const(Const), + Const(TyConst), } impl GenericArgKind { @@ -894,7 +931,7 @@ impl GenericArgKind { /// Panic if this generic argument is not a const, otherwise /// return the const. #[track_caller] - pub fn expect_const(&self) -> &Const { + pub fn expect_const(&self) -> &TyConst { match self { GenericArgKind::Const(c) => c, _ => panic!("{self:?}"), @@ -913,7 +950,7 @@ impl GenericArgKind { #[derive(Clone, Debug, Eq, PartialEq)] pub enum TermKind { Type(Ty), - Const(Const), + Const(TyConst), } #[derive(Clone, Debug, Eq, PartialEq)] @@ -1202,6 +1239,7 @@ impl Allocation { #[derive(Clone, Debug, Eq, PartialEq)] pub enum ConstantKind { + Ty(TyConst), Allocated(Allocation), Unevaluated(UnevaluatedConst), Param(ParamConst), @@ -1335,7 +1373,7 @@ pub enum PredicateKind { ObjectSafe(TraitDef), SubType(SubtypePredicate), Coerce(CoercePredicate), - ConstEquate(Const, Const), + ConstEquate(TyConst, TyConst), Ambiguous, AliasRelate(TermKind, TermKind, AliasRelationDirection), } @@ -1346,9 +1384,9 @@ pub enum ClauseKind { RegionOutlives(RegionOutlivesPredicate), TypeOutlives(TypeOutlivesPredicate), Projection(ProjectionPredicate), - ConstArgHasType(Const, Ty), + ConstArgHasType(TyConst, Ty), WellFormed(GenericArgKind), - ConstEvaluatable(Const), + ConstEvaluatable(TyConst), } #[derive(Clone, Debug, Eq, PartialEq)] @@ -1426,7 +1464,8 @@ macro_rules! index_impl { }; } -index_impl!(ConstId); +index_impl!(TyConstId); +index_impl!(MirConstId); index_impl!(Ty); index_impl!(Span); diff --git a/compiler/stable_mir/src/visitor.rs b/compiler/stable_mir/src/visitor.rs index 2d7159f87fec..fc1da8fafe48 100644 --- a/compiler/stable_mir/src/visitor.rs +++ b/compiler/stable_mir/src/visitor.rs @@ -1,10 +1,10 @@ use std::ops::ControlFlow; -use crate::Opaque; +use crate::{ty::TyConst, Opaque}; use super::ty::{ - Allocation, Binder, Const, ConstDef, ExistentialPredicate, FnSig, GenericArgKind, GenericArgs, - Promoted, Region, RigidTy, TermKind, Ty, UnevaluatedConst, + Allocation, Binder, ConstDef, ExistentialPredicate, FnSig, GenericArgKind, GenericArgs, + MirConst, Promoted, Region, RigidTy, TermKind, Ty, UnevaluatedConst, }; pub trait Visitor: Sized { @@ -12,7 +12,7 @@ pub trait Visitor: Sized { fn visit_ty(&mut self, ty: &Ty) -> ControlFlow { ty.super_visit(self) } - fn visit_const(&mut self, c: &Const) -> ControlFlow { + fn visit_const(&mut self, c: &TyConst) -> ControlFlow { c.super_visit(self) } fn visit_reg(&mut self, reg: &Region) -> ControlFlow { @@ -42,12 +42,32 @@ impl Visitable for Ty { } } -impl Visitable for Const { +impl Visitable for TyConst { fn visit(&self, visitor: &mut V) -> ControlFlow { visitor.visit_const(self) } + fn super_visit(&self, visitor: &mut V) -> ControlFlow { + match &self.kind { + crate::ty::TyConstKind::Param(_) => {} + crate::ty::TyConstKind::Bound(_, _) => {} + crate::ty::TyConstKind::Unevaluated(_, args) => args.visit(visitor)?, + crate::ty::TyConstKind::Value(ty, alloc) => { + alloc.visit(visitor)?; + ty.visit(visitor)?; + } + crate::ty::TyConstKind::ZSTValue(ty) => ty.visit(visitor)?, + } + ControlFlow::Continue(()) + } +} + +impl Visitable for MirConst { + fn visit(&self, visitor: &mut V) -> ControlFlow { + self.super_visit(visitor) + } fn super_visit(&self, visitor: &mut V) -> ControlFlow { match &self.kind() { + super::ty::ConstantKind::Ty(ct) => ct.visit(visitor)?, super::ty::ConstantKind::Allocated(alloc) => alloc.visit(visitor)?, super::ty::ConstantKind::Unevaluated(uv) => uv.visit(visitor)?, super::ty::ConstantKind::Param(_) | super::ty::ConstantKind::ZeroSized => {} diff --git a/tests/ui-fulldeps/stable-mir/check_transform.rs b/tests/ui-fulldeps/stable-mir/check_transform.rs index 6345ee24f789..b203e76e54f4 100644 --- a/tests/ui-fulldeps/stable-mir/check_transform.rs +++ b/tests/ui-fulldeps/stable-mir/check_transform.rs @@ -22,7 +22,7 @@ use rustc_smir::rustc_internal; use stable_mir::mir::alloc::GlobalAlloc; use stable_mir::mir::mono::Instance; use stable_mir::mir::{Body, Constant, Operand, Rvalue, StatementKind, TerminatorKind}; -use stable_mir::ty::{Const, ConstantKind}; +use stable_mir::ty::{ConstantKind, MirConst}; use stable_mir::{CrateDef, CrateItems, ItemKind}; use std::convert::TryFrom; use std::io::Write; @@ -77,7 +77,7 @@ fn check_msg(body: &Body, expected: &str) { }; assert_eq!(alloc.provenance.ptrs.len(), 1); - let alloc_prov_id = alloc.provenance.ptrs[0].1 .0; + let alloc_prov_id = alloc.provenance.ptrs[0].1.0; let GlobalAlloc::Memory(val) = GlobalAlloc::from(alloc_prov_id) else { unreachable!() }; @@ -95,7 +95,7 @@ fn change_panic_msg(mut body: Body, new_msg: &str) -> Body { for bb in &mut body.blocks { match &mut bb.terminator.kind { TerminatorKind::Call { args, .. } => { - let new_const = Const::from_str(new_msg); + let new_const = MirConst::from_str(new_msg); args[0] = Operand::Constant(Constant { literal: new_const, span: bb.terminator.span, From 67a73f265f6eb66f0804f467a640fee45301be73 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 4 Jun 2024 11:27:54 +0000 Subject: [PATCH 210/211] bless privacy tests (only diagnostic duplication) --- .../generic_const_exprs/eval-privacy.rs | 1 + .../generic_const_exprs/eval-privacy.stderr | 13 ++++++++++++- tests/ui/privacy/where-priv-type.rs | 1 + tests/ui/privacy/where-priv-type.stderr | 13 ++++++++++++- 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/tests/ui/const-generics/generic_const_exprs/eval-privacy.rs b/tests/ui/const-generics/generic_const_exprs/eval-privacy.rs index 8023b998a409..af17a37bf23a 100644 --- a/tests/ui/const-generics/generic_const_exprs/eval-privacy.rs +++ b/tests/ui/const-generics/generic_const_exprs/eval-privacy.rs @@ -15,6 +15,7 @@ where { type AssocTy = Const<{ my_const_fn(U) }>; //~^ ERROR private type + //~| ERROR private type fn assoc_fn() -> Self::AssocTy { Const } diff --git a/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr b/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr index 043fa34d605a..df0d43bef876 100644 --- a/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr +++ b/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr @@ -7,6 +7,17 @@ LL | type AssocTy = Const<{ my_const_fn(U) }>; LL | const fn my_const_fn(val: u8) -> u8 { | ----------------------------------- `fn(u8) -> u8 {my_const_fn}` declared as private -error: aborting due to 1 previous error +error[E0446]: private type `fn(u8) -> u8 {my_const_fn}` in public interface + --> $DIR/eval-privacy.rs:16:5 + | +LL | type AssocTy = Const<{ my_const_fn(U) }>; + | ^^^^^^^^^^^^ can't leak private type +... +LL | const fn my_const_fn(val: u8) -> u8 { + | ----------------------------------- `fn(u8) -> u8 {my_const_fn}` declared as private + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0446`. diff --git a/tests/ui/privacy/where-priv-type.rs b/tests/ui/privacy/where-priv-type.rs index cd9cce7ec3e8..a62feace2da2 100644 --- a/tests/ui/privacy/where-priv-type.rs +++ b/tests/ui/privacy/where-priv-type.rs @@ -74,6 +74,7 @@ where { type AssocTy = Const<{ my_const_fn(U) }>; //~^ ERROR private type + //~| ERROR private type fn assoc_fn() -> Self::AssocTy { Const } diff --git a/tests/ui/privacy/where-priv-type.stderr b/tests/ui/privacy/where-priv-type.stderr index 126330b14a63..8ea2e17c4361 100644 --- a/tests/ui/privacy/where-priv-type.stderr +++ b/tests/ui/privacy/where-priv-type.stderr @@ -77,6 +77,17 @@ LL | type AssocTy = Const<{ my_const_fn(U) }>; LL | const fn my_const_fn(val: u8) -> u8 { | ----------------------------------- `fn(u8) -> u8 {my_const_fn}` declared as private -error: aborting due to 1 previous error; 5 warnings emitted +error[E0446]: private type `fn(u8) -> u8 {my_const_fn}` in public interface + --> $DIR/where-priv-type.rs:75:5 + | +LL | type AssocTy = Const<{ my_const_fn(U) }>; + | ^^^^^^^^^^^^ can't leak private type +... +LL | const fn my_const_fn(val: u8) -> u8 { + | ----------------------------------- `fn(u8) -> u8 {my_const_fn}` declared as private + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 2 previous errors; 5 warnings emitted For more information about this error, try `rustc --explain E0446`. From c6073174ab1311fec27fb7ba5921c169656b1448 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Tue, 4 Jun 2024 23:33:35 +0000 Subject: [PATCH 211/211] std::unix::fs::get_mode implementation for illumos/solaris. they both support the F_GETFL fctnl flag/O_ACCMODE mask to get the file descriptor access modes. --- library/std/src/sys/pal/unix/fs.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs index a79a232e3d5b..dbaf86d73a61 100644 --- a/library/std/src/sys/pal/unix/fs.rs +++ b/library/std/src/sys/pal/unix/fs.rs @@ -1557,6 +1557,8 @@ impl fmt::Debug for File { target_os = "netbsd", target_os = "openbsd", target_os = "vxworks", + target_os = "solaris", + target_os = "illumos", target_vendor = "apple", ))] fn get_mode(fd: c_int) -> Option<(bool, bool)> { @@ -1579,6 +1581,8 @@ impl fmt::Debug for File { target_os = "netbsd", target_os = "openbsd", target_os = "vxworks", + target_os = "solaris", + target_os = "illumos", target_vendor = "apple", )))] fn get_mode(_fd: c_int) -> Option<(bool, bool)> {

` (where P is one of the previous types except `Self`) -ERROR rustc_hir_typeck::method::confirm Foo was a subtype of &Foo but now is not? + ERROR rustc_hir_typeck::method::confirm Foo was a subtype of &Foo but now is not? error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. 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 2e0566cad08e..17da1f524796 100644 --- a/tests/ui/traits/next-solver/issue-118950-root-region.stderr +++ b/tests/ui/traits/next-solver/issue-118950-root-region.stderr @@ -25,10 +25,10 @@ help: this trait has no implementations, consider adding one LL | trait ToUnit<'a> { | ^^^^^^^^^^^^^^^^ -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) } -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) } -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) } -WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) } + WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: AliasTy { args: ['^0.Named(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), "'a"), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) } error[E0119]: conflicting implementations of trait `Overlap` for type `fn(_)` --> $DIR/issue-118950-root-region.rs:19:1 | From 86cbabbb9d41c8e7bb3b4716e1bb224163532f4e Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 21 May 2024 18:16:47 +0000 Subject: [PATCH 098/211] add logging to search graph --- compiler/rustc_trait_selection/src/solve/search_graph.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_trait_selection/src/solve/search_graph.rs b/compiler/rustc_trait_selection/src/solve/search_graph.rs index f1b8bf4676ee..84878fea1013 100644 --- a/compiler/rustc_trait_selection/src/solve/search_graph.rs +++ b/compiler/rustc_trait_selection/src/solve/search_graph.rs @@ -281,6 +281,7 @@ impl<'tcx> SearchGraph> { }; if let Some(result) = self.lookup_global_cache(tcx, input, available_depth, inspect) { + debug!("global cache hit"); return result; } @@ -365,7 +366,7 @@ impl<'tcx> SearchGraph> { for _ in 0..FIXPOINT_STEP_LIMIT { match self.fixpoint_step_in_task(tcx, input, inspect, &mut prove_goal) { StepResult::Done(final_entry, result) => return (final_entry, result), - StepResult::HasChanged => {} + StepResult::HasChanged => debug!("fixpoint changed provisional results"), } } From aa8f995b89b939fa4e7528b42df36b1eeec4731d Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 24 May 2024 15:46:42 +0000 Subject: [PATCH 099/211] add info to rust-ldd tests failures --- tests/run-make/rust-lld-by-default/rmake.rs | 12 +++++++----- tests/run-make/rust-lld-custom-target/rmake.rs | 12 +++++++----- tests/run-make/rust-lld/rmake.rs | 17 ++++++++++------- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/tests/run-make/rust-lld-by-default/rmake.rs b/tests/run-make/rust-lld-by-default/rmake.rs index 6a8dae1043e3..b46988da5038 100644 --- a/tests/run-make/rust-lld-by-default/rmake.rs +++ b/tests/run-make/rust-lld-by-default/rmake.rs @@ -17,8 +17,9 @@ fn main() { .input("main.rs") .run(); assert!( - find_lld_version_in_logs(output), - "the LLD version string should be present in the output logs" + find_lld_version_in_logs(&output), + "the LLD version string should be present in the output logs:\n{}", + std::str::from_utf8(&output.stderr).unwrap() ); // But it can still be disabled by turning the linker feature off. @@ -29,12 +30,13 @@ fn main() { .input("main.rs") .run(); assert!( - !find_lld_version_in_logs(output), - "the LLD version string should not be present in the output logs" + !find_lld_version_in_logs(&output), + "the LLD version string should not be present in the output logs:\n{}", + std::str::from_utf8(&output.stderr).unwrap() ); } -fn find_lld_version_in_logs(output: Output) -> bool { +fn find_lld_version_in_logs(output: &Output) -> bool { let lld_version_re = Regex::new(r"^LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap(); let stderr = std::str::from_utf8(&output.stderr).unwrap(); stderr.lines().any(|line| lld_version_re.is_match(line)) diff --git a/tests/run-make/rust-lld-custom-target/rmake.rs b/tests/run-make/rust-lld-custom-target/rmake.rs index 9bdb69f47d8e..4eb858574634 100644 --- a/tests/run-make/rust-lld-custom-target/rmake.rs +++ b/tests/run-make/rust-lld-custom-target/rmake.rs @@ -23,8 +23,9 @@ fn main() { .input("lib.rs") .run(); assert!( - find_lld_version_in_logs(output), - "the LLD version string should be present in the output logs" + find_lld_version_in_logs(&output), + "the LLD version string should be present in the output logs:\n{}", + std::str::from_utf8(&output.stderr).unwrap() ); // But it can also be disabled via linker features. @@ -37,12 +38,13 @@ fn main() { .input("lib.rs") .run(); assert!( - !find_lld_version_in_logs(output), - "the LLD version string should not be present in the output logs" + !find_lld_version_in_logs(&output), + "the LLD version string should not be present in the output logs:\n{}", + std::str::from_utf8(&output.stderr).unwrap() ); } -fn find_lld_version_in_logs(output: Output) -> bool { +fn find_lld_version_in_logs(output: &Output) -> bool { let lld_version_re = Regex::new(r"^LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap(); let stderr = std::str::from_utf8(&output.stderr).unwrap(); stderr.lines().any(|line| lld_version_re.is_match(line)) diff --git a/tests/run-make/rust-lld/rmake.rs b/tests/run-make/rust-lld/rmake.rs index feeb82e709e1..e186bc700d3e 100644 --- a/tests/run-make/rust-lld/rmake.rs +++ b/tests/run-make/rust-lld/rmake.rs @@ -21,8 +21,9 @@ fn main() { .input("main.rs") .run(); assert!( - find_lld_version_in_logs(output), - "the LLD version string should be present in the output logs" + find_lld_version_in_logs(&output), + "the LLD version string should be present in the output logs:\n{}", + std::str::from_utf8(&output.stderr).unwrap() ); // It should not be used when we explictly opt-out of lld. @@ -33,8 +34,9 @@ fn main() { .input("main.rs") .run(); assert!( - !find_lld_version_in_logs(output), - "the LLD version string should not be present in the output logs" + !find_lld_version_in_logs(&output), + "the LLD version string should not be present in the output logs:\n{}", + std::str::from_utf8(&output.stderr).unwrap() ); // While we're here, also check that the last linker feature flag "wins" when passed multiple @@ -50,12 +52,13 @@ fn main() { .input("main.rs") .run(); assert!( - find_lld_version_in_logs(output), - "the LLD version string should be present in the output logs" + find_lld_version_in_logs(&output), + "the LLD version string should be present in the output logs:\n{}", + std::str::from_utf8(&output.stderr).unwrap() ); } -fn find_lld_version_in_logs(output: Output) -> bool { +fn find_lld_version_in_logs(output: &Output) -> bool { let lld_version_re = Regex::new(r"^LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap(); let stderr = std::str::from_utf8(&output.stderr).unwrap(); stderr.lines().any(|line| lld_version_re.is_match(line)) From 8160974ce8e751e3283d61493325ae71dccd0877 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 24 May 2024 15:50:20 +0000 Subject: [PATCH 100/211] ignore whitespace in ldd tests --- tests/run-make/rust-lld-by-default/rmake.rs | 2 +- tests/run-make/rust-lld-custom-target/rmake.rs | 2 +- tests/run-make/rust-lld/rmake.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/run-make/rust-lld-by-default/rmake.rs b/tests/run-make/rust-lld-by-default/rmake.rs index b46988da5038..8ab16394a915 100644 --- a/tests/run-make/rust-lld-by-default/rmake.rs +++ b/tests/run-make/rust-lld-by-default/rmake.rs @@ -39,5 +39,5 @@ fn main() { fn find_lld_version_in_logs(output: &Output) -> bool { let lld_version_re = Regex::new(r"^LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap(); let stderr = std::str::from_utf8(&output.stderr).unwrap(); - stderr.lines().any(|line| lld_version_re.is_match(line)) + stderr.lines().any(|line| lld_version_re.is_match(line.trim())) } diff --git a/tests/run-make/rust-lld-custom-target/rmake.rs b/tests/run-make/rust-lld-custom-target/rmake.rs index 4eb858574634..e6c4a321d000 100644 --- a/tests/run-make/rust-lld-custom-target/rmake.rs +++ b/tests/run-make/rust-lld-custom-target/rmake.rs @@ -47,5 +47,5 @@ fn main() { fn find_lld_version_in_logs(output: &Output) -> bool { let lld_version_re = Regex::new(r"^LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap(); let stderr = std::str::from_utf8(&output.stderr).unwrap(); - stderr.lines().any(|line| lld_version_re.is_match(line)) + stderr.lines().any(|line| lld_version_re.is_match(line.trim())) } diff --git a/tests/run-make/rust-lld/rmake.rs b/tests/run-make/rust-lld/rmake.rs index e186bc700d3e..a74e858045d4 100644 --- a/tests/run-make/rust-lld/rmake.rs +++ b/tests/run-make/rust-lld/rmake.rs @@ -61,5 +61,5 @@ fn main() { fn find_lld_version_in_logs(output: &Output) -> bool { let lld_version_re = Regex::new(r"^LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap(); let stderr = std::str::from_utf8(&output.stderr).unwrap(); - stderr.lines().any(|line| lld_version_re.is_match(line)) + stderr.lines().any(|line| lld_version_re.is_match(line.trim())) } From 1e3e3df81ef59a4948d1fc3c3511c48ec67ffdf7 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Tue, 21 May 2024 14:53:50 -0400 Subject: [PATCH 101/211] rewrite emit test --- tests/run-make/emit/Makefile | 22 ---------------------- tests/run-make/emit/rmake.rs | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+), 22 deletions(-) delete mode 100644 tests/run-make/emit/Makefile create mode 100644 tests/run-make/emit/rmake.rs diff --git a/tests/run-make/emit/Makefile b/tests/run-make/emit/Makefile deleted file mode 100644 index b3ca0b79fb0c..000000000000 --- a/tests/run-make/emit/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -all: - $(RUSTC) -Copt-level=0 --emit=llvm-bc,llvm-ir,asm,obj,link test-24876.rs - $(RUSTC) -Copt-level=1 --emit=llvm-bc,llvm-ir,asm,obj,link test-24876.rs - $(RUSTC) -Copt-level=2 --emit=llvm-bc,llvm-ir,asm,obj,link test-24876.rs - $(RUSTC) -Copt-level=3 --emit=llvm-bc,llvm-ir,asm,obj,link test-24876.rs - $(RUSTC) -Copt-level=s --emit=llvm-bc,llvm-ir,asm,obj,link test-24876.rs - $(RUSTC) -Copt-level=z --emit=llvm-bc,llvm-ir,asm,obj,link test-24876.rs - $(RUSTC) -Copt-level=0 --emit=llvm-bc,llvm-ir,asm,obj,link test-26235.rs - $(call RUN,test-26235) || exit 1 - $(RUSTC) -Copt-level=1 --emit=llvm-bc,llvm-ir,asm,obj,link test-26235.rs - $(call RUN,test-26235) || exit 1 - $(RUSTC) -Copt-level=2 --emit=llvm-bc,llvm-ir,asm,obj,link test-26235.rs - $(call RUN,test-26235) || exit 1 - $(RUSTC) -Copt-level=3 --emit=llvm-bc,llvm-ir,asm,obj,link test-26235.rs - $(call RUN,test-26235) || exit 1 - $(RUSTC) -Copt-level=s --emit=llvm-bc,llvm-ir,asm,obj,link test-26235.rs - $(call RUN,test-26235) || exit 1 - $(RUSTC) -Copt-level=z --emit=llvm-bc,llvm-ir,asm,obj,link test-26235.rs - $(call RUN,test-26235) || exit 1 diff --git a/tests/run-make/emit/rmake.rs b/tests/run-make/emit/rmake.rs new file mode 100644 index 000000000000..d3ccc7fdc27a --- /dev/null +++ b/tests/run-make/emit/rmake.rs @@ -0,0 +1,19 @@ +// A bug from 2015 would cause errors when emitting multiple types of files +// in the same rustc call. A fix was created in #30452. This test checks that +// the fix did not accidentally break compilation. +// See https://github.com/rust-lang/rust/pull/30452 + +//@ ignore-cross-compile + +use run_make_support::{run, rustc}; + +fn main() { + let opt_levels = ["0", "1", "2", "3", "s", "z"]; + for level in opt_levels { + rustc().opt_level(level).emit("llvm-bc,llvm-ir,asm,obj,link").input("test-24876.rs"); + } + for level in opt_levels { + rustc().opt_level(level).emit("llvm-bc,llvm-ir,asm,obj,link").input("test-26235.rs"); + run("test-26235"); + } +} From 5db8552b20e6528c6ae3c9247d5bbab962b564f9 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Tue, 21 May 2024 15:05:51 -0400 Subject: [PATCH 102/211] rewrite bare-outfile test --- tests/run-make/bare-outfile/Makefile | 9 --------- tests/run-make/bare-outfile/rmake.rs | 15 +++++++++++++++ 2 files changed, 15 insertions(+), 9 deletions(-) delete mode 100644 tests/run-make/bare-outfile/Makefile create mode 100644 tests/run-make/bare-outfile/rmake.rs diff --git a/tests/run-make/bare-outfile/Makefile b/tests/run-make/bare-outfile/Makefile deleted file mode 100644 index ad6fe4bd167c..000000000000 --- a/tests/run-make/bare-outfile/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# This test checks that manually setting the output file as a bare file with no file extension still results in successful compilation. - -# ignore-cross-compile -include ../tools.mk - -all: - cp foo.rs $(TMPDIR) - cd $(TMPDIR) && $(RUSTC) -o foo foo.rs - $(call RUN,foo) diff --git a/tests/run-make/bare-outfile/rmake.rs b/tests/run-make/bare-outfile/rmake.rs new file mode 100644 index 000000000000..c2b6347f9689 --- /dev/null +++ b/tests/run-make/bare-outfile/rmake.rs @@ -0,0 +1,15 @@ +// This test checks that manually setting the output file as a bare file with no file extension +// still results in successful compilation. + +//@ ignore-cross-compile + +use run_make_support::{run, rustc, tmp_dir}; +use std::fs; +use std::env; + +fn main(){ + fs::copy("foo.rs", tmp_dir()).unwrap(); + env::set_current_dir(tmp_dir()); + rustc().output("foo").input("foo.rs"); + run("foo"); +} From 836c08ed2109348f1304255b9b90c70ddcb4d844 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Tue, 21 May 2024 15:50:57 -0400 Subject: [PATCH 103/211] rewrite mixing-formats test --- tests/run-make/mixing-formats/Makefile | 75 ---------------------- tests/run-make/mixing-formats/rmake.rs | 87 ++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 75 deletions(-) delete mode 100644 tests/run-make/mixing-formats/Makefile create mode 100644 tests/run-make/mixing-formats/rmake.rs diff --git a/tests/run-make/mixing-formats/Makefile b/tests/run-make/mixing-formats/Makefile deleted file mode 100644 index d01978a15995..000000000000 --- a/tests/run-make/mixing-formats/Makefile +++ /dev/null @@ -1,75 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -# Testing various mixings of rlibs and dylibs. Makes sure that it's possible to -# link an rlib to a dylib. The dependency tree among the file looks like: -# -# foo -# / \ -# bar1 bar2 -# / \ / -# baz baz2 -# -# This is generally testing the permutations of the foo/bar1/bar2 layer against -# the baz/baz2 layer - -all: - # Building just baz - $(RUSTC) --crate-type=rlib foo.rs - $(RUSTC) --crate-type=dylib bar1.rs -C prefer-dynamic - $(RUSTC) --crate-type=dylib,rlib baz.rs -C prefer-dynamic - $(RUSTC) --crate-type=bin baz.rs - rm $(TMPDIR)/* - $(RUSTC) --crate-type=dylib foo.rs -C prefer-dynamic - $(RUSTC) --crate-type=rlib bar1.rs - $(RUSTC) --crate-type=dylib,rlib baz.rs -C prefer-dynamic - $(RUSTC) --crate-type=bin baz.rs - rm $(TMPDIR)/* - # Building baz2 - $(RUSTC) --crate-type=rlib foo.rs - $(RUSTC) --crate-type=dylib bar1.rs -C prefer-dynamic - $(RUSTC) --crate-type=dylib bar2.rs -C prefer-dynamic - $(RUSTC) --crate-type=dylib baz2.rs && exit 1 || exit 0 - $(RUSTC) --crate-type=bin baz2.rs && exit 1 || exit 0 - rm $(TMPDIR)/* - $(RUSTC) --crate-type=rlib foo.rs - $(RUSTC) --crate-type=rlib bar1.rs - $(RUSTC) --crate-type=dylib bar2.rs -C prefer-dynamic - $(RUSTC) --crate-type=dylib,rlib baz2.rs - $(RUSTC) --crate-type=bin baz2.rs - rm $(TMPDIR)/* - $(RUSTC) --crate-type=rlib foo.rs - $(RUSTC) --crate-type=dylib bar1.rs -C prefer-dynamic - $(RUSTC) --crate-type=rlib bar2.rs - $(RUSTC) --crate-type=dylib,rlib baz2.rs -C prefer-dynamic - $(RUSTC) --crate-type=bin baz2.rs - rm $(TMPDIR)/* - $(RUSTC) --crate-type=rlib foo.rs - $(RUSTC) --crate-type=rlib bar1.rs - $(RUSTC) --crate-type=rlib bar2.rs - $(RUSTC) --crate-type=dylib,rlib baz2.rs -C prefer-dynamic - $(RUSTC) --crate-type=bin baz2.rs - rm $(TMPDIR)/* - $(RUSTC) --crate-type=dylib foo.rs -C prefer-dynamic - $(RUSTC) --crate-type=rlib bar1.rs - $(RUSTC) --crate-type=rlib bar2.rs - $(RUSTC) --crate-type=dylib,rlib baz2.rs -C prefer-dynamic - $(RUSTC) --crate-type=bin baz2.rs - rm $(TMPDIR)/* - $(RUSTC) --crate-type=dylib foo.rs -C prefer-dynamic - $(RUSTC) --crate-type=dylib bar1.rs -C prefer-dynamic - $(RUSTC) --crate-type=rlib bar2.rs - $(RUSTC) --crate-type=dylib,rlib baz2.rs - $(RUSTC) --crate-type=bin baz2.rs - rm $(TMPDIR)/* - $(RUSTC) --crate-type=dylib foo.rs -C prefer-dynamic - $(RUSTC) --crate-type=rlib bar1.rs - $(RUSTC) --crate-type=dylib bar2.rs -C prefer-dynamic - $(RUSTC) --crate-type=dylib,rlib baz2.rs - $(RUSTC) --crate-type=bin baz2.rs - rm $(TMPDIR)/* - $(RUSTC) --crate-type=dylib foo.rs -C prefer-dynamic - $(RUSTC) --crate-type=dylib bar1.rs -C prefer-dynamic - $(RUSTC) --crate-type=dylib bar2.rs -C prefer-dynamic - $(RUSTC) --crate-type=dylib,rlib baz2.rs - $(RUSTC) --crate-type=bin baz2.rs diff --git a/tests/run-make/mixing-formats/rmake.rs b/tests/run-make/mixing-formats/rmake.rs new file mode 100644 index 000000000000..c80951a15975 --- /dev/null +++ b/tests/run-make/mixing-formats/rmake.rs @@ -0,0 +1,87 @@ +// Testing various mixings of rlibs and dylibs. Makes sure that it's possible to +// link an rlib to a dylib. The dependency tree among the file looks like: +// +// foo +// / \ +// bar1 bar2 +// / \ / +// baz baz2 +// +// This is generally testing the permutations of the foo/bar1/bar2 layer against +// the baz/baz2 layer + +//@ ignore-cross-compile + +use run_make_support::{rustc, tmp_dir}; +use std::fs; + +fn main() { + // Building just baz + rustc().crate_type("rlib").input("foo.rs").run(); + rustc().crate_type("dylib").input("bar1.rs").arg("-Cprefer-dynamic").run(); + rustc().crate_type("dylib,rlib").input("baz.rs").arg("-Cprefer-dynamic").run(); + rustc().crate_type("bin").input("baz.rs").run(); + fs::remove_dir_all(tmp_dir()).unwrap(); + fs::create_dir(tmp_dir()).unwrap(); + rustc().crate_type("dylib").input("foo.rs").arg("-Cprefer-dynamic").run(); + rustc().crate_type("rlib").input("bar1.rs").run(); + rustc().crate_type("dylib,rlib").input("baz.rs").arg("-Cprefer-dynamic").run(); + rustc().crate_type("bin").input("baz.rs").run(); + fs::remove_dir_all(tmp_dir()).unwrap(); + fs::create_dir(tmp_dir()).unwrap(); + // Building baz2 + rustc().crate_type("rlib").input("foo.rs").run(); + rustc().crate_type("dylib").input("bar1.rs").arg("-Cprefer-dynamic").run(); + rustc().crate_type("dylib").input("bar2.rs").arg("-Cprefer-dynamic").run(); + rustc().crate_type("dylib").input("baz2.rs").run_fail_assert_exit_code(1); + rustc().crate_type("bin").input("baz2.rs").run_fail_assert_exit_code(1); + fs::remove_dir_all(tmp_dir()).unwrap(); + fs::create_dir(tmp_dir()).unwrap(); + rustc().crate_type("rlib").input("foo.rs").run(); + rustc().crate_type("rlib").input("bar1.rs").run(); + rustc().crate_type("dylib").input("bar2.rs").arg("-Cprefer-dynamic").run(); + rustc().crate_type("dylib,rlib").input("baz2.rs").run(); + rustc().crate_type("bin").input("baz2.rs").run; + fs::remove_dir_all(tmp_dir()).unwrap(); + fs::create_dir(tmp_dir()).unwrap(); + rustc().crate_type("rlib").input("foo.rs").run(); + rustc().crate_type("dylib").input("bar1.rs").arg("-Cprefer-dynamic").run(); + rustc().crate_type("rlib").input("bar2.rs").run(); + rustc().crate_type("dylib,rlib").input("baz2.rs").arg("-Cprefer-dynamic").run(); + rustc().crate_type("bin").input("baz2.rs").run(); + fs::remove_dir_all(tmp_dir()).unwrap(); + fs::create_dir(tmp_dir()).unwrap(); + rustc().crate_type("rlib").input("foo.rs").run(); + rustc().crate_type("rlib").input("bar1.rs").run(); + rustc().crate_type("rlib").input("bar2.rs").run(); + rustc().crate_type("dylib,rlib").input("baz2.rs").arg("-Cprefer-dynamic").run(); + rustc().crate_type("bin").input("baz2.rs").run(); + fs::remove_dir_all(tmp_dir()).unwrap(); + fs::create_dir(tmp_dir()).unwrap(); + rustc().crate_type("dylib").input("foo.rs").arg("-Cprefer-dynamic").run(); + rustc().crate_type("rlib").input("bar1.rs").run(); + rustc().crate_type("rlib").input("bar2.rs").run(); + rustc().crate_type("dylib,rlib").input("baz2.rs").arg("-Cprefer-dynamic").run(); + rustc().crate_type("bin").input("baz2.rs").run(); + fs::remove_dir_all(tmp_dir()).unwrap(); + fs::create_dir(tmp_dir()).unwrap(); + rustc().crate_type("dylib").input("foo.rs").arg("-Cprefer-dynamic").run(); + rustc().crate_type("dylib").input("bar1.rs").arg("-Cprefer-dynamic").run(); + rustc().crate_type("rlib").input("bar2.rs").run(); + rustc().crate_type("dylib,rlib").input("baz2.rs").run(); + rustc().crate_type("bin").input("baz2.rs").run(); + fs::remove_dir_all(tmp_dir()).unwrap(); + fs::create_dir(tmp_dir()).unwrap(); + rustc().crate_type("dylib").input("foo.rs").arg("-Cprefer-dynamic").run(); + rustc().crate_type("rlib").input("bar1.rs").run(); + rustc().crate_type("dylib").input("bar2.rs").arg("-Cprefer-dynamic").run(); + rustc().crate_type("dylib,rlib").input("baz2.rs").run(); + rustc().crate_type("bin").input("baz2.rs").run(); + fs::remove_dir_all(tmp_dir()).unwrap(); + fs::create_dir(tmp_dir()).unwrap(); + rustc().crate_type("dylib").input("foo.rs").arg("-Cprefer-dynamic").run(); + rustc().crate_type("dylib").input("bar1.rs").arg("-Cprefer-dynamic").run(); + rustc().crate_type("dylib").input("bar2.rs").arg("-Cprefer-dynamic").run(); + rustc().crate_type("dylib,rlib").input("baz2.rs").run(); + rustc().crate_type("bin").input("baz2.rs").run(); +} From 2f4b7dc047eb151d7bb774ac117a91041c912543 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 30 May 2024 15:07:32 -0400 Subject: [PATCH 104/211] Fold item bound before checking that they hold --- .../src/check/compare_impl_item.rs | 29 ++++++- .../defaults-unsound-62211-1.current.stderr | 16 ++-- .../defaults-unsound-62211-1.next.stderr | 86 ++++++++++++++++--- .../defaults-unsound-62211-1.rs | 11 ++- .../defaults-unsound-62211-2.current.stderr | 16 ++-- .../defaults-unsound-62211-2.next.stderr | 86 ++++++++++++++++--- .../defaults-unsound-62211-2.rs | 11 ++- ...malization-for-nested-goals.current.stderr | 6 +- ...normalization-for-nested-goals.next.stderr | 24 ++++++ ...sume-gat-normalization-for-nested-goals.rs | 3 +- ...n-default-items-drop-coherence.next.stderr | 11 +-- ...ialization-default-items-drop-coherence.rs | 2 +- ...cialization-overlap-projection.next.stderr | 27 +----- .../specialization-overlap-projection.rs | 3 - .../next-solver/specialization-transmute.rs | 2 +- .../specialization-transmute.stderr | 11 +-- .../specialization-unconstrained.rs | 2 +- .../specialization-unconstrained.stderr | 11 +-- .../next-solver/unsound-region-obligation.rs | 2 +- .../unsound-region-obligation.stderr | 2 +- 20 files changed, 246 insertions(+), 115 deletions(-) create mode 100644 tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.next.stderr 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 8928711253cd..db749ef3f81b 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -2026,10 +2026,19 @@ pub(super) fn check_type_bounds<'tcx>( // to its definition type. This should be the param-env we use to *prove* the // predicate too, but we don't do that because of performance issues. // See . + let trait_projection_ty = Ty::new_projection(tcx, trait_ty.def_id, rebased_args); + let impl_identity_ty = tcx.type_of(impl_ty.def_id).instantiate_identity(); let normalize_param_env = param_env_with_gat_bounds(tcx, impl_ty, impl_trait_ref); for mut obligation in util::elaborate(tcx, obligations) { - let normalized_predicate = - ocx.normalize(&normalize_cause, normalize_param_env, obligation.predicate); + let normalized_predicate = if infcx.next_trait_solver() { + obligation.predicate.fold_with(&mut ReplaceTy { + tcx, + from: trait_projection_ty, + to: impl_identity_ty, + }) + } else { + ocx.normalize(&normalize_cause, normalize_param_env, obligation.predicate) + }; debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate); obligation.predicate = normalized_predicate; @@ -2050,6 +2059,22 @@ pub(super) fn check_type_bounds<'tcx>( ocx.resolve_regions_and_report_errors(impl_ty_def_id, &outlives_env) } +struct ReplaceTy<'tcx> { + tcx: TyCtxt<'tcx>, + from: Ty<'tcx>, + to: Ty<'tcx>, +} + +impl<'tcx> TypeFolder> for ReplaceTy<'tcx> { + fn interner(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + if self.from == ty { self.to } else { ty.super_fold_with(self) } + } +} + /// Install projection predicates that allow GATs to project to their own /// definition types. This is not allowed in general in cases of default /// associated types in trait definitions, or when specialization is involved, diff --git a/tests/ui/associated-types/defaults-unsound-62211-1.current.stderr b/tests/ui/associated-types/defaults-unsound-62211-1.current.stderr index 9d52e923aded..8b6f0a47aed9 100644 --- a/tests/ui/associated-types/defaults-unsound-62211-1.current.stderr +++ b/tests/ui/associated-types/defaults-unsound-62211-1.current.stderr @@ -1,12 +1,12 @@ error[E0277]: `Self` doesn't implement `std::fmt::Display` - --> $DIR/defaults-unsound-62211-1.rs:26:96 + --> $DIR/defaults-unsound-62211-1.rs:24:96 | LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; | ^^^^ `Self` cannot be formatted with the default formatter | = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead note: required by a bound in `UncheckedCopy::Output` - --> $DIR/defaults-unsound-62211-1.rs:26:86 + --> $DIR/defaults-unsound-62211-1.rs:24:86 | LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; | ^^^^^^^ required by this bound in `UncheckedCopy::Output` @@ -16,13 +16,13 @@ LL | trait UncheckedCopy: Sized + std::fmt::Display { | +++++++++++++++++++ error[E0277]: cannot add-assign `&'static str` to `Self` - --> $DIR/defaults-unsound-62211-1.rs:26:96 + --> $DIR/defaults-unsound-62211-1.rs:24:96 | LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; | ^^^^ no implementation for `Self += &'static str` | note: required by a bound in `UncheckedCopy::Output` - --> $DIR/defaults-unsound-62211-1.rs:26:47 + --> $DIR/defaults-unsound-62211-1.rs:24:47 | LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output` @@ -32,13 +32,13 @@ LL | trait UncheckedCopy: Sized + AddAssign<&'static str> { | +++++++++++++++++++++++++ error[E0277]: the trait bound `Self: Deref` is not satisfied - --> $DIR/defaults-unsound-62211-1.rs:26:96 + --> $DIR/defaults-unsound-62211-1.rs:24:96 | LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; | ^^^^ the trait `Deref` is not implemented for `Self` | note: required by a bound in `UncheckedCopy::Output` - --> $DIR/defaults-unsound-62211-1.rs:26:25 + --> $DIR/defaults-unsound-62211-1.rs:24:25 | LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; | ^^^^^^^^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output` @@ -48,13 +48,13 @@ LL | trait UncheckedCopy: Sized + Deref { | +++++++ error[E0277]: the trait bound `Self: Copy` is not satisfied - --> $DIR/defaults-unsound-62211-1.rs:26:96 + --> $DIR/defaults-unsound-62211-1.rs:24:96 | LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; | ^^^^ the trait `Copy` is not implemented for `Self` | note: required by a bound in `UncheckedCopy::Output` - --> $DIR/defaults-unsound-62211-1.rs:26:18 + --> $DIR/defaults-unsound-62211-1.rs:24:18 | LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; | ^^^^ required by this bound in `UncheckedCopy::Output` diff --git a/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr b/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr index ffb02eccc77d..0fc1bb0b00f3 100644 --- a/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr +++ b/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr @@ -1,17 +1,81 @@ -warning: calls to `std::mem::drop` with a value that implements `Copy` does nothing - --> $DIR/defaults-unsound-62211-1.rs:52:5 +error[E0277]: `Self` doesn't implement `std::fmt::Display` + --> $DIR/defaults-unsound-62211-1.rs:24:96 | -LL | drop(origin); - | ^^^^^------^ - | | - | argument has type `::Output` +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^ `Self` cannot be formatted with the default formatter | - = note: `#[warn(dropping_copy_types)]` on by default -help: use `let _ = ...` to ignore the expression or result + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `UncheckedCopy::Output` + --> $DIR/defaults-unsound-62211-1.rs:24:86 | -LL - drop(origin); -LL + let _ = origin; +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^^^^ required by this bound in `UncheckedCopy::Output` +help: consider further restricting `Self` | +LL | trait UncheckedCopy: Sized + std::fmt::Display { + | +++++++++++++++++++ -warning: 1 warning emitted +error[E0277]: cannot add-assign `&'static str` to `Self` + --> $DIR/defaults-unsound-62211-1.rs:24:96 + | +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^ no implementation for `Self += &'static str` + | +note: required by a bound in `UncheckedCopy::Output` + --> $DIR/defaults-unsound-62211-1.rs:24:47 + | +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output` +help: consider further restricting `Self` + | +LL | trait UncheckedCopy: Sized + AddAssign<&'static str> { + | +++++++++++++++++++++++++ +error[E0271]: type mismatch resolving `::Target == str` + --> $DIR/defaults-unsound-62211-1.rs:24:96 + | +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^ types differ + | +note: required by a bound in `UncheckedCopy::Output` + --> $DIR/defaults-unsound-62211-1.rs:24:31 + | +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output` + +error[E0277]: the trait bound `Self: Deref` is not satisfied + --> $DIR/defaults-unsound-62211-1.rs:24:96 + | +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^ the trait `Deref` is not implemented for `Self` + | +note: required by a bound in `UncheckedCopy::Output` + --> $DIR/defaults-unsound-62211-1.rs:24:25 + | +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^^^^^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output` +help: consider further restricting `Self` + | +LL | trait UncheckedCopy: Sized + Deref { + | +++++++ + +error[E0277]: the trait bound `Self: Copy` is not satisfied + --> $DIR/defaults-unsound-62211-1.rs:24:96 + | +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^ the trait `Copy` is not implemented for `Self` + | +note: required by a bound in `UncheckedCopy::Output` + --> $DIR/defaults-unsound-62211-1.rs:24:18 + | +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^ required by this bound in `UncheckedCopy::Output` +help: consider further restricting `Self` + | +LL | trait UncheckedCopy: Sized + Copy { + | ++++++ + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0271, E0277. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/associated-types/defaults-unsound-62211-1.rs b/tests/ui/associated-types/defaults-unsound-62211-1.rs index d9cf5aa97acd..f054611ed780 100644 --- a/tests/ui/associated-types/defaults-unsound-62211-1.rs +++ b/tests/ui/associated-types/defaults-unsound-62211-1.rs @@ -1,8 +1,6 @@ //@ revisions: current next //@[next] compile-flags: -Znext-solver //@ ignore-compare-mode-next-solver (explicit revisions) -//@[next] known-bug: rust-lang/trait-system-refactor-initiative#46 -//@[next] check-pass //! Regression test for https://github.com/rust-lang/rust/issues/62211 //! @@ -24,10 +22,11 @@ trait UncheckedCopy: Sized { // This Output is said to be Copy. Yet we default to Self // and it's accepted, not knowing if Self ineed is Copy type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - //[current]~^ ERROR the trait bound `Self: Copy` is not satisfied - //[current]~| ERROR the trait bound `Self: Deref` is not satisfied - //[current]~| ERROR cannot add-assign `&'static str` to `Self` - //[current]~| ERROR `Self` doesn't implement `std::fmt::Display` + //~^ ERROR the trait bound `Self: Copy` is not satisfied + //~| ERROR the trait bound `Self: Deref` is not satisfied + //~| ERROR cannot add-assign `&'static str` to `Self` + //~| ERROR `Self` doesn't implement `std::fmt::Display` + //[next]~| ERROR type mismatch resolving `::Target == str` // We said the Output type was Copy, so we can Copy it freely! fn unchecked_copy(other: &Self::Output) -> Self::Output { diff --git a/tests/ui/associated-types/defaults-unsound-62211-2.current.stderr b/tests/ui/associated-types/defaults-unsound-62211-2.current.stderr index 4fd2ca6408a1..7552b0891333 100644 --- a/tests/ui/associated-types/defaults-unsound-62211-2.current.stderr +++ b/tests/ui/associated-types/defaults-unsound-62211-2.current.stderr @@ -1,12 +1,12 @@ error[E0277]: `Self` doesn't implement `std::fmt::Display` - --> $DIR/defaults-unsound-62211-2.rs:26:96 + --> $DIR/defaults-unsound-62211-2.rs:24:96 | LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; | ^^^^ `Self` cannot be formatted with the default formatter | = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead note: required by a bound in `UncheckedCopy::Output` - --> $DIR/defaults-unsound-62211-2.rs:26:86 + --> $DIR/defaults-unsound-62211-2.rs:24:86 | LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; | ^^^^^^^ required by this bound in `UncheckedCopy::Output` @@ -16,13 +16,13 @@ LL | trait UncheckedCopy: Sized + std::fmt::Display { | +++++++++++++++++++ error[E0277]: cannot add-assign `&'static str` to `Self` - --> $DIR/defaults-unsound-62211-2.rs:26:96 + --> $DIR/defaults-unsound-62211-2.rs:24:96 | LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; | ^^^^ no implementation for `Self += &'static str` | note: required by a bound in `UncheckedCopy::Output` - --> $DIR/defaults-unsound-62211-2.rs:26:47 + --> $DIR/defaults-unsound-62211-2.rs:24:47 | LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output` @@ -32,13 +32,13 @@ LL | trait UncheckedCopy: Sized + AddAssign<&'static str> { | +++++++++++++++++++++++++ error[E0277]: the trait bound `Self: Deref` is not satisfied - --> $DIR/defaults-unsound-62211-2.rs:26:96 + --> $DIR/defaults-unsound-62211-2.rs:24:96 | LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; | ^^^^ the trait `Deref` is not implemented for `Self` | note: required by a bound in `UncheckedCopy::Output` - --> $DIR/defaults-unsound-62211-2.rs:26:25 + --> $DIR/defaults-unsound-62211-2.rs:24:25 | LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; | ^^^^^^^^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output` @@ -48,13 +48,13 @@ LL | trait UncheckedCopy: Sized + Deref { | +++++++ error[E0277]: the trait bound `Self: Copy` is not satisfied - --> $DIR/defaults-unsound-62211-2.rs:26:96 + --> $DIR/defaults-unsound-62211-2.rs:24:96 | LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; | ^^^^ the trait `Copy` is not implemented for `Self` | note: required by a bound in `UncheckedCopy::Output` - --> $DIR/defaults-unsound-62211-2.rs:26:18 + --> $DIR/defaults-unsound-62211-2.rs:24:18 | LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; | ^^^^ required by this bound in `UncheckedCopy::Output` diff --git a/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr b/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr index e6ae8183e77d..751352d7c16d 100644 --- a/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr +++ b/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr @@ -1,17 +1,81 @@ -warning: calls to `std::mem::drop` with a value that implements `Copy` does nothing - --> $DIR/defaults-unsound-62211-2.rs:52:5 +error[E0277]: `Self` doesn't implement `std::fmt::Display` + --> $DIR/defaults-unsound-62211-2.rs:24:96 | -LL | drop(origin); - | ^^^^^------^ - | | - | argument has type `::Output` +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^ `Self` cannot be formatted with the default formatter | - = note: `#[warn(dropping_copy_types)]` on by default -help: use `let _ = ...` to ignore the expression or result + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `UncheckedCopy::Output` + --> $DIR/defaults-unsound-62211-2.rs:24:86 | -LL - drop(origin); -LL + let _ = origin; +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^^^^ required by this bound in `UncheckedCopy::Output` +help: consider further restricting `Self` | +LL | trait UncheckedCopy: Sized + std::fmt::Display { + | +++++++++++++++++++ -warning: 1 warning emitted +error[E0277]: cannot add-assign `&'static str` to `Self` + --> $DIR/defaults-unsound-62211-2.rs:24:96 + | +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^ no implementation for `Self += &'static str` + | +note: required by a bound in `UncheckedCopy::Output` + --> $DIR/defaults-unsound-62211-2.rs:24:47 + | +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output` +help: consider further restricting `Self` + | +LL | trait UncheckedCopy: Sized + AddAssign<&'static str> { + | +++++++++++++++++++++++++ +error[E0271]: type mismatch resolving `::Target == str` + --> $DIR/defaults-unsound-62211-2.rs:24:96 + | +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^ types differ + | +note: required by a bound in `UncheckedCopy::Output` + --> $DIR/defaults-unsound-62211-2.rs:24:31 + | +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output` + +error[E0277]: the trait bound `Self: Deref` is not satisfied + --> $DIR/defaults-unsound-62211-2.rs:24:96 + | +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^ the trait `Deref` is not implemented for `Self` + | +note: required by a bound in `UncheckedCopy::Output` + --> $DIR/defaults-unsound-62211-2.rs:24:25 + | +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^^^^^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output` +help: consider further restricting `Self` + | +LL | trait UncheckedCopy: Sized + Deref { + | +++++++ + +error[E0277]: the trait bound `Self: Copy` is not satisfied + --> $DIR/defaults-unsound-62211-2.rs:24:96 + | +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^ the trait `Copy` is not implemented for `Self` + | +note: required by a bound in `UncheckedCopy::Output` + --> $DIR/defaults-unsound-62211-2.rs:24:18 + | +LL | type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; + | ^^^^ required by this bound in `UncheckedCopy::Output` +help: consider further restricting `Self` + | +LL | trait UncheckedCopy: Sized + Copy { + | ++++++ + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0271, E0277. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/associated-types/defaults-unsound-62211-2.rs b/tests/ui/associated-types/defaults-unsound-62211-2.rs index 6cbac1bf2364..956f14df0d54 100644 --- a/tests/ui/associated-types/defaults-unsound-62211-2.rs +++ b/tests/ui/associated-types/defaults-unsound-62211-2.rs @@ -1,8 +1,6 @@ //@ revisions: current next //@[next] compile-flags: -Znext-solver //@ ignore-compare-mode-next-solver (explicit revisions) -//@[next] known-bug: rust-lang/trait-system-refactor-initiative#46 -//@[next] check-pass //! Regression test for https://github.com/rust-lang/rust/issues/62211 //! @@ -24,10 +22,11 @@ trait UncheckedCopy: Sized { // This Output is said to be Copy. Yet we default to Self // and it's accepted, not knowing if Self ineed is Copy type Output: Copy + Deref + AddAssign<&'static str> + From + Display = Self; - //[current]~^ ERROR the trait bound `Self: Copy` is not satisfied - //[current]~| ERROR the trait bound `Self: Deref` is not satisfied - //[current]~| ERROR cannot add-assign `&'static str` to `Self` - //[current]~| ERROR `Self` doesn't implement `std::fmt::Display` + //~^ ERROR the trait bound `Self: Copy` is not satisfied + //~| ERROR the trait bound `Self: Deref` is not satisfied + //~| ERROR cannot add-assign `&'static str` to `Self` + //~| ERROR `Self` doesn't implement `std::fmt::Display` + //[next]~| ERROR type mismatch resolving `::Target == str` // We said the Output type was Copy, so we can Copy it freely! fn unchecked_copy(other: &Self::Output) -> Self::Output { diff --git a/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.current.stderr b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.current.stderr index 2097115af009..c5c4f2c4d231 100644 --- a/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.current.stderr +++ b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.current.stderr @@ -1,16 +1,16 @@ error[E0277]: the trait bound `::Bar<()>: Eq` is not satisfied - --> $DIR/assume-gat-normalization-for-nested-goals.rs:10:30 + --> $DIR/assume-gat-normalization-for-nested-goals.rs:9:30 | LL | type Bar: Baz = i32; | ^^^ the trait `Eq` is not implemented for `::Bar<()>`, which is required by `i32: Baz` | note: required for `i32` to implement `Baz` - --> $DIR/assume-gat-normalization-for-nested-goals.rs:17:23 + --> $DIR/assume-gat-normalization-for-nested-goals.rs:16:23 | LL | impl Baz for i32 where T::Bar<()>: Eq {} | ^^^^^^ ^^^ ------- unsatisfied trait bound introduced here note: required by a bound in `Foo::Bar` - --> $DIR/assume-gat-normalization-for-nested-goals.rs:10:18 + --> $DIR/assume-gat-normalization-for-nested-goals.rs:9:18 | LL | type Bar: Baz = i32; | ^^^^^^^^^ required by this bound in `Foo::Bar` diff --git a/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.next.stderr b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.next.stderr new file mode 100644 index 000000000000..2c372b6c3a78 --- /dev/null +++ b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.next.stderr @@ -0,0 +1,24 @@ +error[E0277]: the trait bound `i32: Baz` is not satisfied + --> $DIR/assume-gat-normalization-for-nested-goals.rs:9:30 + | +LL | type Bar: Baz = i32; + | ^^^ the trait `Eq` is not implemented for `i32`, which is required by `i32: Baz` + | +note: required for `i32` to implement `Baz` + --> $DIR/assume-gat-normalization-for-nested-goals.rs:16:23 + | +LL | impl Baz for i32 where T::Bar<()>: Eq {} + | ^^^^^^ ^^^ ------- unsatisfied trait bound introduced here +note: required by a bound in `Foo::Bar` + --> $DIR/assume-gat-normalization-for-nested-goals.rs:9:18 + | +LL | type Bar: Baz = i32; + | ^^^^^^^^^ required by this bound in `Foo::Bar` +help: consider further restricting the associated type + | +LL | trait Foo where ::Bar<()>: Eq { + | +++++++++++++++++++++++++++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.rs b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.rs index 56b50594e523..4050b6fc4258 100644 --- a/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.rs +++ b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.rs @@ -1,8 +1,7 @@ //@ revisions: current next //@[next] compile-flags: -Znext-solver //@ ignore-compare-mode-next-solver (explicit revisions) -//@[current] known-bug: #117606 -//@[next] check-pass +//@ known-bug: #117606 #![feature(associated_type_defaults)] 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 78d77a78e0ee..e9498a003179 100644 --- a/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr +++ b/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr @@ -7,13 +7,6 @@ LL | impl Overlap for u32 { LL | impl Overlap for ::Id { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32` -error[E0282]: type annotations needed - --> $DIR/specialization-default-items-drop-coherence.rs:18:23 - | -LL | default type Id = T; - | ^ cannot infer type for associated type `::Id` +error: aborting due to 1 previous error -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0119, E0282. -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/specialization/specialization-default-items-drop-coherence.rs b/tests/ui/specialization/specialization-default-items-drop-coherence.rs index fad041f2ee10..6dc012776391 100644 --- a/tests/ui/specialization/specialization-default-items-drop-coherence.rs +++ b/tests/ui/specialization/specialization-default-items-drop-coherence.rs @@ -15,7 +15,7 @@ trait Default { } impl Default for T { - default type Id = T; //[next]~ ERROR type annotations needed + default type Id = T; } trait Overlap { diff --git a/tests/ui/specialization/specialization-overlap-projection.next.stderr b/tests/ui/specialization/specialization-overlap-projection.next.stderr index ab040193fa4c..5b17696162ed 100644 --- a/tests/ui/specialization/specialization-overlap-projection.next.stderr +++ b/tests/ui/specialization/specialization-overlap-projection.next.stderr @@ -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:28: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:30:1 + --> $DIR/specialization-overlap-projection.rs:27:1 | LL | impl Foo for u32 {} | ---------------- first implementation here @@ -25,25 +25,6 @@ LL | impl Foo for u32 {} LL | impl Foo for ::Output {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32` -error[E0282]: type annotations needed - --> $DIR/specialization-overlap-projection.rs:17:27 - | -LL | default type Output = bool; - | ^^^^ cannot infer type for associated type `::Output` +error: aborting due to 2 previous errors; 1 warning emitted -error[E0282]: type annotations needed - --> $DIR/specialization-overlap-projection.rs:21:35 - | -LL | impl Assoc for u8 { type Output = u8; } - | ^^ cannot infer type for associated type `::Output` - -error[E0282]: type annotations needed - --> $DIR/specialization-overlap-projection.rs:23:36 - | -LL | impl Assoc for u16 { type Output = u16; } - | ^^^ cannot infer type for associated type `::Output` - -error: aborting due to 5 previous errors; 1 warning emitted - -Some errors have detailed explanations: E0119, E0282. -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/specialization/specialization-overlap-projection.rs b/tests/ui/specialization/specialization-overlap-projection.rs index 78e75f623c4b..16dccf82dcb9 100644 --- a/tests/ui/specialization/specialization-overlap-projection.rs +++ b/tests/ui/specialization/specialization-overlap-projection.rs @@ -15,13 +15,10 @@ trait Assoc { impl Assoc for T { default type Output = bool; - //[next]~^ ERROR type annotations needed } impl Assoc for u8 { type Output = u8; } -//[next]~^ ERROR type annotations needed impl Assoc for u16 { type Output = u16; } -//[next]~^ ERROR type annotations needed trait Foo {} impl Foo for u32 {} diff --git a/tests/ui/traits/next-solver/specialization-transmute.rs b/tests/ui/traits/next-solver/specialization-transmute.rs index caa3bfc552eb..9e31fed9b180 100644 --- a/tests/ui/traits/next-solver/specialization-transmute.rs +++ b/tests/ui/traits/next-solver/specialization-transmute.rs @@ -10,7 +10,7 @@ trait Default { } impl Default for T { - default type Id = T; //~ ERROR type annotations needed + default type Id = T; // This will be fixed by #111994 fn intu(&self) -> &Self::Id { //~^ ERROR type annotations needed diff --git a/tests/ui/traits/next-solver/specialization-transmute.stderr b/tests/ui/traits/next-solver/specialization-transmute.stderr index 76ae08fdb7a7..524522bef098 100644 --- a/tests/ui/traits/next-solver/specialization-transmute.stderr +++ b/tests/ui/traits/next-solver/specialization-transmute.stderr @@ -34,13 +34,6 @@ note: required by a bound in `transmute` LL | fn transmute, U: Copy>(t: T) -> U { | ^^^^^^ required by this bound in `transmute` -error[E0282]: type annotations needed - --> $DIR/specialization-transmute.rs:13:23 - | -LL | default type Id = T; - | ^ cannot infer type for associated type `::Id` +error: aborting due to 4 previous errors; 1 warning emitted -error: aborting due to 5 previous errors; 1 warning emitted - -Some errors have detailed explanations: E0282, E0284. -For more information about an error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/traits/next-solver/specialization-unconstrained.rs b/tests/ui/traits/next-solver/specialization-unconstrained.rs index f4046fba20b2..e44246a1262a 100644 --- a/tests/ui/traits/next-solver/specialization-unconstrained.rs +++ b/tests/ui/traits/next-solver/specialization-unconstrained.rs @@ -11,7 +11,7 @@ trait Default { } impl Default for T { - default type Id = T; //~ ERROR type annotations needed + default type Id = T; } fn test, U>() {} diff --git a/tests/ui/traits/next-solver/specialization-unconstrained.stderr b/tests/ui/traits/next-solver/specialization-unconstrained.stderr index 68232aacc0c5..a6f6a4f260d4 100644 --- a/tests/ui/traits/next-solver/specialization-unconstrained.stderr +++ b/tests/ui/traits/next-solver/specialization-unconstrained.stderr @@ -20,13 +20,6 @@ note: required by a bound in `test` LL | fn test, U>() {} | ^^^^^^ required by this bound in `test` -error[E0282]: type annotations needed - --> $DIR/specialization-unconstrained.rs:14:22 - | -LL | default type Id = T; - | ^ cannot infer type for associated type `::Id` +error: aborting due to 1 previous error; 1 warning emitted -error: aborting due to 2 previous errors; 1 warning emitted - -Some errors have detailed explanations: E0282, E0284. -For more information about an error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/traits/next-solver/unsound-region-obligation.rs b/tests/ui/traits/next-solver/unsound-region-obligation.rs index 32a510d16543..733be2043548 100644 --- a/tests/ui/traits/next-solver/unsound-region-obligation.rs +++ b/tests/ui/traits/next-solver/unsound-region-obligation.rs @@ -1,4 +1,4 @@ -//~ ERROR the type `<() as StaticTy>::Item<'a>` does not fulfill the required lifetime +//~ ERROR the type `&'a ()` does not fulfill the required lifetime //@ compile-flags: -Znext-solver // Regression test for rust-lang/trait-system-refactor-initiative#59 diff --git a/tests/ui/traits/next-solver/unsound-region-obligation.stderr b/tests/ui/traits/next-solver/unsound-region-obligation.stderr index 518de7ea3e02..fe96a184f430 100644 --- a/tests/ui/traits/next-solver/unsound-region-obligation.stderr +++ b/tests/ui/traits/next-solver/unsound-region-obligation.stderr @@ -1,4 +1,4 @@ -error[E0477]: the type `<() as StaticTy>::Item<'a>` does not fulfill the required lifetime +error[E0477]: the type `&'a ()` does not fulfill the required lifetime | = note: type must satisfy the static lifetime From 5c68eb3facbd5dcde1c05d4c5a37cc845f504759 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 30 May 2024 15:52:17 -0400 Subject: [PATCH 105/211] Add a bunch of tests --- ...rr => defaults-suitability.current.stderr} | 34 ++--- .../defaults-suitability.next.stderr | 142 ++++++++++++++++++ .../associated-types/defaults-suitability.rs | 3 + ...4108.stderr => issue-54108.current.stderr} | 4 +- .../associated-types/issue-54108.next.stderr | 33 ++++ tests/ui/associated-types/issue-54108.rs | 5 + ...3593.stderr => issue-63593.current.stderr} | 4 +- .../associated-types/issue-63593.next.stderr | 19 +++ tests/ui/associated-types/issue-63593.rs | 4 + ...4816.stderr => issue-74816.current.stderr} | 8 +- .../issue-74816.next.stderr | 35 +++++ .../generic-associated-types/issue-74816.rs | 4 + ...4824.stderr => issue-74824.current.stderr} | 8 +- .../issue-74824.next.stderr | 33 ++++ .../generic-associated-types/issue-74824.rs | 4 + 15 files changed, 311 insertions(+), 29 deletions(-) rename tests/ui/associated-types/{defaults-suitability.stderr => defaults-suitability.current.stderr} (88%) create mode 100644 tests/ui/associated-types/defaults-suitability.next.stderr rename tests/ui/associated-types/{issue-54108.stderr => issue-54108.current.stderr} (93%) create mode 100644 tests/ui/associated-types/issue-54108.next.stderr rename tests/ui/associated-types/{issue-63593.stderr => issue-63593.current.stderr} (89%) create mode 100644 tests/ui/associated-types/issue-63593.next.stderr rename tests/ui/generic-associated-types/{issue-74816.stderr => issue-74816.current.stderr} (89%) create mode 100644 tests/ui/generic-associated-types/issue-74816.next.stderr rename tests/ui/generic-associated-types/{issue-74824.stderr => issue-74824.current.stderr} (90%) create mode 100644 tests/ui/generic-associated-types/issue-74824.next.stderr diff --git a/tests/ui/associated-types/defaults-suitability.stderr b/tests/ui/associated-types/defaults-suitability.current.stderr similarity index 88% rename from tests/ui/associated-types/defaults-suitability.stderr rename to tests/ui/associated-types/defaults-suitability.current.stderr index 82b35a486378..3cdeaa93a340 100644 --- a/tests/ui/associated-types/defaults-suitability.stderr +++ b/tests/ui/associated-types/defaults-suitability.current.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `NotClone: Clone` is not satisfied - --> $DIR/defaults-suitability.rs:13:22 + --> $DIR/defaults-suitability.rs:16:22 | LL | type Ty: Clone = NotClone; | ^^^^^^^^ the trait `Clone` is not implemented for `NotClone` | note: required by a bound in `Tr::Ty` - --> $DIR/defaults-suitability.rs:13:14 + --> $DIR/defaults-suitability.rs:16:14 | LL | type Ty: Clone = NotClone; | ^^^^^ required by this bound in `Tr::Ty` @@ -16,13 +16,13 @@ LL | struct NotClone; | error[E0277]: the trait bound `NotClone: Clone` is not satisfied - --> $DIR/defaults-suitability.rs:22:15 + --> $DIR/defaults-suitability.rs:25:15 | LL | type Ty = NotClone; | ^^^^^^^^ the trait `Clone` is not implemented for `NotClone` | note: required by a bound in `Tr2::Ty` - --> $DIR/defaults-suitability.rs:20:15 + --> $DIR/defaults-suitability.rs:23:15 | LL | Self::Ty: Clone, | ^^^^^ required by this bound in `Tr2::Ty` @@ -36,14 +36,14 @@ LL | struct NotClone; | error[E0277]: the trait bound `T: Clone` is not satisfied - --> $DIR/defaults-suitability.rs:28:23 + --> $DIR/defaults-suitability.rs:31:23 | LL | type Bar: Clone = Vec; | ^^^^^^ the trait `Clone` is not implemented for `T`, which is required by `Vec: Clone` | = note: required for `Vec` to implement `Clone` note: required by a bound in `Foo::Bar` - --> $DIR/defaults-suitability.rs:28:15 + --> $DIR/defaults-suitability.rs:31:15 | LL | type Bar: Clone = Vec; | ^^^^^ required by this bound in `Foo::Bar` @@ -53,30 +53,30 @@ LL | trait Foo { | +++++++++++++++++++ error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/defaults-suitability.rs:34:29 + --> $DIR/defaults-suitability.rs:37:29 | LL | type Assoc: Foo = (); | ^^ the trait `Foo` is not implemented for `()` | help: this trait has no implementations, consider adding one - --> $DIR/defaults-suitability.rs:27:1 + --> $DIR/defaults-suitability.rs:30:1 | LL | trait Foo { | ^^^^^^^^^^^^ note: required by a bound in `Bar::Assoc` - --> $DIR/defaults-suitability.rs:34:17 + --> $DIR/defaults-suitability.rs:37:17 | LL | type Assoc: Foo = (); | ^^^^^^^^^ required by this bound in `Bar::Assoc` error[E0277]: the trait bound `NotClone: IsU8` is not satisfied - --> $DIR/defaults-suitability.rs:56:18 + --> $DIR/defaults-suitability.rs:59:18 | LL | type Assoc = NotClone; | ^^^^^^^^ the trait `IsU8` is not implemented for `NotClone` | note: required by a bound in `D::Assoc` - --> $DIR/defaults-suitability.rs:53:18 + --> $DIR/defaults-suitability.rs:56:18 | LL | Self::Assoc: IsU8, | ^^^^^^^^^^^^^^^^^ required by this bound in `D::Assoc` @@ -85,14 +85,14 @@ LL | type Assoc = NotClone; | ----- required by a bound in this associated type error[E0277]: the trait bound `>::Baz: Clone` is not satisfied - --> $DIR/defaults-suitability.rs:65:23 + --> $DIR/defaults-suitability.rs:68:23 | LL | type Bar: Clone = Vec; | ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `>::Baz`, which is required by `Vec<>::Baz>: Clone` | = note: required for `Vec<>::Baz>` to implement `Clone` note: required by a bound in `Foo2::Bar` - --> $DIR/defaults-suitability.rs:65:15 + --> $DIR/defaults-suitability.rs:68:15 | LL | type Bar: Clone = Vec; | ^^^^^ required by this bound in `Foo2::Bar` @@ -102,14 +102,14 @@ LL | trait Foo2 where >::Baz: Clone { | +++++++++++++++++++++++++++++++++++ error[E0277]: the trait bound `>::Baz: Clone` is not satisfied - --> $DIR/defaults-suitability.rs:74:23 + --> $DIR/defaults-suitability.rs:77:23 | LL | type Bar: Clone = Vec; | ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `>::Baz`, which is required by `Vec<>::Baz>: Clone` | = note: required for `Vec<>::Baz>` to implement `Clone` note: required by a bound in `Foo25::Bar` - --> $DIR/defaults-suitability.rs:74:15 + --> $DIR/defaults-suitability.rs:77:15 | LL | type Bar: Clone = Vec; | ^^^^^ required by this bound in `Foo25::Bar` @@ -119,13 +119,13 @@ LL | trait Foo25 where >::Baz: Clone { | ++++++++++++++++++++++++++++++++++++ error[E0277]: the trait bound `T: Clone` is not satisfied - --> $DIR/defaults-suitability.rs:87:16 + --> $DIR/defaults-suitability.rs:90:16 | LL | type Baz = T; | ^ the trait `Clone` is not implemented for `T` | note: required by a bound in `Foo3::Baz` - --> $DIR/defaults-suitability.rs:84:16 + --> $DIR/defaults-suitability.rs:87:16 | LL | Self::Baz: Clone, | ^^^^^ required by this bound in `Foo3::Baz` diff --git a/tests/ui/associated-types/defaults-suitability.next.stderr b/tests/ui/associated-types/defaults-suitability.next.stderr new file mode 100644 index 000000000000..3cdeaa93a340 --- /dev/null +++ b/tests/ui/associated-types/defaults-suitability.next.stderr @@ -0,0 +1,142 @@ +error[E0277]: the trait bound `NotClone: Clone` is not satisfied + --> $DIR/defaults-suitability.rs:16:22 + | +LL | type Ty: Clone = NotClone; + | ^^^^^^^^ the trait `Clone` is not implemented for `NotClone` + | +note: required by a bound in `Tr::Ty` + --> $DIR/defaults-suitability.rs:16:14 + | +LL | type Ty: Clone = NotClone; + | ^^^^^ required by this bound in `Tr::Ty` +help: consider annotating `NotClone` with `#[derive(Clone)]` + | +LL + #[derive(Clone)] +LL | struct NotClone; + | + +error[E0277]: the trait bound `NotClone: Clone` is not satisfied + --> $DIR/defaults-suitability.rs:25:15 + | +LL | type Ty = NotClone; + | ^^^^^^^^ the trait `Clone` is not implemented for `NotClone` + | +note: required by a bound in `Tr2::Ty` + --> $DIR/defaults-suitability.rs:23:15 + | +LL | Self::Ty: Clone, + | ^^^^^ required by this bound in `Tr2::Ty` +LL | { +LL | type Ty = NotClone; + | -- required by a bound in this associated type +help: consider annotating `NotClone` with `#[derive(Clone)]` + | +LL + #[derive(Clone)] +LL | struct NotClone; + | + +error[E0277]: the trait bound `T: Clone` is not satisfied + --> $DIR/defaults-suitability.rs:31:23 + | +LL | type Bar: Clone = Vec; + | ^^^^^^ the trait `Clone` is not implemented for `T`, which is required by `Vec: Clone` + | + = note: required for `Vec` to implement `Clone` +note: required by a bound in `Foo::Bar` + --> $DIR/defaults-suitability.rs:31:15 + | +LL | type Bar: Clone = Vec; + | ^^^^^ required by this bound in `Foo::Bar` +help: consider restricting type parameter `T` + | +LL | trait Foo { + | +++++++++++++++++++ + +error[E0277]: the trait bound `(): Foo` is not satisfied + --> $DIR/defaults-suitability.rs:37:29 + | +LL | type Assoc: Foo = (); + | ^^ the trait `Foo` is not implemented for `()` + | +help: this trait has no implementations, consider adding one + --> $DIR/defaults-suitability.rs:30:1 + | +LL | trait Foo { + | ^^^^^^^^^^^^ +note: required by a bound in `Bar::Assoc` + --> $DIR/defaults-suitability.rs:37:17 + | +LL | type Assoc: Foo = (); + | ^^^^^^^^^ required by this bound in `Bar::Assoc` + +error[E0277]: the trait bound `NotClone: IsU8` is not satisfied + --> $DIR/defaults-suitability.rs:59:18 + | +LL | type Assoc = NotClone; + | ^^^^^^^^ the trait `IsU8` is not implemented for `NotClone` + | +note: required by a bound in `D::Assoc` + --> $DIR/defaults-suitability.rs:56:18 + | +LL | Self::Assoc: IsU8, + | ^^^^^^^^^^^^^^^^^ required by this bound in `D::Assoc` +... +LL | type Assoc = NotClone; + | ----- required by a bound in this associated type + +error[E0277]: the trait bound `>::Baz: Clone` is not satisfied + --> $DIR/defaults-suitability.rs:68:23 + | +LL | type Bar: Clone = Vec; + | ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `>::Baz`, which is required by `Vec<>::Baz>: Clone` + | + = note: required for `Vec<>::Baz>` to implement `Clone` +note: required by a bound in `Foo2::Bar` + --> $DIR/defaults-suitability.rs:68:15 + | +LL | type Bar: Clone = Vec; + | ^^^^^ required by this bound in `Foo2::Bar` +help: consider further restricting the associated type + | +LL | trait Foo2 where >::Baz: Clone { + | +++++++++++++++++++++++++++++++++++ + +error[E0277]: the trait bound `>::Baz: Clone` is not satisfied + --> $DIR/defaults-suitability.rs:77:23 + | +LL | type Bar: Clone = Vec; + | ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `>::Baz`, which is required by `Vec<>::Baz>: Clone` + | + = note: required for `Vec<>::Baz>` to implement `Clone` +note: required by a bound in `Foo25::Bar` + --> $DIR/defaults-suitability.rs:77:15 + | +LL | type Bar: Clone = Vec; + | ^^^^^ required by this bound in `Foo25::Bar` +help: consider further restricting the associated type + | +LL | trait Foo25 where >::Baz: Clone { + | ++++++++++++++++++++++++++++++++++++ + +error[E0277]: the trait bound `T: Clone` is not satisfied + --> $DIR/defaults-suitability.rs:90:16 + | +LL | type Baz = T; + | ^ the trait `Clone` is not implemented for `T` + | +note: required by a bound in `Foo3::Baz` + --> $DIR/defaults-suitability.rs:87:16 + | +LL | Self::Baz: Clone, + | ^^^^^ required by this bound in `Foo3::Baz` +... +LL | type Baz = T; + | --- required by a bound in this associated type +help: consider further restricting type parameter `T` + | +LL | Self::Baz: Clone, T: std::clone::Clone + | ~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/defaults-suitability.rs b/tests/ui/associated-types/defaults-suitability.rs index 504c957d9875..bab2f004ac75 100644 --- a/tests/ui/associated-types/defaults-suitability.rs +++ b/tests/ui/associated-types/defaults-suitability.rs @@ -1,3 +1,6 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver //! Checks that associated type defaults are properly validated. //! //! This means: diff --git a/tests/ui/associated-types/issue-54108.stderr b/tests/ui/associated-types/issue-54108.current.stderr similarity index 93% rename from tests/ui/associated-types/issue-54108.stderr rename to tests/ui/associated-types/issue-54108.current.stderr index f300208fcc87..8850b4548e33 100644 --- a/tests/ui/associated-types/issue-54108.stderr +++ b/tests/ui/associated-types/issue-54108.current.stderr @@ -1,12 +1,12 @@ error[E0277]: cannot add `::ActualSize` to `::ActualSize` - --> $DIR/issue-54108.rs:19:17 + --> $DIR/issue-54108.rs:23:17 | LL | type Size = ::ActualSize; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `::ActualSize + ::ActualSize` | = help: the trait `Add` is not implemented for `::ActualSize` note: required by a bound in `Encoder::Size` - --> $DIR/issue-54108.rs:4:16 + --> $DIR/issue-54108.rs:8:16 | LL | type Size: Add; | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Encoder::Size` diff --git a/tests/ui/associated-types/issue-54108.next.stderr b/tests/ui/associated-types/issue-54108.next.stderr new file mode 100644 index 000000000000..9f6f00e7ca8f --- /dev/null +++ b/tests/ui/associated-types/issue-54108.next.stderr @@ -0,0 +1,33 @@ +error[E0271]: type mismatch resolving `<::ActualSize as Add>::Output == ::ActualSize` + --> $DIR/issue-54108.rs:23:17 + | +LL | type Size = ::ActualSize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ + | +note: required by a bound in `Encoder::Size` + --> $DIR/issue-54108.rs:8:20 + | +LL | type Size: Add; + | ^^^^^^^^^^^^^^^^^^^ required by this bound in `Encoder::Size` + +error[E0277]: cannot add `::ActualSize` to `::ActualSize` + --> $DIR/issue-54108.rs:23:17 + | +LL | type Size = ::ActualSize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `::ActualSize + ::ActualSize` + | + = help: the trait `Add` is not implemented for `::ActualSize` +note: required by a bound in `Encoder::Size` + --> $DIR/issue-54108.rs:8:16 + | +LL | type Size: Add; + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Encoder::Size` +help: consider further restricting the associated type + | +LL | T: SubEncoder, ::ActualSize: Add + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0271, E0277. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/associated-types/issue-54108.rs b/tests/ui/associated-types/issue-54108.rs index 87f67ce4b527..7c652fd7f49b 100644 --- a/tests/ui/associated-types/issue-54108.rs +++ b/tests/ui/associated-types/issue-54108.rs @@ -1,3 +1,7 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + use std::ops::Add; pub trait Encoder { @@ -18,6 +22,7 @@ where { type Size = ::ActualSize; //~^ ERROR: cannot add `::ActualSize` to `::ActualSize` + //[next]~| ERROR type mismatch resolving `<::ActualSize as Add>::Output == ::ActualSize` fn foo(&self) -> Self::Size { self.bar() + self.bar() diff --git a/tests/ui/associated-types/issue-63593.stderr b/tests/ui/associated-types/issue-63593.current.stderr similarity index 89% rename from tests/ui/associated-types/issue-63593.stderr rename to tests/ui/associated-types/issue-63593.current.stderr index 67151431a67a..76fdefeb4e52 100644 --- a/tests/ui/associated-types/issue-63593.stderr +++ b/tests/ui/associated-types/issue-63593.current.stderr @@ -1,11 +1,11 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation time - --> $DIR/issue-63593.rs:9:17 + --> $DIR/issue-63593.rs:13:17 | LL | type This = Self; | ^^^^ doesn't have a size known at compile-time | note: required by a bound in `MyTrait::This` - --> $DIR/issue-63593.rs:9:5 + --> $DIR/issue-63593.rs:13:5 | LL | type This = Self; | ^^^^^^^^^^^^^^^^^ required by this bound in `MyTrait::This` diff --git a/tests/ui/associated-types/issue-63593.next.stderr b/tests/ui/associated-types/issue-63593.next.stderr new file mode 100644 index 000000000000..76fdefeb4e52 --- /dev/null +++ b/tests/ui/associated-types/issue-63593.next.stderr @@ -0,0 +1,19 @@ +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/issue-63593.rs:13:17 + | +LL | type This = Self; + | ^^^^ doesn't have a size known at compile-time + | +note: required by a bound in `MyTrait::This` + --> $DIR/issue-63593.rs:13:5 + | +LL | type This = Self; + | ^^^^^^^^^^^^^^^^^ required by this bound in `MyTrait::This` +help: consider further restricting `Self` + | +LL | trait MyTrait: Sized { + | +++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/issue-63593.rs b/tests/ui/associated-types/issue-63593.rs index 8dbc24c06732..dea81f729b4e 100644 --- a/tests/ui/associated-types/issue-63593.rs +++ b/tests/ui/associated-types/issue-63593.rs @@ -1,3 +1,7 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + #![feature(associated_type_defaults)] // Tests that `Self` is not assumed to implement `Sized` when used as an diff --git a/tests/ui/generic-associated-types/issue-74816.stderr b/tests/ui/generic-associated-types/issue-74816.current.stderr similarity index 89% rename from tests/ui/generic-associated-types/issue-74816.stderr rename to tests/ui/generic-associated-types/issue-74816.current.stderr index 45018e6976cf..335486c6538c 100644 --- a/tests/ui/generic-associated-types/issue-74816.stderr +++ b/tests/ui/generic-associated-types/issue-74816.current.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `Self: Trait1` is not satisfied - --> $DIR/issue-74816.rs:8:31 + --> $DIR/issue-74816.rs:12:31 | LL | type Associated: Trait1 = Self; | ^^^^ the trait `Trait1` is not implemented for `Self` | note: required by a bound in `Trait2::Associated` - --> $DIR/issue-74816.rs:8:22 + --> $DIR/issue-74816.rs:12:22 | LL | type Associated: Trait1 = Self; | ^^^^^^ required by this bound in `Trait2::Associated` @@ -15,13 +15,13 @@ LL | trait Trait2: Trait1 { | ++++++++ error[E0277]: the size for values of type `Self` cannot be known at compilation time - --> $DIR/issue-74816.rs:8:31 + --> $DIR/issue-74816.rs:12:31 | LL | type Associated: Trait1 = Self; | ^^^^ doesn't have a size known at compile-time | note: required by a bound in `Trait2::Associated` - --> $DIR/issue-74816.rs:8:5 + --> $DIR/issue-74816.rs:12:5 | LL | type Associated: Trait1 = Self; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Trait2::Associated` diff --git a/tests/ui/generic-associated-types/issue-74816.next.stderr b/tests/ui/generic-associated-types/issue-74816.next.stderr new file mode 100644 index 000000000000..335486c6538c --- /dev/null +++ b/tests/ui/generic-associated-types/issue-74816.next.stderr @@ -0,0 +1,35 @@ +error[E0277]: the trait bound `Self: Trait1` is not satisfied + --> $DIR/issue-74816.rs:12:31 + | +LL | type Associated: Trait1 = Self; + | ^^^^ the trait `Trait1` is not implemented for `Self` + | +note: required by a bound in `Trait2::Associated` + --> $DIR/issue-74816.rs:12:22 + | +LL | type Associated: Trait1 = Self; + | ^^^^^^ required by this bound in `Trait2::Associated` +help: consider further restricting `Self` + | +LL | trait Trait2: Trait1 { + | ++++++++ + +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/issue-74816.rs:12:31 + | +LL | type Associated: Trait1 = Self; + | ^^^^ doesn't have a size known at compile-time + | +note: required by a bound in `Trait2::Associated` + --> $DIR/issue-74816.rs:12:5 + | +LL | type Associated: Trait1 = Self; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Trait2::Associated` +help: consider further restricting `Self` + | +LL | trait Trait2: Sized { + | +++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/issue-74816.rs b/tests/ui/generic-associated-types/issue-74816.rs index 344afb87f99c..e2f4ddc7485c 100644 --- a/tests/ui/generic-associated-types/issue-74816.rs +++ b/tests/ui/generic-associated-types/issue-74816.rs @@ -1,3 +1,7 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + #![feature(associated_type_defaults)] trait Trait1 { diff --git a/tests/ui/generic-associated-types/issue-74824.stderr b/tests/ui/generic-associated-types/issue-74824.current.stderr similarity index 90% rename from tests/ui/generic-associated-types/issue-74824.stderr rename to tests/ui/generic-associated-types/issue-74824.current.stderr index 942d9583be1b..b06c7f127ac0 100644 --- a/tests/ui/generic-associated-types/issue-74824.stderr +++ b/tests/ui/generic-associated-types/issue-74824.current.stderr @@ -1,17 +1,17 @@ error[E0277]: the trait bound `Box: Copy` is not satisfied - --> $DIR/issue-74824.rs:6:26 + --> $DIR/issue-74824.rs:10:26 | LL | type Copy: Copy = Box; | ^^^^^^ the trait `Copy` is not implemented for `Box` | note: required by a bound in `UnsafeCopy::Copy` - --> $DIR/issue-74824.rs:6:19 + --> $DIR/issue-74824.rs:10:19 | LL | type Copy: Copy = Box; | ^^^^ required by this bound in `UnsafeCopy::Copy` error[E0277]: the trait bound `T: Clone` is not satisfied - --> $DIR/issue-74824.rs:6:26 + --> $DIR/issue-74824.rs:10:26 | LL | type Copy: Copy = Box; | ^^^^^^ the trait `Clone` is not implemented for `T`, which is required by `::Copy: Copy` @@ -19,7 +19,7 @@ LL | type Copy: Copy = Box; = note: required for `Box` to implement `Clone` = note: required for `::Copy` to implement `Copy` note: required by a bound in `UnsafeCopy::Copy` - --> $DIR/issue-74824.rs:6:19 + --> $DIR/issue-74824.rs:10:19 | LL | type Copy: Copy = Box; | ^^^^ required by this bound in `UnsafeCopy::Copy` diff --git a/tests/ui/generic-associated-types/issue-74824.next.stderr b/tests/ui/generic-associated-types/issue-74824.next.stderr new file mode 100644 index 000000000000..b06c7f127ac0 --- /dev/null +++ b/tests/ui/generic-associated-types/issue-74824.next.stderr @@ -0,0 +1,33 @@ +error[E0277]: the trait bound `Box: Copy` is not satisfied + --> $DIR/issue-74824.rs:10:26 + | +LL | type Copy: Copy = Box; + | ^^^^^^ the trait `Copy` is not implemented for `Box` + | +note: required by a bound in `UnsafeCopy::Copy` + --> $DIR/issue-74824.rs:10:19 + | +LL | type Copy: Copy = Box; + | ^^^^ required by this bound in `UnsafeCopy::Copy` + +error[E0277]: the trait bound `T: Clone` is not satisfied + --> $DIR/issue-74824.rs:10:26 + | +LL | type Copy: Copy = Box; + | ^^^^^^ the trait `Clone` is not implemented for `T`, which is required by `::Copy: Copy` + | + = note: required for `Box` to implement `Clone` + = note: required for `::Copy` to implement `Copy` +note: required by a bound in `UnsafeCopy::Copy` + --> $DIR/issue-74824.rs:10:19 + | +LL | type Copy: Copy = Box; + | ^^^^ required by this bound in `UnsafeCopy::Copy` +help: consider restricting type parameter `T` + | +LL | type Copy: Copy = Box; + | +++++++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/issue-74824.rs b/tests/ui/generic-associated-types/issue-74824.rs index 10c45d133642..7cfb862abed0 100644 --- a/tests/ui/generic-associated-types/issue-74824.rs +++ b/tests/ui/generic-associated-types/issue-74824.rs @@ -1,3 +1,7 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + #![feature(associated_type_defaults)] use std::ops::Deref; From 34c56c45cff1d0029dafd7d19c524975292382af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Mon, 27 May 2024 23:53:46 +0200 Subject: [PATCH 106/211] Rename HIR `TypeBinding` to `AssocItemConstraint` and related cleanup --- compiler/rustc_ast/src/ast.rs | 43 +++-- compiler/rustc_ast/src/mut_visit.rs | 14 +- compiler/rustc_ast/src/visit.rs | 17 +- compiler/rustc_ast_lowering/src/index.rs | 8 +- compiler/rustc_ast_lowering/src/lib.rs | 51 +++-- compiler/rustc_ast_lowering/src/path.rs | 31 +-- .../rustc_ast_passes/src/ast_validation.rs | 16 +- compiler/rustc_ast_passes/src/feature_gate.rs | 32 ++-- compiler/rustc_ast_passes/src/node_count.rs | 4 +- compiler/rustc_ast_pretty/src/pprust/state.rs | 8 +- .../src/diagnostics/region_name.rs | 12 +- .../src/error_codes/E0229.md | 13 +- compiler/rustc_hir/src/hir.rs | 178 +++++++++++------- compiler/rustc_hir/src/intravisit.rs | 27 +-- compiler/rustc_hir_analysis/messages.ftl | 8 +- .../src/collect/resolve_bound_vars.rs | 33 ++-- .../rustc_hir_analysis/src/collect/type_of.rs | 5 +- compiler/rustc_hir_analysis/src/errors.rs | 4 +- .../src/hir_ty_lowering/bounds.rs | 78 ++++---- .../src/hir_ty_lowering/errors.rs | 98 +++++----- .../src/hir_ty_lowering/generics.rs | 30 +-- .../src/hir_ty_lowering/lint.rs | 10 +- .../src/hir_ty_lowering/mod.rs | 75 ++++---- .../wrong_number_of_generic_args.rs | 12 +- compiler/rustc_hir_pretty/src/lib.rs | 26 +-- .../src/fn_ctxt/suggestions.rs | 14 +- compiler/rustc_middle/src/hir/map/mod.rs | 4 +- compiler/rustc_parse/src/parser/path.rs | 33 ++-- compiler/rustc_passes/src/hir_stats.rs | 8 +- compiler/rustc_resolve/src/late.rs | 6 +- .../rustc_resolve/src/late/diagnostics.rs | 6 +- .../src/traits/error_reporting/suggestions.rs | 12 +- src/librustdoc/clean/auto_trait.rs | 4 +- src/librustdoc/clean/blanket_impl.rs | 4 +- src/librustdoc/clean/inline.rs | 6 +- src/librustdoc/clean/mod.rs | 79 ++++---- src/librustdoc/clean/simplify.rs | 6 +- src/librustdoc/clean/types.rs | 47 +++-- src/librustdoc/clean/utils.rs | 25 +-- src/librustdoc/html/format.rs | 16 +- src/librustdoc/html/render/search_index.rs | 46 ++--- src/librustdoc/json/conversions.rs | 22 +-- .../src/implied_bounds_in_impls.rs | 54 +++--- src/tools/clippy/clippy_lints/src/len_zero.rs | 17 +- .../clippy_lints/src/manual_async_fn.rs | 10 +- .../clippy/clippy_utils/src/ast_utils.rs | 6 +- .../clippy/clippy_utils/src/hir_utils.rs | 8 +- src/tools/rustfmt/src/types.rs | 12 +- tests/rustdoc-ui/invalid_associated_const.rs | 4 +- .../invalid_associated_const.stderr | 12 +- tests/rustdoc-ui/issue-102467.rs | 4 +- tests/rustdoc-ui/issue-102467.stderr | 12 +- .../associated-consts/issue-102335-const.rs | 4 +- .../issue-102335-const.stderr | 12 +- .../associated-type-bounds/issue-102335-ty.rs | 8 +- .../issue-102335-ty.stderr | 24 +-- .../associated-type-bounds/no-gat-position.rs | 2 +- .../no-gat-position.stderr | 4 +- .../associated-types/associated-types-eq-2.rs | 24 +-- .../associated-types-eq-2.stderr | 64 +++---- .../associated-types-eq-expr-path.rs | 4 +- .../associated-types-eq-expr-path.stderr | 6 +- .../rtn-in-impl-signature.rs | 2 +- .../rtn-in-impl-signature.stderr | 4 +- .../issue-89013-no-kw.rs | 2 +- .../issue-89013-no-kw.stderr | 4 +- .../parser-error-recovery/issue-89013.rs | 2 +- .../parser-error-recovery/issue-89013.stderr | 4 +- tests/ui/error-codes/E0229.rs | 8 +- tests/ui/error-codes/E0229.stderr | 50 ++--- ...ture-gate-unboxed-closures-manual-impls.rs | 2 +- ...-gate-unboxed-closures-manual-impls.stderr | 4 +- tests/ui/fn/issue-39259.rs | 2 +- tests/ui/fn/issue-39259.stderr | 4 +- .../issue-102335-gat.rs | 4 +- .../issue-102335-gat.stderr | 12 +- tests/ui/issues/issue-23543.rs | 2 +- tests/ui/issues/issue-23543.stderr | 4 +- tests/ui/issues/issue-23544.rs | 2 +- tests/ui/issues/issue-23544.stderr | 4 +- tests/ui/issues/issue-24682.rs | 6 +- tests/ui/issues/issue-24682.stderr | 12 +- tests/ui/issues/issue-39687.rs | 2 +- tests/ui/issues/issue-39687.stderr | 4 +- tests/ui/issues/issue-43431.rs | 2 +- tests/ui/issues/issue-43431.stderr | 4 +- ...invalid-associated-type-supertrait-hrtb.rs | 2 +- ...lid-associated-type-supertrait-hrtb.stderr | 6 +- tests/ui/lifetimes/issue-95023.rs | 2 +- tests/ui/lifetimes/issue-95023.stderr | 4 +- tests/ui/methods/method-call-type-binding.rs | 2 +- .../methods/method-call-type-binding.stderr | 4 +- tests/ui/suggestions/issue-85347.rs | 8 +- tests/ui/suggestions/issue-85347.stderr | 12 +- ...type-ascription-instead-of-path-in-type.rs | 2 +- ...-ascription-instead-of-path-in-type.stderr | 4 +- tests/ui/traits/issue-87558.rs | 2 +- tests/ui/traits/issue-87558.stderr | 4 +- .../bad_const_generics_args_on_const_param.rs | 2 +- ..._const_generics_args_on_const_param.stderr | 4 +- tests/ui/typeck/escaping_bound_vars.rs | 2 +- tests/ui/typeck/escaping_bound_vars.stderr | 4 +- tests/ui/typeck/issue-83693.rs | 4 +- tests/ui/typeck/issue-83693.stderr | 8 +- tests/ui/typeck/issue-84768.rs | 2 +- tests/ui/typeck/issue-84768.stderr | 4 +- tests/ui/typeck/issue-91267.rs | 2 +- tests/ui/typeck/issue-91267.stderr | 4 +- 108 files changed, 878 insertions(+), 818 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 1a166956075c..8e801ebc2f91 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -167,7 +167,7 @@ impl PathSegment { } } -/// The arguments of a path segment. +/// The generic arguments and associated item constraints of a path segment. /// /// E.g., `` as in `Foo` or `(A, B)` as in `Foo(A, B)`. #[derive(Clone, Encodable, Decodable, Debug)] @@ -221,14 +221,13 @@ pub struct AngleBracketedArgs { pub args: ThinVec, } -/// Either an argument for a parameter e.g., `'a`, `Vec`, `0`, -/// or a constraint on an associated item, e.g., `Item = String` or `Item: Bound`. +/// Either an argument for a generic parameter or a constraint on an associated item. #[derive(Clone, Encodable, Decodable, Debug)] pub enum AngleBracketedArg { - /// Argument for a generic parameter. + /// A generic argument for a generic parameter. Arg(GenericArg), - /// Constraint for an associated item. - Constraint(AssocConstraint), + /// A constraint on an associated item. + Constraint(AssocItemConstraint), } impl AngleBracketedArg { @@ -418,7 +417,7 @@ impl Default for WhereClause { /// A single predicate in a where-clause. #[derive(Clone, Encodable, Decodable, Debug)] pub enum WherePredicate { - /// A type binding (e.g., `for<'c> Foo: Send + Clone + 'c`). + /// A type bound (e.g., `for<'c> Foo: Send + Clone + 'c`). BoundPredicate(WhereBoundPredicate), /// A lifetime predicate (e.g., `'a: 'b + 'c`). RegionPredicate(WhereRegionPredicate), @@ -2034,18 +2033,25 @@ impl UintTy { } } -/// A constraint on an associated type (e.g., `A = Bar` in `Foo` or -/// `A: TraitA + TraitB` in `Foo`). +/// A constraint on an associated item. +/// +/// ### Examples +/// +/// * the `A = Ty` and `B = Ty` in `Trait` +/// * the `G = Ty` in `Trait = Ty>` +/// * the `A: Bound` in `Trait` +/// * the `RetTy` in `Trait(ArgTy, ArgTy) -> RetTy` +/// * the `C = { Ct }` in `Trait` (feature `associated_const_equality`) +/// * the `f(): Bound` in `Trait` (feature `return_type_notation`) #[derive(Clone, Encodable, Decodable, Debug)] -pub struct AssocConstraint { +pub struct AssocItemConstraint { pub id: NodeId, pub ident: Ident, pub gen_args: Option, - pub kind: AssocConstraintKind, + pub kind: AssocItemConstraintKind, pub span: Span, } -/// The kinds of an `AssocConstraint`. #[derive(Clone, Encodable, Decodable, Debug)] pub enum Term { Ty(P), @@ -2064,12 +2070,17 @@ impl From for Term { } } -/// The kinds of an `AssocConstraint`. +/// The kind of [associated item constraint][AssocItemConstraint]. #[derive(Clone, Encodable, Decodable, Debug)] -pub enum AssocConstraintKind { - /// E.g., `A = Bar`, `A = 3` in `Foo` where A is an associated type. +pub enum AssocItemConstraintKind { + /// An equality constraint for an associated item (e.g., `AssocTy = Ty` in `Trait`). + /// + /// Also known as an *associated item binding* (we *bind* an associated item to a term). + /// + /// Furthermore, associated type equality constraints can also be referred to as *associated type + /// bindings*. Similarly with associated const equality constraints and *associated const bindings*. Equality { term: Term }, - /// E.g. `A: TraitA + TraitB` in `Foo`. + /// A bound on an associated type (e.g., `AssocTy: Bound` in `Trait`). Bound { bounds: GenericBounds }, } diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 566b20c490ef..635f0f034503 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -175,8 +175,8 @@ pub trait MutVisitor: Sized { noop_visit_lifetime(l, self); } - fn visit_constraint(&mut self, t: &mut AssocConstraint) { - noop_visit_constraint(t, self); + fn visit_assoc_item_constraint(&mut self, c: &mut AssocItemConstraint) { + noop_visit_assoc_item_constraint(c, self); } fn visit_foreign_mod(&mut self, nm: &mut ForeignMod) { @@ -463,8 +463,8 @@ pub fn noop_flat_map_arm(mut arm: Arm, vis: &mut T) -> SmallVec<[ smallvec![arm] } -fn noop_visit_constraint( - AssocConstraint { id, ident, gen_args, kind, span }: &mut AssocConstraint, +fn noop_visit_assoc_item_constraint( + AssocItemConstraint { id, ident, gen_args, kind, span }: &mut AssocItemConstraint, vis: &mut T, ) { vis.visit_id(id); @@ -473,11 +473,11 @@ fn noop_visit_constraint( vis.visit_generic_args(gen_args); } match kind { - AssocConstraintKind::Equality { term } => match term { + AssocItemConstraintKind::Equality { term } => match term { Term::Ty(ty) => vis.visit_ty(ty), Term::Const(c) => vis.visit_anon_const(c), }, - AssocConstraintKind::Bound { bounds } => visit_bounds(bounds, vis), + AssocItemConstraintKind::Bound { bounds } => visit_bounds(bounds, vis), } vis.visit_span(span); } @@ -607,7 +607,7 @@ fn noop_visit_angle_bracketed_parameter_data( let AngleBracketedArgs { args, span } = data; visit_thin_vec(args, |arg| match arg { AngleBracketedArg::Arg(arg) => vis.visit_generic_arg(arg), - AngleBracketedArg::Constraint(constraint) => vis.visit_constraint(constraint), + AngleBracketedArg::Constraint(constraint) => vis.visit_assoc_item_constraint(constraint), }); vis.visit_span(span); } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 93de42b55cc3..e5ce9419e16e 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -246,8 +246,11 @@ pub trait Visitor<'ast>: Sized { fn visit_generic_arg(&mut self, generic_arg: &'ast GenericArg) -> Self::Result { walk_generic_arg(self, generic_arg) } - fn visit_assoc_constraint(&mut self, constraint: &'ast AssocConstraint) -> Self::Result { - walk_assoc_constraint(self, constraint) + fn visit_assoc_item_constraint( + &mut self, + constraint: &'ast AssocItemConstraint, + ) -> Self::Result { + walk_assoc_item_constraint(self, constraint) } fn visit_attribute(&mut self, attr: &'ast Attribute) -> Self::Result { walk_attribute(self, attr) @@ -558,7 +561,7 @@ where match arg { AngleBracketedArg::Arg(a) => try_visit!(visitor.visit_generic_arg(a)), AngleBracketedArg::Constraint(c) => { - try_visit!(visitor.visit_assoc_constraint(c)) + try_visit!(visitor.visit_assoc_item_constraint(c)) } } } @@ -582,18 +585,18 @@ where } } -pub fn walk_assoc_constraint<'a, V: Visitor<'a>>( +pub fn walk_assoc_item_constraint<'a, V: Visitor<'a>>( visitor: &mut V, - constraint: &'a AssocConstraint, + constraint: &'a AssocItemConstraint, ) -> V::Result { try_visit!(visitor.visit_ident(constraint.ident)); visit_opt!(visitor, visit_generic_args, &constraint.gen_args); match &constraint.kind { - AssocConstraintKind::Equality { term } => match term { + AssocItemConstraintKind::Equality { term } => match term { Term::Ty(ty) => try_visit!(visitor.visit_ty(ty)), Term::Const(c) => try_visit!(visitor.visit_anon_const(c)), }, - AssocConstraintKind::Bound { bounds } => { + AssocItemConstraintKind::Bound { bounds } => { walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); } } diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index 7254be2b2f42..44f37b5533a6 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -333,10 +333,10 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { }); } - fn visit_assoc_type_binding(&mut self, type_binding: &'hir TypeBinding<'hir>) { - self.insert(type_binding.span, type_binding.hir_id, Node::TypeBinding(type_binding)); - self.with_parent(type_binding.hir_id, |this| { - intravisit::walk_assoc_type_binding(this, type_binding) + fn visit_assoc_item_constraint(&mut self, constraint: &'hir AssocItemConstraint<'hir>) { + self.insert(constraint.span, constraint.hir_id, Node::AssocItemConstraint(constraint)); + self.with_parent(constraint.hir_id, |this| { + intravisit::walk_assoc_item_constraint(this, constraint) }) } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index a9af5ad74592..201dffb629a1 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -961,24 +961,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { DelimArgs { dspan: args.dspan, delim: args.delim, tokens: args.tokens.flattened() } } - /// Given an associated type constraint like one of these: - /// - /// ```ignore (illustrative) - /// T: Iterator - /// ^^^^^^^^^^^ - /// T: Iterator - /// ^^^^^^^^^^^^ - /// ``` - /// - /// returns a `hir::TypeBinding` representing `Item`. - #[instrument(level = "debug", skip(self))] - fn lower_assoc_ty_constraint( + /// Lower an associated item constraint. + #[instrument(level = "debug", skip_all)] + fn lower_assoc_item_constraint( &mut self, - constraint: &AssocConstraint, + constraint: &AssocItemConstraint, itctx: ImplTraitContext, - ) -> hir::TypeBinding<'hir> { - debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", constraint, itctx); - // lower generic arguments of identifier in constraint + ) -> hir::AssocItemConstraint<'hir> { + debug!(?constraint, ?itctx); + // Lower the generic arguments for the associated item. let gen_args = if let Some(gen_args) = &constraint.gen_args { let gen_args_ctor = match gen_args { GenericArgs::AngleBracketed(data) => { @@ -994,7 +985,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }; GenericArgsCtor { args: Default::default(), - bindings: &[], + constraints: &[], parenthesized, span: data.inputs_span, } @@ -1024,7 +1015,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { err.emit(); GenericArgsCtor { args: Default::default(), - bindings: &[], + constraints: &[], parenthesized: hir::GenericArgsParentheses::ReturnTypeNotation, span: data.span, } @@ -1046,14 +1037,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.arena.alloc(hir::GenericArgs::none()) }; let kind = match &constraint.kind { - AssocConstraintKind::Equality { term } => { + AssocItemConstraintKind::Equality { term } => { let term = match term { Term::Ty(ty) => self.lower_ty(ty, itctx).into(), Term::Const(c) => self.lower_anon_const(c).into(), }; - hir::TypeBindingKind::Equality { term } + hir::AssocItemConstraintKind::Equality { term } } - AssocConstraintKind::Bound { bounds } => { + AssocItemConstraintKind::Bound { bounds } => { // Disallow ATB in dyn types if self.is_in_dyn_type { let suggestion = match itctx { @@ -1077,18 +1068,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }); let err_ty = &*self.arena.alloc(self.ty(constraint.span, hir::TyKind::Err(guar))); - hir::TypeBindingKind::Equality { term: err_ty.into() } + hir::AssocItemConstraintKind::Equality { term: err_ty.into() } } else { - // Desugar `AssocTy: Bounds` into a type binding where the + // Desugar `AssocTy: Bounds` into an assoc type binding where the // later desugars into a trait predicate. let bounds = self.lower_param_bounds(bounds, itctx); - hir::TypeBindingKind::Constraint { bounds } + hir::AssocItemConstraintKind::Bound { bounds } } } }; - hir::TypeBinding { + hir::AssocItemConstraint { hir_id: self.lower_node_id(constraint.id), ident: self.lower_ident(constraint.ident), gen_args, @@ -2008,7 +1999,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let bound_args = self.arena.alloc(hir::GenericArgs { args: &[], - bindings: arena_vec![self; self.assoc_ty_binding(assoc_ty_name, opaque_ty_span, output_ty)], + constraints: arena_vec![self; self.assoc_ty_binding(assoc_ty_name, opaque_ty_span, output_ty)], parenthesized: hir::GenericArgsParentheses::No, span_ext: DUMMY_SP, }); @@ -2581,10 +2572,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } -/// Helper struct for delayed construction of GenericArgs. +/// Helper struct for the delayed construction of [`hir::GenericArgs`]. struct GenericArgsCtor<'hir> { args: SmallVec<[hir::GenericArg<'hir>; 4]>, - bindings: &'hir [hir::TypeBinding<'hir>], + constraints: &'hir [hir::AssocItemConstraint<'hir>], parenthesized: hir::GenericArgsParentheses, span: Span, } @@ -2664,14 +2655,14 @@ impl<'hir> GenericArgsCtor<'hir> { fn is_empty(&self) -> bool { self.args.is_empty() - && self.bindings.is_empty() + && self.constraints.is_empty() && self.parenthesized == hir::GenericArgsParentheses::No } fn into_generic_args(self, this: &LoweringContext<'_, 'hir>) -> &'hir hir::GenericArgs<'hir> { let ga = hir::GenericArgs { args: this.arena.alloc_from_iter(self.args), - bindings: self.bindings, + constraints: self.constraints, parenthesized: self.parenthesized, span_ext: this.lower_span(self.span), }; diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 7679424dceb9..9d38e1e67847 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -281,7 +281,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ( GenericArgsCtor { args: Default::default(), - bindings: &[], + constraints: &[], parenthesized: hir::GenericArgsParentheses::No, span: path_span.shrink_to_hi(), }, @@ -390,13 +390,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { AngleBracketedArg::Constraint(_) => None, }) .collect(); - let bindings = self.arena.alloc_from_iter(data.args.iter().filter_map(|arg| match arg { - AngleBracketedArg::Constraint(c) => Some(self.lower_assoc_ty_constraint(c, itctx)), - AngleBracketedArg::Arg(_) => None, - })); + let constraints = + self.arena.alloc_from_iter(data.args.iter().filter_map(|arg| match arg { + AngleBracketedArg::Constraint(c) => { + Some(self.lower_assoc_item_constraint(c, itctx)) + } + AngleBracketedArg::Arg(_) => None, + })); let ctor = GenericArgsCtor { args, - bindings, + constraints, parenthesized: hir::GenericArgsParentheses::No, span: data.span, }; @@ -454,12 +457,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { Some(bound_modifier_allowed_features), ); } - let binding = self.assoc_ty_binding(sym::Output, output_span, output_ty); + let constraint = self.assoc_ty_binding(sym::Output, output_span, output_ty); ( GenericArgsCtor { args, - bindings: arena_vec![self; binding], + constraints: arena_vec![self; constraint], parenthesized: hir::GenericArgsParentheses::ParenSugar, span: data.inputs_span, }, @@ -467,24 +470,24 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) } - /// An associated type binding `$assoc_ty_name = $ty`. + /// An associated type binding (i.e., associated type equality constraint). pub(crate) fn assoc_ty_binding( &mut self, assoc_ty_name: rustc_span::Symbol, span: Span, ty: &'hir hir::Ty<'hir>, - ) -> hir::TypeBinding<'hir> { + ) -> hir::AssocItemConstraint<'hir> { let ident = Ident::with_dummy_span(assoc_ty_name); - let kind = hir::TypeBindingKind::Equality { term: ty.into() }; + let kind = hir::AssocItemConstraintKind::Equality { term: ty.into() }; let args = arena_vec![self;]; - let bindings = arena_vec![self;]; + let constraints = arena_vec![self;]; let gen_args = self.arena.alloc(hir::GenericArgs { args, - bindings, + constraints, parenthesized: hir::GenericArgsParentheses::No, span_ext: DUMMY_SP, }); - hir::TypeBinding { + hir::AssocItemConstraint { hir_id: self.next_id(), gen_args, span: self.lower_span(span), diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index c57be3cdf353..3dfa5dde9492 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -673,7 +673,7 @@ impl<'a> AstValidator<'a> { let constraint_sugg = data.args.iter().filter_map(|a| match a { AngleBracketedArg::Arg(_) => None, AngleBracketedArg::Constraint(c) => { - Some(pprust::to_string(|s| s.print_assoc_constraint(c))) + Some(pprust::to_string(|s| s.print_assoc_item_constraint(c))) } }); format!( @@ -1201,11 +1201,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> { for arg in &data.args { match arg { AngleBracketedArg::Arg(arg) => self.visit_generic_arg(arg), - // Type bindings such as `Item = impl Debug` in `Iterator` - // are allowed to contain nested `impl Trait`. + // Associated type bindings such as `Item = impl Debug` in + // `Iterator` are allowed to contain nested `impl Trait`. AngleBracketedArg::Constraint(constraint) => { self.with_impl_trait(None, |this| { - this.visit_assoc_constraint(constraint); + this.visit_assoc_item_constraint(constraint); }); } } @@ -1365,7 +1365,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } } } - // The lowered form of parenthesized generic args contains a type binding. + // The lowered form of parenthesized generic args contains an associated type binding. Some(ast::GenericArgs::Parenthesized(args)) => { self.dcx().emit_err(errors::NegativeBoundWithParentheticalNotation { span: args.span, @@ -1591,11 +1591,13 @@ fn deny_equality_constraints( let len = assoc_path.segments.len() - 1; let gen_args = args.as_deref().cloned(); // Build ``. - let arg = AngleBracketedArg::Constraint(AssocConstraint { + let arg = AngleBracketedArg::Constraint(AssocItemConstraint { id: rustc_ast::node_id::DUMMY_NODE_ID, ident: *ident, gen_args, - kind: AssocConstraintKind::Equality { term: predicate.rhs_ty.clone().into() }, + kind: AssocItemConstraintKind::Equality { + term: predicate.rhs_ty.clone().into(), + }, span: ident.span, }); // Add `` to `Foo`. diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index a522f04b21db..a9dca9b6a293 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -1,6 +1,6 @@ use rustc_ast as ast; use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor}; -use rustc_ast::{attr, AssocConstraint, AssocConstraintKind, NodeId}; +use rustc_ast::{attr, AssocItemConstraint, AssocItemConstraintKind, NodeId}; use rustc_ast::{token, PatKind}; use rustc_feature::{AttributeGate, BuiltinAttribute, Features, GateIssue, BUILTIN_ATTRIBUTE_MAP}; use rustc_session::parse::{feature_err, feature_err_issue, feature_warn}; @@ -344,7 +344,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { for predicate in &g.where_clause.predicates { match predicate { ast::WherePredicate::BoundPredicate(bound_pred) => { - // A type binding, eg `for<'c> Foo: Send+Clone+'c` + // A type bound (e.g., `for<'c> Foo: Send + Clone + 'c`). self.check_late_bound_lifetime_defs(&bound_pred.bound_generic_params); } _ => {} @@ -445,21 +445,21 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { visit::walk_fn(self, fn_kind) } - fn visit_assoc_constraint(&mut self, constraint: &'a AssocConstraint) { - if let AssocConstraintKind::Bound { .. } = constraint.kind { - if let Some(ast::GenericArgs::Parenthesized(args)) = constraint.gen_args.as_ref() - && args.inputs.is_empty() - && matches!(args.output, ast::FnRetTy::Default(..)) - { - gate!( - &self, - return_type_notation, - constraint.span, - "return type notation is experimental" - ); - } + fn visit_assoc_item_constraint(&mut self, constraint: &'a AssocItemConstraint) { + if let AssocItemConstraintKind::Bound { .. } = constraint.kind + && let Some(ast::GenericArgs::Parenthesized(args)) = constraint.gen_args.as_ref() + && args.inputs.is_empty() + && let ast::FnRetTy::Default(..) = args.output + { + gate!( + &self, + return_type_notation, + constraint.span, + "return type notation is experimental" + ); } - visit::walk_assoc_constraint(self, constraint) + + visit::walk_assoc_item_constraint(self, constraint) } fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) { diff --git a/compiler/rustc_ast_passes/src/node_count.rs b/compiler/rustc_ast_passes/src/node_count.rs index 2128acba0bab..c61640de6f79 100644 --- a/compiler/rustc_ast_passes/src/node_count.rs +++ b/compiler/rustc_ast_passes/src/node_count.rs @@ -119,9 +119,9 @@ impl<'ast> Visitor<'ast> for NodeCounter { self.count += 1; walk_generic_args(self, generic_args) } - fn visit_assoc_constraint(&mut self, constraint: &AssocConstraint) { + fn visit_assoc_item_constraint(&mut self, constraint: &AssocItemConstraint) { self.count += 1; - walk_assoc_constraint(self, constraint) + walk_assoc_item_constraint(self, constraint) } fn visit_attribute(&mut self, _attr: &Attribute) { self.count += 1; diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index f02fe4cf0a72..4c29ca0ca465 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1045,7 +1045,7 @@ impl<'a> PrintState<'a> for State<'a> { self.word("<"); self.commasep(Inconsistent, &data.args, |s, arg| match arg { ast::AngleBracketedArg::Arg(a) => s.print_generic_arg(a), - ast::AngleBracketedArg::Constraint(c) => s.print_assoc_constraint(c), + ast::AngleBracketedArg::Constraint(c) => s.print_assoc_item_constraint(c), }); self.word(">") } @@ -1097,21 +1097,21 @@ impl<'a> State<'a> { } } - pub fn print_assoc_constraint(&mut self, constraint: &ast::AssocConstraint) { + pub fn print_assoc_item_constraint(&mut self, constraint: &ast::AssocItemConstraint) { self.print_ident(constraint.ident); if let Some(args) = constraint.gen_args.as_ref() { self.print_generic_args(args, false) } self.space(); match &constraint.kind { - ast::AssocConstraintKind::Equality { term } => { + ast::AssocItemConstraintKind::Equality { term } => { self.word_space("="); match term { Term::Ty(ty) => self.print_type(ty), Term::Const(c) => self.print_expr_anon_const(c, &[]), } } - ast::AssocConstraintKind::Bound { bounds } => { + ast::AssocItemConstraintKind::Bound { bounds } => { if !bounds.is_empty() { self.word_nbsp(":"); self.print_type_bounds(bounds); diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 46011c1f43ec..07f4a385b611 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -12,7 +12,7 @@ use rustc_middle::ty::print::RegionHighlightMode; use rustc_middle::ty::{self, RegionVid, Ty}; use rustc_middle::ty::{GenericArgKind, GenericArgsRef}; use rustc_middle::{bug, span_bug}; -use rustc_span::symbol::{kw, sym, Ident, Symbol}; +use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::{Span, DUMMY_SP}; use crate::{universal_regions::DefiningTy, MirBorrowckCtxt}; @@ -842,13 +842,9 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { }) = opaque_ty.kind && let Some(segment) = trait_ref.trait_ref.path.segments.last() && let Some(args) = segment.args - && let [ - hir::TypeBinding { - ident: Ident { name: sym::Output, .. }, - kind: hir::TypeBindingKind::Equality { term: hir::Term::Ty(ty) }, - .. - }, - ] = args.bindings + && let [constraint] = args.constraints + && constraint.ident.name == sym::Output + && let Some(ty) = constraint.ty() { ty } else { diff --git a/compiler/rustc_error_codes/src/error_codes/E0229.md b/compiler/rustc_error_codes/src/error_codes/E0229.md index a8fab057d43a..f4a983cb9efc 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0229.md +++ b/compiler/rustc_error_codes/src/error_codes/E0229.md @@ -1,5 +1,4 @@ -An associated type binding was done outside of the type parameter declaration -and `where` clause. +An associated item constraint was written in an unexpected context. Erroneous code example: @@ -16,12 +15,12 @@ impl Foo for isize { fn boo(&self) -> usize { 42 } } -fn baz(x: &>::A) {} -// error: associated type bindings are not allowed here +fn baz(x: &>::A) {} +// error: associated item constraint are not allowed here ``` -To solve this error, please move the type bindings in the type parameter -declaration: +To solve this error, please move the associated item constraints to the type +parameter declaration: ``` # struct Bar; @@ -29,7 +28,7 @@ declaration: fn baz>(x: &::A) {} // ok! ``` -Or in the `where` clause: +Or into the where-clause: ``` # struct Bar; diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 2f4dcdbdf2b1..ed344255a5ed 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -300,23 +300,30 @@ impl GenericArg<'_> { } } +/// The generic arguments and associated item constraints of a path segment. #[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct GenericArgs<'hir> { /// The generic arguments for this path segment. pub args: &'hir [GenericArg<'hir>], - /// Bindings (equality constraints) on associated types, if present. - /// E.g., `Foo`. - pub bindings: &'hir [TypeBinding<'hir>], - /// Were arguments written in parenthesized form `Fn(T) -> U`? + /// The associated item constraints for this path segment. + pub constraints: &'hir [AssocItemConstraint<'hir>], + /// Whether the arguments were written in parenthesized form (e.g., `Fn(T) -> U`). + /// /// This is required mostly for pretty-printing and diagnostics, /// but also for changing lifetime elision rules to be "function-like". pub parenthesized: GenericArgsParentheses, - /// The span encompassing arguments and the surrounding brackets `<>` or `()` + /// The span encompassing the arguments, constraints and the surrounding brackets (`<>` or `()`). + /// + /// For example: + /// + /// ```ignore (illustrative) /// Foo Fn(T, U, V) -> W /// ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ + /// ``` + /// /// Note that this may be: /// - empty, if there are no generic brackets (but there may be hidden lifetimes) - /// - dummy, if this was generated while desugaring + /// - dummy, if this was generated during desugaring pub span_ext: Span, } @@ -324,39 +331,63 @@ impl<'hir> GenericArgs<'hir> { pub const fn none() -> Self { Self { args: &[], - bindings: &[], + constraints: &[], parenthesized: GenericArgsParentheses::No, span_ext: DUMMY_SP, } } - pub fn inputs(&self) -> &[Ty<'hir>] { - if self.parenthesized == GenericArgsParentheses::ParenSugar { - for arg in self.args { - match arg { - GenericArg::Lifetime(_) => {} - GenericArg::Type(ref ty) => { - if let TyKind::Tup(ref tys) = ty.kind { - return tys; - } - break; - } - GenericArg::Const(_) => {} - GenericArg::Infer(_) => {} - } - } + /// Obtain the list of input types and the output type if the generic arguments are parenthesized. + /// + /// Returns the `Ty0, Ty1, ...` and the `RetTy` in `Trait(Ty0, Ty1, ...) -> RetTy`. + /// Panics if the parenthesized arguments have an incorrect form (this shouldn't happen). + pub fn paren_sugar_inputs_output(&self) -> Option<(&[Ty<'hir>], &Ty<'hir>)> { + if self.parenthesized != GenericArgsParentheses::ParenSugar { + return None; } - panic!("GenericArgs::inputs: not a `Fn(T) -> U`"); + + let inputs = self + .args + .iter() + .find_map(|arg| { + let GenericArg::Type(ty) = arg else { return None }; + let TyKind::Tup(tys) = &ty.kind else { return None }; + Some(tys) + }) + .unwrap(); + + Some((inputs, self.paren_sugar_output_inner())) } - pub fn has_err(&self) -> bool { - self.args.iter().any(|arg| match arg { - GenericArg::Type(ty) => matches!(ty.kind, TyKind::Err(_)), - _ => false, - }) || self.bindings.iter().any(|arg| match arg.kind { - TypeBindingKind::Equality { term: Term::Ty(ty) } => matches!(ty.kind, TyKind::Err(_)), - _ => false, - }) + /// Obtain the output type if the generic arguments are parenthesized. + /// + /// Returns the `RetTy` in `Trait(Ty0, Ty1, ...) -> RetTy`. + /// Panics if the parenthesized arguments have an incorrect form (this shouldn't happen). + pub fn paren_sugar_output(&self) -> Option<&Ty<'hir>> { + (self.parenthesized == GenericArgsParentheses::ParenSugar) + .then(|| self.paren_sugar_output_inner()) + } + + fn paren_sugar_output_inner(&self) -> &Ty<'hir> { + let [constraint] = self.constraints.try_into().unwrap(); + debug_assert_eq!(constraint.ident.name, sym::Output); + constraint.ty().unwrap() + } + + pub fn has_err(&self) -> Option { + self.args + .iter() + .find_map(|arg| { + let GenericArg::Type(ty) = arg else { return None }; + let TyKind::Err(guar) = ty.kind else { return None }; + Some(guar) + }) + .or_else(|| { + self.constraints.iter().find_map(|constraint| { + let TyKind::Err(guar) = constraint.ty()?.kind else { return None }; + Some(guar) + }) + }) } #[inline] @@ -383,9 +414,11 @@ impl<'hir> GenericArgs<'hir> { .count() } - /// The span encompassing the text inside the surrounding brackets. - /// It will also include bindings if they aren't in the form `-> Ret` - /// Returns `None` if the span is empty (e.g. no brackets) or dummy + /// The span encompassing the arguments and constraints[^1] inside the surrounding brackets. + /// + /// Returns `None` if the span is empty (i.e., no brackets) or dummy. + /// + /// [^1]: Unless of the form `-> Ty` (see [`GenericArgsParentheses`]). pub fn span(&self) -> Option { let span_ext = self.span_ext()?; Some(span_ext.with_lo(span_ext.lo() + BytePos(1)).with_hi(span_ext.hi() - BytePos(1))) @@ -660,9 +693,7 @@ impl<'hir> Generics<'hir> { |bound| { let span_for_parentheses = if let Some(trait_ref) = bound.trait_ref() && let [.., segment] = trait_ref.path.segments - && segment.args().parenthesized == GenericArgsParentheses::ParenSugar - && let [binding] = segment.args().bindings - && let TypeBindingKind::Equality { term: Term::Ty(ret_ty) } = binding.kind + && let Some(ret_ty) = segment.args().paren_sugar_output() && let ret_ty = ret_ty.peel_refs() && let TyKind::TraitObject( _, @@ -748,7 +779,7 @@ impl<'hir> Generics<'hir> { /// A single predicate in a where-clause. #[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum WherePredicate<'hir> { - /// A type binding (e.g., `for<'c> Foo: Send + Clone + 'c`). + /// A type bound (e.g., `for<'c> Foo: Send + Clone + 'c`). BoundPredicate(WhereBoundPredicate<'hir>), /// A lifetime predicate (e.g., `'a: 'b + 'c`). RegionPredicate(WhereRegionPredicate<'hir>), @@ -2361,24 +2392,43 @@ pub enum ImplItemKind<'hir> { Type(&'hir Ty<'hir>), } -/// An associated item binding. +/// A constraint on an associated item. /// /// ### Examples /// -/// * `Trait` -/// * `Trait = Ty>` -/// * `Trait` -/// * `Trait` (under feature `associated_const_equality`) -/// * `Trait` (under feature `return_type_notation`) +/// * the `A = Ty` and `B = Ty` in `Trait` +/// * the `G = Ty` in `Trait = Ty>` +/// * the `A: Bound` in `Trait` +/// * the `RetTy` in `Trait(ArgTy, ArgTy) -> RetTy` +/// * the `C = { Ct }` in `Trait` (feature `associated_const_equality`) +/// * the `f(): Bound` in `Trait` (feature `return_type_notation`) #[derive(Debug, Clone, Copy, HashStable_Generic)] -pub struct TypeBinding<'hir> { +pub struct AssocItemConstraint<'hir> { pub hir_id: HirId, pub ident: Ident, pub gen_args: &'hir GenericArgs<'hir>, - pub kind: TypeBindingKind<'hir>, + pub kind: AssocItemConstraintKind<'hir>, pub span: Span, } +impl<'hir> AssocItemConstraint<'hir> { + /// Obtain the type on the RHS of an assoc ty equality constraint if applicable. + pub fn ty(self) -> Option<&'hir Ty<'hir>> { + match self.kind { + AssocItemConstraintKind::Equality { term: Term::Ty(ty) } => Some(ty), + _ => None, + } + } + + /// Obtain the const on the RHS of an assoc const equality constraint if applicable. + pub fn ct(self) -> Option<&'hir AnonConst> { + match self.kind { + AssocItemConstraintKind::Equality { term: Term::Const(ct) } => Some(ct), + _ => None, + } + } +} + #[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum Term<'hir> { Ty(&'hir Ty<'hir>), @@ -2397,28 +2447,18 @@ impl<'hir> From<&'hir AnonConst> for Term<'hir> { } } -// Represents the two kinds of type bindings. +/// The kind of [associated item constraint][AssocItemConstraint]. #[derive(Debug, Clone, Copy, HashStable_Generic)] -pub enum TypeBindingKind<'hir> { - /// E.g., `Foo`. - Constraint { bounds: &'hir [GenericBound<'hir>] }, - /// E.g., `Foo`. +pub enum AssocItemConstraintKind<'hir> { + /// An equality constraint for an associated item (e.g., `AssocTy = Ty` in `Trait`). + /// + /// Also known as an *associated item binding* (we *bind* an associated item to a term). + /// + /// Furthermore, associated type equality constraints can also be referred to as *associated type + /// bindings*. Similarly with associated const equality constraints and *associated const bindings*. Equality { term: Term<'hir> }, -} - -impl TypeBinding<'_> { - pub fn ty(&self) -> &Ty<'_> { - match self.kind { - TypeBindingKind::Equality { term: Term::Ty(ref ty) } => ty, - _ => panic!("expected equality type binding for parenthesized generic args"), - } - } - pub fn opt_const(&self) -> Option<&'_ AnonConst> { - match self.kind { - TypeBindingKind::Equality { term: Term::Const(ref c) } => Some(c), - _ => None, - } - } + /// A bound on an associated type (e.g., `AssocTy: Bound` in `Trait`). + Bound { bounds: &'hir [GenericBound<'hir>] }, } #[derive(Debug, Clone, Copy, HashStable_Generic)] @@ -3615,7 +3655,7 @@ pub enum Node<'hir> { Stmt(&'hir Stmt<'hir>), PathSegment(&'hir PathSegment<'hir>), Ty(&'hir Ty<'hir>), - TypeBinding(&'hir TypeBinding<'hir>), + AssocItemConstraint(&'hir AssocItemConstraint<'hir>), TraitRef(&'hir TraitRef<'hir>), Pat(&'hir Pat<'hir>), PatField(&'hir PatField<'hir>), @@ -3664,7 +3704,7 @@ impl<'hir> Node<'hir> { | Node::PathSegment(PathSegment { ident, .. }) => Some(*ident), Node::Lifetime(lt) => Some(lt.ident), Node::GenericParam(p) => Some(p.name.ident()), - Node::TypeBinding(b) => Some(b.ident), + Node::AssocItemConstraint(c) => Some(c.ident), Node::PatField(f) => Some(f.ident), Node::ExprField(f) => Some(f.ident), Node::PreciseCapturingNonLifetimeArg(a) => Some(a.ident), @@ -3843,7 +3883,7 @@ impl<'hir> Node<'hir> { expect_stmt, &'hir Stmt<'hir>, Node::Stmt(n), n; expect_path_segment, &'hir PathSegment<'hir>, Node::PathSegment(n), n; expect_ty, &'hir Ty<'hir>, Node::Ty(n), n; - expect_type_binding, &'hir TypeBinding<'hir>, Node::TypeBinding(n), n; + expect_assoc_item_constraint, &'hir AssocItemConstraint<'hir>, Node::AssocItemConstraint(n), n; expect_trait_ref, &'hir TraitRef<'hir>, Node::TraitRef(n), n; expect_pat, &'hir Pat<'hir>, Node::Pat(n), n; expect_pat_field, &'hir PatField<'hir>, Node::PatField(n), n; diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index b202ea8dca37..10f911ed00b4 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -456,8 +456,11 @@ pub trait Visitor<'v>: Sized { fn visit_generic_args(&mut self, generic_args: &'v GenericArgs<'v>) -> Self::Result { walk_generic_args(self, generic_args) } - fn visit_assoc_type_binding(&mut self, type_binding: &'v TypeBinding<'v>) -> Self::Result { - walk_assoc_type_binding(self, type_binding) + fn visit_assoc_item_constraint( + &mut self, + constraint: &'v AssocItemConstraint<'v>, + ) -> Self::Result { + walk_assoc_item_constraint(self, constraint) } fn visit_attribute(&mut self, _attr: &'v Attribute) -> Self::Result { Self::Result::output() @@ -1259,23 +1262,25 @@ pub fn walk_generic_args<'v, V: Visitor<'v>>( generic_args: &'v GenericArgs<'v>, ) -> V::Result { walk_list!(visitor, visit_generic_arg, generic_args.args); - walk_list!(visitor, visit_assoc_type_binding, generic_args.bindings); + walk_list!(visitor, visit_assoc_item_constraint, generic_args.constraints); V::Result::output() } -pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>( +pub fn walk_assoc_item_constraint<'v, V: Visitor<'v>>( visitor: &mut V, - type_binding: &'v TypeBinding<'v>, + constraint: &'v AssocItemConstraint<'v>, ) -> V::Result { - try_visit!(visitor.visit_id(type_binding.hir_id)); - try_visit!(visitor.visit_ident(type_binding.ident)); - try_visit!(visitor.visit_generic_args(type_binding.gen_args)); - match type_binding.kind { - TypeBindingKind::Equality { ref term } => match term { + try_visit!(visitor.visit_id(constraint.hir_id)); + try_visit!(visitor.visit_ident(constraint.ident)); + try_visit!(visitor.visit_generic_args(constraint.gen_args)); + match constraint.kind { + AssocItemConstraintKind::Equality { ref term } => match term { Term::Ty(ref ty) => try_visit!(visitor.visit_ty(ty)), Term::Const(ref c) => try_visit!(visitor.visit_anon_const(c)), }, - TypeBindingKind::Constraint { bounds } => walk_list!(visitor, visit_param_bound, bounds), + AssocItemConstraintKind::Bound { bounds } => { + walk_list!(visitor, visit_param_bound, bounds) + } } V::Result::output() } diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index cf492a2a3fee..67959d9dfede 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -4,6 +4,10 @@ hir_analysis_ambiguous_assoc_item = ambiguous associated {$assoc_kind} `{$assoc_ hir_analysis_ambiguous_lifetime_bound = ambiguous lifetime bound, explicit lifetime bound required +hir_analysis_assoc_item_constraints_not_allowed_here = + associated item constraints are not allowed here + .label = associated item constraint not allowed here + hir_analysis_assoc_item_not_found = associated {$assoc_kind} `{$assoc_name}` not found for `{$ty_param_name}` hir_analysis_assoc_item_not_found_found_in_other_trait_label = there is {$identically_named -> @@ -24,10 +28,6 @@ hir_analysis_assoc_kind_mismatch = expected {$expected}, found {$got} hir_analysis_assoc_kind_mismatch_wrap_in_braces_sugg = consider adding braces here -hir_analysis_assoc_type_binding_not_allowed = - associated type bindings are not allowed here - .label = associated type not allowed here - hir_analysis_associated_type_trait_uninferred_generic_params = cannot use the associated type of a trait with uninferred generic parameters .suggestion = use a fully qualified path with inferred lifetimes 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 5c7733065c61..c1850f78f2fb 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -1468,12 +1468,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { depth: usize, generic_args: &'tcx hir::GenericArgs<'tcx>, ) { - if generic_args.parenthesized == hir::GenericArgsParentheses::ParenSugar { - self.visit_fn_like_elision( - generic_args.inputs(), - Some(generic_args.bindings[0].ty()), - false, - ); + if let Some((inputs, output)) = generic_args.paren_sugar_inputs_output() { + self.visit_fn_like_elision(inputs, Some(output), false); return; } @@ -1608,8 +1604,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { } } - // Hack: when resolving the type `XX` in binding like `dyn - // Foo<'b, Item = XX>`, the current object-lifetime default + // Hack: When resolving the type `XX` in an assoc ty binding like + // `dyn Foo<'b, Item = XX>`, the current object-lifetime default // would be to examine the trait `Foo` to check whether it has // a lifetime bound declared on `Item`. e.g., if `Foo` is // declared like so, then the default object lifetime bound in @@ -1637,7 +1633,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { // Resolve lifetimes found in the bindings, so either in the type `XX` in `Item = XX` or // in the trait ref `YY<...>` in `Item: YY<...>`. - for binding in generic_args.bindings { + for constraint in generic_args.constraints { let scope = Scope::ObjectLifetimeDefault { lifetime: if has_lifetime_parameter { None @@ -1646,7 +1642,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { }, s: self.scope, }; - // If the binding is parenthesized, then this must be `feature(return_type_notation)`. + // If the args are parenthesized, then this must be `feature(return_type_notation)`. // In that case, introduce a binder over all of the function's early and late bound vars. // // For example, given @@ -1659,13 +1655,14 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { // `for<'a> T::Trait<'a, x(): for<'b> Other<'b>>` // this is going to expand to something like: // `for<'a> for<'r, T> >::x::<'r, T>::{opaque#0}: for<'b> Other<'b>`. - if binding.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation { + if constraint.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation + { let bound_vars = if let Some(type_def_id) = type_def_id && self.tcx.def_kind(type_def_id) == DefKind::Trait && let Some((mut bound_vars, assoc_fn)) = BoundVarContext::supertrait_hrtb_vars( self.tcx, type_def_id, - binding.ident, + constraint.ident, ty::AssocKind::Fn, ) { bound_vars.extend(self.tcx.generics_of(assoc_fn.def_id).own_params.iter().map( @@ -1686,22 +1683,22 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { } else { self.tcx .dcx() - .span_delayed_bug(binding.ident.span, "bad return type notation here"); + .span_delayed_bug(constraint.ident.span, "bad return type notation here"); vec![] }; self.with(scope, |this| { let scope = Scope::Supertrait { bound_vars, s: this.scope }; this.with(scope, |this| { let (bound_vars, _) = this.poly_trait_ref_binder_info(); - this.record_late_bound_vars(binding.hir_id, bound_vars); - this.visit_assoc_type_binding(binding) + this.record_late_bound_vars(constraint.hir_id, bound_vars); + this.visit_assoc_item_constraint(constraint) }); }); } else if let Some(type_def_id) = type_def_id { let bound_vars = BoundVarContext::supertrait_hrtb_vars( self.tcx, type_def_id, - binding.ident, + constraint.ident, ty::AssocKind::Type, ) .map(|(bound_vars, _)| bound_vars); @@ -1710,10 +1707,10 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { bound_vars: bound_vars.unwrap_or_default(), s: this.scope, }; - this.with(scope, |this| this.visit_assoc_type_binding(binding)); + this.with(scope, |this| this.visit_assoc_item_constraint(constraint)); }); } else { - self.with(scope, |this| this.visit_assoc_type_binding(binding)); + self.with(scope, |this| this.visit_assoc_item_constraint(constraint)); } } } diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 1475e53c47c2..24a1df70e05d 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -220,9 +220,10 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { .position(|arg| arg.hir_id() == hir_id) .map(|index| (index, seg)) .or_else(|| { - args.bindings + args.constraints .iter() - .filter_map(TypeBinding::opt_const) + .copied() + .filter_map(AssocItemConstraint::ct) .position(|ct| ct.hir_id == hir_id) .map(|idx| (idx, seg)) }) diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 1c99713b3ae1..8a9d4cd4ac70 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -290,8 +290,8 @@ pub struct AmbiguousLifetimeBound { } #[derive(Diagnostic)] -#[diag(hir_analysis_assoc_type_binding_not_allowed, code = E0229)] -pub struct AssocTypeBindingNotAllowed { +#[diag(hir_analysis_assoc_item_constraints_not_allowed_here, code = E0229)] +pub struct AssocItemConstraintsNotAllowedHere { #[primary_span] #[label] pub span: Span, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index b0ae73fcc4be..b6a1799c03f1 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -230,32 +230,34 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { bounds } - /// Lower an associated item binding from HIR into `bounds`. + /// Lower an associated item constraint from the HIR into `bounds`. /// /// ### A Note on Binders /// /// Given something like `T: for<'a> Iterator`, /// the `trait_ref` here will be `for<'a> T: Iterator`. - /// The `binding` data however is from *inside* the binder + /// The `constraint` data however is from *inside* the binder /// (e.g., `&'a u32`) and hence may reference bound regions. - #[instrument(level = "debug", skip(self, bounds, dup_bindings, path_span))] - pub(super) fn lower_assoc_item_binding( + #[instrument(level = "debug", skip(self, bounds, duplicates, path_span))] + pub(super) fn lower_assoc_item_constraint( &self, hir_ref_id: hir::HirId, trait_ref: ty::PolyTraitRef<'tcx>, - binding: &hir::TypeBinding<'tcx>, + constraint: &hir::AssocItemConstraint<'tcx>, bounds: &mut Bounds<'tcx>, - dup_bindings: &mut FxIndexMap, + duplicates: &mut FxIndexMap, path_span: Span, only_self_bounds: OnlySelfBounds, ) -> Result<(), ErrorGuaranteed> { let tcx = self.tcx(); - let assoc_kind = if binding.gen_args.parenthesized + let assoc_kind = if constraint.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation { ty::AssocKind::Fn - } else if let hir::TypeBindingKind::Equality { term: hir::Term::Const(_) } = binding.kind { + } else if let hir::AssocItemConstraintKind::Equality { term: hir::Term::Const(_) } = + constraint.kind + { ty::AssocKind::Const } else { ty::AssocKind::Type @@ -272,7 +274,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let candidate = if self.probe_trait_that_defines_assoc_item( trait_ref.def_id(), assoc_kind, - binding.ident, + constraint.ident, ) { // Simple case: The assoc item is defined in the current trait. trait_ref @@ -284,14 +286,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { trait_ref.skip_binder().print_only_trait_name(), None, assoc_kind, - binding.ident, + constraint.ident, path_span, - Some(binding), + Some(constraint), )? }; let (assoc_ident, def_scope) = - tcx.adjust_ident_and_get_scope(binding.ident, candidate.def_id(), hir_ref_id); + tcx.adjust_ident_and_get_scope(constraint.ident, candidate.def_id(), hir_ref_id); // We have already adjusted the item name above, so compare with `.normalize_to_macros_2_0()` // instead of calling `filter_by_name_and_kind` which would needlessly normalize the @@ -306,26 +308,26 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let reported = tcx .dcx() .struct_span_err( - binding.span, - format!("{} `{}` is private", assoc_item.kind, binding.ident), + constraint.span, + format!("{} `{}` is private", assoc_item.kind, constraint.ident), ) - .with_span_label(binding.span, format!("private {}", assoc_item.kind)) + .with_span_label(constraint.span, format!("private {}", assoc_item.kind)) .emit(); self.set_tainted_by_errors(reported); } - tcx.check_stability(assoc_item.def_id, Some(hir_ref_id), binding.span, None); + tcx.check_stability(assoc_item.def_id, Some(hir_ref_id), constraint.span, None); - dup_bindings + duplicates .entry(assoc_item.def_id) .and_modify(|prev_span| { tcx.dcx().emit_err(errors::ValueOfAssociatedStructAlreadySpecified { - span: binding.span, + span: constraint.span, prev_span: *prev_span, - item_name: binding.ident, + item_name: constraint.ident, def_path: tcx.def_path_str(assoc_item.container_id(tcx)), }); }) - .or_insert(binding.span); + .or_insert(constraint.span); let projection_term = if let ty::AssocKind::Fn = assoc_kind { let mut emitted_bad_param_err = None; @@ -384,7 +386,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { alias_ty.into() } else { return Err(tcx.dcx().emit_err(crate::errors::ReturnTypeNotationOnNonRpitit { - span: binding.span, + span: constraint.span, ty: tcx.liberate_late_bound_regions(assoc_item.def_id, output), fn_span: tcx.hir().span_if_local(assoc_item.def_id), note: (), @@ -398,19 +400,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output); let instantiation_output = ty::EarlyBinder::bind(shifted_output).instantiate(tcx, args); - let bound_vars = tcx.late_bound_vars(binding.hir_id); + let bound_vars = tcx.late_bound_vars(constraint.hir_id); ty::Binder::bind_with_vars(instantiation_output, bound_vars) } else { // Create the generic arguments for the associated type or constant by joining the // parent arguments (the arguments of the trait) and the own arguments (the ones of // the associated item itself) and construct an alias type using them. let alias_ty = candidate.map_bound(|trait_ref| { - let ident = Ident::new(assoc_item.name, binding.ident.span); + let ident = Ident::new(assoc_item.name, constraint.ident.span); let item_segment = hir::PathSegment { ident, - hir_id: binding.hir_id, + hir_id: constraint.hir_id, res: Res::Err, - args: Some(binding.gen_args), + args: Some(constraint.gen_args), infer_args: false, }; @@ -426,26 +428,26 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }); // Provide the resolved type of the associated constant to `type_of(AnonConst)`. - if let hir::TypeBindingKind::Equality { term: hir::Term::Const(anon_const) } = - binding.kind + if let hir::AssocItemConstraintKind::Equality { term: hir::Term::Const(anon_const) } = + constraint.kind { let ty = alias_ty.map_bound(|ty| tcx.type_of(ty.def_id).instantiate(tcx, ty.args)); - let ty = check_assoc_const_binding_type(tcx, assoc_ident, ty, binding.hir_id); + let ty = check_assoc_const_binding_type(tcx, assoc_ident, ty, constraint.hir_id); tcx.feed_anon_const_type(anon_const.def_id, ty::EarlyBinder::bind(ty)); } alias_ty }; - match binding.kind { - hir::TypeBindingKind::Equality { .. } if let ty::AssocKind::Fn = assoc_kind => { + match constraint.kind { + hir::AssocItemConstraintKind::Equality { .. } if let ty::AssocKind::Fn = assoc_kind => { return Err(tcx.dcx().emit_err(crate::errors::ReturnTypeNotationEqualityBound { - span: binding.span, + span: constraint.span, })); } // Lower an equality constraint like `Item = u32` as found in HIR bound `T: Iterator` // to a projection predicate: `::Item = u32`. - hir::TypeBindingKind::Equality { term } => { + hir::AssocItemConstraintKind::Equality { term } => { let term = match term { hir::Term::Ty(ty) => self.lower_ty(ty).into(), hir::Term::Const(ct) => ty::Const::from_anon_const(tcx, ct.def_id).into(), @@ -469,18 +471,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // struct S1 Fn(&i32, &i32) -> &'a i32>(F); // ---- ---- ^^^^^^^ // NOTE(associated_const_equality): This error should be impossible to trigger - // with associated const equality bounds. + // with associated const equality constraints. self.validate_late_bound_regions( late_bound_in_projection_ty, late_bound_in_term, |br_name| { struct_span_code_err!( tcx.dcx(), - binding.span, + constraint.span, E0582, "binding for associated type `{}` references {}, \ - which does not appear in the trait input types", - binding.ident, + which does not appear in the trait input types", + constraint.ident, br_name ) }, @@ -492,12 +494,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { projection_term, term, }), - binding.span, + constraint.span, ); } // Lower a constraint like `Item: Debug` as found in HIR bound `T: Iterator` // to a bound involving a projection: `::Item: Debug`. - hir::TypeBindingKind::Constraint { bounds: hir_bounds } => { + hir::AssocItemConstraintKind::Bound { bounds: hir_bounds } => { // NOTE: If `only_self_bounds` is true, do NOT expand this associated type bound into // a trait predicate, since we only want to add predicates for the `Self` type. if !only_self_bounds.0 { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 9c687d3282bd..821c56530407 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -1,5 +1,5 @@ use crate::errors::{ - self, AssocTypeBindingNotAllowed, ManualImplementation, MissingTypeParams, + self, AssocItemConstraintsNotAllowedHere, ManualImplementation, MissingTypeParams, ParenthesizedFnTraitExpansion, TraitObjectDeclaredWithNoTraits, }; use crate::fluent_generated as fluent; @@ -121,7 +121,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { assoc_kind: ty::AssocKind, assoc_name: Ident, span: Span, - binding: Option<&hir::TypeBinding<'tcx>>, + constraint: Option<&hir::AssocItemConstraint<'tcx>>, ) -> ErrorGuaranteed where I: Iterator>, @@ -135,7 +135,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .find(|item| tcx.hygienic_eq(assoc_name, item.ident(tcx), r.def_id())) }) { return self.complain_about_assoc_kind_mismatch( - assoc_item, assoc_kind, assoc_name, span, binding, + assoc_item, assoc_kind, assoc_name, span, constraint, ); } @@ -300,18 +300,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { assoc_kind: ty::AssocKind, ident: Ident, span: Span, - binding: Option<&hir::TypeBinding<'tcx>>, + constraint: Option<&hir::AssocItemConstraint<'tcx>>, ) -> ErrorGuaranteed { let tcx = self.tcx(); let bound_on_assoc_const_label = if let ty::AssocKind::Const = assoc_item.kind - && let Some(binding) = binding - && let hir::TypeBindingKind::Constraint { .. } = binding.kind + && let Some(constraint) = constraint + && let hir::AssocItemConstraintKind::Bound { .. } = constraint.kind { - let lo = if binding.gen_args.span_ext.is_dummy() { + let lo = if constraint.gen_args.span_ext.is_dummy() { ident.span } else { - binding.gen_args.span_ext + constraint.gen_args.span_ext }; Some(lo.between(span.shrink_to_hi())) } else { @@ -319,8 +319,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }; // FIXME(associated_const_equality): This has quite a few false positives and negatives. - let wrap_in_braces_sugg = if let Some(binding) = binding - && let hir::TypeBindingKind::Equality { term: hir::Term::Ty(hir_ty) } = binding.kind + let wrap_in_braces_sugg = if let Some(constraint) = constraint + && let Some(hir_ty) = constraint.ty() && let ty = self.lower_ty(hir_ty) && (ty.is_enum() || ty.references_error()) && tcx.features().associated_const_equality @@ -333,10 +333,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { None }; - // For equality bounds, we want to blame the term (RHS) instead of the item (LHS) since + // For equality constraints, we want to blame the term (RHS) instead of the item (LHS) since // one can argue that that's more “intuitive” to the user. - let (span, expected_because_label, expected, got) = if let Some(binding) = binding - && let hir::TypeBindingKind::Equality { term } = binding.kind + let (span, expected_because_label, expected, got) = if let Some(constraint) = constraint + && let hir::AssocItemConstraintKind::Equality { term } = constraint.kind { let span = match term { hir::Term::Ty(ty) => ty.span, @@ -791,8 +791,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let path = poly_trait_ref.trait_ref.path.segments.last()?; let args = path.args?; - Some(args.bindings.iter().filter_map(|binding| { - let ident = binding.ident; + Some(args.constraints.iter().filter_map(|constraint| { + let ident = constraint.ident; let trait_def = path.res.def_id(); let assoc_item = tcx.associated_items(trait_def).find_by_name_and_kind( tcx, @@ -1192,14 +1192,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } -/// Emits an error regarding forbidden type binding associations -pub fn prohibit_assoc_item_binding( +/// Emit an error for the given associated item constraint. +pub fn prohibit_assoc_item_constraint( tcx: TyCtxt<'_>, - binding: &hir::TypeBinding<'_>, + constraint: &hir::AssocItemConstraint<'_>, segment: Option<(DefId, &hir::PathSegment<'_>, Span)>, ) -> ErrorGuaranteed { - let mut err = tcx.dcx().create_err(AssocTypeBindingNotAllowed { - span: binding.span, + let mut err = tcx.dcx().create_err(AssocItemConstraintsNotAllowedHere { + span: constraint.span, fn_trait_expansion: if let Some((_, segment, span)) = segment && segment.args().parenthesized == hir::GenericArgsParentheses::ParenSugar { @@ -1217,13 +1217,12 @@ pub fn prohibit_assoc_item_binding( // otherwise suggest the removal of the binding. if let Some((def_id, segment, _)) = segment && segment.args().parenthesized == hir::GenericArgsParentheses::No - && let hir::TypeBindingKind::Equality { term } = binding.kind + && let hir::AssocItemConstraintKind::Equality { term } = constraint.kind { // Suggests removal of the offending binding let suggest_removal = |e: &mut Diag<'_>| { - let bindings = segment.args().bindings; + let constraints = segment.args().constraints; let args = segment.args().args; - let binding_span = binding.span; // Compute the span to remove based on the position // of the binding. We do that as follows: @@ -1236,26 +1235,21 @@ pub fn prohibit_assoc_item_binding( // the start of the next span or will simply be the // span encomassing everything within the generics brackets - let Some(binding_index) = bindings.iter().position(|b| b.hir_id == binding.hir_id) - else { + let Some(index) = constraints.iter().position(|b| b.hir_id == constraint.hir_id) else { bug!("a type binding exists but its HIR ID not found in generics"); }; - let preceding_span = if binding_index > 0 { - Some(bindings[binding_index - 1].span) + let preceding_span = if index > 0 { + Some(constraints[index - 1].span) } else { args.last().map(|a| a.span()) }; - let next_span = if binding_index < bindings.len() - 1 { - Some(bindings[binding_index + 1].span) - } else { - None - }; + let next_span = constraints.get(index + 1).map(|constraint| constraint.span); let removal_span = match (preceding_span, next_span) { - (Some(prec), _) => binding_span.with_lo(prec.hi()), - (None, Some(next)) => binding_span.with_hi(next.lo()), + (Some(prec), _) => constraint.span.with_lo(prec.hi()), + (None, Some(next)) => constraint.span.with_hi(next.lo()), (None, None) => { let Some(generics_span) = segment.args().span_ext() else { bug!("a type binding exists but generic span is empty"); @@ -1269,7 +1263,7 @@ pub fn prohibit_assoc_item_binding( if let Ok(suggestion) = tcx.sess.source_map().span_to_snippet(removal_span) { e.span_suggestion_verbose( removal_span, - "consider removing this type binding", + "consider removing this associated item binding", suggestion, Applicability::MaybeIncorrect, ); @@ -1281,7 +1275,7 @@ pub fn prohibit_assoc_item_binding( let suggest_direct_use = |e: &mut Diag<'_>, sp: Span| { if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(sp) { e.span_suggestion_verbose( - binding.span, + constraint.span, format!("to use `{snippet}` as a generic argument specify it directly"), snippet, Applicability::MaybeIncorrect, @@ -1289,11 +1283,11 @@ pub fn prohibit_assoc_item_binding( } }; - // Check if the type has a generic param with the - // same name as the assoc type name in type binding + // Check if the type has a generic param with the same name + // as the assoc type name in the associated item binding. let generics = tcx.generics_of(def_id); let matching_param = - generics.own_params.iter().find(|p| p.name.as_str() == binding.ident.as_str()); + generics.own_params.iter().find(|p| p.name.as_str() == constraint.ident.as_str()); // Now emit the appropriate suggestion if let Some(matching_param) = matching_param { @@ -1322,8 +1316,7 @@ pub(crate) fn fn_trait_to_string( ) -> String { let args = trait_segment .args - .as_ref() - .and_then(|args| args.args.get(0)) + .and_then(|args| args.args.first()) .and_then(|arg| match arg { hir::GenericArg::Type(ty) => match ty.kind { hir::TyKind::Tup(t) => t @@ -1334,7 +1327,7 @@ pub(crate) fn fn_trait_to_string( _ => tcx.sess.source_map().span_to_snippet(ty.span), } .map(|s| { - // `s.empty()` checks to see if the type is the unit tuple, if so we don't want a comma + // `is_empty()` checks to see if the type is the unit tuple, if so we don't want a comma if parenthesized || s.is_empty() { format!("({s})") } else { format!("({s},)") } }) .ok(), @@ -1344,20 +1337,17 @@ pub(crate) fn fn_trait_to_string( let ret = trait_segment .args() - .bindings + .constraints .iter() - .find_map(|b| match (b.ident.name == sym::Output, &b.kind) { - (true, hir::TypeBindingKind::Equality { term }) => { - let span = match term { - hir::Term::Ty(ty) => ty.span, - hir::Term::Const(c) => tcx.hir().span(c.hir_id), - }; - - (span != tcx.hir().span(trait_segment.hir_id)) - .then_some(tcx.sess.source_map().span_to_snippet(span).ok()) - .flatten() + .find_map(|c| { + if c.ident.name == sym::Output + && let Some(ty) = c.ty() + && ty.span != tcx.hir().span(trait_segment.hir_id) + { + tcx.sess.source_map().span_to_snippet(ty.span).ok() + } else { + None } - _ => None, }) .unwrap_or_else(|| "()".to_string()); diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs index 749f78e79201..455ed7d39cb2 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs @@ -1,6 +1,6 @@ use super::IsMethodCall; use crate::hir_ty_lowering::{ - errors::prohibit_assoc_item_binding, ExplicitLateBound, GenericArgCountMismatch, + errors::prohibit_assoc_item_constraint, ExplicitLateBound, GenericArgCountMismatch, GenericArgCountResult, GenericArgPosition, GenericArgsLowerer, }; use crate::structured_errors::{GenericArgsInfo, StructuredDiag, WrongNumberOfGenericArgs}; @@ -452,9 +452,9 @@ pub(crate) fn check_generic_arg_count( (gen_pos != GenericArgPosition::Type || seg.infer_args) && !gen_args.has_lifetime_params(); if gen_pos != GenericArgPosition::Type - && let Some(b) = gen_args.bindings.first() + && let Some(c) = gen_args.constraints.first() { - prohibit_assoc_item_binding(tcx, b, None); + prohibit_assoc_item_constraint(tcx, c, None); } let explicit_late_bound = @@ -566,17 +566,19 @@ pub(crate) fn check_generic_arg_count( debug!(?gen_args_info); - let reported = WrongNumberOfGenericArgs::new( - tcx, - gen_args_info, - seg, - gen_params, - params_offset, - gen_args, - def_id, - ) - .diagnostic() - .emit_unless(gen_args.has_err()); + let reported = gen_args.has_err().unwrap_or_else(|| { + WrongNumberOfGenericArgs::new( + tcx, + gen_args_info, + seg, + gen_params, + params_offset, + gen_args, + def_id, + ) + .diagnostic() + .emit() + }); Err(reported) }; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs index d9d36f5299b5..7be661ba74d0 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs @@ -268,8 +268,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { fn maybe_suggest_assoc_ty_bound(&self, self_ty: &hir::Ty<'_>, diag: &mut Diag<'_>) { let mut parents = self.tcx().hir().parent_iter(self_ty.hir_id); - if let Some((_, hir::Node::TypeBinding(binding))) = parents.next() - && let hir::TypeBindingKind::Equality { term: hir::Term::Ty(obj_ty) } = binding.kind + if let Some((_, hir::Node::AssocItemConstraint(constraint))) = parents.next() + && let Some(obj_ty) = constraint.ty() { if let Some((_, hir::Node::TraitRef(..))) = parents.next() && let Some((_, hir::Node::Ty(ty))) = parents.next() @@ -279,10 +279,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { return; } - let lo = if binding.gen_args.span_ext.is_dummy() { - binding.ident.span + let lo = if constraint.gen_args.span_ext.is_dummy() { + constraint.ident.span } else { - binding.gen_args.span_ext + constraint.gen_args.span_ext }; let hi = obj_ty.span; 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 4b1c0da6ce11..fd59fb4d2845 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -22,7 +22,7 @@ mod object_safety; use crate::bounds::Bounds; use crate::collect::HirPlaceholderCollector; use crate::errors::{AmbiguousLifetimeBound, WildPatTy}; -use crate::hir_ty_lowering::errors::{prohibit_assoc_item_binding, GenericsArgsErrExtend}; +use crate::hir_ty_lowering::errors::{prohibit_assoc_item_constraint, GenericsArgsErrExtend}; use crate::hir_ty_lowering::generics::{check_generic_arg_count, lower_generic_args}; use crate::middle::resolve_bound_vars as rbv; use crate::require_c_abi_if_c_variadic; @@ -324,8 +324,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { None, ty::BoundConstness::NotConst, ); - if let Some(b) = item_segment.args().bindings.first() { - prohibit_assoc_item_binding(self.tcx(), b, Some((def_id, item_segment, span))); + if let Some(c) = item_segment.args().constraints.first() { + prohibit_assoc_item_constraint(self.tcx(), c, Some((def_id, item_segment, span))); } args } @@ -335,7 +335,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// If this is a trait reference, you also need to pass the self type `self_ty`. /// The lowering process may involve applying defaulted type parameters. /// - /// Associated item bindings are not handled here! + /// Associated item constraints are not handled here! They are either lowered via + /// `lower_assoc_item_constraint` or rejected via `prohibit_assoc_item_constraint`. /// /// ### Example /// @@ -349,7 +350,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// which will have been resolved to a `def_id` /// 3. The `generic_args` contains info on the `<...>` contents. The `usize` type /// parameters are returned in the `GenericArgsRef` - /// 4. Associated type bindings like `Output = u32` are contained in `generic_args.bindings`. + /// 4. Associated item constraints like `Output = u32` are contained in `generic_args.constraints`. /// /// Note that the type listing given here is *exactly* what the user provided. /// @@ -411,8 +412,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Skip processing if type has no generic parameters. // Traits always have `Self` as a generic parameter, which means they will not return early - // here and so associated type bindings will be handled regardless of whether there are any - // non-`Self` generic parameters. + // here and so associated item constraints will be handled regardless of whether there are + // any non-`Self` generic parameters. if generics.is_own_empty() { return (tcx.mk_args(parent_args), arg_count); } @@ -621,8 +622,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { None, ty::BoundConstness::NotConst, ); - if let Some(b) = item_segment.args().bindings.first() { - prohibit_assoc_item_binding(self.tcx(), b, Some((item_def_id, item_segment, span))); + if let Some(c) = item_segment.args().constraints.first() { + prohibit_assoc_item_constraint(self.tcx(), c, Some((item_def_id, item_segment, span))); } args } @@ -654,13 +655,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// /// *Polymorphic* in the sense that it may bind late-bound vars. /// - /// This may generate auxiliary bounds if the trait reference contains associated item bindings. + /// This may generate auxiliary bounds iff the trait reference contains associated item constraints. /// /// ### Example /// /// Given the trait ref `Iterator` and the self type `Ty`, this will add the /// - /// 1. *trait predicate* `` (known as `Foo: Iterator` in surface syntax) and the + /// 1. *trait predicate* `` (known as `Ty: Iterator` in the surface syntax) and the /// 2. *projection predicate* `::Item = u32` /// /// to `bounds`. @@ -714,27 +715,27 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { debug!(?poly_trait_ref); bounds.push_trait_bound(tcx, poly_trait_ref, span, polarity); - let mut dup_bindings = FxIndexMap::default(); - for binding in trait_segment.args().bindings { - // Don't register additional associated type bounds for negative bounds, - // since we should have emitten an error for them earlier, and they will - // not be well-formed! + let mut dup_constraints = FxIndexMap::default(); + for constraint in trait_segment.args().constraints { + // Don't register any associated item constraints for negative bounds, + // since we should have emitted an error for them earlier, and they + // would not be well-formed! if polarity != ty::PredicatePolarity::Positive { assert!( self.tcx().dcx().has_errors().is_some(), - "negative trait bounds should not have bindings", + "negative trait bounds should not have assoc item constraints", ); continue; } // Specify type to assert that error was already reported in `Err` case. - let _: Result<_, ErrorGuaranteed> = self.lower_assoc_item_binding( + let _: Result<_, ErrorGuaranteed> = self.lower_assoc_item_constraint( trait_ref.hir_ref_id, poly_trait_ref, - binding, + constraint, bounds, - &mut dup_bindings, - binding.span, + &mut dup_constraints, + constraint.span, only_self_bounds, ); // Okay to ignore `Err` because of `ErrorGuaranteed` (see above). @@ -766,8 +767,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { Some(self_ty), constness, ); - if let Some(b) = trait_segment.args().bindings.first() { - prohibit_assoc_item_binding(self.tcx(), b, Some((trait_def_id, trait_segment, span))); + if let Some(c) = trait_segment.args().constraints.first() { + prohibit_assoc_item_constraint( + self.tcx(), + c, + Some((trait_def_id, trait_segment, span)), + ); } ty::TraitRef::new(self.tcx(), trait_def_id, generic_args) } @@ -849,7 +854,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// /// This fails if there is no such bound in the list of candidates or if there are multiple /// candidates in which case it reports ambiguity. - #[instrument(level = "debug", skip(self, all_candidates, ty_param_name, binding), ret)] + #[instrument(level = "debug", skip(self, all_candidates, ty_param_name, constraint), ret)] fn probe_single_bound_for_assoc_item( &self, all_candidates: impl Fn() -> I, @@ -858,7 +863,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { assoc_kind: ty::AssocKind, assoc_name: Ident, span: Span, - binding: Option<&hir::TypeBinding<'tcx>>, + constraint: Option<&hir::AssocItemConstraint<'tcx>>, ) -> Result, ErrorGuaranteed> where I: Iterator>, @@ -877,7 +882,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { assoc_kind, assoc_name, span, - binding, + constraint, ); self.set_tainted_by_errors(reported); return Err(reported); @@ -897,8 +902,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }); // Provide a more specific error code index entry for equality bindings. err.code( - if let Some(binding) = binding - && let hir::TypeBindingKind::Equality { .. } = binding.kind + if let Some(constraint) = constraint + && let hir::AssocItemConstraintKind::Equality { .. } = constraint.kind { E0222 } else { @@ -906,7 +911,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }, ); - // FIXME(#97583): Resugar equality bounds to type/const bindings. + // FIXME(#97583): Print associated item bindings properly (i.e., not as equality predicates!). // FIXME: Turn this into a structured, translateable & more actionable suggestion. let mut where_bounds = vec![]; for bound in [bound, bound2].into_iter().chain(matching_candidates) { @@ -921,9 +926,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { bound_span, format!("ambiguous `{assoc_name}` from `{}`", bound.print_trait_sugared(),), ); - if let Some(binding) = binding { - match binding.kind { - hir::TypeBindingKind::Equality { term } => { + if let Some(constraint) = constraint { + match constraint.kind { + hir::AssocItemConstraintKind::Equality { term } => { let term: ty::Term<'_> = match term { hir::Term::Ty(ty) => self.lower_ty(ty).into(), hir::Term::Const(ct) => { @@ -937,7 +942,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { )); } // FIXME: Provide a suggestion. - hir::TypeBindingKind::Constraint { bounds: _ } => {} + hir::AssocItemConstraintKind::Bound { bounds: _ } => {} } } else { err.span_suggestion_verbose( @@ -1545,8 +1550,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { for segment in segments { // Only emit the first error to avoid overloading the user with error messages. - if let Some(b) = segment.args().bindings.first() { - return Err(prohibit_assoc_item_binding(self.tcx(), b, None)); + if let Some(c) = segment.args().constraints.first() { + return Err(prohibit_assoc_item_constraint(self.tcx(), c, None)); } } diff --git a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs index 9ddba7a6e7a9..5d435a8edf9f 100644 --- a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs +++ b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs @@ -489,7 +489,11 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { .in_definition_order() .filter(|item| item.kind == AssocKind::Type) .filter(|item| { - !self.gen_args.bindings.iter().any(|binding| binding.ident.name == item.name) + !self + .gen_args + .constraints + .iter() + .any(|constraint| constraint.ident.name == item.name) }) .map(|item| item.name.to_ident_string()) .collect() @@ -679,11 +683,11 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { (last_lt.span().shrink_to_hi(), false) }; let has_non_lt_args = self.num_provided_type_or_const_args() != 0; - let has_bindings = !self.gen_args.bindings.is_empty(); + let has_constraints = !self.gen_args.constraints.is_empty(); let sugg_prefix = if is_first { "" } else { ", " }; let sugg_suffix = - if is_first && (has_non_lt_args || has_bindings) { ", " } else { "" }; + if is_first && (has_non_lt_args || has_constraints) { ", " } else { "" }; let sugg = format!("{sugg_prefix}{suggested_args}{sugg_suffix}"); debug!("sugg: {:?}", sugg); @@ -741,7 +745,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { let sugg_prefix = if is_first { "" } else { ", " }; let sugg_suffix = - if is_first && !self.gen_args.bindings.is_empty() { ", " } else { "" }; + if is_first && !self.gen_args.constraints.is_empty() { ", " } else { "" }; let sugg = format!("{sugg_prefix}{suggested_args}{sugg_suffix}"); debug!("sugg: {:?}", sugg); diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 488537e81bec..413d50dff514 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -90,7 +90,7 @@ impl<'a> State<'a> { Node::Stmt(a) => self.print_stmt(a), Node::PathSegment(a) => self.print_path_segment(a), Node::Ty(a) => self.print_type(a), - Node::TypeBinding(a) => self.print_type_binding(a), + Node::AssocItemConstraint(a) => self.print_assoc_item_constraint(a), Node::TraitRef(a) => self.print_trait_ref(a), Node::Pat(a) => self.print_pat(a), Node::PatField(a) => self.print_patfield(a), @@ -1136,7 +1136,7 @@ impl<'a> State<'a> { self.print_ident(segment.ident); let generic_args = segment.args(); - if !generic_args.args.is_empty() || !generic_args.bindings.is_empty() { + if !generic_args.args.is_empty() || !generic_args.constraints.is_empty() { self.print_generic_args(generic_args, true); } @@ -1677,9 +1677,9 @@ impl<'a> State<'a> { }); } - for binding in generic_args.bindings { + for constraint in generic_args.constraints { start_or_comma(self); - self.print_type_binding(binding); + self.print_assoc_item_constraint(constraint); } if !empty.get() { @@ -1687,13 +1687,15 @@ impl<'a> State<'a> { } } hir::GenericArgsParentheses::ParenSugar => { + let (inputs, output) = generic_args.paren_sugar_inputs_output().unwrap(); + self.word("("); - self.commasep(Inconsistent, generic_args.inputs(), |s, ty| s.print_type(ty)); + self.commasep(Inconsistent, inputs, |s, ty| s.print_type(ty)); self.word(")"); self.space_if_not_bol(); self.word_space("->"); - self.print_type(generic_args.bindings[0].ty()); + self.print_type(output); } hir::GenericArgsParentheses::ReturnTypeNotation => { self.word("(..)"); @@ -1701,19 +1703,19 @@ impl<'a> State<'a> { } } - fn print_type_binding(&mut self, binding: &hir::TypeBinding<'_>) { - self.print_ident(binding.ident); - self.print_generic_args(binding.gen_args, false); + fn print_assoc_item_constraint(&mut self, constraint: &hir::AssocItemConstraint<'_>) { + self.print_ident(constraint.ident); + self.print_generic_args(constraint.gen_args, false); self.space(); - match binding.kind { - hir::TypeBindingKind::Equality { ref term } => { + match constraint.kind { + hir::AssocItemConstraintKind::Equality { ref term } => { self.word_space("="); match term { Term::Ty(ty) => self.print_type(ty), Term::Const(ref c) => self.print_anon_const(c), } } - hir::TypeBindingKind::Constraint { bounds } => { + hir::AssocItemConstraintKind::Bound { bounds } => { self.print_bounds(":", bounds); } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index cfd4dd4d1dd0..b3836fbb793f 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -848,19 +848,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && let [hir::GenericBound::Trait(trait_ref, _)] = op_ty.bounds && let Some(hir::PathSegment { args: Some(generic_args), .. }) = trait_ref.trait_ref.path.segments.last() - && let hir::GenericArgs { bindings: [ty_binding], .. } = generic_args - && let hir::TypeBindingKind::Equality { term: hir::Term::Ty(term) } = - ty_binding.kind + && let [constraint] = generic_args.constraints + && let Some(ty) = constraint.ty() { // Check if async function's return type was omitted. // Don't emit suggestions if the found type is `impl Future<...>`. debug!(?found); if found.is_suggestable(self.tcx, false) { - if term.span.is_empty() { + if ty.span.is_empty() { err.subdiagnostic( self.dcx(), errors::AddReturnTypeSuggestion::Add { - span: term.span, + span: ty.span, found: found.to_string(), }, ); @@ -868,10 +867,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { err.subdiagnostic( self.dcx(), - errors::ExpectedReturnTypeLabel::Other { - span: term.span, - expected, - }, + errors::ExpectedReturnTypeLabel::Other { span: ty.span, expected }, ); } } diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index b17af47fbcd4..173c8ce83751 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -901,7 +901,7 @@ impl<'hir> Map<'hir> { .with_hi(seg.args.map_or_else(|| ident_span.hi(), |args| args.span_ext.hi())) } Node::Ty(ty) => ty.span, - Node::TypeBinding(tb) => tb.span, + Node::AssocItemConstraint(constraint) => constraint.span, Node::TraitRef(tr) => tr.path.span, Node::Pat(pat) => pat.span, Node::PatField(field) => field.span, @@ -1167,7 +1167,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { Node::Stmt(_) => node_str("stmt"), Node::PathSegment(_) => node_str("path segment"), Node::Ty(_) => node_str("type"), - Node::TypeBinding(_) => node_str("type binding"), + Node::AssocItemConstraint(_) => node_str("assoc item constraint"), Node::TraitRef(_) => node_str("trait ref"), Node::Pat(_) => node_str("pat"), Node::PatField(_) => node_str("pattern field"), diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index d845e8ab90d5..fcedc1a4af3a 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -7,8 +7,8 @@ use ast::token::IdentIsRaw; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Token, TokenKind}; use rustc_ast::{ - self as ast, AngleBracketedArg, AngleBracketedArgs, AnonConst, AssocConstraint, - AssocConstraintKind, BlockCheckMode, GenericArg, GenericArgs, Generics, ParenthesizedArgs, + self as ast, AngleBracketedArg, AngleBracketedArgs, AnonConst, AssocItemConstraint, + AssocItemConstraintKind, BlockCheckMode, GenericArg, GenericArgs, Generics, ParenthesizedArgs, Path, PathSegment, QSelf, }; use rustc_errors::{Applicability, Diag, PResult}; @@ -720,10 +720,7 @@ impl<'a> Parser<'a> { )); } let kind = if self.eat(&token::Colon) { - // Parse associated type constraint bound. - - let bounds = self.parse_generic_bounds()?; - AssocConstraintKind::Bound { bounds } + AssocItemConstraintKind::Bound { bounds: self.parse_generic_bounds()? } } else if self.eat(&token::Eq) { self.parse_assoc_equality_term( ident, @@ -735,17 +732,17 @@ impl<'a> Parser<'a> { }; let span = lo.to(self.prev_token.span); - // Gate associated type bounds, e.g., `Iterator`. - if let AssocConstraintKind::Bound { .. } = kind { - if let Some(ast::GenericArgs::Parenthesized(args)) = &gen_args - && args.inputs.is_empty() - && matches!(args.output, ast::FnRetTy::Default(..)) - { - self.psess.gated_spans.gate(sym::return_type_notation, span); - } + + if let AssocItemConstraintKind::Bound { .. } = kind + && let Some(ast::GenericArgs::Parenthesized(args)) = &gen_args + && args.inputs.is_empty() + && let ast::FnRetTy::Default(..) = args.output + { + self.psess.gated_spans.gate(sym::return_type_notation, span); } + let constraint = - AssocConstraint { id: ast::DUMMY_NODE_ID, ident, gen_args, kind, span }; + AssocItemConstraint { id: ast::DUMMY_NODE_ID, ident, gen_args, kind, span }; Ok(Some(AngleBracketedArg::Constraint(constraint))) } else { // we only want to suggest `:` and `=` in contexts where the previous token @@ -772,7 +769,7 @@ impl<'a> Parser<'a> { ident: Ident, gen_args: Option<&GenericArgs>, eq: Span, - ) -> PResult<'a, AssocConstraintKind> { + ) -> PResult<'a, AssocItemConstraintKind> { let arg = self.parse_generic_arg(None)?; let span = ident.span.to(self.prev_token.span); let term = match arg { @@ -820,7 +817,7 @@ impl<'a> Parser<'a> { return Err(err); } }; - Ok(AssocConstraintKind::Equality { term }) + Ok(AssocItemConstraintKind::Equality { term }) } /// We do not permit arbitrary expressions as const arguments. They must be one of: @@ -941,7 +938,7 @@ impl<'a> Parser<'a> { } /// Given a arg inside of generics, we try to destructure it as if it were the LHS in - /// `LHS = ...`, i.e. an associated type binding. + /// `LHS = ...`, i.e. an associated item binding. /// This returns a bool indicating if there are any `for<'a, 'b>` binder args, the /// identifier, and any GAT arguments. fn get_ident_from_generic_arg( diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index a980d5dcaba4..bfc2c7b89b03 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -477,9 +477,9 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { hir_visit::walk_generic_args(self, ga) } - fn visit_assoc_type_binding(&mut self, type_binding: &'v hir::TypeBinding<'v>) { - self.record("TypeBinding", Id::Node(type_binding.hir_id), type_binding); - hir_visit::walk_assoc_type_binding(self, type_binding) + fn visit_assoc_item_constraint(&mut self, constraint: &'v hir::AssocItemConstraint<'v>) { + self.record("AssocItemConstraint", Id::Node(constraint.hir_id), constraint); + hir_visit::walk_assoc_item_constraint(self, constraint) } fn visit_attribute(&mut self, attr: &'v ast::Attribute) { @@ -688,7 +688,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { ast_visit::walk_path_segment(self, path_segment) } - // `GenericArgs` has one inline use (in `ast::AssocConstraint::gen_args`) and one + // `GenericArgs` has one inline use (in `ast::AssocItemConstraint::gen_args`) and one // non-inline use (in `ast::PathSegment::args`). The latter case is more // common, so we implement `visit_generic_args` and tolerate the double // counting in the former case. diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 63d0d6c260db..0c1726a4b653 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1148,7 +1148,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, self.diag_metadata.currently_processing_generic_args = prev; } - fn visit_assoc_constraint(&mut self, constraint: &'ast AssocConstraint) { + fn visit_assoc_item_constraint(&mut self, constraint: &'ast AssocItemConstraint) { self.visit_ident(constraint.ident); if let Some(ref gen_args) = constraint.gen_args { // Forbid anonymous lifetimes in GAT parameters until proper semantics are decided. @@ -1157,13 +1157,13 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, }); } match constraint.kind { - AssocConstraintKind::Equality { ref term } => match term { + AssocItemConstraintKind::Equality { ref term } => match term { Term::Ty(ty) => self.visit_ty(ty), Term::Const(c) => { self.resolve_anon_const(c, AnonConstKind::ConstArg(IsRepeatExpr::No)) } }, - AssocConstraintKind::Bound { ref bounds } => { + AssocItemConstraintKind::Bound { ref bounds } => { self.record_lifetime_params_for_impl_trait(constraint.id); walk_list!(self, visit_param_bound, bounds, BoundKind::Bound); } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 9daa22f89d2c..ec24eac4a9d0 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -508,7 +508,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { let ast::AngleBracketedArg::Constraint(constraint) = param else { continue; }; - let ast::AssocConstraintKind::Bound { bounds } = &constraint.kind else { + let ast::AssocItemConstraintKind::Bound { bounds } = &constraint.kind else { continue; }; for bound in bounds { @@ -3390,11 +3390,11 @@ fn mk_where_bound_predicate( }; let mut segments = ThinVec::from(preceding); - let added_constraint = ast::AngleBracketedArg::Constraint(ast::AssocConstraint { + let added_constraint = ast::AngleBracketedArg::Constraint(ast::AssocItemConstraint { id: DUMMY_NODE_ID, ident: last.ident, gen_args: None, - kind: ast::AssocConstraintKind::Equality { + kind: ast::AssocItemConstraintKind::Equality { term: ast::Term::Ty(ast::ptr::P(ast::Ty { kind: ast::TyKind::Path(None, poly_trait_ref.trait_ref.path.clone()), id: DUMMY_NODE_ID, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 6c56ebb62aed..7a61e77609b0 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -450,7 +450,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } /// When after several dereferencing, the reference satisfies the trait - /// binding. This function provides dereference suggestion for this + /// bound. This function provides dereference suggestion for this /// specific situation. fn suggest_dereferences( &self, @@ -777,7 +777,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } /// We tried to apply the bound to an `fn` or closure. Check whether calling it would - /// evaluate to a type that *would* satisfy the trait binding. If it would, suggest calling + /// evaluate to a type that *would* satisfy the trait bound. If it would, suggest calling /// it: `bar(foo)` → `bar(foo())`. This case is *very* likely to be hit if `foo` is `async`. fn suggest_fn_call( &self, @@ -1241,7 +1241,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let param_env = obligation.param_env; - // Try to apply the original trait binding obligation by borrowing. + // Try to apply the original trait bound by borrowing. let mut try_borrowing = |old_pred: ty::PolyTraitPredicate<'tcx>, blacklist: &[DefId]| -> bool { @@ -4908,14 +4908,12 @@ pub fn suggest_desugaring_async_fn_to_impl_future_in_trait<'tcx>( // `async fn` should always lower to a single bound... but don't ICE. return None; }; - let Some(hir::PathSegment { args: Some(generics), .. }) = - trait_ref.trait_ref.path.segments.last() + let Some(hir::PathSegment { args: Some(args), .. }) = trait_ref.trait_ref.path.segments.last() else { // desugaring to a single path segment for `Future<...>`. return None; }; - let Some(hir::TypeBindingKind::Equality { term: hir::Term::Ty(future_output_ty) }) = - generics.bindings.get(0).map(|binding| binding.kind) + let Some(future_output_ty) = args.constraints.first().and_then(|constraint| constraint.ty()) else { // Also should never happen. return None; diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index bccad29e0a98..ac927e9a1942 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -11,7 +11,7 @@ use thin_vec::ThinVec; use crate::clean::{self, simplify, Lifetime}; use crate::clean::{ - clean_generic_param_def, clean_middle_ty, clean_predicate, clean_trait_ref_with_bindings, + clean_generic_param_def, clean_middle_ty, clean_predicate, clean_trait_ref_with_constraints, clean_ty_generics, }; use crate::core::DocContext; @@ -121,7 +121,7 @@ fn synthesize_auto_trait_impl<'tcx>( kind: Box::new(clean::ImplItem(Box::new(clean::Impl { safety: hir::Safety::Safe, generics, - trait_: Some(clean_trait_ref_with_bindings(cx, trait_ref, ThinVec::new())), + 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, diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index 29be3a70d54b..4c7a2ecdb53f 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -10,7 +10,7 @@ use thin_vec::ThinVec; use crate::clean; use crate::clean::{ - clean_middle_assoc_item, clean_middle_ty, clean_trait_ref_with_bindings, clean_ty_generics, + clean_middle_assoc_item, clean_middle_ty, clean_trait_ref_with_constraints, clean_ty_generics, }; use crate::core::DocContext; @@ -95,7 +95,7 @@ pub(crate) fn synthesize_blanket_impls( ), // FIXME(eddyb) compute both `trait_` and `for_` from // the post-inference `trait_ref`, as it's more accurate. - trait_: Some(clean_trait_ref_with_bindings( + trait_: Some(clean_trait_ref_with_constraints( cx, ty::Binder::dummy(trait_ref.instantiate_identity()), ThinVec::new(), diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 2919a4c4beb0..c7366ce1a68c 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -20,7 +20,7 @@ use rustc_span::symbol::{kw, sym, Symbol}; use crate::clean::{ self, clean_bound_vars, clean_generics, clean_impl_item, clean_middle_assoc_item, - clean_middle_field, clean_middle_ty, clean_poly_fn_sig, clean_trait_ref_with_bindings, + clean_middle_field, clean_middle_ty, clean_poly_fn_sig, clean_trait_ref_with_constraints, clean_ty, clean_ty_alias_inner_type, clean_ty_generics, clean_variant_def, utils, Attributes, AttributesExt, ImplKind, ItemId, Type, }; @@ -566,7 +566,7 @@ pub(crate) fn build_impl( }; let polarity = tcx.impl_polarity(did); let trait_ = associated_trait - .map(|t| clean_trait_ref_with_bindings(cx, ty::Binder::dummy(t), ThinVec::new())); + .map(|t| clean_trait_ref_with_constraints(cx, ty::Binder::dummy(t), ThinVec::new())); if trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait() { super::build_deref_target_impls(cx, &trait_items, ret); } @@ -688,7 +688,7 @@ fn build_module_items( name: prim_ty.as_sym(), args: clean::GenericArgs::AngleBracketed { args: Default::default(), - bindings: ThinVec::new(), + constraints: ThinVec::new(), }, }], }, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 73737da482d0..839bfdf44af1 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -231,10 +231,10 @@ fn clean_generic_bound<'tcx>( }) } -pub(crate) fn clean_trait_ref_with_bindings<'tcx>( +pub(crate) fn clean_trait_ref_with_constraints<'tcx>( cx: &mut DocContext<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>, - bindings: ThinVec, + constraints: ThinVec, ) -> Path { let kind = cx.tcx.def_kind(trait_ref.def_id()).into(); if !matches!(kind, ItemType::Trait | ItemType::TraitAlias) { @@ -245,7 +245,7 @@ pub(crate) fn clean_trait_ref_with_bindings<'tcx>( cx, trait_ref.def_id(), true, - bindings, + constraints, trait_ref.map_bound(|tr| tr.args), ); @@ -254,14 +254,14 @@ pub(crate) fn clean_trait_ref_with_bindings<'tcx>( path } -fn clean_poly_trait_ref_with_bindings<'tcx>( +fn clean_poly_trait_ref_with_constraints<'tcx>( cx: &mut DocContext<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tcx>, - bindings: ThinVec, + constraints: ThinVec, ) -> GenericBound { GenericBound::TraitBound( PolyTrait { - trait_: clean_trait_ref_with_bindings(cx, poly_trait_ref, bindings), + trait_: clean_trait_ref_with_constraints(cx, poly_trait_ref, constraints), generic_params: clean_bound_vars(poly_trait_ref.bound_vars()), }, hir::TraitBoundModifier::None, @@ -395,7 +395,7 @@ fn clean_poly_trait_predicate<'tcx>( let poly_trait_ref = pred.map_bound(|pred| pred.trait_ref); Some(WherePredicate::BoundPredicate { ty: clean_middle_ty(poly_trait_ref.self_ty(), cx, None, None), - bounds: vec![clean_poly_trait_ref_with_bindings(cx, poly_trait_ref, ThinVec::new())], + bounds: vec![clean_poly_trait_ref_with_constraints(cx, poly_trait_ref, ThinVec::new())], bound_params: Vec::new(), }) } @@ -481,8 +481,11 @@ fn clean_projection<'tcx>( return clean_middle_opaque_bounds(cx, bounds); } - let trait_ = - clean_trait_ref_with_bindings(cx, ty.map_bound(|ty| ty.trait_ref(cx.tcx)), ThinVec::new()); + let trait_ = clean_trait_ref_with_constraints( + cx, + ty.map_bound(|ty| ty.trait_ref(cx.tcx)), + ThinVec::new(), + ); let self_type = clean_middle_ty(ty.map_bound(|ty| ty.self_ty()), cx, None, None); let self_def_id = if let Some(def_id) = def_id { cx.tcx.opt_parent(def_id).or(Some(def_id)) @@ -522,7 +525,7 @@ fn projection_to_path_segment<'tcx>( def_id, ) .into(), - bindings: Default::default(), + constraints: Default::default(), }, } } @@ -1453,8 +1456,8 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( _ => return true, } match &assoc.args { - GenericArgs::AngleBracketed { args, bindings } => { - if !bindings.is_empty() + GenericArgs::AngleBracketed { args, constraints } => { + if !constraints.is_empty() || generics .params .iter() @@ -2135,7 +2138,7 @@ pub(crate) fn clean_middle_ty<'tcx>( let bindings = obj .projection_bounds() - .map(|pb| TypeBinding { + .map(|pb| AssocItemConstraint { assoc: projection_to_path_segment( pb.map_bound(|pb| { pb @@ -2149,7 +2152,7 @@ pub(crate) fn clean_middle_ty<'tcx>( }), cx, ), - kind: TypeBindingKind::Equality { + kind: AssocItemConstraintKind::Equality { term: clean_middle_term(pb.map_bound(|pb| pb.term), cx), }, }) @@ -2198,7 +2201,7 @@ pub(crate) fn clean_middle_ty<'tcx>( def_id, ) .into(), - bindings: Default::default(), + constraints: Default::default(), }, }, should_show_cast: false, @@ -2304,14 +2307,14 @@ fn clean_middle_opaque_bounds<'tcx>( .filter_map(|bound| { if let ty::ClauseKind::Projection(proj) = bound.kind().skip_binder() { if proj.projection_term.trait_ref(cx.tcx) == trait_ref.skip_binder() { - Some(TypeBinding { + Some(AssocItemConstraint { assoc: projection_to_path_segment( // FIXME: This needs to be made resilient for `AliasTerm`s that // are associated consts. bound.kind().rebind(proj.projection_term.expect_ty(cx.tcx)), cx, ), - kind: TypeBindingKind::Equality { + kind: AssocItemConstraintKind::Equality { term: clean_middle_term(bound.kind().rebind(proj.term), cx), }, }) @@ -2324,7 +2327,7 @@ fn clean_middle_opaque_bounds<'tcx>( }) .collect(); - Some(clean_poly_trait_ref_with_bindings(cx, trait_ref, bindings)) + Some(clean_poly_trait_ref_with_constraints(cx, trait_ref, bindings)) }) .collect::>(); @@ -2505,11 +2508,12 @@ fn clean_generic_args<'tcx>( cx: &mut DocContext<'tcx>, ) -> GenericArgs { // FIXME(return_type_notation): Fix RTN parens rendering - if generic_args.parenthesized == hir::GenericArgsParentheses::ParenSugar { - let output = clean_ty(generic_args.bindings[0].ty(), cx); - let output = if output != Type::Tuple(Vec::new()) { Some(Box::new(output)) } else { None }; - let inputs = - generic_args.inputs().iter().map(|x| clean_ty(x, cx)).collect::>().into(); + if let Some((inputs, output)) = generic_args.paren_sugar_inputs_output() { + let inputs = inputs.iter().map(|x| clean_ty(x, cx)).collect::>().into(); + let output = match output.kind { + hir::TyKind::Tup(&[]) => None, + _ => Some(Box::new(clean_ty(output, cx))), + }; GenericArgs::Parenthesized { inputs, output } } else { let args = generic_args @@ -2536,9 +2540,12 @@ fn clean_generic_args<'tcx>( }) .collect::>() .into(); - let bindings = - generic_args.bindings.iter().map(|x| clean_type_binding(x, cx)).collect::>(); - GenericArgs::AngleBracketed { args, bindings } + let constraints = generic_args + .constraints + .iter() + .map(|c| clean_assoc_item_constraint(c, cx)) + .collect::>(); + GenericArgs::AngleBracketed { args, constraints } } } @@ -3107,20 +3114,20 @@ fn clean_maybe_renamed_foreign_item<'tcx>( }) } -fn clean_type_binding<'tcx>( - type_binding: &hir::TypeBinding<'tcx>, +fn clean_assoc_item_constraint<'tcx>( + constraint: &hir::AssocItemConstraint<'tcx>, cx: &mut DocContext<'tcx>, -) -> TypeBinding { - TypeBinding { +) -> AssocItemConstraint { + AssocItemConstraint { assoc: PathSegment { - name: type_binding.ident.name, - args: clean_generic_args(type_binding.gen_args, cx), + name: constraint.ident.name, + args: clean_generic_args(constraint.gen_args, cx), }, - kind: match type_binding.kind { - hir::TypeBindingKind::Equality { ref term } => { - TypeBindingKind::Equality { term: clean_hir_term(term, cx) } + kind: match constraint.kind { + hir::AssocItemConstraintKind::Equality { ref term } => { + AssocItemConstraintKind::Equality { term: clean_hir_term(term, cx) } } - hir::TypeBindingKind::Constraint { bounds } => TypeBindingKind::Constraint { + hir::AssocItemConstraintKind::Bound { bounds } => AssocItemConstraintKind::Bound { bounds: bounds.iter().filter_map(|b| clean_generic_bound(b, cx)).collect(), }, }, diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index 5a3ccb6239a0..af61eb6ae8de 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -90,10 +90,10 @@ pub(crate) fn merge_bounds( let last = trait_ref.trait_.segments.last_mut().expect("segments were empty"); match last.args { - PP::AngleBracketed { ref mut bindings, .. } => { - bindings.push(clean::TypeBinding { + PP::AngleBracketed { ref mut constraints, .. } => { + constraints.push(clean::AssocItemConstraint { assoc: assoc.clone(), - kind: clean::TypeBindingKind::Equality { term: rhs.clone() }, + kind: clean::AssocItemConstraintKind::Equality { term: rhs.clone() }, }); } PP::Parenthesized { ref mut output, .. } => match output { diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 7aab07c06a33..ce4e044336a4 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1627,9 +1627,9 @@ impl Type { if let Type::ImplTrait(mut v) = self && let Some(GenericBound::TraitBound(PolyTrait { mut trait_, .. }, _)) = v.pop() && let Some(segment) = trait_.segments.pop() - && let GenericArgs::AngleBracketed { mut bindings, .. } = segment.args - && let Some(binding) = bindings.pop() - && let TypeBindingKind::Equality { term } = binding.kind + && let GenericArgs::AngleBracketed { mut constraints, .. } = segment.args + && let Some(constraint) = constraints.pop() + && let AssocItemConstraintKind::Equality { term } = constraint.kind && let Term::Type(ty) = term { ty @@ -2259,34 +2259,38 @@ impl GenericArg { #[derive(Clone, PartialEq, Eq, Debug, Hash)] pub(crate) enum GenericArgs { - AngleBracketed { args: Box<[GenericArg]>, bindings: ThinVec }, + AngleBracketed { args: Box<[GenericArg]>, constraints: ThinVec }, Parenthesized { inputs: Box<[Type]>, output: Option> }, } impl GenericArgs { pub(crate) fn is_empty(&self) -> bool { match self { - GenericArgs::AngleBracketed { args, bindings } => { - args.is_empty() && bindings.is_empty() + GenericArgs::AngleBracketed { args, constraints } => { + args.is_empty() && constraints.is_empty() } GenericArgs::Parenthesized { inputs, output } => inputs.is_empty() && output.is_none(), } } - pub(crate) fn bindings<'a>(&'a self) -> Box + 'a> { + pub(crate) fn constraints<'a>(&'a self) -> Box + 'a> { match self { - GenericArgs::AngleBracketed { bindings, .. } => Box::new(bindings.iter().cloned()), + GenericArgs::AngleBracketed { constraints, .. } => { + Box::new(constraints.iter().cloned()) + } GenericArgs::Parenthesized { output, .. } => Box::new( output .as_ref() - .map(|ty| TypeBinding { + .map(|ty| AssocItemConstraint { assoc: PathSegment { name: sym::Output, args: GenericArgs::AngleBracketed { args: Vec::new().into_boxed_slice(), - bindings: ThinVec::new(), + constraints: ThinVec::new(), }, }, - kind: TypeBindingKind::Equality { term: Term::Type((**ty).clone()) }, + kind: AssocItemConstraintKind::Equality { + term: Term::Type((**ty).clone()), + }, }) .into_iter(), ), @@ -2545,18 +2549,27 @@ pub(crate) struct ProcMacro { pub(crate) helpers: Vec, } -/// An type binding on an associated type (e.g., `A = Bar` in `Foo` or -/// `A: Send + Sync` in `Foo`). +/// A constraint on an associated item. +/// +/// ### Examples +/// +/// * the `A = Ty` and `B = Ty` in `Trait` +/// * the `G = Ty` in `Trait = Ty>` +/// * the `A: Bound` in `Trait` +/// * the `RetTy` in `Trait(ArgTy, ArgTy) -> RetTy` +/// * the `C = { Ct }` in `Trait` (feature `associated_const_equality`) +/// * the `f(): Bound` in `Trait` (feature `return_type_notation`) #[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub(crate) struct TypeBinding { +pub(crate) struct AssocItemConstraint { pub(crate) assoc: PathSegment, - pub(crate) kind: TypeBindingKind, + pub(crate) kind: AssocItemConstraintKind, } +/// The kind of [associated item constraint][AssocItemConstraint]. #[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub(crate) enum TypeBindingKind { +pub(crate) enum AssocItemConstraintKind { Equality { term: Term }, - Constraint { bounds: Vec }, + Bound { bounds: Vec }, } // Some nodes are used a lot. Make sure they don't unintentionally get bigger. diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index aa923cc61173..995a4d6d48de 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -2,9 +2,10 @@ use crate::clean::auto_trait::synthesize_auto_trait_impls; use crate::clean::blanket_impl::synthesize_blanket_impls; use crate::clean::render_macro_matchers::render_macro_matcher; use crate::clean::{ - clean_doc_module, clean_middle_const, clean_middle_region, clean_middle_ty, inline, Crate, - ExternalCrate, Generic, GenericArg, GenericArgs, ImportSource, Item, ItemKind, Lifetime, Path, - PathSegment, Primitive, PrimitiveType, Term, Type, TypeBinding, TypeBindingKind, + clean_doc_module, clean_middle_const, clean_middle_region, clean_middle_ty, inline, + AssocItemConstraint, AssocItemConstraintKind, Crate, ExternalCrate, Generic, GenericArg, + GenericArgs, ImportSource, Item, ItemKind, Lifetime, Path, PathSegment, Primitive, + PrimitiveType, Term, Type, }; use crate::core::DocContext; use crate::html::format::visibility_to_src_with_space; @@ -200,11 +201,11 @@ fn can_elide_generic_arg<'tcx>( actual.skip_binder() == default.skip_binder() } -fn clean_middle_generic_args_with_bindings<'tcx>( +fn clean_middle_generic_args_with_constraints<'tcx>( cx: &mut DocContext<'tcx>, did: DefId, has_self: bool, - bindings: ThinVec, + constraints: ThinVec, ty_args: ty::Binder<'tcx, GenericArgsRef<'tcx>>, ) -> GenericArgs { let args = clean_middle_generic_args(cx, ty_args.map_bound(|args| &args[..]), has_self, did); @@ -219,17 +220,19 @@ fn clean_middle_generic_args_with_bindings<'tcx>( // The trait's first substitution is the one after self, if there is one. match ty.skip_binder().kind() { ty::Tuple(tys) => tys.iter().map(|t| clean_middle_ty(ty.rebind(t), cx, None, None)).collect::>().into(), - _ => return GenericArgs::AngleBracketed { args: args.into(), bindings }, + _ => return GenericArgs::AngleBracketed { args: args.into(), constraints }, }; - let output = bindings.into_iter().next().and_then(|binding| match binding.kind { - TypeBindingKind::Equality { term: Term::Type(ty) } if ty != Type::Tuple(Vec::new()) => { + let output = constraints.into_iter().next().and_then(|binding| match binding.kind { + AssocItemConstraintKind::Equality { term: Term::Type(ty) } + if ty != Type::Tuple(Vec::new()) => + { Some(Box::new(ty)) } _ => None, }); GenericArgs::Parenthesized { inputs, output } } else { - GenericArgs::AngleBracketed { args: args.into(), bindings } + GenericArgs::AngleBracketed { args: args.into(), constraints } } } @@ -237,7 +240,7 @@ pub(super) fn clean_middle_path<'tcx>( cx: &mut DocContext<'tcx>, did: DefId, has_self: bool, - bindings: ThinVec, + constraints: ThinVec, args: ty::Binder<'tcx, GenericArgsRef<'tcx>>, ) -> Path { let def_kind = cx.tcx.def_kind(did); @@ -246,7 +249,7 @@ pub(super) fn clean_middle_path<'tcx>( res: Res::Def(def_kind, did), segments: thin_vec![PathSegment { name, - args: clean_middle_generic_args_with_bindings(cx, did, has_self, bindings, args), + args: clean_middle_generic_args_with_constraints(cx, did, has_self, constraints, args), }], } } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 587c464b0ed1..03555dab5019 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -420,8 +420,8 @@ impl clean::GenericArgs { fn print<'a, 'tcx: 'a>(&'a self, cx: &'a Context<'tcx>) -> impl Display + 'a + Captures<'tcx> { display_fn(move |f| { match self { - clean::GenericArgs::AngleBracketed { args, bindings } => { - if !args.is_empty() || !bindings.is_empty() { + clean::GenericArgs::AngleBracketed { args, constraints } => { + if !args.is_empty() || !constraints.is_empty() { if f.alternate() { f.write_str("<")?; } else { @@ -439,15 +439,15 @@ impl clean::GenericArgs { write!(f, "{}", arg.print(cx))?; } } - for binding in bindings.iter() { + for constraint in constraints.iter() { if comma { f.write_str(", ")?; } comma = true; if f.alternate() { - write!(f, "{:#}", binding.print(cx))?; + write!(f, "{:#}", constraint.print(cx))?; } else { - write!(f, "{}", binding.print(cx))?; + write!(f, "{}", constraint.print(cx))?; } } if f.alternate() { @@ -1699,7 +1699,7 @@ impl clean::ImportSource { } } -impl clean::TypeBinding { +impl clean::AssocItemConstraint { pub(crate) fn print<'a, 'tcx: 'a>( &'a self, cx: &'a Context<'tcx>, @@ -1708,11 +1708,11 @@ impl clean::TypeBinding { f.write_str(self.assoc.name.as_str())?; self.assoc.args.print(cx).fmt(f)?; match self.kind { - clean::TypeBindingKind::Equality { ref term } => { + clean::AssocItemConstraintKind::Equality { ref term } => { f.write_str(" = ")?; term.print(cx).fmt(f)?; } - clean::TypeBindingKind::Constraint { ref bounds } => { + clean::AssocItemConstraintKind::Bound { ref bounds } => { if !bounds.is_empty() { f.write_str(": ")?; print_generic_bounds(bounds, cx).fmt(f)?; diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index e635c1e611de..bc8bdffc3314 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -727,7 +727,7 @@ pub(crate) fn get_function_type_for_search<'tcx>( name: *name, args: clean::GenericArgs::AngleBracketed { args: Vec::new().into_boxed_slice(), - bindings: ThinVec::new(), + constraints: ThinVec::new(), }, }) .collect(), @@ -1049,7 +1049,7 @@ fn simplify_fn_type<'tcx, 'a>( // So in here, we can add it directly and look for its own type parameters (so for `Option`, // we will look for them but not for `T`). let mut ty_generics = Vec::new(); - let mut ty_bindings = Vec::new(); + let mut ty_constraints = Vec::new(); if let Some(arg_generics) = arg.generic_args() { for ty in arg_generics.into_iter().filter_map(|gen| match gen { clean::GenericArg::Type(ty) => Some(ty), @@ -1067,14 +1067,14 @@ fn simplify_fn_type<'tcx, 'a>( cache, ); } - for binding in arg_generics.bindings() { - simplify_fn_binding( + for constraint in arg_generics.constraints() { + simplify_fn_constraint( self_, generics, - &binding, + &constraint, tcx, recurse + 1, - &mut ty_bindings, + &mut ty_constraints, rgen, is_return, cache, @@ -1137,7 +1137,7 @@ fn simplify_fn_type<'tcx, 'a>( *stored_bounds = type_bounds; } } - ty_bindings.push(( + ty_constraints.push(( RenderTypeId::AssociatedType(name), vec![RenderType { id: Some(RenderTypeId::Index(idx)), @@ -1152,17 +1152,17 @@ fn simplify_fn_type<'tcx, 'a>( if id.is_some() || !ty_generics.is_empty() { res.push(RenderType { id, - bindings: if ty_bindings.is_empty() { None } else { Some(ty_bindings) }, + bindings: if ty_constraints.is_empty() { None } else { Some(ty_constraints) }, generics: if ty_generics.is_empty() { None } else { Some(ty_generics) }, }); } } } -fn simplify_fn_binding<'tcx, 'a>( +fn simplify_fn_constraint<'tcx, 'a>( self_: Option<&'a Type>, generics: &Generics, - binding: &'a clean::TypeBinding, + constraint: &'a clean::AssocItemConstraint, tcx: TyCtxt<'tcx>, recurse: usize, res: &mut Vec<(RenderTypeId, Vec)>, @@ -1170,9 +1170,9 @@ fn simplify_fn_binding<'tcx, 'a>( is_return: bool, cache: &Cache, ) { - let mut ty_binding_constraints = Vec::new(); - let ty_binding_assoc = RenderTypeId::AssociatedType(binding.assoc.name); - for gen in &binding.assoc.args { + let mut ty_constraints = Vec::new(); + let ty_constrained_assoc = RenderTypeId::AssociatedType(constraint.assoc.name); + for gen in &constraint.assoc.args { match gen { clean::GenericArg::Type(arg) => simplify_fn_type( self_, @@ -1180,7 +1180,7 @@ fn simplify_fn_binding<'tcx, 'a>( &arg, tcx, recurse + 1, - &mut ty_binding_constraints, + &mut ty_constraints, rgen, is_return, cache, @@ -1190,11 +1190,11 @@ fn simplify_fn_binding<'tcx, 'a>( | clean::GenericArg::Infer => {} } } - for binding in binding.assoc.args.bindings() { - simplify_fn_binding( + for constraint in constraint.assoc.args.constraints() { + simplify_fn_constraint( self_, generics, - &binding, + &constraint, tcx, recurse + 1, res, @@ -1203,8 +1203,8 @@ fn simplify_fn_binding<'tcx, 'a>( cache, ); } - match &binding.kind { - clean::TypeBindingKind::Equality { term } => { + match &constraint.kind { + clean::AssocItemConstraintKind::Equality { term } => { if let clean::Term::Type(arg) = &term { simplify_fn_type( self_, @@ -1212,14 +1212,14 @@ fn simplify_fn_binding<'tcx, 'a>( arg, tcx, recurse + 1, - &mut ty_binding_constraints, + &mut ty_constraints, rgen, is_return, cache, ); } } - clean::TypeBindingKind::Constraint { bounds } => { + clean::AssocItemConstraintKind::Bound { bounds } => { for bound in &bounds[..] { if let Some(path) = bound.get_trait_path() { let ty = Type::Path { path }; @@ -1229,7 +1229,7 @@ fn simplify_fn_binding<'tcx, 'a>( &ty, tcx, recurse + 1, - &mut ty_binding_constraints, + &mut ty_constraints, rgen, is_return, cache, @@ -1238,7 +1238,7 @@ fn simplify_fn_binding<'tcx, 'a>( } } } - res.push((ty_binding_assoc, ty_binding_constraints)); + res.push((ty_constrained_assoc, ty_constraints)); } /// Return the full list of types when bounds have been resolved. diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index f856b4e9f16c..42237f7ddc78 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -153,9 +153,9 @@ impl FromWithTcx for GenericArgs { fn from_tcx(args: clean::GenericArgs, tcx: TyCtxt<'_>) -> Self { use clean::GenericArgs::*; match args { - AngleBracketed { args, bindings } => GenericArgs::AngleBracketed { + AngleBracketed { args, constraints } => GenericArgs::AngleBracketed { args: args.into_vec().into_tcx(tcx), - bindings: bindings.into_tcx(tcx), + bindings: constraints.into_tcx(tcx), }, Parenthesized { inputs, output } => GenericArgs::Parenthesized { inputs: inputs.into_vec().into_tcx(tcx), @@ -187,22 +187,22 @@ impl FromWithTcx for Constant { } } -impl FromWithTcx for TypeBinding { - fn from_tcx(binding: clean::TypeBinding, tcx: TyCtxt<'_>) -> Self { +impl FromWithTcx for TypeBinding { + fn from_tcx(constraint: clean::AssocItemConstraint, tcx: TyCtxt<'_>) -> Self { TypeBinding { - name: binding.assoc.name.to_string(), - args: binding.assoc.args.into_tcx(tcx), - binding: binding.kind.into_tcx(tcx), + name: constraint.assoc.name.to_string(), + args: constraint.assoc.args.into_tcx(tcx), + binding: constraint.kind.into_tcx(tcx), } } } -impl FromWithTcx for TypeBindingKind { - fn from_tcx(kind: clean::TypeBindingKind, tcx: TyCtxt<'_>) -> Self { - use clean::TypeBindingKind::*; +impl FromWithTcx for TypeBindingKind { + fn from_tcx(kind: clean::AssocItemConstraintKind, tcx: TyCtxt<'_>) -> Self { + use clean::AssocItemConstraintKind::*; match kind { Equality { term } => TypeBindingKind::Equality(term.into_tcx(tcx)), - Constraint { bounds } => TypeBindingKind::Constraint(bounds.into_tcx(tcx)), + Bound { bounds } => TypeBindingKind::Constraint(bounds.into_tcx(tcx)), } } } diff --git a/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs b/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs index dc935ed3d7fe..2b389d4f9b19 100644 --- a/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs +++ b/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs @@ -3,7 +3,7 @@ use clippy_utils::source::snippet; use rustc_errors::{Applicability, SuggestionStyle}; use rustc_hir::def_id::DefId; use rustc_hir::{ - GenericArg, GenericBound, GenericBounds, ItemKind, PredicateOrigin, TraitBoundModifier, TyKind, TypeBinding, + GenericArg, GenericBound, GenericBounds, ItemKind, PredicateOrigin, TraitBoundModifier, TyKind, AssocItemConstraint, WherePredicate, }; use rustc_hir_analysis::lower_ty; @@ -54,9 +54,9 @@ fn emit_lint( poly_trait: &rustc_hir::PolyTraitRef<'_>, bounds: GenericBounds<'_>, index: usize, - // The bindings that were implied, used for suggestion purposes since removing a bound with associated types - // means we might need to then move it to a different bound - implied_bindings: &[TypeBinding<'_>], + // The constraints that were implied, used for suggestion purposes since removing a bound with + // associated types means we might need to then move it to a different bound. + implied_constraints: &[AssocItemConstraint<'_>], bound: &ImplTraitBound<'_>, ) { let implied_by = snippet(cx, bound.span, ".."); @@ -83,29 +83,29 @@ fn emit_lint( let mut sugg = vec![(implied_span_extended, String::new())]; - // We also might need to include associated type binding that were specified in the implied bound, + // We also might need to include associated item constraints that were specified in the implied bound, // but omitted in the implied-by bound: // `fn f() -> impl Deref + DerefMut` // If we're going to suggest removing `Deref<..>`, we'll need to put `` on `DerefMut` - let omitted_assoc_tys: Vec<_> = implied_bindings + let omitted_constraints: Vec<_> = implied_constraints .iter() - .filter(|binding| !bound.bindings.iter().any(|b| b.ident == binding.ident)) + .filter(|constraint| !bound.constraints.iter().any(|c| c.ident == constraint.ident)) .collect(); - if !omitted_assoc_tys.is_empty() { - // `<>` needs to be added if there aren't yet any generic arguments or bindings - let needs_angle_brackets = bound.args.is_empty() && bound.bindings.is_empty(); - let insert_span = match (bound.args, bound.bindings) { - ([.., arg], [.., binding]) => arg.span().max(binding.span).shrink_to_hi(), + if !omitted_constraints.is_empty() { + // `<>` needs to be added if there aren't yet any generic arguments or constraints + let needs_angle_brackets = bound.args.is_empty() && bound.constraints.is_empty(); + let insert_span = match (bound.args, bound.constraints) { + ([.., arg], [.., constraint]) => arg.span().max(constraint.span).shrink_to_hi(), ([.., arg], []) => arg.span().shrink_to_hi(), - ([], [.., binding]) => binding.span.shrink_to_hi(), + ([], [.., constraint]) => constraint.span.shrink_to_hi(), ([], []) => bound.span.shrink_to_hi(), }; - let mut associated_tys_sugg = if needs_angle_brackets { + let mut constraints_sugg = if needs_angle_brackets { "<".to_owned() } else { - // If angle brackets aren't needed (i.e., there are already generic arguments or bindings), + // If angle brackets aren't needed (i.e., there are already generic arguments or constraints), // we need to add a comma: // `impl A` // ^ if we insert `Assoc=i32` without a comma here, that'd be invalid syntax: @@ -113,16 +113,16 @@ fn emit_lint( ", ".to_owned() }; - for (index, binding) in omitted_assoc_tys.into_iter().enumerate() { + for (index, constraint) in omitted_constraints.into_iter().enumerate() { if index > 0 { - associated_tys_sugg += ", "; + constraints_sugg += ", "; } - associated_tys_sugg += &snippet(cx, binding.span, ".."); + constraints_sugg += &snippet(cx, constraint.span, ".."); } if needs_angle_brackets { - associated_tys_sugg += ">"; + constraints_sugg += ">"; } - sugg.push((insert_span, associated_tys_sugg)); + sugg.push((insert_span, constraints_sugg)); } diag.multipart_suggestion_with_style( @@ -229,8 +229,8 @@ struct ImplTraitBound<'tcx> { trait_def_id: DefId, /// The generic arguments on the `impl Trait` bound args: &'tcx [GenericArg<'tcx>], - /// The associated types on this bound - bindings: &'tcx [TypeBinding<'tcx>], + /// The associated item constraints of this bound + constraints: &'tcx [AssocItemConstraint<'tcx>], } /// Given an `impl Trait` type, gets all the supertraits from each bound ("implied bounds"). @@ -253,7 +253,7 @@ fn collect_supertrait_bounds<'tcx>(cx: &LateContext<'tcx>, bounds: GenericBounds Some(ImplTraitBound { predicates, args: path.args.map_or([].as_slice(), |p| p.args), - bindings: path.args.map_or([].as_slice(), |p| p.bindings), + constraints: path.args.map_or([].as_slice(), |p| p.constraints), trait_def_id, span: bound.span(), }) @@ -310,20 +310,20 @@ fn check<'tcx>(cx: &LateContext<'tcx>, bounds: GenericBounds<'tcx>) { if let GenericBound::Trait(poly_trait, TraitBoundModifier::None) = bound && let [.., path] = poly_trait.trait_ref.path.segments && let implied_args = path.args.map_or([].as_slice(), |a| a.args) - && let implied_bindings = path.args.map_or([].as_slice(), |a| a.bindings) + && let implied_constraints = path.args.map_or([].as_slice(), |a| a.constraints) && let Some(def_id) = poly_trait.trait_ref.path.res.opt_def_id() && let Some(bound) = find_bound_in_supertraits(cx, def_id, implied_args, &supertraits) // If the implied bound has a type binding that also exists in the implied-by trait, // then we shouldn't lint. See #11880 for an example. && let assocs = cx.tcx.associated_items(bound.trait_def_id) - && !implied_bindings.iter().any(|binding| { + && !implied_constraints.iter().any(|constraint| { assocs - .filter_by_name_unhygienic(binding.ident.name) + .filter_by_name_unhygienic(constraint.ident.name) .next() .is_some_and(|assoc| assoc.kind == ty::AssocKind::Type) }) { - emit_lint(cx, poly_trait, bounds, index, implied_bindings, bound); + emit_lint(cx, poly_trait, bounds, index, implied_constraints, bound); } } } diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs index 97a245b76d44..2091e74665fb 100644 --- a/src/tools/clippy/clippy_lints/src/len_zero.rs +++ b/src/tools/clippy/clippy_lints/src/len_zero.rs @@ -9,7 +9,7 @@ use rustc_hir::def_id::{DefId, DefIdSet}; use rustc_hir::{ AssocItemKind, BinOpKind, Expr, ExprKind, FnRetTy, GenericArg, GenericBound, ImplItem, ImplItemKind, ImplicitSelfKind, Item, ItemKind, Mutability, Node, OpaqueTyOrigin, PatKind, PathSegment, PrimTy, QPath, - TraitItemRef, TyKind, TypeBindingKind, + TraitItemRef, TyKind, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, AssocKind, FnSig, Ty}; @@ -307,17 +307,12 @@ fn extract_future_output<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<& && let [GenericBound::Trait(trait_ref, _)] = &opaque.bounds && let Some(segment) = trait_ref.trait_ref.path.segments.last() && let Some(generic_args) = segment.args - && generic_args.bindings.len() == 1 - && let TypeBindingKind::Equality { - term: - rustc_hir::Term::Ty(rustc_hir::Ty { - kind: TyKind::Path(QPath::Resolved(_, path)), - .. - }), - } = &generic_args.bindings[0].kind - && path.segments.len() == 1 + && let [constraint] = generic_args.constraints + && let Some(ty) = constraint.ty() + && let TyKind::Path(QPath::Resolved(_, path)) = ty.kind + && let [segment] = path.segments { - return Some(&path.segments[0]); + return Some(segment); } None diff --git a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs index 4cd5f3b81e52..25c7e5d38b31 100644 --- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs +++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs @@ -4,8 +4,7 @@ use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; use rustc_hir::{ Block, Body, Closure, ClosureKind, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, FnDecl, - FnRetTy, GenericArg, GenericBound, ImplItem, Item, ItemKind, LifetimeName, Node, Term, TraitRef, Ty, TyKind, - TypeBindingKind, + FnRetTy, GenericArg, GenericBound, ImplItem, Item, ItemKind, LifetimeName, Node, TraitRef, Ty, TyKind, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; @@ -138,10 +137,9 @@ fn future_trait_ref<'tcx>( fn future_output_ty<'tcx>(trait_ref: &'tcx TraitRef<'tcx>) -> Option<&'tcx Ty<'tcx>> { if let Some(segment) = trait_ref.path.segments.last() && let Some(args) = segment.args - && args.bindings.len() == 1 - && let binding = &args.bindings[0] - && binding.ident.name == sym::Output - && let TypeBindingKind::Equality { term: Term::Ty(output) } = binding.kind + && let [constraint] = args.constraints + && constraint.ident.name == sym::Output + && let Some(output) = constraint.ty() { return Some(output); } diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index d4a5f547211a..bbdde3049dbd 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -108,7 +108,7 @@ pub fn eq_generic_args(l: &GenericArgs, r: &GenericArgs) -> bool { pub fn eq_angle_arg(l: &AngleBracketedArg, r: &AngleBracketedArg) -> bool { match (l, r) { (AngleBracketedArg::Arg(l), AngleBracketedArg::Arg(r)) => eq_generic_arg(l, r), - (AngleBracketedArg::Constraint(l), AngleBracketedArg::Constraint(r)) => eq_assoc_constraint(l, r), + (AngleBracketedArg::Constraint(l), AngleBracketedArg::Constraint(r)) => eq_assoc_item_constraint(l, r), _ => false, } } @@ -802,8 +802,8 @@ fn eq_term(l: &Term, r: &Term) -> bool { } } -pub fn eq_assoc_constraint(l: &AssocConstraint, r: &AssocConstraint) -> bool { - use AssocConstraintKind::*; +pub fn eq_assoc_item_constraint(l: &AssocItemConstraint, r: &AssocItemConstraint) -> bool { + use AssocItemConstraintKind::*; eq_id(l.ident, r.ident) && match (&l.kind, &r.kind) { (Equality { term: l }, Equality { term: r }) => eq_term(l, r), diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 9f285621e0c9..36634817fc91 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -9,7 +9,7 @@ use rustc_hir::MatchSource::TryDesugar; use rustc_hir::{ ArrayLen, BinOpKind, BindingMode, Block, BodyId, Closure, Expr, ExprField, ExprKind, FnRetTy, GenericArg, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime, LifetimeName, Pat, PatField, PatKind, Path, - PathSegment, PrimTy, QPath, Stmt, StmtKind, Ty, TyKind, TypeBinding, + PathSegment, PrimTy, QPath, Stmt, StmtKind, Ty, TyKind, AssocItemConstraint, }; use rustc_lexer::{tokenize, TokenKind}; use rustc_lint::LateContext; @@ -486,7 +486,7 @@ impl HirEqInterExpr<'_, '_, '_> { fn eq_path_parameters(&mut self, left: &GenericArgs<'_>, right: &GenericArgs<'_>) -> bool { if left.parenthesized == right.parenthesized { over(left.args, right.args, |l, r| self.eq_generic_arg(l, r)) // FIXME(flip1995): may not work - && over(left.bindings, right.bindings, |l, r| self.eq_type_binding(l, r)) + && over(left.constraints, right.constraints, |l, r| self.eq_assoc_type_binding(l, r)) } else { false } @@ -518,8 +518,8 @@ impl HirEqInterExpr<'_, '_, '_> { } } - fn eq_type_binding(&mut self, left: &TypeBinding<'_>, right: &TypeBinding<'_>) -> bool { - left.ident.name == right.ident.name && self.eq_ty(left.ty(), right.ty()) + fn eq_assoc_type_binding(&mut self, left: &AssocItemConstraint<'_>, right: &AssocItemConstraint<'_>) -> bool { + left.ident.name == right.ident.name && self.eq_ty(left.ty().expect("expected assoc type binding"), right.ty().expect("expected assoc type binding")) } fn check_ctxt(&mut self, left: SyntaxContext, right: SyntaxContext) -> bool { diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index 75dea90d994c..7d14d9e727ab 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -140,7 +140,7 @@ pub(crate) enum SegmentParam<'a> { Const(&'a ast::AnonConst), LifeTime(&'a ast::Lifetime), Type(&'a ast::Ty), - Binding(&'a ast::AssocConstraint), + Binding(&'a ast::AssocItemConstraint), } impl<'a> SegmentParam<'a> { @@ -175,9 +175,9 @@ impl<'a> Rewrite for SegmentParam<'a> { } } -impl Rewrite for ast::AssocConstraint { +impl Rewrite for ast::AssocItemConstraint { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { - use ast::AssocConstraintKind::{Bound, Equality}; + use ast::AssocItemConstraintKind::{Bound, Equality}; let mut result = String::with_capacity(128); result.push_str(rewrite_ident(context, self.ident)); @@ -205,14 +205,14 @@ impl Rewrite for ast::AssocConstraint { } } -impl Rewrite for ast::AssocConstraintKind { +impl Rewrite for ast::AssocItemConstraintKind { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { match self { - ast::AssocConstraintKind::Equality { term } => match term { + ast::AssocItemConstraintKind::Equality { term } => match term { Term::Ty(ty) => ty.rewrite(context, shape), Term::Const(c) => c.rewrite(context, shape), }, - ast::AssocConstraintKind::Bound { bounds } => bounds.rewrite(context, shape), + ast::AssocItemConstraintKind::Bound { bounds } => bounds.rewrite(context, shape), } } } diff --git a/tests/rustdoc-ui/invalid_associated_const.rs b/tests/rustdoc-ui/invalid_associated_const.rs index 6f211a383a6f..f93834268f63 100644 --- a/tests/rustdoc-ui/invalid_associated_const.rs +++ b/tests/rustdoc-ui/invalid_associated_const.rs @@ -2,8 +2,8 @@ trait T { type A: S = 34>; - //~^ ERROR associated type bindings are not allowed here - //~| ERROR associated type bindings are not allowed here + //~^ ERROR associated item constraints are not allowed here + //~| ERROR associated item constraints are not allowed here } trait S { diff --git a/tests/rustdoc-ui/invalid_associated_const.stderr b/tests/rustdoc-ui/invalid_associated_const.stderr index 5eaddc2b8c98..6e5ddc449828 100644 --- a/tests/rustdoc-ui/invalid_associated_const.stderr +++ b/tests/rustdoc-ui/invalid_associated_const.stderr @@ -1,22 +1,22 @@ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/invalid_associated_const.rs:4:17 | LL | type A: S = 34>; - | ^^^^^^^^ associated type not allowed here + | ^^^^^^^^ associated item constraint not allowed here | -help: consider removing this type binding +help: consider removing this associated item binding | LL | type A: S = 34>; | ~~~~~~~~~~ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/invalid_associated_const.rs:4:17 | LL | type A: S = 34>; - | ^^^^^^^^ associated type not allowed here + | ^^^^^^^^ associated item constraint not allowed here | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: consider removing this type binding +help: consider removing this associated item binding | LL | type A: S = 34>; | ~~~~~~~~~~ diff --git a/tests/rustdoc-ui/issue-102467.rs b/tests/rustdoc-ui/issue-102467.rs index a27e61569794..d9bd48103d24 100644 --- a/tests/rustdoc-ui/issue-102467.rs +++ b/tests/rustdoc-ui/issue-102467.rs @@ -5,8 +5,8 @@ trait T { type A: S = 34>; - //~^ ERROR associated type bindings are not allowed here - //~| ERROR associated type bindings are not allowed here + //~^ ERROR associated item constraints are not allowed here + //~| ERROR associated item constraints are not allowed here } trait S { diff --git a/tests/rustdoc-ui/issue-102467.stderr b/tests/rustdoc-ui/issue-102467.stderr index 119ca949e999..99f911023192 100644 --- a/tests/rustdoc-ui/issue-102467.stderr +++ b/tests/rustdoc-ui/issue-102467.stderr @@ -1,22 +1,22 @@ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/issue-102467.rs:7:17 | LL | type A: S = 34>; - | ^^^^^^^^ associated type not allowed here + | ^^^^^^^^ associated item constraint not allowed here | -help: consider removing this type binding +help: consider removing this associated item binding | LL | type A: S = 34>; | ~~~~~~~~~~ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/issue-102467.rs:7:17 | LL | type A: S = 34>; - | ^^^^^^^^ associated type not allowed here + | ^^^^^^^^ associated item constraint not allowed here | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: consider removing this type binding +help: consider removing this associated item binding | LL | type A: S = 34>; | ~~~~~~~~~~ diff --git a/tests/ui/associated-consts/issue-102335-const.rs b/tests/ui/associated-consts/issue-102335-const.rs index 969c2c43b716..fd922cd0f1d8 100644 --- a/tests/ui/associated-consts/issue-102335-const.rs +++ b/tests/ui/associated-consts/issue-102335-const.rs @@ -2,8 +2,8 @@ trait T { type A: S = 34>; - //~^ ERROR associated type bindings are not allowed here - //~| ERROR associated type bindings are not allowed here + //~^ ERROR associated item constraints are not allowed here + //~| ERROR associated item constraints are not allowed here } trait S { diff --git a/tests/ui/associated-consts/issue-102335-const.stderr b/tests/ui/associated-consts/issue-102335-const.stderr index 905d7c75c200..dc1631220e2a 100644 --- a/tests/ui/associated-consts/issue-102335-const.stderr +++ b/tests/ui/associated-consts/issue-102335-const.stderr @@ -1,22 +1,22 @@ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/issue-102335-const.rs:4:17 | LL | type A: S = 34>; - | ^^^^^^^^ associated type not allowed here + | ^^^^^^^^ associated item constraint not allowed here | -help: consider removing this type binding +help: consider removing this associated item binding | LL | type A: S = 34>; | ~~~~~~~~~~ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/issue-102335-const.rs:4:17 | LL | type A: S = 34>; - | ^^^^^^^^ associated type not allowed here + | ^^^^^^^^ associated item constraint not allowed here | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: consider removing this type binding +help: consider removing this associated item binding | LL | type A: S = 34>; | ~~~~~~~~~~ diff --git a/tests/ui/associated-type-bounds/issue-102335-ty.rs b/tests/ui/associated-type-bounds/issue-102335-ty.rs index b2df68b18ae4..86bde6367a4c 100644 --- a/tests/ui/associated-type-bounds/issue-102335-ty.rs +++ b/tests/ui/associated-type-bounds/issue-102335-ty.rs @@ -1,13 +1,13 @@ trait T { type A: S = ()>; // Just one erroneous equality constraint - //~^ ERROR associated type bindings are not allowed here - //~| ERROR associated type bindings are not allowed here + //~^ ERROR associated item constraints are not allowed here + //~| ERROR associated item constraints are not allowed here } trait T2 { type A: S = ()>; // More than one erroneous equality constraints - //~^ ERROR associated type bindings are not allowed here - //~| ERROR associated type bindings are not allowed here + //~^ ERROR associated item constraints are not allowed here + //~| ERROR associated item constraints are not allowed here } trait Q {} diff --git a/tests/ui/associated-type-bounds/issue-102335-ty.stderr b/tests/ui/associated-type-bounds/issue-102335-ty.stderr index cf30b0a4f6ca..cd585f7f7d8f 100644 --- a/tests/ui/associated-type-bounds/issue-102335-ty.stderr +++ b/tests/ui/associated-type-bounds/issue-102335-ty.stderr @@ -1,45 +1,45 @@ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/issue-102335-ty.rs:2:17 | LL | type A: S = ()>; // Just one erroneous equality constraint - | ^^^^^^^^^ associated type not allowed here + | ^^^^^^^^^ associated item constraint not allowed here | -help: consider removing this type binding +help: consider removing this associated item binding | LL | type A: S = ()>; // Just one erroneous equality constraint | ~~~~~~~~~~~ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/issue-102335-ty.rs:2:17 | LL | type A: S = ()>; // Just one erroneous equality constraint - | ^^^^^^^^^ associated type not allowed here + | ^^^^^^^^^ associated item constraint not allowed here | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: consider removing this type binding +help: consider removing this associated item binding | LL | type A: S = ()>; // Just one erroneous equality constraint | ~~~~~~~~~~~ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/issue-102335-ty.rs:8:17 | LL | type A: S = ()>; // More than one erroneous equality constraints - | ^^^^^^^^^ associated type not allowed here + | ^^^^^^^^^ associated item constraint not allowed here | -help: consider removing this type binding +help: consider removing this associated item binding | LL | type A: S = ()>; // More than one erroneous equality constraints | ~~~~~~~~~~ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/issue-102335-ty.rs:8:17 | LL | type A: S = ()>; // More than one erroneous equality constraints - | ^^^^^^^^^ associated type not allowed here + | ^^^^^^^^^ associated item constraint not allowed here | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: consider removing this type binding +help: consider removing this associated item binding | LL | type A: S = ()>; // More than one erroneous equality constraints | ~~~~~~~~~~ diff --git a/tests/ui/associated-type-bounds/no-gat-position.rs b/tests/ui/associated-type-bounds/no-gat-position.rs index 5005c5027f42..cb62c8824681 100644 --- a/tests/ui/associated-type-bounds/no-gat-position.rs +++ b/tests/ui/associated-type-bounds/no-gat-position.rs @@ -4,7 +4,7 @@ pub trait Iter { type Item<'a>: 'a where Self: 'a; fn next<'a>(&'a mut self) -> Option>; - //~^ ERROR associated type bindings are not allowed here + //~^ ERROR associated item constraints are not allowed here } impl Iter for () { diff --git a/tests/ui/associated-type-bounds/no-gat-position.stderr b/tests/ui/associated-type-bounds/no-gat-position.stderr index c348d33c3a9a..e167ac1fda45 100644 --- a/tests/ui/associated-type-bounds/no-gat-position.stderr +++ b/tests/ui/associated-type-bounds/no-gat-position.stderr @@ -1,8 +1,8 @@ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/no-gat-position.rs:6:56 | LL | fn next<'a>(&'a mut self) -> Option>; - | ^^^^^^^^^ associated type not allowed here + | ^^^^^^^^^ associated item constraint not allowed here error: aborting due to 1 previous error diff --git a/tests/ui/associated-types/associated-types-eq-2.rs b/tests/ui/associated-types/associated-types-eq-2.rs index 43b0208461e4..f0a7d1e46b1b 100644 --- a/tests/ui/associated-types/associated-types-eq-2.rs +++ b/tests/ui/associated-types/associated-types-eq-2.rs @@ -18,14 +18,14 @@ impl Tr1 for isize { // Test for when the assoc type is // specified as an equality constraint impl Tr1 for usize { -//~^ ERROR associated type bindings are not allowed here +//~^ ERROR associated item constraints are not allowed here //~| ERROR not all trait items implemented, missing: `A` fn boo(&self) -> usize { 42 } } // Test for a wronngly used equality constraint in a func arg fn baz(_x: &>::A) {} -//~^ ERROR associated type bindings are not allowed here +//~^ ERROR associated item constraints are not allowed here @@ -38,28 +38,28 @@ trait Tr2 { // (Note: E0229 is emitted only for the first erroneous equality // constraint (T2) not for any subequent ones (e.g. T3)) impl Tr2 for Bar { -//~^ ERROR associated type bindings are not allowed here +//~^ ERROR associated item constraints are not allowed here //~| ERROR trait takes 3 generic arguments but 1 generic argument was supplied } // Test for when equality constraint's ident matches a // generic param's ident but has different case impl Tr2 for Qux { -//~^ ERROR associated type bindings are not allowed here +//~^ ERROR associated item constraints are not allowed here //~| ERROR trait takes 3 generic arguments but 1 generic argument was supplied } // Test for when equality constraint's ident // matches none of the generic param idents impl Tr2 for Bar { -//~^ ERROR associated type bindings are not allowed here +//~^ ERROR associated item constraints are not allowed here //~| ERROR trait takes 3 generic arguments but 1 generic argument was supplied } // Test for when the term in equality constraint is itself generic struct GenericTerm { _t: T } impl Tr2> for Bar { -//~^ ERROR associated type bindings are not allowed here +//~^ ERROR associated item constraints are not allowed here //~| ERROR trait takes 3 generic arguments but 2 generic arguments were supplied } @@ -74,7 +74,7 @@ trait Tr3 { // (Deliberately spread over multiple lines to test that // our suggestion spans are kosher in the face of such formatting) impl Tr3 for Bar { @@ -83,7 +83,7 @@ impl Tr3 for Qux { -//~^ ERROR associated type bindings are not allowed here +//~^ ERROR associated item constraints are not allowed here //~| ERROR associated const equality is incomplete //~| ERROR trait takes 3 generic arguments but 0 generic arguments were supplied } @@ -91,14 +91,14 @@ impl Tr3 for Qux { // Test for when equality constraint's ident // matches the const param ident but the constraint is a type arg impl Tr3 for Bar { -//~^ ERROR associated type bindings are not allowed here +//~^ ERROR associated item constraints are not allowed here //~| ERROR trait takes 3 generic arguments but 0 generic arguments were supplied } // Test for when equality constraint's ident // matches a type param ident but the constraint is a const arg impl Tr3<42, T2 = 42, T3 = usize> for Bar { -//~^ ERROR associated type bindings are not allowed here +//~^ ERROR associated item constraints are not allowed here //~| ERROR associated const equality is incomplete //~| ERROR trait takes 3 generic arguments but 1 generic argument was supplied } @@ -106,7 +106,7 @@ impl Tr3<42, T2 = 42, T3 = usize> for Bar { // Test for when equality constraint's ident // matches none of the param idents impl Tr3 for Bar { -//~^ ERROR associated type bindings are not allowed here +//~^ ERROR associated item constraints are not allowed here //~| ERROR associated const equality is incomplete //~| ERROR trait takes 3 generic arguments but 0 generic arguments were supplied } @@ -117,7 +117,7 @@ impl Tr3 for Bar { struct St<'a, T> { v: &'a T } impl<'a, T> St<'a , T = Qux> { -//~^ ERROR associated type bindings are not allowed here +//~^ ERROR associated item constraints are not allowed here //~| ERROR struct takes 1 generic argument but 0 generic arguments were supplied } diff --git a/tests/ui/associated-types/associated-types-eq-2.stderr b/tests/ui/associated-types/associated-types-eq-2.stderr index b68c82f590c1..53e4e59128ea 100644 --- a/tests/ui/associated-types/associated-types-eq-2.stderr +++ b/tests/ui/associated-types/associated-types-eq-2.stderr @@ -43,13 +43,13 @@ LL | impl Tr3 for Bar { = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/associated-types-eq-2.rs:20:10 | LL | impl Tr1 for usize { - | ^^^^^^^^^ associated type not allowed here + | ^^^^^^^^^ associated item constraint not allowed here | -help: consider removing this type binding +help: consider removing this associated item binding | LL | impl Tr1 for usize { | ~~~~~~~~~~~ @@ -63,13 +63,13 @@ LL | type A; LL | impl Tr1 for usize { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `A` in implementation -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/associated-types-eq-2.rs:27:31 | LL | fn baz(_x: &>::A) {} - | ^^^^^ associated type not allowed here + | ^^^^^ associated item constraint not allowed here | -help: consider removing this type binding +help: consider removing this associated item binding | LL | fn baz(_x: &>::A) {} | ~~~~~~~ @@ -92,11 +92,11 @@ help: add missing generic arguments LL | impl Tr2 for Bar { | ++++++++ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/associated-types-eq-2.rs:40:15 | LL | impl Tr2 for Bar { - | ^^^^^^^^ associated type not allowed here + | ^^^^^^^^ associated item constraint not allowed here | help: to use `Qux` as a generic argument specify it directly | @@ -121,13 +121,13 @@ help: add missing generic arguments LL | impl Tr2 for Qux { | ++++++++ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/associated-types-eq-2.rs:47:15 | LL | impl Tr2 for Qux { - | ^^^^^^^^ associated type not allowed here + | ^^^^^^^^ associated item constraint not allowed here | -help: consider removing this type binding +help: consider removing this associated item binding | LL | impl Tr2 for Qux { | ~~~~~~~~~~ @@ -150,13 +150,13 @@ help: add missing generic arguments LL | impl Tr2 for Bar { | ++++++++ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/associated-types-eq-2.rs:54:15 | LL | impl Tr2 for Bar { - | ^^^^^^^ associated type not allowed here + | ^^^^^^^ associated item constraint not allowed here | -help: consider removing this type binding +help: consider removing this associated item binding | LL | impl Tr2 for Bar { | ~~~~~~~~~ @@ -179,11 +179,11 @@ help: add missing generic argument LL | impl Tr2> for Bar { | ++++ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/associated-types-eq-2.rs:61:20 | LL | impl Tr2> for Bar { - | ^^^^^^^^^^^^^^^^^^^^^ associated type not allowed here + | ^^^^^^^^^^^^^^^^^^^^^ associated item constraint not allowed here | help: to use `GenericTerm` as a generic argument specify it directly | @@ -206,7 +206,7 @@ help: add missing generic arguments LL | impl Tr3 $DIR/associated-types-eq-2.rs:76:10 | LL | impl Tr3 for Bar { - | |____^ associated type not allowed here + | |____^ associated item constraint not allowed here | help: to use `42` as a generic argument specify it directly | @@ -238,13 +238,13 @@ help: add missing generic arguments LL | impl Tr3 for Qux { | ++++++++++ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/associated-types-eq-2.rs:85:10 | LL | impl Tr3 for Qux { - | ^^^^^^ associated type not allowed here + | ^^^^^^ associated item constraint not allowed here | -help: consider removing this type binding +help: consider removing this associated item binding | LL | impl Tr3 for Qux { | ~~~~~~~ @@ -265,13 +265,13 @@ help: add missing generic arguments LL | impl Tr3 for Bar { | ++++++++++ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/associated-types-eq-2.rs:93:10 | LL | impl Tr3 for Bar { - | ^^^^^^^ associated type not allowed here + | ^^^^^^^ associated item constraint not allowed here | -help: consider removing this type binding +help: consider removing this associated item binding | LL | impl Tr3 for Bar { | ~~~~~~~~ @@ -294,13 +294,13 @@ help: add missing generic arguments LL | impl Tr3<42, T2, T3, T2 = 42, T3 = usize> for Bar { | ++++++++ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/associated-types-eq-2.rs:100:14 | LL | impl Tr3<42, T2 = 42, T3 = usize> for Bar { - | ^^^^^^^ associated type not allowed here + | ^^^^^^^ associated item constraint not allowed here | -help: consider removing this type binding +help: consider removing this associated item binding | LL | impl Tr3<42, T2 = 42, T3 = usize> for Bar { | ~~~~~~~~~ @@ -321,13 +321,13 @@ help: add missing generic arguments LL | impl Tr3 for Bar { | ++++++++++ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/associated-types-eq-2.rs:108:10 | LL | impl Tr3 for Bar { - | ^^^^^^ associated type not allowed here + | ^^^^^^ associated item constraint not allowed here | -help: consider removing this type binding +help: consider removing this associated item binding | LL | impl Tr3 for Bar { | ~~~~~~~ @@ -348,11 +348,11 @@ help: add missing generic argument LL | impl<'a, T> St<'a, T , T = Qux> { | +++ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/associated-types-eq-2.rs:119:21 | LL | impl<'a, T> St<'a , T = Qux> { - | ^^^^^^^ associated type not allowed here + | ^^^^^^^ associated item constraint not allowed here | help: to use `Qux` as a generic argument specify it directly | diff --git a/tests/ui/associated-types/associated-types-eq-expr-path.rs b/tests/ui/associated-types/associated-types-eq-expr-path.rs index 143992f29f19..4561e596c665 100644 --- a/tests/ui/associated-types/associated-types-eq-expr-path.rs +++ b/tests/ui/associated-types/associated-types-eq-expr-path.rs @@ -11,6 +11,6 @@ impl Foo for isize { } pub fn main() { - let x: isize = Foo::::bar(); - //~^ ERROR associated type bindings are not allowed here + let x: isize = Foo::::bar(); + //~^ ERROR associated item constraints are not allowed here } diff --git a/tests/ui/associated-types/associated-types-eq-expr-path.stderr b/tests/ui/associated-types/associated-types-eq-expr-path.stderr index 7559f3b7c2e5..3d0e3e61eca9 100644 --- a/tests/ui/associated-types/associated-types-eq-expr-path.stderr +++ b/tests/ui/associated-types/associated-types-eq-expr-path.stderr @@ -1,8 +1,8 @@ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/associated-types-eq-expr-path.rs:14:26 | -LL | let x: isize = Foo::::bar(); - | ^^^^^^^ associated type not allowed here +LL | let x: isize = Foo::::bar(); + | ^^^^^^^^^ associated item constraint not allowed here error: aborting due to 1 previous error diff --git a/tests/ui/async-await/return-type-notation/rtn-in-impl-signature.rs b/tests/ui/async-await/return-type-notation/rtn-in-impl-signature.rs index 68a750778ada..637678692bd1 100644 --- a/tests/ui/async-await/return-type-notation/rtn-in-impl-signature.rs +++ b/tests/ui/async-await/return-type-notation/rtn-in-impl-signature.rs @@ -8,7 +8,7 @@ trait Super1<'a> { } impl Super1<'_, bar(): Send> for () {} -//~^ ERROR associated type bindings are not allowed here +//~^ ERROR associated item constraints are not allowed here //~| ERROR not all trait items implemented fn main() {} diff --git a/tests/ui/async-await/return-type-notation/rtn-in-impl-signature.stderr b/tests/ui/async-await/return-type-notation/rtn-in-impl-signature.stderr index d925c7316b6e..b07c5735dff6 100644 --- a/tests/ui/async-await/return-type-notation/rtn-in-impl-signature.stderr +++ b/tests/ui/async-await/return-type-notation/rtn-in-impl-signature.stderr @@ -7,11 +7,11 @@ LL | #![feature(return_type_notation)] = note: see issue #109417 for more information = note: `#[warn(incomplete_features)]` on by default -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/rtn-in-impl-signature.rs:10:17 | LL | impl Super1<'_, bar(): Send> for () {} - | ^^^^^^^^^^^ associated type not allowed here + | ^^^^^^^^^^^ associated item constraint not allowed here error[E0046]: not all trait items implemented, missing: `bar` --> $DIR/rtn-in-impl-signature.rs:10:1 diff --git a/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs b/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs index 79743abe4093..fbf1553c182c 100644 --- a/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs +++ b/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs @@ -8,7 +8,7 @@ const T: usize = 42; impl Foo for Bar { //~^ ERROR trait takes 1 generic argument but 0 generic arguments were supplied -//~| ERROR associated type bindings are not allowed here +//~| ERROR associated item constraints are not allowed here //~| ERROR associated const equality is incomplete fn do_x(&self) -> [u8; 3] { [0u8; 3] diff --git a/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr b/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr index 941764a575e6..a132859b412f 100644 --- a/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr +++ b/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr @@ -24,11 +24,11 @@ help: add missing generic argument LL | impl Foo for Bar { | ++ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/issue-89013-no-kw.rs:9:10 | LL | impl Foo for Bar { - | ^^^^^ associated type not allowed here + | ^^^^^ associated item constraint not allowed here | help: to use `3` as a generic argument specify it directly | diff --git a/tests/ui/const-generics/parser-error-recovery/issue-89013.rs b/tests/ui/const-generics/parser-error-recovery/issue-89013.rs index 335d0d94e83c..c9c7ff3a1704 100644 --- a/tests/ui/const-generics/parser-error-recovery/issue-89013.rs +++ b/tests/ui/const-generics/parser-error-recovery/issue-89013.rs @@ -9,7 +9,7 @@ const T: usize = 42; impl Foo for Bar { //~^ ERROR expected lifetime, type, or constant, found keyword `const` //~| ERROR trait takes 1 generic -//~| ERROR associated type bindings are not allowed here +//~| ERROR associated item constraints are not allowed here //~| ERROR associated const equality is incomplete fn do_x(&self) -> [u8; 3] { [0u8; 3] diff --git a/tests/ui/const-generics/parser-error-recovery/issue-89013.stderr b/tests/ui/const-generics/parser-error-recovery/issue-89013.stderr index a4c9e065c15c..2fdd12085652 100644 --- a/tests/ui/const-generics/parser-error-recovery/issue-89013.stderr +++ b/tests/ui/const-generics/parser-error-recovery/issue-89013.stderr @@ -36,11 +36,11 @@ help: add missing generic argument LL | impl Foo for Bar { | ++ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/issue-89013.rs:9:10 | LL | impl Foo for Bar { - | ^^^^^^^^^^^ associated type not allowed here + | ^^^^^^^^^^^ associated item constraint not allowed here | help: to use `3` as a generic argument specify it directly | diff --git a/tests/ui/error-codes/E0229.rs b/tests/ui/error-codes/E0229.rs index 558baae37f76..da2758dfba8f 100644 --- a/tests/ui/error-codes/E0229.rs +++ b/tests/ui/error-codes/E0229.rs @@ -10,10 +10,10 @@ impl Foo for isize { fn boo(&self) -> usize { 42 } } -fn baz(x: &>::A) {} -//~^ ERROR associated type bindings are not allowed here [E0229] -//~| ERROR associated type bindings are not allowed here [E0229] -//~| ERROR associated type bindings are not allowed here [E0229] +fn baz(x: &>::A) {} +//~^ ERROR associated item constraints are not allowed here [E0229] +//~| ERROR associated item constraints are not allowed here [E0229] +//~| ERROR associated item constraints are not allowed here [E0229] //~| ERROR the trait bound `I: Foo` is not satisfied //~| ERROR the trait bound `I: Foo` is not satisfied diff --git a/tests/ui/error-codes/E0229.stderr b/tests/ui/error-codes/E0229.stderr index ae7dc9ac2659..7d9cedc3bdc4 100644 --- a/tests/ui/error-codes/E0229.stderr +++ b/tests/ui/error-codes/E0229.stderr @@ -1,58 +1,58 @@ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/E0229.rs:13:25 | -LL | fn baz(x: &>::A) {} - | ^^^^^ associated type not allowed here +LL | fn baz(x: &>::A) {} + | ^^^^^^^ associated item constraint not allowed here | -help: consider removing this type binding +help: consider removing this associated item binding | -LL | fn baz(x: &>::A) {} - | ~~~~~~~ +LL | fn baz(x: &>::A) {} + | ~~~~~~~~~ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/E0229.rs:13:25 | -LL | fn baz(x: &>::A) {} - | ^^^^^ associated type not allowed here +LL | fn baz(x: &>::A) {} + | ^^^^^^^ associated item constraint not allowed here | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: consider removing this type binding +help: consider removing this associated item binding | -LL | fn baz(x: &>::A) {} - | ~~~~~~~ +LL | fn baz(x: &>::A) {} + | ~~~~~~~~~ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/E0229.rs:13:25 | -LL | fn baz(x: &>::A) {} - | ^^^^^ associated type not allowed here +LL | fn baz(x: &>::A) {} + | ^^^^^^^ associated item constraint not allowed here | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: consider removing this type binding +help: consider removing this associated item binding | -LL | fn baz(x: &>::A) {} - | ~~~~~~~ +LL | fn baz(x: &>::A) {} + | ~~~~~~~~~ error[E0277]: the trait bound `I: Foo` is not satisfied --> $DIR/E0229.rs:13:15 | -LL | fn baz(x: &>::A) {} - | ^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `I` +LL | fn baz(x: &>::A) {} + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `I` | help: consider restricting type parameter `I` | -LL | fn baz(x: &>::A) {} +LL | fn baz(x: &>::A) {} | +++++ error[E0277]: the trait bound `I: Foo` is not satisfied - --> $DIR/E0229.rs:13:37 + --> $DIR/E0229.rs:13:39 | -LL | fn baz(x: &>::A) {} - | ^^ the trait `Foo` is not implemented for `I` +LL | fn baz(x: &>::A) {} + | ^^ the trait `Foo` is not implemented for `I` | help: consider restricting type parameter `I` | -LL | fn baz(x: &>::A) {} +LL | fn baz(x: &>::A) {} | +++++ error: aborting due to 5 previous errors diff --git a/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.rs b/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.rs index b8ce9c85b727..ff528274c59b 100644 --- a/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.rs +++ b/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.rs @@ -16,7 +16,7 @@ impl Fn<()> for Foo { } struct Foo1; impl FnOnce() for Foo1 { - //~^ ERROR associated type bindings are not allowed here + //~^ ERROR associated item constraints are not allowed here //~| ERROR manual implementations of `FnOnce` are experimental //~| ERROR not all trait items implemented extern "rust-call" fn call_once(self, args: ()) -> () {} diff --git a/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr b/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr index c3f161469e30..ed9ecc732b59 100644 --- a/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr +++ b/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr @@ -105,11 +105,11 @@ LL | impl FnOnce() for Foo1 { | = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:18:6 | LL | impl FnOnce() for Foo1 { - | ^^^^^^^^ associated type not allowed here + | ^^^^^^^^ associated item constraint not allowed here | help: parenthesized trait syntax expands to `FnOnce<(), Output=()>` --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:18:6 diff --git a/tests/ui/fn/issue-39259.rs b/tests/ui/fn/issue-39259.rs index 16983b652fc8..d4569a9094b2 100644 --- a/tests/ui/fn/issue-39259.rs +++ b/tests/ui/fn/issue-39259.rs @@ -4,7 +4,7 @@ struct S; impl Fn(u32) -> u32 for S { - //~^ ERROR associated type bindings are not allowed here [E0229] + //~^ ERROR associated item constraints are not allowed here [E0229] //~| ERROR expected a `FnMut(u32)` closure, found `S` fn call(&self) -> u32 { //~^ ERROR method `call` has 1 parameter but the declaration in trait `call` has 2 diff --git a/tests/ui/fn/issue-39259.stderr b/tests/ui/fn/issue-39259.stderr index 47150a3c155c..095a5c472313 100644 --- a/tests/ui/fn/issue-39259.stderr +++ b/tests/ui/fn/issue-39259.stderr @@ -1,8 +1,8 @@ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/issue-39259.rs:6:17 | LL | impl Fn(u32) -> u32 for S { - | ^^^ associated type not allowed here + | ^^^ associated item constraint not allowed here | help: parenthesized trait syntax expands to `Fn<(u32,), Output=u32>` --> $DIR/issue-39259.rs:6:6 diff --git a/tests/ui/generic-associated-types/issue-102335-gat.rs b/tests/ui/generic-associated-types/issue-102335-gat.rs index 3a4a0c107715..0be6ee3930f1 100644 --- a/tests/ui/generic-associated-types/issue-102335-gat.rs +++ b/tests/ui/generic-associated-types/issue-102335-gat.rs @@ -1,7 +1,7 @@ trait T { type A: S = ()>; - //~^ ERROR associated type bindings are not allowed here - //~| ERROR associated type bindings are not allowed here + //~^ ERROR associated item constraints are not allowed here + //~| ERROR associated item constraints are not allowed here } trait Q {} diff --git a/tests/ui/generic-associated-types/issue-102335-gat.stderr b/tests/ui/generic-associated-types/issue-102335-gat.stderr index 23b114a3a55e..b4772486e6e4 100644 --- a/tests/ui/generic-associated-types/issue-102335-gat.stderr +++ b/tests/ui/generic-associated-types/issue-102335-gat.stderr @@ -1,22 +1,22 @@ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/issue-102335-gat.rs:2:21 | LL | type A: S = ()>; - | ^^^^^^^^ associated type not allowed here + | ^^^^^^^^ associated item constraint not allowed here | -help: consider removing this type binding +help: consider removing this associated item binding | LL | type A: S = ()>; | ~~~~~~~~~~ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/issue-102335-gat.rs:2:21 | LL | type A: S = ()>; - | ^^^^^^^^ associated type not allowed here + | ^^^^^^^^ associated item constraint not allowed here | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: consider removing this type binding +help: consider removing this associated item binding | LL | type A: S = ()>; | ~~~~~~~~~~ diff --git a/tests/ui/issues/issue-23543.rs b/tests/ui/issues/issue-23543.rs index 843e1a8a83ae..248bf77a7083 100644 --- a/tests/ui/issues/issue-23543.rs +++ b/tests/ui/issues/issue-23543.rs @@ -5,7 +5,7 @@ struct Foo; pub trait D { fn f(self) where T: A; - //~^ ERROR associated type bindings are not allowed here [E0229] + //~^ ERROR associated item constraints are not allowed here [E0229] } fn main() {} diff --git a/tests/ui/issues/issue-23543.stderr b/tests/ui/issues/issue-23543.stderr index d917a4c51d59..17243aefbbcd 100644 --- a/tests/ui/issues/issue-23543.stderr +++ b/tests/ui/issues/issue-23543.stderr @@ -1,8 +1,8 @@ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/issue-23543.rs:7:17 | LL | where T: A; - | ^^^^^^^^^^^ associated type not allowed here + | ^^^^^^^^^^^ associated item constraint not allowed here error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-23544.rs b/tests/ui/issues/issue-23544.rs index 6ad00b2fba4b..bbd05a59353d 100644 --- a/tests/ui/issues/issue-23544.rs +++ b/tests/ui/issues/issue-23544.rs @@ -3,7 +3,7 @@ pub trait A: Copy {} pub trait D { fn f(self) where T: A; - //~^ ERROR associated type bindings are not allowed here [E0229] + //~^ ERROR associated item constraints are not allowed here [E0229] } fn main() {} diff --git a/tests/ui/issues/issue-23544.stderr b/tests/ui/issues/issue-23544.stderr index 2a7e93f0eb71..8d652a9da279 100644 --- a/tests/ui/issues/issue-23544.stderr +++ b/tests/ui/issues/issue-23544.stderr @@ -1,8 +1,8 @@ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/issue-23544.rs:5:17 | LL | where T: A; - | ^^^^^^^^^^^^^^^^^^^^^^^ associated type not allowed here + | ^^^^^^^^^^^^^^^^^^^^^^^ associated item constraint not allowed here error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-24682.rs b/tests/ui/issues/issue-24682.rs index 0d1ab73417c0..1bd42f3cbe3e 100644 --- a/tests/ui/issues/issue-24682.rs +++ b/tests/ui/issues/issue-24682.rs @@ -2,17 +2,17 @@ trait A: Sized { type N; fn x() -> Self< - N= //~ ERROR associated type bindings are not allowed here + N= //~ ERROR associated item constraints are not allowed here Self::N> { loop {} } fn y(&self) -> std - //~ ERROR associated type bindings are not allowed here + //~ ERROR associated item constraints are not allowed here ::option::Option<()> { None } fn z(&self) -> - u32 //~ ERROR associated type bindings are not allowed here + u32 //~ ERROR associated item constraints are not allowed here { 42 } } diff --git a/tests/ui/issues/issue-24682.stderr b/tests/ui/issues/issue-24682.stderr index e1943bf4d683..a107e8b52cd5 100644 --- a/tests/ui/issues/issue-24682.stderr +++ b/tests/ui/issues/issue-24682.stderr @@ -1,21 +1,21 @@ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/issue-24682.rs:5:11 | LL | / N= LL | | Self::N> { - | |_________________^ associated type not allowed here + | |_________________^ associated item constraint not allowed here -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/issue-24682.rs:11:13 | LL | - | ^^^^ associated type not allowed here + | ^^^^ associated item constraint not allowed here -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/issue-24682.rs:15:13 | LL | u32 - | ^^^^ associated type not allowed here + | ^^^^ associated item constraint not allowed here error: aborting due to 3 previous errors diff --git a/tests/ui/issues/issue-39687.rs b/tests/ui/issues/issue-39687.rs index cbb721fbb57c..58f981b63d11 100644 --- a/tests/ui/issues/issue-39687.rs +++ b/tests/ui/issues/issue-39687.rs @@ -2,5 +2,5 @@ fn main() { ::call; - //~^ ERROR associated type bindings are not allowed here [E0229] + //~^ ERROR associated item constraints are not allowed here [E0229] } diff --git a/tests/ui/issues/issue-39687.stderr b/tests/ui/issues/issue-39687.stderr index f4742115a199..87e5fdc2d8f2 100644 --- a/tests/ui/issues/issue-39687.stderr +++ b/tests/ui/issues/issue-39687.stderr @@ -1,8 +1,8 @@ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/issue-39687.rs:4:14 | LL | ::call; - | ^^^^ associated type not allowed here + | ^^^^ associated item constraint not allowed here error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-43431.rs b/tests/ui/issues/issue-43431.rs index e7ec35105f75..0286336910e1 100644 --- a/tests/ui/issues/issue-43431.rs +++ b/tests/ui/issues/issue-43431.rs @@ -7,7 +7,7 @@ trait CallSingle { impl B> CallSingle for F { fn call(&self, a: A) -> B { B>::call(self, (a,)) - //~^ ERROR associated type bindings are not allowed here + //~^ ERROR associated item constraints are not allowed here } } diff --git a/tests/ui/issues/issue-43431.stderr b/tests/ui/issues/issue-43431.stderr index 6d47ba271624..27a720408e4b 100644 --- a/tests/ui/issues/issue-43431.stderr +++ b/tests/ui/issues/issue-43431.stderr @@ -1,8 +1,8 @@ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/issue-43431.rs:9:27 | LL | B>::call(self, (a,)) - | ^ associated type not allowed here + | ^ associated item constraint not allowed here error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.rs b/tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.rs index a47e71afcf0b..78069e682c13 100644 --- a/tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.rs +++ b/tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.rs @@ -3,6 +3,6 @@ struct Foo {} impl Foo { fn bar(foo: Foo) {} - //~^ associated type bindings are not allowed here + //~^ associated item constraints are not allowed here } fn main() {} diff --git a/tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.stderr b/tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.stderr index d6da842e6aba..f8d919fd68b6 100644 --- a/tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.stderr +++ b/tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.stderr @@ -1,10 +1,10 @@ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/issue-83753-invalid-associated-type-supertrait-hrtb.rs:5:21 | LL | fn bar(foo: Foo) {} - | ^^^^^^^^^^^^^^ associated type not allowed here + | ^^^^^^^^^^^^^^ associated item constraint not allowed here | -help: consider removing this type binding +help: consider removing this associated item binding | LL | fn bar(foo: Foo) {} | ~~~~~~~~~~~~~~~~ diff --git a/tests/ui/lifetimes/issue-95023.rs b/tests/ui/lifetimes/issue-95023.rs index ee39a8c49c05..7a67297c7632 100644 --- a/tests/ui/lifetimes/issue-95023.rs +++ b/tests/ui/lifetimes/issue-95023.rs @@ -2,7 +2,7 @@ struct ErrorKind; struct Error(ErrorKind); impl Fn(&isize) for Error { //~^ ERROR manual implementations of `Fn` are experimental [E0183] - //~^^ ERROR associated type bindings are not allowed here [E0229] + //~^^ ERROR associated item constraints are not allowed here [E0229] //~| ERROR not all trait items implemented //~| ERROR expected a `FnMut(&isize)` closure, found `Error` fn foo(&self) -> Self::B<{ N }>; diff --git a/tests/ui/lifetimes/issue-95023.stderr b/tests/ui/lifetimes/issue-95023.stderr index c4285dbf4bdb..feec4f83f78e 100644 --- a/tests/ui/lifetimes/issue-95023.stderr +++ b/tests/ui/lifetimes/issue-95023.stderr @@ -20,11 +20,11 @@ LL | impl Fn(&isize) for Error { | = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/issue-95023.rs:3:6 | LL | impl Fn(&isize) for Error { - | ^^^^^^^^^^ associated type not allowed here + | ^^^^^^^^^^ associated item constraint not allowed here | help: parenthesized trait syntax expands to `Fn<(&isize,), Output=()>` --> $DIR/issue-95023.rs:3:6 diff --git a/tests/ui/methods/method-call-type-binding.rs b/tests/ui/methods/method-call-type-binding.rs index f547ca8d1c2a..290c66fabe3b 100644 --- a/tests/ui/methods/method-call-type-binding.rs +++ b/tests/ui/methods/method-call-type-binding.rs @@ -1,3 +1,3 @@ fn main() { - 0.clone::(); //~ ERROR associated type bindings are not allowed here + 0.clone::(); //~ ERROR associated item constraints are not allowed here } diff --git a/tests/ui/methods/method-call-type-binding.stderr b/tests/ui/methods/method-call-type-binding.stderr index 54d855d340ea..1acb0b2e12b4 100644 --- a/tests/ui/methods/method-call-type-binding.stderr +++ b/tests/ui/methods/method-call-type-binding.stderr @@ -1,8 +1,8 @@ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/method-call-type-binding.rs:2:15 | LL | 0.clone::(); - | ^^^^^^ associated type not allowed here + | ^^^^^^ associated item constraint not allowed here error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/issue-85347.rs b/tests/ui/suggestions/issue-85347.rs index 95e76e76cfa8..5d1a902af304 100644 --- a/tests/ui/suggestions/issue-85347.rs +++ b/tests/ui/suggestions/issue-85347.rs @@ -3,12 +3,12 @@ trait Foo { type Bar<'a>: Deref::Bar>; //~^ ERROR associated type takes 1 lifetime argument but 0 lifetime arguments were supplied //~| HELP add missing - //~| ERROR associated type bindings are not allowed here - //~| HELP consider removing this type binding + //~| ERROR associated item constraints are not allowed here + //~| HELP consider removing this associated item binding //~| ERROR associated type takes 1 lifetime argument but 0 lifetime arguments were supplied //~| HELP add missing - //~| ERROR associated type bindings are not allowed here - //~| HELP consider removing this type binding + //~| ERROR associated item constraints are not allowed here + //~| HELP consider removing this associated item binding } fn main() {} diff --git a/tests/ui/suggestions/issue-85347.stderr b/tests/ui/suggestions/issue-85347.stderr index de0aa09ce49c..b3616041c4cd 100644 --- a/tests/ui/suggestions/issue-85347.stderr +++ b/tests/ui/suggestions/issue-85347.stderr @@ -14,13 +14,13 @@ help: add missing lifetime argument LL | type Bar<'a>: Deref::Bar<'a, Target = Self>>; | +++ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/issue-85347.rs:3:46 | LL | type Bar<'a>: Deref::Bar>; - | ^^^^^^^^^^^^^ associated type not allowed here + | ^^^^^^^^^^^^^ associated item constraint not allowed here | -help: consider removing this type binding +help: consider removing this associated item binding | LL | type Bar<'a>: Deref::Bar>; | ~~~~~~~~~~~~~~~ @@ -42,14 +42,14 @@ help: add missing lifetime argument LL | type Bar<'a>: Deref::Bar<'a, Target = Self>>; | +++ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/issue-85347.rs:3:46 | LL | type Bar<'a>: Deref::Bar>; - | ^^^^^^^^^^^^^ associated type not allowed here + | ^^^^^^^^^^^^^ associated item constraint not allowed here | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: consider removing this type binding +help: consider removing this associated item binding | LL | type Bar<'a>: Deref::Bar>; | ~~~~~~~~~~~~~~~ diff --git a/tests/ui/suggestions/type-ascription-instead-of-path-in-type.rs b/tests/ui/suggestions/type-ascription-instead-of-path-in-type.rs index c98eec4af01c..99f943d71e9e 100644 --- a/tests/ui/suggestions/type-ascription-instead-of-path-in-type.rs +++ b/tests/ui/suggestions/type-ascription-instead-of-path-in-type.rs @@ -8,5 +8,5 @@ fn main() { //~| HELP you might have meant to write a path instead of an associated type bound //~| ERROR struct takes at least 1 generic argument but 0 generic arguments were supplied //~| HELP add missing generic argument - //~| ERROR associated type bindings are not allowed here + //~| ERROR associated item constraints are not allowed here } diff --git a/tests/ui/suggestions/type-ascription-instead-of-path-in-type.stderr b/tests/ui/suggestions/type-ascription-instead-of-path-in-type.stderr index 834c141ec3e1..56b6a69a283f 100644 --- a/tests/ui/suggestions/type-ascription-instead-of-path-in-type.stderr +++ b/tests/ui/suggestions/type-ascription-instead-of-path-in-type.stderr @@ -20,11 +20,11 @@ help: add missing generic argument LL | let _: Vec = A::B; | ++ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/type-ascription-instead-of-path-in-type.rs:6:16 | LL | let _: Vec = A::B; - | ^^^ associated type not allowed here + | ^^^ associated item constraint not allowed here error: aborting due to 3 previous errors diff --git a/tests/ui/traits/issue-87558.rs b/tests/ui/traits/issue-87558.rs index 76f0f7453ddd..61a24f6b9671 100644 --- a/tests/ui/traits/issue-87558.rs +++ b/tests/ui/traits/issue-87558.rs @@ -2,7 +2,7 @@ struct ErrorKind; struct Error(ErrorKind); impl Fn(&isize) for Error { //~^ ERROR manual implementations of `Fn` are experimental - //~| ERROR associated type bindings are not allowed here + //~| ERROR associated item constraints are not allowed here //~| ERROR closure, found `Error` //~| ERROR not all trait items implemented, missing: `call` fn from() {} //~ ERROR method `from` is not a member of trait `Fn` diff --git a/tests/ui/traits/issue-87558.stderr b/tests/ui/traits/issue-87558.stderr index 1ce273a9f25e..21d8fc0f567c 100644 --- a/tests/ui/traits/issue-87558.stderr +++ b/tests/ui/traits/issue-87558.stderr @@ -12,11 +12,11 @@ LL | impl Fn(&isize) for Error { | = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/issue-87558.rs:3:6 | LL | impl Fn(&isize) for Error { - | ^^^^^^^^^^ associated type not allowed here + | ^^^^^^^^^^ associated item constraint not allowed here | help: parenthesized trait syntax expands to `Fn<(&isize,), Output=()>` --> $DIR/issue-87558.rs:3:6 diff --git a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs index 050b7b44b4e0..3defe0cb44d3 100644 --- a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs +++ b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs @@ -5,6 +5,6 @@ type Pat = std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>); //~^ ERROR type and const arguments are not allowed on const parameter `START` //~| ERROR type arguments are not allowed on const parameter `END` -//~| ERROR associated type bindings are not allowed here +//~| ERROR associated item constraints are not allowed here fn main() {} diff --git a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr index 40effe924da8..7f4e6e314f53 100644 --- a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr +++ b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr @@ -26,11 +26,11 @@ note: const parameter `END` defined here LL | type Pat = | ^^^ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/bad_const_generics_args_on_const_param.rs:5:67 | LL | std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>); - | ^^^^^^^^^^ associated type not allowed here + | ^^^^^^^^^^ associated item constraint not allowed here error: aborting due to 3 previous errors diff --git a/tests/ui/typeck/escaping_bound_vars.rs b/tests/ui/typeck/escaping_bound_vars.rs index 985a3fdbccf3..3cde041f1858 100644 --- a/tests/ui/typeck/escaping_bound_vars.rs +++ b/tests/ui/typeck/escaping_bound_vars.rs @@ -10,7 +10,7 @@ pub fn test() where (): Test<{ 1 + (<() as Elide(&())>::call) }>, //~^ ERROR cannot capture late-bound lifetime in constant - //~| ERROR associated type bindings are not allowed here + //~| ERROR associated item constraints are not allowed here { } diff --git a/tests/ui/typeck/escaping_bound_vars.stderr b/tests/ui/typeck/escaping_bound_vars.stderr index bd9c95fab979..f383099ce13b 100644 --- a/tests/ui/typeck/escaping_bound_vars.stderr +++ b/tests/ui/typeck/escaping_bound_vars.stderr @@ -6,11 +6,11 @@ LL | (): Test<{ 1 + (<() as Elide(&())>::call) }>, | | | lifetime defined here -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/escaping_bound_vars.rs:11:28 | LL | (): Test<{ 1 + (<() as Elide(&())>::call) }>, - | ^^^^^^^^^^ associated type not allowed here + | ^^^^^^^^^^ associated item constraint not allowed here error: aborting due to 2 previous errors diff --git a/tests/ui/typeck/issue-83693.rs b/tests/ui/typeck/issue-83693.rs index a4255822056d..02a0bb30d7ce 100644 --- a/tests/ui/typeck/issue-83693.rs +++ b/tests/ui/typeck/issue-83693.rs @@ -8,12 +8,12 @@ impl F { fn call() { ::call //~^ ERROR: cannot find type `TestResult` in this scope [E0412] - //~| associated type bindings are not allowed here [E0229] + //~| associated item constraints are not allowed here [E0229] } } fn call() { ::call //~^ ERROR: cannot find type `x` in this scope [E0412] - //~| ERROR: associated type bindings are not allowed here [E0229] + //~| ERROR: associated item constraints are not allowed here [E0229] } diff --git a/tests/ui/typeck/issue-83693.stderr b/tests/ui/typeck/issue-83693.stderr index ce4f73b820a1..34bca426116e 100644 --- a/tests/ui/typeck/issue-83693.stderr +++ b/tests/ui/typeck/issue-83693.stderr @@ -19,17 +19,17 @@ error[E0412]: cannot find type `x` in this scope LL | ::call | ^ not found in this scope -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/issue-83693.rs:9:18 | LL | ::call - | ^^^^^^^^^^^^^^^ associated type not allowed here + | ^^^^^^^^^^^^^^^ associated item constraint not allowed here -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/issue-83693.rs:16:11 | LL | ::call - | ^^^^^^^^^^ associated type not allowed here + | ^^^^^^^^^^ associated item constraint not allowed here error: aborting due to 5 previous errors diff --git a/tests/ui/typeck/issue-84768.rs b/tests/ui/typeck/issue-84768.rs index ffa92823b42f..3ba5dffcf07a 100644 --- a/tests/ui/typeck/issue-84768.rs +++ b/tests/ui/typeck/issue-84768.rs @@ -5,6 +5,6 @@ fn transform_mut(f: F) where F: for<'b> FnOnce(&'b mut u8) { ::call_once(f, 1) - //~^ ERROR: associated type bindings are not allowed here [E0229] + //~^ ERROR: associated item constraints are not allowed here [E0229] //~| ERROR: mismatched types [E0308] } diff --git a/tests/ui/typeck/issue-84768.stderr b/tests/ui/typeck/issue-84768.stderr index 3d2d53f5c76c..72784ba59c9b 100644 --- a/tests/ui/typeck/issue-84768.stderr +++ b/tests/ui/typeck/issue-84768.stderr @@ -1,8 +1,8 @@ -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/issue-84768.rs:7:11 | LL | ::call_once(f, 1) - | ^^^^^^^^^^^^^^^ associated type not allowed here + | ^^^^^^^^^^^^^^^ associated item constraint not allowed here error[E0308]: mismatched types --> $DIR/issue-84768.rs:7:42 diff --git a/tests/ui/typeck/issue-91267.rs b/tests/ui/typeck/issue-91267.rs index 4e39cfab5b43..1bffa09e6436 100644 --- a/tests/ui/typeck/issue-91267.rs +++ b/tests/ui/typeck/issue-91267.rs @@ -3,6 +3,6 @@ fn main() { type_ascribe!(0, u8=e>) //~^ ERROR: cannot find type `e` in this scope [E0412] - //~| ERROR: associated type bindings are not allowed here [E0229] + //~| ERROR: associated item constraints are not allowed here [E0229] //~| ERROR: mismatched types [E0308] } diff --git a/tests/ui/typeck/issue-91267.stderr b/tests/ui/typeck/issue-91267.stderr index 399309d0ec44..d16b1997e9f7 100644 --- a/tests/ui/typeck/issue-91267.stderr +++ b/tests/ui/typeck/issue-91267.stderr @@ -4,11 +4,11 @@ error[E0412]: cannot find type `e` in this scope LL | type_ascribe!(0, u8=e>) | ^ not found in this scope -error[E0229]: associated type bindings are not allowed here +error[E0229]: associated item constraints are not allowed here --> $DIR/issue-91267.rs:4:25 | LL | type_ascribe!(0, u8=e>) - | ^^^^^^ associated type not allowed here + | ^^^^^^ associated item constraint not allowed here error[E0308]: mismatched types --> $DIR/issue-91267.rs:4:5 From 86afea97fdc3e4c1c8ad441bd68f7988f660aba0 Mon Sep 17 00:00:00 2001 From: Waffle Maybe Date: Fri, 31 May 2024 00:46:07 +0200 Subject: [PATCH 107/211] Don't recompute `tail` in `lower_stmts` --- compiler/rustc_ast_lowering/src/block.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs index eef6e8280afb..e821a08bf181 100644 --- a/compiler/rustc_ast_lowering/src/block.rs +++ b/compiler/rustc_ast_lowering/src/block.rs @@ -76,7 +76,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { StmtKind::Empty => {} StmtKind::MacCall(..) => panic!("shouldn't exist here"), } - ast_stmts = &ast_stmts[1..]; + ast_stmts = tail; } (self.arena.alloc_from_iter(stmts), expr) } From e110567dcdf7b77cda5f3413af7c6fadec899a9a Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Fri, 31 May 2024 00:22:40 +0000 Subject: [PATCH 108/211] Revert "Auto merge of #115105 - cjgillot:dest-prop-default, r=oli-obk" This reverts commit cfb730450f847bb622243eaaab15e77e58d91767, reversing changes made to 91c0823ee63e793d990bb9fed898dc95b5d6db51. --- compiler/rustc_mir_transform/src/dest_prop.rs | 2 +- compiler/rustc_mir_transform/src/lib.rs | 4 +- compiler/rustc_mir_transform/src/nrvo.rs | 235 ++++++++++++++++++ ...in.DestinationPropagation.panic-abort.diff | 2 +- ...n.DestinationPropagation.panic-unwind.diff | 2 +- .../{dest-prop => }/nrvo_miscompile_111005.rs | 4 +- ...mpile_111005.wrong.RenameReturnPlace.diff} | 7 +- ...e.nrvo.RenameReturnPlace.panic-abort.diff} | 31 ++- ....nrvo.RenameReturnPlace.panic-unwind.diff} | 31 ++- .../nrvo_borrowed.rs => nrvo_simple.rs} | 4 +- ....{impl#0}-partial_cmp.PreCodegen.after.mir | 32 +-- ...ward_loop.PreCodegen.after.panic-abort.mir | 64 ++--- ...ard_loop.PreCodegen.after.panic-unwind.mir | 64 ++--- ...ated_loop.PreCodegen.after.panic-abort.mir | 80 +++--- ...ted_loop.PreCodegen.after.panic-unwind.mir | 80 +++--- ...ward_loop.PreCodegen.after.panic-abort.mir | 66 ++--- ...ard_loop.PreCodegen.after.panic-unwind.mir | 66 ++--- ...ange_loop.PreCodegen.after.panic-abort.mir | 56 +++-- ...nge_loop.PreCodegen.after.panic-unwind.mir | 56 +++-- ...erse_loop.PreCodegen.after.panic-abort.mir | 74 +++--- ...rse_loop.PreCodegen.after.panic-unwind.mir | 74 +++--- 21 files changed, 661 insertions(+), 373 deletions(-) create mode 100644 compiler/rustc_mir_transform/src/nrvo.rs rename tests/mir-opt/{dest-prop => }/nrvo_miscompile_111005.rs (78%) rename tests/mir-opt/{dest-prop/nrvo_miscompile_111005.wrong.DestinationPropagation.diff => nrvo_miscompile_111005.wrong.RenameReturnPlace.diff} (60%) rename tests/mir-opt/{dest-prop/nrvo_borrowed.nrvo.DestinationPropagation.panic-abort.diff => nrvo_simple.nrvo.RenameReturnPlace.panic-abort.diff} (53%) rename tests/mir-opt/{dest-prop/nrvo_borrowed.nrvo.DestinationPropagation.panic-unwind.diff => nrvo_simple.nrvo.RenameReturnPlace.panic-unwind.diff} (53%) rename tests/mir-opt/{dest-prop/nrvo_borrowed.rs => nrvo_simple.rs} (68%) diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index f0778594353d..b1016c0867c6 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -160,7 +160,7 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation { // 2. Despite being an overall perf improvement, this still causes a 30% regression in // keccak. We can temporarily fix this by bounding function size, but in the long term // we should fix this by being smarter about invalidating analysis results. - sess.mir_opt_level() >= 2 + sess.mir_opt_level() >= 3 } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index b03c99654e22..a8741254ffbf 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -88,6 +88,7 @@ mod match_branches; mod mentioned_items; mod multiple_return_terminators; mod normalize_array_len; +mod nrvo; mod prettify; mod promote_consts; mod ref_prop; @@ -607,12 +608,13 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { &jump_threading::JumpThreading, &early_otherwise_branch::EarlyOtherwiseBranch, &simplify_comparison_integral::SimplifyComparisonIntegral, + &dest_prop::DestinationPropagation, &o1(simplify_branches::SimplifyConstCondition::Final), &o1(remove_noop_landing_pads::RemoveNoopLandingPads), &o1(simplify::SimplifyCfg::Final), ©_prop::CopyProp, &dead_store_elimination::DeadStoreElimination::Final, - &dest_prop::DestinationPropagation, + &nrvo::RenameReturnPlace, &simplify::SimplifyLocals::Final, &multiple_return_terminators::MultipleReturnTerminators, &deduplicate_blocks::DeduplicateBlocks, diff --git a/compiler/rustc_mir_transform/src/nrvo.rs b/compiler/rustc_mir_transform/src/nrvo.rs new file mode 100644 index 000000000000..885dbd5f3393 --- /dev/null +++ b/compiler/rustc_mir_transform/src/nrvo.rs @@ -0,0 +1,235 @@ +//! See the docs for [`RenameReturnPlace`]. + +use rustc_hir::Mutability; +use rustc_index::bit_set::BitSet; +use rustc_middle::bug; +use rustc_middle::mir::visit::{MutVisitor, NonUseContext, PlaceContext, Visitor}; +use rustc_middle::mir::{self, BasicBlock, Local, Location}; +use rustc_middle::ty::TyCtxt; + +use crate::MirPass; + +/// This pass looks for MIR that always copies the same local into the return place and eliminates +/// the copy by renaming all uses of that local to `_0`. +/// +/// This allows LLVM to perform an optimization similar to the named return value optimization +/// (NRVO) that is guaranteed in C++. This avoids a stack allocation and `memcpy` for the +/// relatively common pattern of allocating a buffer on the stack, mutating it, and returning it by +/// value like so: +/// +/// ```rust +/// fn foo(init: fn(&mut [u8; 1024])) -> [u8; 1024] { +/// let mut buf = [0; 1024]; +/// init(&mut buf); +/// buf +/// } +/// ``` +/// +/// For now, this pass is very simple and only capable of eliminating a single copy. A more general +/// version of copy propagation, such as the one based on non-overlapping live ranges in [#47954] and +/// [#71003], could yield even more benefits. +/// +/// [#47954]: https://github.com/rust-lang/rust/pull/47954 +/// [#71003]: https://github.com/rust-lang/rust/pull/71003 +pub struct RenameReturnPlace; + +impl<'tcx> MirPass<'tcx> for RenameReturnPlace { + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + // unsound: #111005 + sess.mir_opt_level() > 0 && sess.opts.unstable_opts.unsound_mir_opts + } + + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut mir::Body<'tcx>) { + let def_id = body.source.def_id(); + let Some(returned_local) = local_eligible_for_nrvo(body) else { + debug!("`{:?}` was ineligible for NRVO", def_id); + return; + }; + + if !tcx.consider_optimizing(|| format!("RenameReturnPlace {def_id:?}")) { + return; + } + + debug!( + "`{:?}` was eligible for NRVO, making {:?} the return place", + def_id, returned_local + ); + + RenameToReturnPlace { tcx, to_rename: returned_local }.visit_body_preserves_cfg(body); + + // Clean up the `NOP`s we inserted for statements made useless by our renaming. + for block_data in body.basic_blocks.as_mut_preserves_cfg() { + block_data.statements.retain(|stmt| stmt.kind != mir::StatementKind::Nop); + } + + // Overwrite the debuginfo of `_0` with that of the renamed local. + let (renamed_decl, ret_decl) = + body.local_decls.pick2_mut(returned_local, mir::RETURN_PLACE); + + // Sometimes, the return place is assigned a local of a different but coercible type, for + // example `&mut T` instead of `&T`. Overwriting the `LocalInfo` for the return place means + // its type may no longer match the return type of its function. This doesn't cause a + // problem in codegen because these two types are layout-compatible, but may be unexpected. + debug!("_0: {:?} = {:?}: {:?}", ret_decl.ty, returned_local, renamed_decl.ty); + ret_decl.clone_from(renamed_decl); + + // The return place is always mutable. + ret_decl.mutability = Mutability::Mut; + } +} + +/// MIR that is eligible for the NRVO must fulfill two conditions: +/// 1. The return place must not be read prior to the `Return` terminator. +/// 2. A simple assignment of a whole local to the return place (e.g., `_0 = _1`) must be the +/// only definition of the return place reaching the `Return` terminator. +/// +/// If the MIR fulfills both these conditions, this function returns the `Local` that is assigned +/// to the return place along all possible paths through the control-flow graph. +fn local_eligible_for_nrvo(body: &mir::Body<'_>) -> Option { + if IsReturnPlaceRead::run(body) { + return None; + } + + let mut copied_to_return_place = None; + for block in body.basic_blocks.indices() { + // Look for blocks with a `Return` terminator. + if !matches!(body[block].terminator().kind, mir::TerminatorKind::Return) { + continue; + } + + // Look for an assignment of a single local to the return place prior to the `Return`. + let returned_local = find_local_assigned_to_return_place(block, body)?; + match body.local_kind(returned_local) { + // FIXME: Can we do this for arguments as well? + mir::LocalKind::Arg => return None, + + mir::LocalKind::ReturnPointer => bug!("Return place was assigned to itself?"), + mir::LocalKind::Temp => {} + } + + // If multiple different locals are copied to the return place. We can't pick a + // single one to rename. + if copied_to_return_place.is_some_and(|old| old != returned_local) { + return None; + } + + copied_to_return_place = Some(returned_local); + } + + copied_to_return_place +} + +fn find_local_assigned_to_return_place(start: BasicBlock, body: &mir::Body<'_>) -> Option { + let mut block = start; + let mut seen = BitSet::new_empty(body.basic_blocks.len()); + + // Iterate as long as `block` has exactly one predecessor that we have not yet visited. + while seen.insert(block) { + trace!("Looking for assignments to `_0` in {:?}", block); + + let local = body[block].statements.iter().rev().find_map(as_local_assigned_to_return_place); + if local.is_some() { + return local; + } + + match body.basic_blocks.predecessors()[block].as_slice() { + &[pred] => block = pred, + _ => return None, + } + } + + None +} + +// If this statement is an assignment of an unprojected local to the return place, +// return that local. +fn as_local_assigned_to_return_place(stmt: &mir::Statement<'_>) -> Option { + if let mir::StatementKind::Assign(box (lhs, rhs)) = &stmt.kind { + if lhs.as_local() == Some(mir::RETURN_PLACE) { + if let mir::Rvalue::Use(mir::Operand::Copy(rhs) | mir::Operand::Move(rhs)) = rhs { + return rhs.as_local(); + } + } + } + + None +} + +struct RenameToReturnPlace<'tcx> { + to_rename: Local, + tcx: TyCtxt<'tcx>, +} + +/// Replaces all uses of `self.to_rename` with `_0`. +impl<'tcx> MutVisitor<'tcx> for RenameToReturnPlace<'tcx> { + fn tcx(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn visit_statement(&mut self, stmt: &mut mir::Statement<'tcx>, loc: Location) { + // Remove assignments of the local being replaced to the return place, since it is now the + // return place: + // _0 = _1 + if as_local_assigned_to_return_place(stmt) == Some(self.to_rename) { + stmt.kind = mir::StatementKind::Nop; + return; + } + + // Remove storage annotations for the local being replaced: + // StorageLive(_1) + if let mir::StatementKind::StorageLive(local) | mir::StatementKind::StorageDead(local) = + stmt.kind + { + if local == self.to_rename { + stmt.kind = mir::StatementKind::Nop; + return; + } + } + + self.super_statement(stmt, loc) + } + + fn visit_terminator(&mut self, terminator: &mut mir::Terminator<'tcx>, loc: Location) { + // Ignore the implicit "use" of the return place in a `Return` statement. + if let mir::TerminatorKind::Return = terminator.kind { + return; + } + + self.super_terminator(terminator, loc); + } + + fn visit_local(&mut self, l: &mut Local, ctxt: PlaceContext, _: Location) { + if *l == mir::RETURN_PLACE { + assert_eq!(ctxt, PlaceContext::NonUse(NonUseContext::VarDebugInfo)); + } else if *l == self.to_rename { + *l = mir::RETURN_PLACE; + } + } +} + +struct IsReturnPlaceRead(bool); + +impl IsReturnPlaceRead { + fn run(body: &mir::Body<'_>) -> bool { + let mut vis = IsReturnPlaceRead(false); + vis.visit_body(body); + vis.0 + } +} + +impl<'tcx> Visitor<'tcx> for IsReturnPlaceRead { + fn visit_local(&mut self, l: Local, ctxt: PlaceContext, _: Location) { + if l == mir::RETURN_PLACE && ctxt.is_use() && !ctxt.is_place_assignment() { + self.0 = true; + } + } + + fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, loc: Location) { + // Ignore the implicit "use" of the return place in a `Return` statement. + if let mir::TerminatorKind::Return = terminator.kind { + return; + } + + self.super_terminator(terminator, loc); + } +} diff --git a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff index b596e25ddfdf..570ec129f06e 100644 --- a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff +++ b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-abort.diff @@ -18,7 +18,7 @@ bb0: { StorageLive(_1); StorageLive(_2); - nop; + _2 = const 1_u32; _1 = Un { us: const 1_u32 }; StorageDead(_2); StorageLive(_3); diff --git a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff index b596e25ddfdf..570ec129f06e 100644 --- a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff +++ b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.panic-unwind.diff @@ -18,7 +18,7 @@ bb0: { StorageLive(_1); StorageLive(_2); - nop; + _2 = const 1_u32; _1 = Un { us: const 1_u32 }; StorageDead(_2); StorageLive(_3); diff --git a/tests/mir-opt/dest-prop/nrvo_miscompile_111005.rs b/tests/mir-opt/nrvo_miscompile_111005.rs similarity index 78% rename from tests/mir-opt/dest-prop/nrvo_miscompile_111005.rs rename to tests/mir-opt/nrvo_miscompile_111005.rs index faf30cfd1b01..18814b0678fe 100644 --- a/tests/mir-opt/dest-prop/nrvo_miscompile_111005.rs +++ b/tests/mir-opt/nrvo_miscompile_111005.rs @@ -1,13 +1,13 @@ // skip-filecheck // This is a miscompilation, #111005 to track -//@ test-mir-pass: DestinationPropagation +//@ test-mir-pass: RenameReturnPlace #![feature(custom_mir, core_intrinsics)] extern crate core; use core::intrinsics::mir::*; -// EMIT_MIR nrvo_miscompile_111005.wrong.DestinationPropagation.diff +// EMIT_MIR nrvo_miscompile_111005.wrong.RenameReturnPlace.diff #[custom_mir(dialect = "runtime", phase = "initial")] pub fn wrong(arg: char) -> char { mir!({ diff --git a/tests/mir-opt/dest-prop/nrvo_miscompile_111005.wrong.DestinationPropagation.diff b/tests/mir-opt/nrvo_miscompile_111005.wrong.RenameReturnPlace.diff similarity index 60% rename from tests/mir-opt/dest-prop/nrvo_miscompile_111005.wrong.DestinationPropagation.diff rename to tests/mir-opt/nrvo_miscompile_111005.wrong.RenameReturnPlace.diff index afacf5c14966..260b472daa92 100644 --- a/tests/mir-opt/dest-prop/nrvo_miscompile_111005.wrong.DestinationPropagation.diff +++ b/tests/mir-opt/nrvo_miscompile_111005.wrong.RenameReturnPlace.diff @@ -1,5 +1,5 @@ -- // MIR for `wrong` before DestinationPropagation -+ // MIR for `wrong` after DestinationPropagation +- // MIR for `wrong` before RenameReturnPlace ++ // MIR for `wrong` after RenameReturnPlace fn wrong(_1: char) -> char { let mut _0: char; @@ -9,9 +9,8 @@ - _2 = _1; - _0 = _2; - _2 = const 'b'; -+ nop; + _0 = _1; -+ _1 = const 'b'; ++ _0 = const 'b'; return; } } diff --git a/tests/mir-opt/dest-prop/nrvo_borrowed.nrvo.DestinationPropagation.panic-abort.diff b/tests/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.panic-abort.diff similarity index 53% rename from tests/mir-opt/dest-prop/nrvo_borrowed.nrvo.DestinationPropagation.panic-abort.diff rename to tests/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.panic-abort.diff index 4d34f43fd5ce..f7bc5559ab7b 100644 --- a/tests/mir-opt/dest-prop/nrvo_borrowed.nrvo.DestinationPropagation.panic-abort.diff +++ b/tests/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.panic-abort.diff @@ -1,5 +1,5 @@ -- // MIR for `nrvo` before DestinationPropagation -+ // MIR for `nrvo` after DestinationPropagation +- // MIR for `nrvo` before RenameReturnPlace ++ // MIR for `nrvo` after RenameReturnPlace fn nrvo(_1: for<'a> fn(&'a mut [u8; 1024])) -> [u8; 1024] { debug init => _1; @@ -10,33 +10,32 @@ let mut _5: &mut [u8; 1024]; let mut _6: &mut [u8; 1024]; scope 1 { - debug buf => _2; +- debug buf => _2; ++ debug buf => _0; } bb0: { - StorageLive(_2); - _2 = [const 0_u8; 1024]; +- StorageLive(_2); +- _2 = [const 0_u8; 1024]; ++ _0 = [const 0_u8; 1024]; StorageLive(_3); -- StorageLive(_4); -- _4 = _1; -+ nop; -+ nop; + StorageLive(_4); + _4 = _1; StorageLive(_5); StorageLive(_6); - _6 = &mut _2; +- _6 = &mut _2; ++ _6 = &mut _0; _5 = &mut (*_6); -- _3 = move _4(move _5) -> [return: bb1, unwind unreachable]; -+ _3 = move _1(move _5) -> [return: bb1, unwind unreachable]; + _3 = move _4(move _5) -> [return: bb1, unwind unreachable]; } bb1: { StorageDead(_5); -- StorageDead(_4); -+ nop; + StorageDead(_4); StorageDead(_6); StorageDead(_3); - _0 = _2; - StorageDead(_2); +- _0 = _2; +- StorageDead(_2); return; } } diff --git a/tests/mir-opt/dest-prop/nrvo_borrowed.nrvo.DestinationPropagation.panic-unwind.diff b/tests/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.panic-unwind.diff similarity index 53% rename from tests/mir-opt/dest-prop/nrvo_borrowed.nrvo.DestinationPropagation.panic-unwind.diff rename to tests/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.panic-unwind.diff index 9c3cbef38d69..3df8e567f1fe 100644 --- a/tests/mir-opt/dest-prop/nrvo_borrowed.nrvo.DestinationPropagation.panic-unwind.diff +++ b/tests/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.panic-unwind.diff @@ -1,5 +1,5 @@ -- // MIR for `nrvo` before DestinationPropagation -+ // MIR for `nrvo` after DestinationPropagation +- // MIR for `nrvo` before RenameReturnPlace ++ // MIR for `nrvo` after RenameReturnPlace fn nrvo(_1: for<'a> fn(&'a mut [u8; 1024])) -> [u8; 1024] { debug init => _1; @@ -10,33 +10,32 @@ let mut _5: &mut [u8; 1024]; let mut _6: &mut [u8; 1024]; scope 1 { - debug buf => _2; +- debug buf => _2; ++ debug buf => _0; } bb0: { - StorageLive(_2); - _2 = [const 0_u8; 1024]; +- StorageLive(_2); +- _2 = [const 0_u8; 1024]; ++ _0 = [const 0_u8; 1024]; StorageLive(_3); -- StorageLive(_4); -- _4 = _1; -+ nop; -+ nop; + StorageLive(_4); + _4 = _1; StorageLive(_5); StorageLive(_6); - _6 = &mut _2; +- _6 = &mut _2; ++ _6 = &mut _0; _5 = &mut (*_6); -- _3 = move _4(move _5) -> [return: bb1, unwind continue]; -+ _3 = move _1(move _5) -> [return: bb1, unwind continue]; + _3 = move _4(move _5) -> [return: bb1, unwind continue]; } bb1: { StorageDead(_5); -- StorageDead(_4); -+ nop; + StorageDead(_4); StorageDead(_6); StorageDead(_3); - _0 = _2; - StorageDead(_2); +- _0 = _2; +- StorageDead(_2); return; } } diff --git a/tests/mir-opt/dest-prop/nrvo_borrowed.rs b/tests/mir-opt/nrvo_simple.rs similarity index 68% rename from tests/mir-opt/dest-prop/nrvo_borrowed.rs rename to tests/mir-opt/nrvo_simple.rs index 405423f24624..5d2894a704a5 100644 --- a/tests/mir-opt/dest-prop/nrvo_borrowed.rs +++ b/tests/mir-opt/nrvo_simple.rs @@ -1,8 +1,8 @@ // skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY -//@ test-mir-pass: DestinationPropagation +//@ test-mir-pass: RenameReturnPlace -// EMIT_MIR nrvo_borrowed.nrvo.DestinationPropagation.diff +// EMIT_MIR nrvo_simple.nrvo.RenameReturnPlace.diff fn nrvo(init: fn(&mut [u8; 1024])) -> [u8; 1024] { let mut buf = [0; 1024]; init(&mut buf); diff --git a/tests/mir-opt/pre-codegen/derived_ord.{impl#0}-partial_cmp.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/derived_ord.{impl#0}-partial_cmp.PreCodegen.after.mir index b58e05f93688..47f10451b057 100644 --- a/tests/mir-opt/pre-codegen/derived_ord.{impl#0}-partial_cmp.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/derived_ord.{impl#0}-partial_cmp.PreCodegen.after.mir @@ -4,9 +4,10 @@ fn ::partial_cmp(_1: &MultiField, _2: &M debug self => _1; debug other => _2; let mut _0: std::option::Option; - let mut _6: i8; + let mut _6: std::option::Option; + let mut _7: i8; scope 1 { - debug cmp => _0; + debug cmp => _6; } scope 2 (inlined std::cmp::impls::::partial_cmp) { let mut _3: char; @@ -14,9 +15,9 @@ fn ::partial_cmp(_1: &MultiField, _2: &M let mut _5: std::cmp::Ordering; } scope 3 (inlined std::cmp::impls::::partial_cmp) { - let mut _7: i16; let mut _8: i16; - let mut _9: std::cmp::Ordering; + let mut _9: i16; + let mut _10: std::cmp::Ordering; } bb0: { @@ -27,26 +28,27 @@ fn ::partial_cmp(_1: &MultiField, _2: &M _5 = Cmp(move _3, move _4); StorageDead(_4); StorageDead(_3); - _0 = Option::::Some(_5); - _6 = discriminant(_5); - switchInt(move _6) -> [0: bb1, otherwise: bb2]; + _6 = Option::::Some(_5); + _7 = discriminant(_5); + switchInt(move _7) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_9); - StorageLive(_7); - _7 = ((*_1).1: i16); + StorageLive(_10); StorageLive(_8); - _8 = ((*_2).1: i16); - _9 = Cmp(move _7, move _8); - StorageDead(_8); - StorageDead(_7); - _0 = Option::::Some(move _9); + _8 = ((*_1).1: i16); + StorageLive(_9); + _9 = ((*_2).1: i16); + _10 = Cmp(move _8, move _9); StorageDead(_9); + StorageDead(_8); + _0 = Option::::Some(move _10); + StorageDead(_10); goto -> bb3; } bb2: { + _0 = _6; goto -> bb3; } diff --git a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir index 163279c1c334..96b4962854de 100644 --- a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir @@ -5,25 +5,27 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { debug end => _2; debug f => _3; let mut _0: (); - let mut _7: std::option::Option; - let mut _9: &impl Fn(u32); - let mut _10: (u32,); - let _11: (); + let mut _4: u32; + let mut _9: std::option::Option; + let mut _11: &impl Fn(u32); + let mut _12: (u32,); + let _13: (); scope 1 { - debug ((iter: std::ops::Range).0: u32) => _1; + debug ((iter: std::ops::Range).0: u32) => _4; debug ((iter: std::ops::Range).1: u32) => _2; - let _8: u32; + let _10: u32; scope 2 { - debug x => _8; + debug x => _10; } scope 4 (inlined iter::range::>::next) { scope 5 (inlined as iter::range::RangeIteratorImpl>::spec_next) { - let mut _5: bool; - let _6: u32; + let mut _6: bool; + let _7: u32; + let mut _8: u32; scope 6 { } scope 7 (inlined std::cmp::impls::::lt) { - let mut _4: u32; + let mut _5: u32; } } } @@ -32,24 +34,27 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { } bb0: { + StorageLive(_4); + _4 = _1; goto -> bb1; } bb1: { + StorageLive(_9); StorageLive(_7); StorageLive(_6); StorageLive(_5); - StorageLive(_4); - _4 = _1; - _5 = Lt(move _4, _2); - StorageDead(_4); - switchInt(move _5) -> [0: bb2, otherwise: bb4]; + _5 = _4; + _6 = Lt(move _5, _2); + StorageDead(_5); + switchInt(move _6) -> [0: bb2, otherwise: bb4]; } bb2: { - StorageDead(_5); StorageDead(_6); StorageDead(_7); + StorageDead(_9); + StorageDead(_4); drop(_3) -> [return: bb3, unwind unreachable]; } @@ -58,26 +63,29 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { } bb4: { - _6 = _1; - _1 = ::forward_unchecked(_6, const 1_usize) -> [return: bb5, unwind unreachable]; + _7 = _4; + StorageLive(_8); + _8 = ::forward_unchecked(_7, const 1_usize) -> [return: bb5, unwind unreachable]; } bb5: { - _7 = Option::::Some(_6); - StorageDead(_5); + _4 = move _8; + StorageDead(_8); + _9 = Option::::Some(_7); StorageDead(_6); - _8 = ((_7 as Some).0: u32); - StorageLive(_9); - _9 = &_3; - StorageLive(_10); - _10 = (_8,); - _11 = >::call(move _9, move _10) -> [return: bb6, unwind unreachable]; + StorageDead(_7); + _10 = ((_9 as Some).0: u32); + StorageLive(_11); + _11 = &_3; + StorageLive(_12); + _12 = (_10,); + _13 = >::call(move _11, move _12) -> [return: bb6, unwind unreachable]; } bb6: { - StorageDead(_10); + StorageDead(_12); + StorageDead(_11); StorageDead(_9); - StorageDead(_7); goto -> bb1; } } diff --git a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir index 05f72ade9249..ce8e2bd083ed 100644 --- a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir @@ -5,25 +5,27 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { debug end => _2; debug f => _3; let mut _0: (); - let mut _7: std::option::Option; - let mut _9: &impl Fn(u32); - let mut _10: (u32,); - let _11: (); + let mut _4: u32; + let mut _9: std::option::Option; + let mut _11: &impl Fn(u32); + let mut _12: (u32,); + let _13: (); scope 1 { - debug ((iter: std::ops::Range).0: u32) => _1; + debug ((iter: std::ops::Range).0: u32) => _4; debug ((iter: std::ops::Range).1: u32) => _2; - let _8: u32; + let _10: u32; scope 2 { - debug x => _8; + debug x => _10; } scope 4 (inlined iter::range::>::next) { scope 5 (inlined as iter::range::RangeIteratorImpl>::spec_next) { - let mut _5: bool; - let _6: u32; + let mut _6: bool; + let _7: u32; + let mut _8: u32; scope 6 { } scope 7 (inlined std::cmp::impls::::lt) { - let mut _4: u32; + let mut _5: u32; } } } @@ -32,24 +34,27 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { } bb0: { + StorageLive(_4); + _4 = _1; goto -> bb1; } bb1: { + StorageLive(_9); StorageLive(_7); StorageLive(_6); StorageLive(_5); - StorageLive(_4); - _4 = _1; - _5 = Lt(move _4, _2); - StorageDead(_4); - switchInt(move _5) -> [0: bb2, otherwise: bb4]; + _5 = _4; + _6 = Lt(move _5, _2); + StorageDead(_5); + switchInt(move _6) -> [0: bb2, otherwise: bb4]; } bb2: { - StorageDead(_5); StorageDead(_6); StorageDead(_7); + StorageDead(_9); + StorageDead(_4); drop(_3) -> [return: bb3, unwind continue]; } @@ -58,26 +63,29 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { } bb4: { - _6 = _1; - _1 = ::forward_unchecked(_6, const 1_usize) -> [return: bb5, unwind: bb7]; + _7 = _4; + StorageLive(_8); + _8 = ::forward_unchecked(_7, const 1_usize) -> [return: bb5, unwind: bb7]; } bb5: { - _7 = Option::::Some(_6); - StorageDead(_5); + _4 = move _8; + StorageDead(_8); + _9 = Option::::Some(_7); StorageDead(_6); - _8 = ((_7 as Some).0: u32); - StorageLive(_9); - _9 = &_3; - StorageLive(_10); - _10 = (_8,); - _11 = >::call(move _9, move _10) -> [return: bb6, unwind: bb7]; + StorageDead(_7); + _10 = ((_9 as Some).0: u32); + StorageLive(_11); + _11 = &_3; + StorageLive(_12); + _12 = (_10,); + _13 = >::call(move _11, move _12) -> [return: bb6, unwind: bb7]; } bb6: { - StorageDead(_10); + StorageDead(_12); + StorageDead(_11); StorageDead(_9); - StorageDead(_7); goto -> bb1; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir index e761dc1e8b83..d979c5ec1d5a 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir @@ -4,22 +4,22 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _11: std::slice::Iter<'_, T>; - let mut _12: std::iter::Enumerate>; + let mut _12: std::slice::Iter<'_, T>; let mut _13: std::iter::Enumerate>; - let mut _14: &mut std::iter::Enumerate>; - let mut _15: std::option::Option<(usize, &T)>; - let mut _16: isize; - let mut _19: &impl Fn(usize, &T); - let mut _20: (usize, &T); - let _21: (); + let mut _14: std::iter::Enumerate>; + let mut _15: &mut std::iter::Enumerate>; + let mut _16: std::option::Option<(usize, &T)>; + let mut _17: isize; + let mut _20: &impl Fn(usize, &T); + let mut _21: (usize, &T); + let _22: (); scope 1 { - debug iter => _13; - let _17: usize; - let _18: &T; + debug iter => _14; + let _18: usize; + let _19: &T; scope 2 { - debug i => _17; - debug x => _18; + debug i => _18; + debug x => _19; } } scope 3 (inlined core::slice::::iter) { @@ -28,10 +28,11 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { let mut _7: bool; let mut _8: *mut T; let mut _9: *mut T; - let mut _10: *const T; + let mut _11: *const T; scope 5 { let _6: std::ptr::NonNull; scope 6 { + let _10: *const T; scope 7 { } scope 11 (inlined without_provenance::) { @@ -60,16 +61,16 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb0: { - StorageLive(_11); + StorageLive(_12); StorageLive(_3); StorageLive(_6); - StorageLive(_10); StorageLive(_4); StorageLive(_5); _3 = Len((*_1)); _4 = &raw const (*_1); _5 = _4 as *const T (PtrToPtr); _6 = NonNull:: { pointer: _5 }; + StorageLive(_10); StorageLive(_7); _7 = const ::IS_ZST; switchInt(move _7) -> [0: bb1, otherwise: bb2]; @@ -93,35 +94,38 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { bb3: { StorageDead(_7); - _11 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> }; + StorageLive(_11); + _11 = _10; + _12 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _11, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_11); + StorageDead(_10); StorageDead(_5); StorageDead(_4); - StorageDead(_10); StorageDead(_6); StorageDead(_3); - _12 = Enumerate::> { iter: _11, count: const 0_usize }; - StorageDead(_11); - StorageLive(_13); - _13 = _12; + _13 = Enumerate::> { iter: _12, count: const 0_usize }; + StorageDead(_12); + StorageLive(_14); + _14 = _13; goto -> bb4; } bb4: { + StorageLive(_16); StorageLive(_15); - StorageLive(_14); - _14 = &mut _13; - _15 = > as Iterator>::next(move _14) -> [return: bb5, unwind unreachable]; + _15 = &mut _14; + _16 = > as Iterator>::next(move _15) -> [return: bb5, unwind unreachable]; } bb5: { - StorageDead(_14); - _16 = discriminant(_15); - switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_15); + _17 = discriminant(_16); + switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_15); - StorageDead(_13); + StorageDead(_16); + StorageDead(_14); drop(_2) -> [return: bb7, unwind unreachable]; } @@ -130,19 +134,19 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb8: { - _17 = (((_15 as Some).0: (usize, &T)).0: usize); - _18 = (((_15 as Some).0: (usize, &T)).1: &T); - StorageLive(_19); - _19 = &_2; + _18 = (((_16 as Some).0: (usize, &T)).0: usize); + _19 = (((_16 as Some).0: (usize, &T)).1: &T); StorageLive(_20); - _20 = (_17, _18); - _21 = >::call(move _19, move _20) -> [return: bb9, unwind unreachable]; + _20 = &_2; + StorageLive(_21); + _21 = (_18, _19); + _22 = >::call(move _20, move _21) -> [return: bb9, unwind unreachable]; } bb9: { + StorageDead(_21); StorageDead(_20); - StorageDead(_19); - StorageDead(_15); + StorageDead(_16); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir index da293cdb5a17..8491c49f7673 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir @@ -4,22 +4,22 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _11: std::slice::Iter<'_, T>; - let mut _12: std::iter::Enumerate>; + let mut _12: std::slice::Iter<'_, T>; let mut _13: std::iter::Enumerate>; - let mut _14: &mut std::iter::Enumerate>; - let mut _15: std::option::Option<(usize, &T)>; - let mut _16: isize; - let mut _19: &impl Fn(usize, &T); - let mut _20: (usize, &T); - let _21: (); + let mut _14: std::iter::Enumerate>; + let mut _15: &mut std::iter::Enumerate>; + let mut _16: std::option::Option<(usize, &T)>; + let mut _17: isize; + let mut _20: &impl Fn(usize, &T); + let mut _21: (usize, &T); + let _22: (); scope 1 { - debug iter => _13; - let _17: usize; - let _18: &T; + debug iter => _14; + let _18: usize; + let _19: &T; scope 2 { - debug i => _17; - debug x => _18; + debug i => _18; + debug x => _19; } } scope 3 (inlined core::slice::::iter) { @@ -28,10 +28,11 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { let mut _7: bool; let mut _8: *mut T; let mut _9: *mut T; - let mut _10: *const T; + let mut _11: *const T; scope 5 { let _6: std::ptr::NonNull; scope 6 { + let _10: *const T; scope 7 { } scope 11 (inlined without_provenance::) { @@ -60,16 +61,16 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb0: { - StorageLive(_11); + StorageLive(_12); StorageLive(_3); StorageLive(_6); - StorageLive(_10); StorageLive(_4); StorageLive(_5); _3 = Len((*_1)); _4 = &raw const (*_1); _5 = _4 as *const T (PtrToPtr); _6 = NonNull:: { pointer: _5 }; + StorageLive(_10); StorageLive(_7); _7 = const ::IS_ZST; switchInt(move _7) -> [0: bb1, otherwise: bb2]; @@ -93,35 +94,38 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { bb3: { StorageDead(_7); - _11 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> }; + StorageLive(_11); + _11 = _10; + _12 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _11, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_11); + StorageDead(_10); StorageDead(_5); StorageDead(_4); - StorageDead(_10); StorageDead(_6); StorageDead(_3); - _12 = Enumerate::> { iter: _11, count: const 0_usize }; - StorageDead(_11); - StorageLive(_13); - _13 = _12; + _13 = Enumerate::> { iter: _12, count: const 0_usize }; + StorageDead(_12); + StorageLive(_14); + _14 = _13; goto -> bb4; } bb4: { + StorageLive(_16); StorageLive(_15); - StorageLive(_14); - _14 = &mut _13; - _15 = > as Iterator>::next(move _14) -> [return: bb5, unwind: bb11]; + _15 = &mut _14; + _16 = > as Iterator>::next(move _15) -> [return: bb5, unwind: bb11]; } bb5: { - StorageDead(_14); - _16 = discriminant(_15); - switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_15); + _17 = discriminant(_16); + switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_15); - StorageDead(_13); + StorageDead(_16); + StorageDead(_14); drop(_2) -> [return: bb7, unwind continue]; } @@ -130,19 +134,19 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb8: { - _17 = (((_15 as Some).0: (usize, &T)).0: usize); - _18 = (((_15 as Some).0: (usize, &T)).1: &T); - StorageLive(_19); - _19 = &_2; + _18 = (((_16 as Some).0: (usize, &T)).0: usize); + _19 = (((_16 as Some).0: (usize, &T)).1: &T); StorageLive(_20); - _20 = (_17, _18); - _21 = >::call(move _19, move _20) -> [return: bb9, unwind: bb11]; + _20 = &_2; + StorageLive(_21); + _21 = (_18, _19); + _22 = >::call(move _20, move _21) -> [return: bb9, unwind: bb11]; } bb9: { + StorageDead(_21); StorageDead(_20); - StorageDead(_19); - StorageDead(_15); + StorageDead(_16); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir index d824857ac5d9..67dd0c85ea1d 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir @@ -4,19 +4,19 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _11: std::slice::Iter<'_, T>; let mut _12: std::slice::Iter<'_, T>; - let mut _13: &mut std::slice::Iter<'_, T>; - let mut _14: std::option::Option<&T>; - let mut _15: isize; - let mut _17: &impl Fn(&T); - let mut _18: (&T,); - let _19: (); + let mut _13: std::slice::Iter<'_, T>; + let mut _14: &mut std::slice::Iter<'_, T>; + let mut _15: std::option::Option<&T>; + let mut _16: isize; + let mut _18: &impl Fn(&T); + let mut _19: (&T,); + let _20: (); scope 1 { - debug iter => _12; - let _16: &T; + debug iter => _13; + let _17: &T; scope 2 { - debug x => _16; + debug x => _17; } } scope 3 (inlined core::slice::::iter) { @@ -25,10 +25,11 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { let mut _7: bool; let mut _8: *mut T; let mut _9: *mut T; - let mut _10: *const T; + let mut _11: *const T; scope 5 { let _6: std::ptr::NonNull; scope 6 { + let _10: *const T; scope 7 { } scope 11 (inlined without_provenance::) { @@ -55,13 +56,13 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { bb0: { StorageLive(_3); StorageLive(_6); - StorageLive(_10); StorageLive(_4); StorageLive(_5); _3 = Len((*_1)); _4 = &raw const (*_1); _5 = _4 as *const T (PtrToPtr); _6 = NonNull:: { pointer: _5 }; + StorageLive(_10); StorageLive(_7); _7 = const ::IS_ZST; switchInt(move _7) -> [0: bb1, otherwise: bb2]; @@ -85,33 +86,36 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { bb3: { StorageDead(_7); - _11 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> }; + StorageLive(_11); + _11 = _10; + _12 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _11, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_11); + StorageDead(_10); StorageDead(_5); StorageDead(_4); - StorageDead(_10); StorageDead(_6); StorageDead(_3); - StorageLive(_12); - _12 = _11; + StorageLive(_13); + _13 = _12; goto -> bb4; } bb4: { + StorageLive(_15); StorageLive(_14); - StorageLive(_13); - _13 = &mut _12; - _14 = as Iterator>::next(move _13) -> [return: bb5, unwind unreachable]; + _14 = &mut _13; + _15 = as Iterator>::next(move _14) -> [return: bb5, unwind unreachable]; } bb5: { - StorageDead(_13); - _15 = discriminant(_14); - switchInt(move _15) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_14); + _16 = discriminant(_15); + switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_14); - StorageDead(_12); + StorageDead(_15); + StorageDead(_13); drop(_2) -> [return: bb7, unwind unreachable]; } @@ -120,18 +124,18 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _16 = ((_14 as Some).0: &T); - StorageLive(_17); - _17 = &_2; + _17 = ((_15 as Some).0: &T); StorageLive(_18); - _18 = (_16,); - _19 = >::call(move _17, move _18) -> [return: bb9, unwind unreachable]; + _18 = &_2; + StorageLive(_19); + _19 = (_17,); + _20 = >::call(move _18, move _19) -> [return: bb9, unwind unreachable]; } bb9: { + StorageDead(_19); StorageDead(_18); - StorageDead(_17); - StorageDead(_14); + StorageDead(_15); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir index 75437119aa60..7c41e9e1f1b7 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir @@ -4,19 +4,19 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _11: std::slice::Iter<'_, T>; let mut _12: std::slice::Iter<'_, T>; - let mut _13: &mut std::slice::Iter<'_, T>; - let mut _14: std::option::Option<&T>; - let mut _15: isize; - let mut _17: &impl Fn(&T); - let mut _18: (&T,); - let _19: (); + let mut _13: std::slice::Iter<'_, T>; + let mut _14: &mut std::slice::Iter<'_, T>; + let mut _15: std::option::Option<&T>; + let mut _16: isize; + let mut _18: &impl Fn(&T); + let mut _19: (&T,); + let _20: (); scope 1 { - debug iter => _12; - let _16: &T; + debug iter => _13; + let _17: &T; scope 2 { - debug x => _16; + debug x => _17; } } scope 3 (inlined core::slice::::iter) { @@ -25,10 +25,11 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { let mut _7: bool; let mut _8: *mut T; let mut _9: *mut T; - let mut _10: *const T; + let mut _11: *const T; scope 5 { let _6: std::ptr::NonNull; scope 6 { + let _10: *const T; scope 7 { } scope 11 (inlined without_provenance::) { @@ -55,13 +56,13 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { bb0: { StorageLive(_3); StorageLive(_6); - StorageLive(_10); StorageLive(_4); StorageLive(_5); _3 = Len((*_1)); _4 = &raw const (*_1); _5 = _4 as *const T (PtrToPtr); _6 = NonNull:: { pointer: _5 }; + StorageLive(_10); StorageLive(_7); _7 = const ::IS_ZST; switchInt(move _7) -> [0: bb1, otherwise: bb2]; @@ -85,33 +86,36 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { bb3: { StorageDead(_7); - _11 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> }; + StorageLive(_11); + _11 = _10; + _12 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _11, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_11); + StorageDead(_10); StorageDead(_5); StorageDead(_4); - StorageDead(_10); StorageDead(_6); StorageDead(_3); - StorageLive(_12); - _12 = _11; + StorageLive(_13); + _13 = _12; goto -> bb4; } bb4: { + StorageLive(_15); StorageLive(_14); - StorageLive(_13); - _13 = &mut _12; - _14 = as Iterator>::next(move _13) -> [return: bb5, unwind: bb11]; + _14 = &mut _13; + _15 = as Iterator>::next(move _14) -> [return: bb5, unwind: bb11]; } bb5: { - StorageDead(_13); - _15 = discriminant(_14); - switchInt(move _15) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_14); + _16 = discriminant(_15); + switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_14); - StorageDead(_12); + StorageDead(_15); + StorageDead(_13); drop(_2) -> [return: bb7, unwind continue]; } @@ -120,18 +124,18 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _16 = ((_14 as Some).0: &T); - StorageLive(_17); - _17 = &_2; + _17 = ((_15 as Some).0: &T); StorageLive(_18); - _18 = (_16,); - _19 = >::call(move _17, move _18) -> [return: bb9, unwind: bb11]; + _18 = &_2; + StorageLive(_19); + _19 = (_17,); + _20 = >::call(move _18, move _19) -> [return: bb9, unwind: bb11]; } bb9: { + StorageDead(_19); StorageDead(_18); - StorageDead(_17); - StorageDead(_14); + StorageDead(_15); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir index dc370911d8a9..dbe6f39548c8 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir @@ -6,27 +6,28 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { let mut _0: (); let mut _3: usize; let mut _4: usize; - let mut _8: std::option::Option; - let mut _10: usize; - let mut _11: bool; - let mut _13: &impl Fn(usize, &T); - let mut _14: (usize, &T); - let _15: (); + let mut _9: std::option::Option; + let mut _11: usize; + let mut _12: bool; + let mut _14: &impl Fn(usize, &T); + let mut _15: (usize, &T); + let _16: (); scope 1 { debug ((iter: std::ops::Range).0: usize) => _4; debug ((iter: std::ops::Range).1: usize) => _3; - let _9: usize; + let _10: usize; scope 2 { - debug i => _9; - let _12: &T; + debug i => _10; + let _13: &T; scope 3 { - debug x => _12; + debug x => _13; } } scope 5 (inlined iter::range::>::next) { scope 6 (inlined as iter::range::RangeIteratorImpl>::spec_next) { let mut _6: bool; let _7: usize; + let mut _8: usize; scope 7 { } scope 8 (inlined std::cmp::impls::::lt) { @@ -40,12 +41,13 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { bb0: { _3 = Len((*_1)); + StorageLive(_4); _4 = const 0_usize; goto -> bb1; } bb1: { - StorageLive(_8); + StorageLive(_9); StorageLive(_7); StorageLive(_6); StorageLive(_5); @@ -58,7 +60,8 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { bb2: { StorageDead(_6); StorageDead(_7); - StorageDead(_8); + StorageDead(_9); + StorageDead(_4); drop(_2) -> [return: bb3, unwind unreachable]; } @@ -68,32 +71,35 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { bb4: { _7 = _4; - _4 = ::forward_unchecked(_7, const 1_usize) -> [return: bb5, unwind unreachable]; + StorageLive(_8); + _8 = ::forward_unchecked(_7, const 1_usize) -> [return: bb5, unwind unreachable]; } bb5: { - _8 = Option::::Some(_7); + _4 = move _8; + StorageDead(_8); + _9 = Option::::Some(_7); StorageDead(_6); StorageDead(_7); - _9 = ((_8 as Some).0: usize); - _10 = Len((*_1)); - _11 = Lt(_9, _10); - assert(move _11, "index out of bounds: the length is {} but the index is {}", move _10, _9) -> [success: bb6, unwind unreachable]; + _10 = ((_9 as Some).0: usize); + _11 = Len((*_1)); + _12 = Lt(_10, _11); + assert(move _12, "index out of bounds: the length is {} but the index is {}", move _11, _10) -> [success: bb6, unwind unreachable]; } bb6: { - _12 = &(*_1)[_9]; - StorageLive(_13); - _13 = &_2; + _13 = &(*_1)[_10]; StorageLive(_14); - _14 = (_9, _12); - _15 = >::call(move _13, move _14) -> [return: bb7, unwind unreachable]; + _14 = &_2; + StorageLive(_15); + _15 = (_10, _13); + _16 = >::call(move _14, move _15) -> [return: bb7, unwind unreachable]; } bb7: { + StorageDead(_15); StorageDead(_14); - StorageDead(_13); - StorageDead(_8); + StorageDead(_9); goto -> bb1; } } diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir index 751e14441d43..5b6441cfb3b2 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir @@ -6,27 +6,28 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { let mut _0: (); let mut _3: usize; let mut _4: usize; - let mut _8: std::option::Option; - let mut _10: usize; - let mut _11: bool; - let mut _13: &impl Fn(usize, &T); - let mut _14: (usize, &T); - let _15: (); + let mut _9: std::option::Option; + let mut _11: usize; + let mut _12: bool; + let mut _14: &impl Fn(usize, &T); + let mut _15: (usize, &T); + let _16: (); scope 1 { debug ((iter: std::ops::Range).0: usize) => _4; debug ((iter: std::ops::Range).1: usize) => _3; - let _9: usize; + let _10: usize; scope 2 { - debug i => _9; - let _12: &T; + debug i => _10; + let _13: &T; scope 3 { - debug x => _12; + debug x => _13; } } scope 5 (inlined iter::range::>::next) { scope 6 (inlined as iter::range::RangeIteratorImpl>::spec_next) { let mut _6: bool; let _7: usize; + let mut _8: usize; scope 7 { } scope 8 (inlined std::cmp::impls::::lt) { @@ -40,12 +41,13 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { bb0: { _3 = Len((*_1)); + StorageLive(_4); _4 = const 0_usize; goto -> bb1; } bb1: { - StorageLive(_8); + StorageLive(_9); StorageLive(_7); StorageLive(_6); StorageLive(_5); @@ -58,7 +60,8 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { bb2: { StorageDead(_6); StorageDead(_7); - StorageDead(_8); + StorageDead(_9); + StorageDead(_4); drop(_2) -> [return: bb3, unwind continue]; } @@ -68,32 +71,35 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { bb4: { _7 = _4; - _4 = ::forward_unchecked(_7, const 1_usize) -> [return: bb5, unwind: bb8]; + StorageLive(_8); + _8 = ::forward_unchecked(_7, const 1_usize) -> [return: bb5, unwind: bb8]; } bb5: { - _8 = Option::::Some(_7); + _4 = move _8; + StorageDead(_8); + _9 = Option::::Some(_7); StorageDead(_6); StorageDead(_7); - _9 = ((_8 as Some).0: usize); - _10 = Len((*_1)); - _11 = Lt(_9, _10); - assert(move _11, "index out of bounds: the length is {} but the index is {}", move _10, _9) -> [success: bb6, unwind: bb8]; + _10 = ((_9 as Some).0: usize); + _11 = Len((*_1)); + _12 = Lt(_10, _11); + assert(move _12, "index out of bounds: the length is {} but the index is {}", move _11, _10) -> [success: bb6, unwind: bb8]; } bb6: { - _12 = &(*_1)[_9]; - StorageLive(_13); - _13 = &_2; + _13 = &(*_1)[_10]; StorageLive(_14); - _14 = (_9, _12); - _15 = >::call(move _13, move _14) -> [return: bb7, unwind: bb8]; + _14 = &_2; + StorageLive(_15); + _15 = (_10, _13); + _16 = >::call(move _14, move _15) -> [return: bb7, unwind: bb8]; } bb7: { + StorageDead(_15); StorageDead(_14); - StorageDead(_13); - StorageDead(_8); + StorageDead(_9); goto -> bb1; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir index 9200d311d6d7..ffeef1e04a15 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir @@ -4,22 +4,22 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _11: std::slice::Iter<'_, T>; - let mut _12: std::iter::Rev>; + let mut _12: std::slice::Iter<'_, T>; let mut _13: std::iter::Rev>; - let mut _15: std::option::Option<&T>; - let mut _16: isize; - let mut _18: &impl Fn(&T); - let mut _19: (&T,); - let _20: (); + let mut _14: std::iter::Rev>; + let mut _16: std::option::Option<&T>; + let mut _17: isize; + let mut _19: &impl Fn(&T); + let mut _20: (&T,); + let _21: (); scope 1 { - debug iter => _13; - let _17: &T; + debug iter => _14; + let _18: &T; scope 2 { - debug x => _17; + debug x => _18; } scope 17 (inlined > as Iterator>::next) { - let mut _14: &mut std::slice::Iter<'_, T>; + let mut _15: &mut std::slice::Iter<'_, T>; } } scope 3 (inlined core::slice::::iter) { @@ -28,10 +28,11 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { let mut _7: bool; let mut _8: *mut T; let mut _9: *mut T; - let mut _10: *const T; + let mut _11: *const T; scope 5 { let _6: std::ptr::NonNull; scope 6 { + let _10: *const T; scope 7 { } scope 11 (inlined without_provenance::) { @@ -60,16 +61,16 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb0: { - StorageLive(_11); + StorageLive(_12); StorageLive(_3); StorageLive(_6); - StorageLive(_10); StorageLive(_4); StorageLive(_5); _3 = Len((*_1)); _4 = &raw const (*_1); _5 = _4 as *const T (PtrToPtr); _6 = NonNull:: { pointer: _5 }; + StorageLive(_10); StorageLive(_7); _7 = const ::IS_ZST; switchInt(move _7) -> [0: bb1, otherwise: bb2]; @@ -93,35 +94,38 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { bb3: { StorageDead(_7); - _11 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> }; + StorageLive(_11); + _11 = _10; + _12 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _11, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_11); + StorageDead(_10); StorageDead(_5); StorageDead(_4); - StorageDead(_10); StorageDead(_6); StorageDead(_3); - _12 = Rev::> { iter: _11 }; - StorageDead(_11); - StorageLive(_13); - _13 = _12; + _13 = Rev::> { iter: _12 }; + StorageDead(_12); + StorageLive(_14); + _14 = _13; goto -> bb4; } bb4: { + StorageLive(_16); StorageLive(_15); - StorageLive(_14); - _14 = &mut (_13.0: std::slice::Iter<'_, T>); - _15 = as DoubleEndedIterator>::next_back(move _14) -> [return: bb5, unwind unreachable]; + _15 = &mut (_14.0: std::slice::Iter<'_, T>); + _16 = as DoubleEndedIterator>::next_back(move _15) -> [return: bb5, unwind unreachable]; } bb5: { - StorageDead(_14); - _16 = discriminant(_15); - switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_15); + _17 = discriminant(_16); + switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_15); - StorageDead(_13); + StorageDead(_16); + StorageDead(_14); drop(_2) -> [return: bb7, unwind unreachable]; } @@ -130,18 +134,18 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _17 = ((_15 as Some).0: &T); - StorageLive(_18); - _18 = &_2; + _18 = ((_16 as Some).0: &T); StorageLive(_19); - _19 = (_17,); - _20 = >::call(move _18, move _19) -> [return: bb9, unwind unreachable]; + _19 = &_2; + StorageLive(_20); + _20 = (_18,); + _21 = >::call(move _19, move _20) -> [return: bb9, unwind unreachable]; } bb9: { + StorageDead(_20); StorageDead(_19); - StorageDead(_18); - StorageDead(_15); + StorageDead(_16); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir index 5a2d9d2a6814..c7cd37afd866 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir @@ -4,22 +4,22 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _11: std::slice::Iter<'_, T>; - let mut _12: std::iter::Rev>; + let mut _12: std::slice::Iter<'_, T>; let mut _13: std::iter::Rev>; - let mut _15: std::option::Option<&T>; - let mut _16: isize; - let mut _18: &impl Fn(&T); - let mut _19: (&T,); - let _20: (); + let mut _14: std::iter::Rev>; + let mut _16: std::option::Option<&T>; + let mut _17: isize; + let mut _19: &impl Fn(&T); + let mut _20: (&T,); + let _21: (); scope 1 { - debug iter => _13; - let _17: &T; + debug iter => _14; + let _18: &T; scope 2 { - debug x => _17; + debug x => _18; } scope 17 (inlined > as Iterator>::next) { - let mut _14: &mut std::slice::Iter<'_, T>; + let mut _15: &mut std::slice::Iter<'_, T>; } } scope 3 (inlined core::slice::::iter) { @@ -28,10 +28,11 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { let mut _7: bool; let mut _8: *mut T; let mut _9: *mut T; - let mut _10: *const T; + let mut _11: *const T; scope 5 { let _6: std::ptr::NonNull; scope 6 { + let _10: *const T; scope 7 { } scope 11 (inlined without_provenance::) { @@ -60,16 +61,16 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb0: { - StorageLive(_11); + StorageLive(_12); StorageLive(_3); StorageLive(_6); - StorageLive(_10); StorageLive(_4); StorageLive(_5); _3 = Len((*_1)); _4 = &raw const (*_1); _5 = _4 as *const T (PtrToPtr); _6 = NonNull:: { pointer: _5 }; + StorageLive(_10); StorageLive(_7); _7 = const ::IS_ZST; switchInt(move _7) -> [0: bb1, otherwise: bb2]; @@ -93,35 +94,38 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { bb3: { StorageDead(_7); - _11 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> }; + StorageLive(_11); + _11 = _10; + _12 = std::slice::Iter::<'_, T> { ptr: _6, end_or_len: move _11, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_11); + StorageDead(_10); StorageDead(_5); StorageDead(_4); - StorageDead(_10); StorageDead(_6); StorageDead(_3); - _12 = Rev::> { iter: _11 }; - StorageDead(_11); - StorageLive(_13); - _13 = _12; + _13 = Rev::> { iter: _12 }; + StorageDead(_12); + StorageLive(_14); + _14 = _13; goto -> bb4; } bb4: { + StorageLive(_16); StorageLive(_15); - StorageLive(_14); - _14 = &mut (_13.0: std::slice::Iter<'_, T>); - _15 = as DoubleEndedIterator>::next_back(move _14) -> [return: bb5, unwind: bb11]; + _15 = &mut (_14.0: std::slice::Iter<'_, T>); + _16 = as DoubleEndedIterator>::next_back(move _15) -> [return: bb5, unwind: bb11]; } bb5: { - StorageDead(_14); - _16 = discriminant(_15); - switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_15); + _17 = discriminant(_16); + switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_15); - StorageDead(_13); + StorageDead(_16); + StorageDead(_14); drop(_2) -> [return: bb7, unwind continue]; } @@ -130,18 +134,18 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _17 = ((_15 as Some).0: &T); - StorageLive(_18); - _18 = &_2; + _18 = ((_16 as Some).0: &T); StorageLive(_19); - _19 = (_17,); - _20 = >::call(move _18, move _19) -> [return: bb9, unwind: bb11]; + _19 = &_2; + StorageLive(_20); + _20 = (_18,); + _21 = >::call(move _19, move _20) -> [return: bb9, unwind: bb11]; } bb9: { + StorageDead(_20); StorageDead(_19); - StorageDead(_18); - StorageDead(_15); + StorageDead(_16); goto -> bb4; } From ed5205fe66ccd49116e99e4244483caaa8cf933e Mon Sep 17 00:00:00 2001 From: r0cky Date: Fri, 31 May 2024 08:29:42 +0800 Subject: [PATCH 109/211] Avoid unwrap diag.code directly --- .../infer/error_reporting/note_and_explain.rs | 4 +-- ...t-proj-ty-as-type-of-const-issue-125757.rs | 19 ++++++++++ ...oj-ty-as-type-of-const-issue-125757.stderr | 36 +++++++++++++++++++ 3 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.rs create mode 100644 tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.stderr diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs index f4514c235084..19ef2d61fca3 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs @@ -182,7 +182,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { diag.span_label(p_span, format!("{expected}this type parameter")); } diag.help("type parameters must be constrained to match other types"); - if tcx.sess.teach(diag.code.unwrap()) { + if diag.code.is_some_and(|code| tcx.sess.teach(code)) { diag.help( "given a type parameter `T` and a method `foo`: ``` @@ -663,7 +663,7 @@ impl Trait for X { https://doc.rust-lang.org/book/ch19-03-advanced-traits.html", ); } - if tcx.sess.teach(diag.code.unwrap()) { + if diag.code.is_some_and(|code| tcx.sess.teach(code)) { diag.help( "given an associated type `T` and a method `foo`: ``` 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 new file mode 100644 index 000000000000..59a015da84eb --- /dev/null +++ b/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.rs @@ -0,0 +1,19 @@ +#![feature(specialization)] +#![allow(incomplete_features)] + +trait Trait { + type Type; +} + +impl Trait for i32 { + default type Type = i32; +} + +struct Wrapper::Type> {} +//~^ ERROR `::Type` is forbidden as the type of a const generic parameter + +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 new file mode 100644 index 000000000000..b4c14c2294e5 --- /dev/null +++ b/tests/ui/specialization/default-proj-ty-as-type-of-const-issue-125757.stderr @@ -0,0 +1,36 @@ +error: `::Type` is forbidden as the type of a const generic parameter + --> $DIR/default-proj-ty-as-type-of-const-issue-125757.rs:12:25 + | +LL | struct Wrapper::Type> {} + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + +error: the constant `C` is not of type `::Type` + --> $DIR/default-proj-ty-as-type-of-const-issue-125757.rs:15:22 + | +LL | impl Wrapper {} + | ^^^^^^^^^^ expected associated type, found `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 +note: required by a bound in `Wrapper` + --> $DIR/default-proj-ty-as-type-of-const-issue-125757.rs:12:16 + | +LL | struct Wrapper::Type> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound 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 + +For more information about this error, try `rustc --explain E0308`. From 94d4040925571c7a69cebe6c6e9aeab172da65d1 Mon Sep 17 00:00:00 2001 From: Lokathor Date: Thu, 30 May 2024 19:34:05 -0600 Subject: [PATCH 110/211] The modern styling is apparently to use Title Case for the chip/company, "Arm". --- .../src/platform-support/arm-none-eabi.md | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/doc/rustc/src/platform-support/arm-none-eabi.md b/src/doc/rustc/src/platform-support/arm-none-eabi.md index 09f3461cb980..de0ef322fa67 100644 --- a/src/doc/rustc/src/platform-support/arm-none-eabi.md +++ b/src/doc/rustc/src/platform-support/arm-none-eabi.md @@ -3,7 +3,7 @@ ## Common Target Details This documentation covers details that apply to a range of bare-metal targets -for 32-bit ARM CPUs. The `arm-none-eabi` flavor of the GNU compiler toolchain is +for 32-bit Arm CPUs. The `arm-none-eabi` flavor of the GNU compiler toolchain is often used to assist compilation to these targets. Details that apply only to only a specific target in this group are covered in @@ -11,55 +11,55 @@ their own document. ### Tier 2 Target List -- ARM A-Profile Architectures +- Arm A-Profile Architectures - `armv7a-none-eabi` -- ARM R-Profile Architectures +- Arm R-Profile Architectures - [`armv7r-none-eabi` and `armv7r-none-eabihf`](armv7r-none-eabi.md) - [`armebv7r-none-eabi` and `armebv7r-none-eabihf`](armv7r-none-eabi.md) -- ARM M-Profile Architectures +- Arm M-Profile Architectures - [`thumbv6m-none-eabi`](thumbv6m-none-eabi.md) - [`thumbv7m-none-eabi`](thumbv7m-none-eabi.md) - [`thumbv7em-none-eabi` and `thumbv7em-none-eabihf`](thumbv7em-none-eabi.md) - [`thumbv8m.base-none-eabi`](thumbv8m.base-none-eabi.md) - [`thumbv8m.main-none-eabi` and `thumbv8m.main-none-eabihf`](thumbv8m.main-none-eabi.md) -- *Legacy* ARM Architectures +- *Legacy* Arm Architectures - None ### Tier 3 Target List -- ARM A-Profile Architectures +- Arm A-Profile Architectures - `armv7a-none-eabihf` -- ARM R-Profile Architectures +- Arm R-Profile Architectures - [`armv8r-none-eabihf`](armv8r-none-eabihf.md) -- ARM M-Profile Architectures +- Arm M-Profile Architectures - None -- *Legacy* ARM Architectures +- *Legacy* Arm Architectures - [`armv4t-none-eabi` and `thumbv4t-none-eabi`](armv4t-none-eabi.md) - [`armv5te-none-eabi` and `thumbv5te-none-eabi`](armv5te-none-eabi.md) ## Instruction Sets -There are two 32-bit instruction set architectures (ISAs) defined by ARM: +There are two 32-bit instruction set architectures (ISAs) defined by Arm: - The [*A32 ISA*][a32-isa], with fixed-width 32-bit instructions. Previously - known as the *ARM* ISA, this originated with the original ARM1 of 1985 and has + known as the *Arm* ISA, this originated with the original Arm1 of 1985 and has been updated by various revisions to the architecture specifications ever since. - The [*T32 ISA*][t32-isa], with a mix of 16-bit and 32-bit width instructions. Note that this term includes both the original 16-bit width *Thumb* ISA - introduced with the ARMv4T architecture in 1994, and the later 16/32-bit sized - *Thumb-2* ISA introduced with the ARMv6T2 architecture in 2003. + introduced with the Armv4T architecture in 1994, and the later 16/32-bit sized + *Thumb-2* ISA introduced with the Armv6T2 architecture in 2003. -Again, these ISAs have been revised by subsequent revisions to the relevant ARM +Again, these ISAs have been revised by subsequent revisions to the relevant Arm architecture specifications. There is also a 64-bit ISA with fixed-width 32-bit instructions called the *A64 ISA*, but targets which implement that instruction set generally start with `aarch64*` and are discussed elsewhere. -Rust targets starting with `arm*` generate ARM (A32) code by default, whilst -targets named `thumb*` generate Thumb (T32) code by default. Most ARM chips -support both Thumb mode and ARM mode, with the notable exception that M-profile +Rust targets starting with `arm*` generate Arm (A32) code by default, whilst +targets named `thumb*` generate Thumb (T32) code by default. Most Arm chips +support both Thumb mode and Arm mode, with the notable exception that M-profile processors (`thumbv*m*-none-eabi*` targets) *only* support Thumb-mode. Rust targets ending with `eabi` use the so-called *soft-float ABI*: functions @@ -92,14 +92,14 @@ instructions. ## Target CPU and Target Feature options -It is possible to tell Rust (or LLVM) that you have a specific model of ARM +It is possible to tell Rust (or LLVM) that you have a specific model of Arm processor, using the [`-C target-cpu`][target-cpu] option. You can also control whether Rust (or LLVM) will include instructions that target optional hardware features, e.g. hardware floating-point, or Advanced SIMD operations, using [`-C target-feature`][target-feature]. It is important to note that selecting a *target-cpu* will typically enable -*all* the optional features available from ARM on that model of CPU and your +*all* the optional features available from Arm on that model of CPU and your particular implementation of that CPU may not have those features available. In that case, you can use `-C target-feature=-option` to turn off the specific CPU features you do not have available, leaving you with the optimized instruction @@ -116,7 +116,7 @@ uses (likely linker related ones): ```toml rustflags = [ - # Usual ARM bare-metal linker setup + # Usual Arm bare-metal linker setup "-Clink-arg=-Tlink.x", "-Clink-arg=--nmagic", # tell Rust we have a Cortex-M55 @@ -139,7 +139,7 @@ These targets are cross-compiled and use static linking. By default, the `lld` linker included with Rust will be used; however, you may want to use the GNU linker instead. This can be obtained for Windows/Mac/Linux -from the [ARM Developer Website][arm-gnu-toolchain], or possibly from your OS's +from the [Arm Developer Website][arm-gnu-toolchain], or possibly from your OS's package manager. To use it, add the following to your `.cargo/config.toml`: ```toml @@ -185,7 +185,7 @@ Most of `core` should work as expected, with the following notes: specific kind of FPU) * Integer division is also emulated in software on some targets, depending on the target, `target-cpu` and `target-feature`s. -* Older ARM architectures (e.g. ARMv4, ARMv5TE and ARMv6-M) are limited to basic +* Older Arm architectures (e.g. Armv4, Armv5TE and Armv6-M) are limited to basic [`load`][atomic-load] and [`store`][atomic-store] operations, and not more advanced operations like [`fetch_add`][fetch-add] or [`compare_exchange`][compare-exchange]. From 08fe940f0a47f7281ec916a924ec978cac994491 Mon Sep 17 00:00:00 2001 From: Lucas Scharenbroch Date: Thu, 30 May 2024 21:39:12 -0500 Subject: [PATCH 111/211] Improve renaming suggestion for names with leading underscores --- compiler/rustc_resolve/src/diagnostics.rs | 38 ++++++++++++++--------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 856cfbc01e8c..d1541527cf59 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1562,6 +1562,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Some(suggestion) if suggestion.candidate == kw::Underscore => return false, Some(suggestion) => suggestion, }; + + let mut did_label_def_span = false; + if let Some(def_span) = suggestion.res.opt_def_id().map(|def_id| self.def_span(def_id)) { if span.overlaps(def_span) { // Don't suggest typo suggestion for itself like in the following: @@ -1595,31 +1598,38 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { errors::DefinedHere::SingleItem { span, candidate_descr, candidate } } }; + did_label_def_span = true; err.subdiagnostic(self.tcx.dcx(), label); } - let (span, sugg, post) = if let SuggestionTarget::SimilarlyNamed = suggestion.target + let (span, msg, sugg) = if let SuggestionTarget::SimilarlyNamed = suggestion.target && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) && let Some(span) = suggestion.span && let Some(candidate) = suggestion.candidate.as_str().strip_prefix('_') && snippet == candidate { + let candidate = suggestion.candidate; // When the suggested binding change would be from `x` to `_x`, suggest changing the // original binding definition instead. (#60164) - let post = format!(", consider renaming `{}` into `{snippet}`", suggestion.candidate); - (span, snippet, post) - } else { - (span, suggestion.candidate.to_ident_string(), String::new()) - }; - let msg = match suggestion.target { - SuggestionTarget::SimilarlyNamed => format!( - "{} {} with a similar name exists{post}", - suggestion.res.article(), - suggestion.res.descr() - ), - SuggestionTarget::SingleItem => { - format!("maybe you meant this {}", suggestion.res.descr()) + let msg = format!( + "the leading underscore in `{candidate}` marks it as unused, consider renaming it to `{snippet}`" + ); + if !did_label_def_span { + err.span_label(span, format!("`{candidate}` defined here")); } + (span, msg, snippet) + } else { + let msg = match suggestion.target { + SuggestionTarget::SimilarlyNamed => format!( + "{} {} with a similar name exists", + suggestion.res.article(), + suggestion.res.descr() + ), + SuggestionTarget::SingleItem => { + format!("maybe you meant this {}", suggestion.res.descr()) + } + }; + (span, msg, suggestion.candidate.to_ident_string()) }; err.span_suggestion(span, msg, sugg, Applicability::MaybeIncorrect); true From 9af96745d693b5b263fab27c84d7cb55465ca09b Mon Sep 17 00:00:00 2001 From: Lucas Scharenbroch Date: Thu, 30 May 2024 21:39:41 -0500 Subject: [PATCH 112/211] Update ui tests for leading-underscore suggestion --- tests/ui/macros/expand-full-no-resolution.stderr | 4 ++-- tests/ui/suggestions/silenced-binding-typo.stderr | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/ui/macros/expand-full-no-resolution.stderr b/tests/ui/macros/expand-full-no-resolution.stderr index 2537a5032a92..df6f20332bfd 100644 --- a/tests/ui/macros/expand-full-no-resolution.stderr +++ b/tests/ui/macros/expand-full-no-resolution.stderr @@ -7,7 +7,7 @@ LL | macro_rules! _a { LL | format_args!(a!()); | ^ | -help: a macro with a similar name exists, consider renaming `_a` into `a` +help: the leading underscore in `_a` marks it as unused, consider renaming it to `a` | LL | macro_rules! a { | ~ @@ -21,7 +21,7 @@ LL | macro_rules! _a { LL | env!(a!()); | ^ | -help: a macro with a similar name exists, consider renaming `_a` into `a` +help: the leading underscore in `_a` marks it as unused, consider renaming it to `a` | LL | macro_rules! a { | ~ diff --git a/tests/ui/suggestions/silenced-binding-typo.stderr b/tests/ui/suggestions/silenced-binding-typo.stderr index c362d00c713a..a1e8b9e30d4b 100644 --- a/tests/ui/suggestions/silenced-binding-typo.stderr +++ b/tests/ui/suggestions/silenced-binding-typo.stderr @@ -1,10 +1,12 @@ error[E0425]: cannot find value `x` in this scope --> $DIR/silenced-binding-typo.rs:4:14 | +LL | let _x = 42; + | -- `_x` defined here LL | let _y = x; | ^ | -help: a local variable with a similar name exists, consider renaming `_x` into `x` +help: the leading underscore in `_x` marks it as unused, consider renaming it to `x` | LL | let x = 42; | ~ From 772e48cfbb92dd415ec7ce564926e33015d45469 Mon Sep 17 00:00:00 2001 From: Henry Chen Date: Wed, 22 May 2024 19:44:59 +0800 Subject: [PATCH 113/211] minor: replace command-group with process-wrap Because command-group no longer receives updates and depends on an older version of nix. --- src/tools/rust-analyzer/Cargo.lock | 106 +++++++++++------- src/tools/rust-analyzer/Cargo.toml | 2 +- .../rust-analyzer/crates/flycheck/Cargo.toml | 2 +- .../crates/flycheck/src/command.rs | 16 ++- 4 files changed, 77 insertions(+), 49 deletions(-) diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index 8eb872514a5d..3558c39bb32c 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -216,16 +216,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "command-group" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5080df6b0f0ecb76cab30808f00d937ba725cebe266a3da8cd89dff92f2a9916" -dependencies = [ - "nix 0.26.4", - "winapi", -] - [[package]] name = "countme" version = "3.0.1" @@ -292,7 +282,7 @@ version = "3.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "672465ae37dc1bc6380a6547a8883d5dd397b0f1faaad4f265726cc7042a5345" dependencies = [ - "nix 0.28.0", + "nix", "windows-sys 0.52.0", ] @@ -432,9 +422,9 @@ name = "flycheck" version = "0.0.0" dependencies = [ "cargo_metadata", - "command-group", "crossbeam-channel", "paths", + "process-wrap", "rustc-hash", "serde", "serde_json", @@ -1121,17 +1111,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "nix" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" -dependencies = [ - "bitflags 1.3.2", - "cfg-if", - "libc", -] - [[package]] name = "nix" version = "0.28.0" @@ -1397,6 +1376,18 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "process-wrap" +version = "8.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38ee68ae331824036479c84060534b18254c864fa73366c58d86db3b7b811619" +dependencies = [ + "indexmap", + "nix", + "tracing", + "windows", +] + [[package]] name = "profile" version = "0.0.0" @@ -2374,22 +2365,6 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - [[package]] name = "winapi-util" version = "0.1.8" @@ -2400,10 +2375,57 @@ dependencies = [ ] [[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" +name = "windows" +version = "0.56.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "1de69df01bdf1ead2f4ac895dc77c9351aefff65b2f3db429a343f9cbf05e132" +dependencies = [ + "windows-core", + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-core" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4698e52ed2d08f8658ab0c39512a7c00ee5fe2688c65f8c0a4f06750d729f2a6" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-result", + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-implement" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-result" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "749f0da9cc72d82e600d8d2e44cadd0b9eedb9038f71a1c58556ac1c5791813b" +dependencies = [ + "windows-targets 0.52.5", +] [[package]] name = "windows-sys" diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml index 3108c1b3dfe5..ccc27e21333b 100644 --- a/src/tools/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/Cargo.toml @@ -111,7 +111,6 @@ chalk-solve = { version = "0.97.0", default-features = false } chalk-ir = "0.97.0" chalk-recursive = { version = "0.97.0", default-features = false } chalk-derive = "0.97.0" -command-group = "2.0.1" crossbeam-channel = "0.5.8" dissimilar = "1.0.7" dot = "0.1.4" @@ -132,6 +131,7 @@ object = { version = "0.33.0", default-features = false, features = [ "macho", "pe", ] } +process-wrap = { version = "8.0.2", features = ["std"] } pulldown-cmark-to-cmark = "10.0.4" pulldown-cmark = { version = "0.9.0", default-features = false } rayon = "1.8.0" diff --git a/src/tools/rust-analyzer/crates/flycheck/Cargo.toml b/src/tools/rust-analyzer/crates/flycheck/Cargo.toml index b8c10da1b6e3..d81a5fe34006 100644 --- a/src/tools/rust-analyzer/crates/flycheck/Cargo.toml +++ b/src/tools/rust-analyzer/crates/flycheck/Cargo.toml @@ -18,7 +18,7 @@ tracing.workspace = true rustc-hash.workspace = true serde_json.workspace = true serde.workspace = true -command-group.workspace = true +process-wrap.workspace = true # local deps paths.workspace = true diff --git a/src/tools/rust-analyzer/crates/flycheck/src/command.rs b/src/tools/rust-analyzer/crates/flycheck/src/command.rs index 8ba7018316a1..38c7c81f57a1 100644 --- a/src/tools/rust-analyzer/crates/flycheck/src/command.rs +++ b/src/tools/rust-analyzer/crates/flycheck/src/command.rs @@ -9,8 +9,8 @@ use std::{ process::{ChildStderr, ChildStdout, Command, Stdio}, }; -use command_group::{CommandGroup, GroupChild}; use crossbeam_channel::Sender; +use process_wrap::std::{StdChildWrapper, StdCommandWrap}; use stdx::process::streaming_output; /// Cargo output is structured as a one JSON per line. This trait abstracts parsing one line of @@ -85,7 +85,7 @@ impl CargoActor { } } -struct JodGroupChild(GroupChild); +struct JodGroupChild(Box); impl Drop for JodGroupChild { fn drop(&mut self) { @@ -119,14 +119,20 @@ impl fmt::Debug for CommandHandle { impl CommandHandle { pub(crate) fn spawn(mut command: Command, sender: Sender) -> std::io::Result { command.stdout(Stdio::piped()).stderr(Stdio::piped()).stdin(Stdio::null()); - let mut child = command.group_spawn().map(JodGroupChild)?; let program = command.get_program().into(); let arguments = command.get_args().map(|arg| arg.into()).collect::>(); let current_dir = command.get_current_dir().map(|arg| arg.to_path_buf()); - let stdout = child.0.inner().stdout.take().unwrap(); - let stderr = child.0.inner().stderr.take().unwrap(); + let mut child = StdCommandWrap::from(command); + #[cfg(unix)] + child.wrap(process_wrap::std::ProcessSession); + #[cfg(windows)] + child.wrap(process_wrap::std::JobObject); + let mut child = child.spawn().map(JodGroupChild)?; + + let stdout = child.0.stdout().take().unwrap(); + let stderr = child.0.stderr().take().unwrap(); let actor = CargoActor::::new(sender, stdout, stderr); let thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker) From 4b96e44ebbf42dc8b6f3e5ac4894739adc17d826 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Thu, 30 May 2024 22:05:30 -0700 Subject: [PATCH 114/211] Also InstSimplify `&raw*` We do this for `&*` and `&mut*` already; might as well do it for raw pointers too. --- .../rustc_mir_transform/src/instsimplify.rs | 2 +- .../ref_of_deref.pointers.InstSimplify.diff | 58 +++++++++++++++++++ .../ref_of_deref.references.InstSimplify.diff | 58 +++++++++++++++++++ tests/mir-opt/instsimplify/ref_of_deref.rs | 40 +++++++++++++ 4 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 tests/mir-opt/instsimplify/ref_of_deref.pointers.InstSimplify.diff create mode 100644 tests/mir-opt/instsimplify/ref_of_deref.references.InstSimplify.diff create mode 100644 tests/mir-opt/instsimplify/ref_of_deref.rs diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index a54332b6f257..40db3e38fd32 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -123,7 +123,7 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> { /// Transform `&(*a)` ==> `a`. fn simplify_ref_deref(&self, source_info: &SourceInfo, rvalue: &mut Rvalue<'tcx>) { - if let Rvalue::Ref(_, _, place) = rvalue { + if let Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) = rvalue { if let Some((base, ProjectionElem::Deref)) = place.as_ref().last_projection() { if rvalue.ty(self.local_decls, self.tcx) != base.ty(self.local_decls, self.tcx).ty { return; diff --git a/tests/mir-opt/instsimplify/ref_of_deref.pointers.InstSimplify.diff b/tests/mir-opt/instsimplify/ref_of_deref.pointers.InstSimplify.diff new file mode 100644 index 000000000000..52b3d1e1d40b --- /dev/null +++ b/tests/mir-opt/instsimplify/ref_of_deref.pointers.InstSimplify.diff @@ -0,0 +1,58 @@ +- // MIR for `pointers` before InstSimplify ++ // MIR for `pointers` after InstSimplify + + fn pointers(_1: *const [i32], _2: *mut i32) -> () { + debug const_ptr => _1; + debug mut_ptr => _2; + let mut _0: (); + let _3: &[i32]; + scope 1 { + debug _a => _3; + let _4: &i32; + scope 2 { + debug _b => _4; + let _5: &mut i32; + scope 3 { + debug _c => _5; + let _6: *const [i32]; + scope 4 { + debug _d => _6; + let _7: *const i32; + scope 5 { + debug _e => _7; + let _8: *mut i32; + scope 6 { + debug _f => _8; + } + } + } + } + } + } + + bb0: { + StorageLive(_3); + _3 = &(*_1); + StorageLive(_4); + _4 = &(*_2); + StorageLive(_5); + _5 = &mut (*_2); + StorageLive(_6); +- _6 = &raw const (*_1); ++ _6 = _1; + StorageLive(_7); + _7 = &raw const (*_2); + StorageLive(_8); +- _8 = &raw mut (*_2); ++ _8 = _2; + _0 = const (); + StorageDead(_8); + StorageDead(_7); + StorageDead(_6); + StorageDead(_5); + StorageDead(_4); + StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/instsimplify/ref_of_deref.references.InstSimplify.diff b/tests/mir-opt/instsimplify/ref_of_deref.references.InstSimplify.diff new file mode 100644 index 000000000000..ca0828a225a0 --- /dev/null +++ b/tests/mir-opt/instsimplify/ref_of_deref.references.InstSimplify.diff @@ -0,0 +1,58 @@ +- // MIR for `references` before InstSimplify ++ // MIR for `references` after InstSimplify + + fn references(_1: &i32, _2: &mut [i32]) -> () { + debug const_ref => _1; + debug mut_ref => _2; + let mut _0: (); + let _3: &i32; + scope 1 { + debug _a => _3; + let _4: &[i32]; + scope 2 { + debug _b => _4; + let _5: &mut [i32]; + scope 3 { + debug _c => _5; + let _6: *const i32; + scope 4 { + debug _d => _6; + let _7: *const [i32]; + scope 5 { + debug _e => _7; + let _8: *mut [i32]; + scope 6 { + debug _f => _8; + } + } + } + } + } + } + + bb0: { + StorageLive(_3); +- _3 = &(*_1); ++ _3 = _1; + StorageLive(_4); + _4 = &(*_2); + StorageLive(_5); +- _5 = &mut (*_2); ++ _5 = _2; + StorageLive(_6); + _6 = &raw const (*_1); + StorageLive(_7); + _7 = &raw const (*_2); + StorageLive(_8); + _8 = &raw mut (*_2); + _0 = const (); + StorageDead(_8); + StorageDead(_7); + StorageDead(_6); + StorageDead(_5); + StorageDead(_4); + StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/instsimplify/ref_of_deref.rs b/tests/mir-opt/instsimplify/ref_of_deref.rs new file mode 100644 index 000000000000..37e164bc17f1 --- /dev/null +++ b/tests/mir-opt/instsimplify/ref_of_deref.rs @@ -0,0 +1,40 @@ +//@ test-mir-pass: InstSimplify +#![crate_type = "lib"] +#![feature(raw_ref_op)] + +// For each of these, only 2 of the 6 should simplify, +// as the others have the wrong types. + +// EMIT_MIR ref_of_deref.references.InstSimplify.diff +// CHECK-LABEL: references +pub fn references(const_ref: &i32, mut_ref: &mut [i32]) { + // CHECK: _3 = _1; + let _a = &*const_ref; + // CHECK: _4 = &(*_2); + let _b = &*mut_ref; + // CHECK: _5 = _2; + let _c = &mut *mut_ref; + // CHECK: _6 = &raw const (*_1); + let _d = &raw const *const_ref; + // CHECK: _7 = &raw const (*_2); + let _e = &raw const *mut_ref; + // CHECK: _8 = &raw mut (*_2); + let _f = &raw mut *mut_ref; +} + +// EMIT_MIR ref_of_deref.pointers.InstSimplify.diff +// CHECK-LABEL: pointers +pub unsafe fn pointers(const_ptr: *const [i32], mut_ptr: *mut i32) { + // CHECK: _3 = &(*_1); + let _a = &*const_ptr; + // CHECK: _4 = &(*_2); + let _b = &*mut_ptr; + // CHECK: _5 = &mut (*_2); + let _c = &mut *mut_ptr; + // CHECK: _6 = _1; + let _d = &raw const *const_ptr; + // CHECK: _7 = &raw const (*_2); + let _e = &raw const *mut_ptr; + // CHECK: _8 = _2; + let _f = &raw mut *mut_ptr; +} From 72800d3b896a5733d08213ec357f3a875f1f5b0e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 29 May 2024 14:11:20 +1000 Subject: [PATCH 115/211] Run rustfmt on `tests/codegen/`. Except for `simd-intrinsic/`, which has a lot of files containing multiple types like `u8x64` which really are better when hand-formatted. There is a surprising amount of two-space indenting in this directory. Non-trivial changes: - `rustfmt::skip` needed in `debug-column.rs` to preserve meaning of the test. - `rustfmt::skip` used in a few places where hand-formatting read more nicely: `enum/enum-match.rs` - Line number adjustments needed for the expected output of `debug-column.rs` and `coroutine-debug.rs`. --- rustfmt.toml | 2 +- tests/codegen/aarch64-struct-align-128.rs | 50 ++++--- tests/codegen/abi-efiapi.rs | 12 +- .../codegen/abi-main-signature-16bit-c-int.rs | 4 +- .../codegen/abi-main-signature-32bit-c-int.rs | 3 +- tests/codegen/abi-repr-ext.rs | 12 +- tests/codegen/abi-x86_64_sysv.rs | 16 +-- tests/codegen/adjustments.rs | 11 +- tests/codegen/align-byval.rs | 21 +-- tests/codegen/align-enum.rs | 6 +- tests/codegen/align-offset.rs | 1 - tests/codegen/align-struct.rs | 14 +- tests/codegen/array-cmp.rs | 11 +- tests/codegen/asm-maybe-uninit.rs | 2 +- tests/codegen/asm-sanitize-llvm.rs | 8 +- tests/codegen/atomicptr.rs | 3 +- tests/codegen/autovectorize-f32x4.rs | 31 ++-- tests/codegen/auxiliary/extern_decl.rs | 4 +- tests/codegen/auxiliary/nounwind.rs | 3 +- tests/codegen/avr/avr-func-addrspace.rs | 22 +-- .../binary-search-index-no-bound-check.rs | 6 +- tests/codegen/bool-cmp.rs | 8 +- tests/codegen/branch-protection.rs | 7 +- tests/codegen/cast-target-abi.rs | 13 +- tests/codegen/cf-protection.rs | 7 +- tests/codegen/cffi/ffi-const.rs | 7 +- tests/codegen/cffi/ffi-out-of-bounds-loads.rs | 9 +- tests/codegen/cffi/ffi-pure.rs | 7 +- tests/codegen/cfguard-checks.rs | 3 +- tests/codegen/cfguard-disabled.rs | 3 +- tests/codegen/cfguard-nochecks.rs | 3 +- tests/codegen/cfguard-non-msvc.rs | 3 +- tests/codegen/coercions.rs | 2 +- tests/codegen/constant-branch.rs | 32 ++--- tests/codegen/coroutine-debug-msvc.rs | 13 +- tests/codegen/coroutine-debug.rs | 13 +- tests/codegen/dealloc-no-unwind.rs | 10 +- tests/codegen/debug-column.rs | 5 +- tests/codegen/debug-compile-unit-path.rs | 2 +- .../debuginfo-generic-closure-env-names.rs | 7 +- tests/codegen/dllimports/auxiliary/wrapper.rs | 4 +- tests/codegen/dllimports/main.rs | 6 +- tests/codegen/drop-in-place-noalias.rs | 2 +- tests/codegen/drop.rs | 28 ++-- tests/codegen/dst-offset.rs | 53 ++++--- tests/codegen/dst-vtable-align-nonzero.rs | 14 +- tests/codegen/ehcontguard_disabled.rs | 3 +- tests/codegen/ehcontguard_enabled.rs | 3 +- tests/codegen/emcripten-catch-unwind.rs | 17 ++- tests/codegen/enable-lto-unit-splitting.rs | 5 +- tests/codegen/enum/enum-bounds-check.rs | 5 +- tests/codegen/enum/enum-debug-clike.rs | 6 +- tests/codegen/enum/enum-debug-niche.rs | 7 +- tests/codegen/enum/enum-debug-tagged.rs | 5 +- tests/codegen/enum/enum-match.rs | 1 + .../enum/unreachable_enum_default_branch.rs | 9 +- tests/codegen/fatptr.rs | 2 +- tests/codegen/float_math.rs | 30 ++-- tests/codegen/force-frame-pointers.rs | 2 +- tests/codegen/force-no-unwind-tables.rs | 2 +- tests/codegen/force-unwind-tables.rs | 2 +- tests/codegen/frame-pointer.rs | 9 +- tests/codegen/function-arguments-noopt.rs | 28 ++-- tests/codegen/function-arguments.rs | 132 +++++++----------- tests/codegen/generic-debug.rs | 2 +- tests/codegen/inline-always-works-always.rs | 2 +- tests/codegen/inline-debuginfo.rs | 2 +- .../instrument-coverage.rs | 6 +- tests/codegen/integer-cmp.rs | 16 +-- tests/codegen/integer-overflow.rs | 3 +- tests/codegen/internalize-closures.rs | 3 +- tests/codegen/intrinsic-no-unnamed-attr.rs | 4 +- tests/codegen/intrinsics/const_eval_select.rs | 8 +- tests/codegen/intrinsics/likely.rs | 14 +- tests/codegen/intrinsics/prefetch.rs | 5 +- tests/codegen/is_val_statically_known.rs | 2 +- tests/codegen/issue-97217.rs | 2 +- tests/codegen/issues/issue-103327.rs | 6 +- .../issues/issue-105386-ub-in-debuginfo.rs | 3 +- tests/codegen/issues/issue-119422.rs | 4 +- tests/codegen/issues/issue-13018.rs | 2 +- tests/codegen/issues/issue-32364.rs | 5 +- tests/codegen/issues/issue-37945.rs | 34 ++--- tests/codegen/issues/issue-45466.rs | 2 +- .../issue-45964-bounds-check-slice-pos.rs | 2 +- tests/codegen/issues/issue-47278.rs | 6 +- tests/codegen/issues/issue-47442.rs | 2 +- tests/codegen/issues/issue-56267-2.rs | 2 +- tests/codegen/issues/issue-56267.rs | 2 +- tests/codegen/issues/issue-56927.rs | 2 +- tests/codegen/issues/issue-73031.rs | 6 +- tests/codegen/issues/issue-73258.rs | 5 +- .../issues/issue-73338-effecient-cmp.rs | 10 +- ...issue-73396-bounds-check-after-position.rs | 36 +---- tests/codegen/issues/issue-75546.rs | 4 +- tests/codegen/issues/issue-77812.rs | 2 +- tests/codegen/issues/issue-84268.rs | 4 +- .../issues/issue-96497-slice-size-nowrap.rs | 2 +- tests/codegen/issues/issue-99960.rs | 6 +- tests/codegen/lib-optimizations/iter-sum.rs | 1 - tests/codegen/lifetime_start_end.rs | 16 +-- tests/codegen/link-dead-code.rs | 12 +- tests/codegen/link_section.rs | 2 +- .../loongarch-abi/loongarch64-lp64d-abi.rs | 9 +- tests/codegen/lto-removes-invokes.rs | 4 +- .../macos/i686-macosx-deployment-target.rs | 12 +- .../macos/i686-no-macosx-deployment-target.rs | 12 +- .../macos/x86_64-macosx-deployment-target.rs | 12 +- .../x86_64-no-macosx-deployment-target.rs | 12 +- tests/codegen/match-optimized.rs | 34 ++--- tests/codegen/match-optimizes-away.rs | 15 +- tests/codegen/mir_zst_stores.rs | 4 +- tests/codegen/naked-fn/naked-functions.rs | 7 +- tests/codegen/no-assumes-on-casts.rs | 8 +- tests/codegen/noalias-freeze.rs | 4 +- tests/codegen/noalias-unpin.rs | 2 +- .../non-terminate/infinite-recursion.rs | 1 - tests/codegen/noreturnflag.rs | 4 +- tests/codegen/nounwind.rs | 6 +- tests/codegen/optimize-attr-1.rs | 2 +- tests/codegen/option-niche-eq.rs | 2 +- tests/codegen/packed.rs | 36 ++--- tests/codegen/panic-abort-windows.rs | 6 +- tests/codegen/personality_lifetimes.rs | 8 +- tests/codegen/pgo-instrumentation.rs | 6 +- tests/codegen/pic-relocation-model.rs | 8 +- tests/codegen/pie-relocation-model.rs | 8 +- tests/codegen/powerpc64le-struct-align-128.rs | 30 ++-- tests/codegen/precondition-checks.rs | 4 +- tests/codegen/refs.rs | 9 +- tests/codegen/repr/transparent-imm-array.rs | 43 ++++-- tests/codegen/repr/transparent-mips64.rs | 42 ++++-- tests/codegen/repr/transparent-sparc64.rs | 43 ++++-- tests/codegen/repr/transparent-struct-ptr.rs | 43 ++++-- tests/codegen/repr/transparent-sysv64.rs | 23 ++- tests/codegen/repr/transparent.rs | 94 +++++++++---- .../riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs | 12 +- .../address-sanitizer-globals-tracking.rs | 2 +- .../cfi/add-canonical-jump-tables-flag.rs | 5 +- .../cfi/add-enable-split-lto-unit-flag.rs | 5 +- .../cfi/emit-type-checks-attr-no-sanitize.rs | 2 +- .../codegen/sanitizer/cfi/emit-type-checks.rs | 2 +- .../emit-type-metadata-attr-cfi-encoding.rs | 34 ++--- ...adata-id-itanium-cxx-abi-const-generics.rs | 11 +- ...tadata-id-itanium-cxx-abi-drop-in-place.rs | 2 +- ...adata-id-itanium-cxx-abi-function-types.rs | 24 ++-- ...e-metadata-id-itanium-cxx-abi-lifetimes.rs | 11 +- ...itanium-cxx-abi-method-secondary-typeid.rs | 3 +- ...tadata-id-itanium-cxx-abi-pointer-types.rs | 32 ++--- ...data-id-itanium-cxx-abi-primitive-types.rs | 122 ++++++++-------- ...-itanium-cxx-abi-repr-transparent-types.rs | 27 ++-- ...adata-id-itanium-cxx-abi-sequence-types.rs | 20 +-- ...metadata-id-itanium-cxx-abi-trait-types.rs | 102 ++++++++------ ...a-id-itanium-cxx-abi-user-defined-types.rs | 28 ++-- ...pe-metadata-itanium-cxx-abi-generalized.rs | 2 +- ...-itanium-cxx-abi-normalized-generalized.rs | 2 +- ...ype-metadata-itanium-cxx-abi-normalized.rs | 2 +- .../cfi/emit-type-metadata-itanium-cxx-abi.rs | 2 +- .../cfi/emit-type-metadata-trait-objects.rs | 14 +- .../sanitizer/cfi/generalize-pointers.rs | 26 ++-- .../sanitizer/cfi/normalize-integers.rs | 26 ++-- .../dataflow-instrument-functions.rs | 5 +- tests/codegen/sanitizer/kcfi/add-kcfi-flag.rs | 13 +- ...it-kcfi-operand-bundle-attr-no-sanitize.rs | 10 +- ...rand-bundle-itanium-cxx-abi-generalized.rs | 10 +- ...-itanium-cxx-abi-normalized-generalized.rs | 10 +- ...erand-bundle-itanium-cxx-abi-normalized.rs | 10 +- ...mit-kcfi-operand-bundle-itanium-cxx-abi.rs | 10 +- .../kcfi/emit-kcfi-operand-bundle.rs | 10 +- .../kcfi/emit-type-metadata-trait-objects.rs | 48 +++---- .../codegen/sanitizer/memory-track-origins.rs | 2 +- .../codegen/sanitizer/no-sanitize-inlining.rs | 2 +- tests/codegen/sanitizer/no-sanitize.rs | 2 +- tests/codegen/set-discriminant-invalid.rs | 18 +-- tests/codegen/simd/issue-120720-reduce-nan.rs | 5 +- tests/codegen/simd/swap-simd-types.rs | 18 +-- tests/codegen/slice-position-bounds-check.rs | 10 +- .../codegen/slice-windows-no-bounds-check.rs | 5 +- .../some-abis-do-extend-params-to-32-bits.rs | 73 +++++++--- tests/codegen/sparc-struct-abi.rs | 19 ++- tests/codegen/split-lto-unit.rs | 5 +- tests/codegen/sroa-fragment-debuginfo.rs | 22 +-- tests/codegen/stack-probes-inline.rs | 4 +- tests/codegen/static-relocation-model-msvc.rs | 4 +- tests/codegen/stores.rs | 24 ++-- tests/codegen/swap-large-types.rs | 32 ++--- tests/codegen/target-feature-overrides.rs | 15 +- tests/codegen/thin-lto.rs | 3 +- tests/codegen/tied-features-strength.rs | 1 - tests/codegen/to_vec.rs | 4 +- tests/codegen/transmute-optimized.rs | 10 +- tests/codegen/try_identity.rs | 6 +- tests/codegen/try_question_mark_nop.rs | 22 +-- tests/codegen/tune-cpu-on-functions.rs | 2 +- tests/codegen/tuple-layout-opt.rs | 26 +++- tests/codegen/union-abi.rs | 93 +++++++++--- tests/codegen/unwind-abis/aapcs-unwind-abi.rs | 10 +- tests/codegen/unwind-abis/c-unwind-abi.rs | 6 +- tests/codegen/unwind-abis/cdecl-unwind-abi.rs | 6 +- .../unwind-abis/fastcall-unwind-abi.rs | 10 +- .../codegen/unwind-abis/stdcall-unwind-abi.rs | 10 +- .../codegen/unwind-abis/system-unwind-abi.rs | 6 +- .../codegen/unwind-abis/sysv64-unwind-abi.rs | 10 +- .../unwind-abis/thiscall-unwind-abi.rs | 10 +- .../unwind-abis/vectorcall-unwind-abi.rs | 10 +- tests/codegen/unwind-abis/win64-unwind-abi.rs | 10 +- tests/codegen/vec-iter-collect-len.rs | 2 +- tests/codegen/vtable-upcast.rs | 6 +- tests/codegen/wasm_exceptions.rs | 26 ++-- tests/codegen/zip.rs | 4 +- tests/codegen/zst-offset.rs | 9 +- 211 files changed, 1445 insertions(+), 1332 deletions(-) diff --git a/rustfmt.toml b/rustfmt.toml index f17c038899cb..24d300e91fa6 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -14,7 +14,7 @@ ignore = [ # - some contain syntax errors that cause rustfmt to give an error # - some UI tests are broken by different formatting # - some require special comments in a particular position (e.g. `EMIT_MIR` comments) - "/tests/codegen/", + "/tests/codegen/simd-intrinsic/", # Many types like `u8x64` are better hand-formatted. "/tests/codegen-units/", "/tests/coverage/", "/tests/coverage-run-rustdoc/", diff --git a/tests/codegen/aarch64-struct-align-128.rs b/tests/codegen/aarch64-struct-align-128.rs index 0a30a2527da6..d1b4132d501f 100644 --- a/tests/codegen/aarch64-struct-align-128.rs +++ b/tests/codegen/aarch64-struct-align-128.rs @@ -12,14 +12,12 @@ #![crate_type = "lib"] #![no_core] -#[lang="sized"] -trait Sized { } -#[lang="freeze"] -trait Freeze { } -#[lang="copy"] -trait Copy { } - - +#[lang = "sized"] +trait Sized {} +#[lang = "freeze"] +trait Freeze {} +#[lang = "copy"] +trait Copy {} // Passed as `[i64 x 2]`, since it's an aggregate with size <= 128 bits, align < 128 bits. #[repr(C)] @@ -31,7 +29,7 @@ pub struct Align8 { // repr(transparent), so same as above. #[repr(transparent)] pub struct Transparent8 { - a: Align8 + a: Align8, } // Passed as `[i64 x 2]`, since it's an aggregate with size <= 128 bits, align < 128 bits. @@ -47,8 +45,6 @@ extern "C" { fn test_8(a: Align8, b: Transparent8, c: Wrapped8); } - - // Passed as `i128`, since it's an aggregate with size <= 128 bits, align = 128 bits. // EXCEPT on Linux, where there's a special case to use its unadjusted alignment, // making it the same as `Align8`, so it's be passed as `[i64 x 2]`. @@ -62,7 +58,7 @@ pub struct Align16 { // repr(transparent), so same as above. #[repr(transparent)] pub struct Transparent16 { - a: Align16 + a: Align16, } // Passed as `i128`, since it's an aggregate with size <= 128 bits, align = 128 bits. @@ -79,8 +75,6 @@ extern "C" { fn test_16(a: Align16, b: Transparent16, c: Wrapped16); } - - // Passed as `i128`, since it's an aggregate with size <= 128 bits, align = 128 bits. #[repr(C)] pub struct I128 { @@ -90,13 +84,13 @@ pub struct I128 { // repr(transparent), so same as above. #[repr(transparent)] pub struct TransparentI128 { - a: I128 + a: I128, } // Passed as `i128`, since it's an aggregate with size <= 128 bits, align = 128 bits. #[repr(C)] pub struct WrappedI128 { - pub a: I128 + pub a: I128, } extern "C" { @@ -106,8 +100,6 @@ extern "C" { fn test_i128(a: I128, b: TransparentI128, c: WrappedI128); } - - // Passed as `[2 x i64]`, since it's an aggregate with size <= 128 bits, align < 128 bits. // Note that the Linux special case does not apply, because packing is not considered "adjustment". #[repr(C)] @@ -119,13 +111,13 @@ pub struct Packed { // repr(transparent), so same as above. #[repr(transparent)] pub struct TransparentPacked { - a: Packed + a: Packed, } // Passed as `[2 x i64]`, since it's an aggregate with size <= 128 bits, align < 128 bits. #[repr(C)] pub struct WrappedPacked { - pub a: Packed + pub a: Packed, } extern "C" { @@ -135,13 +127,19 @@ extern "C" { fn test_packed(a: Packed, b: TransparentPacked, c: WrappedPacked); } - - pub unsafe fn main( - a1: Align8, a2: Transparent8, a3: Wrapped8, - b1: Align16, b2: Transparent16, b3: Wrapped16, - c1: I128, c2: TransparentI128, c3: WrappedI128, - d1: Packed, d2: TransparentPacked, d3: WrappedPacked, + a1: Align8, + a2: Transparent8, + a3: Wrapped8, + b1: Align16, + b2: Transparent16, + b3: Wrapped16, + c1: I128, + c2: TransparentI128, + c3: WrappedI128, + d1: Packed, + d2: TransparentPacked, + d3: WrappedPacked, ) { test_8(a1, a2, a3); test_16(b1, b2, b3); diff --git a/tests/codegen/abi-efiapi.rs b/tests/codegen/abi-efiapi.rs index fa73f649ed87..986d042268aa 100644 --- a/tests/codegen/abi-efiapi.rs +++ b/tests/codegen/abi-efiapi.rs @@ -17,12 +17,12 @@ #![feature(no_core, lang_items)] #![no_core] -#[lang="sized"] -trait Sized { } -#[lang="freeze"] -trait Freeze { } -#[lang="copy"] -trait Copy { } +#[lang = "sized"] +trait Sized {} +#[lang = "freeze"] +trait Freeze {} +#[lang = "copy"] +trait Copy {} //x86_64: define win64cc void @has_efiapi //i686: define void @has_efiapi diff --git a/tests/codegen/abi-main-signature-16bit-c-int.rs b/tests/codegen/abi-main-signature-16bit-c-int.rs index 9832088ab338..d44b80475e47 100644 --- a/tests/codegen/abi-main-signature-16bit-c-int.rs +++ b/tests/codegen/abi-main-signature-16bit-c-int.rs @@ -6,8 +6,6 @@ //@[avr] only-avr //@[msp] only-msp430 - -fn main() { -} +fn main() {} // CHECK: define i16 @main(i16, i8**) diff --git a/tests/codegen/abi-main-signature-32bit-c-int.rs b/tests/codegen/abi-main-signature-32bit-c-int.rs index 7684024a2e38..ce475adde44c 100644 --- a/tests/codegen/abi-main-signature-32bit-c-int.rs +++ b/tests/codegen/abi-main-signature-32bit-c-int.rs @@ -6,7 +6,6 @@ //@ ignore-avr //@ ignore-wasi wasi codegens the main symbol differently -fn main() { -} +fn main() {} // CHECK: define{{( hidden| noundef)*}} i32 @main(i32{{( %0)?}}, ptr{{( %1)?}}) diff --git a/tests/codegen/abi-repr-ext.rs b/tests/codegen/abi-repr-ext.rs index 2e100a372355..a42f73566961 100644 --- a/tests/codegen/abi-repr-ext.rs +++ b/tests/codegen/abi-repr-ext.rs @@ -24,14 +24,17 @@ #![no_std] #![no_core] -#[lang="sized"] trait Sized { } -#[lang="freeze"] trait Freeze { } -#[lang="copy"] trait Copy { } +#[lang = "sized"] +trait Sized {} +#[lang = "freeze"] +trait Freeze {} +#[lang = "copy"] +trait Copy {} #[repr(i8)] pub enum Type { Type1 = 0, - Type2 = 1 + Type2 = 1, } // To accommodate rust#97800, one might consider writing the below as: @@ -50,7 +53,6 @@ pub enum Type { // riscv-SAME: signext // CHECK-SAME: i8 @test() - #[no_mangle] pub extern "C" fn test() -> Type { Type::Type1 diff --git a/tests/codegen/abi-x86_64_sysv.rs b/tests/codegen/abi-x86_64_sysv.rs index 659c1d93e208..09909f994d65 100644 --- a/tests/codegen/abi-x86_64_sysv.rs +++ b/tests/codegen/abi-x86_64_sysv.rs @@ -5,25 +5,25 @@ #![crate_type = "lib"] pub struct S24 { - a: i8, - b: i8, - c: i8, + a: i8, + b: i8, + c: i8, } pub struct S48 { - a: i16, - b: i16, - c: i8, + a: i16, + b: i16, + c: i8, } // CHECK: i24 @struct_24_bits(i24 #[no_mangle] pub extern "sysv64" fn struct_24_bits(a: S24) -> S24 { - a + a } // CHECK: i48 @struct_48_bits(i48 #[no_mangle] pub extern "sysv64" fn struct_48_bits(a: S48) -> S48 { - a + a } diff --git a/tests/codegen/adjustments.rs b/tests/codegen/adjustments.rs index 549a9737eb15..7f7831def083 100644 --- a/tests/codegen/adjustments.rs +++ b/tests/codegen/adjustments.rs @@ -5,17 +5,16 @@ // Hack to get the correct size for the length part in slices // CHECK: @helper([[USIZE:i[0-9]+]] %_1) #[no_mangle] -pub fn helper(_: usize) { -} +pub fn helper(_: usize) {} // CHECK-LABEL: @no_op_slice_adjustment #[no_mangle] pub fn no_op_slice_adjustment(x: &[u8]) -> &[u8] { // We used to generate an extra alloca and memcpy for the block's trailing expression value, so // check that we copy directly to the return value slot -// CHECK: %0 = insertvalue { ptr, [[USIZE]] } poison, ptr %x.0, 0 -// CHECK: %1 = insertvalue { ptr, [[USIZE]] } %0, [[USIZE]] %x.1, 1 -// CHECK: ret { ptr, [[USIZE]] } %1 + // CHECK: %0 = insertvalue { ptr, [[USIZE]] } poison, ptr %x.0, 0 + // CHECK: %1 = insertvalue { ptr, [[USIZE]] } %0, [[USIZE]] %x.1, 1 + // CHECK: ret { ptr, [[USIZE]] } %1 { x } } @@ -24,6 +23,6 @@ pub fn no_op_slice_adjustment(x: &[u8]) -> &[u8] { pub fn no_op_slice_adjustment2(x: &[u8]) -> &[u8] { // We used to generate an extra alloca and memcpy for the function's return value, so check // that there's no memcpy (the slice is written to sret_slot element-wise) -// CHECK-NOT: call void @llvm.memcpy. + // CHECK-NOT: call void @llvm.memcpy. no_op_slice_adjustment(x) } diff --git a/tests/codegen/align-byval.rs b/tests/codegen/align-byval.rs index 3a2be2b2b9c3..223696229cb1 100644 --- a/tests/codegen/align-byval.rs +++ b/tests/codegen/align-byval.rs @@ -23,9 +23,12 @@ #![no_std] #![no_core] -#[lang="sized"] trait Sized { } -#[lang="freeze"] trait Freeze { } -#[lang="copy"] trait Copy { } +#[lang = "sized"] +trait Sized {} +#[lang = "freeze"] +trait Freeze {} +#[lang = "copy"] +trait Copy {} impl Copy for i32 {} impl Copy for i64 {} @@ -58,7 +61,7 @@ pub struct ForceAlign4 { pub struct NaturalAlign8 { a: i64, b: i64, - c: i64 + c: i64, } // On i686-windows, this is passed by reference (because alignment is >4 and requested/forced), @@ -68,7 +71,7 @@ pub struct NaturalAlign8 { pub struct ForceAlign8 { a: i64, b: i64, - c: i64 + c: i64, } // On i686-windows, this is passed on stack, because requested alignment is <=4. @@ -77,28 +80,28 @@ pub struct ForceAlign8 { pub struct LowerFA8 { a: i64, b: i64, - c: i64 + c: i64, } // On i686-windows, this is passed by reference, because it contains a field with // requested/forced alignment. #[repr(C)] pub struct WrappedFA8 { - a: ForceAlign8 + a: ForceAlign8, } // On i686-windows, this has the same ABI as ForceAlign8, i.e. passed by reference. #[repr(transparent)] pub struct TransparentFA8 { _0: (), - a: ForceAlign8 + a: ForceAlign8, } #[repr(C)] #[repr(align(16))] pub struct ForceAlign16 { a: [i32; 16], - b: i8 + b: i8, } // CHECK-LABEL: @call_na1 diff --git a/tests/codegen/align-enum.rs b/tests/codegen/align-enum.rs index 93d5a87fb309..e8dd95d3afb0 100644 --- a/tests/codegen/align-enum.rs +++ b/tests/codegen/align-enum.rs @@ -18,8 +18,8 @@ pub struct Nested64 { // CHECK-LABEL: @align64 #[no_mangle] pub fn align64(a: u32) -> Align64 { -// CHECK: %a64 = alloca [64 x i8], align 64 -// CHECK: call void @llvm.memcpy.{{.*}}(ptr align 64 %{{.*}}, ptr align 64 %{{.*}}, i{{[0-9]+}} 64, i1 false) + // CHECK: %a64 = alloca [64 x i8], align 64 + // CHECK: call void @llvm.memcpy.{{.*}}(ptr align 64 %{{.*}}, ptr align 64 %{{.*}}, i{{[0-9]+}} 64, i1 false) let a64 = Align64::A(a); a64 } @@ -27,7 +27,7 @@ pub fn align64(a: u32) -> Align64 { // CHECK-LABEL: @nested64 #[no_mangle] pub fn nested64(a: u8, b: u32, c: u16) -> Nested64 { -// CHECK: %n64 = alloca [128 x i8], align 64 + // CHECK: %n64 = alloca [128 x i8], align 64 let n64 = Nested64 { a, b: Align64::B(b), c }; n64 } diff --git a/tests/codegen/align-offset.rs b/tests/codegen/align-offset.rs index 15b11f413cb5..aeac230f718f 100644 --- a/tests/codegen/align-offset.rs +++ b/tests/codegen/align-offset.rs @@ -53,7 +53,6 @@ pub fn align_offset_word_slice(slice: &[Align4]) -> usize { slice.as_ptr().align_offset(32) } - // CHECK-LABEL: @align_offset_word_ptr(ptr{{.+}}%ptr #[no_mangle] pub fn align_offset_word_ptr(ptr: *const Align4) -> usize { diff --git a/tests/codegen/align-struct.rs b/tests/codegen/align-struct.rs index e70b42b47db8..cc65b08a9223 100644 --- a/tests/codegen/align-struct.rs +++ b/tests/codegen/align-struct.rs @@ -25,9 +25,9 @@ pub enum Enum64 { // CHECK-LABEL: @align64 #[no_mangle] -pub fn align64(i : i32) -> Align64 { -// CHECK: %a64 = alloca [64 x i8], align 64 -// CHECK: call void @llvm.memcpy.{{.*}}(ptr align 64 %{{.*}}, ptr align 64 %{{.*}}, i{{[0-9]+}} 64, i1 false) +pub fn align64(i: i32) -> Align64 { + // CHECK: %a64 = alloca [64 x i8], align 64 + // CHECK: call void @llvm.memcpy.{{.*}}(ptr align 64 %{{.*}}, ptr align 64 %{{.*}}, i{{[0-9]+}} 64, i1 false) let a64 = Align64(i); a64 } @@ -37,14 +37,14 @@ pub fn align64(i : i32) -> Align64 { // CHECK-LABEL: @align64_load #[no_mangle] pub fn align64_load(a: Align64) -> i32 { -// CHECK: {{%.*}} = load i32, ptr {{%.*}}, align 64 + // CHECK: {{%.*}} = load i32, ptr {{%.*}}, align 64 a.0 } // CHECK-LABEL: @nested64 #[no_mangle] pub fn nested64(a: Align64, b: i32, c: i32, d: i8) -> Nested64 { -// CHECK: %n64 = alloca [128 x i8], align 64 + // CHECK: %n64 = alloca [128 x i8], align 64 let n64 = Nested64 { a, b, c, d }; n64 } @@ -52,7 +52,7 @@ pub fn nested64(a: Align64, b: i32, c: i32, d: i8) -> Nested64 { // CHECK-LABEL: @enum4 #[no_mangle] pub fn enum4(a: i32) -> Enum4 { -// CHECK: %e4 = alloca [8 x i8], align 4 + // CHECK: %e4 = alloca [8 x i8], align 4 let e4 = Enum4::A(a); e4 } @@ -60,7 +60,7 @@ pub fn enum4(a: i32) -> Enum4 { // CHECK-LABEL: @enum64 #[no_mangle] pub fn enum64(a: Align64) -> Enum64 { -// CHECK: %e64 = alloca [128 x i8], align 64 + // CHECK: %e64 = alloca [128 x i8], align 64 let e64 = Enum64::A(a); e64 } diff --git a/tests/codegen/array-cmp.rs b/tests/codegen/array-cmp.rs index 194c0adf1d2e..2565a385b61b 100644 --- a/tests/codegen/array-cmp.rs +++ b/tests/codegen/array-cmp.rs @@ -10,9 +10,10 @@ #[no_mangle] pub fn compare() -> bool { let bytes = 12.5f32.to_ne_bytes(); - bytes == if cfg!(target_endian = "big") { - [0x41, 0x48, 0x00, 0x00] - } else { - [0x00, 0x00, 0x48, 0x41] - } + bytes + == if cfg!(target_endian = "big") { + [0x41, 0x48, 0x00, 0x00] + } else { + [0x00, 0x00, 0x48, 0x41] + } } diff --git a/tests/codegen/asm-maybe-uninit.rs b/tests/codegen/asm-maybe-uninit.rs index f9bf280b3846..55813c35a468 100644 --- a/tests/codegen/asm-maybe-uninit.rs +++ b/tests/codegen/asm-maybe-uninit.rs @@ -4,8 +4,8 @@ #![crate_type = "rlib"] #![allow(asm_sub_register)] -use std::mem::MaybeUninit; use std::arch::asm; +use std::mem::MaybeUninit; // CHECK-LABEL: @int #[no_mangle] diff --git a/tests/codegen/asm-sanitize-llvm.rs b/tests/codegen/asm-sanitize-llvm.rs index 8638ed2236ac..fb332f9a0f3e 100644 --- a/tests/codegen/asm-sanitize-llvm.rs +++ b/tests/codegen/asm-sanitize-llvm.rs @@ -21,14 +21,10 @@ trait Copy {} pub unsafe fn we_escape_dollar_signs() { // CHECK: call void asm sideeffect alignstack inteldialect "banana$$:" - asm!( - r"banana$:", - ) + asm!(r"banana$:",) } pub unsafe fn we_escape_escapes_too() { // CHECK: call void asm sideeffect alignstack inteldialect "banana\{{(\\|5C)}}36:" - asm!( - r"banana\36:", - ) + asm!(r"banana\36:",) } diff --git a/tests/codegen/atomicptr.rs b/tests/codegen/atomicptr.rs index cbbd56155123..ea8b382c8fcc 100644 --- a/tests/codegen/atomicptr.rs +++ b/tests/codegen/atomicptr.rs @@ -6,13 +6,12 @@ //@ compile-flags: -O -Cno-prepopulate-passes #![crate_type = "lib"] - #![feature(strict_provenance)] #![feature(strict_provenance_atomic_ptr)] +use std::ptr::without_provenance_mut; use std::sync::atomic::AtomicPtr; use std::sync::atomic::Ordering::Relaxed; -use std::ptr::without_provenance_mut; // Portability hack so that we can say [[USIZE]] instead of i64/i32/i16 for usize. // CHECK: @helper([[USIZE:i[0-9]+]] noundef %_1) diff --git a/tests/codegen/autovectorize-f32x4.rs b/tests/codegen/autovectorize-f32x4.rs index 90c9f3691045..254362842f91 100644 --- a/tests/codegen/autovectorize-f32x4.rs +++ b/tests/codegen/autovectorize-f32x4.rs @@ -5,25 +5,20 @@ // CHECK-LABEL: @auto_vectorize_direct #[no_mangle] pub fn auto_vectorize_direct(a: [f32; 4], b: [f32; 4]) -> [f32; 4] { -// CHECK: load <4 x float> -// CHECK: load <4 x float> -// CHECK: fadd <4 x float> -// CHECK: store <4 x float> - [ - a[0] + b[0], - a[1] + b[1], - a[2] + b[2], - a[3] + b[3], - ] + // CHECK: load <4 x float> + // CHECK: load <4 x float> + // CHECK: fadd <4 x float> + // CHECK: store <4 x float> + [a[0] + b[0], a[1] + b[1], a[2] + b[2], a[3] + b[3]] } // CHECK-LABEL: @auto_vectorize_loop #[no_mangle] pub fn auto_vectorize_loop(a: [f32; 4], b: [f32; 4]) -> [f32; 4] { -// CHECK: load <4 x float> -// CHECK: load <4 x float> -// CHECK: fadd <4 x float> -// CHECK: store <4 x float> + // CHECK: load <4 x float> + // CHECK: load <4 x float> + // CHECK: fadd <4 x float> + // CHECK: store <4 x float> let mut c = [0.0; 4]; for i in 0..4 { c[i] = a[i] + b[i]; @@ -34,9 +29,9 @@ pub fn auto_vectorize_loop(a: [f32; 4], b: [f32; 4]) -> [f32; 4] { // CHECK-LABEL: @auto_vectorize_array_from_fn #[no_mangle] pub fn auto_vectorize_array_from_fn(a: [f32; 4], b: [f32; 4]) -> [f32; 4] { -// CHECK: load <4 x float> -// CHECK: load <4 x float> -// CHECK: fadd <4 x float> -// CHECK: store <4 x float> + // CHECK: load <4 x float> + // CHECK: load <4 x float> + // CHECK: fadd <4 x float> + // CHECK: store <4 x float> std::array::from_fn(|i| a[i] + b[i]) } diff --git a/tests/codegen/auxiliary/extern_decl.rs b/tests/codegen/auxiliary/extern_decl.rs index edc48351869a..d17e77b14448 100644 --- a/tests/codegen/auxiliary/extern_decl.rs +++ b/tests/codegen/auxiliary/extern_decl.rs @@ -5,7 +5,9 @@ #![crate_type = "lib"] #[no_mangle] -pub fn extern_fn() -> u8 { unsafe { extern_static } } +pub fn extern_fn() -> u8 { + unsafe { extern_static } +} #[no_mangle] pub static mut extern_static: u8 = 71; diff --git a/tests/codegen/auxiliary/nounwind.rs b/tests/codegen/auxiliary/nounwind.rs index 73c5aee33878..40f66442c6ed 100644 --- a/tests/codegen/auxiliary/nounwind.rs +++ b/tests/codegen/auxiliary/nounwind.rs @@ -1,3 +1,2 @@ #[no_mangle] -pub fn bar() { -} +pub fn bar() {} diff --git a/tests/codegen/avr/avr-func-addrspace.rs b/tests/codegen/avr/avr-func-addrspace.rs index fb53abecfdb2..2d9efb52c7cf 100644 --- a/tests/codegen/avr/avr-func-addrspace.rs +++ b/tests/codegen/avr/avr-func-addrspace.rs @@ -14,15 +14,18 @@ #![no_core] #[lang = "sized"] -pub trait Sized { } +pub trait Sized {} #[lang = "copy"] -pub trait Copy { } +pub trait Copy {} #[lang = "receiver"] -pub trait Receiver { } +pub trait Receiver {} #[lang = "tuple_trait"] -pub trait Tuple { } +pub trait Tuple {} -pub struct Result { _a: T, _b: E } +pub struct Result { + _a: T, + _b: E, +} impl Copy for usize {} impl Copy for &usize {} @@ -39,7 +42,7 @@ pub trait FnOnce { } #[lang = "fn_mut"] -pub trait FnMut : FnOnce { +pub trait FnMut: FnOnce { extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; } @@ -64,7 +67,7 @@ fn arbitrary_black_box(ptr: &usize, _: &mut u32) -> Result<(), ()> { #[inline(never)] #[no_mangle] -fn call_through_fn_trait(a: &mut impl Fn<(), Output=()>) { +fn call_through_fn_trait(a: &mut impl Fn<(), Output = ()>) { (*a)() } @@ -110,7 +113,10 @@ pub unsafe fn transmute_fn_ptr_to_data(x: fn()) -> *const () { transmute(x) } -pub enum Either { A(T), B(U) } +pub enum Either { + A(T), + B(U), +} // Previously, we would codegen this as passing/returning a scalar pair of `{ i8, ptr }`, // with the `ptr` field representing both `&i32` and `fn()` depending on the variant. diff --git a/tests/codegen/binary-search-index-no-bound-check.rs b/tests/codegen/binary-search-index-no-bound-check.rs index 96f6bb54b3fe..a213c015a40b 100644 --- a/tests/codegen/binary-search-index-no-bound-check.rs +++ b/tests/codegen/binary-search-index-no-bound-check.rs @@ -11,11 +11,7 @@ pub fn binary_search_index_no_bounds_check(s: &[u8]) -> u8 { // CHECK-NOT: slice_start_index_len_fail // CHECK-NOT: slice_end_index_len_fail // CHECK-NOT: panic_bounds_check - if let Ok(idx) = s.binary_search(&b'\\') { - s[idx] - } else { - 42 - } + if let Ok(idx) = s.binary_search(&b'\\') { s[idx] } else { 42 } } // Similarly, check that `partition_point` is known to return a valid fencepost. diff --git a/tests/codegen/bool-cmp.rs b/tests/codegen/bool-cmp.rs index 29ee3e0627bc..71d3411689f4 100644 --- a/tests/codegen/bool-cmp.rs +++ b/tests/codegen/bool-cmp.rs @@ -10,9 +10,9 @@ use std::cmp::Ordering; // CHECK-LABEL: @cmp_bool #[no_mangle] pub fn cmp_bool(a: bool, b: bool) -> Ordering { -// LLVM 10 produces (zext a) + (sext b), but the final lowering is (zext a) - (zext b). -// CHECK: zext i1 -// CHECK: {{z|s}}ext i1 -// CHECK: {{sub|add}} nsw + // LLVM 10 produces (zext a) + (sext b), but the final lowering is (zext a) - (zext b). + // CHECK: zext i1 + // CHECK: {{z|s}}ext i1 + // CHECK: {{sub|add}} nsw a.cmp(&b) } diff --git a/tests/codegen/branch-protection.rs b/tests/codegen/branch-protection.rs index 0961b1b9f522..a29ec67d578b 100644 --- a/tests/codegen/branch-protection.rs +++ b/tests/codegen/branch-protection.rs @@ -12,12 +12,11 @@ #![feature(no_core, lang_items)] #![no_core] -#[lang="sized"] -trait Sized { } +#[lang = "sized"] +trait Sized {} // A basic test function. -pub fn test() { -} +pub fn test() {} // BTI: !"branch-target-enforcement", i32 1 // BTI: !"sign-return-address", i32 0 diff --git a/tests/codegen/cast-target-abi.rs b/tests/codegen/cast-target-abi.rs index 9c31acc9bb7c..c6a8b7bbf378 100644 --- a/tests/codegen/cast-target-abi.rs +++ b/tests/codegen/cast-target-abi.rs @@ -18,9 +18,12 @@ #![no_std] #![no_core] -#[lang="sized"] trait Sized { } -#[lang="freeze"] trait Freeze { } -#[lang="copy"] trait Copy { } +#[lang = "sized"] +trait Sized {} +#[lang = "freeze"] +trait Freeze {} +#[lang = "copy"] +trait Copy {} // This struct will be passed as a single `i64` or `i32`. // This may be (if `i64)) larger than the Rust layout, which is just `{ i16, i16 }`. @@ -104,7 +107,6 @@ pub unsafe fn return_twou16s() -> TwoU16s { // powerpc64: [[RETVAL:%.+]] = alloca [4 x i8], align 2 // powerpc64: call void @returns_twou16s(ptr {{.+}} [[RETVAL]]) - // The other targets copy the cast ABI type to an alloca. // aarch64: [[ABI_ALLOCA:%.+]] = alloca [8 x i8], align [[ABI_ALIGN:8]] @@ -151,7 +153,6 @@ pub unsafe fn return_fiveu16s() -> FiveU16s { // powerpc64: call void @returns_fiveu16s(ptr {{.+}} [[RET_PTR]]) - // The other targets copy the cast ABI type to the sret pointer. // aarch64: [[ABI_ALLOCA:%.+]] = alloca [16 x i8], align [[ABI_ALIGN:8]] @@ -199,7 +200,6 @@ pub unsafe fn return_doubledouble() -> DoubleDouble { // powerpc64: [[RETVAL:%.+]] = alloca [16 x i8], align 8 // powerpc64: call void @returns_doubledouble(ptr {{.+}} [[RETVAL]]) - // The other targets copy the cast ABI type to an alloca. // aarch64: [[ABI_ALLOCA:%.+]] = alloca [16 x i8], align [[ABI_ALIGN:8]] @@ -266,7 +266,6 @@ pub unsafe fn return_doublefloat() -> DoubleFloat { // powerpc64: [[RETVAL:%.+]] = alloca [16 x i8], align 8 // powerpc64: call void @returns_doublefloat(ptr {{.+}} [[RETVAL]]) - // The other targets copy the cast ABI type to an alloca. // aarch64: [[ABI_ALLOCA:%.+]] = alloca [16 x i8], align [[ABI_ALIGN:8]] diff --git a/tests/codegen/cf-protection.rs b/tests/codegen/cf-protection.rs index 5120bbf114d9..244d1eb25442 100644 --- a/tests/codegen/cf-protection.rs +++ b/tests/codegen/cf-protection.rs @@ -13,12 +13,11 @@ #![feature(no_core, lang_items)] #![no_core] -#[lang="sized"] -trait Sized { } +#[lang = "sized"] +trait Sized {} // A basic test function. -pub fn test() { -} +pub fn test() {} // undefined-NOT: !"cf-protection-branch" // undefined-NOT: !"cf-protection-return" diff --git a/tests/codegen/cffi/ffi-const.rs b/tests/codegen/cffi/ffi-const.rs index 8044ad105d5d..564b8f7f8d8d 100644 --- a/tests/codegen/cffi/ffi-const.rs +++ b/tests/codegen/cffi/ffi-const.rs @@ -2,12 +2,15 @@ #![crate_type = "lib"] #![feature(ffi_const)] -pub fn bar() { unsafe { foo() } } +pub fn bar() { + unsafe { foo() } +} extern "C" { // CHECK-LABEL: declare{{.*}}void @foo() // CHECK-SAME: [[ATTRS:#[0-9]+]] // The attribute changed from `readnone` to `memory(none)` with LLVM 16.0. // CHECK-DAG: attributes [[ATTRS]] = { {{.*}}{{readnone|memory\(none\)}}{{.*}} } - #[ffi_const] pub fn foo(); + #[ffi_const] + pub fn foo(); } diff --git a/tests/codegen/cffi/ffi-out-of-bounds-loads.rs b/tests/codegen/cffi/ffi-out-of-bounds-loads.rs index 35bf00f8f3c3..614d5d94f620 100644 --- a/tests/codegen/cffi/ffi-out-of-bounds-loads.rs +++ b/tests/codegen/cffi/ffi-out-of-bounds-loads.rs @@ -13,9 +13,12 @@ #![no_std] #![no_core] -#[lang="sized"] trait Sized { } -#[lang="freeze"] trait Freeze { } -#[lang="copy"] trait Copy { } +#[lang = "sized"] +trait Sized {} +#[lang = "freeze"] +trait Freeze {} +#[lang = "copy"] +trait Copy {} #[repr(C)] struct S { diff --git a/tests/codegen/cffi/ffi-pure.rs b/tests/codegen/cffi/ffi-pure.rs index 51135fd37535..601509d5c90f 100644 --- a/tests/codegen/cffi/ffi-pure.rs +++ b/tests/codegen/cffi/ffi-pure.rs @@ -2,12 +2,15 @@ #![crate_type = "lib"] #![feature(ffi_pure)] -pub fn bar() { unsafe { foo() } } +pub fn bar() { + unsafe { foo() } +} extern "C" { // CHECK-LABEL: declare{{.*}}void @foo() // CHECK-SAME: [[ATTRS:#[0-9]+]] // The attribute changed from `readonly` to `memory(read)` with LLVM 16.0. // CHECK-DAG: attributes [[ATTRS]] = { {{.*}}{{readonly|memory\(read\)}}{{.*}} } - #[ffi_pure] pub fn foo(); + #[ffi_pure] + pub fn foo(); } diff --git a/tests/codegen/cfguard-checks.rs b/tests/codegen/cfguard-checks.rs index 2b09a5fe12c2..cdf6406ad61b 100644 --- a/tests/codegen/cfguard-checks.rs +++ b/tests/codegen/cfguard-checks.rs @@ -4,8 +4,7 @@ #![crate_type = "lib"] // A basic test function. -pub fn test() { -} +pub fn test() {} // Ensure the module flag cfguard=2 is present // CHECK: !"cfguard", i32 2 diff --git a/tests/codegen/cfguard-disabled.rs b/tests/codegen/cfguard-disabled.rs index 105e02072615..90915c0f0c6b 100644 --- a/tests/codegen/cfguard-disabled.rs +++ b/tests/codegen/cfguard-disabled.rs @@ -4,8 +4,7 @@ #![crate_type = "lib"] // A basic test function. -pub fn test() { -} +pub fn test() {} // Ensure the module flag cfguard is not present // CHECK-NOT: !"cfguard" diff --git a/tests/codegen/cfguard-nochecks.rs b/tests/codegen/cfguard-nochecks.rs index 0443880d72da..5f386533ec1a 100644 --- a/tests/codegen/cfguard-nochecks.rs +++ b/tests/codegen/cfguard-nochecks.rs @@ -4,8 +4,7 @@ #![crate_type = "lib"] // A basic test function. -pub fn test() { -} +pub fn test() {} // Ensure the module flag cfguard=1 is present // CHECK: !"cfguard", i32 1 diff --git a/tests/codegen/cfguard-non-msvc.rs b/tests/codegen/cfguard-non-msvc.rs index 5d266de8a94d..1e6559aaf5d2 100644 --- a/tests/codegen/cfguard-non-msvc.rs +++ b/tests/codegen/cfguard-non-msvc.rs @@ -4,8 +4,7 @@ #![crate_type = "lib"] // A basic test function. -pub fn test() { -} +pub fn test() {} // Ensure the cfguard module flag is not added for non-MSVC targets. // CHECK-NOT: !"cfguard" diff --git a/tests/codegen/coercions.rs b/tests/codegen/coercions.rs index a205e541df10..63c1742c6399 100644 --- a/tests/codegen/coercions.rs +++ b/tests/codegen/coercions.rs @@ -7,7 +7,7 @@ static X: i32 = 5; // CHECK-LABEL: @raw_ptr_to_raw_ptr_noop // CHECK-NOT: alloca #[no_mangle] -pub fn raw_ptr_to_raw_ptr_noop() -> *const i32{ +pub fn raw_ptr_to_raw_ptr_noop() -> *const i32 { &X as *const i32 } diff --git a/tests/codegen/constant-branch.rs b/tests/codegen/constant-branch.rs index 3328b1eb4a88..a2710cc4b258 100644 --- a/tests/codegen/constant-branch.rs +++ b/tests/codegen/constant-branch.rs @@ -8,18 +8,10 @@ #[no_mangle] pub fn if_bool() { // CHECK: br label %{{.+}} - _ = if true { - 0 - } else { - 1 - }; + _ = if true { 0 } else { 1 }; // CHECK: br label %{{.+}} - _ = if false { - 0 - } else { - 1 - }; + _ = if false { 0 } else { 1 }; } // CHECK-LABEL: @if_constant_int_eq @@ -27,18 +19,10 @@ pub fn if_bool() { pub fn if_constant_int_eq() { let val = 0; // CHECK: br label %{{.+}} - _ = if val == 0 { - 0 - } else { - 1 - }; + _ = if val == 0 { 0 } else { 1 }; // CHECK: br label %{{.+}} - _ = if val == 1 { - 0 - } else { - 1 - }; + _ = if val == 1 { 0 } else { 1 }; } // CHECK-LABEL: @if_constant_match @@ -48,19 +32,19 @@ pub fn if_constant_match() { _ = match 1 { 1 => 2, 2 => 3, - _ => 4 + _ => 4, }; // CHECK: br label %{{.+}} _ = match 1 { 2 => 3, - _ => 4 + _ => 4, }; // CHECK: br label %[[MINUS1:.+]] _ = match -1 { - // CHECK: [[MINUS1]]: - // CHECK: store i32 1 + // CHECK: [[MINUS1]]: + // CHECK: store i32 1 -1 => 1, _ => 0, } diff --git a/tests/codegen/coroutine-debug-msvc.rs b/tests/codegen/coroutine-debug-msvc.rs index e2296db1d594..9e2ec3ea28ac 100644 --- a/tests/codegen/coroutine-debug-msvc.rs +++ b/tests/codegen/coroutine-debug-msvc.rs @@ -11,7 +11,8 @@ use std::ops::Coroutine; fn coroutine_test() -> impl Coroutine { - #[coroutine] || { + #[coroutine] + || { yield 0; let s = String::from("foo"); yield 1; @@ -23,23 +24,23 @@ fn coroutine_test() -> impl Coroutine { // CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "enum2$" // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant0", scope: [[GEN]], // For brevity, we only check the struct name and members of the last variant. -// CHECK-SAME: file: [[FILE:![0-9]*]], line: 14, +// CHECK-SAME: file: [[FILE:![0-9]*]], line: 15, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant1", scope: [[GEN]], -// CHECK-SAME: file: [[FILE]], line: 18, +// CHECK-SAME: file: [[FILE]], line: 19, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant2", scope: [[GEN]], -// CHECK-SAME: file: [[FILE]], line: 18, +// CHECK-SAME: file: [[FILE]], line: 19, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant3", scope: [[GEN]], -// CHECK-SAME: file: [[FILE]], line: 15, +// CHECK-SAME: file: [[FILE]], line: 16, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant4", scope: [[GEN]], -// CHECK-SAME: file: [[FILE]], line: 17, +// CHECK-SAME: file: [[FILE]], line: 18, // CHECK-SAME: baseType: [[VARIANT_WRAPPER:![0-9]*]] // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) diff --git a/tests/codegen/coroutine-debug.rs b/tests/codegen/coroutine-debug.rs index 914515f58b85..d00667a37d5e 100644 --- a/tests/codegen/coroutine-debug.rs +++ b/tests/codegen/coroutine-debug.rs @@ -11,7 +11,8 @@ use std::ops::Coroutine; fn coroutine_test() -> impl Coroutine { - #[coroutine] || { + #[coroutine] + || { yield 0; let s = String::from("foo"); yield 1; @@ -26,26 +27,26 @@ fn coroutine_test() -> impl Coroutine { // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: discriminator: [[DISC:![0-9]*]] // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "0", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE:![0-9]*]], line: 14, +// CHECK-SAME: file: [[FILE:![0-9]*]], line: 15, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DICompositeType(tag: DW_TAG_structure_type, name: "Unresumed", scope: [[GEN]], // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "1", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE]], line: 18, +// CHECK-SAME: file: [[FILE]], line: 19, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "2", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE]], line: 18, +// CHECK-SAME: file: [[FILE]], line: 19, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "3", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE]], line: 15, +// CHECK-SAME: file: [[FILE]], line: 16, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "4", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE]], line: 17, +// CHECK-SAME: file: [[FILE]], line: 18, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN]], diff --git a/tests/codegen/dealloc-no-unwind.rs b/tests/codegen/dealloc-no-unwind.rs index 667f6fea1857..ead26da610e2 100644 --- a/tests/codegen/dealloc-no-unwind.rs +++ b/tests/codegen/dealloc-no-unwind.rs @@ -1,13 +1,17 @@ //@ compile-flags: -O -#![crate_type="lib"] +#![crate_type = "lib"] struct A; impl Drop for A { fn drop(&mut self) { - extern "C" { fn foo(); } - unsafe { foo(); } + extern "C" { + fn foo(); + } + unsafe { + foo(); + } } } diff --git a/tests/codegen/debug-column.rs b/tests/codegen/debug-column.rs index ff25fbe1b132..d14a5c29142e 100644 --- a/tests/codegen/debug-column.rs +++ b/tests/codegen/debug-column.rs @@ -3,6 +3,7 @@ //@ ignore-windows //@ compile-flags: -C debuginfo=2 +#[rustfmt::skip] fn main() { unsafe { // Column numbers are 1-based. Regression test for #65437. @@ -13,8 +14,8 @@ fn main() { // CHECK: call void @turtle(){{( #[0-9]+)?}}, !dbg [[B:!.*]] /* ż */ turtle(); - // CHECK: [[A]] = !DILocation(line: 10, column: 9, - // CHECK: [[B]] = !DILocation(line: 14, column: 10, + // CHECK: [[A]] = !DILocation(line: 11, column: 9, + // CHECK: [[B]] = !DILocation(line: 15, column: 10, } } diff --git a/tests/codegen/debug-compile-unit-path.rs b/tests/codegen/debug-compile-unit-path.rs index 4be418d66103..6131d9d7351a 100644 --- a/tests/codegen/debug-compile-unit-path.rs +++ b/tests/codegen/debug-compile-unit-path.rs @@ -3,7 +3,7 @@ // // Ensure that we remap the compile unit directory and that we set it to the compilers current // working directory and not something else. -#![crate_type="rlib"] +#![crate_type = "rlib"] // CHECK-DAG: [[FILE:![0-9]*]] = !DIFile(filename: "/base/debug-compile-unit-path.rs{{.*}}", directory: "/cwd/") // CHECK-DAG: {{![0-9]*}} = distinct !DICompileUnit({{.*}}file: [[FILE]] diff --git a/tests/codegen/debuginfo-generic-closure-env-names.rs b/tests/codegen/debuginfo-generic-closure-env-names.rs index 04ff7fff4399..6d56fbc40abe 100644 --- a/tests/codegen/debuginfo-generic-closure-env-names.rs +++ b/tests/codegen/debuginfo-generic-closure-env-names.rs @@ -46,7 +46,6 @@ // NONMSVC-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}", scope: ![[function_containing_closure_NAMESPACE]] // MSVC-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "closure_env$0", scope: ![[function_containing_closure_NAMESPACE]] - #![crate_type = "lib"] use std::future::Future; @@ -70,11 +69,9 @@ async fn generic_async_function(x: T) -> T { x } -fn generic_async_block(x: T) -> impl Future { +fn generic_async_block(x: T) -> impl Future { static _X: u8 = 0; // Same as above - async move { - x - } + async move { x } } pub fn instantiate_generics() { diff --git a/tests/codegen/dllimports/auxiliary/wrapper.rs b/tests/codegen/dllimports/auxiliary/wrapper.rs index 7d1f6ab70d5f..00a29f7ee7e5 100644 --- a/tests/codegen/dllimports/auxiliary/wrapper.rs +++ b/tests/codegen/dllimports/auxiliary/wrapper.rs @@ -1,13 +1,13 @@ //@ no-prefer-dynamic #![crate_type = "rlib"] -#[link(name = "dummy", kind="dylib")] +#[link(name = "dummy", kind = "dylib")] extern "C" { pub fn dylib_func2(x: i32) -> i32; pub static dylib_global2: i32; } -#[link(name = "dummy", kind="static")] +#[link(name = "dummy", kind = "static")] extern "C" { pub fn static_func2(x: i32) -> i32; pub static static_global2: i32; diff --git a/tests/codegen/dllimports/main.rs b/tests/codegen/dllimports/main.rs index c1626853b16d..93d350a22380 100644 --- a/tests/codegen/dllimports/main.rs +++ b/tests/codegen/dllimports/main.rs @@ -1,4 +1,4 @@ - // This test is for *-windows-msvc only. +// This test is for *-windows-msvc only. //@ only-windows //@ ignore-gnu @@ -20,13 +20,13 @@ extern crate wrapper; // CHECK: declare noundef i32 @static_func1(i32 noundef) // CHECK: declare noundef i32 @static_func2(i32 noundef) -#[link(name = "dummy", kind="dylib")] +#[link(name = "dummy", kind = "dylib")] extern "C" { pub fn dylib_func1(x: i32) -> i32; pub static dylib_global1: i32; } -#[link(name = "dummy", kind="static")] +#[link(name = "dummy", kind = "static")] extern "C" { pub fn static_func1(x: i32) -> i32; pub static static_global1: i32; diff --git a/tests/codegen/drop-in-place-noalias.rs b/tests/codegen/drop-in-place-noalias.rs index 36532ea8f532..2dc769df1c92 100644 --- a/tests/codegen/drop-in-place-noalias.rs +++ b/tests/codegen/drop-in-place-noalias.rs @@ -3,7 +3,7 @@ // Tests that the compiler can apply `noalias` and other &mut attributes to `drop_in_place`. // Note that non-Unpin types should not get `noalias`, matching &mut behavior. -#![crate_type="lib"] +#![crate_type = "lib"] use std::marker::PhantomPinned; diff --git a/tests/codegen/drop.rs b/tests/codegen/drop.rs index 1e80247ba8aa..b22a8ef27d23 100644 --- a/tests/codegen/drop.rs +++ b/tests/codegen/drop.rs @@ -7,28 +7,26 @@ struct SomeUniqueName; impl Drop for SomeUniqueName { #[inline(never)] - fn drop(&mut self) { - } + fn drop(&mut self) {} } #[inline(never)] -pub fn possibly_unwinding() { -} +pub fn possibly_unwinding() {} // CHECK-LABEL: @droppy #[no_mangle] pub fn droppy() { -// Check that there are exactly 6 drop calls. The cleanups for the unwinding should be reused, so -// that's one new drop call per call to possibly_unwinding(), and finally 3 drop calls for the -// regular function exit. We used to have problems with quadratic growths of drop calls in such -// functions. -// FIXME(eddyb) the `void @` forces a match on the instruction, instead of the -// comment, that's `; call core::ptr::drop_in_place::` -// for the `v0` mangling, should switch to matching on that once `legacy` is gone. -// CHECK-COUNT-6: {{(call|invoke) void @.*}}drop_in_place{{.*}}SomeUniqueName -// CHECK-NOT: {{(call|invoke) void @.*}}drop_in_place{{.*}}SomeUniqueName -// The next line checks for the } that ends the function definition -// CHECK-LABEL: {{^[}]}} + // Check that there are exactly 6 drop calls. The cleanups for the unwinding should be reused, + // so that's one new drop call per call to possibly_unwinding(), and finally 3 drop calls for + // the regular function exit. We used to have problems with quadratic growths of drop calls in + // such functions. + // FIXME(eddyb) the `void @` forces a match on the instruction, instead of the + // comment, that's `; call core::ptr::drop_in_place::` + // for the `v0` mangling, should switch to matching on that once `legacy` is gone. + // CHECK-COUNT-6: {{(call|invoke) void @.*}}drop_in_place{{.*}}SomeUniqueName + // CHECK-NOT: {{(call|invoke) void @.*}}drop_in_place{{.*}}SomeUniqueName + // The next line checks for the } that ends the function definition + // CHECK-LABEL: {{^[}]}} let _s = SomeUniqueName; possibly_unwinding(); let _s = SomeUniqueName; diff --git a/tests/codegen/dst-offset.rs b/tests/codegen/dst-offset.rs index ce735baeb6a9..7177a960432a 100644 --- a/tests/codegen/dst-offset.rs +++ b/tests/codegen/dst-offset.rs @@ -3,7 +3,6 @@ //@ compile-flags: -C no-prepopulate-passes -Copt-level=0 #![crate_type = "lib"] - #![feature(extern_types)] use std::ptr::addr_of; @@ -11,8 +10,7 @@ use std::ptr::addr_of; // Hack to get the correct type for usize // CHECK: @helper([[USIZE:i[0-9]+]] %_1) #[no_mangle] -pub fn helper(_: usize) { -} +pub fn helper(_: usize) {} struct Dst { x: u32, @@ -23,30 +21,31 @@ struct Dst { // CHECK: @dst_dyn_trait_offset(ptr align {{[0-9]+}} [[DATA_PTR:%.+]], ptr align {{[0-9]+}} [[VTABLE_PTR:%.+]]) #[no_mangle] pub fn dst_dyn_trait_offset(s: &Dst) -> &dyn Drop { -// The alignment of dyn trait is unknown, so we compute the offset based on align from the vtable. + // The alignment of dyn trait is unknown, so we compute the offset based on align from the + // vtable. -// CHECK: [[SIZE_PTR:%[0-9]+]] = getelementptr inbounds i8, ptr [[VTABLE_PTR]] -// CHECK: load [[USIZE]], ptr [[SIZE_PTR]] -// CHECK: [[ALIGN_PTR:%[0-9]+]] = getelementptr inbounds i8, ptr [[VTABLE_PTR]] -// CHECK: load [[USIZE]], ptr [[ALIGN_PTR]] + // CHECK: [[SIZE_PTR:%[0-9]+]] = getelementptr inbounds i8, ptr [[VTABLE_PTR]] + // CHECK: load [[USIZE]], ptr [[SIZE_PTR]] + // CHECK: [[ALIGN_PTR:%[0-9]+]] = getelementptr inbounds i8, ptr [[VTABLE_PTR]] + // CHECK: load [[USIZE]], ptr [[ALIGN_PTR]] -// CHECK: getelementptr inbounds i8, ptr [[DATA_PTR]] -// CHECK-NEXT: insertvalue -// CHECK-NEXT: insertvalue -// CHECK-NEXT: ret + // CHECK: getelementptr inbounds i8, ptr [[DATA_PTR]] + // CHECK-NEXT: insertvalue + // CHECK-NEXT: insertvalue + // CHECK-NEXT: ret &s.z } // CHECK-LABEL: @dst_slice_offset #[no_mangle] pub fn dst_slice_offset(s: &Dst<[u16]>) -> &[u16] { -// The alignment of [u16] is known, so we generate a GEP directly. + // The alignment of [u16] is known, so we generate a GEP directly. -// CHECK: start: -// CHECK-NEXT: getelementptr inbounds i8, {{.+}}, [[USIZE]] 6 -// CHECK-NEXT: insertvalue -// CHECK-NEXT: insertvalue -// CHECK-NEXT: ret + // CHECK: start: + // CHECK-NEXT: getelementptr inbounds i8, {{.+}}, [[USIZE]] 6 + // CHECK-NEXT: insertvalue + // CHECK-NEXT: insertvalue + // CHECK-NEXT: ret &s.z } @@ -60,25 +59,25 @@ struct PackedDstSlice { // CHECK-LABEL: @packed_dst_slice_offset #[no_mangle] pub fn packed_dst_slice_offset(s: &PackedDstSlice) -> *const [u16] { -// The alignment of [u16] is known, so we generate a GEP directly. + // The alignment of [u16] is known, so we generate a GEP directly. -// CHECK: start: -// CHECK-NEXT: getelementptr inbounds i8, {{.+}}, [[USIZE]] 5 -// CHECK-NEXT: insertvalue -// CHECK-NEXT: insertvalue -// CHECK-NEXT: ret + // CHECK: start: + // CHECK-NEXT: getelementptr inbounds i8, {{.+}}, [[USIZE]] 5 + // CHECK-NEXT: insertvalue + // CHECK-NEXT: insertvalue + // CHECK-NEXT: ret addr_of!(s.z) } -extern { +extern "C" { pub type Extern; } // CHECK-LABEL: @dst_extern #[no_mangle] pub fn dst_extern(s: &Dst) -> &Extern { -// Computing the alignment of an extern type is currently unsupported and just panics. + // Computing the alignment of an extern type is currently unsupported and just panics. -// CHECK: call void @{{.+}}panic + // CHECK: call void @{{.+}}panic &s.z } diff --git a/tests/codegen/dst-vtable-align-nonzero.rs b/tests/codegen/dst-vtable-align-nonzero.rs index b0507f4c217d..cb07e43238c1 100644 --- a/tests/codegen/dst-vtable-align-nonzero.rs +++ b/tests/codegen/dst-vtable-align-nonzero.rs @@ -10,9 +10,15 @@ pub trait Trait { fn f(&self); } -pub struct WrapperWithAlign1 { x: u8, y: T } +pub struct WrapperWithAlign1 { + x: u8, + y: T, +} -pub struct WrapperWithAlign2 { x: u16, y: T } +pub struct WrapperWithAlign2 { + x: u16, + y: T, +} pub struct Struct { _field: i8, @@ -22,7 +28,7 @@ pub struct Struct { // CHECK-LABEL: @eliminates_runtime_check_when_align_1 #[no_mangle] pub fn eliminates_runtime_check_when_align_1( - x: &Struct> + x: &Struct>, ) -> &WrapperWithAlign1 { // CHECK: load [[USIZE:i[0-9]+]], {{.+}} !range [[RANGE_META:![0-9]+]] // CHECK-NOT: llvm.umax @@ -35,7 +41,7 @@ pub fn eliminates_runtime_check_when_align_1( // CHECK-LABEL: @does_not_eliminate_runtime_check_when_align_2 #[no_mangle] pub fn does_not_eliminate_runtime_check_when_align_2( - x: &Struct> + x: &Struct>, ) -> &WrapperWithAlign2 { // CHECK: [[X0:%[0-9]+]] = load [[USIZE]], {{.+}} !range [[RANGE_META]] // CHECK: {{icmp|llvm.umax}} diff --git a/tests/codegen/ehcontguard_disabled.rs b/tests/codegen/ehcontguard_disabled.rs index dc4b5eb430bf..9efb2721b3e8 100644 --- a/tests/codegen/ehcontguard_disabled.rs +++ b/tests/codegen/ehcontguard_disabled.rs @@ -3,8 +3,7 @@ #![crate_type = "lib"] // A basic test function. -pub fn test() { -} +pub fn test() {} // Ensure the module flag ehcontguard is not present // CHECK-NOT: !"ehcontguard" diff --git a/tests/codegen/ehcontguard_enabled.rs b/tests/codegen/ehcontguard_enabled.rs index fde66f1c148e..ecc5512fd5de 100644 --- a/tests/codegen/ehcontguard_enabled.rs +++ b/tests/codegen/ehcontguard_enabled.rs @@ -3,8 +3,7 @@ #![crate_type = "lib"] // A basic test function. -pub fn test() { -} +pub fn test() {} // Ensure the module flag ehcontguard=1 is present // CHECK: !"ehcontguard", i32 1 diff --git a/tests/codegen/emcripten-catch-unwind.rs b/tests/codegen/emcripten-catch-unwind.rs index 7de7bd81b5c0..6cda8c6799f4 100644 --- a/tests/codegen/emcripten-catch-unwind.rs +++ b/tests/codegen/emcripten-catch-unwind.rs @@ -9,18 +9,23 @@ #![no_std] #![no_core] -#[lang="sized"] trait Sized { } -#[lang="freeze"] trait Freeze { } -#[lang="copy"] trait Copy { } +#[lang = "sized"] +trait Sized {} +#[lang = "freeze"] +trait Freeze {} +#[lang = "copy"] +trait Copy {} #[rustc_intrinsic] -fn size_of() -> usize { loop {} } +fn size_of() -> usize { + loop {} +} extern "rust-intrinsic" { fn catch_unwind( try_fn: fn(_: *mut u8), data: *mut u8, - catch_fn: fn(_: *mut u8, _: *mut u8) + catch_fn: fn(_: *mut u8, _: *mut u8), ) -> i32; } @@ -36,7 +41,7 @@ pub fn ptr_size() -> usize { pub unsafe fn test_catch_unwind( try_fn: fn(_: *mut u8), data: *mut u8, - catch_fn: fn(_: *mut u8, _: *mut u8) + catch_fn: fn(_: *mut u8, _: *mut u8), ) -> i32 { // CHECK: start: // CHECK: [[ALLOCA:%.*]] = alloca diff --git a/tests/codegen/enable-lto-unit-splitting.rs b/tests/codegen/enable-lto-unit-splitting.rs index e46980944778..51c2671bc4eb 100644 --- a/tests/codegen/enable-lto-unit-splitting.rs +++ b/tests/codegen/enable-lto-unit-splitting.rs @@ -2,9 +2,8 @@ // //@ compile-flags: -Clto -Ctarget-feature=-crt-static -Zsplit-lto-unit -#![crate_type="lib"] +#![crate_type = "lib"] -pub fn foo() { -} +pub fn foo() {} // CHECK: !{{[0-9]+}} = !{i32 4, !"EnableSplitLTOUnit", i32 1} diff --git a/tests/codegen/enum/enum-bounds-check.rs b/tests/codegen/enum/enum-bounds-check.rs index a1b32ec9295b..c44c007ed6a9 100644 --- a/tests/codegen/enum/enum-bounds-check.rs +++ b/tests/codegen/enum/enum-bounds-check.rs @@ -3,7 +3,8 @@ #![crate_type = "lib"] pub enum Foo { - A, B + A, + B, } // CHECK-LABEL: @lookup @@ -15,7 +16,7 @@ pub fn lookup(buf: &[u8; 2], f: Foo) -> u8 { pub enum Bar { A = 2, - B = 3 + B = 3, } // CHECK-LABEL: @lookup_unmodified diff --git a/tests/codegen/enum/enum-debug-clike.rs b/tests/codegen/enum/enum-debug-clike.rs index 59ad58784439..89c803cce5e7 100644 --- a/tests/codegen/enum/enum-debug-clike.rs +++ b/tests/codegen/enum/enum-debug-clike.rs @@ -17,7 +17,11 @@ #![allow(unused_variables)] #![allow(unused_assignments)] -enum E { A, B, C } +enum E { + A, + B, + C, +} pub fn main() { let e = E::C; diff --git a/tests/codegen/enum/enum-debug-niche.rs b/tests/codegen/enum/enum-debug-niche.rs index 90de928bced6..59e8b8a78b43 100644 --- a/tests/codegen/enum/enum-debug-niche.rs +++ b/tests/codegen/enum/enum-debug-niche.rs @@ -23,7 +23,12 @@ #![allow(unused_variables)] #![allow(unused_assignments)] -enum E { A, B, C, D(bool) } +enum E { + A, + B, + C, + D(bool), +} pub fn main() { let e = E::D(true); diff --git a/tests/codegen/enum/enum-debug-tagged.rs b/tests/codegen/enum/enum-debug-tagged.rs index f13922ee33b8..e8f147665b08 100644 --- a/tests/codegen/enum/enum-debug-tagged.rs +++ b/tests/codegen/enum/enum-debug-tagged.rs @@ -21,7 +21,10 @@ #![allow(unused_variables)] #![allow(unused_assignments)] -enum E { A(u32), B(u32) } +enum E { + A(u32), + B(u32), +} pub fn main() { let e = E::A(23); diff --git a/tests/codegen/enum/enum-match.rs b/tests/codegen/enum/enum-match.rs index ced26c0a4340..8da5de63e67d 100644 --- a/tests/codegen/enum/enum-match.rs +++ b/tests/codegen/enum/enum-match.rs @@ -50,6 +50,7 @@ pub fn match1(e: Enum1) -> u8 { } // Case 2: Special cases don't apply. +#[rustfmt::skip] pub enum X { _2=2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, diff --git a/tests/codegen/enum/unreachable_enum_default_branch.rs b/tests/codegen/enum/unreachable_enum_default_branch.rs index dae01cfb055e..81a258f27220 100644 --- a/tests/codegen/enum/unreachable_enum_default_branch.rs +++ b/tests/codegen/enum/unreachable_enum_default_branch.rs @@ -22,8 +22,7 @@ const C: Int = Int(153); // CHECK-NEXT: ret i1 [[SPEC_SELECT]] #[no_mangle] pub fn implicit_match(x: Int) -> bool { - (x >= A && x <= B) - || x == C + (x >= A && x <= B) || x == C } // The code is from https://github.com/rust-lang/rust/issues/110097. @@ -35,9 +34,5 @@ pub fn implicit_match(x: Int) -> bool { // CHECK-NEXT: ret #[no_mangle] pub fn if_let(val: Result) -> Result { - if let Ok(x) = val { - Ok(x) - } else { - Err(()) - } + if let Ok(x) = val { Ok(x) } else { Err(()) } } diff --git a/tests/codegen/fatptr.rs b/tests/codegen/fatptr.rs index 0f13e66fbad0..041807202b84 100644 --- a/tests/codegen/fatptr.rs +++ b/tests/codegen/fatptr.rs @@ -7,6 +7,6 @@ pub trait T {} // CHECK-LABEL: @copy_fat_ptr #[no_mangle] pub fn copy_fat_ptr(x: &T) { -// CHECK-NOT: extractvalue + // CHECK-NOT: extractvalue let x2 = x; } diff --git a/tests/codegen/float_math.rs b/tests/codegen/float_math.rs index dcca51c2f5eb..31387ec82b92 100644 --- a/tests/codegen/float_math.rs +++ b/tests/codegen/float_math.rs @@ -3,48 +3,40 @@ #![crate_type = "lib"] #![feature(core_intrinsics)] -use std::intrinsics::{fadd_fast, fsub_fast, fmul_fast, fdiv_fast, frem_fast}; +use std::intrinsics::{fadd_fast, fdiv_fast, fmul_fast, frem_fast, fsub_fast}; // CHECK-LABEL: @add #[no_mangle] pub fn add(x: f32, y: f32) -> f32 { -// CHECK: fadd float -// CHECK-NOT: fast + // CHECK: fadd float + // CHECK-NOT: fast x + y } // CHECK-LABEL: @addition #[no_mangle] pub fn addition(x: f32, y: f32) -> f32 { -// CHECK: fadd fast float - unsafe { - fadd_fast(x, y) - } + // CHECK: fadd fast float + unsafe { fadd_fast(x, y) } } // CHECK-LABEL: @subtraction #[no_mangle] pub fn subtraction(x: f32, y: f32) -> f32 { -// CHECK: fsub fast float - unsafe { - fsub_fast(x, y) - } + // CHECK: fsub fast float + unsafe { fsub_fast(x, y) } } // CHECK-LABEL: @multiplication #[no_mangle] pub fn multiplication(x: f32, y: f32) -> f32 { -// CHECK: fmul fast float - unsafe { - fmul_fast(x, y) - } + // CHECK: fmul fast float + unsafe { fmul_fast(x, y) } } // CHECK-LABEL: @division #[no_mangle] pub fn division(x: f32, y: f32) -> f32 { -// CHECK: fdiv fast float - unsafe { - fdiv_fast(x, y) - } + // CHECK: fdiv fast float + unsafe { fdiv_fast(x, y) } } diff --git a/tests/codegen/force-frame-pointers.rs b/tests/codegen/force-frame-pointers.rs index c41824e024fd..84e0bcb39add 100644 --- a/tests/codegen/force-frame-pointers.rs +++ b/tests/codegen/force-frame-pointers.rs @@ -1,6 +1,6 @@ //@ compile-flags: -C no-prepopulate-passes -C force-frame-pointers=y -Copt-level=0 -#![crate_type="lib"] +#![crate_type = "lib"] // CHECK: attributes #{{.*}} "frame-pointer"="all" pub fn foo() {} diff --git a/tests/codegen/force-no-unwind-tables.rs b/tests/codegen/force-no-unwind-tables.rs index 0189ae7c0a68..e823bedac0f6 100644 --- a/tests/codegen/force-no-unwind-tables.rs +++ b/tests/codegen/force-no-unwind-tables.rs @@ -1,7 +1,7 @@ //@ compile-flags: -C no-prepopulate-passes -C panic=abort -C force-unwind-tables=n //@ ignore-windows -#![crate_type="lib"] +#![crate_type = "lib"] // CHECK-LABEL: define{{.*}}void @foo // CHECK-NOT: attributes #{{.*}} uwtable diff --git a/tests/codegen/force-unwind-tables.rs b/tests/codegen/force-unwind-tables.rs index 33fdf7653f49..a2ef8a104543 100644 --- a/tests/codegen/force-unwind-tables.rs +++ b/tests/codegen/force-unwind-tables.rs @@ -1,6 +1,6 @@ //@ compile-flags: -C no-prepopulate-passes -C force-unwind-tables=y -Copt-level=0 -#![crate_type="lib"] +#![crate_type = "lib"] // CHECK: attributes #{{.*}} uwtable pub fn foo() {} diff --git a/tests/codegen/frame-pointer.rs b/tests/codegen/frame-pointer.rs index 879535bcc368..da81c2e9cd9a 100644 --- a/tests/codegen/frame-pointer.rs +++ b/tests/codegen/frame-pointer.rs @@ -13,13 +13,12 @@ #![feature(no_core, lang_items)] #![no_core] -#[lang="sized"] -trait Sized { } -#[lang="copy"] -trait Copy { } +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} impl Copy for u32 {} - // CHECK: define i32 @peach{{.*}}[[PEACH_ATTRS:\#[0-9]+]] { #[no_mangle] pub fn peach(x: u32) -> u32 { diff --git a/tests/codegen/function-arguments-noopt.rs b/tests/codegen/function-arguments-noopt.rs index 0d42915893bc..c80f119696df 100644 --- a/tests/codegen/function-arguments-noopt.rs +++ b/tests/codegen/function-arguments-noopt.rs @@ -7,63 +7,63 @@ #![feature(rustc_attrs)] pub struct S { - _field: [i32; 8], + _field: [i32; 8], } // CHECK: zeroext i1 @boolean(i1 zeroext %x) #[no_mangle] pub fn boolean(x: bool) -> bool { - x + x } // CHECK-LABEL: @boolean_call #[no_mangle] pub fn boolean_call(x: bool, f: fn(bool) -> bool) -> bool { -// CHECK: call zeroext i1 %f(i1 zeroext %x) - f(x) + // CHECK: call zeroext i1 %f(i1 zeroext %x) + f(x) } // CHECK: align 4 ptr @borrow(ptr align 4 %x) #[no_mangle] pub fn borrow(x: &i32) -> &i32 { - x + x } // CHECK: align 4 ptr @borrow_mut(ptr align 4 %x) #[no_mangle] pub fn borrow_mut(x: &mut i32) -> &mut i32 { - x + x } // CHECK-LABEL: @borrow_call #[no_mangle] pub fn borrow_call(x: &i32, f: fn(&i32) -> &i32) -> &i32 { - // CHECK: call align 4 ptr %f(ptr align 4 %x) - f(x) + // CHECK: call align 4 ptr %f(ptr align 4 %x) + f(x) } // CHECK: void @struct_(ptr sret([32 x i8]) align 4{{( %_0)?}}, ptr align 4 %x) #[no_mangle] pub fn struct_(x: S) -> S { - x + x } // CHECK-LABEL: @struct_call #[no_mangle] pub fn struct_call(x: S, f: fn(S) -> S) -> S { - // CHECK: call void %f(ptr sret([32 x i8]) align 4{{( %_0)?}}, ptr align 4 %{{.+}}) - f(x) + // CHECK: call void %f(ptr sret([32 x i8]) align 4{{( %_0)?}}, ptr align 4 %{{.+}}) + f(x) } // CHECK: { i1, i8 } @enum_(i1 zeroext %x.0, i8 %x.1) #[no_mangle] pub fn enum_(x: Option) -> Option { - x + x } // CHECK-LABEL: @enum_call #[no_mangle] pub fn enum_call(x: Option, f: fn(Option) -> Option) -> Option { - // CHECK: call { i1, i8 } %f(i1 zeroext %x.0, i8 %x.1) - f(x) + // CHECK: call { i1, i8 } %f(i1 zeroext %x.0, i8 %x.1) + f(x) } diff --git a/tests/codegen/function-arguments.rs b/tests/codegen/function-arguments.rs index ebcbcae8563c..56504df40347 100644 --- a/tests/codegen/function-arguments.rs +++ b/tests/codegen/function-arguments.rs @@ -3,129 +3,123 @@ #![feature(dyn_star)] #![feature(allocator_api)] +use std::marker::PhantomPinned; use std::mem::MaybeUninit; use std::num::NonZero; -use std::marker::PhantomPinned; use std::ptr::NonNull; pub struct S { - _field: [i32; 8], + _field: [i32; 8], } pub struct UnsafeInner { - _field: std::cell::UnsafeCell, + _field: std::cell::UnsafeCell, } pub struct NotUnpin { - _field: i32, - _marker: PhantomPinned, + _field: i32, + _marker: PhantomPinned, } pub enum MyBool { - True, - False, + True, + False, } // CHECK: noundef zeroext i1 @boolean(i1 noundef zeroext %x) #[no_mangle] pub fn boolean(x: bool) -> bool { - x + x } // CHECK: i8 @maybeuninit_boolean(i8 %x) #[no_mangle] pub fn maybeuninit_boolean(x: MaybeUninit) -> MaybeUninit { - x + x } // CHECK: noundef zeroext i1 @enum_bool(i1 noundef zeroext %x) #[no_mangle] pub fn enum_bool(x: MyBool) -> MyBool { - x + x } // CHECK: i8 @maybeuninit_enum_bool(i8 %x) #[no_mangle] pub fn maybeuninit_enum_bool(x: MaybeUninit) -> MaybeUninit { - x + x } // CHECK: noundef i32 @char(i32 noundef %x) #[no_mangle] pub fn char(x: char) -> char { - x + x } // CHECK: i32 @maybeuninit_char(i32 %x) #[no_mangle] pub fn maybeuninit_char(x: MaybeUninit) -> MaybeUninit { - x + x } // CHECK: noundef i64 @int(i64 noundef %x) #[no_mangle] pub fn int(x: u64) -> u64 { - x + x } // CHECK: noundef i64 @nonzero_int(i64 noundef %x) #[no_mangle] pub fn nonzero_int(x: NonZero) -> NonZero { - x + x } // CHECK: noundef i64 @option_nonzero_int(i64 noundef %x) #[no_mangle] pub fn option_nonzero_int(x: Option>) -> Option> { - x + x } // CHECK: @readonly_borrow(ptr noalias noundef readonly align 4 dereferenceable(4) %_1) // FIXME #25759 This should also have `nocapture` #[no_mangle] -pub fn readonly_borrow(_: &i32) { -} +pub fn readonly_borrow(_: &i32) {} // CHECK: noundef align 4 dereferenceable(4) ptr @readonly_borrow_ret() #[no_mangle] pub fn readonly_borrow_ret() -> &'static i32 { - loop {} + loop {} } // CHECK: @static_borrow(ptr noalias noundef readonly align 4 dereferenceable(4) %_1) // static borrow may be captured #[no_mangle] -pub fn static_borrow(_: &'static i32) { -} +pub fn static_borrow(_: &'static i32) {} // CHECK: @named_borrow(ptr noalias noundef readonly align 4 dereferenceable(4) %_1) // borrow with named lifetime may be captured #[no_mangle] -pub fn named_borrow<'r>(_: &'r i32) { -} +pub fn named_borrow<'r>(_: &'r i32) {} // CHECK: @unsafe_borrow(ptr noundef nonnull align 2 %_1) // unsafe interior means this isn't actually readonly and there may be aliases ... #[no_mangle] -pub fn unsafe_borrow(_: &UnsafeInner) { -} +pub fn unsafe_borrow(_: &UnsafeInner) {} // CHECK: @mutable_unsafe_borrow(ptr noalias noundef align 2 dereferenceable(2) %_1) // ... unless this is a mutable borrow, those never alias #[no_mangle] -pub fn mutable_unsafe_borrow(_: &mut UnsafeInner) { -} +pub fn mutable_unsafe_borrow(_: &mut UnsafeInner) {} // CHECK: @mutable_borrow(ptr noalias noundef align 4 dereferenceable(4) %_1) // FIXME #25759 This should also have `nocapture` #[no_mangle] -pub fn mutable_borrow(_: &mut i32) { -} +pub fn mutable_borrow(_: &mut i32) {} // CHECK: noundef align 4 dereferenceable(4) ptr @mutable_borrow_ret() #[no_mangle] pub fn mutable_borrow_ret() -> &'static mut i32 { - loop {} + loop {} } #[no_mangle] @@ -133,53 +127,44 @@ pub fn mutable_borrow_ret() -> &'static mut i32 { // This one is *not* `noalias` because it might be self-referential. // It is also not `dereferenceable` due to // . -pub fn mutable_notunpin_borrow(_: &mut NotUnpin) { -} +pub fn mutable_notunpin_borrow(_: &mut NotUnpin) {} // CHECK: @notunpin_borrow(ptr noalias noundef readonly align 4 dereferenceable(4) %_1) // But `&NotUnpin` behaves perfectly normal. #[no_mangle] -pub fn notunpin_borrow(_: &NotUnpin) { -} +pub fn notunpin_borrow(_: &NotUnpin) {} // CHECK: @indirect_struct(ptr noalias nocapture noundef readonly align 4 dereferenceable(32) %_1) #[no_mangle] -pub fn indirect_struct(_: S) { -} +pub fn indirect_struct(_: S) {} // CHECK: @borrowed_struct(ptr noalias noundef readonly align 4 dereferenceable(32) %_1) // FIXME #25759 This should also have `nocapture` #[no_mangle] -pub fn borrowed_struct(_: &S) { -} +pub fn borrowed_struct(_: &S) {} // CHECK: @option_borrow(ptr noalias noundef readonly align 4 dereferenceable_or_null(4) %x) #[no_mangle] -pub fn option_borrow(x: Option<&i32>) { -} +pub fn option_borrow(x: Option<&i32>) {} // CHECK: @option_borrow_mut(ptr noalias noundef align 4 dereferenceable_or_null(4) %x) #[no_mangle] -pub fn option_borrow_mut(x: Option<&mut i32>) { -} +pub fn option_borrow_mut(x: Option<&mut i32>) {} // CHECK: @raw_struct(ptr noundef %_1) #[no_mangle] -pub fn raw_struct(_: *const S) { -} +pub fn raw_struct(_: *const S) {} // CHECK: @raw_option_nonnull_struct(ptr noundef %_1) #[no_mangle] -pub fn raw_option_nonnull_struct(_: Option>) { -} - +pub fn raw_option_nonnull_struct(_: Option>) {} // `Box` can get deallocated during execution of the function, so it should // not get `dereferenceable`. // CHECK: noundef nonnull align 4 ptr @_box(ptr noalias noundef nonnull align 4 %x) #[no_mangle] pub fn _box(x: Box) -> Box { - x + x } // With a custom allocator, it should *not* have `noalias`. (See @@ -188,106 +173,93 @@ pub fn _box(x: Box) -> Box { // CHECK: @_box_custom(ptr noundef nonnull align 4 %x.0, ptr noalias noundef nonnull readonly align 1 %x.1) #[no_mangle] pub fn _box_custom(x: Box) { - drop(x) + drop(x) } // CHECK: noundef nonnull align 4 ptr @notunpin_box(ptr noundef nonnull align 4 %x) #[no_mangle] pub fn notunpin_box(x: Box) -> Box { - x + x } // CHECK: @struct_return(ptr{{( dead_on_unwind)?}} noalias nocapture noundef{{( writable)?}} sret([32 x i8]) align 4 dereferenceable(32){{( %_0)?}}) #[no_mangle] pub fn struct_return() -> S { - S { - _field: [0, 0, 0, 0, 0, 0, 0, 0] - } + S { _field: [0, 0, 0, 0, 0, 0, 0, 0] } } // Hack to get the correct size for the length part in slices // CHECK: @helper([[USIZE:i[0-9]+]] noundef %_1) #[no_mangle] -pub fn helper(_: usize) { -} +pub fn helper(_: usize) {} // CHECK: @slice(ptr noalias noundef nonnull readonly align 1 %_1.0, [[USIZE]] noundef %_1.1) // FIXME #25759 This should also have `nocapture` #[no_mangle] -pub fn slice(_: &[u8]) { -} +pub fn slice(_: &[u8]) {} // CHECK: @mutable_slice(ptr noalias noundef nonnull align 1 %_1.0, [[USIZE]] noundef %_1.1) // FIXME #25759 This should also have `nocapture` #[no_mangle] -pub fn mutable_slice(_: &mut [u8]) { -} +pub fn mutable_slice(_: &mut [u8]) {} // CHECK: @unsafe_slice(ptr noundef nonnull align 2 %_1.0, [[USIZE]] noundef %_1.1) // unsafe interior means this isn't actually readonly and there may be aliases ... #[no_mangle] -pub fn unsafe_slice(_: &[UnsafeInner]) { -} +pub fn unsafe_slice(_: &[UnsafeInner]) {} // CHECK: @raw_slice(ptr noundef %_1.0, [[USIZE]] noundef %_1.1) #[no_mangle] -pub fn raw_slice(_: *const [u8]) { -} +pub fn raw_slice(_: *const [u8]) {} // CHECK: @str(ptr noalias noundef nonnull readonly align 1 %_1.0, [[USIZE]] noundef %_1.1) // FIXME #25759 This should also have `nocapture` #[no_mangle] -pub fn str(_: &[u8]) { -} +pub fn str(_: &[u8]) {} // CHECK: @trait_borrow(ptr noundef nonnull align 1 %_1.0, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}) %_1.1) // FIXME #25759 This should also have `nocapture` #[no_mangle] -pub fn trait_borrow(_: &dyn Drop) { -} +pub fn trait_borrow(_: &dyn Drop) {} // CHECK: @option_trait_borrow(ptr noundef align 1 %x.0, ptr %x.1) #[no_mangle] -pub fn option_trait_borrow(x: Option<&dyn Drop>) { -} +pub fn option_trait_borrow(x: Option<&dyn Drop>) {} // CHECK: @option_trait_borrow_mut(ptr noundef align 1 %x.0, ptr %x.1) #[no_mangle] -pub fn option_trait_borrow_mut(x: Option<&mut dyn Drop>) { -} +pub fn option_trait_borrow_mut(x: Option<&mut dyn Drop>) {} // CHECK: @trait_raw(ptr noundef %_1.0, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}) %_1.1) #[no_mangle] -pub fn trait_raw(_: *const dyn Drop) { -} +pub fn trait_raw(_: *const dyn Drop) {} // CHECK: @trait_box(ptr noalias noundef nonnull align 1{{( %0)?}}, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}){{( %1)?}}) #[no_mangle] -pub fn trait_box(_: Box) { -} +pub fn trait_box(_: Box) {} // CHECK: { ptr, ptr } @trait_option(ptr noalias noundef align 1 %x.0, ptr %x.1) #[no_mangle] pub fn trait_option(x: Option>) -> Option> { - x + x } // CHECK: { ptr, [[USIZE]] } @return_slice(ptr noalias noundef nonnull readonly align 2 %x.0, [[USIZE]] noundef %x.1) #[no_mangle] pub fn return_slice(x: &[u16]) -> &[u16] { - x + x } // CHECK: { i16, i16 } @enum_id_1(i16 noundef %x.0, i16 %x.1) #[no_mangle] pub fn enum_id_1(x: Option>) -> Option> { - x + x } // CHECK: { i1, i8 } @enum_id_2(i1 noundef zeroext %x.0, i8 %x.1) #[no_mangle] pub fn enum_id_2(x: Option) -> Option { - x + x } // CHECK: { ptr, {{.+}} } @dyn_star(ptr noundef %x.0, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}) %x.1) @@ -295,5 +267,5 @@ pub fn enum_id_2(x: Option) -> Option { // so do like the `trait_box` test and just match on `{{.+}}` for the vtable. #[no_mangle] pub fn dyn_star(x: dyn* Drop) -> dyn* Drop { - x + x } diff --git a/tests/codegen/generic-debug.rs b/tests/codegen/generic-debug.rs index 0f289026396f..3423abe7187b 100644 --- a/tests/codegen/generic-debug.rs +++ b/tests/codegen/generic-debug.rs @@ -13,6 +13,6 @@ pub struct Generic(Type); -fn main () { +fn main() { let generic = Generic(10); } diff --git a/tests/codegen/inline-always-works-always.rs b/tests/codegen/inline-always-works-always.rs index e9ca05d17569..07200fd9e373 100644 --- a/tests/codegen/inline-always-works-always.rs +++ b/tests/codegen/inline-always-works-always.rs @@ -3,7 +3,7 @@ //@[SIZE-OPT] compile-flags: -Copt-level=s //@[SPEED-OPT] compile-flags: -Copt-level=3 -#![crate_type="rlib"] +#![crate_type = "rlib"] #[no_mangle] #[inline(always)] diff --git a/tests/codegen/inline-debuginfo.rs b/tests/codegen/inline-debuginfo.rs index f327180560de..1e1c9037f5c9 100644 --- a/tests/codegen/inline-debuginfo.rs +++ b/tests/codegen/inline-debuginfo.rs @@ -1,4 +1,4 @@ -#![crate_type="rlib"] +#![crate_type = "rlib"] //@ compile-flags: -Copt-level=3 -g // diff --git a/tests/codegen/instrument-coverage/instrument-coverage.rs b/tests/codegen/instrument-coverage/instrument-coverage.rs index d638a544d5a5..65fa437d2506 100644 --- a/tests/codegen/instrument-coverage/instrument-coverage.rs +++ b/tests/codegen/instrument-coverage/instrument-coverage.rs @@ -12,12 +12,10 @@ // CHECK: @__llvm_profile_filename = {{.*}}"default_%m_%p.profraw\00"{{.*}} // CHECK: @__llvm_coverage_mapping -#![crate_type="lib"] +#![crate_type = "lib"] #[inline(never)] -fn some_function() { - -} +fn some_function() {} pub fn some_other_function() { some_function(); diff --git a/tests/codegen/integer-cmp.rs b/tests/codegen/integer-cmp.rs index 46972878da50..bba112b246f3 100644 --- a/tests/codegen/integer-cmp.rs +++ b/tests/codegen/integer-cmp.rs @@ -10,19 +10,19 @@ use std::cmp::Ordering; // CHECK-LABEL: @cmp_signed #[no_mangle] pub fn cmp_signed(a: i64, b: i64) -> Ordering { -// CHECK: icmp slt -// CHECK: icmp ne -// CHECK: zext i1 -// CHECK: select i1 + // CHECK: icmp slt + // CHECK: icmp ne + // CHECK: zext i1 + // CHECK: select i1 a.cmp(&b) } // CHECK-LABEL: @cmp_unsigned #[no_mangle] pub fn cmp_unsigned(a: u32, b: u32) -> Ordering { -// CHECK: icmp ult -// CHECK: icmp ne -// CHECK: zext i1 -// CHECK: select i1 + // CHECK: icmp ult + // CHECK: icmp ne + // CHECK: zext i1 + // CHECK: select i1 a.cmp(&b) } diff --git a/tests/codegen/integer-overflow.rs b/tests/codegen/integer-overflow.rs index 00780251bbc1..a6407476fc20 100644 --- a/tests/codegen/integer-overflow.rs +++ b/tests/codegen/integer-overflow.rs @@ -2,7 +2,6 @@ #![crate_type = "lib"] - pub struct S1<'a> { data: &'a [u8], position: usize, @@ -12,7 +11,7 @@ pub struct S1<'a> { #[no_mangle] pub fn slice_no_index_order<'a>(s: &'a mut S1, n: usize) -> &'a [u8] { // CHECK-NOT: slice_index_order_fail - let d = &s.data[s.position..s.position+n]; + let d = &s.data[s.position..s.position + n]; s.position += n; return d; } diff --git a/tests/codegen/internalize-closures.rs b/tests/codegen/internalize-closures.rs index d37aa5fee8da..f226ea6faac8 100644 --- a/tests/codegen/internalize-closures.rs +++ b/tests/codegen/internalize-closures.rs @@ -1,7 +1,6 @@ //@ compile-flags: -C no-prepopulate-passes -Zmir-opt-level=0 pub fn main() { - // We want to make sure that closures get 'internal' linkage instead of // 'weak_odr' when they are not shared between codegen units // FIXME(eddyb) `legacy` mangling uses `{{closure}}`, while `v0` @@ -9,6 +8,6 @@ pub fn main() { // CHECK-LABEL: ; internalize_closures::main::{{.*}}closure // CHECK-NEXT: ; Function Attrs: // CHECK-NEXT: define internal - let c = |x:i32| { x + 1 }; + let c = |x: i32| x + 1; let _ = c(1); } diff --git a/tests/codegen/intrinsic-no-unnamed-attr.rs b/tests/codegen/intrinsic-no-unnamed-attr.rs index 45d06c70a6d7..fce0de80d7b6 100644 --- a/tests/codegen/intrinsic-no-unnamed-attr.rs +++ b/tests/codegen/intrinsic-no-unnamed-attr.rs @@ -8,5 +8,7 @@ extern "rust-intrinsic" { // CHECK: @llvm.sqrt.f32(float) #{{[0-9]*}} fn main() { - unsafe { sqrtf32(0.0f32); } + unsafe { + sqrtf32(0.0f32); + } } diff --git a/tests/codegen/intrinsics/const_eval_select.rs b/tests/codegen/intrinsics/const_eval_select.rs index c8debe8d7113..baa985b00cd0 100644 --- a/tests/codegen/intrinsics/const_eval_select.rs +++ b/tests/codegen/intrinsics/const_eval_select.rs @@ -6,10 +6,14 @@ use std::intrinsics::const_eval_select; -const fn foo(_: i32) -> i32 { 1 } +const fn foo(_: i32) -> i32 { + 1 +} #[no_mangle] -pub fn hi(n: i32) -> i32 { n } +pub fn hi(n: i32) -> i32 { + n +} #[no_mangle] pub unsafe fn hey() { diff --git a/tests/codegen/intrinsics/likely.rs b/tests/codegen/intrinsics/likely.rs index c5904085fc08..098fd9936ce1 100644 --- a/tests/codegen/intrinsics/likely.rs +++ b/tests/codegen/intrinsics/likely.rs @@ -3,17 +3,13 @@ #![crate_type = "lib"] #![feature(core_intrinsics)] -use std::intrinsics::{likely,unlikely}; +use std::intrinsics::{likely, unlikely}; #[no_mangle] pub fn check_likely(x: i32, y: i32) -> Option { unsafe { // CHECK: call i1 @llvm.expect.i1(i1 %{{.*}}, i1 true) - if likely(x == y) { - None - } else { - Some(x + y) - } + if likely(x == y) { None } else { Some(x + y) } } } @@ -21,10 +17,6 @@ pub fn check_likely(x: i32, y: i32) -> Option { pub fn check_unlikely(x: i32, y: i32) -> Option { unsafe { // CHECK: call i1 @llvm.expect.i1(i1 %{{.*}}, i1 false) - if unlikely(x == y) { - None - } else { - Some(x + y) - } + if unlikely(x == y) { None } else { Some(x + y) } } } diff --git a/tests/codegen/intrinsics/prefetch.rs b/tests/codegen/intrinsics/prefetch.rs index edd8c20b38f1..3f9f21c85cbf 100644 --- a/tests/codegen/intrinsics/prefetch.rs +++ b/tests/codegen/intrinsics/prefetch.rs @@ -3,8 +3,9 @@ #![crate_type = "lib"] #![feature(core_intrinsics)] -use std::intrinsics::{prefetch_read_data, prefetch_write_data, - prefetch_read_instruction, prefetch_write_instruction}; +use std::intrinsics::{ + prefetch_read_data, prefetch_read_instruction, prefetch_write_data, prefetch_write_instruction, +}; #[no_mangle] pub fn check_prefetch_read_data(data: &[i8]) { diff --git a/tests/codegen/is_val_statically_known.rs b/tests/codegen/is_val_statically_known.rs index 255d8950a974..6af4f353a481 100644 --- a/tests/codegen/is_val_statically_known.rs +++ b/tests/codegen/is_val_statically_known.rs @@ -75,7 +75,7 @@ pub fn _slice_ref(a: &[u8]) -> i32 { #[no_mangle] pub fn _slice_ref_borrow() -> i32 { // CHECK: ret i32 6 - _slice_ref(&[0;3]) + _slice_ref(&[0; 3]) } // CHECK-LABEL: @_slice_ref_arg( diff --git a/tests/codegen/issue-97217.rs b/tests/codegen/issue-97217.rs index a0dfff2ef2eb..ecf1fa1ddb3e 100644 --- a/tests/codegen/issue-97217.rs +++ b/tests/codegen/issue-97217.rs @@ -16,6 +16,6 @@ pub fn issue97217() -> i32 { let v1 = vec![5, 6, 7]; let v1_iter = v1.iter(); let total: i32 = v1_iter.sum(); - println!("{}",total); + println!("{}", total); total } diff --git a/tests/codegen/issues/issue-103327.rs b/tests/codegen/issues/issue-103327.rs index 398b1f376b78..f8cf273e4a6c 100644 --- a/tests/codegen/issues/issue-103327.rs +++ b/tests/codegen/issues/issue-103327.rs @@ -9,9 +9,5 @@ pub fn test(a: i32, b: i32) -> bool { let c1 = (a >= 0) && (a <= 10); let c2 = (b >= 0) && (b <= 20); - if c1 & c2 { - a + 100 != b - } else { - true - } + if c1 & c2 { a + 100 != b } else { true } } diff --git a/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs b/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs index 56b4330b1a6c..db9eeda19a6c 100644 --- a/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs +++ b/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs @@ -6,7 +6,8 @@ pub struct S([usize; 8]); #[no_mangle] pub fn outer_function(x: S, y: S) -> usize { - (#[inline(always)]|| { + (#[inline(always)] + || { let _z = x; y.0[0] })() diff --git a/tests/codegen/issues/issue-119422.rs b/tests/codegen/issues/issue-119422.rs index aa56bfe79acb..682430a79f4a 100644 --- a/tests/codegen/issues/issue-119422.rs +++ b/tests/codegen/issues/issue-119422.rs @@ -5,8 +5,8 @@ //@ only-64bit (because the LLVM type of i64 for usize shows up) #![crate_type = "lib"] -use core::ptr::NonNull; use core::num::NonZero; +use core::ptr::NonNull; // CHECK-LABEL: @check_non_null #[no_mangle] @@ -73,7 +73,7 @@ pub fn isize_try_from_i32(x: NonZero) -> NonZero { // CHECK-LABEL: @u64_from_nonzero_is_not_zero #[no_mangle] -pub fn u64_from_nonzero_is_not_zero(x: NonZero)->bool { +pub fn u64_from_nonzero_is_not_zero(x: NonZero) -> bool { // CHECK-NOT: br // CHECK: ret i1 false // CHECK-NOT: br diff --git a/tests/codegen/issues/issue-13018.rs b/tests/codegen/issues/issue-13018.rs index d0a8ce159118..66282dc42749 100644 --- a/tests/codegen/issues/issue-13018.rs +++ b/tests/codegen/issues/issue-13018.rs @@ -6,6 +6,6 @@ use std::rc::Rc; pub fn foo(t: &Rc>) { -// CHECK-NOT: __rust_dealloc + // CHECK-NOT: __rust_dealloc drop(t.clone()); } diff --git a/tests/codegen/issues/issue-32364.rs b/tests/codegen/issues/issue-32364.rs index 50006e3f2181..016981d1947a 100644 --- a/tests/codegen/issues/issue-32364.rs +++ b/tests/codegen/issues/issue-32364.rs @@ -7,10 +7,9 @@ struct Foo; impl Foo { -// CHECK: define internal x86_stdcallcc void @{{.*}}foo{{.*}}() + // CHECK: define internal x86_stdcallcc void @{{.*}}foo{{.*}}() #[inline(never)] - pub extern "stdcall" fn foo() { - } + pub extern "stdcall" fn foo() {} } fn main() { diff --git a/tests/codegen/issues/issue-37945.rs b/tests/codegen/issues/issue-37945.rs index 756a75e2f0ed..01d1c694ec7c 100644 --- a/tests/codegen/issues/issue-37945.rs +++ b/tests/codegen/issues/issue-37945.rs @@ -9,26 +9,26 @@ use std::slice::Iter; #[no_mangle] pub fn is_empty_1(xs: Iter) -> bool { -// CHECK-LABEL: @is_empty_1( -// CHECK-NEXT: start: -// CHECK-NEXT: [[A:%.*]] = icmp ne ptr {{%xs.0|%xs.1}}, null -// CHECK-NEXT: tail call void @llvm.assume(i1 [[A]]) -// The order between %xs.0 and %xs.1 on the next line doesn't matter -// and different LLVM versions produce different order. -// CHECK-NEXT: [[B:%.*]] = icmp eq ptr {{%xs.0, %xs.1|%xs.1, %xs.0}} -// CHECK-NEXT: ret i1 [[B:%.*]] - {xs}.next().is_none() + // CHECK-LABEL: @is_empty_1( + // CHECK-NEXT: start: + // CHECK-NEXT: [[A:%.*]] = icmp ne ptr {{%xs.0|%xs.1}}, null + // CHECK-NEXT: tail call void @llvm.assume(i1 [[A]]) + // The order between %xs.0 and %xs.1 on the next line doesn't matter + // and different LLVM versions produce different order. + // CHECK-NEXT: [[B:%.*]] = icmp eq ptr {{%xs.0, %xs.1|%xs.1, %xs.0}} + // CHECK-NEXT: ret i1 [[B:%.*]] + { xs }.next().is_none() } #[no_mangle] pub fn is_empty_2(xs: Iter) -> bool { -// CHECK-LABEL: @is_empty_2 -// CHECK-NEXT: start: -// CHECK-NEXT: [[C:%.*]] = icmp ne ptr {{%xs.0|%xs.1}}, null -// CHECK-NEXT: tail call void @llvm.assume(i1 [[C]]) -// The order between %xs.0 and %xs.1 on the next line doesn't matter -// and different LLVM versions produce different order. -// CHECK-NEXT: [[D:%.*]] = icmp eq ptr {{%xs.0, %xs.1|%xs.1, %xs.0}} -// CHECK-NEXT: ret i1 [[D:%.*]] + // CHECK-LABEL: @is_empty_2 + // CHECK-NEXT: start: + // CHECK-NEXT: [[C:%.*]] = icmp ne ptr {{%xs.0|%xs.1}}, null + // CHECK-NEXT: tail call void @llvm.assume(i1 [[C]]) + // The order between %xs.0 and %xs.1 on the next line doesn't matter + // and different LLVM versions produce different order. + // CHECK-NEXT: [[D:%.*]] = icmp eq ptr {{%xs.0, %xs.1|%xs.1, %xs.0}} + // CHECK-NEXT: ret i1 [[D:%.*]] xs.map(|&x| x).next().is_none() } diff --git a/tests/codegen/issues/issue-45466.rs b/tests/codegen/issues/issue-45466.rs index fc714247dfb6..8a324fa555bb 100644 --- a/tests/codegen/issues/issue-45466.rs +++ b/tests/codegen/issues/issue-45466.rs @@ -1,6 +1,6 @@ //@ compile-flags: -O -#![crate_type="rlib"] +#![crate_type = "rlib"] // CHECK-LABEL: @memzero // CHECK-NOT: store diff --git a/tests/codegen/issues/issue-45964-bounds-check-slice-pos.rs b/tests/codegen/issues/issue-45964-bounds-check-slice-pos.rs index b7568bea4d0a..ea9288564e9d 100644 --- a/tests/codegen/issues/issue-45964-bounds-check-slice-pos.rs +++ b/tests/codegen/issues/issue-45964-bounds-check-slice-pos.rs @@ -3,7 +3,7 @@ //@ compile-flags: -O -#![crate_type="rlib"] +#![crate_type = "rlib"] // CHECK-LABEL: @test #[no_mangle] diff --git a/tests/codegen/issues/issue-47278.rs b/tests/codegen/issues/issue-47278.rs index 9076274f45e9..4f0a5bdf36f4 100644 --- a/tests/codegen/issues/issue-47278.rs +++ b/tests/codegen/issues/issue-47278.rs @@ -1,9 +1,11 @@ // -C no-prepopulate-passes -#![crate_type="staticlib"] +#![crate_type = "staticlib"] #[repr(C)] pub struct Foo(u64); // CHECK: define {{.*}} @foo( #[no_mangle] -pub extern "C" fn foo(_: Foo) -> Foo { loop {} } +pub extern "C" fn foo(_: Foo) -> Foo { + loop {} +} diff --git a/tests/codegen/issues/issue-47442.rs b/tests/codegen/issues/issue-47442.rs index 6944336d3356..445234e55add 100644 --- a/tests/codegen/issues/issue-47442.rs +++ b/tests/codegen/issues/issue-47442.rs @@ -4,7 +4,7 @@ // CHECK-NOT: Unwind #![feature(test)] -#![crate_type="rlib"] +#![crate_type = "rlib"] extern crate test; diff --git a/tests/codegen/issues/issue-56267-2.rs b/tests/codegen/issues/issue-56267-2.rs index ced0d2d63bb5..98e3732777e3 100644 --- a/tests/codegen/issues/issue-56267-2.rs +++ b/tests/codegen/issues/issue-56267-2.rs @@ -1,6 +1,6 @@ //@ compile-flags: -C no-prepopulate-passes -#![crate_type="rlib"] +#![crate_type = "rlib"] #[allow(dead_code)] pub struct Foo { diff --git a/tests/codegen/issues/issue-56267.rs b/tests/codegen/issues/issue-56267.rs index fc3754f2d990..cabcc298482d 100644 --- a/tests/codegen/issues/issue-56267.rs +++ b/tests/codegen/issues/issue-56267.rs @@ -1,6 +1,6 @@ //@ compile-flags: -C no-prepopulate-passes -#![crate_type="rlib"] +#![crate_type = "rlib"] #[allow(dead_code)] pub struct Foo { diff --git a/tests/codegen/issues/issue-56927.rs b/tests/codegen/issues/issue-56927.rs index e4a0a1791418..a40718689b3e 100644 --- a/tests/codegen/issues/issue-56927.rs +++ b/tests/codegen/issues/issue-56927.rs @@ -1,6 +1,6 @@ //@ compile-flags: -C no-prepopulate-passes -#![crate_type="rlib"] +#![crate_type = "rlib"] #[repr(align(16))] pub struct S { diff --git a/tests/codegen/issues/issue-73031.rs b/tests/codegen/issues/issue-73031.rs index 61a269999e90..db9c6d6db233 100644 --- a/tests/codegen/issues/issue-73031.rs +++ b/tests/codegen/issues/issue-73031.rs @@ -12,11 +12,7 @@ pub enum All { // CHECK-LABEL: @issue_73031 #[no_mangle] pub fn issue_73031(a: &mut All, q: i32) -> i32 { - *a = if q == 5 { - All::Foo - } else { - All::Bar - }; + *a = if q == 5 { All::Foo } else { All::Bar }; match *a { // CHECK-NOT: panic All::None => panic!(), diff --git a/tests/codegen/issues/issue-73258.rs b/tests/codegen/issues/issue-73258.rs index 48f14fe2dfe3..e5c622b5656b 100644 --- a/tests/codegen/issues/issue-73258.rs +++ b/tests/codegen/issues/issue-73258.rs @@ -7,7 +7,10 @@ #[derive(Clone, Copy)] #[repr(u8)] pub enum Foo { - A, B, C, D, + A, + B, + C, + D, } // CHECK-LABEL: @issue_73258( diff --git a/tests/codegen/issues/issue-73338-effecient-cmp.rs b/tests/codegen/issues/issue-73338-effecient-cmp.rs index a64eb56f9030..71641a5457b1 100644 --- a/tests/codegen/issues/issue-73338-effecient-cmp.rs +++ b/tests/codegen/issues/issue-73338-effecient-cmp.rs @@ -4,7 +4,7 @@ //@ compile-flags: -Copt-level=3 -#![crate_type="lib"] +#![crate_type = "lib"] #[repr(u32)] #[derive(Copy, Clone, Eq, PartialEq, PartialOrd)] @@ -15,25 +15,25 @@ pub enum Foo { } #[no_mangle] -pub fn compare_less(a: Foo, b: Foo)->bool{ +pub fn compare_less(a: Foo, b: Foo) -> bool { // CHECK-NOT: br {{.*}} a < b } #[no_mangle] -pub fn compare_le(a: Foo, b: Foo)->bool{ +pub fn compare_le(a: Foo, b: Foo) -> bool { // CHECK-NOT: br {{.*}} a <= b } #[no_mangle] -pub fn compare_ge(a: Foo, b: Foo)->bool{ +pub fn compare_ge(a: Foo, b: Foo) -> bool { // CHECK-NOT: br {{.*}} a >= b } #[no_mangle] -pub fn compare_greater(a: Foo, b: Foo)->bool{ +pub fn compare_greater(a: Foo, b: Foo) -> bool { // CHECK-NOT: br {{.*}} a > b } diff --git a/tests/codegen/issues/issue-73396-bounds-check-after-position.rs b/tests/codegen/issues/issue-73396-bounds-check-after-position.rs index ef4538ac84e1..9b3b1318ced1 100644 --- a/tests/codegen/issues/issue-73396-bounds-check-after-position.rs +++ b/tests/codegen/issues/issue-73396-bounds-check-after-position.rs @@ -12,11 +12,7 @@ pub fn position_slice_to_no_bounds_check(s: &[u8]) -> &[u8] { // CHECK-NOT: slice_end_index_len_fail // CHECK-NOT: panic_bounds_check // CHECK-NOT: unreachable - if let Some(idx) = s.iter().position(|b| *b == b'\\') { - &s[..idx] - } else { - s - } + if let Some(idx) = s.iter().position(|b| *b == b'\\') { &s[..idx] } else { s } } // CHECK-LABEL: @position_slice_from_no_bounds_check @@ -27,11 +23,7 @@ pub fn position_slice_from_no_bounds_check(s: &[u8]) -> &[u8] { // CHECK-NOT: slice_end_index_len_fail // CHECK-NOT: panic_bounds_check // CHECK-NOT: unreachable - if let Some(idx) = s.iter().position(|b| *b == b'\\') { - &s[idx..] - } else { - s - } + if let Some(idx) = s.iter().position(|b| *b == b'\\') { &s[idx..] } else { s } } // CHECK-LABEL: @position_index_no_bounds_check @@ -42,11 +34,7 @@ pub fn position_index_no_bounds_check(s: &[u8]) -> u8 { // CHECK-NOT: slice_end_index_len_fail // CHECK-NOT: panic_bounds_check // CHECK-NOT: unreachable - if let Some(idx) = s.iter().position(|b| *b == b'\\') { - s[idx] - } else { - 42 - } + if let Some(idx) = s.iter().position(|b| *b == b'\\') { s[idx] } else { 42 } } // CHECK-LABEL: @rposition_slice_to_no_bounds_check #[no_mangle] @@ -56,11 +44,7 @@ pub fn rposition_slice_to_no_bounds_check(s: &[u8]) -> &[u8] { // CHECK-NOT: slice_end_index_len_fail // CHECK-NOT: panic_bounds_check // CHECK-NOT: unreachable - if let Some(idx) = s.iter().rposition(|b| *b == b'\\') { - &s[..idx] - } else { - s - } + if let Some(idx) = s.iter().rposition(|b| *b == b'\\') { &s[..idx] } else { s } } // CHECK-LABEL: @rposition_slice_from_no_bounds_check @@ -71,11 +55,7 @@ pub fn rposition_slice_from_no_bounds_check(s: &[u8]) -> &[u8] { // CHECK-NOT: slice_end_index_len_fail // CHECK-NOT: panic_bounds_check // CHECK-NOT: unreachable - if let Some(idx) = s.iter().rposition(|b| *b == b'\\') { - &s[idx..] - } else { - s - } + if let Some(idx) = s.iter().rposition(|b| *b == b'\\') { &s[idx..] } else { s } } // CHECK-LABEL: @rposition_index_no_bounds_check @@ -86,9 +66,5 @@ pub fn rposition_index_no_bounds_check(s: &[u8]) -> u8 { // CHECK-NOT: slice_end_index_len_fail // CHECK-NOT: panic_bounds_check // CHECK-NOT: unreachable - if let Some(idx) = s.iter().rposition(|b| *b == b'\\') { - s[idx] - } else { - 42 - } + if let Some(idx) = s.iter().rposition(|b| *b == b'\\') { s[idx] } else { 42 } } diff --git a/tests/codegen/issues/issue-75546.rs b/tests/codegen/issues/issue-75546.rs index 992ef97d6242..1132c8ab5093 100644 --- a/tests/codegen/issues/issue-75546.rs +++ b/tests/codegen/issues/issue-75546.rs @@ -9,7 +9,9 @@ pub fn issue_75546() { let mut i = 1u32; while i < u32::MAX { // CHECK-NOT: panic - if i == 0 { panic!(); } + if i == 0 { + panic!(); + } i += 1; } } diff --git a/tests/codegen/issues/issue-77812.rs b/tests/codegen/issues/issue-77812.rs index b9ce0a4f7db2..bf84ac21b16d 100644 --- a/tests/codegen/issues/issue-77812.rs +++ b/tests/codegen/issues/issue-77812.rs @@ -10,7 +10,7 @@ pub enum Variant { Two, } -extern { +extern "C" { fn exf1(); fn exf2(); } diff --git a/tests/codegen/issues/issue-84268.rs b/tests/codegen/issues/issue-84268.rs index 1e3950609b33..5e852133ed3d 100644 --- a/tests/codegen/issues/issue-84268.rs +++ b/tests/codegen/issues/issue-84268.rs @@ -17,7 +17,5 @@ pub struct M([i32; 4]); pub fn is_infinite(v: V) -> M { // CHECK: fabs // CHECK: cmp oeq - unsafe { - simd_eq(simd_fabs(v), V([f32::INFINITY; 4])) - } + unsafe { simd_eq(simd_fabs(v), V([f32::INFINITY; 4])) } } diff --git a/tests/codegen/issues/issue-96497-slice-size-nowrap.rs b/tests/codegen/issues/issue-96497-slice-size-nowrap.rs index c2b262b3334c..f922462cc279 100644 --- a/tests/codegen/issues/issue-96497-slice-size-nowrap.rs +++ b/tests/codegen/issues/issue-96497-slice-size-nowrap.rs @@ -4,7 +4,7 @@ //@ compile-flags: -O -#![crate_type="lib"] +#![crate_type = "lib"] // CHECK-LABEL: @simple_size_of_nowrap #[no_mangle] diff --git a/tests/codegen/issues/issue-99960.rs b/tests/codegen/issues/issue-99960.rs index 075495061750..9029121d35f4 100644 --- a/tests/codegen/issues/issue-99960.rs +++ b/tests/codegen/issues/issue-99960.rs @@ -6,9 +6,5 @@ pub fn test(dividend: i64, divisor: i64) -> Option { // CHECK-LABEL: @test( // CHECK-NOT: panic - if dividend > i64::min_value() && divisor != 0 { - Some(dividend / divisor) - } else { - None - } + if dividend > i64::min_value() && divisor != 0 { Some(dividend / divisor) } else { None } } diff --git a/tests/codegen/lib-optimizations/iter-sum.rs b/tests/codegen/lib-optimizations/iter-sum.rs index b563a6debb52..ea8c916bfc1b 100644 --- a/tests/codegen/lib-optimizations/iter-sum.rs +++ b/tests/codegen/lib-optimizations/iter-sum.rs @@ -2,7 +2,6 @@ //@ only-x86_64 (vectorization varies between architectures) #![crate_type = "lib"] - // Ensure that slice + take + sum gets vectorized. // Currently this relies on the slice::Iter::try_fold implementation // CHECK-LABEL: @slice_take_sum diff --git a/tests/codegen/lifetime_start_end.rs b/tests/codegen/lifetime_start_end.rs index 38e878451588..99d37c25dcac 100644 --- a/tests/codegen/lifetime_start_end.rs +++ b/tests/codegen/lifetime_start_end.rs @@ -8,27 +8,27 @@ pub fn test() { let a = 0u8; &a; // keep variable in an alloca -// CHECK: call void @llvm.lifetime.start{{.*}}(i{{[0-9 ]+}}, ptr %a) + // CHECK: call void @llvm.lifetime.start{{.*}}(i{{[0-9 ]+}}, ptr %a) { let b = &Some(a); &b; // keep variable in an alloca -// CHECK: call void @llvm.lifetime.start{{.*}}(i{{[0-9 ]+}}, {{.*}}) + // CHECK: call void @llvm.lifetime.start{{.*}}(i{{[0-9 ]+}}, {{.*}}) -// CHECK: call void @llvm.lifetime.start{{.*}}(i{{[0-9 ]+}}, {{.*}}) + // CHECK: call void @llvm.lifetime.start{{.*}}(i{{[0-9 ]+}}, {{.*}}) -// CHECK: call void @llvm.lifetime.end{{.*}}(i{{[0-9 ]+}}, {{.*}}) + // CHECK: call void @llvm.lifetime.end{{.*}}(i{{[0-9 ]+}}, {{.*}}) -// CHECK: call void @llvm.lifetime.end{{.*}}(i{{[0-9 ]+}}, {{.*}}) + // CHECK: call void @llvm.lifetime.end{{.*}}(i{{[0-9 ]+}}, {{.*}}) } let c = 1u8; &c; // keep variable in an alloca -// CHECK: call void @llvm.lifetime.start{{.*}}(i{{[0-9 ]+}}, ptr %c) + // CHECK: call void @llvm.lifetime.start{{.*}}(i{{[0-9 ]+}}, ptr %c) -// CHECK: call void @llvm.lifetime.end{{.*}}(i{{[0-9 ]+}}, ptr %c) + // CHECK: call void @llvm.lifetime.end{{.*}}(i{{[0-9 ]+}}, ptr %c) -// CHECK: call void @llvm.lifetime.end{{.*}}(i{{[0-9 ]+}}, ptr %a) + // CHECK: call void @llvm.lifetime.end{{.*}}(i{{[0-9 ]+}}, ptr %a) } diff --git a/tests/codegen/link-dead-code.rs b/tests/codegen/link-dead-code.rs index 7769622233f6..93e1d84d9c70 100644 --- a/tests/codegen/link-dead-code.rs +++ b/tests/codegen/link-dead-code.rs @@ -8,15 +8,21 @@ // CHECK-LABEL: ; link_dead_code::const_fn // CHECK-NEXT: ; Function Attrs: // CHECK-NEXT: define hidden -const fn const_fn() -> i32 { 1 } +const fn const_fn() -> i32 { + 1 +} // CHECK-LABEL: ; link_dead_code::inline_fn // CHECK-NEXT: ; Function Attrs: // CHECK-NEXT: define hidden #[inline] -fn inline_fn() -> i32 { 2 } +fn inline_fn() -> i32 { + 2 +} // CHECK-LABEL: ; link_dead_code::private_fn // CHECK-NEXT: ; Function Attrs: // CHECK-NEXT: define hidden -fn private_fn() -> i32 { 3 } +fn private_fn() -> i32 { + 3 +} diff --git a/tests/codegen/link_section.rs b/tests/codegen/link_section.rs index 281d3fb99d46..196f5edb7d63 100644 --- a/tests/codegen/link_section.rs +++ b/tests/codegen/link_section.rs @@ -16,7 +16,7 @@ pub static VAR1: u32 = 0x01000000; pub enum E { A(u32), - B(f32) + B(f32), } // CHECK: @VAR2 = {{(dso_local )?}}constant {{.*}}, section ".test_two" diff --git a/tests/codegen/loongarch-abi/loongarch64-lp64d-abi.rs b/tests/codegen/loongarch-abi/loongarch64-lp64d-abi.rs index d978f2d25254..cba1a980caa7 100644 --- a/tests/codegen/loongarch-abi/loongarch64-lp64d-abi.rs +++ b/tests/codegen/loongarch-abi/loongarch64-lp64d-abi.rs @@ -6,9 +6,12 @@ #![no_std] #![no_core] -#[lang="sized"] trait Sized { } -#[lang="freeze"] trait Freeze { } -#[lang="copy"] trait Copy { } +#[lang = "sized"] +trait Sized {} +#[lang = "freeze"] +trait Freeze {} +#[lang = "copy"] +trait Copy {} // CHECK: define void @f_fpr_tracking(double %0, double %1, double %2, double %3, double %4, double %5, double %6, double %7, i8 noundef zeroext %i) #[no_mangle] diff --git a/tests/codegen/lto-removes-invokes.rs b/tests/codegen/lto-removes-invokes.rs index f0102c25d5bd..3217c239bf78 100644 --- a/tests/codegen/lto-removes-invokes.rs +++ b/tests/codegen/lto-removes-invokes.rs @@ -10,8 +10,8 @@ fn main() { fn foo() { let _a = Box::new(3); bar(); -// CHECK-LABEL: define dso_local void @foo -// CHECK: call void @bar + // CHECK-LABEL: define dso_local void @foo + // CHECK: call void @bar } #[inline(never)] diff --git a/tests/codegen/macos/i686-macosx-deployment-target.rs b/tests/codegen/macos/i686-macosx-deployment-target.rs index b854476de418..389434da1f67 100644 --- a/tests/codegen/macos/i686-macosx-deployment-target.rs +++ b/tests/codegen/macos/i686-macosx-deployment-target.rs @@ -8,12 +8,12 @@ #![feature(no_core, lang_items)] #![no_core] -#[lang="sized"] -trait Sized { } -#[lang="freeze"] -trait Freeze { } -#[lang="copy"] -trait Copy { } +#[lang = "sized"] +trait Sized {} +#[lang = "freeze"] +trait Freeze {} +#[lang = "copy"] +trait Copy {} #[repr(C)] pub struct Bool { diff --git a/tests/codegen/macos/i686-no-macosx-deployment-target.rs b/tests/codegen/macos/i686-no-macosx-deployment-target.rs index a49a3467e7a0..4c6b7656e593 100644 --- a/tests/codegen/macos/i686-no-macosx-deployment-target.rs +++ b/tests/codegen/macos/i686-no-macosx-deployment-target.rs @@ -8,12 +8,12 @@ #![feature(no_core, lang_items)] #![no_core] -#[lang="sized"] -trait Sized { } -#[lang="freeze"] -trait Freeze { } -#[lang="copy"] -trait Copy { } +#[lang = "sized"] +trait Sized {} +#[lang = "freeze"] +trait Freeze {} +#[lang = "copy"] +trait Copy {} #[repr(C)] pub struct Bool { diff --git a/tests/codegen/macos/x86_64-macosx-deployment-target.rs b/tests/codegen/macos/x86_64-macosx-deployment-target.rs index eac989c29541..a40deca24bbe 100644 --- a/tests/codegen/macos/x86_64-macosx-deployment-target.rs +++ b/tests/codegen/macos/x86_64-macosx-deployment-target.rs @@ -8,12 +8,12 @@ #![feature(no_core, lang_items)] #![no_core] -#[lang="sized"] -trait Sized { } -#[lang="freeze"] -trait Freeze { } -#[lang="copy"] -trait Copy { } +#[lang = "sized"] +trait Sized {} +#[lang = "freeze"] +trait Freeze {} +#[lang = "copy"] +trait Copy {} #[repr(C)] pub struct Bool { diff --git a/tests/codegen/macos/x86_64-no-macosx-deployment-target.rs b/tests/codegen/macos/x86_64-no-macosx-deployment-target.rs index ed294cf4e3dc..26d519ef1a6d 100644 --- a/tests/codegen/macos/x86_64-no-macosx-deployment-target.rs +++ b/tests/codegen/macos/x86_64-no-macosx-deployment-target.rs @@ -8,12 +8,12 @@ #![feature(no_core, lang_items)] #![no_core] -#[lang="sized"] -trait Sized { } -#[lang="freeze"] -trait Freeze { } -#[lang="copy"] -trait Copy { } +#[lang = "sized"] +trait Sized {} +#[lang = "freeze"] +trait Freeze {} +#[lang = "copy"] +trait Copy {} #[repr(C)] pub struct Bool { diff --git a/tests/codegen/match-optimized.rs b/tests/codegen/match-optimized.rs index 5cecafb9f29c..d6893be0b7be 100644 --- a/tests/codegen/match-optimized.rs +++ b/tests/codegen/match-optimized.rs @@ -11,23 +11,23 @@ pub enum E { // CHECK-LABEL: @exhaustive_match #[no_mangle] pub fn exhaustive_match(e: E) -> u8 { -// CHECK: switch{{.*}}, label %[[OTHERWISE:[a-zA-Z0-9_]+]] [ -// CHECK-NEXT: i[[TY:[0-9]+]] [[DISCR:[0-9]+]], label %[[A:[a-zA-Z0-9_]+]] -// CHECK-NEXT: i[[TY:[0-9]+]] [[DISCR:[0-9]+]], label %[[B:[a-zA-Z0-9_]+]] -// CHECK-NEXT: i[[TY:[0-9]+]] [[DISCR:[0-9]+]], label %[[C:[a-zA-Z0-9_]+]] -// CHECK-NEXT: ] -// CHECK: [[OTHERWISE]]: -// CHECK-NEXT: unreachable -// -// CHECK: [[A]]: -// CHECK-NEXT: store i8 0, ptr %_0, align 1 -// CHECK-NEXT: br label %[[EXIT:[a-zA-Z0-9_]+]] -// CHECK: [[B]]: -// CHECK-NEXT: store i8 1, ptr %_0, align 1 -// CHECK-NEXT: br label %[[EXIT]] -// CHECK: [[C]]: -// CHECK-NEXT: store i8 3, ptr %_0, align 1 -// CHECK-NEXT: br label %[[EXIT]] + // CHECK: switch{{.*}}, label %[[OTHERWISE:[a-zA-Z0-9_]+]] [ + // CHECK-NEXT: i[[TY:[0-9]+]] [[DISCR:[0-9]+]], label %[[A:[a-zA-Z0-9_]+]] + // CHECK-NEXT: i[[TY:[0-9]+]] [[DISCR:[0-9]+]], label %[[B:[a-zA-Z0-9_]+]] + // CHECK-NEXT: i[[TY:[0-9]+]] [[DISCR:[0-9]+]], label %[[C:[a-zA-Z0-9_]+]] + // CHECK-NEXT: ] + // CHECK: [[OTHERWISE]]: + // CHECK-NEXT: unreachable + // + // CHECK: [[A]]: + // CHECK-NEXT: store i8 0, ptr %_0, align 1 + // CHECK-NEXT: br label %[[EXIT:[a-zA-Z0-9_]+]] + // CHECK: [[B]]: + // CHECK-NEXT: store i8 1, ptr %_0, align 1 + // CHECK-NEXT: br label %[[EXIT]] + // CHECK: [[C]]: + // CHECK-NEXT: store i8 3, ptr %_0, align 1 + // CHECK-NEXT: br label %[[EXIT]] match e { E::A => 0, E::B => 1, diff --git a/tests/codegen/match-optimizes-away.rs b/tests/codegen/match-optimizes-away.rs index 55ece89cec21..82ab5718b375 100644 --- a/tests/codegen/match-optimizes-away.rs +++ b/tests/codegen/match-optimizes-away.rs @@ -1,11 +1,20 @@ // //@ compile-flags: -O -#![crate_type="lib"] +#![crate_type = "lib"] -pub enum Three { A, B, C } +pub enum Three { + A, + B, + C, +} #[repr(u16)] -pub enum Four { A, B, C, D } +pub enum Four { + A, + B, + C, + D, +} #[no_mangle] pub fn three_valued(x: Three) -> Three { diff --git a/tests/codegen/mir_zst_stores.rs b/tests/codegen/mir_zst_stores.rs index 667273c2f0f7..ff1d429cffdb 100644 --- a/tests/codegen/mir_zst_stores.rs +++ b/tests/codegen/mir_zst_stores.rs @@ -4,7 +4,9 @@ use std::marker::PhantomData; #[derive(Copy, Clone)] -struct Zst { phantom: PhantomData } +struct Zst { + phantom: PhantomData, +} // CHECK-LABEL: @mir // CHECK-NOT: store{{.*}}undef diff --git a/tests/codegen/naked-fn/naked-functions.rs b/tests/codegen/naked-fn/naked-functions.rs index 3c426825537b..307745a921cf 100644 --- a/tests/codegen/naked-fn/naked-functions.rs +++ b/tests/codegen/naked-fn/naked-functions.rs @@ -14,8 +14,7 @@ pub unsafe extern "C" fn naked_empty() { // CHECK-NEXT: {{.+}}: // CHECK-NEXT: call void asm // CHECK-NEXT: unreachable - asm!("ret", - options(noreturn)); + asm!("ret", options(noreturn)); } // CHECK: Function Attrs: naked @@ -26,7 +25,5 @@ pub unsafe extern "C" fn naked_with_args_and_return(a: isize, b: isize) -> isize // CHECK-NEXT: {{.+}}: // CHECK-NEXT: call void asm // CHECK-NEXT: unreachable - asm!("lea rax, [rdi + rsi]", - "ret", - options(noreturn)); + asm!("lea rax, [rdi + rsi]", "ret", options(noreturn)); } diff --git a/tests/codegen/no-assumes-on-casts.rs b/tests/codegen/no-assumes-on-casts.rs index b9c264daa2d1..9c00dc2c0155 100644 --- a/tests/codegen/no-assumes-on-casts.rs +++ b/tests/codegen/no-assumes-on-casts.rs @@ -6,14 +6,14 @@ #[no_mangle] pub fn fna(a: i16) -> i32 { a as i32 -// CHECK-NOT: assume -// CHECK: sext + // CHECK-NOT: assume + // CHECK: sext } // CHECK-LABEL: fnb #[no_mangle] pub fn fnb(a: u16) -> u32 { a as u32 -// CHECK-NOT: assume -// CHECK: zext + // CHECK-NOT: assume + // CHECK: zext } diff --git a/tests/codegen/noalias-freeze.rs b/tests/codegen/noalias-freeze.rs index 8086f3afbbc8..32c840140260 100644 --- a/tests/codegen/noalias-freeze.rs +++ b/tests/codegen/noalias-freeze.rs @@ -8,7 +8,9 @@ #![crate_type = "lib"] -fn project(x: &(T,)) -> &T { &x.0 } +fn project(x: &(T,)) -> &T { + &x.0 +} fn dummy() {} diff --git a/tests/codegen/noalias-unpin.rs b/tests/codegen/noalias-unpin.rs index 546b1edb7b61..630a62020c11 100644 --- a/tests/codegen/noalias-unpin.rs +++ b/tests/codegen/noalias-unpin.rs @@ -4,7 +4,7 @@ pub struct SelfRef { self_ref: *mut SelfRef, - _pin: std::marker::PhantomPinned + _pin: std::marker::PhantomPinned, } // CHECK-LABEL: @test_self_ref( diff --git a/tests/codegen/non-terminate/infinite-recursion.rs b/tests/codegen/non-terminate/infinite-recursion.rs index 804704c0292e..19123639896b 100644 --- a/tests/codegen/non-terminate/infinite-recursion.rs +++ b/tests/codegen/non-terminate/infinite-recursion.rs @@ -1,7 +1,6 @@ //@ compile-flags: -C opt-level=3 #![crate_type = "lib"] - #![allow(unconditional_recursion)] // CHECK-LABEL: @infinite_recursion diff --git a/tests/codegen/noreturnflag.rs b/tests/codegen/noreturnflag.rs index a8f08628986a..d9bb30b2703a 100644 --- a/tests/codegen/noreturnflag.rs +++ b/tests/codegen/noreturnflag.rs @@ -4,7 +4,7 @@ #[no_mangle] pub fn foo() -> ! { -// CHECK: @foo() unnamed_addr #0 + // CHECK: @foo() unnamed_addr #0 loop {} } @@ -12,7 +12,7 @@ pub enum EmptyEnum {} #[no_mangle] pub fn bar() -> EmptyEnum { -// CHECK: @bar() unnamed_addr #0 + // CHECK: @bar() unnamed_addr #0 loop {} } diff --git a/tests/codegen/nounwind.rs b/tests/codegen/nounwind.rs index 2b237ef01208..464bc2535c2b 100644 --- a/tests/codegen/nounwind.rs +++ b/tests/codegen/nounwind.rs @@ -10,7 +10,7 @@ extern crate nounwind; #[no_mangle] pub fn foo() { nounwind::bar(); -// CHECK: @foo() unnamed_addr #0 -// CHECK: @bar() unnamed_addr #0 -// CHECK: attributes #0 = { {{.*}}nounwind{{.*}} } + // CHECK: @foo() unnamed_addr #0 + // CHECK: @bar() unnamed_addr #0 + // CHECK: attributes #0 = { {{.*}}nounwind{{.*}} } } diff --git a/tests/codegen/optimize-attr-1.rs b/tests/codegen/optimize-attr-1.rs index c8e68779aae6..3aee44791e0e 100644 --- a/tests/codegen/optimize-attr-1.rs +++ b/tests/codegen/optimize-attr-1.rs @@ -4,7 +4,7 @@ //@[SPEED-OPT] compile-flags: -Copt-level=3 -Ccodegen-units=1 #![feature(optimize_attribute)] -#![crate_type="rlib"] +#![crate_type = "rlib"] // CHECK-LABEL: define{{.*}}i32 @nothing // CHECK-SAME: [[NOTHING_ATTRS:#[0-9]+]] diff --git a/tests/codegen/option-niche-eq.rs b/tests/codegen/option-niche-eq.rs index 25ea5dd595c3..4d3a7ce3764b 100644 --- a/tests/codegen/option-niche-eq.rs +++ b/tests/codegen/option-niche-eq.rs @@ -4,8 +4,8 @@ extern crate core; use core::cmp::Ordering; -use core::ptr::NonNull; use core::num::NonZero; +use core::ptr::NonNull; // CHECK-LABEL: @non_zero_eq #[no_mangle] diff --git a/tests/codegen/packed.rs b/tests/codegen/packed.rs index 5142df9c4881..790d618b2ead 100644 --- a/tests/codegen/packed.rs +++ b/tests/codegen/packed.rs @@ -6,20 +6,20 @@ #[repr(packed)] pub struct Packed1 { dealign: u8, - data: u32 + data: u32, } #[repr(packed(2))] pub struct Packed2 { dealign: u8, - data: u32 + data: u32, } // CHECK-LABEL: @write_pkd1 #[no_mangle] pub fn write_pkd1(pkd: &mut Packed1) -> u32 { -// CHECK: %{{.*}} = load i32, ptr %{{.*}}, align 1 -// CHECK: store i32 42, ptr %{{.*}}, align 1 + // CHECK: %{{.*}} = load i32, ptr %{{.*}}, align 1 + // CHECK: store i32 42, ptr %{{.*}}, align 1 let result = pkd.data; pkd.data = 42; result @@ -28,8 +28,8 @@ pub fn write_pkd1(pkd: &mut Packed1) -> u32 { // CHECK-LABEL: @write_pkd2 #[no_mangle] pub fn write_pkd2(pkd: &mut Packed2) -> u32 { -// CHECK: %{{.*}} = load i32, ptr %{{.*}}, align 2 -// CHECK: store i32 42, ptr %{{.*}}, align 2 + // CHECK: %{{.*}} = load i32, ptr %{{.*}}, align 2 + // CHECK: store i32 42, ptr %{{.*}}, align 2 let result = pkd.data; pkd.data = 42; result @@ -39,21 +39,21 @@ pub struct Array([i32; 8]); #[repr(packed)] pub struct BigPacked1 { dealign: u8, - data: Array + data: Array, } #[repr(packed(2))] pub struct BigPacked2 { dealign: u8, - data: Array + data: Array, } // CHECK-LABEL: @call_pkd1 #[no_mangle] pub fn call_pkd1(f: fn() -> Array) -> BigPacked1 { -// CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca [32 x i8] -// CHECK: call void %{{.*}}(ptr noalias nocapture noundef sret{{.*}} dereferenceable(32) [[ALLOCA]]) -// CHECK: call void @llvm.memcpy.{{.*}}(ptr align 1 %{{.*}}, ptr align 4 %{{.*}}, i{{[0-9]+}} 32, i1 false) + // CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca [32 x i8] + // CHECK: call void %{{.*}}(ptr noalias nocapture noundef sret{{.*}} dereferenceable(32) [[ALLOCA]]) + // CHECK: call void @llvm.memcpy.{{.*}}(ptr align 1 %{{.*}}, ptr align 4 %{{.*}}, i{{[0-9]+}} 32, i1 false) // check that calls whose destination is a field of a packed struct // go through an alloca rather than calling the function with an // unaligned destination. @@ -63,9 +63,9 @@ pub fn call_pkd1(f: fn() -> Array) -> BigPacked1 { // CHECK-LABEL: @call_pkd2 #[no_mangle] pub fn call_pkd2(f: fn() -> Array) -> BigPacked2 { -// CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca [32 x i8] -// CHECK: call void %{{.*}}(ptr noalias nocapture noundef sret{{.*}} dereferenceable(32) [[ALLOCA]]) -// CHECK: call void @llvm.memcpy.{{.*}}(ptr align 2 %{{.*}}, ptr align 4 %{{.*}}, i{{[0-9]+}} 32, i1 false) + // CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca [32 x i8] + // CHECK: call void %{{.*}}(ptr noalias nocapture noundef sret{{.*}} dereferenceable(32) [[ALLOCA]]) + // CHECK: call void @llvm.memcpy.{{.*}}(ptr align 2 %{{.*}}, ptr align 4 %{{.*}}, i{{[0-9]+}} 32, i1 false) // check that calls whose destination is a field of a packed struct // go through an alloca rather than calling the function with an // unaligned destination. @@ -119,14 +119,14 @@ pub struct Packed2Pair(u8, u32); // CHECK-LABEL: @pkd1_pair #[no_mangle] pub fn pkd1_pair(pair1: &mut Packed1Pair, pair2: &mut Packed1Pair) { -// CHECK: call void @llvm.memcpy.{{.*}}(ptr align 1 %{{.*}}, ptr align 1 %{{.*}}, i{{[0-9]+}} 5, i1 false) + // CHECK: call void @llvm.memcpy.{{.*}}(ptr align 1 %{{.*}}, ptr align 1 %{{.*}}, i{{[0-9]+}} 5, i1 false) *pair2 = *pair1; } // CHECK-LABEL: @pkd2_pair #[no_mangle] pub fn pkd2_pair(pair1: &mut Packed2Pair, pair2: &mut Packed2Pair) { -// CHECK: call void @llvm.memcpy.{{.*}}(ptr align 2 %{{.*}}, ptr align 2 %{{.*}}, i{{[0-9]+}} 6, i1 false) + // CHECK: call void @llvm.memcpy.{{.*}}(ptr align 2 %{{.*}}, ptr align 2 %{{.*}}, i{{[0-9]+}} 6, i1 false) *pair2 = *pair1; } @@ -141,13 +141,13 @@ pub struct Packed2NestedPair((u32, u32)); // CHECK-LABEL: @pkd1_nested_pair #[no_mangle] pub fn pkd1_nested_pair(pair1: &mut Packed1NestedPair, pair2: &mut Packed1NestedPair) { -// CHECK: call void @llvm.memcpy.{{.*}}(ptr align 1 %{{.*}}, ptr align 1 %{{.*}}, i{{[0-9]+}} 8, i1 false) + // CHECK: call void @llvm.memcpy.{{.*}}(ptr align 1 %{{.*}}, ptr align 1 %{{.*}}, i{{[0-9]+}} 8, i1 false) *pair2 = *pair1; } // CHECK-LABEL: @pkd2_nested_pair #[no_mangle] pub fn pkd2_nested_pair(pair1: &mut Packed2NestedPair, pair2: &mut Packed2NestedPair) { -// CHECK: call void @llvm.memcpy.{{.*}}(ptr align 2 %{{.*}}, ptr align 2 %{{.*}}, i{{[0-9]+}} 8, i1 false) + // CHECK: call void @llvm.memcpy.{{.*}}(ptr align 2 %{{.*}}, ptr align 2 %{{.*}}, i{{[0-9]+}} 8, i1 false) *pair2 = *pair1; } diff --git a/tests/codegen/panic-abort-windows.rs b/tests/codegen/panic-abort-windows.rs index 71caa1b3d2af..eb61e649f04a 100644 --- a/tests/codegen/panic-abort-windows.rs +++ b/tests/codegen/panic-abort-windows.rs @@ -8,11 +8,9 @@ // CHECK: Function Attrs: nounwind uwtable // CHECK-NEXT: define void @normal_uwtable() #[no_mangle] -pub fn normal_uwtable() { -} +pub fn normal_uwtable() {} // CHECK: Function Attrs: nounwind uwtable // CHECK-NEXT: define void @extern_uwtable() #[no_mangle] -pub extern fn extern_uwtable() { -} +pub extern "C" fn extern_uwtable() {} diff --git a/tests/codegen/personality_lifetimes.rs b/tests/codegen/personality_lifetimes.rs index 0ef4aa424d83..828af05436b4 100644 --- a/tests/codegen/personality_lifetimes.rs +++ b/tests/codegen/personality_lifetimes.rs @@ -3,19 +3,17 @@ //@ compile-flags: -O -C no-prepopulate-passes -#![crate_type="lib"] +#![crate_type = "lib"] struct S; impl Drop for S { #[inline(never)] - fn drop(&mut self) { - } + fn drop(&mut self) {} } #[inline(never)] -fn might_unwind() { -} +fn might_unwind() {} // CHECK-LABEL: @test #[no_mangle] diff --git a/tests/codegen/pgo-instrumentation.rs b/tests/codegen/pgo-instrumentation.rs index e2c348edf822..b1906c145c6b 100644 --- a/tests/codegen/pgo-instrumentation.rs +++ b/tests/codegen/pgo-instrumentation.rs @@ -10,12 +10,10 @@ // CHECK-DAG: @__profd_{{.*}}pgo_instrumentation{{.*}}some_other_function{{.*}} = {{.*}}global // CHECK: @__llvm_profile_filename = {{.*}}"default_%m.profraw\00"{{.*}} -#![crate_type="lib"] +#![crate_type = "lib"] #[inline(never)] -fn some_function() { - -} +fn some_function() {} pub fn some_other_function() { some_function(); diff --git a/tests/codegen/pic-relocation-model.rs b/tests/codegen/pic-relocation-model.rs index 10ade847133a..a1d1678a6bda 100644 --- a/tests/codegen/pic-relocation-model.rs +++ b/tests/codegen/pic-relocation-model.rs @@ -5,15 +5,15 @@ // CHECK: define i8 @call_foreign_fn() #[no_mangle] pub fn call_foreign_fn() -> u8 { - unsafe { - foreign_fn() - } + unsafe { foreign_fn() } } // (Allow but do not require `zeroext` here, because it is not worth effort to // spell out which targets have it and which ones do not; see rust#97800.) // CHECK: declare{{( zeroext)?}} i8 @foreign_fn() -extern "C" {fn foreign_fn() -> u8;} +extern "C" { + fn foreign_fn() -> u8; +} // CHECK: !{i32 {{[78]}}, !"PIC Level", i32 2} diff --git a/tests/codegen/pie-relocation-model.rs b/tests/codegen/pie-relocation-model.rs index 20bf8919ac10..b10af6934522 100644 --- a/tests/codegen/pie-relocation-model.rs +++ b/tests/codegen/pie-relocation-model.rs @@ -8,15 +8,15 @@ // CHECK: define dso_local i8 @call_foreign_fn() #[no_mangle] pub fn call_foreign_fn() -> u8 { - unsafe { - foreign_fn() - } + unsafe { foreign_fn() } } // External functions are still marked as non-dso_local, since we don't know if the symbol // is defined in the binary or in the shared library. // CHECK: declare zeroext i8 @foreign_fn() -extern "C" {fn foreign_fn() -> u8;} +extern "C" { + fn foreign_fn() -> u8; +} // CHECK: !{i32 {{[78]}}, !"PIC Level", i32 2} // CHECK: !{i32 7, !"PIE Level", i32 2} diff --git a/tests/codegen/powerpc64le-struct-align-128.rs b/tests/codegen/powerpc64le-struct-align-128.rs index 0096c6d3138b..3981cd121296 100644 --- a/tests/codegen/powerpc64le-struct-align-128.rs +++ b/tests/codegen/powerpc64le-struct-align-128.rs @@ -8,12 +8,12 @@ #![crate_type = "lib"] #![no_core] -#[lang="sized"] -trait Sized { } -#[lang="freeze"] -trait Freeze { } -#[lang="copy"] -trait Copy { } +#[lang = "sized"] +trait Sized {} +#[lang = "freeze"] +trait Freeze {} +#[lang = "copy"] +trait Copy {} #[repr(C)] pub struct Align8 { @@ -23,7 +23,7 @@ pub struct Align8 { #[repr(transparent)] pub struct Transparent8 { - a: Align8 + a: Align8, } #[repr(C)] @@ -45,7 +45,7 @@ pub struct Align16 { #[repr(transparent)] pub struct Transparent16 { - a: Align16 + a: Align16, } #[repr(C)] @@ -69,7 +69,7 @@ pub struct Align32 { #[repr(transparent)] pub struct Transparent32 { - a: Align32 + a: Align32, } #[repr(C)] @@ -83,9 +83,15 @@ extern "C" { } pub unsafe fn main( - a1: Align8, a2: Transparent8, a3: Wrapped8, - b1: Align16, b2: Transparent16, b3: Wrapped16, - c1: Align32, c2: Transparent32, c3: Wrapped32, + a1: Align8, + a2: Transparent8, + a3: Wrapped8, + b1: Align16, + b2: Transparent16, + b3: Wrapped16, + c1: Align32, + c2: Transparent32, + c3: Wrapped32, ) { test_8(a1, a2, a3); test_16(b1, b2, b3); diff --git a/tests/codegen/precondition-checks.rs b/tests/codegen/precondition-checks.rs index 191494450037..16812ca17207 100644 --- a/tests/codegen/precondition-checks.rs +++ b/tests/codegen/precondition-checks.rs @@ -21,7 +21,5 @@ use std::ptr::NonNull; #[no_mangle] pub unsafe fn nonnull_new(ptr: *mut u8) -> NonNull { // CHECK: ; call core::ptr::non_null::NonNull::new_unchecked - unsafe { - NonNull::new_unchecked(ptr) - } + unsafe { NonNull::new_unchecked(ptr) } } diff --git a/tests/codegen/refs.rs b/tests/codegen/refs.rs index 40ce04c07a11..97c362950855 100644 --- a/tests/codegen/refs.rs +++ b/tests/codegen/refs.rs @@ -5,17 +5,16 @@ // Hack to get the correct size for the length part in slices // CHECK: @helper([[USIZE:i[0-9]+]] %_1) #[no_mangle] -pub fn helper(_: usize) { -} +pub fn helper(_: usize) {} // CHECK-LABEL: @ref_dst #[no_mangle] pub fn ref_dst(s: &[u8]) { // We used to generate an extra alloca and memcpy to ref the dst, so check that we copy // directly to the alloca for "x" -// CHECK: store ptr %s.0, {{.*}} %x -// CHECK: [[X1:%[0-9]+]] = getelementptr inbounds i8, {{.*}} %x, {{i32 4|i64 8}} -// CHECK: store [[USIZE]] %s.1, {{.*}} [[X1]] + // CHECK: store ptr %s.0, {{.*}} %x + // CHECK: [[X1:%[0-9]+]] = getelementptr inbounds i8, {{.*}} %x, {{i32 4|i64 8}} + // CHECK: store [[USIZE]] %s.1, {{.*}} [[X1]] let x = &*s; &x; // keep variable in an alloca diff --git a/tests/codegen/repr/transparent-imm-array.rs b/tests/codegen/repr/transparent-imm-array.rs index 917a2c6ef527..1acd4742d356 100644 --- a/tests/codegen/repr/transparent-imm-array.rs +++ b/tests/codegen/repr/transparent-imm-array.rs @@ -26,15 +26,17 @@ #![no_std] #![no_core] -#[lang="sized"] trait Sized { } -#[lang="freeze"] trait Freeze { } -#[lang="copy"] trait Copy { } +#[lang = "sized"] +trait Sized {} +#[lang = "freeze"] +trait Freeze {} +#[lang = "copy"] +trait Copy {} impl Copy for [u32; 16] {} impl Copy for BigS {} impl Copy for BigU {} - #[repr(C)] pub struct BigS([u32; 16]); @@ -53,20 +55,27 @@ pub enum TeBigS { // CHECK: define void @test_BigS(ptr [[BIGS_RET_ATTRS1:.*]] sret([64 x i8]) [[BIGS_RET_ATTRS2:.*]], [16 x i32] #[no_mangle] -pub extern fn test_BigS(_: BigS) -> BigS { loop {} } +pub extern "C" fn test_BigS(_: BigS) -> BigS { + loop {} +} // CHECK: define void @test_TsBigS(ptr [[BIGS_RET_ATTRS1]] sret([64 x i8]) [[BIGS_RET_ATTRS2]], [16 x i32] #[no_mangle] -pub extern fn test_TsBigS(_: TsBigS) -> TsBigS { loop {} } +pub extern "C" fn test_TsBigS(_: TsBigS) -> TsBigS { + loop {} +} // CHECK: define void @test_TuBigS(ptr [[BIGS_RET_ATTRS1]] sret([64 x i8]) [[BIGS_RET_ATTRS2]], [16 x i32] #[no_mangle] -pub extern fn test_TuBigS(_: TuBigS) -> TuBigS { loop {} } +pub extern "C" fn test_TuBigS(_: TuBigS) -> TuBigS { + loop {} +} // CHECK: define void @test_TeBigS(ptr [[BIGS_RET_ATTRS1]] sret([64 x i8]) [[BIGS_RET_ATTRS2]], [16 x i32] #[no_mangle] -pub extern fn test_TeBigS(_: TeBigS) -> TeBigS { loop {} } - +pub extern "C" fn test_TeBigS(_: TeBigS) -> TeBigS { + loop {} +} #[repr(C)] pub union BigU { @@ -88,16 +97,24 @@ pub enum TeBigU { // CHECK: define void @test_BigU(ptr [[BIGU_RET_ATTRS1:.*]] sret([64 x i8]) [[BIGU_RET_ATTRS2:.*]], [16 x i32] #[no_mangle] -pub extern fn test_BigU(_: BigU) -> BigU { loop {} } +pub extern "C" fn test_BigU(_: BigU) -> BigU { + loop {} +} // CHECK: define void @test_TsBigU(ptr [[BIGU_RET_ATTRS1]] sret([64 x i8]) [[BIGU_RET_ATTRS2]], [16 x i32] #[no_mangle] -pub extern fn test_TsBigU(_: TsBigU) -> TsBigU { loop {} } +pub extern "C" fn test_TsBigU(_: TsBigU) -> TsBigU { + loop {} +} // CHECK: define void @test_TuBigU(ptr [[BIGU_RET_ATTRS1]] sret([64 x i8]) [[BIGU_RET_ATTRS2]], [16 x i32] #[no_mangle] -pub extern fn test_TuBigU(_: TuBigU) -> TuBigU { loop {} } +pub extern "C" fn test_TuBigU(_: TuBigU) -> TuBigU { + loop {} +} // CHECK: define void @test_TeBigU(ptr [[BIGU_RET_ATTRS1]] sret([64 x i8]) [[BIGU_RET_ATTRS2]], [16 x i32] #[no_mangle] -pub extern fn test_TeBigU(_: TeBigU) -> TeBigU { loop {} } +pub extern "C" fn test_TeBigU(_: TeBigU) -> TeBigU { + loop {} +} diff --git a/tests/codegen/repr/transparent-mips64.rs b/tests/codegen/repr/transparent-mips64.rs index ebed8d7989fd..588d440b4d7b 100644 --- a/tests/codegen/repr/transparent-mips64.rs +++ b/tests/codegen/repr/transparent-mips64.rs @@ -13,9 +13,12 @@ #![no_std] #![no_core] -#[lang="sized"] trait Sized { } -#[lang="freeze"] trait Freeze { } -#[lang="copy"] trait Copy { } +#[lang = "sized"] +trait Sized {} +#[lang = "freeze"] +trait Freeze {} +#[lang = "copy"] +trait Copy {} impl Copy for [u32; 16] {} impl Copy for BigS {} @@ -39,20 +42,27 @@ pub enum TeBigS { // CHECK: define void @test_BigS(ptr [[BIGS_RET_ATTRS1:.*]] sret([64 x i8]) [[BIGS_RET_ATTRS2:.*]], [8 x i64] #[no_mangle] -pub extern fn test_BigS(_: BigS) -> BigS { loop {} } +pub extern "C" fn test_BigS(_: BigS) -> BigS { + loop {} +} // CHECK: define void @test_TsBigS(ptr [[BIGS_RET_ATTRS1]] sret([64 x i8]) [[BIGS_RET_ATTRS2]], [8 x i64] #[no_mangle] -pub extern fn test_TsBigS(_: TsBigS) -> TsBigS { loop {} } +pub extern "C" fn test_TsBigS(_: TsBigS) -> TsBigS { + loop {} +} // CHECK: define void @test_TuBigS(ptr [[BIGS_RET_ATTRS1]] sret([64 x i8]) [[BIGS_RET_ATTRS2]], [8 x i64] #[no_mangle] -pub extern fn test_TuBigS(_: TuBigS) -> TuBigS { loop {} } +pub extern "C" fn test_TuBigS(_: TuBigS) -> TuBigS { + loop {} +} // CHECK: define void @test_TeBigS(ptr [[BIGS_RET_ATTRS1]] sret([64 x i8]) [[BIGS_RET_ATTRS2]], [8 x i64] #[no_mangle] -pub extern fn test_TeBigS(_: TeBigS) -> TeBigS { loop {} } - +pub extern "C" fn test_TeBigS(_: TeBigS) -> TeBigS { + loop {} +} #[repr(C)] pub union BigU { @@ -74,16 +84,24 @@ pub enum TeBigU { // CHECK: define void @test_BigU(ptr [[BIGU_RET_ATTRS1:.*]] sret([64 x i8]) [[BIGU_RET_ATTRS2:.*]], [8 x i64] #[no_mangle] -pub extern fn test_BigU(_: BigU) -> BigU { loop {} } +pub extern "C" fn test_BigU(_: BigU) -> BigU { + loop {} +} // CHECK: define void @test_TsBigU(ptr [[BIGU_RET_ATTRS1]] sret([64 x i8]) [[BIGU_RET_ATTRS2]], [8 x i64] #[no_mangle] -pub extern fn test_TsBigU(_: TsBigU) -> TsBigU { loop {} } +pub extern "C" fn test_TsBigU(_: TsBigU) -> TsBigU { + loop {} +} // CHECK: define void @test_TuBigU(ptr [[BIGU_RET_ATTRS1]] sret([64 x i8]) [[BIGU_RET_ATTRS2]], [8 x i64] #[no_mangle] -pub extern fn test_TuBigU(_: TuBigU) -> TuBigU { loop {} } +pub extern "C" fn test_TuBigU(_: TuBigU) -> TuBigU { + loop {} +} // CHECK: define void @test_TeBigU(ptr [[BIGU_RET_ATTRS1]] sret([64 x i8]) [[BIGU_RET_ATTRS2]], [8 x i64] #[no_mangle] -pub extern fn test_TeBigU(_: TeBigU) -> TeBigU { loop {} } +pub extern "C" fn test_TeBigU(_: TeBigU) -> TeBigU { + loop {} +} diff --git a/tests/codegen/repr/transparent-sparc64.rs b/tests/codegen/repr/transparent-sparc64.rs index 7005a07f554f..8e4c8ce2ee9b 100644 --- a/tests/codegen/repr/transparent-sparc64.rs +++ b/tests/codegen/repr/transparent-sparc64.rs @@ -8,15 +8,17 @@ #![no_std] #![no_core] -#[lang="sized"] trait Sized { } -#[lang="freeze"] trait Freeze { } -#[lang="copy"] trait Copy { } +#[lang = "sized"] +trait Sized {} +#[lang = "freeze"] +trait Freeze {} +#[lang = "copy"] +trait Copy {} impl Copy for [u32; 16] {} impl Copy for BigS {} impl Copy for BigU {} - #[repr(C)] pub struct BigS([u32; 16]); @@ -37,26 +39,33 @@ pub enum TeBigS { // CHECK-NOT: byval // CHECK-SAME: %{{[0-9a-z_]+}}) #[no_mangle] -pub extern "C" fn test_BigS(_: BigS) -> BigS { loop {} } +pub extern "C" fn test_BigS(_: BigS) -> BigS { + loop {} +} // CHECK: define{{.*}}void @test_TsBigS(ptr [[BIGS_RET_ATTRS1]] sret([64 x i8]) [[BIGS_RET_ATTRS2]], ptr // CHECK-NOT: byval // CHECK-SAME: %{{[0-9a-z_]+}}) #[no_mangle] -pub extern "C" fn test_TsBigS(_: TsBigS) -> TsBigS { loop {} } +pub extern "C" fn test_TsBigS(_: TsBigS) -> TsBigS { + loop {} +} // CHECK: define{{.*}}void @test_TuBigS(ptr [[BIGS_RET_ATTRS1]] sret([64 x i8]) [[BIGS_RET_ATTRS2]], ptr // CHECK-NOT: byval // CHECK-SAME: %{{[0-9a-z_]+}}) #[no_mangle] -pub extern "C" fn test_TuBigS(_: TuBigS) -> TuBigS { loop {} } +pub extern "C" fn test_TuBigS(_: TuBigS) -> TuBigS { + loop {} +} // CHECK: define{{.*}}void @test_TeBigS(ptr [[BIGS_RET_ATTRS1]] sret([64 x i8]) [[BIGS_RET_ATTRS2]], ptr // CHECK-NOT: byval // CHECK-SAME: %{{[0-9a-z_]+}}) #[no_mangle] -pub extern "C" fn test_TeBigS(_: TeBigS) -> TeBigS { loop {} } - +pub extern "C" fn test_TeBigS(_: TeBigS) -> TeBigS { + loop {} +} #[repr(C)] pub union BigU { @@ -80,22 +89,30 @@ pub enum TeBigU { // CHECK-NOT: byval // CHECK-SAME: %{{[0-9a-z_]+}}) #[no_mangle] -pub extern "C" fn test_BigU(_: BigU) -> BigU { loop {} } +pub extern "C" fn test_BigU(_: BigU) -> BigU { + loop {} +} // CHECK: define{{.*}}void @test_TsBigU(ptr [[BIGU_RET_ATTRS1:.*]] sret([64 x i8]) [[BIGU_RET_ATTRS2:.*]], ptr // CHECK-NOT: byval // CHECK-SAME: %{{[0-9a-z_]+}}) #[no_mangle] -pub extern "C" fn test_TsBigU(_: TsBigU) -> TsBigU { loop {} } +pub extern "C" fn test_TsBigU(_: TsBigU) -> TsBigU { + loop {} +} // CHECK: define{{.*}}void @test_TuBigU(ptr [[BIGU_RET_ATTRS1]] sret([64 x i8]) [[BIGU_RET_ATTRS2:.*]], ptr // CHECK-NOT: byval // CHECK-SAME: %{{[0-9a-z_]+}}) #[no_mangle] -pub extern "C" fn test_TuBigU(_: TuBigU) -> TuBigU { loop {} } +pub extern "C" fn test_TuBigU(_: TuBigU) -> TuBigU { + loop {} +} // CHECK: define{{.*}}void @test_TeBigU(ptr [[BIGU_RET_ATTRS1]] sret([64 x i8]) [[BIGU_RET_ATTRS2:.*]], ptr // CHECK-NOT: byval // CHECK-SAME: %{{[0-9a-z_]+}}) #[no_mangle] -pub extern "C" fn test_TeBigU(_: TeBigU) -> TeBigU { loop {} } +pub extern "C" fn test_TeBigU(_: TeBigU) -> TeBigU { + loop {} +} diff --git a/tests/codegen/repr/transparent-struct-ptr.rs b/tests/codegen/repr/transparent-struct-ptr.rs index 26f0120752f2..9cffd6c7f732 100644 --- a/tests/codegen/repr/transparent-struct-ptr.rs +++ b/tests/codegen/repr/transparent-struct-ptr.rs @@ -22,15 +22,17 @@ #![no_std] #![no_core] -#[lang="sized"] trait Sized { } -#[lang="freeze"] trait Freeze { } -#[lang="copy"] trait Copy { } +#[lang = "sized"] +trait Sized {} +#[lang = "freeze"] +trait Freeze {} +#[lang = "copy"] +trait Copy {} impl Copy for [u32; 16] {} impl Copy for BigS {} impl Copy for BigU {} - #[repr(C)] pub struct BigS([u32; 16]); @@ -49,20 +51,27 @@ pub enum TeBigS { // CHECK: define{{.*}}void @test_BigS(ptr [[BIGS_RET_ATTRS1:.*]] sret([64 x i8]) [[BIGS_RET_ATTRS2:.*]], ptr [[BIGS_ARG_ATTRS1:.*]] byval([64 x i8]) [[BIGS_ARG_ATTRS2:.*]]) #[no_mangle] -pub extern "C" fn test_BigS(_: BigS) -> BigS { loop {} } +pub extern "C" fn test_BigS(_: BigS) -> BigS { + loop {} +} // CHECK: define{{.*}}void @test_TsBigS(ptr [[BIGS_RET_ATTRS1]] sret([64 x i8]) [[BIGS_RET_ATTRS2]], ptr [[BIGS_ARG_ATTRS1]] byval([64 x i8]) [[BIGS_ARG_ATTRS2:.*]]) #[no_mangle] -pub extern "C" fn test_TsBigS(_: TsBigS) -> TsBigS { loop {} } +pub extern "C" fn test_TsBigS(_: TsBigS) -> TsBigS { + loop {} +} // CHECK: define{{.*}}void @test_TuBigS(ptr [[BIGS_RET_ATTRS1]] sret([64 x i8]) [[BIGS_RET_ATTRS2]], ptr [[BIGS_ARG_ATTRS1]] byval([64 x i8]) [[BIGS_ARG_ATTRS2:.*]]) #[no_mangle] -pub extern "C" fn test_TuBigS(_: TuBigS) -> TuBigS { loop {} } +pub extern "C" fn test_TuBigS(_: TuBigS) -> TuBigS { + loop {} +} // CHECK: define{{.*}}void @test_TeBigS(ptr [[BIGS_RET_ATTRS1]] sret([64 x i8]) [[BIGS_RET_ATTRS2]], ptr [[BIGS_ARG_ATTRS1]] byval([64 x i8]) [[BIGS_ARG_ATTRS2]]) #[no_mangle] -pub extern "C" fn test_TeBigS(_: TeBigS) -> TeBigS { loop {} } - +pub extern "C" fn test_TeBigS(_: TeBigS) -> TeBigS { + loop {} +} #[repr(C)] pub union BigU { @@ -84,16 +93,24 @@ pub enum TeBigU { // CHECK: define{{.*}}void @test_BigU(ptr [[BIGU_RET_ATTRS1:.*]] sret([64 x i8]) [[BIGU_RET_ATTRS2:.*]], ptr [[BIGU_ARG_ATTRS1:.*]] byval([64 x i8]) [[BIGU_ARG_ATTRS2:.*]]) #[no_mangle] -pub extern "C" fn test_BigU(_: BigU) -> BigU { loop {} } +pub extern "C" fn test_BigU(_: BigU) -> BigU { + loop {} +} // CHECK: define{{.*}}void @test_TsBigU(ptr [[BIGU_RET_ATTRS1:.*]] sret([64 x i8]) [[BIGU_RET_ATTRS2:.*]], ptr [[BIGU_ARG_ATTRS1]] byval([64 x i8]) [[BIGU_ARG_ATTRS2]]) #[no_mangle] -pub extern "C" fn test_TsBigU(_: TsBigU) -> TsBigU { loop {} } +pub extern "C" fn test_TsBigU(_: TsBigU) -> TsBigU { + loop {} +} // CHECK: define{{.*}}void @test_TuBigU(ptr [[BIGU_RET_ATTRS1]] sret([64 x i8]) [[BIGU_RET_ATTRS2:.*]], ptr [[BIGU_ARG_ATTRS1]] byval([64 x i8]) [[BIGU_ARG_ATTRS2]]) #[no_mangle] -pub extern "C" fn test_TuBigU(_: TuBigU) -> TuBigU { loop {} } +pub extern "C" fn test_TuBigU(_: TuBigU) -> TuBigU { + loop {} +} // CHECK: define{{.*}}void @test_TeBigU(ptr [[BIGU_RET_ATTRS1]] sret([64 x i8]) [[BIGU_RET_ATTRS2:.*]], ptr [[BIGU_ARG_ATTRS1]] byval([64 x i8]) [[BIGU_ARG_ATTRS2]]) #[no_mangle] -pub extern "C" fn test_TeBigU(_: TeBigU) -> TeBigU { loop {} } +pub extern "C" fn test_TeBigU(_: TeBigU) -> TeBigU { + loop {} +} diff --git a/tests/codegen/repr/transparent-sysv64.rs b/tests/codegen/repr/transparent-sysv64.rs index 1c7bca7ee406..afb06dcc1bdf 100644 --- a/tests/codegen/repr/transparent-sysv64.rs +++ b/tests/codegen/repr/transparent-sysv64.rs @@ -13,19 +13,28 @@ #![no_std] #![no_core] -#[lang="sized"] trait Sized { } -#[lang="freeze"] trait Freeze { } -#[lang="copy"] trait Copy { } +#[lang = "sized"] +trait Sized {} +#[lang = "freeze"] +trait Freeze {} +#[lang = "copy"] +trait Copy {} #[repr(C)] -pub struct Rgb8 { r: u8, g: u8, b: u8 } +pub struct Rgb8 { + r: u8, + g: u8, + b: u8, +} #[repr(transparent)] pub struct Rgb8Wrap(Rgb8); // CHECK: i24 @test_Rgb8Wrap(i24{{( %0)?}}) #[no_mangle] -pub extern "sysv64" fn test_Rgb8Wrap(_: Rgb8Wrap) -> Rgb8Wrap { loop {} } +pub extern "sysv64" fn test_Rgb8Wrap(_: Rgb8Wrap) -> Rgb8Wrap { + loop {} +} #[repr(C)] pub union FloatBits { @@ -38,4 +47,6 @@ pub struct SmallUnion(FloatBits); // CHECK: i32 @test_SmallUnion(i32{{( %0)?}}) #[no_mangle] -pub extern "sysv64" fn test_SmallUnion(_: SmallUnion) -> SmallUnion { loop {} } +pub extern "sysv64" fn test_SmallUnion(_: SmallUnion) -> SmallUnion { + loop {} +} diff --git a/tests/codegen/repr/transparent.rs b/tests/codegen/repr/transparent.rs index 17ec476035f2..4b41332db451 100644 --- a/tests/codegen/repr/transparent.rs +++ b/tests/codegen/repr/transparent.rs @@ -8,7 +8,7 @@ // For RISCV: see codegen/riscv-abi // For LoongArch: see codegen/loongarch-abi -#![crate_type="lib"] +#![crate_type = "lib"] #![feature(repr_simd, transparent_unions)] use std::marker::PhantomData; @@ -24,83 +24,112 @@ pub struct F32(f32); // CHECK: define{{.*}}float @test_F32(float noundef %_1) #[no_mangle] -pub extern "C" fn test_F32(_: F32) -> F32 { loop {} } +pub extern "C" fn test_F32(_: F32) -> F32 { + loop {} +} #[repr(transparent)] pub struct Ptr(*mut u8); // CHECK: define{{.*}}ptr @test_Ptr(ptr noundef %_1) #[no_mangle] -pub extern "C" fn test_Ptr(_: Ptr) -> Ptr { loop {} } +pub extern "C" fn test_Ptr(_: Ptr) -> Ptr { + loop {} +} #[repr(transparent)] pub struct WithZst(u64, Zst1); // CHECK: define{{.*}}i64 @test_WithZst(i64 noundef %_1) #[no_mangle] -pub extern "C" fn test_WithZst(_: WithZst) -> WithZst { loop {} } +pub extern "C" fn test_WithZst(_: WithZst) -> WithZst { + loop {} +} #[repr(transparent)] pub struct WithZeroSizedArray(*const f32, [i8; 0]); // CHECK: define{{.*}}ptr @test_WithZeroSizedArray(ptr noundef %_1) #[no_mangle] -pub extern "C" fn test_WithZeroSizedArray(_: WithZeroSizedArray) -> WithZeroSizedArray { loop {} } +pub extern "C" fn test_WithZeroSizedArray(_: WithZeroSizedArray) -> WithZeroSizedArray { + loop {} +} #[repr(transparent)] pub struct Generic(T); // CHECK: define{{.*}}double @test_Generic(double noundef %_1) #[no_mangle] -pub extern "C" fn test_Generic(_: Generic) -> Generic { loop {} } +pub extern "C" fn test_Generic(_: Generic) -> Generic { + loop {} +} #[repr(transparent)] pub struct GenericPlusZst(T, Zst2); #[repr(u8)] -pub enum Bool { True, False, FileNotFound } +pub enum Bool { + True, + False, + FileNotFound, +} // CHECK: define{{( dso_local)?}} noundef{{( zeroext)?}} i8 @test_Gpz(i8 noundef{{( zeroext)?}} %_1) #[no_mangle] -pub extern "C" fn test_Gpz(_: GenericPlusZst) -> GenericPlusZst { loop {} } +pub extern "C" fn test_Gpz(_: GenericPlusZst) -> GenericPlusZst { + loop {} +} #[repr(transparent)] pub struct LifetimePhantom<'a, T: 'a>(*const T, PhantomData<&'a T>); // CHECK: define{{.*}}ptr @test_LifetimePhantom(ptr noundef %_1) #[no_mangle] -pub extern "C" fn test_LifetimePhantom(_: LifetimePhantom) -> LifetimePhantom { loop {} } +pub extern "C" fn test_LifetimePhantom(_: LifetimePhantom) -> LifetimePhantom { + loop {} +} // This works despite current alignment resrictions because PhantomData is always align(1) #[repr(transparent)] -pub struct UnitPhantom { val: T, unit: PhantomData } +pub struct UnitPhantom { + val: T, + unit: PhantomData, +} pub struct Px; // CHECK: define{{.*}}float @test_UnitPhantom(float noundef %_1) #[no_mangle] -pub extern "C" fn test_UnitPhantom(_: UnitPhantom) -> UnitPhantom { loop {} } +pub extern "C" fn test_UnitPhantom(_: UnitPhantom) -> UnitPhantom { + loop {} +} #[repr(transparent)] pub struct TwoZsts(Zst1, i8, Zst2); // CHECK: define{{( dso_local)?}} noundef{{( signext)?}} i8 @test_TwoZsts(i8 noundef{{( signext)?}} %_1) #[no_mangle] -pub extern "C" fn test_TwoZsts(_: TwoZsts) -> TwoZsts { loop {} } +pub extern "C" fn test_TwoZsts(_: TwoZsts) -> TwoZsts { + loop {} +} #[repr(transparent)] pub struct Nested1(Zst2, Generic); // CHECK: define{{.*}}double @test_Nested1(double noundef %_1) #[no_mangle] -pub extern "C" fn test_Nested1(_: Nested1) -> Nested1 { loop {} } +pub extern "C" fn test_Nested1(_: Nested1) -> Nested1 { + loop {} +} #[repr(transparent)] pub struct Nested2(Nested1, Zst1); // CHECK: define{{.*}}double @test_Nested2(double noundef %_1) #[no_mangle] -pub extern "C" fn test_Nested2(_: Nested2) -> Nested2 { loop {} } +pub extern "C" fn test_Nested2(_: Nested2) -> Nested2 { + loop {} +} #[repr(simd)] struct f32x4(f32, f32, f32, f32); @@ -110,35 +139,47 @@ pub struct Vector(f32x4); // CHECK: define{{.*}}<4 x float> @test_Vector(<4 x float> %_1) #[no_mangle] -pub extern "C" fn test_Vector(_: Vector) -> Vector { loop {} } +pub extern "C" fn test_Vector(_: Vector) -> Vector { + loop {} +} -trait Mirror { type It: ?Sized; } -impl Mirror for T { type It = Self; } +trait Mirror { + type It: ?Sized; +} +impl Mirror for T { + type It = Self; +} #[repr(transparent)] pub struct StructWithProjection(::It); // CHECK: define{{.*}}float @test_Projection(float noundef %_1) #[no_mangle] -pub extern "C" fn test_Projection(_: StructWithProjection) -> StructWithProjection { loop {} } +pub extern "C" fn test_Projection(_: StructWithProjection) -> StructWithProjection { + loop {} +} #[repr(transparent)] pub enum EnumF32 { - Variant(F32) + Variant(F32), } // CHECK: define{{.*}}float @test_EnumF32(float noundef %_1) #[no_mangle] -pub extern "C" fn test_EnumF32(_: EnumF32) -> EnumF32 { loop {} } +pub extern "C" fn test_EnumF32(_: EnumF32) -> EnumF32 { + loop {} +} #[repr(transparent)] pub enum EnumF32WithZsts { - Variant(Zst1, F32, Zst2) + Variant(Zst1, F32, Zst2), } // CHECK: define{{.*}}float @test_EnumF32WithZsts(float noundef %_1) #[no_mangle] -pub extern "C" fn test_EnumF32WithZsts(_: EnumF32WithZsts) -> EnumF32WithZsts { loop {} } +pub extern "C" fn test_EnumF32WithZsts(_: EnumF32WithZsts) -> EnumF32WithZsts { + loop {} +} #[repr(transparent)] pub union UnionF32 { @@ -147,7 +188,9 @@ pub union UnionF32 { // CHECK: define{{.*}} float @test_UnionF32(float %_1) #[no_mangle] -pub extern "C" fn test_UnionF32(_: UnionF32) -> UnionF32 { loop {} } +pub extern "C" fn test_UnionF32(_: UnionF32) -> UnionF32 { + loop {} +} #[repr(transparent)] pub union UnionF32WithZsts { @@ -158,8 +201,9 @@ pub union UnionF32WithZsts { // CHECK: define{{.*}}float @test_UnionF32WithZsts(float %_1) #[no_mangle] -pub extern "C" fn test_UnionF32WithZsts(_: UnionF32WithZsts) -> UnionF32WithZsts { loop {} } - +pub extern "C" fn test_UnionF32WithZsts(_: UnionF32WithZsts) -> UnionF32WithZsts { + loop {} +} // All that remains to be tested are aggregates. They are tested in separate files called // transparent-*.rs with `only-*` or `ignore-*` directives, because the expected LLVM IR diff --git a/tests/codegen/riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs b/tests/codegen/riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs index 95c936ece730..977749ad578a 100644 --- a/tests/codegen/riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs +++ b/tests/codegen/riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs @@ -83,8 +83,7 @@ pub struct Tiny { // CHECK: define void @f_agg_tiny(i64 %0) #[no_mangle] -pub extern "C" fn f_agg_tiny(mut e: Tiny) { -} +pub extern "C" fn f_agg_tiny(mut e: Tiny) {} // CHECK: define i64 @f_agg_tiny_ret() #[no_mangle] @@ -100,8 +99,7 @@ pub struct Small { // CHECK: define void @f_agg_small([2 x i64] %0) #[no_mangle] -pub extern "C" fn f_agg_small(mut x: Small) { -} +pub extern "C" fn f_agg_small(mut x: Small) {} // CHECK: define [2 x i64] @f_agg_small_ret() #[no_mangle] @@ -116,8 +114,7 @@ pub struct SmallAligned { // CHECK: define void @f_agg_small_aligned(i128 %0) #[no_mangle] -pub extern "C" fn f_agg_small_aligned(mut x: SmallAligned) { -} +pub extern "C" fn f_agg_small_aligned(mut x: SmallAligned) {} #[repr(C)] pub struct Large { @@ -129,8 +126,7 @@ pub struct Large { // CHECK: define void @f_agg_large(ptr {{.*}}%x) #[no_mangle] -pub extern "C" fn f_agg_large(mut x: Large) { -} +pub extern "C" fn f_agg_large(mut x: Large) {} // CHECK: define void @f_agg_large_ret(ptr {{.*}}sret{{.*}}, i32 noundef signext %i, i8 noundef signext %j) #[no_mangle] diff --git a/tests/codegen/sanitizer/address-sanitizer-globals-tracking.rs b/tests/codegen/sanitizer/address-sanitizer-globals-tracking.rs index 8ffa235c18f1..f319306f93fd 100644 --- a/tests/codegen/sanitizer/address-sanitizer-globals-tracking.rs +++ b/tests/codegen/sanitizer/address-sanitizer-globals-tracking.rs @@ -23,7 +23,7 @@ //@[ASAN] compile-flags: //@[ASAN-FAT-LTO] compile-flags: -Cprefer-dynamic=false -Clto=fat -#![crate_type="staticlib"] +#![crate_type = "staticlib"] // The test below mimics `CACHED_POW10` from `library/core/src/num/flt2dec/strategy/grisu.rs` which // (because of incorrect handling of `___asan_globals_registered` during LTO) was incorrectly diff --git a/tests/codegen/sanitizer/cfi/add-canonical-jump-tables-flag.rs b/tests/codegen/sanitizer/cfi/add-canonical-jump-tables-flag.rs index f122fbdc0866..22577e2a3c46 100644 --- a/tests/codegen/sanitizer/cfi/add-canonical-jump-tables-flag.rs +++ b/tests/codegen/sanitizer/cfi/add-canonical-jump-tables-flag.rs @@ -3,9 +3,8 @@ //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi -#![crate_type="lib"] +#![crate_type = "lib"] -pub fn foo() { -} +pub fn foo() {} // CHECK: !{{[0-9]+}} = !{i32 4, !"CFI Canonical Jump Tables", i32 1} diff --git a/tests/codegen/sanitizer/cfi/add-enable-split-lto-unit-flag.rs b/tests/codegen/sanitizer/cfi/add-enable-split-lto-unit-flag.rs index 05eea13c6ee0..283b8f261029 100644 --- a/tests/codegen/sanitizer/cfi/add-enable-split-lto-unit-flag.rs +++ b/tests/codegen/sanitizer/cfi/add-enable-split-lto-unit-flag.rs @@ -3,9 +3,8 @@ //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi -#![crate_type="lib"] +#![crate_type = "lib"] -pub fn foo() { -} +pub fn foo() {} // CHECK: !{{[0-9]+}} = !{i32 4, !"EnableSplitLTOUnit", i32 1} diff --git a/tests/codegen/sanitizer/cfi/emit-type-checks-attr-no-sanitize.rs b/tests/codegen/sanitizer/cfi/emit-type-checks-attr-no-sanitize.rs index 9f72de2ebcc9..259967e89181 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-checks-attr-no-sanitize.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-checks-attr-no-sanitize.rs @@ -3,7 +3,7 @@ //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Copt-level=0 -#![crate_type="lib"] +#![crate_type = "lib"] #![feature(no_sanitize)] #[no_sanitize(cfi)] diff --git a/tests/codegen/sanitizer/cfi/emit-type-checks.rs b/tests/codegen/sanitizer/cfi/emit-type-checks.rs index 6ec6f0e5476d..37edbefee56a 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-checks.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-checks.rs @@ -3,7 +3,7 @@ //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Copt-level=0 -#![crate_type="lib"] +#![crate_type = "lib"] pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 { // CHECK-LABEL: define{{.*}}foo{{.*}}!type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-attr-cfi-encoding.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-attr-cfi-encoding.rs index be4af9b7962d..9bc2e42db0f6 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-metadata-attr-cfi-encoding.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-attr-cfi-encoding.rs @@ -3,13 +3,13 @@ //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Copt-level=0 -#![crate_type="lib"] +#![crate_type = "lib"] #![feature(cfi_encoding, extern_types)] #[cfi_encoding = "3Foo"] pub struct Type1(i32); -extern { +extern "C" { #[cfi_encoding = "3Bar"] type Type2; } @@ -25,35 +25,35 @@ pub struct Type4(i32); #[repr(transparent)] pub struct Type5(u32); -pub fn foo0(_: Type1) { } +pub fn foo0(_: Type1) {} // CHECK: define{{.*}}foo0{{.*}}!type ![[TYPE0:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo1(_: Type1, _: Type1) { } +pub fn foo1(_: Type1, _: Type1) {} // CHECK: define{{.*}}foo1{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo2(_: Type1, _: Type1, _: Type1) { } +pub fn foo2(_: Type1, _: Type1, _: Type1) {} // CHECK: define{{.*}}foo2{{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo3(_: *mut Type2) { } +pub fn foo3(_: *mut Type2) {} // CHECK: define{{.*}}foo3{{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo4(_: *mut Type2, _: *mut Type2) { } +pub fn foo4(_: *mut Type2, _: *mut Type2) {} // CHECK: define{{.*}}foo4{{.*}}!type ![[TYPE4:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo5(_: *mut Type2, _: *mut Type2, _: *mut Type2) { } +pub fn foo5(_: *mut Type2, _: *mut Type2, _: *mut Type2) {} // CHECK: define{{.*}}foo5{{.*}}!type ![[TYPE5:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo6(_: *mut Type3) { } +pub fn foo6(_: *mut Type3) {} // CHECK: define{{.*}}foo6{{.*}}!type ![[TYPE6:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo7(_: *mut Type3, _: *mut Type3) { } +pub fn foo7(_: *mut Type3, _: *mut Type3) {} // CHECK: define{{.*}}foo7{{.*}}!type ![[TYPE7:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo8(_: *mut Type3, _: *mut Type3, _: *mut Type3) { } +pub fn foo8(_: *mut Type3, _: *mut Type3, _: *mut Type3) {} // CHECK: define{{.*}}foo8{{.*}}!type ![[TYPE8:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo9(_: Type4) { } +pub fn foo9(_: Type4) {} // CHECK: define{{.*}}foo9{{.*}}!type ![[TYPE9:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo10(_: Type4, _: Type4) { } +pub fn foo10(_: Type4, _: Type4) {} // CHECK: define{{.*}}foo10{{.*}}!type ![[TYPE10:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo11(_: Type4, _: Type4, _: Type4) { } +pub fn foo11(_: Type4, _: Type4, _: Type4) {} // CHECK: define{{.*}}foo11{{.*}}!type ![[TYPE11:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo12(_: Type5) { } +pub fn foo12(_: Type5) {} // CHECK: define{{.*}}foo12{{.*}}!type ![[TYPE12:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo13(_: Type5, _: Type5) { } +pub fn foo13(_: Type5, _: Type5) {} // CHECK: define{{.*}}foo13{{.*}}!type ![[TYPE13:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo14(_: Type5, _: Type5, _: Type5) { } +pub fn foo14(_: Type5, _: Type5, _: Type5) {} // CHECK: define{{.*}}foo14{{.*}}!type ![[TYPE14:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} // CHECK: ![[TYPE0]] = !{i64 0, !"_ZTSFv3FooE"} diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-const-generics.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-const-generics.rs index 6608caca8af8..25dba97962ae 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-const-generics.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-const-generics.rs @@ -4,25 +4,26 @@ //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Copt-level=0 -#![crate_type="lib"] +#![crate_type = "lib"] #![feature(type_alias_impl_trait)] extern crate core; pub type Type1 = impl Send; -pub fn foo() where +pub fn foo() +where Type1: 'static, { pub struct Foo([T; N]); let _: Type1 = Foo([0; 32]); } -pub fn foo1(_: Type1) { } +pub fn foo1(_: Type1) {} // CHECK: define{{.*}}4foo1{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo2(_: Type1, _: Type1) { } +pub fn foo2(_: Type1, _: Type1) {} // CHECK: define{{.*}}4foo2{{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo3(_: Type1, _: Type1, _: Type1) { } +pub fn foo3(_: Type1, _: Type1, _: Type1) {} // CHECK: define{{.*}}4foo3{{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} // CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo3FooIu3i32Lu5usize32EEE"} diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-drop-in-place.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-drop-in-place.rs index 3ec1988edd6e..2a7eca6fc196 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-drop-in-place.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-drop-in-place.rs @@ -3,7 +3,7 @@ //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Copt-level=0 -Zsanitizer=cfi -Ctarget-feature=-crt-static -#![crate_type="lib"] +#![crate_type = "lib"] // CHECK-LABEL: define{{.*}}4core3ptr47drop_in_place$LT$dyn$u20$core..marker..Send$GT$ // CHECK-SAME: {{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-function-types.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-function-types.rs index c5dadf70de95..7e60aafff680 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-function-types.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-function-types.rs @@ -4,29 +4,29 @@ //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Copt-level=0 -Zsanitizer=cfi -Ctarget-feature=-crt-static -#![crate_type="lib"] +#![crate_type = "lib"] -pub fn foo1(_: fn(i32) -> i32) { } +pub fn foo1(_: fn(i32) -> i32) {} // CHECK: define{{.*}}4foo1{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo2(_: fn(i32) -> i32, _: fn(i32) -> i32) { } +pub fn foo2(_: fn(i32) -> i32, _: fn(i32) -> i32) {} // CHECK: define{{.*}}4foo2{{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo3(_: fn(i32) -> i32, _: fn(i32) -> i32, _: fn(i32) -> i32) { } +pub fn foo3(_: fn(i32) -> i32, _: fn(i32) -> i32, _: fn(i32) -> i32) {} // CHECK: define{{.*}}4foo3{{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo4(_: &dyn Fn(i32) -> i32) { } +pub fn foo4(_: &dyn Fn(i32) -> i32) {} // CHECK: define{{.*}}4foo4{{.*}}!type ![[TYPE4:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo5(_: &dyn Fn(i32) -> i32, _: &dyn Fn(i32) -> i32) { } +pub fn foo5(_: &dyn Fn(i32) -> i32, _: &dyn Fn(i32) -> i32) {} // CHECK: define{{.*}}4foo5{{.*}}!type ![[TYPE5:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo6(_: &dyn Fn(i32) -> i32, _: &dyn Fn(i32) -> i32, _: &dyn Fn(i32) -> i32) { } +pub fn foo6(_: &dyn Fn(i32) -> i32, _: &dyn Fn(i32) -> i32, _: &dyn Fn(i32) -> i32) {} // CHECK: define{{.*}}4foo6{{.*}}!type ![[TYPE6:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo7(_: &dyn FnMut(i32) -> i32) { } +pub fn foo7(_: &dyn FnMut(i32) -> i32) {} // CHECK: define{{.*}}4foo7{{.*}}!type ![[TYPE7:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo8(_: &dyn FnMut(i32) -> i32, _: &dyn FnMut(i32) -> i32) { } +pub fn foo8(_: &dyn FnMut(i32) -> i32, _: &dyn FnMut(i32) -> i32) {} // CHECK: define{{.*}}4foo8{{.*}}!type ![[TYPE8:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo9(_: &dyn FnMut(i32) -> i32, _: &dyn FnMut(i32) -> i32, _: &dyn FnMut(i32) -> i32) { } +pub fn foo9(_: &dyn FnMut(i32) -> i32, _: &dyn FnMut(i32) -> i32, _: &dyn FnMut(i32) -> i32) {} // CHECK: define{{.*}}4foo9{{.*}}!type ![[TYPE9:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo10(_: &dyn FnOnce(i32) -> i32) { } +pub fn foo10(_: &dyn FnOnce(i32) -> i32) {} // CHECK: define{{.*}}5foo10{{.*}}!type ![[TYPE10:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo11(_: &dyn FnOnce(i32) -> i32, _: &dyn FnOnce(i32) -> i32) { } +pub fn foo11(_: &dyn FnOnce(i32) -> i32, _: &dyn FnOnce(i32) -> i32) {} // CHECK: define{{.*}}5foo11{{.*}}!type ![[TYPE11:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} pub fn foo12(_: &dyn FnOnce(i32) -> i32, _: &dyn FnOnce(i32) -> i32, _: &dyn FnOnce(i32) -> i32) {} // CHECK: define{{.*}}5foo12{{.*}}!type ![[TYPE12:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-lifetimes.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-lifetimes.rs index 4d08c0c3039a..3ef119fd905a 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-lifetimes.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-lifetimes.rs @@ -4,14 +4,15 @@ //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Copt-level=0 -#![crate_type="lib"] +#![crate_type = "lib"] #![feature(type_alias_impl_trait)] extern crate core; pub type Type1 = impl Send; -pub fn foo<'a>() where +pub fn foo<'a>() +where Type1: 'static, { pub struct Foo<'a>(&'a i32); @@ -19,9 +20,9 @@ pub fn foo<'a>() where let _: Type1 = Bar; } -pub fn foo1(_: Type1) { } +pub fn foo1(_: Type1) {} // CHECK: define{{.*}}4foo1{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo2(_: Type1, _: Type1) { } +pub fn foo2(_: Type1, _: Type1) {} // CHECK: define{{.*}}4foo2{{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo3(_: Type1, _: Type1, _: Type1) { } +pub fn foo3(_: Type1, _: Type1, _: Type1) {} // CHECK: define{{.*}}4foo3{{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-method-secondary-typeid.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-method-secondary-typeid.rs index 671db563dde7..9d611777ff0b 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-method-secondary-typeid.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-method-secondary-typeid.rs @@ -4,7 +4,7 @@ //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Copt-level=0 -Zsanitizer=cfi -Ctarget-feature=-crt-static -#![crate_type="lib"] +#![crate_type = "lib"] trait Trait1 { fn foo(&self); @@ -17,6 +17,5 @@ impl Trait1 for Type1 { // CHECK: define{{.*}}3foo{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} } - // CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_{{[[:print:]]+}}6Trait1u6regionEEE"} // CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtC{{[[:print:]]+}}_{{[[:print:]]+}}5Type1EE"} diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-pointer-types.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-pointer-types.rs index 6ad6f3ac3489..d37bb740f550 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-pointer-types.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-pointer-types.rs @@ -4,37 +4,37 @@ //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Copt-level=0 -Zsanitizer=cfi -Ctarget-feature=-crt-static -#![crate_type="lib"] +#![crate_type = "lib"] -pub fn foo1(_: &mut i32) { } +pub fn foo1(_: &mut i32) {} // CHECK: define{{.*}}4foo1{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo2(_: &mut i32, _: &i32) { } +pub fn foo2(_: &mut i32, _: &i32) {} // CHECK: define{{.*}}4foo2{{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo3(_: &mut i32, _: &i32, _: &i32) { } +pub fn foo3(_: &mut i32, _: &i32, _: &i32) {} // CHECK: define{{.*}}4foo3{{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo4(_: &i32) { } +pub fn foo4(_: &i32) {} // CHECK: define{{.*}}4foo4{{.*}}!type ![[TYPE4:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo5(_: &i32, _: &mut i32) { } +pub fn foo5(_: &i32, _: &mut i32) {} // CHECK: define{{.*}}4foo5{{.*}}!type ![[TYPE5:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo6(_: &i32, _: &mut i32, _: &mut i32) { } +pub fn foo6(_: &i32, _: &mut i32, _: &mut i32) {} // CHECK: define{{.*}}4foo6{{.*}}!type ![[TYPE6:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo7(_: *mut i32) { } +pub fn foo7(_: *mut i32) {} // CHECK: define{{.*}}4foo7{{.*}}!type ![[TYPE7:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo8(_: *mut i32, _: *const i32) { } +pub fn foo8(_: *mut i32, _: *const i32) {} // CHECK: define{{.*}}4foo8{{.*}}!type ![[TYPE8:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo9(_: *mut i32, _: *const i32, _: *const i32) { } +pub fn foo9(_: *mut i32, _: *const i32, _: *const i32) {} // CHECK: define{{.*}}4foo9{{.*}}!type ![[TYPE9:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo10(_: *const i32) { } +pub fn foo10(_: *const i32) {} // CHECK: define{{.*}}5foo10{{.*}}!type ![[TYPE10:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo11(_: *const i32, _: *mut i32) { } +pub fn foo11(_: *const i32, _: *mut i32) {} // CHECK: define{{.*}}5foo11{{.*}}!type ![[TYPE11:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo12(_: *const i32, _: *mut i32, _: *mut i32) { } +pub fn foo12(_: *const i32, _: *mut i32, _: *mut i32) {} // CHECK: define{{.*}}5foo12{{.*}}!type ![[TYPE12:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo13(_: fn(i32) -> i32) { } +pub fn foo13(_: fn(i32) -> i32) {} // CHECK: define{{.*}}5foo13{{.*}}!type ![[TYPE13:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo14(_: fn(i32) -> i32, _: fn(i32) -> i32) { } +pub fn foo14(_: fn(i32) -> i32, _: fn(i32) -> i32) {} // CHECK: define{{.*}}5foo14{{.*}}!type ![[TYPE14:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo15(_: fn(i32) -> i32, _: fn(i32) -> i32, _: fn(i32) -> i32) { } +pub fn foo15(_: fn(i32) -> i32, _: fn(i32) -> i32, _: fn(i32) -> i32) {} // CHECK: define{{.*}}5foo15{{.*}}!type ![[TYPE15:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} // CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvU3mutu3refIu3i32EE"} diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-primitive-types.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-primitive-types.rs index 38f507856bde..7d9e4d058727 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-primitive-types.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-primitive-types.rs @@ -4,130 +4,130 @@ //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Copt-level=0 -Zsanitizer=cfi -Ctarget-feature=-crt-static -#![crate_type="lib"] +#![crate_type = "lib"] extern crate core; use core::ffi::*; -pub fn foo1(_: ()) { } +pub fn foo1(_: ()) {} // CHECK: define{{.*}}4foo1{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo2(_: (), _: c_void) { } +pub fn foo2(_: (), _: c_void) {} // CHECK: define{{.*}}4foo2{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo3(_: (), _: c_void, _: c_void) { } +pub fn foo3(_: (), _: c_void, _: c_void) {} // CHECK: define{{.*}}4foo3{{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo4(_: *mut ()) { } +pub fn foo4(_: *mut ()) {} // CHECK: define{{.*}}4foo4{{.*}}!type ![[TYPE4:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo5(_: *mut (), _: *mut c_void) { } +pub fn foo5(_: *mut (), _: *mut c_void) {} // CHECK: define{{.*}}4foo5{{.*}}!type ![[TYPE5:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo6(_: *mut (), _: *mut c_void, _: *mut c_void) { } +pub fn foo6(_: *mut (), _: *mut c_void, _: *mut c_void) {} // CHECK: define{{.*}}4foo6{{.*}}!type ![[TYPE6:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo7(_: *const ()) { } +pub fn foo7(_: *const ()) {} // CHECK: define{{.*}}4foo7{{.*}}!type ![[TYPE7:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo8(_: *const (), _: *const c_void) { } +pub fn foo8(_: *const (), _: *const c_void) {} // CHECK: define{{.*}}4foo8{{.*}}!type ![[TYPE8:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo9(_: *const (), _: *const c_void, _: *const c_void) { } +pub fn foo9(_: *const (), _: *const c_void, _: *const c_void) {} // CHECK: define{{.*}}4foo9{{.*}}!type ![[TYPE9:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo10(_: bool) { } +pub fn foo10(_: bool) {} // CHECK: define{{.*}}5foo10{{.*}}!type ![[TYPE10:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo11(_: bool, _: bool) { } +pub fn foo11(_: bool, _: bool) {} // CHECK: define{{.*}}5foo11{{.*}}!type ![[TYPE11:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo12(_: bool, _: bool, _: bool) { } +pub fn foo12(_: bool, _: bool, _: bool) {} // CHECK: define{{.*}}5foo12{{.*}}!type ![[TYPE12:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo13(_: i8) { } +pub fn foo13(_: i8) {} // CHECK: define{{.*}}5foo13{{.*}}!type ![[TYPE13:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo14(_: i8, _: i8) { } +pub fn foo14(_: i8, _: i8) {} // CHECK: define{{.*}}5foo14{{.*}}!type ![[TYPE14:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo15(_: i8, _: i8, _: i8) { } +pub fn foo15(_: i8, _: i8, _: i8) {} // CHECK: define{{.*}}5foo15{{.*}}!type ![[TYPE15:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo16(_: i16) { } +pub fn foo16(_: i16) {} // CHECK: define{{.*}}5foo16{{.*}}!type ![[TYPE16:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo17(_: i16, _: i16) { } +pub fn foo17(_: i16, _: i16) {} // CHECK: define{{.*}}5foo17{{.*}}!type ![[TYPE17:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo18(_: i16, _: i16, _: i16) { } +pub fn foo18(_: i16, _: i16, _: i16) {} // CHECK: define{{.*}}5foo18{{.*}}!type ![[TYPE18:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo19(_: i32) { } +pub fn foo19(_: i32) {} // CHECK: define{{.*}}5foo19{{.*}}!type ![[TYPE19:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo20(_: i32, _: i32) { } +pub fn foo20(_: i32, _: i32) {} // CHECK: define{{.*}}5foo20{{.*}}!type ![[TYPE20:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo21(_: i32, _: i32, _: i32) { } +pub fn foo21(_: i32, _: i32, _: i32) {} // CHECK: define{{.*}}5foo21{{.*}}!type ![[TYPE21:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo22(_: i64) { } +pub fn foo22(_: i64) {} // CHECK: define{{.*}}5foo22{{.*}}!type ![[TYPE22:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo23(_: i64, _: i64) { } +pub fn foo23(_: i64, _: i64) {} // CHECK: define{{.*}}5foo23{{.*}}!type ![[TYPE23:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo24(_: i64, _: i64, _: i64) { } +pub fn foo24(_: i64, _: i64, _: i64) {} // CHECK: define{{.*}}5foo24{{.*}}!type ![[TYPE24:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo25(_: i128) { } +pub fn foo25(_: i128) {} // CHECK: define{{.*}}5foo25{{.*}}!type ![[TYPE25:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo26(_: i128, _: i128) { } +pub fn foo26(_: i128, _: i128) {} // CHECK: define{{.*}}5foo26{{.*}}!type ![[TYPE26:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo27(_: i128, _: i128, _: i128) { } +pub fn foo27(_: i128, _: i128, _: i128) {} // CHECK: define{{.*}}5foo27{{.*}}!type ![[TYPE27:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo28(_: isize) { } +pub fn foo28(_: isize) {} // CHECK: define{{.*}}5foo28{{.*}}!type ![[TYPE28:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo29(_: isize, _: isize) { } +pub fn foo29(_: isize, _: isize) {} // CHECK: define{{.*}}5foo29{{.*}}!type ![[TYPE29:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo30(_: isize, _: isize, _: isize) { } +pub fn foo30(_: isize, _: isize, _: isize) {} // CHECK: define{{.*}}5foo30{{.*}}!type ![[TYPE30:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo31(_: u8) { } +pub fn foo31(_: u8) {} // CHECK: define{{.*}}5foo31{{.*}}!type ![[TYPE31:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo32(_: u8, _: u8) { } +pub fn foo32(_: u8, _: u8) {} // CHECK: define{{.*}}5foo32{{.*}}!type ![[TYPE32:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo33(_: u8, _: u8, _: u8) { } +pub fn foo33(_: u8, _: u8, _: u8) {} // CHECK: define{{.*}}5foo33{{.*}}!type ![[TYPE33:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo34(_: u16) { } +pub fn foo34(_: u16) {} // CHECK: define{{.*}}5foo34{{.*}}!type ![[TYPE34:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo35(_: u16, _: u16) { } +pub fn foo35(_: u16, _: u16) {} // CHECK: define{{.*}}5foo35{{.*}}!type ![[TYPE35:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo36(_: u16, _: u16, _: u16) { } +pub fn foo36(_: u16, _: u16, _: u16) {} // CHECK: define{{.*}}5foo36{{.*}}!type ![[TYPE36:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo37(_: u32) { } +pub fn foo37(_: u32) {} // CHECK: define{{.*}}5foo37{{.*}}!type ![[TYPE37:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo38(_: u32, _: u32) { } +pub fn foo38(_: u32, _: u32) {} // CHECK: define{{.*}}5foo38{{.*}}!type ![[TYPE38:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo39(_: u32, _: u32, _: u32) { } +pub fn foo39(_: u32, _: u32, _: u32) {} // CHECK: define{{.*}}5foo39{{.*}}!type ![[TYPE39:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo40(_: u64) { } +pub fn foo40(_: u64) {} // CHECK: define{{.*}}5foo40{{.*}}!type ![[TYPE40:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo41(_: u64, _: u64) { } +pub fn foo41(_: u64, _: u64) {} // CHECK: define{{.*}}5foo41{{.*}}!type ![[TYPE41:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo42(_: u64, _: u64, _: u64) { } +pub fn foo42(_: u64, _: u64, _: u64) {} // CHECK: define{{.*}}5foo42{{.*}}!type ![[TYPE42:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo43(_: u128) { } +pub fn foo43(_: u128) {} // CHECK: define{{.*}}5foo43{{.*}}!type ![[TYPE43:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo44(_: u128, _: u128) { } +pub fn foo44(_: u128, _: u128) {} // CHECK: define{{.*}}5foo44{{.*}}!type ![[TYPE44:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo45(_: u128, _: u128, _: u128) { } +pub fn foo45(_: u128, _: u128, _: u128) {} // CHECK: define{{.*}}5foo45{{.*}}!type ![[TYPE45:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo46(_: usize) { } +pub fn foo46(_: usize) {} // CHECK: define{{.*}}5foo46{{.*}}!type ![[TYPE46:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo47(_: usize, _: usize) { } +pub fn foo47(_: usize, _: usize) {} // CHECK: define{{.*}}5foo47{{.*}}!type ![[TYPE47:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo48(_: usize, _: usize, _: usize) { } +pub fn foo48(_: usize, _: usize, _: usize) {} // CHECK: define{{.*}}5foo48{{.*}}!type ![[TYPE48:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo49(_: f32) { } +pub fn foo49(_: f32) {} // CHECK: define{{.*}}5foo49{{.*}}!type ![[TYPE49:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo50(_: f32, _: f32) { } +pub fn foo50(_: f32, _: f32) {} // CHECK: define{{.*}}5foo50{{.*}}!type ![[TYPE50:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo51(_: f32, _: f32, _: f32) { } +pub fn foo51(_: f32, _: f32, _: f32) {} // CHECK: define{{.*}}5foo51{{.*}}!type ![[TYPE51:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo52(_: f64) { } +pub fn foo52(_: f64) {} // CHECK: define{{.*}}5foo52{{.*}}!type ![[TYPE52:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo53(_: f64, _: f64) { } +pub fn foo53(_: f64, _: f64) {} // CHECK: define{{.*}}5foo53{{.*}}!type ![[TYPE53:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo54(_: f64, _: f64, _: f64) { } +pub fn foo54(_: f64, _: f64, _: f64) {} // CHECK: define{{.*}}5foo54{{.*}}!type ![[TYPE54:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo55(_: char) { } +pub fn foo55(_: char) {} // CHECK: define{{.*}}5foo55{{.*}}!type ![[TYPE55:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo56(_: char, _: char) { } +pub fn foo56(_: char, _: char) {} // CHECK: define{{.*}}5foo56{{.*}}!type ![[TYPE56:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo57(_: char, _: char, _: char) { } +pub fn foo57(_: char, _: char, _: char) {} // CHECK: define{{.*}}5foo57{{.*}}!type ![[TYPE57:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo58(_: &str) { } +pub fn foo58(_: &str) {} // CHECK: define{{.*}}5foo58{{.*}}!type ![[TYPE58:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo59(_: &str, _: &str) { } +pub fn foo59(_: &str, _: &str) {} // CHECK: define{{.*}}5foo59{{.*}}!type ![[TYPE59:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo60(_: &str, _: &str, _: &str) { } +pub fn foo60(_: &str, _: &str, _: &str) {} // CHECK: define{{.*}}5foo60{{.*}}!type ![[TYPE60:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} // CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvvE"} diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-repr-transparent-types.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-repr-transparent-types.rs index 1332338b26ab..0f97c70f3f92 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-repr-transparent-types.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-repr-transparent-types.rs @@ -4,7 +4,7 @@ //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Copt-level=0 -Zsanitizer=cfi -Ctarget-feature=-crt-static -#![crate_type="lib"] +#![crate_type = "lib"] extern crate core; use core::ffi::*; @@ -40,32 +40,31 @@ pub struct Type4(Type4Helper); #[repr(transparent)] pub struct Type4Helper(*mut T); -pub fn foo1(_: Type1) { } +pub fn foo1(_: Type1) {} // CHECK: define{{.*}}4foo1{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo2(_: Type1, _: Type1) { } +pub fn foo2(_: Type1, _: Type1) {} // CHECK: define{{.*}}4foo2{{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo3(_: Type1, _: Type1, _: Type1) { } +pub fn foo3(_: Type1, _: Type1, _: Type1) {} // CHECK: define{{.*}}4foo3{{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo4(_: Type2) { } +pub fn foo4(_: Type2) {} // CHECK: define{{.*}}4foo4{{.*}}!type ![[TYPE4:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo5(_: Type2, _: Type2) { } +pub fn foo5(_: Type2, _: Type2) {} // CHECK: define{{.*}}4foo5{{.*}}!type ![[TYPE5:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo6(_: Type2, _: Type2, _: Type2) { } +pub fn foo6(_: Type2, _: Type2, _: Type2) {} // CHECK: define{{.*}}4foo6{{.*}}!type ![[TYPE6:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo7(_: Type3) { } +pub fn foo7(_: Type3) {} // CHECK: define{{.*}}4foo7{{.*}}!type ![[TYPE7:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo8(_: Type3, _: Type3) { } +pub fn foo8(_: Type3, _: Type3) {} // CHECK: define{{.*}}4foo8{{.*}}!type ![[TYPE8:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo9(_: Type3, _: Type3, _: Type3) { } +pub fn foo9(_: Type3, _: Type3, _: Type3) {} // CHECK: define{{.*}}4foo9{{.*}}!type ![[TYPE9:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo10(_: Type4) { } +pub fn foo10(_: Type4) {} // CHECK: define{{.*}}5foo10{{.*}}!type ![[TYPE10:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo11(_: Type4, _: Type4) { } +pub fn foo11(_: Type4, _: Type4) {} // CHECK: define{{.*}}5foo11{{.*}}!type ![[TYPE11:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo12(_: Type4, _: Type4, _: Type4) { } +pub fn foo12(_: Type4, _: Type4, _: Type4) {} // CHECK: define{{.*}}5foo12{{.*}}!type ![[TYPE12:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} - // CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_{{[[:print:]]+}}3FooE"} // CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_{{[[:print:]]+}}3FooS_E"} // CHECK: ![[TYPE3]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_{{[[:print:]]+}}3FooS_S_E"} diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-sequence-types.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-sequence-types.rs index dd2e05dd2ec6..bdee3f47a837 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-sequence-types.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-sequence-types.rs @@ -4,25 +4,25 @@ //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Copt-level=0 -Zsanitizer=cfi -Ctarget-feature=-crt-static -#![crate_type="lib"] +#![crate_type = "lib"] -pub fn foo1(_: (i32, i32)) { } +pub fn foo1(_: (i32, i32)) {} // CHECK: define{{.*}}4foo1{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo2(_: (i32, i32), _: (i32, i32)) { } +pub fn foo2(_: (i32, i32), _: (i32, i32)) {} // CHECK: define{{.*}}4foo2{{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo3(_: (i32, i32), _: (i32, i32), _: (i32, i32)) { } +pub fn foo3(_: (i32, i32), _: (i32, i32), _: (i32, i32)) {} // CHECK: define{{.*}}4foo3{{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo4(_: [i32; 32]) { } +pub fn foo4(_: [i32; 32]) {} // CHECK: define{{.*}}4foo4{{.*}}!type ![[TYPE4:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo5(_: [i32; 32], _: [i32; 32]) { } +pub fn foo5(_: [i32; 32], _: [i32; 32]) {} // CHECK: define{{.*}}4foo5{{.*}}!type ![[TYPE5:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo6(_: [i32; 32], _: [i32; 32], _: [i32; 32]) { } +pub fn foo6(_: [i32; 32], _: [i32; 32], _: [i32; 32]) {} // CHECK: define{{.*}}4foo6{{.*}}!type ![[TYPE6:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo7(_: &[i32]) { } +pub fn foo7(_: &[i32]) {} // CHECK: define{{.*}}4foo7{{.*}}!type ![[TYPE7:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo8(_: &[i32], _: &[i32]) { } +pub fn foo8(_: &[i32], _: &[i32]) {} // CHECK: define{{.*}}4foo8{{.*}}!type ![[TYPE8:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo9(_: &[i32], _: &[i32], _: &[i32]) { } +pub fn foo9(_: &[i32], _: &[i32], _: &[i32]) {} // CHECK: define{{.*}}4foo9{{.*}}!type ![[TYPE9:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} // CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvu5tupleIu3i32S_EE"} diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-trait-types.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-trait-types.rs index 6d9fe7040f70..55e816178f8f 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-trait-types.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-trait-types.rs @@ -4,7 +4,7 @@ //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Copt-level=0 -Zsanitizer=cfi -Ctarget-feature=-crt-static -#![crate_type="lib"] +#![crate_type = "lib"] extern crate core; @@ -16,8 +16,7 @@ pub trait Trait1 { pub struct Type1; impl Trait1 for Type1 { - fn foo(&self) { - } + fn foo(&self) {} } pub trait Trait2 { @@ -27,8 +26,7 @@ pub trait Trait2 { pub struct Type2; impl Trait2 for Type2 { - fn bar(&self) { - } + fn bar(&self) {} } pub trait Trait3 { @@ -38,8 +36,7 @@ pub trait Trait3 { pub struct Type3; impl Trait3 for T { - fn baz(&self, _: &U) { - } + fn baz(&self, _: &U) {} } pub trait Trait4<'a, T> { @@ -64,71 +61,88 @@ pub trait Trait5 { pub struct Type5; impl Trait5 for T { - fn quux(&self, _: &[U; N]) { - } + fn quux(&self, _: &[U; N]) {} } -pub fn foo1(_: &dyn Send) { } +pub fn foo1(_: &dyn Send) {} // CHECK: define{{.*}}4foo1{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo2(_: &dyn Send, _: &dyn Send) { } +pub fn foo2(_: &dyn Send, _: &dyn Send) {} // CHECK: define{{.*}}4foo2{{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo3(_: &dyn Send, _: &dyn Send, _: &dyn Send) { } +pub fn foo3(_: &dyn Send, _: &dyn Send, _: &dyn Send) {} // CHECK: define{{.*}}4foo3{{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo4(_: &(dyn Send + Sync)) { } +pub fn foo4(_: &(dyn Send + Sync)) {} // CHECK: define{{.*}}4foo4{{.*}}!type ![[TYPE4:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo5(_: &(dyn Send + Sync), _: &(dyn Sync + Send)) { } +pub fn foo5(_: &(dyn Send + Sync), _: &(dyn Sync + Send)) {} // CHECK: define{{.*}}4foo5{{.*}}!type ![[TYPE5:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo6(_: &(dyn Send + Sync), _: &(dyn Sync + Send), _: &(dyn Sync + Send)) { } +pub fn foo6(_: &(dyn Send + Sync), _: &(dyn Sync + Send), _: &(dyn Sync + Send)) {} // CHECK: define{{.*}}4foo6{{.*}}!type ![[TYPE6:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo7(_: &(dyn Trait1 + Send)) { } +pub fn foo7(_: &(dyn Trait1 + Send)) {} // CHECK: define{{.*}}4foo7{{.*}}!type ![[TYPE7:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo8(_: &(dyn Trait1 + Send), _: &(dyn Trait1 + Send)) { } +pub fn foo8(_: &(dyn Trait1 + Send), _: &(dyn Trait1 + Send)) {} // CHECK: define{{.*}}4foo8{{.*}}!type ![[TYPE8:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo9(_: &(dyn Trait1 + Send), _: &(dyn Trait1 + Send), _: &(dyn Trait1 + Send)) { } +pub fn foo9(_: &(dyn Trait1 + Send), _: &(dyn Trait1 + Send), _: &(dyn Trait1 + Send)) {} // CHECK: define{{.*}}4foo9{{.*}}!type ![[TYPE9:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo10(_: &(dyn Trait1 + Send + Sync)) { } +pub fn foo10(_: &(dyn Trait1 + Send + Sync)) {} // CHECK: define{{.*}}5foo10{{.*}}!type ![[TYPE10:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo11(_: &(dyn Trait1 + Send + Sync), _: &(dyn Trait1 + Sync + Send)) { } +pub fn foo11(_: &(dyn Trait1 + Send + Sync), _: &(dyn Trait1 + Sync + Send)) {} // CHECK: define{{.*}}5foo11{{.*}}!type ![[TYPE11:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo12(_: &(dyn Trait1 + Send + Sync), - _: &(dyn Trait1 + Sync + Send), - _: &(dyn Trait1 + Sync + Send)) { } +pub fn foo12( + _: &(dyn Trait1 + Send + Sync), + _: &(dyn Trait1 + Sync + Send), + _: &(dyn Trait1 + Sync + Send), +) { +} // CHECK: define{{.*}}5foo12{{.*}}!type ![[TYPE12:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo13(_: &dyn Trait1) { } +pub fn foo13(_: &dyn Trait1) {} // CHECK: define{{.*}}5foo13{{.*}}!type ![[TYPE13:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo14(_: &dyn Trait1, _: &dyn Trait1) { } +pub fn foo14(_: &dyn Trait1, _: &dyn Trait1) {} // CHECK: define{{.*}}5foo14{{.*}}!type ![[TYPE14:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo15(_: &dyn Trait1, _: &dyn Trait1, _: &dyn Trait1) { } +pub fn foo15(_: &dyn Trait1, _: &dyn Trait1, _: &dyn Trait1) {} // CHECK: define{{.*}}5foo15{{.*}}!type ![[TYPE15:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo16(_: &dyn Trait2) { } -pub fn bar16() { let a = Type2; foo16(&a); } +pub fn foo16(_: &dyn Trait2) {} +pub fn bar16() { + let a = Type2; + foo16(&a); +} // CHECK: define{{.*}}5foo16{{.*}}!type ![[TYPE16:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo17(_: &dyn Trait2, _: &dyn Trait2) { } -pub fn bar17() { let a = Type2; foo17(&a, &a); } +pub fn foo17(_: &dyn Trait2, _: &dyn Trait2) {} +pub fn bar17() { + let a = Type2; + foo17(&a, &a); +} // CHECK: define{{.*}}5foo17{{.*}}!type ![[TYPE17:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo18(_: &dyn Trait2, _: &dyn Trait2, _: &dyn Trait2) { } -pub fn bar18() { let a = Type2; foo18(&a, &a, &a); } +pub fn foo18(_: &dyn Trait2, _: &dyn Trait2, _: &dyn Trait2) {} +pub fn bar18() { + let a = Type2; + foo18(&a, &a, &a); +} // CHECK: define{{.*}}5foo18{{.*}}!type ![[TYPE18:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo19(_: &dyn Trait3) { } +pub fn foo19(_: &dyn Trait3) {} // CHECK: define{{.*}}5foo19{{.*}}!type ![[TYPE19:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo20(_: &dyn Trait3, _: &dyn Trait3) { } +pub fn foo20(_: &dyn Trait3, _: &dyn Trait3) {} // CHECK: define{{.*}}5foo20{{.*}}!type ![[TYPE20:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo21(_: &dyn Trait3, _: &dyn Trait3, _: &dyn Trait3) { } +pub fn foo21(_: &dyn Trait3, _: &dyn Trait3, _: &dyn Trait3) {} // CHECK: define{{.*}}5foo21{{.*}}!type ![[TYPE21:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo22<'a>(_: &dyn Trait4<'a, Type4, Output = &'a i32>) { } +pub fn foo22<'a>(_: &dyn Trait4<'a, Type4, Output = &'a i32>) {} // CHECK: define{{.*}}5foo22{{.*}}!type ![[TYPE22:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo23<'a>(_: &dyn Trait4<'a, Type4, Output = &'a i32>, - _: &dyn Trait4<'a, Type4, Output = &'a i32>) { } +pub fn foo23<'a>( + _: &dyn Trait4<'a, Type4, Output = &'a i32>, + _: &dyn Trait4<'a, Type4, Output = &'a i32>, +) { +} // CHECK: define{{.*}}5foo23{{.*}}!type ![[TYPE23:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo24<'a>(_: &dyn Trait4<'a, Type4, Output = &'a i32>, - _: &dyn Trait4<'a, Type4, Output = &'a i32>, - _: &dyn Trait4<'a, Type4, Output = &'a i32>) { } +pub fn foo24<'a>( + _: &dyn Trait4<'a, Type4, Output = &'a i32>, + _: &dyn Trait4<'a, Type4, Output = &'a i32>, + _: &dyn Trait4<'a, Type4, Output = &'a i32>, +) { +} // CHECK: define{{.*}}5foo24{{.*}}!type ![[TYPE24:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo25(_: &dyn Trait5) { } +pub fn foo25(_: &dyn Trait5) {} // CHECK: define{{.*}}5foo25{{.*}}!type ![[TYPE25:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo26(_: &dyn Trait5, _: &dyn Trait5) { } +pub fn foo26(_: &dyn Trait5, _: &dyn Trait5) {} // CHECK: define{{.*}}5foo26{{.*}}!type ![[TYPE26:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo27(_: &dyn Trait5, _: &dyn Trait5, _: &dyn Trait5) { } +pub fn foo27(_: &dyn Trait5, _: &dyn Trait5, _: &dyn Trait5) {} // CHECK: define{{.*}}5foo27{{.*}}!type ![[TYPE27:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} // CHECK: ![[TYPE13]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_{{[[:print:]]+}}6Trait1u6regionEEE"} diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-user-defined-types.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-user-defined-types.rs index 4eaf42bf87d1..c1f3ca61afeb 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-user-defined-types.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-user-defined-types.rs @@ -4,7 +4,7 @@ //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Copt-level=0 -Zsanitizer=cfi -Ctarget-feature=-crt-static -#![crate_type="lib"] +#![crate_type = "lib"] #![feature(extern_types)] pub struct Struct1 { @@ -19,33 +19,33 @@ pub union Union1 { member1: std::mem::ManuallyDrop, } -extern { +extern "C" { pub type type1; } -pub fn foo1(_: &Struct1::) { } +pub fn foo1(_: &Struct1) {} // CHECK: define{{.*}}4foo1{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo2(_: &Struct1::, _: &Struct1::) { } +pub fn foo2(_: &Struct1, _: &Struct1) {} // CHECK: define{{.*}}4foo2{{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo3(_: &Struct1::, _: &Struct1::, _: &Struct1::) { } +pub fn foo3(_: &Struct1, _: &Struct1, _: &Struct1) {} // CHECK: define{{.*}}4foo3{{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo4(_: &Enum1::) { } +pub fn foo4(_: &Enum1) {} // CHECK: define{{.*}}4foo4{{.*}}!type ![[TYPE4:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo5(_: &Enum1::, _: &Enum1::) { } +pub fn foo5(_: &Enum1, _: &Enum1) {} // CHECK: define{{.*}}4foo5{{.*}}!type ![[TYPE5:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo6(_: &Enum1::, _: &Enum1::, _: &Enum1::) { } +pub fn foo6(_: &Enum1, _: &Enum1, _: &Enum1) {} // CHECK: define{{.*}}4foo6{{.*}}!type ![[TYPE6:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo7(_: &Union1::) { } +pub fn foo7(_: &Union1) {} // CHECK: define{{.*}}4foo7{{.*}}!type ![[TYPE7:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo8(_: &Union1::, _: &Union1::) { } +pub fn foo8(_: &Union1, _: &Union1) {} // CHECK: define{{.*}}4foo8{{.*}}!type ![[TYPE8:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo9(_: &Union1::, _: &Union1::, _: &Union1::) { } +pub fn foo9(_: &Union1, _: &Union1, _: &Union1) {} // CHECK: define{{.*}}4foo9{{.*}}!type ![[TYPE9:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo10(_: *mut type1) { } +pub fn foo10(_: *mut type1) {} // CHECK: define{{.*}}5foo10{{.*}}!type ![[TYPE10:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo11(_: *mut type1, _: *mut type1) { } +pub fn foo11(_: *mut type1, _: *mut type1) {} // CHECK: define{{.*}}5foo11{{.*}}!type ![[TYPE11:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo12(_: *mut type1, _: *mut type1, _: *mut type1) { } +pub fn foo12(_: *mut type1, _: *mut type1, _: *mut type1) {} // CHECK: define{{.*}}5foo12{{.*}}!type ![[TYPE12:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} // CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtC{{[[:print:]]+}}_{{[[:print:]]+}}7Struct1Iu3i32EEE"} diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-itanium-cxx-abi-generalized.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-itanium-cxx-abi-generalized.rs index ccd7ee93ca1f..32637b64b3ea 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-metadata-itanium-cxx-abi-generalized.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-itanium-cxx-abi-generalized.rs @@ -3,7 +3,7 @@ //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-generalize-pointers -#![crate_type="lib"] +#![crate_type = "lib"] pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 { // CHECK-LABEL: define{{.*}}foo diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-itanium-cxx-abi-normalized-generalized.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-itanium-cxx-abi-normalized-generalized.rs index d41300341780..51121b0aef1a 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-metadata-itanium-cxx-abi-normalized-generalized.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-itanium-cxx-abi-normalized-generalized.rs @@ -3,7 +3,7 @@ //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-normalize-integers -Zsanitizer-cfi-generalize-pointers -#![crate_type="lib"] +#![crate_type = "lib"] pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 { // CHECK-LABEL: define{{.*}}foo diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-itanium-cxx-abi-normalized.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-itanium-cxx-abi-normalized.rs index ac18379165de..1cfdd23006e3 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-metadata-itanium-cxx-abi-normalized.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-itanium-cxx-abi-normalized.rs @@ -3,7 +3,7 @@ //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-normalize-integers -#![crate_type="lib"] +#![crate_type = "lib"] pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 { // CHECK-LABEL: define{{.*}}foo diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-itanium-cxx-abi.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-itanium-cxx-abi.rs index 526ba62c264d..56ab1ce4b358 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-metadata-itanium-cxx-abi.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-itanium-cxx-abi.rs @@ -3,7 +3,7 @@ //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -#![crate_type="lib"] +#![crate_type = "lib"] pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 { // CHECK-LABEL: define{{.*}}foo diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-trait-objects.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-trait-objects.rs index 318aad9291c4..0e57ce322d12 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-metadata-trait-objects.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-trait-objects.rs @@ -3,7 +3,7 @@ //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Copt-level=0 -Ctarget-feature=-crt-static -Zsanitizer=cfi -#![crate_type="lib"] +#![crate_type = "lib"] pub trait Trait1 { fn foo(&self); @@ -13,8 +13,7 @@ pub trait Trait1 { pub struct Type1; impl Trait1 for Type1 { - fn foo(&self) { - } + fn foo(&self) {} } pub trait Trait2 { @@ -24,8 +23,7 @@ pub trait Trait2 { pub struct Type2; impl Trait2 for Type2 { - fn bar(&self) { - } + fn bar(&self) {} } pub trait Trait3 { @@ -35,8 +33,7 @@ pub trait Trait3 { pub struct Type3; impl Trait3 for T { - fn baz(&self, _: &U) { - } + fn baz(&self, _: &U) {} } pub trait Trait4<'a, T> { @@ -61,8 +58,7 @@ pub trait Trait5 { pub struct Type5; impl Trait5 for T { - fn quux(&self, _: &[U; N]) { - } + fn quux(&self, _: &[U; N]) {} } pub fn foo1(a: &dyn Trait1) { diff --git a/tests/codegen/sanitizer/cfi/generalize-pointers.rs b/tests/codegen/sanitizer/cfi/generalize-pointers.rs index eaf3dad19092..57004da6f8e0 100644 --- a/tests/codegen/sanitizer/cfi/generalize-pointers.rs +++ b/tests/codegen/sanitizer/cfi/generalize-pointers.rs @@ -3,33 +3,33 @@ //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-generalize-pointers -Copt-level=0 -#![crate_type="lib"] +#![crate_type = "lib"] extern crate core; -pub fn foo0(_: &mut i32) { } +pub fn foo0(_: &mut i32) {} // CHECK: define{{.*}}foo0{{.*}}!type ![[TYPE0:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo1(_: &mut i32, _: &mut i32) { } +pub fn foo1(_: &mut i32, _: &mut i32) {} // CHECK: define{{.*}}foo1{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo2(_: &mut i32, _: &mut i32, _: &mut i32) { } +pub fn foo2(_: &mut i32, _: &mut i32, _: &mut i32) {} // CHECK: define{{.*}}foo2{{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo3(_: &i32) { } +pub fn foo3(_: &i32) {} // CHECK: define{{.*}}foo3{{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo4(_: &i32, _: &i32) { } +pub fn foo4(_: &i32, _: &i32) {} // CHECK: define{{.*}}foo4{{.*}}!type ![[TYPE4:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo5(_: &i32, _: &i32, _: &i32) { } +pub fn foo5(_: &i32, _: &i32, _: &i32) {} // CHECK: define{{.*}}foo5{{.*}}!type ![[TYPE5:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo6(_: *mut i32) { } +pub fn foo6(_: *mut i32) {} // CHECK: define{{.*}}foo6{{.*}}!type ![[TYPE6:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo7(_: *mut i32, _: *mut i32) { } +pub fn foo7(_: *mut i32, _: *mut i32) {} // CHECK: define{{.*}}foo7{{.*}}!type ![[TYPE7:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo8(_: *mut i32, _: *mut i32, _: *mut i32) { } +pub fn foo8(_: *mut i32, _: *mut i32, _: *mut i32) {} // CHECK: define{{.*}}foo8{{.*}}!type ![[TYPE8:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo9(_: *const i32) { } +pub fn foo9(_: *const i32) {} // CHECK: define{{.*}}foo9{{.*}}!type ![[TYPE9:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo10(_: *const i32, _: *const i32) { } +pub fn foo10(_: *const i32, _: *const i32) {} // CHECK: define{{.*}}foo10{{.*}}!type ![[TYPE10:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo11(_: *const i32, _: *const i32, _: *const i32) { } +pub fn foo11(_: *const i32, _: *const i32, _: *const i32) {} // CHECK: define{{.*}}foo11{{.*}}!type ![[TYPE11:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} // CHECK: ![[TYPE0]] = !{i64 0, !"_ZTSFvU3mutu3refIvEE.generalized"} diff --git a/tests/codegen/sanitizer/cfi/normalize-integers.rs b/tests/codegen/sanitizer/cfi/normalize-integers.rs index 801ed312be5b..770ee4e64e08 100644 --- a/tests/codegen/sanitizer/cfi/normalize-integers.rs +++ b/tests/codegen/sanitizer/cfi/normalize-integers.rs @@ -3,33 +3,33 @@ //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-normalize-integers -Copt-level=0 -#![crate_type="lib"] +#![crate_type = "lib"] extern crate core; -pub fn foo0(_: bool) { } +pub fn foo0(_: bool) {} // CHECK: define{{.*}}foo0{{.*}}!type ![[TYPE0:[0-9]+]] !type !{{[0-9]+}} -pub fn foo1(_: bool, _: bool) { } +pub fn foo1(_: bool, _: bool) {} // CHECK: define{{.*}}foo1{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} -pub fn foo2(_: bool, _: bool, _: bool) { } +pub fn foo2(_: bool, _: bool, _: bool) {} // CHECK: define{{.*}}foo2{{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}} -pub fn foo3(_: char) { } +pub fn foo3(_: char) {} // CHECK: define{{.*}}foo3{{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}} -pub fn foo4(_: char, _: char) { } +pub fn foo4(_: char, _: char) {} // CHECK: define{{.*}}foo4{{.*}}!type ![[TYPE4:[0-9]+]] !type !{{[0-9]+}} -pub fn foo5(_: char, _: char, _: char) { } +pub fn foo5(_: char, _: char, _: char) {} // CHECK: define{{.*}}foo5{{.*}}!type ![[TYPE5:[0-9]+]] !type !{{[0-9]+}} -pub fn foo6(_: isize) { } +pub fn foo6(_: isize) {} // CHECK: define{{.*}}foo6{{.*}}!type ![[TYPE6:[0-9]+]] !type !{{[0-9]+}} -pub fn foo7(_: isize, _: isize) { } +pub fn foo7(_: isize, _: isize) {} // CHECK: define{{.*}}foo7{{.*}}!type ![[TYPE7:[0-9]+]] !type !{{[0-9]+}} -pub fn foo8(_: isize, _: isize, _: isize) { } +pub fn foo8(_: isize, _: isize, _: isize) {} // CHECK: define{{.*}}foo8{{.*}}!type ![[TYPE8:[0-9]+]] !type !{{[0-9]+}} -pub fn foo9(_: (), _: usize) { } +pub fn foo9(_: (), _: usize) {} // CHECK: define{{.*}}foo9{{.*}}!type ![[TYPE9:[0-9]+]] !type !{{[0-9]+}} -pub fn foo10(_: (), _: usize, _: usize) { } +pub fn foo10(_: (), _: usize, _: usize) {} // CHECK: define{{.*}}foo10{{.*}}!type ![[TYPE10:[0-9]+]] !type !{{[0-9]+}} -pub fn foo11(_: (), _: usize, _: usize, _: usize) { } +pub fn foo11(_: (), _: usize, _: usize, _: usize) {} // CHECK: define{{.*}}foo11{{.*}}!type ![[TYPE11:[0-9]+]] !type !{{[0-9]+}} // CHECK: ![[TYPE0]] = !{i64 0, !"_ZTSFvu2u8E.normalized"} diff --git a/tests/codegen/sanitizer/dataflow-instrument-functions.rs b/tests/codegen/sanitizer/dataflow-instrument-functions.rs index 69c3560882c1..a2d0d63cc175 100644 --- a/tests/codegen/sanitizer/dataflow-instrument-functions.rs +++ b/tests/codegen/sanitizer/dataflow-instrument-functions.rs @@ -3,8 +3,7 @@ //@ needs-sanitizer-dataflow //@ compile-flags: -Copt-level=0 -Zsanitizer=dataflow -#![crate_type="lib"] +#![crate_type = "lib"] -pub fn foo() { -} +pub fn foo() {} // CHECK: define{{.*}}foo{{.*}}.dfsan diff --git a/tests/codegen/sanitizer/kcfi/add-kcfi-flag.rs b/tests/codegen/sanitizer/kcfi/add-kcfi-flag.rs index 7751d3baf79a..013de74f8d68 100644 --- a/tests/codegen/sanitizer/kcfi/add-kcfi-flag.rs +++ b/tests/codegen/sanitizer/kcfi/add-kcfi-flag.rs @@ -8,15 +8,14 @@ //@ compile-flags: -Ctarget-feature=-crt-static -Zsanitizer=kcfi #![feature(no_core, lang_items)] -#![crate_type="lib"] +#![crate_type = "lib"] #![no_core] -#[lang="sized"] -trait Sized { } -#[lang="copy"] -trait Copy { } +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} -pub fn foo() { -} +pub fn foo() {} // CHECK: !{{[0-9]+}} = !{i32 4, !"kcfi", i32 1} diff --git a/tests/codegen/sanitizer/kcfi/emit-kcfi-operand-bundle-attr-no-sanitize.rs b/tests/codegen/sanitizer/kcfi/emit-kcfi-operand-bundle-attr-no-sanitize.rs index 8055c63a2f8f..ba2e397f6daa 100644 --- a/tests/codegen/sanitizer/kcfi/emit-kcfi-operand-bundle-attr-no-sanitize.rs +++ b/tests/codegen/sanitizer/kcfi/emit-kcfi-operand-bundle-attr-no-sanitize.rs @@ -7,14 +7,14 @@ //@ [x86_64] needs-llvm-components: //@ compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi -Copt-level=0 -#![crate_type="lib"] +#![crate_type = "lib"] #![feature(no_core, no_sanitize, lang_items)] #![no_core] -#[lang="sized"] -trait Sized { } -#[lang="copy"] -trait Copy { } +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} impl Copy for i32 {} diff --git a/tests/codegen/sanitizer/kcfi/emit-kcfi-operand-bundle-itanium-cxx-abi-generalized.rs b/tests/codegen/sanitizer/kcfi/emit-kcfi-operand-bundle-itanium-cxx-abi-generalized.rs index bd1dfc4c413e..4e95bdf4d7c4 100644 --- a/tests/codegen/sanitizer/kcfi/emit-kcfi-operand-bundle-itanium-cxx-abi-generalized.rs +++ b/tests/codegen/sanitizer/kcfi/emit-kcfi-operand-bundle-itanium-cxx-abi-generalized.rs @@ -7,14 +7,14 @@ //@ [x86_64] needs-llvm-components: //@ compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi -Zsanitizer-cfi-generalize-pointers -#![crate_type="lib"] +#![crate_type = "lib"] #![feature(no_core, lang_items)] #![no_core] -#[lang="sized"] -trait Sized { } -#[lang="copy"] -trait Copy { } +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} impl Copy for i32 {} diff --git a/tests/codegen/sanitizer/kcfi/emit-kcfi-operand-bundle-itanium-cxx-abi-normalized-generalized.rs b/tests/codegen/sanitizer/kcfi/emit-kcfi-operand-bundle-itanium-cxx-abi-normalized-generalized.rs index b8275f44fac5..31b43b509880 100644 --- a/tests/codegen/sanitizer/kcfi/emit-kcfi-operand-bundle-itanium-cxx-abi-normalized-generalized.rs +++ b/tests/codegen/sanitizer/kcfi/emit-kcfi-operand-bundle-itanium-cxx-abi-normalized-generalized.rs @@ -7,14 +7,14 @@ //@ [x86_64] needs-llvm-components: //@ compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi -Zsanitizer-cfi-normalize-integers -Zsanitizer-cfi-generalize-pointers -#![crate_type="lib"] +#![crate_type = "lib"] #![feature(no_core, lang_items)] #![no_core] -#[lang="sized"] -trait Sized { } -#[lang="copy"] -trait Copy { } +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} impl Copy for i32 {} diff --git a/tests/codegen/sanitizer/kcfi/emit-kcfi-operand-bundle-itanium-cxx-abi-normalized.rs b/tests/codegen/sanitizer/kcfi/emit-kcfi-operand-bundle-itanium-cxx-abi-normalized.rs index cd1b0c5efb0a..4755f6062aaa 100644 --- a/tests/codegen/sanitizer/kcfi/emit-kcfi-operand-bundle-itanium-cxx-abi-normalized.rs +++ b/tests/codegen/sanitizer/kcfi/emit-kcfi-operand-bundle-itanium-cxx-abi-normalized.rs @@ -7,14 +7,14 @@ //@ [x86_64] needs-llvm-components: //@ compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi -Zsanitizer-cfi-normalize-integers -#![crate_type="lib"] +#![crate_type = "lib"] #![feature(no_core, lang_items)] #![no_core] -#[lang="sized"] -trait Sized { } -#[lang="copy"] -trait Copy { } +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} impl Copy for i32 {} diff --git a/tests/codegen/sanitizer/kcfi/emit-kcfi-operand-bundle-itanium-cxx-abi.rs b/tests/codegen/sanitizer/kcfi/emit-kcfi-operand-bundle-itanium-cxx-abi.rs index 12690577da7a..be9760bd9afa 100644 --- a/tests/codegen/sanitizer/kcfi/emit-kcfi-operand-bundle-itanium-cxx-abi.rs +++ b/tests/codegen/sanitizer/kcfi/emit-kcfi-operand-bundle-itanium-cxx-abi.rs @@ -7,14 +7,14 @@ //@ [x86_64] needs-llvm-components: //@ compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi -Copt-level=0 -#![crate_type="lib"] +#![crate_type = "lib"] #![feature(no_core, lang_items)] #![no_core] -#[lang="sized"] -trait Sized { } -#[lang="copy"] -trait Copy { } +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} impl Copy for i32 {} diff --git a/tests/codegen/sanitizer/kcfi/emit-kcfi-operand-bundle.rs b/tests/codegen/sanitizer/kcfi/emit-kcfi-operand-bundle.rs index f4b3e48638e4..c9c94cdb3292 100644 --- a/tests/codegen/sanitizer/kcfi/emit-kcfi-operand-bundle.rs +++ b/tests/codegen/sanitizer/kcfi/emit-kcfi-operand-bundle.rs @@ -7,14 +7,14 @@ //@ [x86_64] needs-llvm-components: //@ compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi -Copt-level=0 -#![crate_type="lib"] +#![crate_type = "lib"] #![feature(no_core, lang_items)] #![no_core] -#[lang="sized"] -trait Sized { } -#[lang="copy"] -trait Copy { } +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} impl Copy for i32 {} diff --git a/tests/codegen/sanitizer/kcfi/emit-type-metadata-trait-objects.rs b/tests/codegen/sanitizer/kcfi/emit-type-metadata-trait-objects.rs index f9c7cca39898..fc4d570dc2eb 100644 --- a/tests/codegen/sanitizer/kcfi/emit-type-metadata-trait-objects.rs +++ b/tests/codegen/sanitizer/kcfi/emit-type-metadata-trait-objects.rs @@ -7,30 +7,32 @@ //@ [x86_64] needs-llvm-components: //@ compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi -Copt-level=0 -#![crate_type="lib"] +#![crate_type = "lib"] #![feature(arbitrary_self_types, no_core, lang_items)] #![no_core] -#[lang="sized"] -trait Sized { } -#[lang="copy"] -trait Copy { } -#[lang="receiver"] -trait Receiver { } -#[lang="dispatch_from_dyn"] -trait DispatchFromDyn { } +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} +#[lang = "receiver"] +trait Receiver {} +#[lang = "dispatch_from_dyn"] +trait DispatchFromDyn {} impl<'a, T: ?Sized + Unsize, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {} #[lang = "unsize"] -trait Unsize { } +trait Unsize {} #[lang = "coerce_unsized"] -pub trait CoerceUnsized { } +pub trait CoerceUnsized {} impl<'a, 'b: 'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} -#[lang="freeze"] -trait Freeze { } -#[lang="drop_in_place"] -fn drop_in_place_fn() { } -#[lang="drop"] -trait Drop { fn drop(&mut self); } +#[lang = "freeze"] +trait Freeze {} +#[lang = "drop_in_place"] +fn drop_in_place_fn() {} +#[lang = "drop"] +trait Drop { + fn drop(&mut self); +} pub trait Trait1 { fn foo(&self); @@ -39,8 +41,7 @@ pub trait Trait1 { pub struct Type1; impl Trait1 for Type1 { - fn foo(&self) { - } + fn foo(&self) {} } pub trait Trait2 { @@ -50,8 +51,7 @@ pub trait Trait2 { pub struct Type2; impl Trait2 for Type2 { - fn bar(&self) { - } + fn bar(&self) {} } pub trait Trait3 { @@ -61,8 +61,7 @@ pub trait Trait3 { pub struct Type3; impl Trait3 for T { - fn baz(&self, _: &U) { - } + fn baz(&self, _: &U) {} } pub trait Trait4<'a, T> { @@ -88,8 +87,7 @@ pub struct Type5; impl Copy for Type5 {} impl Trait5 for T { - fn quux(&self, _: &[U; N]) { - } + fn quux(&self, _: &[U; N]) {} } pub fn foo1(a: &dyn Trait1) { diff --git a/tests/codegen/sanitizer/memory-track-origins.rs b/tests/codegen/sanitizer/memory-track-origins.rs index 956053ec42c7..318c277e10cb 100644 --- a/tests/codegen/sanitizer/memory-track-origins.rs +++ b/tests/codegen/sanitizer/memory-track-origins.rs @@ -11,7 +11,7 @@ //@[MSAN-1-LTO] compile-flags: -Zsanitizer-memory-track-origins=1 -C lto=fat //@[MSAN-2-LTO] compile-flags: -Zsanitizer-memory-track-origins -C lto=fat -#![crate_type="lib"] +#![crate_type = "lib"] // MSAN-0-NOT: @__msan_track_origins // MSAN-1: @__msan_track_origins = weak_odr {{.*}}constant i32 1 diff --git a/tests/codegen/sanitizer/no-sanitize-inlining.rs b/tests/codegen/sanitizer/no-sanitize-inlining.rs index d5e47884f858..4bd832d2ab19 100644 --- a/tests/codegen/sanitizer/no-sanitize-inlining.rs +++ b/tests/codegen/sanitizer/no-sanitize-inlining.rs @@ -8,7 +8,7 @@ //@[ASAN] compile-flags: -Zsanitizer=address //@[LSAN] compile-flags: -Zsanitizer=leak -#![crate_type="lib"] +#![crate_type = "lib"] #![feature(no_sanitize)] // ASAN-LABEL: define void @test diff --git a/tests/codegen/sanitizer/no-sanitize.rs b/tests/codegen/sanitizer/no-sanitize.rs index 2614416210ff..47d3fd83f112 100644 --- a/tests/codegen/sanitizer/no-sanitize.rs +++ b/tests/codegen/sanitizer/no-sanitize.rs @@ -4,7 +4,7 @@ //@ needs-sanitizer-address //@ compile-flags: -Zsanitizer=address -Ctarget-feature=-crt-static -Copt-level=0 -#![crate_type="lib"] +#![crate_type = "lib"] #![feature(no_sanitize)] // CHECK-LABEL: ; no_sanitize::unsanitized diff --git a/tests/codegen/set-discriminant-invalid.rs b/tests/codegen/set-discriminant-invalid.rs index 593da8cf80d0..0b7cb14880c9 100644 --- a/tests/codegen/set-discriminant-invalid.rs +++ b/tests/codegen/set-discriminant-invalid.rs @@ -7,17 +7,12 @@ pub struct TokioError { b: bool, } pub enum Error { - Api { - source: ApiError, - }, + Api { source: ApiError }, Ethereum, - Tokio { - source: TokioError, - }, + Tokio { source: TokioError }, } struct Api; -impl IntoError for Api -{ +impl IntoError for Api { type Source = ApiError; // CHECK-LABEL: @into_error // CHECK: llvm.trap() @@ -27,14 +22,11 @@ impl IntoError for Api // CHECK-NEXT: ret #[no_mangle] fn into_error(self, error: Self::Source) -> Error { - Error::Api { - source: error, - } + Error::Api { source: error } } } -pub trait IntoError -{ +pub trait IntoError { /// The underlying error type Source; diff --git a/tests/codegen/simd/issue-120720-reduce-nan.rs b/tests/codegen/simd/issue-120720-reduce-nan.rs index 0372582bf7f3..13af0bb076e6 100644 --- a/tests/codegen/simd/issue-120720-reduce-nan.rs +++ b/tests/codegen/simd/issue-120720-reduce-nan.rs @@ -15,8 +15,7 @@ pub unsafe fn demo() -> bool { // CHECK: %0 = tail call reassoc double @llvm.vector.reduce.fadd.v8f64( // CHECK: %_0.i = fcmp uno double %0, 0.000000e+00 // CHECK: ret i1 %_0.i - let res = unsafe { - _mm512_reduce_add_pd(_mm512_set_pd(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, f64::NAN)) - }; + let res = + unsafe { _mm512_reduce_add_pd(_mm512_set_pd(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, f64::NAN)) }; res.is_nan() } diff --git a/tests/codegen/simd/swap-simd-types.rs b/tests/codegen/simd/swap-simd-types.rs index 32e75220d696..cd6e84286e1c 100644 --- a/tests/codegen/simd/swap-simd-types.rs +++ b/tests/codegen/simd/swap-simd-types.rs @@ -13,18 +13,18 @@ use core::arch::x86_64::__m256; // CHECK-LABEL: @swap_single_m256 #[no_mangle] pub fn swap_single_m256(x: &mut __m256, y: &mut __m256) { -// CHECK-NOT: alloca -// CHECK: load <8 x float>{{.+}}align 32 -// CHECK: store <8 x float>{{.+}}align 32 + // CHECK-NOT: alloca + // CHECK: load <8 x float>{{.+}}align 32 + // CHECK: store <8 x float>{{.+}}align 32 swap(x, y) } // CHECK-LABEL: @swap_m256_slice #[no_mangle] pub fn swap_m256_slice(x: &mut [__m256], y: &mut [__m256]) { -// CHECK-NOT: alloca -// CHECK: load <8 x float>{{.+}}align 32 -// CHECK: store <8 x float>{{.+}}align 32 + // CHECK-NOT: alloca + // CHECK: load <8 x float>{{.+}}align 32 + // CHECK: store <8 x float>{{.+}}align 32 if x.len() == y.len() { x.swap_with_slice(y); } @@ -33,8 +33,8 @@ pub fn swap_m256_slice(x: &mut [__m256], y: &mut [__m256]) { // CHECK-LABEL: @swap_bytes32 #[no_mangle] pub fn swap_bytes32(x: &mut [u8; 32], y: &mut [u8; 32]) { -// CHECK-NOT: alloca -// CHECK: load <32 x i8>{{.+}}align 1 -// CHECK: store <32 x i8>{{.+}}align 1 + // CHECK-NOT: alloca + // CHECK: load <32 x i8>{{.+}}align 1 + // CHECK: store <32 x i8>{{.+}}align 1 swap(x, y) } diff --git a/tests/codegen/slice-position-bounds-check.rs b/tests/codegen/slice-position-bounds-check.rs index 301895883ee3..f83e2f2ec440 100644 --- a/tests/codegen/slice-position-bounds-check.rs +++ b/tests/codegen/slice-position-bounds-check.rs @@ -3,9 +3,7 @@ fn search(arr: &mut [T], a: &T) -> Result { match arr.iter().position(|x| x == a) { - Some(p) => { - Ok(p) - }, + Some(p) => Ok(p), None => Err(()), } } @@ -15,11 +13,7 @@ fn search(arr: &mut [T], a: &T) -> Result { pub fn position_no_bounds_check(y: &mut [u32], x: &u32, z: &u32) -> bool { // This contains "call assume" so we cannot just rule out all calls // CHECK-NOT: panic_bounds_check - if let Ok(p) = search(y, x) { - y[p] == *z - } else { - false - } + if let Ok(p) = search(y, x) { y[p] == *z } else { false } } // just to make sure that panicking really emits "panic_bounds_check" somewhere in the IR diff --git a/tests/codegen/slice-windows-no-bounds-check.rs b/tests/codegen/slice-windows-no-bounds-check.rs index 188011ebe7fd..db3211c8defd 100644 --- a/tests/codegen/slice-windows-no-bounds-check.rs +++ b/tests/codegen/slice-windows-no-bounds-check.rs @@ -12,10 +12,7 @@ pub fn naive_string_search(haystack: &str, needle: &str) -> Option { } // CHECK-NOT: panic // CHECK-NOT: fail - haystack - .as_bytes() - .windows(needle.len()) - .position(|sub| sub == needle.as_bytes()) + haystack.as_bytes().windows(needle.len()).position(|sub| sub == needle.as_bytes()) } // CHECK-LABEL: @next diff --git a/tests/codegen/some-abis-do-extend-params-to-32-bits.rs b/tests/codegen/some-abis-do-extend-params-to-32-bits.rs index a75a239e2ab8..10970cacdcf0 100644 --- a/tests/codegen/some-abis-do-extend-params-to-32-bits.rs +++ b/tests/codegen/some-abis-do-extend-params-to-32-bits.rs @@ -24,9 +24,12 @@ #![no_std] #![no_core] -#[lang="sized"] trait Sized { } -#[lang="freeze"] trait Freeze { } -#[lang="copy"] trait Copy { } +#[lang = "sized"] +trait Sized {} +#[lang = "freeze"] +trait Freeze {} +#[lang = "copy"] +trait Copy {} // The patterns in this file are written in the style of a table to make the // uniformities and distinctions more apparent. @@ -40,7 +43,8 @@ // aarch64-linux: void @c_arg_u8(i8 %_a) // arm: void @c_arg_u8(i8 zeroext %_a) // riscv: void @c_arg_u8(i8 zeroext %_a) -#[no_mangle] pub extern "C" fn c_arg_u8(_a: u8) { } +#[no_mangle] +pub extern "C" fn c_arg_u8(_a: u8) {} // x86_64: void @c_arg_u16(i16 zeroext %_a) // i686: void @c_arg_u16(i16 zeroext %_a) @@ -49,7 +53,8 @@ // aarch64-linux: void @c_arg_u16(i16 %_a) // arm: void @c_arg_u16(i16 zeroext %_a) // riscv: void @c_arg_u16(i16 zeroext %_a) -#[no_mangle] pub extern "C" fn c_arg_u16(_a: u16) { } +#[no_mangle] +pub extern "C" fn c_arg_u16(_a: u16) {} // x86_64: void @c_arg_u32(i32 %_a) // i686: void @c_arg_u32(i32 %_a) @@ -58,7 +63,8 @@ // aarch64-linux: void @c_arg_u32(i32 %_a) // arm: void @c_arg_u32(i32 %_a) // riscv: void @c_arg_u32(i32 signext %_a) -#[no_mangle] pub extern "C" fn c_arg_u32(_a: u32) { } +#[no_mangle] +pub extern "C" fn c_arg_u32(_a: u32) {} // x86_64: void @c_arg_u64(i64 %_a) // i686: void @c_arg_u64(i64 %_a) @@ -67,7 +73,8 @@ // aarch64-linux: void @c_arg_u64(i64 %_a) // arm: void @c_arg_u64(i64 %_a) // riscv: void @c_arg_u64(i64 %_a) -#[no_mangle] pub extern "C" fn c_arg_u64(_a: u64) { } +#[no_mangle] +pub extern "C" fn c_arg_u64(_a: u64) {} // x86_64: void @c_arg_i8(i8 signext %_a) // i686: void @c_arg_i8(i8 signext %_a) @@ -76,7 +83,8 @@ // aarch64-linux: void @c_arg_i8(i8 %_a) // arm: void @c_arg_i8(i8 signext %_a) // riscv: void @c_arg_i8(i8 signext %_a) -#[no_mangle] pub extern "C" fn c_arg_i8(_a: i8) { } +#[no_mangle] +pub extern "C" fn c_arg_i8(_a: i8) {} // x86_64: void @c_arg_i16(i16 signext %_a) // i686: void @c_arg_i16(i16 signext %_a) @@ -85,7 +93,8 @@ // aarch64-linux: void @c_arg_i16(i16 %_a) // arm: void @c_arg_i16(i16 signext %_a) // riscv: void @c_arg_i16(i16 signext %_a) -#[no_mangle] pub extern "C" fn c_arg_i16(_a: i16) { } +#[no_mangle] +pub extern "C" fn c_arg_i16(_a: i16) {} // x86_64: void @c_arg_i32(i32 %_a) // i686: void @c_arg_i32(i32 %_a) @@ -94,7 +103,8 @@ // aarch64-linux: void @c_arg_i32(i32 %_a) // arm: void @c_arg_i32(i32 %_a) // riscv: void @c_arg_i32(i32 signext %_a) -#[no_mangle] pub extern "C" fn c_arg_i32(_a: i32) { } +#[no_mangle] +pub extern "C" fn c_arg_i32(_a: i32) {} // x86_64: void @c_arg_i64(i64 %_a) // i686: void @c_arg_i64(i64 %_a) @@ -103,7 +113,8 @@ // aarch64-linux: void @c_arg_i64(i64 %_a) // arm: void @c_arg_i64(i64 %_a) // riscv: void @c_arg_i64(i64 %_a) -#[no_mangle] pub extern "C" fn c_arg_i64(_a: i64) { } +#[no_mangle] +pub extern "C" fn c_arg_i64(_a: i64) {} // x86_64: zeroext i8 @c_ret_u8() // i686: zeroext i8 @c_ret_u8() @@ -112,7 +123,10 @@ // aarch64-linux: i8 @c_ret_u8() // arm: zeroext i8 @c_ret_u8() // riscv: zeroext i8 @c_ret_u8() -#[no_mangle] pub extern "C" fn c_ret_u8() -> u8 { 0 } +#[no_mangle] +pub extern "C" fn c_ret_u8() -> u8 { + 0 +} // x86_64: zeroext i16 @c_ret_u16() // i686: zeroext i16 @c_ret_u16() @@ -121,7 +135,10 @@ // aarch64-linux: i16 @c_ret_u16() // arm: zeroext i16 @c_ret_u16() // riscv: zeroext i16 @c_ret_u16() -#[no_mangle] pub extern "C" fn c_ret_u16() -> u16 { 0 } +#[no_mangle] +pub extern "C" fn c_ret_u16() -> u16 { + 0 +} // x86_64: i32 @c_ret_u32() // i686: i32 @c_ret_u32() @@ -130,7 +147,10 @@ // aarch64-linux: i32 @c_ret_u32() // arm: i32 @c_ret_u32() // riscv: signext i32 @c_ret_u32() -#[no_mangle] pub extern "C" fn c_ret_u32() -> u32 { 0 } +#[no_mangle] +pub extern "C" fn c_ret_u32() -> u32 { + 0 +} // x86_64: i64 @c_ret_u64() // i686: i64 @c_ret_u64() @@ -139,7 +159,10 @@ // aarch64-linux: i64 @c_ret_u64() // arm: i64 @c_ret_u64() // riscv: i64 @c_ret_u64() -#[no_mangle] pub extern "C" fn c_ret_u64() -> u64 { 0 } +#[no_mangle] +pub extern "C" fn c_ret_u64() -> u64 { + 0 +} // x86_64: signext i8 @c_ret_i8() // i686: signext i8 @c_ret_i8() @@ -148,7 +171,10 @@ // aarch64-linux: i8 @c_ret_i8() // arm: signext i8 @c_ret_i8() // riscv: signext i8 @c_ret_i8() -#[no_mangle] pub extern "C" fn c_ret_i8() -> i8 { 0 } +#[no_mangle] +pub extern "C" fn c_ret_i8() -> i8 { + 0 +} // x86_64: signext i16 @c_ret_i16() // i686: signext i16 @c_ret_i16() @@ -157,7 +183,10 @@ // aarch64-linux: i16 @c_ret_i16() // arm: signext i16 @c_ret_i16() // riscv: signext i16 @c_ret_i16() -#[no_mangle] pub extern "C" fn c_ret_i16() -> i16 { 0 } +#[no_mangle] +pub extern "C" fn c_ret_i16() -> i16 { + 0 +} // x86_64: i32 @c_ret_i32() // i686: i32 @c_ret_i32() @@ -166,7 +195,10 @@ // aarch64-linux: i32 @c_ret_i32() // arm: i32 @c_ret_i32() // riscv: signext i32 @c_ret_i32() -#[no_mangle] pub extern "C" fn c_ret_i32() -> i32 { 0 } +#[no_mangle] +pub extern "C" fn c_ret_i32() -> i32 { + 0 +} // x86_64: i64 @c_ret_i64() // i686: i64 @c_ret_i64() @@ -175,7 +207,10 @@ // aarch64-linux: i64 @c_ret_i64() // arm: i64 @c_ret_i64() // riscv: i64 @c_ret_i64() -#[no_mangle] pub extern "C" fn c_ret_i64() -> i64 { 0 } +#[no_mangle] +pub extern "C" fn c_ret_i64() -> i64 { + 0 +} const C_SOURCE_FILE: &'static str = r##" #include diff --git a/tests/codegen/sparc-struct-abi.rs b/tests/codegen/sparc-struct-abi.rs index 0850e9e15eaf..5d9781663570 100644 --- a/tests/codegen/sparc-struct-abi.rs +++ b/tests/codegen/sparc-struct-abi.rs @@ -6,12 +6,12 @@ #![feature(no_core, lang_items)] #![no_core] -#[lang="sized"] -trait Sized { } -#[lang="freeze"] -trait Freeze { } -#[lang="copy"] -trait Copy { } +#[lang = "sized"] +trait Sized {} +#[lang = "freeze"] +trait Freeze {} +#[lang = "copy"] +trait Copy {} #[repr(C)] pub struct Bool { @@ -26,7 +26,6 @@ pub extern "C" fn structbool() -> Bool { Bool { b: true } } - #[repr(C)] pub struct BoolFloat { b: bool, @@ -44,8 +43,7 @@ pub extern "C" fn structboolfloat() -> BoolFloat { // CHECK: define void @structboolfloat_input({ i32, float } inreg %0) // CHECK-NEXT: start: #[no_mangle] -pub extern "C" fn structboolfloat_input(a: BoolFloat) { } - +pub extern "C" fn structboolfloat_input(a: BoolFloat) {} #[repr(C)] pub struct ShortDouble { @@ -64,8 +62,7 @@ pub extern "C" fn structshortdouble() -> ShortDouble { // CHECK: define void @structshortdouble_input({ i64, double } %0) // CHECK-NEXT: start: #[no_mangle] -pub extern "C" fn structshortdouble_input(a: ShortDouble) { } - +pub extern "C" fn structshortdouble_input(a: ShortDouble) {} #[repr(C)] pub struct FloatLongFloat { diff --git a/tests/codegen/split-lto-unit.rs b/tests/codegen/split-lto-unit.rs index 6cea9a2d8d5f..7858a0e7b796 100644 --- a/tests/codegen/split-lto-unit.rs +++ b/tests/codegen/split-lto-unit.rs @@ -3,9 +3,8 @@ //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Ctarget-feature=-crt-static -Zsplit-lto-unit -#![crate_type="lib"] +#![crate_type = "lib"] -pub fn foo() { -} +pub fn foo() {} // CHECK: !{{[0-9]+}} = !{i32 4, !"EnableSplitLTOUnit", i32 1} diff --git a/tests/codegen/sroa-fragment-debuginfo.rs b/tests/codegen/sroa-fragment-debuginfo.rs index 670ddb56540e..0413cf968942 100644 --- a/tests/codegen/sroa-fragment-debuginfo.rs +++ b/tests/codegen/sroa-fragment-debuginfo.rs @@ -13,13 +13,13 @@ pub struct ExtraSlice<'input> { #[no_mangle] pub fn extra(s: &[u8]) { -// CHECK: void @extra( -// CHECK: %slice.dbg.spill1 = alloca [4 x i8], -// CHECK: %slice.dbg.spill = alloca [16 x i8], -// CHECK: %s.dbg.spill = alloca [16 x i8], -// CHECK: dbg{{.}}declare({{(metadata )?}}ptr %s.dbg.spill, {{(metadata )?}}![[S_EXTRA:.*]], {{(metadata )?}}!DIExpression() -// CHECK: dbg{{.}}declare({{(metadata )?}}ptr %slice.dbg.spill, {{(metadata )?}}![[SLICE_EXTRA:.*]], {{(metadata )?}}!DIExpression(DW_OP_LLVM_fragment, 0, 128) -// CHECK: dbg{{.}}declare({{(metadata )?}}ptr %slice.dbg.spill1, {{(metadata )?}}![[SLICE_EXTRA]], {{(metadata )?}}!DIExpression(DW_OP_LLVM_fragment, 128, 32) + // CHECK: void @extra( + // CHECK: %slice.dbg.spill1 = alloca [4 x i8], + // CHECK: %slice.dbg.spill = alloca [16 x i8], + // CHECK: %s.dbg.spill = alloca [16 x i8], + // CHECK: dbg{{.}}declare({{(metadata )?}}ptr %s.dbg.spill, {{(metadata )?}}![[S_EXTRA:.*]], {{(metadata )?}}!DIExpression() + // CHECK: dbg{{.}}declare({{(metadata )?}}ptr %slice.dbg.spill, {{(metadata )?}}![[SLICE_EXTRA:.*]], {{(metadata )?}}!DIExpression(DW_OP_LLVM_fragment, 0, 128) + // CHECK: dbg{{.}}declare({{(metadata )?}}ptr %slice.dbg.spill1, {{(metadata )?}}![[SLICE_EXTRA]], {{(metadata )?}}!DIExpression(DW_OP_LLVM_fragment, 128, 32) let slice = ExtraSlice { slice: s, extra: s.len() as u32 }; } @@ -35,10 +35,10 @@ pub fn zst(s: &[u8]) { // The field `extra` is a ZST. The fragment for the field `slice` encompasses the whole // variable, so is not a fragment. In that case, the variable must have no fragment. -// CHECK: void @zst( -// CHECK-NOT: dbg{{.}}declare({{(metadata )?}}ptr %slice.dbg.spill, {{(metadata )?}}!{}, {{(metadata )?}}!DIExpression(DW_OP_LLVM_fragment, -// CHECK: dbg{{.}}declare({{(metadata )?}}ptr %{{.*}}, {{(metadata )?}}![[SLICE_ZST:.*]], {{(metadata )?}}!DIExpression() -// CHECK-NOT: dbg{{.}}declare({{(metadata )?}}ptr %{{.*}}, {{(metadata )?}}![[SLICE_ZST]], + // CHECK: void @zst( + // CHECK-NOT: dbg{{.}}declare({{(metadata )?}}ptr %slice.dbg.spill, {{(metadata )?}}!{}, {{(metadata )?}}!DIExpression(DW_OP_LLVM_fragment, + // CHECK: dbg{{.}}declare({{(metadata )?}}ptr %{{.*}}, {{(metadata )?}}![[SLICE_ZST:.*]], {{(metadata )?}}!DIExpression() + // CHECK-NOT: dbg{{.}}declare({{(metadata )?}}ptr %{{.*}}, {{(metadata )?}}![[SLICE_ZST]], let slice = ZstSlice { slice: s, extra: Zst }; } diff --git a/tests/codegen/stack-probes-inline.rs b/tests/codegen/stack-probes-inline.rs index 6bd6b0cb354c..c5073b9cc221 100644 --- a/tests/codegen/stack-probes-inline.rs +++ b/tests/codegen/stack-probes-inline.rs @@ -27,6 +27,6 @@ trait Sized {} #[no_mangle] pub fn foo() { -// CHECK: @foo() unnamed_addr #0 -// CHECK: attributes #0 = { {{.*}}"probe-stack"="inline-asm"{{.*}} } + // CHECK: @foo() unnamed_addr #0 + // CHECK: attributes #0 = { {{.*}}"probe-stack"="inline-asm"{{.*}} } } diff --git a/tests/codegen/static-relocation-model-msvc.rs b/tests/codegen/static-relocation-model-msvc.rs index 5501827498cc..8ed8331466c7 100644 --- a/tests/codegen/static-relocation-model-msvc.rs +++ b/tests/codegen/static-relocation-model-msvc.rs @@ -20,7 +20,5 @@ extern crate extern_decl; #[no_mangle] pub fn access_extern() -> u8 { - unsafe { - extern_decl::extern_fn() + extern_decl::extern_static - } + unsafe { extern_decl::extern_fn() + extern_decl::extern_static } } diff --git a/tests/codegen/stores.rs b/tests/codegen/stores.rs index 86ec52fa1015..aa3090db6d31 100644 --- a/tests/codegen/stores.rs +++ b/tests/codegen/stores.rs @@ -4,10 +4,10 @@ #![crate_type = "lib"] pub struct Bytes { - a: u8, - b: u8, - c: u8, - d: u8, + a: u8, + b: u8, + c: u8, + d: u8, } // CHECK-LABEL: small_array_alignment @@ -15,10 +15,10 @@ pub struct Bytes { // dependent alignment #[no_mangle] pub fn small_array_alignment(x: &mut [i8; 4], y: [i8; 4]) { -// CHECK: [[TMP:%.+]] = alloca [4 x i8], align 4 -// CHECK: %y = alloca [4 x i8], align 1 -// CHECK: store i32 %0, ptr [[TMP]] -// CHECK: call void @llvm.memcpy.{{.*}}(ptr align 1 {{.+}}, ptr align 4 {{.+}}, i{{[0-9]+}} 4, i1 false) + // CHECK: [[TMP:%.+]] = alloca [4 x i8], align 4 + // CHECK: %y = alloca [4 x i8], align 1 + // CHECK: store i32 %0, ptr [[TMP]] + // CHECK: call void @llvm.memcpy.{{.*}}(ptr align 1 {{.+}}, ptr align 4 {{.+}}, i{{[0-9]+}} 4, i1 false) *x = y; } @@ -27,9 +27,9 @@ pub fn small_array_alignment(x: &mut [i8; 4], y: [i8; 4]) { // dependent alignment #[no_mangle] pub fn small_struct_alignment(x: &mut Bytes, y: Bytes) { -// CHECK: [[TMP:%.+]] = alloca [4 x i8], align 4 -// CHECK: %y = alloca [4 x i8], align 1 -// CHECK: store i32 %0, ptr [[TMP]] -// CHECK: call void @llvm.memcpy.{{.*}}(ptr align 1 {{.+}}, ptr align 4 {{.+}}, i{{[0-9]+}} 4, i1 false) + // CHECK: [[TMP:%.+]] = alloca [4 x i8], align 4 + // CHECK: %y = alloca [4 x i8], align 1 + // CHECK: store i32 %0, ptr [[TMP]] + // CHECK: call void @llvm.memcpy.{{.*}}(ptr align 1 {{.+}}, ptr align 4 {{.+}}, i{{[0-9]+}} 4, i1 false) *x = y; } diff --git a/tests/codegen/swap-large-types.rs b/tests/codegen/swap-large-types.rs index b976f6fe207b..761d48969dad 100644 --- a/tests/codegen/swap-large-types.rs +++ b/tests/codegen/swap-large-types.rs @@ -4,7 +4,7 @@ #![crate_type = "lib"] use std::mem::swap; -use std::ptr::{read, copy_nonoverlapping, write}; +use std::ptr::{copy_nonoverlapping, read, write}; type KeccakBuffer = [[u64; 5]; 5]; @@ -15,7 +15,7 @@ type KeccakBuffer = [[u64; 5]; 5]; // CHECK-LABEL: @swap_basic #[no_mangle] pub fn swap_basic(x: &mut KeccakBuffer, y: &mut KeccakBuffer) { -// CHECK: alloca [200 x i8] + // CHECK: alloca [200 x i8] // SAFETY: exclusive references are always valid to read/write, // are non-overlapping, and nothing here panics so it's drop-safe. @@ -32,9 +32,9 @@ pub fn swap_basic(x: &mut KeccakBuffer, y: &mut KeccakBuffer) { // CHECK-LABEL: @swap_std #[no_mangle] pub fn swap_std(x: &mut KeccakBuffer, y: &mut KeccakBuffer) { -// CHECK-NOT: alloca -// CHECK: load <{{[0-9]+}} x i64> -// CHECK: store <{{[0-9]+}} x i64> + // CHECK-NOT: alloca + // CHECK: load <{{[0-9]+}} x i64> + // CHECK: store <{{[0-9]+}} x i64> swap(x, y) } @@ -44,9 +44,9 @@ pub fn swap_std(x: &mut KeccakBuffer, y: &mut KeccakBuffer) { // CHECK-LABEL: @swap_slice #[no_mangle] pub fn swap_slice(x: &mut [KeccakBuffer], y: &mut [KeccakBuffer]) { -// CHECK-NOT: alloca -// CHECK: load <{{[0-9]+}} x i64> -// CHECK: store <{{[0-9]+}} x i64> + // CHECK-NOT: alloca + // CHECK: load <{{[0-9]+}} x i64> + // CHECK: store <{{[0-9]+}} x i64> if x.len() == y.len() { x.swap_with_slice(y); } @@ -59,9 +59,9 @@ type OneKilobyteBuffer = [u8; 1024]; // CHECK-LABEL: @swap_1kb_slices #[no_mangle] pub fn swap_1kb_slices(x: &mut [OneKilobyteBuffer], y: &mut [OneKilobyteBuffer]) { -// CHECK-NOT: alloca -// CHECK: load <{{[0-9]+}} x i8> -// CHECK: store <{{[0-9]+}} x i8> + // CHECK-NOT: alloca + // CHECK: load <{{[0-9]+}} x i8> + // CHECK: store <{{[0-9]+}} x i8> if x.len() == y.len() { x.swap_with_slice(y); } @@ -81,10 +81,10 @@ pub struct BigButHighlyAligned([u8; 64 * 3]); // CHECK-LABEL: @swap_big_aligned #[no_mangle] pub fn swap_big_aligned(x: &mut BigButHighlyAligned, y: &mut BigButHighlyAligned) { -// CHECK-NOT: call void @llvm.memcpy -// CHECK: call void @llvm.memcpy.{{.+}}(ptr noundef nonnull align 64 dereferenceable(192) -// CHECK: call void @llvm.memcpy.{{.+}}(ptr noundef nonnull align 64 dereferenceable(192) -// CHECK: call void @llvm.memcpy.{{.+}}(ptr noundef nonnull align 64 dereferenceable(192) -// CHECK-NOT: call void @llvm.memcpy + // CHECK-NOT: call void @llvm.memcpy + // CHECK: call void @llvm.memcpy.{{.+}}(ptr noundef nonnull align 64 dereferenceable(192) + // CHECK: call void @llvm.memcpy.{{.+}}(ptr noundef nonnull align 64 dereferenceable(192) + // CHECK: call void @llvm.memcpy.{{.+}}(ptr noundef nonnull align 64 dereferenceable(192) + // CHECK-NOT: call void @llvm.memcpy swap(x, y) } diff --git a/tests/codegen/target-feature-overrides.rs b/tests/codegen/target-feature-overrides.rs index 61b1b3fd2578..1e2c364dbbc9 100644 --- a/tests/codegen/target-feature-overrides.rs +++ b/tests/codegen/target-feature-overrides.rs @@ -9,7 +9,6 @@ #![crate_type = "lib"] #![no_core] - #[lang = "sized"] trait Sized {} #[lang = "copy"] @@ -23,19 +22,19 @@ extern "C" { #[target_feature(enable = "avx")] #[no_mangle] pub unsafe fn apple() -> u32 { -// CHECK-LABEL: @apple() -// CHECK-SAME: [[APPLEATTRS:#[0-9]+]] { -// CHECK: {{.*}}call{{.*}}@peach + // CHECK-LABEL: @apple() + // CHECK-SAME: [[APPLEATTRS:#[0-9]+]] { + // CHECK: {{.*}}call{{.*}}@peach peach() } // target features same as global #[no_mangle] pub unsafe fn banana() -> u32 { -// CHECK-LABEL: @banana() -// CHECK-SAME: [[BANANAATTRS:#[0-9]+]] { -// COMPAT: {{.*}}call{{.*}}@peach -// INCOMPAT: {{.*}}call{{.*}}@apple + // CHECK-LABEL: @banana() + // CHECK-SAME: [[BANANAATTRS:#[0-9]+]] { + // COMPAT: {{.*}}call{{.*}}@peach + // INCOMPAT: {{.*}}call{{.*}}@apple apple() // Compatible for inline in COMPAT revision and can't be inlined in INCOMPAT } diff --git a/tests/codegen/thin-lto.rs b/tests/codegen/thin-lto.rs index c75f9841a773..4339d20532ea 100644 --- a/tests/codegen/thin-lto.rs +++ b/tests/codegen/thin-lto.rs @@ -3,5 +3,4 @@ // CHECK: main -pub fn main() { -} +pub fn main() {} diff --git a/tests/codegen/tied-features-strength.rs b/tests/codegen/tied-features-strength.rs index b97865295a23..7f0805bc1b43 100644 --- a/tests/codegen/tied-features-strength.rs +++ b/tests/codegen/tied-features-strength.rs @@ -19,7 +19,6 @@ //@ [ENABLE_NEON] compile-flags: -C target-feature=+neon -Copt-level=0 // ENABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(\+fp-armv8,?)|(\+neon,?))*}}" } - #![feature(no_core, lang_items)] #![no_core] diff --git a/tests/codegen/to_vec.rs b/tests/codegen/to_vec.rs index 651084d811ca..4666f8d6f153 100644 --- a/tests/codegen/to_vec.rs +++ b/tests/codegen/to_vec.rs @@ -5,6 +5,6 @@ // CHECK-LABEL: @copy_to_vec #[no_mangle] fn copy_to_vec(s: &[u64]) -> Vec { - s.to_vec() - // CHECK: call void @llvm.memcpy + s.to_vec() + // CHECK: call void @llvm.memcpy } diff --git a/tests/codegen/transmute-optimized.rs b/tests/codegen/transmute-optimized.rs index 8e5bcb2340e4..11bd0523788a 100644 --- a/tests/codegen/transmute-optimized.rs +++ b/tests/codegen/transmute-optimized.rs @@ -5,7 +5,9 @@ // destination types for transmutes. #[repr(u32)] -pub enum AlwaysZero32 { X = 0 } +pub enum AlwaysZero32 { + X = 0, +} // CHECK-LABEL: i32 @issue_109958(i32 #[no_mangle] @@ -81,7 +83,11 @@ pub fn div_transmute_nonzero(a: u32, b: std::num::NonZero) -> u32 { } #[repr(i8)] -pub enum OneTwoThree { One = 1, Two = 2, Three = 3 } +pub enum OneTwoThree { + One = 1, + Two = 2, + Three = 3, +} // CHECK-LABEL: i8 @ordering_transmute_onetwothree(i8 #[no_mangle] diff --git a/tests/codegen/try_identity.rs b/tests/codegen/try_identity.rs index 87b7d0727d08..6a3a8a06e82b 100644 --- a/tests/codegen/try_identity.rs +++ b/tests/codegen/try_identity.rs @@ -13,9 +13,9 @@ type R = Result; // optimization that picks up the `?` desugaring, as `SimplifyArmIdentity` does not. #[no_mangle] pub fn try_identity(x: R) -> R { -// CHECK: start: -// FIXME(JakobDegen): Broken by deaggregation change CHECK-NOT\: br {{.*}} -// CHECK ret void + // CHECK: start: + // FIXME(JakobDegen): Broken by deaggregation change CHECK-NOT\: br {{.*}} + // CHECK ret void let y = match into_result(x) { Err(e) => return from_error(From::from(e)), Ok(v) => v, diff --git a/tests/codegen/try_question_mark_nop.rs b/tests/codegen/try_question_mark_nop.rs index f6cdf9552097..c23f41f54671 100644 --- a/tests/codegen/try_question_mark_nop.rs +++ b/tests/codegen/try_question_mark_nop.rs @@ -4,7 +4,7 @@ #![crate_type = "lib"] #![feature(try_blocks)] -use std::ops::ControlFlow::{self, Continue, Break}; +use std::ops::ControlFlow::{self, Break, Continue}; use std::ptr::NonNull; // CHECK-LABEL: @option_nop_match_32 @@ -27,9 +27,7 @@ pub fn option_nop_traits_32(x: Option) -> Option { // CHECK-NEXT: insertvalue { i32, i32 } // CHECK-NEXT: insertvalue { i32, i32 } // CHECK-NEXT: ret { i32, i32 } - try { - x? - } + try { x? } } // CHECK-LABEL: @result_nop_match_32 @@ -52,9 +50,7 @@ pub fn result_nop_traits_32(x: Result) -> Result { // CHECK-NEXT: insertvalue { i32, i32 } // CHECK-NEXT: insertvalue { i32, i32 } // CHECK-NEXT: ret { i32, i32 } - try { - x? - } + try { x? } } // CHECK-LABEL: @result_nop_match_64 @@ -77,9 +73,7 @@ pub fn result_nop_traits_64(x: Result) -> Result { // CHECK-NEXT: insertvalue { i64, i64 } // CHECK-NEXT: insertvalue { i64, i64 } // CHECK-NEXT: ret { i64, i64 } - try { - x? - } + try { x? } } // CHECK-LABEL: @result_nop_match_ptr @@ -102,9 +96,7 @@ pub fn result_nop_traits_ptr(x: Result>) -> Result) -> ControlFlow ScalarZstLast { loop {} } +pub fn test_ScalarZstLast(_: ScalarZstLast) -> ScalarZstLast { + loop {} +} type ScalarZstFirst = ((), u128); // CHECK: define {{(dso_local )?}}i128 @test_ScalarZstFirst(i128 %_1) #[no_mangle] -pub fn test_ScalarZstFirst(_: ScalarZstFirst) -> ScalarZstFirst { loop {} } +pub fn test_ScalarZstFirst(_: ScalarZstFirst) -> ScalarZstFirst { + loop {} +} type ScalarPairZstLast = (u8, u128, ()); // CHECK: define {{(dso_local )?}}{ i128, i8 } @test_ScalarPairZstLast(i128 %_1.0, i8 %_1.1) #[no_mangle] -pub fn test_ScalarPairZstLast(_: ScalarPairZstLast) -> ScalarPairZstLast { loop {} } +pub fn test_ScalarPairZstLast(_: ScalarPairZstLast) -> ScalarPairZstLast { + loop {} +} type ScalarPairZstFirst = ((), u8, u128); // CHECK: define {{(dso_local )?}}{ i8, i128 } @test_ScalarPairZstFirst(i8 %_1.0, i128 %_1.1) #[no_mangle] -pub fn test_ScalarPairZstFirst(_: ScalarPairZstFirst) -> ScalarPairZstFirst { loop {} } +pub fn test_ScalarPairZstFirst(_: ScalarPairZstFirst) -> ScalarPairZstFirst { + loop {} +} type ScalarPairLotsOfZsts = ((), u8, (), u128, ()); // CHECK: define {{(dso_local )?}}{ i128, i8 } @test_ScalarPairLotsOfZsts(i128 %_1.0, i8 %_1.1) #[no_mangle] -pub fn test_ScalarPairLotsOfZsts(_: ScalarPairLotsOfZsts) -> ScalarPairLotsOfZsts { loop {} } +pub fn test_ScalarPairLotsOfZsts(_: ScalarPairLotsOfZsts) -> ScalarPairLotsOfZsts { + loop {} +} type ScalarPairLottaNesting = (((), ((), u8, (), u128, ())), ()); // CHECK: define {{(dso_local )?}}{ i128, i8 } @test_ScalarPairLottaNesting(i128 %_1.0, i8 %_1.1) #[no_mangle] -pub fn test_ScalarPairLottaNesting(_: ScalarPairLottaNesting) -> ScalarPairLottaNesting { loop {} } +pub fn test_ScalarPairLottaNesting(_: ScalarPairLottaNesting) -> ScalarPairLottaNesting { + loop {} +} diff --git a/tests/codegen/union-abi.rs b/tests/codegen/union-abi.rs index b1b0daa13b64..9e02fa9ff359 100644 --- a/tests/codegen/union-abi.rs +++ b/tests/codegen/union-abi.rs @@ -4,7 +4,7 @@ // This test that using union forward the abi of the inner type, as // discussed in #54668 -#![crate_type="lib"] +#![crate_type = "lib"] #![feature(repr_simd)] #[derive(Copy, Clone)] @@ -15,62 +15,111 @@ pub enum Unhab {} pub struct i64x4(i64, i64, i64, i64); #[derive(Copy, Clone)] -pub union UnionI64x4{ a:(), b: i64x4 } +pub union UnionI64x4 { + a: (), + b: i64x4, +} // CHECK: define {{(dso_local )?}}void @test_UnionI64x4(ptr {{.*}} %_1) #[no_mangle] -pub fn test_UnionI64x4(_: UnionI64x4) { loop {} } +pub fn test_UnionI64x4(_: UnionI64x4) { + loop {} +} -pub union UnionI64x4_{ a: i64x4, b: (), c:i64x4, d: Unhab, e: ((),()), f: UnionI64x4 } +pub union UnionI64x4_ { + a: i64x4, + b: (), + c: i64x4, + d: Unhab, + e: ((), ()), + f: UnionI64x4, +} // CHECK: define {{(dso_local )?}}void @test_UnionI64x4_(ptr {{.*}} %_1) #[no_mangle] -pub fn test_UnionI64x4_(_: UnionI64x4_) { loop {} } +pub fn test_UnionI64x4_(_: UnionI64x4_) { + loop {} +} -pub union UnionI64x4I64{ a: i64x4, b: i64 } +pub union UnionI64x4I64 { + a: i64x4, + b: i64, +} // CHECK: define {{(dso_local )?}}void @test_UnionI64x4I64(ptr {{.*}} %_1) #[no_mangle] -pub fn test_UnionI64x4I64(_: UnionI64x4I64) { loop {} } +pub fn test_UnionI64x4I64(_: UnionI64x4I64) { + loop {} +} -pub union UnionI64x4Tuple{ a: i64x4, b: (i64, i64, i64, i64) } +pub union UnionI64x4Tuple { + a: i64x4, + b: (i64, i64, i64, i64), +} // CHECK: define {{(dso_local )?}}void @test_UnionI64x4Tuple(ptr {{.*}} %_1) #[no_mangle] -pub fn test_UnionI64x4Tuple(_: UnionI64x4Tuple) { loop {} } +pub fn test_UnionI64x4Tuple(_: UnionI64x4Tuple) { + loop {} +} - -pub union UnionF32{a:f32} +pub union UnionF32 { + a: f32, +} // CHECK: define {{(dso_local )?}}float @test_UnionF32(float %_1) #[no_mangle] -pub fn test_UnionF32(_: UnionF32) -> UnionF32 { loop {} } +pub fn test_UnionF32(_: UnionF32) -> UnionF32 { + loop {} +} -pub union UnionF32F32{a:f32, b:f32} +pub union UnionF32F32 { + a: f32, + b: f32, +} // CHECK: define {{(dso_local )?}}float @test_UnionF32F32(float %_1) #[no_mangle] -pub fn test_UnionF32F32(_: UnionF32F32) -> UnionF32F32 { loop {} } +pub fn test_UnionF32F32(_: UnionF32F32) -> UnionF32F32 { + loop {} +} -pub union UnionF32U32{a:f32, b:u32} +pub union UnionF32U32 { + a: f32, + b: u32, +} // CHECK: define {{(dso_local )?}}i32 @test_UnionF32U32(i32{{( %0)?}}) #[no_mangle] -pub fn test_UnionF32U32(_: UnionF32U32) -> UnionF32U32 { loop {} } +pub fn test_UnionF32U32(_: UnionF32U32) -> UnionF32U32 { + loop {} +} -pub union UnionU128{a:u128} +pub union UnionU128 { + a: u128, +} // CHECK: define {{(dso_local )?}}i128 @test_UnionU128(i128 %_1) #[no_mangle] -pub fn test_UnionU128(_: UnionU128) -> UnionU128 { loop {} } +pub fn test_UnionU128(_: UnionU128) -> UnionU128 { + loop {} +} #[repr(C)] -pub union CUnionU128{a:u128} +pub union CUnionU128 { + a: u128, +} // CHECK: define {{(dso_local )?}}void @test_CUnionU128(ptr {{.*}} %_1) #[no_mangle] -pub fn test_CUnionU128(_: CUnionU128) { loop {} } +pub fn test_CUnionU128(_: CUnionU128) { + loop {} +} -pub union UnionBool { b:bool } +pub union UnionBool { + b: bool, +} // CHECK: define {{(dso_local )?}}noundef zeroext i1 @test_UnionBool(i8 %b) #[no_mangle] -pub fn test_UnionBool(b: UnionBool) -> bool { unsafe { b.b } } +pub fn test_UnionBool(b: UnionBool) -> bool { + unsafe { b.b } +} // CHECK: %_0 = trunc i8 %b to i1 diff --git a/tests/codegen/unwind-abis/aapcs-unwind-abi.rs b/tests/codegen/unwind-abis/aapcs-unwind-abi.rs index 484af78105f1..48c7ecf78242 100644 --- a/tests/codegen/unwind-abis/aapcs-unwind-abi.rs +++ b/tests/codegen/unwind-abis/aapcs-unwind-abi.rs @@ -2,8 +2,8 @@ //@ compile-flags: --target=armv7-unknown-linux-gnueabihf --crate-type=rlib -Cno-prepopulate-passes #![no_core] #![feature(no_core, lang_items, c_unwind)] -#[lang="sized"] -trait Sized { } +#[lang = "sized"] +trait Sized {} // Test that `nounwind` attributes are correctly applied to exported `aapcs` and // `aapcs-unwind` extern functions. `aapcs-unwind` functions MUST NOT have this attribute. We @@ -11,13 +11,11 @@ trait Sized { } // CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 { #[no_mangle] -pub extern "aapcs" fn rust_item_that_cannot_unwind() { -} +pub extern "aapcs" fn rust_item_that_cannot_unwind() {} // CHECK: @rust_item_that_can_unwind() unnamed_addr #1 { #[no_mangle] -pub extern "aapcs-unwind" fn rust_item_that_can_unwind() { -} +pub extern "aapcs-unwind" fn rust_item_that_can_unwind() {} // Now, make some assertions that the LLVM attributes for these functions are correct. First, make // sure that the first item is correctly marked with the `nounwind` attribute: diff --git a/tests/codegen/unwind-abis/c-unwind-abi.rs b/tests/codegen/unwind-abis/c-unwind-abi.rs index 140c18e6bb33..99763943a6ac 100644 --- a/tests/codegen/unwind-abis/c-unwind-abi.rs +++ b/tests/codegen/unwind-abis/c-unwind-abi.rs @@ -10,13 +10,11 @@ // CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 { #[no_mangle] -pub extern "C" fn rust_item_that_cannot_unwind() { -} +pub extern "C" fn rust_item_that_cannot_unwind() {} // CHECK: @rust_item_that_can_unwind() unnamed_addr #1 { #[no_mangle] -pub extern "C-unwind" fn rust_item_that_can_unwind() { -} +pub extern "C-unwind" fn rust_item_that_can_unwind() {} // Now, make some assertions that the LLVM attributes for these functions are correct. First, make // sure that the first item is correctly marked with the `nounwind` attribute: diff --git a/tests/codegen/unwind-abis/cdecl-unwind-abi.rs b/tests/codegen/unwind-abis/cdecl-unwind-abi.rs index 5604b8d5765a..78dbb55b35a2 100644 --- a/tests/codegen/unwind-abis/cdecl-unwind-abi.rs +++ b/tests/codegen/unwind-abis/cdecl-unwind-abi.rs @@ -10,13 +10,11 @@ // CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 { #[no_mangle] -pub extern "cdecl" fn rust_item_that_cannot_unwind() { -} +pub extern "cdecl" fn rust_item_that_cannot_unwind() {} // CHECK: @rust_item_that_can_unwind() unnamed_addr #1 { #[no_mangle] -pub extern "cdecl-unwind" fn rust_item_that_can_unwind() { -} +pub extern "cdecl-unwind" fn rust_item_that_can_unwind() {} // Now, make some assertions that the LLVM attributes for these functions are correct. First, make // sure that the first item is correctly marked with the `nounwind` attribute: diff --git a/tests/codegen/unwind-abis/fastcall-unwind-abi.rs b/tests/codegen/unwind-abis/fastcall-unwind-abi.rs index 18e2cd22c8aa..3cbeaf51d960 100644 --- a/tests/codegen/unwind-abis/fastcall-unwind-abi.rs +++ b/tests/codegen/unwind-abis/fastcall-unwind-abi.rs @@ -2,8 +2,8 @@ //@ compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib -Cno-prepopulate-passes #![no_core] #![feature(no_core, lang_items, c_unwind)] -#[lang="sized"] -trait Sized { } +#[lang = "sized"] +trait Sized {} // Test that `nounwind` attributes are correctly applied to exported `fastcall` and // `fastcall-unwind` extern functions. `fastcall-unwind` functions MUST NOT have this attribute. We @@ -11,13 +11,11 @@ trait Sized { } // CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 { #[no_mangle] -pub extern "fastcall" fn rust_item_that_cannot_unwind() { -} +pub extern "fastcall" fn rust_item_that_cannot_unwind() {} // CHECK: @rust_item_that_can_unwind() unnamed_addr #1 { #[no_mangle] -pub extern "fastcall-unwind" fn rust_item_that_can_unwind() { -} +pub extern "fastcall-unwind" fn rust_item_that_can_unwind() {} // Now, make some assertions that the LLVM attributes for these functions are correct. First, make // sure that the first item is correctly marked with the `nounwind` attribute: diff --git a/tests/codegen/unwind-abis/stdcall-unwind-abi.rs b/tests/codegen/unwind-abis/stdcall-unwind-abi.rs index a5e600fe076f..ffb235cd1168 100644 --- a/tests/codegen/unwind-abis/stdcall-unwind-abi.rs +++ b/tests/codegen/unwind-abis/stdcall-unwind-abi.rs @@ -2,8 +2,8 @@ //@ compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib -Cno-prepopulate-passes #![no_core] #![feature(no_core, lang_items, c_unwind)] -#[lang="sized"] -trait Sized { } +#[lang = "sized"] +trait Sized {} // Test that `nounwind` attributes are correctly applied to exported `stdcall` and `stdcall-unwind` // extern functions. `stdcall-unwind` functions MUST NOT have this attribute. We disable @@ -11,13 +11,11 @@ trait Sized { } // CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 { #[no_mangle] -pub extern "stdcall" fn rust_item_that_cannot_unwind() { -} +pub extern "stdcall" fn rust_item_that_cannot_unwind() {} // CHECK: @rust_item_that_can_unwind() unnamed_addr #1 { #[no_mangle] -pub extern "stdcall-unwind" fn rust_item_that_can_unwind() { -} +pub extern "stdcall-unwind" fn rust_item_that_can_unwind() {} // Now, make some assertions that the LLVM attributes for these functions are correct. First, make // sure that the first item is correctly marked with the `nounwind` attribute: diff --git a/tests/codegen/unwind-abis/system-unwind-abi.rs b/tests/codegen/unwind-abis/system-unwind-abi.rs index b001c1f951c4..1dd0e9bbbec7 100644 --- a/tests/codegen/unwind-abis/system-unwind-abi.rs +++ b/tests/codegen/unwind-abis/system-unwind-abi.rs @@ -10,13 +10,11 @@ // CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 { #[no_mangle] -pub extern "system" fn rust_item_that_cannot_unwind() { -} +pub extern "system" fn rust_item_that_cannot_unwind() {} // CHECK: @rust_item_that_can_unwind() unnamed_addr #1 { #[no_mangle] -pub extern "system-unwind" fn rust_item_that_can_unwind() { -} +pub extern "system-unwind" fn rust_item_that_can_unwind() {} // Now, make some assertions that the LLVM attributes for these functions are correct. First, make // sure that the first item is correctly marked with the `nounwind` attribute: diff --git a/tests/codegen/unwind-abis/sysv64-unwind-abi.rs b/tests/codegen/unwind-abis/sysv64-unwind-abi.rs index 49407f748bc3..9824009dc559 100644 --- a/tests/codegen/unwind-abis/sysv64-unwind-abi.rs +++ b/tests/codegen/unwind-abis/sysv64-unwind-abi.rs @@ -2,8 +2,8 @@ //@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=rlib -Cno-prepopulate-passes #![no_core] #![feature(no_core, lang_items, c_unwind)] -#[lang="sized"] -trait Sized { } +#[lang = "sized"] +trait Sized {} // Test that `nounwind` attributes are correctly applied to exported `sysv64` and // `sysv64-unwind` extern functions. `sysv64-unwind` functions MUST NOT have this attribute. We @@ -11,13 +11,11 @@ trait Sized { } // CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 { #[no_mangle] -pub extern "sysv64" fn rust_item_that_cannot_unwind() { -} +pub extern "sysv64" fn rust_item_that_cannot_unwind() {} // CHECK: @rust_item_that_can_unwind() unnamed_addr #1 { #[no_mangle] -pub extern "sysv64-unwind" fn rust_item_that_can_unwind() { -} +pub extern "sysv64-unwind" fn rust_item_that_can_unwind() {} // Now, make some assertions that the LLVM attributes for these functions are correct. First, make // sure that the first item is correctly marked with the `nounwind` attribute: diff --git a/tests/codegen/unwind-abis/thiscall-unwind-abi.rs b/tests/codegen/unwind-abis/thiscall-unwind-abi.rs index d07e9b81d783..a96f4d5a350c 100644 --- a/tests/codegen/unwind-abis/thiscall-unwind-abi.rs +++ b/tests/codegen/unwind-abis/thiscall-unwind-abi.rs @@ -2,8 +2,8 @@ //@ compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib -Cno-prepopulate-passes #![no_core] #![feature(no_core, lang_items, c_unwind)] -#[lang="sized"] -trait Sized { } +#[lang = "sized"] +trait Sized {} // Test that `nounwind` attributes are correctly applied to exported `thiscall` and // `thiscall-unwind` extern functions. `thiscall-unwind` functions MUST NOT have this attribute. We @@ -11,13 +11,11 @@ trait Sized { } // CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 { #[no_mangle] -pub extern "thiscall" fn rust_item_that_cannot_unwind() { -} +pub extern "thiscall" fn rust_item_that_cannot_unwind() {} // CHECK: @rust_item_that_can_unwind() unnamed_addr #1 { #[no_mangle] -pub extern "thiscall-unwind" fn rust_item_that_can_unwind() { -} +pub extern "thiscall-unwind" fn rust_item_that_can_unwind() {} // Now, make some assertions that the LLVM attributes for these functions are correct. First, make // sure that the first item is correctly marked with the `nounwind` attribute: diff --git a/tests/codegen/unwind-abis/vectorcall-unwind-abi.rs b/tests/codegen/unwind-abis/vectorcall-unwind-abi.rs index a89794fbf6e3..9929e3e3703d 100644 --- a/tests/codegen/unwind-abis/vectorcall-unwind-abi.rs +++ b/tests/codegen/unwind-abis/vectorcall-unwind-abi.rs @@ -2,8 +2,8 @@ //@ compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib -Cno-prepopulate-passes #![no_core] #![feature(no_core, lang_items, c_unwind, abi_vectorcall)] -#[lang="sized"] -trait Sized { } +#[lang = "sized"] +trait Sized {} // Test that `nounwind` attributes are correctly applied to exported `vectorcall` and // `vectorcall-unwind` extern functions. `vectorcall-unwind` functions MUST NOT have this attribute. @@ -11,13 +11,11 @@ trait Sized { } // CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 { #[no_mangle] -pub extern "vectorcall" fn rust_item_that_cannot_unwind() { -} +pub extern "vectorcall" fn rust_item_that_cannot_unwind() {} // CHECK: @rust_item_that_can_unwind() unnamed_addr #1 { #[no_mangle] -pub extern "vectorcall-unwind" fn rust_item_that_can_unwind() { -} +pub extern "vectorcall-unwind" fn rust_item_that_can_unwind() {} // Now, make some assertions that the LLVM attributes for these functions are correct. First, make // sure that the first item is correctly marked with the `nounwind` attribute: diff --git a/tests/codegen/unwind-abis/win64-unwind-abi.rs b/tests/codegen/unwind-abis/win64-unwind-abi.rs index aa466469c4de..a45a94f628d1 100644 --- a/tests/codegen/unwind-abis/win64-unwind-abi.rs +++ b/tests/codegen/unwind-abis/win64-unwind-abi.rs @@ -2,8 +2,8 @@ //@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=rlib -Cno-prepopulate-passes #![no_core] #![feature(no_core, lang_items, c_unwind)] -#[lang="sized"] -trait Sized { } +#[lang = "sized"] +trait Sized {} // Test that `nounwind` attributes are correctly applied to exported `win64` and // `win64-unwind` extern functions. `win64-unwind` functions MUST NOT have this attribute. We @@ -11,13 +11,11 @@ trait Sized { } // CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 { #[no_mangle] -pub extern "win64" fn rust_item_that_cannot_unwind() { -} +pub extern "win64" fn rust_item_that_cannot_unwind() {} // CHECK: @rust_item_that_can_unwind() unnamed_addr #1 { #[no_mangle] -pub extern "win64-unwind" fn rust_item_that_can_unwind() { -} +pub extern "win64-unwind" fn rust_item_that_can_unwind() {} // Now, make some assertions that the LLVM attributes for these functions are correct. First, make // sure that the first item is correctly marked with the `nounwind` attribute: diff --git a/tests/codegen/vec-iter-collect-len.rs b/tests/codegen/vec-iter-collect-len.rs index e4242c574023..8c5d2f6f9a74 100644 --- a/tests/codegen/vec-iter-collect-len.rs +++ b/tests/codegen/vec-iter-collect-len.rs @@ -1,5 +1,5 @@ //@ compile-flags: -O -#![crate_type="lib"] +#![crate_type = "lib"] #[no_mangle] pub fn get_len() -> usize { diff --git a/tests/codegen/vtable-upcast.rs b/tests/codegen/vtable-upcast.rs index 41a4be26cb44..ae7b4bf7aee9 100644 --- a/tests/codegen/vtable-upcast.rs +++ b/tests/codegen/vtable-upcast.rs @@ -8,15 +8,15 @@ pub trait Base { fn base(&self); } -pub trait A : Base { +pub trait A: Base { fn a(&self); } -pub trait B : Base { +pub trait B: Base { fn b(&self); } -pub trait Diamond : A + B { +pub trait Diamond: A + B { fn diamond(&self); } diff --git a/tests/codegen/wasm_exceptions.rs b/tests/codegen/wasm_exceptions.rs index a53722f834c5..3910850e03a0 100644 --- a/tests/codegen/wasm_exceptions.rs +++ b/tests/codegen/wasm_exceptions.rs @@ -5,7 +5,7 @@ #![feature(core_intrinsics)] #![feature(rustc_attrs)] -extern { +extern "C" { fn may_panic(); #[rustc_nounwind] @@ -16,7 +16,9 @@ struct LogOnDrop; impl Drop for LogOnDrop { fn drop(&mut self) { - unsafe { log_number(0); } + unsafe { + log_number(0); + } } } @@ -24,7 +26,9 @@ impl Drop for LogOnDrop { #[no_mangle] pub fn test_cleanup() { let _log_on_drop = LogOnDrop; - unsafe { may_panic(); } + unsafe { + may_panic(); + } // CHECK-NOT: call // CHECK: invoke void @may_panic() @@ -35,12 +39,16 @@ pub fn test_cleanup() { #[no_mangle] pub fn test_rtry() { unsafe { - core::intrinsics::catch_unwind(|_| { - may_panic(); - }, core::ptr::null_mut(), |data, exception| { - log_number(data as usize); - log_number(exception as usize); - }); + core::intrinsics::catch_unwind( + |_| { + may_panic(); + }, + core::ptr::null_mut(), + |data, exception| { + log_number(data as usize); + log_number(exception as usize); + }, + ); } // CHECK-NOT: call diff --git a/tests/codegen/zip.rs b/tests/codegen/zip.rs index 5db0a93b78ef..ea8caba61f39 100644 --- a/tests/codegen/zip.rs +++ b/tests/codegen/zip.rs @@ -5,7 +5,7 @@ // CHECK-LABEL: @zip_copy #[no_mangle] pub fn zip_copy(xs: &[u8], ys: &mut [u8]) { -// CHECK: memcpy + // CHECK: memcpy for (x, y) in xs.iter().zip(ys) { *y = *x; } @@ -14,7 +14,7 @@ pub fn zip_copy(xs: &[u8], ys: &mut [u8]) { // CHECK-LABEL: @zip_copy_mapped #[no_mangle] pub fn zip_copy_mapped(xs: &[u8], ys: &mut [u8]) { -// CHECK: memcpy + // CHECK: memcpy for (x, y) in xs.iter().map(|&x| x).zip(ys) { *y = x; } diff --git a/tests/codegen/zst-offset.rs b/tests/codegen/zst-offset.rs index b623d492d9d6..14e97fd26ddf 100644 --- a/tests/codegen/zst-offset.rs +++ b/tests/codegen/zst-offset.rs @@ -6,14 +6,13 @@ // Hack to get the correct size for the length part in slices // CHECK: @helper([[USIZE:i[0-9]+]] %_1) #[no_mangle] -pub fn helper(_: usize) { -} +pub fn helper(_: usize) {} // Check that we correctly generate a GEP for a ZST that is not included in Scalar layout // CHECK-LABEL: @scalar_layout #[no_mangle] pub fn scalar_layout(s: &(u64, ())) { -// CHECK: getelementptr inbounds i8, {{.+}}, [[USIZE]] 8 + // CHECK: getelementptr inbounds i8, {{.+}}, [[USIZE]] 8 let x = &s.1; witness(&x); // keep variable in an alloca } @@ -22,7 +21,7 @@ pub fn scalar_layout(s: &(u64, ())) { // CHECK-LABEL: @scalarpair_layout #[no_mangle] pub fn scalarpair_layout(s: &(u64, u32, ())) { -// CHECK: getelementptr inbounds i8, {{.+}}, [[USIZE]] 12 + // CHECK: getelementptr inbounds i8, {{.+}}, [[USIZE]] 12 let x = &s.2; witness(&x); // keep variable in an alloca } @@ -34,7 +33,7 @@ pub struct U64x4(u64, u64, u64, u64); // CHECK-LABEL: @vector_layout #[no_mangle] pub fn vector_layout(s: &(U64x4, ())) { -// CHECK: getelementptr inbounds i8, {{.+}}, [[USIZE]] 32 + // CHECK: getelementptr inbounds i8, {{.+}}, [[USIZE]] 32 let x = &s.1; witness(&x); // keep variable in an alloca } From 780a91786ec73a0ec1d2847e860f2d71dd7704fe Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 29 May 2024 14:25:55 +1000 Subject: [PATCH 116/211] Run rustfmt on `tests/codegen-units/`. --- rustfmt.toml | 1 - .../auxiliary/cgu_export_trait_method.rs | 38 +++-- .../auxiliary/cgu_extern_closures.rs | 9 +- .../item-collection/cross-crate-closures.rs | 1 - .../cross-crate-trait-method.rs | 2 - .../drop_in_place_intrinsic.rs | 1 - .../item-collection/function-as-argument.rs | 1 - .../item-collection/generic-drop-glue.rs | 13 +- .../item-collection/generic-impl.rs | 13 +- .../instantiation-through-vtable.rs | 6 +- .../item-collection/non-generic-drop-glue.rs | 12 +- .../item-collection/non-generic-functions.rs | 4 +- .../item-collection/overloaded-operators.rs | 20 +-- .../item-collection/static-init.rs | 4 +- .../item-collection/trait-implementations.rs | 34 ++-- .../trait-method-as-argument.rs | 13 +- .../trait-method-default-impl.rs | 8 +- .../codegen-units/item-collection/unsizing.rs | 8 +- .../unused-traits-and-generics.rs | 8 +- .../auxiliary/shared_generics_aux.rs | 2 +- .../partitioning/extern-generic.rs | 2 +- .../inlining-from-extern-crate.rs | 11 +- .../partitioning/local-generic.rs | 6 +- .../local-inlining-but-not-all.rs | 11 +- .../partitioning/local-inlining.rs | 11 +- .../partitioning/local-transitive-inlining.rs | 11 +- .../methods-are-with-self-type.rs | 5 +- .../partitioning/regular-modules.rs | 2 +- .../partitioning/shared-generics.rs | 3 +- tests/codegen-units/partitioning/statics.rs | 2 +- .../partitioning/vtable-through-const.rs | 22 ++- .../unused_type_parameters.rs | 153 +++++++++--------- 32 files changed, 208 insertions(+), 229 deletions(-) diff --git a/rustfmt.toml b/rustfmt.toml index 24d300e91fa6..5f40abcbaa5b 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -15,7 +15,6 @@ ignore = [ # - some UI tests are broken by different formatting # - some require special comments in a particular position (e.g. `EMIT_MIR` comments) "/tests/codegen/simd-intrinsic/", # Many types like `u8x64` are better hand-formatted. - "/tests/codegen-units/", "/tests/coverage/", "/tests/coverage-run-rustdoc/", "/tests/crashes/", diff --git a/tests/codegen-units/item-collection/auxiliary/cgu_export_trait_method.rs b/tests/codegen-units/item-collection/auxiliary/cgu_export_trait_method.rs index 5566bb4e4b28..1992baf8c765 100644 --- a/tests/codegen-units/item-collection/auxiliary/cgu_export_trait_method.rs +++ b/tests/codegen-units/item-collection/auxiliary/cgu_export_trait_method.rs @@ -2,25 +2,43 @@ #![crate_type = "lib"] -pub trait Trait : Sized { +pub trait Trait: Sized { fn without_self() -> u32; - fn without_self_default() -> u32 { 0 } + fn without_self_default() -> u32 { + 0 + } - fn with_default_impl(self) -> Self { self } - fn with_default_impl_generic(self, x: T) -> (Self, T) { (self, x) } + fn with_default_impl(self) -> Self { + self + } + fn with_default_impl_generic(self, x: T) -> (Self, T) { + (self, x) + } fn without_default_impl(x: u32) -> (Self, u32); fn without_default_impl_generic(x: T) -> (Self, T); } impl Trait for char { - fn without_self() -> u32 { 2 } - fn without_default_impl(x: u32) -> (Self, u32) { ('c', x) } - fn without_default_impl_generic(x: T) -> (Self, T) { ('c', x) } + fn without_self() -> u32 { + 2 + } + fn without_default_impl(x: u32) -> (Self, u32) { + ('c', x) + } + fn without_default_impl_generic(x: T) -> (Self, T) { + ('c', x) + } } impl Trait for u32 { - fn without_self() -> u32 { 1 } - fn without_default_impl(x: u32) -> (Self, u32) { (0, x) } - fn without_default_impl_generic(x: T) -> (Self, T) { (0, x) } + fn without_self() -> u32 { + 1 + } + fn without_default_impl(x: u32) -> (Self, u32) { + (0, x) + } + fn without_default_impl_generic(x: T) -> (Self, T) { + (0, x) + } } diff --git a/tests/codegen-units/item-collection/auxiliary/cgu_extern_closures.rs b/tests/codegen-units/item-collection/auxiliary/cgu_extern_closures.rs index 05ea0a89ff29..0192a3d4188c 100644 --- a/tests/codegen-units/item-collection/auxiliary/cgu_extern_closures.rs +++ b/tests/codegen-units/item-collection/auxiliary/cgu_extern_closures.rs @@ -2,22 +2,19 @@ #[inline] pub fn inlined_fn(x: i32, y: i32) -> i32 { - - let closure = |a, b| { a + b }; + let closure = |a, b| a + b; closure(x, y) } pub fn inlined_fn_generic(x: i32, y: i32, z: T) -> (i32, T) { - - let closure = |a, b| { a + b }; + let closure = |a, b| a + b; (closure(x, y), z) } pub fn non_inlined_fn(x: i32, y: i32) -> i32 { - - let closure = |a, b| { a + b }; + let closure = |a, b| a + b; closure(x, y) } diff --git a/tests/codegen-units/item-collection/cross-crate-closures.rs b/tests/codegen-units/item-collection/cross-crate-closures.rs index 4ec7f17d5847..2dab19401ed7 100644 --- a/tests/codegen-units/item-collection/cross-crate-closures.rs +++ b/tests/codegen-units/item-collection/cross-crate-closures.rs @@ -14,7 +14,6 @@ extern crate cgu_extern_closures; //~ MONO_ITEM fn cross_crate_closures::start[0] #[start] fn start(_: isize, _: *const *const u8) -> isize { - //~ MONO_ITEM fn cgu_extern_closures::inlined_fn[0] //~ MONO_ITEM fn cgu_extern_closures::inlined_fn[0]::{{closure}}[0] let _ = cgu_extern_closures::inlined_fn(1, 2); diff --git a/tests/codegen-units/item-collection/cross-crate-trait-method.rs b/tests/codegen-units/item-collection/cross-crate-trait-method.rs index 84977328e490..997777603155 100644 --- a/tests/codegen-units/item-collection/cross-crate-trait-method.rs +++ b/tests/codegen-units/item-collection/cross-crate-trait-method.rs @@ -24,8 +24,6 @@ fn start(_: isize, _: *const *const u8) -> isize { //~ MONO_ITEM fn ::with_default_impl let _ = Trait::with_default_impl('c'); - - //~ MONO_ITEM fn ::with_default_impl_generic::<&str> let _ = Trait::with_default_impl_generic(0u32, "abc"); //~ MONO_ITEM fn ::with_default_impl_generic:: diff --git a/tests/codegen-units/item-collection/drop_in_place_intrinsic.rs b/tests/codegen-units/item-collection/drop_in_place_intrinsic.rs index 66dcda260660..947faa165a9c 100644 --- a/tests/codegen-units/item-collection/drop_in_place_intrinsic.rs +++ b/tests/codegen-units/item-collection/drop_in_place_intrinsic.rs @@ -15,7 +15,6 @@ impl Drop for StructWithDtor { //~ MONO_ITEM fn start #[start] fn start(_: isize, _: *const *const u8) -> isize { - //~ MONO_ITEM fn std::ptr::drop_in_place::<[StructWithDtor; 2]> - shim(Some([StructWithDtor; 2])) @@ drop_in_place_intrinsic-cgu.0[Internal] let x = [StructWithDtor(0), StructWithDtor(1)]; diff --git a/tests/codegen-units/item-collection/function-as-argument.rs b/tests/codegen-units/item-collection/function-as-argument.rs index 4e6fd99d29ed..4be713dc3673 100644 --- a/tests/codegen-units/item-collection/function-as-argument.rs +++ b/tests/codegen-units/item-collection/function-as-argument.rs @@ -16,7 +16,6 @@ fn take_fn_pointer(f: fn(T1, T2), x: T1, y: T2) { //~ MONO_ITEM fn start #[start] fn start(_: isize, _: *const *const u8) -> isize { - //~ MONO_ITEM fn take_fn_once::}> //~ MONO_ITEM fn function:: //~ MONO_ITEM fn } as std::ops::FnOnce<(u32, &str)>>::call_once - shim(fn(u32, &str) {function::}) diff --git a/tests/codegen-units/item-collection/generic-drop-glue.rs b/tests/codegen-units/item-collection/generic-drop-glue.rs index 99250dc7dc67..d861d269fae4 100644 --- a/tests/codegen-units/item-collection/generic-drop-glue.rs +++ b/tests/codegen-units/item-collection/generic-drop-glue.rs @@ -21,7 +21,7 @@ struct StructNoDrop { enum EnumWithDrop { A(T1), - B(T2) + B(T2), } impl Drop for EnumWithDrop { @@ -30,10 +30,9 @@ impl Drop for EnumWithDrop { enum EnumNoDrop { A(T1), - B(T2) + B(T2), } - struct NonGenericNoDrop(#[allow(dead_code)] i32); struct NonGenericWithDrop(#[allow(dead_code)] i32); @@ -67,24 +66,24 @@ fn start(_: isize, _: *const *const u8) -> isize { //~ MONO_ITEM fn as std::ops::Drop>::drop let _ = match EnumWithDrop::A::(0) { EnumWithDrop::A(x) => x, - EnumWithDrop::B(x) => x as i32 + EnumWithDrop::B(x) => x as i32, }; //~ MONO_ITEM fn std::ptr::drop_in_place::> - shim(Some(EnumWithDrop)) @@ generic_drop_glue-cgu.0[Internal] //~ MONO_ITEM fn as std::ops::Drop>::drop let _ = match EnumWithDrop::B::(1.0) { EnumWithDrop::A(x) => x, - EnumWithDrop::B(x) => x as f64 + EnumWithDrop::B(x) => x as f64, }; let _ = match EnumNoDrop::A::(0) { EnumNoDrop::A(x) => x, - EnumNoDrop::B(x) => x as i32 + EnumNoDrop::B(x) => x as i32, }; let _ = match EnumNoDrop::B::(1.0) { EnumNoDrop::A(x) => x, - EnumNoDrop::B(x) => x as f64 + EnumNoDrop::B(x) => x as f64, }; 0 diff --git a/tests/codegen-units/item-collection/generic-impl.rs b/tests/codegen-units/item-collection/generic-impl.rs index 6e60907c1857..23d09e0d8af3 100644 --- a/tests/codegen-units/item-collection/generic-impl.rs +++ b/tests/codegen-units/item-collection/generic-impl.rs @@ -8,15 +8,13 @@ struct Struct { f: fn(x: T) -> T, } -fn id(x: T) -> T { x } +fn id(x: T) -> T { + x +} impl Struct { - fn new(x: T) -> Struct { - Struct { - x: x, - f: id - } + Struct { x: x, f: id } } fn get(self, x: T2) -> (T, T2) { @@ -25,11 +23,10 @@ impl Struct { } pub struct LifeTimeOnly<'a> { - _a: &'a u32 + _a: &'a u32, } impl<'a> LifeTimeOnly<'a> { - //~ MONO_ITEM fn LifeTimeOnly::<'_>::foo pub fn foo(&self) {} //~ MONO_ITEM fn LifeTimeOnly::<'_>::bar diff --git a/tests/codegen-units/item-collection/instantiation-through-vtable.rs b/tests/codegen-units/item-collection/instantiation-through-vtable.rs index 08e8c03a7328..59dd4311a03b 100644 --- a/tests/codegen-units/item-collection/instantiation-through-vtable.rs +++ b/tests/codegen-units/item-collection/instantiation-through-vtable.rs @@ -10,11 +10,13 @@ trait Trait { } struct Struct { - _a: T + _a: T, } impl Trait for Struct { - fn foo(&self) -> u32 { 0 } + fn foo(&self) -> u32 { + 0 + } fn bar(&self) {} } diff --git a/tests/codegen-units/item-collection/non-generic-drop-glue.rs b/tests/codegen-units/item-collection/non-generic-drop-glue.rs index d74b17463bf1..f7bb2f3f2f4d 100644 --- a/tests/codegen-units/item-collection/non-generic-drop-glue.rs +++ b/tests/codegen-units/item-collection/non-generic-drop-glue.rs @@ -7,7 +7,7 @@ //~ MONO_ITEM fn std::ptr::drop_in_place:: - shim(Some(StructWithDrop)) @@ non_generic_drop_glue-cgu.0[Internal] struct StructWithDrop { - x: i32 + x: i32, } impl Drop for StructWithDrop { @@ -16,12 +16,12 @@ impl Drop for StructWithDrop { } struct StructNoDrop { - x: i32 + x: i32, } //~ MONO_ITEM fn std::ptr::drop_in_place:: - shim(Some(EnumWithDrop)) @@ non_generic_drop_glue-cgu.0[Internal] enum EnumWithDrop { - A(i32) + A(i32), } impl Drop for EnumWithDrop { @@ -30,7 +30,7 @@ impl Drop for EnumWithDrop { } enum EnumNoDrop { - A(i32) + A(i32), } //~ MONO_ITEM fn start @@ -39,10 +39,10 @@ fn start(_: isize, _: *const *const u8) -> isize { let _ = StructWithDrop { x: 0 }.x; let _ = StructNoDrop { x: 0 }.x; let _ = match EnumWithDrop::A(0) { - EnumWithDrop::A(x) => x + EnumWithDrop::A(x) => x, }; let _ = match EnumNoDrop::A(0) { - EnumNoDrop::A(x) => x + EnumNoDrop::A(x) => x, }; 0 diff --git a/tests/codegen-units/item-collection/non-generic-functions.rs b/tests/codegen-units/item-collection/non-generic-functions.rs index 49a999a0d7c8..d4d7d221827d 100644 --- a/tests/codegen-units/item-collection/non-generic-functions.rs +++ b/tests/codegen-units/item-collection/non-generic-functions.rs @@ -25,7 +25,9 @@ fn bar() { baz(); } -struct Struct { _x: i32 } +struct Struct { + _x: i32, +} impl Struct { //~ MONO_ITEM fn Struct::foo diff --git a/tests/codegen-units/item-collection/overloaded-operators.rs b/tests/codegen-units/item-collection/overloaded-operators.rs index 23141c27de6e..69b55695d3d3 100644 --- a/tests/codegen-units/item-collection/overloaded-operators.rs +++ b/tests/codegen-units/item-collection/overloaded-operators.rs @@ -1,12 +1,12 @@ //@ compile-flags:-Zprint-mono-items=eager #![deny(dead_code)] -#![crate_type="lib"] +#![crate_type = "lib"] -use std::ops::{Index, IndexMut, Add, Deref}; +use std::ops::{Add, Deref, Index, IndexMut}; pub struct Indexable { - data: [u8; 3] + data: [u8; 3], } impl Index for Indexable { @@ -14,32 +14,22 @@ impl Index for Indexable { //~ MONO_ITEM fn >::index fn index(&self, index: usize) -> &Self::Output { - if index >= 3 { - &self.data[0] - } else { - &self.data[index] - } + if index >= 3 { &self.data[0] } else { &self.data[index] } } } impl IndexMut for Indexable { //~ MONO_ITEM fn >::index_mut fn index_mut(&mut self, index: usize) -> &mut Self::Output { - if index >= 3 { - &mut self.data[0] - } else { - &mut self.data[index] - } + if index >= 3 { &mut self.data[0] } else { &mut self.data[index] } } } - //~ MONO_ITEM fn ::eq //~ MONO_ITEM fn ::ne #[derive(PartialEq)] pub struct Equatable(u32); - impl Add for Equatable { type Output = u32; diff --git a/tests/codegen-units/item-collection/static-init.rs b/tests/codegen-units/item-collection/static-init.rs index b357f5cd66b2..1406fba2b984 100644 --- a/tests/codegen-units/item-collection/static-init.rs +++ b/tests/codegen-units/item-collection/static-init.rs @@ -2,9 +2,9 @@ #![feature(start)] -pub static FN : fn() = foo::; +pub static FN: fn() = foo::; -pub fn foo() { } +pub fn foo() {} //~ MONO_ITEM fn foo:: //~ MONO_ITEM static FN diff --git a/tests/codegen-units/item-collection/trait-implementations.rs b/tests/codegen-units/item-collection/trait-implementations.rs index b364cc5b3336..e4c444499e05 100644 --- a/tests/codegen-units/item-collection/trait-implementations.rs +++ b/tests/codegen-units/item-collection/trait-implementations.rs @@ -9,7 +9,6 @@ pub trait SomeTrait { } impl SomeTrait for i64 { - //~ MONO_ITEM fn ::foo fn foo(&self) {} @@ -17,7 +16,6 @@ impl SomeTrait for i64 { } impl SomeTrait for i32 { - //~ MONO_ITEM fn ::foo fn foo(&self) {} @@ -31,7 +29,6 @@ pub trait SomeGenericTrait { // Concrete impl of generic trait impl SomeGenericTrait for f64 { - //~ MONO_ITEM fn >::foo fn foo(&self, _: u32) {} @@ -40,7 +37,6 @@ impl SomeGenericTrait for f64 { // Generic impl of generic trait impl SomeGenericTrait for f32 { - fn foo(&self, _: T) {} fn bar(&self, _: T, _: T2) {} } @@ -48,26 +44,26 @@ impl SomeGenericTrait for f32 { //~ MONO_ITEM fn start #[start] fn start(_: isize, _: *const *const u8) -> isize { - //~ MONO_ITEM fn ::bar:: - 0i32.bar('x'); + //~ MONO_ITEM fn ::bar:: + 0i32.bar('x'); - //~ MONO_ITEM fn >::bar::<&str> - 0f64.bar(0u32, "&str"); + //~ MONO_ITEM fn >::bar::<&str> + 0f64.bar(0u32, "&str"); - //~ MONO_ITEM fn >::bar::<()> - 0f64.bar(0u32, ()); + //~ MONO_ITEM fn >::bar::<()> + 0f64.bar(0u32, ()); - //~ MONO_ITEM fn >::foo - 0f32.foo('x'); + //~ MONO_ITEM fn >::foo + 0f32.foo('x'); - //~ MONO_ITEM fn >::foo - 0f32.foo(-1i64); + //~ MONO_ITEM fn >::foo + 0f32.foo(-1i64); - //~ MONO_ITEM fn >::bar::<()> - 0f32.bar(0u32, ()); + //~ MONO_ITEM fn >::bar::<()> + 0f32.bar(0u32, ()); - //~ MONO_ITEM fn >::bar::<&str> - 0f32.bar("&str", "&str"); + //~ MONO_ITEM fn >::bar::<&str> + 0f32.bar("&str", "&str"); - 0 + 0 } diff --git a/tests/codegen-units/item-collection/trait-method-as-argument.rs b/tests/codegen-units/item-collection/trait-method-as-argument.rs index c25e3ea45ecc..10cf2a0e967e 100644 --- a/tests/codegen-units/item-collection/trait-method-as-argument.rs +++ b/tests/codegen-units/item-collection/trait-method-as-argument.rs @@ -3,16 +3,19 @@ #![deny(dead_code)] #![feature(start)] -trait Trait : Sized { - fn foo(self) -> Self { self } +trait Trait: Sized { + fn foo(self) -> Self { + self + } } impl Trait for u32 { - fn foo(self) -> u32 { self } + fn foo(self) -> u32 { + self + } } -impl Trait for char { -} +impl Trait for char {} fn take_foo_once T>(f: F, arg: T) -> T { (f)(arg) diff --git a/tests/codegen-units/item-collection/trait-method-default-impl.rs b/tests/codegen-units/item-collection/trait-method-default-impl.rs index 89fec350f09c..b0a43d28e40b 100644 --- a/tests/codegen-units/item-collection/trait-method-default-impl.rs +++ b/tests/codegen-units/item-collection/trait-method-default-impl.rs @@ -4,8 +4,10 @@ #![feature(start)] trait SomeTrait { - fn foo(&self) { } - fn bar(&self, x: T) -> T { x } + fn foo(&self) {} + fn bar(&self, x: T) -> T { + x + } } impl SomeTrait for i8 { @@ -17,7 +19,7 @@ impl SomeTrait for i8 { } trait SomeGenericTrait { - fn foo(&self) { } + fn foo(&self) {} fn bar(&self, x: T1, y: T2) {} } diff --git a/tests/codegen-units/item-collection/unsizing.rs b/tests/codegen-units/item-collection/unsizing.rs index 1e2d7f174845..5ea8b47962a8 100644 --- a/tests/codegen-units/item-collection/unsizing.rs +++ b/tests/codegen-units/item-collection/unsizing.rs @@ -27,7 +27,7 @@ impl Trait for char { struct Struct { _a: u32, _b: i32, - _c: T + _c: T, } impl Trait for f64 { @@ -60,11 +60,7 @@ fn start(_: isize, _: *const *const u8) -> isize { let _char_unsized = char_sized as &Trait; // struct field - let struct_sized = &Struct { - _a: 1, - _b: 2, - _c: 3.0f64 - }; + let struct_sized = &Struct { _a: 1, _b: 2, _c: 3.0f64 }; //~ MONO_ITEM fn std::ptr::drop_in_place:: - shim(None) @@ unsizing-cgu.0[Internal] //~ MONO_ITEM fn ::foo let _struct_unsized = struct_sized as &Struct; diff --git a/tests/codegen-units/item-collection/unused-traits-and-generics.rs b/tests/codegen-units/item-collection/unused-traits-and-generics.rs index 27cdae2c0962..d5088d3f8937 100644 --- a/tests/codegen-units/item-collection/unused-traits-and-generics.rs +++ b/tests/codegen-units/item-collection/unused-traits-and-generics.rs @@ -1,6 +1,6 @@ //@ compile-flags:-Zprint-mono-items=eager -#![crate_type="lib"] +#![crate_type = "lib"] #![deny(dead_code)] // This test asserts that no codegen items are generated for generic items that @@ -16,7 +16,7 @@ pub fn foo(x: T) -> (T, T) { } pub struct Struct { - x: T + x: T, } impl Struct { @@ -29,7 +29,7 @@ impl Struct { pub enum Enum { A(T), - B { x: T } + B { x: T }, } impl Enum { @@ -56,7 +56,7 @@ impl TupleStruct { pub type Pair = (T, T); pub struct NonGeneric { - x: i32 + x: i32, } impl NonGeneric { diff --git a/tests/codegen-units/partitioning/auxiliary/shared_generics_aux.rs b/tests/codegen-units/partitioning/auxiliary/shared_generics_aux.rs index 158932d165df..b6c568ed387a 100644 --- a/tests/codegen-units/partitioning/auxiliary/shared_generics_aux.rs +++ b/tests/codegen-units/partitioning/auxiliary/shared_generics_aux.rs @@ -3,7 +3,7 @@ //@ compile-flags:-Zshare-generics=yes -Copt-level=0 //@ no-prefer-dynamic -#![crate_type="rlib"] +#![crate_type = "rlib"] pub fn generic_fn(x: T, y: T) -> (T, T) { (x, y) diff --git a/tests/codegen-units/partitioning/extern-generic.rs b/tests/codegen-units/partitioning/extern-generic.rs index 0e4b6a37f712..602a5240283b 100644 --- a/tests/codegen-units/partitioning/extern-generic.rs +++ b/tests/codegen-units/partitioning/extern-generic.rs @@ -3,7 +3,7 @@ //@ compile-flags:-Zprint-mono-items=eager -Zshare-generics=y #![allow(dead_code)] -#![crate_type="lib"] +#![crate_type = "lib"] //@ aux-build:cgu_generic_function.rs extern crate cgu_generic_function; diff --git a/tests/codegen-units/partitioning/inlining-from-extern-crate.rs b/tests/codegen-units/partitioning/inlining-from-extern-crate.rs index d021f467f1f9..b007ffe1cb51 100644 --- a/tests/codegen-units/partitioning/inlining-from-extern-crate.rs +++ b/tests/codegen-units/partitioning/inlining-from-extern-crate.rs @@ -3,7 +3,7 @@ //@ compile-flags:-Zprint-mono-items=lazy //@ compile-flags:-Zinline-in-all-cgus -#![crate_type="lib"] +#![crate_type = "lib"] //@ aux-build:cgu_explicit_inlining.rs extern crate cgu_explicit_inlining; @@ -15,8 +15,7 @@ extern crate cgu_explicit_inlining; //~ MONO_ITEM fn cgu_explicit_inlining::always_inlined @@ inlining_from_extern_crate[Internal] inlining_from_extern_crate-mod2[Internal] //~ MONO_ITEM fn user @@ inlining_from_extern_crate[External] -pub fn user() -{ +pub fn user() { cgu_explicit_inlining::inlined(); cgu_explicit_inlining::always_inlined(); @@ -28,8 +27,7 @@ pub mod mod1 { use cgu_explicit_inlining; //~ MONO_ITEM fn mod1::user @@ inlining_from_extern_crate-mod1[External] - pub fn user() - { + pub fn user() { cgu_explicit_inlining::inlined(); // does not generate a monomorphization in this crate @@ -41,8 +39,7 @@ pub mod mod2 { use cgu_explicit_inlining; //~ MONO_ITEM fn mod2::user @@ inlining_from_extern_crate-mod2[External] - pub fn user() - { + pub fn user() { cgu_explicit_inlining::always_inlined(); // does not generate a monomorphization in this crate diff --git a/tests/codegen-units/partitioning/local-generic.rs b/tests/codegen-units/partitioning/local-generic.rs index 06f46b23db6a..0cfc572650c1 100644 --- a/tests/codegen-units/partitioning/local-generic.rs +++ b/tests/codegen-units/partitioning/local-generic.rs @@ -3,13 +3,15 @@ //@ compile-flags:-Zprint-mono-items=eager #![allow(dead_code)] -#![crate_type="lib"] +#![crate_type = "lib"] //~ MONO_ITEM fn generic:: @@ local_generic.volatile[External] //~ MONO_ITEM fn generic:: @@ local_generic.volatile[External] //~ MONO_ITEM fn generic:: @@ local_generic.volatile[External] //~ MONO_ITEM fn generic::<&str> @@ local_generic.volatile[External] -pub fn generic(x: T) -> T { x } +pub fn generic(x: T) -> T { + x +} //~ MONO_ITEM fn user @@ local_generic[Internal] fn user() { diff --git a/tests/codegen-units/partitioning/local-inlining-but-not-all.rs b/tests/codegen-units/partitioning/local-inlining-but-not-all.rs index 2f9cbe83f1d5..454de255254a 100644 --- a/tests/codegen-units/partitioning/local-inlining-but-not-all.rs +++ b/tests/codegen-units/partitioning/local-inlining-but-not-all.rs @@ -4,16 +4,13 @@ //@ compile-flags:-Zinline-in-all-cgus=no #![allow(dead_code)] -#![crate_type="lib"] +#![crate_type = "lib"] mod inline { //~ MONO_ITEM fn inline::inlined_function @@ local_inlining_but_not_all-inline[External] #[inline] - pub fn inlined_function() - { - - } + pub fn inlined_function() {} } pub mod user1 { @@ -37,7 +34,5 @@ pub mod user2 { pub mod non_user { //~ MONO_ITEM fn non_user::baz @@ local_inlining_but_not_all-non_user[External] - pub fn baz() { - - } + pub fn baz() {} } diff --git a/tests/codegen-units/partitioning/local-inlining.rs b/tests/codegen-units/partitioning/local-inlining.rs index 2329a876c960..42c68b5c6218 100644 --- a/tests/codegen-units/partitioning/local-inlining.rs +++ b/tests/codegen-units/partitioning/local-inlining.rs @@ -4,17 +4,14 @@ //@ compile-flags:-Zinline-in-all-cgus #![allow(dead_code)] -#![crate_type="lib"] +#![crate_type = "lib"] mod inline { // Important: This function should show up in all codegen units where it is inlined //~ MONO_ITEM fn inline::inlined_function @@ local_inlining-user1[Internal] local_inlining-user2[Internal] #[inline(always)] - pub fn inlined_function() - { - - } + pub fn inlined_function() {} } pub mod user1 { @@ -38,7 +35,5 @@ pub mod user2 { pub mod non_user { //~ MONO_ITEM fn non_user::baz @@ local_inlining-non_user[External] - pub fn baz() { - - } + pub fn baz() {} } diff --git a/tests/codegen-units/partitioning/local-transitive-inlining.rs b/tests/codegen-units/partitioning/local-transitive-inlining.rs index 4ccc53aea1d1..0d279ebe7404 100644 --- a/tests/codegen-units/partitioning/local-transitive-inlining.rs +++ b/tests/codegen-units/partitioning/local-transitive-inlining.rs @@ -4,16 +4,13 @@ //@ compile-flags:-Zinline-in-all-cgus #![allow(dead_code)] -#![crate_type="rlib"] +#![crate_type = "rlib"] mod inline { //~ MONO_ITEM fn inline::inlined_function @@ local_transitive_inlining-indirect_user[Internal] #[inline(always)] - pub fn inlined_function() - { - - } + pub fn inlined_function() {} } mod direct_user { @@ -38,7 +35,5 @@ pub mod indirect_user { pub mod non_user { //~ MONO_ITEM fn non_user::baz @@ local_transitive_inlining-non_user[External] - pub fn baz() { - - } + pub fn baz() {} } diff --git a/tests/codegen-units/partitioning/methods-are-with-self-type.rs b/tests/codegen-units/partitioning/methods-are-with-self-type.rs index 3ba53334cc90..901e7507d738 100644 --- a/tests/codegen-units/partitioning/methods-are-with-self-type.rs +++ b/tests/codegen-units/partitioning/methods-are-with-self-type.rs @@ -15,7 +15,7 @@ struct SomeType; struct SomeGenericType(T1, T2); mod mod1 { - use super::{SomeType, SomeGenericType}; + use super::{SomeGenericType, SomeType}; // Even though the impl is in `mod1`, the methods should end up in the // parent module, since that is where their self-type is. @@ -40,8 +40,7 @@ trait Trait { // We provide an implementation of `Trait` for all types. The corresponding // monomorphizations should end up in whichever module the concrete `T` is. -impl Trait for T -{ +impl Trait for T { fn foo(&self) {} } diff --git a/tests/codegen-units/partitioning/regular-modules.rs b/tests/codegen-units/partitioning/regular-modules.rs index 68601975d062..294971464155 100644 --- a/tests/codegen-units/partitioning/regular-modules.rs +++ b/tests/codegen-units/partitioning/regular-modules.rs @@ -3,7 +3,7 @@ //@ compile-flags:-Zprint-mono-items=eager #![allow(dead_code)] -#![crate_type="lib"] +#![crate_type = "lib"] //~ MONO_ITEM fn foo @@ regular_modules[Internal] fn foo() {} diff --git a/tests/codegen-units/partitioning/shared-generics.rs b/tests/codegen-units/partitioning/shared-generics.rs index 5b78794316c6..ea312719ac91 100644 --- a/tests/codegen-units/partitioning/shared-generics.rs +++ b/tests/codegen-units/partitioning/shared-generics.rs @@ -4,14 +4,13 @@ //@ incremental //@ compile-flags:-Zprint-mono-items=eager -Zshare-generics=yes -Copt-level=0 -#![crate_type="rlib"] +#![crate_type = "rlib"] //@ aux-build:shared_generics_aux.rs extern crate shared_generics_aux; //~ MONO_ITEM fn foo pub fn foo() { - //~ MONO_ITEM fn shared_generics_aux::generic_fn:: @@ shared_generics_aux-in-shared_generics.volatile[External] let _ = shared_generics_aux::generic_fn(0u16, 1u16); diff --git a/tests/codegen-units/partitioning/statics.rs b/tests/codegen-units/partitioning/statics.rs index c7eef1f3789d..00dd6d877e1e 100644 --- a/tests/codegen-units/partitioning/statics.rs +++ b/tests/codegen-units/partitioning/statics.rs @@ -2,7 +2,7 @@ //@ incremental //@ compile-flags:-Zprint-mono-items=lazy -#![crate_type="rlib"] +#![crate_type = "rlib"] //~ MONO_ITEM static FOO @@ statics[Internal] static FOO: u32 = 0; diff --git a/tests/codegen-units/partitioning/vtable-through-const.rs b/tests/codegen-units/partitioning/vtable-through-const.rs index f91c0c0bfdbf..a9186cea9c89 100644 --- a/tests/codegen-units/partitioning/vtable-through-const.rs +++ b/tests/codegen-units/partitioning/vtable-through-const.rs @@ -28,20 +28,24 @@ mod mod1 { } impl Trait1Gen for NeedsDrop { - fn do_something(&self, x: T) -> T { x } - fn do_something_else(&self, x: T) -> T { x } + fn do_something(&self, x: T) -> T { + x + } + fn do_something_else(&self, x: T) -> T { + x + } } //~ MONO_ITEM fn mod1::id:: @@ vtable_through_const-mod1.volatile[Internal] - fn id(x: T) -> T { x } + fn id(x: T) -> T { + x + } // These are referenced, so they produce mono-items (see start()) pub const TRAIT1_REF: &'static Trait1 = &NeedsDrop as &Trait1; pub const TRAIT1_GEN_REF: &'static Trait1Gen = &NeedsDrop as &Trait1Gen; pub const ID_CHAR: fn(char) -> char = id::; - - pub trait Trait2 { fn do_something(&self) {} fn do_something_else(&self) {} @@ -57,8 +61,12 @@ mod mod1 { } impl Trait2Gen for NeedsDrop { - fn do_something(&self, x: T) -> T { x } - fn do_something_else(&self, x: T) -> T { x } + fn do_something(&self, x: T) -> T { + x + } + fn do_something_else(&self, x: T) -> T { + x + } } // These are not referenced, so they do not produce mono-items diff --git a/tests/codegen-units/polymorphization/unused_type_parameters.rs b/tests/codegen-units/polymorphization/unused_type_parameters.rs index cf5f7c320985..438305f112f3 100644 --- a/tests/codegen-units/polymorphization/unused_type_parameters.rs +++ b/tests/codegen-units/polymorphization/unused_type_parameters.rs @@ -9,54 +9,51 @@ mod functions { // Function doesn't have any type parameters to be unused. pub fn no_parameters() {} -//~ MONO_ITEM fn functions::no_parameters + //~ MONO_ITEM fn functions::no_parameters // Function has an unused type parameter. - pub fn unused() { - } + pub fn unused() {} -//~ MONO_ITEM fn functions::unused:: + //~ MONO_ITEM fn functions::unused:: // Function uses type parameter in value of a binding. pub fn used_binding_value() { let _: T = Default::default(); } -//~ MONO_ITEM fn functions::used_binding_value:: -//~ MONO_ITEM fn functions::used_binding_value:: + //~ MONO_ITEM fn functions::used_binding_value:: + //~ MONO_ITEM fn functions::used_binding_value:: // Function uses type parameter in type of a binding. pub fn used_binding_type() { let _: Option = None; } -//~ MONO_ITEM fn functions::used_binding_type:: -//~ MONO_ITEM fn functions::used_binding_type:: + //~ MONO_ITEM fn functions::used_binding_type:: + //~ MONO_ITEM fn functions::used_binding_type:: // Function uses type parameter in argument. - pub fn used_argument(_: T) { - } + pub fn used_argument(_: T) {} -//~ MONO_ITEM fn functions::used_argument:: -//~ MONO_ITEM fn functions::used_argument:: -// + //~ MONO_ITEM fn functions::used_argument:: + //~ MONO_ITEM fn functions::used_argument:: + // // Function uses type parameter in substitutions to another function. pub fn used_substs() { unused::() } -//~ MONO_ITEM fn functions::used_substs:: -//~ MONO_ITEM fn functions::used_substs:: + //~ MONO_ITEM fn functions::used_substs:: + //~ MONO_ITEM fn functions::used_substs:: } - mod closures { // Function doesn't have any type parameters to be unused. pub fn no_parameters() { let _ = || {}; } -//~ MONO_ITEM fn closures::no_parameters + //~ MONO_ITEM fn closures::no_parameters // Function has an unused type parameter in parent and closure. pub fn unused() -> u32 { @@ -64,8 +61,8 @@ mod closures { add_one(3) } -//~ MONO_ITEM fn closures::unused::::{closure#0} -//~ MONO_ITEM fn closures::unused:: + //~ MONO_ITEM fn closures::unused::::{closure#0} + //~ MONO_ITEM fn closures::unused:: // Function has an unused type parameter in closure, but not in parent. pub fn used_parent() -> u32 { @@ -74,9 +71,9 @@ mod closures { add_one(3) } -//~ MONO_ITEM fn closures::used_parent::::{closure#0} -//~ MONO_ITEM fn closures::used_parent:: -//~ MONO_ITEM fn closures::used_parent:: + //~ MONO_ITEM fn closures::used_parent::::{closure#0} + //~ MONO_ITEM fn closures::used_parent:: + //~ MONO_ITEM fn closures::used_parent:: // Function uses type parameter in value of a binding in closure. pub fn used_binding_value() -> T { @@ -88,10 +85,10 @@ mod closures { x() } -//~ MONO_ITEM fn closures::used_binding_value::::{closure#0} -//~ MONO_ITEM fn closures::used_binding_value::::{closure#0} -//~ MONO_ITEM fn closures::used_binding_value:: -//~ MONO_ITEM fn closures::used_binding_value:: + //~ MONO_ITEM fn closures::used_binding_value::::{closure#0} + //~ MONO_ITEM fn closures::used_binding_value::::{closure#0} + //~ MONO_ITEM fn closures::used_binding_value:: + //~ MONO_ITEM fn closures::used_binding_value:: // Function uses type parameter in type of a binding in closure. pub fn used_binding_type() -> Option { @@ -103,10 +100,10 @@ mod closures { x() } -//~ MONO_ITEM fn closures::used_binding_type::::{closure#0} -//~ MONO_ITEM fn closures::used_binding_type::::{closure#0} -//~ MONO_ITEM fn closures::used_binding_type:: -//~ MONO_ITEM fn closures::used_binding_type:: + //~ MONO_ITEM fn closures::used_binding_type::::{closure#0} + //~ MONO_ITEM fn closures::used_binding_type::::{closure#0} + //~ MONO_ITEM fn closures::used_binding_type:: + //~ MONO_ITEM fn closures::used_binding_type:: // Function and closure uses type parameter in argument. pub fn used_argument(t: T) -> u32 { @@ -114,10 +111,10 @@ mod closures { x(t) } -//~ MONO_ITEM fn closures::used_argument::::{closure#0} -//~ MONO_ITEM fn closures::used_argument::::{closure#0} -//~ MONO_ITEM fn closures::used_argument:: -//~ MONO_ITEM fn closures::used_argument:: + //~ MONO_ITEM fn closures::used_argument::::{closure#0} + //~ MONO_ITEM fn closures::used_argument::::{closure#0} + //~ MONO_ITEM fn closures::used_argument:: + //~ MONO_ITEM fn closures::used_argument:: // Closure uses type parameter in argument. pub fn used_argument_closure() -> u32 { @@ -126,10 +123,10 @@ mod closures { x(t) } -//~ MONO_ITEM fn closures::used_argument_closure::::{closure#0} -//~ MONO_ITEM fn closures::used_argument_closure::::{closure#0} -//~ MONO_ITEM fn closures::used_argument_closure:: -//~ MONO_ITEM fn closures::used_argument_closure:: + //~ MONO_ITEM fn closures::used_argument_closure::::{closure#0} + //~ MONO_ITEM fn closures::used_argument_closure::::{closure#0} + //~ MONO_ITEM fn closures::used_argument_closure:: + //~ MONO_ITEM fn closures::used_argument_closure:: // Closure uses type parameter as upvar. pub fn used_upvar() -> T { @@ -138,10 +135,10 @@ mod closures { y() } -//~ MONO_ITEM fn closures::used_upvar::::{closure#0} -//~ MONO_ITEM fn closures::used_upvar::::{closure#0} -//~ MONO_ITEM fn closures::used_upvar:: -//~ MONO_ITEM fn closures::used_upvar:: + //~ MONO_ITEM fn closures::used_upvar::::{closure#0} + //~ MONO_ITEM fn closures::used_upvar::::{closure#0} + //~ MONO_ITEM fn closures::used_upvar:: + //~ MONO_ITEM fn closures::used_upvar:: // Closure uses type parameter in substitutions to another function. pub fn used_substs() { @@ -149,10 +146,10 @@ mod closures { x() } -//~ MONO_ITEM fn closures::used_substs::::{closure#0} -//~ MONO_ITEM fn closures::used_substs::::{closure#0} -//~ MONO_ITEM fn closures::used_substs:: -//~ MONO_ITEM fn closures::used_substs:: + //~ MONO_ITEM fn closures::used_substs::::{closure#0} + //~ MONO_ITEM fn closures::used_substs::::{closure#0} + //~ MONO_ITEM fn closures::used_substs:: + //~ MONO_ITEM fn closures::used_substs:: } mod methods { @@ -160,32 +157,30 @@ mod methods { impl Foo { // Function has an unused type parameter from impl. - pub fn unused_impl() { - } + pub fn unused_impl() {} -//~ MONO_ITEM fn methods::Foo::::unused_impl + //~ MONO_ITEM fn methods::Foo::::unused_impl // Function has an unused type parameter from impl and fn. - pub fn unused_both() { - } + pub fn unused_both() {} -//~ MONO_ITEM fn methods::Foo::::unused_both:: + //~ MONO_ITEM fn methods::Foo::::unused_both:: // Function uses type parameter from impl. pub fn used_impl() { let _: F = Default::default(); } -//~ MONO_ITEM fn methods::Foo::::used_impl -//~ MONO_ITEM fn methods::Foo::::used_impl + //~ MONO_ITEM fn methods::Foo::::used_impl + //~ MONO_ITEM fn methods::Foo::::used_impl // Function uses type parameter from impl. pub fn used_fn() { let _: G = Default::default(); } -//~ MONO_ITEM fn methods::Foo::::used_fn:: -//~ MONO_ITEM fn methods::Foo::::used_fn:: + //~ MONO_ITEM fn methods::Foo::::used_fn:: + //~ MONO_ITEM fn methods::Foo::::used_fn:: // Function uses type parameter from impl. pub fn used_both() { @@ -193,16 +188,16 @@ mod methods { let _: G = Default::default(); } -//~ MONO_ITEM fn methods::Foo::::used_both:: -//~ MONO_ITEM fn methods::Foo::::used_both:: + //~ MONO_ITEM fn methods::Foo::::used_both:: + //~ MONO_ITEM fn methods::Foo::::used_both:: // Function uses type parameter in substitutions to another function. pub fn used_substs() { super::functions::unused::() } -//~ MONO_ITEM fn methods::Foo::::used_substs -//~ MONO_ITEM fn methods::Foo::::used_substs + //~ MONO_ITEM fn methods::Foo::::used_substs + //~ MONO_ITEM fn methods::Foo::::used_substs // Function has an unused type parameter from impl and fn. pub fn closure_unused_all() -> u32 { @@ -210,8 +205,8 @@ mod methods { add_one(3) } -//~ MONO_ITEM fn methods::Foo::::closure_unused_all::::{closure#0} -//~ MONO_ITEM fn methods::Foo::::closure_unused_all:: + //~ MONO_ITEM fn methods::Foo::::closure_unused_all::::{closure#0} + //~ MONO_ITEM fn methods::Foo::::closure_unused_all:: // Function uses type parameter from impl and fn in closure. pub fn closure_used_both() -> u32 { @@ -224,10 +219,10 @@ mod methods { add_one(3) } -//~ MONO_ITEM fn methods::Foo::::closure_used_both::::{closure#0} -//~ MONO_ITEM fn methods::Foo::::closure_used_both::::{closure#0} -//~ MONO_ITEM fn methods::Foo::::closure_used_both:: -//~ MONO_ITEM fn methods::Foo::::closure_used_both:: + //~ MONO_ITEM fn methods::Foo::::closure_used_both::::{closure#0} + //~ MONO_ITEM fn methods::Foo::::closure_used_both::::{closure#0} + //~ MONO_ITEM fn methods::Foo::::closure_used_both:: + //~ MONO_ITEM fn methods::Foo::::closure_used_both:: // Function uses type parameter from fn in closure. pub fn closure_used_fn() -> u32 { @@ -239,10 +234,10 @@ mod methods { add_one(3) } -//~ MONO_ITEM fn methods::Foo::::closure_used_fn::::{closure#0} -//~ MONO_ITEM fn methods::Foo::::closure_used_fn::::{closure#0} -//~ MONO_ITEM fn methods::Foo::::closure_used_fn:: -//~ MONO_ITEM fn methods::Foo::::closure_used_fn:: + //~ MONO_ITEM fn methods::Foo::::closure_used_fn::::{closure#0} + //~ MONO_ITEM fn methods::Foo::::closure_used_fn::::{closure#0} + //~ MONO_ITEM fn methods::Foo::::closure_used_fn:: + //~ MONO_ITEM fn methods::Foo::::closure_used_fn:: // Function uses type parameter from impl in closure. pub fn closure_used_impl() -> u32 { @@ -254,10 +249,10 @@ mod methods { add_one(3) } -//~ MONO_ITEM fn methods::Foo::::closure_used_impl::::{closure#0} -//~ MONO_ITEM fn methods::Foo::::closure_used_impl::::{closure#0} -//~ MONO_ITEM fn methods::Foo::::closure_used_impl:: -//~ MONO_ITEM fn methods::Foo::::closure_used_impl:: + //~ MONO_ITEM fn methods::Foo::::closure_used_impl::::{closure#0} + //~ MONO_ITEM fn methods::Foo::::closure_used_impl::::{closure#0} + //~ MONO_ITEM fn methods::Foo::::closure_used_impl:: + //~ MONO_ITEM fn methods::Foo::::closure_used_impl:: // Closure uses type parameter in substitutions to another function. pub fn closure_used_substs() { @@ -265,15 +260,13 @@ mod methods { x() } -//~ MONO_ITEM fn methods::Foo::::closure_used_substs::{closure#0} -//~ MONO_ITEM fn methods::Foo::::closure_used_substs::{closure#0} -//~ MONO_ITEM fn methods::Foo::::closure_used_substs -//~ MONO_ITEM fn methods::Foo::::closure_used_substs + //~ MONO_ITEM fn methods::Foo::::closure_used_substs::{closure#0} + //~ MONO_ITEM fn methods::Foo::::closure_used_substs::{closure#0} + //~ MONO_ITEM fn methods::Foo::::closure_used_substs + //~ MONO_ITEM fn methods::Foo::::closure_used_substs } } - - fn dispatch() { functions::no_parameters(); functions::unused::(); From e86709c58a9a423ddd72f058af9778daefac4e98 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 29 May 2024 14:29:54 +1000 Subject: [PATCH 117/211] Run rustfmt on `tests/coverage/`. There are no changes to `.rs` files because #125693 recently formatted them all. --- rustfmt.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/rustfmt.toml b/rustfmt.toml index 5f40abcbaa5b..b8ffb807cf01 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -15,7 +15,6 @@ ignore = [ # - some UI tests are broken by different formatting # - some require special comments in a particular position (e.g. `EMIT_MIR` comments) "/tests/codegen/simd-intrinsic/", # Many types like `u8x64` are better hand-formatted. - "/tests/coverage/", "/tests/coverage-run-rustdoc/", "/tests/crashes/", "/tests/debuginfo/", From 4fd2003026bf66dd09f40e81958f0b1ecfdeb62d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 29 May 2024 14:35:52 +1000 Subject: [PATCH 118/211] Run rustfmt on `tests/coverage-run-rustdoc/`. There are only two tiny Rust files in this directory, and they are already formatted correctly. --- rustfmt.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/rustfmt.toml b/rustfmt.toml index b8ffb807cf01..e633ab2c6e34 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -15,7 +15,6 @@ ignore = [ # - some UI tests are broken by different formatting # - some require special comments in a particular position (e.g. `EMIT_MIR` comments) "/tests/codegen/simd-intrinsic/", # Many types like `u8x64` are better hand-formatted. - "/tests/coverage-run-rustdoc/", "/tests/crashes/", "/tests/debuginfo/", "/tests/incremental/", From 70bc0c5b204375e3efe1572689356bf99a9f4e9d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 29 May 2024 14:37:37 +1000 Subject: [PATCH 119/211] Explain why we don't run rustfmt on `tests/crashes/`. --- rustfmt.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rustfmt.toml b/rustfmt.toml index e633ab2c6e34..6f79e4b4e525 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -15,7 +15,7 @@ ignore = [ # - some UI tests are broken by different formatting # - some require special comments in a particular position (e.g. `EMIT_MIR` comments) "/tests/codegen/simd-intrinsic/", # Many types like `u8x64` are better hand-formatted. - "/tests/crashes/", + "/tests/crashes/", # Many tests contain syntax errors. "/tests/debuginfo/", "/tests/incremental/", "/tests/mir-opt/", From 06c4cc44b61cab331d0db1f0592ec7d172abf881 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 31 May 2024 08:56:38 +0000 Subject: [PATCH 120/211] Also resolve the type of constants, even if we already turned it into an error constant --- compiler/rustc_hir_typeck/src/writeback.rs | 1 + .../const_generic_type.rs | 10 ++++++++++ .../const_generic_type.stderr | 19 +++++++++++++++++++ 3 files changed, 30 insertions(+) create mode 100644 tests/ui/type-alias-impl-trait/const_generic_type.rs create mode 100644 tests/ui/type-alias-impl-trait/const_generic_type.stderr diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 31caa52d2671..e337105f0110 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -865,6 +865,7 @@ impl<'cx, 'tcx> TypeFolder> for Resolver<'cx, 'tcx> { self.handle_term(ct, ty::Const::outer_exclusive_binder, |tcx, guar| { ty::Const::new_error(tcx, guar, ct.ty()) }) + .super_fold_with(self) } fn fold_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> { diff --git a/tests/ui/type-alias-impl-trait/const_generic_type.rs b/tests/ui/type-alias-impl-trait/const_generic_type.rs new file mode 100644 index 000000000000..3af122fc4e33 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/const_generic_type.rs @@ -0,0 +1,10 @@ +//@edition: 2021 + +#![feature(type_alias_impl_trait)] +type Bar = impl std::fmt::Display; + +async fn test() {} +//~^ ERROR: type annotations needed +//~| ERROR: `Bar` is forbidden as the type of a const generic parameter + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/const_generic_type.stderr b/tests/ui/type-alias-impl-trait/const_generic_type.stderr new file mode 100644 index 000000000000..5501f23c8bb1 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/const_generic_type.stderr @@ -0,0 +1,19 @@ +error[E0283]: type annotations needed + --> $DIR/const_generic_type.rs:6:1 + | +LL | async fn test() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type + | + = note: cannot satisfy `_: std::fmt::Display` + +error: `Bar` is forbidden as the type of a const generic parameter + --> $DIR/const_generic_type.rs:6:24 + | +LL | async fn test() {} + | ^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0283`. From befcdec7778bc901f47fa8ebd4d5e322a8bd187e Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 31 May 2024 08:58:56 +0000 Subject: [PATCH 121/211] Check that we can constrain the hidden tpye of a TAIT used in a const generic type --- .../const_generic_type.infer.stderr | 10 ++++++++++ ..._type.stderr => const_generic_type.no_infer.stderr} | 8 ++++---- tests/ui/type-alias-impl-trait/const_generic_type.rs | 10 +++++++--- 3 files changed, 21 insertions(+), 7 deletions(-) create mode 100644 tests/ui/type-alias-impl-trait/const_generic_type.infer.stderr rename tests/ui/type-alias-impl-trait/{const_generic_type.stderr => const_generic_type.no_infer.stderr} (73%) diff --git a/tests/ui/type-alias-impl-trait/const_generic_type.infer.stderr b/tests/ui/type-alias-impl-trait/const_generic_type.infer.stderr new file mode 100644 index 000000000000..6a1a770228da --- /dev/null +++ b/tests/ui/type-alias-impl-trait/const_generic_type.infer.stderr @@ -0,0 +1,10 @@ +error: `Bar` is forbidden as the type of a const generic parameter + --> $DIR/const_generic_type.rs:7:24 + | +LL | async fn test() { + | ^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + +error: aborting due to 1 previous error + diff --git a/tests/ui/type-alias-impl-trait/const_generic_type.stderr b/tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr similarity index 73% rename from tests/ui/type-alias-impl-trait/const_generic_type.stderr rename to tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr index 5501f23c8bb1..a1a69bfaca37 100644 --- a/tests/ui/type-alias-impl-trait/const_generic_type.stderr +++ b/tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr @@ -1,15 +1,15 @@ error[E0283]: type annotations needed - --> $DIR/const_generic_type.rs:6:1 + --> $DIR/const_generic_type.rs:7:1 | -LL | async fn test() {} +LL | async fn test() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type | = note: cannot satisfy `_: std::fmt::Display` error: `Bar` is forbidden as the type of a const generic parameter - --> $DIR/const_generic_type.rs:6:24 + --> $DIR/const_generic_type.rs:7:24 | -LL | async fn test() {} +LL | async fn test() { | ^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` diff --git a/tests/ui/type-alias-impl-trait/const_generic_type.rs b/tests/ui/type-alias-impl-trait/const_generic_type.rs index 3af122fc4e33..95a5e1c62861 100644 --- a/tests/ui/type-alias-impl-trait/const_generic_type.rs +++ b/tests/ui/type-alias-impl-trait/const_generic_type.rs @@ -1,10 +1,14 @@ //@edition: 2021 +//@revisions: infer no_infer #![feature(type_alias_impl_trait)] type Bar = impl std::fmt::Display; -async fn test() {} -//~^ ERROR: type annotations needed -//~| ERROR: `Bar` is forbidden as the type of a const generic parameter +async fn test() { + //[no_infer]~^ ERROR: type annotations needed + //~^^ ERROR: `Bar` is forbidden as the type of a const generic parameter + #[cfg(infer)] + let x: u32 = N; +} fn main() {} From 3079bd96b94fda7acba3161bd53719576224a210 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 29 May 2024 15:01:33 +1000 Subject: [PATCH 122/211] Run rustfmt on `tests/run-make/`. With the exception of `tests/run-make/translation/test.rs`, which has a syntax error. The expected output in `rustdoc-error-lines/rmake.rs`'s required slight tweaking. The two `reproducible-build.rs` files need `// ignore-tidy-linelength` because rustfmt produces lines longer than 100 chars, which tidy doesn't like, yuk. --- rustfmt.toml | 2 +- tests/run-make/a-b-a-linker-guard/a.rs | 4 +- .../allow-non-lint-warnings-cmdline/foo.rs | 2 +- .../allow-warnings-cmdline-stability/foo.rs | 4 +- .../atomic-lock-free/atomic_lock_free.rs | 2 +- tests/run-make/bare-outfile/foo.rs | 3 +- tests/run-make/box-struct-no-segfault/foo.rs | 8 ++-- tests/run-make/box-struct-no-segfault/main.rs | 4 +- .../c-link-to-rust-va-list-fn/checkrust.rs | 18 ++++---- tests/run-make/compiler-lookup-paths-2/c.rs | 2 +- tests/run-make/crate-data-smoke/rmake.rs | 33 +++------------ .../run-make/cross-lang-lto-clang/rustlib.rs | 2 +- .../cross-lang-lto-pgo-smoketest/rustlib.rs | 2 +- .../staticlib.rs | 2 +- tests/run-make/debug-assertions/debug.rs | 20 +++++++-- tests/run-make/dep-info-spaces/lib.rs | 2 +- tests/run-make/dep-info/lib.rs | 2 +- tests/run-make/deref-impl-rustdoc-ice/baz.rs | 6 ++- tests/run-make/deref-impl-rustdoc-ice/foo.rs | 4 +- tests/run-make/dylib-chain/m2.rs | 4 +- tests/run-make/dylib-chain/m3.rs | 4 +- tests/run-make/dylib-chain/m4.rs | 4 +- tests/run-make/emit/test-26235.rs | 25 +++++++---- .../extern-diff-internal-name/test.rs | 3 +- tests/run-make/extern-flag-disambiguates/a.rs | 4 +- tests/run-make/extern-flag-disambiguates/b.rs | 8 +++- tests/run-make/extern-flag-disambiguates/c.rs | 8 +++- tests/run-make/extern-flag-disambiguates/d.rs | 10 +++-- .../run-make/extern-fn-explicit-align/test.rs | 4 +- tests/run-make/extern-fn-reachable/dylib.rs | 15 ++++--- .../extern-fn-struct-passing-abi/test.rs | 8 +++- tests/run-make/extern-multiple-copies/bar.rs | 2 +- .../app.rs | 1 - tests/run-make/incr-prev-body-beyond-eof/a.rs | 4 -- tests/run-make/incr-prev-body-beyond-eof/b.rs | 2 +- tests/run-make/inline-always-many-cgu/foo.rs | 6 +-- .../interdependent-c-libraries/main.rs | 2 +- .../intrinsic-unreachable/exit-ret.rs | 2 +- .../intrinsic-unreachable/exit-unreachable.rs | 2 +- tests/run-make/issue-18943/foo.rs | 6 +-- tests/run-make/issue-20626/foo.rs | 4 +- tests/run-make/issue-22131/foo.rs | 4 +- tests/run-make/issue-26006/in/libc/lib.rs | 4 +- tests/run-make/issue-26006/in/time/lib.rs | 2 +- tests/run-make/issue-37839/b.rs | 3 +- .../issue-47551/eh_frame-terminator.rs | 4 +- tests/run-make/issue-69368/c.rs | 2 +- tests/run-make/link-arg/empty.rs | 2 +- .../long-linker-command-lines-cmd-exe/foo.rs | 24 ++++++----- .../run-make/long-linker-command-lines/foo.rs | 41 +++++++++++-------- .../many-crates-but-no-match/crateA1.rs | 2 +- .../many-crates-but-no-match/crateA2.rs | 6 ++- .../many-crates-but-no-match/crateA3.rs | 6 ++- .../metadata-flag-frobs-symbols/foo.rs | 4 +- tests/run-make/mixing-deps/dylib.rs | 4 +- tests/run-make/mixing-deps/prog.rs | 5 +-- tests/run-make/mixing-libs/dylib.rs | 4 +- .../native_lib_in_src.rs | 10 +++-- tests/run-make/non-pie-thread-local/foo.rs | 4 +- .../pass-non-c-like-enum-to-c/nonclike.rs | 4 +- tests/run-make/pdb-buildinfo-cl-cmd/main.rs | 3 +- .../pgo-branch-weights/interesting.rs | 5 +-- tests/run-make/pgo-branch-weights/opaque.rs | 4 +- .../interesting.rs | 8 +--- .../pgo-indirect-call-promotion/main.rs | 5 +-- .../pgo-indirect-call-promotion/opaque.rs | 4 +- tests/run-make/pgo-use/main.rs | 2 +- .../run-make/pointer-auth-link-with-c/test.rs | 4 +- tests/run-make/pretty-print-to-file/input.rs | 8 ++-- tests/run-make/print-check-cfg/rmake.rs | 10 +++-- tests/run-make/proc-macro-init-order/b.rs | 3 +- tests/run-make/proc-macro-init-order/c.rs | 2 +- tests/run-make/prune-link-args/empty.rs | 2 +- .../driver.rs | 5 +-- tests/run-make/raw-dylib-c/lib.rs | 6 +-- .../raw-dylib-cross-compilation/lib.rs | 2 +- .../run-make/raw-dylib-custom-dlltool/lib.rs | 2 +- .../raw-dylib-import-name-type/driver.rs | 2 +- .../raw-dylib-inline-cross-dylib/driver.rs | 2 +- .../raw-dylib-inline-cross-dylib/lib.rs | 2 +- tests/run-make/raw-dylib-link-ordinal/lib.rs | 2 +- tests/run-make/reproducible-build-2/linker.rs | 4 +- .../reproducible-build-aux.rs | 4 +- .../reproducible-build.rs | 19 ++++----- tests/run-make/reproducible-build/linker.rs | 4 +- .../reproducible-build-aux.rs | 4 +- .../reproducible-build/reproducible-build.rs | 19 ++++----- tests/run-make/reset-codegen-1/foo.rs | 2 +- tests/run-make/resolve-rename/bar.rs | 4 +- tests/run-make/resolve-rename/baz.rs | 4 +- .../return-non-c-like-enum-from-c/nonclike.rs | 2 +- .../return-non-c-like-enum/nonclike.rs | 2 +- tests/run-make/rlib-chain/m2.rs | 4 +- tests/run-make/rlib-chain/m3.rs | 4 +- tests/run-make/rlib-chain/m4.rs | 4 +- tests/run-make/rustdoc-error-lines/input.rs | 4 +- tests/run-make/rustdoc-error-lines/rmake.rs | 8 ++-- tests/run-make/rustdoc-map-file/foo.rs | 4 +- .../src/lib.rs | 4 +- .../examples/ex.rs | 10 ++--- .../rustdoc-scrape-examples-macros/src/lib.rs | 4 +- .../examples/ex.rs | 2 +- .../examples/ex.rs | 6 ++- .../share-generics-dylib/linked_leaf.rs | 3 +- tests/run-make/split-debuginfo/main.rs | 2 +- .../stable-symbol-names1.rs | 22 +++++----- .../stable-symbol-names2.rs | 18 ++++---- tests/run-make/static-unwinding/lib.rs | 9 +++- tests/run-make/static-unwinding/main.rs | 10 +++-- tests/run-make/suspicious-library/bar.rs | 4 +- .../symbol-mangling-hashed/a_dylib.rs | 2 +- .../run-make/symbol-mangling-hashed/a_rlib.rs | 2 +- .../run-make/symbol-mangling-hashed/b_bin.rs | 2 +- .../symbol-mangling-hashed/b_dylib.rs | 4 +- tests/run-make/symbol-visibility/a_cdylib.rs | 2 +- .../symbol-visibility/a_rust_dylib.rs | 6 ++- .../symbol-visibility/an_executable.rs | 2 +- tests/run-make/symbol-visibility/an_rlib.rs | 2 +- tests/run-make/symlinked-extern/bar.rs | 3 +- tests/run-make/symlinked-extern/foo.rs | 4 +- tests/run-make/target-cpu-native/foo.rs | 3 +- .../run-make/test-harness/test-ignore-cfg.rs | 6 +-- .../type-mismatch-same-crate-name/crateA.rs | 4 +- .../type-mismatch-same-crate-name/crateB.rs | 4 +- .../use-suggestions.rs | 2 +- tests/run-make/wasm-custom-section/bar.rs | 2 +- .../run-make/wasm-custom-sections-opt/foo.rs | 2 +- .../wasm-exceptions-nostd/src/arena_alloc.rs | 9 +--- .../run-make/wasm-exceptions-nostd/src/lib.rs | 30 +++++++------- .../wasm-exceptions-nostd/src/panicking.rs | 5 +-- tests/run-make/wasm-export-all-symbols/bar.rs | 2 +- .../run-make/wasm-symbols-not-exported/bar.rs | 5 +-- .../run-make/wasm-symbols-not-exported/foo.rs | 2 +- .../run-make/wasm-symbols-not-imported/foo.rs | 2 +- tests/run-make/windows-spawn/spawn.rs | 2 +- .../enclave/build.rs | 24 ++++------- 136 files changed, 421 insertions(+), 370 deletions(-) diff --git a/rustfmt.toml b/rustfmt.toml index 6f79e4b4e525..dfc41819968a 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -20,7 +20,7 @@ ignore = [ "/tests/incremental/", "/tests/mir-opt/", "/tests/pretty/", - "/tests/run-make/", + "/tests/run-make/translation/test.rs", # Contains syntax errors. "/tests/run-make-fulldeps/", "/tests/run-pass-valgrind/", "/tests/rustdoc/", diff --git a/tests/run-make/a-b-a-linker-guard/a.rs b/tests/run-make/a-b-a-linker-guard/a.rs index aa07b1e71607..22686760f1aa 100644 --- a/tests/run-make/a-b-a-linker-guard/a.rs +++ b/tests/run-make/a-b-a-linker-guard/a.rs @@ -2,7 +2,7 @@ #![crate_type = "dylib"] #[cfg(x)] -pub fn foo(x: u32) { } +pub fn foo(x: u32) {} #[cfg(y)] -pub fn foo(x: i32) { } +pub fn foo(x: i32) {} diff --git a/tests/run-make/allow-non-lint-warnings-cmdline/foo.rs b/tests/run-make/allow-non-lint-warnings-cmdline/foo.rs index 46e72da2de9f..02e8ccabf792 100644 --- a/tests/run-make/allow-non-lint-warnings-cmdline/foo.rs +++ b/tests/run-make/allow-non-lint-warnings-cmdline/foo.rs @@ -2,4 +2,4 @@ #[derive(Copy, Clone)] pub struct Foo; -pub fn main() { } +pub fn main() {} diff --git a/tests/run-make/allow-warnings-cmdline-stability/foo.rs b/tests/run-make/allow-warnings-cmdline-stability/foo.rs index 869b54354168..0b91b63c1185 100644 --- a/tests/run-make/allow-warnings-cmdline-stability/foo.rs +++ b/tests/run-make/allow-warnings-cmdline-stability/foo.rs @@ -2,4 +2,6 @@ extern crate bar; -pub fn main() { bar::baz() } +pub fn main() { + bar::baz() +} diff --git a/tests/run-make/atomic-lock-free/atomic_lock_free.rs b/tests/run-make/atomic-lock-free/atomic_lock_free.rs index 47d90b1856be..1f1116b9bfd1 100644 --- a/tests/run-make/atomic-lock-free/atomic_lock_free.rs +++ b/tests/run-make/atomic-lock-free/atomic_lock_free.rs @@ -1,5 +1,5 @@ #![feature(no_core, intrinsics, lang_items)] -#![crate_type="rlib"] +#![crate_type = "rlib"] #![no_core] extern "rust-intrinsic" { diff --git a/tests/run-make/bare-outfile/foo.rs b/tests/run-make/bare-outfile/foo.rs index f79c691f0853..f328e4d9d04c 100644 --- a/tests/run-make/bare-outfile/foo.rs +++ b/tests/run-make/bare-outfile/foo.rs @@ -1,2 +1 @@ -fn main() { -} +fn main() {} diff --git a/tests/run-make/box-struct-no-segfault/foo.rs b/tests/run-make/box-struct-no-segfault/foo.rs index 1dcabe42dc11..0897b74b3567 100644 --- a/tests/run-make/box-struct-no-segfault/foo.rs +++ b/tests/run-make/box-struct-no-segfault/foo.rs @@ -1,8 +1,8 @@ -#![crate_type="lib"] +#![crate_type = "lib"] pub struct Foo(()); impl Foo { - pub fn new() -> Foo { - Foo(()) - } + pub fn new() -> Foo { + Foo(()) + } } diff --git a/tests/run-make/box-struct-no-segfault/main.rs b/tests/run-make/box-struct-no-segfault/main.rs index de12b1fd9dc3..1a456af48e8d 100644 --- a/tests/run-make/box-struct-no-segfault/main.rs +++ b/tests/run-make/box-struct-no-segfault/main.rs @@ -1,7 +1,7 @@ -#![crate_type="lib"] +#![crate_type = "lib"] extern crate foo; use foo::Foo; pub fn crash() -> Box { - Box::new(Foo::new()) + Box::new(Foo::new()) } diff --git a/tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs b/tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs index e518579b906a..196c6440747a 100644 --- a/tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs +++ b/tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs @@ -1,16 +1,16 @@ #![crate_type = "staticlib"] #![feature(c_variadic)] -use std::ffi::{c_char, c_double, c_int, c_long, c_longlong}; use std::ffi::VaList; -use std::ffi::{CString, CStr}; +use std::ffi::{c_char, c_double, c_int, c_long, c_longlong}; +use std::ffi::{CStr, CString}; macro_rules! continue_if { ($cond:expr) => { if !($cond) { return 0xff; } - } + }; } unsafe fn compare_c_str(ptr: *const c_char, val: &str) -> bool { @@ -59,13 +59,11 @@ pub unsafe extern "C" fn check_list_copy_0(mut ap: VaList) -> usize { continue_if!(ap.arg::() == 16); continue_if!(ap.arg::() == 'A' as c_char); continue_if!(compare_c_str(ap.arg::<*const c_char>(), "Skip Me!")); - ap.with_copy(|mut ap| { - if compare_c_str(ap.arg::<*const c_char>(), "Correct") { - 0 - } else { - 0xff - } - }) + ap.with_copy( + |mut ap| { + if compare_c_str(ap.arg::<*const c_char>(), "Correct") { 0 } else { 0xff } + }, + ) } #[no_mangle] diff --git a/tests/run-make/compiler-lookup-paths-2/c.rs b/tests/run-make/compiler-lookup-paths-2/c.rs index e37bc2e1dcef..1326edb575ed 100644 --- a/tests/run-make/compiler-lookup-paths-2/c.rs +++ b/tests/run-make/compiler-lookup-paths-2/c.rs @@ -1,3 +1,3 @@ #![crate_type = "lib"] -extern crate b; extern crate a; +extern crate b; diff --git a/tests/run-make/crate-data-smoke/rmake.rs b/tests/run-make/crate-data-smoke/rmake.rs index 80d43903a532..86fe5593e661 100644 --- a/tests/run-make/crate-data-smoke/rmake.rs +++ b/tests/run-make/crate-data-smoke/rmake.rs @@ -3,41 +3,20 @@ use std::process::Output; use run_make_support::{bin_name, rust_lib_name, rustc}; fn compare_stdout>(output: Output, expected: S) { - assert_eq!( - String::from_utf8(output.stdout).unwrap().trim(), - expected.as_ref() - ); + assert_eq!(String::from_utf8(output.stdout).unwrap().trim(), expected.as_ref()); } fn main() { compare_stdout(rustc().print("crate-name").input("crate.rs").run(), "foo"); + compare_stdout(rustc().print("file-names").input("crate.rs").run(), bin_name("foo")); compare_stdout( - rustc().print("file-names").input("crate.rs").run(), + rustc().print("file-names").crate_type("lib").arg("--test").input("crate.rs").run(), bin_name("foo"), ); compare_stdout( - rustc() - .print("file-names") - .crate_type("lib") - .arg("--test") - .input("crate.rs") - .run(), - bin_name("foo"), - ); - compare_stdout( - rustc() - .print("file-names") - .arg("--test") - .input("lib.rs") - .run(), + rustc().print("file-names").arg("--test").input("lib.rs").run(), bin_name("mylib"), ); - compare_stdout( - rustc().print("file-names").input("lib.rs").run(), - rust_lib_name("mylib"), - ); - compare_stdout( - rustc().print("file-names").input("rlib.rs").run(), - rust_lib_name("mylib"), - ); + compare_stdout(rustc().print("file-names").input("lib.rs").run(), rust_lib_name("mylib")); + compare_stdout(rustc().print("file-names").input("rlib.rs").run(), rust_lib_name("mylib")); } diff --git a/tests/run-make/cross-lang-lto-clang/rustlib.rs b/tests/run-make/cross-lang-lto-clang/rustlib.rs index 8a74d74a420b..9aff29ef9bb6 100644 --- a/tests/run-make/cross-lang-lto-clang/rustlib.rs +++ b/tests/run-make/cross-lang-lto-clang/rustlib.rs @@ -1,4 +1,4 @@ -#![crate_type="staticlib"] +#![crate_type = "staticlib"] #[no_mangle] pub extern "C" fn rust_always_inlined() -> u32 { diff --git a/tests/run-make/cross-lang-lto-pgo-smoketest/rustlib.rs b/tests/run-make/cross-lang-lto-pgo-smoketest/rustlib.rs index 8a74d74a420b..9aff29ef9bb6 100644 --- a/tests/run-make/cross-lang-lto-pgo-smoketest/rustlib.rs +++ b/tests/run-make/cross-lang-lto-pgo-smoketest/rustlib.rs @@ -1,4 +1,4 @@ -#![crate_type="staticlib"] +#![crate_type = "staticlib"] #[no_mangle] pub extern "C" fn rust_always_inlined() -> u32 { diff --git a/tests/run-make/cross-lang-lto-upstream-rlibs/staticlib.rs b/tests/run-make/cross-lang-lto-upstream-rlibs/staticlib.rs index 34951dda3b6e..76c24df78987 100644 --- a/tests/run-make/cross-lang-lto-upstream-rlibs/staticlib.rs +++ b/tests/run-make/cross-lang-lto-upstream-rlibs/staticlib.rs @@ -1,4 +1,4 @@ -#![crate_type="staticlib"] +#![crate_type = "staticlib"] extern crate upstream; diff --git a/tests/run-make/debug-assertions/debug.rs b/tests/run-make/debug-assertions/debug.rs index 76ca60a71c88..9eebf60ded09 100644 --- a/tests/run-make/debug-assertions/debug.rs +++ b/tests/run-make/debug-assertions/debug.rs @@ -15,19 +15,33 @@ fn main() { fn debug_assert_eq() { let mut hit1 = false; let mut hit2 = false; - debug_assert_eq!({ hit1 = true; 1 }, { hit2 = true; 2 }); + debug_assert_eq!( + { + hit1 = true; + 1 + }, + { + hit2 = true; + 2 + } + ); assert!(!hit1); assert!(!hit2); } fn debug_assert() { let mut hit = false; - debug_assert!({ hit = true; false }); + debug_assert!({ + hit = true; + false + }); assert!(!hit); } fn overflow() { - fn add(a: u8, b: u8) -> u8 { a + b } + fn add(a: u8, b: u8) -> u8 { + a + b + } add(200u8, 200u8); } diff --git a/tests/run-make/dep-info-spaces/lib.rs b/tests/run-make/dep-info-spaces/lib.rs index 6264e7b67ec6..4e061892cf7a 100644 --- a/tests/run-make/dep-info-spaces/lib.rs +++ b/tests/run-make/dep-info-spaces/lib.rs @@ -1,4 +1,4 @@ -#[path="foo foo.rs"] +#[path = "foo foo.rs"] pub mod foo; pub mod bar; diff --git a/tests/run-make/dep-info/lib.rs b/tests/run-make/dep-info/lib.rs index eb8631259d43..6e2781cd4b20 100644 --- a/tests/run-make/dep-info/lib.rs +++ b/tests/run-make/dep-info/lib.rs @@ -1,4 +1,4 @@ #![crate_name = "foo"] -pub mod foo; pub mod bar; +pub mod foo; diff --git a/tests/run-make/deref-impl-rustdoc-ice/baz.rs b/tests/run-make/deref-impl-rustdoc-ice/baz.rs index cd2425f9b692..f606ef9bd6b6 100644 --- a/tests/run-make/deref-impl-rustdoc-ice/baz.rs +++ b/tests/run-make/deref-impl-rustdoc-ice/baz.rs @@ -1,8 +1,10 @@ -extern crate foo; extern crate bar; +extern crate foo; pub struct Bar; impl ::std::ops::Deref for Bar { type Target = bar::S; - fn deref(&self) -> &Self::Target { unimplemented!() } + fn deref(&self) -> &Self::Target { + unimplemented!() + } } diff --git a/tests/run-make/deref-impl-rustdoc-ice/foo.rs b/tests/run-make/deref-impl-rustdoc-ice/foo.rs index a106e4fde5cc..df00ed4b9e0b 100644 --- a/tests/run-make/deref-impl-rustdoc-ice/foo.rs +++ b/tests/run-make/deref-impl-rustdoc-ice/foo.rs @@ -3,7 +3,9 @@ extern crate proc_macro; #[proc_macro_derive(A)] -pub fn derive(ts: proc_macro::TokenStream) -> proc_macro::TokenStream { ts } +pub fn derive(ts: proc_macro::TokenStream) -> proc_macro::TokenStream { + ts +} #[derive(Debug)] struct S; diff --git a/tests/run-make/dylib-chain/m2.rs b/tests/run-make/dylib-chain/m2.rs index 62176ddc9f35..92950a919154 100644 --- a/tests/run-make/dylib-chain/m2.rs +++ b/tests/run-make/dylib-chain/m2.rs @@ -1,4 +1,6 @@ #![crate_type = "dylib"] extern crate m1; -pub fn m2() { m1::m1() } +pub fn m2() { + m1::m1() +} diff --git a/tests/run-make/dylib-chain/m3.rs b/tests/run-make/dylib-chain/m3.rs index d213aeda9ac1..28a8ca9d7dde 100644 --- a/tests/run-make/dylib-chain/m3.rs +++ b/tests/run-make/dylib-chain/m3.rs @@ -1,4 +1,6 @@ #![crate_type = "dylib"] extern crate m2; -pub fn m3() { m2::m2() } +pub fn m3() { + m2::m2() +} diff --git a/tests/run-make/dylib-chain/m4.rs b/tests/run-make/dylib-chain/m4.rs index fa8ec6079dea..c732512af9fc 100644 --- a/tests/run-make/dylib-chain/m4.rs +++ b/tests/run-make/dylib-chain/m4.rs @@ -1,3 +1,5 @@ extern crate m3; -fn main() { m3::m3() } +fn main() { + m3::m3() +} diff --git a/tests/run-make/emit/test-26235.rs b/tests/run-make/emit/test-26235.rs index 07d975f3317c..d91c46d2dec8 100644 --- a/tests/run-make/emit/test-26235.rs +++ b/tests/run-make/emit/test-26235.rs @@ -6,16 +6,22 @@ fn main() { type Key = u32; const NUM_THREADS: usize = 2; - #[derive(Clone,Copy)] + #[derive(Clone, Copy)] struct Stats { upsert: S, delete: S, insert: S, - update: S + update: S, }; - impl Stats where S: Copy { - fn dot(self, s: Stats, f: F) -> Stats where F: Fn(S, T) -> B { + impl Stats + where + S: Copy, + { + fn dot(self, s: Stats, f: F) -> Stats + where + F: Fn(S, T) -> B, + { let Stats { upsert: u1, delete: d1, insert: i1, update: p1 } = self; let Stats { upsert: u2, delete: d2, insert: i2, update: p2 } = s; Stats { upsert: f(u1, u2), delete: f(d1, d2), insert: f(i1, i2), update: f(p1, p2) } @@ -38,9 +44,12 @@ fn main() { make_threads(); { - let Stats { ref upsert, ref delete, ref insert, ref update } = stats.iter().fold( - Stats::new(0), |res, &s| res.dot(s, |x: Key, y: Key| x.wrapping_add(y))); - println!("upserts: {}, deletes: {}, inserts: {}, updates: {}", - upsert, delete, insert, update); + let Stats { ref upsert, ref delete, ref insert, ref update } = stats + .iter() + .fold(Stats::new(0), |res, &s| res.dot(s, |x: Key, y: Key| x.wrapping_add(y))); + println!( + "upserts: {}, deletes: {}, inserts: {}, updates: {}", + upsert, delete, insert, update + ); } } diff --git a/tests/run-make/extern-diff-internal-name/test.rs b/tests/run-make/extern-diff-internal-name/test.rs index 4c53dc28a80e..d210f8833165 100644 --- a/tests/run-make/extern-diff-internal-name/test.rs +++ b/tests/run-make/extern-diff-internal-name/test.rs @@ -1,5 +1,4 @@ #[macro_use] extern crate foo; -fn main() { -} +fn main() {} diff --git a/tests/run-make/extern-flag-disambiguates/a.rs b/tests/run-make/extern-flag-disambiguates/a.rs index 2b1a3190150f..fe4bb5ccac40 100644 --- a/tests/run-make/extern-flag-disambiguates/a.rs +++ b/tests/run-make/extern-flag-disambiguates/a.rs @@ -3,4 +3,6 @@ static FOO: usize = 3; -pub fn token() -> &'static usize { &FOO } +pub fn token() -> &'static usize { + &FOO +} diff --git a/tests/run-make/extern-flag-disambiguates/b.rs b/tests/run-make/extern-flag-disambiguates/b.rs index 1d7a7339ce27..fc3303e5ef8a 100644 --- a/tests/run-make/extern-flag-disambiguates/b.rs +++ b/tests/run-make/extern-flag-disambiguates/b.rs @@ -5,5 +5,9 @@ extern crate a; static FOO: usize = 3; -pub fn token() -> &'static usize { &FOO } -pub fn a_token() -> &'static usize { a::token() } +pub fn token() -> &'static usize { + &FOO +} +pub fn a_token() -> &'static usize { + a::token() +} diff --git a/tests/run-make/extern-flag-disambiguates/c.rs b/tests/run-make/extern-flag-disambiguates/c.rs index 3f9d143ed2dc..26ac787e74d1 100644 --- a/tests/run-make/extern-flag-disambiguates/c.rs +++ b/tests/run-make/extern-flag-disambiguates/c.rs @@ -5,5 +5,9 @@ extern crate a; static FOO: usize = 3; -pub fn token() -> &'static usize { &FOO } -pub fn a_token() -> &'static usize { a::token() } +pub fn token() -> &'static usize { + &FOO +} +pub fn a_token() -> &'static usize { + a::token() +} diff --git a/tests/run-make/extern-flag-disambiguates/d.rs b/tests/run-make/extern-flag-disambiguates/d.rs index 249c6a107ff3..f0ab2b063e11 100644 --- a/tests/run-make/extern-flag-disambiguates/d.rs +++ b/tests/run-make/extern-flag-disambiguates/d.rs @@ -1,9 +1,13 @@ -#[cfg(before)] extern crate a; +#[cfg(before)] +extern crate a; +#[cfg(after)] +extern crate a; extern crate b; extern crate c; -#[cfg(after)] extern crate a; -fn t(a: &'static usize) -> usize { a as *const _ as usize } +fn t(a: &'static usize) -> usize { + a as *const _ as usize +} fn main() { assert_eq!(t(a::token()), t(b::a_token())); diff --git a/tests/run-make/extern-fn-explicit-align/test.rs b/tests/run-make/extern-fn-explicit-align/test.rs index 846622de3cd1..81991b5919ce 100644 --- a/tests/run-make/extern-fn-explicit-align/test.rs +++ b/tests/run-make/extern-fn-explicit-align/test.rs @@ -1,6 +1,6 @@ // Issue #80127: Passing structs via FFI should work with explicit alignment. -use std::ffi::{CStr, c_char}; +use std::ffi::{c_char, CStr}; use std::ptr::null_mut; #[repr(C)] @@ -18,7 +18,7 @@ pub struct TwoU64s { #[repr(C)] pub struct WrappedU64s { - pub a: TwoU64s + pub a: TwoU64s, } #[repr(C)] diff --git a/tests/run-make/extern-fn-reachable/dylib.rs b/tests/run-make/extern-fn-reachable/dylib.rs index cd0179348705..fe0c7023b27b 100644 --- a/tests/run-make/extern-fn-reachable/dylib.rs +++ b/tests/run-make/extern-fn-reachable/dylib.rs @@ -1,14 +1,19 @@ #![crate_type = "dylib"] #![allow(dead_code)] -#[no_mangle] pub extern "C" fn fun1() {} -#[no_mangle] extern "C" fn fun2() {} +#[no_mangle] +pub extern "C" fn fun1() {} +#[no_mangle] +extern "C" fn fun2() {} mod foo { - #[no_mangle] pub extern "C" fn fun3() {} + #[no_mangle] + pub extern "C" fn fun3() {} } pub mod bar { - #[no_mangle] pub extern "C" fn fun4() {} + #[no_mangle] + pub extern "C" fn fun4() {} } -#[no_mangle] pub fn fun5() {} +#[no_mangle] +pub fn fun5() {} diff --git a/tests/run-make/extern-fn-struct-passing-abi/test.rs b/tests/run-make/extern-fn-struct-passing-abi/test.rs index 99e079f98a87..f898592fce98 100644 --- a/tests/run-make/extern-fn-struct-passing-abi/test.rs +++ b/tests/run-make/extern-fn-struct-passing-abi/test.rs @@ -90,8 +90,12 @@ extern "C" { fn byval_rect_with_many_huge(a: Huge, b: Huge, c: Huge, d: Huge, e: Huge, f: Huge, g: Rect); fn byval_rect_with_many_huge64( - a: Huge64, b: Huge64, c: Huge64, - d: Huge64, e: Huge64, f: Huge64, + a: Huge64, + b: Huge64, + c: Huge64, + d: Huge64, + e: Huge64, + f: Huge64, g: Rect, ); diff --git a/tests/run-make/extern-multiple-copies/bar.rs b/tests/run-make/extern-multiple-copies/bar.rs index c6b3595f6775..aa0bee77cb29 100644 --- a/tests/run-make/extern-multiple-copies/bar.rs +++ b/tests/run-make/extern-multiple-copies/bar.rs @@ -1,5 +1,5 @@ -extern crate foo2; // foo2 first to exhibit the bug extern crate foo1; +extern crate foo2; // foo2 first to exhibit the bug fn main() { /* ... */ diff --git a/tests/run-make/external-crate-panic-handle-no-lint/app.rs b/tests/run-make/external-crate-panic-handle-no-lint/app.rs index 8127b9578bfe..e0168579ccab 100644 --- a/tests/run-make/external-crate-panic-handle-no-lint/app.rs +++ b/tests/run-make/external-crate-panic-handle-no-lint/app.rs @@ -1,7 +1,6 @@ #![crate_type = "bin"] #![no_main] #![no_std] - #![deny(unused_extern_crates)] // `panic` provides a `panic_handler` so it shouldn't trip the `unused_extern_crates` lint diff --git a/tests/run-make/incr-prev-body-beyond-eof/a.rs b/tests/run-make/incr-prev-body-beyond-eof/a.rs index ca70fb563349..59ac25444000 100644 --- a/tests/run-make/incr-prev-body-beyond-eof/a.rs +++ b/tests/run-make/incr-prev-body-beyond-eof/a.rs @@ -9,8 +9,4 @@ fn main() { // Basically, avoid modifying this file, including adding or removing whitespace! fn foo() { assert_eq!(1, 1); - - - - } diff --git a/tests/run-make/incr-prev-body-beyond-eof/b.rs b/tests/run-make/incr-prev-body-beyond-eof/b.rs index a272e44a6326..2f26a1ffe97a 100644 --- a/tests/run-make/incr-prev-body-beyond-eof/b.rs +++ b/tests/run-make/incr-prev-body-beyond-eof/b.rs @@ -8,5 +8,5 @@ fn main() { // a.rs, the body must end on a line number which does not exist in b.rs. // Basically, avoid modifying this file, including adding or removing whitespace! fn foo() { - assert_eq!(1, 1);//// + assert_eq!(1, 1); //// } diff --git a/tests/run-make/inline-always-many-cgu/foo.rs b/tests/run-make/inline-always-many-cgu/foo.rs index 65fe69c16fe7..b7c5371ea49c 100644 --- a/tests/run-make/inline-always-many-cgu/foo.rs +++ b/tests/run-make/inline-always-many-cgu/foo.rs @@ -2,11 +2,9 @@ pub mod a { #[inline(always)] - pub fn foo() { - } + pub fn foo() {} - pub fn bar() { - } + pub fn bar() {} } #[no_mangle] diff --git a/tests/run-make/interdependent-c-libraries/main.rs b/tests/run-make/interdependent-c-libraries/main.rs index 2aba427df474..a429030d3a2b 100644 --- a/tests/run-make/interdependent-c-libraries/main.rs +++ b/tests/run-make/interdependent-c-libraries/main.rs @@ -1,5 +1,5 @@ -extern crate foo; extern crate bar; +extern crate foo; fn main() { bar::doit(); diff --git a/tests/run-make/intrinsic-unreachable/exit-ret.rs b/tests/run-make/intrinsic-unreachable/exit-ret.rs index c8ba5b4599f2..3653316b5c67 100644 --- a/tests/run-make/intrinsic-unreachable/exit-ret.rs +++ b/tests/run-make/intrinsic-unreachable/exit-ret.rs @@ -1,4 +1,4 @@ -#![crate_type="lib"] +#![crate_type = "lib"] use std::arch::asm; #[deny(unreachable_code)] diff --git a/tests/run-make/intrinsic-unreachable/exit-unreachable.rs b/tests/run-make/intrinsic-unreachable/exit-unreachable.rs index 75f893eb2df1..d0f193d49eef 100644 --- a/tests/run-make/intrinsic-unreachable/exit-unreachable.rs +++ b/tests/run-make/intrinsic-unreachable/exit-unreachable.rs @@ -1,5 +1,5 @@ #![feature(core_intrinsics)] -#![crate_type="lib"] +#![crate_type = "lib"] use std::arch::asm; use std::intrinsics; diff --git a/tests/run-make/issue-18943/foo.rs b/tests/run-make/issue-18943/foo.rs index d18400dd3a54..54daec8dd1ea 100644 --- a/tests/run-make/issue-18943/foo.rs +++ b/tests/run-make/issue-18943/foo.rs @@ -1,5 +1,5 @@ -trait Foo { } +trait Foo {} -trait Bar { } +trait Bar {} -impl<'a> Foo for Bar + 'a { } +impl<'a> Foo for Bar + 'a {} diff --git a/tests/run-make/issue-20626/foo.rs b/tests/run-make/issue-20626/foo.rs index a474e234e72d..1007686d9fe1 100644 --- a/tests/run-make/issue-20626/foo.rs +++ b/tests/run-make/issue-20626/foo.rs @@ -1,4 +1,6 @@ -fn identity(a: &u32) -> &u32 { a } +fn identity(a: &u32) -> &u32 { + a +} fn print_foo(f: &fn(&u32) -> &u32, x: &u32) { print!("{}", (*f)(x)); diff --git a/tests/run-make/issue-22131/foo.rs b/tests/run-make/issue-22131/foo.rs index 33255d76879f..7b955a07b979 100644 --- a/tests/run-make/issue-22131/foo.rs +++ b/tests/run-make/issue-22131/foo.rs @@ -2,4 +2,6 @@ /// assert_eq!(foo::foo(), 1); /// ``` #[cfg(feature = "bar")] -pub fn foo() -> i32 { 1 } +pub fn foo() -> i32 { + 1 +} diff --git a/tests/run-make/issue-26006/in/libc/lib.rs b/tests/run-make/issue-26006/in/libc/lib.rs index 23f2bf51800a..bad155a99bd6 100644 --- a/tests/run-make/issue-26006/in/libc/lib.rs +++ b/tests/run-make/issue-26006/in/libc/lib.rs @@ -1,3 +1,3 @@ -#![crate_type="rlib"] +#![crate_type = "rlib"] -pub fn something(){} +pub fn something() {} diff --git a/tests/run-make/issue-26006/in/time/lib.rs b/tests/run-make/issue-26006/in/time/lib.rs index 87f2f824a366..51ed27cd713f 100644 --- a/tests/run-make/issue-26006/in/time/lib.rs +++ b/tests/run-make/issue-26006/in/time/lib.rs @@ -1,4 +1,4 @@ #![feature(rustc_private)] extern crate libc; -fn main(){} +fn main() {} diff --git a/tests/run-make/issue-37839/b.rs b/tests/run-make/issue-37839/b.rs index 355d2b165274..067f47c1b7a1 100644 --- a/tests/run-make/issue-37839/b.rs +++ b/tests/run-make/issue-37839/b.rs @@ -1,2 +1,3 @@ #![crate_type = "lib"] -#[macro_use] extern crate a; +#[macro_use] +extern crate a; diff --git a/tests/run-make/issue-47551/eh_frame-terminator.rs b/tests/run-make/issue-47551/eh_frame-terminator.rs index 35db4bc7d1f7..0c90d8c791c7 100644 --- a/tests/run-make/issue-47551/eh_frame-terminator.rs +++ b/tests/run-make/issue-47551/eh_frame-terminator.rs @@ -7,9 +7,7 @@ struct Foo { impl Foo { const fn new() -> Self { - Self { - array: [0x1122_3344_5566_7788; 10240] - } + Self { array: [0x1122_3344_5566_7788; 10240] } } } diff --git a/tests/run-make/issue-69368/c.rs b/tests/run-make/issue-69368/c.rs index 729c4249a053..9d72657aa593 100644 --- a/tests/run-make/issue-69368/c.rs +++ b/tests/run-make/issue-69368/c.rs @@ -2,8 +2,8 @@ #![feature(start)] #![no_std] -extern crate alloc; extern crate a; +extern crate alloc; extern crate b; use alloc::vec::Vec; diff --git a/tests/run-make/link-arg/empty.rs b/tests/run-make/link-arg/empty.rs index 45590d86ba6c..f328e4d9d04c 100644 --- a/tests/run-make/link-arg/empty.rs +++ b/tests/run-make/link-arg/empty.rs @@ -1 +1 @@ -fn main() { } +fn main() {} diff --git a/tests/run-make/long-linker-command-lines-cmd-exe/foo.rs b/tests/run-make/long-linker-command-lines-cmd-exe/foo.rs index 74d7b9b07f69..1d5202dcdb49 100644 --- a/tests/run-make/long-linker-command-lines-cmd-exe/foo.rs +++ b/tests/run-make/long-linker-command-lines-cmd-exe/foo.rs @@ -13,13 +13,13 @@ use std::env; use std::fs::{self, File}; -use std::io::{BufWriter, Write, Read}; +use std::io::{BufWriter, Read, Write}; use std::path::PathBuf; use std::process::Command; fn main() { if !cfg!(windows) { - return + return; } let tmpdir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); @@ -31,16 +31,16 @@ fn main() { let file = file.to_str().unwrap(); fs::copy(&file[1..], &ok).unwrap(); } - None => { File::create(¬_ok).unwrap(); } + None => { + File::create(¬_ok).unwrap(); + } } - return + return; } let rustc = env::var_os("RUSTC").unwrap_or("rustc".into()); let me = env::current_exe().unwrap(); - let bat = me.parent() - .unwrap() - .join("foo.bat"); + let bat = me.parent().unwrap().join("foo.bat"); let bat_linker = format!("linker={}", bat.display()); for i in (1..).map(|i| i * 10) { println!("attempt: {}", i); @@ -61,8 +61,10 @@ fn main() { drop(fs::remove_file(¬_ok)); let status = Command::new(&rustc) .arg(&file) - .arg("-C").arg(&bat_linker) - .arg("--out-dir").arg(&tmpdir) + .arg("-C") + .arg(&bat_linker) + .arg("--out-dir") + .arg(&tmpdir) .env("YOU_ARE_A_LINKER", "1") .env("MY_LINKER", &me) .status() @@ -74,7 +76,7 @@ fn main() { if !ok.exists() { assert!(not_ok.exists()); - continue + continue; } let mut contents = Vec::new(); @@ -96,6 +98,6 @@ fn main() { assert!(contents.windows(exp.len()).any(|w| w == &exp[..])); } - break + break; } } diff --git a/tests/run-make/long-linker-command-lines/foo.rs b/tests/run-make/long-linker-command-lines/foo.rs index db238c0cf1a9..9d4a701ad876 100644 --- a/tests/run-make/long-linker-command-lines/foo.rs +++ b/tests/run-make/long-linker-command-lines/foo.rs @@ -34,9 +34,7 @@ fn write_test_case(file: &Path, n: usize) -> HashSet { fn read_linker_args(path: &Path) -> String { let contents = fs::read(path).unwrap(); if cfg!(target_env = "msvc") { - let mut i = contents.chunks(2).map(|c| { - c[0] as u16 | ((c[1] as u16) << 8) - }); + let mut i = contents.chunks(2).map(|c| c[0] as u16 | ((c[1] as u16) << 8)); assert_eq!(i.next(), Some(0xfeff), "Expected UTF-16 BOM"); String::from_utf16(&i.collect::>()).unwrap() } else { @@ -52,7 +50,7 @@ fn main() { let file = file.to_str().expect("non-utf8 file argument"); fs::copy(&file[1..], &ok).unwrap(); } - return + return; } let rustc = env::var_os("RUSTC").unwrap_or("rustc".into()); @@ -65,28 +63,35 @@ fn main() { drop(fs::remove_file(&ok)); let output = Command::new(&rustc) .arg(&file) - .arg("-C").arg(&me_as_linker) - .arg("--out-dir").arg(&tmpdir) + .arg("-C") + .arg(&me_as_linker) + .arg("--out-dir") + .arg(&tmpdir) .env("YOU_ARE_A_LINKER", "1") .output() .unwrap(); if !output.status.success() { let stderr = String::from_utf8_lossy(&output.stderr); - panic!("status: {}\nstdout:\n{}\nstderr:\n{}", - output.status, - String::from_utf8_lossy(&output.stdout), - stderr.lines().map(|l| { - if l.len() > 200 { - format!("{}...\n", &l[..200]) - } else { - format!("{}\n", l) - } - }).collect::()); + panic!( + "status: {}\nstdout:\n{}\nstderr:\n{}", + output.status, + String::from_utf8_lossy(&output.stdout), + stderr + .lines() + .map(|l| { + if l.len() > 200 { + format!("{}...\n", &l[..200]) + } else { + format!("{}\n", l) + } + }) + .collect::() + ); } if !ok.exists() { - continue + continue; } let linker_args = read_linker_args(&ok); @@ -101,6 +106,6 @@ fn main() { linker_args, ); - break + break; } } diff --git a/tests/run-make/many-crates-but-no-match/crateA1.rs b/tests/run-make/many-crates-but-no-match/crateA1.rs index 3fed5a38e2ca..f3025909b7de 100644 --- a/tests/run-make/many-crates-but-no-match/crateA1.rs +++ b/tests/run-make/many-crates-but-no-match/crateA1.rs @@ -1,4 +1,4 @@ -#![crate_name="crateA"] +#![crate_name = "crateA"] // Base crate pub fn func() {} diff --git a/tests/run-make/many-crates-but-no-match/crateA2.rs b/tests/run-make/many-crates-but-no-match/crateA2.rs index 8db07a015ff2..ff9f9d4d300b 100644 --- a/tests/run-make/many-crates-but-no-match/crateA2.rs +++ b/tests/run-make/many-crates-but-no-match/crateA2.rs @@ -1,4 +1,6 @@ -#![crate_name="crateA"] +#![crate_name = "crateA"] // Base crate -pub fn func() { println!("hello"); } +pub fn func() { + println!("hello"); +} diff --git a/tests/run-make/many-crates-but-no-match/crateA3.rs b/tests/run-make/many-crates-but-no-match/crateA3.rs index a1e8e40a38c2..dddf7f728eed 100644 --- a/tests/run-make/many-crates-but-no-match/crateA3.rs +++ b/tests/run-make/many-crates-but-no-match/crateA3.rs @@ -1,4 +1,6 @@ -#![crate_name="crateA"] +#![crate_name = "crateA"] // Base crate -pub fn foo() { println!("world!"); } +pub fn foo() { + println!("world!"); +} diff --git a/tests/run-make/metadata-flag-frobs-symbols/foo.rs b/tests/run-make/metadata-flag-frobs-symbols/foo.rs index 696aed2fa1db..cdc8433d8a40 100644 --- a/tests/run-make/metadata-flag-frobs-symbols/foo.rs +++ b/tests/run-make/metadata-flag-frobs-symbols/foo.rs @@ -3,4 +3,6 @@ static FOO: usize = 3; -pub fn foo() -> &'static usize { &FOO } +pub fn foo() -> &'static usize { + &FOO +} diff --git a/tests/run-make/mixing-deps/dylib.rs b/tests/run-make/mixing-deps/dylib.rs index 88976d5b663f..f3dd134249db 100644 --- a/tests/run-make/mixing-deps/dylib.rs +++ b/tests/run-make/mixing-deps/dylib.rs @@ -3,4 +3,6 @@ extern crate both; use std::mem; -pub fn addr() -> usize { unsafe { mem::transmute(&both::foo) } } +pub fn addr() -> usize { + unsafe { mem::transmute(&both::foo) } +} diff --git a/tests/run-make/mixing-deps/prog.rs b/tests/run-make/mixing-deps/prog.rs index 188981dc1a31..1e52ee16982d 100644 --- a/tests/run-make/mixing-deps/prog.rs +++ b/tests/run-make/mixing-deps/prog.rs @@ -1,9 +1,8 @@ -extern crate dylib; extern crate both; +extern crate dylib; use std::mem; fn main() { - assert_eq!(unsafe { mem::transmute::<&isize, usize>(&both::foo) }, - dylib::addr()); + assert_eq!(unsafe { mem::transmute::<&isize, usize>(&both::foo) }, dylib::addr()); } diff --git a/tests/run-make/mixing-libs/dylib.rs b/tests/run-make/mixing-libs/dylib.rs index 6856887501c2..cde5cc139ba6 100644 --- a/tests/run-make/mixing-libs/dylib.rs +++ b/tests/run-make/mixing-libs/dylib.rs @@ -1,4 +1,6 @@ #![crate_type = "dylib"] extern crate rlib; -pub fn dylib() { rlib::rlib() } +pub fn dylib() { + rlib::rlib() +} diff --git a/tests/run-make/native-link-modifier-whole-archive/native_lib_in_src.rs b/tests/run-make/native-link-modifier-whole-archive/native_lib_in_src.rs index 971f3be7a61e..d5bc0c3eb697 100644 --- a/tests/run-make/native-link-modifier-whole-archive/native_lib_in_src.rs +++ b/tests/run-make/native-link-modifier-whole-archive/native_lib_in_src.rs @@ -1,9 +1,11 @@ use std::io::Write; -#[link(name = "c_static_lib_with_constructor", - kind = "static", - modifiers = "-bundle,+whole-archive")] -extern {} +#[link( + name = "c_static_lib_with_constructor", + kind = "static", + modifiers = "-bundle,+whole-archive" +)] +extern "C" {} pub fn hello() { print!("native_lib_in_src."); diff --git a/tests/run-make/non-pie-thread-local/foo.rs b/tests/run-make/non-pie-thread-local/foo.rs index b67f3847cd49..30d2537750d7 100644 --- a/tests/run-make/non-pie-thread-local/foo.rs +++ b/tests/run-make/non-pie-thread-local/foo.rs @@ -2,7 +2,9 @@ struct Destroy; impl Drop for Destroy { - fn drop(&mut self) { println!("drop"); } + fn drop(&mut self) { + println!("drop"); + } } thread_local! { diff --git a/tests/run-make/pass-non-c-like-enum-to-c/nonclike.rs b/tests/run-make/pass-non-c-like-enum-to-c/nonclike.rs index 517286a868d8..7b5c620b3381 100644 --- a/tests/run-make/pass-non-c-like-enum-to-c/nonclike.rs +++ b/tests/run-make/pass-non-c-like-enum-to-c/nonclike.rs @@ -4,7 +4,7 @@ pub enum TT { BB, } -#[repr(C,u8)] +#[repr(C, u8)] pub enum T { A(u64), B, @@ -16,6 +16,6 @@ extern "C" { } fn main() { - assert_eq!(33, unsafe { tt_add(TT::AA(1,2), TT::AA(10,20)) }); + assert_eq!(33, unsafe { tt_add(TT::AA(1, 2), TT::AA(10, 20)) }); assert_eq!(11, unsafe { t_add(T::A(1), T::A(10)) }); } diff --git a/tests/run-make/pdb-buildinfo-cl-cmd/main.rs b/tests/run-make/pdb-buildinfo-cl-cmd/main.rs index f79c691f0853..f328e4d9d04c 100644 --- a/tests/run-make/pdb-buildinfo-cl-cmd/main.rs +++ b/tests/run-make/pdb-buildinfo-cl-cmd/main.rs @@ -1,2 +1 @@ -fn main() { -} +fn main() {} diff --git a/tests/run-make/pgo-branch-weights/interesting.rs b/tests/run-make/pgo-branch-weights/interesting.rs index a26d6fd69d14..7066496f4beb 100644 --- a/tests/run-make/pgo-branch-weights/interesting.rs +++ b/tests/run-make/pgo-branch-weights/interesting.rs @@ -1,5 +1,5 @@ -#![crate_name="interesting"] -#![crate_type="rlib"] +#![crate_name = "interesting"] +#![crate_type = "rlib"] extern crate opaque; @@ -22,7 +22,6 @@ pub fn function_called_42_times(c: char) { // This branch is taken 12 times opaque::f1(); } else { - if c == 'b' { // This branch is taken 28 times opaque::f2(); diff --git a/tests/run-make/pgo-branch-weights/opaque.rs b/tests/run-make/pgo-branch-weights/opaque.rs index 72f93c9feab6..39dedf0f7bf5 100644 --- a/tests/run-make/pgo-branch-weights/opaque.rs +++ b/tests/run-make/pgo-branch-weights/opaque.rs @@ -1,5 +1,5 @@ -#![crate_name="opaque"] -#![crate_type="rlib"] +#![crate_name = "opaque"] +#![crate_type = "rlib"] pub fn f1() {} pub fn f2() {} diff --git a/tests/run-make/pgo-indirect-call-promotion/interesting.rs b/tests/run-make/pgo-indirect-call-promotion/interesting.rs index 4fd096d626de..398017f9611b 100644 --- a/tests/run-make/pgo-indirect-call-promotion/interesting.rs +++ b/tests/run-make/pgo-indirect-call-promotion/interesting.rs @@ -1,5 +1,5 @@ -#![crate_name="interesting"] -#![crate_type="rlib"] +#![crate_name = "interesting"] +#![crate_type = "rlib"] extern crate opaque; @@ -15,7 +15,6 @@ pub fn function_called_never() { #[no_mangle] pub fn call_a_bunch_of_functions(fns: &[fn()]) { - // Indirect call promotion transforms the below into something like // // for f in fns { @@ -33,13 +32,11 @@ pub fn call_a_bunch_of_functions(fns: &[fn()]) { } } - pub trait Foo { fn foo(&self); } impl Foo for u32 { - #[no_mangle] fn foo(&self) { opaque::opaque_f2(); @@ -48,7 +45,6 @@ impl Foo for u32 { #[no_mangle] pub fn call_a_bunch_of_trait_methods(trait_objects: &[&dyn Foo]) { - // Same as above, just with vtables in between for x in trait_objects { x.foo(); diff --git a/tests/run-make/pgo-indirect-call-promotion/main.rs b/tests/run-make/pgo-indirect-call-promotion/main.rs index 27181f30710b..604f1f748737 100644 --- a/tests/run-make/pgo-indirect-call-promotion/main.rs +++ b/tests/run-make/pgo-indirect-call-promotion/main.rs @@ -2,9 +2,8 @@ extern crate interesting; fn main() { // function pointer case - let fns: Vec<_> = std::iter::repeat(interesting::function_called_always as fn()) - .take(1000) - .collect(); + let fns: Vec<_> = + std::iter::repeat(interesting::function_called_always as fn()).take(1000).collect(); interesting::call_a_bunch_of_functions(&fns[..]); // Trait object case diff --git a/tests/run-make/pgo-indirect-call-promotion/opaque.rs b/tests/run-make/pgo-indirect-call-promotion/opaque.rs index 9628d711c505..d7b2e810bed1 100644 --- a/tests/run-make/pgo-indirect-call-promotion/opaque.rs +++ b/tests/run-make/pgo-indirect-call-promotion/opaque.rs @@ -1,5 +1,5 @@ -#![crate_name="opaque"] -#![crate_type="rlib"] +#![crate_name = "opaque"] +#![crate_type = "rlib"] #[no_mangle] pub fn opaque_f1() {} diff --git a/tests/run-make/pgo-use/main.rs b/tests/run-make/pgo-use/main.rs index eb9192c87e6f..6150cff4d63a 100644 --- a/tests/run-make/pgo-use/main.rs +++ b/tests/run-make/pgo-use/main.rs @@ -11,7 +11,7 @@ pub fn hot_function(c: u8) { fn main() { let arg = std::env::args().skip(1).next().unwrap(); - for i in 0 .. 1000_000 { + for i in 0..1000_000 { let some_value = arg.as_bytes()[i % arg.len()]; if some_value == b'!' { // This branch is never taken at runtime diff --git a/tests/run-make/pointer-auth-link-with-c/test.rs b/tests/run-make/pointer-auth-link-with-c/test.rs index 615ad0aeb3d0..1a3be80e898b 100644 --- a/tests/run-make/pointer-auth-link-with-c/test.rs +++ b/tests/run-make/pointer-auth-link-with-c/test.rs @@ -4,5 +4,7 @@ extern "C" { } fn main() { - unsafe {foo();} + unsafe { + foo(); + } } diff --git a/tests/run-make/pretty-print-to-file/input.rs b/tests/run-make/pretty-print-to-file/input.rs index aa828155b205..ce23804e4307 100644 --- a/tests/run-make/pretty-print-to-file/input.rs +++ b/tests/run-make/pretty-print-to-file/input.rs @@ -1,5 +1,5 @@ -#[crate_type="lib"] +#[crate_type = "lib"] -pub fn -foo() -> i32 -{ 45 } +pub fn foo() -> i32 { + 45 +} diff --git a/tests/run-make/print-check-cfg/rmake.rs b/tests/run-make/print-check-cfg/rmake.rs index 554884b7d579..f7f5fcf2340b 100644 --- a/tests/run-make/print-check-cfg/rmake.rs +++ b/tests/run-make/print-check-cfg/rmake.rs @@ -40,19 +40,21 @@ fn main() { /*contains*/ &["feature", "feature=\"\"", "feature=\"test\"", "feature=\"lol\""], ); check( - /*args*/ &[ + /*args*/ + &[ r#"--check-cfg=cfg(feature, values(any()))"#, - r#"--check-cfg=cfg(feature, values("tmp"))"# + r#"--check-cfg=cfg(feature, values("tmp"))"#, ], /*has_any*/ false, /*has_any_any*/ false, /*contains*/ &["unix", "miri", "feature=any()"], ); check( - /*args*/ &[ + /*args*/ + &[ r#"--check-cfg=cfg(has_foo, has_bar)"#, r#"--check-cfg=cfg(feature, values("tmp"))"#, - r#"--check-cfg=cfg(feature, values("tmp"))"# + r#"--check-cfg=cfg(feature, values("tmp"))"#, ], /*has_any*/ false, /*has_any_any*/ false, diff --git a/tests/run-make/proc-macro-init-order/b.rs b/tests/run-make/proc-macro-init-order/b.rs index 355d2b165274..067f47c1b7a1 100644 --- a/tests/run-make/proc-macro-init-order/b.rs +++ b/tests/run-make/proc-macro-init-order/b.rs @@ -1,2 +1,3 @@ #![crate_type = "lib"] -#[macro_use] extern crate a; +#[macro_use] +extern crate a; diff --git a/tests/run-make/proc-macro-init-order/c.rs b/tests/run-make/proc-macro-init-order/c.rs index b9c2155728cb..505f8470338e 100644 --- a/tests/run-make/proc-macro-init-order/c.rs +++ b/tests/run-make/proc-macro-init-order/c.rs @@ -1,3 +1,3 @@ #![crate_type = "staticlib"] -extern crate b; extern crate a; +extern crate b; diff --git a/tests/run-make/prune-link-args/empty.rs b/tests/run-make/prune-link-args/empty.rs index 45590d86ba6c..f328e4d9d04c 100644 --- a/tests/run-make/prune-link-args/empty.rs +++ b/tests/run-make/prune-link-args/empty.rs @@ -1 +1 @@ -fn main() { } +fn main() {} diff --git a/tests/run-make/raw-dylib-alt-calling-convention/driver.rs b/tests/run-make/raw-dylib-alt-calling-convention/driver.rs index b7f372c6b2b2..918e013af6ef 100644 --- a/tests/run-make/raw-dylib-alt-calling-convention/driver.rs +++ b/tests/run-make/raw-dylib-alt-calling-convention/driver.rs @@ -2,7 +2,6 @@ extern crate raw_dylib_alt_calling_convention_test; fn main() { raw_dylib_alt_calling_convention_test::library_function( - std::env::args().skip(1).next().map_or( - false, - |s| std::str::FromStr::from_str(&s).unwrap())); + std::env::args().skip(1).next().map_or(false, |s| std::str::FromStr::from_str(&s).unwrap()), + ); } diff --git a/tests/run-make/raw-dylib-c/lib.rs b/tests/run-make/raw-dylib-c/lib.rs index f17125f308c2..ebb08a0ba9e9 100644 --- a/tests/run-make/raw-dylib-c/lib.rs +++ b/tests/run-make/raw-dylib-c/lib.rs @@ -1,16 +1,16 @@ #[link(name = "extern_1.dll", kind = "raw-dylib", modifiers = "+verbatim")] -extern { +extern "C" { fn extern_fn_1(); } #[link(name = "extern_2", kind = "raw-dylib")] -extern { +extern "C" { fn extern_fn_3(); } pub fn library_function() { #[link(name = "extern_1", kind = "raw-dylib")] - extern { + extern "C" { fn extern_fn_2(); fn print_extern_variable(); static mut extern_variable: i32; diff --git a/tests/run-make/raw-dylib-cross-compilation/lib.rs b/tests/run-make/raw-dylib-cross-compilation/lib.rs index 3338ac0a0b50..d3b7fd23ca82 100644 --- a/tests/run-make/raw-dylib-cross-compilation/lib.rs +++ b/tests/run-make/raw-dylib-cross-compilation/lib.rs @@ -8,7 +8,7 @@ trait Sized {} #[link(name = "extern_1", kind = "raw-dylib")] -extern { +extern "C" { fn extern_fn(); } diff --git a/tests/run-make/raw-dylib-custom-dlltool/lib.rs b/tests/run-make/raw-dylib-custom-dlltool/lib.rs index 2f3f497a00de..db1d64505038 100644 --- a/tests/run-make/raw-dylib-custom-dlltool/lib.rs +++ b/tests/run-make/raw-dylib-custom-dlltool/lib.rs @@ -1,5 +1,5 @@ #[link(name = "extern_1", kind = "raw-dylib")] -extern { +extern "C" { fn extern_fn_1(); } diff --git a/tests/run-make/raw-dylib-import-name-type/driver.rs b/tests/run-make/raw-dylib-import-name-type/driver.rs index 6c1c212f187b..b235fef9e308 100644 --- a/tests/run-make/raw-dylib-import-name-type/driver.rs +++ b/tests/run-make/raw-dylib-import-name-type/driver.rs @@ -76,7 +76,7 @@ extern "vectorcall" { } #[link(name = "extern", kind = "raw-dylib")] -extern { +extern "C" { fn print_extern_variable_undecorated(); fn print_extern_variable_noprefix(); fn print_extern_variable_decorated(); diff --git a/tests/run-make/raw-dylib-inline-cross-dylib/driver.rs b/tests/run-make/raw-dylib-inline-cross-dylib/driver.rs index 0c3125be6f59..53f3fcb2f880 100644 --- a/tests/run-make/raw-dylib-inline-cross-dylib/driver.rs +++ b/tests/run-make/raw-dylib-inline-cross-dylib/driver.rs @@ -2,7 +2,7 @@ extern crate raw_dylib_test; extern crate raw_dylib_test_wrapper; #[link(name = "extern_2", kind = "raw-dylib")] -extern { +extern "C" { fn extern_fn_2(); } diff --git a/tests/run-make/raw-dylib-inline-cross-dylib/lib.rs b/tests/run-make/raw-dylib-inline-cross-dylib/lib.rs index 4877cb80aea5..07e289a21d97 100644 --- a/tests/run-make/raw-dylib-inline-cross-dylib/lib.rs +++ b/tests/run-make/raw-dylib-inline-cross-dylib/lib.rs @@ -1,5 +1,5 @@ #[link(name = "extern_1", kind = "raw-dylib")] -extern { +extern "C" { fn extern_fn_1(); fn extern_fn_2(); } diff --git a/tests/run-make/raw-dylib-link-ordinal/lib.rs b/tests/run-make/raw-dylib-link-ordinal/lib.rs index 1bbb45bbc772..69f0a5bca46f 100644 --- a/tests/run-make/raw-dylib-link-ordinal/lib.rs +++ b/tests/run-make/raw-dylib-link-ordinal/lib.rs @@ -1,5 +1,5 @@ #[link(name = "exporter", kind = "raw-dylib")] -extern { +extern "C" { #[link_ordinal(13)] fn imported_function(); #[link_ordinal(5)] diff --git a/tests/run-make/reproducible-build-2/linker.rs b/tests/run-make/reproducible-build-2/linker.rs index 998d1f328596..ec238b2fa562 100644 --- a/tests/run-make/reproducible-build-2/linker.rs +++ b/tests/run-make/reproducible-build-2/linker.rs @@ -1,7 +1,7 @@ use std::env; -use std::path::Path; use std::fs::File; use std::io::{Read, Write}; +use std::path::Path; fn main() { let mut dst = env::current_exe().unwrap(); @@ -19,7 +19,7 @@ fn main() { if !path.is_file() { out.push_str(&arg); out.push_str("\n"); - continue + continue; } let mut contents = Vec::new(); diff --git a/tests/run-make/reproducible-build-2/reproducible-build-aux.rs b/tests/run-make/reproducible-build-2/reproducible-build-aux.rs index 8105b3d2bda3..9708b2d15b42 100644 --- a/tests/run-make/reproducible-build-2/reproducible-build-aux.rs +++ b/tests/run-make/reproducible-build-2/reproducible-build-aux.rs @@ -1,4 +1,4 @@ -#![crate_type="lib"] +#![crate_type = "lib"] pub static STATIC: i32 = 1234; @@ -18,7 +18,7 @@ impl Drop for Struct { pub enum Enum { Variant1, Variant2(u32), - Variant3 { x: u32 } + Variant3 { x: u32 }, } pub struct TupleStruct(pub i8, pub i16, pub i32, pub i64); diff --git a/tests/run-make/reproducible-build-2/reproducible-build.rs b/tests/run-make/reproducible-build-2/reproducible-build.rs index a6c04774c869..849b3d510af8 100644 --- a/tests/run-make/reproducible-build-2/reproducible-build.rs +++ b/tests/run-make/reproducible-build-2/reproducible-build.rs @@ -18,6 +18,8 @@ // - Trait object shims // - Fn Pointer shims +// ignore-tidy-linelength + #![allow(dead_code, warnings)] extern crate reproducible_build_aux; @@ -40,7 +42,7 @@ impl Drop for Struct { pub enum Enum { Variant1, Variant2(u32), - Variant3 { x: u32 } + Variant3 { x: u32 }, } struct TupleStruct(i8, i16, i32, i64); @@ -67,19 +69,14 @@ fn main() { generic_fn::>(); generic_fn::, reproducible_build_aux::Struct>(); - let dropped = Struct { - x: "", - y: 'a', - }; + let dropped = Struct { x: "", y: 'a' }; let _ = Enum::Variant1; let _ = Enum::Variant2(0); let _ = Enum::Variant3 { x: 0 }; let _ = TupleStruct(1, 2, 3, 4); - let closure = |x| { - x + 1i32 - }; + let closure = |x| x + 1i32; fn inner i32>(f: F) -> i32 { f(STATIC) @@ -94,13 +91,13 @@ fn main() { f(0); } - with_fn_once_adapter(|_:i32| { }); + with_fn_once_adapter(|_: i32| {}); reproducible_build_aux::regular_fn(STATIC); reproducible_build_aux::generic_fn::(); reproducible_build_aux::generic_fn::>(); - reproducible_build_aux::generic_fn::, - reproducible_build_aux::Struct>(); + reproducible_build_aux::generic_fn::, reproducible_build_aux::Struct>( + ); let _ = reproducible_build_aux::Enum::Variant1; let _ = reproducible_build_aux::Enum::Variant2(0); diff --git a/tests/run-make/reproducible-build/linker.rs b/tests/run-make/reproducible-build/linker.rs index 3dda6f190e44..ab3b4049cc32 100644 --- a/tests/run-make/reproducible-build/linker.rs +++ b/tests/run-make/reproducible-build/linker.rs @@ -1,7 +1,7 @@ use std::env; -use std::path::Path; use std::fs::File; use std::io::{Read, Write}; +use std::path::Path; fn main() { let mut dst = env::current_exe().unwrap(); @@ -19,7 +19,7 @@ fn main() { if !path.is_file() { out.push_str(&arg); out.push_str("\n"); - continue + continue; } let mut contents = Vec::new(); diff --git a/tests/run-make/reproducible-build/reproducible-build-aux.rs b/tests/run-make/reproducible-build/reproducible-build-aux.rs index 8105b3d2bda3..9708b2d15b42 100644 --- a/tests/run-make/reproducible-build/reproducible-build-aux.rs +++ b/tests/run-make/reproducible-build/reproducible-build-aux.rs @@ -1,4 +1,4 @@ -#![crate_type="lib"] +#![crate_type = "lib"] pub static STATIC: i32 = 1234; @@ -18,7 +18,7 @@ impl Drop for Struct { pub enum Enum { Variant1, Variant2(u32), - Variant3 { x: u32 } + Variant3 { x: u32 }, } pub struct TupleStruct(pub i8, pub i16, pub i32, pub i64); diff --git a/tests/run-make/reproducible-build/reproducible-build.rs b/tests/run-make/reproducible-build/reproducible-build.rs index a6c04774c869..849b3d510af8 100644 --- a/tests/run-make/reproducible-build/reproducible-build.rs +++ b/tests/run-make/reproducible-build/reproducible-build.rs @@ -18,6 +18,8 @@ // - Trait object shims // - Fn Pointer shims +// ignore-tidy-linelength + #![allow(dead_code, warnings)] extern crate reproducible_build_aux; @@ -40,7 +42,7 @@ impl Drop for Struct { pub enum Enum { Variant1, Variant2(u32), - Variant3 { x: u32 } + Variant3 { x: u32 }, } struct TupleStruct(i8, i16, i32, i64); @@ -67,19 +69,14 @@ fn main() { generic_fn::>(); generic_fn::, reproducible_build_aux::Struct>(); - let dropped = Struct { - x: "", - y: 'a', - }; + let dropped = Struct { x: "", y: 'a' }; let _ = Enum::Variant1; let _ = Enum::Variant2(0); let _ = Enum::Variant3 { x: 0 }; let _ = TupleStruct(1, 2, 3, 4); - let closure = |x| { - x + 1i32 - }; + let closure = |x| x + 1i32; fn inner i32>(f: F) -> i32 { f(STATIC) @@ -94,13 +91,13 @@ fn main() { f(0); } - with_fn_once_adapter(|_:i32| { }); + with_fn_once_adapter(|_: i32| {}); reproducible_build_aux::regular_fn(STATIC); reproducible_build_aux::generic_fn::(); reproducible_build_aux::generic_fn::>(); - reproducible_build_aux::generic_fn::, - reproducible_build_aux::Struct>(); + reproducible_build_aux::generic_fn::, reproducible_build_aux::Struct>( + ); let _ = reproducible_build_aux::Enum::Variant1; let _ = reproducible_build_aux::Enum::Variant2(0); diff --git a/tests/run-make/reset-codegen-1/foo.rs b/tests/run-make/reset-codegen-1/foo.rs index 45590d86ba6c..f328e4d9d04c 100644 --- a/tests/run-make/reset-codegen-1/foo.rs +++ b/tests/run-make/reset-codegen-1/foo.rs @@ -1 +1 @@ -fn main() { } +fn main() {} diff --git a/tests/run-make/resolve-rename/bar.rs b/tests/run-make/resolve-rename/bar.rs index 4a09ce355e68..706ff4535202 100644 --- a/tests/run-make/resolve-rename/bar.rs +++ b/tests/run-make/resolve-rename/bar.rs @@ -2,4 +2,6 @@ extern crate foo; -pub fn bar() { foo::foo() } +pub fn bar() { + foo::foo() +} diff --git a/tests/run-make/resolve-rename/baz.rs b/tests/run-make/resolve-rename/baz.rs index 9176073ef97f..74822fb4e1ef 100644 --- a/tests/run-make/resolve-rename/baz.rs +++ b/tests/run-make/resolve-rename/baz.rs @@ -2,4 +2,6 @@ extern crate bar; -pub fn baz() { bar::bar() } +pub fn baz() { + bar::bar() +} diff --git a/tests/run-make/return-non-c-like-enum-from-c/nonclike.rs b/tests/run-make/return-non-c-like-enum-from-c/nonclike.rs index ea22a2a56e09..1cd6360bdd23 100644 --- a/tests/run-make/return-non-c-like-enum-from-c/nonclike.rs +++ b/tests/run-make/return-non-c-like-enum-from-c/nonclike.rs @@ -4,7 +4,7 @@ pub enum TT { BB, } -#[repr(C,u8)] +#[repr(C, u8)] pub enum T { A(u64), B, diff --git a/tests/run-make/return-non-c-like-enum/nonclike.rs b/tests/run-make/return-non-c-like-enum/nonclike.rs index de529cf641ab..32884d8d690b 100644 --- a/tests/run-make/return-non-c-like-enum/nonclike.rs +++ b/tests/run-make/return-non-c-like-enum/nonclike.rs @@ -9,7 +9,7 @@ pub extern "C" fn tt_new(a: u64, b: u64) -> TT { TT::AA(a, b) } -#[repr(C,u8)] +#[repr(C, u8)] pub enum T { A(u64), B, diff --git a/tests/run-make/rlib-chain/m2.rs b/tests/run-make/rlib-chain/m2.rs index eba12fe12188..9430e1d156c0 100644 --- a/tests/run-make/rlib-chain/m2.rs +++ b/tests/run-make/rlib-chain/m2.rs @@ -1,4 +1,6 @@ #![crate_type = "rlib"] extern crate m1; -pub fn m2() { m1::m1() } +pub fn m2() { + m1::m1() +} diff --git a/tests/run-make/rlib-chain/m3.rs b/tests/run-make/rlib-chain/m3.rs index ade191db49c8..b45712e55e16 100644 --- a/tests/run-make/rlib-chain/m3.rs +++ b/tests/run-make/rlib-chain/m3.rs @@ -1,4 +1,6 @@ #![crate_type = "rlib"] extern crate m2; -pub fn m3() { m2::m2() } +pub fn m3() { + m2::m2() +} diff --git a/tests/run-make/rlib-chain/m4.rs b/tests/run-make/rlib-chain/m4.rs index fa8ec6079dea..c732512af9fc 100644 --- a/tests/run-make/rlib-chain/m4.rs +++ b/tests/run-make/rlib-chain/m4.rs @@ -1,3 +1,5 @@ extern crate m3; -fn main() { m3::m3() } +fn main() { + m3::m3() +} diff --git a/tests/run-make/rustdoc-error-lines/input.rs b/tests/run-make/rustdoc-error-lines/input.rs index b4db182e85f2..1ca2efc0dd59 100644 --- a/tests/run-make/rustdoc-error-lines/input.rs +++ b/tests/run-make/rustdoc-error-lines/input.rs @@ -6,9 +6,7 @@ /// #![feature(bool_to_option)] /// let x: char = 1; /// ``` -pub fn foo() { - -} +pub fn foo() {} /// Add some text around the test... /// diff --git a/tests/run-make/rustdoc-error-lines/rmake.rs b/tests/run-make/rustdoc-error-lines/rmake.rs index 31536c78dd46..db6e28e4feb7 100644 --- a/tests/run-make/rustdoc-error-lines/rmake.rs +++ b/tests/run-make/rustdoc-error-lines/rmake.rs @@ -11,10 +11,10 @@ fn main() { let should_contain = &[ "input.rs - foo (line 5)", "input.rs:7:15", - "input.rs - bar (line 15)", - "input.rs:17:15", - "input.rs - bar (line 24)", - "input.rs:26:15", + "input.rs - bar (line 13)", + "input.rs:15:15", + "input.rs - bar (line 22)", + "input.rs:24:15", ]; for text in should_contain { assert!(output.contains(text), "output doesn't contains {:?}", text); diff --git a/tests/run-make/rustdoc-map-file/foo.rs b/tests/run-make/rustdoc-map-file/foo.rs index e12b9d2292c5..f98543f9b052 100644 --- a/tests/run-make/rustdoc-map-file/foo.rs +++ b/tests/run-make/rustdoc-map-file/foo.rs @@ -1,5 +1,5 @@ -pub use private::Quz; pub use hidden::Bar; +pub use private::Quz; mod private { pub struct Quz; @@ -12,5 +12,5 @@ pub mod hidden { #[macro_export] macro_rules! foo { - () => {} + () => {}; } diff --git a/tests/run-make/rustdoc-scrape-examples-invalid-expr/src/lib.rs b/tests/run-make/rustdoc-scrape-examples-invalid-expr/src/lib.rs index c30c99dec603..ba8ee66fc78b 100644 --- a/tests/run-make/rustdoc-scrape-examples-invalid-expr/src/lib.rs +++ b/tests/run-make/rustdoc-scrape-examples-invalid-expr/src/lib.rs @@ -1 +1,3 @@ -pub const fn f() -> usize { 5 } +pub const fn f() -> usize { + 5 +} diff --git a/tests/run-make/rustdoc-scrape-examples-macros/examples/ex.rs b/tests/run-make/rustdoc-scrape-examples-macros/examples/ex.rs index 4d8c8b30e311..70a9a187f07e 100644 --- a/tests/run-make/rustdoc-scrape-examples-macros/examples/ex.rs +++ b/tests/run-make/rustdoc-scrape-examples-macros/examples/ex.rs @@ -8,20 +8,20 @@ a_proc_macro!(); // no #[an_attr_macro] fn a() { - f(); // no + f(); // no } #[an_attr_macro(with_span)] fn b() { - f(); // yes + f(); // yes } fn c() { - a_rules_macro!(f()); // yes + a_rules_macro!(f()); // yes } fn d() { - a_rules_macro!(()); // no + a_rules_macro!(()); // no } -fn main(){} +fn main() {} diff --git a/tests/run-make/rustdoc-scrape-examples-macros/src/lib.rs b/tests/run-make/rustdoc-scrape-examples-macros/src/lib.rs index d8658a0f2557..26ab1390a49a 100644 --- a/tests/run-make/rustdoc-scrape-examples-macros/src/lib.rs +++ b/tests/run-make/rustdoc-scrape-examples-macros/src/lib.rs @@ -8,5 +8,7 @@ pub fn f() {} #[macro_export] macro_rules! a_rules_macro { - ($e:expr) => { ($e, foobar::f()); } + ($e:expr) => { + ($e, foobar::f()); + }; } diff --git a/tests/run-make/rustdoc-scrape-examples-test/examples/ex.rs b/tests/run-make/rustdoc-scrape-examples-test/examples/ex.rs index d1a9a74e7825..c37b8dd48853 100644 --- a/tests/run-make/rustdoc-scrape-examples-test/examples/ex.rs +++ b/tests/run-make/rustdoc-scrape-examples-test/examples/ex.rs @@ -2,5 +2,5 @@ fn main() {} #[test] fn a_test() { - foobar::ok(); + foobar::ok(); } diff --git a/tests/run-make/rustdoc-scrape-examples-whitespace/examples/ex.rs b/tests/run-make/rustdoc-scrape-examples-whitespace/examples/ex.rs index 44ff689dfc87..09df782a1367 100644 --- a/tests/run-make/rustdoc-scrape-examples-whitespace/examples/ex.rs +++ b/tests/run-make/rustdoc-scrape-examples-whitespace/examples/ex.rs @@ -1,8 +1,10 @@ struct Foo; impl Foo { - fn bar() { foobar::ok(); } + fn bar() { + foobar::ok(); + } } fn main() { - Foo::bar(); + Foo::bar(); } diff --git a/tests/run-make/share-generics-dylib/linked_leaf.rs b/tests/run-make/share-generics-dylib/linked_leaf.rs index e510dad691c5..200a732d588d 100644 --- a/tests/run-make/share-generics-dylib/linked_leaf.rs +++ b/tests/run-make/share-generics-dylib/linked_leaf.rs @@ -1,11 +1,12 @@ +// Blank line after this one because it must come before `instance_user_{a,b}_rlib`. extern crate instance_user_dylib; + extern crate instance_user_a_rlib; extern crate instance_user_b_rlib; use std::cell::Cell; fn main() { - instance_user_a_rlib::foo(); instance_user_b_rlib::foo(); instance_user_dylib::foo(); diff --git a/tests/run-make/split-debuginfo/main.rs b/tests/run-make/split-debuginfo/main.rs index 21fa16e40a4a..e815672fa819 100644 --- a/tests/run-make/split-debuginfo/main.rs +++ b/tests/run-make/split-debuginfo/main.rs @@ -1,6 +1,6 @@ extern crate bar; -use bar::{Bar, make_bar}; +use bar::{make_bar, Bar}; fn main() { let b = make_bar(3); diff --git a/tests/run-make/stable-symbol-names/stable-symbol-names1.rs b/tests/run-make/stable-symbol-names/stable-symbol-names1.rs index b85a428278cd..ff20d4306dd7 100644 --- a/tests/run-make/stable-symbol-names/stable-symbol-names1.rs +++ b/tests/run-make/stable-symbol-names/stable-symbol-names1.rs @@ -1,31 +1,31 @@ -#![crate_type="rlib"] +#![crate_type = "rlib"] pub trait Foo { - fn generic_method(); + fn generic_method(); } pub struct Bar; impl Foo for Bar { - fn generic_method() {} + fn generic_method() {} } pub fn mono_function() { - Bar::generic_method::(); + Bar::generic_method::(); } pub fn mono_function_lifetime<'a>(x: &'a u64) -> u64 { - *x + *x } pub fn generic_function(t: T) -> T { - t + t } pub fn user() { - generic_function(0u32); - generic_function("abc"); - let x = 2u64; - generic_function(&x); - let _ = mono_function_lifetime(&x); + generic_function(0u32); + generic_function("abc"); + let x = 2u64; + generic_function(&x); + let _ = mono_function_lifetime(&x); } diff --git a/tests/run-make/stable-symbol-names/stable-symbol-names2.rs b/tests/run-make/stable-symbol-names/stable-symbol-names2.rs index 33df9d6c6898..6a50c2a4f573 100644 --- a/tests/run-make/stable-symbol-names/stable-symbol-names2.rs +++ b/tests/run-make/stable-symbol-names/stable-symbol-names2.rs @@ -1,17 +1,17 @@ -#![crate_type="rlib"] +#![crate_type = "rlib"] extern crate stable_symbol_names1; pub fn user() { - stable_symbol_names1::generic_function(1u32); - stable_symbol_names1::generic_function("def"); - let x = 2u64; - stable_symbol_names1::generic_function(&x); - stable_symbol_names1::mono_function(); - stable_symbol_names1::mono_function_lifetime(&0); + stable_symbol_names1::generic_function(1u32); + stable_symbol_names1::generic_function("def"); + let x = 2u64; + stable_symbol_names1::generic_function(&x); + stable_symbol_names1::mono_function(); + stable_symbol_names1::mono_function_lifetime(&0); } pub fn trait_impl_test_function() { - use stable_symbol_names1::*; - Bar::generic_method::(); + use stable_symbol_names1::*; + Bar::generic_method::(); } diff --git a/tests/run-make/static-unwinding/lib.rs b/tests/run-make/static-unwinding/lib.rs index 3fb1117a1105..975de43cfd8d 100644 --- a/tests/run-make/static-unwinding/lib.rs +++ b/tests/run-make/static-unwinding/lib.rs @@ -5,11 +5,16 @@ pub static mut statik: isize = 0; struct A; impl Drop for A { fn drop(&mut self) { - unsafe { statik = 1; } + unsafe { + statik = 1; + } } } -pub fn callback(f: F) where F: FnOnce() { +pub fn callback(f: F) +where + F: FnOnce(), +{ let _a = A; f(); } diff --git a/tests/run-make/static-unwinding/main.rs b/tests/run-make/static-unwinding/main.rs index 0c66ea1aa07f..ceb0a24804c5 100644 --- a/tests/run-make/static-unwinding/main.rs +++ b/tests/run-make/static-unwinding/main.rs @@ -7,15 +7,19 @@ static mut statik: isize = 0; struct A; impl Drop for A { fn drop(&mut self) { - unsafe { statik = 1; } + unsafe { + statik = 1; + } } } fn main() { - thread::spawn(move|| { + thread::spawn(move || { let _a = A; lib::callback(|| panic!()); - }).join().unwrap_err(); + }) + .join() + .unwrap_err(); unsafe { assert_eq!(lib::statik, 1); diff --git a/tests/run-make/suspicious-library/bar.rs b/tests/run-make/suspicious-library/bar.rs index 550c94cd0c60..030693a694f9 100644 --- a/tests/run-make/suspicious-library/bar.rs +++ b/tests/run-make/suspicious-library/bar.rs @@ -1,3 +1,5 @@ extern crate foo; -fn main() { foo::foo() } +fn main() { + foo::foo() +} diff --git a/tests/run-make/symbol-mangling-hashed/a_dylib.rs b/tests/run-make/symbol-mangling-hashed/a_dylib.rs index 8aec8fd82a53..49d65b72cacc 100644 --- a/tests/run-make/symbol-mangling-hashed/a_dylib.rs +++ b/tests/run-make/symbol-mangling-hashed/a_dylib.rs @@ -1,4 +1,4 @@ -#![crate_type="dylib"] +#![crate_type = "dylib"] pub fn hello() { println!("hello dylib"); } diff --git a/tests/run-make/symbol-mangling-hashed/a_rlib.rs b/tests/run-make/symbol-mangling-hashed/a_rlib.rs index 873c86c5d0b4..71e44ccc2007 100644 --- a/tests/run-make/symbol-mangling-hashed/a_rlib.rs +++ b/tests/run-make/symbol-mangling-hashed/a_rlib.rs @@ -1,4 +1,4 @@ -#![crate_type="rlib"] +#![crate_type = "rlib"] pub fn hello() { println!("hello rlib"); diff --git a/tests/run-make/symbol-mangling-hashed/b_bin.rs b/tests/run-make/symbol-mangling-hashed/b_bin.rs index bcc53c37e122..8ee7fecda62a 100644 --- a/tests/run-make/symbol-mangling-hashed/b_bin.rs +++ b/tests/run-make/symbol-mangling-hashed/b_bin.rs @@ -1,5 +1,5 @@ -extern crate a_rlib; extern crate a_dylib; +extern crate a_rlib; extern crate b_dylib; fn main() { diff --git a/tests/run-make/symbol-mangling-hashed/b_dylib.rs b/tests/run-make/symbol-mangling-hashed/b_dylib.rs index c26a04b39ec3..3252c9c75c2a 100644 --- a/tests/run-make/symbol-mangling-hashed/b_dylib.rs +++ b/tests/run-make/symbol-mangling-hashed/b_dylib.rs @@ -1,7 +1,7 @@ -#![crate_type="dylib"] +#![crate_type = "dylib"] -extern crate a_rlib; extern crate a_dylib; +extern crate a_rlib; pub fn hello() { a_rlib::hello(); diff --git a/tests/run-make/symbol-visibility/a_cdylib.rs b/tests/run-make/symbol-visibility/a_cdylib.rs index d4fbff85bfe6..cc034c8a31e5 100644 --- a/tests/run-make/symbol-visibility/a_cdylib.rs +++ b/tests/run-make/symbol-visibility/a_cdylib.rs @@ -1,4 +1,4 @@ -#![crate_type="cdylib"] +#![crate_type = "cdylib"] extern crate an_rlib; diff --git a/tests/run-make/symbol-visibility/a_rust_dylib.rs b/tests/run-make/symbol-visibility/a_rust_dylib.rs index a47df0ab7eed..22c0482343ee 100644 --- a/tests/run-make/symbol-visibility/a_rust_dylib.rs +++ b/tests/run-make/symbol-visibility/a_rust_dylib.rs @@ -1,4 +1,4 @@ -#![crate_type="dylib"] +#![crate_type = "dylib"] extern crate an_rlib; @@ -12,4 +12,6 @@ pub extern "C" fn public_c_function_from_rust_dylib() { } // This should be exported if -Zshare-generics=yes -pub fn public_generic_function_from_rust_dylib(x: T) -> T { x } +pub fn public_generic_function_from_rust_dylib(x: T) -> T { + x +} diff --git a/tests/run-make/symbol-visibility/an_executable.rs b/tests/run-make/symbol-visibility/an_executable.rs index 3f5e125ad193..945873bd9ce1 100644 --- a/tests/run-make/symbol-visibility/an_executable.rs +++ b/tests/run-make/symbol-visibility/an_executable.rs @@ -1,4 +1,4 @@ -#![crate_type="bin"] +#![crate_type = "bin"] extern crate an_rlib; diff --git a/tests/run-make/symbol-visibility/an_rlib.rs b/tests/run-make/symbol-visibility/an_rlib.rs index 3696422b11e9..b291dbe571cd 100644 --- a/tests/run-make/symbol-visibility/an_rlib.rs +++ b/tests/run-make/symbol-visibility/an_rlib.rs @@ -1,4 +1,4 @@ -#![crate_type="rlib"] +#![crate_type = "rlib"] pub fn public_rust_function_from_rlib() {} diff --git a/tests/run-make/symlinked-extern/bar.rs b/tests/run-make/symlinked-extern/bar.rs index cd9c959d5e6a..895582d5f13b 100644 --- a/tests/run-make/symlinked-extern/bar.rs +++ b/tests/run-make/symlinked-extern/bar.rs @@ -2,5 +2,4 @@ extern crate foo; -pub fn bar(_s: foo::S) { -} +pub fn bar(_s: foo::S) {} diff --git a/tests/run-make/symlinked-extern/foo.rs b/tests/run-make/symlinked-extern/foo.rs index c00700b8cf83..4dcf6e135f60 100644 --- a/tests/run-make/symlinked-extern/foo.rs +++ b/tests/run-make/symlinked-extern/foo.rs @@ -2,4 +2,6 @@ pub struct S; -pub fn foo() -> S { S } +pub fn foo() -> S { + S +} diff --git a/tests/run-make/target-cpu-native/foo.rs b/tests/run-make/target-cpu-native/foo.rs index f79c691f0853..f328e4d9d04c 100644 --- a/tests/run-make/target-cpu-native/foo.rs +++ b/tests/run-make/target-cpu-native/foo.rs @@ -1,2 +1 @@ -fn main() { -} +fn main() {} diff --git a/tests/run-make/test-harness/test-ignore-cfg.rs b/tests/run-make/test-harness/test-ignore-cfg.rs index 31ef131f2ad7..c6bd7680bd5c 100644 --- a/tests/run-make/test-harness/test-ignore-cfg.rs +++ b/tests/run-make/test-harness/test-ignore-cfg.rs @@ -1,9 +1,7 @@ #[test] #[cfg_attr(ignorecfg, ignore)] -fn shouldignore() { -} +fn shouldignore() {} #[test] #[cfg_attr(noignorecfg, ignore)] -fn shouldnotignore() { -} +fn shouldnotignore() {} diff --git a/tests/run-make/type-mismatch-same-crate-name/crateA.rs b/tests/run-make/type-mismatch-same-crate-name/crateA.rs index 4871c8c2e9cc..0dccfbb4bed6 100644 --- a/tests/run-make/type-mismatch-same-crate-name/crateA.rs +++ b/tests/run-make/type-mismatch-same-crate-name/crateA.rs @@ -3,7 +3,7 @@ mod foo { } mod bar { - pub trait Bar{} + pub trait Bar {} pub fn bar() -> Box { unimplemented!() @@ -12,5 +12,5 @@ mod bar { // This makes the publicly accessible path // differ from the internal one. +pub use bar::{bar, Bar}; pub use foo::Foo; -pub use bar::{Bar, bar}; diff --git a/tests/run-make/type-mismatch-same-crate-name/crateB.rs b/tests/run-make/type-mismatch-same-crate-name/crateB.rs index 24fcc7cadc10..e946c0ecac76 100644 --- a/tests/run-make/type-mismatch-same-crate-name/crateB.rs +++ b/tests/run-make/type-mismatch-same-crate-name/crateB.rs @@ -1,4 +1,4 @@ extern crate crateA; -pub fn try_foo(x: crateA::Foo){} -pub fn try_bar(x: Box){} +pub fn try_foo(x: crateA::Foo) {} +pub fn try_bar(x: Box) {} diff --git a/tests/run-make/use-suggestions-rust-2018/use-suggestions.rs b/tests/run-make/use-suggestions-rust-2018/use-suggestions.rs index d262d6f9877c..1bb987d0ebdf 100644 --- a/tests/run-make/use-suggestions-rust-2018/use-suggestions.rs +++ b/tests/run-make/use-suggestions-rust-2018/use-suggestions.rs @@ -1,3 +1,3 @@ fn main() { - let x = Baz{}; + let x = Baz {}; } diff --git a/tests/run-make/wasm-custom-section/bar.rs b/tests/run-make/wasm-custom-section/bar.rs index c95f3e1438b7..1e94e99ff086 100644 --- a/tests/run-make/wasm-custom-section/bar.rs +++ b/tests/run-make/wasm-custom-section/bar.rs @@ -10,4 +10,4 @@ pub static A: [u8; 2] = [5, 6]; pub static B: [u8; 2] = [7, 8]; #[no_mangle] -pub extern fn foo() {} +pub extern "C" fn foo() {} diff --git a/tests/run-make/wasm-custom-sections-opt/foo.rs b/tests/run-make/wasm-custom-sections-opt/foo.rs index 9af7728b7f3a..f521dd937a0e 100644 --- a/tests/run-make/wasm-custom-sections-opt/foo.rs +++ b/tests/run-make/wasm-custom-sections-opt/foo.rs @@ -13,7 +13,7 @@ pub mod another { } #[no_mangle] -pub extern fn foo() { +pub extern "C" fn foo() { // This will import `another::foo` through ThinLTO passes, and it better not // also accidentally import the `FOO` custom section into this module as // well diff --git a/tests/run-make/wasm-exceptions-nostd/src/arena_alloc.rs b/tests/run-make/wasm-exceptions-nostd/src/arena_alloc.rs index 572d253309ce..12f1b4d8d12f 100644 --- a/tests/run-make/wasm-exceptions-nostd/src/arena_alloc.rs +++ b/tests/run-make/wasm-exceptions-nostd/src/arena_alloc.rs @@ -14,9 +14,7 @@ pub struct ArenaAllocator { impl ArenaAllocator { pub const fn new() -> Self { - Self { - arena: UnsafeCell::new(Arena::new()), - } + Self { arena: UnsafeCell::new(Arena::new()) } } } @@ -42,10 +40,7 @@ struct Arena { impl Arena { pub const fn new() -> Self { - Self { - buf: [0x55; ARENA_SIZE], - allocated: 0, - } + Self { buf: [0x55; ARENA_SIZE], allocated: 0 } } pub unsafe fn alloc(&mut self, layout: Layout) -> *mut u8 { diff --git a/tests/run-make/wasm-exceptions-nostd/src/lib.rs b/tests/run-make/wasm-exceptions-nostd/src/lib.rs index 9d336510469c..3ea8797d3a6d 100644 --- a/tests/run-make/wasm-exceptions-nostd/src/lib.rs +++ b/tests/run-make/wasm-exceptions-nostd/src/lib.rs @@ -1,9 +1,7 @@ #![no_std] #![crate_type = "cdylib"] - // Allow a few unstable features because we create a panic // runtime for native wasm exceptions from scratch - #![feature(core_intrinsics)] #![feature(lang_items)] #![feature(link_llvm_intrinsics)] @@ -39,20 +37,24 @@ pub extern "C" fn start() -> usize { let data = 0x1234usize as *mut u8; // Something to recognize unsafe { - core::intrinsics::catch_unwind(|data: *mut u8| { - let _log_on_drop = LogOnDrop; + core::intrinsics::catch_unwind( + |data: *mut u8| { + let _log_on_drop = LogOnDrop; - logging::log_str(&alloc::format!("`r#try` called with ptr {:?}", data)); - let x = [12]; - let _ = x[4]; // should panic + logging::log_str(&alloc::format!("`r#try` called with ptr {:?}", data)); + let x = [12]; + let _ = x[4]; // should panic - logging::log_str("This line should not be visible! :("); - }, data, |data, exception| { - let exception = *Box::from_raw(exception as *mut String); - logging::log_str("Caught something!"); - logging::log_str(&alloc::format!(" data : {:?}", data)); - logging::log_str(&alloc::format!(" exception: {:?}", exception)); - }); + logging::log_str("This line should not be visible! :("); + }, + data, + |data, exception| { + let exception = *Box::from_raw(exception as *mut String); + logging::log_str("Caught something!"); + logging::log_str(&alloc::format!(" data : {:?}", data)); + logging::log_str(&alloc::format!(" exception: {:?}", exception)); + }, + ); } logging::log_str("This program terminates correctly."); diff --git a/tests/run-make/wasm-exceptions-nostd/src/panicking.rs b/tests/run-make/wasm-exceptions-nostd/src/panicking.rs index 4a8923fd43db..52a32f3cd303 100644 --- a/tests/run-make/wasm-exceptions-nostd/src/panicking.rs +++ b/tests/run-make/wasm-exceptions-nostd/src/panicking.rs @@ -17,10 +17,7 @@ fn panic_handler(info: &core::panic::PanicInfo<'_>) -> ! { use alloc::boxed::Box; use alloc::string::ToString; - let msg = info - .message() - .map(|msg| msg.to_string()) - .unwrap_or("(no message)".to_string()); + let msg = info.message().map(|msg| msg.to_string()).unwrap_or("(no message)".to_string()); let exception = Box::new(msg.to_string()); unsafe { let exception_raw = Box::into_raw(exception); diff --git a/tests/run-make/wasm-export-all-symbols/bar.rs b/tests/run-make/wasm-export-all-symbols/bar.rs index ac9c20a57e5a..039291f902e5 100644 --- a/tests/run-make/wasm-export-all-symbols/bar.rs +++ b/tests/run-make/wasm-export-all-symbols/bar.rs @@ -1,7 +1,7 @@ #![crate_type = "rlib"] #[no_mangle] -pub extern fn foo() {} +pub extern "C" fn foo() {} #[no_mangle] pub static FOO: u64 = 42; diff --git a/tests/run-make/wasm-symbols-not-exported/bar.rs b/tests/run-make/wasm-symbols-not-exported/bar.rs index 6ffbd3ec6900..dd4d14416e70 100644 --- a/tests/run-make/wasm-symbols-not-exported/bar.rs +++ b/tests/run-make/wasm-symbols-not-exported/bar.rs @@ -11,15 +11,14 @@ unsafe impl GlobalAlloc for B { 1 as *mut u8 } - unsafe fn dealloc(&self, ptr: *mut u8, x: Layout) { - } + unsafe fn dealloc(&self, ptr: *mut u8, x: Layout) {} } #[global_allocator] static A: B = B; #[no_mangle] -pub extern fn foo(a: u32) -> u32 { +pub extern "C" fn foo(a: u32) -> u32 { assert_eq!(a, 3); a * 2 } diff --git a/tests/run-make/wasm-symbols-not-exported/foo.rs b/tests/run-make/wasm-symbols-not-exported/foo.rs index d46baee01b96..f85103f35354 100644 --- a/tests/run-make/wasm-symbols-not-exported/foo.rs +++ b/tests/run-make/wasm-symbols-not-exported/foo.rs @@ -1,7 +1,7 @@ #![crate_type = "cdylib"] #[no_mangle] -pub extern fn foo() { +pub extern "C" fn foo() { println!("foo"); panic!("test"); } diff --git a/tests/run-make/wasm-symbols-not-imported/foo.rs b/tests/run-make/wasm-symbols-not-imported/foo.rs index b25bdc9800d1..6af8d50a2ace 100644 --- a/tests/run-make/wasm-symbols-not-imported/foo.rs +++ b/tests/run-make/wasm-symbols-not-imported/foo.rs @@ -4,7 +4,7 @@ use core::panic::PanicInfo; #[no_mangle] -pub extern fn foo() { +pub extern "C" fn foo() { panic!() } diff --git a/tests/run-make/windows-spawn/spawn.rs b/tests/run-make/windows-spawn/spawn.rs index a9e86d1577e5..4afbaf876cd0 100644 --- a/tests/run-make/windows-spawn/spawn.rs +++ b/tests/run-make/windows-spawn/spawn.rs @@ -6,5 +6,5 @@ fn main() { assert_eq!( Command::new("hopefullydoesntexist").arg("bar").spawn().unwrap_err().kind(), ErrorKind::NotFound - ) + ); } diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/build.rs b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/build.rs index 3a7aa1be868c..f1fb58039485 100644 --- a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/build.rs +++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/build.rs @@ -1,17 +1,9 @@ fn main() { - cc::Build::new() - .file("foo.c") - .compile("foo_c"); + cc::Build::new().file("foo.c").compile("foo_c"); - cc::Build::new() - .file("foo_asm.s") - .compile("foo_asm"); + cc::Build::new().file("foo_asm.s").compile("foo_asm"); - cc::Build::new() - .cpp(true) - .cpp_set_stdlib(None) - .file("foo_cxx.cpp") - .compile("foo_cxx"); + cc::Build::new().cpp(true).cpp_set_stdlib(None).file("foo_cxx.cpp").compile("foo_cxx"); // When the cmake crate detects the clang compiler, it passes the // "--target" argument to the linker which subsequently fails. The @@ -20,11 +12,11 @@ fn main() { // `CMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY` can be used // https://cmake.org/cmake/help/v3.5/module/CMakeForceCompiler.html let dst = cmake::Config::new("libcmake_foo") - .build_target("cmake_foo") - .define("CMAKE_C_COMPILER_FORCED", "1") - .define("CMAKE_CXX_COMPILER_FORCED", "1") - .define("CMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY", "1") - .build(); + .build_target("cmake_foo") + .define("CMAKE_C_COMPILER_FORCED", "1") + .define("CMAKE_CXX_COMPILER_FORCED", "1") + .define("CMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY", "1") + .build(); println!("cargo:rustc-link-search=native={}/build/", dst.display()); println!("cargo:rustc-link-lib=static=cmake_foo"); } From d71a015d01bd9a2b0fdec502aa2c738e4270bf62 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 29 May 2024 15:06:29 +1000 Subject: [PATCH 123/211] Explain why we don't run rustfmt on `tests/debuginfo/`. --- rustfmt.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rustfmt.toml b/rustfmt.toml index dfc41819968a..beb33467b48c 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -16,7 +16,7 @@ ignore = [ # - some require special comments in a particular position (e.g. `EMIT_MIR` comments) "/tests/codegen/simd-intrinsic/", # Many types like `u8x64` are better hand-formatted. "/tests/crashes/", # Many tests contain syntax errors. - "/tests/debuginfo/", + "/tests/debuginfo/", # Tests are somewhat sensitive to source code layout. "/tests/incremental/", "/tests/mir-opt/", "/tests/pretty/", From 0ea498aa9fc7ddf696d53fe961d30e63e4d38438 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 29 May 2024 15:10:38 +1000 Subject: [PATCH 124/211] Explain why we don't run rustfmt on `tests/incremental/`. --- rustfmt.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rustfmt.toml b/rustfmt.toml index beb33467b48c..2b502cf9bc6f 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -17,7 +17,7 @@ ignore = [ "/tests/codegen/simd-intrinsic/", # Many types like `u8x64` are better hand-formatted. "/tests/crashes/", # Many tests contain syntax errors. "/tests/debuginfo/", # Tests are somewhat sensitive to source code layout. - "/tests/incremental/", + "/tests/incremental/", # Tests are somewhat sensitive to source code layout. "/tests/mir-opt/", "/tests/pretty/", "/tests/run-make/translation/test.rs", # Contains syntax errors. From 9abfebdf1e3eb821d160673d0fbd1d58b310b4e6 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 30 May 2024 16:06:14 +1000 Subject: [PATCH 125/211] Add an alternate `--demangle` mode to coverage-dump The coverage-dump tool already needs `rustc_demangle` for its own purposes, so the amount of extra code needed for a demangle mode is very small. --- src/tools/coverage-dump/README.md | 5 +++++ src/tools/coverage-dump/src/main.rs | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/tools/coverage-dump/README.md b/src/tools/coverage-dump/README.md index e2625d5adf27..49d8e14c7bcc 100644 --- a/src/tools/coverage-dump/README.md +++ b/src/tools/coverage-dump/README.md @@ -6,3 +6,8 @@ The output format is mostly arbitrary, so it's OK to change the output as long as any affected tests are also re-blessed. However, the output should be consistent across different executions on different platforms, so avoid printing any information that is platform-specific or non-deterministic. + +## Demangle mode + +When run as `coverage-dump --demangle`, this tool instead functions as a +command-line demangler that can be invoked by `llvm-cov`. diff --git a/src/tools/coverage-dump/src/main.rs b/src/tools/coverage-dump/src/main.rs index 93fed1799e04..b21e3e292f2b 100644 --- a/src/tools/coverage-dump/src/main.rs +++ b/src/tools/coverage-dump/src/main.rs @@ -7,6 +7,13 @@ fn main() -> anyhow::Result<()> { let args = std::env::args().collect::>(); + // The coverage-dump tool already needs `rustc_demangle` in order to read + // coverage metadata, so it's very easy to also have a separate mode that + // turns it into a command-line demangler for use by coverage-run tests. + if &args[1..] == &["--demangle"] { + return demangle(); + } + let llvm_ir_path = args.get(1).context("LLVM IR file not specified")?; let llvm_ir = std::fs::read_to_string(llvm_ir_path).context("couldn't read LLVM IR file")?; @@ -15,3 +22,15 @@ fn main() -> anyhow::Result<()> { Ok(()) } + +fn demangle() -> anyhow::Result<()> { + use std::fmt::Write as _; + + let stdin = std::io::read_to_string(std::io::stdin())?; + let mut output = String::with_capacity(stdin.len()); + for line in stdin.lines() { + writeln!(output, "{:#}", rustc_demangle::demangle(line))?; + } + print!("{output}"); + Ok(()) +} From 10ffc228a851489b1678d830517541bd00d4da49 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 30 May 2024 16:21:42 +1000 Subject: [PATCH 126/211] Use `coverage-dump --demangle` as the demangler for coverage-run tests This avoids the need to build `rust-demangler` when running coverage tests, since we typically need to build `coverage-dump` anyway. --- src/bootstrap/src/core/build_steps/test.rs | 13 +------------ src/tools/compiletest/src/runtest/coverage.rs | 17 ++++++++++++----- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 215886863624..76302a7900de 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1781,7 +1781,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the .arg(builder.ensure(tool::JsonDocLint { compiler: json_compiler, target })); } - if mode == "coverage-map" { + if matches!(mode, "coverage-map" | "coverage-run") { let coverage_dump = builder.ensure(tool::CoverageDump { compiler: compiler.with_stage(0), target: compiler.host, @@ -1789,17 +1789,6 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the cmd.arg("--coverage-dump-path").arg(coverage_dump); } - if mode == "coverage-run" { - // The demangler doesn't need the current compiler, so we can avoid - // unnecessary rebuilds by using the bootstrap compiler instead. - let rust_demangler = builder.ensure(tool::RustDemangler { - compiler: compiler.with_stage(0), - target: compiler.host, - extra_features: Vec::new(), - }); - cmd.arg("--rust-demangler-path").arg(rust_demangler); - } - cmd.arg("--src-base").arg(builder.src.join("tests").join(suite)); cmd.arg("--build-base").arg(testdir(builder, compiler.host).join(suite)); diff --git a/src/tools/compiletest/src/runtest/coverage.rs b/src/tools/compiletest/src/runtest/coverage.rs index dad3fb301333..8bd7c7e808d3 100644 --- a/src/tools/compiletest/src/runtest/coverage.rs +++ b/src/tools/compiletest/src/runtest/coverage.rs @@ -10,10 +10,15 @@ use crate::common::{UI_COVERAGE, UI_COVERAGE_MAP}; use crate::runtest::{static_regex, Emit, ProcRes, TestCx, WillExecute}; impl<'test> TestCx<'test> { + fn coverage_dump_path(&self) -> &Path { + self.config + .coverage_dump_path + .as_deref() + .unwrap_or_else(|| self.fatal("missing --coverage-dump")) + } + pub(crate) fn run_coverage_map_test(&self) { - let Some(coverage_dump_path) = &self.config.coverage_dump_path else { - self.fatal("missing --coverage-dump"); - }; + let coverage_dump_path = self.coverage_dump_path(); let (proc_res, llvm_ir_path) = self.compile_test_and_save_ir(); if !proc_res.status.success() { @@ -102,8 +107,10 @@ impl<'test> TestCx<'test> { let proc_res = self.run_llvm_tool("llvm-cov", |cmd| { cmd.args(["show", "--format=text", "--show-line-counts-or-regions"]); - cmd.arg("--Xdemangler"); - cmd.arg(self.config.rust_demangler_path.as_ref().unwrap()); + // Specify the demangler binary and its arguments. + let coverage_dump_path = self.coverage_dump_path(); + cmd.arg("--Xdemangler").arg(coverage_dump_path); + cmd.arg("--Xdemangler").arg("--demangle"); cmd.arg("--instr-profile"); cmd.arg(&profdata_path); From feb8f3cc5d0728db5038de151f02bac540dc713a Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 30 May 2024 17:15:36 +1000 Subject: [PATCH 127/211] Use `Builder::tool_exe` to build the coverage-dump tool This appears to be the canonical way to build a tool with the stage 0 compiler. --- src/bootstrap/src/core/build_steps/test.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 76302a7900de..29b3d1669b4b 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1782,10 +1782,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the } if matches!(mode, "coverage-map" | "coverage-run") { - let coverage_dump = builder.ensure(tool::CoverageDump { - compiler: compiler.with_stage(0), - target: compiler.host, - }); + let coverage_dump = builder.tool_exe(Tool::CoverageDump); cmd.arg("--coverage-dump-path").arg(coverage_dump); } From 54b6849e06cc4847625cdf6a7312eb017786867f Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 30 May 2024 17:22:02 +1000 Subject: [PATCH 128/211] Remove unused rust-demangler support from compiletest --- src/tools/compiletest/src/common.rs | 3 --- src/tools/compiletest/src/lib.rs | 3 --- src/tools/compiletest/src/runtest.rs | 4 ---- 3 files changed, 10 deletions(-) diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 7ff45edd4b26..b0047770564c 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -187,9 +187,6 @@ pub struct Config { /// The rustdoc executable. pub rustdoc_path: Option, - /// The rust-demangler executable. - pub rust_demangler_path: Option, - /// The coverage-dump executable. pub coverage_dump_path: Option, diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 99bde107f3a4..62e71e9b59dd 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -46,7 +46,6 @@ pub fn parse_config(args: Vec) -> Config { .reqopt("", "run-lib-path", "path to target shared libraries", "PATH") .reqopt("", "rustc-path", "path to rustc to use for compiling", "PATH") .optopt("", "rustdoc-path", "path to rustdoc to use for compiling", "PATH") - .optopt("", "rust-demangler-path", "path to rust-demangler to use in tests", "PATH") .optopt("", "coverage-dump-path", "path to coverage-dump to use in tests", "PATH") .reqopt("", "python", "path to python to use for doc tests", "PATH") .optopt("", "jsondocck-path", "path to jsondocck to use for doc tests", "PATH") @@ -232,7 +231,6 @@ pub fn parse_config(args: Vec) -> Config { run_lib_path: make_absolute(opt_path(matches, "run-lib-path")), rustc_path: opt_path(matches, "rustc-path"), rustdoc_path: matches.opt_str("rustdoc-path").map(PathBuf::from), - rust_demangler_path: matches.opt_str("rust-demangler-path").map(PathBuf::from), coverage_dump_path: matches.opt_str("coverage-dump-path").map(PathBuf::from), python: matches.opt_str("python").unwrap(), jsondocck_path: matches.opt_str("jsondocck-path"), @@ -337,7 +335,6 @@ pub fn log_config(config: &Config) { logv(c, format!("run_lib_path: {:?}", config.run_lib_path)); logv(c, format!("rustc_path: {:?}", config.rustc_path.display())); logv(c, format!("rustdoc_path: {:?}", config.rustdoc_path)); - logv(c, format!("rust_demangler_path: {:?}", config.rust_demangler_path)); logv(c, format!("src_base: {:?}", config.src_base.display())); logv(c, format!("build_base: {:?}", config.build_base.display())); logv(c, format!("stage_id: {}", config.stage_id)); diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 4ea12a0f9e48..79e158992d47 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -3561,10 +3561,6 @@ impl<'test> TestCx<'test> { cmd.env("RUSTDOC", cwd.join(rustdoc)); } - if let Some(ref rust_demangler) = self.config.rust_demangler_path { - cmd.env("RUST_DEMANGLER", cwd.join(rust_demangler)); - } - if let Some(ref node) = self.config.nodejs { cmd.env("NODE", node); } From 20699fe6b23615cac13e4661b755fde2b4f36822 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 30 May 2024 11:51:06 -0400 Subject: [PATCH 129/211] Stop using translate_args in the new solver --- .../src/solve/eval_ctxt/mod.rs | 11 -- .../src/solve/normalizes_to/mod.rs | 123 +++++++++++------- ...-constraining-predicates-ambig.next.stderr | 12 ++ ...-requires-constraining-predicates-ambig.rs | 29 +++++ ...res-constraining-predicates.current.stderr | 12 ++ ...quires-constraining-predicates.next.stderr | 12 ++ ...e-impl-requires-constraining-predicates.rs | 24 ++++ 7 files changed, 167 insertions(+), 56 deletions(-) create mode 100644 tests/ui/specialization/source-impl-requires-constraining-predicates-ambig.next.stderr create mode 100644 tests/ui/specialization/source-impl-requires-constraining-predicates-ambig.rs create mode 100644 tests/ui/specialization/source-impl-requires-constraining-predicates.current.stderr create mode 100644 tests/ui/specialization/source-impl-requires-constraining-predicates.next.stderr create mode 100644 tests/ui/specialization/source-impl-requires-constraining-predicates.rs diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs index b18b59d9a752..f18f1f4f8f0d 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -12,7 +12,6 @@ use rustc_middle::bug; use rustc_middle::traits::solve::{ inspect, CanonicalInput, CanonicalResponse, Certainty, PredefinedOpaquesData, QueryResult, }; -use rustc_middle::traits::specialization_graph; use rustc_middle::ty::AliasRelationDirection; use rustc_middle::ty::TypeFolder; use rustc_middle::ty::{ @@ -900,16 +899,6 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { args } - pub(super) fn translate_args( - &self, - param_env: ty::ParamEnv<'tcx>, - source_impl: DefId, - source_args: ty::GenericArgsRef<'tcx>, - target_node: specialization_graph::Node, - ) -> ty::GenericArgsRef<'tcx> { - crate::traits::translate_args(self.infcx, param_env, source_impl, source_args, target_node) - } - pub(super) fn register_ty_outlives(&self, ty: Ty<'tcx>, lt: ty::Region<'tcx>) { self.infcx.register_region_obligation_with_cause(ty, lt, &ObligationCause::dummy()); } diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs index 22a77e2ecb8d..8c63bd824bc0 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs @@ -1,4 +1,4 @@ -use crate::traits::specialization_graph; +use crate::traits::specialization_graph::{self, LeafDef, Node}; use super::assembly::structural_traits::AsyncCallableRelevantTypes; use super::assembly::{self, structural_traits, Candidate}; @@ -9,7 +9,6 @@ use rustc_infer::infer::InferCtxt; use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::solve::inspect::ProbeKind; use rustc_infer::traits::solve::MaybeCause; -use rustc_infer::traits::specialization_graph::LeafDef; use rustc_infer::traits::Reveal; use rustc_middle::traits::solve::{CandidateSource, Certainty, Goal, QueryResult}; use rustc_middle::traits::BuiltinImplSource; @@ -189,8 +188,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { // In case the associated item is hidden due to specialization, we have to // return ambiguity this would otherwise be incomplete, resulting in // unsoundness during coherence (#105782). - let Some(assoc_def) = fetch_eligible_assoc_item_def( - ecx, + let Some(assoc_def) = ecx.fetch_eligible_assoc_item_def( goal.param_env, goal_trait_ref, goal.predicate.def_id(), @@ -235,16 +233,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { // // And then map these args to the args of the defining impl of `Assoc`, going // from `[u32, u64]` to `[u32, i32, u64]`. - let impl_args_with_gat = - goal.predicate.alias.args.rebase_onto(tcx, goal_trait_ref.def_id, impl_args); - let args = ecx.translate_args( - goal.param_env, - impl_def_id, - impl_args_with_gat, - assoc_def.defining_node, - ); + let associated_item_args = + ecx.translate_args(&assoc_def, goal, impl_def_id, impl_args, impl_trait_ref)?; - if !tcx.check_args_compatible(assoc_def.item.def_id, args) { + if !tcx.check_args_compatible(assoc_def.item.def_id, associated_item_args) { return error_response( ecx, "associated item has mismatched generic item arguments", @@ -272,7 +264,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { ty::AssocKind::Fn => unreachable!("we should never project to a fn"), }; - ecx.instantiate_normalizes_to_term(goal, term.instantiate(tcx, args)); + ecx.instantiate_normalizes_to_term(goal, term.instantiate(tcx, associated_item_args)); ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) } @@ -889,38 +881,79 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { } } -/// This behavior is also implemented in `rustc_ty_utils` and in the old `project` code. -/// -/// FIXME: We should merge these 3 implementations as it's likely that they otherwise -/// diverge. -#[instrument(level = "trace", skip(ecx, param_env), ret)] -fn fetch_eligible_assoc_item_def<'tcx>( - ecx: &EvalCtxt<'_, InferCtxt<'tcx>>, - param_env: ty::ParamEnv<'tcx>, - goal_trait_ref: ty::TraitRef<'tcx>, - trait_assoc_def_id: DefId, - impl_def_id: DefId, -) -> Result, NoSolution> { - let node_item = - specialization_graph::assoc_def(ecx.interner(), impl_def_id, trait_assoc_def_id) - .map_err(|ErrorGuaranteed { .. }| NoSolution)?; +impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { + fn translate_args( + &mut self, + assoc_def: &LeafDef, + goal: Goal<'tcx, ty::NormalizesTo<'tcx>>, + impl_def_id: DefId, + impl_args: ty::GenericArgsRef<'tcx>, + impl_trait_ref: rustc_type_ir::TraitRef>, + ) -> Result, NoSolution> { + let tcx = self.interner(); + Ok(match assoc_def.defining_node { + Node::Trait(_) => goal.predicate.alias.args, + Node::Impl(target_impl_def_id) => { + if target_impl_def_id == impl_def_id { + // Same impl, no need to fully translate, just a rebase from + // the trait is sufficient. + goal.predicate.alias.args.rebase_onto(tcx, impl_trait_ref.def_id, impl_args) + } else { + let target_args = self.fresh_args_for_item(target_impl_def_id); + let target_trait_ref = tcx + .impl_trait_ref(target_impl_def_id) + .unwrap() + .instantiate(tcx, target_args); + // Relate source impl to target impl by equating trait refs. + self.eq(goal.param_env, impl_trait_ref, target_trait_ref)?; + // Also add predicates since they may be needed to constrain the + // target impl's params. + self.add_goals( + GoalSource::Misc, + tcx.predicates_of(target_impl_def_id) + .instantiate(tcx, target_args) + .into_iter() + .map(|(pred, _)| goal.with(tcx, pred)), + ); + goal.predicate.alias.args.rebase_onto(tcx, impl_trait_ref.def_id, target_args) + } + } + }) + } - let eligible = if node_item.is_final() { - // Non-specializable items are always projectable. - true - } else { - // Only reveal a specializable default if we're past type-checking - // and the obligation is monomorphic, otherwise passes such as - // transmute checking and polymorphic MIR optimizations could - // get a result which isn't correct for all monomorphizations. - if param_env.reveal() == Reveal::All { - let poly_trait_ref = ecx.resolve_vars_if_possible(goal_trait_ref); - !poly_trait_ref.still_further_specializable() + /// This behavior is also implemented in `rustc_ty_utils` and in the old `project` code. + /// + /// FIXME: We should merge these 3 implementations as it's likely that they otherwise + /// diverge. + #[instrument(level = "trace", skip(self, param_env), ret)] + fn fetch_eligible_assoc_item_def( + &self, + param_env: ty::ParamEnv<'tcx>, + goal_trait_ref: ty::TraitRef<'tcx>, + trait_assoc_def_id: DefId, + impl_def_id: DefId, + ) -> Result, NoSolution> { + let node_item = + specialization_graph::assoc_def(self.interner(), impl_def_id, trait_assoc_def_id) + .map_err(|ErrorGuaranteed { .. }| NoSolution)?; + + let eligible = if node_item.is_final() { + // Non-specializable items are always projectable. + true } else { - trace!(?node_item.item.def_id, "not eligible due to default"); - false - } - }; + // Only reveal a specializable default if we're past type-checking + // and the obligation is monomorphic, otherwise passes such as + // transmute checking and polymorphic MIR optimizations could + // get a result which isn't correct for all monomorphizations. + if param_env.reveal() == Reveal::All { + let poly_trait_ref = self.resolve_vars_if_possible(goal_trait_ref); + !poly_trait_ref.still_further_specializable() + } else { + trace!(?node_item.item.def_id, "not eligible due to default"); + false + } + }; - if eligible { Ok(Some(node_item)) } else { Ok(None) } + if eligible { Ok(Some(node_item)) } else { Ok(None) } + } } diff --git a/tests/ui/specialization/source-impl-requires-constraining-predicates-ambig.next.stderr b/tests/ui/specialization/source-impl-requires-constraining-predicates-ambig.next.stderr new file mode 100644 index 000000000000..17918a77821d --- /dev/null +++ b/tests/ui/specialization/source-impl-requires-constraining-predicates-ambig.next.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/source-impl-requires-constraining-predicates-ambig.rs:14: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 + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/source-impl-requires-constraining-predicates-ambig.rs b/tests/ui/specialization/source-impl-requires-constraining-predicates-ambig.rs new file mode 100644 index 000000000000..977493c885b2 --- /dev/null +++ b/tests/ui/specialization/source-impl-requires-constraining-predicates-ambig.rs @@ -0,0 +1,29 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] check-pass +//@[current] known-bug: unknown +//@[current] failure-status: 101 +//@[current] dont-check-compiler-stderr + +// Tests that rebasing from the concrete impl to the default impl also processes the +// `[u32; 0]: IntoIterator` predicate to constrain the `?U` impl arg. +// This test also makes sure that we don't do anything weird when rebasing the args +// is ambiguous. + +#![feature(specialization)] +//[next]~^ WARN the feature `specialization` is incomplete + +trait Spec { + type Assoc; +} + +default impl Spec for T where T: IntoIterator { + type Assoc = U; +} + +impl Spec for [T; 0] {} + +fn main() { + let x: <[_; 0] as Spec>::Assoc = 1; +} diff --git a/tests/ui/specialization/source-impl-requires-constraining-predicates.current.stderr b/tests/ui/specialization/source-impl-requires-constraining-predicates.current.stderr new file mode 100644 index 000000000000..3442e5b5ca61 --- /dev/null +++ b/tests/ui/specialization/source-impl-requires-constraining-predicates.current.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/source-impl-requires-constraining-predicates.rs:9: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 + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/source-impl-requires-constraining-predicates.next.stderr b/tests/ui/specialization/source-impl-requires-constraining-predicates.next.stderr new file mode 100644 index 000000000000..3442e5b5ca61 --- /dev/null +++ b/tests/ui/specialization/source-impl-requires-constraining-predicates.next.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/source-impl-requires-constraining-predicates.rs:9: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 + +warning: 1 warning emitted + diff --git a/tests/ui/specialization/source-impl-requires-constraining-predicates.rs b/tests/ui/specialization/source-impl-requires-constraining-predicates.rs new file mode 100644 index 000000000000..532fc3676406 --- /dev/null +++ b/tests/ui/specialization/source-impl-requires-constraining-predicates.rs @@ -0,0 +1,24 @@ +//@ check-pass +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +// Tests that rebasing from the concrete impl to the default impl also processes the +// `[u32; 0]: IntoIterator` predicate to constrain the `?U` impl arg. + +#![feature(specialization)] +//~^ WARN the feature `specialization` is incomplete + +trait Spec { + type Assoc; +} + +default impl Spec for T where T: IntoIterator { + type Assoc = U; +} + +impl Spec for [T; 0] {} + +fn main() { + let x: <[u32; 0] as Spec>::Assoc = 1; +} From a7e7848833d7a5a3f26249603ba3545ab18e7431 Mon Sep 17 00:00:00 2001 From: Urgau Date: Fri, 31 May 2024 17:02:27 +0200 Subject: [PATCH 130/211] Refactor --print=check-cfg test --- tests/run-make/print-check-cfg/rmake.rs | 150 ++++++++++++++---------- 1 file changed, 86 insertions(+), 64 deletions(-) diff --git a/tests/run-make/print-check-cfg/rmake.rs b/tests/run-make/print-check-cfg/rmake.rs index f7f5fcf2340b..2d5221644265 100644 --- a/tests/run-make/print-check-cfg/rmake.rs +++ b/tests/run-make/print-check-cfg/rmake.rs @@ -8,61 +8,70 @@ use std::ops::Deref; use run_make_support::rustc; +struct CheckCfg { + args: &'static [&'static str], + contains: Contains, +} + +enum Contains { + Some { contains: &'static [&'static str], doesnt_contain: &'static [&'static str] }, + Only(&'static str), +} + fn main() { - check( - /*args*/ &[], - /*has_any*/ false, - /*has_any_any*/ true, - /*contains*/ &[], - ); - check( - /*args*/ &["--check-cfg=cfg()"], - /*has_any*/ false, - /*has_any_any*/ false, - /*contains*/ &["unix", "miri"], - ); - check( - /*args*/ &["--check-cfg=cfg(any())"], - /*has_any*/ true, - /*has_any_any*/ false, - /*contains*/ &["windows", "test"], - ); - check( - /*args*/ &["--check-cfg=cfg(feature)"], - /*has_any*/ false, - /*has_any_any*/ false, - /*contains*/ &["unix", "miri", "feature"], - ); - check( - /*args*/ &[r#"--check-cfg=cfg(feature, values(none(), "", "test", "lol"))"#], - /*has_any*/ false, - /*has_any_any*/ false, - /*contains*/ &["feature", "feature=\"\"", "feature=\"test\"", "feature=\"lol\""], - ); - check( - /*args*/ - &[ + check(CheckCfg { args: &[], contains: Contains::Only("any()=any()") }); + check(CheckCfg { + args: &["--check-cfg=cfg()"], + contains: Contains::Some { + contains: &["unix", "miri"], + doesnt_contain: &["any()", "any()=any()"], + }, + }); + check(CheckCfg { + args: &["--check-cfg=cfg(any())"], + contains: Contains::Some { + contains: &["any()", "unix", r#"target_feature="crt-static""#], + doesnt_contain: &["any()=any()"], + }, + }); + check(CheckCfg { + args: &["--check-cfg=cfg(feature)"], + contains: Contains::Some { + contains: &["unix", "miri", "feature"], + doesnt_contain: &["any()", "any()=any()", "feature=none()", "feature="], + }, + }); + check(CheckCfg { + args: &[r#"--check-cfg=cfg(feature, values(none(), "", "test", "lol"))"#], + contains: Contains::Some { + contains: &["feature", "feature=\"\"", "feature=\"test\"", "feature=\"lol\""], + doesnt_contain: &["any()", "any()=any()", "feature=none()", "feature="], + }, + }); + check(CheckCfg { + args: &[ r#"--check-cfg=cfg(feature, values(any()))"#, r#"--check-cfg=cfg(feature, values("tmp"))"#, ], - /*has_any*/ false, - /*has_any_any*/ false, - /*contains*/ &["unix", "miri", "feature=any()"], - ); - check( - /*args*/ - &[ + contains: Contains::Some { + contains: &["unix", "miri", "feature=any()"], + doesnt_contain: &["any()", "any()=any()", "feature", "feature=", "feature=\"tmp\""], + }, + }); + check(CheckCfg { + args: &[ r#"--check-cfg=cfg(has_foo, has_bar)"#, r#"--check-cfg=cfg(feature, values("tmp"))"#, r#"--check-cfg=cfg(feature, values("tmp"))"#, ], - /*has_any*/ false, - /*has_any_any*/ false, - /*contains*/ &["has_foo", "has_bar", "feature=\"tmp\""], - ); + contains: Contains::Some { + contains: &["has_foo", "has_bar", "feature=\"tmp\""], + doesnt_contain: &["any()", "any()=any()", "feature"], + }, + }); } -fn check(args: &[&str], has_any: bool, has_any_any: bool, contains: &[&str]) { +fn check(CheckCfg { args, contains }: CheckCfg) { let output = rustc() .input("lib.rs") .arg("-Zunstable-options") @@ -72,18 +81,11 @@ fn check(args: &[&str], has_any: bool, has_any_any: bool, contains: &[&str]) { let stdout = String::from_utf8(output.stdout).unwrap(); - let mut found_any = false; - let mut found_any_any = false; let mut found = HashSet::::new(); - let mut recorded = HashSet::::new(); for l in stdout.lines() { assert!(l == l.trim()); - if l == "any()" { - found_any = true; - } else if l == "any()=any()" { - found_any_any = true; - } else if let Some((left, right)) = l.split_once('=') { + if let Some((left, right)) = l.split_once('=') { if right != "any()" && right != "" { assert!(right.starts_with("\"")); assert!(right.ends_with("\"")); @@ -92,17 +94,37 @@ fn check(args: &[&str], has_any: bool, has_any_any: bool, contains: &[&str]) { } else { assert!(!l.contains("\"")); } - assert!(recorded.insert(l.to_string()), "{}", &l); - if contains.contains(&l) { - assert!(found.insert(l.to_string()), "{}", &l); - } + assert!(found.insert(l.to_string()), "{}", &l); } - let should_found = HashSet::::from_iter(contains.iter().map(|s| s.to_string())); - let diff: Vec<_> = should_found.difference(&found).collect(); - - assert_eq!(found_any, has_any); - assert_eq!(found_any_any, has_any_any); - assert_eq!(found_any_any, recorded.len() == 1); - assert!(diff.is_empty(), "{:?} != {:?} (~ {:?})", &should_found, &found, &diff); + match contains { + Contains::Some { contains, doesnt_contain } => { + { + let should_found = + HashSet::::from_iter(contains.iter().map(|s| s.to_string())); + let diff: Vec<_> = should_found.difference(&found).collect(); + assert!( + diff.is_empty(), + "should found: {:?}, didn't found {:?}", + &should_found, + &diff + ); + } + { + let should_not_find = + HashSet::::from_iter(doesnt_contain.iter().map(|s| s.to_string())); + let diff: Vec<_> = should_not_find.intersection(&found).collect(); + assert!( + diff.is_empty(), + "should not find {:?}, did found {:?}", + &should_not_find, + &diff + ); + } + } + Contains::Only(only) => { + assert!(found.contains(&only.to_string()), "{:?} != {:?}", &only, &found); + assert!(found.len() == 1, "len: {}, instead of 1", found.len()); + } + } } From fa3835c4196f83a644c14baf8d410a885b1abedc Mon Sep 17 00:00:00 2001 From: Luke Franceschini Date: Fri, 31 May 2024 11:24:26 -0400 Subject: [PATCH 131/211] docs: Missing word typo --- src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs b/src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs index fab62e95d19a..c19f19803f17 100644 --- a/src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs +++ b/src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs @@ -16,7 +16,7 @@ use crate::{ // // This is the same as `Go to Definition` with the following exceptions: // - outline modules will navigate to the `mod name;` item declaration -// - trait assoc items will navigate to the assoc item of the trait declaration opposed to the trait impl +// - trait assoc items will navigate to the assoc item of the trait declaration as opposed to the trait impl // - fields in patterns will navigate to the field declaration of the struct, union or variant pub(crate) fn goto_declaration( db: &RootDatabase, From d3c8e6788cfbcc64ab7710cab7a56e276e7d5a7a Mon Sep 17 00:00:00 2001 From: Luv-Ray Date: Sat, 1 Jun 2024 09:40:46 +0800 Subject: [PATCH 132/211] check index `value <= 0xFFFF_FF00` --- .../rustc_mir_transform/src/known_panics_lint.rs | 8 ++++++-- tests/crashes/121126.rs | 4 ---- tests/ui/indexing/index-bounds.rs | 10 ++++++++++ tests/ui/indexing/index-bounds.stderr | 16 ++++++++++++++++ 4 files changed, 32 insertions(+), 6 deletions(-) delete mode 100644 tests/crashes/121126.rs create mode 100644 tests/ui/indexing/index-bounds.rs create mode 100644 tests/ui/indexing/index-bounds.stderr diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs index 9ba22870403f..8b46658b3225 100644 --- a/compiler/rustc_mir_transform/src/known_panics_lint.rs +++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs @@ -102,8 +102,12 @@ impl<'tcx> Value<'tcx> { } (PlaceElem::Index(idx), Value::Aggregate { fields, .. }) => { let idx = prop.get_const(idx.into())?.immediate()?; - let idx = prop.ecx.read_target_usize(idx).ok()?; - fields.get(FieldIdx::from_u32(idx.try_into().ok()?)).unwrap_or(&Value::Uninit) + let idx = prop.ecx.read_target_usize(idx).ok()?.try_into().ok()?; + if idx <= FieldIdx::MAX_AS_U32 { + fields.get(FieldIdx::from_u32(idx)).unwrap_or(&Value::Uninit) + } else { + return None; + } } ( PlaceElem::ConstantIndex { offset, min_length: _, from_end: false }, diff --git a/tests/crashes/121126.rs b/tests/crashes/121126.rs deleted file mode 100644 index 2ebe91f02ded..000000000000 --- a/tests/crashes/121126.rs +++ /dev/null @@ -1,4 +0,0 @@ -//@ known-bug: #121126 -fn main() { - let _n = 1i64 >> [64][4_294_967_295]; -} diff --git a/tests/ui/indexing/index-bounds.rs b/tests/ui/indexing/index-bounds.rs new file mode 100644 index 000000000000..2b318beeeaa7 --- /dev/null +++ b/tests/ui/indexing/index-bounds.rs @@ -0,0 +1,10 @@ +//@ build-fail + +fn main() { + let _n = [64][200]; + //~^ ERROR this operation will panic at runtime [unconditional_panic] + + // issue #121126, test index value between 0xFFFF_FF00 and u32::MAX + let _n = [64][u32::MAX as usize - 1]; + //~^ ERROR this operation will panic at runtime [unconditional_panic] +} diff --git a/tests/ui/indexing/index-bounds.stderr b/tests/ui/indexing/index-bounds.stderr new file mode 100644 index 000000000000..51d8c7567a46 --- /dev/null +++ b/tests/ui/indexing/index-bounds.stderr @@ -0,0 +1,16 @@ +error: this operation will panic at runtime + --> $DIR/index-bounds.rs:4:14 + | +LL | let _n = [64][200]; + | ^^^^^^^^^ index out of bounds: the length is 1 but the index is 200 + | + = note: `#[deny(unconditional_panic)]` on by default + +error: this operation will panic at runtime + --> $DIR/index-bounds.rs:8:14 + | +LL | let _n = [64][u32::MAX as usize - 1]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the length is 1 but the index is 4294967294 + +error: aborting due to 2 previous errors + From 15564fa194996773130194bb049ef55ede7c452d Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Fri, 31 May 2024 22:13:20 -0400 Subject: [PATCH 133/211] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 431db31d0dbe..7a6fad0984d2 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 431db31d0dbeda320caf8ef8535ea48eb3093407 +Subproject commit 7a6fad0984d28c8330974636972aa296b67c4513 From 7cee7c664befc25a4d3392e9fbdb6999b23b4619 Mon Sep 17 00:00:00 2001 From: coekjan Date: Fri, 17 May 2024 21:18:51 +0800 Subject: [PATCH 134/211] stablize `const_binary_heap_constructor` & create an unstable feature `const_binary_heap_new_in` for `BinaryHeap::new_in` --- library/alloc/src/collections/binary_heap/mod.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs index 846b9a1404d2..0b04fb4a2744 100644 --- a/library/alloc/src/collections/binary_heap/mod.rs +++ b/library/alloc/src/collections/binary_heap/mod.rs @@ -440,7 +440,10 @@ impl BinaryHeap { /// heap.push(4); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_binary_heap_constructor", issue = "112353")] + #[rustc_const_stable( + feature = "const_binary_heap_constructor", + since = "CURRENT_RUSTC_VERSION" + )] #[must_use] pub const fn new() -> BinaryHeap { BinaryHeap { data: vec![] } @@ -484,7 +487,7 @@ impl BinaryHeap { /// heap.push(4); /// ``` #[unstable(feature = "allocator_api", issue = "32838")] - #[rustc_const_unstable(feature = "const_binary_heap_constructor", issue = "112353")] + #[rustc_const_unstable(feature = "const_binary_heap_new_in", issue = "112353")] #[must_use] pub const fn new_in(alloc: A) -> BinaryHeap { BinaryHeap { data: Vec::new_in(alloc) } From b0d0cc6590925aa5493f3810d0f581bf9c476714 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 30 May 2024 16:31:59 +0200 Subject: [PATCH 135/211] Add `Cc::output` method --- src/tools/run-make-support/src/cc.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/tools/run-make-support/src/cc.rs b/src/tools/run-make-support/src/cc.rs index 799c36b10499..0012e7b66af3 100644 --- a/src/tools/run-make-support/src/cc.rs +++ b/src/tools/run-make-support/src/cc.rs @@ -80,6 +80,13 @@ impl Cc { self } + /// Specify path of the output binary. + pub fn output>(&mut self, path: P) -> &mut Self { + self.cmd.arg("-o"); + self.cmd.arg(path.as_ref()); + self + } + /// Get the [`Output`][::std::process::Output] of the finished process. pub fn command_output(&mut self) -> ::std::process::Output { self.cmd.output().expect("failed to get output of finished process") From 8742bf375b067096c2d3c6898a311cd0e80fde56 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 30 May 2024 16:32:12 +0200 Subject: [PATCH 136/211] Migrate `run-make/cdylib` to `rmake.rs` --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/cdylib/Makefile | 23 ------------ tests/run-make/cdylib/rmake.rs | 36 +++++++++++++++++++ 3 files changed, 36 insertions(+), 24 deletions(-) delete mode 100644 tests/run-make/cdylib/Makefile create mode 100644 tests/run-make/cdylib/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 009200aca15d..ebe9d2b7bb0b 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -14,7 +14,6 @@ run-make/c-unwind-abi-catch-panic/Makefile run-make/cat-and-grep-sanity-check/Makefile run-make/cdylib-dylib-linkage/Makefile run-make/cdylib-fewer-symbols/Makefile -run-make/cdylib/Makefile run-make/codegen-options-parsing/Makefile run-make/comment-section/Makefile run-make/compiler-lookup-paths-2/Makefile diff --git a/tests/run-make/cdylib/Makefile b/tests/run-make/cdylib/Makefile deleted file mode 100644 index 2c6414c32553..000000000000 --- a/tests/run-make/cdylib/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -# When the cdylib crate type was added as a variation of dylib, it needed a test to check its function. -# See https://github.com/rust-lang/rust/pull/33553 - -# ignore-cross-compile -include ../tools.mk - -all: $(call RUN_BINFILE,foo) - $(call RUN,foo) - rm $(call DYLIB,foo) - $(RUSTC) foo.rs -C lto - $(call RUN,foo) - -ifdef IS_MSVC -$(call RUN_BINFILE,foo): $(call DYLIB,foo) - $(CC) $(CFLAGS) foo.c $(TMPDIR)/foo.dll.lib $(call OUT_EXE,foo) -else -$(call RUN_BINFILE,foo): $(call DYLIB,foo) - $(CC) $(CFLAGS) foo.c -lfoo -o $(call RUN_BINFILE,foo) -L $(TMPDIR) -endif - -$(call DYLIB,foo): - $(RUSTC) bar.rs - $(RUSTC) foo.rs diff --git a/tests/run-make/cdylib/rmake.rs b/tests/run-make/cdylib/rmake.rs new file mode 100644 index 000000000000..fcb4f56621f6 --- /dev/null +++ b/tests/run-make/cdylib/rmake.rs @@ -0,0 +1,36 @@ +// This test tries to check that basic cdylib libraries can be compiled and linked successfully +// with C code, that the cdylib itself can depend on another rlib, and that the library can be built +// with LTO. +// +// - `bar.rs` is a rlib +// - `foo.rs` is a cdylib that relies on an extern crate `bar` and defines two `extern "C"` +// functions: +// - `foo()` which calls `bar::bar()`. +// - `bar()` which implements basic addition. + +//@ ignore-cross-compile + +use std::fs::remove_file; + +use run_make_support::{cc, dynamic_lib, is_msvc, run, rustc, tmp_dir}; + +fn main() { + rustc().input("bar.rs").run(); + rustc().input("foo.rs").run(); + + if is_msvc() { + cc().input("foo.c").arg(tmp_dir().join("foo.dll.lib")).out_exe("foo").run(); + } else { + cc().input("foo.c") + .arg("-lfoo") + .output(tmp_dir().join("foo")) + .library_search_path(tmp_dir()) + .run(); + } + + run("foo"); + remove_file(dynamic_lib("foo")).unwrap(); + + rustc().input("foo.rs").arg("-Clto").run(); + run("foo"); +} From 190a96f9d347363ac9e3d3ac3d3821cf35e3b0a9 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 1 Jun 2024 10:29:45 +0200 Subject: [PATCH 137/211] Migrate `run-make/emit-named-files` to `rmake.rs` --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/emit-named-files/Makefile | 33 ------------------- tests/run-make/emit-named-files/rmake.rs | 25 ++++++++++++++ 3 files changed, 25 insertions(+), 34 deletions(-) delete mode 100644 tests/run-make/emit-named-files/Makefile create mode 100644 tests/run-make/emit-named-files/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 009200aca15d..95fc30cb7757 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -38,7 +38,6 @@ run-make/dump-ice-to-disk/Makefile run-make/dump-mono-stats/Makefile run-make/duplicate-output-flavors/Makefile run-make/dylib-chain/Makefile -run-make/emit-named-files/Makefile run-make/emit-path-unhashed/Makefile run-make/emit-shared-files/Makefile run-make/emit-stack-sizes/Makefile diff --git a/tests/run-make/emit-named-files/Makefile b/tests/run-make/emit-named-files/Makefile deleted file mode 100644 index 2b97b841fc00..000000000000 --- a/tests/run-make/emit-named-files/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -include ../tools.mk - -OUT=$(TMPDIR)/emit - -all: asm llvm-bc llvm-ir obj metadata link dep-info mir - -asm: $(OUT) - $(RUSTC) --emit asm=$(OUT)/libfoo.s foo.rs - test -f $(OUT)/libfoo.s -llvm-bc: $(OUT) - $(RUSTC) --emit llvm-bc=$(OUT)/libfoo.bc foo.rs - test -f $(OUT)/libfoo.bc -llvm-ir: $(OUT) - $(RUSTC) --emit llvm-ir=$(OUT)/libfoo.ll foo.rs - test -f $(OUT)/libfoo.ll -obj: $(OUT) - $(RUSTC) --emit obj=$(OUT)/libfoo.o foo.rs - test -f $(OUT)/libfoo.o -metadata: $(OUT) - $(RUSTC) --emit metadata=$(OUT)/libfoo.rmeta foo.rs - test -f $(OUT)/libfoo.rmeta -link: $(OUT) - $(RUSTC) --emit link=$(OUT)/libfoo.rlib foo.rs - test -f $(OUT)/libfoo.rlib -dep-info: $(OUT) - $(RUSTC) --emit dep-info=$(OUT)/libfoo.d foo.rs - test -f $(OUT)/libfoo.d -mir: $(OUT) - $(RUSTC) --emit mir=$(OUT)/libfoo.mir foo.rs - test -f $(OUT)/libfoo.mir - -$(OUT): - mkdir -p $(OUT) diff --git a/tests/run-make/emit-named-files/rmake.rs b/tests/run-make/emit-named-files/rmake.rs new file mode 100644 index 000000000000..068f9796d0e9 --- /dev/null +++ b/tests/run-make/emit-named-files/rmake.rs @@ -0,0 +1,25 @@ +use std::fs::create_dir; +use std::path::Path; + +use run_make_support::{rustc, tmp_dir}; + +fn emit_and_check(out_dir: &Path, out_file: &str, format: &str) { + let out_file = out_dir.join(out_file); + rustc().input("foo.rs").emit(&format!("{format}={}", out_file.display())).run(); + assert!(out_file.is_file()); +} + +fn main() { + let out_dir = tmp_dir().join("emit"); + + create_dir(&out_dir).unwrap(); + + emit_and_check(&out_dir, "libfoo.s", "asm"); + emit_and_check(&out_dir, "libfoo.bc", "llvm-bc"); + emit_and_check(&out_dir, "libfoo.ll", "llvm-ir"); + emit_and_check(&out_dir, "libfoo.o", "obj"); + emit_and_check(&out_dir, "libfoo.rmeta", "metadata"); + emit_and_check(&out_dir, "libfoo.rlib", "link"); + emit_and_check(&out_dir, "libfoo.d", "dep-info"); + emit_and_check(&out_dir, "libfoo.mir", "mir"); +} From dd9c8cc467a8a6af3a785bac285458dd9def6cf0 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 6 Apr 2024 16:42:38 -0400 Subject: [PATCH 138/211] Increase vtable layout size This improves LLVM's codegen by allowing vtable loads to be hoisted out of loops (as just one example). --- compiler/rustc_middle/src/ty/layout.rs | 25 ++-- compiler/rustc_middle/src/ty/vtable.rs | 64 ++++++++++ .../src/traits/object_safety.rs | 113 ++++++++++-------- tests/debuginfo/unsized.rs | 6 +- 4 files changed, 134 insertions(+), 74 deletions(-) diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 60ce87440328..71030febf769 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -827,25 +827,14 @@ where }); } - let mk_dyn_vtable = || { + let mk_dyn_vtable = |principal: Option>| { + let min_count = ty::vtable_min_entries(tcx, principal); Ty::new_imm_ref( tcx, tcx.lifetimes.re_static, - Ty::new_array(tcx, tcx.types.usize, 3), + // FIXME: properly type (e.g. usize and fn pointers) the fields. + Ty::new_array(tcx, tcx.types.usize, min_count.try_into().unwrap()), ) - /* FIXME: use actual fn pointers - Warning: naively computing the number of entries in the - vtable by counting the methods on the trait + methods on - all parent traits does not work, because some methods can - be not object safe and thus excluded from the vtable. - Increase this counter if you tried to implement this but - failed to do it without duplicating a lot of code from - other places in the compiler: 2 - Ty::new_tup(tcx,&[ - Ty::new_array(tcx,tcx.types.usize, 3), - Ty::new_array(tcx,Option), - ]) - */ }; let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type() @@ -864,16 +853,16 @@ where // `std::mem::uninitialized::<&dyn Trait>()`, for example. if let ty::Adt(def, args) = metadata.kind() && Some(def.did()) == tcx.lang_items().dyn_metadata() - && args.type_at(0).is_trait() + && let ty::Dynamic(data, _, ty::Dyn) = args.type_at(0).kind() { - mk_dyn_vtable() + mk_dyn_vtable(data.principal()) } else { metadata } } else { match tcx.struct_tail_erasing_lifetimes(pointee, cx.param_env()).kind() { ty::Slice(_) | ty::Str => tcx.types.usize, - ty::Dynamic(_, _, ty::Dyn) => mk_dyn_vtable(), + ty::Dynamic(data, _, ty::Dyn) => mk_dyn_vtable(data.principal()), _ => bug!("TyAndLayout::field({:?}): not applicable", this), } }; diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs index b8371cc2bca5..092451b80aa5 100644 --- a/compiler/rustc_middle/src/ty/vtable.rs +++ b/compiler/rustc_middle/src/ty/vtable.rs @@ -3,6 +3,8 @@ use std::fmt; use crate::mir::interpret::{alloc_range, AllocId, Allocation, Pointer, Scalar}; use crate::ty::{self, Instance, PolyTraitRef, Ty, TyCtxt}; use rustc_ast::Mutability; +use rustc_data_structures::fx::FxHashSet; +use rustc_hir::def_id::DefId; use rustc_macros::HashStable; #[derive(Clone, Copy, PartialEq, HashStable)] @@ -46,6 +48,65 @@ pub const COMMON_VTABLE_ENTRIES_DROPINPLACE: usize = 0; pub const COMMON_VTABLE_ENTRIES_SIZE: usize = 1; pub const COMMON_VTABLE_ENTRIES_ALIGN: usize = 2; +// FIXME: This is duplicating equivalent code in compiler/rustc_trait_selection/src/traits/util.rs +// But that is a downstream crate, and this code is pretty simple. Probably OK for now. +struct SupertraitDefIds<'tcx> { + tcx: TyCtxt<'tcx>, + stack: Vec, + visited: FxHashSet, +} + +fn supertrait_def_ids(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SupertraitDefIds<'_> { + SupertraitDefIds { + tcx, + stack: vec![trait_def_id], + visited: Some(trait_def_id).into_iter().collect(), + } +} + +impl Iterator for SupertraitDefIds<'_> { + type Item = DefId; + + fn next(&mut self) -> Option { + let def_id = self.stack.pop()?; + let predicates = self.tcx.super_predicates_of(def_id); + let visited = &mut self.visited; + self.stack.extend( + predicates + .predicates + .iter() + .filter_map(|(pred, _)| pred.as_trait_clause()) + .map(|trait_ref| trait_ref.def_id()) + .filter(|&super_def_id| visited.insert(super_def_id)), + ); + Some(def_id) + } +} + +// Note that we don't have access to a self type here, this has to be purely based on the trait (and +// supertrait) definitions. That means we can't call into the same vtable_entries code since that +// returns a specific instantiation (e.g., with Vacant slots when bounds aren't satisfied). The goal +// here is to do a best-effort approximation without duplicating a lot of code. +// +// This function is used in layout computation for e.g. &dyn Trait, so it's critical that this +// function is an accurate approximation. We verify this when actually computing the vtable below. +pub(crate) fn vtable_min_entries<'tcx>( + tcx: TyCtxt<'tcx>, + trait_ref: Option>, +) -> usize { + let mut count = TyCtxt::COMMON_VTABLE_ENTRIES.len(); + let Some(trait_ref) = trait_ref else { + return count; + }; + + // This includes self in supertraits. + for def_id in supertrait_def_ids(tcx, trait_ref.def_id()) { + count += tcx.own_existential_vtable_entries(def_id).len(); + } + + count +} + /// Retrieves an allocation that represents the contents of a vtable. /// Since this is a query, allocations are cached and not duplicated. pub(super) fn vtable_allocation_provider<'tcx>( @@ -63,6 +124,9 @@ pub(super) fn vtable_allocation_provider<'tcx>( TyCtxt::COMMON_VTABLE_ENTRIES }; + // This confirms that the layout computation for &dyn Trait has an accurate sizing. + assert!(vtable_entries.len() >= vtable_min_entries(tcx, poly_trait_ref)); + let layout = tcx .layout_of(ty::ParamEnv::reveal_all().and(ty)) .expect("failed to build vtable representation"); diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index f4051561dae4..fb46d4f14829 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -26,6 +26,7 @@ use rustc_middle::ty::{TypeVisitableExt, Upcast}; use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY; use rustc_span::symbol::Symbol; use rustc_span::Span; +use rustc_target::abi::Abi; use smallvec::SmallVec; use std::iter; @@ -145,6 +146,14 @@ fn object_safety_violations_for_trait( violations.push(ObjectSafetyViolation::SupertraitNonLifetimeBinder(spans)); } + if violations.is_empty() { + for item in tcx.associated_items(trait_def_id).in_definition_order() { + if let ty::AssocKind::Fn = item.kind { + check_receiver_correct(tcx, trait_def_id, *item); + } + } + } + debug!( "object_safety_violations_for_trait(trait_def_id={:?}) = {:?}", trait_def_id, violations @@ -493,59 +502,8 @@ fn virtual_call_violations_for_method<'tcx>( }; errors.push(MethodViolationCode::UndispatchableReceiver(span)); } else { - // Do sanity check to make sure the receiver actually has the layout of a pointer. - - use rustc_target::abi::Abi; - - let param_env = tcx.param_env(method.def_id); - - let abi_of_ty = |ty: Ty<'tcx>| -> Option { - match tcx.layout_of(param_env.and(ty)) { - Ok(layout) => Some(layout.abi), - Err(err) => { - // #78372 - tcx.dcx().span_delayed_bug( - tcx.def_span(method.def_id), - format!("error: {err}\n while computing layout for type {ty:?}"), - ); - None - } - } - }; - - // e.g., `Rc<()>` - let unit_receiver_ty = - receiver_for_self_ty(tcx, receiver_ty, tcx.types.unit, method.def_id); - - match abi_of_ty(unit_receiver_ty) { - Some(Abi::Scalar(..)) => (), - abi => { - tcx.dcx().span_delayed_bug( - tcx.def_span(method.def_id), - format!( - "receiver when `Self = ()` should have a Scalar ABI; found {abi:?}" - ), - ); - } - } - - let trait_object_ty = object_ty_for_trait(tcx, trait_def_id, tcx.lifetimes.re_static); - - // e.g., `Rc` - let trait_object_receiver = - receiver_for_self_ty(tcx, receiver_ty, trait_object_ty, method.def_id); - - match abi_of_ty(trait_object_receiver) { - Some(Abi::ScalarPair(..)) => (), - abi => { - tcx.dcx().span_delayed_bug( - tcx.def_span(method.def_id), - format!( - "receiver when `Self = {trait_object_ty}` should have a ScalarPair ABI; found {abi:?}" - ), - ); - } - } + // We confirm that the `receiver_is_dispatchable` is accurate later, + // see `check_receiver_correct`. It should be kept in sync with this code. } } @@ -606,6 +564,55 @@ fn virtual_call_violations_for_method<'tcx>( errors } +/// This code checks that `receiver_is_dispatchable` is correctly implemented. +/// +/// This check is outlined from the object safety check to avoid cycles with +/// layout computation, which relies on knowing whether methods are object safe. +pub fn check_receiver_correct<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, method: ty::AssocItem) { + if !is_vtable_safe_method(tcx, trait_def_id, method) { + return; + } + + let method_def_id = method.def_id; + let sig = tcx.fn_sig(method_def_id).instantiate_identity(); + let param_env = tcx.param_env(method_def_id); + let receiver_ty = tcx.liberate_late_bound_regions(method_def_id, sig.input(0)); + + if receiver_ty == tcx.types.self_param { + // Assumed OK, may change later if unsized_locals permits `self: Self` as dispatchable. + return; + } + + // e.g., `Rc<()>` + let unit_receiver_ty = receiver_for_self_ty(tcx, receiver_ty, tcx.types.unit, method_def_id); + match tcx.layout_of(param_env.and(unit_receiver_ty)).map(|l| l.abi) { + Ok(Abi::Scalar(..)) => (), + abi => { + tcx.dcx().span_delayed_bug( + tcx.def_span(method_def_id), + format!("receiver {unit_receiver_ty:?} when `Self = ()` should have a Scalar ABI; found {abi:?}"), + ); + } + } + + let trait_object_ty = object_ty_for_trait(tcx, trait_def_id, tcx.lifetimes.re_static); + + // e.g., `Rc` + let trait_object_receiver = + receiver_for_self_ty(tcx, receiver_ty, trait_object_ty, method_def_id); + match tcx.layout_of(param_env.and(trait_object_receiver)).map(|l| l.abi) { + Ok(Abi::ScalarPair(..)) => (), + abi => { + tcx.dcx().span_delayed_bug( + tcx.def_span(method_def_id), + format!( + "receiver {trait_object_receiver:?} when `Self = {trait_object_ty}` should have a ScalarPair ABI; found {abi:?}" + ), + ); + } + } +} + /// Performs a type instantiation to produce the version of `receiver_ty` when `Self = self_ty`. /// For example, for `receiver_ty = Rc` and `self_ty = Foo`, returns `Rc`. fn receiver_for_self_ty<'tcx>( diff --git a/tests/debuginfo/unsized.rs b/tests/debuginfo/unsized.rs index f76376de3836..982ab003a2a1 100644 --- a/tests/debuginfo/unsized.rs +++ b/tests/debuginfo/unsized.rs @@ -46,13 +46,13 @@ // cdb-command:dx c // cdb-check:c [Type: ref$ > >] // cdb-check: [+0x000] pointer : 0x[...] [Type: unsized::Foo > *] -// cdb-check: [...] vtable : 0x[...] [Type: unsigned [...]int[...] (*)[3]] +// cdb-check: [...] vtable : 0x[...] [Type: unsigned [...]int[...] (*)[4]] // cdb-command:dx _box // cdb-check: // cdb-check:_box [Type: alloc::boxed::Box >,alloc::alloc::Global>] // cdb-check:[+0x000] pointer : 0x[...] [Type: unsized::Foo > *] -// cdb-check:[...] vtable : 0x[...] [Type: unsigned [...]int[...] (*)[3]] +// cdb-check:[...] vtable : 0x[...] [Type: unsigned [...]int[...] (*)[4]] // cdb-command:dx tuple_slice // cdb-check:tuple_slice [Type: ref$ > >] @@ -62,7 +62,7 @@ // cdb-command:dx tuple_dyn // cdb-check:tuple_dyn [Type: ref$ > >] // cdb-check: [+0x000] pointer : 0x[...] [Type: tuple$ > *] -// cdb-check: [...] vtable : 0x[...] [Type: unsigned [...]int[...] (*)[3]] +// cdb-check: [...] vtable : 0x[...] [Type: unsigned [...]int[...] (*)[4]] #![feature(unsized_tuple_coercion)] #![feature(omit_gdb_pretty_printer_section)] From 95e073234ff513375879e898fecb5ba727f8cee5 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 27 Apr 2024 13:58:37 -0400 Subject: [PATCH 139/211] Deduplicate supertrait_def_ids code --- .../rustc_hir_analysis/src/coherence/mod.rs | 3 +- compiler/rustc_middle/src/ty/vtable.rs | 22 +++++------ .../src/solve/trait_goals.rs | 5 +-- .../rustc_trait_selection/src/traits/mod.rs | 5 +-- .../src/traits/object_safety.rs | 5 ++- .../src/traits/select/candidate_assembly.rs | 3 +- .../src/traits/select/mod.rs | 3 +- .../rustc_trait_selection/src/traits/util.rs | 39 +------------------ src/tools/clippy/clippy_lints/src/len_zero.rs | 2 +- 9 files changed, 22 insertions(+), 65 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index 054a3af212a5..480318acca8e 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -12,7 +12,6 @@ use rustc_middle::query::Providers; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; use rustc_session::parse::feature_err; use rustc_span::{sym, ErrorGuaranteed}; -use rustc_trait_selection::traits; mod builtin; mod inherent_impls; @@ -199,7 +198,7 @@ fn check_object_overlap<'tcx>( // With the feature enabled, the trait is not implemented automatically, // so this is valid. } else { - let mut supertrait_def_ids = traits::supertrait_def_ids(tcx, component_def_id); + let mut supertrait_def_ids = tcx.supertrait_def_ids(component_def_id); if supertrait_def_ids.any(|d| d == trait_def_id) { let span = tcx.def_span(impl_def_id); return Err(struct_span_code_err!( diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs index 092451b80aa5..dc3c84f9e439 100644 --- a/compiler/rustc_middle/src/ty/vtable.rs +++ b/compiler/rustc_middle/src/ty/vtable.rs @@ -42,28 +42,26 @@ impl<'tcx> fmt::Debug for VtblEntry<'tcx> { impl<'tcx> TyCtxt<'tcx> { pub const COMMON_VTABLE_ENTRIES: &'tcx [VtblEntry<'tcx>] = &[VtblEntry::MetadataDropInPlace, VtblEntry::MetadataSize, VtblEntry::MetadataAlign]; + + pub fn supertrait_def_ids(self, trait_def_id: DefId) -> SupertraitDefIds<'tcx> { + SupertraitDefIds { + tcx: self, + stack: vec![trait_def_id], + visited: Some(trait_def_id).into_iter().collect(), + } + } } pub const COMMON_VTABLE_ENTRIES_DROPINPLACE: usize = 0; pub const COMMON_VTABLE_ENTRIES_SIZE: usize = 1; pub const COMMON_VTABLE_ENTRIES_ALIGN: usize = 2; -// FIXME: This is duplicating equivalent code in compiler/rustc_trait_selection/src/traits/util.rs -// But that is a downstream crate, and this code is pretty simple. Probably OK for now. -struct SupertraitDefIds<'tcx> { +pub struct SupertraitDefIds<'tcx> { tcx: TyCtxt<'tcx>, stack: Vec, visited: FxHashSet, } -fn supertrait_def_ids(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SupertraitDefIds<'_> { - SupertraitDefIds { - tcx, - stack: vec![trait_def_id], - visited: Some(trait_def_id).into_iter().collect(), - } -} - impl Iterator for SupertraitDefIds<'_> { type Item = DefId; @@ -100,7 +98,7 @@ pub(crate) fn vtable_min_entries<'tcx>( }; // This includes self in supertraits. - for def_id in supertrait_def_ids(tcx, trait_ref.def_id()) { + for def_id in tcx.supertrait_def_ids(trait_ref.def_id()) { count += tcx.own_existential_vtable_entries(def_id).len(); } diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index 67dd3fa85fa1..e93d5c96b880 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -1,7 +1,5 @@ //! Dealing with trait goals, i.e. `T: Trait<'a, U>`. -use crate::traits::supertrait_def_ids; - use super::assembly::structural_traits::AsyncCallableRelevantTypes; use super::assembly::{self, structural_traits, Candidate}; use super::{EvalCtxt, GoalSource, SolverMode}; @@ -837,7 +835,8 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { let a_auto_traits: FxIndexSet = a_data .auto_traits() .chain(a_data.principal_def_id().into_iter().flat_map(|principal_def_id| { - supertrait_def_ids(self.interner(), principal_def_id) + self.interner() + .supertrait_def_ids(principal_def_id) .filter(|def_id| self.interner().trait_is_auto(*def_id)) })) .collect(); diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index ab4d06f26603..786ab091e915 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -65,10 +65,7 @@ pub use self::structural_normalize::StructurallyNormalizeExt; pub use self::util::elaborate; pub use self::util::{expand_trait_aliases, TraitAliasExpander, TraitAliasExpansionInfo}; pub use self::util::{get_vtable_index_of_object_method, impl_item_is_final, upcast_choices}; -pub use self::util::{ - supertrait_def_ids, supertraits, transitive_bounds, transitive_bounds_that_define_assoc_item, - SupertraitDefIds, -}; +pub use self::util::{supertraits, transitive_bounds, transitive_bounds_that_define_assoc_item}; pub use self::util::{with_replaced_escaping_bound_vars, BoundVarReplacer, PlaceholderReplacer}; pub use rustc_infer::traits::*; diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index fb46d4f14829..0f32b6ef9e39 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -45,7 +45,8 @@ pub fn hir_ty_lowering_object_safety_violations( trait_def_id: DefId, ) -> Vec { debug_assert!(tcx.generics_of(trait_def_id).has_self); - let violations = traits::supertrait_def_ids(tcx, trait_def_id) + let violations = tcx + .supertrait_def_ids(trait_def_id) .map(|def_id| predicates_reference_self(tcx, def_id, true)) .filter(|spans| !spans.is_empty()) .map(ObjectSafetyViolation::SupertraitSelf) @@ -59,7 +60,7 @@ fn object_safety_violations(tcx: TyCtxt<'_>, trait_def_id: DefId) -> &'_ [Object debug!("object_safety_violations: {:?}", trait_def_id); tcx.arena.alloc_from_iter( - traits::supertrait_def_ids(tcx, trait_def_id) + tcx.supertrait_def_ids(trait_def_id) .flat_map(|def_id| object_safety_violations_for_trait(tcx, def_id)), ) } 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 fd7c47ad6fb3..d513a5d2996c 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -1004,7 +1004,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let a_auto_traits: FxIndexSet = a_data .auto_traits() .chain(principal_def_id_a.into_iter().flat_map(|principal_def_id| { - util::supertrait_def_ids(self.tcx(), principal_def_id) + self.tcx() + .supertrait_def_ids(principal_def_id) .filter(|def_id| self.tcx().trait_is_auto(*def_id)) })) .collect(); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 92c0c37d0c37..dcb0875639fc 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2591,8 +2591,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { let a_auto_traits: FxIndexSet = a_data .auto_traits() .chain(a_data.principal_def_id().into_iter().flat_map(|principal_def_id| { - util::supertrait_def_ids(tcx, principal_def_id) - .filter(|def_id| tcx.trait_is_auto(*def_id)) + tcx.supertrait_def_ids(principal_def_id).filter(|def_id| tcx.trait_is_auto(*def_id)) })) .collect(); diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index 445fa1761b9f..213b412e8676 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -2,7 +2,7 @@ use std::collections::BTreeMap; use super::NormalizeExt; use super::{ObligationCause, PredicateObligation, SelectionContext}; -use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; +use rustc_data_structures::fx::FxIndexMap; use rustc_errors::Diag; use rustc_hir::def_id::DefId; use rustc_infer::infer::{InferCtxt, InferOk}; @@ -161,43 +161,6 @@ impl<'tcx> Iterator for TraitAliasExpander<'tcx> { } } -/////////////////////////////////////////////////////////////////////////// -// Iterator over def-IDs of supertraits -/////////////////////////////////////////////////////////////////////////// - -pub struct SupertraitDefIds<'tcx> { - tcx: TyCtxt<'tcx>, - stack: Vec, - visited: FxHashSet, -} - -pub fn supertrait_def_ids(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SupertraitDefIds<'_> { - SupertraitDefIds { - tcx, - stack: vec![trait_def_id], - visited: Some(trait_def_id).into_iter().collect(), - } -} - -impl Iterator for SupertraitDefIds<'_> { - type Item = DefId; - - fn next(&mut self) -> Option { - let def_id = self.stack.pop()?; - let predicates = self.tcx.super_predicates_of(def_id); - let visited = &mut self.visited; - self.stack.extend( - predicates - .predicates - .iter() - .filter_map(|(pred, _)| pred.as_trait_clause()) - .map(|trait_ref| trait_ref.def_id()) - .filter(|&super_def_id| visited.insert(super_def_id)), - ); - Some(def_id) - } -} - /////////////////////////////////////////////////////////////////////////// // Other /////////////////////////////////////////////////////////////////////////// diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs index 2091e74665fb..57e0a7aa2c7e 100644 --- a/src/tools/clippy/clippy_lints/src/len_zero.rs +++ b/src/tools/clippy/clippy_lints/src/len_zero.rs @@ -253,7 +253,7 @@ fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items // fill the set with current and super traits fn fill_trait_set(traitt: DefId, set: &mut DefIdSet, cx: &LateContext<'_>) { if set.insert(traitt) { - for supertrait in rustc_trait_selection::traits::supertrait_def_ids(cx.tcx, traitt) { + for supertrait in cx.tcx.supertrait_def_ids(traitt) { fill_trait_set(supertrait, set, cx); } } From f476d37e4eda7551aa9a4f4a0edb67032b3ae0f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Ml=C3=A1dek?= Date: Sat, 1 Jun 2024 15:43:49 +0200 Subject: [PATCH 140/211] Move state trackig of diagnostic clearing inside `FlycheckActor` --- .../rust-analyzer/crates/flycheck/src/lib.rs | 27 +++++++++++++++++++ .../crates/rust-analyzer/src/global_state.rs | 19 ------------- .../crates/rust-analyzer/src/main_loop.rs | 26 +++--------------- 3 files changed, 31 insertions(+), 41 deletions(-) diff --git a/src/tools/rust-analyzer/crates/flycheck/src/lib.rs b/src/tools/rust-analyzer/crates/flycheck/src/lib.rs index 6d5ca8321e5d..afdc3e389b36 100644 --- a/src/tools/rust-analyzer/crates/flycheck/src/lib.rs +++ b/src/tools/rust-analyzer/crates/flycheck/src/lib.rs @@ -163,6 +163,9 @@ pub enum Message { /// Request adding a diagnostic with fixes included to a file AddDiagnostic { id: usize, workspace_root: AbsPathBuf, diagnostic: Diagnostic }, + /// Request clearing all previous diagnostics + ClearDiagnostics { id: usize }, + /// Request check progress notification to client Progress { /// Flycheck instance ID @@ -180,6 +183,9 @@ impl fmt::Debug for Message { .field("workspace_root", workspace_root) .field("diagnostic_code", &diagnostic.code.as_ref().map(|it| &it.code)) .finish(), + Message::ClearDiagnostics { id } => { + f.debug_struct("ClearDiagnostics").field("id", id).finish() + } Message::Progress { id, progress } => { f.debug_struct("Progress").field("id", id).field("progress", progress).finish() } @@ -220,6 +226,8 @@ struct FlycheckActor { command_handle: Option>, /// The receiver side of the channel mentioned above. command_receiver: Option>, + + status: FlycheckStatus, } enum Event { @@ -227,6 +235,13 @@ enum Event { CheckEvent(Option), } +#[derive(PartialEq)] +enum FlycheckStatus { + Started, + DiagnosticSent, + Finished, +} + const SAVED_FILE_PLACEHOLDER: &str = "$saved_file"; impl FlycheckActor { @@ -248,6 +263,7 @@ impl FlycheckActor { manifest_path, command_handle: None, command_receiver: None, + status: FlycheckStatus::Finished, } } @@ -298,12 +314,14 @@ impl FlycheckActor { self.command_handle = Some(command_handle); self.command_receiver = Some(receiver); self.report_progress(Progress::DidStart); + self.status = FlycheckStatus::Started; } Err(error) => { self.report_progress(Progress::DidFailToRestart(format!( "Failed to run the following command: {} error={}", formatted_command, error ))); + self.status = FlycheckStatus::Finished; } } } @@ -323,7 +341,11 @@ impl FlycheckActor { error ); } + if self.status == FlycheckStatus::Started { + self.send(Message::ClearDiagnostics { id: self.id }); + } self.report_progress(Progress::DidFinish(res)); + self.status = FlycheckStatus::Finished; } Event::CheckEvent(Some(message)) => match message { CargoCheckMessage::CompilerArtifact(msg) => { @@ -341,11 +363,15 @@ impl FlycheckActor { message = msg.message, "diagnostic received" ); + if self.status == FlycheckStatus::Started { + self.send(Message::ClearDiagnostics { id: self.id }); + } self.send(Message::AddDiagnostic { id: self.id, workspace_root: self.root.clone(), diagnostic: msg, }); + self.status = FlycheckStatus::DiagnosticSent; } }, } @@ -362,6 +388,7 @@ impl FlycheckActor { ); command_handle.cancel(); self.report_progress(Progress::DidCancel); + self.status = FlycheckStatus::Finished; } } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs index 1216de2de415..f64e66183d1b 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs @@ -87,7 +87,6 @@ pub(crate) struct GlobalState { pub(crate) flycheck_sender: Sender, pub(crate) flycheck_receiver: Receiver, pub(crate) last_flycheck_error: Option, - pub(crate) flycheck_status: FxHashMap, // Test explorer pub(crate) test_run_session: Option>, @@ -166,14 +165,6 @@ pub(crate) struct GlobalStateSnapshot { pub(crate) flycheck: Arc<[FlycheckHandle]>, } -#[derive(Debug, Clone)] -pub(crate) enum FlycheckStatus { - Unknown, - Started, - DiagnosticReceived, - Finished, -} - impl std::panic::UnwindSafe for GlobalStateSnapshot {} impl GlobalState { @@ -233,7 +224,6 @@ impl GlobalState { flycheck_sender, flycheck_receiver, last_flycheck_error: None, - flycheck_status: FxHashMap::default(), test_run_session: None, test_run_sender, @@ -521,12 +511,3 @@ pub(crate) fn url_to_file_id(vfs: &vfs::Vfs, url: &Url) -> anyhow::Result bool { - match self { - FlycheckStatus::Unknown | FlycheckStatus::Started => false, - FlycheckStatus::DiagnosticReceived | FlycheckStatus::Finished => true, - } - } -} diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs index efedea77fef5..193b3fdd4a8e 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs @@ -19,7 +19,7 @@ use crate::{ config::Config, diagnostics::fetch_native_diagnostics, dispatch::{NotificationDispatcher, RequestDispatcher}, - global_state::{file_id_to_url, url_to_file_id, FlycheckStatus, GlobalState}, + global_state::{file_id_to_url, url_to_file_id, GlobalState}, hack_recover_crate_name, lsp::{ from_proto, to_proto, @@ -804,13 +804,6 @@ impl GlobalState { fn handle_flycheck_msg(&mut self, message: flycheck::Message) { match message { flycheck::Message::AddDiagnostic { id, workspace_root, diagnostic } => { - let flycheck_status = - self.flycheck_status.entry(id).or_insert(FlycheckStatus::Unknown); - - if !flycheck_status.should_clear_old_diagnostics() { - self.diagnostics.clear_check(id); - } - *flycheck_status = FlycheckStatus::DiagnosticReceived; let snap = self.snapshot(); let diagnostics = crate::diagnostics::to_proto::map_rust_diagnostic_to_lsp( &self.config.diagnostics_map(), @@ -836,35 +829,24 @@ impl GlobalState { } } + flycheck::Message::ClearDiagnostics { id } => self.diagnostics.clear_check(id), + flycheck::Message::Progress { id, progress } => { let (state, message) = match progress { - flycheck::Progress::DidStart => { - self.flycheck_status.insert(id, FlycheckStatus::Started); - (Progress::Begin, None) - } + flycheck::Progress::DidStart => (Progress::Begin, None), flycheck::Progress::DidCheckCrate(target) => (Progress::Report, Some(target)), flycheck::Progress::DidCancel => { self.last_flycheck_error = None; - // We do not clear - self.flycheck_status.insert(id, FlycheckStatus::Finished); (Progress::End, None) } flycheck::Progress::DidFailToRestart(err) => { self.last_flycheck_error = Some(format!("cargo check failed to start: {err}")); - self.flycheck_status.insert(id, FlycheckStatus::Finished); return; } flycheck::Progress::DidFinish(result) => { self.last_flycheck_error = result.err().map(|err| format!("cargo check failed to start: {err}")); - let flycheck_status = - self.flycheck_status.entry(id).or_insert(FlycheckStatus::Unknown); - - if !flycheck_status.should_clear_old_diagnostics() { - self.diagnostics.clear_check(id); - } - *flycheck_status = FlycheckStatus::Finished; (Progress::End, None) } }; From 5cdec6582a6eab3b66b078cb858294792c096aa8 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sat, 1 Jun 2024 17:19:46 +0300 Subject: [PATCH 141/211] include missing submodule on bootstrap As of https://github.com/rust-lang/rust/pull/125408 PR, rustbook now relies on dependencies from the "src/doc/book" submodule. However, bootstrap does not automatically sync this submodule before reading metadata informations. And if the submodule is not present, reading metadata will fail because rustbook's dependencies will be missing. This change makes "src/doc/book" to be fetched/synced automatically before trying to read metadata. Signed-off-by: onur-ozkan --- src/bootstrap/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 8312885915c5..cde090637e01 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -469,7 +469,8 @@ impl Build { // Make sure we update these before gathering metadata so we don't get an error about missing // Cargo.toml files. - let rust_submodules = ["src/tools/cargo", "library/backtrace", "library/stdarch"]; + let rust_submodules = + ["src/tools/cargo", "src/doc/book", "library/backtrace", "library/stdarch"]; for s in rust_submodules { build.update_submodule(Path::new(s)); } From 0a83764cbd607f57364c01b99031536075cc0581 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 16 Apr 2024 21:08:11 -0400 Subject: [PATCH 142/211] Simplify IntVarValue/FloatVarValue --- compiler/rustc_infer/src/infer/freshen.rs | 26 +++--- compiler/rustc_infer/src/infer/mod.rs | 76 ++++++++++------- .../rustc_infer/src/infer/relate/combine.rs | 81 +++++-------------- .../rustc_infer/src/infer/relate/lattice.rs | 4 +- .../src/infer/relate/type_relating.rs | 4 +- compiler/rustc_middle/src/infer/unify_key.rs | 16 +--- compiler/rustc_middle/src/ty/error.rs | 22 +---- compiler/rustc_type_ir/src/ty_kind.rs | 79 ++++++++++++------ .../parser/recover/recover-range-pats.stderr | 9 --- 9 files changed, 145 insertions(+), 172 deletions(-) diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index b2d89523ea84..a3c8d5f4251e 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -33,7 +33,6 @@ use super::InferCtxt; use rustc_data_structures::fx::FxHashMap; use rustc_middle::bug; -use rustc_middle::infer::unify_key::ToType; use rustc_middle::ty::fold::TypeFolder; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeVisitableExt}; use std::collections::hash_map::Entry; @@ -204,22 +203,27 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> { ty::IntVar(v) => { let mut inner = self.infcx.inner.borrow_mut(); - let input = inner - .int_unification_table() - .probe_value(v) - .map(|v| v.to_type(self.infcx.tcx)) - .ok_or_else(|| ty::IntVar(inner.int_unification_table().find(v))); + let value = inner.int_unification_table().probe_value(v); + let input = match value { + ty::IntVarValue::IntType(ty) => Ok(Ty::new_int(self.infcx.tcx, ty)), + ty::IntVarValue::UintType(ty) => Ok(Ty::new_uint(self.infcx.tcx, ty)), + ty::IntVarValue::Unknown => { + Err(ty::IntVar(inner.int_unification_table().find(v))) + } + }; drop(inner); Some(self.freshen_ty(input, |n| Ty::new_fresh_int(self.infcx.tcx, n))) } ty::FloatVar(v) => { let mut inner = self.infcx.inner.borrow_mut(); - let input = inner - .float_unification_table() - .probe_value(v) - .map(|v| v.to_type(self.infcx.tcx)) - .ok_or_else(|| ty::FloatVar(inner.float_unification_table().find(v))); + let value = inner.float_unification_table().probe_value(v); + let input = match value { + ty::FloatVarValue::Known(ty) => Ok(Ty::new_float(self.infcx.tcx, ty)), + ty::FloatVarValue::Unknown => { + Err(ty::FloatVar(inner.float_unification_table().find(v))) + } + }; drop(inner); Some(self.freshen_ty(input, |n| Ty::new_fresh_float(self.infcx.tcx, n))) } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index c8bb6cf5f9b4..9e64bc4f103e 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -29,9 +29,9 @@ use rustc_errors::{Diag, DiagCtxt, ErrorGuaranteed}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_macros::extension; use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues}; +use rustc_middle::infer::unify_key::ConstVariableOrigin; use rustc_middle::infer::unify_key::ConstVariableValue; use rustc_middle::infer::unify_key::EffectVarValue; -use rustc_middle::infer::unify_key::{ConstVariableOrigin, ToType}; use rustc_middle::infer::unify_key::{ConstVidKey, EffectVidKey}; use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult}; use rustc_middle::mir::ConstraintCategory; @@ -811,13 +811,13 @@ impl<'tcx> InferCtxt<'tcx> { vars.extend( (0..inner.int_unification_table().len()) .map(|i| ty::IntVid::from_u32(i as u32)) - .filter(|&vid| inner.int_unification_table().probe_value(vid).is_none()) + .filter(|&vid| inner.int_unification_table().probe_value(vid).is_unknown()) .map(|v| Ty::new_int_var(self.tcx, v)), ); vars.extend( (0..inner.float_unification_table().len()) .map(|i| ty::FloatVid::from_u32(i as u32)) - .filter(|&vid| inner.float_unification_table().probe_value(vid).is_none()) + .filter(|&vid| inner.float_unification_table().probe_value(vid).is_unknown()) .map(|v| Ty::new_float_var(self.tcx, v)), ); vars @@ -1025,14 +1025,28 @@ impl<'tcx> InferCtxt<'tcx> { ty::Const::new_var(self.tcx, vid, ty) } + pub fn next_const_var_id(&self, origin: ConstVariableOrigin) -> ConstVid { + self.inner + .borrow_mut() + .const_unification_table() + .new_key(ConstVariableValue::Unknown { origin, universe: self.universe() }) + .vid + } + + fn next_int_var_id(&self) -> IntVid { + self.inner.borrow_mut().int_unification_table().new_key(ty::IntVarValue::Unknown) + } + pub fn next_int_var(&self) -> Ty<'tcx> { - let vid = self.inner.borrow_mut().int_unification_table().new_key(None); - Ty::new_int_var(self.tcx, vid) + Ty::new_int_var(self.tcx, self.next_int_var_id()) + } + + fn next_float_var_id(&self) -> FloatVid { + self.inner.borrow_mut().float_unification_table().new_key(ty::FloatVarValue::Unknown) } pub fn next_float_var(&self) -> Ty<'tcx> { - let vid = self.inner.borrow_mut().float_unification_table().new_key(None); - Ty::new_float_var(self.tcx, vid) + Ty::new_float_var(self.tcx, self.next_float_var_id()) } /// Creates a fresh region variable with the next available index. @@ -1258,19 +1272,18 @@ impl<'tcx> InferCtxt<'tcx> { known.map(|t| self.shallow_resolve(t)) } - ty::IntVar(v) => self - .inner - .borrow_mut() - .int_unification_table() - .probe_value(v) - .map(|v| v.to_type(self.tcx)), + ty::IntVar(v) => match self.inner.borrow_mut().int_unification_table().probe_value(v) { + ty::IntVarValue::Unknown => None, + ty::IntVarValue::IntType(ty) => Some(Ty::new_int(self.tcx, ty)), + ty::IntVarValue::UintType(ty) => Some(Ty::new_uint(self.tcx, ty)), + }, - ty::FloatVar(v) => self - .inner - .borrow_mut() - .float_unification_table() - .probe_value(v) - .map(|v| v.to_type(self.tcx)), + ty::FloatVar(v) => { + match self.inner.borrow_mut().float_unification_table().probe_value(v) { + ty::FloatVarValue::Unknown => None, + ty::FloatVarValue::Known(ty) => Some(Ty::new_float(self.tcx, ty)), + } + } ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => None, } @@ -1321,10 +1334,13 @@ impl<'tcx> InferCtxt<'tcx> { /// or else the root int var in the unification table. pub fn opportunistic_resolve_int_var(&self, vid: ty::IntVid) -> Ty<'tcx> { let mut inner = self.inner.borrow_mut(); - if let Some(value) = inner.int_unification_table().probe_value(vid) { - value.to_type(self.tcx) - } else { - Ty::new_int_var(self.tcx, inner.int_unification_table().find(vid)) + let value = inner.int_unification_table().probe_value(vid); + match value { + ty::IntVarValue::IntType(ty) => Ty::new_int(self.tcx, ty), + ty::IntVarValue::UintType(ty) => Ty::new_uint(self.tcx, ty), + ty::IntVarValue::Unknown => { + Ty::new_int_var(self.tcx, inner.int_unification_table().find(vid)) + } } } @@ -1332,10 +1348,12 @@ impl<'tcx> InferCtxt<'tcx> { /// or else the root float var in the unification table. pub fn opportunistic_resolve_float_var(&self, vid: ty::FloatVid) -> Ty<'tcx> { let mut inner = self.inner.borrow_mut(); - if let Some(value) = inner.float_unification_table().probe_value(vid) { - value.to_type(self.tcx) - } else { - Ty::new_float_var(self.tcx, inner.float_unification_table().find(vid)) + let value = inner.float_unification_table().probe_value(vid); + match value { + ty::FloatVarValue::Known(ty) => Ty::new_float(self.tcx, ty), + ty::FloatVarValue::Unknown => { + Ty::new_float_var(self.tcx, inner.float_unification_table().find(vid)) + } } } @@ -1626,7 +1644,7 @@ impl<'tcx> InferCtxt<'tcx> { // If `inlined_probe_value` returns a value it's always a // `ty::Int(_)` or `ty::UInt(_)`, which never matches a // `ty::Infer(_)`. - self.inner.borrow_mut().int_unification_table().inlined_probe_value(v).is_some() + !self.inner.borrow_mut().int_unification_table().inlined_probe_value(v).is_unknown() } TyOrConstInferVar::TyFloat(v) => { @@ -1634,7 +1652,7 @@ impl<'tcx> InferCtxt<'tcx> { // `ty::Float(_)`, which never matches a `ty::Infer(_)`. // // Not `inlined_probe_value(v)` because this call site is colder. - self.inner.borrow_mut().float_unification_table().probe_value(v).is_some() + !self.inner.borrow_mut().float_unification_table().probe_value(v).is_unknown() } TyOrConstInferVar::Const(v) => { diff --git a/compiler/rustc_infer/src/infer/relate/combine.rs b/compiler/rustc_infer/src/infer/relate/combine.rs index 04ca043e6fe0..b193f4bcede6 100644 --- a/compiler/rustc_infer/src/infer/relate/combine.rs +++ b/compiler/rustc_infer/src/infer/relate/combine.rs @@ -26,7 +26,7 @@ use crate::infer::{DefineOpaqueTypes, InferCtxt, TypeTrace}; use crate::traits::{Obligation, PredicateObligations}; use rustc_middle::bug; use rustc_middle::infer::unify_key::EffectVarValue; -use rustc_middle::ty::error::{ExpectedFound, TypeError}; +use rustc_middle::ty::error::TypeError; use rustc_middle::ty::relate::{RelateResult, TypeRelation}; use rustc_middle::ty::{self, InferConst, Ty, TyCtxt, TypeVisitableExt, Upcast}; use rustc_middle::ty::{IntType, UintType}; @@ -68,40 +68,38 @@ impl<'tcx> InferCtxt<'tcx> { match (a.kind(), b.kind()) { // Relate integral variables to other types (&ty::Infer(ty::IntVar(a_id)), &ty::Infer(ty::IntVar(b_id))) => { - self.inner - .borrow_mut() - .int_unification_table() - .unify_var_var(a_id, b_id) - .map_err(|e| int_unification_error(true, e))?; + self.inner.borrow_mut().int_unification_table().union(a_id, b_id); Ok(a) } (&ty::Infer(ty::IntVar(v_id)), &ty::Int(v)) => { - self.unify_integral_variable(true, v_id, IntType(v)) + self.unify_integral_variable(v_id, IntType(v)); + Ok(b) } (&ty::Int(v), &ty::Infer(ty::IntVar(v_id))) => { - self.unify_integral_variable(false, v_id, IntType(v)) + self.unify_integral_variable(v_id, IntType(v)); + Ok(a) } (&ty::Infer(ty::IntVar(v_id)), &ty::Uint(v)) => { - self.unify_integral_variable(true, v_id, UintType(v)) + self.unify_integral_variable(v_id, UintType(v)); + Ok(b) } (&ty::Uint(v), &ty::Infer(ty::IntVar(v_id))) => { - self.unify_integral_variable(false, v_id, UintType(v)) + self.unify_integral_variable(v_id, UintType(v)); + Ok(a) } // Relate floating-point variables to other types (&ty::Infer(ty::FloatVar(a_id)), &ty::Infer(ty::FloatVar(b_id))) => { - self.inner - .borrow_mut() - .float_unification_table() - .unify_var_var(a_id, b_id) - .map_err(|e| float_unification_error(true, e))?; + self.inner.borrow_mut().float_unification_table().union(a_id, b_id); Ok(a) } (&ty::Infer(ty::FloatVar(v_id)), &ty::Float(v)) => { - self.unify_float_variable(true, v_id, v) + self.unify_float_variable(v_id, ty::FloatVarValue::Known(v)); + Ok(b) } (&ty::Float(v), &ty::Infer(ty::FloatVar(v_id))) => { - self.unify_float_variable(false, v_id, v) + self.unify_float_variable(v_id, ty::FloatVarValue::Known(v)); + Ok(a) } // We don't expect `TyVar` or `Fresh*` vars at this point with lazy norm. @@ -244,35 +242,14 @@ impl<'tcx> InferCtxt<'tcx> { } } - fn unify_integral_variable( - &self, - vid_is_expected: bool, - vid: ty::IntVid, - val: ty::IntVarValue, - ) -> RelateResult<'tcx, Ty<'tcx>> { - self.inner - .borrow_mut() - .int_unification_table() - .unify_var_value(vid, Some(val)) - .map_err(|e| int_unification_error(vid_is_expected, e))?; - match val { - IntType(v) => Ok(Ty::new_int(self.tcx, v)), - UintType(v) => Ok(Ty::new_uint(self.tcx, v)), - } + #[inline(always)] + fn unify_integral_variable(&self, vid: ty::IntVid, val: ty::IntVarValue) { + self.inner.borrow_mut().int_unification_table().union_value(vid, val); } - fn unify_float_variable( - &self, - vid_is_expected: bool, - vid: ty::FloatVid, - val: ty::FloatTy, - ) -> RelateResult<'tcx, Ty<'tcx>> { - self.inner - .borrow_mut() - .float_unification_table() - .unify_var_value(vid, Some(ty::FloatVarValue(val))) - .map_err(|e| float_unification_error(vid_is_expected, e))?; - Ok(Ty::new_float(self.tcx, val)) + #[inline(always)] + fn unify_float_variable(&self, vid: ty::FloatVid, val: ty::FloatVarValue) { + self.inner.borrow_mut().float_unification_table().union_value(vid, val); } fn unify_effect_variable(&self, vid: ty::EffectVid, val: ty::Const<'tcx>) -> ty::Const<'tcx> { @@ -350,19 +327,3 @@ pub trait ObligationEmittingRelation<'tcx>: TypeRelation<'tcx> { /// Register `AliasRelate` obligation(s) that both types must be related to each other. fn register_type_relate_obligation(&mut self, a: Ty<'tcx>, b: Ty<'tcx>); } - -fn int_unification_error<'tcx>( - a_is_expected: bool, - v: (ty::IntVarValue, ty::IntVarValue), -) -> TypeError<'tcx> { - let (a, b) = v; - TypeError::IntMismatch(ExpectedFound::new(a_is_expected, a, b)) -} - -fn float_unification_error<'tcx>( - a_is_expected: bool, - v: (ty::FloatVarValue, ty::FloatVarValue), -) -> TypeError<'tcx> { - let (ty::FloatVarValue(a), ty::FloatVarValue(b)) = v; - TypeError::FloatMismatch(ExpectedFound::new(a_is_expected, a, b)) -} diff --git a/compiler/rustc_infer/src/infer/relate/lattice.rs b/compiler/rustc_infer/src/infer/relate/lattice.rs index 38e25b0d9b68..c0c51a2820b3 100644 --- a/compiler/rustc_infer/src/infer/relate/lattice.rs +++ b/compiler/rustc_infer/src/infer/relate/lattice.rs @@ -64,8 +64,8 @@ where let infcx = this.infcx(); - let a = infcx.inner.borrow_mut().type_variables().replace_if_possible(a); - let b = infcx.inner.borrow_mut().type_variables().replace_if_possible(b); + let a = infcx.shallow_resolve(a); + let b = infcx.shallow_resolve(b); match (a.kind(), b.kind()) { // If one side is known to be a variable and one is not, diff --git a/compiler/rustc_infer/src/infer/relate/type_relating.rs b/compiler/rustc_infer/src/infer/relate/type_relating.rs index 21064fff97f7..e55a58788212 100644 --- a/compiler/rustc_infer/src/infer/relate/type_relating.rs +++ b/compiler/rustc_infer/src/infer/relate/type_relating.rs @@ -80,8 +80,8 @@ impl<'tcx> TypeRelation<'tcx> for TypeRelating<'_, '_, 'tcx> { } let infcx = self.fields.infcx; - let a = infcx.inner.borrow_mut().type_variables().replace_if_possible(a); - let b = infcx.inner.borrow_mut().type_variables().replace_if_possible(b); + let a = infcx.shallow_resolve(a); + let b = infcx.shallow_resolve(b); match (a.kind(), b.kind()) { (&ty::Infer(TyVar(a_id)), &ty::Infer(TyVar(b_id))) => { diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs index 105be21f2727..a5da7e7739e4 100644 --- a/compiler/rustc_middle/src/infer/unify_key.rs +++ b/compiler/rustc_middle/src/infer/unify_key.rs @@ -86,21 +86,6 @@ impl<'tcx> UnifyValue for RegionVariableValue<'tcx> { } } -impl ToType for ty::IntVarValue { - fn to_type<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { - match *self { - ty::IntType(i) => Ty::new_int(tcx, i), - ty::UintType(i) => Ty::new_uint(tcx, i), - } - } -} - -impl ToType for ty::FloatVarValue { - fn to_type<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { - Ty::new_float(tcx, self.0) - } -} - // Generic consts. #[derive(Copy, Clone, Debug)] @@ -211,6 +196,7 @@ impl<'tcx> EffectVarValue<'tcx> { impl<'tcx> UnifyValue for EffectVarValue<'tcx> { type Error = NoError; + fn unify_values(value1: &Self, value2: &Self) -> Result { match (*value1, *value2) { (EffectVarValue::Unknown, EffectVarValue::Unknown) => Ok(EffectVarValue::Unknown), diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 99d703be873e..9e2c626478ac 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -49,8 +49,6 @@ pub enum TypeError<'tcx> { Sorts(ExpectedFound>), ArgumentSorts(ExpectedFound>, usize), - IntMismatch(ExpectedFound), - FloatMismatch(ExpectedFound), Traits(ExpectedFound), VariadicMismatch(ExpectedFound), @@ -155,23 +153,6 @@ impl<'tcx> TypeError<'tcx> { report_maybe_different(&format!("trait `{expected}`"), &format!("trait `{found}`")) .into() } - IntMismatch(ref values) => { - let expected = match values.expected { - ty::IntVarValue::IntType(ty) => ty.name_str(), - ty::IntVarValue::UintType(ty) => ty.name_str(), - }; - let found = match values.found { - ty::IntVarValue::IntType(ty) => ty.name_str(), - ty::IntVarValue::UintType(ty) => ty.name_str(), - }; - format!("expected `{expected}`, found `{found}`").into() - } - FloatMismatch(ref values) => format!( - "expected `{}`, found `{}`", - values.expected.name_str(), - values.found.name_str() - ) - .into(), VariadicMismatch(ref values) => format!( "expected {} fn, found {} function", if values.expected { "variadic" } else { "non-variadic" }, @@ -206,8 +187,7 @@ impl<'tcx> TypeError<'tcx> { match self { CyclicTy(_) | CyclicConst(_) | SafetyMismatch(_) | ConstnessMismatch(_) | PolarityMismatch(_) | Mismatch | AbiMismatch(_) | FixedArraySize(_) - | ArgumentSorts(..) | Sorts(_) | IntMismatch(_) | FloatMismatch(_) - | VariadicMismatch(_) | TargetFeatureCast(_) => false, + | ArgumentSorts(..) | Sorts(_) | VariadicMismatch(_) | TargetFeatureCast(_) => false, Mutability | ArgumentMutability(_) diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 38082bf3c16f..28226f94fde5 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -1,7 +1,7 @@ #[cfg(feature = "nightly")] use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; #[cfg(feature = "nightly")] -use rustc_data_structures::unify::{EqUnifyValue, UnifyKey}; +use rustc_data_structures::unify::{NoError, UnifyKey, UnifyValue}; #[cfg(feature = "nightly")] use rustc_macros::{Decodable, Encodable, HashStable_NoContext, TyDecodable, TyEncodable}; use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; @@ -715,14 +715,30 @@ impl FloatTy { } } -#[derive(Clone, Copy, PartialEq, Eq)] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum IntVarValue { + Unknown, IntType(IntTy), UintType(UintTy), } -#[derive(Clone, Copy, PartialEq, Eq)] -pub struct FloatVarValue(pub FloatTy); +impl IntVarValue { + pub fn is_unknown(&self) -> bool { + matches!(self, IntVarValue::Unknown) + } +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub enum FloatVarValue { + Unknown, + Known(FloatTy), +} + +impl FloatVarValue { + pub fn is_unknown(&self) -> bool { + matches!(self, FloatVarValue::Unknown) + } +} rustc_index::newtype_index! { /// A **ty**pe **v**ariable **ID**. @@ -807,11 +823,28 @@ impl UnifyKey for TyVid { } #[cfg(feature = "nightly")] -impl EqUnifyValue for IntVarValue {} +impl UnifyValue for IntVarValue { + type Error = NoError; + + fn unify_values(value1: &Self, value2: &Self) -> Result { + match (*value1, *value2) { + (IntVarValue::Unknown, IntVarValue::Unknown) => Ok(IntVarValue::Unknown), + ( + IntVarValue::Unknown, + known @ (IntVarValue::UintType(_) | IntVarValue::IntType(_)), + ) + | ( + known @ (IntVarValue::UintType(_) | IntVarValue::IntType(_)), + IntVarValue::Unknown, + ) => Ok(known), + _ => panic!("differing ints should have been resolved first"), + } + } +} #[cfg(feature = "nightly")] impl UnifyKey for IntVid { - type Value = Option; + type Value = IntVarValue; #[inline] // make this function eligible for inlining - it is quite hot. fn index(&self) -> u32 { self.as_u32() @@ -826,11 +859,26 @@ impl UnifyKey for IntVid { } #[cfg(feature = "nightly")] -impl EqUnifyValue for FloatVarValue {} +impl UnifyValue for FloatVarValue { + type Error = NoError; + + fn unify_values(value1: &Self, value2: &Self) -> Result { + match (*value1, *value2) { + (FloatVarValue::Unknown, FloatVarValue::Unknown) => Ok(FloatVarValue::Unknown), + (FloatVarValue::Unknown, FloatVarValue::Known(known)) + | (FloatVarValue::Known(known), FloatVarValue::Unknown) => { + Ok(FloatVarValue::Known(known)) + } + (FloatVarValue::Known(_), FloatVarValue::Known(_)) => { + panic!("differing floats should have been resolved first") + } + } + } +} #[cfg(feature = "nightly")] impl UnifyKey for FloatVid { - type Value = Option; + type Value = FloatVarValue; #[inline] fn index(&self) -> u32 { self.as_u32() @@ -858,21 +906,6 @@ impl HashStable for InferTy { } } -impl fmt::Debug for IntVarValue { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { - IntVarValue::IntType(ref v) => v.fmt(f), - IntVarValue::UintType(ref v) => v.fmt(f), - } - } -} - -impl fmt::Debug for FloatVarValue { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.0.fmt(f) - } -} - impl fmt::Display for InferTy { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use InferTy::*; diff --git a/tests/ui/parser/recover/recover-range-pats.stderr b/tests/ui/parser/recover/recover-range-pats.stderr index e0ea8ec24dcf..e29b6c1c666b 100644 --- a/tests/ui/parser/recover/recover-range-pats.stderr +++ b/tests/ui/parser/recover/recover-range-pats.stderr @@ -316,9 +316,6 @@ LL | if let X.. .0 = 0 {} | | | | | expected `u8`, found floating-point number | this is of type `u8` - | - = note: expected type `u8` - found type `{float}` error[E0029]: only `char` and numeric types are allowed in range patterns --> $DIR/recover-range-pats.rs:31:12 @@ -353,9 +350,6 @@ LL | if let X..=.0 = 0 {} | | | | | expected `u8`, found floating-point number | this is of type `u8` - | - = note: expected type `u8` - found type `{float}` error[E0029]: only `char` and numeric types are allowed in range patterns --> $DIR/recover-range-pats.rs:52:12 @@ -390,9 +384,6 @@ LL | if let X... .0 = 0 {} | | | | | expected `u8`, found floating-point number | this is of type `u8` - | - = note: expected type `u8` - found type `{float}` error[E0029]: only `char` and numeric types are allowed in range patterns --> $DIR/recover-range-pats.rs:71:12 From f14b9651a1cb2544fb79cac587971fa3113602b7 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 31 May 2024 13:56:23 -0400 Subject: [PATCH 143/211] Inline fold_infer_ty --- compiler/rustc_infer/src/infer/mod.rs | 74 +++++++++++++-------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 9e64bc4f103e..cb5c976ac1c2 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -41,7 +41,7 @@ use rustc_middle::ty::fold::BoundVarReplacerDelegate; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::relate::RelateResult; use rustc_middle::ty::visit::TypeVisitableExt; -use rustc_middle::ty::{self, GenericParamDefKind, InferConst, InferTy, Ty, TyCtxt}; +use rustc_middle::ty::{self, GenericParamDefKind, InferConst, Ty, TyCtxt}; use rustc_middle::ty::{ConstVid, EffectVid, FloatVid, IntVid, TyVid}; use rustc_middle::ty::{GenericArg, GenericArgKind, GenericArgs, GenericArgsRef}; use rustc_middle::{bug, span_bug}; @@ -1248,44 +1248,44 @@ impl<'tcx> InferCtxt<'tcx> { } pub fn shallow_resolve(&self, ty: Ty<'tcx>) -> Ty<'tcx> { - if let ty::Infer(v) = ty.kind() { self.fold_infer_ty(*v).unwrap_or(ty) } else { ty } - } - - // This is separate from `shallow_resolve` to keep that method small and inlinable. - #[inline(never)] - fn fold_infer_ty(&self, v: InferTy) -> Option> { - match v { - ty::TyVar(v) => { - // Not entirely obvious: if `typ` is a type variable, - // it can be resolved to an int/float variable, which - // can then be recursively resolved, hence the - // recursion. Note though that we prevent type - // variables from unifying to other type variables - // directly (though they may be embedded - // structurally), and we prevent cycles in any case, - // so this recursion should always be of very limited - // depth. - // - // Note: if these two lines are combined into one we get - // dynamic borrow errors on `self.inner`. - let known = self.inner.borrow_mut().type_variables().probe(v).known(); - known.map(|t| self.shallow_resolve(t)) - } - - ty::IntVar(v) => match self.inner.borrow_mut().int_unification_table().probe_value(v) { - ty::IntVarValue::Unknown => None, - ty::IntVarValue::IntType(ty) => Some(Ty::new_int(self.tcx, ty)), - ty::IntVarValue::UintType(ty) => Some(Ty::new_uint(self.tcx, ty)), - }, - - ty::FloatVar(v) => { - match self.inner.borrow_mut().float_unification_table().probe_value(v) { - ty::FloatVarValue::Unknown => None, - ty::FloatVarValue::Known(ty) => Some(Ty::new_float(self.tcx, ty)), + if let ty::Infer(v) = *ty.kind() { + match v { + ty::TyVar(v) => { + // Not entirely obvious: if `typ` is a type variable, + // it can be resolved to an int/float variable, which + // can then be recursively resolved, hence the + // recursion. Note though that we prevent type + // variables from unifying to other type variables + // directly (though they may be embedded + // structurally), and we prevent cycles in any case, + // so this recursion should always be of very limited + // depth. + // + // Note: if these two lines are combined into one we get + // dynamic borrow errors on `self.inner`. + let known = self.inner.borrow_mut().type_variables().probe(v).known(); + known.map_or(ty, |t| self.shallow_resolve(t)) } - } - ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => None, + ty::IntVar(v) => { + match self.inner.borrow_mut().int_unification_table().probe_value(v) { + ty::IntVarValue::Unknown => ty, + ty::IntVarValue::IntType(ty) => Ty::new_int(self.tcx, ty), + ty::IntVarValue::UintType(ty) => Ty::new_uint(self.tcx, ty), + } + } + + ty::FloatVar(v) => { + match self.inner.borrow_mut().float_unification_table().probe_value(v) { + ty::FloatVarValue::Unknown => ty, + ty::FloatVarValue::Known(ty) => Ty::new_float(self.tcx, ty), + } + } + + ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => ty, + } + } else { + ty } } From 208c316a61d3f21f834845ea35aca41369673f59 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 1 Jun 2024 10:31:28 -0400 Subject: [PATCH 144/211] Address nits --- compiler/rustc_infer/src/infer/mod.rs | 8 ++++---- compiler/rustc_type_ir/src/ty_kind.rs | 22 ++++++++++++++++++---- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index cb5c976ac1c2..3380f945241c 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1269,16 +1269,16 @@ impl<'tcx> InferCtxt<'tcx> { ty::IntVar(v) => { match self.inner.borrow_mut().int_unification_table().probe_value(v) { - ty::IntVarValue::Unknown => ty, ty::IntVarValue::IntType(ty) => Ty::new_int(self.tcx, ty), ty::IntVarValue::UintType(ty) => Ty::new_uint(self.tcx, ty), + ty::IntVarValue::Unknown => ty, } } ty::FloatVar(v) => { match self.inner.borrow_mut().float_unification_table().probe_value(v) { - ty::FloatVarValue::Unknown => ty, ty::FloatVarValue::Known(ty) => Ty::new_float(self.tcx, ty), + ty::FloatVarValue::Unknown => ty, } } @@ -1644,7 +1644,7 @@ impl<'tcx> InferCtxt<'tcx> { // If `inlined_probe_value` returns a value it's always a // `ty::Int(_)` or `ty::UInt(_)`, which never matches a // `ty::Infer(_)`. - !self.inner.borrow_mut().int_unification_table().inlined_probe_value(v).is_unknown() + self.inner.borrow_mut().int_unification_table().inlined_probe_value(v).is_known() } TyOrConstInferVar::TyFloat(v) => { @@ -1652,7 +1652,7 @@ impl<'tcx> InferCtxt<'tcx> { // `ty::Float(_)`, which never matches a `ty::Infer(_)`. // // Not `inlined_probe_value(v)` because this call site is colder. - !self.inner.borrow_mut().float_unification_table().probe_value(v).is_unknown() + self.inner.borrow_mut().float_unification_table().probe_value(v).is_known() } TyOrConstInferVar::Const(v) => { diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 28226f94fde5..ddff3a247843 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -723,8 +723,15 @@ pub enum IntVarValue { } impl IntVarValue { - pub fn is_unknown(&self) -> bool { - matches!(self, IntVarValue::Unknown) + pub fn is_known(self) -> bool { + match self { + IntVarValue::IntType(_) | IntVarValue::UintType(_) => true, + IntVarValue::Unknown => false, + } + } + + pub fn is_unknown(self) -> bool { + !self.is_known() } } @@ -735,8 +742,15 @@ pub enum FloatVarValue { } impl FloatVarValue { - pub fn is_unknown(&self) -> bool { - matches!(self, FloatVarValue::Unknown) + pub fn is_known(self) -> bool { + match self { + FloatVarValue::Known(_) => true, + FloatVarValue::Unknown => false, + } + } + + pub fn is_unknown(self) -> bool { + !self.is_known() } } From ee47480f4cae83279d884d6bcc9e5e6ddf3334b8 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 27 May 2024 18:32:17 -0400 Subject: [PATCH 145/211] Yeet PolyFnSig from Interner --- compiler/rustc_middle/src/ty/context.rs | 1 - compiler/rustc_middle/src/ty/structural_impls.rs | 12 ------------ compiler/rustc_type_ir/src/binder.rs | 15 ++++++++++++++- compiler/rustc_type_ir/src/interner.rs | 1 - compiler/rustc_type_ir/src/ty_kind.rs | 2 +- 5 files changed, 15 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index c2219fba023b..30dd887c88a2 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -113,7 +113,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type ErrorGuaranteed = ErrorGuaranteed; type BoundExistentialPredicates = &'tcx List>; - type PolyFnSig = PolyFnSig<'tcx>; type AllocId = crate::mir::interpret::AllocId; type Pat = Pattern<'tcx>; diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index af3aa3b56f7b..90791bdd20dc 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -259,18 +259,6 @@ impl<'tcx> DebugWithInfcx> for Region<'tcx> { } } -impl<'tcx, T: DebugWithInfcx>> DebugWithInfcx> for ty::Binder<'tcx, T> { - fn fmt>>( - this: WithInfcx<'_, Infcx, &Self>, - f: &mut core::fmt::Formatter<'_>, - ) -> core::fmt::Result { - f.debug_tuple("Binder") - .field(&this.map(|data| data.as_ref().skip_binder())) - .field(&this.data.bound_vars()) - .finish() - } -} - /////////////////////////////////////////////////////////////////////////// // Atomic structs // diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs index e50d59ba5f0e..9a2c9059967b 100644 --- a/compiler/rustc_type_ir/src/binder.rs +++ b/compiler/rustc_type_ir/src/binder.rs @@ -8,11 +8,12 @@ use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; use rustc_serialize::Decodable; use tracing::debug; +use crate::debug::{DebugWithInfcx, WithInfcx}; use crate::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable}; use crate::inherent::*; use crate::lift::Lift; use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; -use crate::{self as ty, Interner, SsoHashSet}; +use crate::{self as ty, InferCtxtLike, Interner, SsoHashSet}; /// Binder is a binder for higher-ranked lifetimes or types. It is part of the /// compiler's representation for things like `for<'a> Fn(&'a isize)` @@ -55,6 +56,18 @@ where } } +impl> DebugWithInfcx for ty::Binder { + fn fmt>( + this: WithInfcx<'_, Infcx, &Self>, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + f.debug_tuple("Binder") + .field(&this.map(|data| data.as_ref().skip_binder())) + .field(&this.data.bound_vars()) + .finish() + } +} + macro_rules! impl_binder_encode_decode { ($($t:ty),+ $(,)?) => { $( diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 2a228c973d34..ca39318cc0c8 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -69,7 +69,6 @@ pub trait Interner: // Things stored inside of tys type ErrorGuaranteed: Copy + Debug + Hash + Eq; type BoundExistentialPredicates: Copy + DebugWithInfcx + Hash + Eq; - type PolyFnSig: Copy + DebugWithInfcx + Hash + Eq; type AllocId: Copy + Debug + Hash + Eq; type Pat: Copy + Debug + Hash + Eq + DebugWithInfcx; type Safety: Safety; diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 38082bf3c16f..aa285169f276 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -141,7 +141,7 @@ pub enum TyKind { /// fn foo() -> i32 { 1 } /// let bar: fn() -> i32 = foo; /// ``` - FnPtr(I::PolyFnSig), + FnPtr(ty::Binder>), /// A trait object. Written as `dyn for<'b> Trait<'b, Assoc = u32> + Send + 'a`. Dynamic(I::BoundExistentialPredicates, I::Region, DynKind), From 333458c2cbafbea22480075decc4a827f913a020 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 31 May 2024 14:13:46 -0400 Subject: [PATCH 146/211] Uplift TypeRelation and Relate --- compiler/rustc_borrowck/src/type_check/mod.rs | 5 +- compiler/rustc_codegen_gcc/src/type_of.rs | 2 +- .../src/debuginfo/metadata.rs | 3 +- .../src/debuginfo/metadata/enums/cpp_like.rs | 2 +- .../src/debuginfo/metadata/enums/mod.rs | 2 +- compiler/rustc_codegen_llvm/src/type_of.rs | 2 +- .../src/interpret/discriminant.rs | 2 +- compiler/rustc_middle/src/mir/query.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 4 +- compiler/rustc_middle/src/ty/generic_args.rs | 69 +- compiler/rustc_middle/src/ty/layout.rs | 2 +- compiler/rustc_middle/src/ty/mod.rs | 6 +- compiler/rustc_middle/src/ty/print/pretty.rs | 7 +- compiler/rustc_middle/src/ty/relate.rs | 22 - compiler/rustc_middle/src/ty/sty.rs | 731 ++---------------- compiler/rustc_mir_transform/src/coroutine.rs | 2 +- compiler/rustc_mir_transform/src/shim.rs | 4 +- compiler/rustc_mir_transform/src/validate.rs | 4 +- .../src/solve/assembly/structural_traits.rs | 8 +- .../rustc_trait_selection/src/traits/util.rs | 8 +- compiler/rustc_ty_utils/src/layout.rs | 3 +- compiler/rustc_type_ir/src/inherent.rs | 28 +- compiler/rustc_type_ir/src/interner.rs | 6 +- compiler/rustc_type_ir/src/predicate.rs | 2 +- compiler/rustc_type_ir/src/ty_kind.rs | 8 +- compiler/rustc_type_ir/src/ty_kind/closure.rs | 696 +++++++++++++++++ .../clippy/clippy_lints/src/eta_reduction.rs | 4 +- 27 files changed, 882 insertions(+), 752 deletions(-) create mode 100644 compiler/rustc_type_ir/src/ty_kind/closure.rs diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index a05fa967af03..291d2782c32c 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -27,8 +27,9 @@ use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::cast::CastTy; use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{ - self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, Dynamic, - OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt, UserType, UserTypeAnnotationIndex, + self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, CoroutineArgsExt, + Dynamic, OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt, UserType, + UserTypeAnnotationIndex, }; use rustc_middle::ty::{GenericArgsRef, UserArgs}; use rustc_middle::{bug, span_bug}; diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs index 2155cabe171c..a88d50cb4340 100644 --- a/compiler/rustc_codegen_gcc/src/type_of.rs +++ b/compiler/rustc_codegen_gcc/src/type_of.rs @@ -5,7 +5,7 @@ use rustc_codegen_ssa::traits::{BaseTypeMethods, DerivedTypeMethods, LayoutTypeM use rustc_middle::bug; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::print::with_no_trimmed_paths; -use rustc_middle::ty::{self, Ty, TypeVisitableExt}; +use rustc_middle::ty::{self, CoroutineArgsExt, Ty, TypeVisitableExt}; use rustc_target::abi::call::{CastTarget, FnAbi, Reg}; use rustc_target::abi::{ self, Abi, Align, FieldsShape, Float, Int, Integer, PointeeInfo, Pointer, Size, TyAbiInterface, diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 10d3c0d0e744..a543ccbde0ed 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -31,7 +31,8 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_middle::bug; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::{ - self, AdtKind, Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt, Visibility, + self, AdtKind, CoroutineArgsExt, Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt, + Visibility, }; use rustc_session::config::{self, DebugInfo, Lto}; use rustc_span::symbol::Symbol; diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs index 4edef14422e5..12f98eef97d4 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs @@ -12,7 +12,7 @@ use rustc_middle::{ ty::{ self, layout::{LayoutOf, TyAndLayout}, - AdtDef, CoroutineArgs, Ty, + AdtDef, CoroutineArgs, CoroutineArgsExt, Ty, }, }; use rustc_target::abi::{Align, Endian, Size, TagEncoding, VariantIdx, Variants}; diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs index bacd74f430f7..2b00bb14593e 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs @@ -10,7 +10,7 @@ use rustc_middle::{ ty::{ self, layout::{IntegerExt, LayoutOf, PrimitiveExt, TyAndLayout}, - AdtDef, CoroutineArgs, Ty, VariantDef, + AdtDef, CoroutineArgs, CoroutineArgsExt, Ty, VariantDef, }, }; use rustc_span::Symbol; diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs index 011d8ab57c75..7be941ed7498 100644 --- a/compiler/rustc_codegen_llvm/src/type_of.rs +++ b/compiler/rustc_codegen_llvm/src/type_of.rs @@ -4,7 +4,7 @@ use rustc_codegen_ssa::traits::*; use rustc_middle::bug; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; -use rustc_middle::ty::{self, Ty, TypeVisitableExt}; +use rustc_middle::ty::{self, CoroutineArgsExt, Ty, TypeVisitableExt}; use rustc_target::abi::{Abi, Align, FieldsShape}; use rustc_target::abi::{Float, Int, Pointer}; use rustc_target::abi::{Scalar, Size, Variants}; diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs index 224d17dbf52b..67fbf9642bf0 100644 --- a/compiler/rustc_const_eval/src/interpret/discriminant.rs +++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs @@ -3,7 +3,7 @@ use rustc_middle::mir; use rustc_middle::span_bug; use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt}; -use rustc_middle::ty::{self, ScalarInt, Ty}; +use rustc_middle::ty::{self, CoroutineArgsExt, ScalarInt, Ty}; use rustc_target::abi::{self, TagEncoding}; use rustc_target::abi::{VariantIdx, Variants}; use tracing::{instrument, trace}; diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 9d70231be3b0..46b38e4a6a60 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -1,7 +1,7 @@ //! Values computed by queries that use MIR. use crate::mir; -use crate::ty::{self, OpaqueHiddenType, Ty, TyCtxt}; +use crate::ty::{self, CoroutineArgsExt, OpaqueHiddenType, Ty, TyCtxt}; use rustc_data_structures::fx::FxIndexMap; use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::LocalDefId; diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 30dd887c88a2..47f66c644062 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -90,7 +90,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type AdtDef = ty::AdtDef<'tcx>; type GenericArgs = ty::GenericArgsRef<'tcx>; - type OwnItemArgs = &'tcx [ty::GenericArg<'tcx>]; + type GenericArgsSlice = &'tcx [ty::GenericArg<'tcx>]; type GenericArg = ty::GenericArg<'tcx>; type Term = ty::Term<'tcx>; @@ -190,7 +190,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self, def_id: Self::DefId, args: Self::GenericArgs, - ) -> (rustc_type_ir::TraitRef, Self::OwnItemArgs) { + ) -> (rustc_type_ir::TraitRef, Self::GenericArgsSlice) { assert_matches!(self.def_kind(def_id), DefKind::AssocTy | DefKind::AssocConst); let trait_def_id = self.parent(def_id); assert_matches!(self.def_kind(trait_def_id), DefKind::Trait); diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index 7a516b9f2c80..c3ab755175d8 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -2,9 +2,10 @@ use crate::ty::codec::{TyDecoder, TyEncoder}; use crate::ty::fold::{FallibleTypeFolder, TypeFoldable}; -use crate::ty::sty::{ClosureArgs, CoroutineArgs, CoroutineClosureArgs, InlineConstArgs}; use crate::ty::visit::{TypeVisitable, TypeVisitor}; -use crate::ty::{self, Lift, List, Ty, TyCtxt}; +use crate::ty::{ + self, ClosureArgs, CoroutineArgs, CoroutineClosureArgs, InlineConstArgs, Lift, List, Ty, TyCtxt, +}; use rustc_ast_ir::visit::VisitorResult; use rustc_ast_ir::walk_visitable_list; @@ -56,6 +57,64 @@ impl<'tcx> rustc_type_ir::inherent::GenericArgs> for ty::GenericArg ) -> ty::GenericArgsRef<'tcx> { ty::GenericArgs::extend_with_error(tcx, def_id, original_args) } + + fn split_closure_args(self) -> ty::ClosureArgsParts> { + match self[..] { + [ref parent_args @ .., closure_kind_ty, closure_sig_as_fn_ptr_ty, tupled_upvars_ty] => { + ty::ClosureArgsParts { + parent_args, + closure_kind_ty: closure_kind_ty.expect_ty(), + closure_sig_as_fn_ptr_ty: closure_sig_as_fn_ptr_ty.expect_ty(), + tupled_upvars_ty: tupled_upvars_ty.expect_ty(), + } + } + _ => bug!("closure args missing synthetics"), + } + } + + fn split_coroutine_closure_args(self) -> ty::CoroutineClosureArgsParts> { + match self[..] { + [ + ref parent_args @ .., + closure_kind_ty, + signature_parts_ty, + tupled_upvars_ty, + coroutine_captures_by_ref_ty, + coroutine_witness_ty, + ] => ty::CoroutineClosureArgsParts { + parent_args, + closure_kind_ty: closure_kind_ty.expect_ty(), + signature_parts_ty: signature_parts_ty.expect_ty(), + tupled_upvars_ty: tupled_upvars_ty.expect_ty(), + coroutine_captures_by_ref_ty: coroutine_captures_by_ref_ty.expect_ty(), + coroutine_witness_ty: coroutine_witness_ty.expect_ty(), + }, + _ => bug!("closure args missing synthetics"), + } + } + + fn split_coroutine_args(self) -> ty::CoroutineArgsParts> { + match self[..] { + [ + ref parent_args @ .., + kind_ty, + resume_ty, + yield_ty, + return_ty, + witness, + tupled_upvars_ty, + ] => ty::CoroutineArgsParts { + parent_args, + kind_ty: kind_ty.expect_ty(), + resume_ty: resume_ty.expect_ty(), + yield_ty: yield_ty.expect_ty(), + return_ty: return_ty.expect_ty(), + witness: witness.expect_ty(), + tupled_upvars_ty: tupled_upvars_ty.expect_ty(), + }, + _ => bug!("coroutine args missing synthetics"), + } + } } impl<'tcx> rustc_type_ir::inherent::IntoKind for GenericArg<'tcx> { @@ -295,7 +354,7 @@ impl<'tcx> GenericArgs<'tcx> { /// Closure args have a particular structure controlled by the /// compiler that encodes information like the signature and closure kind; /// see `ty::ClosureArgs` struct for more comments. - pub fn as_closure(&'tcx self) -> ClosureArgs<'tcx> { + pub fn as_closure(&'tcx self) -> ClosureArgs> { ClosureArgs { args: self } } @@ -303,7 +362,7 @@ impl<'tcx> GenericArgs<'tcx> { /// Coroutine-closure args have a particular structure controlled by the /// compiler that encodes information like the signature and closure kind; /// see `ty::CoroutineClosureArgs` struct for more comments. - pub fn as_coroutine_closure(&'tcx self) -> CoroutineClosureArgs<'tcx> { + pub fn as_coroutine_closure(&'tcx self) -> CoroutineClosureArgs> { CoroutineClosureArgs { args: self } } @@ -311,7 +370,7 @@ impl<'tcx> GenericArgs<'tcx> { /// Coroutine args have a particular structure controlled by the /// compiler that encodes information like the signature and coroutine kind; /// see `ty::CoroutineArgs` struct for more comments. - pub fn as_coroutine(&'tcx self) -> CoroutineArgs<'tcx> { + pub fn as_coroutine(&'tcx self) -> CoroutineArgs> { CoroutineArgs { args: self } } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 60ce87440328..3c84ee5e7347 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -2,7 +2,7 @@ use crate::error::UnsupportedFnAbi; use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::query::TyCtxtAt; use crate::ty::normalize_erasing_regions::NormalizationError; -use crate::ty::{self, Ty, TyCtxt, TypeVisitableExt}; +use crate::ty::{self, CoroutineArgsExt, Ty, TyCtxt, TypeVisitableExt}; use rustc_error_messages::DiagMessage; use rustc_errors::{ Diag, DiagArgValue, DiagCtxt, Diagnostic, EmissionGuarantee, IntoDiagArg, Level, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 90c154233dab..2643ce976ded 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -113,10 +113,8 @@ pub use self::region::{ pub use self::rvalue_scopes::RvalueScopes; pub use self::sty::{ AliasTy, Article, Binder, BoundTy, BoundTyKind, BoundVariableKind, CanonicalPolyFnSig, - ClosureArgs, ClosureArgsParts, CoroutineArgs, CoroutineArgsParts, CoroutineClosureArgs, - CoroutineClosureArgsParts, CoroutineClosureSignature, EarlyBinder, FnSig, GenSig, - InlineConstArgs, InlineConstArgsParts, ParamConst, ParamTy, PolyFnSig, TyKind, TypeAndMut, - UpvarArgs, VarianceDiagInfo, + CoroutineArgsExt, EarlyBinder, FnSig, InlineConstArgs, InlineConstArgsParts, ParamConst, + ParamTy, PolyFnSig, TyKind, TypeAndMut, UpvarArgs, VarianceDiagInfo, }; pub use self::trait_def::TraitDef; pub use self::typeck_results::{ diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 83790db99260..126da2f5a7c5 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1938,7 +1938,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { Ok(()) } - fn pretty_closure_as_impl(&mut self, closure: ty::ClosureArgs<'tcx>) -> Result<(), PrintError> { + fn pretty_closure_as_impl( + &mut self, + closure: ty::ClosureArgs>, + ) -> Result<(), PrintError> { let sig = closure.sig(); let kind = closure.kind_ty().to_opt_closure_kind().unwrap_or(ty::ClosureKind::Fn); @@ -2973,7 +2976,7 @@ impl<'tcx> ty::PolyTraitPredicate<'tcx> { #[derive(Debug, Copy, Clone, Lift)] pub struct PrintClosureAsImpl<'tcx> { - pub closure: ty::ClosureArgs<'tcx>, + pub closure: ty::ClosureArgs>, } macro_rules! forward_display_to_print { diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index f02b4849f83d..b41798588909 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -756,28 +756,6 @@ impl<'tcx> Relate<'tcx> for &'tcx ty::List> { } } -impl<'tcx> Relate<'tcx> for ty::ClosureArgs<'tcx> { - fn relate>( - relation: &mut R, - a: ty::ClosureArgs<'tcx>, - b: ty::ClosureArgs<'tcx>, - ) -> RelateResult<'tcx, ty::ClosureArgs<'tcx>> { - let args = relate_args_invariantly(relation, a.args, b.args)?; - Ok(ty::ClosureArgs { args }) - } -} - -impl<'tcx> Relate<'tcx> for ty::CoroutineArgs<'tcx> { - fn relate>( - relation: &mut R, - a: ty::CoroutineArgs<'tcx>, - b: ty::CoroutineArgs<'tcx>, - ) -> RelateResult<'tcx, ty::CoroutineArgs<'tcx>> { - let args = relate_args_invariantly(relation, a.args, b.args)?; - Ok(ty::CoroutineArgs { args }) - } -} - impl<'tcx> Relate<'tcx> for GenericArgsRef<'tcx> { fn relate>( relation: &mut R, diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 5f7385fccc98..879396b06781 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -16,7 +16,7 @@ use rustc_errors::{ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::LangItem; -use rustc_macros::{HashStable, Lift, TyDecodable, TyEncodable, TypeFoldable}; +use rustc_macros::{extension, HashStable, TyDecodable, TyEncodable, TypeFoldable}; use rustc_span::symbol::{sym, Symbol}; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT}; @@ -30,7 +30,6 @@ use ty::util::{AsyncDropGlueMorphology, IntTypeExt}; use rustc_type_ir::TyKind::*; use rustc_type_ir::{self as ir, BoundVar, CollectAndApply, DynKind}; -use super::fold::FnMutDelegate; use super::GenericParamDefKind; // Re-export and re-parameterize some `I = TyCtxt<'tcx>` types here @@ -60,670 +59,14 @@ impl<'tcx> Article for TyKind<'tcx> { } } -/// A closure can be modeled as a struct that looks like: -/// ```ignore (illustrative) -/// struct Closure<'l0...'li, T0...Tj, CK, CS, U>(...U); -/// ``` -/// where: -/// -/// - 'l0...'li and T0...Tj are the generic parameters -/// in scope on the function that defined the closure, -/// - CK represents the *closure kind* (Fn vs FnMut vs FnOnce). This -/// is rather hackily encoded via a scalar type. See -/// `Ty::to_opt_closure_kind` for details. -/// - CS represents the *closure signature*, representing as a `fn()` -/// type. For example, `fn(u32, u32) -> u32` would mean that the closure -/// implements `CK<(u32, u32), Output = u32>`, where `CK` is the trait -/// specified above. -/// - U is a type parameter representing the types of its upvars, tupled up -/// (borrowed, if appropriate; that is, if a U field represents a by-ref upvar, -/// and the up-var has the type `Foo`, then that field of U will be `&Foo`). -/// -/// So, for example, given this function: -/// ```ignore (illustrative) -/// fn foo<'a, T>(data: &'a mut T) { -/// do(|| data.count += 1) -/// } -/// ``` -/// the type of the closure would be something like: -/// ```ignore (illustrative) -/// struct Closure<'a, T, U>(...U); -/// ``` -/// Note that the type of the upvar is not specified in the struct. -/// You may wonder how the impl would then be able to use the upvar, -/// if it doesn't know it's type? The answer is that the impl is -/// (conceptually) not fully generic over Closure but rather tied to -/// instances with the expected upvar types: -/// ```ignore (illustrative) -/// impl<'b, 'a, T> FnMut() for Closure<'a, T, (&'b mut &'a mut T,)> { -/// ... -/// } -/// ``` -/// You can see that the *impl* fully specified the type of the upvar -/// and thus knows full well that `data` has type `&'b mut &'a mut T`. -/// (Here, I am assuming that `data` is mut-borrowed.) -/// -/// Now, the last question you may ask is: Why include the upvar types -/// in an extra type parameter? The reason for this design is that the -/// upvar types can reference lifetimes that are internal to the -/// creating function. In my example above, for example, the lifetime -/// `'b` represents the scope of the closure itself; this is some -/// subset of `foo`, probably just the scope of the call to the to -/// `do()`. If we just had the lifetime/type parameters from the -/// enclosing function, we couldn't name this lifetime `'b`. Note that -/// there can also be lifetimes in the types of the upvars themselves, -/// if one of them happens to be a reference to something that the -/// creating fn owns. -/// -/// OK, you say, so why not create a more minimal set of parameters -/// that just includes the extra lifetime parameters? The answer is -/// primarily that it would be hard --- we don't know at the time when -/// we create the closure type what the full types of the upvars are, -/// nor do we know which are borrowed and which are not. In this -/// design, we can just supply a fresh type parameter and figure that -/// out later. -/// -/// All right, you say, but why include the type parameters from the -/// original function then? The answer is that codegen may need them -/// when monomorphizing, and they may not appear in the upvars. A -/// closure could capture no variables but still make use of some -/// in-scope type parameter with a bound (e.g., if our example above -/// had an extra `U: Default`, and the closure called `U::default()`). -/// -/// There is another reason. This design (implicitly) prohibits -/// closures from capturing themselves (except via a trait -/// object). This simplifies closure inference considerably, since it -/// means that when we infer the kind of a closure or its upvars, we -/// don't have to handle cycles where the decisions we make for -/// closure C wind up influencing the decisions we ought to make for -/// closure C (which would then require fixed point iteration to -/// handle). Plus it fixes an ICE. :P -/// -/// ## Coroutines -/// -/// Coroutines are handled similarly in `CoroutineArgs`. The set of -/// type parameters is similar, but `CK` and `CS` are replaced by the -/// following type parameters: -/// -/// * `GS`: The coroutine's "resume type", which is the type of the -/// argument passed to `resume`, and the type of `yield` expressions -/// inside the coroutine. -/// * `GY`: The "yield type", which is the type of values passed to -/// `yield` inside the coroutine. -/// * `GR`: The "return type", which is the type of value returned upon -/// completion of the coroutine. -/// * `GW`: The "coroutine witness". -#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable, Lift)] -pub struct ClosureArgs<'tcx> { - /// Lifetime and type parameters from the enclosing function, - /// concatenated with a tuple containing the types of the upvars. - /// - /// These are separated out because codegen wants to pass them around - /// when monomorphizing. - pub args: GenericArgsRef<'tcx>, -} - -/// Struct returned by `split()`. -pub struct ClosureArgsParts<'tcx> { - /// This is the args of the typeck root. - pub parent_args: &'tcx [GenericArg<'tcx>], - /// Represents the maximum calling capability of the closure. - pub closure_kind_ty: Ty<'tcx>, - /// Captures the closure's signature. This closure signature is "tupled", and - /// thus has a peculiar signature of `extern "rust-call" fn((Args, ...)) -> Ty`. - pub closure_sig_as_fn_ptr_ty: Ty<'tcx>, - /// The upvars captured by the closure. Remains an inference variable - /// until the upvar analysis, which happens late in HIR typeck. - pub tupled_upvars_ty: Ty<'tcx>, -} - -impl<'tcx> ClosureArgs<'tcx> { - /// Construct `ClosureArgs` from `ClosureArgsParts`, containing `Args` - /// for the closure parent, alongside additional closure-specific components. - pub fn new(tcx: TyCtxt<'tcx>, parts: ClosureArgsParts<'tcx>) -> ClosureArgs<'tcx> { - ClosureArgs { - args: tcx.mk_args_from_iter(parts.parent_args.iter().copied().chain([ - parts.closure_kind_ty.into(), - parts.closure_sig_as_fn_ptr_ty.into(), - parts.tupled_upvars_ty.into(), - ])), - } - } - - /// Divides the closure args into their respective components. - /// The ordering assumed here must match that used by `ClosureArgs::new` above. - fn split(self) -> ClosureArgsParts<'tcx> { - match self.args[..] { - [ref parent_args @ .., closure_kind_ty, closure_sig_as_fn_ptr_ty, tupled_upvars_ty] => { - ClosureArgsParts { - parent_args, - closure_kind_ty: closure_kind_ty.expect_ty(), - closure_sig_as_fn_ptr_ty: closure_sig_as_fn_ptr_ty.expect_ty(), - tupled_upvars_ty: tupled_upvars_ty.expect_ty(), - } - } - _ => bug!("closure args missing synthetics"), - } - } - - /// Returns the generic parameters of the closure's parent. - pub fn parent_args(self) -> &'tcx [GenericArg<'tcx>] { - self.split().parent_args - } - - /// Returns an iterator over the list of types of captured paths by the closure. - /// In case there was a type error in figuring out the types of the captured path, an - /// empty iterator is returned. - #[inline] - pub fn upvar_tys(self) -> &'tcx List> { - match *self.tupled_upvars_ty().kind() { - TyKind::Error(_) => ty::List::empty(), - TyKind::Tuple(tys) => tys, - TyKind::Infer(_) => bug!("upvar_tys called before capture types are inferred"), - ty => bug!("Unexpected representation of upvar types tuple {:?}", ty), - } - } - - /// Returns the tuple type representing the upvars for this closure. - #[inline] - pub fn tupled_upvars_ty(self) -> Ty<'tcx> { - self.split().tupled_upvars_ty - } - - /// Returns the closure kind for this closure; may return a type - /// variable during inference. To get the closure kind during - /// inference, use `infcx.closure_kind(args)`. - pub fn kind_ty(self) -> Ty<'tcx> { - self.split().closure_kind_ty - } - - /// Returns the `fn` pointer type representing the closure signature for this - /// closure. - // FIXME(eddyb) this should be unnecessary, as the shallowly resolved - // type is known at the time of the creation of `ClosureArgs`, - // see `rustc_hir_analysis::check::closure`. - pub fn sig_as_fn_ptr_ty(self) -> Ty<'tcx> { - self.split().closure_sig_as_fn_ptr_ty - } - - /// Returns the closure kind for this closure; only usable outside - /// of an inference context, because in that context we know that - /// there are no type variables. - /// - /// If you have an inference context, use `infcx.closure_kind()`. - pub fn kind(self) -> ty::ClosureKind { - self.kind_ty().to_opt_closure_kind().unwrap() - } - - /// Extracts the signature from the closure. - pub fn sig(self) -> ty::PolyFnSig<'tcx> { - match *self.sig_as_fn_ptr_ty().kind() { - ty::FnPtr(sig) => sig, - ty => bug!("closure_sig_as_fn_ptr_ty is not a fn-ptr: {ty:?}"), - } - } - - pub fn print_as_impl_trait(self) -> ty::print::PrintClosureAsImpl<'tcx> { - ty::print::PrintClosureAsImpl { closure: self } - } -} - -#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable, Lift)] -pub struct CoroutineClosureArgs<'tcx> { - pub args: GenericArgsRef<'tcx>, -} - -/// See docs for explanation of how each argument is used. -/// -/// See [`CoroutineClosureSignature`] for how these arguments are put together -/// to make a callable [`FnSig`] suitable for typeck and borrowck. -pub struct CoroutineClosureArgsParts<'tcx> { - /// This is the args of the typeck root. - pub parent_args: &'tcx [GenericArg<'tcx>], - /// Represents the maximum calling capability of the closure. - pub closure_kind_ty: Ty<'tcx>, - /// Represents all of the relevant parts of the coroutine returned by this - /// coroutine-closure. This signature parts type will have the general - /// shape of `fn(tupled_inputs, resume_ty) -> (return_ty, yield_ty)`, where - /// `resume_ty`, `return_ty`, and `yield_ty` are the respective types for the - /// coroutine returned by the coroutine-closure. - /// - /// Use `coroutine_closure_sig` to break up this type rather than using it - /// yourself. - pub signature_parts_ty: Ty<'tcx>, - /// The upvars captured by the closure. Remains an inference variable - /// until the upvar analysis, which happens late in HIR typeck. - pub tupled_upvars_ty: Ty<'tcx>, - /// a function pointer that has the shape `for<'env> fn() -> (&'env T, ...)`. - /// This allows us to represent the binder of the self-captures of the closure. - /// - /// For example, if the coroutine returned by the closure borrows `String` - /// from the closure's upvars, this will be `for<'env> fn() -> (&'env String,)`, - /// while the `tupled_upvars_ty`, representing the by-move version of the same - /// captures, will be `(String,)`. - pub coroutine_captures_by_ref_ty: Ty<'tcx>, - /// Witness type returned by the generator produced by this coroutine-closure. - pub coroutine_witness_ty: Ty<'tcx>, -} - -impl<'tcx> CoroutineClosureArgs<'tcx> { - pub fn new( - tcx: TyCtxt<'tcx>, - parts: CoroutineClosureArgsParts<'tcx>, - ) -> CoroutineClosureArgs<'tcx> { - CoroutineClosureArgs { - args: tcx.mk_args_from_iter(parts.parent_args.iter().copied().chain([ - parts.closure_kind_ty.into(), - parts.signature_parts_ty.into(), - parts.tupled_upvars_ty.into(), - parts.coroutine_captures_by_ref_ty.into(), - parts.coroutine_witness_ty.into(), - ])), - } - } - - fn split(self) -> CoroutineClosureArgsParts<'tcx> { - match self.args[..] { - [ - ref parent_args @ .., - closure_kind_ty, - signature_parts_ty, - tupled_upvars_ty, - coroutine_captures_by_ref_ty, - coroutine_witness_ty, - ] => CoroutineClosureArgsParts { - parent_args, - closure_kind_ty: closure_kind_ty.expect_ty(), - signature_parts_ty: signature_parts_ty.expect_ty(), - tupled_upvars_ty: tupled_upvars_ty.expect_ty(), - coroutine_captures_by_ref_ty: coroutine_captures_by_ref_ty.expect_ty(), - coroutine_witness_ty: coroutine_witness_ty.expect_ty(), - }, - _ => bug!("closure args missing synthetics"), - } - } - - pub fn parent_args(self) -> &'tcx [GenericArg<'tcx>] { - self.split().parent_args - } - - #[inline] - pub fn upvar_tys(self) -> &'tcx List> { - match self.tupled_upvars_ty().kind() { - TyKind::Error(_) => ty::List::empty(), - TyKind::Tuple(..) => self.tupled_upvars_ty().tuple_fields(), - TyKind::Infer(_) => bug!("upvar_tys called before capture types are inferred"), - ty => bug!("Unexpected representation of upvar types tuple {:?}", ty), - } - } - - #[inline] - pub fn tupled_upvars_ty(self) -> Ty<'tcx> { - self.split().tupled_upvars_ty - } - - pub fn kind_ty(self) -> Ty<'tcx> { - self.split().closure_kind_ty - } - - pub fn kind(self) -> ty::ClosureKind { - self.kind_ty().to_opt_closure_kind().unwrap() - } - - pub fn signature_parts_ty(self) -> Ty<'tcx> { - self.split().signature_parts_ty - } - - pub fn coroutine_closure_sig(self) -> Binder<'tcx, CoroutineClosureSignature<'tcx>> { - let interior = self.coroutine_witness_ty(); - let ty::FnPtr(sig) = self.signature_parts_ty().kind() else { bug!() }; - sig.map_bound(|sig| { - let [resume_ty, tupled_inputs_ty] = *sig.inputs() else { - bug!(); - }; - let [yield_ty, return_ty] = **sig.output().tuple_fields() else { bug!() }; - CoroutineClosureSignature { - interior, - tupled_inputs_ty, - resume_ty, - yield_ty, - return_ty, - c_variadic: sig.c_variadic, - safety: sig.safety, - abi: sig.abi, - } - }) - } - - pub fn coroutine_captures_by_ref_ty(self) -> Ty<'tcx> { - self.split().coroutine_captures_by_ref_ty - } - - pub fn coroutine_witness_ty(self) -> Ty<'tcx> { - self.split().coroutine_witness_ty - } - - pub fn has_self_borrows(&self) -> bool { - match self.coroutine_captures_by_ref_ty().kind() { - ty::FnPtr(sig) => sig - .skip_binder() - .visit_with(&mut HasRegionsBoundAt { binder: ty::INNERMOST }) - .is_break(), - ty::Error(_) => true, - _ => bug!(), - } - } -} -/// Unlike `has_escaping_bound_vars` or `outermost_exclusive_binder`, this will -/// detect only regions bound *at* the debruijn index. -struct HasRegionsBoundAt { - binder: ty::DebruijnIndex, -} -// FIXME: Could be optimized to not walk into components with no escaping bound vars. -impl<'tcx> TypeVisitor> for HasRegionsBoundAt { - type Result = ControlFlow<()>; - fn visit_binder>>( - &mut self, - t: &ty::Binder<'tcx, T>, - ) -> Self::Result { - self.binder.shift_in(1); - t.super_visit_with(self)?; - self.binder.shift_out(1); - ControlFlow::Continue(()) - } - - fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result { - if let ty::ReBound(binder, _) = *r - && self.binder == binder - { - ControlFlow::Break(()) - } else { - ControlFlow::Continue(()) - } - } -} - -#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)] -pub struct CoroutineClosureSignature<'tcx> { - pub interior: Ty<'tcx>, - pub tupled_inputs_ty: Ty<'tcx>, - pub resume_ty: Ty<'tcx>, - pub yield_ty: Ty<'tcx>, - pub return_ty: Ty<'tcx>, - - // Like the `fn_sig_as_fn_ptr_ty` of a regular closure, these types - // never actually differ. But we save them rather than recreating them - // from scratch just for good measure. - /// Always false - pub c_variadic: bool, - /// Always [`hir::Safety::Safe`] - pub safety: hir::Safety, - /// Always [`abi::Abi::RustCall`] - pub abi: abi::Abi, -} - -impl<'tcx> CoroutineClosureSignature<'tcx> { - /// Construct a coroutine from the closure signature. Since a coroutine signature - /// is agnostic to the type of generator that is returned (by-ref/by-move), - /// the caller must specify what "flavor" of generator that they'd like to - /// create. Additionally, they must manually compute the upvars of the closure. - /// - /// This helper is not really meant to be used directly except for early on - /// during typeck, when we want to put inference vars into the kind and upvars tys. - /// When the kind and upvars are known, use the other helper functions. - pub fn to_coroutine( - self, - tcx: TyCtxt<'tcx>, - parent_args: &'tcx [GenericArg<'tcx>], - coroutine_kind_ty: Ty<'tcx>, - coroutine_def_id: DefId, - tupled_upvars_ty: Ty<'tcx>, - ) -> Ty<'tcx> { - let coroutine_args = ty::CoroutineArgs::new( - tcx, - ty::CoroutineArgsParts { - parent_args, - kind_ty: coroutine_kind_ty, - resume_ty: self.resume_ty, - yield_ty: self.yield_ty, - return_ty: self.return_ty, - witness: self.interior, - tupled_upvars_ty, - }, - ); - - Ty::new_coroutine(tcx, coroutine_def_id, coroutine_args.args) - } - - /// Given known upvars and a [`ClosureKind`](ty::ClosureKind), compute the coroutine - /// returned by that corresponding async fn trait. - /// - /// This function expects the upvars to have been computed already, and doesn't check - /// that the `ClosureKind` is actually supported by the coroutine-closure. - pub fn to_coroutine_given_kind_and_upvars( - self, - tcx: TyCtxt<'tcx>, - parent_args: &'tcx [GenericArg<'tcx>], - coroutine_def_id: DefId, - goal_kind: ty::ClosureKind, - env_region: ty::Region<'tcx>, - closure_tupled_upvars_ty: Ty<'tcx>, - coroutine_captures_by_ref_ty: Ty<'tcx>, - ) -> Ty<'tcx> { - let tupled_upvars_ty = Self::tupled_upvars_by_closure_kind( - tcx, - goal_kind, - self.tupled_inputs_ty, - closure_tupled_upvars_ty, - coroutine_captures_by_ref_ty, - env_region, - ); - - self.to_coroutine( - tcx, - parent_args, - Ty::from_coroutine_closure_kind(tcx, goal_kind), - coroutine_def_id, - tupled_upvars_ty, - ) - } - - /// Compute the tupled upvars that a coroutine-closure's output coroutine - /// would return for the given `ClosureKind`. - /// - /// When `ClosureKind` is `FnMut`/`Fn`, then this will use the "captures by ref" - /// to return a set of upvars which are borrowed with the given `env_region`. - /// - /// This ensures that the `AsyncFn::call` will return a coroutine whose upvars' - /// lifetimes are related to the lifetime of the borrow on the closure made for - /// the call. This allows borrowck to enforce the self-borrows correctly. - pub fn tupled_upvars_by_closure_kind( - tcx: TyCtxt<'tcx>, - kind: ty::ClosureKind, - tupled_inputs_ty: Ty<'tcx>, - closure_tupled_upvars_ty: Ty<'tcx>, - coroutine_captures_by_ref_ty: Ty<'tcx>, - env_region: ty::Region<'tcx>, - ) -> Ty<'tcx> { - match kind { - ty::ClosureKind::Fn | ty::ClosureKind::FnMut => { - let ty::FnPtr(sig) = *coroutine_captures_by_ref_ty.kind() else { - bug!(); - }; - let coroutine_captures_by_ref_ty = tcx.replace_escaping_bound_vars_uncached( - sig.output().skip_binder(), - FnMutDelegate { - consts: &mut |c, t| ty::Const::new_bound(tcx, ty::INNERMOST, c, t), - types: &mut |t| Ty::new_bound(tcx, ty::INNERMOST, t), - regions: &mut |_| env_region, - }, - ); - Ty::new_tup_from_iter( - tcx, - tupled_inputs_ty - .tuple_fields() - .iter() - .chain(coroutine_captures_by_ref_ty.tuple_fields()), - ) - } - ty::ClosureKind::FnOnce => Ty::new_tup_from_iter( - tcx, - tupled_inputs_ty - .tuple_fields() - .iter() - .chain(closure_tupled_upvars_ty.tuple_fields()), - ), - } - } -} -/// Similar to `ClosureArgs`; see the above documentation for more. -#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)] -pub struct CoroutineArgs<'tcx> { - pub args: GenericArgsRef<'tcx>, -} - -pub struct CoroutineArgsParts<'tcx> { - /// This is the args of the typeck root. - pub parent_args: &'tcx [GenericArg<'tcx>], - - /// The coroutines returned by a coroutine-closure's `AsyncFnOnce`/`AsyncFnMut` - /// implementations must be distinguished since the former takes the closure's - /// upvars by move, and the latter takes the closure's upvars by ref. - /// - /// This field distinguishes these fields so that codegen can select the right - /// body for the coroutine. This has the same type representation as the closure - /// kind: `i8`/`i16`/`i32`. - /// - /// For regular coroutines, this field will always just be `()`. - pub kind_ty: Ty<'tcx>, - - pub resume_ty: Ty<'tcx>, - pub yield_ty: Ty<'tcx>, - pub return_ty: Ty<'tcx>, - - /// The interior type of the coroutine. - /// Represents all types that are stored in locals - /// in the coroutine's body. - pub witness: Ty<'tcx>, - - /// The upvars captured by the closure. Remains an inference variable - /// until the upvar analysis, which happens late in HIR typeck. - pub tupled_upvars_ty: Ty<'tcx>, -} - -impl<'tcx> CoroutineArgs<'tcx> { - /// Construct `CoroutineArgs` from `CoroutineArgsParts`, containing `Args` - /// for the coroutine parent, alongside additional coroutine-specific components. - pub fn new(tcx: TyCtxt<'tcx>, parts: CoroutineArgsParts<'tcx>) -> CoroutineArgs<'tcx> { - CoroutineArgs { - args: tcx.mk_args_from_iter(parts.parent_args.iter().copied().chain([ - parts.kind_ty.into(), - parts.resume_ty.into(), - parts.yield_ty.into(), - parts.return_ty.into(), - parts.witness.into(), - parts.tupled_upvars_ty.into(), - ])), - } - } - - /// Divides the coroutine args into their respective components. - /// The ordering assumed here must match that used by `CoroutineArgs::new` above. - fn split(self) -> CoroutineArgsParts<'tcx> { - match self.args[..] { - [ - ref parent_args @ .., - kind_ty, - resume_ty, - yield_ty, - return_ty, - witness, - tupled_upvars_ty, - ] => CoroutineArgsParts { - parent_args, - kind_ty: kind_ty.expect_ty(), - resume_ty: resume_ty.expect_ty(), - yield_ty: yield_ty.expect_ty(), - return_ty: return_ty.expect_ty(), - witness: witness.expect_ty(), - tupled_upvars_ty: tupled_upvars_ty.expect_ty(), - }, - _ => bug!("coroutine args missing synthetics"), - } - } - - /// Returns the generic parameters of the coroutine's parent. - pub fn parent_args(self) -> &'tcx [GenericArg<'tcx>] { - self.split().parent_args - } - - // Returns the kind of the coroutine. See docs on the `kind_ty` field. - pub fn kind_ty(self) -> Ty<'tcx> { - self.split().kind_ty - } - - /// This describes the types that can be contained in a coroutine. - /// It will be a type variable initially and unified in the last stages of typeck of a body. - /// It contains a tuple of all the types that could end up on a coroutine frame. - /// The state transformation MIR pass may only produce layouts which mention types - /// in this tuple. Upvars are not counted here. - pub fn witness(self) -> Ty<'tcx> { - self.split().witness - } - - /// Returns an iterator over the list of types of captured paths by the coroutine. - /// In case there was a type error in figuring out the types of the captured path, an - /// empty iterator is returned. - #[inline] - pub fn upvar_tys(self) -> &'tcx List> { - match *self.tupled_upvars_ty().kind() { - TyKind::Error(_) => ty::List::empty(), - TyKind::Tuple(tys) => tys, - TyKind::Infer(_) => bug!("upvar_tys called before capture types are inferred"), - ty => bug!("Unexpected representation of upvar types tuple {:?}", ty), - } - } - - /// Returns the tuple type representing the upvars for this coroutine. - #[inline] - pub fn tupled_upvars_ty(self) -> Ty<'tcx> { - self.split().tupled_upvars_ty - } - - /// Returns the type representing the resume type of the coroutine. - pub fn resume_ty(self) -> Ty<'tcx> { - self.split().resume_ty - } - - /// Returns the type representing the yield type of the coroutine. - pub fn yield_ty(self) -> Ty<'tcx> { - self.split().yield_ty - } - - /// Returns the type representing the return type of the coroutine. - pub fn return_ty(self) -> Ty<'tcx> { - self.split().return_ty - } - - /// Returns the "coroutine signature", which consists of its resume, yield - /// and return types. - pub fn sig(self) -> GenSig<'tcx> { - let parts = self.split(); - ty::GenSig { - resume_ty: parts.resume_ty, - yield_ty: parts.yield_ty, - return_ty: parts.return_ty, - } - } -} - -impl<'tcx> CoroutineArgs<'tcx> { +#[extension(pub trait CoroutineArgsExt<'tcx>)] +impl<'tcx> ty::CoroutineArgs> { /// Coroutine has not been resumed yet. - pub const UNRESUMED: usize = 0; + const UNRESUMED: usize = 0; /// Coroutine has returned or is completed. - pub const RETURNED: usize = 1; + const RETURNED: usize = 1; /// Coroutine has been poisoned. - pub const POISONED: usize = 2; + const POISONED: usize = 2; const UNRESUMED_NAME: &'static str = "Unresumed"; const RETURNED_NAME: &'static str = "Returned"; @@ -731,7 +74,7 @@ impl<'tcx> CoroutineArgs<'tcx> { /// The valid variant indices of this coroutine. #[inline] - pub fn variant_range(&self, def_id: DefId, tcx: TyCtxt<'tcx>) -> Range { + fn variant_range(&self, def_id: DefId, tcx: TyCtxt<'tcx>) -> Range { // FIXME requires optimized MIR FIRST_VARIANT ..tcx.coroutine_layout(def_id, tcx.types.unit).unwrap().variant_fields.next_index() @@ -740,7 +83,7 @@ impl<'tcx> CoroutineArgs<'tcx> { /// The discriminant for the given variant. Panics if the `variant_index` is /// out of range. #[inline] - pub fn discriminant_for_variant( + fn discriminant_for_variant( &self, def_id: DefId, tcx: TyCtxt<'tcx>, @@ -755,7 +98,7 @@ impl<'tcx> CoroutineArgs<'tcx> { /// The set of all discriminants for the coroutine, enumerated with their /// variant indices. #[inline] - pub fn discriminants( + fn discriminants( self, def_id: DefId, tcx: TyCtxt<'tcx>, @@ -767,7 +110,7 @@ impl<'tcx> CoroutineArgs<'tcx> { /// Calls `f` with a reference to the name of the enumerator for the given /// variant `v`. - pub fn variant_name(v: VariantIdx) -> Cow<'static, str> { + fn variant_name(v: VariantIdx) -> Cow<'static, str> { match v.as_usize() { Self::UNRESUMED => Cow::from(Self::UNRESUMED_NAME), Self::RETURNED => Cow::from(Self::RETURNED_NAME), @@ -778,7 +121,7 @@ impl<'tcx> CoroutineArgs<'tcx> { /// The type of the state discriminant used in the coroutine type. #[inline] - pub fn discr_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + fn discr_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { tcx.types.u32 } @@ -789,7 +132,7 @@ impl<'tcx> CoroutineArgs<'tcx> { /// The locals are grouped by their variant number. Note that some locals may /// be repeated in multiple variants. #[inline] - pub fn state_tys( + fn state_tys( self, def_id: DefId, tcx: TyCtxt<'tcx>, @@ -805,7 +148,7 @@ impl<'tcx> CoroutineArgs<'tcx> { /// This is the types of the fields of a coroutine which are not stored in a /// variant. #[inline] - pub fn prefix_tys(self) -> &'tcx List> { + fn prefix_tys(self) -> &'tcx List> { self.upvar_tys() } } @@ -859,7 +202,7 @@ impl<'tcx> UpvarArgs<'tcx> { /// /// When the inline const is instantiated, `R` is instantiated as the actual inferred /// type of the constant. The reason that `R` is represented as an extra type parameter -/// is the same reason that [`ClosureArgs`] have `CS` and `U` as type parameters: +/// is the same reason that [`ty::ClosureArgs`] have `CS` and `U` as type parameters: /// inline const can reference lifetimes that are internal to the creating function. #[derive(Copy, Clone, Debug)] pub struct InlineConstArgs<'tcx> { @@ -938,13 +281,6 @@ impl BoundVariableKind { } } -#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)] -pub struct GenSig<'tcx> { - pub resume_ty: Ty<'tcx>, - pub yield_ty: Ty<'tcx>, - pub return_ty: Ty<'tcx>, -} - pub type PolyFnSig<'tcx> = Binder<'tcx, FnSig<'tcx>>; pub type CanonicalPolyFnSig<'tcx> = Canonical<'tcx, Binder<'tcx, FnSig<'tcx>>>; @@ -1451,6 +787,41 @@ impl<'tcx> rustc_type_ir::inherent::Ty> for Ty<'tcx> { ) -> Self { Ty::new_alias(interner, kind, alias_ty) } + + fn new_coroutine( + interner: TyCtxt<'tcx>, + def_id: DefId, + args: ty::GenericArgsRef<'tcx>, + ) -> Self { + Ty::new_coroutine(interner, def_id, args) + } + + fn new_tup_from_iter(interner: TyCtxt<'tcx>, iter: It) -> T::Output + where + It: Iterator, + T: CollectAndApply, + { + Ty::new_tup_from_iter(interner, iter) + } + + fn tuple_fields(self) -> &'tcx ty::List> { + self.tuple_fields() + } + + fn to_opt_closure_kind(self) -> Option { + self.to_opt_closure_kind() + } + + fn from_closure_kind(interner: TyCtxt<'tcx>, kind: ty::ClosureKind) -> Self { + Ty::from_closure_kind(interner, kind) + } + + fn from_coroutine_closure_kind( + interner: TyCtxt<'tcx>, + kind: rustc_type_ir::ClosureKind, + ) -> Self { + Ty::from_coroutine_closure_kind(interner, kind) + } } /// Type utilities @@ -2169,8 +1540,8 @@ impl<'tcx> Ty<'tcx> { /// } /// ``` /// - /// After upvar analysis, you should instead use [`ClosureArgs::kind()`] - /// or [`CoroutineClosureArgs::kind()`] to assert that the `ClosureKind` + /// After upvar analysis, you should instead use [`ty::ClosureArgs::kind()`] + /// or [`ty::CoroutineClosureArgs::kind()`] to assert that the `ClosureKind` /// has been constrained instead of manually calling this method. /// /// ```rust,ignore (snippet of compiler code) diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index a3e6e5a5a915..ade2ac0080e5 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -69,7 +69,7 @@ use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::CoroutineArgs; use rustc_middle::ty::InstanceDef; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{self, CoroutineArgsExt, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_mir_dataflow::impls::{ MaybeBorrowedLocals, MaybeLiveLocals, MaybeRequiresStorage, MaybeStorageLive, diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index dcf54ad2cfc8..d03c2d18c0c3 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -4,7 +4,7 @@ use rustc_hir::lang_items::LangItem; use rustc_middle::mir::*; use rustc_middle::query::Providers; use rustc_middle::ty::GenericArgs; -use rustc_middle::ty::{self, CoroutineArgs, EarlyBinder, Ty, TyCtxt}; +use rustc_middle::ty::{self, CoroutineArgs, CoroutineArgsExt, EarlyBinder, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT}; @@ -634,7 +634,7 @@ impl<'tcx> CloneShimBuilder<'tcx> { dest: Place<'tcx>, src: Place<'tcx>, coroutine_def_id: DefId, - args: CoroutineArgs<'tcx>, + args: CoroutineArgs>, ) { self.block(vec![], TerminatorKind::Goto { target: self.block_index_offset(3) }, false); let unwind = self.block(vec![], TerminatorKind::UnwindResume, true); diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 851e16559580..5e83a6f373aa 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -8,7 +8,9 @@ use rustc_middle::mir::coverage::CoverageKind; use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; -use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitableExt, Variance}; +use rustc_middle::ty::{ + self, CoroutineArgsExt, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitableExt, Variance, +}; use rustc_middle::{bug, span_bug}; use rustc_target::abi::{Size, FIRST_VARIANT}; use rustc_target::spec::abi::Abi; diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index 08796ef3109e..48acf2a4e996 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -554,8 +554,8 @@ fn coroutine_closure_to_certain_coroutine<'tcx>( goal_kind: ty::ClosureKind, goal_region: ty::Region<'tcx>, def_id: DefId, - args: ty::CoroutineClosureArgs<'tcx>, - sig: ty::CoroutineClosureSignature<'tcx>, + args: ty::CoroutineClosureArgs>, + sig: ty::CoroutineClosureSignature>, ) -> Ty<'tcx> { sig.to_coroutine_given_kind_and_upvars( tcx, @@ -578,8 +578,8 @@ fn coroutine_closure_to_ambiguous_coroutine<'tcx>( goal_kind: ty::ClosureKind, goal_region: ty::Region<'tcx>, def_id: DefId, - args: ty::CoroutineClosureArgs<'tcx>, - sig: ty::CoroutineClosureSignature<'tcx>, + args: ty::CoroutineClosureArgs>, + sig: ty::CoroutineClosureSignature>, ) -> Ty<'tcx> { let upvars_projection_def_id = tcx.require_lang_item(LangItem::AsyncFnKindUpvars, None); let tupled_upvars_ty = Ty::new_projection( diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index 445fa1761b9f..8619c5ef77f6 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -295,7 +295,7 @@ pub fn coroutine_trait_ref_and_outputs<'tcx>( tcx: TyCtxt<'tcx>, fn_trait_def_id: DefId, self_ty: Ty<'tcx>, - sig: ty::GenSig<'tcx>, + sig: ty::GenSig>, ) -> (ty::TraitRef<'tcx>, Ty<'tcx>, Ty<'tcx>) { assert!(!self_ty.has_escaping_bound_vars()); let trait_ref = ty::TraitRef::new(tcx, fn_trait_def_id, [self_ty, sig.resume_ty]); @@ -306,7 +306,7 @@ pub fn future_trait_ref_and_outputs<'tcx>( tcx: TyCtxt<'tcx>, fn_trait_def_id: DefId, self_ty: Ty<'tcx>, - sig: ty::GenSig<'tcx>, + sig: ty::GenSig>, ) -> (ty::TraitRef<'tcx>, Ty<'tcx>) { assert!(!self_ty.has_escaping_bound_vars()); let trait_ref = ty::TraitRef::new(tcx, fn_trait_def_id, [self_ty]); @@ -317,7 +317,7 @@ pub fn iterator_trait_ref_and_outputs<'tcx>( tcx: TyCtxt<'tcx>, iterator_def_id: DefId, self_ty: Ty<'tcx>, - sig: ty::GenSig<'tcx>, + sig: ty::GenSig>, ) -> (ty::TraitRef<'tcx>, Ty<'tcx>) { assert!(!self_ty.has_escaping_bound_vars()); let trait_ref = ty::TraitRef::new(tcx, iterator_def_id, [self_ty]); @@ -328,7 +328,7 @@ pub fn async_iterator_trait_ref_and_outputs<'tcx>( tcx: TyCtxt<'tcx>, async_iterator_def_id: DefId, self_ty: Ty<'tcx>, - sig: ty::GenSig<'tcx>, + sig: ty::GenSig>, ) -> (ty::TraitRef<'tcx>, Ty<'tcx>) { assert!(!self_ty.has_escaping_bound_vars()); let trait_ref = ty::TraitRef::new(tcx, async_iterator_def_id, [self_ty]); diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 1dee14fae57e..6045abc50a9d 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -10,7 +10,8 @@ use rustc_middle::ty::layout::{ }; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{ - self, AdtDef, EarlyBinder, FieldDef, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt, + self, AdtDef, CoroutineArgsExt, EarlyBinder, FieldDef, GenericArgsRef, Ty, TyCtxt, + TypeVisitableExt, }; use rustc_session::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo}; use rustc_span::sym; diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 7b1dfecfee2e..f305ed9b5d77 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -9,7 +9,7 @@ use std::ops::Deref; use crate::fold::{TypeFoldable, TypeSuperFoldable}; use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable}; -use crate::{self as ty, DebugWithInfcx, Interner, UpcastFrom}; +use crate::{self as ty, CollectAndApply, DebugWithInfcx, Interner, UpcastFrom}; pub trait Ty>: Copy @@ -34,6 +34,21 @@ pub trait Ty>: fn new_anon_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self; fn new_alias(interner: I, kind: ty::AliasTyKind, alias_ty: ty::AliasTy) -> Self; + + fn new_coroutine(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self; + + fn new_tup_from_iter(interner: I, iter: It) -> T::Output + where + It: Iterator, + T: CollectAndApply; + + fn tuple_fields(self) -> I::Tys; + + fn to_opt_closure_kind(self) -> Option; + + fn from_closure_kind(interner: I, kind: ty::ClosureKind) -> Self; + + fn from_coroutine_closure_kind(interner: I, kind: ty::ClosureKind) -> Self; } pub trait Tys>: @@ -43,17 +58,18 @@ pub trait Tys>: + Eq + IntoIterator + Deref> - + TypeVisitable + + TypeFoldable + + Default { fn split_inputs_and_output(self) -> (I::FnInputTys, I::Ty); } -pub trait Abi>: Copy + Debug + Hash + Eq { +pub trait Abi>: Copy + Debug + Hash + Eq + TypeVisitable { /// Whether this ABI is `extern "Rust"`. fn is_rust(self) -> bool; } -pub trait Safety>: Copy + Debug + Hash + Eq { +pub trait Safety>: Copy + Debug + Hash + Eq + TypeVisitable { fn is_safe(self) -> bool; fn prefix_str(self) -> &'static str; @@ -129,6 +145,10 @@ pub trait GenericArgs>: def_id: I::DefId, original_args: &[I::GenericArg], ) -> I::GenericArgs; + + fn split_closure_args(self) -> ty::ClosureArgsParts; + fn split_coroutine_closure_args(self) -> ty::CoroutineClosureArgsParts; + fn split_coroutine_args(self) -> ty::CoroutineArgsParts; } pub trait Predicate>: diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index ca39318cc0c8..6ebb434299b3 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -29,9 +29,7 @@ pub trait Interner: type AdtDef: Copy + Debug + Hash + Eq; type GenericArgs: GenericArgs; - /// The slice of args for a specific item. For a GAT like `type Foo<'a>`, it will be `['a]`, - /// not including the args from the parent item (trait or impl). - type OwnItemArgs: Copy + Debug + Hash + Eq; + type GenericArgsSlice: Copy + Debug + Hash + Eq + Deref; type GenericArg: Copy + DebugWithInfcx + Hash @@ -111,7 +109,7 @@ pub trait Interner: self, def_id: Self::DefId, args: Self::GenericArgs, - ) -> (ty::TraitRef, Self::OwnItemArgs); + ) -> (ty::TraitRef, Self::GenericArgsSlice); fn mk_args(self, args: &[Self::GenericArg]) -> Self::GenericArgs; fn mk_args_from_iter(self, args: impl Iterator) -> Self::GenericArgs; diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index 48a6f79993cc..e7039583c91c 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -604,7 +604,7 @@ impl AliasTerm { /// For example, if this is a projection of `::Item<'a>`, /// then this function would return a `T: StreamingIterator` trait reference and /// `['a]` as the own args. - pub fn trait_ref_and_own_args(self, interner: I) -> (TraitRef, I::OwnItemArgs) { + pub fn trait_ref_and_own_args(self, interner: I) -> (TraitRef, I::GenericArgsSlice) { interner.trait_ref_and_own_args_for_alias(self.def_id, self.args) } diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index aa285169f276..6569f3123aa9 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -7,13 +7,15 @@ use rustc_macros::{Decodable, Encodable, HashStable_NoContext, TyDecodable, TyEn use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; use std::fmt; +pub use self::closure::*; +use self::TyKind::*; use crate::inherent::*; use crate::{self as ty, DebruijnIndex, DebugWithInfcx, InferCtxtLike, Interner, WithInfcx}; -use self::TyKind::*; - use rustc_ast_ir::Mutability; +mod closure; + /// Specifies how a trait object is represented. #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))] @@ -514,7 +516,7 @@ impl AliasTy { /// For example, if this is a projection of `::Item<'a>`, /// then this function would return a `T: StreamingIterator` trait reference and /// `['a]` as the own args. - pub fn trait_ref_and_own_args(self, interner: I) -> (ty::TraitRef, I::OwnItemArgs) { + pub fn trait_ref_and_own_args(self, interner: I) -> (ty::TraitRef, I::GenericArgsSlice) { debug_assert_eq!(self.kind(interner), AliasTyKind::Projection); interner.trait_ref_and_own_args_for_alias(self.def_id, self.args) } diff --git a/compiler/rustc_type_ir/src/ty_kind/closure.rs b/compiler/rustc_type_ir/src/ty_kind/closure.rs new file mode 100644 index 000000000000..97752934632c --- /dev/null +++ b/compiler/rustc_type_ir/src/ty_kind/closure.rs @@ -0,0 +1,696 @@ +use std::ops::ControlFlow; + +use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; + +use crate::fold::{shift_region, TypeFoldable, TypeFolder, TypeSuperFoldable}; +use crate::inherent::*; +use crate::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; +use crate::{self as ty, Interner}; + +/// A closure can be modeled as a struct that looks like: +/// ```ignore (illustrative) +/// struct Closure<'l0...'li, T0...Tj, CK, CS, U>(...U); +/// ``` +/// where: +/// +/// - 'l0...'li and T0...Tj are the generic parameters +/// in scope on the function that defined the closure, +/// - CK represents the *closure kind* (Fn vs FnMut vs FnOnce). This +/// is rather hackily encoded via a scalar type. See +/// `Ty::to_opt_closure_kind` for details. +/// - CS represents the *closure signature*, representing as a `fn()` +/// type. For example, `fn(u32, u32) -> u32` would mean that the closure +/// implements `CK<(u32, u32), Output = u32>`, where `CK` is the trait +/// specified above. +/// - U is a type parameter representing the types of its upvars, tupled up +/// (borrowed, if appropriate; that is, if a U field represents a by-ref upvar, +/// and the up-var has the type `Foo`, then that field of U will be `&Foo`). +/// +/// So, for example, given this function: +/// ```ignore (illustrative) +/// fn foo<'a, T>(data: &'a mut T) { +/// do(|| data.count += 1) +/// } +/// ``` +/// the type of the closure would be something like: +/// ```ignore (illustrative) +/// struct Closure<'a, T, U>(...U); +/// ``` +/// Note that the type of the upvar is not specified in the struct. +/// You may wonder how the impl would then be able to use the upvar, +/// if it doesn't know it's type? The answer is that the impl is +/// (conceptually) not fully generic over Closure but rather tied to +/// instances with the expected upvar types: +/// ```ignore (illustrative) +/// impl<'b, 'a, T> FnMut() for Closure<'a, T, (&'b mut &'a mut T,)> { +/// ... +/// } +/// ``` +/// You can see that the *impl* fully specified the type of the upvar +/// and thus knows full well that `data` has type `&'b mut &'a mut T`. +/// (Here, I am assuming that `data` is mut-borrowed.) +/// +/// Now, the last question you may ask is: Why include the upvar types +/// in an extra type parameter? The reason for this design is that the +/// upvar types can reference lifetimes that are internal to the +/// creating function. In my example above, for example, the lifetime +/// `'b` represents the scope of the closure itself; this is some +/// subset of `foo`, probably just the scope of the call to the to +/// `do()`. If we just had the lifetime/type parameters from the +/// enclosing function, we couldn't name this lifetime `'b`. Note that +/// there can also be lifetimes in the types of the upvars themselves, +/// if one of them happens to be a reference to something that the +/// creating fn owns. +/// +/// OK, you say, so why not create a more minimal set of parameters +/// that just includes the extra lifetime parameters? The answer is +/// primarily that it would be hard --- we don't know at the time when +/// we create the closure type what the full types of the upvars are, +/// nor do we know which are borrowed and which are not. In this +/// design, we can just supply a fresh type parameter and figure that +/// out later. +/// +/// All right, you say, but why include the type parameters from the +/// original function then? The answer is that codegen may need them +/// when monomorphizing, and they may not appear in the upvars. A +/// closure could capture no variables but still make use of some +/// in-scope type parameter with a bound (e.g., if our example above +/// had an extra `U: Default`, and the closure called `U::default()`). +/// +/// There is another reason. This design (implicitly) prohibits +/// closures from capturing themselves (except via a trait +/// object). This simplifies closure inference considerably, since it +/// means that when we infer the kind of a closure or its upvars, we +/// don't have to handle cycles where the decisions we make for +/// closure C wind up influencing the decisions we ought to make for +/// closure C (which would then require fixed point iteration to +/// handle). Plus it fixes an ICE. :P +/// +/// ## Coroutines +/// +/// Coroutines are handled similarly in `CoroutineArgs`. The set of +/// type parameters is similar, but `CK` and `CS` are replaced by the +/// following type parameters: +/// +/// * `GS`: The coroutine's "resume type", which is the type of the +/// argument passed to `resume`, and the type of `yield` expressions +/// inside the coroutine. +/// * `GY`: The "yield type", which is the type of values passed to +/// `yield` inside the coroutine. +/// * `GR`: The "return type", which is the type of value returned upon +/// completion of the coroutine. +/// * `GW`: The "coroutine witness". +#[derive(derivative::Derivative)] +#[derivative( + Clone(bound = ""), + Copy(bound = ""), + Hash(bound = ""), + PartialEq(bound = ""), + Eq(bound = ""), + Debug(bound = "") +)] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] +pub struct ClosureArgs { + /// Lifetime and type parameters from the enclosing function, + /// concatenated with a tuple containing the types of the upvars. + /// + /// These are separated out because codegen wants to pass them around + /// when monomorphizing. + pub args: I::GenericArgs, +} + +/// Struct returned by `split()`. +pub struct ClosureArgsParts { + /// This is the args of the typeck root. + pub parent_args: I::GenericArgsSlice, + /// Represents the maximum calling capability of the closure. + pub closure_kind_ty: I::Ty, + /// Captures the closure's signature. This closure signature is "tupled", and + /// thus has a peculiar signature of `extern "rust-call" fn((Args, ...)) -> Ty`. + pub closure_sig_as_fn_ptr_ty: I::Ty, + /// The upvars captured by the closure. Remains an inference variable + /// until the upvar analysis, which happens late in HIR typeck. + pub tupled_upvars_ty: I::Ty, +} + +impl ClosureArgs { + /// Construct `ClosureArgs` from `ClosureArgsParts`, containing `Args` + /// for the closure parent, alongside additional closure-specific components. + pub fn new(tcx: I, parts: ClosureArgsParts) -> ClosureArgs { + ClosureArgs { + args: tcx.mk_args_from_iter(parts.parent_args.iter().copied().chain([ + parts.closure_kind_ty.into(), + parts.closure_sig_as_fn_ptr_ty.into(), + parts.tupled_upvars_ty.into(), + ])), + } + } + + /// Divides the closure args into their respective components. + /// The ordering assumed here must match that used by `ClosureArgs::new` above. + fn split(self) -> ClosureArgsParts { + self.args.split_closure_args() + } + + /// Returns the generic parameters of the closure's parent. + pub fn parent_args(self) -> I::GenericArgsSlice { + self.split().parent_args + } + + /// Returns an iterator over the list of types of captured paths by the closure. + /// In case there was a type error in figuring out the types of the captured path, an + /// empty iterator is returned. + #[inline] + pub fn upvar_tys(self) -> I::Tys { + match self.tupled_upvars_ty().kind() { + ty::Error(_) => Default::default(), + ty::Tuple(tys) => tys, + ty::Infer(_) => panic!("upvar_tys called before capture types are inferred"), + ty => panic!("Unexpected representation of upvar types tuple {:?}", ty), + } + } + + /// Returns the tuple type representing the upvars for this closure. + #[inline] + pub fn tupled_upvars_ty(self) -> I::Ty { + self.split().tupled_upvars_ty + } + + /// Returns the closure kind for this closure; may return a type + /// variable during inference. To get the closure kind during + /// inference, use `infcx.closure_kind(args)`. + pub fn kind_ty(self) -> I::Ty { + self.split().closure_kind_ty + } + + /// Returns the `fn` pointer type representing the closure signature for this + /// closure. + // FIXME(eddyb) this should be unnecessary, as the shallowly resolved + // type is known at the time of the creation of `ClosureArgs`, + // see `rustc_hir_analysis::check::closure`. + pub fn sig_as_fn_ptr_ty(self) -> I::Ty { + self.split().closure_sig_as_fn_ptr_ty + } + + /// Returns the closure kind for this closure; only usable outside + /// of an inference context, because in that context we know that + /// there are no type variables. + /// + /// If you have an inference context, use `infcx.closure_kind()`. + pub fn kind(self) -> ty::ClosureKind { + self.kind_ty().to_opt_closure_kind().unwrap() + } + + /// Extracts the signature from the closure. + pub fn sig(self) -> ty::Binder> { + match self.sig_as_fn_ptr_ty().kind() { + ty::FnPtr(sig) => sig, + ty => panic!("closure_sig_as_fn_ptr_ty is not a fn-ptr: {ty:?}"), + } + } +} + +#[derive(derivative::Derivative)] +#[derivative( + Clone(bound = ""), + Copy(bound = ""), + Hash(bound = ""), + PartialEq(bound = ""), + Eq(bound = ""), + Debug(bound = "") +)] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] +pub struct CoroutineClosureArgs { + pub args: I::GenericArgs, +} + +/// See docs for explanation of how each argument is used. +/// +/// See [`CoroutineClosureSignature`] for how these arguments are put together +/// to make a callable [`ty::FnSig`] suitable for typeck and borrowck. +pub struct CoroutineClosureArgsParts { + /// This is the args of the typeck root. + pub parent_args: I::GenericArgsSlice, + /// Represents the maximum calling capability of the closure. + pub closure_kind_ty: I::Ty, + /// Represents all of the relevant parts of the coroutine returned by this + /// coroutine-closure. This signature parts type will have the general + /// shape of `fn(tupled_inputs, resume_ty) -> (return_ty, yield_ty)`, where + /// `resume_ty`, `return_ty`, and `yield_ty` are the respective types for the + /// coroutine returned by the coroutine-closure. + /// + /// Use `coroutine_closure_sig` to break up this type rather than using it + /// yourself. + pub signature_parts_ty: I::Ty, + /// The upvars captured by the closure. Remains an inference variable + /// until the upvar analysis, which happens late in HIR typeck. + pub tupled_upvars_ty: I::Ty, + /// a function pointer that has the shape `for<'env> fn() -> (&'env T, ...)`. + /// This allows us to represent the binder of the self-captures of the closure. + /// + /// For example, if the coroutine returned by the closure borrows `String` + /// from the closure's upvars, this will be `for<'env> fn() -> (&'env String,)`, + /// while the `tupled_upvars_ty`, representing the by-move version of the same + /// captures, will be `(String,)`. + pub coroutine_captures_by_ref_ty: I::Ty, + /// Witness type returned by the generator produced by this coroutine-closure. + pub coroutine_witness_ty: I::Ty, +} + +impl CoroutineClosureArgs { + pub fn new(tcx: I, parts: CoroutineClosureArgsParts) -> CoroutineClosureArgs { + CoroutineClosureArgs { + args: tcx.mk_args_from_iter(parts.parent_args.iter().copied().chain([ + parts.closure_kind_ty.into(), + parts.signature_parts_ty.into(), + parts.tupled_upvars_ty.into(), + parts.coroutine_captures_by_ref_ty.into(), + parts.coroutine_witness_ty.into(), + ])), + } + } + + fn split(self) -> CoroutineClosureArgsParts { + self.args.split_coroutine_closure_args() + } + + pub fn parent_args(self) -> I::GenericArgsSlice { + self.split().parent_args + } + + #[inline] + pub fn upvar_tys(self) -> I::Tys { + match self.tupled_upvars_ty().kind() { + ty::Error(_) => Default::default(), + ty::Tuple(..) => self.tupled_upvars_ty().tuple_fields(), + ty::Infer(_) => panic!("upvar_tys called before capture types are inferred"), + ty => panic!("Unexpected representation of upvar types tuple {:?}", ty), + } + } + + #[inline] + pub fn tupled_upvars_ty(self) -> I::Ty { + self.split().tupled_upvars_ty + } + + pub fn kind_ty(self) -> I::Ty { + self.split().closure_kind_ty + } + + pub fn kind(self) -> ty::ClosureKind { + self.kind_ty().to_opt_closure_kind().unwrap() + } + + pub fn signature_parts_ty(self) -> I::Ty { + self.split().signature_parts_ty + } + + pub fn coroutine_closure_sig(self) -> ty::Binder> { + let interior = self.coroutine_witness_ty(); + let ty::FnPtr(sig) = self.signature_parts_ty().kind() else { panic!() }; + sig.map_bound(|sig| { + let [resume_ty, tupled_inputs_ty] = *sig.inputs() else { + panic!(); + }; + let [yield_ty, return_ty] = **sig.output().tuple_fields() else { panic!() }; + CoroutineClosureSignature { + interior, + tupled_inputs_ty, + resume_ty, + yield_ty, + return_ty, + c_variadic: sig.c_variadic, + safety: sig.safety, + abi: sig.abi, + } + }) + } + + pub fn coroutine_captures_by_ref_ty(self) -> I::Ty { + self.split().coroutine_captures_by_ref_ty + } + + pub fn coroutine_witness_ty(self) -> I::Ty { + self.split().coroutine_witness_ty + } + + pub fn has_self_borrows(&self) -> bool { + match self.coroutine_captures_by_ref_ty().kind() { + ty::FnPtr(sig) => sig + .skip_binder() + .visit_with(&mut HasRegionsBoundAt { binder: ty::INNERMOST }) + .is_break(), + ty::Error(_) => true, + _ => panic!(), + } + } +} + +/// Unlike `has_escaping_bound_vars` or `outermost_exclusive_binder`, this will +/// detect only regions bound *at* the debruijn index. +struct HasRegionsBoundAt { + binder: ty::DebruijnIndex, +} +// FIXME: Could be optimized to not walk into components with no escaping bound vars. +impl TypeVisitor for HasRegionsBoundAt { + type Result = ControlFlow<()>; + fn visit_binder>(&mut self, t: &ty::Binder) -> Self::Result { + self.binder.shift_in(1); + t.super_visit_with(self)?; + self.binder.shift_out(1); + ControlFlow::Continue(()) + } + + fn visit_region(&mut self, r: I::Region) -> Self::Result { + if matches!(r.kind(), ty::ReBound(binder, _) if self.binder == binder) { + ControlFlow::Break(()) + } else { + ControlFlow::Continue(()) + } + } +} + +#[derive(derivative::Derivative)] +#[derivative( + Clone(bound = ""), + Copy(bound = ""), + Hash(bound = ""), + PartialEq(bound = ""), + Eq(bound = ""), + Debug(bound = "") +)] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic)] +pub struct CoroutineClosureSignature { + pub interior: I::Ty, + pub tupled_inputs_ty: I::Ty, + pub resume_ty: I::Ty, + pub yield_ty: I::Ty, + pub return_ty: I::Ty, + + // Like the `fn_sig_as_fn_ptr_ty` of a regular closure, these types + // never actually differ. But we save them rather than recreating them + // from scratch just for good measure. + /// Always false + pub c_variadic: bool, + /// Always `Normal` (safe) + pub safety: I::Safety, + /// Always `RustCall` + pub abi: I::Abi, +} + +impl CoroutineClosureSignature { + /// Construct a coroutine from the closure signature. Since a coroutine signature + /// is agnostic to the type of generator that is returned (by-ref/by-move), + /// the caller must specify what "flavor" of generator that they'd like to + /// create. Additionally, they must manually compute the upvars of the closure. + /// + /// This helper is not really meant to be used directly except for early on + /// during typeck, when we want to put inference vars into the kind and upvars tys. + /// When the kind and upvars are known, use the other helper functions. + pub fn to_coroutine( + self, + tcx: I, + parent_args: I::GenericArgsSlice, + coroutine_kind_ty: I::Ty, + coroutine_def_id: I::DefId, + tupled_upvars_ty: I::Ty, + ) -> I::Ty { + let coroutine_args = ty::CoroutineArgs::new( + tcx, + ty::CoroutineArgsParts { + parent_args, + kind_ty: coroutine_kind_ty, + resume_ty: self.resume_ty, + yield_ty: self.yield_ty, + return_ty: self.return_ty, + witness: self.interior, + tupled_upvars_ty, + }, + ); + + Ty::new_coroutine(tcx, coroutine_def_id, coroutine_args.args) + } + + /// Given known upvars and a [`ClosureKind`](ty::ClosureKind), compute the coroutine + /// returned by that corresponding async fn trait. + /// + /// This function expects the upvars to have been computed already, and doesn't check + /// that the `ClosureKind` is actually supported by the coroutine-closure. + pub fn to_coroutine_given_kind_and_upvars( + self, + tcx: I, + parent_args: I::GenericArgsSlice, + coroutine_def_id: I::DefId, + goal_kind: ty::ClosureKind, + env_region: I::Region, + closure_tupled_upvars_ty: I::Ty, + coroutine_captures_by_ref_ty: I::Ty, + ) -> I::Ty { + let tupled_upvars_ty = Self::tupled_upvars_by_closure_kind( + tcx, + goal_kind, + self.tupled_inputs_ty, + closure_tupled_upvars_ty, + coroutine_captures_by_ref_ty, + env_region, + ); + + self.to_coroutine( + tcx, + parent_args, + Ty::from_coroutine_closure_kind(tcx, goal_kind), + coroutine_def_id, + tupled_upvars_ty, + ) + } + + /// Compute the tupled upvars that a coroutine-closure's output coroutine + /// would return for the given `ClosureKind`. + /// + /// When `ClosureKind` is `FnMut`/`Fn`, then this will use the "captures by ref" + /// to return a set of upvars which are borrowed with the given `env_region`. + /// + /// This ensures that the `AsyncFn::call` will return a coroutine whose upvars' + /// lifetimes are related to the lifetime of the borrow on the closure made for + /// the call. This allows borrowck to enforce the self-borrows correctly. + pub fn tupled_upvars_by_closure_kind( + tcx: I, + kind: ty::ClosureKind, + tupled_inputs_ty: I::Ty, + closure_tupled_upvars_ty: I::Ty, + coroutine_captures_by_ref_ty: I::Ty, + env_region: I::Region, + ) -> I::Ty { + match kind { + ty::ClosureKind::Fn | ty::ClosureKind::FnMut => { + let ty::FnPtr(sig) = coroutine_captures_by_ref_ty.kind() else { + panic!(); + }; + let coroutine_captures_by_ref_ty = + sig.output().skip_binder().fold_with(&mut FoldEscapingRegions { + interner: tcx, + region: env_region, + debruijn: ty::INNERMOST, + }); + Ty::new_tup_from_iter( + tcx, + tupled_inputs_ty + .tuple_fields() + .into_iter() + .chain(coroutine_captures_by_ref_ty.tuple_fields()), + ) + } + ty::ClosureKind::FnOnce => Ty::new_tup_from_iter( + tcx, + tupled_inputs_ty + .tuple_fields() + .into_iter() + .chain(closure_tupled_upvars_ty.tuple_fields()), + ), + } + } +} + +/// Instantiates a `for<'env> ...` binder with a specific region. +// FIXME(async_closures): Get rid of this in favor of `BoundVarReplacerDelegate` +// when that is uplifted. +struct FoldEscapingRegions { + interner: I, + debruijn: ty::DebruijnIndex, + region: I::Region, +} + +impl TypeFolder for FoldEscapingRegions { + fn interner(&self) -> I { + self.interner + } + + fn fold_binder(&mut self, t: ty::Binder) -> ty::Binder + where + T: TypeFoldable, + { + self.debruijn.shift_in(1); + let result = t.super_fold_with(self); + self.debruijn.shift_out(1); + result + } + + fn fold_region(&mut self, r: ::Region) -> ::Region { + if let ty::ReBound(debruijn, _) = r.kind() { + assert!( + debruijn <= self.debruijn, + "cannot instantiate binder with escaping bound vars" + ); + if self.debruijn == debruijn { + shift_region(self.interner, self.region, self.debruijn.as_u32()) + } else { + r + } + } else { + r + } + } +} + +#[derive(derivative::Derivative)] +#[derivative( + Clone(bound = ""), + Copy(bound = ""), + Hash(bound = ""), + PartialEq(bound = ""), + Eq(bound = ""), + Debug(bound = "") +)] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic)] +pub struct GenSig { + pub resume_ty: I::Ty, + pub yield_ty: I::Ty, + pub return_ty: I::Ty, +} + +/// Similar to `ClosureArgs`; see the above documentation for more. +#[derive(derivative::Derivative)] +#[derivative( + Clone(bound = ""), + Copy(bound = ""), + Hash(bound = ""), + PartialEq(bound = ""), + Eq(bound = ""), + Debug(bound = "") +)] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] +pub struct CoroutineArgs { + pub args: I::GenericArgs, +} + +pub struct CoroutineArgsParts { + /// This is the args of the typeck root. + pub parent_args: I::GenericArgsSlice, + + /// The coroutines returned by a coroutine-closure's `AsyncFnOnce`/`AsyncFnMut` + /// implementations must be distinguished since the former takes the closure's + /// upvars by move, and the latter takes the closure's upvars by ref. + /// + /// This field distinguishes these fields so that codegen can select the right + /// body for the coroutine. This has the same type representation as the closure + /// kind: `i8`/`i16`/`i32`. + /// + /// For regular coroutines, this field will always just be `()`. + pub kind_ty: I::Ty, + + pub resume_ty: I::Ty, + pub yield_ty: I::Ty, + pub return_ty: I::Ty, + + /// The interior type of the coroutine. + /// Represents all types that are stored in locals + /// in the coroutine's body. + pub witness: I::Ty, + + /// The upvars captured by the closure. Remains an inference variable + /// until the upvar analysis, which happens late in HIR typeck. + pub tupled_upvars_ty: I::Ty, +} + +impl CoroutineArgs { + /// Construct `CoroutineArgs` from `CoroutineArgsParts`, containing `Args` + /// for the coroutine parent, alongside additional coroutine-specific components. + pub fn new(tcx: I, parts: CoroutineArgsParts) -> CoroutineArgs { + CoroutineArgs { + args: tcx.mk_args_from_iter(parts.parent_args.iter().copied().chain([ + parts.kind_ty.into(), + parts.resume_ty.into(), + parts.yield_ty.into(), + parts.return_ty.into(), + parts.witness.into(), + parts.tupled_upvars_ty.into(), + ])), + } + } + + /// Divides the coroutine args into their respective components. + /// The ordering assumed here must match that used by `CoroutineArgs::new` above. + fn split(self) -> CoroutineArgsParts { + self.args.split_coroutine_args() + } + + /// Returns the generic parameters of the coroutine's parent. + pub fn parent_args(self) -> I::GenericArgsSlice { + self.split().parent_args + } + + // Returns the kind of the coroutine. See docs on the `kind_ty` field. + pub fn kind_ty(self) -> I::Ty { + self.split().kind_ty + } + + /// This describes the types that can be contained in a coroutine. + /// It will be a type variable initially and unified in the last stages of typeck of a body. + /// It contains a tuple of all the types that could end up on a coroutine frame. + /// The state transformation MIR pass may only produce layouts which mention types + /// in this tuple. Upvars are not counted here. + pub fn witness(self) -> I::Ty { + self.split().witness + } + + /// Returns an iterator over the list of types of captured paths by the coroutine. + /// In case there was a type error in figuring out the types of the captured path, an + /// empty iterator is returned. + #[inline] + pub fn upvar_tys(self) -> I::Tys { + match self.tupled_upvars_ty().kind() { + ty::Error(_) => Default::default(), + ty::Tuple(tys) => tys, + ty::Infer(_) => panic!("upvar_tys called before capture types are inferred"), + ty => panic!("Unexpected representation of upvar types tuple {:?}", ty), + } + } + + /// Returns the tuple type representing the upvars for this coroutine. + #[inline] + pub fn tupled_upvars_ty(self) -> I::Ty { + self.split().tupled_upvars_ty + } + + /// Returns the type representing the resume type of the coroutine. + pub fn resume_ty(self) -> I::Ty { + self.split().resume_ty + } + + /// Returns the type representing the yield type of the coroutine. + pub fn yield_ty(self) -> I::Ty { + self.split().yield_ty + } + + /// Returns the type representing the return type of the coroutine. + pub fn return_ty(self) -> I::Ty { + self.split().return_ty + } + + /// Returns the "coroutine signature", which consists of its resume, yield + /// and return types. + pub fn sig(self) -> GenSig { + let parts = self.split(); + GenSig { resume_ty: parts.resume_ty, yield_ty: parts.yield_ty, return_ty: parts.return_ty } + } +} diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs index b58018ca0353..48c4c4206fe8 100644 --- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs +++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs @@ -10,7 +10,7 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{ self, Binder, ClosureArgs, ClosureKind, FnSig, GenericArg, GenericArgKind, List, Region, RegionKind, Ty, - TypeVisitableExt, TypeckResults, + TypeVisitableExt, TypeckResults, TyCtxt, }; use rustc_session::declare_lint_pass; use rustc_span::symbol::sym; @@ -240,7 +240,7 @@ fn check_inputs( }) } -fn check_sig<'tcx>(cx: &LateContext<'tcx>, closure: ClosureArgs<'tcx>, call_sig: FnSig<'_>) -> bool { +fn check_sig<'tcx>(cx: &LateContext<'tcx>, closure: ClosureArgs>, call_sig: FnSig<'_>) -> bool { call_sig.safety == Safety::Safe && !has_late_bound_to_non_late_bound_regions( cx.tcx.signature_unclosure(closure.sig(), Safety::Safe).skip_binder(), From 9bdc5b2455bbd8d71e912b5ceaeb390abb987c91 Mon Sep 17 00:00:00 2001 From: Caleb Zulawski Date: Sat, 1 Jun 2024 14:17:16 -0400 Subject: [PATCH 147/211] Improve documentation --- compiler/rustc_codegen_llvm/src/intrinsic.rs | 7 ++++++- tests/ui/simd/repr_packed.rs | 5 +++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 83a71752ffd8..87098566f6b1 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -480,10 +480,15 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> { } _ if name.as_str().starts_with("simd_") => { - // Unpack non-power-of-2 #[repr(packed)] + // Unpack non-power-of-2 #[repr(packed, simd)] arguments. + // This gives them the expected layout of a regular #[repr(simd)] vector. let mut loaded_args = Vec::new(); for (ty, arg) in arg_tys.iter().zip(args) { loaded_args.push( + // #[repr(packed, simd)] vectors are passed like arrays (as references, + // with reduced alignment and no padding) rather than as immediates. + // We can use a vector load to fix the layout and turn the argument + // into an immediate. if ty.is_simd() && let OperandValue::Ref(place) = arg.val { diff --git a/tests/ui/simd/repr_packed.rs b/tests/ui/simd/repr_packed.rs index 52c794563de6..1ba15bda98dd 100644 --- a/tests/ui/simd/repr_packed.rs +++ b/tests/ui/simd/repr_packed.rs @@ -36,12 +36,13 @@ fn main() { check_ty::(); unsafe { - // powers-of-two have no padding and work as usual + // powers-of-two have no padding and have the same layout as #[repr(simd)] let x: Simd = simd_add(Simd::([0., 1., 2., 3.]), Simd::([2., 2., 2., 2.])); assert_eq!(std::mem::transmute::<_, [f64; 4]>(x), [2., 3., 4., 5.]); - // non-powers-of-two have padding and lesser alignment, but the intrinsic handles it + // non-powers-of-two should have padding (which is removed by #[repr(packed)]), + // but the intrinsic handles it let x: Simd = simd_add(Simd::([0., 1., 2.]), Simd::([2., 2., 2.])); let arr: [f64; 3] = x.0; assert_eq!(arr, [2., 3., 4.]); From 89386092f19eaf4ba7a4a76fbb666e537575160a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Sat, 1 Jun 2024 18:39:03 +0200 Subject: [PATCH 148/211] Reject CVarArgs in parse_ty_for_where_clause --- compiler/rustc_parse/src/parser/ty.rs | 5 +++-- .../macro/mbe-dotdotdot-may-not-begin-a-type.rs | 11 +++++++++++ tests/ui/parser/variadic-ffi-nested-syntactic-fail.rs | 4 ++++ .../parser/variadic-ffi-nested-syntactic-fail.stderr | 10 ++++++++-- 4 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 tests/ui/parser/macro/mbe-dotdotdot-may-not-begin-a-type.rs diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 2df8f58507b0..2033f3878875 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -194,7 +194,7 @@ impl<'a> Parser<'a> { pub(super) fn parse_ty_for_where_clause(&mut self) -> PResult<'a, P> { self.parse_ty_common( AllowPlus::Yes, - AllowCVariadic::Yes, + AllowCVariadic::No, RecoverQPath::Yes, RecoverReturnSign::OnlyFatArrow, None, @@ -344,8 +344,9 @@ impl<'a> Parser<'a> { match allow_c_variadic { AllowCVariadic::Yes => TyKind::CVarArgs, AllowCVariadic::No => { - // FIXME(Centril): Should we just allow `...` syntactically + // FIXME(c_variadic): Should we just allow `...` syntactically // anywhere in a type and use semantic restrictions instead? + // NOTE: This may regress certain MBE calls if done incorrectly. let guar = self .dcx() .emit_err(NestedCVariadicType { span: lo.to(self.prev_token.span) }); diff --git a/tests/ui/parser/macro/mbe-dotdotdot-may-not-begin-a-type.rs b/tests/ui/parser/macro/mbe-dotdotdot-may-not-begin-a-type.rs new file mode 100644 index 000000000000..8be99f22d2ee --- /dev/null +++ b/tests/ui/parser/macro/mbe-dotdotdot-may-not-begin-a-type.rs @@ -0,0 +1,11 @@ +// A bare `...` represents `CVarArgs` (`VaListImpl<'_>`) in function argument type +// position without being a proper type syntactically. +// This test ensures that we do not regress certain MBE calls would we ever promote +// `...` to a proper type syntactically. + +//@ check-pass + +macro_rules! ck { ($ty:ty) => { compile_error!(""); }; (...) => {}; } +ck!(...); + +fn main() {} diff --git a/tests/ui/parser/variadic-ffi-nested-syntactic-fail.rs b/tests/ui/parser/variadic-ffi-nested-syntactic-fail.rs index 4da9ad84bab7..d9d3f9227a9e 100644 --- a/tests/ui/parser/variadic-ffi-nested-syntactic-fail.rs +++ b/tests/ui/parser/variadic-ffi-nested-syntactic-fail.rs @@ -4,6 +4,10 @@ fn f1<'a>(x: u8, y: &'a ...) {} fn f2<'a>(x: u8, y: Vec<&'a ...>) {} //~^ ERROR C-variadic type `...` may not be nested inside another type +// Regression test for issue #125847. +fn f3() where for<> ...: {} +//~^ ERROR C-variadic type `...` may not be nested inside another type + fn main() { let _recovery_witness: () = 0; //~^ ERROR: mismatched types diff --git a/tests/ui/parser/variadic-ffi-nested-syntactic-fail.stderr b/tests/ui/parser/variadic-ffi-nested-syntactic-fail.stderr index 8b9d676a45da..38833d6555b1 100644 --- a/tests/ui/parser/variadic-ffi-nested-syntactic-fail.stderr +++ b/tests/ui/parser/variadic-ffi-nested-syntactic-fail.stderr @@ -10,15 +10,21 @@ error[E0743]: C-variadic type `...` may not be nested inside another type LL | fn f2<'a>(x: u8, y: Vec<&'a ...>) {} | ^^^ +error[E0743]: C-variadic type `...` may not be nested inside another type + --> $DIR/variadic-ffi-nested-syntactic-fail.rs:8:21 + | +LL | fn f3() where for<> ...: {} + | ^^^ + error[E0308]: mismatched types - --> $DIR/variadic-ffi-nested-syntactic-fail.rs:8:33 + --> $DIR/variadic-ffi-nested-syntactic-fail.rs:12:33 | LL | let _recovery_witness: () = 0; | -- ^ expected `()`, found integer | | | expected due to this -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0308, E0743. For more information about an error, try `rustc --explain E0308`. From 8ab8bb0603dfab5c2c65e5a5ed2b1a2baac23004 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sat, 1 Jun 2024 20:57:29 +0200 Subject: [PATCH 149/211] fix: Fix container search failing for tokens originating within derive attributes --- .../rust-analyzer/crates/hir-expand/src/db.rs | 2 +- .../crates/hir-expand/src/files.rs | 22 ++++++--------- .../crates/hir-expand/src/lib.rs | 16 +++++++++-- .../rust-analyzer/crates/hir/src/semantics.rs | 28 +++++++------------ .../crates/hir/src/semantics/source_to_def.rs | 20 +++++++++---- 5 files changed, 48 insertions(+), 40 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs index 2e5fa6131a77..12421bbe7026 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs @@ -298,7 +298,7 @@ pub fn expand_speculative( // prefer tokens of the same kind and text // Note the inversion of the score here, as we want to prefer the first token in case // of all tokens having the same score - (t.kind() != token_to_map.kind()) as u8 + (t.text() != token_to_map.text()) as u8 + (t.kind() != token_to_map.kind()) as u8 + 2 * ((t.text() != token_to_map.text()) as u8) })?; Some((node.syntax_node(), token)) } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/files.rs b/src/tools/rust-analyzer/crates/hir-expand/src/files.rs index 04a4851ddb72..1ba85c5c7eac 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/files.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/files.rs @@ -153,24 +153,20 @@ impl InFileWrapper { // region:specific impls impl InFile<&SyntaxNode> { - /// Skips the attributed item that caused the macro invocation we are climbing up - pub fn ancestors_with_macros_skip_attr_item( + /// Traverse up macro calls and skips the macro invocation node + pub fn ancestors_with_macros( self, db: &dyn db::ExpandDatabase, ) -> impl Iterator> + '_ { let succ = move |node: &InFile| match node.value.parent() { Some(parent) => Some(node.with_value(parent)), - None => { - let macro_file_id = node.file_id.macro_file()?; - let parent_node = macro_file_id.call_node(db); - if macro_file_id.is_attr_macro(db) { - // macro call was an attributed item, skip it - // FIXME: does this fail if this is a direct expansion of another macro? - parent_node.map(|node| node.parent()).transpose() - } else { - Some(parent_node) - } - } + None => db + .lookup_intern_macro_call(node.file_id.macro_file()?.macro_call_id) + .to_node_item(db) + .syntax() + .cloned() + .map(|node| node.parent()) + .transpose(), }; iter::successors(succ(&self.cloned()), succ) } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs index 4ab989bec2f0..83e92565f4d8 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs @@ -33,8 +33,8 @@ use std::{fmt, hash::Hash}; use base_db::{salsa::impl_intern_value_trivial, CrateId, FileId}; use either::Either; use span::{ - Edition, ErasedFileAstId, FileRange, HirFileIdRepr, Span, SpanAnchor, SyntaxContextData, - SyntaxContextId, + Edition, ErasedFileAstId, FileAstId, FileRange, HirFileIdRepr, Span, SpanAnchor, + SyntaxContextData, SyntaxContextId, }; use syntax::{ ast::{self, AstNode}, @@ -546,6 +546,18 @@ impl MacroCallLoc { } } + pub fn to_node_item(&self, db: &dyn ExpandDatabase) -> InFile { + match self.kind { + MacroCallKind::FnLike { ast_id, .. } => { + InFile::new(ast_id.file_id, ast_id.map(FileAstId::upcast).to_node(db)) + } + MacroCallKind::Derive { ast_id, .. } => { + InFile::new(ast_id.file_id, ast_id.map(FileAstId::upcast).to_node(db)) + } + MacroCallKind::Attr { ast_id, .. } => InFile::new(ast_id.file_id, ast_id.to_node(db)), + } + } + fn expand_to(&self) -> ExpandTo { match self.kind { MacroCallKind::FnLike { expand_to, .. } => expand_to, diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index 6c70cc4baf0a..53242611f814 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -862,10 +862,9 @@ impl<'db> SemanticsImpl<'db> { // attribute we failed expansion for earlier, this might be a derive invocation // or derive helper attribute let attr = meta.parent_attr()?; - let adt = if let Some(adt) = attr.syntax().parent().and_then(ast::Adt::cast) { - // this might be a derive, or a derive helper on an ADT + // this might be a derive on an ADT let derive_call = self.with_ctx(|ctx| { // so try downmapping the token into the pseudo derive expansion // see [hir_expand::builtin_attr_macro] for how the pseudo derive expansion works @@ -882,7 +881,7 @@ impl<'db> SemanticsImpl<'db> { let file_id = call_id.as_macro_file(); let text_range = attr.syntax().text_range(); // remove any other token in this macro input, all their mappings are the - // same as this one + // same as this tokens.retain(|t| !text_range.contains_range(t.text_range())); return process_expansion_for_token(&mut stack, file_id); } @@ -890,21 +889,14 @@ impl<'db> SemanticsImpl<'db> { } } else { // Otherwise this could be a derive helper on a variant or field - if let Some(field) = - attr.syntax().parent().and_then(ast::RecordField::cast) - { - field.syntax().ancestors().take(4).find_map(ast::Adt::cast) - } else if let Some(field) = - attr.syntax().parent().and_then(ast::TupleField::cast) - { - field.syntax().ancestors().take(4).find_map(ast::Adt::cast) - } else if let Some(variant) = - attr.syntax().parent().and_then(ast::Variant::cast) - { - variant.syntax().ancestors().nth(2).and_then(ast::Adt::cast) - } else { - None - } + attr.syntax().ancestors().find_map(ast::Item::cast).and_then(|it| { + match it { + ast::Item::Struct(it) => Some(ast::Adt::Struct(it)), + ast::Item::Enum(it) => Some(ast::Adt::Enum(it)), + ast::Item::Union(it) => Some(ast::Adt::Union(it)), + _ => None, + } + }) }?; if !self.with_ctx(|ctx| ctx.has_derives(InFile::new(file_id, &adt))) { return None; diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs index d2bd8b0e799f..77e7cdb58abc 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs @@ -139,7 +139,7 @@ impl SourceToDefCtx<'_, '_> { let _p = tracing::span!(tracing::Level::INFO, "module_to_def").entered(); let parent_declaration = src .syntax() - .ancestors_with_macros_skip_attr_item(self.db.upcast()) + .ancestors_with_macros(self.db.upcast()) .find_map(|it| it.map(Either::::cast).transpose()) .map(|it| it.transpose()); @@ -366,7 +366,7 @@ impl SourceToDefCtx<'_, '_> { } pub(super) fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option { - for container in src.ancestors_with_macros_skip_attr_item(self.db.upcast()) { + for container in src.ancestors_with_macros(self.db.upcast()) { if let Some(res) = self.container_to_def(container) { return Some(res); } @@ -420,7 +420,7 @@ impl SourceToDefCtx<'_, '_> { } fn find_generic_param_container(&mut self, src: InFile<&SyntaxNode>) -> Option { - let ancestors = src.ancestors_with_macros_skip_attr_item(self.db.upcast()); + let ancestors = src.ancestors_with_macros(self.db.upcast()); for InFile { file_id, value } in ancestors { let item = match ast::Item::cast(value) { Some(it) => it, @@ -429,6 +429,7 @@ impl SourceToDefCtx<'_, '_> { let res: GenericDefId = match item { ast::Item::Fn(it) => self.fn_to_def(InFile::new(file_id, it))?.into(), ast::Item::Struct(it) => self.struct_to_def(InFile::new(file_id, it))?.into(), + ast::Item::Union(it) => self.union_to_def(InFile::new(file_id, it))?.into(), ast::Item::Enum(it) => self.enum_to_def(InFile::new(file_id, it))?.into(), ast::Item::Trait(it) => self.trait_to_def(InFile::new(file_id, it))?.into(), ast::Item::TraitAlias(it) => { @@ -446,11 +447,18 @@ impl SourceToDefCtx<'_, '_> { } fn find_pat_or_label_container(&mut self, src: InFile<&SyntaxNode>) -> Option { - let ancestors = src.ancestors_with_macros_skip_attr_item(self.db.upcast()); + let ancestors = src.ancestors_with_macros(self.db.upcast()); for InFile { file_id, value } in ancestors { - let item = match ast::Item::cast(value) { + let item = match ast::Item::cast(value.clone()) { Some(it) => it, - None => continue, + None => { + if let Some(variant) = ast::Variant::cast(value.clone()) { + return self + .enum_variant_to_def(InFile::new(file_id, variant)) + .map(Into::into); + } + continue; + } }; let res: DefWithBodyId = match item { ast::Item::Const(it) => self.const_to_def(InFile::new(file_id, it))?.into(), From 11d6f18bf6a853ccae06371b67a43a41a4dd8af2 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 1 Jun 2024 02:36:55 -0700 Subject: [PATCH 150/211] Add some more specific checks to the MIR validator None of the `PointerCoercion`s had any, so while there's probably more that could be done here, hopefully these are better than the previous nothing. --- compiler/rustc_mir_transform/src/validate.rs | 101 +++++++++++++++++-- 1 file changed, 94 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 5e83a6f373aa..3b4d4c938771 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -8,6 +8,7 @@ use rustc_middle::mir::coverage::CoverageKind; use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; +use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::{ self, CoroutineArgsExt, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitableExt, Variance, }; @@ -1134,9 +1135,76 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { // FIXME(dyn-star): make sure nothing needs to be done here. } // FIXME: Add Checks for these - CastKind::PointerWithExposedProvenance - | CastKind::PointerExposeProvenance - | CastKind::PointerCoercion(_) => {} + CastKind::PointerWithExposedProvenance | CastKind::PointerExposeProvenance => {} + CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer) => { + // FIXME: check signature compatibility. + check_kinds!( + op_ty, + "CastKind::{kind:?} input must be a fn item, not {:?}", + ty::FnDef(..) + ); + check_kinds!( + target_type, + "CastKind::{kind:?} output must be a fn pointer, not {:?}", + ty::FnPtr(..) + ); + } + CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer) => { + // FIXME: check safety and signature compatibility. + check_kinds!( + op_ty, + "CastKind::{kind:?} input must be a fn pointer, not {:?}", + ty::FnPtr(..) + ); + check_kinds!( + target_type, + "CastKind::{kind:?} output must be a fn pointer, not {:?}", + ty::FnPtr(..) + ); + } + CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(..)) => { + // FIXME: check safety, captures, and signature compatibility. + check_kinds!( + op_ty, + "CastKind::{kind:?} input must be a closure, not {:?}", + ty::Closure(..) + ); + check_kinds!( + target_type, + "CastKind::{kind:?} output must be a fn pointer, not {:?}", + ty::FnPtr(..) + ); + } + CastKind::PointerCoercion(PointerCoercion::MutToConstPointer) => { + // FIXME: check same pointee? + check_kinds!( + op_ty, + "CastKind::{kind:?} input must be a raw mut pointer, not {:?}", + ty::RawPtr(_, Mutability::Mut) + ); + check_kinds!( + target_type, + "CastKind::{kind:?} output must be a raw const pointer, not {:?}", + ty::RawPtr(_, Mutability::Not) + ); + } + CastKind::PointerCoercion(PointerCoercion::ArrayToPointer) => { + // FIXME: Check pointee types + check_kinds!( + op_ty, + "CastKind::{kind:?} input must be a raw pointer, not {:?}", + ty::RawPtr(..) + ); + check_kinds!( + target_type, + "CastKind::{kind:?} output must be a raw pointer, not {:?}", + ty::RawPtr(..) + ); + } + CastKind::PointerCoercion(PointerCoercion::Unsize) => { + // This is used for all `CoerceUnsized` types, + // not just pointers/references, so is hard to check. + } CastKind::IntToInt | CastKind::IntToFloat => { let input_valid = op_ty.is_integral() || op_ty.is_char() || op_ty.is_bool(); let target_valid = target_type.is_numeric() || target_type.is_char(); @@ -1147,10 +1215,29 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { ); } } - CastKind::FnPtrToPtr | CastKind::PtrToPtr => { - if !(op_ty.is_any_ptr() && target_type.is_unsafe_ptr()) { - self.fail(location, "Can't cast {op_ty} into 'Ptr'"); - } + CastKind::FnPtrToPtr => { + check_kinds!( + op_ty, + "CastKind::{kind:?} input must be a fn pointer, not {:?}", + ty::FnPtr(..) + ); + check_kinds!( + target_type, + "CastKind::{kind:?} output must be a raw pointer, not {:?}", + ty::RawPtr(..) + ); + } + CastKind::PtrToPtr => { + check_kinds!( + op_ty, + "CastKind::{kind:?} input must be a raw pointer, not {:?}", + ty::RawPtr(..) + ); + check_kinds!( + target_type, + "CastKind::{kind:?} output must be a raw pointer, not {:?}", + ty::RawPtr(..) + ); } CastKind::FloatToFloat | CastKind::FloatToInt => { if !op_ty.is_floating_point() || !target_type.is_numeric() { From 849c5254afdeb96a740cfac989a382fde69b6067 Mon Sep 17 00:00:00 2001 From: RustyYato Date: Tue, 13 Feb 2024 18:16:00 -0700 Subject: [PATCH 151/211] Change f32::midpoint to upcast to f64 This has been verified by kani as a correct optimization see: https://github.com/rust-lang/rust/issues/110840#issuecomment-1942587398 The new implementation is branchless, and only differs in which NaN values are produced (if any are produced at all). Which is fine to change. Aside from NaN handling, this implementation produces bitwise identical results to the original implementation. The new implementation is gated on targets that have a fast 64-bit floating point implementation in hardware, and on WASM. --- library/core/src/num/f32.rs | 51 +++++++++++++++++++++++------------ library/core/tests/num/mod.rs | 29 +++++++++++++++++--- 2 files changed, 60 insertions(+), 20 deletions(-) diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index 047cb64ce506..7551a5094920 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -1016,25 +1016,42 @@ impl f32 { /// ``` #[unstable(feature = "num_midpoint", issue = "110840")] pub fn midpoint(self, other: f32) -> f32 { - const LO: f32 = f32::MIN_POSITIVE * 2.; - const HI: f32 = f32::MAX / 2.; + cfg_if! { + if #[cfg(any( + target_arch = "x86_64", + target_arch = "aarch64", + all(any(target_arch="riscv32", target_arch= "riscv64"), target_feature="d"), + all(target_arch = "arm", target_feature="vfp2"), + target_arch = "wasm32", + target_arch = "wasm64", + ))] { + // whitelist the faster implementation to targets that have known good 64-bit float + // implementations. Falling back to the branchy code on targets that don't have + // 64-bit hardware floats or buggy implementations. + // see: https://github.com/rust-lang/rust/pull/121062#issuecomment-2123408114 + ((f64::from(self) + f64::from(other)) / 2.0) as f32 + } else { + const LO: f32 = f32::MIN_POSITIVE * 2.; + const HI: f32 = f32::MAX / 2.; - let (a, b) = (self, other); - let abs_a = a.abs_private(); - let abs_b = b.abs_private(); + let (a, b) = (self, other); + let abs_a = a.abs_private(); + let abs_b = b.abs_private(); - if abs_a <= HI && abs_b <= HI { - // Overflow is impossible - (a + b) / 2. - } else if abs_a < LO { - // Not safe to halve a - a + (b / 2.) - } else if abs_b < LO { - // Not safe to halve b - (a / 2.) + b - } else { - // Not safe to halve a and b - (a / 2.) + (b / 2.) + if abs_a <= HI && abs_b <= HI { + // Overflow is impossible + (a + b) / 2. + } else if abs_a < LO { + // Not safe to halve a + a + (b / 2.) + } else if abs_b < LO { + // Not safe to halve b + (a / 2.) + b + } else { + // Not safe to halve a and b + (a / 2.) + (b / 2.) + } + } } } diff --git a/library/core/tests/num/mod.rs b/library/core/tests/num/mod.rs index 863da9b18a28..4b41db72f9bd 100644 --- a/library/core/tests/num/mod.rs +++ b/library/core/tests/num/mod.rs @@ -719,7 +719,7 @@ assume_usize_width! { } macro_rules! test_float { - ($modname: ident, $fty: ty, $inf: expr, $neginf: expr, $nan: expr, $min: expr, $max: expr, $min_pos: expr) => { + ($modname: ident, $fty: ty, $inf: expr, $neginf: expr, $nan: expr, $min: expr, $max: expr, $min_pos: expr, $max_exp:expr) => { mod $modname { #[test] fn min() { @@ -870,6 +870,27 @@ macro_rules! test_float { assert!(($nan as $fty).midpoint(1.0).is_nan()); assert!((1.0 as $fty).midpoint($nan).is_nan()); assert!(($nan as $fty).midpoint($nan).is_nan()); + + // test if large differences in magnitude are still correctly computed. + // NOTE: that because of how small x and y are, x + y can never overflow + // so (x + y) / 2.0 is always correct + // in particular, `2.pow(i)` will never be at the max exponent, so it could + // be safely doubled, while j is significantly smaller. + for i in $max_exp.saturating_sub(64)..$max_exp { + for j in 0..64u8 { + let large = <$fty>::from(2.0f32).powi(i); + // a much smaller number, such that there is no chance of overflow to test + // potential double rounding in midpoint's implementation. + let small = <$fty>::from(2.0f32).powi($max_exp - 1) + * <$fty>::EPSILON + * <$fty>::from(j); + + let naive = (large + small) / 2.0; + let midpoint = large.midpoint(small); + + assert_eq!(naive, midpoint); + } + } } #[test] fn rem_euclid() { @@ -902,7 +923,8 @@ test_float!( f32::NAN, f32::MIN, f32::MAX, - f32::MIN_POSITIVE + f32::MIN_POSITIVE, + f32::MAX_EXP ); test_float!( f64, @@ -912,5 +934,6 @@ test_float!( f64::NAN, f64::MIN, f64::MAX, - f64::MIN_POSITIVE + f64::MIN_POSITIVE, + f64::MAX_EXP ); From 45622450f8bcf4e39238ade6830873a30438e173 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= Date: Fri, 31 May 2024 17:52:41 +0000 Subject: [PATCH 152/211] compiletest: split rmake executable from scratch dir When implementing support for rmake.rs, I copied over the `$TMPDIR` directory logic from the legacy Makefile setup. In doing so, I also compiled recipe `rmake.rs` into executables which unfortunately are placed into `$TMPDIR` as well. This causes a problem on Windows where: - The `rmake.exe` executable is placed in `$TMPDIR`. - We run the `rmake.exe` as a process. - The process uses `rmake.exe` inside `$TMPDIR`. - Windows prevents the .exe file from being deleted when the process is still alive. - The recipe test code tries to `remove_dir_all($TMPDIR)`, which fails with access denied because `rmake.exe` is still being used. We fix this by separating the recipe executable and the sratch directory: ``` base_dir/ rmake.exe scratch/ ``` We construct a base directory, unique to each run-make test, under which we place rmake.exe alongside a `scratch/` directory. This `scratch/` directory is what is passed to rmake.rs tests as `$TMPDIR`, so now `remove_dir_all($TMPDIR)` has a chance to succeed because it no longer contains `rmake.exe`. Oops. This was a fun one to try figure out. --- src/tools/compiletest/src/runtest.rs | 33 ++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 79e158992d47..1c2e3c406713 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -3431,11 +3431,23 @@ impl<'test> TestCx<'test> { let build_root = self.config.build_base.parent().unwrap().parent().unwrap(); let build_root = cwd.join(&build_root); - let tmpdir = cwd.join(self.output_base_name()); - if tmpdir.exists() { - self.aggressive_rm_rf(&tmpdir).unwrap(); + // We construct the following directory tree for each rmake.rs test: + // ``` + // base_dir/ + // rmake.exe + // scratch/ + // ``` + // having the executable separate from the scratch directory allows the recipes to + // `remove_dir_all(scratch)` without running into permission denied issues because + // the executable is not under the `scratch/` directory. + // + // This setup diverges from legacy Makefile run-make tests. + let base_dir = cwd.join(self.output_base_name()); + if base_dir.exists() { + self.aggressive_rm_rf(&base_dir).unwrap(); } - create_dir_all(&tmpdir).unwrap(); + let rmake_out_dir = base_dir.join("rmake_out"); + create_dir_all(&rmake_out_dir).unwrap(); // HACK: assume stageN-target, we only want stageN. let stage = self.config.stage_id.split('-').next().unwrap(); @@ -3452,8 +3464,11 @@ impl<'test> TestCx<'test> { stage_std_path.push("lib"); // Then, we need to build the recipe `rmake.rs` and link in the support library. - let recipe_bin = - tmpdir.join(if self.config.target.contains("windows") { "rmake.exe" } else { "rmake" }); + let recipe_bin = base_dir.join(if self.config.target.contains("windows") { + "rmake.exe" + } else { + "rmake" + }); let mut support_lib_deps = PathBuf::new(); support_lib_deps.push(&build_root); @@ -3494,7 +3509,7 @@ impl<'test> TestCx<'test> { .env("S", &src_root) .env("RUST_BUILD_STAGE", &self.config.stage_id) .env("RUSTC", cwd.join(&self.config.rustc_path)) - .env("TMPDIR", &tmpdir) + .env("TMPDIR", &rmake_out_dir) .env("LD_LIB_PATH_ENVVAR", dylib_env_var()) .env(dylib_env_var(), &host_dylib_env_paths) .env("HOST_RPATH_DIR", cwd.join(&self.config.compile_lib_path)) @@ -3530,7 +3545,7 @@ impl<'test> TestCx<'test> { let dylib_env_paths = env::join_paths(dylib_env_paths).unwrap(); let mut target_rpath_env_path = Vec::new(); - target_rpath_env_path.push(&tmpdir); + target_rpath_env_path.push(&rmake_out_dir); target_rpath_env_path.extend(&orig_dylib_env_paths); let target_rpath_env_path = env::join_paths(target_rpath_env_path).unwrap(); @@ -3546,7 +3561,7 @@ impl<'test> TestCx<'test> { .env("S", &src_root) .env("RUST_BUILD_STAGE", &self.config.stage_id) .env("RUSTC", cwd.join(&self.config.rustc_path)) - .env("TMPDIR", &tmpdir) + .env("TMPDIR", &rmake_out_dir) .env("HOST_RPATH_DIR", cwd.join(&self.config.compile_lib_path)) .env("TARGET_RPATH_DIR", cwd.join(&self.config.run_lib_path)) .env("LLVM_COMPONENTS", &self.config.llvm_components) From 36d5fc9a64769be2dc539d90c9dd374ef45d30c6 Mon Sep 17 00:00:00 2001 From: Vincenzo Palazzo Date: Fri, 31 May 2024 18:10:30 +0000 Subject: [PATCH 153/211] Avoid checking the edition as much as possible Inside #123865, we are adding support for the new semantics for expr2024, but we have noted a performance issue. We realized there is a redundant check for each token regarding an edition. This commit moves the edition check to the end, avoiding some extra checks that can slow down compilation time. Link: https://github.com/rust-lang/rust/pull/123865 Co-Developed-by: @eholk Signed-off-by: Vincenzo Palazzo --- compiler/rustc_parse/src/parser/nonterminal.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 619c4c63e511..a0b704aeea5f 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -47,7 +47,7 @@ impl<'a> Parser<'a> { token.can_begin_expr() // This exception is here for backwards compatibility. && !token.is_keyword(kw::Let) - && (token.span.edition().at_least_rust_2024() || !token.is_keyword(kw::Const)) + && (!token.is_keyword(kw::Const) || token.span.edition().at_least_rust_2024()) } NonterminalKind::Ty => token.can_begin_type(), NonterminalKind::Ident => get_macro_ident(token).is_some(), From f122a6f2f137649efdf4f6a8561b3be52b4a88bb Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sun, 2 Jun 2024 09:28:34 +0200 Subject: [PATCH 154/211] feat: Enable completions within derive helper attributes --- .../rust-analyzer/crates/hir/src/semantics.rs | 221 +++++++++++------- .../ide-completion/src/context/analysis.rs | 86 ++++++- 2 files changed, 209 insertions(+), 98 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index 53242611f814..43de2a6ee7dc 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -380,6 +380,27 @@ impl<'db> SemanticsImpl<'db> { self.with_ctx(|ctx| ctx.has_derives(adt)) } + pub fn derive_helper(&self, attr: &ast::Attr) -> Option> { + let adt = attr.syntax().ancestors().find_map(ast::Item::cast).and_then(|it| match it { + ast::Item::Struct(it) => Some(ast::Adt::Struct(it)), + ast::Item::Enum(it) => Some(ast::Adt::Enum(it)), + ast::Item::Union(it) => Some(ast::Adt::Union(it)), + _ => None, + })?; + let attr_name = attr.path().and_then(|it| it.as_single_name_ref())?.as_name(); + let sa = self.analyze_no_infer(adt.syntax())?; + let id = self.db.ast_id_map(sa.file_id).ast_id(&adt); + let res: Vec<_> = sa + .resolver + .def_map() + .derive_helpers_in_scope(InFile::new(sa.file_id, id))? + .iter() + .filter(|&(name, _, _)| *name == attr_name) + .map(|&(_, macro_, call)| (macro_.into(), call.as_macro_file())) + .collect(); + res.is_empty().not().then_some(res) + } + pub fn is_attr_macro_call(&self, item: &ast::Item) -> bool { let file_id = self.find_file(item.syntax()).file_id; let src = InFile::new(file_id, item.clone()); @@ -409,6 +430,20 @@ impl<'db> SemanticsImpl<'db> { ) } + pub fn speculative_expand_raw( + &self, + macro_file: MacroFileId, + speculative_args: &SyntaxNode, + token_to_map: SyntaxToken, + ) -> Option<(SyntaxNode, SyntaxToken)> { + hir_expand::db::expand_speculative( + self.db.upcast(), + macro_file.macro_call_id, + speculative_args, + token_to_map, + ) + } + /// Expand the macro call with a different item as the input, mapping the `token_to_map` down into the /// expansion. `token_to_map` should be a token from the `speculative args` node. pub fn speculative_expand_attr_macro( @@ -826,99 +861,109 @@ impl<'db> SemanticsImpl<'db> { // Then check for token trees, that means we are either in a function-like macro or // secondary attribute inputs - let tt = token.parent_ancestors().map_while(ast::TokenTree::cast).last()?; - let parent = tt.syntax().parent()?; - - if tt.left_delimiter_token().map_or(false, |it| it == token) { - return None; - } - if tt.right_delimiter_token().map_or(false, |it| it == token) { - return None; - } - - if let Some(macro_call) = ast::MacroCall::cast(parent.clone()) { - let mcall: hir_expand::files::InFileWrapper = - InFile::new(file_id, macro_call); - let file_id = match mcache.get(&mcall) { - Some(&it) => it, - None => { - let it = sa.expand(self.db, mcall.as_ref())?; - mcache.insert(mcall, it); - it + let tt = token + .parent_ancestors() + .map_while(Either::::cast) + .last()?; + match tt { + Either::Left(tt) => { + if tt.left_delimiter_token().map_or(false, |it| it == token) { + return None; } - }; - let text_range = tt.syntax().text_range(); - // remove any other token in this macro input, all their mappings are the - // same as this one - tokens.retain(|t| !text_range.contains_range(t.text_range())); - - process_expansion_for_token(&mut stack, file_id).or(file_id - .eager_arg(self.db.upcast()) - .and_then(|arg| { - // also descend into eager expansions - process_expansion_for_token(&mut stack, arg.as_macro_file()) - })) - } else if let Some(meta) = ast::Meta::cast(parent) { - // attribute we failed expansion for earlier, this might be a derive invocation - // or derive helper attribute - let attr = meta.parent_attr()?; - let adt = if let Some(adt) = attr.syntax().parent().and_then(ast::Adt::cast) - { - // this might be a derive on an ADT - let derive_call = self.with_ctx(|ctx| { - // so try downmapping the token into the pseudo derive expansion - // see [hir_expand::builtin_attr_macro] for how the pseudo derive expansion works - ctx.attr_to_derive_macro_call( - InFile::new(file_id, &adt), - InFile::new(file_id, attr.clone()), - ) - .map(|(_, call_id, _)| call_id) - }); - - match derive_call { - Some(call_id) => { - // resolved to a derive - let file_id = call_id.as_macro_file(); - let text_range = attr.syntax().text_range(); - // remove any other token in this macro input, all their mappings are the - // same as this - tokens.retain(|t| !text_range.contains_range(t.text_range())); - return process_expansion_for_token(&mut stack, file_id); - } - None => Some(adt), + if tt.right_delimiter_token().map_or(false, |it| it == token) { + return None; } - } else { - // Otherwise this could be a derive helper on a variant or field - attr.syntax().ancestors().find_map(ast::Item::cast).and_then(|it| { - match it { - ast::Item::Struct(it) => Some(ast::Adt::Struct(it)), - ast::Item::Enum(it) => Some(ast::Adt::Enum(it)), - ast::Item::Union(it) => Some(ast::Adt::Union(it)), - _ => None, + let macro_call = tt.syntax().parent().and_then(ast::MacroCall::cast)?; + let mcall: hir_expand::files::InFileWrapper = + InFile::new(file_id, macro_call); + let file_id = match mcache.get(&mcall) { + Some(&it) => it, + None => { + let it = sa.expand(self.db, mcall.as_ref())?; + mcache.insert(mcall, it); + it } - }) - }?; - if !self.with_ctx(|ctx| ctx.has_derives(InFile::new(file_id, &adt))) { - return None; + }; + let text_range = tt.syntax().text_range(); + // remove any other token in this macro input, all their mappings are the + // same as this one + tokens.retain(|t| !text_range.contains_range(t.text_range())); + + process_expansion_for_token(&mut stack, file_id).or(file_id + .eager_arg(self.db.upcast()) + .and_then(|arg| { + // also descend into eager expansions + process_expansion_for_token(&mut stack, arg.as_macro_file()) + })) } - // Not an attribute, nor a derive, so it's either a builtin or a derive helper - // Try to resolve to a derive helper and downmap - let attr_name = - attr.path().and_then(|it| it.as_single_name_ref())?.as_name(); - let id = self.db.ast_id_map(file_id).ast_id(&adt); - let helpers = def_map.derive_helpers_in_scope(InFile::new(file_id, id))?; - let mut res = None; - for (.., derive) in - helpers.iter().filter(|(helper, ..)| *helper == attr_name) - { - res = res.or(process_expansion_for_token( - &mut stack, - derive.as_macro_file(), - )); + Either::Right(meta) => { + // attribute we failed expansion for earlier, this might be a derive invocation + // or derive helper attribute + let attr = meta.parent_attr()?; + let adt = match attr.syntax().parent().and_then(ast::Adt::cast) { + Some(adt) => { + // this might be a derive on an ADT + let derive_call = self.with_ctx(|ctx| { + // so try downmapping the token into the pseudo derive expansion + // see [hir_expand::builtin_attr_macro] for how the pseudo derive expansion works + ctx.attr_to_derive_macro_call( + InFile::new(file_id, &adt), + InFile::new(file_id, attr.clone()), + ) + .map(|(_, call_id, _)| call_id) + }); + + match derive_call { + Some(call_id) => { + // resolved to a derive + let file_id = call_id.as_macro_file(); + let text_range = attr.syntax().text_range(); + // remove any other token in this macro input, all their mappings are the + // same as this + tokens.retain(|t| { + !text_range.contains_range(t.text_range()) + }); + return process_expansion_for_token( + &mut stack, file_id, + ); + } + None => Some(adt), + } + } + None => { + // Otherwise this could be a derive helper on a variant or field + attr.syntax().ancestors().find_map(ast::Item::cast).and_then( + |it| match it { + ast::Item::Struct(it) => Some(ast::Adt::Struct(it)), + ast::Item::Enum(it) => Some(ast::Adt::Enum(it)), + ast::Item::Union(it) => Some(ast::Adt::Union(it)), + _ => None, + }, + ) + } + }?; + if !self.with_ctx(|ctx| ctx.has_derives(InFile::new(file_id, &adt))) { + return None; + } + let attr_name = + attr.path().and_then(|it| it.as_single_name_ref())?.as_name(); + // Not an attribute, nor a derive, so it's either a builtin or a derive helper + // Try to resolve to a derive helper and downmap + let id = self.db.ast_id_map(file_id).ast_id(&adt); + let helpers = + def_map.derive_helpers_in_scope(InFile::new(file_id, id))?; + + let mut res = None; + for (.., derive) in + helpers.iter().filter(|(helper, ..)| *helper == attr_name) + { + res = res.or(process_expansion_for_token( + &mut stack, + derive.as_macro_file(), + )); + } + res } - res - } else { - None } })() .is_none(); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs index 79c503e0a10d..f0c6e7a63b00 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs @@ -3,8 +3,9 @@ use std::iter; use hir::{Semantics, Type, TypeInfo, Variant}; use ide_db::{active_parameter::ActiveParameter, RootDatabase}; +use itertools::Either; use syntax::{ - algo::{find_node_at_offset, non_trivia_sibling}, + algo::{ancestors_at_offset, find_node_at_offset, non_trivia_sibling}, ast::{self, AttrKind, HasArgList, HasGenericParams, HasLoopBody, HasName, NameOrNameRef}, match_ast, AstNode, AstToken, Direction, NodeOrToken, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, TextRange, TextSize, T, @@ -119,20 +120,45 @@ fn expand( } // No attributes have been expanded, so look for macro_call! token trees or derive token trees - let orig_tt = match find_node_at_offset::(&original_file, offset) { + let orig_tt = match ancestors_at_offset(&original_file, offset) + .map_while(Either::::cast) + .last() + { Some(it) => it, None => break 'expansion, }; - let spec_tt = match find_node_at_offset::(&speculative_file, offset) { + let spec_tt = match ancestors_at_offset(&speculative_file, offset) + .map_while(Either::::cast) + .last() + { Some(it) => it, None => break 'expansion, }; - // Expand pseudo-derive expansion - if let (Some(orig_attr), Some(spec_attr)) = ( - orig_tt.syntax().parent().and_then(ast::Meta::cast).and_then(|it| it.parent_attr()), - spec_tt.syntax().parent().and_then(ast::Meta::cast).and_then(|it| it.parent_attr()), - ) { + let (tts, attrs) = match (orig_tt, spec_tt) { + (Either::Left(orig_tt), Either::Left(spec_tt)) => { + let attrs = orig_tt + .syntax() + .parent() + .and_then(ast::Meta::cast) + .and_then(|it| it.parent_attr()) + .zip( + spec_tt + .syntax() + .parent() + .and_then(ast::Meta::cast) + .and_then(|it| it.parent_attr()), + ); + (Some((orig_tt, spec_tt)), attrs) + } + (Either::Right(orig_path), Either::Right(spec_path)) => { + (None, orig_path.parent_attr().zip(spec_path.parent_attr())) + } + _ => break 'expansion, + }; + + // Expand pseudo-derive expansion aka `derive(Debug$0)` + if let Some((orig_attr, spec_attr)) = attrs { if let (Some(actual_expansion), Some((fake_expansion, fake_mapped_token))) = ( sema.expand_derive_as_pseudo_attr_macro(&orig_attr), sema.speculative_expand_derive_as_pseudo_attr_macro( @@ -147,15 +173,54 @@ fn expand( fake_mapped_token.text_range().start(), orig_attr, )); + break 'expansion; + } + + if let Some(spec_adt) = + spec_attr.syntax().ancestors().find_map(ast::Item::cast).and_then(|it| match it { + ast::Item::Struct(it) => Some(ast::Adt::Struct(it)), + ast::Item::Enum(it) => Some(ast::Adt::Enum(it)), + ast::Item::Union(it) => Some(ast::Adt::Union(it)), + _ => None, + }) + { + // might be the path of derive helper or a token tree inside of one + if let Some(helpers) = sema.derive_helper(&orig_attr) { + for (_mac, file) in helpers { + if let Some((fake_expansion, fake_mapped_token)) = sema + .speculative_expand_raw( + file, + spec_adt.syntax(), + fake_ident_token.clone(), + ) + { + // we are inside a derive helper token tree, treat this as being inside + // the derive expansion + let actual_expansion = sema.parse_or_expand(file.into()); + let new_offset = fake_mapped_token.text_range().start(); + if new_offset + relative_offset > actual_expansion.text_range().end() { + // offset outside of bounds from the original expansion, + // stop here to prevent problems from happening + break 'expansion; + } + original_file = actual_expansion; + speculative_file = fake_expansion; + fake_ident_token = fake_mapped_token; + offset = new_offset; + continue 'expansion; + } + } + } } // at this point we won't have any more successful expansions, so stop break 'expansion; } // Expand fn-like macro calls + let Some((orig_tt, spec_tt)) = tts else { break 'expansion }; if let (Some(actual_macro_call), Some(macro_call_with_fake_ident)) = ( - orig_tt.syntax().ancestors().find_map(ast::MacroCall::cast), - spec_tt.syntax().ancestors().find_map(ast::MacroCall::cast), + orig_tt.syntax().parent().and_then(ast::MacroCall::cast), + spec_tt.syntax().parent().and_then(ast::MacroCall::cast), ) { let mac_call_path0 = actual_macro_call.path().as_ref().map(|s| s.syntax().text()); let mac_call_path1 = @@ -201,6 +266,7 @@ fn expand( // none of our states have changed so stop the loop break 'expansion; } + ExpansionResult { original_file, speculative_file, offset, fake_ident_token, derive_ctx } } From 5f0043ace66f0db0581bc4bc52d90773cc23d3ac Mon Sep 17 00:00:00 2001 From: Urgau Date: Fri, 31 May 2024 15:39:10 +0200 Subject: [PATCH 155/211] Handle no values cfg with --print=check-cfg --- compiler/rustc_driver_impl/src/lib.rs | 18 +++++++++++------- .../src/compiler-flags/print-check-cfg.md | 1 + tests/run-make/print-check-cfg/rmake.rs | 14 ++++++++++++++ 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 08b97b4953e9..627fd74c8d77 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -814,13 +814,17 @@ fn print_crate_info( match expected_values { ExpectedValues::Any => check_cfgs.push(format!("{name}=any()")), ExpectedValues::Some(values) => { - check_cfgs.extend(values.iter().map(|value| { - if let Some(value) = value { - format!("{name}=\"{value}\"") - } else { - name.to_string() - } - })) + if !values.is_empty() { + check_cfgs.extend(values.iter().map(|value| { + if let Some(value) = value { + format!("{name}=\"{value}\"") + } else { + name.to_string() + } + })) + } else { + check_cfgs.push(format!("{name}=")) + } } } } diff --git a/src/doc/unstable-book/src/compiler-flags/print-check-cfg.md b/src/doc/unstable-book/src/compiler-flags/print-check-cfg.md index e55165b53740..a9237a0f4ef7 100644 --- a/src/doc/unstable-book/src/compiler-flags/print-check-cfg.md +++ b/src/doc/unstable-book/src/compiler-flags/print-check-cfg.md @@ -15,6 +15,7 @@ This print option works similarly to `--print=cfg` (modulo check-cfg specifics): - `cfg(feature, values("foo", "bar"))`: `feature="foo"` and `feature="bar"` - `cfg(feature, values(none(), ""))`: `feature` and `feature=""` - `cfg(feature, values(any()))`: `feature=any()` + - `cfg(feature, values())`: `feature=` - `cfg(any())`: `any()` - *nothing*: `any()=any()` diff --git a/tests/run-make/print-check-cfg/rmake.rs b/tests/run-make/print-check-cfg/rmake.rs index 2d5221644265..a0aa95c8abcf 100644 --- a/tests/run-make/print-check-cfg/rmake.rs +++ b/tests/run-make/print-check-cfg/rmake.rs @@ -48,6 +48,20 @@ fn main() { doesnt_contain: &["any()", "any()=any()", "feature=none()", "feature="], }, }); + check(CheckCfg { + args: &["--check-cfg=cfg(feature, values())"], + contains: Contains::Some { + contains: &["feature="], + doesnt_contain: &["any()", "any()=any()", "feature=none()", "feature"], + }, + }); + check(CheckCfg { + args: &["--check-cfg=cfg(feature, values())", "--check-cfg=cfg(feature, values(none()))"], + contains: Contains::Some { + contains: &["feature"], + doesnt_contain: &["any()", "any()=any()", "feature=none()", "feature="], + }, + }); check(CheckCfg { args: &[ r#"--check-cfg=cfg(feature, values(any()))"#, From f58bf91aceb7bc029bd130a84cbb156f9149491d Mon Sep 17 00:00:00 2001 From: Urgau Date: Fri, 31 May 2024 15:42:07 +0200 Subject: [PATCH 156/211] Add missing tracking issue number for --print=check-cfg --- src/doc/unstable-book/src/compiler-flags/print-check-cfg.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/unstable-book/src/compiler-flags/print-check-cfg.md b/src/doc/unstable-book/src/compiler-flags/print-check-cfg.md index a9237a0f4ef7..ab63c986e856 100644 --- a/src/doc/unstable-book/src/compiler-flags/print-check-cfg.md +++ b/src/doc/unstable-book/src/compiler-flags/print-check-cfg.md @@ -1,6 +1,6 @@ # `print=check-cfg` -The tracking issue for this feature is: [#XXXXXX](https://github.com/rust-lang/rust/issues/XXXXXX). +The tracking issue for this feature is: [#125704](https://github.com/rust-lang/rust/issues/125704). ------------------------ From 2416f460f8ae0aa7ed0a47a1c2ed2c3d96645435 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 31 May 2024 10:47:30 +0200 Subject: [PATCH 157/211] Add `dynamic_lib_extension` and `read_dir` functions to `run-make-support` library --- src/tools/run-make-support/src/lib.rs | 38 ++++++++++++++++++--------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index 0cf64db6ac9c..323fc40e6481 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -123,12 +123,23 @@ pub fn dynamic_lib_name(name: &str) -> String { // ``` assert!(!name.contains(char::is_whitespace), "dynamic library name cannot contain whitespace"); + let extension = dynamic_lib_extension(); if is_darwin() { - format!("lib{name}.dylib") + format!("lib{name}.{extension}") } else if is_windows() { - format!("{name}.dll") + format!("{name}.{extension}") } else { - format!("lib{name}.so") + format!("lib{name}.{extension}") + } +} + +pub fn dynamic_lib_extension() -> &'static str { + if is_darwin() { + "dylib" + } else if is_windows() { + "dll" + } else { + "so" } } @@ -249,16 +260,13 @@ pub fn recursive_diff(dir1: impl AsRef, dir2: impl AsRef) { } let dir2 = dir2.as_ref(); - for entry in fs::read_dir(dir1).unwrap() { - let entry = entry.unwrap(); - let entry_name = entry.file_name(); - let path = entry.path(); - - if path.is_dir() { - recursive_diff(&path, &dir2.join(entry_name)); + read_dir(dir1, |entry_path| { + let entry_name = entry_path.file_name().unwrap(); + if entry_path.is_dir() { + recursive_diff(&entry_path, &dir2.join(entry_name)); } else { let path2 = dir2.join(entry_name); - let file1 = read_file(&path); + let file1 = read_file(&entry_path); let file2 = read_file(&path2); // We don't use `assert_eq!` because they are `Vec`, so not great for display. @@ -267,10 +275,16 @@ pub fn recursive_diff(dir1: impl AsRef, dir2: impl AsRef) { assert!( file1 == file2, "`{}` and `{}` have different content", - path.display(), + entry_path.display(), path2.display(), ); } + }); +} + +pub fn read_dir(dir: impl AsRef, callback: F) { + for entry in fs::read_dir(dir).unwrap() { + callback(&entry.unwrap().path()); } } From d23d3408580ca9ba64cd1418698a643ab73c3f31 Mon Sep 17 00:00:00 2001 From: Rua Date: Sun, 2 Jun 2024 12:01:07 +0200 Subject: [PATCH 158/211] Implement feature `integer_sign_cast` --- library/core/src/num/int_macros.rs | 24 ++++++++++++++++++++++++ library/core/src/num/uint_macros.rs | 24 ++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index c9c6e34eaad8..e674ce46a330 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -183,6 +183,30 @@ macro_rules! int_impl { (self as $UnsignedT).trailing_ones() } + /// Returns the bit pattern of `self` reinterpreted as an unsigned integer of the same size. + /// + /// This is a bit safer than `as` because it wouldn't silently change the size if the code + /// is refactored. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(integer_sign_cast)] + /// + #[doc = concat!("let n = -1", stringify!($SelfT), ";")] + /// + #[doc = concat!("assert_eq!(n.cast_unsigned(), ", stringify!($UnsignedT), "::MAX);")] + /// ``` + #[unstable(feature = "integer_sign_cast", issue = "125882")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn cast_unsigned(self) -> $UnsignedT { + self as $UnsignedT + } + /// Shifts the bits to the left by a specified amount, `n`, /// wrapping the truncated bits to the end of the resulting integer. /// diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 50a8f4111195..229f5ac58780 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -184,6 +184,30 @@ macro_rules! uint_impl { (!self).trailing_zeros() } + /// Returns the bit pattern of `self` reinterpreted as a signed integer of the same size. + /// + /// This is a bit safer than `as` because it wouldn't silently change the size if the code + /// is refactored. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(integer_sign_cast)] + /// + #[doc = concat!("let n = ", stringify!($SelfT), "::MAX;")] + /// + #[doc = concat!("assert_eq!(n.cast_signed(), -1", stringify!($SignedT), ");")] + /// ``` + #[unstable(feature = "integer_sign_cast", issue = "125882")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn cast_signed(self) -> $SignedT { + self as $SignedT + } + /// Shifts the bits to the left by a specified amount, `n`, /// wrapping the truncated bits to the end of the resulting integer. /// From 32933a6869281aaa7718be4c42f5a2b0c9c9c4cf Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 31 May 2024 10:47:57 +0200 Subject: [PATCH 159/211] Migrate `run-make/c-link-to-rust-dylib` to `rmake.rs` --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/c-link-to-rust-dylib/Makefile | 21 ---------- tests/run-make/c-link-to-rust-dylib/rmake.rs | 41 +++++++++++++++++++ 3 files changed, 41 insertions(+), 22 deletions(-) delete mode 100644 tests/run-make/c-link-to-rust-dylib/Makefile create mode 100644 tests/run-make/c-link-to-rust-dylib/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index ebe9d2b7bb0b..57637f7ae642 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/bare-outfile/Makefile run-make/branch-protection-check-IBT/Makefile run-make/c-dynamic-dylib/Makefile run-make/c-dynamic-rlib/Makefile -run-make/c-link-to-rust-dylib/Makefile run-make/c-static-dylib/Makefile run-make/c-static-rlib/Makefile run-make/c-unwind-abi-catch-lib-panic/Makefile diff --git a/tests/run-make/c-link-to-rust-dylib/Makefile b/tests/run-make/c-link-to-rust-dylib/Makefile deleted file mode 100644 index 201f717ece49..000000000000 --- a/tests/run-make/c-link-to-rust-dylib/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -# This test checks that C linking with Rust does not encounter any errors, with dynamic libraries. -# See https://github.com/rust-lang/rust/issues/10434 - -# ignore-cross-compile -include ../tools.mk - -all: $(TMPDIR)/$(call BIN,bar) - $(call RUN,bar) - $(call REMOVE_DYLIBS,foo) - $(call FAIL,bar) - -ifdef IS_MSVC -$(TMPDIR)/$(call BIN,bar): $(call DYLIB,foo) - $(CC) bar.c $(TMPDIR)/foo.dll.lib $(call OUT_EXE,bar) -else -$(TMPDIR)/$(call BIN,bar): $(call DYLIB,foo) - $(CC) bar.c -lfoo -o $(call RUN_BINFILE,bar) -L $(TMPDIR) -endif - -$(call DYLIB,foo): foo.rs - $(RUSTC) foo.rs diff --git a/tests/run-make/c-link-to-rust-dylib/rmake.rs b/tests/run-make/c-link-to-rust-dylib/rmake.rs new file mode 100644 index 000000000000..5c4b6d786496 --- /dev/null +++ b/tests/run-make/c-link-to-rust-dylib/rmake.rs @@ -0,0 +1,41 @@ +// This test checks that C linking with Rust does not encounter any errors, with dynamic libraries. +// See . + +//@ ignore-cross-compile + +use std::fs::remove_file; + +use run_make_support::{ + cc, dynamic_lib_extension, is_msvc, read_dir, run, run_fail, rustc, tmp_dir, +}; + +fn main() { + rustc().input("foo.rs").run(); + + if is_msvc() { + let lib = tmp_dir().join("foo.dll.lib"); + + cc().input("bar.c").arg(lib).out_exe("bar").run(); + } else { + cc().input("bar.c") + .arg("-lfoo") + .output(tmp_dir().join("bar")) + .library_search_path(tmp_dir()) + .run(); + } + + run("bar"); + + let expected_extension = dynamic_lib_extension(); + read_dir(tmp_dir(), |path| { + if path.is_file() + && path.extension().is_some_and(|ext| ext == expected_extension) + && path.file_name().and_then(|name| name.to_str()).is_some_and(|name| { + name.ends_with(".so") || name.ends_with(".dll") || name.ends_with(".dylib") + }) + { + remove_file(path).unwrap(); + } + }); + run_fail("bar"); +} From 5c32f84048f12b4cdbb404c0c543d38dec622d26 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Sun, 2 Jun 2024 01:03:51 -0700 Subject: [PATCH 160/211] Test codegen for repr(packed,simd) --- tests/codegen/simd/packed-simd-alignment.rs | 44 +++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 tests/codegen/simd/packed-simd-alignment.rs diff --git a/tests/codegen/simd/packed-simd-alignment.rs b/tests/codegen/simd/packed-simd-alignment.rs new file mode 100644 index 000000000000..53e88d8e5cf1 --- /dev/null +++ b/tests/codegen/simd/packed-simd-alignment.rs @@ -0,0 +1,44 @@ +//@ compile-flags: -Cno-prepopulate-passes + +#![crate_type = "lib"] +#![feature(repr_simd, core_intrinsics)] +// make sure that codegen emits correctly-aligned loads and stores for repr(packed, simd) types +// the alignment of a load should be no less than T, and no more than the size of the vector type +use std::intrinsics::simd as intrinsics; + +#[derive(Copy, Clone)] +#[repr(packed, simd)] +struct f32x3([f32; 3]); + +#[derive(Copy, Clone)] +#[repr(packed, simd)] +struct f32x4([f32; 4]); + +// CHECK-LABEL: load_f32x3 +#[no_mangle] +pub fn load_f32x3(floats: &f32x3) -> f32x3 { + // FIXME: Is a memcpy really the best we can do? + // CHECK: @llvm.memcpy.{{.*}}ptr align 4 {{.*}}ptr align 4 + *floats +} + +// CHECK-LABEL: load_f32x4 +#[no_mangle] +pub fn load_f32x4(floats: &f32x4) -> f32x4 { + // CHECK: load <4 x float>, ptr %{{[a-z0-9_]*}}, align {{4|8|16}} + *floats +} + +// CHECK-LABEL: add_f32x3 +#[no_mangle] +pub fn add_f32x3(x: f32x3, y: f32x3) -> f32x3 { + // CHECK: load <3 x float>, ptr %{{[a-z0-9_]*}}, align 4 + unsafe { intrinsics::simd_add(x, y) } +} + +// CHECK-LABEL: add_f32x4 +#[no_mangle] +pub fn add_f32x4(x: f32x4, y: f32x4) -> f32x4 { + // CHECK: load <4 x float>, ptr %{{[a-z0-9_]*}}, align {{4|8|16}} + unsafe { intrinsics::simd_add(x, y) } +} From 3aefc4aeb27f0322b0771b187c0c0438c9789e0c Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sun, 2 Jun 2024 12:50:49 +0200 Subject: [PATCH 161/211] Improve compiletest expected/not found formatting compiletest, oh compiletest, you are truly one of the tools in this repository. You're the omnipresent gatekeeper, ensuring that every new change works, doesn't break the world, and is nice. We thank you for your work, for your tests, for your test runs, for your features that help writing tests, for all the stability and and good you have caused. Without you, Rust wouldn't exist as it does, without you, nothing would work, without you, we would all go insane from having changes break and having to test them all by hand. Thank you, compiletest. but holy shit i fucking hate your stupid debug output so much i simply cannot take this anymore aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa By changing a few magic lines in this file called "runtest.rs", we can cause compiletest to emit nicer messages. This is widely regarded as a good thing. We stop wasting vertical space, allowing more errors to be displayed at once. Additionally, we add colors, which make it so much more pretty *and* gay, both of which are very good and useful. There's a bit of fuckery needed to get the colors to work. `colored` checks whether stdout is a terminal. We also print to stdout, so that works well. But.... for some stupid reason that I absolutely refuse to even attempt to debug, stdout is *not* a terminal when executing tests *in a terminal*. But stderr is >:). So this just checks whether stderr is a terminal. If you have a use case where you dump compiletest stdout into a place where colors are not supported while having stderr be a terminal, then I'm sorry for you, but you are gonna get colors and you're gonna like it. Stop it with the usual environment variable, which `colored` also respects by default. --- src/tools/compiletest/src/errors.rs | 12 ++++++++++++ src/tools/compiletest/src/main.rs | 10 +++++++++- src/tools/compiletest/src/runtest.rs | 18 +++++++++++++----- 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/src/tools/compiletest/src/errors.rs b/src/tools/compiletest/src/errors.rs index c11d3da13a8b..7a5abc51d043 100644 --- a/src/tools/compiletest/src/errors.rs +++ b/src/tools/compiletest/src/errors.rs @@ -57,6 +57,18 @@ pub struct Error { pub msg: String, } +impl Error { + pub fn render_for_expected(&self) -> String { + use colored::Colorize; + format!( + "{: <10}line {: >3}: {}", + self.kind.map(|kind| kind.to_string()).unwrap_or_default().to_uppercase(), + self.line_num, + self.msg.cyan(), + ) + } +} + #[derive(PartialEq, Debug)] enum WhichLine { ThisLine, diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 42c751bb6bed..1ec3f0a0552e 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -1,10 +1,18 @@ -use std::{env, sync::Arc}; +use std::{env, io::IsTerminal, sync::Arc}; use compiletest::{common::Mode, log_config, parse_config, run_tests}; fn main() { tracing_subscriber::fmt::init(); + // colored checks stdout by default, but for some reason only stderr is a terminal. + // compiletest *does* print many things to stdout, but it doesn't really matter. + if std::io::stderr().is_terminal() + && matches!(std::env::var("NO_COLOR").as_deref(), Err(_) | Ok("0")) + { + colored::control::set_override(true); + } + let config = Arc::new(parse_config(env::args().collect())); if config.valgrind_path.is_none() && config.force_valgrind { diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 79e158992d47..4c233eed7fdd 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -17,10 +17,10 @@ use crate::json; use crate::read2::{read2_abbreviated, Truncated}; use crate::util::{add_dylib_path, dylib_env_var, logv, PathBufExt}; use crate::ColorConfig; +use colored::Colorize; use miropt_test_tools::{files_for_miropt_test, MiroptTest, MiroptTestFile}; use regex::{Captures, Regex}; use rustfix::{apply_suggestions, get_suggestions_from_json, Filter}; - use std::collections::{HashMap, HashSet}; use std::env; use std::ffi::{OsStr, OsString}; @@ -1493,14 +1493,22 @@ impl<'test> TestCx<'test> { unexpected.len(), not_found.len() )); - println!("status: {}\ncommand: {}", proc_res.status, proc_res.cmdline); + println!("status: {}\ncommand: {}\n", proc_res.status, proc_res.cmdline); if !unexpected.is_empty() { - println!("unexpected errors (from JSON output): {:#?}\n", unexpected); + println!("{}", "--- unexpected errors (from JSON output) ---".green()); + for error in &unexpected { + println!("{}", error.render_for_expected()); + } + println!("{}", "---".green()); } if !not_found.is_empty() { - println!("not found errors (from test file): {:#?}\n", not_found); + println!("{}", "--- not found errors (from test file) ---".red()); + for error in ¬_found { + println!("{}", error.render_for_expected()); + } + println!("{}", "---\n".red()); } - panic!(); + panic!("errors differ from expected"); } } From 590c373e43a701cf0218b30bf5fffada80594d9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= Date: Sun, 2 Jun 2024 14:33:31 +0000 Subject: [PATCH 162/211] compiletest: fix outdated rmake.rs comment --- src/tools/compiletest/src/runtest.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 1c2e3c406713..15263ab18210 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -3435,13 +3435,13 @@ impl<'test> TestCx<'test> { // ``` // base_dir/ // rmake.exe - // scratch/ + // rmake_out/ // ``` - // having the executable separate from the scratch directory allows the recipes to - // `remove_dir_all(scratch)` without running into permission denied issues because - // the executable is not under the `scratch/` directory. + // having the executable separate from the output artifacts directory allows the recipes to + // `remove_dir_all($TMPDIR)` without running into permission denied issues because + // the executable is not under the `rmake_out/` directory. // - // This setup diverges from legacy Makefile run-make tests. + // This setup intentionally diverges from legacy Makefile run-make tests. let base_dir = cwd.join(self.output_base_name()); if base_dir.exists() { self.aggressive_rm_rf(&base_dir).unwrap(); From 361c6a5c3a613d3693e9d97da3d9530cc5b7626d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 2 Jun 2024 18:15:50 +0200 Subject: [PATCH 163/211] typo: depending from -> on --- library/core/src/str/pattern.rs | 2 +- library/std/src/sys/thread_local/fast_local/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/str/pattern.rs b/library/core/src/str/pattern.rs index cc66da25795d..8988229be2e5 100644 --- a/library/core/src/str/pattern.rs +++ b/library/core/src/str/pattern.rs @@ -342,7 +342,7 @@ pub unsafe trait ReverseSearcher<'a>: Searcher<'a> { /// /// `(&str)::Searcher` is not a `DoubleEndedSearcher` because /// the pattern `"aa"` in the haystack `"aaa"` matches as either -/// `"[aa]a"` or `"a[aa]"`, depending from which side it is searched. +/// `"[aa]a"` or `"a[aa]"`, depending on which side it is searched. pub trait DoubleEndedSearcher<'a>: ReverseSearcher<'a> {} ///////////////////////////////////////////////////////////////////////////// diff --git a/library/std/src/sys/thread_local/fast_local/mod.rs b/library/std/src/sys/thread_local/fast_local/mod.rs index 25379071cb7a..152137d92709 100644 --- a/library/std/src/sys/thread_local/fast_local/mod.rs +++ b/library/std/src/sys/thread_local/fast_local/mod.rs @@ -1,7 +1,7 @@ //! Thread local support for platforms with native TLS. //! //! To achieve the best performance, we choose from four different types for -//! the TLS variable, depending from the method of initialization used (`const` +//! the TLS variable, depending on the method of initialization used (`const` //! or lazy) and the drop requirements of the stored type: //! //! | | `Drop` | `!Drop` | From b181e8106c96ed7305cb9d87598249d363035fa8 Mon Sep 17 00:00:00 2001 From: Rua Date: Sun, 2 Jun 2024 21:03:24 +0200 Subject: [PATCH 164/211] Wording of the documentation --- library/core/src/num/int_macros.rs | 4 ++-- library/core/src/num/uint_macros.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index e674ce46a330..96510ee4dca6 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -185,8 +185,8 @@ macro_rules! int_impl { /// Returns the bit pattern of `self` reinterpreted as an unsigned integer of the same size. /// - /// This is a bit safer than `as` because it wouldn't silently change the size if the code - /// is refactored. + /// This produces the same result as an `as` cast, but ensures that the bit-width remains + /// the same. /// /// # Examples /// diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 229f5ac58780..1491c27372bf 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -186,8 +186,8 @@ macro_rules! uint_impl { /// Returns the bit pattern of `self` reinterpreted as a signed integer of the same size. /// - /// This is a bit safer than `as` because it wouldn't silently change the size if the code - /// is refactored. + /// This produces the same result as an `as` cast, but ensures that the bit-width remains + /// the same. /// /// # Examples /// From 22ca74f2b089b7f861794969934c7e00f7a945a7 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 7 May 2024 14:12:37 +1000 Subject: [PATCH 165/211] Fix up comments. Wrap overly long ones, etc. --- compiler/rustc_lint/src/builtin.rs | 42 ++++++++++++-------- compiler/rustc_lint/src/context.rs | 3 +- compiler/rustc_lint/src/errors.rs | 2 +- compiler/rustc_lint/src/internal.rs | 14 +++---- compiler/rustc_lint/src/let_underscore.rs | 10 ++--- compiler/rustc_lint/src/levels.rs | 22 +++++----- compiler/rustc_lint/src/methods.rs | 6 +-- compiler/rustc_lint/src/non_local_def.rs | 2 +- compiler/rustc_lint/src/nonstandard_style.rs | 10 ++--- compiler/rustc_lint/src/unused.rs | 9 +++-- 10 files changed, 69 insertions(+), 51 deletions(-) diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index ba42eae34415..87c433a5dc0b 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1494,8 +1494,9 @@ impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds { let ty = cx.tcx.type_of(item.owner_id).skip_binder(); if ty.has_inherent_projections() { - // Bounds of type aliases that contain opaque types or inherent projections are respected. - // E.g: `type X = impl Trait;`, `type X = (impl Trait, Y);`, `type X = Type::Inherent;`. + // Bounds of type aliases that contain opaque types or inherent projections are + // respected. E.g: `type X = impl Trait;`, `type X = (impl Trait, Y);`, `type X = + // Type::Inherent;`. return; } @@ -2224,7 +2225,8 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { hir_generics.span.shrink_to_hi().to(where_span) }; - // Due to macro expansions, the `full_where_span` might not actually contain all predicates. + // Due to macro expansions, the `full_where_span` might not actually contain all + // predicates. if where_lint_spans.iter().all(|&sp| full_where_span.contains(sp)) { lint_spans.push(full_where_span); } else { @@ -2601,7 +2603,8 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { }; // So we have at least one potentially inhabited variant. Might we have two? let Some(second_variant) = potential_variants.next() else { - // There is only one potentially inhabited variant. So we can recursively check that variant! + // There is only one potentially inhabited variant. So we can recursively + // check that variant! return variant_find_init_error( cx, ty, @@ -2611,10 +2614,10 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { init, ); }; - // So we have at least two potentially inhabited variants. - // If we can prove that we have at least two *definitely* inhabited variants, - // then we have a tag and hence leaving this uninit is definitely disallowed. - // (Leaving it zeroed could be okay, depending on which variant is encoded as zero tag.) + // So we have at least two potentially inhabited variants. If we can prove that + // we have at least two *definitely* inhabited variants, then we have a tag and + // hence leaving this uninit is definitely disallowed. (Leaving it zeroed could + // be okay, depending on which variant is encoded as zero tag.) if init == InitKind::Uninit { let definitely_inhabited = (first_variant.1 as usize) + (second_variant.1 as usize) @@ -2825,7 +2828,8 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels { let mut found_labels = Vec::new(); - // A semicolon might not actually be specified as a separator for all targets, but it seems like LLVM accepts it always + // A semicolon might not actually be specified as a separator for all targets, but + // it seems like LLVM accepts it always. let statements = template_str.split(|c| matches!(c, '\n' | ';')); for statement in statements { // If there's a comment, trim it from the statement @@ -2838,7 +2842,8 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels { let mut chars = possible_label.chars(); let Some(start) = chars.next() else { - // Empty string means a leading ':' in this section, which is not a label. + // Empty string means a leading ':' in this section, which is not a + // label. break 'label_loop; }; @@ -2855,12 +2860,15 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels { // Labels continue with ASCII alphanumeric characters, _, or $ for c in chars { - // Inside a template format arg, any character is permitted for the puproses of label detection - // because we assume that it can be replaced with some other valid label string later. - // `options(raw)` asm blocks cannot have format args, so they are excluded from this special case. + // Inside a template format arg, any character is permitted for the + // puproses of label detection because we assume that it can be + // replaced with some other valid label string later. `options(raw)` + // asm blocks cannot have format args, so they are excluded from this + // special case. if !raw && in_bracket { if c == '{' { - // Nested brackets are not allowed in format args, this cannot be a label. + // Nested brackets are not allowed in format args, this cannot + // be a label. break 'label_loop; } @@ -2873,7 +2881,8 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels { in_bracket = true; } else { if !(c.is_ascii_alphanumeric() || matches!(c, '_' | '$')) { - // The potential label had an invalid character inside it, it cannot be a label. + // The potential label had an invalid character inside it, it + // cannot be a label. break 'label_loop; } } @@ -2892,7 +2901,8 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels { .into_iter() .filter_map(|label| find_label_span(label)) .collect::>(); - // If there were labels but we couldn't find a span, combine the warnings and use the template span + // If there were labels but we couldn't find a span, combine the warnings and + // use the template span. let target_spans: MultiSpan = if spans.len() > 0 { spans.into() } else { (*template_span).into() }; diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 56f07a2b5e99..8f0b4c9565c2 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -94,7 +94,8 @@ enum TargetLint { /// A lint name that should give no warnings and have no effect. /// - /// This is used by rustc to avoid warning about old rustdoc lints before rustdoc registers them as tool lints. + /// This is used by rustc to avoid warning about old rustdoc lints before rustdoc registers + /// them as tool lints. Ignored, } diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs index c23d1221bc86..46dfaf0b83f9 100644 --- a/compiler/rustc_lint/src/errors.rs +++ b/compiler/rustc_lint/src/errors.rs @@ -16,7 +16,7 @@ pub struct OverruledAttribute<'a> { #[subdiagnostic] pub sub: OverruledAttributeSub, } -// + pub enum OverruledAttributeSub { DefaultSource { id: String }, NodeSource { span: Span, reason: Option }, diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 6e291a327fa6..9110cccdc46f 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -18,11 +18,11 @@ use rustc_span::Span; use tracing::debug; declare_tool_lint! { - /// The `default_hash_type` lint detects use of [`std::collections::HashMap`]/[`std::collections::HashSet`], - /// suggesting the use of `FxHashMap`/`FxHashSet`. + /// The `default_hash_type` lint detects use of [`std::collections::HashMap`] and + /// [`std::collections::HashSet`], suggesting the use of `FxHashMap`/`FxHashSet`. /// - /// This can help as `FxHasher` can perform better than the default hasher. DOS protection is not - /// required as input is assumed to be trusted. + /// This can help as `FxHasher` can perform better than the default hasher. DOS protection is + /// not required as input is assumed to be trusted. pub rustc::DEFAULT_HASH_TYPES, Allow, "forbid HashMap and HashSet and suggest the FxHash* variants", @@ -35,7 +35,7 @@ impl LateLintPass<'_> for DefaultHashTypes { fn check_path(&mut self, cx: &LateContext<'_>, path: &Path<'_>, hir_id: HirId) { let Res::Def(rustc_hir::def::DefKind::Struct, def_id) = path.res else { return }; if matches!(cx.tcx.hir_node(hir_id), Node::Item(Item { kind: ItemKind::Use(..), .. })) { - // don't lint imports, only actual usages + // Don't lint imports, only actual usages. return; } let preferred = match cx.tcx.get_diagnostic_name(def_id) { @@ -75,8 +75,8 @@ declare_tool_lint! { /// potential query instability, such as iterating over a `HashMap`. /// /// Due to the [incremental compilation](https://rustc-dev-guide.rust-lang.org/queries/incremental-compilation.html) model, - /// queries must return deterministic, stable results. `HashMap` iteration order can change between compilations, - /// and will introduce instability if query results expose the order. + /// queries must return deterministic, stable results. `HashMap` iteration order can change + /// between compilations, and will introduce instability if query results expose the order. pub rustc::POTENTIAL_QUERY_INSTABILITY, Allow, "require explicit opt-in when using potentially unstable methods or functions", diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs index ea82fb9f2625..e6c274ec09a7 100644 --- a/compiler/rustc_lint/src/let_underscore.rs +++ b/compiler/rustc_lint/src/let_underscore.rs @@ -113,11 +113,11 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore { let mut top_level = true; - // We recursively walk through all patterns, so that we can catch cases where the lock is nested in a pattern. - // For the basic `let_underscore_drop` lint, we only look at the top level, since there are many legitimate reasons - // to bind a sub-pattern to an `_`, if we're only interested in the rest. - // But with locks, we prefer having the chance of "false positives" over missing cases, since the effects can be - // quite catastrophic. + // We recursively walk through all patterns, so that we can catch cases where the lock is + // nested in a pattern. For the basic `let_underscore_drop` lint, we only look at the top + // level, since there are many legitimate reasons to bind a sub-pattern to an `_`, if we're + // only interested in the rest. But with locks, we prefer having the chance of "false + // positives" over missing cases, since the effects can be quite catastrophic. local.pat.walk_always(|pat| { let is_top_level = top_level; top_level = false; diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 84645e0ce7fc..fea59b5193ce 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -750,7 +750,8 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { let level = match Level::from_attr(attr) { None => continue, - // This is the only lint level with a `LintExpectationId` that can be created from an attribute + // This is the only lint level with a `LintExpectationId` that can be created from + // an attribute. Some(Level::Expect(unstable_id)) if let Some(hir_id) = source_hir_id => { let LintExpectationId::Unstable { attr_id, lint_index } = unstable_id else { bug!("stable id Level::from_attr") @@ -760,8 +761,8 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { hir_id, attr_index: attr_index.try_into().unwrap(), lint_index, - // we pass the previous unstable attr_id such that we can trace the ast id when building a map - // to go from unstable to stable id. + // We pass the previous unstable attr_id such that we can trace the ast id + // when building a map to go from unstable to stable id. attr_id: Some(attr_id), }; @@ -860,13 +861,15 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { self.store.check_lint_name(&name, tool_name, self.registered_tools); match &lint_result { CheckLintNameResult::Ok(ids) => { - // This checks for instances where the user writes `#[expect(unfulfilled_lint_expectations)]` - // in that case we want to avoid overriding the lint level but instead add an expectation that - // can't be fulfilled. The lint message will include an explanation, that the + // This checks for instances where the user writes + // `#[expect(unfulfilled_lint_expectations)]` in that case we want to avoid + // overriding the lint level but instead add an expectation that can't be + // fulfilled. The lint message will include an explanation, that the // `unfulfilled_lint_expectations` lint can't be expected. if let Level::Expect(expect_id) = level { - // The `unfulfilled_lint_expectations` lint is not part of any lint groups. Therefore. we - // only need to check the slice if it contains a single lint. + // The `unfulfilled_lint_expectations` lint is not part of any lint + // groups. Therefore. we only need to check the slice if it contains a + // single lint. let is_unfulfilled_lint_expectations = match ids { [lint] => *lint == LintId::of(UNFULFILLED_LINT_EXPECTATIONS), _ => false, @@ -997,7 +1000,8 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { // we don't warn about the name change. if let CheckLintNameResult::Renamed(new_name) = lint_result { // Ignore any errors or warnings that happen because the new name is inaccurate - // NOTE: `new_name` already includes the tool name, so we don't have to add it again. + // NOTE: `new_name` already includes the tool name, so we don't have to add it + // again. let CheckLintNameResult::Ok(ids) = self.store.check_lint_name(&new_name, None, self.registered_tools) else { diff --git a/compiler/rustc_lint/src/methods.rs b/compiler/rustc_lint/src/methods.rs index b93245d58d9d..7a71fec769fe 100644 --- a/compiler/rustc_lint/src/methods.rs +++ b/compiler/rustc_lint/src/methods.rs @@ -25,9 +25,9 @@ declare_lint! { /// /// The inner pointer of a `CString` lives only as long as the `CString` it /// points to. Getting the inner pointer of a *temporary* `CString` allows the `CString` - /// to be dropped at the end of the statement, as it is not being referenced as far as the typesystem - /// is concerned. This means outside of the statement the pointer will point to freed memory, which - /// causes undefined behavior if the pointer is later dereferenced. + /// to be dropped at the end of the statement, as it is not being referenced as far as the + /// typesystem is concerned. This means outside of the statement the pointer will point to + /// freed memory, which causes undefined behavior if the pointer is later dereferenced. pub TEMPORARY_CSTRING_AS_PTR, Warn, "detects getting the inner pointer of a temporary `CString`" diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index 5135996186a7..d7ffc34d824f 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -306,7 +306,7 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { } } -// Detecting if the impl definition is leaking outside of it's defining scope. +// Detecting if the impl definition is leaking outside of its defining scope. // // Rule: for each impl, instantiate all local types with inference vars and // then assemble candidates for that goal, if there are more than 1 (non-private diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index dbb0644cd63f..d64f44471620 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -297,14 +297,14 @@ impl NonSnakeCase { // We cannot provide meaningful suggestions // if the characters are in the category of "Uppercase Letter". let sub = if name != sc { - // We have a valid span in almost all cases, but we don't have one when linting a crate - // name provided via the command line. + // We have a valid span in almost all cases, but we don't have one when linting a + // crate name provided via the command line. if !span.is_dummy() { let sc_ident = Ident::from_str_and_span(&sc, span); if sc_ident.is_reserved() { - // We shouldn't suggest a reserved identifier to fix non-snake-case identifiers. - // Instead, recommend renaming the identifier entirely or, if permitted, - // escaping it to create a raw identifier. + // We shouldn't suggest a reserved identifier to fix non-snake-case + // identifiers. Instead, recommend renaming the identifier entirely or, if + // permitted, escaping it to create a raw identifier. if sc_ident.name.can_be_raw() { NonSnakeCaseDiagSub::RenameOrConvertSuggestion { span, diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index a6993547c8fc..c8da9f179e71 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -387,7 +387,8 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { } } - // Returns whether further errors should be suppressed because either a lint has been emitted or the type should be ignored. + // Returns whether further errors should be suppressed because either a lint has been + // emitted or the type should be ignored. fn check_must_use_def( cx: &LateContext<'_>, def_id: DefId, @@ -677,7 +678,8 @@ trait UnusedDelimLint { return true; } - // Check if LHS needs parens to prevent false-positives in cases like `fn x() -> u8 { ({ 0 } + 1) }`. + // Check if LHS needs parens to prevent false-positives in cases like + // `fn x() -> u8 { ({ 0 } + 1) }`. // // FIXME: https://github.com/rust-lang/rust/issues/119426 // The syntax tree in this code is from after macro expansion, so the @@ -722,7 +724,8 @@ trait UnusedDelimLint { } } - // Check if RHS needs parens to prevent false-positives in cases like `if (() == return) {}`. + // Check if RHS needs parens to prevent false-positives in cases like `if (() == return) + // {}`. if !followed_by_block { return false; } From d070e892305435781604da3e8dc14b862f5ed6a4 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 8 May 2024 10:04:26 +1000 Subject: [PATCH 166/211] Reduce some `pub` exposure. --- compiler/rustc_lint/src/passes.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_lint/src/passes.rs b/compiler/rustc_lint/src/passes.rs index c4f5f152de52..2a843977990c 100644 --- a/compiler/rustc_lint/src/passes.rs +++ b/compiler/rustc_lint/src/passes.rs @@ -237,5 +237,5 @@ macro_rules! declare_combined_early_lint_pass { } /// A lint pass boxed up as a trait object. -pub type EarlyLintPassObject = Box; -pub type LateLintPassObject<'tcx> = Box + 'tcx>; +pub(crate) type EarlyLintPassObject = Box; +pub(crate) type LateLintPassObject<'tcx> = Box + 'tcx>; From 32c8a128544272effe74fcf4bc24c2ec1c339c5c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 7 May 2024 14:37:57 +1000 Subject: [PATCH 167/211] Tweak `CheckLintNameResult::Tool`. It has a clumsy type, with repeated `&'a [LintId]`, and sometimes requires an empty string that isn't used in the `Err`+`None` case. This commit splits it into two variants. --- compiler/rustc_lint/src/context.rs | 39 ++++++++++--------- compiler/rustc_lint/src/levels.rs | 60 +++++++++++++----------------- 2 files changed, 46 insertions(+), 53 deletions(-) diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 8f0b4c9565c2..9f0f116cbd03 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -127,12 +127,16 @@ pub enum CheckLintNameResult<'a> { Renamed(String), /// The lint has been removed due to the given reason. Removed(String), - /// The lint is from a tool. If the Option is None, then either - /// the lint does not exist in the tool or the code was not - /// compiled with the tool and therefore the lint was never - /// added to the `LintStore`. Otherwise the `LintId` will be - /// returned as if it where a rustc lint. - Tool(Result<&'a [LintId], (Option<&'a [LintId]>, String)>), + + /// The lint is from a tool. The `LintId` will be returned as if it were a + /// rustc lint. The `Option` indicates if the lint has been + /// renamed. + Tool(&'a [LintId], Option), + + /// The lint is from a tool. Either the lint does not exist in the tool or + /// the code was not compiled with the tool and therefore the lint was + /// never added to the `LintStore`. + MissingTool, } impl LintStore { @@ -385,14 +389,14 @@ impl LintStore { } else { // 2. The tool isn't currently running, so no lints will be registered. // To avoid giving a false positive, ignore all unknown lints. - CheckLintNameResult::Tool(Err((None, String::new()))) + CheckLintNameResult::MissingTool }; } Some(LintGroup { lint_ids, .. }) => { - return CheckLintNameResult::Tool(Ok(lint_ids)); + return CheckLintNameResult::Tool(lint_ids, None); } }, - Some(Id(id)) => return CheckLintNameResult::Tool(Ok(slice::from_ref(id))), + Some(Id(id)) => return CheckLintNameResult::Tool(slice::from_ref(id), None), // If the lint was registered as removed or renamed by the lint tool, we don't need // to treat tool_lints and rustc lints different and can use the code below. _ => {} @@ -412,7 +416,7 @@ impl LintStore { return if *silent { CheckLintNameResult::Ok(lint_ids) } else { - CheckLintNameResult::Tool(Err((Some(lint_ids), (*name).to_string()))) + CheckLintNameResult::Tool(lint_ids, Some((*name).to_string())) }; } CheckLintNameResult::Ok(lint_ids) @@ -473,18 +477,17 @@ impl LintStore { // Reaching this would be weird, but let's cover this case anyway if let Some(LintAlias { name, silent }) = depr { let LintGroup { lint_ids, .. } = self.lint_groups.get(name).unwrap(); - return if *silent { - CheckLintNameResult::Tool(Err((Some(lint_ids), complete_name))) + if *silent { + CheckLintNameResult::Tool(lint_ids, Some(complete_name)) } else { - CheckLintNameResult::Tool(Err((Some(lint_ids), (*name).to_string()))) - }; + CheckLintNameResult::Tool(lint_ids, Some((*name).to_string())) + } + } else { + CheckLintNameResult::Tool(lint_ids, Some(complete_name)) } - CheckLintNameResult::Tool(Err((Some(lint_ids), complete_name))) } }, - Some(Id(id)) => { - CheckLintNameResult::Tool(Err((Some(slice::from_ref(id)), complete_name))) - } + Some(Id(id)) => CheckLintNameResult::Tool(slice::from_ref(id), Some(complete_name)), Some(other) => { debug!("got renamed lint {:?}", other); CheckLintNameResult::NoLint(None) diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index fea59b5193ce..1317af50a4a8 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -593,7 +593,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { let lint = UnknownLintFromCommandLine { name, suggestion, requested_level }; self.emit_lint(UNKNOWN_LINTS, lint); } - CheckLintNameResult::Tool(Err((Some(_), ref replace))) => { + CheckLintNameResult::Tool(_, Some(ref replace)) => { let name = lint_name.clone(); let requested_level = RequestedLevel { level, lint_name }; let lint = DeprecatedLintNameFromCommandLine { name, replace, requested_level }; @@ -902,32 +902,20 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { } } - CheckLintNameResult::Tool(result) => { - match *result { - Ok(ids) => { + CheckLintNameResult::Tool(ids, new_lint_name) => { + let src = match new_lint_name { + None => { let complete_name = &format!("{}::{}", tool_ident.unwrap().name, name); - let src = LintLevelSource::Node { + LintLevelSource::Node { name: Symbol::intern(complete_name), span: sp, reason, - }; - for &id in ids { - if self.check_gated_lint(id, attr.span, false) { - self.insert_spec(id, (level, src)); - } - } - if let Level::Expect(expect_id) = level { - self.provider.push_expectation( - expect_id, - LintExpectation::new(reason, sp, false, tool_name), - ); } } - Err((Some(ids), ref new_lint_name)) => { - let lint = builtin::RENAMED_AND_REMOVED_LINTS; + Some(new_lint_name) => { self.emit_span_lint( - lint, + builtin::RENAMED_AND_REMOVED_LINTS, sp.into(), DeprecatedLintName { name, @@ -935,29 +923,31 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { replace: new_lint_name, }, ); - - let src = LintLevelSource::Node { + LintLevelSource::Node { name: Symbol::intern(new_lint_name), span: sp, reason, - }; - for id in ids { - self.insert_spec(*id, (level, src)); - } - if let Level::Expect(expect_id) = level { - self.provider.push_expectation( - expect_id, - LintExpectation::new(reason, sp, false, tool_name), - ); } } - Err((None, _)) => { - // If Tool(Err(None, _)) is returned, then either the lint does not - // exist in the tool or the code was not compiled with the tool and - // therefore the lint was never added to the `LintStore`. To detect - // this is the responsibility of the lint tool. + }; + for &id in *ids { + if self.check_gated_lint(id, attr.span, false) { + self.insert_spec(id, (level, src)); } } + if let Level::Expect(expect_id) = level { + self.provider.push_expectation( + expect_id, + LintExpectation::new(reason, sp, false, tool_name), + ); + } + } + + CheckLintNameResult::MissingTool => { + // If `MissingTool` is returned, then either the lint does not + // exist in the tool or the code was not compiled with the tool and + // therefore the lint was never added to the `LintStore`. To detect + // this is the responsibility of the lint tool. } &CheckLintNameResult::NoTool => { From b320ac749193d87b8705c5baaa75ba7b9433448f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Mon, 3 Jun 2024 03:50:15 +0200 Subject: [PATCH 168/211] Add a regression test for a former blanket impl synthesis ICE --- tests/rustdoc-ui/ice-blanket-impl-119792.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 tests/rustdoc-ui/ice-blanket-impl-119792.rs diff --git a/tests/rustdoc-ui/ice-blanket-impl-119792.rs b/tests/rustdoc-ui/ice-blanket-impl-119792.rs new file mode 100644 index 000000000000..90f0ea8469b9 --- /dev/null +++ b/tests/rustdoc-ui/ice-blanket-impl-119792.rs @@ -0,0 +1,19 @@ +//@ check-pass +// https://github.com/rust-lang/rust/issues/119792 + +struct Wrapper(T); + +trait Div {} +trait Mul { + type Output; +} + +impl Mul for Wrapper { + type Output = (); +} + +impl Div for Wrapper {} + +pub trait NumOps {} + +impl NumOps for T where T: Mul + Div {} From 6e120cf4642bbc1ee1021cf83d0dc013392f47e5 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Tue, 21 May 2024 15:52:00 -0400 Subject: [PATCH 169/211] Remove some allowed-makefiles --- src/tools/run-make-support/src/run.rs | 4 +- .../tidy/src/allowed_run_make_makefiles.txt | 3 - tests/run-make/bare-outfile/rmake.rs | 8 +- tests/run-make/emit/rmake.rs | 8 +- tests/run-make/mixing-formats/rmake.rs | 133 +++++++++--------- 5 files changed, 80 insertions(+), 76 deletions(-) diff --git a/src/tools/run-make-support/src/run.rs b/src/tools/run-make-support/src/run.rs index 9aad91f1b463..da4f265efc3b 100644 --- a/src/tools/run-make-support/src/run.rs +++ b/src/tools/run-make-support/src/run.rs @@ -4,12 +4,12 @@ use std::process::{Command, Output}; use crate::is_windows; -use super::{bin_name, handle_failed_output}; +use super::handle_failed_output; fn run_common(name: &str) -> (Command, Output) { let mut bin_path = PathBuf::new(); bin_path.push(env::var("TMPDIR").unwrap()); - bin_path.push(&bin_name(name)); + bin_path.push(name); let ld_lib_path_envvar = env::var("LD_LIB_PATH_ENVVAR").unwrap(); let mut cmd = Command::new(bin_path); cmd.env(&ld_lib_path_envvar, { diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 009200aca15d..06a99725315b 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -2,7 +2,6 @@ run-make/allocator-shim-circular-deps/Makefile run-make/allow-non-lint-warnings-cmdline/Makefile run-make/archive-duplicate-names/Makefile run-make/atomic-lock-free/Makefile -run-make/bare-outfile/Makefile run-make/branch-protection-check-IBT/Makefile run-make/c-dynamic-dylib/Makefile run-make/c-dynamic-rlib/Makefile @@ -43,7 +42,6 @@ run-make/emit-path-unhashed/Makefile run-make/emit-shared-files/Makefile run-make/emit-stack-sizes/Makefile run-make/emit-to-stdout/Makefile -run-make/emit/Makefile run-make/env-dep-info/Makefile run-make/error-found-staticlib-instead-crate/Makefile run-make/error-writing-dependencies/Makefile @@ -150,7 +148,6 @@ run-make/min-global-align/Makefile run-make/mingw-export-call-convention/Makefile run-make/mismatching-target-triples/Makefile run-make/missing-crate-dependency/Makefile -run-make/mixing-formats/Makefile run-make/mixing-libs/Makefile run-make/msvc-opt-minsize/Makefile run-make/multiple-emits/Makefile diff --git a/tests/run-make/bare-outfile/rmake.rs b/tests/run-make/bare-outfile/rmake.rs index c2b6347f9689..82d0fab5073b 100644 --- a/tests/run-make/bare-outfile/rmake.rs +++ b/tests/run-make/bare-outfile/rmake.rs @@ -4,12 +4,12 @@ //@ ignore-cross-compile use run_make_support::{run, rustc, tmp_dir}; -use std::fs; use std::env; +use std::fs; -fn main(){ - fs::copy("foo.rs", tmp_dir()).unwrap(); +fn main() { + fs::copy("foo.rs", tmp_dir().join("foo.rs")).unwrap(); env::set_current_dir(tmp_dir()); - rustc().output("foo").input("foo.rs"); + rustc().output("foo").input("foo.rs").run(); run("foo"); } diff --git a/tests/run-make/emit/rmake.rs b/tests/run-make/emit/rmake.rs index d3ccc7fdc27a..8b3ddb66f923 100644 --- a/tests/run-make/emit/rmake.rs +++ b/tests/run-make/emit/rmake.rs @@ -1,6 +1,6 @@ // A bug from 2015 would cause errors when emitting multiple types of files -// in the same rustc call. A fix was created in #30452. This test checks that -// the fix did not accidentally break compilation. +// in the same rustc call. A fix was created in #30452. This test checks that rustc still compiles +// a source file successfully when emission of multiple output artifacts are requested. // See https://github.com/rust-lang/rust/pull/30452 //@ ignore-cross-compile @@ -10,10 +10,10 @@ use run_make_support::{run, rustc}; fn main() { let opt_levels = ["0", "1", "2", "3", "s", "z"]; for level in opt_levels { - rustc().opt_level(level).emit("llvm-bc,llvm-ir,asm,obj,link").input("test-24876.rs"); + rustc().opt_level(level).emit("llvm-bc,llvm-ir,asm,obj,link").input("test-24876.rs").run(); } for level in opt_levels { - rustc().opt_level(level).emit("llvm-bc,llvm-ir,asm,obj,link").input("test-26235.rs"); + rustc().opt_level(level).emit("llvm-bc,llvm-ir,asm,obj,link").input("test-26235.rs").run(); run("test-26235"); } } diff --git a/tests/run-make/mixing-formats/rmake.rs b/tests/run-make/mixing-formats/rmake.rs index c80951a15975..0d40b0325f77 100644 --- a/tests/run-make/mixing-formats/rmake.rs +++ b/tests/run-make/mixing-formats/rmake.rs @@ -15,70 +15,77 @@ use run_make_support::{rustc, tmp_dir}; use std::fs; +fn test_with_teardown(rustc_calls: impl Fn()) { + rustc_calls(); + //FIXME(Oneirical): This should be replaced with the run-make-support fs wrappers. + fs::remove_dir_all(tmp_dir()).unwrap(); + fs::create_dir(tmp_dir()).unwrap(); +} + fn main() { - // Building just baz - rustc().crate_type("rlib").input("foo.rs").run(); - rustc().crate_type("dylib").input("bar1.rs").arg("-Cprefer-dynamic").run(); - rustc().crate_type("dylib,rlib").input("baz.rs").arg("-Cprefer-dynamic").run(); - rustc().crate_type("bin").input("baz.rs").run(); - fs::remove_dir_all(tmp_dir()).unwrap(); - fs::create_dir(tmp_dir()).unwrap(); - rustc().crate_type("dylib").input("foo.rs").arg("-Cprefer-dynamic").run(); - rustc().crate_type("rlib").input("bar1.rs").run(); - rustc().crate_type("dylib,rlib").input("baz.rs").arg("-Cprefer-dynamic").run(); - rustc().crate_type("bin").input("baz.rs").run(); - fs::remove_dir_all(tmp_dir()).unwrap(); - fs::create_dir(tmp_dir()).unwrap(); - // Building baz2 - rustc().crate_type("rlib").input("foo.rs").run(); - rustc().crate_type("dylib").input("bar1.rs").arg("-Cprefer-dynamic").run(); - rustc().crate_type("dylib").input("bar2.rs").arg("-Cprefer-dynamic").run(); - rustc().crate_type("dylib").input("baz2.rs").run_fail_assert_exit_code(1); - rustc().crate_type("bin").input("baz2.rs").run_fail_assert_exit_code(1); - fs::remove_dir_all(tmp_dir()).unwrap(); - fs::create_dir(tmp_dir()).unwrap(); - rustc().crate_type("rlib").input("foo.rs").run(); - rustc().crate_type("rlib").input("bar1.rs").run(); - rustc().crate_type("dylib").input("bar2.rs").arg("-Cprefer-dynamic").run(); - rustc().crate_type("dylib,rlib").input("baz2.rs").run(); - rustc().crate_type("bin").input("baz2.rs").run; - fs::remove_dir_all(tmp_dir()).unwrap(); - fs::create_dir(tmp_dir()).unwrap(); - rustc().crate_type("rlib").input("foo.rs").run(); - rustc().crate_type("dylib").input("bar1.rs").arg("-Cprefer-dynamic").run(); - rustc().crate_type("rlib").input("bar2.rs").run(); - rustc().crate_type("dylib,rlib").input("baz2.rs").arg("-Cprefer-dynamic").run(); - rustc().crate_type("bin").input("baz2.rs").run(); - fs::remove_dir_all(tmp_dir()).unwrap(); - fs::create_dir(tmp_dir()).unwrap(); - rustc().crate_type("rlib").input("foo.rs").run(); - rustc().crate_type("rlib").input("bar1.rs").run(); - rustc().crate_type("rlib").input("bar2.rs").run(); - rustc().crate_type("dylib,rlib").input("baz2.rs").arg("-Cprefer-dynamic").run(); - rustc().crate_type("bin").input("baz2.rs").run(); - fs::remove_dir_all(tmp_dir()).unwrap(); - fs::create_dir(tmp_dir()).unwrap(); - rustc().crate_type("dylib").input("foo.rs").arg("-Cprefer-dynamic").run(); - rustc().crate_type("rlib").input("bar1.rs").run(); - rustc().crate_type("rlib").input("bar2.rs").run(); - rustc().crate_type("dylib,rlib").input("baz2.rs").arg("-Cprefer-dynamic").run(); - rustc().crate_type("bin").input("baz2.rs").run(); - fs::remove_dir_all(tmp_dir()).unwrap(); - fs::create_dir(tmp_dir()).unwrap(); - rustc().crate_type("dylib").input("foo.rs").arg("-Cprefer-dynamic").run(); - rustc().crate_type("dylib").input("bar1.rs").arg("-Cprefer-dynamic").run(); - rustc().crate_type("rlib").input("bar2.rs").run(); - rustc().crate_type("dylib,rlib").input("baz2.rs").run(); - rustc().crate_type("bin").input("baz2.rs").run(); - fs::remove_dir_all(tmp_dir()).unwrap(); - fs::create_dir(tmp_dir()).unwrap(); - rustc().crate_type("dylib").input("foo.rs").arg("-Cprefer-dynamic").run(); - rustc().crate_type("rlib").input("bar1.rs").run(); - rustc().crate_type("dylib").input("bar2.rs").arg("-Cprefer-dynamic").run(); - rustc().crate_type("dylib,rlib").input("baz2.rs").run(); - rustc().crate_type("bin").input("baz2.rs").run(); - fs::remove_dir_all(tmp_dir()).unwrap(); - fs::create_dir(tmp_dir()).unwrap(); + test_with_teardown(|| { + // Building just baz + rustc().crate_type("rlib").input("foo.rs").run(); + rustc().crate_type("dylib").input("bar1.rs").arg("-Cprefer-dynamic").run(); + rustc().crate_type("dylib,rlib").input("baz.rs").arg("-Cprefer-dynamic").run(); + rustc().crate_type("bin").input("baz.rs").run(); + }); + test_with_teardown(|| { + rustc().crate_type("dylib").input("foo.rs").arg("-Cprefer-dynamic").run(); + rustc().crate_type("rlib").input("bar1.rs").run(); + rustc().crate_type("dylib,rlib").input("baz.rs").arg("-Cprefer-dynamic").run(); + rustc().crate_type("bin").input("baz.rs").run(); + }); + test_with_teardown(|| { + // Building baz2 + rustc().crate_type("rlib").input("foo.rs").run(); + rustc().crate_type("dylib").input("bar1.rs").arg("-Cprefer-dynamic").run(); + rustc().crate_type("dylib").input("bar2.rs").arg("-Cprefer-dynamic").run(); + rustc().crate_type("dylib").input("baz2.rs").run_fail_assert_exit_code(1); + rustc().crate_type("bin").input("baz2.rs").run_fail_assert_exit_code(1); + }); + test_with_teardown(|| { + rustc().crate_type("rlib").input("foo.rs").run(); + rustc().crate_type("rlib").input("bar1.rs").run(); + rustc().crate_type("dylib").input("bar2.rs").arg("-Cprefer-dynamic").run(); + rustc().crate_type("dylib,rlib").input("baz2.rs").run(); + rustc().crate_type("bin").input("baz2.rs").run(); + }); + test_with_teardown(|| { + rustc().crate_type("rlib").input("foo.rs").run(); + rustc().crate_type("dylib").input("bar1.rs").arg("-Cprefer-dynamic").run(); + rustc().crate_type("rlib").input("bar2.rs").run(); + rustc().crate_type("dylib,rlib").input("baz2.rs").arg("-Cprefer-dynamic").run(); + rustc().crate_type("bin").input("baz2.rs").run(); + }); + test_with_teardown(|| { + rustc().crate_type("rlib").input("foo.rs").run(); + rustc().crate_type("rlib").input("bar1.rs").run(); + rustc().crate_type("rlib").input("bar2.rs").run(); + rustc().crate_type("dylib,rlib").input("baz2.rs").arg("-Cprefer-dynamic").run(); + rustc().crate_type("bin").input("baz2.rs").run(); + }); + test_with_teardown(|| { + rustc().crate_type("dylib").input("foo.rs").arg("-Cprefer-dynamic").run(); + rustc().crate_type("rlib").input("bar1.rs").run(); + rustc().crate_type("rlib").input("bar2.rs").run(); + rustc().crate_type("dylib,rlib").input("baz2.rs").arg("-Cprefer-dynamic").run(); + rustc().crate_type("bin").input("baz2.rs").run(); + }); + test_with_teardown(|| { + rustc().crate_type("dylib").input("foo.rs").arg("-Cprefer-dynamic").run(); + rustc().crate_type("dylib").input("bar1.rs").arg("-Cprefer-dynamic").run(); + rustc().crate_type("rlib").input("bar2.rs").run(); + rustc().crate_type("dylib,rlib").input("baz2.rs").run(); + rustc().crate_type("bin").input("baz2.rs").run(); + }); + test_with_teardown(|| { + rustc().crate_type("dylib").input("foo.rs").arg("-Cprefer-dynamic").run(); + rustc().crate_type("rlib").input("bar1.rs").run(); + rustc().crate_type("dylib").input("bar2.rs").arg("-Cprefer-dynamic").run(); + rustc().crate_type("dylib,rlib").input("baz2.rs").run(); + rustc().crate_type("bin").input("baz2.rs").run(); + }); rustc().crate_type("dylib").input("foo.rs").arg("-Cprefer-dynamic").run(); rustc().crate_type("dylib").input("bar1.rs").arg("-Cprefer-dynamic").run(); rustc().crate_type("dylib").input("bar2.rs").arg("-Cprefer-dynamic").run(); From 9987363b7e1940273dd34e9fa63e33e03244c9c5 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Sun, 2 Jun 2024 14:09:14 -0700 Subject: [PATCH 170/211] Test codegen for repr(packed,simd) -> repr(simd) --- tests/codegen/simd/packed-simd.rs | 44 +++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 tests/codegen/simd/packed-simd.rs diff --git a/tests/codegen/simd/packed-simd.rs b/tests/codegen/simd/packed-simd.rs new file mode 100644 index 000000000000..f0911b6e3602 --- /dev/null +++ b/tests/codegen/simd/packed-simd.rs @@ -0,0 +1,44 @@ +//@ revisions:opt3 noopt +//@[opt3] compile-flags: -Copt-level=3 +//@[noopt] compile-flags: -Cno-prepopulate-passes + +#![crate_type = "lib"] +#![no_std] +#![feature(repr_simd, core_intrinsics)] +use core::intrinsics::simd as intrinsics; +use core::{mem, ptr}; + +// Test codegen for not only "packed" but also "fully aligned" SIMD types, and conversion between +// A repr(packed,simd) type with 3 elements can't exceed its element alignment, +// whereas the same type as repr(simd) will instead have padding. + +#[repr(simd, packed)] +pub struct Simd([T; N]); + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct FullSimd([T; N]); + +// non-powers-of-two have padding and need to be expanded to full vectors +fn load(v: Simd) -> FullSimd { + unsafe { + let mut tmp = mem::MaybeUninit::>::uninit(); + ptr::copy_nonoverlapping(&v as *const _, tmp.as_mut_ptr().cast(), 1); + tmp.assume_init() + } +} + +// CHECK-LABEL: square_packed +// CHECK-SAME: ptr{{[a-z_ ]*}} sret([[RET_TYPE:[^)]+]]) [[RET_ALIGN:align (8|16)]]{{[^%]*}} [[RET_VREG:%[_0-9]*]] +// CHECK-SAME: ptr{{[a-z_ ]*}} align 4 +#[no_mangle] +pub fn square_packed(x: Simd) -> FullSimd { + // CHECK-NEXT: start + // noopt: alloca [[RET_TYPE]], [[RET_ALIGN]] + // CHECK: load <3 x float> + let x = load(x); + // CHECK: [[VREG:%[a-z0-9_]+]] = fmul <3 x float> + // CHECK-NEXT: store <3 x float> [[VREG]], ptr [[RET_VREG]], [[RET_ALIGN]] + // CHECK-NEXT: ret void + unsafe { intrinsics::simd_mul(x, x) } +} From ac242996366cd0d1ec48ff76638320969c65bed3 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 3 Jun 2024 10:19:57 +1000 Subject: [PATCH 171/211] Reformat `mir!` macro invocations to use braces. The `mir!` macro has multiple parts: - An optional return type annotation. - A sequence of zero or more local declarations. - A mandatory starting anonymous basic block, which is brace-delimited. - A sequence of zero of more additional named basic blocks. Some `mir!` invocations use braces with a "block" style, like so: ``` mir! { let _unit: (); { let non_copy = S(42); let ptr = std::ptr::addr_of_mut!(non_copy); // Inside `callee`, the first argument and `*ptr` are basically // aliasing places! Call(_unit = callee(Move(*ptr), ptr), ReturnTo(after_call), UnwindContinue()) } after_call = { Return() } } ``` Some invocations use parens with a "block" style, like so: ``` mir!( let x: [i32; 2]; let one: i32; { x = [42, 43]; one = 1; x = [one, 2]; RET = Move(x); Return() } ) ``` And some invocations uses parens with a "tighter" style, like so: ``` mir!({ SetDiscriminant(*b, 0); Return() }) ``` This last style is generally used for cases where just the mandatory starting basic block is present. Its braces are placed next to the parens. This commit changes all `mir!` invocations to use braces with a "block" style. Why? - Consistency is good. - The contents of the invocation is a block of code, so it's odd to use parens. They are more normally used for function-like macros. - Most importantly, the next commit will enable rustfmt for `tests/mir-opt/`. rustfmt is more aggressive about formatting macros that use parens than macros that use braces. Without this commit's changes, rustfmt would break a couple of `mir!` macro invocations that use braces within `tests/mir-opt` by inserting an extraneous comma. E.g.: ``` mir!(type RET = (i32, bool);, { // extraneous comma after ';' RET.0 = 1; RET.1 = true; Return() }) ``` Switching those `mir!` invocations to use braces avoids that problem, resulting in this, which is nicer to read as well as being valid syntax: ``` mir! { type RET = (i32, bool); { RET.0 = 1; RET.1 = true; Return() } } ``` --- .../src/elaborate_drops.rs | 4 +- library/core/src/intrinsics/mir.rs | 58 +++++++++-------- .../ptr_metadata_uninit_slice_data.rs | 10 +-- .../ptr_metadata_uninit_slice_data.stderr | 4 +- .../ptr_metadata_uninit_slice_len.rs | 10 +-- .../ptr_metadata_uninit_slice_len.stderr | 4 +- .../intrinsics/ptr_metadata_uninit_thin.rs | 10 +-- .../ptr_metadata_uninit_thin.stderr | 4 +- .../building/custom/aggregate_exprs.rs | 12 ++-- .../mir-opt/building/custom/arbitrary_let.rs | 4 +- tests/mir-opt/building/custom/arrays.rs | 14 +++-- tests/mir-opt/building/custom/as_cast.rs | 12 ++-- tests/mir-opt/building/custom/assume.rs | 12 ++-- .../building/custom/composite_return.rs | 4 +- tests/mir-opt/building/custom/consts.rs | 30 +++++---- tests/mir-opt/building/custom/debuginfo.rs | 20 +++--- tests/mir-opt/building/custom/enums.rs | 34 +++++----- tests/mir-opt/building/custom/operators.rs | 60 +++++++++--------- tests/mir-opt/building/custom/projections.rs | 62 +++++++++++-------- tests/mir-opt/building/custom/references.rs | 30 ++++----- .../mir-opt/building/custom/simple_assign.rs | 16 ++--- tests/mir-opt/building/custom/terminators.rs | 25 +++----- .../mir-opt/building/custom/unwind_action.rs | 16 ++--- .../building/custom/unwind_terminate.rs | 8 +-- tests/mir-opt/copy-prop/borrowed_local.rs | 12 ++-- tests/mir-opt/copy-prop/custom_move_arg.rs | 22 ++++--- tests/mir-opt/copy-prop/move_projection.rs | 4 +- .../copy-prop/mutate_through_pointer.rs | 18 +++--- tests/mir-opt/copy-prop/non_dominate.rs | 24 +++++-- tests/mir-opt/dataflow-const-prop/enum.rs | 4 +- .../dead-store-elimination/call_arg_copy.rs | 4 +- tests/mir-opt/dead-store-elimination/cycle.rs | 4 +- tests/mir-opt/gvn.rs | 24 +++---- .../instsimplify/duplicate_switch_targets.rs | 4 +- tests/mir-opt/jump_threading.rs | 24 +++---- tests/mir-opt/matches_reduce_branches.rs | 8 +-- tests/mir-opt/nrvo_miscompile_111005.rs | 14 +++-- tests/mir-opt/reference_prop.rs | 16 ++--- tests/mir-opt/set_no_discriminant.rs | 8 +-- tests/mir-opt/simplify_dead_blocks.rs | 4 +- tests/mir-opt/switch_to_self.rs | 4 +- tests/ui/mir/lint/assignment-overlap.rs | 4 +- tests/ui/mir/lint/call-overlap.rs | 4 +- tests/ui/mir/lint/no-storage.rs | 4 +- tests/ui/mir/lint/storage-live.rs | 4 +- tests/ui/mir/lint/storage-return.rs | 4 +- tests/ui/mir/mir_codegen_ssa.rs | 4 +- tests/ui/mir/ssa_call_ret.rs | 4 +- tests/ui/mir/validate/critical-edge.rs | 4 +- tests/ui/mir/validate/noncleanup-cleanup.rs | 5 +- tests/ui/mir/validate/noncleanup-resume.rs | 4 +- tests/ui/mir/validate/noncleanup-terminate.rs | 4 +- 52 files changed, 379 insertions(+), 327 deletions(-) diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index 03d952abad11..665b2260294a 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -34,14 +34,14 @@ use std::fmt; /// /// ```text // fn drop_term(t: &mut T) { -// mir!( +// mir! { // { // Drop(*t, exit) // } // exit = { // Return() // } -// ) +// } // } /// ``` pub struct ElaborateDrops; diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs index fa5bb28adff9..ec8488009b96 100644 --- a/library/core/src/intrinsics/mir.rs +++ b/library/core/src/intrinsics/mir.rs @@ -20,7 +20,7 @@ //! //! #[custom_mir(dialect = "built")] //! pub fn simple(x: i32) -> i32 { -//! mir!( +//! mir! { //! let temp2: i32; //! //! { @@ -33,7 +33,7 @@ //! RET = temp2; //! Return() //! } -//! ) +//! } //! } //! ``` //! @@ -71,7 +71,7 @@ //! //! #[custom_mir(dialect = "built")] //! pub fn choose_load(a: &i32, b: &i32, c: bool) -> i32 { -//! mir!( +//! mir! { //! { //! match c { //! true => t, @@ -93,20 +93,22 @@ //! RET = *temp; //! Return() //! } -//! ) +//! } //! } //! //! #[custom_mir(dialect = "built")] //! fn unwrap_unchecked(opt: Option) -> T { -//! mir!({ -//! RET = Move(Field(Variant(opt, 1), 0)); -//! Return() -//! }) +//! mir! { +//! { +//! RET = Move(Field(Variant(opt, 1), 0)); +//! Return() +//! } +//! } //! } //! //! #[custom_mir(dialect = "runtime", phase = "optimized")] //! fn push_and_pop(v: &mut Vec, value: T) { -//! mir!( +//! mir! { //! let _unused; //! let popped; //! @@ -125,19 +127,19 @@ //! ret = { //! Return() //! } -//! ) +//! } //! } //! //! #[custom_mir(dialect = "runtime", phase = "optimized")] //! fn annotated_return_type() -> (i32, bool) { -//! mir!( +//! mir! { //! type RET = (i32, bool); //! { //! RET.0 = 1; //! RET.1 = true; //! Return() //! } -//! ) +//! } //! } //! ``` //! @@ -152,7 +154,7 @@ //! //! #[custom_mir(dialect = "built")] //! fn borrow_error(should_init: bool) -> i32 { -//! mir!( +//! mir! { //! let temp: i32; //! //! { @@ -171,7 +173,7 @@ //! RET = temp; //! Return() //! } -//! ) +//! } //! } //! ``` //! @@ -179,7 +181,7 @@ //! error[E0381]: used binding is possibly-uninitialized //! --> test.rs:24:13 //! | -//! 8 | / mir!( +//! 8 | / mir! { //! 9 | | let temp: i32; //! 10 | | //! 11 | | { @@ -191,7 +193,7 @@ //! | | ^^^^^^^^^^ value used here but it is possibly-uninitialized //! 25 | | Return() //! 26 | | } -//! 27 | | ) +//! 27 | | } //! | |_____- binding declared here but left uninitialized //! //! error: aborting due to 1 previous error @@ -407,18 +409,22 @@ define!( /// /// #[custom_mir(dialect = "built")] /// fn unwrap_deref(opt: Option<&i32>) -> i32 { - /// mir!({ - /// RET = *Field::<&i32>(Variant(opt, 1), 0); - /// Return() - /// }) + /// mir! { + /// { + /// RET = *Field::<&i32>(Variant(opt, 1), 0); + /// Return() + /// } + /// } /// } /// /// #[custom_mir(dialect = "built")] /// fn set(opt: &mut Option) { - /// mir!({ - /// place!(Field(Variant(*opt, 1), 0)) = 5; - /// Return() - /// }) + /// mir! { + /// { + /// place!(Field(Variant(*opt, 1), 0)) = 5; + /// Return() + /// } + /// } /// } /// ``` fn Field(place: (), field: u32) -> F @@ -455,7 +461,7 @@ define!( /// your MIR into something that is easier to parse in the compiler. #[rustc_macro_transparency = "transparent"] pub macro mir { - ( + { $(type RET = $ret_ty:ty ;)? $(let $local_decl:ident $(: $local_decl_ty:ty)? ;)* $(debug $dbg_name:ident => $dbg_data:expr ;)* @@ -469,7 +475,7 @@ pub macro mir { $($block:tt)* } )* - ) => {{ + } => {{ // First, we declare all basic blocks. __internal_declare_basic_blocks!($( $block_name $(($block_cleanup))? diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.rs b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.rs index ff23f1e729e8..0c305eed6e18 100644 --- a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.rs +++ b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.rs @@ -7,10 +7,12 @@ use std::intrinsics::mir::*; #[custom_mir(dialect = "runtime")] pub unsafe fn deref_meta(p: *const *const [i32]) -> usize { - mir!({ - RET = PtrMetadata(*p); //~ ERROR: Undefined Behavior: using uninitialized data - Return() - }) + mir! { + { + RET = PtrMetadata(*p); //~ ERROR: Undefined Behavior: using uninitialized data + Return() + } + } } fn main() { diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.stderr index 61e1541d1ee4..6478dcc2507f 100644 --- a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.stderr +++ b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.stderr @@ -1,8 +1,8 @@ error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory --> $DIR/ptr_metadata_uninit_slice_data.rs:LL:CC | -LL | RET = PtrMetadata(*p); - | ^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory +LL | RET = PtrMetadata(*p); + | ^^^^^^^^^^^^^^^^^^^^^ 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 diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.rs b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.rs index 65f74c0acdd6..a2ffdc92c4e2 100644 --- a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.rs +++ b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.rs @@ -7,10 +7,12 @@ use std::intrinsics::mir::*; #[custom_mir(dialect = "runtime")] pub unsafe fn deref_meta(p: *const *const [i32]) -> usize { - mir!({ - RET = PtrMetadata(*p); //~ ERROR: Undefined Behavior: using uninitialized data - Return() - }) + mir! { + { + RET = PtrMetadata(*p); //~ ERROR: Undefined Behavior: using uninitialized data + Return() + } + } } fn main() { diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.stderr index de559263a326..4e2e72184323 100644 --- a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.stderr +++ b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.stderr @@ -16,8 +16,8 @@ LL | (*p.as_mut_ptr().cast::<[*const i32; 2]>())[0] = 4 as *const i32; error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory --> $DIR/ptr_metadata_uninit_slice_len.rs:LL:CC | -LL | RET = PtrMetadata(*p); - | ^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory +LL | RET = PtrMetadata(*p); + | ^^^^^^^^^^^^^^^^^^^^^ 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 diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.rs b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.rs index ad2e9fc800eb..e5a51289a8ae 100644 --- a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.rs +++ b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.rs @@ -7,10 +7,12 @@ use std::intrinsics::mir::*; #[custom_mir(dialect = "runtime")] pub unsafe fn deref_meta(p: *const *const i32) -> () { - mir!({ - RET = PtrMetadata(*p); //~ ERROR: Undefined Behavior: using uninitialized data - Return() - }) + mir! { + { + RET = PtrMetadata(*p); //~ ERROR: Undefined Behavior: using uninitialized data + Return() + } + } } fn main() { diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.stderr index 3ab2643afa72..0e218de0eeb5 100644 --- a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.stderr +++ b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.stderr @@ -1,8 +1,8 @@ error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory --> $DIR/ptr_metadata_uninit_thin.rs:LL:CC | -LL | RET = PtrMetadata(*p); - | ^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory +LL | RET = PtrMetadata(*p); + | ^^^^^^^^^^^^^^^^^^^^^ 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 diff --git a/tests/mir-opt/building/custom/aggregate_exprs.rs b/tests/mir-opt/building/custom/aggregate_exprs.rs index d581886247ff..8985f106817b 100644 --- a/tests/mir-opt/building/custom/aggregate_exprs.rs +++ b/tests/mir-opt/building/custom/aggregate_exprs.rs @@ -7,18 +7,18 @@ use core::intrinsics::mir::*; // EMIT_MIR aggregate_exprs.tuple.built.after.mir #[custom_mir(dialect = "built")] fn tuple() -> (i32, bool) { - mir!( + mir! { { RET = (1, true); Return() } - ) + } } // EMIT_MIR aggregate_exprs.array.built.after.mir #[custom_mir(dialect = "built")] fn array() -> [i32; 2] { - mir!( + mir! { let x: [i32; 2]; let one: i32; { @@ -28,7 +28,7 @@ fn array() -> [i32; 2] { RET = Move(x); Return() } - ) + } } struct Foo { @@ -48,7 +48,7 @@ union Onion { // EMIT_MIR aggregate_exprs.adt.built.after.mir #[custom_mir(dialect = "built")] fn adt() -> Onion { - mir!( + mir! { let one: i32; let x: Foo; let y: Bar; @@ -62,7 +62,7 @@ fn adt() -> Onion { RET = Onion { neon: Field(Variant(y, 0), 1) }; Return() } - ) + } } fn main() { diff --git a/tests/mir-opt/building/custom/arbitrary_let.rs b/tests/mir-opt/building/custom/arbitrary_let.rs index f8ee8504e322..3f251cd81bce 100644 --- a/tests/mir-opt/building/custom/arbitrary_let.rs +++ b/tests/mir-opt/building/custom/arbitrary_let.rs @@ -8,7 +8,7 @@ use core::ptr::{addr_of, addr_of_mut}; // EMIT_MIR arbitrary_let.arbitrary_let.built.after.mir #[custom_mir(dialect = "built")] fn arbitrary_let(x: i32) -> i32 { - mir!( + mir! { { let y = x; Goto(second) @@ -21,7 +21,7 @@ fn arbitrary_let(x: i32) -> i32 { let z = y; Goto(third) } - ) + } } fn main() { diff --git a/tests/mir-opt/building/custom/arrays.rs b/tests/mir-opt/building/custom/arrays.rs index e9a53b7aacb7..4bd6f93e1134 100644 --- a/tests/mir-opt/building/custom/arrays.rs +++ b/tests/mir-opt/building/custom/arrays.rs @@ -7,12 +7,14 @@ use core::intrinsics::mir::*; // EMIT_MIR arrays.arrays.built.after.mir #[custom_mir(dialect = "built")] fn arrays() -> usize { - mir!({ - let x = [5_i32; C]; - let c = Len(x); - RET = c; - Return() - }) + mir! { + { + let x = [5_i32; C]; + let c = Len(x); + RET = c; + Return() + } + } } fn main() { diff --git a/tests/mir-opt/building/custom/as_cast.rs b/tests/mir-opt/building/custom/as_cast.rs index 92aea64db07f..908d378771d5 100644 --- a/tests/mir-opt/building/custom/as_cast.rs +++ b/tests/mir-opt/building/custom/as_cast.rs @@ -7,34 +7,34 @@ use core::intrinsics::mir::*; // EMIT_MIR as_cast.int_to_int.built.after.mir #[custom_mir(dialect = "built")] fn int_to_int(x: u32) -> i32 { - mir!( + mir! { { RET = x as i32; Return() } - ) + } } // EMIT_MIR as_cast.float_to_int.built.after.mir #[custom_mir(dialect = "built")] fn float_to_int(x: f32) -> i32 { - mir!( + mir! { { RET = x as i32; Return() } - ) + } } // EMIT_MIR as_cast.int_to_ptr.built.after.mir #[custom_mir(dialect = "built")] fn int_to_ptr(x: usize) -> *const i32 { - mir!( + mir! { { RET = x as *const i32; Return() } - ) + } } fn main() { diff --git a/tests/mir-opt/building/custom/assume.rs b/tests/mir-opt/building/custom/assume.rs index a477e12f0e03..4a55617136a1 100644 --- a/tests/mir-opt/building/custom/assume.rs +++ b/tests/mir-opt/building/custom/assume.rs @@ -7,34 +7,34 @@ use core::intrinsics::mir::*; // EMIT_MIR assume.assume_local.built.after.mir #[custom_mir(dialect = "built")] fn assume_local(x: bool) { - mir!( + mir! { { Assume(x); Return() } - ) + } } // EMIT_MIR assume.assume_place.built.after.mir #[custom_mir(dialect = "built")] fn assume_place(p: (bool, u8)) { - mir!( + mir! { { Assume(p.0); Return() } - ) + } } // EMIT_MIR assume.assume_constant.built.after.mir #[custom_mir(dialect = "built")] fn assume_constant() { - mir!( + mir! { { Assume(true); Return() } - ) + } } fn main() { diff --git a/tests/mir-opt/building/custom/composite_return.rs b/tests/mir-opt/building/custom/composite_return.rs index 33c903fa0f89..0cf2cc8d1890 100644 --- a/tests/mir-opt/building/custom/composite_return.rs +++ b/tests/mir-opt/building/custom/composite_return.rs @@ -7,14 +7,14 @@ use core::intrinsics::mir::*; // EMIT_MIR composite_return.tuple.built.after.mir #[custom_mir(dialect = "runtime", phase = "optimized")] fn tuple() -> (i32, bool) { - mir!( + mir! { type RET = (i32, bool); { RET.0 = 1; RET.1 = true; Return() } - ) + } } fn main() { diff --git a/tests/mir-opt/building/custom/consts.rs b/tests/mir-opt/building/custom/consts.rs index 1a410177fa54..c64709082dc3 100644 --- a/tests/mir-opt/building/custom/consts.rs +++ b/tests/mir-opt/building/custom/consts.rs @@ -9,14 +9,16 @@ const D: i32 = 5; // EMIT_MIR consts.consts.built.after.mir #[custom_mir(dialect = "built")] fn consts() { - mir!({ - let _a = 5_u8; - let _b = const { 5_i8 }; - let _c = C; - let _d = D; - let _e = consts::<10>; - Return() - }) + mir! { + { + let _a = 5_u8; + let _b = const { 5_i8 }; + let _c = C; + let _d = D; + let _e = consts::<10>; + Return() + } + } } static S: i32 = 0x05050505; @@ -24,11 +26,13 @@ static mut T: i32 = 0x0a0a0a0a; // EMIT_MIR consts.statics.built.after.mir #[custom_mir(dialect = "built")] fn statics() { - mir!({ - let _a: &i32 = Static(S); - let _b: *mut i32 = StaticMut(T); - Return() - }) + mir! { + { + let _a: &i32 = Static(S); + let _b: *mut i32 = StaticMut(T); + Return() + } + } } fn main() { diff --git a/tests/mir-opt/building/custom/debuginfo.rs b/tests/mir-opt/building/custom/debuginfo.rs index 3671a1ef0619..7ac3a32674a8 100644 --- a/tests/mir-opt/building/custom/debuginfo.rs +++ b/tests/mir-opt/building/custom/debuginfo.rs @@ -7,24 +7,24 @@ use core::intrinsics::mir::*; // EMIT_MIR debuginfo.pointee.built.after.mir #[custom_mir(dialect = "built")] fn pointee(opt: &mut Option) { - mir!( + mir! { debug foo => Field::(Variant(*opt, 1), 0); { Return() } - ) + } } // EMIT_MIR debuginfo.numbered.built.after.mir #[custom_mir(dialect = "analysis", phase = "post-cleanup")] fn numbered(i: (u32, i32)) { - mir!( + mir! { debug first => i.0; debug second => i.0; { Return() } - ) + } } struct S { x: f32 } @@ -32,35 +32,35 @@ struct S { x: f32 } // EMIT_MIR debuginfo.structured.built.after.mir #[custom_mir(dialect = "analysis", phase = "post-cleanup")] fn structured(i: S) { - mir!( + mir! { debug x => i.x; { Return() } - ) + } } // EMIT_MIR debuginfo.variant.built.after.mir #[custom_mir(dialect = "built")] fn variant(opt: Option) { - mir!( + mir! { debug inner => Field::(Variant(opt, 1), 0); { Return() } - ) + } } // EMIT_MIR debuginfo.variant_deref.built.after.mir #[custom_mir(dialect = "built")] fn variant_deref(opt: Option<&i32>) { - mir!( + mir! { debug pointer => Field::<&i32>(Variant(opt, 1), 0); debug deref => *Field::<&i32>(Variant(opt, 1), 0); { Return() } - ) + } } fn main() { diff --git a/tests/mir-opt/building/custom/enums.rs b/tests/mir-opt/building/custom/enums.rs index 6aab1503c0a3..88ec228986ab 100644 --- a/tests/mir-opt/building/custom/enums.rs +++ b/tests/mir-opt/building/custom/enums.rs @@ -7,7 +7,7 @@ use core::intrinsics::mir::*; // EMIT_MIR enums.switch_bool.built.after.mir #[custom_mir(dialect = "built")] pub fn switch_bool(b: bool) -> u32 { - mir!( + mir! { { match b { true => t, @@ -25,13 +25,13 @@ pub fn switch_bool(b: bool) -> u32 { RET = 10; Return() } - ) + } } // EMIT_MIR enums.switch_option.built.after.mir #[custom_mir(dialect = "built")] pub fn switch_option(option: Option<()>) -> bool { - mir!( + mir! { { let discr = Discriminant(option); match discr { @@ -50,7 +50,7 @@ pub fn switch_option(option: Option<()>) -> bool { RET = true; Return() } - ) + } } #[repr(u8)] @@ -62,7 +62,7 @@ enum Bool { // EMIT_MIR enums.switch_option_repr.built.after.mir #[custom_mir(dialect = "built")] fn switch_option_repr(option: Bool) -> bool { - mir!( + mir! { { let discr = Discriminant(option); match discr { @@ -80,26 +80,30 @@ fn switch_option_repr(option: Bool) -> bool { RET = false; Return() } - ) + } } // EMIT_MIR enums.set_discr.built.after.mir #[custom_mir(dialect = "runtime", phase = "initial")] fn set_discr(option: &mut Option<()>) { - mir!({ - Deinit(*option); - SetDiscriminant(*option, 0); - Return() - }) + mir! { + { + Deinit(*option); + SetDiscriminant(*option, 0); + Return() + } + } } // EMIT_MIR enums.set_discr_repr.built.after.mir #[custom_mir(dialect = "runtime", phase = "initial")] fn set_discr_repr(b: &mut Bool) { - mir!({ - SetDiscriminant(*b, 0); - Return() - }) + mir! { + { + SetDiscriminant(*b, 0); + Return() + } + } } fn main() { diff --git a/tests/mir-opt/building/custom/operators.rs b/tests/mir-opt/building/custom/operators.rs index ff0e8dcbb415..07abf2d96517 100644 --- a/tests/mir-opt/building/custom/operators.rs +++ b/tests/mir-opt/building/custom/operators.rs @@ -6,37 +6,41 @@ use std::intrinsics::mir::*; // EMIT_MIR operators.f.built.after.mir #[custom_mir(dialect = "built")] pub fn f(a: i32, b: bool) -> i32 { - mir!({ - a = -a; - b = !b; - a = a + a; - a = a - a; - a = a * a; - a = a / a; - a = a % a; - a = a ^ a; - a = a & a; - a = a << a; - a = a >> a; - b = a == a; - b = a < a; - b = a <= a; - b = a >= a; - b = a > a; - let res = Checked(a + a); - b = res.1; - a = res.0; - RET = a; - Return() - }) + mir! { + { + a = -a; + b = !b; + a = a + a; + a = a - a; + a = a * a; + a = a / a; + a = a % a; + a = a ^ a; + a = a & a; + a = a << a; + a = a >> a; + b = a == a; + b = a < a; + b = a <= a; + b = a >= a; + b = a > a; + let res = Checked(a + a); + b = res.1; + a = res.0; + RET = a; + Return() + } + } } // EMIT_MIR operators.g.runtime.after.mir #[custom_mir(dialect = "runtime")] pub fn g(p: *const i32, q: *const [i32]) { - mir!({ - let a = PtrMetadata(p); - let b = PtrMetadata(q); - Return() - }) + mir! { + { + let a = PtrMetadata(p); + let b = PtrMetadata(q); + Return() + } + } } diff --git a/tests/mir-opt/building/custom/projections.rs b/tests/mir-opt/building/custom/projections.rs index ac23fe59097f..0250b9b84b62 100644 --- a/tests/mir-opt/building/custom/projections.rs +++ b/tests/mir-opt/building/custom/projections.rs @@ -12,74 +12,84 @@ union U { // EMIT_MIR projections.unions.built.after.mir #[custom_mir(dialect = "built")] fn unions(u: U) -> i32 { - mir!({ - RET = u.a; - Return() - }) + mir! { + { + RET = u.a; + Return() + } + } } // EMIT_MIR projections.tuples.built.after.mir #[custom_mir(dialect = "analysis", phase = "post-cleanup")] fn tuples(i: (u32, i32)) -> (u32, i32) { - mir!( + mir! { type RET = (u32, i32); { RET.0 = i.0; RET.1 = i.1; Return() } - ) + } } // EMIT_MIR projections.unwrap.built.after.mir #[custom_mir(dialect = "built")] fn unwrap(opt: Option) -> i32 { - mir!({ - RET = Field(Variant(opt, 1), 0); - Return() - }) + mir! { + { + RET = Field(Variant(opt, 1), 0); + Return() + } + } } // EMIT_MIR projections.unwrap_deref.built.after.mir #[custom_mir(dialect = "built")] fn unwrap_deref(opt: Option<&i32>) -> i32 { - mir!({ - RET = *Field::<&i32>(Variant(opt, 1), 0); - Return() - }) + mir! { + { + RET = *Field::<&i32>(Variant(opt, 1), 0); + Return() + } + } } // EMIT_MIR projections.set.built.after.mir #[custom_mir(dialect = "built")] fn set(opt: &mut Option) { - mir!({ - place!(Field(Variant(*opt, 1), 0)) = 10; - Return() - }) + mir! { + { + place!(Field(Variant(*opt, 1), 0)) = 10; + Return() + } + } } // EMIT_MIR projections.simple_index.built.after.mir #[custom_mir(dialect = "built")] fn simple_index(a: [i32; 10], b: &[i32]) -> i32 { - mir!({ - let temp = 3; - RET = a[temp]; - RET = (*b)[temp]; - Return() - }) + mir! { + { + let temp = 3; + RET = a[temp]; + RET = (*b)[temp]; + Return() + } + } } // EMIT_MIR projections.copy_for_deref.built.after.mir #[custom_mir(dialect = "runtime", phase = "initial")] fn copy_for_deref(x: (&i32, i32)) -> i32 { - mir!( + mir! { let temp: &i32; { temp = CopyForDeref(x.0); RET = *temp; Return() } - ) + } } fn main() { diff --git a/tests/mir-opt/building/custom/references.rs b/tests/mir-opt/building/custom/references.rs index 04afe6e6494b..7ea8f8b4c156 100644 --- a/tests/mir-opt/building/custom/references.rs +++ b/tests/mir-opt/building/custom/references.rs @@ -8,31 +8,29 @@ use core::ptr::{addr_of, addr_of_mut}; // EMIT_MIR references.mut_ref.built.after.mir #[custom_mir(dialect = "runtime", phase = "optimized")] pub fn mut_ref(x: &mut i32) -> &mut i32 { - mir!( + mir! { let t: *mut i32; - { t = addr_of_mut!(*x); RET = &mut *t; Retag(RET); Return() } - ) + } } // EMIT_MIR references.immut_ref.built.after.mir #[custom_mir(dialect = "runtime", phase = "optimized")] pub fn immut_ref(x: &i32) -> &i32 { - mir!( + mir! { let t: *const i32; - { t = addr_of!(*x); RET = & *t; Retag(RET); Return() } - ) + } } // EMIT_MIR references.raw_pointer.built.after.mir @@ -40,19 +38,23 @@ pub fn immut_ref(x: &i32) -> &i32 { pub fn raw_pointer(x: *const i32) -> *const i32 { // Regression test for a bug in which unsafetyck was not correctly turned off for // `dialect = "built"` - mir!({ - RET = addr_of!(*x); - Return() - }) + mir! { + { + RET = addr_of!(*x); + Return() + } + } } // EMIT_MIR references.raw_pointer_offset.built.after.mir #[custom_mir(dialect = "built")] pub fn raw_pointer_offset(x: *const i32) -> *const i32 { - mir!({ - RET = Offset(x, 1_isize); - Return() - }) + mir! { + { + RET = Offset(x, 1_isize); + Return() + } + } } fn main() { diff --git a/tests/mir-opt/building/custom/simple_assign.rs b/tests/mir-opt/building/custom/simple_assign.rs index 8442272291e1..d6d054ab5a38 100644 --- a/tests/mir-opt/building/custom/simple_assign.rs +++ b/tests/mir-opt/building/custom/simple_assign.rs @@ -7,32 +7,32 @@ use core::intrinsics::mir::*; // EMIT_MIR simple_assign.simple.built.after.mir #[custom_mir(dialect = "built")] pub fn simple(x: i32) -> i32 { - mir!( + mir! { let temp1: i32; let temp2: _; - { StorageLive(temp1); temp1 = x; Goto(exit) } - exit = { temp2 = Move(temp1); StorageDead(temp1); RET = temp2; Return() } - ) + } } // EMIT_MIR simple_assign.simple_ref.built.after.mir #[custom_mir(dialect = "built")] pub fn simple_ref(x: &mut i32) -> &mut i32 { - mir!({ - RET = Move(x); - Return() - }) + mir! { + { + RET = Move(x); + Return() + } + } } fn main() { diff --git a/tests/mir-opt/building/custom/terminators.rs b/tests/mir-opt/building/custom/terminators.rs index 01c132cf3e77..a8e0b4b35bf4 100644 --- a/tests/mir-opt/building/custom/terminators.rs +++ b/tests/mir-opt/building/custom/terminators.rs @@ -11,7 +11,7 @@ fn ident(t: T) -> T { // EMIT_MIR terminators.direct_call.built.after.mir #[custom_mir(dialect = "built")] fn direct_call(x: i32) -> i32 { - mir!( + mir! { { Call(RET = ident(x), ReturnTo(retblock), UnwindContinue()) } @@ -19,21 +19,20 @@ fn direct_call(x: i32) -> i32 { retblock = { Return() } - ) + } } // EMIT_MIR terminators.indirect_call.built.after.mir #[custom_mir(dialect = "built")] fn indirect_call(x: i32, f: fn(i32) -> i32) -> i32 { - mir!( + mir! { { Call(RET = f(x), ReturnTo(retblock), UnwindContinue()) } - retblock = { Return() } - ) + } } struct WriteOnDrop<'a>(&'a mut i32, i32); @@ -47,51 +46,47 @@ impl<'a> Drop for WriteOnDrop<'a> { // EMIT_MIR terminators.drop_first.built.after.mir #[custom_mir(dialect = "built")] fn drop_first<'a>(a: WriteOnDrop<'a>, b: WriteOnDrop<'a>) { - mir!( + mir! { { Drop(a, ReturnTo(retblock), UnwindContinue()) } - retblock = { a = Move(b); Return() } - ) + } } // EMIT_MIR terminators.drop_second.built.after.mir #[custom_mir(dialect = "built")] fn drop_second<'a>(a: WriteOnDrop<'a>, b: WriteOnDrop<'a>) { - mir!( + mir! { { Drop(b, ReturnTo(retblock), UnwindContinue()) } - retblock = { Return() } - ) + } } // EMIT_MIR terminators.assert_nonzero.built.after.mir #[custom_mir(dialect = "built")] fn assert_nonzero(a: i32) { - mir!( + mir! { { match a { 0 => unreachable, _ => retblock } } - unreachable = { Unreachable() } - retblock = { Return() } - ) + } } fn main() { diff --git a/tests/mir-opt/building/custom/unwind_action.rs b/tests/mir-opt/building/custom/unwind_action.rs index e3d54c721457..87aab1ea70c6 100644 --- a/tests/mir-opt/building/custom/unwind_action.rs +++ b/tests/mir-opt/building/custom/unwind_action.rs @@ -9,14 +9,14 @@ use core::intrinsics::mir::*; // CHECK-NEXT: a() -> [return: bb1, unwind unreachable]; #[custom_mir(dialect = "runtime", phase = "optimized")] pub fn a() { - mir!( + mir! { { Call(RET = a(), ReturnTo(bb1), UnwindUnreachable()) } bb1 = { Return() } - ) + } } // CHECK-LABEL: fn b() @@ -24,14 +24,14 @@ pub fn a() { // CHECK-NEXT: b() -> [return: bb1, unwind continue]; #[custom_mir(dialect = "runtime", phase = "optimized")] pub fn b() { - mir!( + mir! { { Call(RET = b(), ReturnTo(bb1), UnwindContinue()) } bb1 = { Return() } - ) + } } // CHECK-LABEL: fn c() @@ -39,14 +39,14 @@ pub fn b() { // CHECK-NEXT: c() -> [return: bb1, unwind terminate(abi)]; #[custom_mir(dialect = "runtime", phase = "optimized")] pub fn c() { - mir!( + mir! { { Call(RET = c(), ReturnTo(bb1), UnwindTerminate(ReasonAbi)) } bb1 = { Return() } - ) + } } // CHECK-LABEL: fn d() @@ -54,7 +54,7 @@ pub fn c() { // CHECK-NEXT: d() -> [return: bb1, unwind: bb2]; #[custom_mir(dialect = "runtime", phase = "optimized")] pub fn d() { - mir!( + mir! { { Call(RET = d(), ReturnTo(bb1), UnwindCleanup(bb2)) } @@ -64,5 +64,5 @@ pub fn d() { bb2 (cleanup) = { UnwindResume() } - ) + } } diff --git a/tests/mir-opt/building/custom/unwind_terminate.rs b/tests/mir-opt/building/custom/unwind_terminate.rs index c5374fa7b690..9b495d52387d 100644 --- a/tests/mir-opt/building/custom/unwind_terminate.rs +++ b/tests/mir-opt/building/custom/unwind_terminate.rs @@ -8,14 +8,14 @@ use core::intrinsics::mir::*; // CHECK-NEXT: terminate(abi); #[custom_mir(dialect = "runtime", phase = "optimized")] pub fn f() { - mir!( + mir! { { Return() } bb1(cleanup) = { UnwindTerminate(ReasonAbi) } - ) + } } // CHECK-LABEL: fn g() @@ -23,12 +23,12 @@ pub fn f() { // CHECK-NEXT: terminate(cleanup); #[custom_mir(dialect = "runtime", phase = "optimized")] pub fn g() { - mir!( + mir! { { Return() } bb1(cleanup) = { UnwindTerminate(ReasonInCleanup) } - ) + } } diff --git a/tests/mir-opt/copy-prop/borrowed_local.rs b/tests/mir-opt/copy-prop/borrowed_local.rs index 512287dd1767..9da05f71b5d4 100644 --- a/tests/mir-opt/copy-prop/borrowed_local.rs +++ b/tests/mir-opt/copy-prop/borrowed_local.rs @@ -24,7 +24,7 @@ fn compare_address() -> bool { // CHECK-NEXT: _0 = cmp_ref(_2, _4) // CHECK: bb1: { // CHECK-NEXT: _0 = opaque::(_3) - mir!( + mir! { { let a = 5_u8; let r1 = &a; @@ -40,7 +40,7 @@ fn compare_address() -> bool { ret = { Return() } - ) + } } /// Generic type `T` is `Freeze`, so shared borrows are immutable. @@ -52,7 +52,7 @@ fn borrowed(x: T) -> bool { // CHECK-NEXT: _0 = opaque::<&T>(_3) // CHECK: bb1: { // CHECK-NEXT: _0 = opaque::(_1) - mir!( + mir! { { let a = x; let r1 = &x; @@ -64,7 +64,7 @@ fn borrowed(x: T) -> bool { ret = { Return() } - ) + } } /// Generic type `T` is not known to be `Freeze`, so shared borrows may be mutable. @@ -77,7 +77,7 @@ fn non_freeze(x: T) -> bool { // CHECK-NEXT: _0 = opaque::<&T>(_3) // CHECK: bb1: { // CHECK-NEXT: _0 = opaque::(_2) - mir!( + mir! { { let a = x; let r1 = &x; @@ -89,7 +89,7 @@ fn non_freeze(x: T) -> bool { ret = { Return() } - ) + } } fn main() { diff --git a/tests/mir-opt/copy-prop/custom_move_arg.rs b/tests/mir-opt/copy-prop/custom_move_arg.rs index a82d4618e68c..3dce7807b347 100644 --- a/tests/mir-opt/copy-prop/custom_move_arg.rs +++ b/tests/mir-opt/copy-prop/custom_move_arg.rs @@ -12,17 +12,19 @@ struct NotCopy(bool); // EMIT_MIR custom_move_arg.f.CopyProp.diff #[custom_mir(dialect = "runtime")] fn f(_1: NotCopy) { - mir!({ - let _2 = _1; - Call(RET = opaque(Move(_1)), ReturnTo(bb1), UnwindUnreachable()) + mir! { + { + let _2 = _1; + Call(RET = opaque(Move(_1)), ReturnTo(bb1), UnwindUnreachable()) + } + bb1 = { + let _3 = Move(_2); + Call(RET = opaque(_3), ReturnTo(bb2), UnwindUnreachable()) + } + bb2 = { + Return() + } } - bb1 = { - let _3 = Move(_2); - Call(RET = opaque(_3), ReturnTo(bb2), UnwindUnreachable()) - } - bb2 = { - Return() - }) } #[inline(never)] diff --git a/tests/mir-opt/copy-prop/move_projection.rs b/tests/mir-opt/copy-prop/move_projection.rs index 231e4082e33b..d8e2e24dda59 100644 --- a/tests/mir-opt/copy-prop/move_projection.rs +++ b/tests/mir-opt/copy-prop/move_projection.rs @@ -13,7 +13,7 @@ struct Foo(u8); #[custom_mir(dialect = "runtime")] fn f(a: Foo) -> bool { - mir!( + mir! { { let b = a; // This is a move out of a copy, so must become a copy of `a.0`. @@ -26,7 +26,7 @@ fn f(a: Foo) -> bool { ret = { Return() } - ) + } } fn main() { diff --git a/tests/mir-opt/copy-prop/mutate_through_pointer.rs b/tests/mir-opt/copy-prop/mutate_through_pointer.rs index 14ca513c6927..53cca045248d 100644 --- a/tests/mir-opt/copy-prop/mutate_through_pointer.rs +++ b/tests/mir-opt/copy-prop/mutate_through_pointer.rs @@ -18,14 +18,16 @@ use core::intrinsics::mir::*; #[custom_mir(dialect = "analysis", phase = "post-cleanup")] fn f(c: bool) -> bool { - mir!({ - let a = c; - let p = core::ptr::addr_of!(a); - let p2 = core::ptr::addr_of_mut!(*p); - *p2 = false; - RET = c; - Return() - }) + mir! { + { + let a = c; + let p = core::ptr::addr_of!(a); + let p2 = core::ptr::addr_of_mut!(*p); + *p2 = false; + RET = c; + Return() + } + } } fn main() { diff --git a/tests/mir-opt/copy-prop/non_dominate.rs b/tests/mir-opt/copy-prop/non_dominate.rs index 34e7eabc81a2..c01275370ea7 100644 --- a/tests/mir-opt/copy-prop/non_dominate.rs +++ b/tests/mir-opt/copy-prop/non_dominate.rs @@ -8,16 +8,28 @@ use core::intrinsics::mir::*; #[custom_mir(dialect = "analysis", phase = "post-cleanup")] fn f(c: bool) -> bool { - mir!( + mir! { let a: bool; let b: bool; - { Goto(bb1) } - bb1 = { b = c; match b { false => bb3, _ => bb2 }} + { + Goto(bb1) + } + bb1 = { + b = c; + match b { false => bb3, _ => bb2 } + } // This assignment to `a` does not dominate the use in `bb3`. // It should not be replaced by `b`. - bb2 = { a = b; c = false; Goto(bb1) } - bb3 = { RET = a; Return() } - ) + bb2 = { + a = b; + c = false; + Goto(bb1) + } + bb3 = { + RET = a; + Return() + } + } } fn main() { diff --git a/tests/mir-opt/dataflow-const-prop/enum.rs b/tests/mir-opt/dataflow-const-prop/enum.rs index 5c52f92cd8f1..ac0705638abb 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.rs +++ b/tests/mir-opt/dataflow-const-prop/enum.rs @@ -84,7 +84,7 @@ struct NonZeroUsize(usize); // CHECK-LABEL: fn mutate_discriminant( #[custom_mir(dialect = "runtime", phase = "post-cleanup")] fn mutate_discriminant() -> u8 { - mir!( + mir! { let x: Option; { SetDiscriminant(x, 1); @@ -109,7 +109,7 @@ fn mutate_discriminant() -> u8 { RET = 2; Unreachable() } - ) + } } // EMIT_MIR enum.multiple.DataflowConstProp.diff diff --git a/tests/mir-opt/dead-store-elimination/call_arg_copy.rs b/tests/mir-opt/dead-store-elimination/call_arg_copy.rs index edb35061cc65..2556848ec462 100644 --- a/tests/mir-opt/dead-store-elimination/call_arg_copy.rs +++ b/tests/mir-opt/dead-store-elimination/call_arg_copy.rs @@ -29,7 +29,7 @@ struct Packed { fn move_packed(packed: Packed) { // CHECK-LABEL: fn move_packed( // CHECK: = use_both(const 0_i32, (_1.1: i32)) - mir!( + mir! { { // We have a packed struct, verify that the copy is not turned into a move. Call(RET = use_both(0, packed.y), ReturnTo(ret), UnwindContinue()) @@ -37,7 +37,7 @@ fn move_packed(packed: Packed) { ret = { Return() } - ) + } } fn main() { diff --git a/tests/mir-opt/dead-store-elimination/cycle.rs b/tests/mir-opt/dead-store-elimination/cycle.rs index 795d57d36f52..c8f0c2644ab3 100644 --- a/tests/mir-opt/dead-store-elimination/cycle.rs +++ b/tests/mir-opt/dead-store-elimination/cycle.rs @@ -20,7 +20,7 @@ fn cycle(mut x: i32, mut y: i32, mut z: i32) { // CHECK-NOT: {{_.*}} = move {{_.*}}; // We use custom MIR to avoid generating debuginfo, that would force to preserve writes. - mir!( + mir! { let condition: bool; { Call(condition = cond(), ReturnTo(bb1), UnwindContinue()) @@ -38,7 +38,7 @@ fn cycle(mut x: i32, mut y: i32, mut z: i32) { ret = { Return() } - ) + } } fn main() { diff --git a/tests/mir-opt/gvn.rs b/tests/mir-opt/gvn.rs index 9be305152835..315377e4356f 100644 --- a/tests/mir-opt/gvn.rs +++ b/tests/mir-opt/gvn.rs @@ -539,7 +539,7 @@ fn slices() { #[custom_mir(dialect = "analysis")] fn duplicate_slice() -> (bool, bool) { // CHECK-LABEL: fn duplicate_slice( - mir!( + mir! { let au: u128; let bu: u128; let cu: u128; @@ -585,7 +585,7 @@ fn duplicate_slice() -> (bool, bool) { RET = (direct, indirect); Return() } - ) + } } fn repeat() { @@ -623,11 +623,13 @@ fn fn_pointers() { fn indirect_static() { static A: Option = None; - mir!({ - let ptr = Static(A); - let out = Field::(Variant(*ptr, 1), 0); - Return() - }) + mir! { + { + let ptr = Static(A); + let out = Field::(Variant(*ptr, 1), 0); + Return() + } + } } /// Verify that having constant index `u64::MAX` does not yield to an overflow in rustc. @@ -733,7 +735,7 @@ fn borrowed(x: T) { // CHECK-NEXT: _0 = opaque::(_1) // CHECK: bb2: { // CHECK-NEXT: _0 = opaque::(_1) - mir!( + mir! { { let a = x; let r1 = &x; @@ -748,7 +750,7 @@ fn borrowed(x: T) { ret = { Return() } - ) + } } /// Generic type `T` is not known to be `Freeze`, so shared borrows may be mutable. @@ -763,7 +765,7 @@ fn non_freeze(x: T) { // CHECK-NEXT: _0 = opaque::(_2) // CHECK: bb2: { // CHECK-NEXT: _0 = opaque::((*_3)) - mir!( + mir! { { let a = x; let r1 = &x; @@ -778,7 +780,7 @@ fn non_freeze(x: T) { ret = { Return() } - ) + } } fn main() { diff --git a/tests/mir-opt/instsimplify/duplicate_switch_targets.rs b/tests/mir-opt/instsimplify/duplicate_switch_targets.rs index 454728249b1a..a47d9d5a71d7 100644 --- a/tests/mir-opt/instsimplify/duplicate_switch_targets.rs +++ b/tests/mir-opt/instsimplify/duplicate_switch_targets.rs @@ -10,7 +10,7 @@ use std::intrinsics::mir::*; pub unsafe fn assert_zero(x: u8) -> u8 { // CHECK-LABEL: fn assert_zero( // CHECK: switchInt({{.*}}) -> [0: {{bb.*}}, otherwise: {{bb.*}}] - mir!( + mir! { { match x { 0 => retblock, @@ -25,5 +25,5 @@ pub unsafe fn assert_zero(x: u8) -> u8 { RET = x; Return() } - ) + } } diff --git a/tests/mir-opt/jump_threading.rs b/tests/mir-opt/jump_threading.rs index 57f4e4a2654f..3ab155fdc9e7 100644 --- a/tests/mir-opt/jump_threading.rs +++ b/tests/mir-opt/jump_threading.rs @@ -157,7 +157,7 @@ fn custom_discr(x: bool) -> u8 { #[custom_mir(dialect = "runtime", phase = "post-cleanup")] fn multiple_match(x: u8) -> u8 { // CHECK-LABEL: fn multiple_match( - mir!( + mir! { { // CHECK: bb0: { // CHECK: switchInt([[x:_.*]]) -> [3: bb1, otherwise: bb2]; @@ -220,7 +220,7 @@ fn multiple_match(x: u8) -> u8 { RET = 11; Return() } - ) + } } /// Both 1-3-4 and 2-3-4 are threadable. As 1 and 2 are the only predecessors of 3, @@ -228,7 +228,7 @@ fn multiple_match(x: u8) -> u8 { #[custom_mir(dialect = "runtime", phase = "post-cleanup")] fn duplicate_chain(x: bool) -> u8 { // CHECK-LABEL: fn duplicate_chain( - mir!( + mir! { let a: u8; { // CHECK: bb0: { @@ -278,7 +278,7 @@ fn duplicate_chain(x: bool) -> u8 { RET = 9; Return() } - ) + } } #[rustc_layout_scalar_valid_range_start(1)] @@ -292,7 +292,7 @@ fn mutate_discriminant() -> u8 { // CHECK-NOT: goto -> {{bb.*}}; // CHECK: switchInt( // CHECK-NOT: goto -> {{bb.*}}; - mir!( + mir! { let x: Option; { SetDiscriminant(x, 1); @@ -313,7 +313,7 @@ fn mutate_discriminant() -> u8 { RET = 2; Unreachable() } - ) + } } /// Verify that we do not try to reason when there are mutable pointers involved. @@ -342,7 +342,7 @@ fn mutable_ref() -> bool { #[custom_mir(dialect = "runtime", phase = "post-cleanup")] fn renumbered_bb(x: bool) -> u8 { // CHECK-LABEL: fn renumbered_bb( - mir!( + mir! { let a: bool; let b: bool; { @@ -398,7 +398,7 @@ fn renumbered_bb(x: bool) -> u8 { // Duplicate of bb4. // CHECK: bb9: { // CHECK-NEXT: goto -> bb6; - ) + } } /// This function has 3 TOs: 1-4-5, 0-1-4-7-5-8 and 3-4-7-5-6 @@ -408,7 +408,7 @@ fn renumbered_bb(x: bool) -> u8 { #[custom_mir(dialect = "runtime", phase = "post-cleanup")] fn disappearing_bb(x: u8) -> u8 { // CHECK-LABEL: fn disappearing_bb( - mir!( + mir! { let a: bool; let b: bool; { @@ -450,7 +450,7 @@ fn disappearing_bb(x: u8) -> u8 { // CHECK: goto -> bb5; // CHECK: bb10: { // CHECK: goto -> bb6; - ) + } } /// Verify that we can thread jumps when we assign from an aggregate constant. @@ -472,7 +472,7 @@ fn aggregate(x: u8) -> u8 { #[custom_mir(dialect = "runtime", phase = "post-cleanup")] fn assume(a: u8, b: bool) -> u8 { // CHECK-LABEL: fn assume( - mir!( + mir! { { // CHECK: bb0: { // CHECK-NEXT: switchInt(_1) -> [7: bb1, otherwise: bb2] @@ -511,7 +511,7 @@ fn assume(a: u8, b: bool) -> u8 { } // CHECK: bb6: { // CHECK-NEXT: goto -> bb5; - ) + } } fn main() { diff --git a/tests/mir-opt/matches_reduce_branches.rs b/tests/mir-opt/matches_reduce_branches.rs index fa466220b653..176d68bcd401 100644 --- a/tests/mir-opt/matches_reduce_branches.rs +++ b/tests/mir-opt/matches_reduce_branches.rs @@ -88,7 +88,7 @@ fn match_u8_i16(i: EnumAu8) -> i16 { fn match_u8_i16_2(i: EnumAu8) -> i16 { // CHECK-LABEL: fn match_u8_i16_2( // CHECK: switchInt - mir!( + mir! { { let a = Discriminant(i); match a { @@ -110,7 +110,7 @@ fn match_u8_i16_2(i: EnumAu8) -> i16 { ret = { Return() } - ) + } } // EMIT_MIR matches_reduce_branches.match_u8_i16_failed.MatchBranchSimplification.diff @@ -158,7 +158,7 @@ fn match_u8_u16(i: EnumBu8) -> u16 { fn match_u8_u16_2(i: EnumBu8) -> i16 { // CHECK-LABEL: fn match_u8_u16_2( // CHECK: switchInt - mir!( + mir! { { let a = Discriminant(i); match a { @@ -187,7 +187,7 @@ fn match_u8_u16_2(i: EnumBu8) -> i16 { ret = { Return() } - ) + } } #[repr(i8)] diff --git a/tests/mir-opt/nrvo_miscompile_111005.rs b/tests/mir-opt/nrvo_miscompile_111005.rs index 18814b0678fe..03008fa81915 100644 --- a/tests/mir-opt/nrvo_miscompile_111005.rs +++ b/tests/mir-opt/nrvo_miscompile_111005.rs @@ -10,12 +10,14 @@ use core::intrinsics::mir::*; // EMIT_MIR nrvo_miscompile_111005.wrong.RenameReturnPlace.diff #[custom_mir(dialect = "runtime", phase = "initial")] pub fn wrong(arg: char) -> char { - mir!({ - let temp = arg; - RET = temp; - temp = 'b'; - Return() - }) + mir! { + { + let temp = arg; + RET = temp; + temp = 'b'; + Return() + } + } } fn main() { diff --git a/tests/mir-opt/reference_prop.rs b/tests/mir-opt/reference_prop.rs index e0b0d6994206..678a7c81084b 100644 --- a/tests/mir-opt/reference_prop.rs +++ b/tests/mir-opt/reference_prop.rs @@ -658,7 +658,7 @@ fn read_through_raw(x: &mut usize) -> usize { // CHECK-NEXT: return; use std::intrinsics::mir::*; - mir!( + mir! { let r1: &mut usize; let r2: &mut usize; let p1: *mut usize; @@ -674,7 +674,7 @@ fn read_through_raw(x: &mut usize) -> usize { RET = *p2; Return() } - ) + } } #[custom_mir(dialect = "runtime", phase = "post-cleanup")] @@ -683,7 +683,7 @@ fn multiple_storage() { // CHECK: _3 = (*_2); use std::intrinsics::mir::*; - mir!( + mir! { let x: i32; { StorageLive(x); @@ -700,7 +700,7 @@ fn multiple_storage() { retblock = { Return() } - ) + } } #[custom_mir(dialect = "runtime", phase = "post-cleanup")] @@ -709,7 +709,7 @@ fn dominate_storage() { // CHECK: _5 = (*_2); use std::intrinsics::mir::*; - mir!( + mir! { let x: i32; let r: &i32; let c: i32; @@ -730,7 +730,7 @@ fn dominate_storage() { let d = true; match d { false => bb2, _ => bb0 } } - ) + } } #[custom_mir(dialect = "runtime", phase = "post-cleanup")] @@ -739,7 +739,7 @@ fn maybe_dead(m: bool) { // CHECK: (*_5) = const 7_i32; use std::intrinsics::mir::*; - mir!( + mir! { let x: i32; let y: i32; { @@ -774,7 +774,7 @@ fn maybe_dead(m: bool) { retblock = { Return() } - ) + } } fn mut_raw_then_mut_shr() -> (i32, i32) { diff --git a/tests/mir-opt/set_no_discriminant.rs b/tests/mir-opt/set_no_discriminant.rs index 0c29d1faf02a..586e28ae426a 100644 --- a/tests/mir-opt/set_no_discriminant.rs +++ b/tests/mir-opt/set_no_discriminant.rs @@ -19,7 +19,7 @@ pub fn f() -> usize { // CHECK-NOT: goto // CHECK: switchInt( // CHECK-NOT: goto - mir!( + mir! { let a: isize; let e: E; { @@ -39,7 +39,7 @@ pub fn f() -> usize { RET = 1; Return() } - ) + } } // EMIT_MIR set_no_discriminant.generic.JumpThreading.diff @@ -49,7 +49,7 @@ pub fn generic() -> usize { // CHECK-NOT: goto // CHECK: switchInt( // CHECK-NOT: goto - mir!( + mir! { let a: isize; let e: E; { @@ -69,7 +69,7 @@ pub fn generic() -> usize { RET = 1; Return() } - ) + } } fn main() { diff --git a/tests/mir-opt/simplify_dead_blocks.rs b/tests/mir-opt/simplify_dead_blocks.rs index 686eac582364..b9a404fd35c8 100644 --- a/tests/mir-opt/simplify_dead_blocks.rs +++ b/tests/mir-opt/simplify_dead_blocks.rs @@ -24,7 +24,7 @@ pub unsafe fn assert_nonzero_nonmax(x: u8) -> u8 { // CHECK-NEXT: _0 = _1; // CHECK-NEXT: return; // CHECK-NEXT: } - mir!( + mir! { { match x { 0 => unreachable, @@ -48,5 +48,5 @@ pub unsafe fn assert_nonzero_nonmax(x: u8) -> u8 { RET = x; Return() } - ) + } } diff --git a/tests/mir-opt/switch_to_self.rs b/tests/mir-opt/switch_to_self.rs index fc270fd33cf8..51a7c13494fb 100644 --- a/tests/mir-opt/switch_to_self.rs +++ b/tests/mir-opt/switch_to_self.rs @@ -8,7 +8,7 @@ use std::intrinsics::mir::*; // EMIT_MIR switch_to_self.test.MatchBranchSimplification.diff #[custom_mir(dialect = "runtime", phase = "post-cleanup")] pub fn test(x: bool) { - mir!( + mir! { { Goto(bb0) } @@ -18,5 +18,5 @@ pub fn test(x: bool) { bb1 = { match x { false => bb0, _ => bb1 } } - ) + } } diff --git a/tests/ui/mir/lint/assignment-overlap.rs b/tests/ui/mir/lint/assignment-overlap.rs index 806d09cda851..6396cccd4e88 100644 --- a/tests/ui/mir/lint/assignment-overlap.rs +++ b/tests/ui/mir/lint/assignment-overlap.rs @@ -9,11 +9,11 @@ use core::intrinsics::mir::*; #[custom_mir(dialect = "runtime", phase = "optimized")] pub fn main() { - mir!( + mir! { let a: [u8; 1024]; { a = a; Return() } - ) + } } diff --git a/tests/ui/mir/lint/call-overlap.rs b/tests/ui/mir/lint/call-overlap.rs index eb806378fe54..def78ea1e3b1 100644 --- a/tests/ui/mir/lint/call-overlap.rs +++ b/tests/ui/mir/lint/call-overlap.rs @@ -9,7 +9,7 @@ use core::intrinsics::mir::*; #[custom_mir(dialect = "runtime", phase = "optimized")] pub fn main() { - mir!( + mir! { let a: [u8; 1024]; { Call(a = f(Move(a)), ReturnTo(bb1), UnwindUnreachable()) @@ -17,7 +17,7 @@ pub fn main() { bb1 = { Return() } - ) + } } pub fn f(a: T) -> T { a } diff --git a/tests/ui/mir/lint/no-storage.rs b/tests/ui/mir/lint/no-storage.rs index 42dd1b963dc1..a6af8646f6ec 100644 --- a/tests/ui/mir/lint/no-storage.rs +++ b/tests/ui/mir/lint/no-storage.rs @@ -8,7 +8,7 @@ use core::intrinsics::mir::*; #[custom_mir(dialect = "built")] pub fn f(a: bool) { - mir!( + mir! { let b: (); { match a { true => bb1, _ => bb2 } @@ -26,5 +26,5 @@ pub fn f(a: bool) { StorageDead(b); Return() } - ) + } } diff --git a/tests/ui/mir/lint/storage-live.rs b/tests/ui/mir/lint/storage-live.rs index 5dea1cb3567e..8273544b56a1 100644 --- a/tests/ui/mir/lint/storage-live.rs +++ b/tests/ui/mir/lint/storage-live.rs @@ -15,14 +15,14 @@ use core::ptr::{addr_of, addr_of_mut}; #[custom_mir(dialect = "built")] fn multiple_storage() { - mir!( + mir! { let a: usize; { StorageLive(a); StorageLive(a); Return() } - ) + } } fn main() { diff --git a/tests/ui/mir/lint/storage-return.rs b/tests/ui/mir/lint/storage-return.rs index b6281d4b2a8e..d51aee9518fb 100644 --- a/tests/ui/mir/lint/storage-return.rs +++ b/tests/ui/mir/lint/storage-return.rs @@ -8,12 +8,12 @@ use core::intrinsics::mir::*; #[custom_mir(dialect = "built")] fn main() { - mir!( + mir! { let a: (); { StorageLive(a); RET = a; Return() } - ) + } } diff --git a/tests/ui/mir/mir_codegen_ssa.rs b/tests/ui/mir/mir_codegen_ssa.rs index bf01edcbaa84..1666b8293eba 100644 --- a/tests/ui/mir/mir_codegen_ssa.rs +++ b/tests/ui/mir/mir_codegen_ssa.rs @@ -5,7 +5,7 @@ use std::intrinsics::mir::*; #[custom_mir(dialect = "runtime", phase = "optimized")] pub fn f(a: u32) -> u32 { - mir!( + mir! { let x: u32; { // Previously code generation failed with ICE "use of .. before def ..." because the @@ -15,5 +15,5 @@ pub fn f(a: u32) -> u32 { RET = x; Return() } - ) + } } diff --git a/tests/ui/mir/ssa_call_ret.rs b/tests/ui/mir/ssa_call_ret.rs index 9b2c78c737f1..baaa7326fd80 100644 --- a/tests/ui/mir/ssa_call_ret.rs +++ b/tests/ui/mir/ssa_call_ret.rs @@ -10,7 +10,7 @@ use core::intrinsics::mir::*; #[custom_mir(dialect = "runtime", phase = "optimized")] pub fn f() -> u32 { - mir!( + mir! { let a: u32; { Call(a = g(), ReturnTo(bb1), UnwindCleanup(bb2)) @@ -23,7 +23,7 @@ pub fn f() -> u32 { RET = a; UnwindResume() } - ) + } } #[inline(never)] diff --git a/tests/ui/mir/validate/critical-edge.rs b/tests/ui/mir/validate/critical-edge.rs index 0a548ae8e584..9048d08a22a7 100644 --- a/tests/ui/mir/validate/critical-edge.rs +++ b/tests/ui/mir/validate/critical-edge.rs @@ -12,7 +12,7 @@ use core::intrinsics::mir::*; #[custom_mir(dialect = "runtime", phase = "optimized")] #[inline(always)] pub fn f(a: u32) -> u32 { - mir!( + mir! { { match a { 0 => bb1, @@ -27,5 +27,5 @@ pub fn f(a: u32) -> u32 { RET = 2; Return() } - ) + } } diff --git a/tests/ui/mir/validate/noncleanup-cleanup.rs b/tests/ui/mir/validate/noncleanup-cleanup.rs index 744e71e99b10..b46bb46952b8 100644 --- a/tests/ui/mir/validate/noncleanup-cleanup.rs +++ b/tests/ui/mir/validate/noncleanup-cleanup.rs @@ -9,13 +9,12 @@ use core::intrinsics::mir::*; #[custom_mir(dialect = "built")] pub fn main() { - mir!( + mir! { { Call(RET = main(), ReturnTo(block), UnwindCleanup(block)) } block = { Return() } - ) - + } } diff --git a/tests/ui/mir/validate/noncleanup-resume.rs b/tests/ui/mir/validate/noncleanup-resume.rs index 5bf6b03c9e94..b2a0e92e0686 100644 --- a/tests/ui/mir/validate/noncleanup-resume.rs +++ b/tests/ui/mir/validate/noncleanup-resume.rs @@ -9,9 +9,9 @@ use core::intrinsics::mir::*; #[custom_mir(dialect = "built")] pub fn main() { - mir!( + mir! { { UnwindResume() } - ) + } } diff --git a/tests/ui/mir/validate/noncleanup-terminate.rs b/tests/ui/mir/validate/noncleanup-terminate.rs index b5bf2604cce6..24cf75e7d8e1 100644 --- a/tests/ui/mir/validate/noncleanup-terminate.rs +++ b/tests/ui/mir/validate/noncleanup-terminate.rs @@ -9,9 +9,9 @@ use core::intrinsics::mir::*; #[custom_mir(dialect = "built")] pub fn main() { - mir!( + mir! { { UnwindTerminate(ReasonAbi) } - ) + } } From c9c80d2c5f3f07d18c90128e92771355111dff20 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 3 Jun 2024 10:18:33 +1000 Subject: [PATCH 172/211] rustfmt `tests/mir-opt`. The only non-obvious changes: - `building/storage_live_dead_in_statics.rs` has a `#[rustfmt::skip]` attribute to avoid reformating a table of data. - Two `.mir` files have slight changes involving line numbers. - In `unusual_item_types.rs` an `EMIT_MIR` annotation is moved to outside a function, which is the usual spot, because `tidy` complains if such a comment is indented. The commit also tweaks the comments in `rustfmt.toml`. --- rustfmt.toml | 14 ++--- tests/mir-opt/address_of.rs | 2 +- tests/mir-opt/array_index_is_temporary.rs | 1 - tests/mir-opt/building/custom/debuginfo.rs | 4 +- tests/mir-opt/building/enum_cast.rs | 24 ++++--- .../building/logical_or_in_conditional.rs | 8 ++- tests/mir-opt/building/match/simple_match.rs | 1 - tests/mir-opt/building/shifts.rs | 13 +--- .../building/storage_live_dead_in_statics.rs | 5 +- .../const_prop/control_flow_simplification.rs | 2 +- tests/mir-opt/const_prop/invalid_constant.rs | 10 +-- tests/mir-opt/const_prop/offset_of.rs | 2 +- .../const_prop/pointer_expose_provenance.rs | 2 +- .../const_prop/scalar_literal_propagation.rs | 2 +- tests/mir-opt/const_prop/switch_int.rs | 2 +- tests/mir-opt/const_prop/transmute.rs | 5 +- .../const_prop/tuple_literal_propagation.rs | 2 +- tests/mir-opt/copy-prop/borrowed_local.rs | 6 +- tests/mir-opt/copy-prop/move_projection.rs | 4 +- tests/mir-opt/dataflow-const-prop/enum.rs | 27 ++++++-- .../dataflow-const-prop/mult_by_zero.rs | 6 +- .../mir-opt/dataflow-const-prop/transmute.rs | 5 +- tests/mir-opt/derefer_complex_case.rs | 4 +- tests/mir-opt/derefer_terminator_test.rs | 4 +- tests/mir-opt/derefer_test.rs | 2 +- tests/mir-opt/derefer_test_multiple.rs | 2 +- tests/mir-opt/enum_opt.rs | 62 +++++++++---------- tests/mir-opt/inline/inline_cycle.rs | 1 - tests/mir-opt/inline/inline_cycle_generic.rs | 1 - tests/mir-opt/inline/inline_options.rs | 12 +++- tests/mir-opt/inline/inline_specialization.rs | 6 +- tests/mir-opt/inline/issue_106141.rs | 6 +- .../issue_76997_inline_scopes_parenting.rs | 5 +- .../mir-opt/instsimplify/combine_array_len.rs | 4 +- .../instsimplify/combine_transmutes.rs | 7 ++- .../issue_104451_unwindable_intrinsics.rs | 4 +- tests/mir-opt/issue_41110.rs | 8 +-- tests/mir-opt/issue_41697.rs | 5 +- ...nt#0}.SimplifyCfg-promote-consts.after.mir | 4 +- tests/mir-opt/issue_41888.rs | 6 +- tests/mir-opt/issue_72181.rs | 12 ++-- tests/mir-opt/issue_72181_1.rs | 4 +- tests/mir-opt/issue_91633.rs | 44 +++++++------ tests/mir-opt/issues/issue_75439.rs | 6 +- tests/mir-opt/jump_threading.rs | 12 +--- tests/mir-opt/lower_array_len.rs | 6 +- tests/mir-opt/lower_slice_len.rs | 6 +- tests/mir-opt/matches_u8.rs | 9 ++- tests/mir-opt/nll/named_lifetimes_basic.rs | 7 ++- tests/mir-opt/nrvo_simple.rs | 4 +- tests/mir-opt/packed_struct_drop_aligned.rs | 1 - tests/mir-opt/pre-codegen/intrinsics.rs | 4 +- .../pre-codegen/optimizes_into_variable.rs | 2 +- tests/mir-opt/pre-codegen/try_identity.rs | 12 ++-- tests/mir-opt/reference_prop.rs | 7 ++- tests/mir-opt/retag.rs | 4 +- tests/mir-opt/return_an_array.rs | 6 +- tests/mir-opt/simplify_locals.rs | 10 +-- tests/mir-opt/simplify_locals_fixedpoint.rs | 4 +- tests/mir-opt/simplify_match.rs | 7 ++- tests/mir-opt/sroa/lifetimes.rs | 5 +- tests/mir-opt/uninhabited_enum.rs | 8 +-- tests/mir-opt/unnamed-fields/field_access.rs | 6 +- tests/mir-opt/unreachable.rs | 4 +- tests/mir-opt/unusual_item_types.rs | 3 +- ...mpl#0}-ASSOCIATED_CONSTANT.built.after.mir | 4 +- 66 files changed, 251 insertions(+), 236 deletions(-) diff --git a/rustfmt.toml b/rustfmt.toml index 2b502cf9bc6f..998bcb983540 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -10,17 +10,13 @@ ignore = [ "/build-*/", "/vendor/", - # Some tests are not formatted, for multiple reasons: - # - some contain syntax errors that cause rustfmt to give an error - # - some UI tests are broken by different formatting - # - some require special comments in a particular position (e.g. `EMIT_MIR` comments) + # Some tests are not formatted, for various reasons. "/tests/codegen/simd-intrinsic/", # Many types like `u8x64` are better hand-formatted. - "/tests/crashes/", # Many tests contain syntax errors. - "/tests/debuginfo/", # Tests are somewhat sensitive to source code layout. - "/tests/incremental/", # Tests are somewhat sensitive to source code layout. - "/tests/mir-opt/", + "/tests/crashes/", # Many of these tests contain syntax errors. + "/tests/debuginfo/", # These tests are somewhat sensitive to source code layout. + "/tests/incremental/", # These tests are somewhat sensitive to source code layout. "/tests/pretty/", - "/tests/run-make/translation/test.rs", # Contains syntax errors. + "/tests/run-make/translation/test.rs", # This test contains syntax errors. "/tests/run-make-fulldeps/", "/tests/run-pass-valgrind/", "/tests/rustdoc/", diff --git a/tests/mir-opt/address_of.rs b/tests/mir-opt/address_of.rs index 57a317a4a90b..164ab38ebe75 100644 --- a/tests/mir-opt/address_of.rs +++ b/tests/mir-opt/address_of.rs @@ -9,7 +9,7 @@ fn address_of_reborrow() { y as *const [i32; 10]; y as *const dyn Send; y as *const [i32]; - y as *const i32; // This is a cast, not a coercion + y as *const i32; // This is a cast, not a coercion let p: *const _ = y; let p: *const [i32; 10] = y; diff --git a/tests/mir-opt/array_index_is_temporary.rs b/tests/mir-opt/array_index_is_temporary.rs index cd44c31d0004..771fb3771b5c 100644 --- a/tests/mir-opt/array_index_is_temporary.rs +++ b/tests/mir-opt/array_index_is_temporary.rs @@ -9,7 +9,6 @@ unsafe fn foo(z: *mut usize) -> u32 { 99 } - // EMIT_MIR array_index_is_temporary.main.SimplifyCfg-pre-optimizations.after.mir fn main() { // CHECK-LABEL: fn main( diff --git a/tests/mir-opt/building/custom/debuginfo.rs b/tests/mir-opt/building/custom/debuginfo.rs index 7ac3a32674a8..5ab83fd4214b 100644 --- a/tests/mir-opt/building/custom/debuginfo.rs +++ b/tests/mir-opt/building/custom/debuginfo.rs @@ -27,7 +27,9 @@ fn numbered(i: (u32, i32)) { } } -struct S { x: f32 } +struct S { + x: f32, +} // EMIT_MIR debuginfo.structured.built.after.mir #[custom_mir(dialect = "analysis", phase = "post-cleanup")] diff --git a/tests/mir-opt/building/enum_cast.rs b/tests/mir-opt/building/enum_cast.rs index df8e397c8fec..7ff0cdbfe8df 100644 --- a/tests/mir-opt/building/enum_cast.rs +++ b/tests/mir-opt/building/enum_cast.rs @@ -5,21 +5,24 @@ // EMIT_MIR enum_cast.far.built.after.mir enum Foo { - A + A, } enum Bar { - A, B + A, + B, } #[repr(u8)] enum Boo { - A, B + A, + B, } #[repr(i16)] enum Far { - A, B + A, + B, } fn foo(foo: Foo) -> usize { @@ -40,7 +43,9 @@ fn far(far: Far) -> isize { // EMIT_MIR enum_cast.droppy.built.after.mir enum Droppy { - A, B, C + A, + B, + C, } impl Drop for Droppy { @@ -82,12 +87,15 @@ fn unsigny(x: UnsignedAroundZero) -> u16 { x as u16 } -enum NotStartingAtZero { A = 4, B = 6, C = 8 } +enum NotStartingAtZero { + A = 4, + B = 6, + C = 8, +} // EMIT_MIR enum_cast.offsetty.built.after.mir fn offsetty(x: NotStartingAtZero) -> u32 { x as u32 } -fn main() { -} +fn main() {} diff --git a/tests/mir-opt/building/logical_or_in_conditional.rs b/tests/mir-opt/building/logical_or_in_conditional.rs index deb841f2b0d5..e6872e6f2ec8 100644 --- a/tests/mir-opt/building/logical_or_in_conditional.rs +++ b/tests/mir-opt/building/logical_or_in_conditional.rs @@ -30,9 +30,13 @@ fn test_or() { // EMIT_MIR logical_or_in_conditional.test_complex.built.after.mir fn test_complex() { - if let E::A(_) = E::f() && ((always_true() && Droppy(0).0 > 0) || Droppy(1).0 > 1) {} + if let E::A(_) = E::f() + && ((always_true() && Droppy(0).0 > 0) || Droppy(1).0 > 1) + {} - if !always_true() && let E::B = E::f() {} + if !always_true() + && let E::B = E::f() + {} } fn main() { diff --git a/tests/mir-opt/building/match/simple_match.rs b/tests/mir-opt/building/match/simple_match.rs index 4f0a3046a061..61c337822c85 100644 --- a/tests/mir-opt/building/match/simple_match.rs +++ b/tests/mir-opt/building/match/simple_match.rs @@ -1,7 +1,6 @@ // skip-filecheck // Test that we don't generate unnecessarily large MIR for very simple matches - // EMIT_MIR simple_match.match_bool.built.after.mir fn match_bool(x: bool) -> usize { match x { diff --git a/tests/mir-opt/building/shifts.rs b/tests/mir-opt/building/shifts.rs index 849d7b55f3a0..d7747bb2f784 100644 --- a/tests/mir-opt/building/shifts.rs +++ b/tests/mir-opt/building/shifts.rs @@ -3,19 +3,12 @@ // EMIT_MIR shifts.shift_signed.built.after.mir fn shift_signed(small: i8, big: u128, a: i8, b: i32, c: i128) -> ([i8; 3], [u128; 3]) { - ( - [small >> a, small >> b, small >> c], - [big << a, big << b, big << c], - ) + ([small >> a, small >> b, small >> c], [big << a, big << b, big << c]) } // EMIT_MIR shifts.shift_unsigned.built.after.mir fn shift_unsigned(small: u8, big: i128, a: u8, b: u32, c: u128) -> ([u8; 3], [i128; 3]) { - ( - [small >> a, small >> b, small >> c], - [big << a, big << b, big << c], - ) + ([small >> a, small >> b, small >> c], [big << a, big << b, big << c]) } -fn main() { -} +fn main() {} diff --git a/tests/mir-opt/building/storage_live_dead_in_statics.rs b/tests/mir-opt/building/storage_live_dead_in_statics.rs index 1f5692118545..7cb74acbf060 100644 --- a/tests/mir-opt/building/storage_live_dead_in_statics.rs +++ b/tests/mir-opt/building/storage_live_dead_in_statics.rs @@ -3,6 +3,7 @@ // generate `StorageStart` or `StorageEnd` statements. // EMIT_MIR storage_live_dead_in_statics.XXX.built.after.mir +#[rustfmt::skip] static XXX: &'static Foo = &Foo { tup: "hi", data: &[ @@ -20,13 +21,13 @@ static XXX: &'static Foo = &Foo { (0, 1), (0, 2), (0, 3), (0, 1), (0, 2), (0, 3), (0, 1), (0, 2), (0, 3), - ] + ], }; #[derive(Debug)] struct Foo { tup: &'static str, - data: &'static [(u32, u32)] + data: &'static [(u32, u32)], } fn main() { diff --git a/tests/mir-opt/const_prop/control_flow_simplification.rs b/tests/mir-opt/const_prop/control_flow_simplification.rs index 39b5f2898306..64605ca11c2c 100644 --- a/tests/mir-opt/const_prop/control_flow_simplification.rs +++ b/tests/mir-opt/const_prop/control_flow_simplification.rs @@ -11,7 +11,7 @@ impl NeedsDrop for This {} // EMIT_MIR control_flow_simplification.hello.GVN.diff // EMIT_MIR control_flow_simplification.hello.PreCodegen.before.mir -fn hello(){ +fn hello() { if ::NEEDS { panic!() } diff --git a/tests/mir-opt/const_prop/invalid_constant.rs b/tests/mir-opt/const_prop/invalid_constant.rs index 2b7271f63ff2..91ee36ae2c54 100644 --- a/tests/mir-opt/const_prop/invalid_constant.rs +++ b/tests/mir-opt/const_prop/invalid_constant.rs @@ -8,7 +8,11 @@ #[derive(Copy, Clone)] #[repr(u32)] -enum E { A, B, C } +enum E { + A, + B, + C, +} #[derive(Copy, Clone)] enum Empty {} @@ -39,7 +43,5 @@ fn main() { // A non-UTF-8 string slice. Regression test for #75763 and #78520. struct Str; - let _non_utf8_str: Str::<{ - unsafe { std::mem::transmute::<&[u8], &str>(&[0xC0, 0xC1, 0xF5]) } - }>; + let _non_utf8_str: Str<{ unsafe { std::mem::transmute::<&[u8], &str>(&[0xC0, 0xC1, 0xF5]) } }>; } diff --git a/tests/mir-opt/const_prop/offset_of.rs b/tests/mir-opt/const_prop/offset_of.rs index 105cbfb53dd0..264c8a3d21cd 100644 --- a/tests/mir-opt/const_prop/offset_of.rs +++ b/tests/mir-opt/const_prop/offset_of.rs @@ -31,7 +31,7 @@ struct Delta { enum Epsilon { A(u8, u16), B, - C { c: u32 } + C { c: u32 }, } enum Zeta { diff --git a/tests/mir-opt/const_prop/pointer_expose_provenance.rs b/tests/mir-opt/const_prop/pointer_expose_provenance.rs index f148a5b6542e..a76fead98594 100644 --- a/tests/mir-opt/const_prop/pointer_expose_provenance.rs +++ b/tests/mir-opt/const_prop/pointer_expose_provenance.rs @@ -2,7 +2,7 @@ //@ test-mir-pass: GVN #[inline(never)] -fn read(_: usize) { } +fn read(_: usize) {} // EMIT_MIR pointer_expose_provenance.main.GVN.diff fn main() { diff --git a/tests/mir-opt/const_prop/scalar_literal_propagation.rs b/tests/mir-opt/const_prop/scalar_literal_propagation.rs index 9d02f24e76bd..15e32490de49 100644 --- a/tests/mir-opt/const_prop/scalar_literal_propagation.rs +++ b/tests/mir-opt/const_prop/scalar_literal_propagation.rs @@ -10,4 +10,4 @@ fn main() { } #[inline(never)] -fn consume(_: u32) { } +fn consume(_: u32) {} diff --git a/tests/mir-opt/const_prop/switch_int.rs b/tests/mir-opt/const_prop/switch_int.rs index 114380e316de..4ee4182caf6a 100644 --- a/tests/mir-opt/const_prop/switch_int.rs +++ b/tests/mir-opt/const_prop/switch_int.rs @@ -3,7 +3,7 @@ // EMIT_MIR_FOR_EACH_PANIC_STRATEGY #[inline(never)] -fn foo(_: i32) { } +fn foo(_: i32) {} // EMIT_MIR switch_int.main.GVN.diff // EMIT_MIR switch_int.main.SimplifyConstCondition-after-const-prop.diff diff --git a/tests/mir-opt/const_prop/transmute.rs b/tests/mir-opt/const_prop/transmute.rs index 9cbf8928753b..892b91a5414c 100644 --- a/tests/mir-opt/const_prop/transmute.rs +++ b/tests/mir-opt/const_prop/transmute.rs @@ -45,7 +45,10 @@ pub unsafe fn undef_union_as_integer() -> u32 { // CHECK-LABEL: fn undef_union_as_integer( // CHECK: _1 = Union32 { // CHECK: _0 = move _1 as u32 (Transmute); - union Union32 { value: u32, unit: () } + union Union32 { + value: u32, + unit: (), + } unsafe { transmute(Union32 { unit: () }) } } diff --git a/tests/mir-opt/const_prop/tuple_literal_propagation.rs b/tests/mir-opt/const_prop/tuple_literal_propagation.rs index 582411c7b59e..e42a62cb6fdf 100644 --- a/tests/mir-opt/const_prop/tuple_literal_propagation.rs +++ b/tests/mir-opt/const_prop/tuple_literal_propagation.rs @@ -10,4 +10,4 @@ fn main() { } #[inline(never)] -fn consume(_: (u32, u32)) { } +fn consume(_: (u32, u32)) {} diff --git a/tests/mir-opt/copy-prop/borrowed_local.rs b/tests/mir-opt/copy-prop/borrowed_local.rs index 9da05f71b5d4..dd1679513f6c 100644 --- a/tests/mir-opt/copy-prop/borrowed_local.rs +++ b/tests/mir-opt/copy-prop/borrowed_local.rs @@ -4,10 +4,12 @@ #![feature(custom_mir, core_intrinsics, freeze)] #![allow(unused_assignments)] extern crate core; -use core::marker::Freeze; use core::intrinsics::mir::*; +use core::marker::Freeze; -fn opaque(_: impl Sized) -> bool { true } +fn opaque(_: impl Sized) -> bool { + true +} fn cmp_ref(a: &u8, b: &u8) -> bool { std::ptr::eq(a as *const u8, b as *const u8) diff --git a/tests/mir-opt/copy-prop/move_projection.rs b/tests/mir-opt/copy-prop/move_projection.rs index d8e2e24dda59..0ac1c4e0ba26 100644 --- a/tests/mir-opt/copy-prop/move_projection.rs +++ b/tests/mir-opt/copy-prop/move_projection.rs @@ -7,7 +7,9 @@ extern crate core; use core::intrinsics::mir::*; -fn opaque(_: impl Sized) -> bool { true } +fn opaque(_: impl Sized) -> bool { + true +} struct Foo(u8); diff --git a/tests/mir-opt/dataflow-const-prop/enum.rs b/tests/mir-opt/dataflow-const-prop/enum.rs index ac0705638abb..946cfa4c76c0 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.rs +++ b/tests/mir-opt/dataflow-const-prop/enum.rs @@ -8,7 +8,7 @@ use std::intrinsics::mir::*; #[derive(Copy, Clone)] enum E { V1(i32), - V2(i32) + V2(i32), } // EMIT_MIR enum.simple.DataflowConstProp.diff @@ -23,7 +23,10 @@ fn simple() { // CHECK: switchInt(const 0_isize) -> [0: [[target_bb:bb.*]], 1: bb2, otherwise: bb1]; // CHECK: [[target_bb]]: { // CHECK: [[x]] = const 0_i32; - let x = match e { E::V1(x1) => x1, E::V2(x2) => x2 }; + let x = match e { + E::V1(x1) => x1, + E::V2(x2) => x2, + }; } // EMIT_MIR enum.constant.DataflowConstProp.diff @@ -39,7 +42,10 @@ fn constant() { // CHECK: switchInt(const 0_isize) -> [0: [[target_bb:bb.*]], 1: bb2, otherwise: bb1]; // CHECK: [[target_bb]]: { // CHECK: [[x]] = const 0_i32; - let x = match e { E::V1(x1) => x1, E::V2(x2) => x2 }; + let x = match e { + E::V1(x1) => x1, + E::V2(x2) => x2, + }; } // EMIT_MIR enum.statics.DataflowConstProp.diff @@ -58,7 +64,10 @@ fn statics() { // CHECK: switchInt(const 0_isize) -> [0: [[target_bb:bb.*]], 1: bb2, otherwise: bb1]; // CHECK: [[target_bb]]: { // CHECK: [[x1]] = const 0_i32; - let x1 = match e1 { E::V1(x11) => x11, E::V2(x12) => x12 }; + let x1 = match e1 { + E::V1(x11) => x11, + E::V2(x12) => x12, + }; static RC: &E = &E::V2(4); @@ -72,7 +81,10 @@ fn statics() { // One is `_9 = &(*_12) and another is `_9 = _11`. It is different from what we can // get by printing MIR directly. It is better to check if there are any bugs in the // MIR passes around this stage. - let x2 = match e2 { E::V1(x21) => x21, E::V2(x22) => x22 }; + let x2 = match e2 { + E::V1(x21) => x21, + E::V2(x22) => x22, + }; } #[rustc_layout_scalar_valid_range_start(1)] @@ -132,7 +144,10 @@ fn multiple(x: bool, i: u8) { // CHECK: [[x2]] = const 0_u8; // CHECK: [[some:_.*]] = (({{_.*}} as Some).0: u8) // CHECK: [[x2]] = [[some]]; - let x2 = match e { Some(i) => i, None => 0 }; + let x2 = match e { + Some(i) => i, + None => 0, + }; // Therefore, `x2` should be `Top` here, and no replacement shall happen. diff --git a/tests/mir-opt/dataflow-const-prop/mult_by_zero.rs b/tests/mir-opt/dataflow-const-prop/mult_by_zero.rs index 3cd0b715a521..26f79c8c0e48 100644 --- a/tests/mir-opt/dataflow-const-prop/mult_by_zero.rs +++ b/tests/mir-opt/dataflow-const-prop/mult_by_zero.rs @@ -2,9 +2,9 @@ // EMIT_MIR mult_by_zero.test.DataflowConstProp.diff // CHECK-LABEL: fn test( -fn test(x : i32) -> i32 { - x * 0 - // CHECK: _0 = const 0_i32; +fn test(x: i32) -> i32 { + x * 0 + // CHECK: _0 = const 0_i32; } fn main() { diff --git a/tests/mir-opt/dataflow-const-prop/transmute.rs b/tests/mir-opt/dataflow-const-prop/transmute.rs index e7f93f421cf8..d0391f6974b4 100644 --- a/tests/mir-opt/dataflow-const-prop/transmute.rs +++ b/tests/mir-opt/dataflow-const-prop/transmute.rs @@ -45,7 +45,10 @@ pub unsafe fn undef_union_as_integer() -> u32 { // CHECK-LABEL: fn undef_union_as_integer( // CHECK: _1 = Union32 { // CHECK: _0 = move _1 as u32 (Transmute); - union Union32 { value: u32, unit: () } + union Union32 { + value: u32, + unit: (), + } unsafe { transmute(Union32 { unit: () }) } } diff --git a/tests/mir-opt/derefer_complex_case.rs b/tests/mir-opt/derefer_complex_case.rs index b1fa2c8733ef..96034522b9fe 100644 --- a/tests/mir-opt/derefer_complex_case.rs +++ b/tests/mir-opt/derefer_complex_case.rs @@ -4,5 +4,7 @@ // EMIT_MIR_FOR_EACH_PANIC_STRATEGY fn main() { - for &foo in &[42, 43] { drop(foo) } + for &foo in &[42, 43] { + drop(foo) + } } diff --git a/tests/mir-opt/derefer_terminator_test.rs b/tests/mir-opt/derefer_terminator_test.rs index 5de6a61eaf2c..fd16c6c2045e 100644 --- a/tests/mir-opt/derefer_terminator_test.rs +++ b/tests/mir-opt/derefer_terminator_test.rs @@ -7,7 +7,9 @@ fn main() { let b = foo(); let d = foo(); match ****(&&&&b) { - true => {let x = 5;}, + true => { + let x = 5; + } false => {} } let y = 42; diff --git a/tests/mir-opt/derefer_test.rs b/tests/mir-opt/derefer_test.rs index 3ca2144e4fc4..5676fa657fe9 100644 --- a/tests/mir-opt/derefer_test.rs +++ b/tests/mir-opt/derefer_test.rs @@ -2,7 +2,7 @@ //@ test-mir-pass: Derefer // EMIT_MIR derefer_test.main.Derefer.diff fn main() { - let mut a = (42,43); + let mut a = (42, 43); let mut b = (99, &mut a); let x = &mut (*b.1).0; let y = &mut (*b.1).1; diff --git a/tests/mir-opt/derefer_test_multiple.rs b/tests/mir-opt/derefer_test_multiple.rs index 145a19ee6a3c..7c03af00e1e6 100644 --- a/tests/mir-opt/derefer_test_multiple.rs +++ b/tests/mir-opt/derefer_test_multiple.rs @@ -1,7 +1,7 @@ // skip-filecheck //@ test-mir-pass: Derefer // EMIT_MIR derefer_test_multiple.main.Derefer.diff -fn main () { +fn main() { let mut a = (42, 43); let mut b = (99, &mut a); let mut c = (11, &mut b); diff --git a/tests/mir-opt/enum_opt.rs b/tests/mir-opt/enum_opt.rs index cacc7301f122..2cc5df84d6b5 100644 --- a/tests/mir-opt/enum_opt.rs +++ b/tests/mir-opt/enum_opt.rs @@ -7,22 +7,22 @@ // Tests that an enum with a variant with no data gets correctly transformed. pub enum NoData { - Large([u8; 8196]), - None, + Large([u8; 8196]), + None, } // Tests that an enum with a variant with data that is a valid candidate gets transformed. pub enum Candidate { - Small(u8), - Large([u8; 8196]), + Small(u8), + Large([u8; 8196]), } // Tests that an enum which has a discriminant much higher than the variant does not get // tformed. #[repr(u32)] pub enum InvalidIdxs { - A = 302, - Large([u64; 1024]), + A = 302, + Large([u64; 1024]), } // Tests that an enum with too high of a discriminant index (not in bounds of usize) does not @@ -37,51 +37,51 @@ pub enum NotTrunctable { // Tests that an enum with discriminants in random order still gets tformed correctly. #[repr(u32)] pub enum RandOrderDiscr { - A = 13, - B([u8; 1024]) = 5, - C = 7, + A = 13, + B([u8; 1024]) = 5, + C = 7, } // EMIT_MIR enum_opt.unin.EnumSizeOpt.diff pub fn unin() -> NoData { - let mut a = NoData::None; - a = NoData::Large([1; 8196]); - a + let mut a = NoData::None; + a = NoData::Large([1; 8196]); + a } // EMIT_MIR enum_opt.cand.EnumSizeOpt.diff pub fn cand() -> Candidate { - let mut a = Candidate::Small(1); - a = Candidate::Large([1; 8196]); - a + let mut a = Candidate::Small(1); + a = Candidate::Large([1; 8196]); + a } // EMIT_MIR enum_opt.invalid.EnumSizeOpt.diff pub fn invalid() -> InvalidIdxs { - let mut a = InvalidIdxs::A; - a = InvalidIdxs::Large([0; 1024]); - a + let mut a = InvalidIdxs::A; + a = InvalidIdxs::Large([0; 1024]); + a } // EMIT_MIR enum_opt.trunc.EnumSizeOpt.diff pub fn trunc() -> NotTrunctable { - let mut a = NotTrunctable::A; - a = NotTrunctable::B([0; 1024]); - a = NotTrunctable::C([0; 4096]); - a + let mut a = NotTrunctable::A; + a = NotTrunctable::B([0; 1024]); + a = NotTrunctable::C([0; 4096]); + a } pub fn rand_order() -> RandOrderDiscr { - let mut a = RandOrderDiscr::A; - a = RandOrderDiscr::B([0; 1024]); - a = RandOrderDiscr::C; - a + let mut a = RandOrderDiscr::A; + a = RandOrderDiscr::B([0; 1024]); + a = RandOrderDiscr::C; + a } pub fn main() { - unin(); - cand(); - invalid(); - trunc(); - rand_order(); + unin(); + cand(); + invalid(); + trunc(); + rand_order(); } diff --git a/tests/mir-opt/inline/inline_cycle.rs b/tests/mir-opt/inline/inline_cycle.rs index 1826e38f894d..651112ccfd7f 100644 --- a/tests/mir-opt/inline/inline_cycle.rs +++ b/tests/mir-opt/inline/inline_cycle.rs @@ -32,7 +32,6 @@ impl Call for A { } } - impl Call for B { #[inline] fn call() { diff --git a/tests/mir-opt/inline/inline_cycle_generic.rs b/tests/mir-opt/inline/inline_cycle_generic.rs index 667bf7f9254d..64f208b1c70b 100644 --- a/tests/mir-opt/inline/inline_cycle_generic.rs +++ b/tests/mir-opt/inline/inline_cycle_generic.rs @@ -26,7 +26,6 @@ impl Call for A { } } - impl Call for B { #[inline] fn call() { diff --git a/tests/mir-opt/inline/inline_options.rs b/tests/mir-opt/inline/inline_options.rs index 7d7c4f718bd7..bd9e0e2d2074 100644 --- a/tests/mir-opt/inline/inline_options.rs +++ b/tests/mir-opt/inline/inline_options.rs @@ -16,8 +16,16 @@ fn main() { // Cost is approximately 3 * 25 + 5 = 80. #[inline] -pub fn not_inlined() { g(); g(); g(); } -pub fn inlined() { g(); g(); g(); } +pub fn not_inlined() { + g(); + g(); + g(); +} +pub fn inlined() { + g(); + g(); + g(); +} #[inline(never)] fn g() {} diff --git a/tests/mir-opt/inline/inline_specialization.rs b/tests/mir-opt/inline/inline_specialization.rs index 6453abc00812..b9d40aca3a43 100644 --- a/tests/mir-opt/inline/inline_specialization.rs +++ b/tests/mir-opt/inline/inline_specialization.rs @@ -5,7 +5,7 @@ fn main() { // CHECK-LABEL: fn main( // CHECK: (inlined as Foo>::bar) - let x = as Foo>::bar(); + let x = as Foo>::bar(); } trait Foo { @@ -14,5 +14,7 @@ trait Foo { impl Foo for Vec { #[inline(always)] - default fn bar() -> u32 { 123 } + default fn bar() -> u32 { + 123 + } } diff --git a/tests/mir-opt/inline/issue_106141.rs b/tests/mir-opt/inline/issue_106141.rs index 1cca7d76b25a..d311ad4527f2 100644 --- a/tests/mir-opt/inline/issue_106141.rs +++ b/tests/mir-opt/inline/issue_106141.rs @@ -19,11 +19,7 @@ fn inner() -> usize { // CHECK: = {{.*}}[_0]; let buffer = &[true]; let index = index(); - if buffer[index] { - index - } else { - 0 - } + if buffer[index] { index } else { 0 } } fn main() { diff --git a/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.rs b/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.rs index 75772c161277..021af7f81bb2 100644 --- a/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.rs +++ b/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.rs @@ -13,6 +13,9 @@ fn main() { // CHECK-NEXT: } // CHECK-NEXT: } // CHECK-NEXT: } - let f = |x| { let y = x; y }; + let f = |x| { + let y = x; + y + }; f(()) } diff --git a/tests/mir-opt/instsimplify/combine_array_len.rs b/tests/mir-opt/instsimplify/combine_array_len.rs index 86455e8b52d5..f12284f64821 100644 --- a/tests/mir-opt/instsimplify/combine_array_len.rs +++ b/tests/mir-opt/instsimplify/combine_array_len.rs @@ -7,9 +7,9 @@ fn norm2(x: [f32; 2]) -> f32 { // CHECK-NOT: Len( let a = x[0]; let b = x[1]; - a*a + b*b + a * a + b * b } fn main() { - assert_eq!(norm2([3.0, 4.0]), 5.0*5.0); + assert_eq!(norm2([3.0, 4.0]), 5.0 * 5.0); } diff --git a/tests/mir-opt/instsimplify/combine_transmutes.rs b/tests/mir-opt/instsimplify/combine_transmutes.rs index 0be7466001fe..c3622c20697a 100644 --- a/tests/mir-opt/instsimplify/combine_transmutes.rs +++ b/tests/mir-opt/instsimplify/combine_transmutes.rs @@ -5,7 +5,7 @@ #![feature(custom_mir)] use std::intrinsics::mir::*; -use std::mem::{MaybeUninit, ManuallyDrop, transmute}; +use std::mem::{transmute, ManuallyDrop, MaybeUninit}; // EMIT_MIR combine_transmutes.identity_transmutes.InstSimplify.diff pub unsafe fn identity_transmutes() { @@ -61,4 +61,7 @@ pub unsafe fn adt_transmutes() { let _a: ManuallyDrop = transmute(MaybeUninit::::uninit()); } -pub union Union32 { u32: u32, i32: i32 } +pub union Union32 { + u32: u32, + i32: i32, +} diff --git a/tests/mir-opt/issue_104451_unwindable_intrinsics.rs b/tests/mir-opt/issue_104451_unwindable_intrinsics.rs index cd068f122367..80655a583c34 100644 --- a/tests/mir-opt/issue_104451_unwindable_intrinsics.rs +++ b/tests/mir-opt/issue_104451_unwindable_intrinsics.rs @@ -5,9 +5,7 @@ // EMIT_MIR issue_104451_unwindable_intrinsics.main.AbortUnwindingCalls.after.mir fn main() { - unsafe { - core::intrinsics::const_eval_select((), ow_ct, ow_ct) - } + unsafe { core::intrinsics::const_eval_select((), ow_ct, ow_ct) } } const fn ow_ct() -> ! { diff --git a/tests/mir-opt/issue_41110.rs b/tests/mir-opt/issue_41110.rs index 38602d5eaef4..5d042815f3b4 100644 --- a/tests/mir-opt/issue_41110.rs +++ b/tests/mir-opt/issue_41110.rs @@ -3,7 +3,6 @@ // check that we don't emit multiple drop flags when they are not needed. - // EMIT_MIR issue_41110.main.ElaborateDrops.diff fn main() { let x = S.other(S.id()); @@ -21,11 +20,12 @@ pub fn test() { struct S; impl Drop for S { - fn drop(&mut self) { - } + fn drop(&mut self) {} } impl S { - fn id(self) -> Self { self } + fn id(self) -> Self { + self + } fn other(self, s: Self) {} } diff --git a/tests/mir-opt/issue_41697.rs b/tests/mir-opt/issue_41697.rs index 92d382c39407..b031f1dc7201 100644 --- a/tests/mir-opt/issue_41697.rs +++ b/tests/mir-opt/issue_41697.rs @@ -14,9 +14,8 @@ trait Foo { fn get(&self) -> [u8; 2]; } - // EMIT_MIR issue_41697.{impl#0}-{constant#0}.SimplifyCfg-promote-consts.after.mir -impl Foo for [u8; 1+1] { +impl Foo for [u8; 1 + 1] { fn get(&self) -> [u8; 2] { *self } @@ -33,7 +32,7 @@ fn unsize_nested_fat_ptr(x: Arc) -> Arc { } fn main() { - let x: Box> = Box::new(Bar([1,2])); + let x: Box> = Box::new(Bar([1, 2])); assert_eq!(unsize_fat_ptr(&*x).0.get(), [1, 2]); let x: Arc = Arc::new([3, 4]); diff --git a/tests/mir-opt/issue_41697.{impl#0}-{constant#0}.SimplifyCfg-promote-consts.after.mir b/tests/mir-opt/issue_41697.{impl#0}-{constant#0}.SimplifyCfg-promote-consts.after.mir index 7d2e97f8d564..27a5a8dd5526 100644 --- a/tests/mir-opt/issue_41697.{impl#0}-{constant#0}.SimplifyCfg-promote-consts.after.mir +++ b/tests/mir-opt/issue_41697.{impl#0}-{constant#0}.SimplifyCfg-promote-consts.after.mir @@ -1,6 +1,6 @@ -// MIR for `::{constant#0}` after SimplifyCfg-promote-consts +// MIR for `::{constant#0}` after SimplifyCfg-promote-consts -::{constant#0}: usize = { +::{constant#0}: usize = { let mut _0: usize; let mut _1: (usize, bool); diff --git a/tests/mir-opt/issue_41888.rs b/tests/mir-opt/issue_41888.rs index 70b202186336..1744d9f85701 100644 --- a/tests/mir-opt/issue_41888.rs +++ b/tests/mir-opt/issue_41888.rs @@ -15,11 +15,13 @@ fn main() { } } -fn cond() -> bool { false } +fn cond() -> bool { + false +} struct K; enum E { F(K), - G(Box) + G(Box), } diff --git a/tests/mir-opt/issue_72181.rs b/tests/mir-opt/issue_72181.rs index 3748c2af83d2..dea8ecbd3ec7 100644 --- a/tests/mir-opt/issue_72181.rs +++ b/tests/mir-opt/issue_72181.rs @@ -9,16 +9,18 @@ enum Never {} union Foo { a: u64, - b: Never + b: Never, } - // EMIT_MIR issue_72181.foo.built.after.mir -fn foo(xs: [(Never, u32); 1]) -> u32 { xs[0].1 } +fn foo(xs: [(Never, u32); 1]) -> u32 { + xs[0].1 +} // EMIT_MIR issue_72181.bar.built.after.mir -fn bar([(_, x)]: [(Never, u32); 1]) -> u32 { x } - +fn bar([(_, x)]: [(Never, u32); 1]) -> u32 { + x +} // EMIT_MIR issue_72181.main.built.after.mir fn main() { diff --git a/tests/mir-opt/issue_72181_1.rs b/tests/mir-opt/issue_72181_1.rs index 32e946559d77..5c8346166aec 100644 --- a/tests/mir-opt/issue_72181_1.rs +++ b/tests/mir-opt/issue_72181_1.rs @@ -14,9 +14,7 @@ fn f(v: Void) -> ! { // EMIT_MIR issue_72181_1.main.built.after.mir fn main() { - let v: Void = unsafe { - std::mem::transmute::<(), Void>(()) - }; + let v: Void = unsafe { std::mem::transmute::<(), Void>(()) }; f(v); } diff --git a/tests/mir-opt/issue_91633.rs b/tests/mir-opt/issue_91633.rs index f7d59f5adfb6..d24c2e19aa73 100644 --- a/tests/mir-opt/issue_91633.rs +++ b/tests/mir-opt/issue_91633.rs @@ -1,32 +1,30 @@ // skip-filecheck //@ compile-flags: -Z mir-opt-level=0 // EMIT_MIR issue_91633.hey.built.after.mir -fn hey (it: &[T]) - where - [T] : std::ops::Index, - { - let _ = &it[0]; - } +fn hey(it: &[T]) +where + [T]: std::ops::Index, +{ + let _ = &it[0]; +} // EMIT_MIR issue_91633.bar.built.after.mir -fn bar (it: Box<[T]>) - where - [T] : std::ops::Index, - { - let _ = it[0]; - } +fn bar(it: Box<[T]>) +where + [T]: std::ops::Index, +{ + let _ = it[0]; +} // EMIT_MIR issue_91633.fun.built.after.mir -fn fun (it: &[T]) -> &T - { - let f = &it[0]; - f - } +fn fun(it: &[T]) -> &T { + let f = &it[0]; + f +} // EMIT_MIR issue_91633.foo.built.after.mir -fn foo (it: Box<[T]>) -> T - { - let f = it[0].clone(); - f - } - fn main(){} +fn foo(it: Box<[T]>) -> T { + let f = it[0].clone(); + f +} +fn main() {} diff --git a/tests/mir-opt/issues/issue_75439.rs b/tests/mir-opt/issues/issue_75439.rs index 8c710a33aa8e..ea763dd1b10d 100644 --- a/tests/mir-opt/issues/issue_75439.rs +++ b/tests/mir-opt/issues/issue_75439.rs @@ -8,11 +8,7 @@ pub fn foo(bytes: [u8; 16]) -> Option<[u8; 4]> { // big endian `u32`s let dwords: [u32; 4] = unsafe { transmute(bytes) }; const FF: u32 = 0x0000_ffff_u32.to_be(); - if let [0, 0, 0 | FF, ip] = dwords { - Some(unsafe { transmute(ip) }) - } else { - None - } + if let [0, 0, 0 | FF, ip] = dwords { Some(unsafe { transmute(ip) }) } else { None } } fn main() { diff --git a/tests/mir-opt/jump_threading.rs b/tests/mir-opt/jump_threading.rs index 3ab155fdc9e7..b4c133716800 100644 --- a/tests/mir-opt/jump_threading.rs +++ b/tests/mir-opt/jump_threading.rs @@ -330,11 +330,7 @@ fn mutable_ref() -> bool { let a = std::ptr::addr_of_mut!(x); x = 7; unsafe { *a = 8 }; - if x == 7 { - true - } else { - false - } + if x == 7 { true } else { false } } /// This function has 2 TOs: 1-3-4 and 0-1-3-4-6. @@ -461,11 +457,7 @@ fn aggregate(x: u8) -> u8 { const FOO: (u8, u8) = (5, 13); let (a, b) = FOO; - if a == 7 { - b - } else { - a - } + if a == 7 { b } else { a } } /// Verify that we can leverage the existence of an `Assume` terminator. diff --git a/tests/mir-opt/lower_array_len.rs b/tests/mir-opt/lower_array_len.rs index 1c30c4c89b96..62fc9ef67d66 100644 --- a/tests/mir-opt/lower_array_len.rs +++ b/tests/mir-opt/lower_array_len.rs @@ -7,11 +7,7 @@ pub fn array_bound(index: usize, slice: &[u8; N]) -> u8 { // CHECK-LABEL: fn array_bound( // CHECK: [[len:_.*]] = const N; // CHECK: Lt(move {{_.*}}, move [[len]]); - if index < slice.len() { - slice[index] - } else { - 42 - } + if index < slice.len() { slice[index] } else { 42 } } // EMIT_MIR lower_array_len.array_bound_mut.NormalizeArrayLen.diff diff --git a/tests/mir-opt/lower_slice_len.rs b/tests/mir-opt/lower_slice_len.rs index b82094dc18f9..6fd7e4bf72cd 100644 --- a/tests/mir-opt/lower_slice_len.rs +++ b/tests/mir-opt/lower_slice_len.rs @@ -5,11 +5,7 @@ pub fn bound(index: usize, slice: &[u8]) -> u8 { // CHECK-LABEL: fn bound( // CHECK-NOT: ::len( - if index < slice.len() { - slice[index] - } else { - 42 - } + if index < slice.len() { slice[index] } else { 42 } } fn main() { diff --git a/tests/mir-opt/matches_u8.rs b/tests/mir-opt/matches_u8.rs index f0be82d02571..86d646256742 100644 --- a/tests/mir-opt/matches_u8.rs +++ b/tests/mir-opt/matches_u8.rs @@ -1,7 +1,6 @@ // skip-filecheck //@ test-mir-pass: MatchBranchSimplification - // EMIT_MIR matches_u8.exhaustive_match.MatchBranchSimplification.diff // EMIT_MIR matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff @@ -27,9 +26,9 @@ pub fn exhaustive_match_i8(e: E) -> i8 { } fn main() { - assert_eq!(exhaustive_match(E::A), 0); - assert_eq!(exhaustive_match(E::B), 1); + assert_eq!(exhaustive_match(E::A), 0); + assert_eq!(exhaustive_match(E::B), 1); - assert_eq!(exhaustive_match_i8(E::A), 0); - assert_eq!(exhaustive_match_i8(E::B), 1); + assert_eq!(exhaustive_match_i8(E::A), 0); + assert_eq!(exhaustive_match_i8(E::B), 1); } diff --git a/tests/mir-opt/nll/named_lifetimes_basic.rs b/tests/mir-opt/nll/named_lifetimes_basic.rs index cc8385370038..93f4a8bfd598 100644 --- a/tests/mir-opt/nll/named_lifetimes_basic.rs +++ b/tests/mir-opt/nll/named_lifetimes_basic.rs @@ -10,7 +10,8 @@ #![allow(warnings)] // EMIT_MIR named_lifetimes_basic.use_x.nll.0.mir -fn use_x<'a, 'b: 'a, 'c>(w: &'a mut i32, x: &'b u32, y: &'a u32, z: &'c u32) -> bool { true } - -fn main() { +fn use_x<'a, 'b: 'a, 'c>(w: &'a mut i32, x: &'b u32, y: &'a u32, z: &'c u32) -> bool { + true } + +fn main() {} diff --git a/tests/mir-opt/nrvo_simple.rs b/tests/mir-opt/nrvo_simple.rs index 5d2894a704a5..df540472e1cc 100644 --- a/tests/mir-opt/nrvo_simple.rs +++ b/tests/mir-opt/nrvo_simple.rs @@ -10,5 +10,7 @@ fn nrvo(init: fn(&mut [u8; 1024])) -> [u8; 1024] { } fn main() { - let _ = nrvo(|buf| { buf[4] = 4; }); + let _ = nrvo(|buf| { + buf[4] = 4; + }); } diff --git a/tests/mir-opt/packed_struct_drop_aligned.rs b/tests/mir-opt/packed_struct_drop_aligned.rs index dff941c4fa0c..3abc6426e7f0 100644 --- a/tests/mir-opt/packed_struct_drop_aligned.rs +++ b/tests/mir-opt/packed_struct_drop_aligned.rs @@ -1,7 +1,6 @@ // skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY - // EMIT_MIR packed_struct_drop_aligned.main.SimplifyCfg-pre-optimizations.after.mir fn main() { let mut x = Packed(Aligned(Droppy(0))); diff --git a/tests/mir-opt/pre-codegen/intrinsics.rs b/tests/mir-opt/pre-codegen/intrinsics.rs index e5c059cda12e..0482b85e95f8 100644 --- a/tests/mir-opt/pre-codegen/intrinsics.rs +++ b/tests/mir-opt/pre-codegen/intrinsics.rs @@ -12,7 +12,6 @@ pub fn f_unit() { f_dispatch(()); } - // EMIT_MIR intrinsics.f_u64.PreCodegen.after.mir pub fn f_u64() { f_dispatch(0u64); @@ -28,8 +27,7 @@ pub fn f_dispatch(t: T) { } #[inline(never)] -pub fn f_zst(_t: T) { -} +pub fn f_zst(_t: T) {} #[inline(never)] pub fn f_non_zst(_t: T) {} diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.rs b/tests/mir-opt/pre-codegen/optimizes_into_variable.rs index 7a1fb1e76c03..de5e2d5c3121 100644 --- a/tests/mir-opt/pre-codegen/optimizes_into_variable.rs +++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.rs @@ -15,5 +15,5 @@ struct Point { fn main() { let x = 2 + 2; let y = [0, 1, 2, 3, 4, 5][3]; - let z = (Point { x: 12, y: 42}).y; + let z = (Point { x: 12, y: 42 }).y; } diff --git a/tests/mir-opt/pre-codegen/try_identity.rs b/tests/mir-opt/pre-codegen/try_identity.rs index 2e17a3ae6e7e..264b303e381d 100644 --- a/tests/mir-opt/pre-codegen/try_identity.rs +++ b/tests/mir-opt/pre-codegen/try_identity.rs @@ -17,18 +17,16 @@ fn new(x: Result) -> Result { } { ControlFlow::Continue(v) => v, ControlFlow::Break(e) => return Err(e), - } + }, ) } // EMIT_MIR try_identity.old.PreCodegen.after.mir fn old(x: Result) -> Result { - Ok( - match x { - Ok(v) => v, - Err(e) => return Err(e), - } - ) + Ok(match x { + Ok(v) => v, + Err(e) => return Err(e), + }) } fn main() { diff --git a/tests/mir-opt/reference_prop.rs b/tests/mir-opt/reference_prop.rs index 678a7c81084b..58d8b524ad64 100644 --- a/tests/mir-opt/reference_prop.rs +++ b/tests/mir-opt/reference_prop.rs @@ -787,7 +787,9 @@ fn mut_raw_then_mut_shr() -> (i32, i32) { let xshr = &*xref; // Verify that we completely replace with `x` in both cases. let a = *xshr; - unsafe { *xraw = 4; } + unsafe { + *xraw = 4; + } (a, x) } @@ -842,8 +844,7 @@ fn debuginfo() { // `constant_index_from_end` and `subslice` should not be promoted, as their value depends // on the slice length. - if let [_, ref constant_index, subslice @ .., ref constant_index_from_end] = &[6; 10][..] { - } + if let [_, ref constant_index, subslice @ .., ref constant_index_from_end] = &[6; 10][..] {} let multiple_borrow = &&&mut T(6).0; } diff --git a/tests/mir-opt/retag.rs b/tests/mir-opt/retag.rs index 43d74aa5726f..001c55991383 100644 --- a/tests/mir-opt/retag.rs +++ b/tests/mir-opt/retag.rs @@ -59,7 +59,9 @@ pub fn main() { fn array_casts() { let mut x: [usize; 2] = [0, 0]; let p = &mut x as *mut usize; - unsafe { *p.add(1) = 1; } + unsafe { + *p.add(1) = 1; + } let x: [usize; 2] = [0, 1]; let p = &x as *const usize; diff --git a/tests/mir-opt/return_an_array.rs b/tests/mir-opt/return_an_array.rs index 09146a824fcd..673b5df7d730 100644 --- a/tests/mir-opt/return_an_array.rs +++ b/tests/mir-opt/return_an_array.rs @@ -2,8 +2,8 @@ // this tests move up progration, which is not yet implemented fn foo() -> [u8; 1024] { - let x = [0; 1024]; - return x; + let x = [0; 1024]; + return x; } -fn main() { } +fn main() {} diff --git a/tests/mir-opt/simplify_locals.rs b/tests/mir-opt/simplify_locals.rs index f57611111cfc..6511b5e87e47 100644 --- a/tests/mir-opt/simplify_locals.rs +++ b/tests/mir-opt/simplify_locals.rs @@ -1,13 +1,12 @@ // skip-filecheck //@ test-mir-pass: SimplifyLocals-before-const-prop - #![feature(thread_local)] #[derive(Copy, Clone)] enum E { - A, - B, + A, + B, } // EMIT_MIR simplify_locals.c.SimplifyLocals-before-const-prop.diff @@ -26,7 +25,7 @@ fn d1() { // EMIT_MIR simplify_locals.d2.SimplifyLocals-before-const-prop.diff fn d2() { // Unused set discriminant - {(10, E::A)}.1 = E::B; + { (10, E::A) }.1 = E::B; } // EMIT_MIR simplify_locals.r.SimplifyLocals-before-const-prop.diff @@ -37,7 +36,8 @@ fn r() { let _ = &mut a; } -#[thread_local] static mut X: u32 = 0; +#[thread_local] +static mut X: u32 = 0; // EMIT_MIR simplify_locals.t1.SimplifyLocals-before-const-prop.diff fn t1() { diff --git a/tests/mir-opt/simplify_locals_fixedpoint.rs b/tests/mir-opt/simplify_locals_fixedpoint.rs index 6947d31dc3e1..0b6c95630c0a 100644 --- a/tests/mir-opt/simplify_locals_fixedpoint.rs +++ b/tests/mir-opt/simplify_locals_fixedpoint.rs @@ -4,9 +4,7 @@ fn foo() { if let (Some(a), None) = (Option::::None, Option::::None) { - if a > 42u8 { - - } + if a > 42u8 {} } } diff --git a/tests/mir-opt/simplify_match.rs b/tests/mir-opt/simplify_match.rs index 2eac93edbb8e..b035b6339fae 100644 --- a/tests/mir-opt/simplify_match.rs +++ b/tests/mir-opt/simplify_match.rs @@ -5,8 +5,11 @@ fn noop() {} // EMIT_MIR simplify_match.main.GVN.diff fn main() { - match { let x = false; x } { + match { + let x = false; + x + } { true => noop(), - false => {}, + false => {} } } diff --git a/tests/mir-opt/sroa/lifetimes.rs b/tests/mir-opt/sroa/lifetimes.rs index 6c18dbaf5a23..90aa2a10938e 100644 --- a/tests/mir-opt/sroa/lifetimes.rs +++ b/tests/mir-opt/sroa/lifetimes.rs @@ -19,10 +19,7 @@ fn foo() { // CHECK-NOT: [foo:_.*]: Foo // CHECK-NOT: Box - let foo: Foo = Foo { - x: Ok(Box::new(5_u32)), - y: 7_u32, - }; + let foo: Foo = Foo { x: Ok(Box::new(5_u32)), y: 7_u32 }; let x = foo.x; let y = foo.y; diff --git a/tests/mir-opt/uninhabited_enum.rs b/tests/mir-opt/uninhabited_enum.rs index 8816f31f9dfa..859535852cf0 100644 --- a/tests/mir-opt/uninhabited_enum.rs +++ b/tests/mir-opt/uninhabited_enum.rs @@ -6,15 +6,15 @@ pub enum Void {} // EMIT_MIR uninhabited_enum.process_never.SimplifyLocals-final.after.mir #[no_mangle] pub fn process_never(input: *const !) { - let _input = unsafe { &*input }; + let _input = unsafe { &*input }; } // EMIT_MIR uninhabited_enum.process_void.SimplifyLocals-final.after.mir #[no_mangle] pub fn process_void(input: *const Void) { - let _input = unsafe { &*input }; - // In the future, this should end with `unreachable`, but we currently only do - // unreachability analysis for `!`. + let _input = unsafe { &*input }; + // In the future, this should end with `unreachable`, but we currently only do + // unreachability analysis for `!`. } fn main() {} diff --git a/tests/mir-opt/unnamed-fields/field_access.rs b/tests/mir-opt/unnamed-fields/field_access.rs index 5badfa1646bc..cc0ac9a34274 100644 --- a/tests/mir-opt/unnamed-fields/field_access.rs +++ b/tests/mir-opt/unnamed-fields/field_access.rs @@ -17,7 +17,7 @@ struct Foo { _: struct { d: [u8; 1], } - } + }, } #[repr(C)] @@ -31,10 +31,9 @@ union Bar { _: union { d: [u8; 1], } - } + }, } - fn access(_: T) {} // CHECK-LABEL: fn foo( @@ -71,5 +70,4 @@ fn bar(bar: Bar) { } } - fn main() {} diff --git a/tests/mir-opt/unreachable.rs b/tests/mir-opt/unreachable.rs index 5838b35a553a..881e3542f0ac 100644 --- a/tests/mir-opt/unreachable.rs +++ b/tests/mir-opt/unreachable.rs @@ -35,7 +35,7 @@ fn if_let() { _y = 42; } - match _x { } + match _x {} } } @@ -56,7 +56,7 @@ fn as_match() { // CHECK: return; match empty() { None => {} - Some(_x) => match _x {} + Some(_x) => match _x {}, } } diff --git a/tests/mir-opt/unusual_item_types.rs b/tests/mir-opt/unusual_item_types.rs index 788475431044..2f05981e812e 100644 --- a/tests/mir-opt/unusual_item_types.rs +++ b/tests/mir-opt/unusual_item_types.rs @@ -3,7 +3,6 @@ // that we don't create filenames containing `<` and `>` //@ compile-flags: -Zmir-opt-level=0 - struct A; // EMIT_MIR unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.built.after.mir @@ -23,8 +22,8 @@ enum E { V = 5, } +// EMIT_MIR core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir pub fn main() { let f = Test::X as fn(usize) -> Test; -// EMIT_MIR core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir let v = Vec::::new(); } diff --git a/tests/mir-opt/unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.built.after.mir b/tests/mir-opt/unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.built.after.mir index a5121ae550d6..e2edbfcd4fa3 100644 --- a/tests/mir-opt/unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.built.after.mir +++ b/tests/mir-opt/unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.built.after.mir @@ -1,6 +1,6 @@ -// MIR for `::ASSOCIATED_CONSTANT` after built +// MIR for `::ASSOCIATED_CONSTANT` after built -const ::ASSOCIATED_CONSTANT: i32 = { +const ::ASSOCIATED_CONSTANT: i32 = { let mut _0: i32; bb0: { From 45760276fd27086995d07abeae9f7e86660c2e3c Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Mon, 3 Jun 2024 12:20:19 +0200 Subject: [PATCH 173/211] Remove stray "this" --- library/std/src/sys/pal/unix/fs.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs index fbbd40bfb796..a79a232e3d5b 100644 --- a/library/std/src/sys/pal/unix/fs.rs +++ b/library/std/src/sys/pal/unix/fs.rs @@ -1910,8 +1910,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { // The code below ensures that `FreeOnDrop` is never a null pointer unsafe { // `copyfile_state_free` returns -1 if the `to` or `from` files - // cannot be closed. However, this is not considered this an - // error. + // cannot be closed. However, this is not considered an error. libc::copyfile_state_free(self.0); } } From 66a13861aee8f3754dbec65af21c2ef6ca9756f9 Mon Sep 17 00:00:00 2001 From: Andrew Wock Date: Sat, 1 Jun 2024 14:59:13 -0400 Subject: [PATCH 174/211] Fix ICE caused by ignoring EffectVars in type inference Signed-off-by: Andrew Wock --- compiler/rustc_infer/src/infer/mod.rs | 2 + compiler/rustc_infer/src/infer/resolve.rs | 3 + tests/crashes/119830.rs | 11 --- .../effects/spec-effectvar-ice.rs | 24 +++++++ .../effects/spec-effectvar-ice.stderr | 69 +++++++++++++++++++ 5 files changed, 98 insertions(+), 11 deletions(-) delete mode 100644 tests/crashes/119830.rs create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.rs create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.stderr diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index c8bb6cf5f9b4..cb93ef7fdb07 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -587,6 +587,7 @@ pub enum FixupError { UnresolvedFloatTy(FloatVid), UnresolvedTy(TyVid), UnresolvedConst(ConstVid), + UnresolvedEffect(EffectVid), } /// See the `region_obligations` field for more information. @@ -614,6 +615,7 @@ impl fmt::Display for FixupError { ), UnresolvedTy(_) => write!(f, "unconstrained type"), UnresolvedConst(_) => write!(f, "unconstrained const value"), + UnresolvedEffect(_) => write!(f, "unconstrained effect value"), } } } diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs index 21ef2e89523f..830d79f52b94 100644 --- a/compiler/rustc_infer/src/infer/resolve.rs +++ b/compiler/rustc_infer/src/infer/resolve.rs @@ -167,6 +167,9 @@ impl<'a, 'tcx> FallibleTypeFolder> for FullTypeResolver<'a, 'tcx> { ty::ConstKind::Infer(InferConst::Fresh(_)) => { bug!("Unexpected const in full const resolver: {:?}", c); } + ty::ConstKind::Infer(InferConst::EffectVar(evid)) => { + return Err(FixupError::UnresolvedEffect(evid)); + } _ => {} } c.try_super_fold_with(self) diff --git a/tests/crashes/119830.rs b/tests/crashes/119830.rs deleted file mode 100644 index 71becc04e169..000000000000 --- a/tests/crashes/119830.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ known-bug: #119830 -#![feature(effects)] -#![feature(min_specialization)] - -trait Specialize {} - -trait Foo {} - -impl const Foo for T {} - -impl const Foo for T where T: const Specialize {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.rs new file mode 100644 index 000000000000..9778217d462d --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.rs @@ -0,0 +1,24 @@ +//@ check-fail +// Fixes #119830 + +#![feature(effects)] +#![feature(min_specialization)] +#![feature(const_trait_impl)] + +trait Specialize {} + +trait Foo {} + +impl const Foo for T {} +//~^ error: const `impl` for trait `Foo` which is not marked with `#[const_trait]` +//~| error: the const parameter `host` is not constrained by the impl trait, self type, or predicates [E0207] + +impl const Foo for T where T: const Specialize {} +//~^ error: const `impl` for trait `Foo` which is not marked with `#[const_trait]` +//~| error: `const` can only be applied to `#[const_trait]` traits +//~| error: the const parameter `host` is not constrained by the impl trait, self type, or predicates [E0207] +//~| error: specialization impl does not specialize any associated items +//~| error: could not resolve generic parameters on overridden impl + +fn main() { +} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.stderr new file mode 100644 index 000000000000..d18063f8d3d8 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.stderr @@ -0,0 +1,69 @@ +error: const `impl` for trait `Foo` which is not marked with `#[const_trait]` + --> $DIR/spec-effectvar-ice.rs:12:15 + | +LL | trait Foo {} + | - help: mark `Foo` as const: `#[const_trait]` +LL | +LL | impl const Foo for T {} + | ^^^ + | + = 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: const `impl` for trait `Foo` which is not marked with `#[const_trait]` + --> $DIR/spec-effectvar-ice.rs:16:15 + | +LL | trait Foo {} + | - help: mark `Foo` as const: `#[const_trait]` +... +LL | impl const Foo for T where T: const Specialize {} + | ^^^ + | + = 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: `const` can only be applied to `#[const_trait]` traits + --> $DIR/spec-effectvar-ice.rs:16:40 + | +LL | impl const Foo for T where T: const Specialize {} + | ^^^^^^^^^^ + +error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates + --> $DIR/spec-effectvar-ice.rs:12:9 + | +LL | impl const Foo for T {} + | ^^^^^ unconstrained const parameter + | + = note: expressions using a const parameter must map each value to a distinct output value + = note: proving the result of expressions other than the parameter are unique is not supported + +error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates + --> $DIR/spec-effectvar-ice.rs:16:9 + | +LL | impl const Foo for T where T: const Specialize {} + | ^^^^^ unconstrained const parameter + | + = note: expressions using a const parameter must map each value to a distinct output value + = note: proving the result of expressions other than the parameter are unique is not supported + +error: specialization impl does not specialize any associated items + --> $DIR/spec-effectvar-ice.rs:16:1 + | +LL | impl const Foo for T where T: const Specialize {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: impl is a specialization of this impl + --> $DIR/spec-effectvar-ice.rs:12:1 + | +LL | impl const Foo for T {} + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: could not resolve generic parameters on overridden impl + --> $DIR/spec-effectvar-ice.rs:16:1 + | +LL | impl const Foo for T where T: const Specialize {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0207`. From aebe8a7ed3f6b915170df8e9056f2bdbaac4de00 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 27 May 2024 08:22:32 +0000 Subject: [PATCH 175/211] Add regression test --- tests/ui/lifetimes/noisy-follow-up-erro.rs | 23 ++++++++++++++++ .../ui/lifetimes/noisy-follow-up-erro.stderr | 27 +++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 tests/ui/lifetimes/noisy-follow-up-erro.rs create mode 100644 tests/ui/lifetimes/noisy-follow-up-erro.stderr diff --git a/tests/ui/lifetimes/noisy-follow-up-erro.rs b/tests/ui/lifetimes/noisy-follow-up-erro.rs new file mode 100644 index 000000000000..47a87068d8fb --- /dev/null +++ b/tests/ui/lifetimes/noisy-follow-up-erro.rs @@ -0,0 +1,23 @@ +struct Foo<'c, 'd>(&'c (), &'d ()); + +impl<'c, 'd> Foo<'c, 'd> { + fn acc(&mut self, _bar: &Bar) -> &'d () { + todo!() + } +} + +struct Bar; + +impl<'a> Bar { + fn boom(&self, foo: &mut Foo<'_, '_, 'a>) -> Result<(), &'a ()> { + //~^ ERROR: struct takes 2 lifetime arguments but 3 lifetime arguments were supplied + self.bar().map_err(|()| foo.acc(self))?; + //~^ ERROR: explicit lifetime required in the type of `foo` + Ok(()) + } + fn bar(&self) -> Result<(), &'a ()> { + todo!() + } +} + +fn main() {} diff --git a/tests/ui/lifetimes/noisy-follow-up-erro.stderr b/tests/ui/lifetimes/noisy-follow-up-erro.stderr new file mode 100644 index 000000000000..f549009a87c1 --- /dev/null +++ b/tests/ui/lifetimes/noisy-follow-up-erro.stderr @@ -0,0 +1,27 @@ +error[E0107]: struct takes 2 lifetime arguments but 3 lifetime arguments were supplied + --> $DIR/noisy-follow-up-erro.rs:12:30 + | +LL | fn boom(&self, foo: &mut Foo<'_, '_, 'a>) -> Result<(), &'a ()> { + | ^^^ -- help: remove this lifetime argument + | | + | expected 2 lifetime arguments + | +note: struct defined here, with 2 lifetime parameters: `'c`, `'d` + --> $DIR/noisy-follow-up-erro.rs:1:8 + | +LL | struct Foo<'c, 'd>(&'c (), &'d ()); + | ^^^ -- -- + +error[E0621]: explicit lifetime required in the type of `foo` + --> $DIR/noisy-follow-up-erro.rs:14:9 + | +LL | fn boom(&self, foo: &mut Foo<'_, '_, 'a>) -> Result<(), &'a ()> { + | -------------------- help: add explicit lifetime `'a` to the type of `foo`: `&mut Foo<'_, 'a>` +LL | +LL | self.bar().map_err(|()| foo.acc(self))?; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'a` required + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0107, E0621. +For more information about an error, try `rustc --explain E0107`. From 61c4b7f1a701798f01df7a685ee3bb515cb7d9f9 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 27 May 2024 09:45:40 +0000 Subject: [PATCH 176/211] Hide some follow-up errors --- compiler/rustc_hir_analysis/src/impl_wf_check.rs | 2 ++ tests/ui/traits/issue-78372.stderr | 12 ++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs index 002be61196aa..5cc1ec71757b 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs @@ -86,6 +86,8 @@ fn enforce_impl_params_are_constrained( let impl_predicates = tcx.predicates_of(impl_def_id); let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).map(ty::EarlyBinder::instantiate_identity); + impl_trait_ref.error_reported()?; + let mut input_parameters = cgp::parameters_for_impl(tcx, impl_self_ty, impl_trait_ref); cgp::identify_constrained_generic_params( tcx, diff --git a/tests/ui/traits/issue-78372.stderr b/tests/ui/traits/issue-78372.stderr index 58a4c229e5e6..cdcb0cdf2593 100644 --- a/tests/ui/traits/issue-78372.stderr +++ b/tests/ui/traits/issue-78372.stderr @@ -55,12 +55,6 @@ LL | impl DispatchFromDyn> for T {} = help: add `#![feature(dispatch_from_dyn)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion between structures - --> $DIR/issue-78372.rs:3:1 - | -LL | impl DispatchFromDyn> for T {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0038]: the trait `Foo` cannot be made into an object --> $DIR/issue-78372.rs:12:17 | @@ -88,6 +82,12 @@ LL | fn foo(self: Smaht); = note: type of `self` must be `Self` or a type that dereferences to it = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin