From 99e6a28804eac57faa37134d61a2bb17069996a2 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Thu, 30 May 2024 18:32:46 -0400 Subject: [PATCH 001/786] Add f16/f128 handling in a couple places --- compiler/rustc_codegen_llvm/src/abi.rs | 2 ++ compiler/rustc_target/src/abi/call/mod.rs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index a6a3f0f964611..2e52d3f426a83 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -121,8 +121,10 @@ impl LlvmType for Reg { match self.kind { RegKind::Integer => cx.type_ix(self.size.bits()), RegKind::Float => match self.size.bits() { + 16 => cx.type_f16(), 32 => cx.type_f32(), 64 => cx.type_f64(), + 128 => cx.type_f128(), _ => bug!("unsupported float: {:?}", self), }, RegKind::Vector => cx.type_vector(cx.type_i8(), self.size.bytes()), diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index fc79c9232d1bd..f83d0492004a2 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -236,8 +236,10 @@ impl Reg { _ => panic!("unsupported integer: {self:?}"), }, RegKind::Float => match self.size.bits() { + 16 => dl.f16_align.abi, 32 => dl.f32_align.abi, 64 => dl.f64_align.abi, + 128 => dl.f128_align.abi, _ => panic!("unsupported float: {self:?}"), }, RegKind::Vector => dl.vector_align(self.size).abi, From c6cc160ec695b23f17df2a3840141093ae0c466b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Wed, 5 Jun 2024 23:29:37 +0200 Subject: [PATCH 002/786] needless_borrows_for_generic_args: Fix for &mut MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit fixes a bug introduced in #12706, where the behavior of the lint has been changed, to avoid suggestions that introduce a move. The motivation in the commit message is quite poor (if the detection for significant drops is not sufficient because it's not transitive, the proper fix would be to make it transitive). However, #12454, the linked issue, provides a good reason for the change — if the value being borrowed is bound to a variable, then moving it will only introduce friction into future refactorings. Thus #12706 changes the logic so that the lint triggers if the value being borrowed is Copy, or is the result of a function call, simplifying the logic to the point where analysing "is this the only use of this value" isn't necessary. However, said PR also introduces an undocumented carveout, where referents that themselves are mutable references are treated as Copy, to catch some cases that we do want to lint against. However, that is not sound — it's possible to consume a mutable reference by moving it. To avoid emitting false suggestions, this PR reintroduces the referent_used_exactly_once logic and runs that check for referents that are themselves mutable references. Thinking about the code shape of &mut x, where x: &mut T, raises the point that while removing the &mut outright won't work, the extra indirection is still undesirable, and perhaps instead we should suggest reborrowing: &mut *x. That, however, is left as possible future work. Fixes #12856 --- .../src/needless_borrows_for_generic_args.rs | 48 +++++++++++++++++-- .../needless_borrows_for_generic_args.fixed | 8 ++++ tests/ui/needless_borrows_for_generic_args.rs | 8 ++++ 3 files changed, 59 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/needless_borrows_for_generic_args.rs b/clippy_lints/src/needless_borrows_for_generic_args.rs index daf166bad90d8..71073716cf8ba 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::PossibleBorrowerMap; +use clippy_utils::mir::{enclosing_mir, expr_local, local_assignments, used_exactly_once, 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,6 +11,7 @@ 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, }; @@ -105,6 +106,7 @@ 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, @@ -153,9 +155,14 @@ 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 is Copy itself OR not a variable (created by a function call) +/// * The borrowed value is: +/// - `Copy` itself, or +/// - the only use of a mutable reference, or +/// - not a variable (created by a function call) +#[expect(clippy::too_many_arguments)] 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, @@ -230,9 +237,9 @@ fn needless_borrow_count<'tcx>( let referent_ty = cx.typeck_results().expr_ty(referent); - if (!is_copy(cx, referent_ty) && !referent_ty.is_ref()) - && let ExprKind::AddrOf(_, _, inner) = reference.kind - && !matches!(inner.kind, ExprKind::Call(..) | ExprKind::MethodCall(..)) + if !(is_copy(cx, referent_ty) + || referent_ty.is_ref() && referent_used_exactly_once(cx, possible_borrowers, reference) + || matches!(referent.kind, ExprKind::Call(..) | ExprKind::MethodCall(..))) { return false; } @@ -335,6 +342,37 @@ 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`. diff --git a/tests/ui/needless_borrows_for_generic_args.fixed b/tests/ui/needless_borrows_for_generic_args.fixed index 5478372cbe00f..593649b60bc71 100644 --- a/tests/ui/needless_borrows_for_generic_args.fixed +++ b/tests/ui/needless_borrows_for_generic_args.fixed @@ -333,4 +333,12 @@ fn main() { f(&y); // Don't lint f("".to_owned()); // Lint } + { + fn takes_writer(_: T) {} + + fn f(mut buffer: &mut Vec) { + takes_writer(&mut buffer); // Don't lint, would make buffer unavailable later + buffer.extend(b"\n"); + } + } } diff --git a/tests/ui/needless_borrows_for_generic_args.rs b/tests/ui/needless_borrows_for_generic_args.rs index 2643815d939b5..0c9b98d739d38 100644 --- a/tests/ui/needless_borrows_for_generic_args.rs +++ b/tests/ui/needless_borrows_for_generic_args.rs @@ -333,4 +333,12 @@ fn main() { f(&y); // Don't lint f(&"".to_owned()); // Lint } + { + fn takes_writer(_: T) {} + + fn f(mut buffer: &mut Vec) { + takes_writer(&mut buffer); // Don't lint, would make buffer unavailable later + buffer.extend(b"\n"); + } + } } From c9b0075563bc43181469ec34a60f5f05b31a2d2c Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 30 Jun 2024 17:09:46 +0000 Subject: [PATCH 003/786] Distribute rustc_codegen_cranelift for arm64 macOS --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index eb21e027dd0e0..3b3c86a1bd17b 100644 --- a/Readme.md +++ b/Readme.md @@ -70,7 +70,7 @@ For more docs on how to build and test see [build_system/usage.txt](build_system |FreeBSD|✅[^no-rustup]|❓|❓|❓| |AIX|❌[^xcoff]|N/A|N/A|❌[^xcoff]| |Other unixes|❓|❓|❓|❓| -|macOS|✅|✅[^no-rustup]|N/A|N/A| +|macOS|✅|✅|N/A|N/A| |Windows|✅[^no-rustup]|❌|N/A|N/A| ✅: Fully supported and tested From 37d8462bd92e0648e65aebc4cecd54e9840e3fe6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bennet=20Ble=C3=9Fmann?= Date: Thu, 4 Jul 2024 21:23:55 +0200 Subject: [PATCH 004/786] fix tests after rebase --- tests/ui/from_str_radix_10.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ui/from_str_radix_10.rs b/tests/ui/from_str_radix_10.rs index 2d5b351f8da3e..0df6a0a202ae7 100644 --- a/tests/ui/from_str_radix_10.rs +++ b/tests/ui/from_str_radix_10.rs @@ -1,4 +1,3 @@ -#![feature(const_int_from_str)] #![warn(clippy::from_str_radix_10)] mod some_mod { @@ -61,7 +60,8 @@ fn main() -> Result<(), Box> { Ok(()) } -fn issue_12732() { +// https://github.com/rust-lang/rust-clippy/issues/12731 +fn issue_12731() { const A: Result = u32::from_str_radix("123", 10); const B: () = { let _ = u32::from_str_radix("123", 10); From 26cdeed27e2304b6820016ee7fbcdb2331f9b113 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bennet=20Ble=C3=9Fmann?= Date: Thu, 4 Jul 2024 22:31:53 +0200 Subject: [PATCH 005/786] bless tests --- tests/ui/from_str_radix_10.fixed | 4 ++-- tests/ui/from_str_radix_10.stderr | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/ui/from_str_radix_10.fixed b/tests/ui/from_str_radix_10.fixed index f9ce1defda17c..6c582190b4424 100644 --- a/tests/ui/from_str_radix_10.fixed +++ b/tests/ui/from_str_radix_10.fixed @@ -1,4 +1,3 @@ -#![feature(const_int_from_str)] #![warn(clippy::from_str_radix_10)] mod some_mod { @@ -61,7 +60,8 @@ fn main() -> Result<(), Box> { Ok(()) } -fn issue_12732() { +// https://github.com/rust-lang/rust-clippy/issues/12731 +fn issue_12731() { const A: Result = u32::from_str_radix("123", 10); const B: () = { 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 01a1bf8940a12..4aa84eca26120 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:29:5 + --> tests/ui/from_str_radix_10.rs:28: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:32:5 + --> tests/ui/from_str_radix_10.rs:31: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:34:5 + --> tests/ui/from_str_radix_10.rs:33: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:36:5 + --> tests/ui/from_str_radix_10.rs:35: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:38:5 + --> tests/ui/from_str_radix_10.rs:37: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:40:5 + --> tests/ui/from_str_radix_10.rs:39: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:44:5 + --> tests/ui/from_str_radix_10.rs:43: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:48:5 + --> tests/ui/from_str_radix_10.rs:47:5 | LL | i32::from_str_radix(&stringier, 10)?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `stringier.parse::()` From 322c2f6b1373a71e99e291f2be6f2c9b82890a02 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 16 Apr 2024 18:31:43 +0000 Subject: [PATCH 006/786] Sync ar_archive_writer to LLVM 18.1.3 From LLVM 15.0.0-rc3. This adds support for COFF archives containing Arm64EC object files and has various fixes for AIX big archive files. --- src/archive.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/archive.rs b/src/archive.rs index 414d3db1c51a1..26db93a75795a 100644 --- a/src/archive.rs +++ b/src/archive.rs @@ -1,7 +1,7 @@ use std::path::{Path, PathBuf}; use rustc_codegen_ssa::back::archive::{ - get_native_object_symbols, ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, + ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, DEFAULT_OBJECT_READER, }; use rustc_session::Session; @@ -9,7 +9,7 @@ pub(crate) struct ArArchiveBuilderBuilder; impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder { fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box { - Box::new(ArArchiveBuilder::new(sess, get_native_object_symbols)) + Box::new(ArArchiveBuilder::new(sess, &DEFAULT_OBJECT_READER)) } fn create_dll_import_lib( From 32efd239554dd80d7983e160024e7d4cd6db3439 Mon Sep 17 00:00:00 2001 From: Ana Hobden Date: Mon, 8 Jul 2024 11:40:04 -0700 Subject: [PATCH 007/786] Add target page for riscv64gc-unknown-linux-gnu --- src/doc/rustc/src/platform-support.md | 2 +- .../riscv64gc-unknown-linux-gnu.md | 127 ++++++++++++++++++ 2 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-gnu.md diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index f5cd4bd217a32..0ecaaf5a9aae6 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -97,7 +97,7 @@ target | notes `powerpc-unknown-linux-gnu` | PowerPC Linux (kernel 3.2, glibc 2.17) `powerpc64-unknown-linux-gnu` | PPC64 Linux (kernel 3.2, glibc 2.17) `powerpc64le-unknown-linux-gnu` | PPC64LE Linux (kernel 3.10, glibc 2.17) -`riscv64gc-unknown-linux-gnu` | RISC-V Linux (kernel 4.20, glibc 2.29) +[`riscv64gc-unknown-linux-gnu`](platform-support/riscv64gc-unknown-linux-gnu.md) | RISC-V Linux (kernel 4.20, glibc 2.29) `s390x-unknown-linux-gnu` | S390x Linux (kernel 3.2, glibc 2.17) `x86_64-unknown-freebsd` | 64-bit FreeBSD `x86_64-unknown-illumos` | illumos diff --git a/src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-gnu.md b/src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-gnu.md new file mode 100644 index 0000000000000..21d547f5aaba7 --- /dev/null +++ b/src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-gnu.md @@ -0,0 +1,127 @@ +# `riscv64gc-unknown-linux-gnu` + +**Tier: 2 (with Host Tools)** + +RISC-V targets using the *RV64I* base instruction set with the *G* collection of extensions, as well as the *C* extension. + + +## Target maintainers + +- TODO + + +## Requirements + +This target requires: + +* Linux Kernel version 4.20 or later +* glibc 2.17 or later + + +## Building the target + +These targets are distributed through `rustup`, and otherwise require no +special configuration. + +If you need to build your own Rust for some reason though, the targets can be +enabled in `config.toml`. For example: + +```toml +[build] +target = ["riscv64gc-unknown-linux-gnu"] +``` + + +## Building Rust programs + + +On a RISC-V host, the `riscv64gc-unknown-linux-gnu` target should be automatically +installed and used by default. + +On a non-RISC-V host, add the target: + +```bash +rustup target add riscv64gc-unknown-linux-gnu +``` + +Then cross compile crates with: + +```bash +cargo build --target riscv64gc-unknown-linux-gnu +``` + + +## Testing + +There are no special requirements for testing and running the targets. +For testing cross builds on the host, please refer to the "Cross-compilation +toolchains and C code" +section below. + + +## Cross-compilation toolchains and C code + +A RISC-V toolchain can be obtained for Windows/Mac/Linux from the +[`riscv-gnu-toolchain`](https://github.com/riscv-collab/riscv-gnu-toolchain) +repostory. Binaries are available via +[embecosm](https://www.embecosm.com/resources/tool-chain-downloads/#riscv-linux), +and may also be available from your OS's package manager. + +On Ubuntu, a RISC-V toolchain can be installed with: + +```bash +apt install gcc-riscv64-linux-gnu g++-riscv64-linux-gnu libc6-dev-riscv64-cross +``` + +Depending on your system, you may need to configure the target to use the GNU +GCC linker. To use it, add the following to your `.cargo/config.toml`: + +```toml +[target.riscv64gc-unknown-linux-gnu] +linker = "riscv64-linux-gnu-gcc" +``` + +If your `riscv64-linux-gnu-*` toolchain is not in your `PATH` you may need to +configure additional settings: + +```toml +[target.riscv64gc-unknown-linux-gnu] +# Adjust the paths to point at your toolchain +cc = "/TOOLCHAIN_PATH/bin/riscv64-linux-gnu-gcc" +cxx = "/TOOLCHAIN_PATH/bin/riscv64-linux-gnu-g++" +ar = "/TOOLCHAIN_PATH/bin/riscv64-linux-gnu-ar" +ranlib = "/TOOLCHAIN_PATH/bin/riscv64-linux-gnu-ranlib" +linker = "/TOOLCHAIN_PATH/bin/riscv64-linux-gnu-gcc" +``` + +To test cross compiled binaries on a non-RISCV-V host, you can use +[`qemu`](https://www.qemu.org/docs/master/system/target-riscv.html). +On Ubuntu, a RISC-V emulator can be obtained with: + +```bash +apt install qemu-system-riscv64 +``` + +Then, in `.cargo/config.toml` set the `runner`: + +```toml +[target.riscv64gc-unknown-linux-gnu] +runner = "qemu-riscv64-static -L /usr/riscv64-linux-gnu -cpu rv64" +``` + +On Mac and Linux, it's also possible to use +[`lima`](https://github.com/lima-vm/lima) to emulate RISC-V in a similar way to +how WSL2 works on Windows: + +```bash +limactl start template://riscv +limactl shell riscv +``` + +Using [Docker (with BuildKit)](https://docs.docker.com/build/buildkit/) the +[`riscv64/ubuntu`](https://hub.docker.com/r/riscv64/ubuntu) image can be used +to buiild or run `riscv64gc-unknown-linux-gnu` binaries. + +```bash +docker run --platform linux/riscv64 -ti --rm --mount "type=bind,src=$(pwd),dst=/checkout" riscv64/ubuntu bash +``` From 22364f86aeba440066db931132ecee8292b709fd Mon Sep 17 00:00:00 2001 From: Neven Villani Date: Tue, 9 Jul 2024 14:24:05 +0200 Subject: [PATCH 008/786] This pattern using lazy protected Reserved IM prevents spurious writes --- .../tree_borrows/reservedim_spurious_write.rs | 109 ++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs diff --git a/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs new file mode 100644 index 0000000000000..1f52537f9a295 --- /dev/null +++ b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs @@ -0,0 +1,109 @@ +// Illustrating a problematic interaction between Reserved, interior mutability, +// and protectors, that makes spurious writes fail in the previous model of Tree Borrows. +// As for all similar tests, we disable preemption so that the error message is deterministic. +//@compile-flags: -Zmiri-tree-borrows -Zmiri-preemption-rate=0 + +use std::cell::Cell; +use std::sync::{Arc, Barrier}; +use std::thread; + +// Here is the problematic interleaving: +// - thread 1: retag and activate `x` (protected) +// - thread 2: create but do not retag (lazy) `y` as Reserved with interior mutability +// - thread 1: spurious write through `x` would go here +// - thread 2: function exit (noop due to lazyness) +// - thread 1: function exit (no permanent effect on `y` because it is now Reserved IM unprotected) +// - thread 2: write through `y` +// In the source code nothing happens to `y` + +// `Send`able raw pointer wrapper. +#[derive(Copy, Clone)] +struct SendPtr(*mut u8); +unsafe impl Send for SendPtr {} + +type IdxBarrier = (usize, Arc); + +// Barriers to enforce the interleaving. +// This macro expects `synchronized!(thread, msg)` where `thread` is a `IdxBarrier`, +// and `msg` is the message to be displayed when the thread reaches this point in the execution. +macro_rules! synchronized { + ($thread:expr, $msg:expr) => {{ + let (thread_id, barrier) = &$thread; + eprintln!("Thread {} executing: {}", thread_id, $msg); + barrier.wait(); + }}; +} + +fn main() { + eprintln!("Without spurious write"); + example(false); + + eprintln!("\nIf this text is visible then the model forbids spurious writes.\n"); + + eprintln!("With spurious write"); + example(true); + + eprintln!("\nIf this text is visible then the model fails to detect a noalias violation.\n"); +} + +fn example(spurious: bool) { + // For this example it is important that we have at least two bytes + // because lazyness is involved. + let mut data = [0u8; 2]; + let ptr = SendPtr(std::ptr::addr_of_mut!(data[0])); + let barrier = Arc::new(Barrier::new(2)); + let bx = Arc::clone(&barrier); + let by = Arc::clone(&barrier); + + // Retag and activate `x`, wait until the other thread creates a lazy permission. + // Then do a spurious write. Finally exit the function after the other thread. + let thread_1 = thread::spawn(move || { + let b = (1, bx); + synchronized!(b, "start"); + let ptr = ptr; + synchronized!(b, "retag x (&mut, protect)"); + fn inner(x: &mut u8, b: IdxBarrier, spurious: bool) { + *x = 42; // activate immediately + synchronized!(b, "[lazy] retag y (&mut, protect, IM)"); + // A spurious write should be valid here because `x` is + // `Active` and protected. + if spurious { + synchronized!(b, "spurious write x (executed)"); + *x = 64; + } else { + synchronized!(b, "spurious write x (skipped)"); + } + synchronized!(b, "ret y"); + synchronized!(b, "ret x"); + } + inner(unsafe { &mut *ptr.0 }, b.clone(), spurious); + synchronized!(b, "write y"); + synchronized!(b, "end"); + }); + + // Create a lazy Reserved with interior mutability. + // Wait for the other thread's spurious write then observe the side effects + // of that write. + let thread_2 = thread::spawn(move || { + let b = (2, by); + synchronized!(b, "start"); + let ptr = ptr; + synchronized!(b, "retag x (&mut, protect)"); + synchronized!(b, "[lazy] retag y (&mut, protect, IM)"); + fn inner(y: &mut Cell, b: IdxBarrier) -> *mut u8 { + synchronized!(b, "spurious write x"); + synchronized!(b, "ret y"); + y as *mut Cell as *mut u8 + } + // Currently `ptr` points to `data[0]`. We retag it for `data[1]` + // then use it for `data[0]` where its initialization has been deferred. + let y = inner(unsafe { &mut *(ptr.0 as *mut Cell).wrapping_add(1) }, b.clone()); + synchronized!(b, "ret x"); + synchronized!(b, "write y"); + unsafe { *y.wrapping_sub(1) = 13 } + synchronized!(b, "end"); + }); + + thread_1.join().unwrap(); + thread_2.join().unwrap(); +} From 2de6e7f3a680a8000f83f2b62252d18a1bb06966 Mon Sep 17 00:00:00 2001 From: Neven Villani Date: Tue, 9 Jul 2024 14:36:46 +0200 Subject: [PATCH 009/786] Implement fix for reservedim_spurious_write: ignore IM on protected --- .../src/borrow_tracker/tree_borrows/mod.rs | 10 ++++- .../src/borrow_tracker/tree_borrows/perms.rs | 5 +++ .../reserved/cell-protected-write.stderr | 6 +-- .../tree_borrows/reservedim_spurious_write.rs | 2 +- .../reservedim_spurious_write.stderr | 41 +++++++++++++++++++ .../tests/pass/tree_borrows/reserved.stderr | 2 +- 6 files changed, 59 insertions(+), 7 deletions(-) create mode 100644 src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.stderr diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs index 86074384084d5..4d9595b352f28 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -141,8 +141,14 @@ impl<'tcx> NewPermission { ) -> Option { let ty_is_freeze = pointee.is_freeze(*cx.tcx, cx.param_env()); let ty_is_unpin = pointee.is_unpin(*cx.tcx, cx.param_env()); + let is_protected = kind == RetagKind::FnEntry; + // As demonstrated by `tests/fail/tree_borrows/reservedim_spurious_write.rs`, + // interior mutability and protectors interact poorly. + // To eliminate the case of Protected Reserved IM we override interior mutability + // in the case of a protected reference. let initial_state = match mutability { - Mutability::Mut if ty_is_unpin => Permission::new_reserved(ty_is_freeze), + Mutability::Mut if ty_is_unpin => + Permission::new_reserved(ty_is_freeze || is_protected), Mutability::Not if ty_is_freeze => Permission::new_frozen(), // Raw pointers never enter this function so they are not handled. // However raw pointers are not the only pointers that take the parent @@ -151,7 +157,7 @@ impl<'tcx> NewPermission { _ => return None, }; - let protector = (kind == RetagKind::FnEntry).then_some(ProtectorKind::StrongProtector); + let protector = is_protected.then_some(ProtectorKind::StrongProtector); Some(Self { zero_size: false, initial_state, protector }) } diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs index 7aa9c3e862bcc..9c19ae76a2d01 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs @@ -22,6 +22,11 @@ enum PermissionPriv { /// - foreign-read then child-write is UB due to `conflicted`, /// - child-write then foreign-read is UB since child-write will activate and then /// foreign-read disables a protected `Active`, which is UB. + /// + /// Note: since the discovery of `tests/fail/tree_borrows/reservedim_spurious_write.rs`, + /// `ty_is_freeze` does not strictly mean that the type has no interior mutability, + /// it could be an interior mutable type that lost its interior mutability privileges + /// when retagged with a protector. Reserved { ty_is_freeze: bool, conflicted: bool }, /// represents: a unique pointer; /// allows: child reads, child writes; diff --git a/src/tools/miri/tests/fail/tree_borrows/reserved/cell-protected-write.stderr b/src/tools/miri/tests/fail/tree_borrows/reserved/cell-protected-write.stderr index 7d000ba55e60b..ce9a5b7f15865 100644 --- a/src/tools/miri/tests/fail/tree_borrows/reserved/cell-protected-write.stderr +++ b/src/tools/miri/tests/fail/tree_borrows/reserved/cell-protected-write.stderr @@ -5,7 +5,7 @@ Warning: this tree is indicative only. Some tags may have been hidden. | RsM | └─┬── | RsM | ├─┬── | RsM | │ └─┬── -| RsM | │ └──── Strongly protected +| Rs | │ └──── Strongly protected | RsM | └──── ────────────────────────────────────────────────── error: Undefined Behavior: write access through (y, callee:y, caller:y) at ALLOC[0x0] is forbidden @@ -16,14 +16,14 @@ LL | *y = 1; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental = help: the accessed tag (y, callee:y, caller:y) is foreign to the protected tag (callee:x) (i.e., it is not a child) - = help: this foreign write access would cause the protected tag (callee:x) (currently Reserved (interior mutable)) to become Disabled + = help: this foreign write access would cause the protected tag (callee:x) (currently Reserved) to become Disabled = help: protected tags must never be Disabled help: the accessed tag was created here --> $DIR/cell-protected-write.rs:LL:CC | LL | let y = (&mut *n).get(); | ^^^^^^^^^ -help: the protected tag was created here, in the initial state Reserved (interior mutable) +help: the protected tag was created here, in the initial state Reserved --> $DIR/cell-protected-write.rs:LL:CC | LL | unsafe fn write_second(x: &mut UnsafeCell, y: *mut u8) { diff --git a/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs index 1f52537f9a295..5e7cb5e34cc2b 100644 --- a/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs +++ b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs @@ -100,7 +100,7 @@ fn example(spurious: bool) { let y = inner(unsafe { &mut *(ptr.0 as *mut Cell).wrapping_add(1) }, b.clone()); synchronized!(b, "ret x"); synchronized!(b, "write y"); - unsafe { *y.wrapping_sub(1) = 13 } + unsafe { *y.wrapping_sub(1) = 13 } //~ERROR: /write access through .* is forbidden/ synchronized!(b, "end"); }); diff --git a/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.stderr b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.stderr new file mode 100644 index 0000000000000..9be6c157c0cbb --- /dev/null +++ b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.stderr @@ -0,0 +1,41 @@ +Without spurious write +Thread 1 executing: start +Thread 2 executing: start +Thread 2 executing: retag x (&mut, protect) +Thread 1 executing: retag x (&mut, protect) +Thread 1 executing: [lazy] retag y (&mut, protect, IM) +Thread 2 executing: [lazy] retag y (&mut, protect, IM) +Thread 2 executing: spurious write x +Thread 1 executing: spurious write x (skipped) +Thread 1 executing: ret y +Thread 2 executing: ret y +Thread 2 executing: ret x +Thread 1 executing: ret x +Thread 1 executing: write y +Thread 2 executing: write y +error: Undefined Behavior: write access through at ALLOC[0x0] is forbidden + --> $DIR/reservedim_spurious_write.rs:LL:CC + | +LL | unsafe { *y.wrapping_sub(1) = 13 } + | ^^^^^^^^^^^^^^^^^^^^^^^ write access through at ALLOC[0x0] is forbidden + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental + = help: the accessed tag has state Disabled which forbids this child write access +help: the accessed tag was created here, in the initial state Reserved + --> $DIR/reservedim_spurious_write.rs:LL:CC + | +LL | fn inner(y: &mut Cell, b: IdxBarrier) -> *mut u8 { + | ^ +help: the accessed tag later transitioned to Disabled due to a protector release (acting as a foreign write access) on every location previously accessed by this tag + --> $DIR/reservedim_spurious_write.rs:LL:CC + | +LL | } + | ^ + = help: this transition corresponds to a loss of read and write permissions + = note: BACKTRACE (of the first span) on thread `unnamed-ID`: + = note: inside closure at $DIR/reservedim_spurious_write.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/pass/tree_borrows/reserved.stderr b/src/tools/miri/tests/pass/tree_borrows/reserved.stderr index 0d0d52c717fed..d149a4065f92b 100644 --- a/src/tools/miri/tests/pass/tree_borrows/reserved.stderr +++ b/src/tools/miri/tests/pass/tree_borrows/reserved.stderr @@ -6,7 +6,7 @@ Warning: this tree is indicative only. Some tags may have been hidden. | RsM | └─┬── | RsM | ├─┬── | RsM | │ └─┬── -| RsCM| │ └──── +| RsC | │ └──── | RsM | └──── ────────────────────────────────────────────────── [interior mut] Foreign Read: Re* -> Re* From 22996ad073870c5ac7753ba1acbaba784adc534d Mon Sep 17 00:00:00 2001 From: Neven Villani Date: Tue, 9 Jul 2024 19:42:12 +0200 Subject: [PATCH 010/786] Apply suggestions - split test into two revisions - clarify comments --- .../src/borrow_tracker/tree_borrows/mod.rs | 3 +- .../tree_borrows/reservedim_spurious_write.rs | 26 +++++------- .../reservedim_spurious_write.with.stderr | 40 +++++++++++++++++++ ... reservedim_spurious_write.without.stderr} | 1 - 4 files changed, 52 insertions(+), 18 deletions(-) create mode 100644 src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.with.stderr rename src/tools/miri/tests/fail/tree_borrows/{reservedim_spurious_write.stderr => reservedim_spurious_write.without.stderr} (98%) diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs index 4d9595b352f28..123d4b407fb4c 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -145,7 +145,8 @@ impl<'tcx> NewPermission { // As demonstrated by `tests/fail/tree_borrows/reservedim_spurious_write.rs`, // interior mutability and protectors interact poorly. // To eliminate the case of Protected Reserved IM we override interior mutability - // in the case of a protected reference. + // in the case of a protected reference: protected references are always considered + // "freeze". let initial_state = match mutability { Mutability::Mut if ty_is_unpin => Permission::new_reserved(ty_is_freeze || is_protected), diff --git a/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs index 5e7cb5e34cc2b..611f64dce5e50 100644 --- a/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs +++ b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs @@ -2,6 +2,12 @@ // and protectors, that makes spurious writes fail in the previous model of Tree Borrows. // As for all similar tests, we disable preemption so that the error message is deterministic. //@compile-flags: -Zmiri-tree-borrows -Zmiri-preemption-rate=0 +// +// One revision without spurious read (default source code) and one with spurious read. +// Both are expected to be UB. Both revisions are expected to have the *same* error +// because we are aligning the behavior of `without` to that of `with` so that the +// spurious write is effectively a noop in the long term. +//@revisions: without with use std::cell::Cell; use std::sync::{Arc, Barrier}; @@ -9,7 +15,7 @@ use std::thread; // Here is the problematic interleaving: // - thread 1: retag and activate `x` (protected) -// - thread 2: create but do not retag (lazy) `y` as Reserved with interior mutability +// - thread 2: retag but do not initialize (lazy) `y` as Reserved with interior mutability // - thread 1: spurious write through `x` would go here // - thread 2: function exit (noop due to lazyness) // - thread 1: function exit (no permanent effect on `y` because it is now Reserved IM unprotected) @@ -35,18 +41,6 @@ macro_rules! synchronized { } fn main() { - eprintln!("Without spurious write"); - example(false); - - eprintln!("\nIf this text is visible then the model forbids spurious writes.\n"); - - eprintln!("With spurious write"); - example(true); - - eprintln!("\nIf this text is visible then the model fails to detect a noalias violation.\n"); -} - -fn example(spurious: bool) { // For this example it is important that we have at least two bytes // because lazyness is involved. let mut data = [0u8; 2]; @@ -62,12 +56,12 @@ fn example(spurious: bool) { synchronized!(b, "start"); let ptr = ptr; synchronized!(b, "retag x (&mut, protect)"); - fn inner(x: &mut u8, b: IdxBarrier, spurious: bool) { + fn inner(x: &mut u8, b: IdxBarrier) { *x = 42; // activate immediately synchronized!(b, "[lazy] retag y (&mut, protect, IM)"); // A spurious write should be valid here because `x` is // `Active` and protected. - if spurious { + if cfg!(with) { synchronized!(b, "spurious write x (executed)"); *x = 64; } else { @@ -76,7 +70,7 @@ fn example(spurious: bool) { synchronized!(b, "ret y"); synchronized!(b, "ret x"); } - inner(unsafe { &mut *ptr.0 }, b.clone(), spurious); + inner(unsafe { &mut *ptr.0 }, b.clone()); synchronized!(b, "write y"); synchronized!(b, "end"); }); diff --git a/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.with.stderr b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.with.stderr new file mode 100644 index 0000000000000..5ac9c912ba9ee --- /dev/null +++ b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.with.stderr @@ -0,0 +1,40 @@ +Thread 1 executing: start +Thread 2 executing: start +Thread 2 executing: retag x (&mut, protect) +Thread 1 executing: retag x (&mut, protect) +Thread 1 executing: [lazy] retag y (&mut, protect, IM) +Thread 2 executing: [lazy] retag y (&mut, protect, IM) +Thread 2 executing: spurious write x +Thread 1 executing: spurious write x (executed) +Thread 1 executing: ret y +Thread 2 executing: ret y +Thread 2 executing: ret x +Thread 1 executing: ret x +Thread 1 executing: write y +Thread 2 executing: write y +error: Undefined Behavior: write access through at ALLOC[0x0] is forbidden + --> $DIR/reservedim_spurious_write.rs:LL:CC + | +LL | unsafe { *y.wrapping_sub(1) = 13 } + | ^^^^^^^^^^^^^^^^^^^^^^^ write access through at ALLOC[0x0] is forbidden + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental + = help: the accessed tag has state Disabled which forbids this child write access +help: the accessed tag was created here, in the initial state Reserved + --> $DIR/reservedim_spurious_write.rs:LL:CC + | +LL | fn inner(y: &mut Cell, b: IdxBarrier) -> *mut u8 { + | ^ +help: the accessed tag later transitioned to Disabled due to a foreign write access at offsets [0x0..0x1] + --> $DIR/reservedim_spurious_write.rs:LL:CC + | +LL | *x = 64; + | ^^^^^^^ + = help: this transition corresponds to a loss of read and write permissions + = note: BACKTRACE (of the first span) on thread `unnamed-ID`: + = note: inside closure at $DIR/reservedim_spurious_write.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.stderr b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.without.stderr similarity index 98% rename from src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.stderr rename to src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.without.stderr index 9be6c157c0cbb..97c71fdedefb3 100644 --- a/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.stderr +++ b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.without.stderr @@ -1,4 +1,3 @@ -Without spurious write Thread 1 executing: start Thread 2 executing: start Thread 2 executing: retag x (&mut, protect) From 68aed4a5cebf846d88716489e4ea66074d669c5b Mon Sep 17 00:00:00 2001 From: Neven Villani Date: Wed, 10 Jul 2024 14:32:02 +0200 Subject: [PATCH 011/786] Second byte is not involved in the example; use a Cell<()> instead --- .../tree_borrows/reservedim_spurious_write.rs | 23 +++++++++++-------- .../reservedim_spurious_write.with.stderr | 6 ++--- .../reservedim_spurious_write.without.stderr | 6 ++--- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs index 611f64dce5e50..6ae79be6cc7e8 100644 --- a/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs +++ b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs @@ -41,10 +41,10 @@ macro_rules! synchronized { } fn main() { - // For this example it is important that we have at least two bytes - // because lazyness is involved. - let mut data = [0u8; 2]; - let ptr = SendPtr(std::ptr::addr_of_mut!(data[0])); + // The conflict occurs one one single location but the example involves + // lazily initialized permissions. + let mut data = 0u8; + let ptr = SendPtr(std::ptr::addr_of_mut!(data)); let barrier = Arc::new(Barrier::new(2)); let bx = Arc::clone(&barrier); let by = Arc::clone(&barrier); @@ -84,17 +84,20 @@ fn main() { let ptr = ptr; synchronized!(b, "retag x (&mut, protect)"); synchronized!(b, "[lazy] retag y (&mut, protect, IM)"); - fn inner(y: &mut Cell, b: IdxBarrier) -> *mut u8 { + fn inner(y: &mut Cell<()>, b: IdxBarrier) -> *mut u8 { synchronized!(b, "spurious write x"); synchronized!(b, "ret y"); - y as *mut Cell as *mut u8 + // `y` is not retagged for any bytes, so the pointer we return + // has its permission lazily initialized. + y as *mut Cell<()> as *mut u8 } - // Currently `ptr` points to `data[0]`. We retag it for `data[1]` - // then use it for `data[0]` where its initialization has been deferred. - let y = inner(unsafe { &mut *(ptr.0 as *mut Cell).wrapping_add(1) }, b.clone()); + // Currently `ptr` points to `data`. + // We do a zero-sized retag so that its permission is lazy. + let y_zst = unsafe { &mut *(ptr.0 as *mut Cell<()>) }; + let y = inner(y_zst, b.clone()); synchronized!(b, "ret x"); synchronized!(b, "write y"); - unsafe { *y.wrapping_sub(1) = 13 } //~ERROR: /write access through .* is forbidden/ + unsafe { *y = 13 } //~ERROR: /write access through .* is forbidden/ synchronized!(b, "end"); }); diff --git a/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.with.stderr b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.with.stderr index 5ac9c912ba9ee..0e4517e90105c 100644 --- a/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.with.stderr +++ b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.with.stderr @@ -15,15 +15,15 @@ Thread 2 executing: write y error: Undefined Behavior: write access through at ALLOC[0x0] is forbidden --> $DIR/reservedim_spurious_write.rs:LL:CC | -LL | unsafe { *y.wrapping_sub(1) = 13 } - | ^^^^^^^^^^^^^^^^^^^^^^^ write access through at ALLOC[0x0] is forbidden +LL | unsafe { *y = 13 } + | ^^^^^^^ write access through at ALLOC[0x0] is forbidden | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental = help: the accessed tag has state Disabled which forbids this child write access help: the accessed tag was created here, in the initial state Reserved --> $DIR/reservedim_spurious_write.rs:LL:CC | -LL | fn inner(y: &mut Cell, b: IdxBarrier) -> *mut u8 { +LL | fn inner(y: &mut Cell<()>, b: IdxBarrier) -> *mut u8 { | ^ help: the accessed tag later transitioned to Disabled due to a foreign write access at offsets [0x0..0x1] --> $DIR/reservedim_spurious_write.rs:LL:CC diff --git a/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.without.stderr b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.without.stderr index 97c71fdedefb3..cbeef90243bfb 100644 --- a/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.without.stderr +++ b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.without.stderr @@ -15,15 +15,15 @@ Thread 2 executing: write y error: Undefined Behavior: write access through at ALLOC[0x0] is forbidden --> $DIR/reservedim_spurious_write.rs:LL:CC | -LL | unsafe { *y.wrapping_sub(1) = 13 } - | ^^^^^^^^^^^^^^^^^^^^^^^ write access through at ALLOC[0x0] is forbidden +LL | unsafe { *y = 13 } + | ^^^^^^^ write access through at ALLOC[0x0] is forbidden | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental = help: the accessed tag has state Disabled which forbids this child write access help: the accessed tag was created here, in the initial state Reserved --> $DIR/reservedim_spurious_write.rs:LL:CC | -LL | fn inner(y: &mut Cell, b: IdxBarrier) -> *mut u8 { +LL | fn inner(y: &mut Cell<()>, b: IdxBarrier) -> *mut u8 { | ^ help: the accessed tag later transitioned to Disabled due to a protector release (acting as a foreign write access) on every location previously accessed by this tag --> $DIR/reservedim_spurious_write.rs:LL:CC From fe0bd76a8bdb80f4460dd59612076cf91370f7a1 Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 10 Jul 2024 16:03:20 +0200 Subject: [PATCH 012/786] elaborate unknowable goals if a trait is unknowable, but its super trait is definitely not implemented, then the trait itself is definitely also not implemented. --- .../src/solve/assembly/mod.rs | 12 +++++++ compiler/rustc_type_ir/src/inherent.rs | 1 + .../normalize-for-errors.next.stderr | 1 + tests/ui/coherence/normalize-for-errors.rs | 1 + .../super-trait-knowable-1.current.stderr | 13 ++++++++ .../super-traits/super-trait-knowable-1.rs | 19 +++++++++++ .../super-traits/super-trait-knowable-2.rs | 33 +++++++++++++++++++ .../super-trait-knowable-3.current.stderr | 13 ++++++++ .../super-traits/super-trait-knowable-3.rs | 22 +++++++++++++ ...8728.stderr => issue-48728.current.stderr} | 2 +- tests/ui/issues/issue-48728.rs | 7 +++- 11 files changed, 122 insertions(+), 2 deletions(-) create mode 100644 tests/ui/coherence/super-traits/super-trait-knowable-1.current.stderr create mode 100644 tests/ui/coherence/super-traits/super-trait-knowable-1.rs create mode 100644 tests/ui/coherence/super-traits/super-trait-knowable-2.rs create mode 100644 tests/ui/coherence/super-traits/super-trait-knowable-3.current.stderr create mode 100644 tests/ui/coherence/super-traits/super-trait-knowable-3.rs rename tests/ui/issues/{issue-48728.stderr => issue-48728.current.stderr} (95%) diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index 01dde9ca587ca..4e1a3558a9c1e 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -699,6 +699,18 @@ where if ecx.trait_ref_is_knowable(goal.param_env, trait_ref)? { Err(NoSolution) } else { + // While the trait bound itself may be unknowable, we may be able to + // prove that a super trait is not implemented. For this, we recursively + // prove the super trait bounds of the current goal. + // + // We skip the goal itself as that one would cycle. + let predicate: I::Predicate = trait_ref.upcast(cx); + ecx.add_goals( + GoalSource::Misc, + elaborate::elaborate(cx, [predicate]) + .skip(1) + .map(|predicate| goal.with(cx, predicate)), + ); ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) } }, diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index de86a8536f7af..2b6ccc8e430b5 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -433,6 +433,7 @@ pub trait Predicate>: + UpcastFrom> + UpcastFrom> + IntoKind>> + + Elaboratable { fn as_clause(self) -> Option; diff --git a/tests/ui/coherence/normalize-for-errors.next.stderr b/tests/ui/coherence/normalize-for-errors.next.stderr index 6c56a9177414b..634a10b7a14c3 100644 --- a/tests/ui/coherence/normalize-for-errors.next.stderr +++ b/tests/ui/coherence/normalize-for-errors.next.stderr @@ -7,6 +7,7 @@ LL | LL | impl MyTrait for (Box<<(MyType,) as Mirror>::Assoc>, S::Item) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(Box<(MyType,)>, <_ as Iterator>::Item)` | + = note: upstream crates may add a new impl of trait `std::clone::Clone` for type `(MyType,)` in future versions = note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions error: aborting due to 1 previous error diff --git a/tests/ui/coherence/normalize-for-errors.rs b/tests/ui/coherence/normalize-for-errors.rs index 2288118676ab3..4188389a3ad5b 100644 --- a/tests/ui/coherence/normalize-for-errors.rs +++ b/tests/ui/coherence/normalize-for-errors.rs @@ -18,5 +18,6 @@ impl MyTrait for (Box<<(MyType,) as Mirror>::Assoc>, S::Item) {} //~^ ERROR conflicting implementations of trait `MyTrait<_>` for type `(Box<(MyType,)>, //~| NOTE conflicting implementation for `(Box<(MyType,)>, //~| NOTE upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions +//[next]~| NOTE upstream crates may add a new impl of trait `std::clone::Clone` for type `(MyType,)` in future versions fn main() {} diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-1.current.stderr b/tests/ui/coherence/super-traits/super-trait-knowable-1.current.stderr new file mode 100644 index 0000000000000..fb01cf158d980 --- /dev/null +++ b/tests/ui/coherence/super-traits/super-trait-knowable-1.current.stderr @@ -0,0 +1,13 @@ +error[E0119]: conflicting implementations of trait `Overlap<_>` for type `()` + --> $DIR/super-trait-knowable-1.rs:16:1 + | +LL | impl> Overlap for U {} + | ----------------------------------- first implementation here +LL | impl Overlap for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` + | + = note: downstream crates may implement trait `Sub<_>` for type `()` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-1.rs b/tests/ui/coherence/super-traits/super-trait-knowable-1.rs new file mode 100644 index 0000000000000..80df8c19ee51f --- /dev/null +++ b/tests/ui/coherence/super-traits/super-trait-knowable-1.rs @@ -0,0 +1,19 @@ +// Added in #124532. While `(): Super` is knowable, `(): Sub` is not. +// +// We therefore elaborate super trait bounds in the implicit negative +// overlap check. + +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] check-pass + +trait Super {} +trait Sub: Super {} + +trait Overlap {} +impl> Overlap for U {} +impl Overlap for () {} +//[current]~^ ERROR conflicting implementations + +fn main() {} diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-2.rs b/tests/ui/coherence/super-traits/super-trait-knowable-2.rs new file mode 100644 index 0000000000000..d1f2e8d1c1a15 --- /dev/null +++ b/tests/ui/coherence/super-traits/super-trait-knowable-2.rs @@ -0,0 +1,33 @@ +// A regression test for pyella-0.1.5 which broke when +// enabling the new solver in coherence. +// +// `Tensor: TensorValue` is knowable while `Tensor: TensorOp` +// may be implemented downstream. We previously didn't check the +// super trait bound in coherence, causing these impls to overlap. +// +// However, we did fail to normalize ` {} +pub trait TensorOp: TensorValue {} + +pub struct Tensor; +impl TensorCompare for Tensor {} +impl TensorCompare for T1 +where + T1: TensorOp, + T1::Unmasked: Sized, +{} + + +fn main() {} diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-3.current.stderr b/tests/ui/coherence/super-traits/super-trait-knowable-3.current.stderr new file mode 100644 index 0000000000000..542edb8b7f674 --- /dev/null +++ b/tests/ui/coherence/super-traits/super-trait-knowable-3.current.stderr @@ -0,0 +1,13 @@ +error[E0119]: conflicting implementations of trait `Overlap<_>` for type `()` + --> $DIR/super-trait-knowable-3.rs:19:1 + | +LL | impl>> Overlap for U {} + | ---------------------------------------- first implementation here +LL | impl Overlap for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` + | + = note: downstream crates may implement trait `Sub<_>` for type `()` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-3.rs b/tests/ui/coherence/super-traits/super-trait-knowable-3.rs new file mode 100644 index 0000000000000..295d7ac48d8cc --- /dev/null +++ b/tests/ui/coherence/super-traits/super-trait-knowable-3.rs @@ -0,0 +1,22 @@ +// Unlike in `super-trait-knowable-1.rs`, the knowable +// super trait bound is in a nested goal so this would not +// compile if we were to only elaborate root goals. + +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] check-pass + +trait Super {} +trait Sub: Super {} + +struct W(T); +trait Bound {} +impl, U> Bound> for T {} + +trait Overlap {} +impl>> Overlap for U {} +impl Overlap for () {} +//[current]~^ ERROR conflicting implementations of trait `Overlap<_>` for type `()` + +fn main() {} diff --git a/tests/ui/issues/issue-48728.stderr b/tests/ui/issues/issue-48728.current.stderr similarity index 95% rename from tests/ui/issues/issue-48728.stderr rename to tests/ui/issues/issue-48728.current.stderr index 6b4247f1d7965..2a1b4ff781854 100644 --- a/tests/ui/issues/issue-48728.stderr +++ b/tests/ui/issues/issue-48728.current.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Clone` for type `Node<[_]>` - --> $DIR/issue-48728.rs:4:10 + --> $DIR/issue-48728.rs:9:10 | LL | #[derive(Clone)] | ^^^^^ conflicting implementation for `Node<[_]>` diff --git a/tests/ui/issues/issue-48728.rs b/tests/ui/issues/issue-48728.rs index cbdc10bd2e1ea..7ef05f4277b27 100644 --- a/tests/ui/issues/issue-48728.rs +++ b/tests/ui/issues/issue-48728.rs @@ -1,7 +1,12 @@ // Regression test for #48728, an ICE that occurred computing // coherence "help" information. -#[derive(Clone)] //~ ERROR conflicting implementations of trait `Clone` +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] check-pass + +#[derive(Clone)] //[current]~ ERROR conflicting implementations of trait `Clone` struct Node(Box); impl Clone for Node<[T]> { From 0d49862998b3695297dffba21c80b35fb73e245d Mon Sep 17 00:00:00 2001 From: Zachary S Date: Wed, 10 Jul 2024 13:05:03 -0500 Subject: [PATCH 013/786] Clarify/add `must_use` messages for more `into_raw*` functions of `alloc` types. --- library/alloc/src/boxed.rs | 2 ++ library/alloc/src/rc.rs | 2 ++ library/alloc/src/string.rs | 2 +- library/alloc/src/vec/mod.rs | 2 ++ 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 65bcb241e4aec..21fd8d24af3d7 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -1097,6 +1097,7 @@ impl Box { /// ``` /// /// [memory layout]: self#memory-layout + #[must_use = "losing the pointer will leak memory"] #[stable(feature = "box_raw", since = "1.4.0")] #[inline] pub fn into_raw(b: Self) -> *mut T { @@ -1150,6 +1151,7 @@ impl Box { /// ``` /// /// [memory layout]: self#memory-layout + #[must_use = "losing the pointer will leak memory"] #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub fn into_raw_with_allocator(b: Self) -> (*mut T, A) { diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 3745ecb48c18e..af3ace96d9c29 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1372,6 +1372,7 @@ impl Rc { /// let x = unsafe { Rc::from_raw_in(ptr, alloc) }; /// assert_eq!(&*x, "hello"); /// ``` + #[must_use = "losing the pointer will leak memory"] #[unstable(feature = "allocator_api", issue = "32838")] pub fn into_raw_with_allocator(this: Self) -> (*const T, A) { let this = mem::ManuallyDrop::new(this); @@ -3100,6 +3101,7 @@ impl Weak { /// /// [`from_raw_in`]: Weak::from_raw_in /// [`as_ptr`]: Weak::as_ptr + #[must_use = "losing the pointer will leak memory"] #[inline] #[unstable(feature = "allocator_api", issue = "32838")] pub fn into_raw_with_allocator(self) -> (*const T, A) { diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 36078da7c35a6..ede2a42d12fe5 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -903,7 +903,7 @@ impl String { /// let rebuilt = unsafe { String::from_raw_parts(ptr, len, cap) }; /// assert_eq!(rebuilt, "hello"); /// ``` - #[must_use = "`self` will be dropped if the result is not used"] + #[must_use = "losing the pointer will leak memory"] #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")] pub fn into_raw_parts(self) -> (*mut u8, usize, usize) { self.vec.into_raw_parts() diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 6e9b017ad75cf..b01ccb3848341 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -879,6 +879,7 @@ impl Vec { /// }; /// assert_eq!(rebuilt, [4294967295, 0, 1]); /// ``` + #[must_use = "losing the pointer will leak memory"] #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")] pub fn into_raw_parts(self) -> (*mut T, usize, usize) { let mut me = ManuallyDrop::new(self); @@ -922,6 +923,7 @@ impl Vec { /// }; /// assert_eq!(rebuilt, [4294967295, 0, 1]); /// ``` + #[must_use = "losing the pointer will leak memory"] #[unstable(feature = "allocator_api", issue = "32838")] // #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")] pub fn into_raw_parts_with_alloc(self) -> (*mut T, usize, usize, A) { From 6d477d3a9de714d877a9eda48b0eda3e12e301be Mon Sep 17 00:00:00 2001 From: Zachary S Date: Wed, 10 Jul 2024 13:08:24 -0500 Subject: [PATCH 014/786] Add `must_use` to IntoRawFd/IntoRawSocket/IntoRawHandle's methods. --- library/std/src/os/fd/raw.rs | 1 + library/std/src/os/solid/io.rs | 1 + library/std/src/os/windows/io/raw.rs | 2 ++ 3 files changed, 4 insertions(+) diff --git a/library/std/src/os/fd/raw.rs b/library/std/src/os/fd/raw.rs index ef896ea95c9c9..9d6fcaa3634d8 100644 --- a/library/std/src/os/fd/raw.rs +++ b/library/std/src/os/fd/raw.rs @@ -138,6 +138,7 @@ pub trait IntoRawFd { /// let raw_fd: RawFd = f.into_raw_fd(); /// # Ok::<(), io::Error>(()) /// ``` + #[must_use = "losing the raw file descriptor may leak resources"] #[stable(feature = "into_raw_os", since = "1.4.0")] fn into_raw_fd(self) -> RawFd; } diff --git a/library/std/src/os/solid/io.rs b/library/std/src/os/solid/io.rs index 19b4fe22093c3..13d8419830df1 100644 --- a/library/std/src/os/solid/io.rs +++ b/library/std/src/os/solid/io.rs @@ -347,6 +347,7 @@ pub trait IntoRawFd { /// This function **transfers ownership** of the underlying file descriptor /// to the caller. Callers are then the unique owners of the file descriptor /// and must close the descriptor once it's no longer needed. + #[must_use = "losing the raw file descriptor may leak resources"] fn into_raw_fd(self) -> RawFd; } diff --git a/library/std/src/os/windows/io/raw.rs b/library/std/src/os/windows/io/raw.rs index 770583a9ce3e0..e76650be742a6 100644 --- a/library/std/src/os/windows/io/raw.rs +++ b/library/std/src/os/windows/io/raw.rs @@ -89,6 +89,7 @@ pub trait IntoRawHandle { /// However, transferring ownership is not strictly required. Use a /// `Into::into` implementation for an API which strictly /// transfers ownership. + #[must_use = "losing the raw handle may leak resources"] #[stable(feature = "into_raw_os", since = "1.4.0")] fn into_raw_handle(self) -> RawHandle; } @@ -230,6 +231,7 @@ pub trait IntoRawSocket { /// However, transferring ownership is not strictly required. Use a /// `Into::into` implementation for an API which strictly /// transfers ownership. + #[must_use = "losing the raw socket may leak resources"] #[stable(feature = "into_raw_os", since = "1.4.0")] fn into_raw_socket(self) -> RawSocket; } From 5f3a6e1805dc59417fbc79734b97f4dc532d4484 Mon Sep 17 00:00:00 2001 From: Urgau Date: Tue, 20 Feb 2024 22:19:26 +0100 Subject: [PATCH 015/786] Remove unary neg from `clippy::precedence` lint --- clippy_lints/src/precedence.rs | 56 +-------------------------------- tests/ui/precedence.fixed | 34 -------------------- tests/ui/precedence.rs | 34 -------------------- tests/ui/precedence.stderr | 32 +------------------ tests/ui/unnecessary_cast.fixed | 2 +- tests/ui/unnecessary_cast.rs | 2 +- 6 files changed, 4 insertions(+), 156 deletions(-) diff --git a/clippy_lints/src/precedence.rs b/clippy_lints/src/precedence.rs index ff83725da6913..37f5dd5583bfb 100644 --- a/clippy_lints/src/precedence.rs +++ b/clippy_lints/src/precedence.rs @@ -1,38 +1,17 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; -use rustc_ast::ast::{BinOpKind, Expr, ExprKind, MethodCall, UnOp}; -use rustc_ast::token; +use rustc_ast::ast::{BinOpKind, Expr, ExprKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::declare_lint_pass; use rustc_span::source_map::Spanned; -const ALLOWED_ODD_FUNCTIONS: [&str; 14] = [ - "asin", - "asinh", - "atan", - "atanh", - "cbrt", - "fract", - "round", - "signum", - "sin", - "sinh", - "tan", - "tanh", - "to_degrees", - "to_radians", -]; - declare_clippy_lint! { /// ### What it does /// Checks for operations where precedence may be unclear /// and suggests to add parentheses. Currently it catches the following: /// * mixed usage of arithmetic and bit shifting/combining operators without /// parentheses - /// * a "negative" numeric literal (which is really a unary `-` followed by a - /// numeric literal) - /// followed by a method call /// /// ### Why is this bad? /// Not everyone knows the precedence of those operators by @@ -41,7 +20,6 @@ declare_clippy_lint! { /// /// ### Example /// * `1 << 2 + 3` equals 32, while `(1 << 2) + 3` equals 7 - /// * `-1i32.abs()` equals -1, while `(-1i32).abs()` equals 1 #[clippy::version = "pre 1.29.0"] pub PRECEDENCE, complexity, @@ -104,38 +82,6 @@ impl EarlyLintPass for Precedence { (false, false) => (), } } - - if let ExprKind::Unary(UnOp::Neg, operand) = &expr.kind { - let mut arg = operand; - - let mut all_odd = true; - while let ExprKind::MethodCall(box MethodCall { seg, receiver, .. }) = &arg.kind { - let seg_str = seg.ident.name.as_str(); - all_odd &= ALLOWED_ODD_FUNCTIONS - .iter() - .any(|odd_function| **odd_function == *seg_str); - arg = receiver; - } - - if !all_odd - && let ExprKind::Lit(lit) = &arg.kind - && let token::LitKind::Integer | token::LitKind::Float = &lit.kind - { - let mut applicability = Applicability::MachineApplicable; - span_lint_and_sugg( - cx, - PRECEDENCE, - expr.span, - "unary minus has lower precedence than method call", - "consider adding parentheses to clarify your intent", - format!( - "-({})", - snippet_with_applicability(cx, operand.span, "..", &mut applicability) - ), - applicability, - ); - } - } } } diff --git a/tests/ui/precedence.fixed b/tests/ui/precedence.fixed index cc87de0d90f18..c25c2062aceba 100644 --- a/tests/ui/precedence.fixed +++ b/tests/ui/precedence.fixed @@ -20,40 +20,6 @@ fn main() { 1 ^ (1 - 1); 3 | (2 - 1); 3 & (5 - 2); - -(1i32.abs()); - -(1f32.abs()); - - // These should not trigger an error - let _ = (-1i32).abs(); - let _ = (-1f32).abs(); - let _ = -(1i32).abs(); - let _ = -(1f32).abs(); - let _ = -(1i32.abs()); - let _ = -(1f32.abs()); - - // Odd functions should not trigger an error - let _ = -1f64.asin(); - let _ = -1f64.asinh(); - let _ = -1f64.atan(); - let _ = -1f64.atanh(); - let _ = -1f64.cbrt(); - let _ = -1f64.fract(); - let _ = -1f64.round(); - let _ = -1f64.signum(); - let _ = -1f64.sin(); - let _ = -1f64.sinh(); - let _ = -1f64.tan(); - let _ = -1f64.tanh(); - let _ = -1f64.to_degrees(); - let _ = -1f64.to_radians(); - - // Chains containing any non-odd function should trigger (issue #5924) - let _ = -(1.0_f64.cos().cos()); - let _ = -(1.0_f64.cos().sin()); - let _ = -(1.0_f64.sin().cos()); - - // Chains of odd functions shouldn't trigger - let _ = -1f64.sin().sin(); let b = 3; trip!(b * 8); diff --git a/tests/ui/precedence.rs b/tests/ui/precedence.rs index 00c18d92b5fb6..dc242ecf4c72e 100644 --- a/tests/ui/precedence.rs +++ b/tests/ui/precedence.rs @@ -20,40 +20,6 @@ fn main() { 1 ^ 1 - 1; 3 | 2 - 1; 3 & 5 - 2; - -1i32.abs(); - -1f32.abs(); - - // These should not trigger an error - let _ = (-1i32).abs(); - let _ = (-1f32).abs(); - let _ = -(1i32).abs(); - let _ = -(1f32).abs(); - let _ = -(1i32.abs()); - let _ = -(1f32.abs()); - - // Odd functions should not trigger an error - let _ = -1f64.asin(); - let _ = -1f64.asinh(); - let _ = -1f64.atan(); - let _ = -1f64.atanh(); - let _ = -1f64.cbrt(); - let _ = -1f64.fract(); - let _ = -1f64.round(); - let _ = -1f64.signum(); - let _ = -1f64.sin(); - let _ = -1f64.sinh(); - let _ = -1f64.tan(); - let _ = -1f64.tanh(); - let _ = -1f64.to_degrees(); - let _ = -1f64.to_radians(); - - // Chains containing any non-odd function should trigger (issue #5924) - let _ = -1.0_f64.cos().cos(); - let _ = -1.0_f64.cos().sin(); - let _ = -1.0_f64.sin().cos(); - - // Chains of odd functions shouldn't trigger - let _ = -1f64.sin().sin(); let b = 3; trip!(b * 8); diff --git a/tests/ui/precedence.stderr b/tests/ui/precedence.stderr index 47e61326219d9..8057c25a5e499 100644 --- a/tests/ui/precedence.stderr +++ b/tests/ui/precedence.stderr @@ -43,35 +43,5 @@ error: operator precedence can trip the unwary LL | 3 & 5 - 2; | ^^^^^^^^^ help: consider parenthesizing your expression: `3 & (5 - 2)` -error: unary minus has lower precedence than method call - --> tests/ui/precedence.rs:23:5 - | -LL | -1i32.abs(); - | ^^^^^^^^^^^ help: consider adding parentheses to clarify your intent: `-(1i32.abs())` - -error: unary minus has lower precedence than method call - --> tests/ui/precedence.rs:24:5 - | -LL | -1f32.abs(); - | ^^^^^^^^^^^ help: consider adding parentheses to clarify your intent: `-(1f32.abs())` - -error: unary minus has lower precedence than method call - --> tests/ui/precedence.rs:51:13 - | -LL | let _ = -1.0_f64.cos().cos(); - | ^^^^^^^^^^^^^^^^^^^^ help: consider adding parentheses to clarify your intent: `-(1.0_f64.cos().cos())` - -error: unary minus has lower precedence than method call - --> tests/ui/precedence.rs:52:13 - | -LL | let _ = -1.0_f64.cos().sin(); - | ^^^^^^^^^^^^^^^^^^^^ help: consider adding parentheses to clarify your intent: `-(1.0_f64.cos().sin())` - -error: unary minus has lower precedence than method call - --> tests/ui/precedence.rs:53:13 - | -LL | let _ = -1.0_f64.sin().cos(); - | ^^^^^^^^^^^^^^^^^^^^ help: consider adding parentheses to clarify your intent: `-(1.0_f64.sin().cos())` - -error: aborting due to 12 previous errors +error: aborting due to 7 previous errors diff --git a/tests/ui/unnecessary_cast.fixed b/tests/ui/unnecessary_cast.fixed index 288541362cddb..c43e50761bd52 100644 --- a/tests/ui/unnecessary_cast.fixed +++ b/tests/ui/unnecessary_cast.fixed @@ -206,7 +206,7 @@ mod fixable { fn issue_9563() { let _: f64 = (-8.0_f64).exp(); - #[allow(clippy::precedence)] + #[allow(ambiguous_negative_literals)] let _: f64 = -8.0_f64.exp(); // should suggest `-8.0_f64.exp()` here not to change code behavior } diff --git a/tests/ui/unnecessary_cast.rs b/tests/ui/unnecessary_cast.rs index eef3a42e35149..4a5ca231315eb 100644 --- a/tests/ui/unnecessary_cast.rs +++ b/tests/ui/unnecessary_cast.rs @@ -206,7 +206,7 @@ mod fixable { fn issue_9563() { let _: f64 = (-8.0 as f64).exp(); - #[allow(clippy::precedence)] + #[allow(ambiguous_negative_literals)] let _: f64 = -(8.0 as f64).exp(); // should suggest `-8.0_f64.exp()` here not to change code behavior } From 84d84daf1735d8996cdaf3aea487051215cffdf3 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Wed, 10 Jul 2024 21:03:25 -0500 Subject: [PATCH 016/786] Explicitly ignore `into_raw_handle()` using `let _ =` in sys/pal/windows. --- library/std/src/sys/pal/windows/process.rs | 2 +- library/std/src/sys/pal/windows/stdio.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/library/std/src/sys/pal/windows/process.rs b/library/std/src/sys/pal/windows/process.rs index c62764696b86b..6b3b79149ce21 100644 --- a/library/std/src/sys/pal/windows/process.rs +++ b/library/std/src/sys/pal/windows/process.rs @@ -571,7 +571,7 @@ impl Stdio { Ok(io) => unsafe { let io = Handle::from_raw_handle(io); let ret = io.duplicate(0, true, c::DUPLICATE_SAME_ACCESS); - io.into_raw_handle(); + let _ = io.into_raw_handle(); // Don't close the handle ret }, // If no stdio handle is available, then propagate the null value. diff --git a/library/std/src/sys/pal/windows/stdio.rs b/library/std/src/sys/pal/windows/stdio.rs index 10aeeac07ea2e..88b3996466fff 100644 --- a/library/std/src/sys/pal/windows/stdio.rs +++ b/library/std/src/sys/pal/windows/stdio.rs @@ -101,7 +101,7 @@ fn write( unsafe { let handle = Handle::from_raw_handle(handle); let ret = handle.write(data); - handle.into_raw_handle(); // Don't close the handle + let _ = handle.into_raw_handle(); // Don't close the handle return ret; } } @@ -250,7 +250,7 @@ impl io::Read for Stdin { unsafe { let handle = Handle::from_raw_handle(handle); let ret = handle.read(buf); - handle.into_raw_handle(); // Don't close the handle + let _ = handle.into_raw_handle(); // Don't close the handle return ret; } } From 78f6386b623c64160fa3475605c7ebfb065f62bf Mon Sep 17 00:00:00 2001 From: Neven Villani Date: Fri, 12 Jul 2024 10:51:32 +0200 Subject: [PATCH 017/786] Clarify comment in tests/fail/tree_borrows/reservedim_spurious_write.rs Co-authored-by: Ralf Jung --- .../tests/fail/tree_borrows/reservedim_spurious_write.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs index 6ae79be6cc7e8..73f227fee2fcb 100644 --- a/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs +++ b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs @@ -41,8 +41,9 @@ macro_rules! synchronized { } fn main() { - // The conflict occurs one one single location but the example involves - // lazily initialized permissions. + // The conflict occurs on one single location but the example involves + // lazily initialized permissions. We will use `&mut Cell<()>` references + // to `data` to achieve this. let mut data = 0u8; let ptr = SendPtr(std::ptr::addr_of_mut!(data)); let barrier = Arc::new(Barrier::new(2)); From d0d2e608865f3c8d624f23d552532574b00780dd Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 13 Jul 2024 18:39:03 +0000 Subject: [PATCH 018/786] Merge commit '659243d85c7489412bd0faa1c068d904a6042941' into sync_cg_clif-2024-07-13 --- Cargo.lock | 94 +++++++++++++++++----------------- rust-toolchain | 2 +- scripts/test_rustc_tests.sh | 4 +- src/abi/mod.rs | 1 - src/archive.rs | 4 +- src/constant.rs | 36 +++++++++++-- src/debuginfo/object.rs | 8 ++- src/intrinsics/llvm.rs | 20 +------- src/intrinsics/llvm_aarch64.rs | 1 - src/intrinsics/llvm_x86.rs | 1 - 10 files changed, 94 insertions(+), 77 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 15c9e9d66fac2..efec5db836bb1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -16,9 +16,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.82" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "arbitrary" @@ -67,7 +67,7 @@ dependencies = [ "cranelift-entity", "cranelift-isle", "gimli", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "log", "regalloc2", "rustc-hash", @@ -182,9 +182,9 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.4.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] @@ -203,9 +203,9 @@ checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" [[package]] name = "gimli" -version = "0.28.0" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" dependencies = [ "fallible-iterator", "indexmap", @@ -223,9 +223,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash", ] @@ -237,20 +237,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown 0.14.3", + "hashbrown 0.14.5", ] [[package]] name = "libc" -version = "0.2.153" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libloading" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" +checksum = "e310b3a6b5907f99202fcdb4960ff45b93735d7c7d96b760fcff8db2dc0e103d" dependencies = [ "cfg-if", "windows-targets", @@ -258,9 +258,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "mach" @@ -273,9 +273,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.2" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "object" @@ -284,7 +284,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce" dependencies = [ "crc32fast", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "indexmap", "memchr", ] @@ -297,9 +297,9 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "proc-macro2" -version = "1.0.81" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -382,9 +382,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "syn" -version = "2.0.60" +version = "2.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +checksum = "2f0209b68b3613b093e0ec905354eccaedcfe83b8cb37cbdeae64026c3064c16" dependencies = [ "proc-macro2", "quote", @@ -393,9 +393,9 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.12.14" +version = "0.12.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" +checksum = "4873307b7c257eddcb50c9bedf158eb669578359fb28428bef438fec8e6ba7c2" [[package]] name = "unicode-ident" @@ -454,9 +454,9 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", @@ -470,66 +470,66 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "zerocopy" -version = "0.7.32" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.32" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", diff --git a/rust-toolchain b/rust-toolchain index cfa91744a0e8d..db9b551bd2a25 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2024-06-30" +channel = "nightly-2024-07-13" components = ["rust-src", "rustc-dev", "llvm-tools"] diff --git a/scripts/test_rustc_tests.sh b/scripts/test_rustc_tests.sh index c1b7e4b0e0768..f0550c23b177f 100755 --- a/scripts/test_rustc_tests.sh +++ b/scripts/test_rustc_tests.sh @@ -34,6 +34,7 @@ rm tests/ui/parser/unclosed-delimiter-in-dep.rs # submodule contains //~ERROR # vendor intrinsics rm tests/ui/asm/x86_64/evex512-implicit-feature.rs # unimplemented AVX512 x86 vendor intrinsic +rm tests/ui/simd/dont-invalid-bitcast-x86_64.rs # unimplemented llvm.x86.sse41.round.ps # exotic linkages rm tests/incremental/hashes/function_interfaces.rs @@ -56,13 +57,13 @@ rm -r tests/run-make/target-specs # i686 not supported by Cranelift rm -r tests/run-make/mismatching-target-triples # same rm tests/ui/asm/x86_64/issue-96797.rs # const and sym inline asm operands don't work entirely correctly rm tests/ui/asm/x86_64/goto.rs # inline asm labels not supported +rm tests/ui/simd/simd-bitmask-notpow2.rs # non-pow-of-2 simd vector sizes # requires LTO rm -r tests/run-make/cdylib rm -r tests/run-make/codegen-options-parsing rm -r tests/run-make/lto-* rm -r tests/run-make/reproducible-build-2 -rm -r tests/run-make/issue-109934-lto-debuginfo rm -r tests/run-make/no-builtins-lto rm -r tests/run-make/reachable-extern-fn-available-lto @@ -109,6 +110,7 @@ rm -r tests/run-make/symbols-include-type-name rm -r tests/run-make/notify-all-emit-artifacts rm -r tests/run-make/reset-codegen-1 rm -r tests/run-make/inline-always-many-cgu +rm -r tests/run-make/intrinsic-unreachable # giving different but possibly correct results # ============================================= diff --git a/src/abi/mod.rs b/src/abi/mod.rs index 9dc94ab33ea9e..fa0de6f9de5ea 100644 --- a/src/abi/mod.rs +++ b/src/abi/mod.rs @@ -395,7 +395,6 @@ pub(crate) fn codegen_terminator_call<'tcx>( crate::intrinsics::codegen_llvm_intrinsic_call( fx, &fx.tcx.symbol_name(instance).name, - fn_args, args, ret_place, target, diff --git a/src/archive.rs b/src/archive.rs index 414d3db1c51a1..3f23e0d9e046b 100644 --- a/src/archive.rs +++ b/src/archive.rs @@ -14,12 +14,12 @@ impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder { fn create_dll_import_lib( &self, - _sess: &Session, + sess: &Session, _lib_name: &str, _dll_imports: &[rustc_session::cstore::DllImport], _tmpdir: &Path, _is_direct_dependency: bool, ) -> PathBuf { - unimplemented!("creating dll imports is not yet supported"); + sess.dcx().fatal("raw-dylib is not yet supported by rustc_codegen_cranelift"); } } diff --git a/src/constant.rs b/src/constant.rs index fd34ed88c0b28..0ba163f50aec5 100644 --- a/src/constant.rs +++ b/src/constant.rs @@ -385,15 +385,43 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant if let Some(section_name) = section_name { let (segment_name, section_name) = if tcx.sess.target.is_like_osx { - let section_name = section_name.as_str(); - if let Some(names) = section_name.split_once(',') { - names - } else { + // See https://github.com/llvm/llvm-project/blob/main/llvm/lib/MC/MCSectionMachO.cpp + let mut parts = section_name.as_str().split(','); + let Some(segment_name) = parts.next() else { tcx.dcx().fatal(format!( "#[link_section = \"{}\"] is not valid for macos target: must be segment and section separated by comma", section_name )); + }; + let Some(section_name) = parts.next() else { + tcx.dcx().fatal(format!( + "#[link_section = \"{}\"] is not valid for macos target: must be segment and section separated by comma", + section_name + )); + }; + if section_name.len() > 16 { + tcx.dcx().fatal(format!( + "#[link_section = \"{}\"] is not valid for macos target: section name bigger than 16 bytes", + section_name + )); + } + let section_type = parts.next().unwrap_or("regular"); + if section_type != "regular" && section_type != "cstring_literals" { + tcx.dcx().fatal(format!( + "#[link_section = \"{}\"] is not supported: unsupported section type {}", + section_name, section_type, + )); + } + let _attrs = parts.next(); + if parts.next().is_some() { + tcx.dcx().fatal(format!( + "#[link_section = \"{}\"] is not valid for macos target: too many components", + section_name + )); } + // FIXME(bytecodealliance/wasmtime#8901) set S_CSTRING_LITERALS section type when + // cstring_literals is specified + (segment_name, section_name) } else { ("", section_name.as_str()) }; diff --git a/src/debuginfo/object.rs b/src/debuginfo/object.rs index 65f4c67b21f13..1c6e471cc870f 100644 --- a/src/debuginfo/object.rs +++ b/src/debuginfo/object.rs @@ -39,7 +39,13 @@ impl WriteDebugInfo for ObjectProduct { let section_id = self.object.add_section( segment, name, - if id == SectionId::EhFrame { SectionKind::ReadOnlyData } else { SectionKind::Debug }, + if id == SectionId::DebugStr || id == SectionId::DebugLineStr { + SectionKind::DebugString + } else if id == SectionId::EhFrame { + SectionKind::ReadOnlyData + } else { + SectionKind::Debug + }, ); self.object .section_mut(section_id) diff --git a/src/intrinsics/llvm.rs b/src/intrinsics/llvm.rs index e50c74b87f603..720a0d8fbf593 100644 --- a/src/intrinsics/llvm.rs +++ b/src/intrinsics/llvm.rs @@ -6,32 +6,16 @@ use crate::prelude::*; pub(crate) fn codegen_llvm_intrinsic_call<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, intrinsic: &str, - generic_args: GenericArgsRef<'tcx>, args: &[Spanned>], ret: CPlace<'tcx>, target: Option, span: Span, ) { if intrinsic.starts_with("llvm.aarch64") { - return llvm_aarch64::codegen_aarch64_llvm_intrinsic_call( - fx, - intrinsic, - generic_args, - args, - ret, - target, - ); + return llvm_aarch64::codegen_aarch64_llvm_intrinsic_call(fx, intrinsic, args, ret, target); } if intrinsic.starts_with("llvm.x86") { - return llvm_x86::codegen_x86_llvm_intrinsic_call( - fx, - intrinsic, - generic_args, - args, - ret, - target, - span, - ); + return llvm_x86::codegen_x86_llvm_intrinsic_call(fx, intrinsic, args, ret, target, span); } match intrinsic { diff --git a/src/intrinsics/llvm_aarch64.rs b/src/intrinsics/llvm_aarch64.rs index e66bcbf4e40e5..f0fb18608e072 100644 --- a/src/intrinsics/llvm_aarch64.rs +++ b/src/intrinsics/llvm_aarch64.rs @@ -6,7 +6,6 @@ use crate::prelude::*; pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, intrinsic: &str, - _args: GenericArgsRef<'tcx>, args: &[Spanned>], ret: CPlace<'tcx>, target: Option, diff --git a/src/intrinsics/llvm_x86.rs b/src/intrinsics/llvm_x86.rs index 399518e58d8c5..e1896138e487b 100644 --- a/src/intrinsics/llvm_x86.rs +++ b/src/intrinsics/llvm_x86.rs @@ -10,7 +10,6 @@ use crate::prelude::*; pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, intrinsic: &str, - _args: GenericArgsRef<'tcx>, args: &[Spanned>], ret: CPlace<'tcx>, target: Option, From fd81880c9108c4b98839d55fe29884a625f05f02 Mon Sep 17 00:00:00 2001 From: Neven Villani Date: Fri, 12 Jul 2024 15:58:59 +0200 Subject: [PATCH 019/786] Leave a trace of the current suboptimal status of foreign_write --- src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs index 9c19ae76a2d01..8e23257b6c006 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs @@ -146,6 +146,12 @@ mod transition { /// non-protected interior mutable `Reserved` which stay the same. fn foreign_write(state: PermissionPriv, protected: bool) -> Option { Some(match state { + // FIXME: since the fix related to reservedim_spurious_write, it is now possible + // to express these transitions of the state machine without an explicit dependency + // on `protected`: because `ty_is_freeze: false` implies `!protected` then + // the line handling `Reserved { .. } if protected` could be deleted. + // This will however require optimizations to the exhaustive tests because + // fewer initial conditions are valid. Reserved { .. } if protected => Disabled, res @ Reserved { ty_is_freeze: false, .. } => res, _ => Disabled, From 5203b7e10d05e3e57ada5406d99950d44d847a79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Sun, 14 Jul 2024 16:59:06 +0200 Subject: [PATCH 020/786] Set rustup profile to minimal (#1516) --- .github/workflows/audit.yml | 1 - .github/workflows/main.yml | 1 - rust-toolchain | 1 + 3 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml index b4f8ce0f5329d..27c95572ef879 100644 --- a/.github/workflows/audit.yml +++ b/.github/workflows/audit.yml @@ -13,7 +13,6 @@ jobs: - uses: actions/checkout@v4 - run: | sed -i 's/components.*/components = []/' rust-toolchain - echo 'profile = "minimal"' >> rust-toolchain - uses: rustsec/audit-check@v1.4.1 with: token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a2ae3d63fb907..896a5c34c3eff 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -29,7 +29,6 @@ jobs: - name: Avoid installing rustc-dev run: | sed -i 's/components.*/components = ["rustfmt"]/' rust-toolchain - echo 'profile = "minimal"' >> rust-toolchain rustfmt -v - name: Rustfmt diff --git a/rust-toolchain b/rust-toolchain index db9b551bd2a25..2478a9bbccee9 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,4 @@ [toolchain] channel = "nightly-2024-07-13" components = ["rust-src", "rustc-dev", "llvm-tools"] +profile = "minimal" From 9d9b55cd2b14bce066cef83d9d85ba798a2ba95c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 15 Jul 2024 21:25:03 +0200 Subject: [PATCH 021/786] make invalid_type_param_default lint show up in cargo future-compat reports and remove the feature gate that silenced the lint --- compiler/rustc_feature/src/removed.rs | 3 ++ compiler/rustc_feature/src/unstable.rs | 2 - .../src/collect/generics_of.rs | 2 - compiler/rustc_lint_defs/src/builtin.rs | 2 +- ...ate-default_type_parameter_fallback.stderr | 21 --------- tests/ui/impl-trait/where-allowed.stderr | 22 ++++++++++ tests/ui/issues/issue-26812.rs | 4 +- tests/ui/issues/issue-26812.stderr | 25 ++++++++++- .../lifetimes/unusual-rib-combinations.stderr | 11 +++++ ...ed-type-param-in-fn-with-assoc-type.stderr | 10 +++++ .../default_type_parameter_in_fn_or_impl.rs} | 0 ...efault_type_parameter_in_fn_or_impl.stderr | 43 +++++++++++++++++++ 12 files changed, 115 insertions(+), 30 deletions(-) delete mode 100644 tests/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr rename tests/ui/{feature-gates/feature-gate-default_type_parameter_fallback.rs => type/default_type_parameter_in_fn_or_impl.rs} (100%) create mode 100644 tests/ui/type/default_type_parameter_in_fn_or_impl.stderr diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index f13aa506c1ec0..a78ae0d6993e2 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -75,6 +75,9 @@ declare_features! ( /// Allows the use of `#[derive(Anything)]` as sugar for `#[derive_Anything]`. (removed, custom_derive, "1.32.0", Some(29644), Some("subsumed by `#[proc_macro_derive]`")), + /// Allows default type parameters to influence type inference. + (removed, default_type_parameter_fallback, "CURRENT_RUSTC_VERSION", Some(27336), + Some("never properly implemented; requires significant design work")), /// Allows using `#[doc(keyword = "...")]`. (removed, doc_keyword, "1.28.0", Some(51315), Some("merged into `#![feature(rustdoc_internals)]`")), diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 948499fb38fbf..407800ce60d5d 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -428,8 +428,6 @@ declare_features! ( (unstable, custom_test_frameworks, "1.30.0", Some(50297)), /// Allows declarative macros 2.0 (`macro`). (unstable, decl_macro, "1.17.0", Some(39412)), - /// Allows default type parameters to influence type inference. - (unstable, default_type_parameter_fallback, "1.3.0", Some(27336)), /// Allows using `#[deprecated_safe]` to deprecate the safeness of a function or trait (unstable, deprecated_safe, "1.61.0", Some(94978)), /// Allows having using `suggestion` in the `#[deprecated]` attribute. diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 22d465c8e62be..398a496a3737f 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -323,8 +323,6 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { if default.is_some() { match allow_defaults { Defaults::Allowed => {} - Defaults::FutureCompatDisallowed - if tcx.features().default_type_parameter_fallback => {} Defaults::FutureCompatDisallowed => { tcx.node_span_lint( lint::builtin::INVALID_TYPE_PARAM_DEFAULT, diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index aa7844f40121b..276a507d3e89b 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -1241,7 +1241,7 @@ declare_lint! { Deny, "type parameter default erroneously allowed in invalid location", @future_incompatible = FutureIncompatibleInfo { - reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, + reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, reference: "issue #36887 ", }; } diff --git a/tests/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr b/tests/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr deleted file mode 100644 index 308de2692930d..0000000000000 --- a/tests/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions - --> $DIR/feature-gate-default_type_parameter_fallback.rs:3:8 - | -LL | fn avg(_: T) {} - | ^^^^^ - | - = 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 #36887 - = note: `#[deny(invalid_type_param_default)]` on by default - -error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions - --> $DIR/feature-gate-default_type_parameter_fallback.rs:8:6 - | -LL | impl S {} - | ^^^^^ - | - = 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 #36887 - -error: aborting due to 2 previous errors - diff --git a/tests/ui/impl-trait/where-allowed.stderr b/tests/ui/impl-trait/where-allowed.stderr index f0d259d01de94..1fb69db98c162 100644 --- a/tests/ui/impl-trait/where-allowed.stderr +++ b/tests/ui/impl-trait/where-allowed.stderr @@ -433,3 +433,25 @@ error: aborting due to 50 previous errors Some errors have detailed explanations: E0053, E0118, E0283, E0562, E0599, E0658, E0666. For more information about an error, try `rustc --explain E0053`. +Future incompatibility report: Future breakage diagnostic: +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/where-allowed.rs:239:7 + | +LL | impl T {} + | ^^^^^^^^^^^^^^ + | + = 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 #36887 + = note: `#[deny(invalid_type_param_default)]` on by default + +Future breakage diagnostic: +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/where-allowed.rs:246:36 + | +LL | fn in_method_generic_param_default(_: T) {} + | ^^^^^^^^^^^^^^ + | + = 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 #36887 + = note: `#[deny(invalid_type_param_default)]` on by default + diff --git a/tests/ui/issues/issue-26812.rs b/tests/ui/issues/issue-26812.rs index 3391ea4b350af..e0723e016b381 100644 --- a/tests/ui/issues/issue-26812.rs +++ b/tests/ui/issues/issue-26812.rs @@ -1,6 +1,6 @@ -#![feature(default_type_parameter_fallback)] - fn avg(_: T) {} //~^ ERROR generic parameters with a default cannot use forward declared identifiers +//~| ERROR defaults for type parameters +//~| WARN previously accepted fn main() {} diff --git a/tests/ui/issues/issue-26812.stderr b/tests/ui/issues/issue-26812.stderr index c2a3d4b83d536..4a18b23fd8b13 100644 --- a/tests/ui/issues/issue-26812.stderr +++ b/tests/ui/issues/issue-26812.stderr @@ -1,9 +1,30 @@ error[E0128]: generic parameters with a default cannot use forward declared identifiers - --> $DIR/issue-26812.rs:3:10 + --> $DIR/issue-26812.rs:1:10 | LL | fn avg(_: T) {} | ^^^^^^^ defaulted generic parameters cannot be forward declared -error: aborting due to 1 previous error +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/issue-26812.rs:1:8 + | +LL | fn avg(_: T) {} + | ^^^^^^^^^ + | + = 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 #36887 + = note: `#[deny(invalid_type_param_default)]` on by default + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0128`. +Future incompatibility report: Future breakage diagnostic: +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/issue-26812.rs:1:8 + | +LL | fn avg(_: T) {} + | ^^^^^^^^^ + | + = 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 #36887 + = note: `#[deny(invalid_type_param_default)]` on by default + diff --git a/tests/ui/lifetimes/unusual-rib-combinations.stderr b/tests/ui/lifetimes/unusual-rib-combinations.stderr index 70f06b4be603c..3f97ae6c5bd54 100644 --- a/tests/ui/lifetimes/unusual-rib-combinations.stderr +++ b/tests/ui/lifetimes/unusual-rib-combinations.stderr @@ -68,3 +68,14 @@ error: aborting due to 8 previous errors Some errors have detailed explanations: E0106, E0214, E0308, E0770. For more information about an error, try `rustc --explain E0106`. +Future incompatibility report: Future breakage diagnostic: +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/unusual-rib-combinations.rs:15:6 + | +LL | fn c() {} + | ^^^^^^^^ + | + = 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 #36887 + = note: `#[deny(invalid_type_param_default)]` on by default + diff --git a/tests/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.stderr b/tests/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.stderr index dc0bea58a70e8..bf8829c09257f 100644 --- a/tests/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.stderr +++ b/tests/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.stderr @@ -12,3 +12,13 @@ LL | foo::(); error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. +Future incompatibility report: Future breakage diagnostic: +warning: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/unbounded-type-param-in-fn-with-assoc-type.rs:3:11 + | +LL | fn foo() -> (T, U) { + | ^^^^^^^ + | + = 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 #36887 + diff --git a/tests/ui/feature-gates/feature-gate-default_type_parameter_fallback.rs b/tests/ui/type/default_type_parameter_in_fn_or_impl.rs similarity index 100% rename from tests/ui/feature-gates/feature-gate-default_type_parameter_fallback.rs rename to tests/ui/type/default_type_parameter_in_fn_or_impl.rs diff --git a/tests/ui/type/default_type_parameter_in_fn_or_impl.stderr b/tests/ui/type/default_type_parameter_in_fn_or_impl.stderr new file mode 100644 index 0000000000000..a3205cd3c29ca --- /dev/null +++ b/tests/ui/type/default_type_parameter_in_fn_or_impl.stderr @@ -0,0 +1,43 @@ +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/default_type_parameter_in_fn_or_impl.rs:3:8 + | +LL | fn avg(_: T) {} + | ^^^^^ + | + = 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 #36887 + = note: `#[deny(invalid_type_param_default)]` on by default + +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/default_type_parameter_in_fn_or_impl.rs:8:6 + | +LL | impl S {} + | ^^^^^ + | + = 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 #36887 + +error: aborting due to 2 previous errors + +Future incompatibility report: Future breakage diagnostic: +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/default_type_parameter_in_fn_or_impl.rs:3:8 + | +LL | fn avg(_: T) {} + | ^^^^^ + | + = 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 #36887 + = note: `#[deny(invalid_type_param_default)]` on by default + +Future breakage diagnostic: +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/default_type_parameter_in_fn_or_impl.rs:8:6 + | +LL | impl S {} + | ^^^^^ + | + = 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 #36887 + = note: `#[deny(invalid_type_param_default)]` on by default + From c01fe3ceac9726b9c79f79efcd694ee5b32cbe29 Mon Sep 17 00:00:00 2001 From: Mohammad Omidvar Date: Mon, 15 Jul 2024 23:43:52 +0000 Subject: [PATCH 022/786] Move compiler_builtin check to the use case --- src/abi/mod.rs | 2 +- src/base.rs | 2 +- src/lib.rs | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/abi/mod.rs b/src/abi/mod.rs index fa0de6f9de5ea..698981ae1536d 100644 --- a/src/abi/mod.rs +++ b/src/abi/mod.rs @@ -10,12 +10,12 @@ use std::mem; use cranelift_codegen::ir::{ArgumentPurpose, SigRef}; use cranelift_codegen::isa::CallConv; use cranelift_module::ModuleError; +use rustc_codegen_ssa::base::is_call_from_compiler_builtins_to_upstream_monomorphization; use rustc_codegen_ssa::errors::CompilerBuiltinsCannotCall; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::ty::layout::FnAbiOf; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::TypeVisitableExt; -use rustc_monomorphize::is_call_from_compiler_builtins_to_upstream_monomorphization; use rustc_session::Session; use rustc_span::source_map::Spanned; use rustc_target::abi::call::{Conv, FnAbi, PassMode}; diff --git a/src/base.rs b/src/base.rs index 5adbbb09ac85f..9bc7b57c53745 100644 --- a/src/base.rs +++ b/src/base.rs @@ -5,13 +5,13 @@ use cranelift_codegen::CodegenError; use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext}; use cranelift_module::ModuleError; use rustc_ast::InlineAsmOptions; +use rustc_codegen_ssa::base::is_call_from_compiler_builtins_to_upstream_monomorphization; use rustc_index::IndexVec; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::layout::FnAbiOf; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::TypeVisitableExt; -use rustc_monomorphize::is_call_from_compiler_builtins_to_upstream_monomorphization; use crate::constant::ConstantCx; use crate::debuginfo::{FunctionDebugContext, TypeDebugContext}; diff --git a/src/lib.rs b/src/lib.rs index 192e6c91ea38b..8d3d5ac98e1e5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,7 +24,6 @@ extern crate rustc_hir; extern crate rustc_incremental; extern crate rustc_index; extern crate rustc_metadata; -extern crate rustc_monomorphize; extern crate rustc_session; extern crate rustc_span; extern crate rustc_target; From fceeb133995b50bddc3df6cf58c4ce684a64fcf3 Mon Sep 17 00:00:00 2001 From: yaxum62 Date: Mon, 15 Jul 2024 21:21:52 -0700 Subject: [PATCH 023/786] Add test for `try_err` lint within try blocks. --- tests/ui/try_err.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tests/ui/try_err.rs b/tests/ui/try_err.rs index 927eccf2d54c5..841ec6b5d5c77 100644 --- a/tests/ui/try_err.rs +++ b/tests/ui/try_err.rs @@ -1,5 +1,5 @@ //@aux-build:proc_macros.rs - +#![feature(try_blocks)] #![deny(clippy::try_err)] #![allow( clippy::unnecessary_wraps, @@ -152,3 +152,11 @@ pub fn try_return(x: bool) -> Result { } Ok(0) } + +// Test that the lint is suppressed in try block. +pub fn try_block() -> Result<(), i32> { + let _: Result<_, i32> = try { + Err(1)?; + }; + Ok(()) +} From 1821defc39d410b3f761dbc0bae45e7ac1e6d585 Mon Sep 17 00:00:00 2001 From: yaxum62 Date: Mon, 15 Jul 2024 21:54:15 -0700 Subject: [PATCH 024/786] add expected output for try_err test --- tests/ui/try_err.fixed | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tests/ui/try_err.fixed b/tests/ui/try_err.fixed index aae4f8ac47f82..f149bfb77740c 100644 --- a/tests/ui/try_err.fixed +++ b/tests/ui/try_err.fixed @@ -1,5 +1,5 @@ //@aux-build:proc_macros.rs - +#![feature(try_blocks)] #![deny(clippy::try_err)] #![allow( clippy::unnecessary_wraps, @@ -152,3 +152,11 @@ pub fn try_return(x: bool) -> Result { } Ok(0) } + +// Test that the lint is suppressed in try block. +pub fn try_block() -> Result<(), i32> { + let _: Result<_, i32> = try { + Err(1)?; + }; + Ok(()) +} From e1e5b8a2b69da18b11147aa8d18e731ee32d9819 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Tue, 16 Jul 2024 05:14:32 +0000 Subject: [PATCH 025/786] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index e90d3732ca577..2c29af8b9357f 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -99b7134389e9766462601a2fc4013840b9d31745 +5c8488605624d67b272953bc21d41db60dbd5654 From 580cdfa6a7a9513b9185b404e346cf7f0e1a6c85 Mon Sep 17 00:00:00 2001 From: "Chai T. Rex" Date: Tue, 16 Jul 2024 10:01:35 -0400 Subject: [PATCH 026/786] Added project-specific Zed IDE settings Created `.zed/settings.json` with all the settings from `.vscode/settings.json`. --- .zed/settings.json | 68 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 .zed/settings.json diff --git a/.zed/settings.json b/.zed/settings.json new file mode 100644 index 0000000000000..e93bed3694921 --- /dev/null +++ b/.zed/settings.json @@ -0,0 +1,68 @@ +{ + "format_on_save": "on", + "lsp": { + "rust-analyzer": { + "initialization_options": { + "diagnostics": { + // in case rustc.source is disabled for performance reasons; disable the errors about this + "disabled": ["unresolved-extern-crate", "unresolved-macro-call"] + }, + "rustc": { + "source": "discover" + }, + "imports": { + "granularity": { + "enforce": true, + "group": "module" + }, + "prefix": "crate" + }, + "cargo": { + "features": ["unstable-features"] + }, + "linkedProjects": [ + "./Cargo.toml", + "./build_system/Cargo.toml", + { + "crates": [ + { + "root_module": "./example/mini_core.rs", + "edition": "2018", + "deps": [], + "cfg": [] + }, + { + "root_module": "./example/mini_core_hello_world.rs", + "edition": "2018", + "deps": [ + { + "crate": 0, + "name": "mini_core" + } + ], + "cfg": [] + }, + { + "root_module": "./example/mod_bench.rs", + "edition": "2018", + "deps": [], + "cfg": [] + } + ] + }, + { + "sysroot_src": "./build/stdlib/library", + "crates": [ + { + "root_module": "./example/std_example.rs", + "edition": "2015", + "deps": [], + "cfg": [] + } + ] + } + ] + } + } + } +} From e0af3c61cd5b90e53c720246f40bf47e97429aa2 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Tue, 16 Jul 2024 15:43:40 -0500 Subject: [PATCH 027/786] When an archive fails to build, print the path Currently the output on failure is as follows: Compiling block-buffer v0.10.4 Compiling crypto-common v0.1.6 Compiling digest v0.10.7 Compiling sha2 v0.10.8 Compiling xz2 v0.1.7 error: failed to build archive: No such file or directory error: could not compile `bootstrap` (lib) due to 1 previous error Print which file is being constructed to give some hint about what is going on. --- compiler/rustc_codegen_llvm/src/back/archive.rs | 4 +++- compiler/rustc_codegen_ssa/messages.ftl | 5 ++--- compiler/rustc_codegen_ssa/src/back/archive.rs | 4 +++- compiler/rustc_codegen_ssa/src/back/link.rs | 3 ++- compiler/rustc_codegen_ssa/src/errors.rs | 2 ++ 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs index a354f3d353610..eca0ead8666b0 100644 --- a/compiler/rustc_codegen_llvm/src/back/archive.rs +++ b/compiler/rustc_codegen_llvm/src/back/archive.rs @@ -101,7 +101,9 @@ impl<'a> ArchiveBuilder for LlvmArchiveBuilder<'a> { fn build(mut self: Box, output: &Path) -> bool { match self.build_with_llvm(output) { Ok(any_members) => any_members, - Err(e) => self.sess.dcx().emit_fatal(ArchiveBuildFailure { error: e }), + Err(error) => { + self.sess.dcx().emit_fatal(ArchiveBuildFailure { path: output.to_owned(), error }) + } } } } diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index 000fe2e3ce0f5..57d789aef80ca 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -4,8 +4,7 @@ codegen_ssa_add_native_library = failed to add native library {$library_path}: { codegen_ssa_apple_sdk_error_sdk_path = failed to get {$sdk_name} SDK path: {$error} -codegen_ssa_archive_build_failure = - failed to build archive: {$error} +codegen_ssa_archive_build_failure = failed to build archive at `{$path}`: {$error} codegen_ssa_atomic_compare_exchange = Atomic compare-exchange intrinsic missing failure memory ordering @@ -198,7 +197,7 @@ codegen_ssa_read_file = failed to read file: {$message} codegen_ssa_repair_vs_build_tools = the Visual Studio build tools may need to be repaired using the Visual Studio installer -codegen_ssa_rlib_archive_build_failure = failed to build archive from rlib: {$error} +codegen_ssa_rlib_archive_build_failure = failed to build archive from rlib at `{$path}`: {$error} codegen_ssa_rlib_incompatible_dependency_formats = `{$ty1}` and `{$ty2}` do not have equivalent dependency formats (`{$list1}` vs `{$list2}`) diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index c99118f5156d1..31b437555f440 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -220,7 +220,9 @@ impl<'a> ArchiveBuilder for ArArchiveBuilder<'a> { let sess = self.sess; match self.build_inner(output) { Ok(any_members) => any_members, - Err(e) => sess.dcx().emit_fatal(ArchiveBuildFailure { error: e }), + Err(error) => { + sess.dcx().emit_fatal(ArchiveBuildFailure { path: output.to_owned(), error }) + } } } } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 1f627353d54e1..b6ca9476ecd73 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -2911,7 +2911,8 @@ fn add_static_crate( false }), ) { - sess.dcx().emit_fatal(errors::RlibArchiveBuildFailure { error }); + sess.dcx() + .emit_fatal(errors::RlibArchiveBuildFailure { path: cratepath.clone(), error }); } if archive.build(&dst) { link_upstream(&dst); diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index e9d31db92541b..138e53f2106f6 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -497,6 +497,7 @@ pub struct UnableToWriteDebuggerVisualizer { #[derive(Diagnostic)] #[diag(codegen_ssa_rlib_archive_build_failure)] pub struct RlibArchiveBuildFailure { + pub path: PathBuf, pub error: Error, } @@ -554,6 +555,7 @@ pub struct UnsupportedLinkSelfContained; #[diag(codegen_ssa_archive_build_failure)] // Public for rustc_codegen_llvm::back::archive pub struct ArchiveBuildFailure { + pub path: PathBuf, pub error: std::io::Error, } From a5fd2c98bdf1881e553500cad4d8ce3b970a0a97 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Wed, 17 Jul 2024 12:51:08 +0700 Subject: [PATCH 028/786] Remove duplicated peel_middle_ty_refs TODO: Should we move `ty::peel_mid_ty_refs_is_mutable` to super module too? --- clippy_lints/src/dereference.rs | 4 ++-- clippy_lints/src/matches/single_match.rs | 8 +++++--- clippy_lints/src/methods/implicit_clone.rs | 6 +++--- clippy_lints/src/methods/unnecessary_to_owned.rs | 13 ++++++------- clippy_lints/src/redundant_slicing.rs | 8 ++++---- clippy_lints/src/size_of_ref.rs | 5 ++--- clippy_utils/src/ty.rs | 13 ------------- 7 files changed, 22 insertions(+), 35 deletions(-) diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index 253f9959e13e7..d0cb24884686a 100644 --- a/clippy_lints/src/dereference.rs +++ b/clippy_lints/src/dereference.rs @@ -1,7 +1,7 @@ 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::ty::{implements_trait, is_manually_drop}; use clippy_utils::{ expr_use_ctxt, get_parent_expr, is_block_like, is_lint_allowed, path_to_local, peel_middle_ty_refs, DefinedTy, ExprUseNode, @@ -947,7 +947,7 @@ fn report<'tcx>( let (expr_str, _expr_is_macro_call) = snippet_with_context(cx, expr.span, data.first_expr.span.ctxt(), "..", &mut app); let ty = typeck.expr_ty(expr); - let (_, ref_count) = peel_mid_ty_refs(ty); + let (_, ref_count) = peel_middle_ty_refs(ty); let deref_str = if ty_changed_count >= ref_count && ref_count != 0 { // a deref call changing &T -> &U requires two deref operators the first time // this occurs. One to remove the reference, a second to call the deref impl. diff --git a/clippy_lints/src/matches/single_match.rs b/clippy_lints/src/matches/single_match.rs index 99fdbcff890b4..d4330400cd0e5 100644 --- a/clippy_lints/src/matches/single_match.rs +++ b/clippy_lints/src/matches/single_match.rs @@ -1,7 +1,9 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::{expr_block, snippet, SpanRangeExt}; -use clippy_utils::ty::{implements_trait, is_type_diagnostic_item, peel_mid_ty_refs}; -use clippy_utils::{is_lint_allowed, is_unit_expr, is_wild, peel_blocks, peel_hir_pat_refs, peel_n_hir_expr_refs}; +use clippy_utils::ty::{implements_trait, is_type_diagnostic_item}; +use clippy_utils::{ + is_lint_allowed, is_unit_expr, is_wild, peel_blocks, peel_hir_pat_refs, peel_middle_ty_refs, peel_n_hir_expr_refs, +}; use core::cmp::max; use rustc_errors::Applicability; use rustc_hir::{Arm, BindingMode, Block, Expr, ExprKind, Pat, PatKind}; @@ -82,7 +84,7 @@ fn report_single_pattern( let (pat, pat_ref_count) = peel_hir_pat_refs(arms[0].pat); let (msg, sugg) = if let PatKind::Path(_) | PatKind::Lit(_) = pat.kind - && let (ty, ty_ref_count) = peel_mid_ty_refs(cx.typeck_results().expr_ty(ex)) + && let (ty, ty_ref_count) = peel_middle_ty_refs(cx.typeck_results().expr_ty(ex)) && let Some(spe_trait_id) = cx.tcx.lang_items().structural_peq_trait() && let Some(pe_trait_id) = cx.tcx.lang_items().eq_trait() && (ty.is_integral() diff --git a/clippy_lints/src/methods/implicit_clone.rs b/clippy_lints/src/methods/implicit_clone.rs index c510cd915d0c9..519091406ccf3 100644 --- a/clippy_lints/src/methods/implicit_clone.rs +++ b/clippy_lints/src/methods/implicit_clone.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_context; -use clippy_utils::ty::{implements_trait, peel_mid_ty_refs}; -use clippy_utils::{is_diag_item_method, is_diag_trait_item}; +use clippy_utils::ty::implements_trait; +use clippy_utils::{is_diag_item_method, is_diag_trait_item, peel_middle_ty_refs}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; @@ -14,7 +14,7 @@ pub fn check(cx: &LateContext<'_>, method_name: &str, expr: &hir::Expr<'_>, recv && is_clone_like(cx, method_name, method_def_id) && let return_type = cx.typeck_results().expr_ty(expr) && let input_type = cx.typeck_results().expr_ty(recv) - && let (input_type, ref_count) = peel_mid_ty_refs(input_type) + && let (input_type, ref_count) = peel_middle_ty_refs(input_type) && !(ref_count > 0 && is_diag_trait_item(cx, method_def_id, sym::ToOwned)) && let Some(ty_name) = input_type.ty_adt_def().map(|adt_def| cx.tcx.item_name(adt_def.did())) && return_type == input_type diff --git a/clippy_lints/src/methods/unnecessary_to_owned.rs b/clippy_lints/src/methods/unnecessary_to_owned.rs index 5d899415d7728..fed2b128dcf30 100644 --- a/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -3,12 +3,11 @@ use super::unnecessary_iter_cloned::{self, is_into_iter}; use clippy_config::msrvs::{self, Msrv}; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::source::{snippet, snippet_opt}; -use clippy_utils::ty::{ - get_iterator_item_ty, implements_trait, is_copy, is_type_diagnostic_item, is_type_lang_item, peel_mid_ty_refs, -}; +use clippy_utils::ty::{get_iterator_item_ty, implements_trait, is_copy, is_type_diagnostic_item, is_type_lang_item}; use clippy_utils::visitors::find_all_ret_expressions; use clippy_utils::{ - fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, match_def_path, paths, return_ty, + fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, match_def_path, paths, peel_middle_ty_refs, + return_ty, }; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; @@ -120,8 +119,8 @@ fn check_addr_of_expr( }, ] = adjustments[..] && let receiver_ty = cx.typeck_results().expr_ty(receiver) - && let (target_ty, n_target_refs) = peel_mid_ty_refs(*target_ty) - && let (receiver_ty, n_receiver_refs) = peel_mid_ty_refs(receiver_ty) + && let (target_ty, n_target_refs) = peel_middle_ty_refs(*target_ty) + && let (receiver_ty, n_receiver_refs) = peel_middle_ty_refs(receiver_ty) // Only flag cases satisfying at least one of the following three conditions: // * the referent and receiver types are distinct // * the referent/receiver type is a copyable array @@ -382,7 +381,7 @@ fn check_other_call_arg<'tcx>( && let fn_sig = cx.tcx.fn_sig(callee_def_id).instantiate_identity().skip_binder() && let Some(i) = recv.into_iter().chain(call_args).position(|arg| arg.hir_id == maybe_arg.hir_id) && let Some(input) = fn_sig.inputs().get(i) - && let (input, n_refs) = peel_mid_ty_refs(*input) + && let (input, n_refs) = peel_middle_ty_refs(*input) && let (trait_predicates, _) = get_input_traits_and_projections(cx, callee_def_id, input) && let Some(sized_def_id) = cx.tcx.lang_items().sized_trait() && let [trait_predicate] = trait_predicates diff --git a/clippy_lints/src/redundant_slicing.rs b/clippy_lints/src/redundant_slicing.rs index 82f22ad693d78..97b2f99299a73 100644 --- a/clippy_lints/src/redundant_slicing.rs +++ b/clippy_lints/src/redundant_slicing.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::get_parent_expr; use clippy_utils::source::snippet_with_context; -use clippy_utils::ty::{is_type_lang_item, peel_mid_ty_refs}; +use clippy_utils::ty::is_type_lang_item; +use clippy_utils::{get_parent_expr, peel_middle_ty_refs}; use rustc_ast::util::parser::PREC_PREFIX; use rustc_errors::Applicability; use rustc_hir::{BorrowKind, Expr, ExprKind, LangItem, Mutability}; @@ -82,8 +82,8 @@ impl<'tcx> LateLintPass<'tcx> for RedundantSlicing { && let ExprKind::Index(indexed, range, _) = addressee.kind && is_type_lang_item(cx, cx.typeck_results().expr_ty_adjusted(range), LangItem::RangeFull) { - let (expr_ty, expr_ref_count) = peel_mid_ty_refs(cx.typeck_results().expr_ty(expr)); - let (indexed_ty, indexed_ref_count) = peel_mid_ty_refs(cx.typeck_results().expr_ty(indexed)); + let (expr_ty, expr_ref_count) = peel_middle_ty_refs(cx.typeck_results().expr_ty(expr)); + let (indexed_ty, indexed_ref_count) = peel_middle_ty_refs(cx.typeck_results().expr_ty(indexed)); let parent_expr = get_parent_expr(cx, expr); let needs_parens_for_prefix = parent_expr.map_or(false, |parent| parent.precedence().order() > PREC_PREFIX); let mut app = Applicability::MachineApplicable; diff --git a/clippy_lints/src/size_of_ref.rs b/clippy_lints/src/size_of_ref.rs index 8d7f12af86e8a..b3d32a6d7d84c 100644 --- a/clippy_lints/src/size_of_ref.rs +++ b/clippy_lints/src/size_of_ref.rs @@ -1,6 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_help; -use clippy_utils::path_def_id; -use clippy_utils::ty::peel_mid_ty_refs; +use clippy_utils::{path_def_id, peel_middle_ty_refs}; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; @@ -60,7 +59,7 @@ impl LateLintPass<'_> for SizeOfRef { && let Some(def_id) = path_def_id(cx, path) && cx.tcx.is_diagnostic_item(sym::mem_size_of_val, def_id) && let arg_ty = cx.typeck_results().expr_ty(arg) - && peel_mid_ty_refs(arg_ty).1 > 1 + && peel_middle_ty_refs(arg_ty).1 > 1 { span_lint_and_help( cx, diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs index fc02b974ee12a..29ea03f7bb180 100644 --- a/clippy_utils/src/ty.rs +++ b/clippy_utils/src/ty.rs @@ -525,19 +525,6 @@ pub fn needs_ordered_drop<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { needs_ordered_drop_inner(cx, ty, &mut FxHashSet::default()) } -/// Peels off all references on the type. Returns the underlying type and the number of references -/// removed. -pub fn peel_mid_ty_refs(ty: Ty<'_>) -> (Ty<'_>, usize) { - fn peel(ty: Ty<'_>, count: usize) -> (Ty<'_>, usize) { - if let ty::Ref(_, ty, _) = ty.kind() { - peel(*ty, count + 1) - } else { - (ty, count) - } - } - peel(ty, 0) -} - /// Peels off all references on the type. Returns the underlying type, the number of references /// removed, and whether the pointer is ultimately mutable or not. pub fn peel_mid_ty_refs_is_mutable(ty: Ty<'_>) -> (Ty<'_>, usize, Mutability) { From 29f5d8f00f5c0287e8991d5818bd87942e6f4563 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 17 Jul 2024 18:17:30 -0400 Subject: [PATCH 029/786] Don't elaborate associated types with Sized bounds in trait_object_ty in cfi --- .../cfi/typeid/itanium_cxx_abi/transform.rs | 1 + tests/ui/sanitizer/cfi-sized-associated-ty.rs | 38 +++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 tests/ui/sanitizer/cfi-sized-associated-ty.rs 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 f0f2d1fefd2f3..7ed36e8598950 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 @@ -230,6 +230,7 @@ fn trait_object_ty<'tcx>(tcx: TyCtxt<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tc tcx.associated_items(super_poly_trait_ref.def_id()) .in_definition_order() .filter(|item| item.kind == ty::AssocKind::Type) + .filter(|item| !tcx.generics_require_sized_self(item.def_id)) .map(move |assoc_ty| { super_poly_trait_ref.map_bound(|super_trait_ref| { let alias_ty = diff --git a/tests/ui/sanitizer/cfi-sized-associated-ty.rs b/tests/ui/sanitizer/cfi-sized-associated-ty.rs new file mode 100644 index 0000000000000..f5b4e22e9d99b --- /dev/null +++ b/tests/ui/sanitizer/cfi-sized-associated-ty.rs @@ -0,0 +1,38 @@ +// Check that we only elaborate non-`Self: Sized` associated types when +// erasing the receiver from trait ref. + +//@ revisions: cfi kcfi +// FIXME(#122848) Remove only-linux once OSX CFI binaries work +//@ only-linux +//@ [cfi] needs-sanitizer-cfi +//@ [kcfi] needs-sanitizer-kcfi +//@ compile-flags: -C target-feature=-crt-static +//@ [cfi] compile-flags: -C codegen-units=1 -C lto -C prefer-dynamic=off -C opt-level=0 +//@ [cfi] compile-flags: -Z sanitizer=cfi +//@ [kcfi] compile-flags: -Z sanitizer=kcfi +//@ [kcfi] compile-flags: -C panic=abort -C prefer-dynamic=off +//@ run-pass + +trait Foo { + type Bar<'a> + where + Self: Sized; + + fn test(&self); +} + +impl Foo for () { + type Bar<'a> = () + where + Self: Sized; + + fn test(&self) {} +} + +fn test(x: &dyn Foo) { + x.test(); +} + +fn main() { + test(&()); +} From 9946a68275dc37ef1c7d1727a7876d65646bee44 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 29 May 2024 23:40:58 +0200 Subject: [PATCH 030/786] Add copy code button --- src/librustdoc/html/static/css/rustdoc.css | 82 +++++++++++++++----- src/librustdoc/html/static/js/main.js | 90 +++++++++++++++++----- 2 files changed, 132 insertions(+), 40 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index cb8b82e8bde0a..aabbd21d70261 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -16,6 +16,28 @@ --src-sidebar-width: 300px; --desktop-sidebar-z-index: 100; --sidebar-elems-left-padding: 24px; + /* clipboard */ + --clipboard-image: url('data:image/svg+xml,\ +\ +\ +'); + --clipboard-image-big: url('data:image/svg+xml,\ +\ +\ +'); + /* Checkmark */ + --checkmark-image: url('data:image/svg+xml,\ +\ +'); } /* See FiraSans-LICENSE.txt for the Fira Sans license. */ @@ -1423,15 +1445,17 @@ documentation. */ top: 20px; } -a.test-arrow { +.example-wrap > a.test-arrow, .example-wrap .button-holder { visibility: hidden; position: absolute; - padding: 5px 10px 5px 10px; - border-radius: 5px; - font-size: 1.375rem; top: 5px; right: 5px; z-index: 1; +} +a.test-arrow { + padding: 5px 10px 5px 10px; + border-radius: 5px; + font-size: 1.375rem; color: var(--test-arrow-color); background-color: var(--test-arrow-background-color); } @@ -1439,9 +1463,41 @@ a.test-arrow:hover { color: var(--test-arrow-hover-color); background-color: var(--test-arrow-hover-background-color); } -.example-wrap:hover .test-arrow { +.example-wrap .button-holder { + display: flex; +} +.example-wrap:hover > .test-arrow { + padding: 3px 10px; +} +.example-wrap:hover > .test-arrow, .example-wrap:hover > .button-holder { visibility: visible; } +.example-wrap .button-holder .copy-button { + color: var(--copy-path-button-color); + background: var(--main-background-color); + height: 43px; + width: 40px; + margin-left: 5px; + padding: 2px 0 0 4px; + border: 0; + cursor: pointer; + border-radius: 5px; +} +.example-wrap .button-holder .copy-button.clicked { + padding-top: 4px; +} +.example-wrap .button-holder .copy-button::before { + filter: var(--copy-path-img-filter); + content: var(--clipboard-image-big); + width: 23px; + height: 22px; +} +.example-wrap .button-holder .copy-button:hover::before { + filter: var(--copy-path-img-hover-filter); +} +.example-wrap .button-holder .copy-button.clicked::before { + content: var(--checkmark-image); +} .code-attribute { font-weight: 300; @@ -1699,15 +1755,7 @@ a.tooltip:hover::after { } #copy-path::before { filter: var(--copy-path-img-filter); - /* clipboard */ - content: url('data:image/svg+xml,\ -\ -\ -'); + content: var(--clipboard-image); width: 19px; height: 18px; } @@ -1715,11 +1763,7 @@ xmlns="http://www.w3.org/2000/svg" aria-label="Copy to clipboard">\ filter: var(--copy-path-img-hover-filter); } #copy-path.clicked::before { - /* Checkmark */ - content: url('data:image/svg+xml,\ - \ - '); + content: var(--checkmark-image); } @keyframes rotating { diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 64c356607788c..c2c1c5dd8047b 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -1769,9 +1769,37 @@ href="https://doc.rust-lang.org/${channel}/rustdoc/read-documentation/search.htm }()); // This section handles the copy button that appears next to the path breadcrumbs +// and the copy buttons on the code examples. (function() { - let reset_button_timeout = null; + // Common functions to copy buttons. + function copyContentToClipboard(content) { + const el = document.createElement("textarea"); + el.value = content; + el.setAttribute("readonly", ""); + // To not make it appear on the screen. + el.style.position = "absolute"; + el.style.left = "-9999px"; + document.body.appendChild(el); + el.select(); + document.execCommand("copy"); + document.body.removeChild(el); + } + + function copyButtonAnimation(button) { + button.classList.add("clicked"); + + if (button.reset_button_timeout !== undefined) { + window.clearTimeout(button.reset_button_timeout); + } + + button.reset_button_timeout = window.setTimeout(() => { + button.reset_button_timeout = undefined; + button.classList.remove("clicked"); + }, 1000); + } + + // Copy button that appears next to the path breadcrumbs. const but = document.getElementById("copy-path"); if (!but) { return; @@ -1786,29 +1814,49 @@ href="https://doc.rust-lang.org/${channel}/rustdoc/read-documentation/search.htm } }); - const el = document.createElement("textarea"); - el.value = path.join("::"); - el.setAttribute("readonly", ""); - // To not make it appear on the screen. - el.style.position = "absolute"; - el.style.left = "-9999px"; - - document.body.appendChild(el); - el.select(); - document.execCommand("copy"); - document.body.removeChild(el); - - but.classList.add("clicked"); + copyContentToClipboard(path.join("::")); + copyButtonAnimation(but); + }; - if (reset_button_timeout !== null) { - window.clearTimeout(reset_button_timeout); + // Copy buttons on code examples. + function copyCode(codeElem) { + if (!codeElem) { + // Should never happen, but the world is a dark and dangerous place. + return; } + copyContentToClipboard(codeElem.textContent); + } - function reset_button() { - reset_button_timeout = null; - but.classList.remove("clicked"); + function addCopyButton(event) { + let elem = event.target; + while (!hasClass(elem, "example-wrap")) { + elem = elem.parentElement; + if (elem.tagName === "body" || hasClass(elem, "docblock")) { + return; + } + } + // Since the button will be added, no need to keep this listener around. + elem.removeEventListener("mouseover", addCopyButton); + + const parent = document.createElement("div"); + parent.className = "button-holder"; + const runButton = elem.querySelector(".test-arrow"); + if (runButton !== null) { + // If there is a run button, we move it into the same div. + parent.appendChild(runButton); } + elem.appendChild(parent); + const copyButton = document.createElement("button"); + copyButton.className = "copy-button"; + copyButton.title = "Copy code to clipboard"; + copyButton.addEventListener("click", () => { + copyCode(elem.querySelector("pre > code")); + copyButtonAnimation(copyButton); + }); + parent.appendChild(copyButton); + } - reset_button_timeout = window.setTimeout(reset_button, 1000); - }; + onEachLazy(document.querySelectorAll(".docblock .example-wrap"), elem => { + elem.addEventListener("mouseover", addCopyButton); + }); }()); From ddaa90fc56bf4b047061a9639097083a61155b8c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 30 May 2024 18:20:28 +0200 Subject: [PATCH 031/786] Add rustdoc GUI test for new copy code feature --- tests/rustdoc-gui/copy-code.goml | 48 ++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 tests/rustdoc-gui/copy-code.goml diff --git a/tests/rustdoc-gui/copy-code.goml b/tests/rustdoc-gui/copy-code.goml new file mode 100644 index 0000000000000..726f9bba9b644 --- /dev/null +++ b/tests/rustdoc-gui/copy-code.goml @@ -0,0 +1,48 @@ +// Checks that the "copy code" button is not triggering JS error and its display +// isn't broken. +go-to: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html" + +define-function: ( + "check-copy-button", + [], + block { + // First we ensure that there are no "copy code" currently existing. + assert-count: (".example-wrap .copy-button", 0) + move-cursor-to: ".example-wrap" + assert-count: (".example-wrap .copy-button", 1) + // We now ensure it's only displayed when the example is hovered. + assert-css: (".example-wrap .copy-button", { "visibility": "visible" }) + move-cursor-to: ".search-input" + assert-css: (".example-wrap .copy-button", { "visibility": "hidden" }) + }, +) + +call-function: ("check-copy-button", {}) +// Checking that the run button and the copy button have the same height. +compare-elements-size: ( + ".example-wrap:nth-of-type(1) .test-arrow", + ".example-wrap:nth-of-type(1) .copy-button", + ["height"], +) +// ... and the same y position. +compare-elements-position: ( + ".example-wrap:nth-of-type(1) .test-arrow", + ".example-wrap:nth-of-type(1) .copy-button", + ["y"], +) +store-size: (".example-wrap:nth-of-type(1) .copy-button", { + "height": copy_height, + "width": copy_width, +}) +assert: |copy_height| > 0 && |copy_width| > 0 + +// Checking same things for the copy button when there is no run button. +go-to: "file://" + |DOC_PATH| + "/lib2/sub_mod/struct.Foo.html" +call-function: ("check-copy-button", {}) +// Ensure there is no run button. +assert-count: (".example-wrap .test-arrow", 0) +// Check it's the same size without a run button. +assert-size: (".example-wrap:nth-of-type(1) .copy-button", { + "height": |copy_height|, + "width": |copy_width|, +}) From 578810b4d21875ca05c89b3b6982c4bb952ba34d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 3 Jun 2024 09:55:11 +0200 Subject: [PATCH 032/786] Make "copy code" button the same size as the "copy path" button --- src/librustdoc/html/static/css/rustdoc.css | 34 +++++++--------------- tests/rustdoc-gui/copy-code.goml | 6 ++++ tests/rustdoc-gui/run-on-hover.goml | 4 +-- 3 files changed, 19 insertions(+), 25 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index aabbd21d70261..821e6379e2add 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -25,14 +25,8 @@ xmlns="http://www.w3.org/2000/svg" aria-label="Copy to clipboard">\ 2s-1.75.755-1.75 1.667c0 .911-.793 1.666-1.75 1.666H4.75C3.793 5.333 3 6.09 3 7z"/>\ \ '); - --clipboard-image-big: url('data:image/svg+xml,\ -\ -\ -'); + --copy-path-height: 34px; + --copy-path-width: 33px; /* Checkmark */ --checkmark-image: url('data:image/svg+xml,\ @@ -1453,9 +1447,9 @@ documentation. */ z-index: 1; } a.test-arrow { - padding: 5px 10px 5px 10px; + padding: 5px 7px; border-radius: 5px; - font-size: 1.375rem; + font-size: 1rem; color: var(--test-arrow-color); background-color: var(--test-arrow-background-color); } @@ -1467,7 +1461,7 @@ a.test-arrow:hover { display: flex; } .example-wrap:hover > .test-arrow { - padding: 3px 10px; + padding: 2px 7px; } .example-wrap:hover > .test-arrow, .example-wrap:hover > .button-holder { visibility: visible; @@ -1475,28 +1469,24 @@ a.test-arrow:hover { .example-wrap .button-holder .copy-button { color: var(--copy-path-button-color); background: var(--main-background-color); - height: 43px; - width: 40px; + height: var(--copy-path-height); + width: var(--copy-path-width); margin-left: 5px; padding: 2px 0 0 4px; border: 0; cursor: pointer; border-radius: 5px; } -.example-wrap .button-holder .copy-button.clicked { - padding-top: 4px; -} .example-wrap .button-holder .copy-button::before { filter: var(--copy-path-img-filter); - content: var(--clipboard-image-big); - width: 23px; - height: 22px; + content: var(--clipboard-image); } .example-wrap .button-holder .copy-button:hover::before { filter: var(--copy-path-img-hover-filter); } .example-wrap .button-holder .copy-button.clicked::before { content: var(--checkmark-image); + padding-right: 5px; } .code-attribute { @@ -1745,8 +1735,8 @@ a.tooltip:hover::after { #copy-path { color: var(--copy-path-button-color); background: var(--main-background-color); - height: 34px; - width: 33px; + height: var(--copy-path-height); + width: var(--copy-path-width); margin-left: 10px; padding: 0; padding-left: 2px; @@ -1756,8 +1746,6 @@ a.tooltip:hover::after { #copy-path::before { filter: var(--copy-path-img-filter); content: var(--clipboard-image); - width: 19px; - height: 18px; } #copy-path:hover::before { filter: var(--copy-path-img-hover-filter); diff --git a/tests/rustdoc-gui/copy-code.goml b/tests/rustdoc-gui/copy-code.goml index 726f9bba9b644..72a5bece1758c 100644 --- a/tests/rustdoc-gui/copy-code.goml +++ b/tests/rustdoc-gui/copy-code.goml @@ -14,6 +14,12 @@ define-function: ( assert-css: (".example-wrap .copy-button", { "visibility": "visible" }) move-cursor-to: ".search-input" assert-css: (".example-wrap .copy-button", { "visibility": "hidden" }) + // Checking that the copy button has the same size as the "copy path" button. + compare-elements-size: ( + "#copy-path", + ".example-wrap:nth-of-type(1) .copy-button", + ["height", "width"], + ) }, ) diff --git a/tests/rustdoc-gui/run-on-hover.goml b/tests/rustdoc-gui/run-on-hover.goml index 087dd3374f803..1698a61b14728 100644 --- a/tests/rustdoc-gui/run-on-hover.goml +++ b/tests/rustdoc-gui/run-on-hover.goml @@ -17,7 +17,7 @@ define-function: ( "visibility": "visible", "color": |color|, "background-color": |background|, - "font-size": "22px", + "font-size": "16px", "border-radius": "5px", }) move-cursor-to: ".test-arrow" @@ -25,7 +25,7 @@ define-function: ( "visibility": "visible", "color": |hover_color|, "background-color": |hover_background|, - "font-size": "22px", + "font-size": "16px", "border-radius": "5px", }) }, From 26d72512e0c7e9077134173aa60d77ba08ac3e9a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 3 Jun 2024 21:27:29 +0200 Subject: [PATCH 033/786] Unify UI between code block buttons and top buttons --- src/librustdoc/html/static/css/rustdoc.css | 21 ++++++++++++++------- tests/rustdoc-gui/run-on-hover.goml | 4 ++-- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 821e6379e2add..8b8f596bdeb8e 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -32,6 +32,8 @@ xmlns="http://www.w3.org/2000/svg" aria-label="Copy to clipboard">\ xmlns="http://www.w3.org/2000/svg" fill="black" height="18px">\ \ '); + --button-left-margin: 4px; + --button-border-radius: 2px; } /* See FiraSans-LICENSE.txt for the Fira Sans license. */ @@ -740,6 +742,11 @@ ul.block, .block li { position: relative; margin-bottom: 10px; } + +.rustdoc .example-wrap > pre { + border-radius: 6px; +} + /* For the last child of a div, the margin will be taken care of by the margin-top of the next item. */ .rustdoc .example-wrap:last-child { @@ -1442,13 +1449,13 @@ documentation. */ .example-wrap > a.test-arrow, .example-wrap .button-holder { visibility: hidden; position: absolute; - top: 5px; - right: 5px; + top: 4px; + right: 4px; z-index: 1; } a.test-arrow { padding: 5px 7px; - border-radius: 5px; + border-radius: var(--button-border-radius); font-size: 1rem; color: var(--test-arrow-color); background-color: var(--test-arrow-background-color); @@ -1471,11 +1478,11 @@ a.test-arrow:hover { background: var(--main-background-color); height: var(--copy-path-height); width: var(--copy-path-width); - margin-left: 5px; + margin-left: var(--button-left-margin); padding: 2px 0 0 4px; border: 0; cursor: pointer; - border-radius: 5px; + border-radius: var(--button-border-radius); } .example-wrap .button-holder .copy-button::before { filter: var(--copy-path-img-filter); @@ -1652,7 +1659,7 @@ a.tooltip:hover::after { } #settings-menu, #help-button { - margin-left: 4px; + margin-left: var(--button-left-margin); display: flex; } #sidebar-button { @@ -1683,7 +1690,7 @@ a.tooltip:hover::after { justify-content: center; background-color: var(--button-background-color); border: 1px solid var(--border-color); - border-radius: 2px; + border-radius: var(--button-border-radius); color: var(--settings-button-color); /* Rare exception to specifying font sizes in rem. Since this is acting as an icon, it's okay to specify their sizes in pixels. */ diff --git a/tests/rustdoc-gui/run-on-hover.goml b/tests/rustdoc-gui/run-on-hover.goml index 1698a61b14728..b62da79b780e9 100644 --- a/tests/rustdoc-gui/run-on-hover.goml +++ b/tests/rustdoc-gui/run-on-hover.goml @@ -18,7 +18,7 @@ define-function: ( "color": |color|, "background-color": |background|, "font-size": "16px", - "border-radius": "5px", + "border-radius": "2px", }) move-cursor-to: ".test-arrow" assert-css: (".test-arrow:hover", { @@ -26,7 +26,7 @@ define-function: ( "color": |hover_color|, "background-color": |hover_background|, "font-size": "16px", - "border-radius": "5px", + "border-radius": "2px", }) }, ) From 58027e265793d632597330ae2209c11b98bd9ed5 Mon Sep 17 00:00:00 2001 From: apoisternex Date: Thu, 18 Jul 2024 15:23:04 -0300 Subject: [PATCH 034/786] Fix [`redundant_slicing`] when the slice is behind a mutable reference Fixes #12751 changelog: Fix [`redundant_slicing`] when the slice is behind a mutable reference --- clippy_lints/src/redundant_slicing.rs | 7 +++++-- tests/ui/deref_by_slicing.fixed | 4 ++++ tests/ui/deref_by_slicing.rs | 4 ++++ tests/ui/deref_by_slicing.stderr | 8 +++++++- 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/redundant_slicing.rs b/clippy_lints/src/redundant_slicing.rs index 82f22ad693d78..7470ff754b5a8 100644 --- a/clippy_lints/src/redundant_slicing.rs +++ b/clippy_lints/src/redundant_slicing.rs @@ -113,8 +113,11 @@ impl<'tcx> LateLintPass<'tcx> for RedundantSlicing { a.kind, Adjust::Borrow(AutoBorrow::Ref(_, AutoBorrowMutability::Mut { .. })) ) - }) { - // The slice was used to make a temporary reference. + }) || (matches!( + cx.typeck_results().expr_ty(indexed).ref_mutability(), + Some(Mutability::Mut) + ) && mutability == Mutability::Not) + { (DEREF_BY_SLICING_LINT, "&*", "reborrow the original value instead") } else if deref_count != 0 { (DEREF_BY_SLICING_LINT, "", "dereference the original value instead") diff --git a/tests/ui/deref_by_slicing.fixed b/tests/ui/deref_by_slicing.fixed index a3c2e84566681..87b33b1f881d8 100644 --- a/tests/ui/deref_by_slicing.fixed +++ b/tests/ui/deref_by_slicing.fixed @@ -25,4 +25,8 @@ fn main() { let bytes: &[u8] = &[]; let _ = (&*bytes).read_to_end(&mut vec![]).unwrap(); // Err, re-borrows slice + + // issue 12751 + let a = &mut [1, 2, 3][..]; + let _ = &*a; } diff --git a/tests/ui/deref_by_slicing.rs b/tests/ui/deref_by_slicing.rs index 5b4a73712ee6e..8d8882a1781e8 100644 --- a/tests/ui/deref_by_slicing.rs +++ b/tests/ui/deref_by_slicing.rs @@ -25,4 +25,8 @@ fn main() { let bytes: &[u8] = &[]; let _ = (&bytes[..]).read_to_end(&mut vec![]).unwrap(); // Err, re-borrows slice + + // issue 12751 + let a = &mut [1, 2, 3][..]; + let _ = &a[..]; } diff --git a/tests/ui/deref_by_slicing.stderr b/tests/ui/deref_by_slicing.stderr index 17b00610899d6..ceb9ab6db73dc 100644 --- a/tests/ui/deref_by_slicing.stderr +++ b/tests/ui/deref_by_slicing.stderr @@ -55,5 +55,11 @@ error: slicing when dereferencing would work LL | let _ = (&bytes[..]).read_to_end(&mut vec![]).unwrap(); // Err, re-borrows slice | ^^^^^^^^^^^^ help: reborrow the original value instead: `(&*bytes)` -error: aborting due to 9 previous errors +error: slicing when dereferencing would work + --> tests/ui/deref_by_slicing.rs:31:13 + | +LL | let _ = &a[..]; + | ^^^^^^ help: reborrow the original value instead: `&*a` + +error: aborting due to 10 previous errors From 462a48e1e731467154ae752a0548e1fdb3a36400 Mon Sep 17 00:00:00 2001 From: Ana Hobden Date: Thu, 18 Jul 2024 06:52:16 -0700 Subject: [PATCH 035/786] Add new maintainers --- src/doc/rustc/src/SUMMARY.md | 1 + .../src/platform-support/riscv64gc-unknown-linux-gnu.md | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 1a8ff931f0177..8aaa129c5899d 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -65,6 +65,7 @@ - [riscv32im-risc0-zkvm-elf](platform-support/riscv32im-risc0-zkvm-elf.md) - [riscv32imac-unknown-xous-elf](platform-support/riscv32imac-unknown-xous-elf.md) - [riscv32*-unknown-none-elf](platform-support/riscv32-unknown-none-elf.md) + - [riscv64gc-unknown-linux-gnu](platform-support/riscv64gc-unknown-linux-gnu.md) - [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md) - [*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md) - [\*-nto-qnx-\*](platform-support/nto-qnx.md) diff --git a/src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-gnu.md b/src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-gnu.md index 21d547f5aaba7..1acc0584be91b 100644 --- a/src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-gnu.md +++ b/src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-gnu.md @@ -7,8 +7,10 @@ RISC-V targets using the *RV64I* base instruction set with the *G* collection of ## Target maintainers -- TODO - +- Kito Cheng, , [@kito-cheng](https://github.com/kito-cheng) +- Michael Maitland, , [@michaelmaitland](https://github.com/michaelmaitland) +- Robin Randhawa, , [@robin-randhawa-sifive](https://github.com/robin-randhawa-sifive) +- Craig Topper, , [@topperc](https://github.com/topperc) ## Requirements From c1c13bd07ca476c0d9b53b0fa1384ea8a83962e3 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Fri, 19 Jul 2024 11:51:21 -0400 Subject: [PATCH 036/786] Avoid ref when using format! in compiler Clean up a few minor refs in `format!` macro, as it has a performance cost. Apparently the compiler is unable to inline `format!("{}", &variable)`, and does a run-time double-reference instead (format macro already does one level referencing). Inlining format args prevents accidental `&` misuse. --- src/abi/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/abi/mod.rs b/src/abi/mod.rs index fa0de6f9de5ea..ac5aaea561cca 100644 --- a/src/abi/mod.rs +++ b/src/abi/mod.rs @@ -505,7 +505,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( let nop_inst = fx.bcx.ins().nop(); fx.add_comment( nop_inst, - format!("virtual call; self arg pass mode: {:?}", &fn_abi.args[0]), + format!("virtual call; self arg pass mode: {:?}", fn_abi.args[0]), ); } From 266abf3c08203d0ae7bf6d0ba18db5a6df2fd1c2 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Fri, 19 Jul 2024 16:10:24 -0400 Subject: [PATCH 037/786] Avoid ref when using format! Clean up a few minor refs in `format!` macro, as it has a performance cost. Apparently the compiler is unable to inline `format!("{}", &variable)`, and does a run-time double-reference instead (format macro already does one level referencing). Inlining format args prevents accidental `&` misuse. --- clippy_lints/src/approx_const.rs | 2 +- clippy_lints/src/default.rs | 2 +- clippy_lints/src/methods/open_options.rs | 2 +- clippy_lints/src/methods/wrong_self_convention.rs | 2 +- clippy_lints/src/no_effect.rs | 2 +- clippy_lints/src/types/borrowed_box.rs | 6 +++--- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index e6d52bcef717c..3b4cc1134802d 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -97,7 +97,7 @@ impl ApproxConstant { cx, APPROX_CONSTANT, e.span, - format!("approximate value of `{module}::consts::{}` found", &name), + format!("approximate value of `{module}::consts::{name}` found"), None, "consider using the constant directly", ); diff --git a/clippy_lints/src/default.rs b/clippy_lints/src/default.rs index 72fa05be3cc60..0b7279f2b360d 100644 --- a/clippy_lints/src/default.rs +++ b/clippy_lints/src/default.rs @@ -221,7 +221,7 @@ impl<'tcx> LateLintPass<'tcx> for Default { .map(ToString::to_string) .collect::>() .join(", "); - format!("{adt_def_ty_name}::<{}>", &tys_str) + format!("{adt_def_ty_name}::<{tys_str}>") } else { binding_type.to_string() }; diff --git a/clippy_lints/src/methods/open_options.rs b/clippy_lints/src/methods/open_options.rs index d425b505a760c..cbeb48b6cc376 100644 --- a/clippy_lints/src/methods/open_options.rs +++ b/clippy_lints/src/methods/open_options.rs @@ -151,7 +151,7 @@ fn check_open_options(cx: &LateContext<'_>, settings: &[(OpenOption, Argument, S cx, NONSENSICAL_OPEN_OPTIONS, prev_span, - format!("the method `{}` is called more than once", &option), + format!("the method `{option}` is called more than once"), ); } } diff --git a/clippy_lints/src/methods/wrong_self_convention.rs b/clippy_lints/src/methods/wrong_self_convention.rs index 28068c6347325..7384e534ed7d7 100644 --- a/clippy_lints/src/methods/wrong_self_convention.rs +++ b/clippy_lints/src/methods/wrong_self_convention.rs @@ -127,7 +127,7 @@ pub(super) fn check<'tcx>( .collect::>() .join(" and "); - format!("methods with the following characteristics: ({})", &s) + format!("methods with the following characteristics: ({s})") } else { format!("methods called {}", &conventions[0]) } diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index 0ecfa7baa72d4..837e8b9028de2 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -272,7 +272,7 @@ fn check_unnecessary_operation(cx: &LateContext<'_>, stmt: &Stmt<'_>) { } let snippet = if let (Some(arr), Some(func)) = (snippet_opt(cx, reduced[0].span), snippet_opt(cx, reduced[1].span)) { - format!("assert!({}.len() > {});", &arr, &func) + format!("assert!({arr}.len() > {func});") } else { return; }; diff --git a/clippy_lints/src/types/borrowed_box.rs b/clippy_lints/src/types/borrowed_box.rs index 801e886261993..89ba33583d6cd 100644 --- a/clippy_lints/src/types/borrowed_box.rs +++ b/clippy_lints/src/types/borrowed_box.rs @@ -48,15 +48,15 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, m let inner_snippet = snippet(cx, inner.span, ".."); let suggestion = match &inner.kind { TyKind::TraitObject(bounds, lt_bound, _) if bounds.len() > 1 || !lt_bound.is_elided() => { - format!("&{ltopt}({})", &inner_snippet) + format!("&{ltopt}({inner_snippet})") }, TyKind::Path(qpath) if get_bounds_if_impl_trait(cx, qpath, inner.hir_id) .map_or(false, |bounds| bounds.len() > 1) => { - format!("&{ltopt}({})", &inner_snippet) + format!("&{ltopt}({inner_snippet})") }, - _ => format!("&{ltopt}{}", &inner_snippet), + _ => format!("&{ltopt}{inner_snippet}"), }; span_lint_and_sugg( cx, From e5544dc087acc760d987781f48680ce505c1855f Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Sat, 20 Jul 2024 05:04:25 +0000 Subject: [PATCH 038/786] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 2c29af8b9357f..b09d4f11f68ef 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -5c8488605624d67b272953bc21d41db60dbd5654 +9057c3ffec44926d5e149dc13ff3ce1613b69cce From b929b68a5ba4570e15637b12d9e687a2ba6673d8 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 20 Jul 2024 15:26:46 +0200 Subject: [PATCH 039/786] Remove the RUSTFLAGS enable method from Readme.md It is a worse option than using `CARGO_PROFILE_DEV_CODEGEN_BACKEND`. When using `--target` it doesn't apply to build scripts and proc macros. It also overrides any `RUSTFLAGS` you may have set in an env var or cargo config. --- Readme.md | 1 - 1 file changed, 1 deletion(-) diff --git a/Readme.md b/Readme.md index eb21e027dd0e0..29050e8b5b4f2 100644 --- a/Readme.md +++ b/Readme.md @@ -16,7 +16,6 @@ $ rustup component add rustc-codegen-cranelift-preview --toolchain nightly Once it is installed, you can enable it with one of the following approaches: - `CARGO_PROFILE_DEV_CODEGEN_BACKEND=cranelift cargo +nightly build -Zcodegen-backend` -- `RUSTFLAGS="-Zcodegen-backend=cranelift" cargo +nightly build` - Add the following to `.cargo/config.toml`: ```toml [unstable] From b70ad2defd4bb5fba6af7958893e22be0f33dfdd Mon Sep 17 00:00:00 2001 From: beetrees Date: Sat, 20 Jul 2024 17:03:35 +0100 Subject: [PATCH 040/786] Remove unneeded libcalls from `codegen_i128.rs` --- src/codegen_i128.rs | 27 ++++----------------------- src/compiler_builtins.rs | 6 ------ 2 files changed, 4 insertions(+), 29 deletions(-) diff --git a/src/codegen_i128.rs b/src/codegen_i128.rs index e16b77648d12f..b6a4769e03114 100644 --- a/src/codegen_i128.rs +++ b/src/codegen_i128.rs @@ -23,19 +23,7 @@ pub(crate) fn maybe_codegen<'tcx>( match bin_op { BinOp::BitAnd | BinOp::BitOr | BinOp::BitXor => None, BinOp::Add | BinOp::AddUnchecked | BinOp::Sub | BinOp::SubUnchecked => None, - BinOp::Mul | BinOp::MulUnchecked => { - let args = [lhs.load_scalar(fx), rhs.load_scalar(fx)]; - let ret_val = fx.lib_call( - "__multi3", - vec![AbiParam::new(types::I128), AbiParam::new(types::I128)], - vec![AbiParam::new(types::I128)], - &args, - )[0]; - Some(CValue::by_val( - ret_val, - fx.layout_of(if is_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 }), - )) - } + BinOp::Mul | BinOp::MulUnchecked => None, BinOp::Offset => unreachable!("offset should only be used on pointers, not 128bit ints"), BinOp::Div | BinOp::Rem => { let name = match (bin_op, is_signed) { @@ -92,6 +80,7 @@ pub(crate) fn maybe_codegen_checked<'tcx>( match bin_op { BinOp::BitAnd | BinOp::BitOr | BinOp::BitXor => unreachable!(), + BinOp::Add | BinOp::Sub => None, BinOp::Mul if is_signed => { let out_ty = Ty::new_tup(fx.tcx, &[lhs.layout().ty, fx.tcx.types.bool]); let oflow = CPlace::new_stack_slot(fx, fx.layout_of(fx.tcx.types.i32)); @@ -112,7 +101,7 @@ pub(crate) fn maybe_codegen_checked<'tcx>( let oflow = fx.bcx.ins().ireduce(types::I8, oflow); Some(CValue::by_val_pair(res, oflow, fx.layout_of(out_ty))) } - BinOp::Add | BinOp::Sub | BinOp::Mul => { + BinOp::Mul => { let out_ty = Ty::new_tup(fx.tcx, &[lhs.layout().ty, fx.tcx.types.bool]); let out_place = CPlace::new_stack_slot(fx, fx.layout_of(out_ty)); let param_types = vec![ @@ -121,15 +110,7 @@ pub(crate) fn maybe_codegen_checked<'tcx>( AbiParam::new(types::I128), ]; let args = [out_place.to_ptr().get_addr(fx), lhs.load_scalar(fx), rhs.load_scalar(fx)]; - let name = match (bin_op, is_signed) { - (BinOp::Add, false) => "__rust_u128_addo", - (BinOp::Add, true) => "__rust_i128_addo", - (BinOp::Sub, false) => "__rust_u128_subo", - (BinOp::Sub, true) => "__rust_i128_subo", - (BinOp::Mul, false) => "__rust_u128_mulo", - _ => unreachable!(), - }; - fx.lib_call(name, param_types, vec![], &args); + fx.lib_call("__rust_u128_mulo", param_types, vec![], &args); Some(out_place.to_cvalue(fx)) } BinOp::AddUnchecked | BinOp::SubUnchecked | BinOp::MulUnchecked => unreachable!(), diff --git a/src/compiler_builtins.rs b/src/compiler_builtins.rs index f3b963200a0fb..4154a62234c12 100644 --- a/src/compiler_builtins.rs +++ b/src/compiler_builtins.rs @@ -38,18 +38,12 @@ builtin_functions! { register_functions_for_jit; // integers - fn __multi3(a: i128, b: i128) -> i128; fn __muloti4(n: i128, d: i128, oflow: &mut i32) -> i128; fn __udivti3(n: u128, d: u128) -> u128; fn __divti3(n: i128, d: i128) -> i128; fn __umodti3(n: u128, d: u128) -> u128; fn __modti3(n: i128, d: i128) -> i128; - fn __rust_u128_addo(a: u128, b: u128) -> (u128, bool); - fn __rust_i128_addo(a: i128, b: i128) -> (i128, bool); - fn __rust_u128_subo(a: u128, b: u128) -> (u128, bool); - fn __rust_i128_subo(a: i128, b: i128) -> (i128, bool); fn __rust_u128_mulo(a: u128, b: u128) -> (u128, bool); - fn __rust_i128_mulo(a: i128, b: i128) -> (i128, bool); // floats fn __floattisf(i: i128) -> f32; From 468f9358f3f73db9a0ea6dc1a94320177718061a Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sun, 21 Jul 2024 09:43:06 +0100 Subject: [PATCH 041/786] std::thread: available_parallelism implementation for vxWorks proposal. --- library/std/src/sys/pal/unix/thread.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs index 619f4e4121e73..0f496a39173a0 100644 --- a/library/std/src/sys/pal/unix/thread.rs +++ b/library/std/src/sys/pal/unix/thread.rs @@ -462,8 +462,18 @@ pub fn available_parallelism() -> io::Result> { Ok(NonZero::new_unchecked(sinfo.cpu_count as usize)) } + } else if #[cfg(target_os = "vxworks")] { + // Note: there is also `vxCpuConfiguredGet`, closer to _SC_NPROCESSORS_CONF + // expectations than the actual cores availability. + extern "C" { + fn vxCpuEnabledGet() -> libc::cpuset_t; + } + + // always fetches a valid bitmask + let set = unsafe { vxCpuEnabledGet() }; + Ok(NonZero::new_unchecked(set.count_ones() as usize)) } else { - // FIXME: implement on vxWorks, Redox, l4re + // FIXME: implement on Redox, l4re Err(io::const_io_error!(io::ErrorKind::Unsupported, "Getting the number of hardware threads is not supported on the target platform")) } } From 4fb3c4bf863f2ab32fee13405f71b6785763e909 Mon Sep 17 00:00:00 2001 From: beetrees Date: Sun, 21 Jul 2024 12:13:58 +0100 Subject: [PATCH 042/786] Fix handling of large alignments in `write_cvalue_maybe_transmute` (#1521) --- src/value_and_place.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/value_and_place.rs b/src/value_and_place.rs index 1aa28daeafc7e..8eb2095e52346 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -677,8 +677,10 @@ impl<'tcx> CPlace<'tcx> { let to_addr = to_ptr.get_addr(fx); let src_layout = from.1; let size = dst_layout.size.bytes(); - let src_align = src_layout.align.abi.bytes() as u8; - let dst_align = dst_layout.align.abi.bytes() as u8; + // `emit_small_memory_copy` uses `u8` for alignments, just use the maximum + // alignment that fits in a `u8` if the actual alignment is larger. + let src_align = src_layout.align.abi.bytes().try_into().unwrap_or(128); + let dst_align = dst_layout.align.abi.bytes().try_into().unwrap_or(128); fx.bcx.emit_small_memory_copy( fx.target_config, to_addr, From 69b9eab4aba6d13c348e09190785fa9c015baae9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= Date: Mon, 22 Jul 2024 16:51:20 +0300 Subject: [PATCH 043/786] Add `O_NOFOLLOW` flag support --- src/tools/miri/src/shims/unix/fs.rs | 29 +++++++++++++++++-- ...libc-fs-readlink.rs => libc-fs-symlink.rs} | 20 +++++++++++++ src/tools/miri/tests/pass-dep/libc/libc-fs.rs | 9 ++++++ 3 files changed, 55 insertions(+), 3 deletions(-) rename src/tools/miri/tests/pass-dep/libc/{libc-fs-readlink.rs => libc-fs-symlink.rs} (76%) diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index e34aa5c09dfe1..d1218114e0d7a 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -266,7 +266,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let this = self.eval_context_mut(); - let path = this.read_pointer(&args[0])?; + let path_raw = this.read_pointer(&args[0])?; + let path = this.read_path_from_c_str(path_raw)?; let flag = this.read_scalar(&args[1])?.to_i32()?; let mut options = OpenOptions::new(); @@ -366,14 +367,36 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return Ok(-1); } } + + let o_nofollow = this.eval_libc_i32("O_NOFOLLOW"); + if flag & o_nofollow == o_nofollow { + #[cfg(unix)] + { + use std::os::unix::fs::OpenOptionsExt; + options.custom_flags(libc::O_NOFOLLOW); + } + // Strictly speaking, this emulation is not equivalent to the O_NOFOLLOW flag behavior: + // the path could change between us checking it here and the later call to `open`. + // But it's good enough for Miri purposes. + #[cfg(not(unix))] + { + // O_NOFOLLOW only fails when the trailing component is a symlink; + // the entire rest of the path can still contain symlinks. + if path.is_symlink() { + let eloop = this.eval_libc("ELOOP"); + this.set_last_error(eloop)?; + return Ok(-1); + } + } + mirror |= o_nofollow; + } + // If `flag` is not equal to `mirror`, there is an unsupported option enabled in `flag`, // then we throw an error. if flag != mirror { throw_unsup_format!("unsupported flags {:#x}", flag & !mirror); } - let path = this.read_path_from_c_str(path)?; - // Reject if isolation is enabled. if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { this.reject_in_isolation("`open`", reject_with)?; diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs-readlink.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs similarity index 76% rename from src/tools/miri/tests/pass-dep/libc/libc-fs-readlink.rs rename to src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs index d72edd7d9e3f2..96ced05cd1e8e 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs-readlink.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs @@ -11,6 +11,11 @@ use std::os::unix::ffi::OsStrExt; mod utils; fn main() { + test_readlink(); + test_nofollow_symlink(); +} + +fn test_readlink() { let bytes = b"Hello, World!\n"; let path = utils::prepare_with_content("miri_test_fs_link_target.txt", bytes); let expected_path = path.as_os_str().as_bytes(); @@ -49,3 +54,18 @@ fn main() { assert_eq!(res, -1); assert_eq!(Error::last_os_error().kind(), ErrorKind::NotFound); } + +fn test_nofollow_symlink() { + let bytes = b"Hello, World!\n"; + let path = utils::prepare_with_content("test_nofollow_symlink_target.txt", bytes); + + let symlink_path = utils::prepare("test_nofollow_symlink.txt"); + std::os::unix::fs::symlink(&path, &symlink_path).unwrap(); + + let symlink_cpath = CString::new(symlink_path.as_os_str().as_bytes()).unwrap(); + + let ret = unsafe { libc::open(symlink_cpath.as_ptr(), libc::O_NOFOLLOW | libc::O_CLOEXEC) }; + assert_eq!(ret, -1); + let err = io::Error::last_os_error().raw_os_error().unwrap(); + assert_eq!(err, libc::ELOOP); +} diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs index eddea92353e3d..5b2bbfbb27d08 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs @@ -37,6 +37,7 @@ fn main() { test_sync_file_range(); test_isatty(); test_read_and_uninit(); + test_nofollow_not_symlink(); } fn test_file_open_unix_allow_two_args() { @@ -423,3 +424,11 @@ fn test_read_and_uninit() { remove_file(&path).unwrap(); } } + +fn test_nofollow_not_symlink() { + let bytes = b"Hello, World!\n"; + let path = utils::prepare_with_content("test_nofollow_not_symlink.txt", bytes); + let cpath = CString::new(path.as_os_str().as_bytes()).unwrap(); + let ret = unsafe { libc::open(cpath.as_ptr(), libc::O_NOFOLLOW | libc::O_CLOEXEC) }; + assert!(ret >= 0); +} From 06a14f1990d9baf984a4162c32c54f707d317114 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= Date: Mon, 22 Jul 2024 17:01:11 +0300 Subject: [PATCH 044/786] Fix test --- src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs index 96ced05cd1e8e..619c6db3a29de 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs @@ -66,6 +66,6 @@ fn test_nofollow_symlink() { let ret = unsafe { libc::open(symlink_cpath.as_ptr(), libc::O_NOFOLLOW | libc::O_CLOEXEC) }; assert_eq!(ret, -1); - let err = io::Error::last_os_error().raw_os_error().unwrap(); + let err = Error::last_os_error().raw_os_error().unwrap(); assert_eq!(err, libc::ELOOP); } From 56d672e8f7605af25dcce6483a3dda9a3ae29e54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= Date: Mon, 22 Jul 2024 18:51:36 +0300 Subject: [PATCH 045/786] Add `pread` and `pwrite` shims --- src/tools/miri/src/shims/unix/fd.rs | 93 +++++++++++++++---- .../miri/src/shims/unix/foreign_items.rs | 44 ++++++++- src/tools/miri/src/shims/unix/fs.rs | 48 ++++++++++ src/tools/miri/tests/pass/shims/fs.rs | 41 ++++++++ 4 files changed, 205 insertions(+), 21 deletions(-) diff --git a/src/tools/miri/src/shims/unix/fd.rs b/src/tools/miri/src/shims/unix/fd.rs index 8fb046b5e64cf..de6d27f5290db 100644 --- a/src/tools/miri/src/shims/unix/fd.rs +++ b/src/tools/miri/src/shims/unix/fd.rs @@ -36,6 +36,30 @@ pub trait FileDescription: std::fmt::Debug + Any { throw_unsup_format!("cannot write to {}", self.name()); } + /// Reads as much as possible into the given buffer from a given offset, + /// and returns the number of bytes read. + fn pread<'tcx>( + &mut self, + _communicate_allowed: bool, + _bytes: &mut [u8], + _offset: u64, + _ecx: &mut MiriInterpCx<'tcx>, + ) -> InterpResult<'tcx, io::Result> { + throw_unsup_format!("cannot pread from {}", self.name()); + } + + /// Writes as much as possible from the given buffer starting at a given offset, + /// and returns the number of bytes written. + fn pwrite<'tcx>( + &mut self, + _communicate_allowed: bool, + _bytes: &[u8], + _offset: u64, + _ecx: &mut MiriInterpCx<'tcx>, + ) -> InterpResult<'tcx, io::Result> { + throw_unsup_format!("cannot pwrite to {}", self.name()); + } + /// Seeks to the given offset (which can be relative to the beginning, end, or current position). /// Returns the new position from the start of the stream. fn seek<'tcx>( @@ -380,7 +404,18 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Ok((-1).into()) } - fn read(&mut self, fd: i32, buf: Pointer, count: u64) -> InterpResult<'tcx, i64> { + /// Read data from `fd` into buffer specified by `buf` and `count`. + /// + /// If `offset` is `None`, reads data from current cursor position associated with `fd` + /// and updates cursor position on completion. Otherwise, reads from the specified offset + /// and keeps the cursor unchanged. + fn read( + &mut self, + fd: i32, + buf: Pointer, + count: u64, + offset: Option, + ) -> InterpResult<'tcx, i64> { let this = self.eval_context_mut(); // Isolation check is done via `FileDescriptor` trait. @@ -398,25 +433,31 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let communicate = this.machine.communicate(); // We temporarily dup the FD to be able to retain mutable access to `this`. - let Some(file_descriptor) = this.machine.fds.dup(fd) else { + let Some(fd) = this.machine.fds.dup(fd) else { trace!("read: FD not found"); return this.fd_not_found(); }; - trace!("read: FD mapped to {:?}", file_descriptor); + trace!("read: FD mapped to {fd:?}"); // We want to read at most `count` bytes. We are sure that `count` is not negative // because it was a target's `usize`. Also we are sure that its smaller than // `usize::MAX` because it is bounded by the host's `isize`. let mut bytes = vec![0; usize::try_from(count).unwrap()]; - // `File::read` never returns a value larger than `count`, - // so this cannot fail. - let result = file_descriptor - .borrow_mut() - .read(communicate, &mut bytes, this)? - .map(|c| i64::try_from(c).unwrap()); - drop(file_descriptor); - - match result { + let result = match offset { + None => fd.borrow_mut().read(communicate, &mut bytes, this), + Some(offset) => { + let Ok(offset) = u64::try_from(offset) else { + let einval = this.eval_libc("EINVAL"); + this.set_last_error(einval)?; + return Ok(-1); + }; + fd.borrow_mut().pread(communicate, &mut bytes, offset, this) + } + }; + drop(fd); + + // `File::read` never returns a value larger than `count`, so this cannot fail. + match result?.map(|c| i64::try_from(c).unwrap()) { Ok(read_bytes) => { // If reading to `bytes` did not fail, we write those bytes to the buffer. // Crucially, if fewer than `bytes.len()` bytes were read, only write @@ -434,7 +475,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } } - fn write(&mut self, fd: i32, buf: Pointer, count: u64) -> InterpResult<'tcx, i64> { + fn write( + &mut self, + fd: i32, + buf: Pointer, + count: u64, + offset: Option, + ) -> InterpResult<'tcx, i64> { let this = self.eval_context_mut(); // Isolation check is done via `FileDescriptor` trait. @@ -451,16 +498,24 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let bytes = this.read_bytes_ptr_strip_provenance(buf, Size::from_bytes(count))?.to_owned(); // We temporarily dup the FD to be able to retain mutable access to `this`. - let Some(file_descriptor) = this.machine.fds.dup(fd) else { + let Some(fd) = this.machine.fds.dup(fd) else { return this.fd_not_found(); }; - let result = file_descriptor - .borrow_mut() - .write(communicate, &bytes, this)? - .map(|c| i64::try_from(c).unwrap()); - drop(file_descriptor); + let result = match offset { + None => fd.borrow_mut().write(communicate, &bytes, this), + Some(offset) => { + let Ok(offset) = u64::try_from(offset) else { + let einval = this.eval_libc("EINVAL"); + this.set_last_error(einval)?; + return Ok(-1); + }; + fd.borrow_mut().pwrite(communicate, &bytes, offset, this) + } + }; + drop(fd); + let result = result?.map(|c| i64::try_from(c).unwrap()); this.try_unwrap_io_result(result) } } diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index 3a18d62203333..966e590fcc41e 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -92,7 +92,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let fd = this.read_scalar(fd)?.to_i32()?; let buf = this.read_pointer(buf)?; let count = this.read_target_usize(count)?; - let result = this.read(fd, buf, count)?; + let result = this.read(fd, buf, count, None)?; this.write_scalar(Scalar::from_target_isize(result, this), dest)?; } "write" => { @@ -101,7 +101,47 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let buf = this.read_pointer(buf)?; let count = this.read_target_usize(n)?; trace!("Called write({:?}, {:?}, {:?})", fd, buf, count); - let result = this.write(fd, buf, count)?; + let result = this.write(fd, buf, count, None)?; + // Now, `result` is the value we return back to the program. + this.write_scalar(Scalar::from_target_isize(result, this), dest)?; + } + "pread" => { + let [fd, buf, count, offset] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let fd = this.read_scalar(fd)?.to_i32()?; + let buf = this.read_pointer(buf)?; + let count = this.read_target_usize(count)?; + let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off_t").size)?; + let result = this.read(fd, buf, count, Some(offset))?; + this.write_scalar(Scalar::from_target_isize(result, this), dest)?; + } + "pwrite" => { + let [fd, buf, n, offset] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let fd = this.read_scalar(fd)?.to_i32()?; + let buf = this.read_pointer(buf)?; + let count = this.read_target_usize(n)?; + let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off_t").size)?; + trace!("Called pwrite({:?}, {:?}, {:?}, {:?})", fd, buf, count, offset); + let result = this.write(fd, buf, count, Some(offset))?; + // Now, `result` is the value we return back to the program. + this.write_scalar(Scalar::from_target_isize(result, this), dest)?; + } + "pread64" => { + let [fd, buf, count, offset] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let fd = this.read_scalar(fd)?.to_i32()?; + let buf = this.read_pointer(buf)?; + let count = this.read_target_usize(count)?; + let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off64_t").size)?; + let result = this.read(fd, buf, count, Some(offset))?; + this.write_scalar(Scalar::from_target_isize(result, this), dest)?; + } + "pwrite64" => { + let [fd, buf, n, offset] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let fd = this.read_scalar(fd)?.to_i32()?; + let buf = this.read_pointer(buf)?; + let count = this.read_target_usize(n)?; + let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off64_t").size)?; + trace!("Called pwrite64({:?}, {:?}, {:?}, {:?})", fd, buf, count, offset); + let result = this.write(fd, buf, count, Some(offset))?; // Now, `result` is the value we return back to the program. this.write_scalar(Scalar::from_target_isize(result, this), dest)?; } diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index e34aa5c09dfe1..80268ced48de7 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -49,6 +49,54 @@ impl FileDescription for FileHandle { Ok(self.file.write(bytes)) } + fn pread<'tcx>( + &mut self, + communicate_allowed: bool, + bytes: &mut [u8], + offset: u64, + _ecx: &mut MiriInterpCx<'tcx>, + ) -> InterpResult<'tcx, io::Result> { + assert!(communicate_allowed, "isolation should have prevented even opening a file"); + // Emulates pread using seek + read + seek to restore cursor position. + // Correctness of this emulation relies on sequential nature of Miri execution. + // The closure is used to emulate `try` block, since we "bubble" `io::Error` using `?`. + let mut f = || { + let cursor_pos = self.file.stream_position()?; + self.file.seek(SeekFrom::Start(offset))?; + let res = self.file.read(bytes); + // Attempt to restore cursor position even if the read has failed + self.file + .seek(SeekFrom::Start(cursor_pos)) + .expect("failed to restore file position, this shouldn't be possible"); + res + }; + Ok(f()) + } + + fn pwrite<'tcx>( + &mut self, + communicate_allowed: bool, + bytes: &[u8], + offset: u64, + _ecx: &mut MiriInterpCx<'tcx>, + ) -> InterpResult<'tcx, io::Result> { + assert!(communicate_allowed, "isolation should have prevented even opening a file"); + // Emulates pwrite using seek + write + seek to restore cursor position. + // Correctness of this emulation relies on sequential nature of Miri execution. + // The closure is used to emulate `try` block, since we "bubble" `io::Error` using `?`. + let mut f = || { + let cursor_pos = self.file.stream_position()?; + self.file.seek(SeekFrom::Start(offset))?; + let res = self.file.write(bytes); + // Attempt to restore cursor position even if the write has failed + self.file + .seek(SeekFrom::Start(cursor_pos)) + .expect("failed to restore file position, this shouldn't be possible"); + res + }; + Ok(f()) + } + fn seek<'tcx>( &mut self, communicate_allowed: bool, diff --git a/src/tools/miri/tests/pass/shims/fs.rs b/src/tools/miri/tests/pass/shims/fs.rs index 16d3e8cab30ab..70e375b098128 100644 --- a/src/tools/miri/tests/pass/shims/fs.rs +++ b/src/tools/miri/tests/pass/shims/fs.rs @@ -30,6 +30,8 @@ fn main() { test_directory(); test_canonicalize(); test_from_raw_os_error(); + #[cfg(unix)] + test_pread_pwrite(); } fn test_path_conversion() { @@ -303,3 +305,42 @@ fn test_from_raw_os_error() { // Make sure we can also format this. let _ = format!("{error:?}"); } + +#[cfg(unix)] +fn test_pread_pwrite() { + use std::os::unix::fs::FileExt; + + let bytes = b"hello world"; + let path = utils::prepare_with_content("miri_test_fs_pread_pwrite.txt", bytes); + let mut f = OpenOptions::new().read(true).write(true).open(path).unwrap(); + + let mut buf1 = [0u8; 3]; + f.seek(SeekFrom::Start(5)).unwrap(); + + // Check that we get expected result after seek + f.read_exact(&mut buf1).unwrap(); + assert_eq!(&buf1, b" wo"); + f.seek(SeekFrom::Start(5)).unwrap(); + + // Check pread + f.read_exact_at(&mut buf1, 2).unwrap(); + assert_eq!(&buf1, b"llo"); + f.read_exact_at(&mut buf1, 6).unwrap(); + assert_eq!(&buf1, b"wor"); + + // Ensure that cursor position is not changed + f.read_exact(&mut buf1).unwrap(); + assert_eq!(&buf1, b" wo"); + f.seek(SeekFrom::Start(5)).unwrap(); + + // Check pwrite + f.write_all_at(b" mo", 6).unwrap(); + + let mut buf2 = [0u8; 11]; + f.read_exact_at(&mut buf2, 0).unwrap(); + assert_eq!(&buf2, b"hello mold"); + + // Ensure that cursor position is not changed + f.read_exact(&mut buf1).unwrap(); + assert_eq!(&buf1, b" m"); +} From bc8fc6b1d8abc1c1265da805534a4f172b1fe5d9 Mon Sep 17 00:00:00 2001 From: xFrednet Date: Sun, 21 Jul 2024 19:26:53 +0200 Subject: [PATCH 046/786] Make restriction lint's use `span_lint_and_then` (i -> l) --- clippy_lints/src/asm_syntax.rs | 22 ++-- clippy_lints/src/float_literal.rs | 40 ++++--- clippy_lints/src/large_include_file.rs | 16 +-- clippy_lints/src/let_underscore.rs | 58 +++++---- .../src/operators/integer_division.rs | 14 +-- tests/ui/excessive_precision.stderr | 111 +++++++++++++++--- tests/ui/lossy_float_literal.stderr | 76 ++++++++++-- 7 files changed, 245 insertions(+), 92 deletions(-) diff --git a/clippy_lints/src/asm_syntax.rs b/clippy_lints/src/asm_syntax.rs index 0db1456d40bfc..69a8eb7d94e74 100644 --- a/clippy_lints/src/asm_syntax.rs +++ b/clippy_lints/src/asm_syntax.rs @@ -1,6 +1,6 @@ use std::fmt; -use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::diagnostics::span_lint_and_then; use rustc_ast::ast::{Expr, ExprKind, InlineAsmOptions}; use rustc_ast::{InlineAsm, Item, ItemKind}; use rustc_lint::{EarlyContext, EarlyLintPass, Lint, LintContext}; @@ -49,14 +49,10 @@ fn check_asm_syntax( }; if style == check_for { - span_lint_and_help( - cx, - lint, - span, - format!("{style} x86 assembly syntax used"), - None, - format!("use {} x86 assembly syntax", !style), - ); + #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")] + span_lint_and_then(cx, lint, span, format!("{style} x86 assembly syntax used"), |diag| { + diag.help(format!("use {} x86 assembly syntax", !style)); + }); } } } @@ -98,13 +94,13 @@ declare_lint_pass!(InlineAsmX86IntelSyntax => [INLINE_ASM_X86_INTEL_SYNTAX]); impl EarlyLintPass for InlineAsmX86IntelSyntax { fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { if let ExprKind::InlineAsm(inline_asm) = &expr.kind { - check_asm_syntax(Self::get_lints()[0], cx, inline_asm, expr.span, AsmStyle::Intel); + check_asm_syntax(INLINE_ASM_X86_INTEL_SYNTAX, cx, inline_asm, expr.span, AsmStyle::Intel); } } fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { if let ItemKind::GlobalAsm(inline_asm) = &item.kind { - check_asm_syntax(Self::get_lints()[0], cx, inline_asm, item.span, AsmStyle::Intel); + check_asm_syntax(INLINE_ASM_X86_INTEL_SYNTAX, cx, inline_asm, item.span, AsmStyle::Intel); } } } @@ -146,13 +142,13 @@ declare_lint_pass!(InlineAsmX86AttSyntax => [INLINE_ASM_X86_ATT_SYNTAX]); impl EarlyLintPass for InlineAsmX86AttSyntax { fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { if let ExprKind::InlineAsm(inline_asm) = &expr.kind { - check_asm_syntax(Self::get_lints()[0], cx, inline_asm, expr.span, AsmStyle::Att); + check_asm_syntax(INLINE_ASM_X86_ATT_SYNTAX, cx, inline_asm, expr.span, AsmStyle::Att); } } fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { if let ItemKind::GlobalAsm(inline_asm) = &item.kind { - check_asm_syntax(Self::get_lints()[0], cx, inline_asm, item.span, AsmStyle::Att); + check_asm_syntax(INLINE_ASM_X86_ATT_SYNTAX, cx, inline_asm, item.span, AsmStyle::Att); } } } diff --git a/clippy_lints/src/float_literal.rs b/clippy_lints/src/float_literal.rs index 2261fcdbdabc9..2998c6f8ae0a4 100644 --- a/clippy_lints/src/float_literal.rs +++ b/clippy_lints/src/float_literal.rs @@ -1,7 +1,7 @@ -use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::numeric_literal; use rustc_ast::ast::{self, LitFloatType, LitKind}; -use rustc_errors::Applicability; +use rustc_errors::{Applicability, SuggestionStyle}; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, FloatTy}; @@ -109,29 +109,41 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral { // If the type suffix is missing the suggestion would be // incorrectly interpreted as an integer so adding a `.0` // suffix to prevent that. - if type_suffix.is_none() { - float_str.push_str(".0"); - } - - span_lint_and_sugg( + + span_lint_and_then( cx, LOSSY_FLOAT_LITERAL, expr.span, "literal cannot be represented as the underlying type without loss of precision", - "consider changing the type or replacing it with", - numeric_literal::format(&float_str, type_suffix, true), - Applicability::MachineApplicable, + |diag| { + if type_suffix.is_none() { + float_str.push_str(".0"); + } + diag.span_suggestion_with_style( + expr.span, + "consider changing the type or replacing it with", + numeric_literal::format(&float_str, type_suffix, true), + Applicability::MachineApplicable, + SuggestionStyle::ShowAlways, + ); + }, ); } } else if digits > max as usize && float_str.len() < sym_str.len() { - span_lint_and_sugg( + span_lint_and_then( cx, EXCESSIVE_PRECISION, expr.span, "float has excessive precision", - "consider changing the type or truncating it to", - numeric_literal::format(&float_str, type_suffix, true), - Applicability::MachineApplicable, + |diag| { + diag.span_suggestion_with_style( + expr.span, + "consider changing the type or truncating it to", + numeric_literal::format(&float_str, type_suffix, true), + Applicability::MachineApplicable, + SuggestionStyle::ShowAlways, + ); + }, ); } } diff --git a/clippy_lints/src/large_include_file.rs b/clippy_lints/src/large_include_file.rs index c67da689aaee0..f2f841dcec33d 100644 --- a/clippy_lints/src/large_include_file.rs +++ b/clippy_lints/src/large_include_file.rs @@ -1,5 +1,5 @@ use clippy_config::Conf; -use clippy_utils::diagnostics::span_lint_and_note; +use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::macros::root_macro_call_first_node; use rustc_ast::LitKind; use rustc_hir::{Expr, ExprKind}; @@ -66,16 +66,18 @@ impl LateLintPass<'_> for LargeIncludeFile { && (cx.tcx.is_diagnostic_item(sym::include_bytes_macro, macro_call.def_id) || cx.tcx.is_diagnostic_item(sym::include_str_macro, macro_call.def_id)) { - span_lint_and_note( + #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")] + span_lint_and_then( cx, LARGE_INCLUDE_FILE, expr.span.source_callsite(), "attempted to include a large file", - None, - format!( - "the configuration allows a maximum size of {} bytes", - self.max_file_size - ), + |diag| { + diag.note(format!( + "the configuration allows a maximum size of {} bytes", + self.max_file_size + )); + }, ); } } diff --git a/clippy_lints/src/let_underscore.rs b/clippy_lints/src/let_underscore.rs index 8fa63f3e8fde0..b522c22a44d70 100644 --- a/clippy_lints/src/let_underscore.rs +++ b/clippy_lints/src/let_underscore.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::ty::{implements_trait, is_must_use_ty, match_type}; use clippy_utils::{is_from_proc_macro, is_must_use_func_call, paths}; use rustc_hir::{LetStmt, LocalSource, PatKind}; @@ -149,43 +149,53 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore { GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false, }); if contains_sync_guard { - span_lint_and_help( + #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")] + span_lint_and_then( cx, LET_UNDERSCORE_LOCK, local.span, "non-binding `let` on a synchronization lock", - None, - "consider using an underscore-prefixed named \ - binding or dropping explicitly with `std::mem::drop`", + |diag| { + diag.help( + "consider using an underscore-prefixed named \ + binding or dropping explicitly with `std::mem::drop`", + ); + }, ); } else if let Some(future_trait_def_id) = cx.tcx.lang_items().future_trait() && implements_trait(cx, cx.typeck_results().expr_ty(init), future_trait_def_id, &[]) { - span_lint_and_help( + #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")] + span_lint_and_then( cx, LET_UNDERSCORE_FUTURE, local.span, "non-binding `let` on a future", - None, - "consider awaiting the future or dropping explicitly with `std::mem::drop`", + |diag| { + diag.help("consider awaiting the future or dropping explicitly with `std::mem::drop`"); + }, ); } else if is_must_use_ty(cx, cx.typeck_results().expr_ty(init)) { - span_lint_and_help( + #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")] + span_lint_and_then( cx, LET_UNDERSCORE_MUST_USE, local.span, "non-binding `let` on an expression with `#[must_use]` type", - None, - "consider explicitly using expression value", + |diag| { + diag.help("consider explicitly using expression value"); + }, ); } else if is_must_use_func_call(cx, init) { - span_lint_and_help( + #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")] + span_lint_and_then( cx, LET_UNDERSCORE_MUST_USE, local.span, "non-binding `let` on a result of a `#[must_use]` function", - None, - "consider explicitly using function result", + |diag| { + diag.help("consider explicitly using function result"); + }, ); } @@ -204,18 +214,22 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore { return; } - span_lint_and_help( + span_lint_and_then( cx, LET_UNDERSCORE_UNTYPED, local.span, "non-binding `let` without a type annotation", - Some(Span::new( - local.pat.span.hi(), - local.pat.span.hi() + BytePos(1), - local.pat.span.ctxt(), - local.pat.span.parent(), - )), - "consider adding a type annotation", + |diag| { + diag.span_help( + Span::new( + local.pat.span.hi(), + local.pat.span.hi() + BytePos(1), + local.pat.span.ctxt(), + local.pat.span.parent(), + ), + "consider adding a type annotation", + ); + }, ); } } diff --git a/clippy_lints/src/operators/integer_division.rs b/clippy_lints/src/operators/integer_division.rs index 631d10f4a72e9..76eba7327cff6 100644 --- a/clippy_lints/src/operators/integer_division.rs +++ b/clippy_lints/src/operators/integer_division.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::diagnostics::span_lint_and_then; use rustc_hir as hir; use rustc_lint::LateContext; @@ -15,13 +15,9 @@ pub(crate) fn check<'tcx>( && cx.typeck_results().expr_ty(left).is_integral() && cx.typeck_results().expr_ty(right).is_integral() { - span_lint_and_help( - cx, - INTEGER_DIVISION, - expr.span, - "integer division", - None, - "division of integers may cause loss of precision. consider using floats", - ); + #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")] + span_lint_and_then(cx, INTEGER_DIVISION, expr.span, "integer division", |diag| { + diag.help("division of integers may cause loss of precision. consider using floats"); + }); } } diff --git a/tests/ui/excessive_precision.stderr b/tests/ui/excessive_precision.stderr index 6d8e166a649d8..81e4fb6765d0b 100644 --- a/tests/ui/excessive_precision.stderr +++ b/tests/ui/excessive_precision.stderr @@ -2,100 +2,179 @@ error: float has excessive precision --> tests/ui/excessive_precision.rs:20:26 | LL | const BAD32_1: f32 = 0.123_456_789_f32; - | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79_f32` + | ^^^^^^^^^^^^^^^^^ | = note: `-D clippy::excessive-precision` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::excessive_precision)]` +help: consider changing the type or truncating it to + | +LL | const BAD32_1: f32 = 0.123_456_79_f32; + | ~~~~~~~~~~~~~~~~ error: float has excessive precision --> tests/ui/excessive_precision.rs:21:26 | LL | const BAD32_2: f32 = 0.123_456_789; - | ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79` + | ^^^^^^^^^^^^^ + | +help: consider changing the type or truncating it to + | +LL | const BAD32_2: f32 = 0.123_456_79; + | ~~~~~~~~~~~~ error: float has excessive precision --> tests/ui/excessive_precision.rs:22:26 | LL | const BAD32_3: f32 = 0.100_000_000_000_1; - | ^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.1` + | ^^^^^^^^^^^^^^^^^^^ + | +help: consider changing the type or truncating it to + | +LL | const BAD32_3: f32 = 0.1; + | ~~~ error: float has excessive precision --> tests/ui/excessive_precision.rs:23:29 | LL | const BAD32_EDGE: f32 = 1.000_000_9; - | ^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.000_001` + | ^^^^^^^^^^^ + | +help: consider changing the type or truncating it to + | +LL | const BAD32_EDGE: f32 = 1.000_001; + | ~~~~~~~~~ error: float has excessive precision --> tests/ui/excessive_precision.rs:27:26 | LL | const BAD64_3: f64 = 0.100_000_000_000_000_000_1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.1` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider changing the type or truncating it to + | +LL | const BAD64_3: f64 = 0.1; + | ~~~ error: float has excessive precision --> tests/ui/excessive_precision.rs:30:22 | LL | println!("{:?}", 8.888_888_888_888_888_888_888); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `8.888_888_888_888_89` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider changing the type or truncating it to + | +LL | println!("{:?}", 8.888_888_888_888_89); + | ~~~~~~~~~~~~~~~~~~~~ error: float has excessive precision --> tests/ui/excessive_precision.rs:41:22 | LL | let bad32: f32 = 1.123_456_789; - | ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8` + | ^^^^^^^^^^^^^ + | +help: consider changing the type or truncating it to + | +LL | let bad32: f32 = 1.123_456_8; + | ~~~~~~~~~~~ error: float has excessive precision --> tests/ui/excessive_precision.rs:42:26 | LL | let bad32_suf: f32 = 1.123_456_789_f32; - | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8_f32` + | ^^^^^^^^^^^^^^^^^ + | +help: consider changing the type or truncating it to + | +LL | let bad32_suf: f32 = 1.123_456_8_f32; + | ~~~~~~~~~~~~~~~ error: float has excessive precision --> tests/ui/excessive_precision.rs:43:21 | LL | let bad32_inf = 1.123_456_789_f32; - | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8_f32` + | ^^^^^^^^^^^^^^^^^ + | +help: consider changing the type or truncating it to + | +LL | let bad32_inf = 1.123_456_8_f32; + | ~~~~~~~~~~~~~~~ error: float has excessive precision --> tests/ui/excessive_precision.rs:53:36 | LL | let bad_vec32: Vec = vec![0.123_456_789]; - | ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79` + | ^^^^^^^^^^^^^ + | +help: consider changing the type or truncating it to + | +LL | let bad_vec32: Vec = vec![0.123_456_79]; + | ~~~~~~~~~~~~ error: float has excessive precision --> tests/ui/excessive_precision.rs:54:36 | LL | let bad_vec64: Vec = vec![0.123_456_789_123_456_789]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_123_456_78` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider changing the type or truncating it to + | +LL | let bad_vec64: Vec = vec![0.123_456_789_123_456_78]; + | ~~~~~~~~~~~~~~~~~~~~~~~~ error: float has excessive precision --> tests/ui/excessive_precision.rs:58:24 | LL | let bad_e32: f32 = 1.123_456_788_888e-10; - | ^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8e-10` + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: consider changing the type or truncating it to + | +LL | let bad_e32: f32 = 1.123_456_8e-10; + | ~~~~~~~~~~~~~~~ error: float has excessive precision --> tests/ui/excessive_precision.rs:61:27 | LL | let bad_bige32: f32 = 1.123_456_788_888E-10; - | ^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8E-10` + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: consider changing the type or truncating it to + | +LL | let bad_bige32: f32 = 1.123_456_8E-10; + | ~~~~~~~~~~~~~~~ error: float has excessive precision --> tests/ui/excessive_precision.rs:70:13 | LL | let _ = 2.225_073_858_507_201_1e-308_f64; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `2.225_073_858_507_201e-308_f64` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider changing the type or truncating it to + | +LL | let _ = 2.225_073_858_507_201e-308_f64; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: float has excessive precision --> tests/ui/excessive_precision.rs:73:13 | LL | let _ = 1.000_000_000_000_001e-324_f64; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0_f64` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider changing the type or truncating it to + | +LL | let _ = 0_f64; + | ~~~~~ error: float has excessive precision --> tests/ui/excessive_precision.rs:83:20 | LL | const _: f64 = 3.0000000000000000e+00; - | ^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `3.0` + | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider changing the type or truncating it to + | +LL | const _: f64 = 3.0; + | ~~~ error: aborting due to 16 previous errors diff --git a/tests/ui/lossy_float_literal.stderr b/tests/ui/lossy_float_literal.stderr index b5a07418734c9..3026854e317ae 100644 --- a/tests/ui/lossy_float_literal.stderr +++ b/tests/ui/lossy_float_literal.stderr @@ -2,70 +2,124 @@ error: literal cannot be represented as the underlying type without loss of prec --> tests/ui/lossy_float_literal.rs:14:18 | LL | let _: f32 = 16_777_217.0; - | ^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_216.0` + | ^^^^^^^^^^^^ | = note: `-D clippy::lossy-float-literal` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::lossy_float_literal)]` +help: consider changing the type or replacing it with + | +LL | let _: f32 = 16_777_216.0; + | ~~~~~~~~~~~~ error: literal cannot be represented as the underlying type without loss of precision --> tests/ui/lossy_float_literal.rs:15:18 | LL | let _: f32 = 16_777_219.0; - | ^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220.0` + | ^^^^^^^^^^^^ + | +help: consider changing the type or replacing it with + | +LL | let _: f32 = 16_777_220.0; + | ~~~~~~~~~~~~ error: literal cannot be represented as the underlying type without loss of precision --> tests/ui/lossy_float_literal.rs:16:18 | LL | let _: f32 = 16_777_219.; - | ^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220.0` + | ^^^^^^^^^^^ + | +help: consider changing the type or replacing it with + | +LL | let _: f32 = 16_777_220.0; + | ~~~~~~~~~~~~ error: literal cannot be represented as the underlying type without loss of precision --> tests/ui/lossy_float_literal.rs:17:18 | LL | let _: f32 = 16_777_219.000; - | ^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220.0` + | ^^^^^^^^^^^^^^ + | +help: consider changing the type or replacing it with + | +LL | let _: f32 = 16_777_220.0; + | ~~~~~~~~~~~~ error: literal cannot be represented as the underlying type without loss of precision --> tests/ui/lossy_float_literal.rs:18:13 | LL | let _ = 16_777_219f32; - | ^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220_f32` + | ^^^^^^^^^^^^^ + | +help: consider changing the type or replacing it with + | +LL | let _ = 16_777_220_f32; + | ~~~~~~~~~~~~~~ error: literal cannot be represented as the underlying type without loss of precision --> tests/ui/lossy_float_literal.rs:19:19 | LL | let _: f32 = -16_777_219.0; - | ^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220.0` + | ^^^^^^^^^^^^ + | +help: consider changing the type or replacing it with + | +LL | let _: f32 = -16_777_220.0; + | ~~~~~~~~~~~~ error: literal cannot be represented as the underlying type without loss of precision --> tests/ui/lossy_float_literal.rs:21:18 | LL | let _: f64 = 9_007_199_254_740_993.0; - | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992.0` + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider changing the type or replacing it with + | +LL | let _: f64 = 9_007_199_254_740_992.0; + | ~~~~~~~~~~~~~~~~~~~~~~~ error: literal cannot be represented as the underlying type without loss of precision --> tests/ui/lossy_float_literal.rs:22:18 | LL | let _: f64 = 9_007_199_254_740_993.; - | ^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992.0` + | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider changing the type or replacing it with + | +LL | let _: f64 = 9_007_199_254_740_992.0; + | ~~~~~~~~~~~~~~~~~~~~~~~ error: literal cannot be represented as the underlying type without loss of precision --> tests/ui/lossy_float_literal.rs:23:18 | LL | let _: f64 = 9_007_199_254_740_993.00; - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992.0` + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider changing the type or replacing it with + | +LL | let _: f64 = 9_007_199_254_740_992.0; + | ~~~~~~~~~~~~~~~~~~~~~~~ error: literal cannot be represented as the underlying type without loss of precision --> tests/ui/lossy_float_literal.rs:24:13 | LL | let _ = 9_007_199_254_740_993f64; - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992_f64` + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider changing the type or replacing it with + | +LL | let _ = 9_007_199_254_740_992_f64; + | ~~~~~~~~~~~~~~~~~~~~~~~~~ error: literal cannot be represented as the underlying type without loss of precision --> tests/ui/lossy_float_literal.rs:25:19 | LL | let _: f64 = -9_007_199_254_740_993.0; - | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992.0` + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider changing the type or replacing it with + | +LL | let _: f64 = -9_007_199_254_740_992.0; + | ~~~~~~~~~~~~~~~~~~~~~~~ error: aborting due to 11 previous errors From d17f113474fc18284bc7ab0d67a815a220244a3e Mon Sep 17 00:00:00 2001 From: xFrednet Date: Sun, 21 Jul 2024 19:53:22 +0200 Subject: [PATCH 047/786] Make restriction lint's use `span_lint_and_then` (m -> m) --- clippy_lints/src/drop_forget_ref.rs | 18 +++++------ clippy_lints/src/float_literal.rs | 2 +- clippy_lints/src/inherent_impl.rs | 9 +++--- clippy_lints/src/methods/map_err_ignore.rs | 13 +++++--- clippy_lints/src/missing_assert_message.rs | 10 +++--- clippy_lints/src/missing_trait_methods.rs | 12 +++---- .../src/mixed_read_write_in_expression.rs | 12 ++++--- clippy_lints/src/module_style.rs | 32 ++++++++++--------- 8 files changed, 61 insertions(+), 47 deletions(-) diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index 4a6ffcd9a7888..c7dd7292a14be 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::span_lint_and_note; +use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::is_must_use_func_call; use clippy_utils::ty::{is_copy, is_must_use_ty, is_type_lang_item}; use rustc_hir::{Arm, Expr, ExprKind, LangItem, Node}; @@ -126,14 +126,14 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef { }, _ => return, }; - span_lint_and_note( - cx, - lint, - expr.span, - msg, - note_span, - format!("argument has type `{arg_ty}`"), - ); + span_lint_and_then(cx, lint, expr.span, msg, |diag| { + let note = format!("argument has type `{arg_ty}`"); + if let Some(span) = note_span { + diag.span_note(span, note); + } else { + diag.note(note); + } + }); } } } diff --git a/clippy_lints/src/float_literal.rs b/clippy_lints/src/float_literal.rs index 2998c6f8ae0a4..39cddece75daa 100644 --- a/clippy_lints/src/float_literal.rs +++ b/clippy_lints/src/float_literal.rs @@ -109,7 +109,7 @@ impl<'tcx> LateLintPass<'tcx> for FloatLiteral { // If the type suffix is missing the suggestion would be // incorrectly interpreted as an integer so adding a `.0` // suffix to prevent that. - + span_lint_and_then( cx, LOSSY_FLOAT_LITERAL, diff --git a/clippy_lints/src/inherent_impl.rs b/clippy_lints/src/inherent_impl.rs index 95ae591884bc4..186bf4035f0c6 100644 --- a/clippy_lints/src/inherent_impl.rs +++ b/clippy_lints/src/inherent_impl.rs @@ -1,6 +1,6 @@ //! lint on inherent implementations -use clippy_utils::diagnostics::span_lint_and_note; +use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::is_lint_allowed; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::LocalDefId; @@ -106,13 +106,14 @@ impl<'tcx> LateLintPass<'tcx> for MultipleInherentImpl { // `TyCtxt::crate_inherent_impls` doesn't have a defined order. Sort the lint output first. lint_spans.sort_by_key(|x| x.0.lo()); for (span, first_span) in lint_spans { - span_lint_and_note( + span_lint_and_then( cx, MULTIPLE_INHERENT_IMPL, span, "multiple implementations of this structure", - Some(first_span), - "first implementation here", + |diag| { + diag.span_note(first_span, "first implementation here"); + }, ); } } diff --git a/clippy_lints/src/methods/map_err_ignore.rs b/clippy_lints/src/methods/map_err_ignore.rs index fbb83c8ce5635..ee34891ad8af0 100644 --- a/clippy_lints/src/methods/map_err_ignore.rs +++ b/clippy_lints/src/methods/map_err_ignore.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::ty::is_type_diagnostic_item; use rustc_hir::{CaptureBy, Closure, Expr, ExprKind, PatKind}; use rustc_lint::LateContext; @@ -22,13 +22,18 @@ pub(super) fn check(cx: &LateContext<'_>, e: &Expr<'_>, arg: &Expr<'_>) { { // span the area of the closure capture and warn that the // original error will be thrown away - span_lint_and_help( + #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")] + span_lint_and_then( cx, MAP_ERR_IGNORE, fn_decl_span, "`map_err(|_|...` wildcard pattern discards the original error", - None, - "consider storing the original error as a source in the new error, or silence this warning using an ignored identifier (`.map_err(|_foo| ...`)", + |diag| { + diag.help( + + "consider storing the original error as a source in the new error, or silence this warning using an ignored identifier (`.map_err(|_foo| ...`)", + ); + }, ); } } diff --git a/clippy_lints/src/missing_assert_message.rs b/clippy_lints/src/missing_assert_message.rs index 935ed48dacc50..a9ea11f4c2b06 100644 --- a/clippy_lints/src/missing_assert_message.rs +++ b/clippy_lints/src/missing_assert_message.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::is_in_test; use clippy_utils::macros::{find_assert_args, find_assert_eq_args, root_macro_call_first_node, PanicExpn}; use rustc_hir::Expr; @@ -79,13 +79,15 @@ impl<'tcx> LateLintPass<'tcx> for MissingAssertMessage { }; if let PanicExpn::Empty = panic_expn { - span_lint_and_help( + #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")] + span_lint_and_then( cx, MISSING_ASSERT_MESSAGE, macro_call.span, "assert without any message", - None, - "consider describing why the failing assert is problematic", + |diag| { + diag.help("consider describing why the failing assert is problematic"); + }, ); } } diff --git a/clippy_lints/src/missing_trait_methods.rs b/clippy_lints/src/missing_trait_methods.rs index 85029a5e6a0d4..59c8c7f38e4e4 100644 --- a/clippy_lints/src/missing_trait_methods.rs +++ b/clippy_lints/src/missing_trait_methods.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::is_lint_allowed; use clippy_utils::macros::span_is_local; use rustc_hir::def_id::DefIdMap; @@ -83,15 +83,15 @@ impl<'tcx> LateLintPass<'tcx> for MissingTraitMethods { cx.tcx.with_stable_hashing_context(|hcx| { for assoc in provided.values_sorted(&hcx, true) { let source_map = cx.tcx.sess.source_map(); - let definition_span = source_map.guess_head_span(cx.tcx.def_span(assoc.def_id)); - - span_lint_and_help( + span_lint_and_then( cx, MISSING_TRAIT_METHODS, source_map.guess_head_span(item.span), format!("missing trait method provided by default: `{}`", assoc.name), - Some(definition_span), - "implement the method", + |diag| { + let definition_span = source_map.guess_head_span(cx.tcx.def_span(assoc.def_id)); + diag.span_help(definition_span, "implement the method"); + }, ); } }); diff --git a/clippy_lints/src/mixed_read_write_in_expression.rs b/clippy_lints/src/mixed_read_write_in_expression.rs index 9c5a8a0cfcdfa..6964d8c8dbb33 100644 --- a/clippy_lints/src/mixed_read_write_in_expression.rs +++ b/clippy_lints/src/mixed_read_write_in_expression.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::{span_lint, span_lint_and_note}; +use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; use clippy_utils::{get_parent_expr, path_to_local, path_to_local_id}; use rustc_hir::intravisit::{walk_expr, Visitor}; use rustc_hir::{BinOpKind, Block, Expr, ExprKind, HirId, LetStmt, Node, Stmt, StmtKind}; @@ -324,13 +324,17 @@ impl<'a, 'tcx> Visitor<'tcx> for ReadVisitor<'a, 'tcx> { if path_to_local_id(expr, self.var) { // Check that this is a read, not a write. if !is_in_assignment_position(self.cx, expr) { - span_lint_and_note( + span_lint_and_then( self.cx, MIXED_READ_WRITE_IN_EXPRESSION, expr.span, format!("unsequenced read of `{}`", self.cx.tcx.hir().name(self.var)), - Some(self.write_expr.span), - "whether read occurs before this write depends on evaluation order", + |diag| { + diag.span_note( + self.write_expr.span, + "whether read occurs before this write depends on evaluation order", + ); + }, ); } } diff --git a/clippy_lints/src/module_style.rs b/clippy_lints/src/module_style.rs index 305499f9da43c..e9c5f64a2550d 100644 --- a/clippy_lints/src/module_style.rs +++ b/clippy_lints/src/module_style.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::diagnostics::span_lint_and_then; use rustc_ast::ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_lint::{EarlyContext, EarlyLintPass, Level, LintContext}; @@ -121,17 +121,18 @@ impl EarlyLintPass for ModStyle { for folder in &folder_segments { if !mod_folders.contains(folder) { if let Some((file, path)) = file_map.get(folder) { - let mut correct = path.to_path_buf(); - correct.pop(); - correct.push(folder); - correct.push("mod.rs"); - span_lint_and_help( + span_lint_and_then( cx, SELF_NAMED_MODULE_FILES, Span::new(file.start_pos, file.start_pos, SyntaxContext::root(), None), format!("`mod.rs` files are required, found `{}`", path.display()), - None, - format!("move `{}` to `{}`", path.display(), correct.display(),), + |diag| { + let mut correct = path.to_path_buf(); + correct.pop(); + correct.push(folder); + correct.push("mod.rs"); + diag.help(format!("move `{}` to `{}`", path.display(), correct.display(),)); + }, ); } } @@ -161,17 +162,18 @@ fn process_paths_for_mod_files<'a>( /// for code-sharing between tests. fn check_self_named_mod_exists(cx: &EarlyContext<'_>, path: &Path, file: &SourceFile) { if path.ends_with("mod.rs") && !path.starts_with("tests") { - let mut mod_file = path.to_path_buf(); - mod_file.pop(); - mod_file.set_extension("rs"); - - span_lint_and_help( + span_lint_and_then( cx, MOD_MODULE_FILES, Span::new(file.start_pos, file.start_pos, SyntaxContext::root(), None), format!("`mod.rs` files are not allowed, found `{}`", path.display()), - None, - format!("move `{}` to `{}`", path.display(), mod_file.display()), + |diag| { + let mut mod_file = path.to_path_buf(); + mod_file.pop(); + mod_file.set_extension("rs"); + + diag.help(format!("move `{}` to `{}`", path.display(), mod_file.display())); + }, ); } } From e2137a248765bec03cef59f3da6e2358a6a79d6d Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Mon, 22 Jul 2024 00:42:35 -0700 Subject: [PATCH 048/786] std: unsafe-wrap personality::dwarf::eh In so doing, move the forbid up to the top of personality::dwarf --- library/std/src/sys/personality/dwarf/eh.rs | 112 ++++++++++--------- library/std/src/sys/personality/dwarf/mod.rs | 2 +- 2 files changed, 61 insertions(+), 53 deletions(-) diff --git a/library/std/src/sys/personality/dwarf/eh.rs b/library/std/src/sys/personality/dwarf/eh.rs index ff88ef4e0e1d0..d7f1e0cef3648 100644 --- a/library/std/src/sys/personality/dwarf/eh.rs +++ b/library/std/src/sys/personality/dwarf/eh.rs @@ -70,45 +70,51 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result let func_start = context.func_start; let mut reader = DwarfReader::new(lsda); - - let start_encoding = reader.read::(); - // base address for landing pad offsets - let lpad_base = if start_encoding != DW_EH_PE_omit { - read_encoded_pointer(&mut reader, context, start_encoding)? - } else { - func_start + let lpad_base = unsafe { + let start_encoding = reader.read::(); + // base address for landing pad offsets + if start_encoding != DW_EH_PE_omit { + read_encoded_pointer(&mut reader, context, start_encoding)? + } else { + func_start + } }; + let call_site_encoding = unsafe { + let ttype_encoding = reader.read::(); + if ttype_encoding != DW_EH_PE_omit { + // Rust doesn't analyze exception types, so we don't care about the type table + reader.read_uleb128(); + } - let ttype_encoding = reader.read::(); - if ttype_encoding != DW_EH_PE_omit { - // Rust doesn't analyze exception types, so we don't care about the type table - reader.read_uleb128(); - } - - let call_site_encoding = reader.read::(); - let call_site_table_length = reader.read_uleb128(); - let action_table = reader.ptr.add(call_site_table_length as usize); + reader.read::() + }; + let action_table = unsafe { + let call_site_table_length = reader.read_uleb128(); + reader.ptr.add(call_site_table_length as usize) + }; let ip = context.ip; if !USING_SJLJ_EXCEPTIONS { // read the callsite table while reader.ptr < action_table { - // these are offsets rather than pointers; - let cs_start = read_encoded_offset(&mut reader, call_site_encoding)?; - let cs_len = read_encoded_offset(&mut reader, call_site_encoding)?; - let cs_lpad = read_encoded_offset(&mut reader, call_site_encoding)?; - let cs_action_entry = reader.read_uleb128(); - // Callsite table is sorted by cs_start, so if we've passed the ip, we - // may stop searching. - if ip < func_start.wrapping_add(cs_start) { - break; - } - if ip < func_start.wrapping_add(cs_start + cs_len) { - if cs_lpad == 0 { - return Ok(EHAction::None); - } else { - let lpad = lpad_base.wrapping_add(cs_lpad); - return Ok(interpret_cs_action(action_table, cs_action_entry, lpad)); + unsafe { + // these are offsets rather than pointers; + let cs_start = read_encoded_offset(&mut reader, call_site_encoding)?; + let cs_len = read_encoded_offset(&mut reader, call_site_encoding)?; + let cs_lpad = read_encoded_offset(&mut reader, call_site_encoding)?; + let cs_action_entry = reader.read_uleb128(); + // Callsite table is sorted by cs_start, so if we've passed the ip, we + // may stop searching. + if ip < func_start.wrapping_add(cs_start) { + break; + } + if ip < func_start.wrapping_add(cs_start + cs_len) { + if cs_lpad == 0 { + return Ok(EHAction::None); + } else { + let lpad = lpad_base.wrapping_add(cs_lpad); + return Ok(interpret_cs_action(action_table, cs_action_entry, lpad)); + } } } } @@ -125,15 +131,15 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result } let mut idx = ip.addr(); loop { - let cs_lpad = reader.read_uleb128(); - let cs_action_entry = reader.read_uleb128(); + let cs_lpad = unsafe { reader.read_uleb128() }; + let cs_action_entry = unsafe { reader.read_uleb128() }; idx -= 1; if idx == 0 { // Can never have null landing pad for sjlj -- that would have // been indicated by a -1 call site index. // FIXME(strict provenance) let lpad = ptr::with_exposed_provenance((cs_lpad + 1) as usize); - return Ok(interpret_cs_action(action_table, cs_action_entry, lpad)); + return Ok(unsafe { interpret_cs_action(action_table, cs_action_entry, lpad) }); } } } @@ -151,9 +157,9 @@ unsafe fn interpret_cs_action( } else { // If lpad != 0 and cs_action_entry != 0, we have to check ttype_index. // If ttype_index == 0 under the condition, we take cleanup action. - let action_record = action_table.offset(cs_action_entry as isize - 1); + let action_record = unsafe { action_table.offset(cs_action_entry as isize - 1) }; let mut action_reader = DwarfReader::new(action_record); - let ttype_index = action_reader.read_sleb128(); + let ttype_index = unsafe { action_reader.read_sleb128() }; if ttype_index == 0 { EHAction::Cleanup(lpad) } else if ttype_index > 0 { @@ -186,18 +192,20 @@ unsafe fn read_encoded_offset(reader: &mut DwarfReader, encoding: u8) -> Result< if encoding == DW_EH_PE_omit || encoding & 0xF0 != 0 { return Err(()); } - let result = match encoding & 0x0F { - // despite the name, LLVM also uses absptr for offsets instead of pointers - DW_EH_PE_absptr => reader.read::(), - DW_EH_PE_uleb128 => reader.read_uleb128() as usize, - DW_EH_PE_udata2 => reader.read::() as usize, - DW_EH_PE_udata4 => reader.read::() as usize, - DW_EH_PE_udata8 => reader.read::() as usize, - DW_EH_PE_sleb128 => reader.read_sleb128() as usize, - DW_EH_PE_sdata2 => reader.read::() as usize, - DW_EH_PE_sdata4 => reader.read::() as usize, - DW_EH_PE_sdata8 => reader.read::() as usize, - _ => return Err(()), + let result = unsafe { + match encoding & 0x0F { + // despite the name, LLVM also uses absptr for offsets instead of pointers + DW_EH_PE_absptr => reader.read::(), + DW_EH_PE_uleb128 => reader.read_uleb128() as usize, + DW_EH_PE_udata2 => reader.read::() as usize, + DW_EH_PE_udata4 => reader.read::() as usize, + DW_EH_PE_udata8 => reader.read::() as usize, + DW_EH_PE_sleb128 => reader.read_sleb128() as usize, + DW_EH_PE_sdata2 => reader.read::() as usize, + DW_EH_PE_sdata4 => reader.read::() as usize, + DW_EH_PE_sdata8 => reader.read::() as usize, + _ => return Err(()), + } }; Ok(result) } @@ -250,14 +258,14 @@ unsafe fn read_encoded_pointer( if encoding & 0x0F != DW_EH_PE_absptr { return Err(()); } - reader.read::<*const u8>() + unsafe { reader.read::<*const u8>() } } else { - let offset = read_encoded_offset(reader, encoding & 0x0F)?; + let offset = unsafe { read_encoded_offset(reader, encoding & 0x0F)? }; base_ptr.wrapping_add(offset) }; if encoding & DW_EH_PE_indirect != 0 { - ptr = *(ptr.cast::<*const u8>()); + ptr = unsafe { *(ptr.cast::<*const u8>()) }; } Ok(ptr) diff --git a/library/std/src/sys/personality/dwarf/mod.rs b/library/std/src/sys/personality/dwarf/mod.rs index 89f7f133e21b4..5c52d96c4cad4 100644 --- a/library/std/src/sys/personality/dwarf/mod.rs +++ b/library/std/src/sys/personality/dwarf/mod.rs @@ -5,6 +5,7 @@ // This module is used only by x86_64-pc-windows-gnu for now, but we // are compiling it everywhere to avoid regressions. #![allow(unused)] +#![forbid(unsafe_op_in_unsafe_fn)] #[cfg(test)] mod tests; @@ -17,7 +18,6 @@ pub struct DwarfReader { pub ptr: *const u8, } -#[forbid(unsafe_op_in_unsafe_fn)] impl DwarfReader { pub fn new(ptr: *const u8) -> DwarfReader { DwarfReader { ptr } From 8366c7fe9c2db004224648239644f0fbecc185ea Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 18 Jul 2024 11:54:04 -0300 Subject: [PATCH 049/786] Stabilize unsafe extern blocks (RFC 3484) --- .../rustc_ast_passes/src/ast_validation.rs | 42 ++++++------------- compiler/rustc_ast_passes/src/feature_gate.rs | 4 -- compiler/rustc_feature/src/accepted.rs | 2 + compiler/rustc_feature/src/unstable.rs | 2 - compiler/rustc_lint_defs/src/builtin.rs | 1 - compiler/rustc_parse/src/parser/mod.rs | 3 -- tests/rustdoc/unsafe-extern-blocks.rs | 3 +- .../feature-gate-unsafe-extern-blocks.rs | 13 ------ .../feature-gate-unsafe-extern-blocks.stderr | 23 ---------- .../lint/unsafe_code/unsafe-extern-blocks.rs | 1 - .../unsafe_code/unsafe-extern-blocks.stderr | 4 +- tests/ui/parser/unsafe-foreign-mod-2.rs | 2 - tests/ui/parser/unsafe-foreign-mod-2.stderr | 18 +------- tests/ui/parser/unsafe-foreign-mod.rs | 6 +-- tests/ui/parser/unsafe-foreign-mod.stderr | 12 ------ tests/ui/rust-2024/safe-outside-extern.rs | 8 ---- tests/ui/rust-2024/safe-outside-extern.stderr | 38 +++++++++++++++++ .../extern-items-unsafe.edition2021.stderr | 4 +- .../extern-items-unsafe.edition2024.stderr | 4 +- .../extern-items-unsafe.rs | 2 - .../extern-items.edition2024.stderr | 2 +- .../unsafe-extern-blocks/extern-items.rs | 2 - .../unsafe-extern-blocks/safe-impl-trait.rs | 3 -- ...it.gated.stderr => safe-impl-trait.stderr} | 2 +- .../unsafe-extern-blocks/safe-items.rs | 2 - .../unsafe-extern-blocks/safe-trait.rs | 3 -- .../unsafe-extern-blocks/safe-trait.stderr | 8 ++++ ...-unadorned-extern-block.edition2021.stderr | 4 +- ...-unadorned-extern-block.edition2024.stderr | 6 +-- .../safe-unsafe-on-unadorned-extern-block.rs | 2 - .../unsafe-extern-suggestion.fixed | 1 - .../unsafe-extern-suggestion.rs | 1 - .../unsafe-extern-suggestion.stderr | 4 +- .../unsafe-items.edition2021.stderr | 4 +- .../unsafe-items.edition2024.stderr | 4 +- .../unsafe-extern-blocks/unsafe-items.rs | 2 - .../unsafe-on-extern-block-issue-126756.fixed | 1 - .../unsafe-on-extern-block-issue-126756.rs | 1 - ...unsafe-on-extern-block-issue-126756.stderr | 2 +- tests/ui/unpretty/expanded-exhaustive.rs | 1 - tests/ui/unpretty/expanded-exhaustive.stdout | 1 - 41 files changed, 85 insertions(+), 163 deletions(-) delete mode 100644 tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.rs delete mode 100644 tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.stderr delete mode 100644 tests/ui/parser/unsafe-foreign-mod.stderr create mode 100644 tests/ui/rust-2024/safe-outside-extern.stderr rename tests/ui/rust-2024/unsafe-extern-blocks/{safe-impl-trait.gated.stderr => safe-impl-trait.stderr} (83%) create mode 100644 tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.stderr diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 34aac6e447304..af1d9beb527bd 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -452,11 +452,6 @@ impl<'a> AstValidator<'a> { item_span: span, block: Some(self.current_extern_span().shrink_to_lo()), }); - } else if !self.features.unsafe_extern_blocks { - self.dcx().emit_err(errors::InvalidSafetyOnExtern { - item_span: span, - block: None, - }); } } } @@ -1053,32 +1048,19 @@ impl<'a> Visitor<'a> for AstValidator<'a> { errors::VisibilityNotPermittedNote::IndividualForeignItems, ); - if this.features.unsafe_extern_blocks { - if &Safety::Default == safety { - if item.span.at_least_rust_2024() { - this.dcx() - .emit_err(errors::MissingUnsafeOnExtern { span: item.span }); - } else { - this.lint_buffer.buffer_lint( - MISSING_UNSAFE_ON_EXTERN, - item.id, - item.span, - BuiltinLintDiag::MissingUnsafeOnExtern { - suggestion: item.span.shrink_to_lo(), - }, - ); - } + if &Safety::Default == safety { + if item.span.at_least_rust_2024() { + this.dcx().emit_err(errors::MissingUnsafeOnExtern { span: item.span }); + } else { + this.lint_buffer.buffer_lint( + MISSING_UNSAFE_ON_EXTERN, + item.id, + item.span, + BuiltinLintDiag::MissingUnsafeOnExtern { + suggestion: item.span.shrink_to_lo(), + }, + ); } - } else if let &Safety::Unsafe(span) = safety { - let mut diag = this - .dcx() - .create_err(errors::UnsafeItem { span, kind: "extern block" }); - rustc_session::parse::add_feature_diagnostics( - &mut diag, - self.session, - sym::unsafe_extern_blocks, - ); - diag.emit(); } if abi.is_none() { diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index e91dfb2776662..f9119c06fcf7c 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -561,10 +561,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { gate_all!(precise_capturing, "precise captures on `impl Trait` are experimental"); gate_all!(global_registration, "global registration is experimental"); gate_all!(unsafe_attributes, "`#[unsafe()]` markers for attributes are experimental"); - gate_all!( - unsafe_extern_blocks, - "`unsafe extern {}` blocks and `safe` keyword are experimental" - ); gate_all!(return_type_notation, "return type notation is experimental"); if !visitor.features.never_patterns { diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index e671c7682391e..d5874f79a22c0 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -387,6 +387,8 @@ declare_features! ( (accepted, unrestricted_attribute_tokens, "1.34.0", Some(55208)), /// The `unsafe_op_in_unsafe_fn` lint (allowed by default): no longer treat an unsafe function as an unsafe block. (accepted, unsafe_block_in_unsafe_fn, "1.52.0", Some(71668)), + /// Allows unsafe on extern declarations and safety qualifiers over internal items. + (accepted, unsafe_extern_blocks, "CURRENT_RUSTC_VERSION", Some(123743)), /// Allows importing and reexporting macros with `use`, /// enables macro modularization in general. (accepted, use_extern_macros, "1.30.0", Some(35896)), diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 741c621db081a..e1433a66556b1 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -628,8 +628,6 @@ declare_features! ( (incomplete, unnamed_fields, "1.74.0", Some(49804)), /// Allows unsafe attributes. (unstable, unsafe_attributes, "1.80.0", Some(123757)), - /// Allows unsafe on extern declarations and safety qualifiers over internal items. - (unstable, unsafe_extern_blocks, "1.80.0", Some(123743)), /// Allows const generic parameters to be defined with types that /// are not `Sized`, e.g. `fn foo() {`. (incomplete, unsized_const_params, "CURRENT_RUSTC_VERSION", Some(95174)), diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 04764b71b1002..4e1fbe8ae9d66 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -4865,7 +4865,6 @@ declare_lint! { /// ### Example /// /// ```rust - /// #![feature(unsafe_extern_blocks)] /// #![warn(missing_unsafe_on_extern)] /// #![allow(dead_code)] /// diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 7326b9ec51f2b..b46653717a4f1 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1205,9 +1205,6 @@ impl<'a> Parser<'a> { if self.eat_keyword_case(kw::Unsafe, case) { Safety::Unsafe(self.prev_token.uninterpolated_span()) } else if self.eat_keyword_case(kw::Safe, case) { - self.psess - .gated_spans - .gate(sym::unsafe_extern_blocks, self.prev_token.uninterpolated_span()); Safety::Safe(self.prev_token.uninterpolated_span()) } else { Safety::Default diff --git a/tests/rustdoc/unsafe-extern-blocks.rs b/tests/rustdoc/unsafe-extern-blocks.rs index 22d3beea6c3a9..829095f300f20 100644 --- a/tests/rustdoc/unsafe-extern-blocks.rs +++ b/tests/rustdoc/unsafe-extern-blocks.rs @@ -1,6 +1,5 @@ // Test to ensure the feature is working as expected. -#![feature(unsafe_extern_blocks)] #![crate_name = "foo"] // @has 'foo/index.html' @@ -13,7 +12,7 @@ // @count - '//ul[@class="item-table"]//sup[@title="unsafe function"]' 1 // @has - '//ul[@class="item-table"]//sup[@title="unsafe function"]' '⚠' -unsafe extern { +unsafe extern "C" { // @has 'foo/static.FOO.html' // @has - '//pre[@class="rust item-decl"]' 'pub static FOO: i32' pub safe static FOO: i32; diff --git a/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.rs b/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.rs deleted file mode 100644 index 3ea62e875b8e3..0000000000000 --- a/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.rs +++ /dev/null @@ -1,13 +0,0 @@ -unsafe extern "C" { - //~^ ERROR extern block cannot be declared unsafe -} - -// We can't gate `unsafe extern` blocks themselves since they were previously -// allowed, but we should gate the `safe` soft keyword. -#[cfg(any())] -unsafe extern "C" { - safe fn foo(); - //~^ ERROR `unsafe extern {}` blocks and `safe` keyword are experimental -} - -fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.stderr b/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.stderr deleted file mode 100644 index 5653494630899..0000000000000 --- a/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error: extern block cannot be declared unsafe - --> $DIR/feature-gate-unsafe-extern-blocks.rs:1:1 - | -LL | unsafe extern "C" { - | ^^^^^^ - | - = note: see issue #123743 for more information - = help: add `#![feature(unsafe_extern_blocks)]` 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[E0658]: `unsafe extern {}` blocks and `safe` keyword are experimental - --> $DIR/feature-gate-unsafe-extern-blocks.rs:9:5 - | -LL | safe fn foo(); - | ^^^^ - | - = note: see issue #123743 for more information - = help: add `#![feature(unsafe_extern_blocks)]` 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: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/lint/unsafe_code/unsafe-extern-blocks.rs b/tests/ui/lint/unsafe_code/unsafe-extern-blocks.rs index 6f2ead70db80c..c264fa1c8daf1 100644 --- a/tests/ui/lint/unsafe_code/unsafe-extern-blocks.rs +++ b/tests/ui/lint/unsafe_code/unsafe-extern-blocks.rs @@ -1,4 +1,3 @@ -#![feature(unsafe_extern_blocks)] #![deny(unsafe_code)] #[allow(unsafe_code)] diff --git a/tests/ui/lint/unsafe_code/unsafe-extern-blocks.stderr b/tests/ui/lint/unsafe_code/unsafe-extern-blocks.stderr index 5439a3112560e..6d3b064da344f 100644 --- a/tests/ui/lint/unsafe_code/unsafe-extern-blocks.stderr +++ b/tests/ui/lint/unsafe_code/unsafe-extern-blocks.stderr @@ -1,5 +1,5 @@ error: usage of an `unsafe extern` block - --> $DIR/unsafe-extern-blocks.rs:9:1 + --> $DIR/unsafe-extern-blocks.rs:8:1 | LL | / unsafe extern "C" { LL | | @@ -8,7 +8,7 @@ LL | | } | |_^ | note: the lint level is defined here - --> $DIR/unsafe-extern-blocks.rs:2:9 + --> $DIR/unsafe-extern-blocks.rs:1:9 | LL | #![deny(unsafe_code)] | ^^^^^^^^^^^ diff --git a/tests/ui/parser/unsafe-foreign-mod-2.rs b/tests/ui/parser/unsafe-foreign-mod-2.rs index 0b63a993c5b9e..6d339cd90881f 100644 --- a/tests/ui/parser/unsafe-foreign-mod-2.rs +++ b/tests/ui/parser/unsafe-foreign-mod-2.rs @@ -1,8 +1,6 @@ extern "C" unsafe { //~^ ERROR expected `{`, found keyword `unsafe` - //~| ERROR extern block cannot be declared unsafe unsafe fn foo(); - //~^ ERROR items in unadorned `extern` blocks cannot have safety qualifiers } fn main() {} diff --git a/tests/ui/parser/unsafe-foreign-mod-2.stderr b/tests/ui/parser/unsafe-foreign-mod-2.stderr index 8bd592b5d4311..0625e3362ed72 100644 --- a/tests/ui/parser/unsafe-foreign-mod-2.stderr +++ b/tests/ui/parser/unsafe-foreign-mod-2.stderr @@ -4,21 +4,5 @@ error: expected `{`, found keyword `unsafe` LL | extern "C" unsafe { | ^^^^^^ expected `{` -error: extern block cannot be declared unsafe - --> $DIR/unsafe-foreign-mod-2.rs:1:12 - | -LL | extern "C" unsafe { - | ^^^^^^ - | - = note: see issue #123743 for more information - = help: add `#![feature(unsafe_extern_blocks)]` 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: items in unadorned `extern` blocks cannot have safety qualifiers - --> $DIR/unsafe-foreign-mod-2.rs:4:5 - | -LL | unsafe fn foo(); - | ^^^^^^^^^^^^^^^^ - -error: aborting due to 3 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/parser/unsafe-foreign-mod.rs b/tests/ui/parser/unsafe-foreign-mod.rs index eab134a4a4de4..623c3bb81e458 100644 --- a/tests/ui/parser/unsafe-foreign-mod.rs +++ b/tests/ui/parser/unsafe-foreign-mod.rs @@ -1,5 +1,5 @@ -unsafe extern "C" { - //~^ ERROR extern block cannot be declared unsafe -} +//@ check-pass + +unsafe extern "C" {} fn main() {} diff --git a/tests/ui/parser/unsafe-foreign-mod.stderr b/tests/ui/parser/unsafe-foreign-mod.stderr deleted file mode 100644 index 60b918a89b34d..0000000000000 --- a/tests/ui/parser/unsafe-foreign-mod.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error: extern block cannot be declared unsafe - --> $DIR/unsafe-foreign-mod.rs:1:1 - | -LL | unsafe extern "C" { - | ^^^^^^ - | - = note: see issue #123743 for more information - = help: add `#![feature(unsafe_extern_blocks)]` 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: aborting due to 1 previous error - diff --git a/tests/ui/rust-2024/safe-outside-extern.rs b/tests/ui/rust-2024/safe-outside-extern.rs index 6773df5ef03b7..674b78dc571ea 100644 --- a/tests/ui/rust-2024/safe-outside-extern.rs +++ b/tests/ui/rust-2024/safe-outside-extern.rs @@ -1,29 +1,21 @@ -//@ revisions: gated ungated -#![cfg_attr(gated, feature(unsafe_extern_blocks))] - safe fn foo() {} //~^ ERROR: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier -//[ungated]~| ERROR: unsafe extern {}` blocks and `safe` keyword are experimental [E0658] safe static FOO: i32 = 1; //~^ ERROR: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier -//[ungated]~| ERROR: unsafe extern {}` blocks and `safe` keyword are experimental [E0658] trait Foo { safe fn foo(); //~^ ERROR: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier - //[ungated]~| ERROR: unsafe extern {}` blocks and `safe` keyword are experimental [E0658] } impl Foo for () { safe fn foo() {} //~^ ERROR: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier - //[ungated]~| ERROR: unsafe extern {}` blocks and `safe` keyword are experimental [E0658] } type FnPtr = safe fn(i32, i32) -> i32; //~^ ERROR: function pointers cannot be declared with `safe` safety qualifier -//[ungated]~| ERROR: unsafe extern {}` blocks and `safe` keyword are experimental [E0658] unsafe static LOL: u8 = 0; //~^ ERROR: static items cannot be declared with `unsafe` safety qualifier outside of `extern` block diff --git a/tests/ui/rust-2024/safe-outside-extern.stderr b/tests/ui/rust-2024/safe-outside-extern.stderr new file mode 100644 index 0000000000000..19d7c5fde0bdf --- /dev/null +++ b/tests/ui/rust-2024/safe-outside-extern.stderr @@ -0,0 +1,38 @@ +error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier + --> $DIR/safe-outside-extern.rs:1:1 + | +LL | safe fn foo() {} + | ^^^^^^^^^^^^^^^^ + +error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier + --> $DIR/safe-outside-extern.rs:4:1 + | +LL | safe static FOO: i32 = 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier + --> $DIR/safe-outside-extern.rs:8:5 + | +LL | safe fn foo(); + | ^^^^^^^^^^^^^^ + +error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier + --> $DIR/safe-outside-extern.rs:13:5 + | +LL | safe fn foo() {} + | ^^^^^^^^^^^^^^^^ + +error: function pointers cannot be declared with `safe` safety qualifier + --> $DIR/safe-outside-extern.rs:17:14 + | +LL | type FnPtr = safe fn(i32, i32) -> i32; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: static items cannot be declared with `unsafe` safety qualifier outside of `extern` block + --> $DIR/safe-outside-extern.rs:20:1 + | +LL | unsafe static LOL: u8 = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr index 3a99caa719b53..77554da10e60b 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr @@ -1,5 +1,5 @@ error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe function or block - --> $DIR/extern-items-unsafe.rs:14:5 + --> $DIR/extern-items-unsafe.rs:12:5 | LL | test1(TEST1); | ^^^^^^^^^^^^ call to unsafe function @@ -7,7 +7,7 @@ LL | test1(TEST1); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: use of extern static is unsafe and requires unsafe function or block - --> $DIR/extern-items-unsafe.rs:14:11 + --> $DIR/extern-items-unsafe.rs:12:11 | LL | test1(TEST1); | ^^^^^ use of extern static diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr index fcf937b7ac577..33b752782d599 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr @@ -1,5 +1,5 @@ error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe block - --> $DIR/extern-items-unsafe.rs:14:5 + --> $DIR/extern-items-unsafe.rs:12:5 | LL | test1(TEST1); | ^^^^^^^^^^^^ call to unsafe function @@ -7,7 +7,7 @@ LL | test1(TEST1); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: use of extern static is unsafe and requires unsafe block - --> $DIR/extern-items-unsafe.rs:14:11 + --> $DIR/extern-items-unsafe.rs:12:11 | LL | test1(TEST1); | ^^^^^ use of extern static diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs index ad569a256db90..721e07acca588 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs @@ -3,8 +3,6 @@ //@[edition2024] edition:2024 //@[edition2024] compile-flags: -Zunstable-options -#![feature(unsafe_extern_blocks)] - unsafe extern "C" { static TEST1: i32; fn test1(i: i32); diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr index d456cfc6829e1..8ef7c2caf21ee 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr @@ -1,5 +1,5 @@ error: extern blocks must be unsafe - --> $DIR/extern-items.rs:9:1 + --> $DIR/extern-items.rs:7:1 | LL | / extern "C" { LL | | diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs index 16fa1bbb8a404..08805c3634765 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs @@ -4,8 +4,6 @@ //@[edition2024] edition:2024 //@[edition2024] compile-flags: -Zunstable-options -#![feature(unsafe_extern_blocks)] - extern "C" { //[edition2024]~^ ERROR extern blocks must be unsafe static TEST1: i32; diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.rs b/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.rs index 57c03e4d896be..67df8c14b39fd 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.rs @@ -1,6 +1,3 @@ -//@ revisions: gated ungated -#![cfg_attr(gated, feature(unsafe_extern_blocks))] - trait Bar {} safe impl Bar for () { } //~^ ERROR expected one of `!` or `::`, found keyword `impl` diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.gated.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.stderr similarity index 83% rename from tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.gated.stderr rename to tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.stderr index 80e7a45f57e79..f1021726b1816 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.gated.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.stderr @@ -1,5 +1,5 @@ error: expected one of `!` or `::`, found keyword `impl` - --> $DIR/safe-impl-trait.rs:5:6 + --> $DIR/safe-impl-trait.rs:2:6 | LL | safe impl Bar for () { } | ^^^^ expected one of `!` or `::` diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs b/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs index 74cd5621fce93..b0b8a8b012a6a 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs @@ -4,8 +4,6 @@ //@[edition2024] compile-flags: -Zunstable-options //@ check-pass -#![feature(unsafe_extern_blocks)] - unsafe extern "C" { safe static TEST1: i32; safe fn test1(i: i32); diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.rs b/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.rs index e73cb45b18877..52773b4cbbbbf 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.rs @@ -1,6 +1,3 @@ -//@ revisions: gated ungated -#![cfg_attr(gated, feature(unsafe_extern_blocks))] - safe trait Foo {} //~^ ERROR expected one of `!` or `::`, found keyword `trait` diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.stderr new file mode 100644 index 0000000000000..1733336a797b2 --- /dev/null +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.stderr @@ -0,0 +1,8 @@ +error: expected one of `!` or `::`, found keyword `trait` + --> $DIR/safe-trait.rs:1:6 + | +LL | safe trait Foo {} + | ^^^^^ expected one of `!` or `::` + +error: aborting due to 1 previous error + diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr index e90613357b1ca..9379798728669 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr @@ -1,5 +1,5 @@ error: items in unadorned `extern` blocks cannot have safety qualifiers - --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:10:5 + --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:8:5 | LL | safe static TEST1: i32; | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -10,7 +10,7 @@ LL | unsafe extern "C" { | ++++++ error: items in unadorned `extern` blocks cannot have safety qualifiers - --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:12:5 + --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:10:5 | LL | safe fn test1(i: i32); | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr index 1207ee158cc13..e9db6006c0b58 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr @@ -1,5 +1,5 @@ error: extern blocks must be unsafe - --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:8:1 + --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:6:1 | LL | / extern "C" { LL | | @@ -11,7 +11,7 @@ LL | | } | |_^ error: items in unadorned `extern` blocks cannot have safety qualifiers - --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:10:5 + --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:8:5 | LL | safe static TEST1: i32; | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -22,7 +22,7 @@ LL | unsafe extern "C" { | ++++++ error: items in unadorned `extern` blocks cannot have safety qualifiers - --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:12:5 + --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:10:5 | LL | safe fn test1(i: i32); | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs index 11f55cb195f29..4badb50b26735 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs @@ -3,8 +3,6 @@ //@[edition2024] edition:2024 //@[edition2024] compile-flags: -Zunstable-options -#![feature(unsafe_extern_blocks)] - extern "C" { //[edition2024]~^ ERROR extern blocks must be unsafe safe static TEST1: i32; diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.fixed b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.fixed index 10c19759d8aaa..f686809615fb0 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.fixed +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.fixed @@ -1,6 +1,5 @@ //@ run-rustfix -#![feature(unsafe_extern_blocks)] #![deny(missing_unsafe_on_extern)] #![allow(unused)] diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.rs b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.rs index b81e52ddc5843..00f1cbdab54ff 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.rs @@ -1,6 +1,5 @@ //@ run-rustfix -#![feature(unsafe_extern_blocks)] #![deny(missing_unsafe_on_extern)] #![allow(unused)] diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.stderr index 0a3c2cd25e3fe..bb1d068ceb91b 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.stderr @@ -1,5 +1,5 @@ error: extern blocks should be unsafe - --> $DIR/unsafe-extern-suggestion.rs:7:1 + --> $DIR/unsafe-extern-suggestion.rs:6:1 | LL | extern "C" { | ^ @@ -16,7 +16,7 @@ LL | | } = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! = note: for more information, see issue #123743 note: the lint level is defined here - --> $DIR/unsafe-extern-suggestion.rs:4:9 + --> $DIR/unsafe-extern-suggestion.rs:3:9 | LL | #![deny(missing_unsafe_on_extern)] | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr index 8bb7ffefeea9e..e3626bb497e4f 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr @@ -1,5 +1,5 @@ error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe function or block - --> $DIR/unsafe-items.rs:20:5 + --> $DIR/unsafe-items.rs:18:5 | LL | test1(TEST1); | ^^^^^^^^^^^^ call to unsafe function @@ -7,7 +7,7 @@ LL | test1(TEST1); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: use of extern static is unsafe and requires unsafe function or block - --> $DIR/unsafe-items.rs:20:11 + --> $DIR/unsafe-items.rs:18:11 | LL | test1(TEST1); | ^^^^^ use of extern static diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr index 9a30142a632c5..89bc501b7b5a5 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr @@ -1,5 +1,5 @@ error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe block - --> $DIR/unsafe-items.rs:20:5 + --> $DIR/unsafe-items.rs:18:5 | LL | test1(TEST1); | ^^^^^^^^^^^^ call to unsafe function @@ -7,7 +7,7 @@ LL | test1(TEST1); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: use of extern static is unsafe and requires unsafe block - --> $DIR/unsafe-items.rs:20:11 + --> $DIR/unsafe-items.rs:18:11 | LL | test1(TEST1); | ^^^^^ use of extern static diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs index 9066953abc615..dc2bae892a988 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs @@ -3,8 +3,6 @@ //@[edition2024] edition:2024 //@[edition2024] compile-flags: -Zunstable-options -#![feature(unsafe_extern_blocks)] - unsafe extern "C" { unsafe static TEST1: i32; unsafe fn test1(i: i32); diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.fixed b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.fixed index 2ff595cc44d1e..857d34eef8521 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.fixed +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.fixed @@ -1,6 +1,5 @@ //@ run-rustfix -#![feature(unsafe_extern_blocks)] #![allow(dead_code)] unsafe extern "C" { diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.rs b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.rs index 6fe43f7a5b46d..edab9850d796f 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.rs @@ -1,6 +1,5 @@ //@ run-rustfix -#![feature(unsafe_extern_blocks)] #![allow(dead_code)] extern "C" { diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.stderr index 05d23d001ada7..073245e650b1c 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.stderr @@ -1,5 +1,5 @@ error: items in unadorned `extern` blocks cannot have safety qualifiers - --> $DIR/unsafe-on-extern-block-issue-126756.rs:7:5 + --> $DIR/unsafe-on-extern-block-issue-126756.rs:6:5 | LL | unsafe fn foo(); | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unpretty/expanded-exhaustive.rs b/tests/ui/unpretty/expanded-exhaustive.rs index 92c2e7b488478..29472df897a1f 100644 --- a/tests/ui/unpretty/expanded-exhaustive.rs +++ b/tests/ui/unpretty/expanded-exhaustive.rs @@ -25,7 +25,6 @@ #![feature(trait_alias)] #![feature(try_blocks)] #![feature(unnamed_fields)] -#![feature(unsafe_extern_blocks)] #![feature(yeet_expr)] #![allow(incomplete_features)] diff --git a/tests/ui/unpretty/expanded-exhaustive.stdout b/tests/ui/unpretty/expanded-exhaustive.stdout index 137a8aa5510d0..cf2f6f8cbaa99 100644 --- a/tests/ui/unpretty/expanded-exhaustive.stdout +++ b/tests/ui/unpretty/expanded-exhaustive.stdout @@ -26,7 +26,6 @@ #![feature(trait_alias)] #![feature(try_blocks)] #![feature(unnamed_fields)] -#![feature(unsafe_extern_blocks)] #![feature(yeet_expr)] #![allow(incomplete_features)] #[prelude_import] From 0cdf6e172cb861387d41ad01540a321a1e09c1b4 Mon Sep 17 00:00:00 2001 From: jusexton Date: Tue, 23 Jul 2024 02:55:58 -0500 Subject: [PATCH 050/786] Fix while_let_on_iterator dropping loop label when applying fix. --- clippy_lints/src/loops/while_let_on_iterator.rs | 7 +++++-- clippy_utils/src/higher.rs | 4 +++- tests/ui/while_let_on_iterator.fixed | 9 +++++++++ tests/ui/while_let_on_iterator.rs | 9 +++++++++ tests/ui/while_let_on_iterator.stderr | 8 +++++++- 5 files changed, 33 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/loops/while_let_on_iterator.rs b/clippy_lints/src/loops/while_let_on_iterator.rs index 194dd4752f91b..c171fa1c622af 100644 --- a/clippy_lints/src/loops/while_let_on_iterator.rs +++ b/clippy_lints/src/loops/while_let_on_iterator.rs @@ -14,7 +14,7 @@ use rustc_span::symbol::sym; use rustc_span::Symbol; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - if let Some(higher::WhileLet { if_then, let_pat, let_expr, .. }) = higher::WhileLet::hir(expr) + if let Some(higher::WhileLet { if_then, let_pat, let_expr, label, .. }) = higher::WhileLet::hir(expr) // check for `Some(..)` pattern && let PatKind::TupleStruct(ref pat_path, some_pat, _) = let_pat.kind && is_res_lang_ctor(cx, cx.qpath_res(pat_path, let_pat.hir_id), LangItem::OptionSome) @@ -27,6 +27,9 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { && !uses_iter(cx, &iter_expr_struct, if_then) { let mut applicability = Applicability::MachineApplicable; + + let loop_label = label.map_or(String::new(), |l| format!("{}: ", l.ident.name)); + let loop_var = if let Some(some_pat) = some_pat.first() { if is_refutable(cx, some_pat) { // Refutable patterns don't work with for loops. @@ -57,7 +60,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { expr.span.with_hi(let_expr.span.hi()), "this loop could be written as a `for` loop", "try", - format!("for {loop_var} in {iterator}{by_ref}"), + format!("{loop_label}for {loop_var} in {iterator}{by_ref}"), applicability, ); } diff --git a/clippy_utils/src/higher.rs b/clippy_utils/src/higher.rs index 277ba8427e054..7ce9bde1a7339 100644 --- a/clippy_utils/src/higher.rs +++ b/clippy_utils/src/higher.rs @@ -367,6 +367,7 @@ pub struct WhileLet<'hir> { pub let_expr: &'hir Expr<'hir>, /// `while let` loop body pub if_then: &'hir Expr<'hir>, + pub label: Option, /// `while let PAT = EXPR` /// ^^^^^^^^^^^^^^ pub let_span: Span, @@ -399,7 +400,7 @@ impl<'hir> WhileLet<'hir> { }), .. }, - _, + label, LoopSource::While, _, ) = expr.kind @@ -408,6 +409,7 @@ impl<'hir> WhileLet<'hir> { let_pat, let_expr, if_then, + label, let_span, }); } diff --git a/tests/ui/while_let_on_iterator.fixed b/tests/ui/while_let_on_iterator.fixed index 59b5c858d0460..b8087c6e000f5 100644 --- a/tests/ui/while_let_on_iterator.fixed +++ b/tests/ui/while_let_on_iterator.fixed @@ -456,6 +456,15 @@ fn fn_once_closure() { }); } +fn issue13123() { + let mut it = 0..20; + 'label: for n in it { + if n % 25 == 0 { + break 'label; + } + } +} + fn main() { let mut it = 0..20; for _ in it { diff --git a/tests/ui/while_let_on_iterator.rs b/tests/ui/while_let_on_iterator.rs index 559513d56946d..8e02f59b51265 100644 --- a/tests/ui/while_let_on_iterator.rs +++ b/tests/ui/while_let_on_iterator.rs @@ -456,6 +456,15 @@ fn fn_once_closure() { }); } +fn issue13123() { + let mut it = 0..20; + 'label: while let Some(n) = it.next() { + if n % 25 == 0 { + break 'label; + } + } +} + fn main() { let mut it = 0..20; while let Some(..) = it.next() { diff --git a/tests/ui/while_let_on_iterator.stderr b/tests/ui/while_let_on_iterator.stderr index 8ff1f23644b16..d96b26acf345d 100644 --- a/tests/ui/while_let_on_iterator.stderr +++ b/tests/ui/while_let_on_iterator.stderr @@ -160,8 +160,14 @@ LL | while let Some(x) = it.next() { error: this loop could be written as a `for` loop --> tests/ui/while_let_on_iterator.rs:461:5 | +LL | 'label: while let Some(n) = it.next() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'label: for n in it` + +error: this loop could be written as a `for` loop + --> tests/ui/while_let_on_iterator.rs:470:5 + | LL | while let Some(..) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in it` -error: aborting due to 27 previous errors +error: aborting due to 28 previous errors From aded725d6b955e5b24bda4b985996667fe9dc16f Mon Sep 17 00:00:00 2001 From: Folkert Date: Thu, 4 Jul 2024 17:26:36 +0200 Subject: [PATCH 051/786] add `is_multiple_of` for unsigned integer types --- library/core/src/num/uint_macros.rs | 29 +++++++++++++++++++++++++++ library/core/tests/lib.rs | 1 + library/core/tests/num/uint_macros.rs | 8 ++++++++ 3 files changed, 38 insertions(+) diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index d50bcde01571c..3c8e358536c75 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -2764,6 +2764,35 @@ macro_rules! uint_impl { } } + /// Returns `true` if `self` is an integer multiple of `rhs`, and false otherwise. + /// + /// This function is equivalent to `self % rhs == 0`, except that it will not panic + /// for `rhs == 0`. Instead, `0.is_multiple_of(0) == true`, and for any non-zero `n`, + /// `n.is_multiple_of(0) == false`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(unsigned_is_multiple_of)] + #[doc = concat!("assert!(6_", stringify!($SelfT), ".is_multiple_of(2));")] + #[doc = concat!("assert!(!5_", stringify!($SelfT), ".is_multiple_of(2));")] + /// + #[doc = concat!("assert!(0_", stringify!($SelfT), ".is_multiple_of(0));")] + #[doc = concat!("assert!(!6_", stringify!($SelfT), ".is_multiple_of(0));")] + /// ``` + #[unstable(feature = "unsigned_is_multiple_of", issue = "128101")] + #[must_use] + #[inline] + #[rustc_inherit_overflow_checks] + pub const fn is_multiple_of(self, rhs: Self) -> bool { + match rhs { + 0 => self == 0, + _ => self % rhs == 0, + } + } + /// Returns `true` if and only if `self == 2^k` for some `k`. /// /// # Examples diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 83a615fcd8be3..f218c3811eebb 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -61,6 +61,7 @@ #![feature(num_midpoint)] #![feature(offset_of_nested)] #![feature(isqrt)] +#![feature(unsigned_is_multiple_of)] #![feature(step_trait)] #![feature(str_internals)] #![feature(std_internals)] diff --git a/library/core/tests/num/uint_macros.rs b/library/core/tests/num/uint_macros.rs index 955440647eb98..d009ad89d5ce7 100644 --- a/library/core/tests/num/uint_macros.rs +++ b/library/core/tests/num/uint_macros.rs @@ -260,6 +260,14 @@ macro_rules! uint_module { assert_eq!(MAX.checked_next_multiple_of(2), None); } + #[test] + fn test_is_next_multiple_of() { + assert!((12 as $T).is_multiple_of(4)); + assert!(!(12 as $T).is_multiple_of(5)); + assert!((0 as $T).is_multiple_of(0)); + assert!(!(12 as $T).is_multiple_of(0)); + } + #[test] fn test_carrying_add() { assert_eq!($T::MAX.carrying_add(1, false), (0, true)); From c646256f0639002cd9e5872f711f09ec77630a74 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Wed, 24 Jul 2024 05:00:48 +0000 Subject: [PATCH 052/786] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index b09d4f11f68ef..60497630ae0d0 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -9057c3ffec44926d5e149dc13ff3ce1613b69cce +42103d69b73fb4e9d03d5cf66ec12985bb526f6e From a0088d7a813a1f63e5af4d6edc5d2c50a0b3702e Mon Sep 17 00:00:00 2001 From: Konstantinos Andrikopoulos Date: Sat, 20 Jul 2024 11:28:48 +0200 Subject: [PATCH 053/786] Allow getpid in isolation mode, add gettid support In order to support gettid when isolation is enabled and when it is disabled, and satisfy its requirement that: In a single-threaded process, the thread ID is equal to the process ID (PID, as returned by getpid(2)). we define the thread ID to be getpid() + . Since the internal thread id of the main thread is zero, this will satisfy that requirement. However, getpid for now was only supported when isolation was disabled. To support getpid in isolation mode, we return a hardcoded value (1000) and return that instead of the real PID. --- src/tools/miri/src/shims/env.rs | 5 +++++ src/tools/miri/src/shims/unix/env.rs | 17 +++++++++++--- .../src/shims/unix/linux/foreign_items.rs | 5 +++++ src/tools/miri/src/shims/windows/env.rs | 3 +-- src/tools/miri/tests/pass-dep/libc/gettid.rs | 22 +++++++++++++++++++ src/tools/miri/tests/pass/getpid.rs | 15 +++++++++++-- 6 files changed, 60 insertions(+), 7 deletions(-) create mode 100644 src/tools/miri/tests/pass-dep/libc/gettid.rs diff --git a/src/tools/miri/src/shims/env.rs b/src/tools/miri/src/shims/env.rs index 7ad395cccb799..6586ea8e48cff 100644 --- a/src/tools/miri/src/shims/env.rs +++ b/src/tools/miri/src/shims/env.rs @@ -108,4 +108,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { EnvVars::Windows(vars) => vars.get(name), } } + + fn get_pid(&self) -> u32 { + let this = self.eval_context_ref(); + if this.machine.communicate() { std::process::id() } else { 1000 } + } } diff --git a/src/tools/miri/src/shims/unix/env.rs b/src/tools/miri/src/shims/unix/env.rs index 405431f4327db..3b8ad65195b8a 100644 --- a/src/tools/miri/src/shims/unix/env.rs +++ b/src/tools/miri/src/shims/unix/env.rs @@ -274,12 +274,23 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let this = self.eval_context_mut(); this.assert_target_os_is_unix("getpid"); - this.check_no_isolation("`getpid`")?; - // The reason we need to do this wacky of a conversion is because // `libc::getpid` returns an i32, however, `std::process::id()` return an u32. // So we un-do the conversion that stdlib does and turn it back into an i32. #[allow(clippy::cast_possible_wrap)] - Ok(std::process::id() as i32) + Ok(this.get_pid() as i32) + } + + fn linux_gettid(&mut self) -> InterpResult<'tcx, i32> { + let this = self.eval_context_ref(); + this.assert_target_os("linux", "gettid"); + + let index = this.machine.threads.active_thread().to_u32(); + + // Compute a TID for this thread, ensuring that the main thread has PID == TID. + let tid = this.get_pid().strict_add(index); + + #[allow(clippy::cast_possible_wrap)] + Ok(tid as i32) } } diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs index 95bee38cd7835..20c6a23479421 100644 --- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs @@ -94,6 +94,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { )?; this.write_scalar(res, dest)?; } + "gettid" => { + let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let result = this.linux_gettid()?; + this.write_scalar(Scalar::from_i32(result), dest)?; + } // Dynamically invoked syscalls "syscall" => { diff --git a/src/tools/miri/src/shims/windows/env.rs b/src/tools/miri/src/shims/windows/env.rs index ed3eb69798637..77ae06bd5c2d8 100644 --- a/src/tools/miri/src/shims/windows/env.rs +++ b/src/tools/miri/src/shims/windows/env.rs @@ -200,9 +200,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn GetCurrentProcessId(&mut self) -> InterpResult<'tcx, u32> { let this = self.eval_context_mut(); this.assert_target_os("windows", "GetCurrentProcessId"); - this.check_no_isolation("`GetCurrentProcessId`")?; - Ok(std::process::id()) + Ok(this.get_pid()) } #[allow(non_snake_case)] diff --git a/src/tools/miri/tests/pass-dep/libc/gettid.rs b/src/tools/miri/tests/pass-dep/libc/gettid.rs new file mode 100644 index 0000000000000..87405b02ac35d --- /dev/null +++ b/src/tools/miri/tests/pass-dep/libc/gettid.rs @@ -0,0 +1,22 @@ +//@only-target-linux +//@revisions: with_isolation without_isolation +//@[without_isolation] compile-flags: -Zmiri-disable-isolation + +use libc::{getpid, gettid}; +use std::thread; + +fn main() { + thread::spawn(|| { + // Test that in isolation mode a deterministic value will be returned. + // The value 1001 is not important, we only care that whatever the value + // is, won't change from execution to execution. + #[cfg(with_isolation)] + assert_eq!(unsafe { gettid() }, 1001); + + assert_ne!(unsafe { gettid() }, unsafe { getpid() }); + }); + + // Test that the thread ID of the main thread is the same as the process + // ID. + assert_eq!(unsafe { gettid() }, unsafe { getpid() }); +} diff --git a/src/tools/miri/tests/pass/getpid.rs b/src/tools/miri/tests/pass/getpid.rs index 733545462ebc0..f350fafff4a26 100644 --- a/src/tools/miri/tests/pass/getpid.rs +++ b/src/tools/miri/tests/pass/getpid.rs @@ -1,9 +1,20 @@ -//@compile-flags: -Zmiri-disable-isolation +//@revisions: with_isolation without_isolation +//@[without_isolation] compile-flags: -Zmiri-disable-isolation fn getpid() -> u32 { std::process::id() } fn main() { - getpid(); + let pid = getpid(); + + std::thread::spawn(move || { + assert_eq!(getpid(), pid); + }); + + // Test that in isolation mode a deterministic value will be returned. + // The value 1000 is not important, we only care that whatever the value + // is, won't change from execution to execution. + #[cfg(with_isolation)] + assert_eq!(pid, 1000); } From ea7625f4266e69498ea5b9287a72e543a514a837 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 24 Jul 2024 16:47:56 +0200 Subject: [PATCH 054/786] Set branch protection function attributes Since LLVM 19, it is necessary to set not only module flags, but also function attributes for branch protection on aarch64. See https://github.com/llvm/llvm-project/commit/e15d67cfc2e5775cc79281aa860f3ad3be628f39 for the relevant LLVM change. --- compiler/rustc_codegen_llvm/src/attributes.rs | 31 +++++++++++-- tests/codegen/branch-protection-old-llvm.rs | 45 +++++++++++++++++++ tests/codegen/branch-protection.rs | 10 +++++ 3 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 tests/codegen/branch-protection-old-llvm.rs diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 3877460fcdb0d..ff01a2088812d 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -4,7 +4,7 @@ use rustc_codegen_ssa::traits::*; use rustc_hir::def_id::DefId; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, PatchableFunctionEntry}; use rustc_middle::ty::{self, TyCtxt}; -use rustc_session::config::{FunctionReturn, OptLevel}; +use rustc_session::config::{BranchProtection, FunctionReturn, OptLevel, PAuthKey, PacRet}; use rustc_span::symbol::sym; use rustc_target::spec::{FramePointer, SanitizerSet, StackProbeType, StackProtector}; use smallvec::SmallVec; @@ -407,8 +407,33 @@ pub fn from_fn_attrs<'ll, 'tcx>( // And it is a module-level attribute, so the alternative is pulling naked functions into new LLVM modules. // Otherwise LLVM's "naked" functions come with endbr prefixes per https://github.com/rust-lang/rust/issues/98768 to_add.push(AttributeKind::NoCfCheck.create_attr(cx.llcx)); - // Need this for AArch64. - to_add.push(llvm::CreateAttrStringValue(cx.llcx, "branch-target-enforcement", "false")); + if llvm_util::get_version() < (19, 0, 0) { + // Prior to LLVM 19, branch-target-enforcement was disabled by setting the attribute to + // the string "false". Now it is disabled by absence of the attribute. + to_add.push(llvm::CreateAttrStringValue(cx.llcx, "branch-target-enforcement", "false")); + } + } else if llvm_util::get_version() >= (19, 0, 0) { + // For non-naked functions, set branch protection attributes on aarch64. + if let Some(BranchProtection { bti, pac_ret }) = + cx.sess().opts.unstable_opts.branch_protection + { + assert!(cx.sess().target.arch == "aarch64"); + if bti { + to_add.push(llvm::CreateAttrString(cx.llcx, "branch-target-enforcement")); + } + if let Some(PacRet { leaf, key }) = pac_ret { + to_add.push(llvm::CreateAttrStringValue( + cx.llcx, + "sign-return-address", + if leaf { "all" } else { "non-leaf" }, + )); + to_add.push(llvm::CreateAttrStringValue( + cx.llcx, + "sign-return-address-key", + if key == PAuthKey::A { "a_key" } else { "b_key" }, + )); + } + } } if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::ALLOCATOR) || codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::ALLOCATOR_ZEROED) diff --git a/tests/codegen/branch-protection-old-llvm.rs b/tests/codegen/branch-protection-old-llvm.rs new file mode 100644 index 0000000000000..bb3c7a4b70c3c --- /dev/null +++ b/tests/codegen/branch-protection-old-llvm.rs @@ -0,0 +1,45 @@ +// Test that the correct module flags are emitted with different branch protection flags. + +//@ revisions: BTI PACRET LEAF BKEY NONE +//@ needs-llvm-components: aarch64 +//@ [BTI] compile-flags: -Z branch-protection=bti +//@ [PACRET] compile-flags: -Z branch-protection=pac-ret +//@ [LEAF] compile-flags: -Z branch-protection=pac-ret,leaf +//@ [BKEY] compile-flags: -Z branch-protection=pac-ret,b-key +//@ compile-flags: --target aarch64-unknown-linux-gnu +//@ ignore-llvm-version: 19 - 99 + +#![crate_type = "lib"] +#![feature(no_core, lang_items)] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +// A basic test function. +pub fn test() {} + +// BTI: !"branch-target-enforcement", i32 1 +// BTI: !"sign-return-address", i32 0 +// BTI: !"sign-return-address-all", i32 0 +// BTI: !"sign-return-address-with-bkey", i32 0 + +// PACRET: !"branch-target-enforcement", i32 0 +// PACRET: !"sign-return-address", i32 1 +// PACRET: !"sign-return-address-all", i32 0 +// PACRET: !"sign-return-address-with-bkey", i32 0 + +// LEAF: !"branch-target-enforcement", i32 0 +// LEAF: !"sign-return-address", i32 1 +// LEAF: !"sign-return-address-all", i32 1 +// LEAF: !"sign-return-address-with-bkey", i32 0 + +// BKEY: !"branch-target-enforcement", i32 0 +// BKEY: !"sign-return-address", i32 1 +// BKEY: !"sign-return-address-all", i32 0 +// BKEY: !"sign-return-address-with-bkey", i32 1 + +// NONE-NOT: branch-target-enforcement +// NONE-NOT: sign-return-address +// NONE-NOT: sign-return-address-all +// NONE-NOT: sign-return-address-with-bkey diff --git a/tests/codegen/branch-protection.rs b/tests/codegen/branch-protection.rs index a29ec67d578b8..2f5ff9e98c22d 100644 --- a/tests/codegen/branch-protection.rs +++ b/tests/codegen/branch-protection.rs @@ -7,6 +7,7 @@ //@ [LEAF] compile-flags: -Z branch-protection=pac-ret,leaf //@ [BKEY] compile-flags: -Z branch-protection=pac-ret,b-key //@ compile-flags: --target aarch64-unknown-linux-gnu +//@ min-llvm-version: 19 #![crate_type = "lib"] #![feature(no_core, lang_items)] @@ -16,23 +17,32 @@ trait Sized {} // A basic test function. +// CHECK: @test(){{.*}} [[ATTR:#[0-9]+]] { +#[no_mangle] pub fn test() {} +// BTI: attributes [[ATTR]] = {{.*}} "branch-target-enforcement" // BTI: !"branch-target-enforcement", i32 1 // BTI: !"sign-return-address", i32 0 // BTI: !"sign-return-address-all", i32 0 // BTI: !"sign-return-address-with-bkey", i32 0 +// PACRET: attributes [[ATTR]] = {{.*}} "sign-return-address"="non-leaf" +// PACRET-SAME: "sign-return-address-key"="a_key" // PACRET: !"branch-target-enforcement", i32 0 // PACRET: !"sign-return-address", i32 1 // PACRET: !"sign-return-address-all", i32 0 // PACRET: !"sign-return-address-with-bkey", i32 0 +// LEAF: attributes [[ATTR]] = {{.*}} "sign-return-address"="all" +// LEAF-SAME: "sign-return-address-key"="a_key" // LEAF: !"branch-target-enforcement", i32 0 // LEAF: !"sign-return-address", i32 1 // LEAF: !"sign-return-address-all", i32 1 // LEAF: !"sign-return-address-with-bkey", i32 0 +// BKEY: attributes [[ATTR]] = {{.*}} "sign-return-address"="non-leaf" +// BKEY-SAME: "sign-return-address-key"="b_key" // BKEY: !"branch-target-enforcement", i32 0 // BKEY: !"sign-return-address", i32 1 // BKEY: !"sign-return-address-all", i32 0 From c45f4646393b4ecab0c75b251f409bf12a1999da Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 22 Jun 2024 16:45:20 +0200 Subject: [PATCH 055/786] show warning when Stacked Borrows skips a reborrow due to 'extern type' --- .../src/borrow_tracker/stacked_borrows/mod.rs | 15 ++++++++- src/tools/miri/src/diagnostics.rs | 31 ++++++++++++++++--- .../fail/extern-type-field-offset.stderr | 13 +++++++- .../ptr_metadata_uninit_slice_len.stderr | 10 +++--- src/tools/miri/tests/pass/box.stack.stderr | 10 +++--- .../miri/tests/pass/extern_types.stack.stderr | 21 ++++++++++--- .../stacked-borrows/issue-miri-2389.stderr | 10 +++--- 7 files changed, 83 insertions(+), 27 deletions(-) diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs index 603733f9dc000..1d75486a78189 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -5,6 +5,7 @@ pub mod diagnostics; mod item; mod stack; +use std::cell::RefCell; use std::cmp; use std::fmt::Write; use std::mem; @@ -820,7 +821,19 @@ trait EvalContextPrivExt<'tcx, 'ecx>: crate::MiriInterpCxExt<'tcx> { // See https://github.com/rust-lang/unsafe-code-guidelines/issues/276. let size = match size { Some(size) => size, - None => return Ok(place.clone()), + None => { + // The first time this happens, show a warning. + thread_local! { static WARNING_SHOWN: RefCell = const { RefCell::new(false) }; } + WARNING_SHOWN.with_borrow_mut(|shown| { + if *shown { + return; + } + // Not yet shown. Show it! + *shown = true; + this.emit_diagnostic(NonHaltingDiagnostic::ExternTypeReborrow); + }); + return Ok(place.clone()); + } }; // Compute new borrow. diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs index 647d7d44bb1bb..45a8a54bc298a 100644 --- a/src/tools/miri/src/diagnostics.rs +++ b/src/tools/miri/src/diagnostics.rs @@ -130,6 +130,7 @@ pub enum NonHaltingDiagnostic { WeakMemoryOutdatedLoad { ptr: Pointer, }, + ExternTypeReborrow, } /// Level of Miri specific diagnostics @@ -593,6 +594,8 @@ impl<'tcx> MiriMachine<'tcx> { RejectedIsolatedOp(_) => ("operation rejected by isolation".to_string(), DiagLevel::Warning), Int2Ptr { .. } => ("integer-to-pointer cast".to_string(), DiagLevel::Warning), + ExternTypeReborrow => + ("reborrow of reference to `extern type`".to_string(), DiagLevel::Warning), CreatedPointerTag(..) | PoppedPointerTag(..) | CreatedCallId(..) @@ -630,6 +633,8 @@ impl<'tcx> MiriMachine<'tcx> { Int2Ptr { .. } => format!("integer-to-pointer cast"), WeakMemoryOutdatedLoad { ptr } => format!("weak memory emulation: outdated value returned from load at {ptr}"), + ExternTypeReborrow => + format!("reborrow of a reference to `extern type` is not properly supported"), }; let notes = match &e { @@ -647,34 +652,50 @@ impl<'tcx> MiriMachine<'tcx> { ( None, format!( - "This program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program." + "this program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program" ), ), ( None, format!( - "See https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation." + "see https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation" ), ), ( None, format!( - "To ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead." + "to ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead" ), ), ( None, format!( - "You can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics." + "you can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics" ), ), ( None, format!( - "Alternatively, `MIRIFLAGS=-Zmiri-permissive-provenance` disables this warning." + "alternatively, `MIRIFLAGS=-Zmiri-permissive-provenance` disables this warning" ), ), ], + ExternTypeReborrow => { + vec![ + ( + None, + format!( + "`extern type` are not compatible with the Stacked Borrows aliasing model implemented by Miri; Miri may miss bugs in this code" + ), + ), + ( + None, + format!( + "try running with `MIRIFLAGS=-Zmiri-tree-borrows` to use the more permissive but also even more experimental Tree Borrows aliasing checks instead" + ), + ), + ] + } _ => vec![], }; diff --git a/src/tools/miri/tests/fail/extern-type-field-offset.stderr b/src/tools/miri/tests/fail/extern-type-field-offset.stderr index 3ed5732b4eb06..c07b63e0c0384 100644 --- a/src/tools/miri/tests/fail/extern-type-field-offset.stderr +++ b/src/tools/miri/tests/fail/extern-type-field-offset.stderr @@ -1,3 +1,14 @@ +warning: reborrow of reference to `extern type` + --> $DIR/extern-type-field-offset.rs:LL:CC + | +LL | let x: &Newtype = unsafe { &*(&buf as *const _ as *const Newtype) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reborrow of a reference to `extern type` is not properly supported + | + = help: `extern type` are not compatible with the Stacked Borrows aliasing model implemented by Miri; Miri may miss bugs in this code + = help: try running with `MIRIFLAGS=-Zmiri-tree-borrows` to use the more permissive but also even more experimental Tree Borrows aliasing checks instead + = note: BACKTRACE: + = note: inside `main` at $DIR/extern-type-field-offset.rs:LL:CC + error: unsupported operation: `extern type` field does not have a known offset --> $DIR/extern-type-field-offset.rs:LL:CC | @@ -10,5 +21,5 @@ LL | let _field = &x.a; note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to 1 previous error +error: aborting due to 1 previous error; 1 warning emitted 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 217bc82010df9..84023cf793713 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 @@ -4,11 +4,11 @@ warning: integer-to-pointer cast LL | (*p.as_mut_ptr().cast::<[*const i32; 2]>())[0] = 4 as *const i32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ integer-to-pointer cast | - = help: This program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program. - = help: See https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation. - = help: To ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead. - = help: You can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics. - = help: Alternatively, `MIRIFLAGS=-Zmiri-permissive-provenance` disables this warning. + = help: this program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program + = help: see https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation + = help: to ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead + = help: you can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics + = help: alternatively, `MIRIFLAGS=-Zmiri-permissive-provenance` disables this warning = note: BACKTRACE: = note: inside `main` at $DIR/ptr_metadata_uninit_slice_len.rs:LL:CC diff --git a/src/tools/miri/tests/pass/box.stack.stderr b/src/tools/miri/tests/pass/box.stack.stderr index 341f84c8992df..f2d01b518fc80 100644 --- a/src/tools/miri/tests/pass/box.stack.stderr +++ b/src/tools/miri/tests/pass/box.stack.stderr @@ -4,11 +4,11 @@ warning: integer-to-pointer cast LL | let r2 = ((r as usize) + 0) as *mut i32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ integer-to-pointer cast | - = help: This program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program. - = help: See https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation. - = help: To ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead. - = help: You can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics. - = help: Alternatively, `MIRIFLAGS=-Zmiri-permissive-provenance` disables this warning. + = help: this program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program + = help: see https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation + = help: to ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead + = help: you can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics + = help: alternatively, `MIRIFLAGS=-Zmiri-permissive-provenance` disables this warning = note: BACKTRACE: = note: inside `into_raw` at $DIR/box.rs:LL:CC note: inside `main` diff --git a/src/tools/miri/tests/pass/extern_types.stack.stderr b/src/tools/miri/tests/pass/extern_types.stack.stderr index 03a9167abbc7c..9b6f632eb5a22 100644 --- a/src/tools/miri/tests/pass/extern_types.stack.stderr +++ b/src/tools/miri/tests/pass/extern_types.stack.stderr @@ -4,11 +4,22 @@ warning: integer-to-pointer cast LL | let x: &Foo = unsafe { &*(16 as *const Foo) }; | ^^^^^^^^^^^^^^^^^^ integer-to-pointer cast | - = help: This program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program. - = help: See https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation. - = help: To ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead. - = help: You can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics. - = help: Alternatively, `MIRIFLAGS=-Zmiri-permissive-provenance` disables this warning. + = help: this program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program + = help: see https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation + = help: to ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead + = help: you can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics + = help: alternatively, `MIRIFLAGS=-Zmiri-permissive-provenance` disables this warning + = note: BACKTRACE: + = note: inside `main` at $DIR/extern_types.rs:LL:CC + +warning: reborrow of reference to `extern type` + --> $DIR/extern_types.rs:LL:CC + | +LL | let x: &Foo = unsafe { &*(16 as *const Foo) }; + | ^^^^^^^^^^^^^^^^^^^^ reborrow of a reference to `extern type` is not properly supported + | + = help: `extern type` are not compatible with the Stacked Borrows aliasing model implemented by Miri; Miri may miss bugs in this code + = help: try running with `MIRIFLAGS=-Zmiri-tree-borrows` to use the more permissive but also even more experimental Tree Borrows aliasing checks instead = note: BACKTRACE: = note: inside `main` at $DIR/extern_types.rs:LL:CC diff --git a/src/tools/miri/tests/pass/stacked-borrows/issue-miri-2389.stderr b/src/tools/miri/tests/pass/stacked-borrows/issue-miri-2389.stderr index b0e1adf27d183..216bb6c76bc9a 100644 --- a/src/tools/miri/tests/pass/stacked-borrows/issue-miri-2389.stderr +++ b/src/tools/miri/tests/pass/stacked-borrows/issue-miri-2389.stderr @@ -4,11 +4,11 @@ warning: integer-to-pointer cast LL | let wildcard = &root0 as *const Cell as usize as *const Cell; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ integer-to-pointer cast | - = help: This program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program. - = help: See https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation. - = help: To ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead. - = help: You can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics. - = help: Alternatively, `MIRIFLAGS=-Zmiri-permissive-provenance` disables this warning. + = help: this program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program + = help: see https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation + = help: to ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead + = help: you can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics + = help: alternatively, `MIRIFLAGS=-Zmiri-permissive-provenance` disables this warning = note: BACKTRACE: = note: inside `main` at $DIR/issue-miri-2389.rs:LL:CC From 486f5b50599b7e73f4488d7291e106e6c057c869 Mon Sep 17 00:00:00 2001 From: GnomedDev Date: Mon, 24 Jun 2024 16:17:59 +0100 Subject: [PATCH 056/786] Use Cow<'static, str> for InlineAsmTemplatePiece::String --- src/inline_asm.rs | 4 +--- src/intrinsics/llvm_x86.rs | 42 ++++++++++++++++++++------------------ 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/inline_asm.rs b/src/inline_asm.rs index c88230c936056..16edec47e1029 100644 --- a/src/inline_asm.rs +++ b/src/inline_asm.rs @@ -46,9 +46,7 @@ pub(crate) fn codegen_inline_asm_terminator<'tcx>( // Used by panic_abort on Windows, but uses a syntax which only happens to work with // asm!() by accident and breaks with the GNU assembler as well as global_asm!() for // the LLVM backend. - if template.len() == 1 - && template[0] == InlineAsmTemplatePiece::String("int $$0x29".to_string()) - { + if template.len() == 1 && template[0] == InlineAsmTemplatePiece::String("int $$0x29".into()) { fx.bcx.ins().trap(TrapCode::User(1)); return; } diff --git a/src/intrinsics/llvm_x86.rs b/src/intrinsics/llvm_x86.rs index e1896138e487b..a20faa2cad3a8 100644 --- a/src/intrinsics/llvm_x86.rs +++ b/src/intrinsics/llvm_x86.rs @@ -40,7 +40,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( shl rdx, 32 or rax, rdx " - .to_string(), + .into(), )], &[ CInlineAsmOperand::In { @@ -471,7 +471,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( // into 0x80000000 for which Cranelift doesn't have a native instruction. codegen_inline_asm_inner( fx, - &[InlineAsmTemplatePiece::String(format!("cvtps2dq xmm0, xmm0"))], + &[InlineAsmTemplatePiece::String("cvtps2dq xmm0, xmm0".into())], &[CInlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)), _late: true, @@ -875,7 +875,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( codegen_inline_asm_inner( fx, - &[InlineAsmTemplatePiece::String(asm.to_string())], + &[InlineAsmTemplatePiece::String(asm.into())], &[ CInlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)), @@ -914,7 +914,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( codegen_inline_asm_inner( fx, - &[InlineAsmTemplatePiece::String(format!("pcmpestri xmm0, xmm1, {imm8}"))], + &[InlineAsmTemplatePiece::String(format!("pcmpestri xmm0, xmm1, {imm8}").into())], &[ CInlineAsmOperand::In { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)), @@ -967,7 +967,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( codegen_inline_asm_inner( fx, - &[InlineAsmTemplatePiece::String(format!("pcmpestrm xmm0, xmm1, {imm8}"))], + &[InlineAsmTemplatePiece::String(format!("pcmpestrm xmm0, xmm1, {imm8}").into())], &[ CInlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)), @@ -1015,7 +1015,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( codegen_inline_asm_inner( fx, - &[InlineAsmTemplatePiece::String(format!("pclmulqdq xmm0, xmm1, {imm8}"))], + &[InlineAsmTemplatePiece::String(format!("pclmulqdq xmm0, xmm1, {imm8}").into())], &[ CInlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)), @@ -1052,7 +1052,9 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( codegen_inline_asm_inner( fx, - &[InlineAsmTemplatePiece::String(format!("aeskeygenassist xmm0, xmm0, {imm8}"))], + &[InlineAsmTemplatePiece::String( + format!("aeskeygenassist xmm0, xmm0, {imm8}").into(), + )], &[CInlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)), _late: true, @@ -1071,7 +1073,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( codegen_inline_asm_inner( fx, - &[InlineAsmTemplatePiece::String("aesimc xmm0, xmm0".to_string())], + &[InlineAsmTemplatePiece::String("aesimc xmm0, xmm0".into())], &[CInlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)), _late: true, @@ -1091,7 +1093,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( codegen_inline_asm_inner( fx, - &[InlineAsmTemplatePiece::String("aesenc xmm0, xmm1".to_string())], + &[InlineAsmTemplatePiece::String("aesenc xmm0, xmm1".into())], &[ CInlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)), @@ -1117,7 +1119,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( codegen_inline_asm_inner( fx, - &[InlineAsmTemplatePiece::String("aesenclast xmm0, xmm1".to_string())], + &[InlineAsmTemplatePiece::String("aesenclast xmm0, xmm1".into())], &[ CInlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)), @@ -1143,7 +1145,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( codegen_inline_asm_inner( fx, - &[InlineAsmTemplatePiece::String("aesdec xmm0, xmm1".to_string())], + &[InlineAsmTemplatePiece::String("aesdec xmm0, xmm1".into())], &[ CInlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)), @@ -1169,7 +1171,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( codegen_inline_asm_inner( fx, - &[InlineAsmTemplatePiece::String("aesdeclast xmm0, xmm1".to_string())], + &[InlineAsmTemplatePiece::String("aesdeclast xmm0, xmm1".into())], &[ CInlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)), @@ -1207,7 +1209,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( codegen_inline_asm_inner( fx, - &[InlineAsmTemplatePiece::String(format!("sha1rnds4 xmm1, xmm2, {func}"))], + &[InlineAsmTemplatePiece::String(format!("sha1rnds4 xmm1, xmm2, {func}").into())], &[ CInlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)), @@ -1233,7 +1235,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( codegen_inline_asm_inner( fx, - &[InlineAsmTemplatePiece::String("sha1msg1 xmm1, xmm2".to_string())], + &[InlineAsmTemplatePiece::String("sha1msg1 xmm1, xmm2".into())], &[ CInlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)), @@ -1259,7 +1261,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( codegen_inline_asm_inner( fx, - &[InlineAsmTemplatePiece::String("sha1msg2 xmm1, xmm2".to_string())], + &[InlineAsmTemplatePiece::String("sha1msg2 xmm1, xmm2".into())], &[ CInlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)), @@ -1285,7 +1287,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( codegen_inline_asm_inner( fx, - &[InlineAsmTemplatePiece::String("sha1nexte xmm1, xmm2".to_string())], + &[InlineAsmTemplatePiece::String("sha1nexte xmm1, xmm2".into())], &[ CInlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)), @@ -1312,7 +1314,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( codegen_inline_asm_inner( fx, - &[InlineAsmTemplatePiece::String("sha256rnds2 xmm1, xmm2".to_string())], + &[InlineAsmTemplatePiece::String("sha256rnds2 xmm1, xmm2".into())], &[ CInlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)), @@ -1343,7 +1345,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( codegen_inline_asm_inner( fx, - &[InlineAsmTemplatePiece::String("sha256msg1 xmm1, xmm2".to_string())], + &[InlineAsmTemplatePiece::String("sha256msg1 xmm1, xmm2".into())], &[ CInlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)), @@ -1369,7 +1371,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( codegen_inline_asm_inner( fx, - &[InlineAsmTemplatePiece::String("sha256msg2 xmm1, xmm2".to_string())], + &[InlineAsmTemplatePiece::String("sha256msg2 xmm1, xmm2".into())], &[ CInlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)), @@ -1435,7 +1437,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( let edx_place = res_place.place_field(fx, FieldIdx::new(1)); codegen_inline_asm_inner( fx, - &[InlineAsmTemplatePiece::String("rdtsc".to_string())], + &[InlineAsmTemplatePiece::String("rdtsc".into())], &[ CInlineAsmOperand::Out { reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)), From e63061d75bd11ad7020cd4366c385a0ad713408f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maja=20K=C4=85dzio=C5=82ka?= Date: Wed, 24 Jul 2024 22:24:12 +0200 Subject: [PATCH 057/786] Apply review suggestion Co-authored-by: Fridtjof Stoldt --- tests/ui/needless_borrows_for_generic_args.fixed | 2 +- tests/ui/needless_borrows_for_generic_args.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ui/needless_borrows_for_generic_args.fixed b/tests/ui/needless_borrows_for_generic_args.fixed index 593649b60bc71..c1dc8b5e8d09c 100644 --- a/tests/ui/needless_borrows_for_generic_args.fixed +++ b/tests/ui/needless_borrows_for_generic_args.fixed @@ -336,7 +336,7 @@ fn main() { { fn takes_writer(_: T) {} - fn f(mut buffer: &mut Vec) { + fn issue_12856(mut buffer: &mut Vec) { takes_writer(&mut buffer); // Don't lint, would make buffer unavailable later buffer.extend(b"\n"); } diff --git a/tests/ui/needless_borrows_for_generic_args.rs b/tests/ui/needless_borrows_for_generic_args.rs index 0c9b98d739d38..c7f66824d5818 100644 --- a/tests/ui/needless_borrows_for_generic_args.rs +++ b/tests/ui/needless_borrows_for_generic_args.rs @@ -336,7 +336,7 @@ fn main() { { fn takes_writer(_: T) {} - fn f(mut buffer: &mut Vec) { + fn issue_12856(mut buffer: &mut Vec) { takes_writer(&mut buffer); // Don't lint, would make buffer unavailable later buffer.extend(b"\n"); } From 12f1463b7e9b1d01b5e46b50d375de0a9026f2b1 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 25 Jul 2024 00:32:50 -0400 Subject: [PATCH 058/786] Don't record trait aliases as marker traits --- compiler/rustc_hir_analysis/src/collect.rs | 14 +++++++++----- tests/crashes/127222.rs | 3 --- tests/ui/traits/alias/not-a-marker.rs | 7 +++++++ tests/ui/traits/alias/not-a-marker.stderr | 11 +++++++++++ 4 files changed, 27 insertions(+), 8 deletions(-) delete mode 100644 tests/crashes/127222.rs create mode 100644 tests/ui/traits/alias/not-a-marker.rs create mode 100644 tests/ui/traits/alias/not-a-marker.stderr diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 565351268c96b..71f466ef5da04 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1207,25 +1207,29 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> { fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef { let item = tcx.hir().expect_item(def_id); - let (is_auto, safety, items) = match item.kind { + let (is_alias, is_auto, safety, items) = match item.kind { hir::ItemKind::Trait(is_auto, safety, .., items) => { - (is_auto == hir::IsAuto::Yes, safety, items) + (false, is_auto == hir::IsAuto::Yes, safety, items) } - hir::ItemKind::TraitAlias(..) => (false, hir::Safety::Safe, &[][..]), + hir::ItemKind::TraitAlias(..) => (true, false, hir::Safety::Safe, &[][..]), _ => span_bug!(item.span, "trait_def_of_item invoked on non-trait"), }; - let constness = if tcx.has_attr(def_id, sym::const_trait) { + // Only regular traits can be const. + let constness = if !is_alias && tcx.has_attr(def_id, sym::const_trait) { hir::Constness::Const } else { hir::Constness::NotConst }; + let paren_sugar = tcx.has_attr(def_id, sym::rustc_paren_sugar); if paren_sugar && !tcx.features().unboxed_closures { tcx.dcx().emit_err(errors::ParenSugarAttribute { span: item.span }); } - let is_marker = tcx.has_attr(def_id, sym::marker); + // Only regular traits can be marker. + let is_marker = !is_alias && tcx.has_attr(def_id, sym::marker); + let rustc_coinductive = tcx.has_attr(def_id, sym::rustc_coinductive); let is_fundamental = tcx.has_attr(def_id, sym::fundamental); diff --git a/tests/crashes/127222.rs b/tests/crashes/127222.rs deleted file mode 100644 index eda0ea3d9b729..0000000000000 --- a/tests/crashes/127222.rs +++ /dev/null @@ -1,3 +0,0 @@ -//@ known-bug: rust-lang/rust#127222 -#[marker] -trait Foo = PartialEq + Send; diff --git a/tests/ui/traits/alias/not-a-marker.rs b/tests/ui/traits/alias/not-a-marker.rs new file mode 100644 index 0000000000000..b004b9ff9ae3f --- /dev/null +++ b/tests/ui/traits/alias/not-a-marker.rs @@ -0,0 +1,7 @@ +#![feature(trait_alias, marker_trait_attr)] + +#[marker] +//~^ ERROR attribute should be applied to a trait +trait Foo = Send; + +fn main() {} diff --git a/tests/ui/traits/alias/not-a-marker.stderr b/tests/ui/traits/alias/not-a-marker.stderr new file mode 100644 index 0000000000000..2f3f6fea30f6a --- /dev/null +++ b/tests/ui/traits/alias/not-a-marker.stderr @@ -0,0 +1,11 @@ +error: attribute should be applied to a trait + --> $DIR/not-a-marker.rs:3:1 + | +LL | #[marker] + | ^^^^^^^^^ +LL | +LL | trait Foo = Send; + | ----------------- not a trait + +error: aborting due to 1 previous error + From 6da04f95a7233089cf714d24a160a5dbaa8d84b9 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Thu, 25 Jul 2024 05:10:15 +0000 Subject: [PATCH 059/786] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 60497630ae0d0..9868188eeee70 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -42103d69b73fb4e9d03d5cf66ec12985bb526f6e +e7d66eac5e8e8f60370c98d186aee9fa0ebd7845 From 9a5e41c56fbd61c5af4626cbd03935115cfaaa38 Mon Sep 17 00:00:00 2001 From: yukang Date: Fri, 19 Jul 2024 14:55:27 +0800 Subject: [PATCH 060/786] add testcase for 127868 --- ...ched-delimiter-corner-case-issue-127868.rs | 7 +++ ...-delimiter-corner-case-issue-127868.stderr | 45 +++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 tests/ui/parser/mismatched-delimiter-corner-case-issue-127868.rs create mode 100644 tests/ui/parser/mismatched-delimiter-corner-case-issue-127868.stderr diff --git a/tests/ui/parser/mismatched-delimiter-corner-case-issue-127868.rs b/tests/ui/parser/mismatched-delimiter-corner-case-issue-127868.rs new file mode 100644 index 0000000000000..edf619664e32d --- /dev/null +++ b/tests/ui/parser/mismatched-delimiter-corner-case-issue-127868.rs @@ -0,0 +1,7 @@ +// ignore-tidy-trailing-newlines +// issue: rust-lang/rust#127868 + +fn main() { + let a = [[[[[[[[[[[[[[[[[[[[1, {, (, [,; +} //~ ERROR mismatched closing delimiter: `}` +//~ ERROR this file contains an unclosed delimiter \ No newline at end of file diff --git a/tests/ui/parser/mismatched-delimiter-corner-case-issue-127868.stderr b/tests/ui/parser/mismatched-delimiter-corner-case-issue-127868.stderr new file mode 100644 index 0000000000000..95e2bf916425a --- /dev/null +++ b/tests/ui/parser/mismatched-delimiter-corner-case-issue-127868.stderr @@ -0,0 +1,45 @@ +error: mismatched closing delimiter: `}` + --> $DIR/mismatched-delimiter-corner-case-issue-127868.rs:5:42 + | +LL | fn main() { + | - closing delimiter possibly meant for this +LL | let a = [[[[[[[[[[[[[[[[[[[[1, {, (, [,; + | ^ unclosed delimiter +LL | } + | ^ mismatched closing delimiter + +error: this file contains an unclosed delimiter + --> $DIR/mismatched-delimiter-corner-case-issue-127868.rs:7:51 + | +LL | fn main() { + | - unclosed delimiter +LL | let a = [[[[[[[[[[[[[[[[[[[[1, {, (, [,; + | -------------------- - this delimiter might not be properly closed... + | |||||||||||||||||||| + | |||||||||||||||||||unclosed delimiter + | ||||||||||||||||||unclosed delimiter + | |||||||||||||||||unclosed delimiter + | ||||||||||||||||unclosed delimiter + | |||||||||||||||unclosed delimiter + | ||||||||||||||unclosed delimiter + | |||||||||||||unclosed delimiter + | ||||||||||||unclosed delimiter + | |||||||||||unclosed delimiter + | ||||||||||unclosed delimiter + | |||||||||unclosed delimiter + | ||||||||unclosed delimiter + | |||||||unclosed delimiter + | ||||||unclosed delimiter + | |||||unclosed delimiter + | ||||unclosed delimiter + | |||unclosed delimiter + | ||unclosed delimiter + | |unclosed delimiter + | unclosed delimiter +LL | } + | - ...as it matches this but it has different indentation +LL | + | ^ + +error: aborting due to 2 previous errors + From 94a3fd7678240f7a8f3cb331e44d7c18009be95e Mon Sep 17 00:00:00 2001 From: yukang Date: Fri, 19 Jul 2024 14:58:16 +0800 Subject: [PATCH 061/786] add limit for unclosed delimiters in lexer diagnostic --- compiler/rustc_parse/src/lexer/tokentrees.rs | 21 +++++++++++++--- tests/ui/parser/brace-in-let-chain.stderr | 8 +----- ...ched-delimiter-corner-case-issue-127868.rs | 3 +-- ...-delimiter-corner-case-issue-127868.stderr | 25 ++++--------------- 4 files changed, 25 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs index 8e54345469133..fc6257d809062 100644 --- a/compiler/rustc_parse/src/lexer/tokentrees.rs +++ b/compiler/rustc_parse/src/lexer/tokentrees.rs @@ -72,16 +72,31 @@ impl<'psess, 'src> TokenTreesReader<'psess, 'src> { fn eof_err(&mut self) -> PErr<'psess> { let msg = "this file contains an unclosed delimiter"; let mut err = self.string_reader.dcx().struct_span_err(self.token.span, msg); - for &(_, sp) in &self.diag_info.open_braces { - err.span_label(sp, "unclosed delimiter"); + + let unclosed_delimiter_show_limit = 5; + let len = usize::min(unclosed_delimiter_show_limit, self.diag_info.open_braces.len()); + for &(_, span) in &self.diag_info.open_braces[..len] { + err.span_label(span, "unclosed delimiter"); self.diag_info.unmatched_delims.push(UnmatchedDelim { found_delim: None, found_span: self.token.span, - unclosed_span: Some(sp), + unclosed_span: Some(span), candidate_span: None, }); } + if let Some((_, span)) = self.diag_info.open_braces.get(unclosed_delimiter_show_limit) + && self.diag_info.open_braces.len() >= unclosed_delimiter_show_limit + 2 + { + err.span_label( + *span, + format!( + "another {} unclosed delimiters begin from here", + self.diag_info.open_braces.len() - unclosed_delimiter_show_limit + ), + ); + } + if let Some((delim, _)) = self.diag_info.open_braces.last() { report_suspicious_mismatch_block( &mut err, diff --git a/tests/ui/parser/brace-in-let-chain.stderr b/tests/ui/parser/brace-in-let-chain.stderr index d76cb25ad8b84..913a34700dfc9 100644 --- a/tests/ui/parser/brace-in-let-chain.stderr +++ b/tests/ui/parser/brace-in-let-chain.stderr @@ -17,14 +17,8 @@ LL | fn qux() { | - unclosed delimiter ... LL | fn foo() { - | - unclosed delimiter -... -LL | fn bar() { - | - unclosed delimiter + | - another 3 unclosed delimiters begin from here ... -LL | fn baz() { - | - unclosed delimiter -LL | if false { LL | { | - this delimiter might not be properly closed... LL | && let () = () diff --git a/tests/ui/parser/mismatched-delimiter-corner-case-issue-127868.rs b/tests/ui/parser/mismatched-delimiter-corner-case-issue-127868.rs index edf619664e32d..5dcaa2663252b 100644 --- a/tests/ui/parser/mismatched-delimiter-corner-case-issue-127868.rs +++ b/tests/ui/parser/mismatched-delimiter-corner-case-issue-127868.rs @@ -1,7 +1,6 @@ -// ignore-tidy-trailing-newlines // issue: rust-lang/rust#127868 fn main() { let a = [[[[[[[[[[[[[[[[[[[[1, {, (, [,; } //~ ERROR mismatched closing delimiter: `}` -//~ ERROR this file contains an unclosed delimiter \ No newline at end of file +//~ ERROR this file contains an unclosed delimiter diff --git a/tests/ui/parser/mismatched-delimiter-corner-case-issue-127868.stderr b/tests/ui/parser/mismatched-delimiter-corner-case-issue-127868.stderr index 95e2bf916425a..94e25c18e4010 100644 --- a/tests/ui/parser/mismatched-delimiter-corner-case-issue-127868.stderr +++ b/tests/ui/parser/mismatched-delimiter-corner-case-issue-127868.stderr @@ -1,5 +1,5 @@ error: mismatched closing delimiter: `}` - --> $DIR/mismatched-delimiter-corner-case-issue-127868.rs:5:42 + --> $DIR/mismatched-delimiter-corner-case-issue-127868.rs:4:42 | LL | fn main() { | - closing delimiter possibly meant for this @@ -9,29 +9,14 @@ LL | } | ^ mismatched closing delimiter error: this file contains an unclosed delimiter - --> $DIR/mismatched-delimiter-corner-case-issue-127868.rs:7:51 + --> $DIR/mismatched-delimiter-corner-case-issue-127868.rs:6:52 | LL | fn main() { | - unclosed delimiter LL | let a = [[[[[[[[[[[[[[[[[[[[1, {, (, [,; - | -------------------- - this delimiter might not be properly closed... - | |||||||||||||||||||| - | |||||||||||||||||||unclosed delimiter - | ||||||||||||||||||unclosed delimiter - | |||||||||||||||||unclosed delimiter - | ||||||||||||||||unclosed delimiter - | |||||||||||||||unclosed delimiter - | ||||||||||||||unclosed delimiter - | |||||||||||||unclosed delimiter - | ||||||||||||unclosed delimiter - | |||||||||||unclosed delimiter - | ||||||||||unclosed delimiter - | |||||||||unclosed delimiter - | ||||||||unclosed delimiter - | |||||||unclosed delimiter - | ||||||unclosed delimiter - | |||||unclosed delimiter - | ||||unclosed delimiter + | ----- - this delimiter might not be properly closed... + | ||||| + | ||||another 16 unclosed delimiters begin from here | |||unclosed delimiter | ||unclosed delimiter | |unclosed delimiter From de1e1637795cae6bb19191f1afb1ab847ed10240 Mon Sep 17 00:00:00 2001 From: y21 <30553356+y21@users.noreply.github.com> Date: Thu, 25 Jul 2024 15:02:31 +0200 Subject: [PATCH 062/786] get rid of unnecessary `res` field in `for_each_expr` visitors --- clippy_utils/src/visitors.rs | 98 ++++++++++++++++++------------------ 1 file changed, 48 insertions(+), 50 deletions(-) diff --git a/clippy_utils/src/visitors.rs b/clippy_utils/src/visitors.rs index 7066c9ad2b96b..2a5d3536ff6b7 100644 --- a/clippy_utils/src/visitors.rs +++ b/clippy_utils/src/visitors.rs @@ -1,6 +1,7 @@ use crate::ty::needs_ordered_drop; use crate::{get_enclosing_block, path_to_local_id}; use core::ops::ControlFlow; +use rustc_ast::visit::{try_visit, VisitorResult}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::intravisit::{self, walk_block, walk_expr, Visitor}; @@ -50,16 +51,17 @@ impl Continue for Descend { /// A type which can be visited. pub trait Visitable<'tcx> { /// Calls the corresponding `visit_*` function on the visitor. - fn visit>(self, visitor: &mut V); + fn visit>(self, visitor: &mut V) -> V::Result; } impl<'tcx, T> Visitable<'tcx> for &'tcx [T] where &'tcx T: Visitable<'tcx>, { - fn visit>(self, visitor: &mut V) { + fn visit>(self, visitor: &mut V) -> V::Result { for x in self { - x.visit(visitor); + try_visit!(x.visit(visitor)); } + V::Result::output() } } impl<'tcx, A, B> Visitable<'tcx> for (A, B) @@ -67,27 +69,28 @@ where A: Visitable<'tcx>, B: Visitable<'tcx>, { - fn visit>(self, visitor: &mut V) { + fn visit>(self, visitor: &mut V) -> V::Result { let (a, b) = self; - a.visit(visitor); - b.visit(visitor); + try_visit!(a.visit(visitor)); + b.visit(visitor) } } impl<'tcx, T> Visitable<'tcx> for Option where T: Visitable<'tcx>, { - fn visit>(self, visitor: &mut V) { + fn visit>(self, visitor: &mut V) -> V::Result { if let Some(x) = self { - x.visit(visitor); + try_visit!(x.visit(visitor)); } + V::Result::output() } } macro_rules! visitable_ref { ($t:ident, $f:ident) => { impl<'tcx> Visitable<'tcx> for &'tcx $t<'tcx> { - fn visit>(self, visitor: &mut V) { - visitor.$f(self); + fn visit>(self, visitor: &mut V) -> V::Result { + visitor.$f(self) } } }; @@ -104,45 +107,37 @@ pub fn for_each_expr_without_closures<'tcx, B, C: Continue>( node: impl Visitable<'tcx>, f: impl FnMut(&'tcx Expr<'tcx>) -> ControlFlow, ) -> Option { - struct V { + struct V { f: F, - res: Option, } - impl<'tcx, B, C: Continue, F: FnMut(&'tcx Expr<'tcx>) -> ControlFlow> Visitor<'tcx> for V { - type Result = ControlFlow<()>; + impl<'tcx, B, C: Continue, F: FnMut(&'tcx Expr<'tcx>) -> ControlFlow> Visitor<'tcx> for V { + type Result = ControlFlow; - fn visit_expr(&mut self, e: &'tcx Expr<'tcx>) -> ControlFlow<()> { - if self.res.is_some() { - return ControlFlow::Break(()); - } + fn visit_expr(&mut self, e: &'tcx Expr<'tcx>) -> Self::Result { match (self.f)(e) { ControlFlow::Continue(c) if c.descend() => walk_expr(self, e), - ControlFlow::Break(b) => { - self.res = Some(b); - ControlFlow::Break(()) - }, + ControlFlow::Break(b) => ControlFlow::Break(b), ControlFlow::Continue(_) => ControlFlow::Continue(()), } } // Avoid unnecessary `walk_*` calls. - fn visit_ty(&mut self, _: &'tcx hir::Ty<'tcx>) -> ControlFlow<()> { + fn visit_ty(&mut self, _: &'tcx hir::Ty<'tcx>) -> Self::Result { ControlFlow::Continue(()) } - fn visit_pat(&mut self, _: &'tcx Pat<'tcx>) -> ControlFlow<()> { + fn visit_pat(&mut self, _: &'tcx Pat<'tcx>) -> Self::Result { ControlFlow::Continue(()) } - fn visit_qpath(&mut self, _: &'tcx QPath<'tcx>, _: HirId, _: Span) -> ControlFlow<()> { + fn visit_qpath(&mut self, _: &'tcx QPath<'tcx>, _: HirId, _: Span) -> Self::Result { ControlFlow::Continue(()) } // Avoid monomorphising all `visit_*` functions. - fn visit_nested_item(&mut self, _: ItemId) -> ControlFlow<()> { + fn visit_nested_item(&mut self, _: ItemId) -> Self::Result { ControlFlow::Continue(()) } } - let mut v = V { f, res: None }; - node.visit(&mut v); - v.res + let mut v = V { f }; + node.visit(&mut v).break_value() } /// Calls the given function once for each expression contained. This will enter bodies, but not @@ -152,44 +147,47 @@ pub fn for_each_expr<'tcx, B, C: Continue>( node: impl Visitable<'tcx>, f: impl FnMut(&'tcx Expr<'tcx>) -> ControlFlow, ) -> Option { - struct V<'tcx, B, F> { + struct V<'tcx, F> { tcx: TyCtxt<'tcx>, f: F, - res: Option, } - impl<'tcx, B, C: Continue, F: FnMut(&'tcx Expr<'tcx>) -> ControlFlow> Visitor<'tcx> for V<'tcx, B, F> { + impl<'tcx, B, C: Continue, F: FnMut(&'tcx Expr<'tcx>) -> ControlFlow> Visitor<'tcx> for V<'tcx, F> { type NestedFilter = nested_filter::OnlyBodies; + type Result = ControlFlow; + fn nested_visit_map(&mut self) -> Self::Map { self.tcx.hir() } - fn visit_expr(&mut self, e: &'tcx Expr<'tcx>) { - if self.res.is_some() { - return; - } + fn visit_expr(&mut self, e: &'tcx Expr<'tcx>) -> Self::Result { match (self.f)(e) { ControlFlow::Continue(c) if c.descend() => walk_expr(self, e), - ControlFlow::Break(b) => self.res = Some(b), - ControlFlow::Continue(_) => (), + ControlFlow::Break(b) => ControlFlow::Break(b), + ControlFlow::Continue(_) => ControlFlow::Continue(()), } } // Only walk closures - fn visit_anon_const(&mut self, _: &'tcx AnonConst) {} + fn visit_anon_const(&mut self, _: &'tcx AnonConst) -> Self::Result { + ControlFlow::Continue(()) + } // Avoid unnecessary `walk_*` calls. - fn visit_ty(&mut self, _: &'tcx hir::Ty<'tcx>) {} - fn visit_pat(&mut self, _: &'tcx Pat<'tcx>) {} - fn visit_qpath(&mut self, _: &'tcx QPath<'tcx>, _: HirId, _: Span) {} + fn visit_ty(&mut self, _: &'tcx hir::Ty<'tcx>) -> Self::Result { + ControlFlow::Continue(()) + } + fn visit_pat(&mut self, _: &'tcx Pat<'tcx>) -> Self::Result { + ControlFlow::Continue(()) + } + fn visit_qpath(&mut self, _: &'tcx QPath<'tcx>, _: HirId, _: Span) -> Self::Result { + ControlFlow::Continue(()) + } // Avoid monomorphising all `visit_*` functions. - fn visit_nested_item(&mut self, _: ItemId) {} + fn visit_nested_item(&mut self, _: ItemId) -> Self::Result { + ControlFlow::Continue(()) + } } - let mut v = V { - tcx: cx.tcx, - f, - res: None, - }; - node.visit(&mut v); - v.res + let mut v = V { tcx: cx.tcx, f }; + node.visit(&mut v).break_value() } /// returns `true` if expr contains match expr desugared from try From b2e612f204e62f0d4dfb5bb4ec1b609b513bb420 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 9 Jul 2024 10:35:53 +0000 Subject: [PATCH 063/786] Update Cranelift to 0.110.1 --- Cargo.lock | 62 +++++++++++++++++++++++++++++++----------------------- Cargo.toml | 12 +++++------ 2 files changed, 42 insertions(+), 32 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index efec5db836bb1..b065720c9ce11 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -46,21 +46,28 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cranelift-bforest" -version = "0.109.0" +version = "0.110.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b6b33d7e757a887989eb18b35712b2a67d96171ec3149d1bfb657b29b7b367c" +checksum = "effa84ab2023f7138045ece6b326588c17447ca22e66db71ec15cb0a6c0c4ad2" dependencies = [ "cranelift-entity", ] +[[package]] +name = "cranelift-bitset" +version = "0.110.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38a1dfc50dca188a15d938867c4400589530bcb0138f7022aae6d059d1d8c309" + [[package]] name = "cranelift-codegen" -version = "0.109.0" +version = "0.110.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9acf15cb22be42d07c3b57d7856329cb228b7315d385346149df2566ad5e4aa" +checksum = "821c20c639350158ecca928dc2a244d0d1c9cef2377a378fc62a445a286eb1ca" dependencies = [ "bumpalo", "cranelift-bforest", + "cranelift-bitset", "cranelift-codegen-meta", "cranelift-codegen-shared", "cranelift-control", @@ -77,39 +84,42 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.109.0" +version = "0.110.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e934d301392b73b3f8b0540391fb82465a0f179a3cee7c726482ac4727efcc97" +checksum = "064473f2fd59b44fa2c9aaa60de1f9c44db5e13521e28bc85d2b92ee535ef625" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.109.0" +version = "0.110.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb2a2566b3d54b854dfb288b3b187f6d3d17d6f762c92898207eba302931da" +checksum = "d0f39b9ebfd2febdc2acfb9a0fca110665bcd5a6839502576307735ed07b2177" [[package]] name = "cranelift-control" -version = "0.109.0" +version = "0.110.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0100f33b704cdacd01ad66ff41f8c5030d57cbff078e2a4e49ab1822591299fa" +checksum = "94e125c189c3a1ca8dfe209fc6f46edba058a6d24e0b92aff69459a15f4711e7" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.109.0" +version = "0.110.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8cfdc315e5d18997093e040a8d234bea1ac1e118a716d3e30f40d449e78207b" +checksum = "ea62eb109baec2247e1a6fa7b74c0f584b1e76e289cfd7017385b4b031fc8450" +dependencies = [ + "cranelift-bitset", +] [[package]] name = "cranelift-frontend" -version = "0.109.0" +version = "0.110.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f74b84f16af2e982b0c0c72233503d9d55cbfe3865dbe807ca28dc6642a28b5" +checksum = "722b089357aacb6c7528b2e59a5fe00917d61ce63448b25a3e477a5b7819fac8" dependencies = [ "cranelift-codegen", "log", @@ -119,15 +129,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.109.0" +version = "0.110.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adf306d3dde705fb94bd48082f01d38c4ededc74293a4c007805f610bf08bc6e" +checksum = "c4b5005a48288e7fc2a2991a377831c534e26929b063c379c018060727785a9b" [[package]] name = "cranelift-jit" -version = "0.109.0" +version = "0.110.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5c5cfb8bbd3339cd25cca30e7516ff8fe5cb1feeddde6980cc4d5ef34df97bb" +checksum = "f843932baf8d1025c5f114b929eda172d74b7163d058e0de2597c308b567c7e9" dependencies = [ "anyhow", "cranelift-codegen", @@ -145,9 +155,9 @@ dependencies = [ [[package]] name = "cranelift-module" -version = "0.109.0" +version = "0.110.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c9b0d4269b36fd858e6d8f20cd4938941186fb831488c361888cb2d6b33a9a6" +checksum = "449819ef1c4af139cf1b9717916fcaea0e23248853d3e95135139773a842d3eb" dependencies = [ "anyhow", "cranelift-codegen", @@ -156,9 +166,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.109.0" +version = "0.110.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ea0ebdef7aff4a79bcbc8b6495f31315f16b3bf311152f472eaa8d679352581" +checksum = "3ae2d48f38081a9e679ad795bd36bb29bedeb5552fc1c195185bf9885fa1b16e" dependencies = [ "cranelift-codegen", "libc", @@ -167,9 +177,9 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.109.0" +version = "0.110.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e33439ec20db058bc7cc3410f9748ab1ad90a35cef713d625c736f43e3820d" +checksum = "3a39ee2cfd0ec485eca76f6b4dc17701a280fa406bc05137bb43f1635ed12c9f" dependencies = [ "anyhow", "cranelift-codegen", @@ -411,9 +421,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "wasmtime-jit-icache-coherence" -version = "22.0.0" +version = "23.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5afe2f0499542f9a4bcfa1b55bfdda803b6ade4e7c93c6b99e0f39dba44b0a91" +checksum = "7fddf3e2980fb1d123d1fcac55189e417fdd3dba4f62139b5a0a1f9efe5669d5" dependencies = [ "anyhow", "cfg-if", diff --git a/Cargo.toml b/Cargo.toml index 2969a6cf6ecaa..a0df502dadc47 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,12 +8,12 @@ crate-type = ["dylib"] [dependencies] # These have to be in sync with each other -cranelift-codegen = { version = "0.109.0", default-features = false, features = ["std", "unwind", "all-arch"] } -cranelift-frontend = { version = "0.109.0" } -cranelift-module = { version = "0.109.0" } -cranelift-native = { version = "0.109.0" } -cranelift-jit = { version = "0.109.0", optional = true } -cranelift-object = { version = "0.109.0" } +cranelift-codegen = { version = "0.110.1", default-features = false, features = ["std", "unwind", "all-arch"] } +cranelift-frontend = { version = "0.110.1" } +cranelift-module = { version = "0.110.1" } +cranelift-native = { version = "0.110.1" } +cranelift-jit = { version = "0.110.1", optional = true } +cranelift-object = { version = "0.110.1" } target-lexicon = "0.12.0" gimli = { version = "0.28", default-features = false, features = ["write"]} object = { version = "0.36", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } From d7683597166371d9370d3f196434ea69733c80e5 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 25 Jul 2024 15:16:41 +0000 Subject: [PATCH 064/786] Rustup to rustc 1.82.0-nightly (c1a6199e9 2024-07-24) --- patches/stdlib-lock.toml | 4 ++-- rust-toolchain | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/patches/stdlib-lock.toml b/patches/stdlib-lock.toml index 9ea53e8f848d9..1c1f81844c3de 100644 --- a/patches/stdlib-lock.toml +++ b/patches/stdlib-lock.toml @@ -252,9 +252,9 @@ dependencies = [ [[package]] name = "r-efi" -version = "4.3.0" +version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e244f96e03a3067f9e521d3167bd42657594cb8588c8d3a2db01545dc1af2e0" +checksum = "e9e935efc5854715dfc0a4c9ef18dc69dee0ec3bf9cc3ab740db831c0fdd86a3" dependencies = [ "compiler_builtins", "rustc-std-workspace-core", diff --git a/rust-toolchain b/rust-toolchain index 2478a9bbccee9..800ac0a1ed064 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2024-07-13" +channel = "nightly-2024-07-25" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From 39bc103817ba5d7826a3d6183025bf0aa24a6fe9 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 25 Jul 2024 16:17:24 +0000 Subject: [PATCH 065/786] Fix rustc test suite --- scripts/test_rustc_tests.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/test_rustc_tests.sh b/scripts/test_rustc_tests.sh index f0550c23b177f..735762b389cfb 100755 --- a/scripts/test_rustc_tests.sh +++ b/scripts/test_rustc_tests.sh @@ -134,6 +134,8 @@ rm tests/ui/deprecation/deprecated_inline_threshold.rs # missing deprecation war # bugs in the test suite # ====================== rm tests/ui/process/nofile-limit.rs # TODO some AArch64 linking issue +rm tests/ui/backtrace/synchronized-panic-handler.rs # missing needs-unwind annotation +rm -r tests/ui/codegen/equal-pointers-unequal # make incorrect assumptions about the location of stack variables rm tests/ui/stdio-is-blocking.rs # really slow with unoptimized libstd @@ -157,8 +159,8 @@ index ea06b620c4c..b969d0009c6 100644 RUSTDOC := \$(RUSTDOC) -Clinker='\$(RUSTC_LINKER)' diff --git a/src/tools/run-make-support/src/rustdoc.rs b/src/tools/run-make-support/src/rustdoc.rs index 9607ff02f96..b7d97caf9a2 100644 ---- a/src/tools/run-make-support/src/rustdoc.rs -+++ b/src/tools/run-make-support/src/rustdoc.rs +--- a/src/tools/run-make-support/src/external_deps/rustdoc.rs ++++ b/src/tools/run-make-support/src/external_deps/rustdoc.rs @@ -34,8 +34,6 @@ pub fn bare() -> Self { #[track_caller] pub fn new() -> Self { From 4e6851e50bde42cef280076aa48035871bfe9520 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Thu, 25 Jul 2024 18:29:17 +0200 Subject: [PATCH 066/786] Merge commit '37f4fbb92913586b73a35772efd00eccd1cbbe13' into clippy-subtree-update --- .cargo/config.toml | 2 +- .github/workflows/lintcheck.yml | 28 +- CHANGELOG.md | 47 +- Cargo.toml | 9 +- book/src/development/adding_lints.md | 14 +- book/src/lint_configuration.md | 3 +- clippy.toml | 1 - clippy_config/Cargo.toml | 2 +- clippy_config/src/conf.rs | 29 +- clippy_config/src/types.rs | 14 +- clippy_dev/src/new_lint.rs | 8 +- clippy_lints/Cargo.toml | 2 +- clippy_lints/src/absolute_paths.rs | 12 +- clippy_lints/src/almost_complete_range.rs | 7 +- clippy_lints/src/approx_const.rs | 8 +- clippy_lints/src/arc_with_non_send_sync.rs | 15 +- clippy_lints/src/assigning_clones.rs | 8 +- clippy_lints/src/attrs/mod.rs | 19 +- clippy_lints/src/await_holding_invalid.rs | 39 +- clippy_lints/src/borrow_deref_ref.rs | 44 +- clippy_lints/src/cargo/mod.rs | 16 +- clippy_lints/src/casts/cast_lossless.rs | 111 ++-- clippy_lints/src/casts/mod.rs | 48 +- clippy_lints/src/casts/ptr_cast_constness.rs | 3 +- clippy_lints/src/checked_conversions.rs | 141 ++--- clippy_lints/src/cognitive_complexity.rs | 6 +- clippy_lints/src/collapsible_if.rs | 33 +- clippy_lints/src/collection_is_never_read.rs | 6 +- clippy_lints/src/copies.rs | 14 +- clippy_lints/src/crate_in_macro_def.rs | 7 +- clippy_lints/src/dbg_macro.rs | 6 +- clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/derivable_impls.rs | 8 +- clippy_lints/src/disallowed_macros.rs | 31 +- clippy_lints/src/disallowed_methods.rs | 42 +- clippy_lints/src/disallowed_names.rs | 11 +- clippy_lints/src/disallowed_script_idents.rs | 18 +- clippy_lints/src/disallowed_types.rs | 91 ++- clippy_lints/src/doc/mod.rs | 12 +- clippy_lints/src/double_parens.rs | 48 +- clippy_lints/src/else_if_without_else.rs | 5 +- clippy_lints/src/empty_enum.rs | 34 +- clippy_lints/src/endian_bytes.rs | 39 +- clippy_lints/src/equatable_if_let.rs | 4 +- clippy_lints/src/error_impl_error.rs | 9 +- clippy_lints/src/escape.rs | 12 +- clippy_lints/src/excessive_bools.rs | 103 ++- clippy_lints/src/excessive_nesting.rs | 9 +- clippy_lints/src/exhaustive_items.rs | 26 +- clippy_lints/src/exit.rs | 6 +- .../src/extra_unused_type_parameters.rs | 35 +- clippy_lints/src/float_literal.rs | 5 +- clippy_lints/src/format_args.rs | 8 +- clippy_lints/src/format_impl.rs | 1 - clippy_lints/src/from_over_into.rs | 14 +- clippy_lints/src/from_str_radix_10.rs | 19 +- clippy_lints/src/functions/mod.rs | 37 +- clippy_lints/src/future_not_send.rs | 14 +- clippy_lints/src/if_let_mutex.rs | 65 +- clippy_lints/src/if_not_else.rs | 63 +- clippy_lints/src/if_then_some_else_none.rs | 33 +- clippy_lints/src/ignored_unit_patterns.rs | 31 +- clippy_lints/src/incompatible_msrv.rs | 5 +- .../src/inconsistent_struct_constructor.rs | 6 +- clippy_lints/src/index_refutable_slice.rs | 11 +- clippy_lints/src/indexing_slicing.rs | 14 +- clippy_lints/src/infinite_iter.rs | 5 +- clippy_lints/src/instant_subtraction.rs | 8 +- clippy_lints/src/item_name_repetitions.rs | 20 +- clippy_lints/src/large_const_arrays.rs | 12 +- clippy_lints/src/large_enum_variant.rs | 7 +- clippy_lints/src/large_futures.rs | 8 +- clippy_lints/src/large_include_file.rs | 8 +- clippy_lints/src/large_stack_arrays.rs | 12 +- clippy_lints/src/large_stack_frames.rs | 6 +- clippy_lints/src/legacy_numeric_constants.rs | 8 +- clippy_lints/src/lib.rs | 463 +++----------- clippy_lints/src/lifetimes.rs | 18 +- clippy_lints/src/literal_representation.rs | 18 +- clippy_lints/src/loops/mod.rs | 7 +- clippy_lints/src/loops/mut_range_bound.rs | 15 +- clippy_lints/src/loops/single_element_loop.rs | 7 +- .../src/loops/while_immutable_condition.rs | 24 +- clippy_lints/src/macro_metavars_in_unsafe.rs | 20 +- clippy_lints/src/manual_bits.rs | 9 +- clippy_lints/src/manual_clamp.rs | 7 +- clippy_lints/src/manual_hash_one.rs | 8 +- clippy_lints/src/manual_is_ascii_check.rs | 8 +- clippy_lints/src/manual_main_separator_str.rs | 8 +- clippy_lints/src/manual_non_exhaustive.rs | 13 +- clippy_lints/src/manual_rem_euclid.rs | 8 +- clippy_lints/src/manual_retain.rs | 8 +- clippy_lints/src/manual_strip.rs | 8 +- clippy_lints/src/matches/manual_unwrap_or.rs | 11 + clippy_lints/src/matches/mod.rs | 6 +- .../matches/significant_drop_in_scrutinee.rs | 6 +- clippy_lints/src/mem_replace.rs | 8 +- .../src/methods/bind_instead_of_map.rs | 109 ++-- clippy_lints/src/methods/mod.rs | 31 +- .../src/methods/option_map_unwrap_or.rs | 32 +- clippy_lints/src/methods/or_fun_call.rs | 133 ++-- .../src/methods/path_ends_with_ext.rs | 2 +- clippy_lints/src/min_ident_chars.rs | 19 +- clippy_lints/src/misc.rs | 43 +- .../src/mismatching_type_param_order.rs | 6 +- clippy_lints/src/missing_const_for_fn.rs | 8 +- .../src/missing_const_for_thread_local.rs | 8 +- clippy_lints/src/missing_doc.rs | 13 +- .../src/missing_enforced_import_rename.rs | 29 +- clippy_lints/src/mut_key.rs | 13 +- clippy_lints/src/mut_mut.rs | 37 +- clippy_lints/src/needless_borrowed_ref.rs | 142 ++--- .../src/needless_borrows_for_generic_args.rs | 6 +- clippy_lints/src/needless_for_each.rs | 16 +- clippy_lints/src/needless_pass_by_ref_mut.rs | 9 +- clippy_lints/src/neg_cmp_op_on_partial_ord.rs | 4 +- clippy_lints/src/non_copy_const.rs | 11 +- clippy_lints/src/non_expressive_names.rs | 23 +- .../src/non_send_fields_in_send_ty.rs | 6 +- clippy_lints/src/nonstandard_macro_braces.rs | 7 +- .../src/operators/arithmetic_side_effects.rs | 55 +- clippy_lints/src/operators/mod.rs | 21 +- clippy_lints/src/option_env_unwrap.rs | 24 +- clippy_lints/src/panic_unimplemented.rs | 12 +- clippy_lints/src/pass_by_ref_or_value.rs | 19 +- clippy_lints/src/pathbuf_init_then_push.rs | 193 ++++++ .../src/permissions_set_readonly_false.rs | 4 +- clippy_lints/src/pub_underscore_fields.rs | 11 +- clippy_lints/src/question_mark.rs | 8 +- clippy_lints/src/ranges.rs | 8 +- clippy_lints/src/raw_strings.rs | 45 +- clippy_lints/src/redundant_closure_call.rs | 25 +- clippy_lints/src/redundant_field_names.rs | 8 +- .../src/redundant_static_lifetimes.rs | 8 +- clippy_lints/src/regex.rs | 2 +- clippy_lints/src/semicolon_block.rs | 12 +- clippy_lints/src/serde_api.rs | 2 +- clippy_lints/src/single_call_fn.rs | 13 +- clippy_lints/src/single_range_in_vec_init.rs | 2 +- clippy_lints/src/string_patterns.rs | 8 +- clippy_lints/src/trait_bounds.rs | 10 +- clippy_lints/src/transmute/mod.rs | 10 +- .../src/transmute/transmute_ptr_to_ptr.rs | 43 +- clippy_lints/src/tuple_array_conversions.rs | 11 +- clippy_lints/src/types/mod.rs | 9 +- clippy_lints/src/unconditional_recursion.rs | 14 +- .../src/undocumented_unsafe_blocks.rs | 8 +- clippy_lints/src/unnecessary_box_returns.rs | 7 +- .../src/unnecessary_struct_initialization.rs | 187 ++++-- clippy_lints/src/unnecessary_wraps.rs | 5 +- clippy_lints/src/unnested_or_patterns.rs | 8 +- clippy_lints/src/unused_peekable.rs | 61 +- clippy_lints/src/unused_self.rs | 5 +- clippy_lints/src/upper_case_acronyms.rs | 8 +- clippy_lints/src/use_self.rs | 6 +- .../interning_defined_symbol.rs | 2 +- .../src/utils/internal_lints/invalid_paths.rs | 2 +- .../internal_lints/unnecessary_def_path.rs | 4 +- clippy_lints/src/vec.rs | 20 +- clippy_lints/src/wildcard_imports.rs | 12 +- clippy_lints/src/write.rs | 8 +- clippy_lints/src/zero_repeat_side_effects.rs | 28 +- clippy_utils/Cargo.toml | 2 +- clippy_utils/src/hir_utils.rs | 2 +- clippy_utils/src/lib.rs | 29 +- clippy_utils/src/numeric_literal.rs | 2 + clippy_utils/src/sugg.rs | 9 +- clippy_utils/src/ty.rs | 8 +- clippy_utils/src/ty/type_certainty/mod.rs | 2 +- clippy_utils/src/visitors.rs | 29 +- declare_clippy_lint/Cargo.toml | 2 +- lintcheck/Cargo.toml | 2 +- lintcheck/ci_crates.toml | 208 +++++++ lintcheck/lintcheck_crates.toml | 74 ++- lintcheck/src/config.rs | 8 +- lintcheck/src/driver.rs | 1 + lintcheck/src/input.rs | 128 ++-- lintcheck/src/json.rs | 216 +++++-- lintcheck/src/main.rs | 63 +- lintcheck/src/output.rs | 33 +- lintcheck/src/recursive.rs | 10 +- rust-toolchain | 2 +- tests/compile-test.rs | 14 +- tests/dogfood.rs | 47 +- tests/integration.rs | 6 +- tests/ui-internal/disallow_span_lint.stderr | 4 +- .../await_holding_invalid_type.stderr | 10 +- .../disallowed_macros.stderr | 2 +- .../index_refutable_slice.fixed | 24 - .../index_refutable_slice.rs | 2 + .../index_refutable_slice.stderr | 2 +- .../conf_disallowed_methods.stderr | 2 +- .../conf_disallowed_types.stderr | 44 +- tests/ui/cast_lossless_bool.stderr | 149 ++++- tests/ui/cast_lossless_float.stderr | 129 +++- tests/ui/cast_lossless_integer.fixed | 129 +++- tests/ui/cast_lossless_integer.rs | 129 +++- tests/ui/cast_lossless_integer.stderr | 523 +++++++++++++--- tests/ui/crashes/ice-3717.fixed | 11 - tests/ui/crashes/ice-3717.rs | 2 + tests/ui/crashes/ice-3717.stderr | 2 +- tests/ui/deref_addrof.fixed | 2 +- tests/ui/deref_addrof.rs | 2 +- tests/ui/derivable_impls.fixed | 295 --------- tests/ui/derivable_impls.rs | 2 + tests/ui/derivable_impls.stderr | 16 +- tests/ui/doc/doc-fixable.fixed | 13 +- tests/ui/doc/doc-fixable.rs | 13 +- tests/ui/doc/doc-fixable.stderr | 44 +- tests/ui/excessive_precision.fixed | 4 + tests/ui/excessive_precision.rs | 4 + tests/ui/excessive_precision.stderr | 8 +- tests/ui/floating_point_powf.fixed | 8 + tests/ui/floating_point_powf.rs | 8 + tests/ui/floating_point_powf.stderr | 32 +- .../if_let_slice_binding.fixed | 177 ------ .../if_let_slice_binding.rs | 2 + .../if_let_slice_binding.stderr | 20 +- .../slice_indexing_in_macro.fixed | 29 - .../slice_indexing_in_macro.rs | 2 + .../slice_indexing_in_macro.stderr | 2 +- tests/ui/let_unit.fixed | 196 ------ tests/ui/let_unit.rs | 2 + tests/ui/let_unit.stderr | 8 +- tests/ui/manual_assert.edition2018.fixed | 76 --- tests/ui/manual_assert.edition2018.stderr | 20 +- tests/ui/manual_assert.edition2021.fixed | 76 --- tests/ui/manual_assert.edition2021.stderr | 20 +- tests/ui/manual_assert.rs | 2 + tests/ui/manual_async_fn.fixed | 115 ---- tests/ui/manual_async_fn.rs | 2 + tests/ui/manual_async_fn.stderr | 26 +- tests/ui/manual_split_once.fixed | 144 ----- tests/ui/manual_split_once.rs | 2 + tests/ui/manual_split_once.stderr | 38 +- tests/ui/manual_unwrap_or.fixed | 16 + tests/ui/manual_unwrap_or.rs | 16 + tests/ui/match_same_arms2.fixed | 258 -------- tests/ui/match_same_arms2.rs | 3 + tests/ui/match_same_arms2.stderr | 30 +- tests/ui/min_ident_chars.stderr | 8 +- .../missing_const_for_fn/could_be_const.fixed | 2 +- .../ui/missing_const_for_fn/could_be_const.rs | 2 +- tests/ui/needless_option_as_deref.fixed | 18 + tests/ui/needless_option_as_deref.rs | 18 + tests/ui/or_fun_call.fixed | 47 ++ tests/ui/or_fun_call.rs | 47 ++ tests/ui/or_fun_call.stderr | 50 +- tests/ui/path_buf_push_overwrite.fixed | 3 +- tests/ui/path_buf_push_overwrite.rs | 3 +- tests/ui/path_buf_push_overwrite.stderr | 2 +- tests/ui/pathbuf_init_then_push.fixed | 22 + tests/ui/pathbuf_init_then_push.rs | 26 + tests/ui/pathbuf_init_then_push.stderr | 33 + tests/ui/ptr_cast_constness.fixed | 4 + tests/ui/ptr_cast_constness.rs | 4 + tests/ui/ptr_cast_constness.stderr | 4 +- tests/ui/redundant_clone.fixed | 1 + tests/ui/redundant_clone.rs | 1 + tests/ui/redundant_clone.stderr | 60 +- tests/ui/significant_drop_tightening.fixed | 144 ----- tests/ui/significant_drop_tightening.rs | 2 + tests/ui/significant_drop_tightening.stderr | 8 +- tests/ui/single_element_loop.fixed | 8 + tests/ui/single_element_loop.rs | 7 + tests/ui/single_element_loop.stderr | 18 +- tests/ui/toplevel_ref_arg.fixed | 2 + tests/ui/toplevel_ref_arg.rs | 2 + tests/ui/transmute_ptr_to_ptr.fixed | 79 ++- tests/ui/transmute_ptr_to_ptr.rs | 87 ++- tests/ui/transmute_ptr_to_ptr.stderr | 152 ++++- .../transmutes_expressible_as_ptr_casts.fixed | 2 +- ...transmutes_expressible_as_ptr_casts.stderr | 13 +- tests/ui/types.fixed | 13 - tests/ui/types.rs | 13 - tests/ui/types.stderr | 11 - tests/ui/unnecessary_iter_cloned.fixed | 201 ------ tests/ui/unnecessary_iter_cloned.rs | 2 + tests/ui/unnecessary_iter_cloned.stderr | 10 +- .../unnecessary_struct_initialization.fixed | 70 +++ tests/ui/unnecessary_struct_initialization.rs | 70 +++ .../unnecessary_struct_initialization.stderr | 44 +- tests/ui/unnecessary_to_owned.fixed | 587 ------------------ tests/ui/unnecessary_to_owned.rs | 2 + tests/ui/unnecessary_to_owned.stderr | 186 +++--- tests/ui/zero_repeat_side_effects.fixed | 20 +- tests/ui/zero_repeat_side_effects.rs | 20 +- tests/ui/zero_repeat_side_effects.stderr | 36 +- triagebot.toml | 2 +- util/gh-pages/index.html | 40 +- util/gh-pages/script.js | 6 + 291 files changed, 4846 insertions(+), 5161 deletions(-) create mode 100644 clippy_lints/src/pathbuf_init_then_push.rs create mode 100644 lintcheck/ci_crates.toml delete mode 100644 tests/ui-toml/max_suggested_slice_pattern_length/index_refutable_slice.fixed delete mode 100644 tests/ui/crashes/ice-3717.fixed delete mode 100644 tests/ui/derivable_impls.fixed delete mode 100644 tests/ui/index_refutable_slice/if_let_slice_binding.fixed delete mode 100644 tests/ui/index_refutable_slice/slice_indexing_in_macro.fixed delete mode 100644 tests/ui/let_unit.fixed delete mode 100644 tests/ui/manual_assert.edition2018.fixed delete mode 100644 tests/ui/manual_assert.edition2021.fixed delete mode 100644 tests/ui/manual_async_fn.fixed delete mode 100644 tests/ui/manual_split_once.fixed delete mode 100644 tests/ui/match_same_arms2.fixed create mode 100644 tests/ui/pathbuf_init_then_push.fixed create mode 100644 tests/ui/pathbuf_init_then_push.rs create mode 100644 tests/ui/pathbuf_init_then_push.stderr delete mode 100644 tests/ui/significant_drop_tightening.fixed delete mode 100644 tests/ui/types.fixed delete mode 100644 tests/ui/types.rs delete mode 100644 tests/ui/types.stderr delete mode 100644 tests/ui/unnecessary_iter_cloned.fixed delete mode 100644 tests/ui/unnecessary_to_owned.fixed diff --git a/.cargo/config.toml b/.cargo/config.toml index 48a63e4856815..7afdd068a9905 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -4,7 +4,7 @@ uibless = "test --test compile-test -- -- --bless" bless = "test -- -- --bless" dev = "run --package clippy_dev --bin clippy_dev --manifest-path clippy_dev/Cargo.toml --" lintcheck = "run --package lintcheck --bin lintcheck --manifest-path lintcheck/Cargo.toml -- " -collect-metadata = "test --test dogfood --features internal -- run_metadata_collection_lint --ignored" +collect-metadata = "test --test dogfood --features internal -- collect_metadata" [build] # -Zbinary-dep-depinfo allows us to track which rlib files to use for compiling UI tests diff --git a/.github/workflows/lintcheck.yml b/.github/workflows/lintcheck.yml index f016a77005920..6a5139b6dc0bb 100644 --- a/.github/workflows/lintcheck.yml +++ b/.github/workflows/lintcheck.yml @@ -53,18 +53,18 @@ jobs: id: cache-json uses: actions/cache@v4 with: - path: lintcheck-logs/lintcheck_crates_logs.json + path: lintcheck-logs/ci_crates_logs.json key: ${{ steps.key.outputs.key }} - name: Run lintcheck if: steps.cache-json.outputs.cache-hit != 'true' - run: ./target/debug/lintcheck --format json --warn-all + run: ./target/debug/lintcheck --format json --warn-all --crates-toml ./lintcheck/ci_crates.toml - name: Upload base JSON uses: actions/upload-artifact@v4 with: name: base - path: lintcheck-logs/lintcheck_crates_logs.json + path: lintcheck-logs/ci_crates_logs.json # Runs lintcheck on the PR and stores the results as an artifact head: @@ -86,13 +86,13 @@ jobs: run: cargo build --manifest-path=lintcheck/Cargo.toml - name: Run lintcheck - run: ./target/debug/lintcheck --format json --warn-all + run: ./target/debug/lintcheck --format json --warn-all --crates-toml ./lintcheck/ci_crates.toml - name: Upload head JSON uses: actions/upload-artifact@v4 with: name: head - path: lintcheck-logs/lintcheck_crates_logs.json + path: lintcheck-logs/ci_crates_logs.json # Retrieves the head and base JSON results and prints the diff to the GH actions step summary diff: @@ -115,4 +115,20 @@ jobs: uses: actions/download-artifact@v4 - name: Diff results - run: ./target/debug/lintcheck diff {base,head}/lintcheck_crates_logs.json >> $GITHUB_STEP_SUMMARY + # GH's summery has a maximum size of 1024k: + # https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-markdown-summary + # That's why we first log to file and then to the summary and logs + run: | + ./target/debug/lintcheck diff {base,head}/ci_crates_logs.json --truncate >> truncated_diff.md + head -c 1024000 truncated_diff.md >> $GITHUB_STEP_SUMMARY + cat truncated_diff.md + ./target/debug/lintcheck diff {base,head}/ci_crates_logs.json >> full_diff.md + + - name: Upload full diff + uses: actions/upload-artifact@v4 + with: + name: diff + if-no-files-found: ignore + path: | + full_diff.md + truncated_diff.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 55281f3cbec0b..60c03b03d9be3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,11 +6,53 @@ document. ## Unreleased / Beta / In Rust Nightly -[ca3b3937...master](https://github.com/rust-lang/rust-clippy/compare/ca3b3937...master) +[c9139bd5...master](https://github.com/rust-lang/rust-clippy/compare/c9139bd5...master) + +## Rust 1.80 + +Current stable, released 2024-07-25 + +[View all 68 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2024-04-18T22%3A50%3A22Z..2024-05-30T08%3A26%3A18Z+base%3Amaster) + +### New Lints + +* Added [`while_float`] to `nursery` + [#12765](https://github.com/rust-lang/rust-clippy/pull/12765) +* Added [`macro_metavars_in_unsafe`] to `suspicious` + [#12107](https://github.com/rust-lang/rust-clippy/pull/12107) +* Added [`renamed_function_params`] to `restriction` + [#11540](https://github.com/rust-lang/rust-clippy/pull/11540) +* Added [`doc_lazy_continuation`] to `style` + [#12770](https://github.com/rust-lang/rust-clippy/pull/12770) + +### Moves and Deprecations + +* Moved [`assigning_clones`] to `pedantic` (From `perf` now allow-by-default) + [#12779](https://github.com/rust-lang/rust-clippy/pull/12779) +* Moved [`single_char_pattern`] to `pedantic` (From `perf` now allow-by-default) + [#11852](https://github.com/rust-lang/rust-clippy/pull/11852) + +### Enhancements + +* [`panic`]: Added [`allow-panic-in-tests`] configuration to allow the lint in tests + [#12803](https://github.com/rust-lang/rust-clippy/pull/12803) +* [`missing_const_for_fn`]: Now respects the [`msrv`] configuration + [#12713](https://github.com/rust-lang/rust-clippy/pull/12713) +* [`missing_panics_doc`]: No longer lints on compile-time panics + [#12790](https://github.com/rust-lang/rust-clippy/pull/12790) +* [`collapsible_match`]: Now considers the [`msrv`] configuration for the suggestion + [#12745](https://github.com/rust-lang/rust-clippy/pull/12745) +* [`useless_vec`]: Added [`allow-useless-vec-in-tests`] configuration to allow the lint in tests + [#12725](https://github.com/rust-lang/rust-clippy/pull/12725) + +### Suggestion Fixes/Improvements + +* [`single_match`], [`single_match_else`]: Suggestions are now machine-applicable + [#12726](https://github.com/rust-lang/rust-clippy/pull/12726) ## Rust 1.79 -Current stable, released 2024-06-13 +Released 2024-06-13 [View all 102 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2024-03-08T11%3A13%3A58Z..2024-04-18T15%3A50%3A50Z+base%3Amaster) @@ -5712,6 +5754,7 @@ Released 2018-09-13 [`partialeq_to_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#partialeq_to_none [`path_buf_push_overwrite`]: https://rust-lang.github.io/rust-clippy/master/index.html#path_buf_push_overwrite [`path_ends_with_ext`]: https://rust-lang.github.io/rust-clippy/master/index.html#path_ends_with_ext +[`pathbuf_init_then_push`]: https://rust-lang.github.io/rust-clippy/master/index.html#pathbuf_init_then_push [`pattern_type_mismatch`]: https://rust-lang.github.io/rust-clippy/master/index.html#pattern_type_mismatch [`permissions_set_readonly_false`]: https://rust-lang.github.io/rust-clippy/master/index.html#permissions_set_readonly_false [`positional_named_format_parameters`]: https://rust-lang.github.io/rust-clippy/master/index.html#positional_named_format_parameters diff --git a/Cargo.toml b/Cargo.toml index 4378849905514..bb4dc97e748e3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.1.81" +version = "0.1.82" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" @@ -30,11 +30,10 @@ color-print = "0.3.4" anstream = "0.6.0" [dev-dependencies] -ui_test = "0.23" +ui_test = "0.24" regex = "1.5.5" toml = "0.7.3" walkdir = "2.3" -# This is used by the `collect-metadata` alias. filetime = "0.2.9" itertools = "0.12" @@ -63,3 +62,7 @@ rustc_private = true [[test]] name = "compile-test" harness = false + +[[test]] +name = "dogfood" +harness = false diff --git a/book/src/development/adding_lints.md b/book/src/development/adding_lints.md index 48c00bcbf3413..a71d94daca74c 100644 --- a/book/src/development/adding_lints.md +++ b/book/src/development/adding_lints.md @@ -458,9 +458,8 @@ pub struct ManualStrip { } impl ManualStrip { - #[must_use] - pub fn new(msrv: Msrv) -> Self { - Self { msrv } + pub fn new(conf: &'static Conf) -> Self { + Self { msrv: conf.msrv.clone() } } } ``` @@ -689,7 +688,6 @@ for some users. Adding a configuration is done in the following steps: ]); // New manual definition struct - #[derive(Copy, Clone)] pub struct StructName {} impl_lint_pass!(StructName => [ @@ -700,7 +698,6 @@ for some users. Adding a configuration is done in the following steps: 2. Next add the configuration value and a corresponding creation method like this: ```rust - #[derive(Copy, Clone)] pub struct StructName { configuration_ident: Type, } @@ -708,9 +705,9 @@ for some users. Adding a configuration is done in the following steps: // ... impl StructName { - pub fn new(configuration_ident: Type) -> Self { + pub fn new(conf: &'static Conf) -> Self { Self { - configuration_ident, + configuration_ident: conf.configuration_ident, } } } @@ -726,8 +723,7 @@ for some users. Adding a configuration is done in the following steps: store.register_*_pass(|| box module::StructName); // New registration with configuration value - let configuration_ident = conf.configuration_ident.clone(); - store.register_*_pass(move || box module::StructName::new(configuration_ident)); + store.register_*_pass(move || box module::StructName::new(conf)); ``` Congratulations the work is almost done. The configuration value can now be diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index ad29339a84ad6..fb717a2c166d4 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -455,7 +455,7 @@ default configuration of Clippy. By default, any configuration will replace the * `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`. * `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list. -**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "DevOps", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PureScript", "TypeScript", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenDNS", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenTelemetry", "WebGL", "WebGL2", "WebGPU", "WebP", "OpenExr", "YCbCr", "sRGB", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]` +**Default Value:** `["TiB", "CoreGraphics", "CoffeeScript", "TeX", "Direct2D", "PiB", "DirectX", "NetBSD", "OAuth", "NaN", "OpenType", "WebGL2", "WebTransport", "JavaScript", "OpenSSL", "OpenSSH", "EiB", "PureScript", "OpenAL", "MiB", "WebAssembly", "MinGW", "CoreFoundation", "WebGPU", "ClojureScript", "CamelCase", "OpenDNS", "NaNs", "OpenMP", "GitLab", "KiB", "sRGB", "CoreText", "macOS", "TypeScript", "GiB", "OpenExr", "YCbCr", "OpenTelemetry", "OpenBSD", "FreeBSD", "GPLv2", "PostScript", "WebP", "LaTeX", "TensorFlow", "AccessKit", "TrueType", "OpenStreetMap", "OpenGL", "DevOps", "OCaml", "WebRTC", "WebGL", "BibLaTeX", "GitHub", "GraphQL", "iOS", "Direct3D", "BibTeX", "DirectWrite", "GPLv3", "IPv6", "WebSocket", "IPv4", "ECMAScript"]` --- **Affected lints:** @@ -679,6 +679,7 @@ The minimum rust version that the project supports. Defaults to the `rust-versio * [`cast_abs_to_unsigned`](https://rust-lang.github.io/rust-clippy/master/index.html#cast_abs_to_unsigned) * [`checked_conversions`](https://rust-lang.github.io/rust-clippy/master/index.html#checked_conversions) * [`cloned_instead_of_copied`](https://rust-lang.github.io/rust-clippy/master/index.html#cloned_instead_of_copied) +* [`collapsible_match`](https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_match) * [`collapsible_str_replace`](https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_str_replace) * [`deprecated_cfg_attr`](https://rust-lang.github.io/rust-clippy/master/index.html#deprecated_cfg_attr) * [`derivable_impls`](https://rust-lang.github.io/rust-clippy/master/index.html#derivable_impls) diff --git a/clippy.toml b/clippy.toml index 319b72e8c5d50..a7b0cc56ea127 100644 --- a/clippy.toml +++ b/clippy.toml @@ -8,7 +8,6 @@ reason = "this function does not add a link to our documentation, please use the path = "rustc_lint::context::LintContext::span_lint" reason = "this function does not add a link to our documentation, please use the `clippy_utils::diagnostics::span_lint*` functions instead" - [[disallowed-methods]] path = "rustc_middle::ty::context::TyCtxt::node_span_lint" reason = "this function does not add a link to our documentation, please use the `clippy_utils::diagnostics::span_lint_hir*` functions instead" diff --git a/clippy_config/Cargo.toml b/clippy_config/Cargo.toml index be0b048ac0c76..e1b2edc8a6ff9 100644 --- a/clippy_config/Cargo.toml +++ b/clippy_config/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_config" -version = "0.1.81" +version = "0.1.82" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index 7f53aad679330..63140a36875da 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -18,23 +18,26 @@ use std::{cmp, env, fmt, fs, io}; #[rustfmt::skip] const DEFAULT_DOC_VALID_IDENTS: &[&str] = &[ "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", + "AccessKit", + "CoreFoundation", "CoreGraphics", "CoreText", "DevOps", - "DirectX", + "Direct2D", "Direct3D", "DirectWrite", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", - "ClojureScript", "CoffeeScript", "JavaScript", "PureScript", "TypeScript", + "ClojureScript", "CoffeeScript", "JavaScript", "PostScript", "PureScript", "TypeScript", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", - "OpenDNS", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenTelemetry", - "WebGL", "WebGL2", "WebGPU", + "OpenAL", "OpenDNS", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenTelemetry", + "OpenType", + "WebGL", "WebGL2", "WebGPU", "WebRTC", "WebSocket", "WebTransport", "WebP", "OpenExr", "YCbCr", "sRGB", "TensorFlow", "TrueType", - "iOS", "macOS", "FreeBSD", + "iOS", "macOS", "FreeBSD", "NetBSD", "OpenBSD", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase", @@ -235,7 +238,7 @@ define_Conf! { /// /// A type, say `SomeType`, listed in this configuration has the same behavior of /// `["SomeType" , "*"], ["*", "SomeType"]` in `arithmetic_side_effects_allowed_binary`. - (arithmetic_side_effects_allowed: FxHashSet = <_>::default()), + (arithmetic_side_effects_allowed: Vec = <_>::default()), /// Lint: ARITHMETIC_SIDE_EFFECTS. /// /// Suppress checking of the passed type pair names in binary operations like addition or @@ -262,12 +265,12 @@ define_Conf! { /// ```toml /// arithmetic-side-effects-allowed-unary = ["SomeType", "AnotherType"] /// ``` - (arithmetic_side_effects_allowed_unary: FxHashSet = <_>::default()), + (arithmetic_side_effects_allowed_unary: Vec = <_>::default()), /// Lint: ENUM_VARIANT_NAMES, LARGE_TYPES_PASSED_BY_VALUE, TRIVIALLY_COPY_PASS_BY_REF, UNNECESSARY_WRAPS, UNUSED_SELF, UPPER_CASE_ACRONYMS, WRONG_SELF_CONVENTION, BOX_COLLECTION, REDUNDANT_ALLOCATION, RC_BUFFER, VEC_BOX, OPTION_OPTION, LINKEDLIST, RC_MUTEX, UNNECESSARY_BOX_RETURNS, SINGLE_CALL_FN, NEEDLESS_PASS_BY_REF_MUT. /// /// Suppress lints whenever the suggested change would cause breakage for other crates. (avoid_breaking_exported_api: bool = true), - /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS, MANUAL_TRY_FOLD, MANUAL_HASH_ONE, ITER_KV_MAP, MANUAL_C_STR_LITERALS, ASSIGNING_CLONES, LEGACY_NUMERIC_CONSTANTS, MANUAL_PATTERN_CHAR_COMPARISON, ALLOW_ATTRIBUTES, ALLOW_ATTRIBUTES_WITHOUT_REASON. + /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS, MANUAL_TRY_FOLD, MANUAL_HASH_ONE, ITER_KV_MAP, MANUAL_C_STR_LITERALS, ASSIGNING_CLONES, LEGACY_NUMERIC_CONSTANTS, MANUAL_PATTERN_CHAR_COMPARISON, ALLOW_ATTRIBUTES, ALLOW_ATTRIBUTES_WITHOUT_REASON, COLLAPSIBLE_MATCH. /// /// The minimum rust version that the project supports. Defaults to the `rust-version` field in `Cargo.toml` #[default_text = ""] @@ -311,7 +314,7 @@ define_Conf! { /// default configuration of Clippy. By default, any configuration will replace the default value. For example: /// * `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`. /// * `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list. - (doc_valid_idents: Vec = DEFAULT_DOC_VALID_IDENTS.iter().map(ToString::to_string).collect()), + (doc_valid_idents: FxHashSet = DEFAULT_DOC_VALID_IDENTS.iter().map(ToString::to_string).collect()), /// Lint: TOO_MANY_ARGUMENTS. /// /// The maximum number of argument a function or method can have @@ -547,7 +550,7 @@ define_Conf! { /// Lint: PATH_ENDS_WITH_EXT. /// /// Additional dotfiles (files or directories starting with a dot) to allow - (allowed_dotfiles: FxHashSet = FxHashSet::default()), + (allowed_dotfiles: Vec = Vec::default()), /// Lint: MULTIPLE_CRATE_VERSIONS. /// /// A list of crate names to allow duplicates of @@ -700,7 +703,6 @@ pub fn lookup_conf_file() -> io::Result<(Option, Vec)> { fn deserialize(file: &SourceFile) -> TryConf { match toml::de::Deserializer::new(file.src.as_ref().unwrap()).deserialize_map(ConfVisitor(file)) { Ok(mut conf) => { - 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( @@ -713,6 +715,11 @@ fn deserialize(file: &SourceFile) -> TryConf { .allowed_idents_below_min_chars .extend(DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS.iter().map(ToString::to_string)); } + if conf.conf.doc_valid_idents.contains("..") { + conf.conf + .doc_valid_idents + .extend(DEFAULT_DOC_VALID_IDENTS.iter().map(ToString::to_string)); + } conf }, diff --git a/clippy_config/src/types.rs b/clippy_config/src/types.rs index 435aa9244c522..d47e34bb5bce5 100644 --- a/clippy_config/src/types.rs +++ b/clippy_config/src/types.rs @@ -2,13 +2,13 @@ use serde::de::{self, Deserializer, Visitor}; use serde::{ser, Deserialize, Serialize}; use std::fmt; -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] pub struct Rename { pub path: String, pub rename: String, } -#[derive(Clone, Debug, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(untagged)] pub enum DisallowedPath { Simple(String), @@ -22,12 +22,10 @@ impl DisallowedPath { path } - pub fn reason(&self) -> Option { - match self { - Self::WithReason { - reason: Some(reason), .. - } => Some(format!("{reason} (from clippy.toml)")), - _ => None, + pub fn reason(&self) -> Option<&str> { + match &self { + Self::WithReason { reason, .. } => reason.as_deref(), + Self::Simple(_) => None, } } } diff --git a/clippy_dev/src/new_lint.rs b/clippy_dev/src/new_lint.rs index d762e30ef02e1..de91233d196c8 100644 --- a/clippy_dev/src/new_lint.rs +++ b/clippy_dev/src/new_lint.rs @@ -140,7 +140,7 @@ fn add_lint(lint: &LintData<'_>, enable_msrv: bool) -> io::Result<()> { let new_lint = if enable_msrv { format!( - "store.register_{lint_pass}_pass(move |{ctor_arg}| Box::new({module_name}::{camel_name}::new(msrv())));\n ", + "store.register_{lint_pass}_pass(move |{ctor_arg}| Box::new({module_name}::{camel_name}::new(conf)));\n ", lint_pass = lint.pass, ctor_arg = if lint.pass == "late" { "_" } else { "" }, module_name = lint.name, @@ -274,6 +274,7 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String { formatdoc!( r#" use clippy_config::msrvs::{{self, Msrv}}; + use clippy_config::Conf; {pass_import} use rustc_lint::{{{context_import}, {pass_type}, LintContext}}; use rustc_session::impl_lint_pass; @@ -301,9 +302,8 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String { }} impl {name_camel} {{ - #[must_use] - pub fn new(msrv: Msrv) -> Self {{ - Self {{ msrv }} + pub fn new(conf: &'static Conf) -> Self {{ + Self {{ msrv: conf.msrv.clone() }} }} }} diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 5708ffba08fd5..eb04c006f89fd 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_lints" -version = "0.1.81" +version = "0.1.82" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" diff --git a/clippy_lints/src/absolute_paths.rs b/clippy_lints/src/absolute_paths.rs index 461117cf965dc..c0a9d888e0b0b 100644 --- a/clippy_lints/src/absolute_paths.rs +++ b/clippy_lints/src/absolute_paths.rs @@ -1,3 +1,4 @@ +use clippy_config::Conf; use clippy_utils::diagnostics::span_lint; use clippy_utils::source::snippet_opt; use rustc_data_structures::fx::FxHashSet; @@ -47,7 +48,16 @@ impl_lint_pass!(AbsolutePaths => [ABSOLUTE_PATHS]); pub struct AbsolutePaths { pub absolute_paths_max_segments: u64, - pub absolute_paths_allowed_crates: FxHashSet, + pub absolute_paths_allowed_crates: &'static FxHashSet, +} + +impl AbsolutePaths { + pub fn new(conf: &'static Conf) -> Self { + Self { + absolute_paths_max_segments: conf.absolute_paths_max_segments, + absolute_paths_allowed_crates: &conf.absolute_paths_allowed_crates, + } + } } impl LateLintPass<'_> for AbsolutePaths { diff --git a/clippy_lints/src/almost_complete_range.rs b/clippy_lints/src/almost_complete_range.rs index 96e9c949b7500..451bae959874f 100644 --- a/clippy_lints/src/almost_complete_range.rs +++ b/clippy_lints/src/almost_complete_range.rs @@ -1,4 +1,5 @@ use clippy_config::msrvs::{self, Msrv}; +use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::{trim_span, walk_span_to_context}; use rustc_ast::ast::{Expr, ExprKind, LitKind, Pat, PatKind, RangeEnd, RangeLimits}; @@ -34,8 +35,10 @@ pub struct AlmostCompleteRange { msrv: Msrv, } impl AlmostCompleteRange { - pub fn new(msrv: Msrv) -> Self { - Self { msrv } + pub fn new(conf: &'static Conf) -> Self { + Self { + msrv: conf.msrv.clone(), + } } } impl EarlyLintPass for AlmostCompleteRange { diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index ec28fd4611184..e6d52bcef717c 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -1,4 +1,5 @@ use clippy_config::msrvs::{self, Msrv}; +use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_help; use rustc_ast::ast::{FloatTy, LitFloatType, LitKind}; use rustc_hir::{Expr, ExprKind}; @@ -67,9 +68,10 @@ pub struct ApproxConstant { } impl ApproxConstant { - #[must_use] - pub fn new(msrv: Msrv) -> Self { - Self { msrv } + pub fn new(conf: &'static Conf) -> Self { + Self { + msrv: conf.msrv.clone(), + } } fn check_lit(&self, cx: &LateContext<'_>, lit: &LitKind, e: &Expr<'_>) { diff --git a/clippy_lints/src/arc_with_non_send_sync.rs b/clippy_lints/src/arc_with_non_send_sync.rs index d57ab539fff42..4eafa330fafab 100644 --- a/clippy_lints/src/arc_with_non_send_sync.rs +++ b/clippy_lints/src/arc_with_non_send_sync.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::is_from_proc_macro; use clippy_utils::ty::{implements_trait, is_type_diagnostic_item}; -use clippy_utils::{is_from_proc_macro, last_path_segment}; -use rustc_hir::{Expr, ExprKind}; +use rustc_hir::{Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; use rustc_middle::ty::print::with_forced_trimmed_paths; @@ -42,12 +42,11 @@ declare_lint_pass!(ArcWithNonSendSync => [ARC_WITH_NON_SEND_SYNC]); impl<'tcx> LateLintPass<'tcx> for ArcWithNonSendSync { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { - if !expr.span.from_expansion() - && let ty = cx.typeck_results().expr_ty(expr) - && is_type_diagnostic_item(cx, ty, sym::Arc) - && let ExprKind::Call(func, [arg]) = expr.kind - && let ExprKind::Path(func_path) = func.kind - && last_path_segment(&func_path).ident.name == sym::new + if let ExprKind::Call(func, [arg]) = expr.kind + && let ExprKind::Path(QPath::TypeRelative(func_ty, func_name)) = func.kind + && func_name.ident.name == sym::new + && !expr.span.from_expansion() + && is_type_diagnostic_item(cx, cx.typeck_results().node_type(func_ty.hir_id), sym::Arc) && let arg_ty = cx.typeck_results().expr_ty(arg) // make sure that the type is not and does not contain any type parameters && arg_ty.walk().all(|arg| { diff --git a/clippy_lints/src/assigning_clones.rs b/clippy_lints/src/assigning_clones.rs index 0de0031ed24ff..03f777600f084 100644 --- a/clippy_lints/src/assigning_clones.rs +++ b/clippy_lints/src/assigning_clones.rs @@ -1,4 +1,5 @@ use clippy_config::msrvs::{self, Msrv}; +use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::mir::{enclosing_mir, PossibleBorrowerMap}; use clippy_utils::sugg::Sugg; @@ -57,9 +58,10 @@ pub struct AssigningClones { } impl AssigningClones { - #[must_use] - pub fn new(msrv: Msrv) -> Self { - Self { msrv } + pub fn new(conf: &'static Conf) -> Self { + Self { + msrv: conf.msrv.clone(), + } } } diff --git a/clippy_lints/src/attrs/mod.rs b/clippy_lints/src/attrs/mod.rs index 8ec60314cc9a0..8f430ae601a85 100644 --- a/clippy_lints/src/attrs/mod.rs +++ b/clippy_lints/src/attrs/mod.rs @@ -16,6 +16,7 @@ mod useless_attribute; mod utils; use clippy_config::msrvs::{self, Msrv}; +use clippy_config::Conf; use rustc_ast::{Attribute, MetaItemKind, NestedMetaItem}; use rustc_hir::{ImplItem, Item, ItemKind, TraitItem}; use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass}; @@ -499,7 +500,6 @@ declare_clippy_lint! { "duplicated attribute" } -#[derive(Clone)] pub struct Attributes { msrv: Msrv, } @@ -517,9 +517,10 @@ impl_lint_pass!(Attributes => [ ]); impl Attributes { - #[must_use] - pub fn new(msrv: Msrv) -> Self { - Self { msrv } + pub fn new(conf: &'static Conf) -> Self { + Self { + msrv: conf.msrv.clone(), + } } } @@ -589,7 +590,15 @@ impl<'tcx> LateLintPass<'tcx> for Attributes { } pub struct EarlyAttributes { - pub msrv: Msrv, + msrv: Msrv, +} + +impl EarlyAttributes { + pub fn new(conf: &'static Conf) -> Self { + Self { + msrv: conf.msrv.clone(), + } + } } impl_lint_pass!(EarlyAttributes => [ diff --git a/clippy_lints/src/await_holding_invalid.rs b/clippy_lints/src/await_holding_invalid.rs index d4a1e2780d083..d5f017b26509b 100644 --- a/clippy_lints/src/await_holding_invalid.rs +++ b/clippy_lints/src/await_holding_invalid.rs @@ -1,11 +1,11 @@ -use clippy_config::types::DisallowedPath; +use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::{match_def_path, paths}; -use rustc_data_structures::fx::FxHashMap; +use clippy_utils::{create_disallowed_map, match_def_path, paths}; use rustc_hir as hir; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::{DefId, DefIdMap}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::mir::CoroutineLayout; +use rustc_middle::ty::TyCtxt; use rustc_session::impl_lint_pass; use rustc_span::{sym, Span}; @@ -172,31 +172,19 @@ declare_clippy_lint! { impl_lint_pass!(AwaitHolding => [AWAIT_HOLDING_LOCK, AWAIT_HOLDING_REFCELL_REF, AWAIT_HOLDING_INVALID_TYPE]); -#[derive(Debug)] pub struct AwaitHolding { - conf_invalid_types: Vec, - def_ids: FxHashMap, + def_ids: DefIdMap<(&'static str, Option<&'static str>)>, } impl AwaitHolding { - pub(crate) fn new(conf_invalid_types: Vec) -> Self { + pub(crate) fn new(tcx: TyCtxt<'_>, conf: &'static Conf) -> Self { Self { - conf_invalid_types, - def_ids: FxHashMap::default(), + def_ids: create_disallowed_map(tcx, &conf.await_holding_invalid_types), } } } impl<'tcx> LateLintPass<'tcx> for AwaitHolding { - fn check_crate(&mut self, cx: &LateContext<'tcx>) { - for conf in &self.conf_invalid_types { - let segs: Vec<_> = conf.path().split("::").collect(); - for id in clippy_utils::def_path_def_ids(cx, &segs) { - self.def_ids.insert(id, conf.clone()); - } - } - } - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { if let hir::ExprKind::Closure(hir::Closure { kind: hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)), @@ -258,25 +246,22 @@ impl AwaitHolding { ); }, ); - } else if let Some(disallowed) = self.def_ids.get(&adt.did()) { - emit_invalid_type(cx, ty_cause.source_info.span, disallowed); + } else if let Some(&(path, reason)) = self.def_ids.get(&adt.did()) { + emit_invalid_type(cx, ty_cause.source_info.span, path, reason); } } } } } -fn emit_invalid_type(cx: &LateContext<'_>, span: Span, disallowed: &DisallowedPath) { +fn emit_invalid_type(cx: &LateContext<'_>, span: Span, path: &'static str, reason: Option<&'static str>) { span_lint_and_then( cx, AWAIT_HOLDING_INVALID_TYPE, span, - format!( - "`{}` may not be held across an await point per `clippy.toml`", - disallowed.path() - ), + format!("holding a disallowed type across an await point `{path}`"), |diag| { - if let Some(reason) = disallowed.reason() { + if let Some(reason) = reason { diag.note(reason); } }, diff --git a/clippy_lints/src/borrow_deref_ref.rs b/clippy_lints/src/borrow_deref_ref.rs index 0ca4a0e067d36..bd123a725a736 100644 --- a/clippy_lints/src/borrow_deref_ref.rs +++ b/clippy_lints/src/borrow_deref_ref.rs @@ -49,35 +49,31 @@ declare_lint_pass!(BorrowDerefRef => [BORROW_DEREF_REF]); impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &rustc_hir::Expr<'tcx>) { - if !e.span.from_expansion() - && let ExprKind::AddrOf(_, Mutability::Not, addrof_target) = e.kind - && !addrof_target.span.from_expansion() + if let ExprKind::AddrOf(_, Mutability::Not, addrof_target) = e.kind && let ExprKind::Unary(UnOp::Deref, deref_target) = addrof_target.kind - && !deref_target.span.from_expansion() && !matches!(deref_target.kind, ExprKind::Unary(UnOp::Deref, ..)) + && !e.span.from_expansion() + && !deref_target.span.from_expansion() + && !addrof_target.span.from_expansion() && let ref_ty = cx.typeck_results().expr_ty(deref_target) && let ty::Ref(_, inner_ty, Mutability::Not) = ref_ty.kind() - { - if let Some(parent_expr) = get_parent_expr(cx, e) { - if matches!(parent_expr.kind, ExprKind::Unary(UnOp::Deref, ..)) - && !is_lint_allowed(cx, DEREF_ADDROF, parent_expr.hir_id) - { - return; + && get_parent_expr(cx, e).map_or(true, |parent| { + match parent.kind { + // `*&*foo` should lint `deref_addrof` instead. + ExprKind::Unary(UnOp::Deref, _) => is_lint_allowed(cx, DEREF_ADDROF, parent.hir_id), + // `&*foo` creates a distinct temporary from `foo` + ExprKind::AddrOf(_, Mutability::Mut, _) => !matches!( + deref_target.kind, + ExprKind::Path(..) + | ExprKind::Field(..) + | ExprKind::Index(..) + | ExprKind::Unary(UnOp::Deref, ..) + ), + _ => true, } - - // modification to `&mut &*x` is different from `&mut x` - if matches!( - deref_target.kind, - ExprKind::Path(..) | ExprKind::Field(..) | ExprKind::Index(..) | ExprKind::Unary(UnOp::Deref, ..) - ) && matches!(parent_expr.kind, ExprKind::AddrOf(_, Mutability::Mut, _)) - { - return; - } - } - if is_from_proc_macro(cx, e) { - return; - } - + }) + && !is_from_proc_macro(cx, e) + { span_lint_and_then( cx, BORROW_DEREF_REF, diff --git a/clippy_lints/src/cargo/mod.rs b/clippy_lints/src/cargo/mod.rs index 593bc6c81ee8e..312ad4c299007 100644 --- a/clippy_lints/src/cargo/mod.rs +++ b/clippy_lints/src/cargo/mod.rs @@ -5,6 +5,7 @@ mod multiple_crate_versions; mod wildcard_dependencies; use cargo_metadata::MetadataCommand; +use clippy_config::Conf; use clippy_utils::diagnostics::span_lint; use clippy_utils::is_lint_allowed; use rustc_data_structures::fx::FxHashSet; @@ -204,8 +205,8 @@ declare_clippy_lint! { } pub struct Cargo { - pub allowed_duplicate_crates: FxHashSet, - pub ignore_publish: bool, + allowed_duplicate_crates: &'static FxHashSet, + ignore_publish: bool, } impl_lint_pass!(Cargo => [ @@ -217,6 +218,15 @@ impl_lint_pass!(Cargo => [ LINT_GROUPS_PRIORITY, ]); +impl Cargo { + pub fn new(conf: &'static Conf) -> Self { + Self { + allowed_duplicate_crates: &conf.allowed_duplicate_crates, + ignore_publish: conf.cargo_ignore_publish, + } + } +} + impl LateLintPass<'_> for Cargo { fn check_crate(&mut self, cx: &LateContext<'_>) { static NO_DEPS_LINTS: &[&Lint] = &[ @@ -253,7 +263,7 @@ impl LateLintPass<'_> for Cargo { { match MetadataCommand::new().exec() { Ok(metadata) => { - multiple_crate_versions::check(cx, &metadata, &self.allowed_duplicate_crates); + multiple_crate_versions::check(cx, &metadata, self.allowed_duplicate_crates); }, Err(e) => { for lint in WITH_DEPS_LINTS { diff --git a/clippy_lints/src/casts/cast_lossless.rs b/clippy_lints/src/casts/cast_lossless.rs index d52ad1c6f23f5..ff460a3fd8e39 100644 --- a/clippy_lints/src/casts/cast_lossless.rs +++ b/clippy_lints/src/casts/cast_lossless.rs @@ -1,19 +1,21 @@ use clippy_config::msrvs::{self, Msrv}; -use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::in_constant; -use clippy_utils::source::{snippet_opt, snippet_with_applicability}; +use clippy_utils::source::snippet_opt; +use clippy_utils::sugg::Sugg; use clippy_utils::ty::is_isize_or_usize; use rustc_errors::Applicability; -use rustc_hir::{Expr, ExprKind, QPath, TyKind}; +use rustc_hir::{Expr, QPath, TyKind}; use rustc_lint::LateContext; -use rustc_middle::ty::{self, FloatTy, Ty, UintTy}; +use rustc_middle::ty::{self, FloatTy, Ty}; +use rustc_span::hygiene; use super::{utils, CAST_LOSSLESS}; pub(super) fn check( cx: &LateContext<'_>, expr: &Expr<'_>, - cast_op: &Expr<'_>, + cast_from_expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>, cast_to_hir: &rustc_hir::Ty<'_>, @@ -23,64 +25,54 @@ pub(super) fn check( return; } - // The suggestion is to use a function call, so if the original expression - // has parens on the outside, they are no longer needed. - let mut app = Applicability::MachineApplicable; - let opt = snippet_opt(cx, cast_op.span.source_callsite()); - let sugg = opt.as_ref().map_or_else( - || { - app = Applicability::HasPlaceholders; - ".." - }, - |snip| { - if should_strip_parens(cast_op, snip) { - &snip[1..snip.len() - 1] - } else { - snip.as_str() - } - }, - ); - - // Display the type alias instead of the aliased type. Fixes #11285 - // - // FIXME: Once `lazy_type_alias` is stabilized(?) we should use `rustc_middle` types instead, - // this will allow us to display the right type with `cast_from` as well. - let cast_to_fmt = if let TyKind::Path(QPath::Resolved(None, path)) = cast_to_hir.kind - // It's a bit annoying but the turbofish is optional for types. A type in an `as` cast - // shouldn't have these if they're primitives, which are the only things we deal with. - // - // This could be removed for performance if this check is determined to have a pretty major - // effect. - && path.segments.iter().all(|segment| segment.args.is_none()) - { - snippet_with_applicability(cx, cast_to_hir.span, "..", &mut app) - } else { - cast_to.to_string().into() - }; - - let message = if cast_from.is_bool() { - format!("casting `{cast_from}` to `{cast_to_fmt}` is more cleanly stated with `{cast_to_fmt}::from(_)`") - } else { - format!("casting `{cast_from}` to `{cast_to_fmt}` may become silently lossy if you later change the type") - }; - - span_lint_and_sugg( + span_lint_and_then( cx, CAST_LOSSLESS, expr.span, - message, - "try", - format!("{cast_to_fmt}::from({sugg})"), - app, + format!("casts from `{cast_from}` to `{cast_to}` can be expressed infallibly using `From`"), + |diag| { + diag.help("an `as` cast can become silently lossy if the types change in the future"); + let mut applicability = Applicability::MachineApplicable; + let from_sugg = Sugg::hir_with_context(cx, cast_from_expr, expr.span.ctxt(), "", &mut applicability); + let Some(ty) = snippet_opt(cx, hygiene::walk_chain(cast_to_hir.span, expr.span.ctxt())) else { + return; + }; + match cast_to_hir.kind { + TyKind::Infer => { + diag.span_suggestion_verbose( + expr.span, + "use `Into::into` instead", + format!("{}.into()", from_sugg.maybe_par()), + applicability, + ); + }, + // Don't suggest `A<_>::B::From(x)` or `macro!()::from(x)` + kind if matches!(kind, TyKind::Path(QPath::Resolved(_, path)) if path.segments.iter().any(|s| s.args.is_some())) + || !cast_to_hir.span.eq_ctxt(expr.span) => + { + diag.span_suggestion_verbose( + expr.span, + format!("use `<{ty}>::from` instead"), + format!("<{ty}>::from({from_sugg})"), + applicability, + ); + }, + _ => { + diag.span_suggestion_verbose( + expr.span, + format!("use `{ty}::from` instead"), + format!("{ty}::from({from_sugg})"), + applicability, + ); + }, + } + }, ); } fn should_lint(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>, msrv: &Msrv) -> bool { // Do not suggest using From in consts/statics until it is valid to do so (see #2267). - // - // If destination is u128, do not lint because source type cannot be larger - // If source is bool, still lint due to the lint message differing (refers to style) - if in_constant(cx, expr.hir_id) || (!cast_from.is_bool() && matches!(cast_to.kind(), ty::Uint(UintTy::U128))) { + if in_constant(cx, expr.hir_id) { return false; } @@ -110,12 +102,3 @@ fn should_lint(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to }, } } - -fn should_strip_parens(cast_expr: &Expr<'_>, snip: &str) -> bool { - if let ExprKind::Binary(_, _, _) = cast_expr.kind { - if snip.starts_with('(') && snip.ends_with(')') { - return true; - } - } - false -} diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs index 54f0c7c468719..c31716fbcee1d 100644 --- a/clippy_lints/src/casts/mod.rs +++ b/clippy_lints/src/casts/mod.rs @@ -24,6 +24,7 @@ mod utils; mod zero_ptr; use clippy_config::msrvs::{self, Msrv}; +use clippy_config::Conf; use clippy_utils::is_hir_ty_cfg_dependant; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -658,11 +659,11 @@ declare_clippy_lint! { /// /// ### Example /// ```rust,ignore - /// let _: (0.0_f32 / 0.0) as u64; + /// let _ = (0.0_f32 / 0.0) as u64; /// ``` /// Use instead: /// ```rust,ignore - /// let _: = 0_u64; + /// let _ = 0_u64; /// ``` #[clippy::version = "1.66.0"] pub CAST_NAN_TO_INT, @@ -722,9 +723,10 @@ pub struct Casts { } impl Casts { - #[must_use] - pub fn new(msrv: Msrv) -> Self { - Self { msrv } + pub fn new(conf: &'static Conf) -> Self { + Self { + msrv: conf.msrv.clone(), + } } } @@ -761,45 +763,45 @@ impl<'tcx> LateLintPass<'tcx> for Casts { return; } - if let ExprKind::Cast(cast_expr, cast_to_hir) = expr.kind { + if let ExprKind::Cast(cast_from_expr, cast_to_hir) = expr.kind { if is_hir_ty_cfg_dependant(cx, cast_to_hir) { return; } let (cast_from, cast_to) = ( - cx.typeck_results().expr_ty(cast_expr), + cx.typeck_results().expr_ty(cast_from_expr), cx.typeck_results().expr_ty(expr), ); - if !expr.span.from_expansion() && unnecessary_cast::check(cx, expr, cast_expr, cast_from, cast_to) { + if !expr.span.from_expansion() && unnecessary_cast::check(cx, expr, cast_from_expr, cast_from, cast_to) { return; } - cast_slice_from_raw_parts::check(cx, expr, cast_expr, cast_to, &self.msrv); - ptr_cast_constness::check(cx, expr, cast_expr, cast_from, cast_to, &self.msrv); - as_ptr_cast_mut::check(cx, expr, cast_expr, cast_to); - fn_to_numeric_cast_any::check(cx, expr, cast_expr, cast_from, cast_to); - fn_to_numeric_cast::check(cx, expr, cast_expr, cast_from, cast_to); - fn_to_numeric_cast_with_truncation::check(cx, expr, cast_expr, cast_from, cast_to); - zero_ptr::check(cx, expr, cast_expr, cast_to_hir); + cast_slice_from_raw_parts::check(cx, expr, cast_from_expr, cast_to, &self.msrv); + ptr_cast_constness::check(cx, expr, cast_from_expr, cast_from, cast_to, &self.msrv); + as_ptr_cast_mut::check(cx, expr, cast_from_expr, cast_to); + fn_to_numeric_cast_any::check(cx, expr, cast_from_expr, cast_from, cast_to); + fn_to_numeric_cast::check(cx, expr, cast_from_expr, cast_from, cast_to); + fn_to_numeric_cast_with_truncation::check(cx, expr, cast_from_expr, cast_from, cast_to); + zero_ptr::check(cx, expr, cast_from_expr, cast_to_hir); if cast_to.is_numeric() { - cast_possible_truncation::check(cx, expr, cast_expr, cast_from, cast_to, cast_to_hir.span); + cast_possible_truncation::check(cx, expr, cast_from_expr, cast_from, cast_to, cast_to_hir.span); if cast_from.is_numeric() { cast_possible_wrap::check(cx, expr, cast_from, cast_to); cast_precision_loss::check(cx, expr, cast_from, cast_to); - cast_sign_loss::check(cx, expr, cast_expr, cast_from, cast_to); - cast_abs_to_unsigned::check(cx, expr, cast_expr, cast_from, cast_to, &self.msrv); - cast_nan_to_int::check(cx, expr, cast_expr, cast_from, cast_to); + cast_sign_loss::check(cx, expr, cast_from_expr, cast_from, cast_to); + cast_abs_to_unsigned::check(cx, expr, cast_from_expr, cast_from, cast_to, &self.msrv); + cast_nan_to_int::check(cx, expr, cast_from_expr, cast_from, cast_to); } - cast_lossless::check(cx, expr, cast_expr, cast_from, cast_to, cast_to_hir, &self.msrv); - cast_enum_constructor::check(cx, expr, cast_expr, cast_from); + cast_lossless::check(cx, expr, cast_from_expr, cast_from, cast_to, cast_to_hir, &self.msrv); + cast_enum_constructor::check(cx, expr, cast_from_expr, cast_from); } as_underscore::check(cx, expr, cast_to_hir); if self.msrv.meets(msrvs::PTR_FROM_REF) { - ref_as_ptr::check(cx, expr, cast_expr, cast_to_hir); + ref_as_ptr::check(cx, expr, cast_from_expr, cast_to_hir); } else if self.msrv.meets(msrvs::BORROW_AS_PTR) { - borrow_as_ptr::check(cx, expr, cast_expr, cast_to_hir); + borrow_as_ptr::check(cx, expr, cast_from_expr, cast_to_hir); } } diff --git a/clippy_lints/src/casts/ptr_cast_constness.rs b/clippy_lints/src/casts/ptr_cast_constness.rs index 921693567fcd4..7513e18d408b1 100644 --- a/clippy_lints/src/casts/ptr_cast_constness.rs +++ b/clippy_lints/src/casts/ptr_cast_constness.rs @@ -4,7 +4,7 @@ use clippy_utils::sugg::Sugg; use rustc_errors::Applicability; use rustc_hir::{Expr, Mutability}; use rustc_lint::LateContext; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::{self, Ty, TypeVisitableExt}; use super::PTR_CAST_CONSTNESS; @@ -24,6 +24,7 @@ pub(super) fn check<'tcx>( (Mutability::Not, Mutability::Mut) | (Mutability::Mut, Mutability::Not) ) && from_ty == to_ty + && !from_ty.has_erased_regions() { let sugg = Sugg::hir(cx, cast_expr, "_"); let constness = match *to_mutbl { diff --git a/clippy_lints/src/checked_conversions.rs b/clippy_lints/src/checked_conversions.rs index 92810ea2aa0ff..0b1ab5411bf18 100644 --- a/clippy_lints/src/checked_conversions.rs +++ b/clippy_lints/src/checked_conversions.rs @@ -1,11 +1,12 @@ //! lint on manually implemented checked conversions that could be transformed into `try_from` use clippy_config::msrvs::{self, Msrv}; +use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::{in_constant, is_integer_literal, SpanlessEq}; use rustc_errors::Applicability; -use rustc_hir::{BinOp, BinOpKind, Expr, ExprKind, QPath, TyKind}; +use rustc_hir::{BinOpKind, Expr, ExprKind, QPath, TyKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::impl_lint_pass; @@ -40,9 +41,10 @@ pub struct CheckedConversions { } impl CheckedConversions { - #[must_use] - pub fn new(msrv: Msrv) -> Self { - Self { msrv } + pub fn new(conf: &'static Conf) -> Self { + Self { + msrv: conf.msrv.clone(), + } } } @@ -50,61 +52,54 @@ impl_lint_pass!(CheckedConversions => [CHECKED_CONVERSIONS]); impl<'tcx> LateLintPass<'tcx> for CheckedConversions { fn check_expr(&mut self, cx: &LateContext<'_>, item: &Expr<'_>) { - if !self.msrv.meets(msrvs::TRY_FROM) { - return; - } - - let result = if !in_constant(cx, item.hir_id) - && !in_external_macro(cx.sess(), item.span) - && let ExprKind::Binary(op, left, right) = &item.kind - { - match op.node { - BinOpKind::Ge | BinOpKind::Le => single_check(item), - BinOpKind::And => double_check(cx, left, right), - _ => None, + if let ExprKind::Binary(op, lhs, rhs) = item.kind + && let (lt1, gt1, op2) = match op.node { + BinOpKind::Le => (lhs, rhs, None), + BinOpKind::Ge => (rhs, lhs, None), + BinOpKind::And + if let ExprKind::Binary(op1, lhs1, rhs1) = lhs.kind + && let ExprKind::Binary(op2, lhs2, rhs2) = rhs.kind + && let Some((lt1, gt1)) = read_le_ge(op1.node, lhs1, rhs1) + && let Some((lt2, gt2)) = read_le_ge(op2.node, lhs2, rhs2) => + { + (lt1, gt1, Some((lt2, gt2))) + }, + _ => return, } - } else { - None - }; - - if let Some(cv) = result { - if let Some(to_type) = cv.to_type { - let mut applicability = Applicability::MachineApplicable; - let snippet = snippet_with_applicability(cx, cv.expr_to_cast.span, "_", &mut applicability); - span_lint_and_sugg( - cx, - CHECKED_CONVERSIONS, - item.span, - "checked cast can be simplified", - "try", - format!("{to_type}::try_from({snippet}).is_ok()"), - applicability, - ); + && !in_external_macro(cx.sess(), item.span) + && !in_constant(cx, item.hir_id) + && self.msrv.meets(msrvs::TRY_FROM) + && let Some(cv) = match op2 { + // todo: check for case signed -> larger unsigned == only x >= 0 + None => check_upper_bound(lt1, gt1).filter(|cv| cv.cvt == ConversionType::FromUnsigned), + Some((lt2, gt2)) => { + let upper_lower = |lt1, gt1, lt2, gt2| { + check_upper_bound(lt1, gt1) + .zip(check_lower_bound(lt2, gt2)) + .and_then(|(l, r)| l.combine(r, cx)) + }; + upper_lower(lt1, gt1, lt2, gt2).or_else(|| upper_lower(lt2, gt2, lt1, gt1)) + }, } + && let Some(to_type) = cv.to_type + { + let mut applicability = Applicability::MachineApplicable; + let snippet = snippet_with_applicability(cx, cv.expr_to_cast.span, "_", &mut applicability); + span_lint_and_sugg( + cx, + CHECKED_CONVERSIONS, + item.span, + "checked cast can be simplified", + "try", + format!("{to_type}::try_from({snippet}).is_ok()"), + applicability, + ); } } extract_msrv_attr!(LateContext); } -/// Searches for a single check from unsigned to _ is done -/// todo: check for case signed -> larger unsigned == only x >= 0 -fn single_check<'tcx>(expr: &'tcx Expr<'tcx>) -> Option> { - check_upper_bound(expr).filter(|cv| cv.cvt == ConversionType::FromUnsigned) -} - -/// Searches for a combination of upper & lower bound checks -fn double_check<'a>(cx: &LateContext<'_>, left: &'a Expr<'_>, right: &'a Expr<'_>) -> Option> { - let upper_lower = |l, r| { - let upper = check_upper_bound(l); - let lower = check_lower_bound(r); - - upper.zip(lower).and_then(|(l, r)| l.combine(r, cx)) - }; - - upper_lower(left, right).or_else(|| upper_lower(right, left)) -} - /// Contains the result of a tried conversion check #[derive(Clone, Debug)] struct Conversion<'a> { @@ -121,6 +116,19 @@ enum ConversionType { FromUnsigned, } +/// Attempts to read either `<=` or `>=` with a normalized operand order. +fn read_le_ge<'tcx>( + op: BinOpKind, + lhs: &'tcx Expr<'tcx>, + rhs: &'tcx Expr<'tcx>, +) -> Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>)> { + match op { + BinOpKind::Le => Some((lhs, rhs)), + BinOpKind::Ge => Some((rhs, lhs)), + _ => None, + } +} + impl<'a> Conversion<'a> { /// Combine multiple conversions if the are compatible pub fn combine(self, other: Self, cx: &LateContext<'_>) -> Option> { @@ -188,29 +196,17 @@ impl ConversionType { } /// Check for `expr <= (to_type::MAX as from_type)` -fn check_upper_bound<'tcx>(expr: &'tcx Expr<'tcx>) -> Option> { - if let ExprKind::Binary(ref op, left, right) = &expr.kind - && let Some((candidate, check)) = normalize_le_ge(op, left, right) - && let Some((from, to)) = get_types_from_cast(check, INTS, "max_value", "MAX") - { - Conversion::try_new(candidate, from, to) +fn check_upper_bound<'tcx>(lt: &'tcx Expr<'tcx>, gt: &'tcx Expr<'tcx>) -> Option> { + if let Some((from, to)) = get_types_from_cast(gt, INTS, "max_value", "MAX") { + Conversion::try_new(lt, from, to) } else { None } } /// Check for `expr >= 0|(to_type::MIN as from_type)` -fn check_lower_bound<'tcx>(expr: &'tcx Expr<'tcx>) -> Option> { - fn check_function<'a>(candidate: &'a Expr<'a>, check: &'a Expr<'a>) -> Option> { - (check_lower_bound_zero(candidate, check)).or_else(|| (check_lower_bound_min(candidate, check))) - } - - // First of we need a binary containing the expression & the cast - if let ExprKind::Binary(ref op, left, right) = &expr.kind { - normalize_le_ge(op, right, left).and_then(|(l, r)| check_function(l, r)) - } else { - None - } +fn check_lower_bound<'tcx>(lt: &'tcx Expr<'tcx>, gt: &'tcx Expr<'tcx>) -> Option> { + check_lower_bound_zero(gt, lt).or_else(|| check_lower_bound_min(gt, lt)) } /// Check for `expr >= 0` @@ -309,15 +305,6 @@ fn int_ty_to_sym<'tcx>(path: &QPath<'_>) -> Option<&'tcx str> { } } -/// Will return the expressions as if they were expr1 <= expr2 -fn normalize_le_ge<'a>(op: &BinOp, left: &'a Expr<'a>, right: &'a Expr<'a>) -> Option<(&'a Expr<'a>, &'a Expr<'a>)> { - match op.node { - BinOpKind::Le => Some((left, right)), - BinOpKind::Ge => Some((right, left)), - _ => None, - } -} - // Constants const UINTS: &[&str] = &["u8", "u16", "u32", "u64", "usize"]; const SINTS: &[&str] = &["i8", "i16", "i32", "i64", "isize"]; diff --git a/clippy_lints/src/cognitive_complexity.rs b/clippy_lints/src/cognitive_complexity.rs index 60815f4f2afbb..5fa0522e4e5f9 100644 --- a/clippy_lints/src/cognitive_complexity.rs +++ b/clippy_lints/src/cognitive_complexity.rs @@ -1,5 +1,6 @@ //! calculate cognitive complexity and warn about overly complex functions +use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::source::{IntoSpan, SpanRangeExt}; use clippy_utils::ty::is_type_diagnostic_item; @@ -39,10 +40,9 @@ pub struct CognitiveComplexity { } impl CognitiveComplexity { - #[must_use] - pub fn new(limit: u64) -> Self { + pub fn new(conf: &'static Conf) -> Self { Self { - limit: LimitStack::new(limit), + limit: LimitStack::new(conf.cognitive_complexity_threshold), } } } diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs index 07b02c98df151..f311c052ad6ee 100644 --- a/clippy_lints/src/collapsible_if.rs +++ b/clippy_lints/src/collapsible_if.rs @@ -93,20 +93,14 @@ declare_lint_pass!(CollapsibleIf => [COLLAPSIBLE_IF, COLLAPSIBLE_ELSE_IF]); impl EarlyLintPass for CollapsibleIf { fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) { - if !expr.span.from_expansion() { - check_if(cx, expr); - } - } -} - -fn check_if(cx: &EarlyContext<'_>, expr: &ast::Expr) { - if let ast::ExprKind::If(check, then, else_) = &expr.kind { - if let Some(else_) = else_ { - check_collapsible_maybe_if_let(cx, then.span, else_); - } else if let ast::ExprKind::Let(..) = check.kind { - // Prevent triggering on `if let a = b { if c { .. } }`. - } else { - check_collapsible_no_if_let(cx, expr, check, then); + if let ast::ExprKind::If(cond, then, else_) = &expr.kind + && !expr.span.from_expansion() + { + if let Some(else_) = else_ { + check_collapsible_maybe_if_let(cx, then.span, else_); + } else if !matches!(cond.kind, ast::ExprKind::Let(..)) { + check_collapsible_no_if_let(cx, expr, cond, then); + } } } } @@ -189,13 +183,10 @@ fn check_collapsible_no_if_let(cx: &EarlyContext<'_>, expr: &ast::Expr, check: & /// If the block contains only one expression, return it. fn expr_block(block: &ast::Block) -> Option<&ast::Expr> { - let mut it = block.stmts.iter(); - - if let (Some(stmt), None) = (it.next(), it.next()) { - match stmt.kind { - ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => Some(expr), - _ => None, - } + if let [stmt] = &*block.stmts + && let ast::StmtKind::Expr(expr) | ast::StmtKind::Semi(expr) = &stmt.kind + { + Some(expr) } else { None } diff --git a/clippy_lints/src/collection_is_never_read.rs b/clippy_lints/src/collection_is_never_read.rs index 28d9f68d504cc..eebda3ff76fd9 100644 --- a/clippy_lints/src/collection_is_never_read.rs +++ b/clippy_lints/src/collection_is_never_read.rs @@ -59,9 +59,9 @@ static COLLECTIONS: [Symbol; 9] = [ impl<'tcx> LateLintPass<'tcx> for CollectionIsNeverRead { fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx LetStmt<'tcx>) { - // Look for local variables whose type is a container. Search surrounding bock for read access. - if match_acceptable_type(cx, local, &COLLECTIONS) - && let PatKind::Binding(_, local_id, _, _) = local.pat.kind + // Look for local variables whose type is a container. Search surrounding block for read access. + if let PatKind::Binding(_, local_id, _, _) = local.pat.kind + && match_acceptable_type(cx, local, &COLLECTIONS) && let Some(enclosing_block) = get_enclosing_block(cx, local.hir_id) && has_no_read_access(cx, local_id, enclosing_block) { diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index d896452be9209..86e0368c4e423 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -1,3 +1,4 @@ +use clippy_config::Conf; use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_then}; use clippy_utils::source::{first_line_of_span, indent_of, reindent_multiline, snippet, IntoSpan, SpanRangeExt}; use clippy_utils::ty::{needs_ordered_drop, InteriorMut}; @@ -11,6 +12,7 @@ use core::ops::ControlFlow; use rustc_errors::Applicability; use rustc_hir::{intravisit, BinOpKind, Block, Expr, ExprKind, HirId, HirIdSet, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::TyCtxt; use rustc_session::impl_lint_pass; use rustc_span::hygiene::walk_chain; use rustc_span::source_map::SourceMap; @@ -159,15 +161,13 @@ declare_clippy_lint! { } pub struct CopyAndPaste<'tcx> { - ignore_interior_mutability: Vec, interior_mut: InteriorMut<'tcx>, } -impl CopyAndPaste<'_> { - pub fn new(ignore_interior_mutability: Vec) -> Self { +impl<'tcx> CopyAndPaste<'tcx> { + pub fn new(tcx: TyCtxt<'tcx>, conf: &'static Conf) -> Self { Self { - ignore_interior_mutability, - interior_mut: InteriorMut::default(), + interior_mut: InteriorMut::new(tcx, &conf.ignore_interior_mutability), } } } @@ -180,10 +180,6 @@ impl_lint_pass!(CopyAndPaste<'_> => [ ]); impl<'tcx> LateLintPass<'tcx> for CopyAndPaste<'tcx> { - fn check_crate(&mut self, cx: &LateContext<'tcx>) { - self.interior_mut = InteriorMut::new(cx, &self.ignore_interior_mutability); - } - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if !expr.span.from_expansion() && matches!(expr.kind, ExprKind::If(..)) && !is_else_clause(cx.tcx, expr) { let (conds, blocks) = if_sequence(expr); diff --git a/clippy_lints/src/crate_in_macro_def.rs b/clippy_lints/src/crate_in_macro_def.rs index adf6f7c473757..678bdbc0ffb8a 100644 --- a/clippy_lints/src/crate_in_macro_def.rs +++ b/clippy_lints/src/crate_in_macro_def.rs @@ -53,10 +53,9 @@ declare_lint_pass!(CrateInMacroDef => [CRATE_IN_MACRO_DEF]); impl EarlyLintPass for CrateInMacroDef { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { - if item.attrs.iter().any(is_macro_export) - && let ItemKind::MacroDef(macro_def) = &item.kind - && let tts = macro_def.body.tokens.clone() - && let Some(span) = contains_unhygienic_crate_reference(&tts) + if let ItemKind::MacroDef(macro_def) = &item.kind + && item.attrs.iter().any(is_macro_export) + && let Some(span) = contains_unhygienic_crate_reference(¯o_def.body.tokens) { span_lint_and_sugg( cx, diff --git a/clippy_lints/src/dbg_macro.rs b/clippy_lints/src/dbg_macro.rs index b0590b0a71cb2..788c6f3ada297 100644 --- a/clippy_lints/src/dbg_macro.rs +++ b/clippy_lints/src/dbg_macro.rs @@ -1,3 +1,4 @@ +use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::is_in_test; use clippy_utils::macros::{macro_backtrace, MacroCall}; @@ -33,7 +34,6 @@ declare_clippy_lint! { "`dbg!` macro is intended as a debugging tool" } -#[derive(Clone)] pub struct DbgMacro { allow_dbg_in_tests: bool, /// Tracks the `dbg!` macro callsites that are already checked. @@ -45,9 +45,9 @@ pub struct DbgMacro { impl_lint_pass!(DbgMacro => [DBG_MACRO]); impl DbgMacro { - pub fn new(allow_dbg_in_tests: bool) -> Self { + pub fn new(conf: &'static Conf) -> Self { DbgMacro { - allow_dbg_in_tests, + allow_dbg_in_tests: conf.allow_dbg_in_tests, checked_dbg_call_site: FxHashSet::default(), prev_ctxt: SyntaxContext::root(), } diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index eabc67601a2f1..69f9eb6842bcd 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -598,6 +598,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::partialeq_to_none::PARTIALEQ_TO_NONE_INFO, crate::pass_by_ref_or_value::LARGE_TYPES_PASSED_BY_VALUE_INFO, crate::pass_by_ref_or_value::TRIVIALLY_COPY_PASS_BY_REF_INFO, + crate::pathbuf_init_then_push::PATHBUF_INIT_THEN_PUSH_INFO, crate::pattern_type_mismatch::PATTERN_TYPE_MISMATCH_INFO, crate::permissions_set_readonly_false::PERMISSIONS_SET_READONLY_FALSE_INFO, crate::precedence::PRECEDENCE_INFO, diff --git a/clippy_lints/src/derivable_impls.rs b/clippy_lints/src/derivable_impls.rs index 0c9ad5e8d0015..f27f68e2cbc5f 100644 --- a/clippy_lints/src/derivable_impls.rs +++ b/clippy_lints/src/derivable_impls.rs @@ -1,4 +1,5 @@ use clippy_config::msrvs::{self, Msrv}; +use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::indent_of; use clippy_utils::{is_default_equivalent, peel_blocks}; @@ -60,9 +61,10 @@ pub struct DerivableImpls { } impl DerivableImpls { - #[must_use] - pub fn new(msrv: Msrv) -> Self { - DerivableImpls { msrv } + pub fn new(conf: &'static Conf) -> Self { + DerivableImpls { + msrv: conf.msrv.clone(), + } } } diff --git a/clippy_lints/src/disallowed_macros.rs b/clippy_lints/src/disallowed_macros.rs index 871f529da6c40..b51d343132b26 100644 --- a/clippy_lints/src/disallowed_macros.rs +++ b/clippy_lints/src/disallowed_macros.rs @@ -1,4 +1,5 @@ -use clippy_config::types::DisallowedPath; +use clippy_config::Conf; +use clippy_utils::create_disallowed_map; use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then}; use clippy_utils::macros::macro_backtrace; use rustc_ast::Attribute; @@ -9,6 +10,7 @@ use rustc_hir::{ Expr, ExprKind, ForeignItem, HirId, ImplItem, Item, ItemKind, OwnerId, Pat, Path, Stmt, TraitItem, Ty, }; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::TyCtxt; use rustc_session::impl_lint_pass; use rustc_span::{ExpnId, MacroKind, Span}; @@ -57,27 +59,24 @@ declare_clippy_lint! { } pub struct DisallowedMacros { - conf_disallowed: Vec, - disallowed: DefIdMap, + disallowed: DefIdMap<(&'static str, Option<&'static str>)>, seen: FxHashSet, - // Track the most recently seen node that can have a `derive` attribute. // Needed to use the correct lint level. derive_src: Option, } impl DisallowedMacros { - pub fn new(conf_disallowed: Vec) -> Self { + pub fn new(tcx: TyCtxt<'_>, conf: &'static Conf) -> Self { Self { - conf_disallowed, - disallowed: DefIdMap::default(), + disallowed: create_disallowed_map(tcx, &conf.disallowed_macros), seen: FxHashSet::default(), derive_src: None, } } fn check(&mut self, cx: &LateContext<'_>, span: Span, derive_src: Option) { - if self.conf_disallowed.is_empty() { + if self.disallowed.is_empty() { return; } @@ -86,11 +85,10 @@ impl DisallowedMacros { return; } - if let Some(&index) = self.disallowed.get(&mac.def_id) { - let conf = &self.conf_disallowed[index]; - let msg = format!("use of a disallowed macro `{}`", conf.path()); + if let Some(&(path, reason)) = self.disallowed.get(&mac.def_id) { + let msg = format!("use of a disallowed macro `{path}`"); let add_note = |diag: &mut Diag<'_, _>| { - if let Some(reason) = conf.reason() { + if let Some(reason) = reason { diag.note(reason); } }; @@ -116,15 +114,6 @@ impl DisallowedMacros { impl_lint_pass!(DisallowedMacros => [DISALLOWED_MACROS]); impl LateLintPass<'_> for DisallowedMacros { - fn check_crate(&mut self, cx: &LateContext<'_>) { - for (index, conf) in self.conf_disallowed.iter().enumerate() { - let segs: Vec<_> = conf.path().split("::").collect(); - for id in clippy_utils::def_path_def_ids(cx, &segs) { - self.disallowed.insert(id, index); - } - } - } - fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { self.check(cx, expr.span, None); // `$t + $t` can have the context of $t, check also the span of the binary operator diff --git a/clippy_lints/src/disallowed_methods.rs b/clippy_lints/src/disallowed_methods.rs index 38fe687f7ccfe..5a01d76a2a621 100644 --- a/clippy_lints/src/disallowed_methods.rs +++ b/clippy_lints/src/disallowed_methods.rs @@ -1,9 +1,11 @@ -use clippy_config::types::DisallowedPath; +use clippy_config::Conf; +use clippy_utils::create_disallowed_map; use clippy_utils::diagnostics::span_lint_and_then; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::DefIdMap; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::TyCtxt; use rustc_session::impl_lint_pass; declare_clippy_lint! { @@ -55,17 +57,14 @@ declare_clippy_lint! { "use of a disallowed method call" } -#[derive(Clone, Debug)] pub struct DisallowedMethods { - conf_disallowed: Vec, - disallowed: DefIdMap, + disallowed: DefIdMap<(&'static str, Option<&'static str>)>, } impl DisallowedMethods { - pub fn new(conf_disallowed: Vec) -> Self { + pub fn new(tcx: TyCtxt<'_>, conf: &'static Conf) -> Self { Self { - conf_disallowed, - disallowed: DefIdMap::default(), + disallowed: create_disallowed_map(tcx, &conf.disallowed_methods), } } } @@ -73,15 +72,6 @@ impl DisallowedMethods { impl_lint_pass!(DisallowedMethods => [DISALLOWED_METHODS]); impl<'tcx> LateLintPass<'tcx> for DisallowedMethods { - fn check_crate(&mut self, cx: &LateContext<'_>) { - for (index, conf) in self.conf_disallowed.iter().enumerate() { - let segs: Vec<_> = conf.path().split("::").collect(); - for id in clippy_utils::def_path_def_ids(cx, &segs) { - self.disallowed.insert(id, index); - } - } - } - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { let (id, span) = match &expr.kind { ExprKind::Path(path) @@ -95,14 +85,18 @@ impl<'tcx> LateLintPass<'tcx> for DisallowedMethods { }, _ => return, }; - if let Some(&index) = self.disallowed.get(&id) { - let conf = &self.conf_disallowed[index]; - let msg = format!("use of a disallowed method `{}`", conf.path()); - span_lint_and_then(cx, DISALLOWED_METHODS, span, msg, |diag| { - if let Some(reason) = conf.reason() { - diag.note(reason); - } - }); + if let Some(&(path, reason)) = self.disallowed.get(&id) { + span_lint_and_then( + cx, + DISALLOWED_METHODS, + span, + format!("use of a disallowed method `{path}`"), + |diag| { + if let Some(reason) = reason { + diag.note(reason); + } + }, + ); } } } diff --git a/clippy_lints/src/disallowed_names.rs b/clippy_lints/src/disallowed_names.rs index 58809604c373e..f55b0cf1c5034 100644 --- a/clippy_lints/src/disallowed_names.rs +++ b/clippy_lints/src/disallowed_names.rs @@ -1,9 +1,11 @@ +use clippy_config::Conf; use clippy_utils::diagnostics::span_lint; use clippy_utils::is_in_test; use rustc_data_structures::fx::FxHashSet; use rustc_hir::{Pat, PatKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; +use rustc_span::Symbol; declare_clippy_lint! { /// ### What it does @@ -24,15 +26,14 @@ declare_clippy_lint! { "usage of a disallowed/placeholder name" } -#[derive(Clone, Debug)] pub struct DisallowedNames { - disallow: FxHashSet, + disallow: FxHashSet, } impl DisallowedNames { - pub fn new(disallowed_names: &[String]) -> Self { + pub fn new(conf: &'static Conf) -> Self { Self { - disallow: disallowed_names.iter().cloned().collect(), + disallow: conf.disallowed_names.iter().map(|x| Symbol::intern(x)).collect(), } } } @@ -42,7 +43,7 @@ impl_lint_pass!(DisallowedNames => [DISALLOWED_NAMES]); impl<'tcx> LateLintPass<'tcx> for DisallowedNames { fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) { if let PatKind::Binding(.., ident, _) = pat.kind - && self.disallow.contains(&ident.name.to_string()) + && self.disallow.contains(&ident.name) && !is_in_test(cx.tcx, pat.hir_id) { span_lint( diff --git a/clippy_lints/src/disallowed_script_idents.rs b/clippy_lints/src/disallowed_script_idents.rs index 5ce11900adf8f..f79264e6b04a1 100644 --- a/clippy_lints/src/disallowed_script_idents.rs +++ b/clippy_lints/src/disallowed_script_idents.rs @@ -1,3 +1,4 @@ +use clippy_config::Conf; use clippy_utils::diagnostics::span_lint; use rustc_ast::ast; use rustc_data_structures::fx::FxHashSet; @@ -44,19 +45,20 @@ declare_clippy_lint! { "usage of non-allowed Unicode scripts" } -#[derive(Clone, Debug)] pub struct DisallowedScriptIdents { whitelist: FxHashSet +pub struct Bar; diff --git a/tests/rustdoc-ui/remap-path-prefix-lint.stderr b/tests/rustdoc-ui/remap-path-prefix-lint.stderr new file mode 100644 index 0000000000000..d7c1bb1965d35 --- /dev/null +++ b/tests/rustdoc-ui/remap-path-prefix-lint.stderr @@ -0,0 +1,14 @@ +error: unopened HTML tag `script` + --> remapped_path/remap-path-prefix-lint.rs:9:5 + | +LL | /// + | ^^^^^^^^^ + | +note: the lint level is defined here + --> remapped_path/remap-path-prefix-lint.rs:7:9 + | +LL | #![deny(rustdoc::invalid_html_tags)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + From 608b322f49183868879b29d0edf927951dd20f63 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Mon, 5 Aug 2024 14:19:32 -0400 Subject: [PATCH 551/786] rewrite staticlib-dylib-linkage to rmake --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - .../run-make/staticlib-dylib-linkage/Makefile | 21 ----------- .../run-make/staticlib-dylib-linkage/rmake.rs | 37 +++++++++++++++++++ 3 files changed, 37 insertions(+), 22 deletions(-) delete mode 100644 tests/run-make/staticlib-dylib-linkage/Makefile create mode 100644 tests/run-make/staticlib-dylib-linkage/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 38880e5e95fcf..6766c3f49de89 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -31,7 +31,6 @@ run-make/reproducible-build/Makefile run-make/rlib-format-packed-bundled-libs/Makefile run-make/simd-ffi/Makefile run-make/split-debuginfo/Makefile -run-make/staticlib-dylib-linkage/Makefile run-make/symbol-mangling-hashed/Makefile run-make/sysroot-crates-are-unstable/Makefile run-make/thumb-none-cortex-m/Makefile diff --git a/tests/run-make/staticlib-dylib-linkage/Makefile b/tests/run-make/staticlib-dylib-linkage/Makefile deleted file mode 100644 index a1e86a7ce4b65..0000000000000 --- a/tests/run-make/staticlib-dylib-linkage/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -include ../tools.mk - -# ignore-cross-compile -# ignore-msvc FIXME(bjorn3) can't figure out how to link with the MSVC toolchain -# ignore-wasm wasm doesn't support dynamic libraries - -all: - $(RUSTC) -C prefer-dynamic bar.rs - $(RUSTC) foo.rs --crate-type staticlib --print native-static-libs \ - -Z staticlib-allow-rdylib-deps 2>&1 | grep 'note: native-static-libs: ' \ - | sed 's/note: native-static-libs: \(.*\)/\1/' > $(TMPDIR)/libs.txt - cat $(TMPDIR)/libs.txt - -ifdef IS_MSVC - $(CC) $(CFLAGS) /c foo.c /Fo:$(TMPDIR)/foo.o - $(RUSTC_LINKER) $(TMPDIR)/foo.o $(TMPDIR)/foo.lib $$(cat $(TMPDIR)/libs.txt) $(call OUT_EXE,foo) -else - $(CC) $(CFLAGS) foo.c -L $(TMPDIR) -lfoo $$(cat $(TMPDIR)/libs.txt) -o $(call RUN_BINFILE,foo) -endif - - $(call RUN,foo) diff --git a/tests/run-make/staticlib-dylib-linkage/rmake.rs b/tests/run-make/staticlib-dylib-linkage/rmake.rs new file mode 100644 index 0000000000000..415491bb8ee0a --- /dev/null +++ b/tests/run-make/staticlib-dylib-linkage/rmake.rs @@ -0,0 +1,37 @@ +// A basic smoke test to check that rustc supports linking to a rust dylib with +// --crate-type staticlib. bar is a dylib, on which foo is dependent - the native +// static lib search paths are collected and used to compile foo.c, the final executable +// which depends on both foo and bar. +// See https://github.com/rust-lang/rust/pull/106560 + +//@ ignore-cross-compile +// Reason: the compiled binary is executed. +//@ ignore-wasm +// Reason: WASM does not support dynamic libraries +//@ ignore-msvc +//FIXME(Oneirical): Getting this to work on MSVC requires passing libcmt.lib to CC, +// which is not trivial to do. +// Tracking issue: https://github.com/rust-lang/rust/issues/128602 +// Discussion: https://github.com/rust-lang/rust/pull/128407#discussion_r1702439172 + +use run_make_support::{cc, regex, run, rustc}; + +fn main() { + rustc().arg("-Cprefer-dynamic").input("bar.rs").run(); + let libs = rustc() + .input("foo.rs") + .crate_type("staticlib") + .print("native-static-libs") + .arg("-Zstaticlib-allow-rdylib-deps") + .run() + .assert_stderr_contains("note: native-static-libs: ") + .stderr_utf8(); + let re = regex::Regex::new(r#"note: native-static-libs:\s*(.+)"#).unwrap(); + let libs = re.find(&libs).unwrap().as_str().trim(); + // remove the note + let (_, library_search_paths) = libs.split_once("note: native-static-libs: ").unwrap(); + // divide the command-line arguments in a vec + let library_search_paths = library_search_paths.split(' ').collect::>(); + cc().input("foo.c").arg("-lfoo").args(library_search_paths).out_exe("foo").run(); + run("foo"); +} From 342b807e1a344c01a10e5e591ad22cdc56911b39 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Thu, 25 Jul 2024 11:43:52 -0400 Subject: [PATCH 552/786] rewrite cross-lang-lto-upstream-rlibs to rmake --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - .../cross-lang-lto-upstream-rlibs/Makefile | 32 ---------- .../cross-lang-lto-upstream-rlibs/rmake.rs | 61 +++++++++++++++++++ 3 files changed, 61 insertions(+), 33 deletions(-) delete mode 100644 tests/run-make/cross-lang-lto-upstream-rlibs/Makefile create mode 100644 tests/run-make/cross-lang-lto-upstream-rlibs/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 a2cfdea712e7c..b248b96d8e173 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -1,6 +1,5 @@ run-make/branch-protection-check-IBT/Makefile run-make/cat-and-grep-sanity-check/Makefile -run-make/cross-lang-lto-upstream-rlibs/Makefile run-make/dep-info-doesnt-run-much/Makefile run-make/dep-info-spaces/Makefile run-make/dep-info/Makefile diff --git a/tests/run-make/cross-lang-lto-upstream-rlibs/Makefile b/tests/run-make/cross-lang-lto-upstream-rlibs/Makefile deleted file mode 100644 index 6f1caa31a8061..0000000000000 --- a/tests/run-make/cross-lang-lto-upstream-rlibs/Makefile +++ /dev/null @@ -1,32 +0,0 @@ -include ../tools.mk - -# ignore windows due to libLLVM being present in PATH and the PATH and library path being the same -# (so fixing it is harder). See #57765 for context -ifndef IS_WINDOWS - -# This test makes sure that we don't loose upstream object files when compiling -# staticlibs with -C linker-plugin-lto - -all: staticlib.rs upstream.rs - $(RUSTC) upstream.rs -C linker-plugin-lto -Ccodegen-units=1 - - # Check No LTO - $(RUSTC) staticlib.rs -C linker-plugin-lto -Ccodegen-units=1 -L. -o $(TMPDIR)/staticlib.a - (cd $(TMPDIR); "$(LLVM_BIN_DIR)"/llvm-ar x ./staticlib.a) - # Make sure the upstream object file was included - ls $(TMPDIR)/upstream.*.rcgu.o - - # Cleanup - rm $(TMPDIR)/* - - # Check ThinLTO - $(RUSTC) upstream.rs -C linker-plugin-lto -Ccodegen-units=1 -Clto=thin - $(RUSTC) staticlib.rs -C linker-plugin-lto -Ccodegen-units=1 -Clto=thin -L. -o $(TMPDIR)/staticlib.a - (cd $(TMPDIR); "$(LLVM_BIN_DIR)"/llvm-ar x ./staticlib.a) - ls $(TMPDIR)/upstream.*.rcgu.o - -else - -all: - -endif diff --git a/tests/run-make/cross-lang-lto-upstream-rlibs/rmake.rs b/tests/run-make/cross-lang-lto-upstream-rlibs/rmake.rs new file mode 100644 index 0000000000000..964be01bc051a --- /dev/null +++ b/tests/run-make/cross-lang-lto-upstream-rlibs/rmake.rs @@ -0,0 +1,61 @@ +// When using the flag -C linker-plugin-lto, static libraries could lose their upstream object +// files during compilation. This bug was fixed in #53031, and this test compiles a staticlib +// dependent on upstream, checking that the upstream object file still exists after no LTO and +// thin LTO. +// See https://github.com/rust-lang/rust/pull/53031 + +// ignore windows due to libLLVM being present in PATH and the PATH and library path being the same +// (so fixing it is harder). See #57765 for context +//FIXME(Oneirical): ignore-windows + +use run_make_support::{ + cwd, has_extension, has_prefix, has_suffix, llvm_ar, rfs, rustc, shallow_find_files, + static_lib_name, +}; + +fn main() { + // The test starts with no LTO enabled. + rustc().input("upstream.rs").arg("-Clinker-plugin-lto").codegen_units(1).run(); + rustc() + .input("staticlib.rs") + .arg("-Clinker-plugin-lto") + .codegen_units(1) + .output(static_lib_name("staticlib")) + .run(); + llvm_ar().arg("x").arg(static_lib_name("staticlib")).run(); + // Ensure the upstream object file was included. + assert_eq!( + shallow_find_files(cwd(), |path| { + has_prefix(path, "upstream.") && has_suffix(path, ".rcgu.o") + }) + .len(), + 1 + ); + // Remove all output files that are not source Rust code for cleanup. + for file in shallow_find_files(cwd(), |path| !has_extension(path, "rs")) { + rfs::remove_file(file) + } + + // Check it again, with Thin LTO. + rustc() + .input("upstream.rs") + .arg("-Clinker-plugin-lto") + .codegen_units(1) + .arg("-Clto=thin") + .run(); + rustc() + .input("staticlib.rs") + .arg("-Clinker-plugin-lto") + .codegen_units(1) + .arg("-Clto=thin") + .output(static_lib_name("staticlib")) + .run(); + llvm_ar().arg("x").arg(static_lib_name("staticlib")).run(); + assert_eq!( + shallow_find_files(cwd(), |path| { + has_prefix(path, "upstream.") && has_suffix(path, ".rcgu.o") + }) + .len(), + 1 + ); +} From fe6feb8c6e55667816dde1ba6fc658a48b77f134 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Thu, 25 Jul 2024 13:07:26 -0400 Subject: [PATCH 553/786] rewrite long-linker-command-lines to rmake --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - .../long-linker-command-lines/Makefile | 8 -------- .../run-make/long-linker-command-lines/foo.rs | 16 ++-------------- .../long-linker-command-lines/rmake.rs | 19 +++++++++++++++++++ 4 files changed, 21 insertions(+), 23 deletions(-) delete mode 100644 tests/run-make/long-linker-command-lines/Makefile create mode 100644 tests/run-make/long-linker-command-lines/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 b248b96d8e173..a67474d998fe6 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -13,7 +13,6 @@ run-make/libtest-json/Makefile run-make/libtest-junit/Makefile run-make/libtest-thread-limit/Makefile run-make/long-linker-command-lines-cmd-exe/Makefile -run-make/long-linker-command-lines/Makefile run-make/macos-deployment-target/Makefile run-make/min-global-align/Makefile run-make/native-link-modifier-bundle/Makefile diff --git a/tests/run-make/long-linker-command-lines/Makefile b/tests/run-make/long-linker-command-lines/Makefile deleted file mode 100644 index b573038e344aa..0000000000000 --- a/tests/run-make/long-linker-command-lines/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -export LD_LIBRARY_PATH := $(HOST_RPATH_DIR) - -all: - $(RUSTC) foo.rs -g -O - RUSTC="$(RUSTC_ORIGINAL)" $(call RUN,foo) diff --git a/tests/run-make/long-linker-command-lines/foo.rs b/tests/run-make/long-linker-command-lines/foo.rs index 9d4a701ad8769..4f0ff30e3c073 100644 --- a/tests/run-make/long-linker-command-lines/foo.rs +++ b/tests/run-make/long-linker-command-lines/foo.rs @@ -1,12 +1,3 @@ -// This is a test which attempts to blow out the system limit with how many -// arguments can be passed to a process. This'll successively call rustc with -// larger and larger argument lists in an attempt to find one that's way too -// big for the system at hand. This file itself is then used as a "linker" to -// detect when the process creation succeeds. -// -// Eventually we should see an argument that looks like `@` as we switch from -// passing literal arguments to passing everything in the file. - use std::collections::HashSet; use std::env; use std::fs::{self, File}; @@ -43,8 +34,7 @@ fn read_linker_args(path: &Path) -> String { } fn main() { - let tmpdir = PathBuf::from(env::var_os("TMPDIR").unwrap()); - let ok = tmpdir.join("ok"); + let ok = PathBuf::from("ok"); if env::var("YOU_ARE_A_LINKER").is_ok() { if let Some(file) = env::args_os().find(|a| a.to_string_lossy().contains("@")) { let file = file.to_str().expect("non-utf8 file argument"); @@ -57,7 +47,7 @@ fn main() { let me_as_linker = format!("linker={}", env::current_exe().unwrap().display()); for i in (1..).map(|i| i * 100) { println!("attempt: {}", i); - let file = tmpdir.join("bar.rs"); + let file = PathBuf::from("bar.rs"); let mut expected_libs = write_test_case(&file, i); drop(fs::remove_file(&ok)); @@ -65,8 +55,6 @@ fn main() { .arg(&file) .arg("-C") .arg(&me_as_linker) - .arg("--out-dir") - .arg(&tmpdir) .env("YOU_ARE_A_LINKER", "1") .output() .unwrap(); diff --git a/tests/run-make/long-linker-command-lines/rmake.rs b/tests/run-make/long-linker-command-lines/rmake.rs new file mode 100644 index 0000000000000..e832d7f03e27e --- /dev/null +++ b/tests/run-make/long-linker-command-lines/rmake.rs @@ -0,0 +1,19 @@ +// This is a test which attempts to blow out the system limit with how many +// arguments can be passed to a process. This'll successively call rustc with +// larger and larger argument lists in an attempt to find one that's way too +// big for the system at hand. This file itself is then used as a "linker" to +// detect when the process creation succeeds. +// +// Eventually we should see an argument that looks like `@` as we switch from +// passing literal arguments to passing everything in the file. +// See https://github.com/rust-lang/rust/issues/41190 + +//@ ignore-cross-compile +// Reason: the compiled binary is executed + +use run_make_support::{run, rustc}; + +fn main() { + rustc().input("foo.rs").arg("-g").opt().run(); + run("foo"); +} From fe4cd9aa8debdf202ca869b32958b2dfc38f6f92 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Thu, 25 Jul 2024 13:11:36 -0400 Subject: [PATCH 554/786] rewrite long-linker-command-lines-cmd-exe to rmake --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - .../cross-lang-lto-upstream-rlibs/rmake.rs | 8 ++---- .../Makefile | 7 ----- .../long-linker-command-lines-cmd-exe/foo.rs | 26 +++---------------- .../rmake.rs | 26 +++++++++++++++++++ .../run-make/long-linker-command-lines/foo.rs | 2 +- 6 files changed, 32 insertions(+), 38 deletions(-) delete mode 100644 tests/run-make/long-linker-command-lines-cmd-exe/Makefile create mode 100644 tests/run-make/long-linker-command-lines-cmd-exe/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 a67474d998fe6..202113658a84e 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -12,7 +12,6 @@ run-make/libs-through-symlinks/Makefile run-make/libtest-json/Makefile run-make/libtest-junit/Makefile run-make/libtest-thread-limit/Makefile -run-make/long-linker-command-lines-cmd-exe/Makefile run-make/macos-deployment-target/Makefile run-make/min-global-align/Makefile run-make/native-link-modifier-bundle/Makefile diff --git a/tests/run-make/cross-lang-lto-upstream-rlibs/rmake.rs b/tests/run-make/cross-lang-lto-upstream-rlibs/rmake.rs index 964be01bc051a..f0b8fa75bee3e 100644 --- a/tests/run-make/cross-lang-lto-upstream-rlibs/rmake.rs +++ b/tests/run-make/cross-lang-lto-upstream-rlibs/rmake.rs @@ -4,10 +4,6 @@ // thin LTO. // See https://github.com/rust-lang/rust/pull/53031 -// ignore windows due to libLLVM being present in PATH and the PATH and library path being the same -// (so fixing it is harder). See #57765 for context -//FIXME(Oneirical): ignore-windows - use run_make_support::{ cwd, has_extension, has_prefix, has_suffix, llvm_ar, rfs, rustc, shallow_find_files, static_lib_name, @@ -22,7 +18,7 @@ fn main() { .codegen_units(1) .output(static_lib_name("staticlib")) .run(); - llvm_ar().arg("x").arg(static_lib_name("staticlib")).run(); + llvm_ar().extract().arg(static_lib_name("staticlib")).run(); // Ensure the upstream object file was included. assert_eq!( shallow_find_files(cwd(), |path| { @@ -50,7 +46,7 @@ fn main() { .arg("-Clto=thin") .output(static_lib_name("staticlib")) .run(); - llvm_ar().arg("x").arg(static_lib_name("staticlib")).run(); + llvm_ar().extract().arg(static_lib_name("staticlib")).run(); assert_eq!( shallow_find_files(cwd(), |path| { has_prefix(path, "upstream.") && has_suffix(path, ".rcgu.o") diff --git a/tests/run-make/long-linker-command-lines-cmd-exe/Makefile b/tests/run-make/long-linker-command-lines-cmd-exe/Makefile deleted file mode 100644 index e43aab7f8e0fd..0000000000000 --- a/tests/run-make/long-linker-command-lines-cmd-exe/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -all: - $(RUSTC) foo.rs -g - cp foo.bat $(TMPDIR)/ - OUT_DIR="$(TMPDIR)" RUSTC="$(RUSTC_ORIGINAL)" $(call RUN,foo) 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 1d5202dcdb493..a28cc7909fefb 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 @@ -1,16 +1,3 @@ -// Like the `long-linker-command-lines` test this test attempts to blow -// a command line limit for running the linker. Unlike that test, however, -// this test is testing `cmd.exe` specifically rather than the OS. -// -// Unfortunately `cmd.exe` has a 8192 limit which is relatively small -// in the grand scheme of things and anyone sripting rustc's linker -// is probably using a `*.bat` script and is likely to hit this limit. -// -// This test uses a `foo.bat` script as the linker which just simply -// delegates back to this program. The compiler should use a lower -// limit for arguments before passing everything via `@`, which -// means that everything should still succeed here. - use std::env; use std::fs::{self, File}; use std::io::{BufWriter, Read, Write}; @@ -18,13 +5,8 @@ use std::path::PathBuf; use std::process::Command; fn main() { - if !cfg!(windows) { - return; - } - - let tmpdir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); - let ok = tmpdir.join("ok"); - let not_ok = tmpdir.join("not_ok"); + let ok = PathBuf::from("ok"); + let not_ok = PathBuf::from("not_ok"); if env::var("YOU_ARE_A_LINKER").is_ok() { match env::args_os().find(|a| a.to_string_lossy().contains("@")) { Some(file) => { @@ -45,7 +27,7 @@ fn main() { for i in (1..).map(|i| i * 10) { println!("attempt: {}", i); - let file = tmpdir.join("bar.rs"); + let file = PathBuf::from("bar.rs"); let mut f = BufWriter::new(File::create(&file).unwrap()); let mut lib_name = String::new(); for _ in 0..i { @@ -63,8 +45,6 @@ fn main() { .arg(&file) .arg("-C") .arg(&bat_linker) - .arg("--out-dir") - .arg(&tmpdir) .env("YOU_ARE_A_LINKER", "1") .env("MY_LINKER", &me) .status() diff --git a/tests/run-make/long-linker-command-lines-cmd-exe/rmake.rs b/tests/run-make/long-linker-command-lines-cmd-exe/rmake.rs new file mode 100644 index 0000000000000..60ed2c5bcd203 --- /dev/null +++ b/tests/run-make/long-linker-command-lines-cmd-exe/rmake.rs @@ -0,0 +1,26 @@ +// Like the `long-linker-command-lines` test this test attempts to blow +// a command line limit for running the linker. Unlike that test, however, +// this test is testing `cmd.exe` specifically rather than the OS. +// +// Unfortunately, the maximum length of the string that you can use at the +// command prompt (`cmd.exe`) is 8191 characters. +// Anyone scripting rustc's linker +// is probably using a `*.bat` script and is likely to hit this limit. +// +// This test uses a `foo.bat` script as the linker which just simply +// delegates back to this program. The compiler should use a lower +// limit for arguments before passing everything via `@`, which +// means that everything should still succeed here. +// See https://github.com/rust-lang/rust/pull/47507 + +//@ ignore-cross-compile +// Reason: the compiled binary is executed +//@ only-windows +// Reason: this test is specific to Windows executables + +use run_make_support::{run, rustc}; + +fn main() { + rustc().input("foo.rs").arg("-g").run(); + run("foo"); +} diff --git a/tests/run-make/long-linker-command-lines/foo.rs b/tests/run-make/long-linker-command-lines/foo.rs index 4f0ff30e3c073..5b30c06fac9e0 100644 --- a/tests/run-make/long-linker-command-lines/foo.rs +++ b/tests/run-make/long-linker-command-lines/foo.rs @@ -43,7 +43,7 @@ fn main() { return; } - let rustc = env::var_os("RUSTC").unwrap_or("rustc".into()); + let rustc = env::var_os("RUSTC").unwrap(); let me_as_linker = format!("linker={}", env::current_exe().unwrap().display()); for i in (1..).map(|i| i * 100) { println!("attempt: {}", i); From cc96efd7e30c92ff5135fbda2273ef86f4be6937 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 6 Aug 2024 11:54:45 -0400 Subject: [PATCH 555/786] Stop unnecessarily taking GenericPredicates by &self --- compiler/rustc_middle/src/ty/generics.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 39c306a720f95..8cb8e9af11cf9 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -376,7 +376,7 @@ pub struct GenericPredicates<'tcx> { impl<'tcx> GenericPredicates<'tcx> { pub fn instantiate( - &self, + self, tcx: TyCtxt<'tcx>, args: GenericArgsRef<'tcx>, ) -> InstantiatedPredicates<'tcx> { @@ -386,20 +386,20 @@ impl<'tcx> GenericPredicates<'tcx> { } pub fn instantiate_own( - &self, + self, tcx: TyCtxt<'tcx>, args: GenericArgsRef<'tcx>, ) -> impl Iterator, Span)> + DoubleEndedIterator + ExactSizeIterator { EarlyBinder::bind(self.predicates).iter_instantiated_copied(tcx, args) } - pub fn instantiate_own_identity(&self) -> impl Iterator, Span)> { + pub fn instantiate_own_identity(self) -> impl Iterator, Span)> { EarlyBinder::bind(self.predicates).iter_identity_copied() } #[instrument(level = "debug", skip(self, tcx))] fn instantiate_into( - &self, + self, tcx: TyCtxt<'tcx>, instantiated: &mut InstantiatedPredicates<'tcx>, args: GenericArgsRef<'tcx>, @@ -413,14 +413,14 @@ impl<'tcx> GenericPredicates<'tcx> { instantiated.spans.extend(self.predicates.iter().map(|(_, sp)| *sp)); } - pub fn instantiate_identity(&self, tcx: TyCtxt<'tcx>) -> InstantiatedPredicates<'tcx> { + pub fn instantiate_identity(self, tcx: TyCtxt<'tcx>) -> InstantiatedPredicates<'tcx> { let mut instantiated = InstantiatedPredicates::empty(); self.instantiate_identity_into(tcx, &mut instantiated); instantiated } fn instantiate_identity_into( - &self, + self, tcx: TyCtxt<'tcx>, instantiated: &mut InstantiatedPredicates<'tcx>, ) { From 5cab8ae4a4a033acb25d629871deb24db19b638b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 6 Aug 2024 19:02:01 +0200 Subject: [PATCH 556/786] miri: make vtable addresses not globally unique --- .../rustc_const_eval/src/interpret/machine.rs | 18 ++- .../rustc_const_eval/src/interpret/memory.rs | 5 +- .../rustc_const_eval/src/interpret/place.rs | 3 +- .../rustc_const_eval/src/interpret/traits.rs | 4 +- .../rustc_middle/src/mir/interpret/mod.rs | 145 ++++++------------ compiler/rustc_middle/src/ty/context.rs | 4 +- compiler/rustc_middle/src/ty/vtable.rs | 11 +- .../src/build/expr/as_constant.rs | 6 +- src/tools/miri/src/lib.rs | 1 + src/tools/miri/src/machine.rs | 47 +++++- src/tools/miri/tests/pass/dyn-traits.rs | 10 ++ .../miri/tests/pass/function_pointers.rs | 3 +- src/tools/miri/tests/pass/rc.rs | 3 +- 13 files changed, 148 insertions(+), 112 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index bdce8253b2e76..1aa0d6af9ec21 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -19,7 +19,7 @@ use rustc_target::spec::abi::Abi as CallAbi; use super::{ throw_unsup, throw_unsup_format, AllocBytes, AllocId, AllocKind, AllocRange, Allocation, ConstAllocation, CtfeProvenance, FnArg, Frame, ImmTy, InterpCx, InterpResult, MPlaceTy, - MemoryKind, Misalignment, OpTy, PlaceTy, Pointer, Provenance, + MemoryKind, Misalignment, OpTy, PlaceTy, Pointer, Provenance, CTFE_ALLOC_SALT, }; /// Data returned by [`Machine::after_stack_pop`], and consumed by @@ -575,6 +575,14 @@ pub trait Machine<'tcx>: Sized { { eval(ecx, val, span, layout) } + + /// Returns the salt to be used for a deduplicated global alloation. + /// If the allocation is for a function, the instance is provided as well + /// (this lets Miri ensure unique addresses for some functions). + fn get_global_alloc_salt( + ecx: &InterpCx<'tcx, Self>, + instance: Option>, + ) -> usize; } /// A lot of the flexibility above is just needed for `Miri`, but all "compile-time" machines @@ -677,4 +685,12 @@ pub macro compile_time_machine(<$tcx: lifetime>) { let (prov, offset) = ptr.into_parts(); Some((prov.alloc_id(), offset, prov.immutable())) } + + #[inline(always)] + fn get_global_alloc_salt( + _ecx: &InterpCx<$tcx, Self>, + _instance: Option>, + ) -> usize { + CTFE_ALLOC_SALT + } } diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 2e5d0ae773654..910aec9b8e1de 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -195,7 +195,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { pub fn fn_ptr(&mut self, fn_val: FnVal<'tcx, M::ExtraFnVal>) -> Pointer { let id = match fn_val { - FnVal::Instance(instance) => self.tcx.reserve_and_set_fn_alloc(instance), + FnVal::Instance(instance) => { + let salt = M::get_global_alloc_salt(self, Some(instance)); + self.tcx.reserve_and_set_fn_alloc(instance, salt) + } FnVal::Other(extra) => { // FIXME(RalfJung): Should we have a cache here? let id = self.tcx.reserve_alloc_id(); diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 470a62026b943..2afdd02c88035 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -1008,7 +1008,8 @@ where // Use cache for immutable strings. let ptr = if mutbl.is_not() { // Use dedup'd allocation function. - let id = tcx.allocate_bytes_dedup(str.as_bytes()); + let salt = M::get_global_alloc_salt(self, None); + let id = tcx.allocate_bytes_dedup(str.as_bytes(), salt); // Turn untagged "global" pointers (obtained via `tcx`) into the machine pointer to the allocation. M::adjust_alloc_root_pointer(&self, Pointer::from(id), Some(kind))? diff --git a/compiler/rustc_const_eval/src/interpret/traits.rs b/compiler/rustc_const_eval/src/interpret/traits.rs index fb50661b8263d..cd4faf06655fe 100644 --- a/compiler/rustc_const_eval/src/interpret/traits.rs +++ b/compiler/rustc_const_eval/src/interpret/traits.rs @@ -28,7 +28,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ensure_monomorphic_enough(*self.tcx, ty)?; ensure_monomorphic_enough(*self.tcx, poly_trait_ref)?; - let vtable_symbolic_allocation = self.tcx.reserve_and_set_vtable_alloc(ty, poly_trait_ref); + let salt = M::get_global_alloc_salt(self, None); + let vtable_symbolic_allocation = + self.tcx.reserve_and_set_vtable_alloc(ty, poly_trait_ref, salt); let vtable_ptr = self.global_root_pointer(Pointer::from(vtable_symbolic_allocation))?; Ok(vtable_ptr.into()) } diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index 1851a61d7533c..91e71c12cae45 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -13,7 +13,6 @@ use std::num::NonZero; use std::{fmt, io}; use rustc_ast::LitKind; -use rustc_attr::InlineAttr; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lock; use rustc_errors::ErrorGuaranteed; @@ -46,7 +45,7 @@ pub use self::pointer::{CtfeProvenance, Pointer, PointerArithmetic, Provenance}; pub use self::value::Scalar; use crate::mir; use crate::ty::codec::{TyDecoder, TyEncoder}; -use crate::ty::{self, GenericArgKind, Instance, Ty, TyCtxt}; +use crate::ty::{self, Instance, Ty, TyCtxt}; /// Uniquely identifies one of the following: /// - A constant @@ -126,11 +125,10 @@ pub fn specialized_encode_alloc_id<'tcx, E: TyEncoder>>( AllocDiscriminant::Alloc.encode(encoder); alloc.encode(encoder); } - GlobalAlloc::Function { instance, unique } => { + GlobalAlloc::Function { instance } => { trace!("encoding {:?} with {:#?}", alloc_id, instance); AllocDiscriminant::Fn.encode(encoder); instance.encode(encoder); - unique.encode(encoder); } GlobalAlloc::VTable(ty, poly_trait_ref) => { trace!("encoding {:?} with {ty:#?}, {poly_trait_ref:#?}", alloc_id); @@ -219,38 +217,32 @@ impl<'s> AllocDecodingSession<'s> { } // Now decode the actual data. - let alloc_id = decoder.with_position(pos, |decoder| { - match alloc_kind { - AllocDiscriminant::Alloc => { - trace!("creating memory alloc ID"); - let alloc = as Decodable<_>>::decode(decoder); - trace!("decoded alloc {:?}", alloc); - decoder.interner().reserve_and_set_memory_alloc(alloc) - } - AllocDiscriminant::Fn => { - trace!("creating fn alloc ID"); - let instance = ty::Instance::decode(decoder); - trace!("decoded fn alloc instance: {:?}", instance); - let unique = bool::decode(decoder); - // Here we cannot call `reserve_and_set_fn_alloc` as that would use a query, which - // is not possible in this context. That's why the allocation stores - // whether it is unique or not. - decoder.interner().reserve_and_set_fn_alloc_internal(instance, unique) - } - AllocDiscriminant::VTable => { - trace!("creating vtable alloc ID"); - let ty = as Decodable>::decode(decoder); - let poly_trait_ref = - > as Decodable>::decode(decoder); - trace!("decoded vtable alloc instance: {ty:?}, {poly_trait_ref:?}"); - decoder.interner().reserve_and_set_vtable_alloc(ty, poly_trait_ref) - } - AllocDiscriminant::Static => { - trace!("creating extern static alloc ID"); - let did = >::decode(decoder); - trace!("decoded static def-ID: {:?}", did); - decoder.interner().reserve_and_set_static_alloc(did) - } + let alloc_id = decoder.with_position(pos, |decoder| match alloc_kind { + AllocDiscriminant::Alloc => { + trace!("creating memory alloc ID"); + let alloc = as Decodable<_>>::decode(decoder); + trace!("decoded alloc {:?}", alloc); + decoder.interner().reserve_and_set_memory_alloc(alloc) + } + AllocDiscriminant::Fn => { + trace!("creating fn alloc ID"); + let instance = ty::Instance::decode(decoder); + trace!("decoded fn alloc instance: {:?}", instance); + decoder.interner().reserve_and_set_fn_alloc(instance, CTFE_ALLOC_SALT) + } + AllocDiscriminant::VTable => { + trace!("creating vtable alloc ID"); + let ty = as Decodable>::decode(decoder); + let poly_trait_ref = + > as Decodable>::decode(decoder); + trace!("decoded vtable alloc instance: {ty:?}, {poly_trait_ref:?}"); + decoder.interner().reserve_and_set_vtable_alloc(ty, poly_trait_ref, CTFE_ALLOC_SALT) + } + AllocDiscriminant::Static => { + trace!("creating extern static alloc ID"); + let did = >::decode(decoder); + trace!("decoded static def-ID: {:?}", did); + decoder.interner().reserve_and_set_static_alloc(did) } }); @@ -265,12 +257,7 @@ impl<'s> AllocDecodingSession<'s> { #[derive(Debug, Clone, Eq, PartialEq, Hash, TyDecodable, TyEncodable, HashStable)] pub enum GlobalAlloc<'tcx> { /// The alloc ID is used as a function pointer. - Function { - instance: Instance<'tcx>, - /// Stores whether this instance is unique, i.e. all pointers to this function use the same - /// alloc ID. - unique: bool, - }, + Function { instance: Instance<'tcx> }, /// This alloc ID points to a symbolic (not-reified) vtable. VTable(Ty<'tcx>, Option>), /// The alloc ID points to a "lazy" static variable that did not get computed (yet). @@ -323,14 +310,17 @@ impl<'tcx> GlobalAlloc<'tcx> { } } +pub const CTFE_ALLOC_SALT: usize = 0; + pub(crate) struct AllocMap<'tcx> { /// Maps `AllocId`s to their corresponding allocations. alloc_map: FxHashMap>, - /// Used to ensure that statics and functions only get one associated `AllocId`. - // - // FIXME: Should we just have two separate dedup maps for statics and functions each? - dedup: FxHashMap, AllocId>, + /// Used to deduplicate global allocations: functions, vtables, string literals, ... + /// + /// The `usize` is a "salt" used by Miri to make deduplication imperfect, thus better emulating + /// the actual guarantees. + dedup: FxHashMap<(GlobalAlloc<'tcx>, usize), AllocId>, /// The `AllocId` to assign to the next requested ID. /// Always incremented; never gets smaller. @@ -368,74 +358,40 @@ impl<'tcx> TyCtxt<'tcx> { /// Reserves a new ID *if* this allocation has not been dedup-reserved before. /// Should not be used for mutable memory. - fn reserve_and_set_dedup(self, alloc: GlobalAlloc<'tcx>) -> AllocId { + fn reserve_and_set_dedup(self, alloc: GlobalAlloc<'tcx>, salt: usize) -> AllocId { let mut alloc_map = self.alloc_map.lock(); if let GlobalAlloc::Memory(mem) = alloc { if mem.inner().mutability.is_mut() { bug!("trying to dedup-reserve mutable memory"); } } - if let Some(&alloc_id) = alloc_map.dedup.get(&alloc) { + let alloc_salt = (alloc, salt); + if let Some(&alloc_id) = alloc_map.dedup.get(&alloc_salt) { return alloc_id; } let id = alloc_map.reserve(); - debug!("creating alloc {alloc:?} with id {id:?}"); - alloc_map.alloc_map.insert(id, alloc.clone()); - alloc_map.dedup.insert(alloc, id); + debug!("creating alloc {:?} with id {id:?}", alloc_salt.0); + alloc_map.alloc_map.insert(id, alloc_salt.0.clone()); + alloc_map.dedup.insert(alloc_salt, id); id } /// Generates an `AllocId` for a memory allocation. If the exact same memory has been /// allocated before, this will return the same `AllocId`. - pub fn reserve_and_set_memory_dedup(self, mem: ConstAllocation<'tcx>) -> AllocId { - self.reserve_and_set_dedup(GlobalAlloc::Memory(mem)) + pub fn reserve_and_set_memory_dedup(self, mem: ConstAllocation<'tcx>, salt: usize) -> AllocId { + self.reserve_and_set_dedup(GlobalAlloc::Memory(mem), salt) } /// Generates an `AllocId` for a static or return a cached one in case this function has been /// called on the same static before. pub fn reserve_and_set_static_alloc(self, static_id: DefId) -> AllocId { - self.reserve_and_set_dedup(GlobalAlloc::Static(static_id)) - } - - /// Generates an `AllocId` for a function. The caller must already have decided whether this - /// function obtains a unique AllocId or gets de-duplicated via the cache. - fn reserve_and_set_fn_alloc_internal(self, instance: Instance<'tcx>, unique: bool) -> AllocId { - let alloc = GlobalAlloc::Function { instance, unique }; - if unique { - // Deduplicate. - self.reserve_and_set_dedup(alloc) - } else { - // Get a fresh ID. - let mut alloc_map = self.alloc_map.lock(); - let id = alloc_map.reserve(); - alloc_map.alloc_map.insert(id, alloc); - id - } + let salt = 0; // Statics have a guaranteed unique address, no salt added. + self.reserve_and_set_dedup(GlobalAlloc::Static(static_id), salt) } - /// Generates an `AllocId` for a function. Depending on the function type, - /// this might get deduplicated or assigned a new ID each time. - pub fn reserve_and_set_fn_alloc(self, instance: Instance<'tcx>) -> AllocId { - // Functions cannot be identified by pointers, as asm-equal functions can get deduplicated - // by the linker (we set the "unnamed_addr" attribute for LLVM) and functions can be - // duplicated across crates. We thus generate a new `AllocId` for every mention of a - // function. This means that `main as fn() == main as fn()` is false, while `let x = main as - // fn(); x == x` is true. However, as a quality-of-life feature it can be useful to identify - // certain functions uniquely, e.g. for backtraces. So we identify whether codegen will - // actually emit duplicate functions. It does that when they have non-lifetime generics, or - // when they can be inlined. All other functions are given a unique address. - // This is not a stable guarantee! The `inline` attribute is a hint and cannot be relied - // upon for anything. But if we don't do this, backtraces look terrible. - let is_generic = instance - .args - .into_iter() - .any(|kind| !matches!(kind.unpack(), GenericArgKind::Lifetime(_))); - let can_be_inlined = match self.codegen_fn_attrs(instance.def_id()).inline { - InlineAttr::Never => false, - _ => true, - }; - let unique = !is_generic && !can_be_inlined; - self.reserve_and_set_fn_alloc_internal(instance, unique) + /// Generates an `AllocId` for a function. Will get deduplicated. + pub fn reserve_and_set_fn_alloc(self, instance: Instance<'tcx>, salt: usize) -> AllocId { + self.reserve_and_set_dedup(GlobalAlloc::Function { instance }, salt) } /// Generates an `AllocId` for a (symbolic, not-reified) vtable. Will get deduplicated. @@ -443,8 +399,9 @@ impl<'tcx> TyCtxt<'tcx> { self, ty: Ty<'tcx>, poly_trait_ref: Option>, + salt: usize, ) -> AllocId { - self.reserve_and_set_dedup(GlobalAlloc::VTable(ty, poly_trait_ref)) + self.reserve_and_set_dedup(GlobalAlloc::VTable(ty, poly_trait_ref), salt) } /// Interns the `Allocation` and return a new `AllocId`, even if there's already an identical diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 8f8fd09c9e4d9..07fed7b17ad33 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1438,11 +1438,11 @@ impl<'tcx> TyCtxt<'tcx> { /// Allocates a read-only byte or string literal for `mir::interpret`. /// Returns the same `AllocId` if called again with the same bytes. - pub fn allocate_bytes_dedup(self, bytes: &[u8]) -> interpret::AllocId { + pub fn allocate_bytes_dedup(self, bytes: &[u8], salt: usize) -> interpret::AllocId { // Create an allocation that just contains these bytes. let alloc = interpret::Allocation::from_bytes_byte_aligned_immutable(bytes); let alloc = self.mk_const_alloc(alloc); - self.reserve_and_set_memory_dedup(alloc) + self.reserve_and_set_memory_dedup(alloc, salt) } /// Returns a range of the start/end indices specified with the diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs index f38f27b84f0b9..951112dfe858e 100644 --- a/compiler/rustc_middle/src/ty/vtable.rs +++ b/compiler/rustc_middle/src/ty/vtable.rs @@ -3,7 +3,7 @@ use std::fmt; use rustc_ast::Mutability; use rustc_macros::HashStable; -use crate::mir::interpret::{alloc_range, AllocId, Allocation, Pointer, Scalar}; +use crate::mir::interpret::{alloc_range, AllocId, Allocation, Pointer, Scalar, CTFE_ALLOC_SALT}; use crate::ty::{self, Instance, PolyTraitRef, Ty, TyCtxt}; #[derive(Clone, Copy, PartialEq, HashStable)] @@ -73,6 +73,11 @@ pub(crate) fn vtable_min_entries<'tcx>( /// Retrieves an allocation that represents the contents of a vtable. /// Since this is a query, allocations are cached and not duplicated. +/// +/// This is an "internal" `AllocId` that should never be used as a value in the interpreted program. +/// The interpreter should use `AllocId` that refer to a `GlobalAlloc::VTable` instead. +/// (This is similar to statics, which also have a similar "internal" `AllocId` storing their +/// initial contents.) pub(super) fn vtable_allocation_provider<'tcx>( tcx: TyCtxt<'tcx>, key: (Ty<'tcx>, Option>), @@ -114,7 +119,7 @@ pub(super) fn vtable_allocation_provider<'tcx>( VtblEntry::MetadataDropInPlace => { if ty.needs_drop(tcx, ty::ParamEnv::reveal_all()) { let instance = ty::Instance::resolve_drop_in_place(tcx, ty); - let fn_alloc_id = tcx.reserve_and_set_fn_alloc(instance); + let fn_alloc_id = tcx.reserve_and_set_fn_alloc(instance, CTFE_ALLOC_SALT); let fn_ptr = Pointer::from(fn_alloc_id); Scalar::from_pointer(fn_ptr, &tcx) } else { @@ -127,7 +132,7 @@ pub(super) fn vtable_allocation_provider<'tcx>( VtblEntry::Method(instance) => { // Prepare the fn ptr we write into the vtable. let instance = instance.polymorphize(tcx); - let fn_alloc_id = tcx.reserve_and_set_fn_alloc(instance); + let fn_alloc_id = tcx.reserve_and_set_fn_alloc(instance, CTFE_ALLOC_SALT); let fn_ptr = Pointer::from(fn_alloc_id); Scalar::from_pointer(fn_ptr, &tcx) } 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 10cf545f1b79d..4430aab73a819 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs @@ -2,7 +2,9 @@ use rustc_ast as ast; use rustc_hir::LangItem; -use rustc_middle::mir::interpret::{Allocation, LitToConstError, LitToConstInput, Scalar}; +use rustc_middle::mir::interpret::{ + Allocation, LitToConstError, LitToConstInput, Scalar, CTFE_ALLOC_SALT, +}; use rustc_middle::mir::*; use rustc_middle::thir::*; use rustc_middle::ty::{ @@ -140,7 +142,7 @@ fn lit_to_mir_constant<'tcx>( ConstValue::Slice { data: allocation, meta: allocation.inner().size().bytes() } } (ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => { - let id = tcx.allocate_bytes_dedup(data); + let id = tcx.allocate_bytes_dedup(data, CTFE_ALLOC_SALT); ConstValue::Scalar(Scalar::from_pointer(id.into(), &tcx)) } (ast::LitKind::CStr(data, _), ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::CStr)) => diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 2b3ae6df5de8a..966d38508f612 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -56,6 +56,7 @@ extern crate either; extern crate tracing; // The rustc crates we need +extern crate rustc_attr; extern crate rustc_apfloat; extern crate rustc_ast; extern crate rustc_const_eval; diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 3e45a3a7e1a12..df4154bcb5892 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -11,6 +11,7 @@ use rand::rngs::StdRng; use rand::Rng; use rand::SeedableRng; +use rustc_attr::InlineAttr; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; #[allow(unused)] use rustc_data_structures::static_assert_size; @@ -47,10 +48,10 @@ pub const SIGRTMIN: i32 = 34; /// `SIGRTMAX` - `SIGRTMIN` >= 8 (which is the value of `_POSIX_RTSIG_MAX`) pub const SIGRTMAX: i32 = 42; -/// Each const has multiple addresses, but only this many. Since const allocations are never -/// deallocated, choosing a new [`AllocId`] and thus base address for each evaluation would -/// produce unbounded memory usage. -const ADDRS_PER_CONST: usize = 16; +/// Each anonymous global (constant, vtable, function pointer, ...) has multiple addresses, but only +/// this many. Since const allocations are never deallocated, choosing a new [`AllocId`] and thus +/// base address for each evaluation would produce unbounded memory usage. +const ADDRS_PER_ANON_GLOBAL: usize = 32; /// Extra data stored with each stack frame pub struct FrameExtra<'tcx> { @@ -1372,7 +1373,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { catch_unwind: None, timing, is_user_relevant: ecx.machine.is_user_relevant(&frame), - salt: ecx.machine.rng.borrow_mut().gen::() % ADDRS_PER_CONST, + salt: ecx.machine.rng.borrow_mut().gen::() % ADDRS_PER_ANON_GLOBAL, }; Ok(frame.with_extra(extra)) @@ -1518,4 +1519,40 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { Entry::Occupied(oe) => Ok(oe.get().clone()), } } + + fn get_global_alloc_salt( + ecx: &InterpCx<'tcx, Self>, + instance: Option>, + ) -> usize { + let unique = if let Some(instance) = instance { + // Functions cannot be identified by pointers, as asm-equal functions can get deduplicated + // by the linker (we set the "unnamed_addr" attribute for LLVM) and functions can be + // duplicated across crates. We thus generate a new `AllocId` for every mention of a + // function. This means that `main as fn() == main as fn()` is false, while `let x = main as + // fn(); x == x` is true. However, as a quality-of-life feature it can be useful to identify + // certain functions uniquely, e.g. for backtraces. So we identify whether codegen will + // actually emit duplicate functions. It does that when they have non-lifetime generics, or + // when they can be inlined. All other functions are given a unique address. + // This is not a stable guarantee! The `inline` attribute is a hint and cannot be relied + // upon for anything. But if we don't do this, backtraces look terrible. + let is_generic = instance + .args + .into_iter() + .any(|kind| !matches!(kind.unpack(), ty::GenericArgKind::Lifetime(_))); + let can_be_inlined = match ecx.tcx.codegen_fn_attrs(instance.def_id()).inline { + InlineAttr::Never => false, + _ => true, + }; + !is_generic && !can_be_inlined + } else { + // Non-functions are never unique. + false + }; + // Always use the same salt if the allocation is unique. + if unique { + CTFE_ALLOC_SALT + } else { + ecx.machine.rng.borrow_mut().gen::() % ADDRS_PER_ANON_GLOBAL + } + } } diff --git a/src/tools/miri/tests/pass/dyn-traits.rs b/src/tools/miri/tests/pass/dyn-traits.rs index 908d521a0d816..f6220120968f7 100644 --- a/src/tools/miri/tests/pass/dyn-traits.rs +++ b/src/tools/miri/tests/pass/dyn-traits.rs @@ -141,7 +141,17 @@ fn unsized_dyn_autoderef() { } */ +fn vtable_ptr_eq() { + use std::{fmt, ptr}; + + // We don't always get the same vtable when casting this to a wide pointer. + let x = &2; + let x_wide = x as &dyn fmt::Display; + assert!((0..256).any(|_| !ptr::eq(x as &dyn fmt::Display, x_wide))); +} + fn main() { ref_box_dyn(); box_box_trait(); + vtable_ptr_eq(); } diff --git a/src/tools/miri/tests/pass/function_pointers.rs b/src/tools/miri/tests/pass/function_pointers.rs index 2aa3ebf2dd0b4..a5c4bc5e0d95b 100644 --- a/src/tools/miri/tests/pass/function_pointers.rs +++ b/src/tools/miri/tests/pass/function_pointers.rs @@ -82,7 +82,8 @@ fn main() { assert!(return_fn_ptr(i) == i); assert!(return_fn_ptr(i) as unsafe fn() -> i32 == i as fn() -> i32 as unsafe fn() -> i32); // Miri gives different addresses to different reifications of a generic function. - assert!(return_fn_ptr(f) != f); + // at least if we try often enough. + assert!((0..256).any(|_| return_fn_ptr(f) != f)); // However, if we only turn `f` into a function pointer and use that pointer, // it is equal to itself. let f2 = f as fn() -> i32; diff --git a/src/tools/miri/tests/pass/rc.rs b/src/tools/miri/tests/pass/rc.rs index 6dd1b3aff9e72..b1470dabc26bd 100644 --- a/src/tools/miri/tests/pass/rc.rs +++ b/src/tools/miri/tests/pass/rc.rs @@ -75,7 +75,8 @@ fn rc_fat_ptr_eq() { let p = Rc::new(1) as Rc; let a: *const dyn Debug = &*p; let r = Rc::into_raw(p); - assert!(a == r); + // Only compare the pointer parts, as the vtable might differ. + assert!(a as *const () == r as *const ()); drop(unsafe { Rc::from_raw(r) }); } From ba3cb156cb5e6cc9860600ec6dc7713d69e6b17b Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 6 Aug 2024 10:20:48 -0700 Subject: [PATCH 557/786] Remove unused lifetime parameter from spawn_unchecked --- library/std/src/thread/mod.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 59720f77465e1..88b31cd78a661 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -434,25 +434,24 @@ impl Builder { /// /// [`io::Result`]: crate::io::Result #[unstable(feature = "thread_spawn_unchecked", issue = "55132")] - pub unsafe fn spawn_unchecked<'a, F, T>(self, f: F) -> io::Result> + pub unsafe fn spawn_unchecked(self, f: F) -> io::Result> where F: FnOnce() -> T, - F: Send + 'a, - T: Send + 'a, + F: Send, + T: Send, { Ok(JoinHandle(unsafe { self.spawn_unchecked_(f, None) }?)) } - unsafe fn spawn_unchecked_<'a, 'scope, F, T>( + unsafe fn spawn_unchecked_<'scope, F, T>( self, f: F, scope_data: Option>, ) -> io::Result> where F: FnOnce() -> T, - F: Send + 'a, - T: Send + 'a, - 'scope: 'a, + F: Send, + T: Send, { let Builder { name, stack_size } = self; @@ -532,7 +531,7 @@ impl Builder { // will call `decrement_num_running_threads` and therefore signal that this thread is // done. drop(their_packet); - // Here, the lifetime `'a` and even `'scope` can end. `main` keeps running for a bit + // Here, the lifetime `'scope` can end. `main` keeps running for a bit // after that before returning itself. }; From 79228526bfa37f2f0ee9b91671a4342064e85f73 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 6 Aug 2024 13:33:32 -0400 Subject: [PATCH 558/786] Cache supertrait outlives of impl header for soundness check --- compiler/rustc_hir_analysis/src/collect.rs | 1 + .../src/collect/item_bounds.rs | 21 ++++++++++ compiler/rustc_middle/src/query/mod.rs | 4 ++ .../src/traits/select/mod.rs | 42 +++++++------------ 4 files changed, 42 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 47ff748547a90..8c1e5e78b75dc 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -67,6 +67,7 @@ pub fn provide(providers: &mut Providers) { item_super_predicates: item_bounds::item_super_predicates, explicit_item_super_predicates: item_bounds::explicit_item_super_predicates, item_non_self_assumptions: item_bounds::item_non_self_assumptions, + impl_super_outlives: item_bounds::impl_super_outlives, generics_of: generics_of::generics_of, predicates_of: predicates_of::predicates_of, predicates_defined_on, diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index 6bff99ea65f0b..ec48c781c0e43 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -212,6 +212,8 @@ pub(super) fn item_super_predicates( }) } +/// This exists as an optimization to compute only the item bounds of the item +/// that are not `Self` bounds. pub(super) fn item_non_self_assumptions( tcx: TyCtxt<'_>, def_id: DefId, @@ -226,6 +228,25 @@ pub(super) fn item_non_self_assumptions( } } +/// This exists as an optimization to compute only the supertraits of this impl's +/// trait that are outlives bounds. +pub(super) fn impl_super_outlives( + tcx: TyCtxt<'_>, + def_id: DefId, +) -> ty::EarlyBinder<'_, ty::Clauses<'_>> { + tcx.impl_trait_header(def_id).expect("expected an impl of trait").trait_ref.map_bound( + |trait_ref| { + let clause: ty::Clause<'_> = trait_ref.upcast(tcx); + tcx.mk_clauses_from_iter(util::elaborate(tcx, [clause]).filter(|clause| { + matches!( + clause.kind().skip_binder(), + ty::ClauseKind::TypeOutlives(_) | ty::ClauseKind::RegionOutlives(_) + ) + })) + }, + ) +} + struct AssocTyToOpaque<'tcx> { tcx: TyCtxt<'tcx>, fn_def_id: DefId, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index c22c2e985abba..f69f78d4f0fe3 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -407,6 +407,10 @@ rustc_queries! { desc { |tcx| "elaborating item assumptions for `{}`", tcx.def_path_str(key) } } + query impl_super_outlives(key: DefId) -> ty::EarlyBinder<'tcx, ty::Clauses<'tcx>> { + desc { |tcx| "elaborating supertrait outlives for trait of `{}`", tcx.def_path_str(key) } + } + /// Look up all native libraries this crate depends on. /// These are assembled from the following places: /// - `extern` blocks (depending on their `link` attributes) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 1d9a90f0300ab..1b2767a6a627f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -17,7 +17,6 @@ use rustc_hir::LangItem; use rustc_infer::infer::relate::TypeRelation; use rustc_infer::infer::BoundRegionConversionTime::{self, HigherRankedType}; use rustc_infer::infer::DefineOpaqueTypes; -use rustc_infer::traits::util::elaborate; use rustc_infer::traits::TraitObligation; use rustc_middle::bug; use rustc_middle::dep_graph::{dep_kinds, DepNodeIndex}; @@ -2801,31 +2800,22 @@ impl<'tcx> SelectionContext<'_, 'tcx> { } // Register any outlives obligations from the trait here, cc #124336. - if matches!(self.tcx().def_kind(def_id), DefKind::Impl { of_trait: true }) - && let Some(header) = self.tcx().impl_trait_header(def_id) - { - let trait_clause: ty::Clause<'tcx> = - header.trait_ref.instantiate(self.tcx(), args).upcast(self.tcx()); - for clause in elaborate(self.tcx(), [trait_clause]) { - if matches!( - clause.kind().skip_binder(), - ty::ClauseKind::TypeOutlives(..) | ty::ClauseKind::RegionOutlives(..) - ) { - let clause = normalize_with_depth_to( - self, - param_env, - cause.clone(), - recursion_depth, - clause, - &mut obligations, - ); - obligations.push(Obligation { - cause: cause.clone(), - recursion_depth, - param_env, - predicate: clause.as_predicate(), - }); - } + if matches!(tcx.def_kind(def_id), DefKind::Impl { of_trait: true }) { + for clause in tcx.impl_super_outlives(def_id).iter_instantiated(tcx, args) { + let clause = normalize_with_depth_to( + self, + param_env, + cause.clone(), + recursion_depth, + clause, + &mut obligations, + ); + obligations.push(Obligation { + cause: cause.clone(), + recursion_depth, + param_env, + predicate: clause.as_predicate(), + }); } } From db6c05f9b93ffa2375773d8a5e69ca59b22d3c85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 9 May 2024 20:55:32 +0000 Subject: [PATCH 559/786] Maintain highlighting in `note` and `help` even when they have a span --- compiler/rustc_errors/src/diagnostic.rs | 21 +++++++++++++++++++++ compiler/rustc_errors/src/emitter.rs | 7 +++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index e1dcbf5b2805b..67ca6d50cca4b 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -741,6 +741,16 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { self } + #[rustc_lint_diagnostics] + pub fn highlighted_span_note( + &mut self, + span: impl Into, + msg: Vec, + ) -> &mut Self { + self.sub_with_highlights(Level::Note, msg, span.into()); + self + } + /// This is like [`Diag::note()`], but it's only printed once. #[rustc_lint_diagnostics] pub fn note_once(&mut self, msg: impl Into) -> &mut Self { @@ -815,6 +825,17 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { self } + /// Add a help message attached to this diagnostic with a customizable highlighted message. + #[rustc_lint_diagnostics] + pub fn highlighted_span_help( + &mut self, + span: impl Into, + msg: Vec, + ) -> &mut Self { + self.sub_with_highlights(Level::Help, msg, span.into()); + self + } + /// Prints the span with some help above it. /// This is like [`Diag::help()`], but it gets its own span. #[rustc_lint_diagnostics] diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 483b757f20c18..8df3b685829df 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -1347,7 +1347,7 @@ impl HumanEmitter { label_width += 2; } let mut line = 0; - for (text, _) in msgs.iter() { + for (text, style) in msgs.iter() { let text = self.translate_message(text, args).map_err(Report::new).unwrap(); // Account for newlines to align output to its label. for text in normalize_whitespace(&text).lines() { @@ -1358,7 +1358,10 @@ impl HumanEmitter { if line == 0 { String::new() } else { " ".repeat(label_width) }, text ), - header_style, + match style { + Style::Highlight => *style, + _ => header_style, + }, ); line += 1; } From 4868680ee9156e16a71c3bf197c19bdc59871001 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 9 May 2024 21:05:05 +0000 Subject: [PATCH 560/786] On trait bound mismatch, detect multiple crate versions in dep tree When encountering an E0277, if the type and the trait both come from a crate with the same name but different crate number, we explain that there are multiple crate versions in the dependency tree. If there's a type that fulfills the bound, and it has the same name as the passed in type and has the same crate name, we explain that the same type in two different versions of the same crate *are different*. ``` error[E0277]: the trait bound `Type: dependency::Trait` is not satisfied --> src/main.rs:4:18 | 4 | do_something(Type); | ------------ ^^^^ the trait `dependency::Trait` is not implemented for `Type` | | | required by a bound introduced by this call | help: you have multiple different versions of crate `dependency` in your dependency graph --> src/main.rs:1:5 | 1 | use bar::do_something; | ^^^ one version of crate `dependency` is used here, as a dependency of crate `bar` 2 | use dependency::Type; | ^^^^^^^^^^ one version of crate `dependency` is used here, as a direct dependency of the current crate note: two types coming from two different versions of the same crate are different types even if they look the same --> /home/gh-estebank/crate_versions/baz-2/src/lib.rs:1:1 | 1 | pub struct Type; | ^^^^^^^^^^^^^^^ this type doesn't implement the required trait | ::: /home/gh-estebank/crate_versions/baz/src/lib.rs:1:1 | 1 | pub struct Type; | ^^^^^^^^^^^^^^^ this type implements the required trait 2 | pub trait Trait {} | --------------- this is the required trait note: required by a bound in `bar::do_something` --> /home/gh-estebank/crate_versions/baz/src/lib.rs:4:24 | 4 | pub fn do_something(_: X) {} | ^^^^^ required by this bound in `do_something` ``` Address #22750. --- .../traits/fulfillment_errors.rs | 163 +++++++++++++----- 1 file changed, 124 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 2ce1b955af521..03b93f1c139b5 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -1624,9 +1624,130 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { other: bool, param_env: ty::ParamEnv<'tcx>, ) -> bool { - // If we have a single implementation, try to unify it with the trait ref - // that failed. This should uncover a better hint for what *is* implemented. + let alternative_candidates = |def_id: DefId| { + let mut impl_candidates: Vec<_> = self + .tcx + .all_impls(def_id) + // ignore `do_not_recommend` items + .filter(|def_id| { + !self + .tcx + .has_attrs_with_path(*def_id, &[sym::diagnostic, sym::do_not_recommend]) + }) + // Ignore automatically derived impls and `!Trait` impls. + .filter_map(|def_id| self.tcx.impl_trait_header(def_id)) + .filter_map(|header| { + (header.polarity != ty::ImplPolarity::Negative + || self.tcx.is_automatically_derived(def_id)) + .then(|| header.trait_ref.instantiate_identity()) + }) + .filter(|trait_ref| { + let self_ty = trait_ref.self_ty(); + // Avoid mentioning type parameters. + if let ty::Param(_) = self_ty.kind() { + false + } + // Avoid mentioning types that are private to another crate + else if let ty::Adt(def, _) = self_ty.peel_refs().kind() { + // FIXME(compiler-errors): This could be generalized, both to + // be more granular, and probably look past other `#[fundamental]` + // types, too. + self.tcx.visibility(def.did()).is_accessible_from(body_def_id, self.tcx) + } else { + true + } + }) + .collect(); + + impl_candidates.sort_by_key(|tr| tr.to_string()); + impl_candidates.dedup(); + impl_candidates + }; + + // We'll check for the case where the reason for the mismatch is that the trait comes from + // one crate version and the type comes from another crate version, even though they both + // are from the same crate. + let trait_def_id = trait_ref.def_id(); + if let ty::Adt(def, _) = trait_ref.self_ty().skip_binder().peel_refs().kind() + && let found_type = def.did() + && trait_def_id.krate != found_type.krate + && self.tcx.crate_name(trait_def_id.krate) == self.tcx.crate_name(found_type.krate) + { + let name = self.tcx.crate_name(trait_def_id.krate); + let spans: Vec<_> = [trait_def_id, found_type] + .into_iter() + .filter_map(|def_id| self.tcx.extern_crate(def_id)) + .map(|data| { + let dependency = if data.dependency_of == LOCAL_CRATE { + "direct dependency of the current crate".to_string() + } else { + let dep = self.tcx.crate_name(data.dependency_of); + format!("dependency of crate `{dep}`") + }; + ( + data.span, + format!("one version of crate `{name}` is used here, as a {dependency}"), + ) + }) + .collect(); + let mut span: MultiSpan = spans.iter().map(|(sp, _)| *sp).collect::>().into(); + for (sp, label) in spans.into_iter() { + span.push_span_label(sp, label); + } + err.highlighted_span_help( + span, + vec![ + StringPart::normal("you have ".to_string()), + StringPart::highlighted("multiple different versions".to_string()), + StringPart::normal(" of crate `".to_string()), + StringPart::highlighted(format!("{name}")), + StringPart::normal("` in your dependency graph".to_string()), + ], + ); + let candidates = if impl_candidates.is_empty() { + alternative_candidates(trait_def_id) + } else { + impl_candidates.into_iter().map(|cand| cand.trait_ref).collect() + }; + if let Some((sp_candidate, sp_found)) = candidates.iter().find_map(|trait_ref| { + if let ty::Adt(def, _) = trait_ref.self_ty().peel_refs().kind() + && let candidate_def_id = def.did() + && let Some(name) = self.tcx.opt_item_name(candidate_def_id) + && let Some(found) = self.tcx.opt_item_name(found_type) + && name == found + && candidate_def_id.krate != found_type.krate + && self.tcx.crate_name(candidate_def_id.krate) + == self.tcx.crate_name(found_type.krate) + { + // A candidate was found of an item with the same name, from two separate + // versions of the same crate, let's clarify. + Some((self.tcx.def_span(candidate_def_id), self.tcx.def_span(found_type))) + } else { + None + } + }) { + let mut span: MultiSpan = vec![sp_candidate, sp_found].into(); + span.push_span_label(self.tcx.def_span(trait_def_id), "this is the required trait"); + span.push_span_label(sp_candidate, "this type implements the required trait"); + span.push_span_label(sp_found, "this type doesn't implement the required trait"); + err.highlighted_span_note( + span, + vec![ + StringPart::normal( + "two types coming from two different versions of the same crate are \ + different types " + .to_string(), + ), + StringPart::highlighted("even if they look the same".to_string()), + ], + ); + } + return true; + } + if let [single] = &impl_candidates { + // If we have a single implementation, try to unify it with the trait ref + // that failed. This should uncover a better hint for what *is* implemented. if self.probe(|_| { let ocx = ObligationCtxt::new(self); @@ -1798,43 +1919,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // Mentioning implementers of `Copy`, `Debug` and friends is not useful. return false; } - let mut impl_candidates: Vec<_> = self - .tcx - .all_impls(def_id) - // ignore `do_not_recommend` items - .filter(|def_id| { - !self - .tcx - .has_attrs_with_path(*def_id, &[sym::diagnostic, sym::do_not_recommend]) - }) - // Ignore automatically derived impls and `!Trait` impls. - .filter_map(|def_id| self.tcx.impl_trait_header(def_id)) - .filter_map(|header| { - (header.polarity != ty::ImplPolarity::Negative - || self.tcx.is_automatically_derived(def_id)) - .then(|| header.trait_ref.instantiate_identity()) - }) - .filter(|trait_ref| { - let self_ty = trait_ref.self_ty(); - // Avoid mentioning type parameters. - if let ty::Param(_) = self_ty.kind() { - false - } - // Avoid mentioning types that are private to another crate - else if let ty::Adt(def, _) = self_ty.peel_refs().kind() { - // FIXME(compiler-errors): This could be generalized, both to - // be more granular, and probably look past other `#[fundamental]` - // types, too. - self.tcx.visibility(def.did()).is_accessible_from(body_def_id, self.tcx) - } else { - true - } - }) - .collect(); - - impl_candidates.sort_by_key(|tr| tr.to_string()); - impl_candidates.dedup(); - return report(impl_candidates, err); + return report(alternative_candidates(def_id), err); } // Sort impl candidates so that ordering is consistent for UI tests. From ba32673215847a27d4cab381f161a43a59002ee8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 13 May 2024 04:19:18 +0000 Subject: [PATCH 561/786] Add test for mixing types from two incompatible crate versions --- .../crate-loading/auxiliary/dep-2-reexport.rs | 4 + .../auxiliary/multiple-dep-versions-1.rs | 7 ++ .../auxiliary/multiple-dep-versions-2.rs | 7 ++ .../ui/crate-loading/multiple-dep-versions.rs | 14 +++ .../crate-loading/multiple-dep-versions.svg | 101 ++++++++++++++++++ 5 files changed, 133 insertions(+) create mode 100644 tests/ui/crate-loading/auxiliary/dep-2-reexport.rs create mode 100644 tests/ui/crate-loading/auxiliary/multiple-dep-versions-1.rs create mode 100644 tests/ui/crate-loading/auxiliary/multiple-dep-versions-2.rs create mode 100644 tests/ui/crate-loading/multiple-dep-versions.rs create mode 100644 tests/ui/crate-loading/multiple-dep-versions.svg diff --git a/tests/ui/crate-loading/auxiliary/dep-2-reexport.rs b/tests/ui/crate-loading/auxiliary/dep-2-reexport.rs new file mode 100644 index 0000000000000..3a793bbbb106e --- /dev/null +++ b/tests/ui/crate-loading/auxiliary/dep-2-reexport.rs @@ -0,0 +1,4 @@ +//@ edition:2021 +//@ aux-build:multiple-dep-versions-2.rs +extern crate dependency; +pub use dependency::do_something; diff --git a/tests/ui/crate-loading/auxiliary/multiple-dep-versions-1.rs b/tests/ui/crate-loading/auxiliary/multiple-dep-versions-1.rs new file mode 100644 index 0000000000000..b96bb6d9e6443 --- /dev/null +++ b/tests/ui/crate-loading/auxiliary/multiple-dep-versions-1.rs @@ -0,0 +1,7 @@ +#![crate_name="dependency"] +//@ edition:2021 +//@ compile-flags: -C metadata=1 -C extra-filename=-1 +pub struct Type; +pub trait Trait {} +impl Trait for Type {} +pub fn do_something(_: X) { } diff --git a/tests/ui/crate-loading/auxiliary/multiple-dep-versions-2.rs b/tests/ui/crate-loading/auxiliary/multiple-dep-versions-2.rs new file mode 100644 index 0000000000000..c79157fa4634f --- /dev/null +++ b/tests/ui/crate-loading/auxiliary/multiple-dep-versions-2.rs @@ -0,0 +1,7 @@ +#![crate_name="dependency"] +//@ edition:2021 +//@ compile-flags: -C metadata=2 -C extra-filename=-2 +pub struct Type(pub i32); +pub trait Trait {} +impl Trait for Type {} +pub fn do_something(_: X) {} diff --git a/tests/ui/crate-loading/multiple-dep-versions.rs b/tests/ui/crate-loading/multiple-dep-versions.rs new file mode 100644 index 0000000000000..9e0a5dc5c5dc9 --- /dev/null +++ b/tests/ui/crate-loading/multiple-dep-versions.rs @@ -0,0 +1,14 @@ +//@ aux-build:dep-2-reexport.rs +//@ aux-build:multiple-dep-versions-1.rs +//@ edition:2021 +//@ compile-flags: --error-format=human --color=always --crate-type bin --extern dependency={{build-base}}/crate-loading/multiple-dep-versions/auxiliary/libdependency-1.so --extern dep_2_reexport={{build-base}}/crate-loading/multiple-dep-versions/auxiliary/libdep_2_reexport.so +//@ ignore-windows + +extern crate dependency; +extern crate dep_2_reexport; +use dependency::Type; +use dep_2_reexport::do_something; + +fn main() { + do_something(Type); +} diff --git a/tests/ui/crate-loading/multiple-dep-versions.svg b/tests/ui/crate-loading/multiple-dep-versions.svg new file mode 100644 index 0000000000000..6b89ca691e0bc --- /dev/null +++ b/tests/ui/crate-loading/multiple-dep-versions.svg @@ -0,0 +1,101 @@ + + + + + + + error[E0277]: the trait bound `Type: dependency::Trait` is not satisfied + + --> $DIR/multiple-dep-versions.rs:13:18 + + | + + LL | do_something(Type); + + | ------------ ^^^^ the trait `dependency::Trait` is not implemented for `Type` + + | | + + | required by a bound introduced by this call + + | + + help: you have multiple different versions of crate `dependency` in your dependency graph + + --> $DIR/multiple-dep-versions.rs:7:1 + + | + + LL | extern crate dependency; + + | ^^^^^^^^^^^^^^^^^^^^^^^^ one version of crate `dependency` is used here, as a direct dependency of the current crate + + LL | extern crate dep_2_reexport; + + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one version of crate `dependency` is used here, as a dependency of crate `dep_2_reexport` + + note: two types coming from two different versions of the same crate are different types even if they look the same + + --> $DIR/auxiliary/multiple-dep-versions-1.rs:4:1 + + | + + LL | pub struct Type; + + | ^^^^^^^^^^^^^^^ this type doesn't implement the required trait + + | + + ::: $DIR/auxiliary/multiple-dep-versions-2.rs:4:1 + + | + + LL | pub struct Type(pub i32); + + | ^^^^^^^^^^^^^^^ this type implements the required trait + + LL | pub trait Trait {} + + | --------------- this is the required trait + + note: required by a bound in `dep_2_reexport::do_something` + + --> $DIR/auxiliary/multiple-dep-versions-2.rs:7:24 + + | + + LL | pub fn do_something<X: Trait>(_: X) {} + + | ^^^^^ required by this bound in `do_something` + + + + error: aborting due to 1 previous error + + + + For more information about this error, try `rustc --explain E0277`. + + + + + + From d8b07718f4a32820d4d3c46a3c82ca0af74cfed3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 13 May 2024 04:30:14 +0000 Subject: [PATCH 562/786] Add `help` about using `cargo tree` --- .../traits/fulfillment_errors.rs | 1 + .../crate-loading/multiple-dep-versions.svg | 24 ++++++++++--------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 03b93f1c139b5..5a25d9a7ecdac 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -1742,6 +1742,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ], ); } + err.help("you can use `cargo tree` to explore your dependency tree"); return true; } diff --git a/tests/ui/crate-loading/multiple-dep-versions.svg b/tests/ui/crate-loading/multiple-dep-versions.svg index 6b89ca691e0bc..671f38d3eb013 100644 --- a/tests/ui/crate-loading/multiple-dep-versions.svg +++ b/tests/ui/crate-loading/multiple-dep-versions.svg @@ -1,4 +1,4 @@ - + , app: &mut Applicability, ) -> String { - let (code, from_macro) = snippet_block_with_context(cx, expr.span, outer, default, indent_relative_to, app); + let (code, from_macro) = snippet_block_with_context(sess, expr.span, outer, default, indent_relative_to, app); if !from_macro && let ExprKind::Block(block, _) = expr.kind && block.rules != BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) @@ -260,13 +285,13 @@ pub fn expr_block( /// let x = (); /// // ^^^^^^^^^^ /// ``` -pub fn first_line_of_span(cx: &T, span: Span) -> Span { - first_char_in_first_line(cx, span).map_or(span, |first_char_pos| span.with_lo(first_char_pos)) +pub fn first_line_of_span(sess: &impl HasSession, span: Span) -> Span { + first_char_in_first_line(sess, span).map_or(span, |first_char_pos| span.with_lo(first_char_pos)) } -fn first_char_in_first_line(cx: &T, span: Span) -> Option { - let line_span = line_span(cx, span); - snippet_opt(cx, line_span).and_then(|snip| { +fn first_char_in_first_line(sess: &impl HasSession, span: Span) -> Option { + let line_span = line_span(sess, span); + snippet_opt(sess, line_span).and_then(|snip| { snip.find(|c: char| !c.is_whitespace()) .map(|pos| line_span.lo() + BytePos::from_usize(pos)) }) @@ -281,9 +306,9 @@ fn first_char_in_first_line(cx: &T, span: Span) -> Option(cx: &T, span: Span) -> Span { +fn line_span(sess: &impl HasSession, span: Span) -> Span { let span = original_sp(span, DUMMY_SP); - let SourceFileAndLine { sf, line } = cx.sess().source_map().lookup_line(span.lo()).unwrap(); + let SourceFileAndLine { sf, line } = sess.sess().source_map().lookup_line(span.lo()).unwrap(); let line_start = sf.lines()[line]; let line_start = sf.absolute_position(line_start); span.with_lo(line_start) @@ -297,13 +322,13 @@ fn line_span(cx: &T, span: Span) -> Span { /// let x = (); /// // ^^ -- will return 4 /// ``` -pub fn indent_of(cx: &T, span: Span) -> Option { - snippet_opt(cx, line_span(cx, span)).and_then(|snip| snip.find(|c: char| !c.is_whitespace())) +pub fn indent_of(sess: &impl HasSession, span: Span) -> Option { + snippet_opt(sess, line_span(sess, span)).and_then(|snip| snip.find(|c: char| !c.is_whitespace())) } /// Gets a snippet of the indentation of the line of a span -pub fn snippet_indent(cx: &T, span: Span) -> Option { - snippet_opt(cx, line_span(cx, span)).map(|mut s| { +pub fn snippet_indent(sess: &impl HasSession, span: Span) -> Option { + snippet_opt(sess, line_span(sess, span)).map(|mut s| { let len = s.len() - s.trim_start().len(); s.truncate(len); s @@ -315,8 +340,8 @@ pub fn snippet_indent(cx: &T, span: Span) -> Option { // sources that the user has no control over. // For some reason these attributes don't have any expansion info on them, so // we have to check it this way until there is a better way. -pub fn is_present_in_source(cx: &T, span: Span) -> bool { - if let Some(snippet) = snippet_opt(cx, span) { +pub fn is_present_in_source(sess: &impl HasSession, span: Span) -> bool { + if let Some(snippet) = snippet_opt(sess, span) { if snippet.is_empty() { return false; } @@ -407,8 +432,8 @@ fn reindent_multiline_inner(s: &str, ignore_first: bool, indent: Option, /// snippet(cx, span1, "..") // -> "value" /// snippet(cx, span2, "..") // -> "Vec::new()" /// ``` -pub fn snippet<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> { - snippet_opt(cx, span).map_or_else(|| Cow::Borrowed(default), From::from) +pub fn snippet<'a>(sess: &impl HasSession, span: Span, default: &'a str) -> Cow<'a, str> { + snippet_opt(sess, span).map_or_else(|| Cow::Borrowed(default), From::from) } /// Same as [`snippet`], but it adapts the applicability level by following rules: @@ -417,13 +442,13 @@ pub fn snippet<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow< /// - 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` -pub fn snippet_with_applicability<'a, T: LintContext>( - cx: &T, +pub fn snippet_with_applicability<'a>( + sess: &impl HasSession, span: Span, default: &'a str, applicability: &mut Applicability, ) -> Cow<'a, str> { - snippet_with_applicability_sess(cx.sess(), span, default, applicability) + snippet_with_applicability_sess(sess.sess(), span, default, applicability) } fn snippet_with_applicability_sess<'a>( @@ -435,7 +460,7 @@ fn snippet_with_applicability_sess<'a>( if *applicability != Applicability::Unspecified && span.from_expansion() { *applicability = Applicability::MaybeIncorrect; } - snippet_opt_sess(sess, span).map_or_else( + snippet_opt(sess, span).map_or_else( || { if *applicability == Applicability::MachineApplicable { *applicability = Applicability::HasPlaceholders; @@ -447,12 +472,8 @@ fn snippet_with_applicability_sess<'a>( } /// Converts a span to a code snippet. Returns `None` if not available. -pub fn snippet_opt(cx: &impl LintContext, span: Span) -> Option { - snippet_opt_sess(cx.sess(), span) -} - -fn snippet_opt_sess(sess: &Session, span: Span) -> Option { - sess.source_map().span_to_snippet(span).ok() +pub fn snippet_opt(sess: &impl HasSession, span: Span) -> Option { + sess.sess().source_map().span_to_snippet(span).ok() } /// Converts a span (from a block) to a code snippet if available, otherwise use default. @@ -489,41 +510,41 @@ fn snippet_opt_sess(sess: &Session, span: Span) -> Option { /// } // aligned with `if` /// ``` /// Note that the first line of the snippet always has 0 indentation. -pub fn snippet_block<'a, T: LintContext>( - cx: &T, +pub fn snippet_block<'a>( + sess: &impl HasSession, span: Span, default: &'a str, indent_relative_to: Option, ) -> Cow<'a, str> { - let snip = snippet(cx, span, default); - let indent = indent_relative_to.and_then(|s| indent_of(cx, s)); + let snip = snippet(sess, span, default); + let indent = indent_relative_to.and_then(|s| indent_of(sess, s)); reindent_multiline(snip, true, indent) } /// Same as `snippet_block`, but adapts the applicability level by the rules of /// `snippet_with_applicability`. pub fn snippet_block_with_applicability<'a>( - cx: &impl LintContext, + sess: &impl HasSession, span: Span, default: &'a str, indent_relative_to: Option, applicability: &mut Applicability, ) -> Cow<'a, str> { - let snip = snippet_with_applicability(cx, span, default, applicability); - let indent = indent_relative_to.and_then(|s| indent_of(cx, s)); + let snip = snippet_with_applicability(sess, span, default, applicability); + let indent = indent_relative_to.and_then(|s| indent_of(sess, s)); reindent_multiline(snip, true, indent) } pub fn snippet_block_with_context<'a>( - cx: &impl LintContext, + sess: &impl HasSession, span: Span, outer: SyntaxContext, default: &'a str, indent_relative_to: Option, app: &mut Applicability, ) -> (Cow<'a, str>, bool) { - let (snip, from_macro) = snippet_with_context(cx, span, outer, default, app); - let indent = indent_relative_to.and_then(|s| indent_of(cx, s)); + let (snip, from_macro) = snippet_with_context(sess, span, outer, default, app); + let indent = indent_relative_to.and_then(|s| indent_of(sess, s)); (reindent_multiline(snip, true, indent), from_macro) } @@ -537,13 +558,13 @@ pub fn snippet_block_with_context<'a>( /// /// This will also return whether or not the snippet is a macro call. pub fn snippet_with_context<'a>( - cx: &impl LintContext, + sess: &impl HasSession, span: Span, outer: SyntaxContext, default: &'a str, applicability: &mut Applicability, ) -> (Cow<'a, str>, bool) { - snippet_with_context_sess(cx.sess(), span, outer, default, applicability) + snippet_with_context_sess(sess.sess(), span, outer, default, applicability) } fn snippet_with_context_sess<'a>( @@ -661,15 +682,15 @@ pub fn trim_span(sm: &SourceMap, span: Span) -> Span { /// writeln!(o, "") -> writeln!(o, "") /// ^^ ^^^^ /// ``` -pub fn expand_past_previous_comma(cx: &LateContext<'_>, span: Span) -> Span { - let extended = cx.sess().source_map().span_extend_to_prev_char(span, ',', true); +pub fn expand_past_previous_comma(sess: &impl HasSession, span: Span) -> Span { + let extended = sess.sess().source_map().span_extend_to_prev_char(span, ',', true); extended.with_lo(extended.lo() - BytePos(1)) } /// Converts `expr` to a `char` literal if it's a `str` literal containing a single /// character (or a single byte with `ascii_only`) pub fn str_literal_to_char_literal( - cx: &LateContext<'_>, + sess: &impl HasSession, expr: &Expr<'_>, applicability: &mut Applicability, ascii_only: bool, @@ -684,7 +705,7 @@ pub fn str_literal_to_char_literal( } && len == 1 { - let snip = snippet_with_applicability(cx, expr.span, string, applicability); + let snip = snippet_with_applicability(sess, expr.span, string, applicability); let ch = if let StrStyle::Raw(nhash) = style { let nhash = nhash as usize; // for raw string: r##"a"## From d2cb227eb4582c961ad0a9b7bfce41b1e08001f0 Mon Sep 17 00:00:00 2001 From: Jason Newcomb Date: Wed, 31 Jul 2024 17:51:09 -0400 Subject: [PATCH 644/786] Don't store `LateContext` in `ConstEvalLateContext` --- clippy_lints/src/enum_clike.rs | 2 +- clippy_lints/src/matches/overlapping_arms.rs | 4 +- .../src/operators/const_comparisons.rs | 2 +- clippy_lints/src/operators/erasing_op.rs | 2 +- clippy_utils/src/consts.rs | 139 +++++++++--------- clippy_utils/src/lib.rs | 4 +- 6 files changed, 75 insertions(+), 78 deletions(-) diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index 30eb643c42ece..e54cd248ead29 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -51,7 +51,7 @@ impl<'tcx> LateLintPass<'tcx> for UnportableVariant { .const_eval_poly(def_id.to_def_id()) .ok() .map(|val| rustc_middle::mir::Const::from_value(val, ty)); - if let Some(Constant::Int(val)) = constant.and_then(|c| mir_to_const(cx, c)) { + if let Some(Constant::Int(val)) = constant.and_then(|c| mir_to_const(cx.tcx, c)) { if let ty::Adt(adt, _) = ty.kind() { if adt.is_enum() { ty = adt.repr().discr_type().to_ty(cx.tcx); diff --git a/clippy_lints/src/matches/overlapping_arms.rs b/clippy_lints/src/matches/overlapping_arms.rs index 7ad66360d8a60..4a6741da45f72 100644 --- a/clippy_lints/src/matches/overlapping_arms.rs +++ b/clippy_lints/src/matches/overlapping_arms.rs @@ -37,13 +37,13 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>) constant(cx, cx.typeck_results(), lhs)? } else { let min_val_const = ty.numeric_min_val(cx.tcx)?; - mir_to_const(cx, mir::Const::from_ty_const(min_val_const, ty, cx.tcx))? + mir_to_const(cx.tcx, mir::Const::from_ty_const(min_val_const, ty, cx.tcx))? }; let rhs_const = if let Some(rhs) = rhs { constant(cx, cx.typeck_results(), rhs)? } else { let max_val_const = ty.numeric_max_val(cx.tcx)?; - mir_to_const(cx, mir::Const::from_ty_const(max_val_const, ty, cx.tcx))? + mir_to_const(cx.tcx, mir::Const::from_ty_const(max_val_const, ty, cx.tcx))? }; let lhs_val = lhs_const.int_value(cx, ty)?; let rhs_val = rhs_const.int_value(cx, ty)?; diff --git a/clippy_lints/src/operators/const_comparisons.rs b/clippy_lints/src/operators/const_comparisons.rs index 7bf9b8ef866a2..1f9f3b3c47305 100644 --- a/clippy_lints/src/operators/const_comparisons.rs +++ b/clippy_lints/src/operators/const_comparisons.rs @@ -20,7 +20,7 @@ use super::{IMPOSSIBLE_COMPARISONS, REDUNDANT_COMPARISONS}; // Flip yoda conditionals, turnings expressions like `42 < x` into `x > 42` fn comparison_to_const<'tcx>( cx: &LateContext<'tcx>, - typeck: &TypeckResults<'tcx>, + typeck: &'tcx TypeckResults<'tcx>, expr: &'tcx Expr<'tcx>, ) -> Option<(CmpOp, &'tcx Expr<'tcx>, &'tcx Expr<'tcx>, Constant<'tcx>, Ty<'tcx>)> { if let ExprKind::Binary(operator, left, right) = expr.kind diff --git a/clippy_lints/src/operators/erasing_op.rs b/clippy_lints/src/operators/erasing_op.rs index 066e08f3bd4ca..fc2129b91036b 100644 --- a/clippy_lints/src/operators/erasing_op.rs +++ b/clippy_lints/src/operators/erasing_op.rs @@ -34,7 +34,7 @@ fn different_types(tck: &TypeckResults<'_>, input: &Expr<'_>, output: &Expr<'_>) fn check_op<'tcx>( cx: &LateContext<'tcx>, - tck: &TypeckResults<'tcx>, + tck: &'tcx TypeckResults<'tcx>, op: &Expr<'tcx>, other: &Expr<'tcx>, parent: &Expr<'tcx>, diff --git a/clippy_utils/src/consts.rs b/clippy_utils/src/consts.rs index de6ccfe476fb0..d465daa06e27d 100644 --- a/clippy_utils/src/consts.rs +++ b/clippy_utils/src/consts.rs @@ -14,10 +14,12 @@ use rustc_lexer::tokenize; use rustc_lint::LateContext; use rustc_middle::mir::interpret::{alloc_range, Scalar}; use rustc_middle::mir::ConstValue; -use rustc_middle::ty::{self, EarlyBinder, FloatTy, GenericArgsRef, IntTy, List, ScalarInt, Ty, TyCtxt, UintTy}; +use rustc_middle::ty::{ + self, EarlyBinder, FloatTy, GenericArgsRef, IntTy, List, ParamEnv, ScalarInt, Ty, TyCtxt, TypeckResults, UintTy, +}; use rustc_middle::{bug, mir, span_bug}; use rustc_span::def_id::DefId; -use rustc_span::symbol::{Ident, Symbol}; +use rustc_span::symbol::Ident; use rustc_span::{sym, SyntaxContext}; use rustc_target::abi::Size; use std::cmp::Ordering; @@ -339,25 +341,25 @@ impl ConstantSource { /// Attempts to check whether the expression is a constant representing an empty slice, str, array, /// etc… pub fn constant_is_empty(lcx: &LateContext<'_>, e: &Expr<'_>) -> Option { - ConstEvalLateContext::new(lcx, lcx.typeck_results()).expr_is_empty(e) + ConstEvalLateContext::new(lcx.tcx, lcx.param_env, lcx.typeck_results()).expr_is_empty(e) } /// Attempts to evaluate the expression as a constant. pub fn constant<'tcx>( lcx: &LateContext<'tcx>, - typeck_results: &ty::TypeckResults<'tcx>, + typeck_results: &'tcx TypeckResults<'tcx>, e: &Expr<'_>, ) -> Option> { - ConstEvalLateContext::new(lcx, typeck_results).expr(e) + ConstEvalLateContext::new(lcx.tcx, lcx.param_env, typeck_results).expr(e) } /// Attempts to evaluate the expression as a constant. pub fn constant_with_source<'tcx>( lcx: &LateContext<'tcx>, - typeck_results: &ty::TypeckResults<'tcx>, + typeck_results: &'tcx TypeckResults<'tcx>, e: &Expr<'_>, ) -> Option<(Constant<'tcx>, ConstantSource)> { - let mut ctxt = ConstEvalLateContext::new(lcx, typeck_results); + let mut ctxt = ConstEvalLateContext::new(lcx.tcx, lcx.param_env, typeck_results); let res = ctxt.expr(e); res.map(|x| (x, ctxt.source)) } @@ -365,7 +367,7 @@ pub fn constant_with_source<'tcx>( /// Attempts to evaluate an expression only if its value is not dependent on other items. pub fn constant_simple<'tcx>( lcx: &LateContext<'tcx>, - typeck_results: &ty::TypeckResults<'tcx>, + typeck_results: &'tcx TypeckResults<'tcx>, e: &Expr<'_>, ) -> Option> { constant_with_source(lcx, typeck_results, e).and_then(|(c, s)| s.is_local().then_some(c)) @@ -373,7 +375,7 @@ pub fn constant_simple<'tcx>( pub fn constant_full_int<'tcx>( lcx: &LateContext<'tcx>, - typeck_results: &ty::TypeckResults<'tcx>, + typeck_results: &'tcx TypeckResults<'tcx>, e: &Expr<'_>, ) -> Option { constant_simple(lcx, typeck_results, e)?.int_value(lcx, typeck_results.expr_ty(e)) @@ -417,20 +419,20 @@ impl Ord for FullInt { } } -pub struct ConstEvalLateContext<'a, 'tcx> { - lcx: &'a LateContext<'tcx>, - typeck_results: &'a ty::TypeckResults<'tcx>, - param_env: ty::ParamEnv<'tcx>, +pub struct ConstEvalLateContext<'tcx> { + tcx: TyCtxt<'tcx>, + typeck_results: &'tcx TypeckResults<'tcx>, + param_env: ParamEnv<'tcx>, source: ConstantSource, args: GenericArgsRef<'tcx>, } -impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { - pub fn new(lcx: &'a LateContext<'tcx>, typeck_results: &'a ty::TypeckResults<'tcx>) -> Self { +impl<'tcx> ConstEvalLateContext<'tcx> { + pub fn new(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, typeck_results: &'tcx TypeckResults<'tcx>) -> Self { Self { - lcx, + tcx, typeck_results, - param_env: lcx.param_env, + param_env, source: ConstantSource::Local, args: List::empty(), } @@ -439,18 +441,19 @@ 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(ConstBlock { body, .. }) => self.expr(self.tcx.hir().body(body).value), ExprKind::DropTemps(e) => self.expr(e), ExprKind::Path(ref qpath) => { - let is_core_crate = if let Some(def_id) = self.lcx.qpath_res(qpath, e.hir_id()).opt_def_id() { - self.lcx.tcx.crate_name(def_id.krate) == sym::core + let is_core_crate = if let Some(def_id) = self.typeck_results.qpath_res(qpath, e.hir_id()).opt_def_id() + { + self.tcx.crate_name(def_id.krate) == sym::core } else { false }; - self.fetch_path_and_apply(qpath, e.hir_id, self.typeck_results.expr_ty(e), |this, result| { - let result = mir_to_const(this.lcx, result)?; + self.fetch_path_and_apply(qpath, e.hir_id, self.typeck_results.expr_ty(e), |self_, result| { + let result = mir_to_const(self_.tcx, result)?; // If source is already Constant we wouldn't want to override it with CoreConstant - this.source = if is_core_crate && !matches!(this.source, ConstantSource::Constant) { + self_.source = if is_core_crate && !matches!(self_.source, ConstantSource::Constant) { ConstantSource::CoreConstant } else { ConstantSource::Constant @@ -470,7 +473,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { ExprKind::Tup(tup) => self.multi(tup).map(Constant::Tuple), ExprKind::Repeat(value, _) => { let n = match self.typeck_results.expr_ty(e).kind() { - ty::Array(_, n) => n.try_eval_target_usize(self.lcx.tcx, self.lcx.param_env)?, + ty::Array(_, n) => n.try_eval_target_usize(self.tcx, self.param_env)?, _ => span_bug!(e.span, "typeck error"), }; self.expr(value).map(|v| Constant::Repeat(Box::new(v), n)) @@ -486,21 +489,16 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { // We only handle a few const functions for now. if args.is_empty() && let ExprKind::Path(qpath) = &callee.kind - && let res = self.typeck_results.qpath_res(qpath, callee.hir_id) - && let Some(def_id) = res.opt_def_id() - && let def_path = self.lcx.get_def_path(def_id) - && let def_path = def_path.iter().take(4).map(Symbol::as_str).collect::>() - && let ["core", "num", int_impl, "max_value"] = *def_path + && let Some(did) = self.typeck_results.qpath_res(qpath, callee.hir_id).opt_def_id() { - let value = match int_impl { - "" => i8::MAX as u128, - "" => i16::MAX as u128, - "" => i32::MAX as u128, - "" => i64::MAX as u128, - "" => i128::MAX as u128, - _ => return None, - }; - Some(Constant::Int(value)) + match self.tcx.get_diagnostic_name(did) { + Some(sym::i8_legacy_fn_max_value) => Some(Constant::Int(i8::MAX as u128)), + Some(sym::i16_legacy_fn_max_value) => Some(Constant::Int(i16::MAX as u128)), + Some(sym::i32_legacy_fn_max_value) => Some(Constant::Int(i32::MAX as u128)), + Some(sym::i64_legacy_fn_max_value) => Some(Constant::Int(i64::MAX as u128)), + Some(sym::i128_legacy_fn_max_value) => Some(Constant::Int(i128::MAX as u128)), + _ => None, + } } else { None } @@ -512,9 +510,9 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { if let Some(Constant::Adt(constant)) = &self.expr(local_expr) && let ty::Adt(adt_def, _) = constant.ty().kind() && adt_def.is_struct() - && let Some(desired_field) = field_of_struct(*adt_def, self.lcx, *constant, field) + && let Some(desired_field) = field_of_struct(*adt_def, self.tcx, *constant, field) { - mir_to_const(self.lcx, desired_field) + mir_to_const(self.tcx, desired_field) } else { result } @@ -528,7 +526,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(ConstBlock { body, .. }) => self.expr_is_empty(self.tcx.hir().body(body).value), ExprKind::DropTemps(e) => self.expr_is_empty(e), ExprKind::Path(ref qpath) => { if !self @@ -539,8 +537,8 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { { return None; } - self.fetch_path_and_apply(qpath, e.hir_id, self.typeck_results.expr_ty(e), |this, result| { - mir_is_empty(this.lcx, result) + self.fetch_path_and_apply(qpath, e.hir_id, self.typeck_results.expr_ty(e), |self_, result| { + mir_is_empty(self_.tcx, result) }) }, ExprKind::Lit(lit) => { @@ -557,7 +555,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { ExprKind::Array(vec) => self.multi(vec).map(|v| v.is_empty()), ExprKind::Repeat(..) => { if let ty::Array(_, n) = self.typeck_results.expr_ty(e).kind() { - Some(n.try_eval_target_usize(self.lcx.tcx, self.lcx.param_env)? == 0) + Some(n.try_eval_target_usize(self.tcx, self.param_env)? == 0) } else { span_bug!(e.span, "typeck error"); } @@ -574,8 +572,8 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { Int(value) => { let value = !value; match *ty.kind() { - ty::Int(ity) => Some(Int(unsext(self.lcx.tcx, value as i128, ity))), - ty::Uint(ity) => Some(Int(clip(self.lcx.tcx, value, ity))), + ty::Int(ity) => Some(Int(unsext(self.tcx, value as i128, ity))), + ty::Uint(ity) => Some(Int(clip(self.tcx, value, ity))), _ => None, } }, @@ -590,7 +588,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { let ty::Int(ity) = *ty.kind() else { return None }; let (min, _) = ity.min_max()?; // sign extend - let value = sext(self.lcx.tcx, value, ity); + let value = sext(self.tcx, value, ity); // Applying unary - to the most negative value of any signed integer type panics. if value == min { @@ -599,7 +597,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { let value = value.checked_neg()?; // clear unused bits - Some(Int(unsext(self.lcx.tcx, value, ity))) + Some(Int(unsext(self.tcx, value, ity))) }, F32(f) => Some(F32(-f)), F64(f) => Some(F64(-f)), @@ -623,7 +621,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { Res::Def(DefKind::Const | DefKind::AssocConst, def_id) => { // Check if this constant is based on `cfg!(..)`, // which is NOT constant for our purposes. - if let Some(node) = self.lcx.tcx.hir().get_if_local(def_id) + if let Some(node) = self.tcx.hir().get_if_local(def_id) && let Node::Item(Item { kind: ItemKind::Const(.., body_id), .. @@ -632,7 +630,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { kind: ExprKind::Lit(_), span, .. - }) = self.lcx.tcx.hir_node(body_id.hir_id) + }) = self.tcx.hir_node(body_id.hir_id) && is_direct_expn_of(*span, "cfg").is_some() { return None; @@ -642,10 +640,9 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { let args = if self.args.is_empty() { args } else { - EarlyBinder::bind(args).instantiate(self.lcx.tcx, self.args) + EarlyBinder::bind(args).instantiate(self.tcx, self.args) }; let result = self - .lcx .tcx .const_eval_resolve(self.param_env, mir::UnevaluatedConst::new(def_id, args), qpath.span()) .ok() @@ -685,7 +682,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { } } - /// A block can only yield a constant if it only has one constant expression. + /// A block can only yield a constant if it has exactly one constant expression. fn block(&mut self, block: &Block<'_>) -> Option> { if block.stmts.is_empty() && let Some(expr) = block.expr @@ -696,7 +693,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { if let Some(expr_span) = walk_span_to_context(expr.span, span.ctxt) && let expr_lo = expr_span.lo() && expr_lo >= span.lo - && let Some(src) = (span.lo..expr_lo).get_source_text(self.lcx) + && let Some(src) = (span.lo..expr_lo).get_source_text(&self.tcx) && let Some(src) = src.as_str() { use rustc_lexer::TokenKind::{BlockComment, LineComment, OpenBrace, Semi, Whitespace}; @@ -739,8 +736,8 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { ty::Int(ity) => { let (ty_min_value, _) = ity.min_max()?; let bits = ity.bits(); - let l = sext(self.lcx.tcx, l, ity); - let r = sext(self.lcx.tcx, r, ity); + let l = sext(self.tcx, l, ity); + let r = sext(self.tcx, r, ity); // Using / or %, where the left-hand argument is the smallest integer of a signed integer type and // the right-hand argument is -1 always panics, even with overflow-checks disabled @@ -751,7 +748,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { return None; } - let zext = |n: i128| Constant::Int(unsext(self.lcx.tcx, n, ity)); + let zext = |n: i128| Constant::Int(unsext(self.tcx, n, ity)); match op.node { // When +, * or binary - create a value greater than the maximum value, or less than // the minimum value that can be stored, it panics. @@ -845,7 +842,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { } } -pub fn mir_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) -> Option> { +pub fn mir_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: mir::Const<'tcx>) -> Option> { let mir::Const::Val(val, _) = result else { // We only work on evaluated consts. return None; @@ -863,13 +860,13 @@ pub fn mir_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) -> _ => None, }, (_, ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Str) => { - let data = val.try_get_slice_bytes_for_diagnostics(lcx.tcx)?; + let data = val.try_get_slice_bytes_for_diagnostics(tcx)?; String::from_utf8(data.to_owned()).ok().map(Constant::Str) }, (_, ty::Adt(adt_def, _)) if adt_def.is_struct() => Some(Constant::Adt(result)), (ConstValue::Indirect { alloc_id, offset }, ty::Array(sub_type, len)) => { - let alloc = lcx.tcx.global_alloc(alloc_id).unwrap_memory().inner(); - let len = len.try_to_target_usize(lcx.tcx)?; + let alloc = tcx.global_alloc(alloc_id).unwrap_memory().inner(); + let len = len.try_to_target_usize(tcx)?; let ty::Float(flt) = sub_type.kind() else { return None; }; @@ -877,7 +874,7 @@ pub fn mir_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) -> let mut res = Vec::new(); for idx in 0..len { let range = alloc_range(offset + size * idx, size); - let val = alloc.read_scalar(&lcx.tcx, range, /* read_provenance */ false).ok()?; + let val = alloc.read_scalar(&tcx, range, /* read_provenance */ false).ok()?; res.push(match flt { FloatTy::F16 => Constant::F16(f16::from_bits(val.to_u16().ok()?)), FloatTy::F32 => Constant::F32(f32::from_bits(val.to_u32().ok()?)), @@ -891,7 +888,7 @@ pub fn mir_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) -> } } -fn mir_is_empty<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) -> Option { +fn mir_is_empty<'tcx>(tcx: TyCtxt<'tcx>, result: mir::Const<'tcx>) -> Option { let mir::Const::Val(val, _) = result else { // We only work on evaluated consts. return None; @@ -902,26 +899,26 @@ fn mir_is_empty<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) -> Opti if let ConstValue::Indirect { alloc_id, offset } = val { // Get the length from the slice, using the same formula as // [`ConstValue::try_get_slice_bytes_for_diagnostics`]. - let a = lcx.tcx.global_alloc(alloc_id).unwrap_memory().inner(); - let ptr_size = lcx.tcx.data_layout.pointer_size; + let a = tcx.global_alloc(alloc_id).unwrap_memory().inner(); + let ptr_size = tcx.data_layout.pointer_size; if a.size() < offset + 2 * ptr_size { // (partially) dangling reference return None; } let len = a - .read_scalar(&lcx.tcx, alloc_range(offset + ptr_size, ptr_size), false) + .read_scalar(&tcx, alloc_range(offset + ptr_size, ptr_size), false) .ok()? - .to_target_usize(&lcx.tcx) + .to_target_usize(&tcx) .ok()?; Some(len == 0) } else { None } }, - ty::Array(_, len) => Some(len.try_to_target_usize(lcx.tcx)? == 0), + ty::Array(_, len) => Some(len.try_to_target_usize(tcx)? == 0), _ => None, }, - (ConstValue::Indirect { .. }, ty::Array(_, len)) => Some(len.try_to_target_usize(lcx.tcx)? == 0), + (ConstValue::Indirect { .. }, ty::Array(_, len)) => Some(len.try_to_target_usize(tcx)? == 0), (ConstValue::ZeroSized, _) => Some(true), _ => None, } @@ -929,12 +926,12 @@ fn mir_is_empty<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) -> Opti fn field_of_struct<'tcx>( adt_def: ty::AdtDef<'tcx>, - lcx: &LateContext<'tcx>, + tcx: TyCtxt<'tcx>, result: mir::Const<'tcx>, field: &Ident, ) -> Option> { if let mir::Const::Val(result, ty) = result - && let Some(dc) = lcx.tcx.try_destructure_mir_constant_for_user_output(result, ty) + && let Some(dc) = tcx.try_destructure_mir_constant_for_user_output(result, ty) && let Some(dc_variant) = dc.variant && let Some(variant) = adt_def.variants().get(dc_variant) && let Some(field_idx) = variant.fields.iter().position(|el| el.name == field.name) diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 86506d33d9f37..d43b15fc58aee 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -1577,7 +1577,7 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti if let rustc_ty::Adt(_, subst) = ty.kind() && let bnd_ty = subst.type_at(0) && let Some(min_val) = bnd_ty.numeric_min_val(cx.tcx) - && let Some(min_const) = mir_to_const(cx, Const::from_ty_const(min_val, bnd_ty, cx.tcx)) + && let Some(min_const) = mir_to_const(cx.tcx, Const::from_ty_const(min_val, bnd_ty, cx.tcx)) && let Some(start_const) = constant(cx, cx.typeck_results(), start) { start_const == min_const @@ -1590,7 +1590,7 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti if let rustc_ty::Adt(_, subst) = ty.kind() && let bnd_ty = subst.type_at(0) && let Some(max_val) = bnd_ty.numeric_max_val(cx.tcx) - && let Some(max_const) = mir_to_const(cx, Const::from_ty_const(max_val, bnd_ty, cx.tcx)) + && let Some(max_const) = mir_to_const(cx.tcx, Const::from_ty_const(max_val, bnd_ty, cx.tcx)) && let Some(end_const) = constant(cx, cx.typeck_results(), end) { end_const == max_const From e4ad36d6a8c0d2947a3ce05959b6a30cf695d8df Mon Sep 17 00:00:00 2001 From: Jason Newcomb Date: Thu, 1 Aug 2024 00:36:21 -0400 Subject: [PATCH 645/786] Require `ConstEvalCtxt` to be constructed. --- clippy_lints/src/assertions_on_constants.rs | 4 +- clippy_lints/src/casts/cast_nan_to_int.rs | 4 +- .../src/casts/cast_possible_truncation.rs | 4 +- clippy_lints/src/casts/cast_sign_loss.rs | 6 +- clippy_lints/src/floating_point_arithmetic.rs | 30 +-- clippy_lints/src/if_not_else.rs | 4 +- clippy_lints/src/implicit_saturating_add.rs | 8 +- clippy_lints/src/index_refutable_slice.rs | 4 +- clippy_lints/src/indexing_slicing.rs | 9 +- .../src/invalid_upcast_comparisons.rs | 4 +- .../src/loops/while_immutable_condition.rs | 4 +- clippy_lints/src/manual_clamp.rs | 7 +- clippy_lints/src/manual_float_methods.rs | 7 +- clippy_lints/src/manual_rem_euclid.rs | 4 +- clippy_lints/src/manual_rotate.rs | 4 +- clippy_lints/src/manual_strip.rs | 4 +- clippy_lints/src/matches/manual_unwrap_or.rs | 4 +- clippy_lints/src/matches/overlapping_arms.rs | 12 +- .../src/methods/is_digit_ascii_radix.rs | 4 +- clippy_lints/src/methods/is_empty.rs | 4 +- clippy_lints/src/methods/iter_nth_zero.rs | 4 +- clippy_lints/src/methods/iter_skip_zero.rs | 4 +- .../src/methods/iterator_step_by_zero.rs | 4 +- clippy_lints/src/methods/mod.rs | 6 +- clippy_lints/src/methods/repeat_once.rs | 4 +- clippy_lints/src/methods/str_splitn.rs | 4 +- .../src/methods/unnecessary_min_or_max.rs | 13 +- clippy_lints/src/minmax.rs | 20 +- .../operators/absurd_extreme_comparisons.rs | 4 +- .../src/operators/arithmetic_side_effects.rs | 10 +- clippy_lints/src/operators/bit_mask.rs | 4 +- .../src/operators/const_comparisons.rs | 5 +- clippy_lints/src/operators/duration_subsec.rs | 4 +- clippy_lints/src/operators/erasing_op.rs | 4 +- clippy_lints/src/operators/float_cmp.rs | 8 +- clippy_lints/src/operators/identity_op.rs | 13 +- .../src/operators/modulo_arithmetic.rs | 16 +- .../src/operators/numeric_arithmetic.rs | 4 +- clippy_lints/src/ranges.rs | 11 +- clippy_lints/src/regex.rs | 4 +- clippy_lints/src/repeat_vec_with_capacity.rs | 4 +- .../src/transmute/transmute_null_to_fn.rs | 7 +- .../src/transmute/transmuting_null.rs | 4 +- .../interning_defined_symbol.rs | 6 +- .../src/utils/internal_lints/invalid_paths.rs | 8 +- clippy_lints/src/vec.rs | 4 +- clippy_lints/src/zero_div_zero.rs | 7 +- clippy_utils/src/consts.rs | 184 +++++++++--------- clippy_utils/src/eager_or_lazy.rs | 16 +- clippy_utils/src/higher.rs | 4 +- clippy_utils/src/hir_utils.rs | 12 +- clippy_utils/src/lib.rs | 10 +- 52 files changed, 267 insertions(+), 276 deletions(-) diff --git a/clippy_lints/src/assertions_on_constants.rs b/clippy_lints/src/assertions_on_constants.rs index ed4cdce8cb886..7eaac80f969f7 100644 --- a/clippy_lints/src/assertions_on_constants.rs +++ b/clippy_lints/src/assertions_on_constants.rs @@ -1,4 +1,4 @@ -use clippy_utils::consts::{constant, Constant}; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::is_inside_always_const_context; use clippy_utils::macros::{find_assert_args, root_macro_call_first_node, PanicExpn}; @@ -43,7 +43,7 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnConstants { let Some((condition, panic_expn)) = find_assert_args(cx, e, macro_call.expn) else { return; }; - let Some(Constant::Bool(val)) = constant(cx, cx.typeck_results(), condition) else { + let Some(Constant::Bool(val)) = ConstEvalCtxt::new(cx).eval(condition) else { return; }; diff --git a/clippy_lints/src/casts/cast_nan_to_int.rs b/clippy_lints/src/casts/cast_nan_to_int.rs index 5bc8692c289f7..464eabe5d9ab7 100644 --- a/clippy_lints/src/casts/cast_nan_to_int.rs +++ b/clippy_lints/src/casts/cast_nan_to_int.rs @@ -1,6 +1,6 @@ use super::CAST_NAN_TO_INT; -use clippy_utils::consts::{constant, Constant}; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_and_note; use rustc_hir::Expr; use rustc_lint::LateContext; @@ -20,7 +20,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, } fn is_known_nan(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { - match constant(cx, cx.typeck_results(), e) { + match ConstEvalCtxt::new(cx).eval(e) { // FIXME(f16_f128): add these types when nan checks are available on all platforms Some(Constant::F64(n)) => n.is_nan(), Some(Constant::F32(n)) => n.is_nan(), diff --git a/clippy_lints/src/casts/cast_possible_truncation.rs b/clippy_lints/src/casts/cast_possible_truncation.rs index 7c5acd1a678d7..102fe25fc67b0 100644 --- a/clippy_lints/src/casts/cast_possible_truncation.rs +++ b/clippy_lints/src/casts/cast_possible_truncation.rs @@ -1,4 +1,4 @@ -use clippy_utils::consts::{constant, Constant}; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; use clippy_utils::expr_or_init; use clippy_utils::source::snippet; @@ -15,7 +15,7 @@ use rustc_target::abi::IntegerType; use super::{utils, CAST_ENUM_TRUNCATION, CAST_POSSIBLE_TRUNCATION}; fn constant_int(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option { - if let Some(Constant::Int(c)) = constant(cx, cx.typeck_results(), expr) { + if let Some(Constant::Int(c)) = ConstEvalCtxt::new(cx).eval(expr) { Some(c) } else { None diff --git a/clippy_lints/src/casts/cast_sign_loss.rs b/clippy_lints/src/casts/cast_sign_loss.rs index 8bbd41b0db1ee..9daf237344a4b 100644 --- a/clippy_lints/src/casts/cast_sign_loss.rs +++ b/clippy_lints/src/casts/cast_sign_loss.rs @@ -1,7 +1,7 @@ use std::convert::Infallible; use std::ops::ControlFlow; -use clippy_utils::consts::{constant, Constant}; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint; use clippy_utils::visitors::{for_each_expr_without_closures, Descend}; use clippy_utils::{method_chain_args, sext}; @@ -88,7 +88,7 @@ fn get_const_signed_int_eval<'cx>( ) -> Option { let ty = ty.into().unwrap_or_else(|| cx.typeck_results().expr_ty(expr)); - if let Constant::Int(n) = constant(cx, cx.typeck_results(), expr)? + if let Constant::Int(n) = ConstEvalCtxt::new(cx).eval(expr)? && let ty::Int(ity) = *ty.kind() { return Some(sext(cx.tcx, n, ity)); @@ -103,7 +103,7 @@ fn get_const_unsigned_int_eval<'cx>( ) -> Option { let ty = ty.into().unwrap_or_else(|| cx.typeck_results().expr_ty(expr)); - if let Constant::Int(n) = constant(cx, cx.typeck_results(), expr)? + if let Constant::Int(n) = ConstEvalCtxt::new(cx).eval(expr)? && let ty::Uint(_ity) = *ty.kind() { return Some(n); diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index 68bdf88d0a7e4..16778a35bb751 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -1,5 +1,5 @@ use clippy_utils::consts::Constant::{Int, F32, F64}; -use clippy_utils::consts::{constant, constant_simple, Constant}; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::{ eq_expr_value, get_parent_expr, higher, in_constant, is_inherent_method_call, is_no_std_crate, numeric_literal, @@ -112,7 +112,7 @@ declare_lint_pass!(FloatingPointArithmetic => [ // Returns the specialized log method for a given base if base is constant // and is one of 2, 10 and e fn get_specialized_log_method(cx: &LateContext<'_>, base: &Expr<'_>) -> Option<&'static str> { - if let Some(value) = constant(cx, cx.typeck_results(), base) { + if let Some(value) = ConstEvalCtxt::new(cx).eval(base) { if F32(2.0) == value || F64(2.0) == value { return Some("log2"); } else if F32(10.0) == value || F64(10.0) == value { @@ -182,10 +182,8 @@ fn check_ln1p(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>) { rhs, ) = receiver.kind { - let recv = match ( - constant(cx, cx.typeck_results(), lhs), - constant(cx, cx.typeck_results(), rhs), - ) { + let ecx = ConstEvalCtxt::new(cx); + let recv = match (ecx.eval(lhs), ecx.eval(rhs)) { (Some(value), _) if F32(1.0) == value || F64(1.0) == value => rhs, (_, Some(value)) if F32(1.0) == value || F64(1.0) == value => lhs, _ => return, @@ -230,7 +228,7 @@ fn get_integer_from_float_constant(value: &Constant<'_>) -> Option { fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) { // Check receiver - if let Some(value) = constant(cx, cx.typeck_results(), receiver) { + if let Some(value) = ConstEvalCtxt::new(cx).eval(receiver) { if let Some(method) = if F32(f32_consts::E) == value || F64(f64_consts::E) == value { Some("exp") } else if F32(2.0) == value || F64(2.0) == value { @@ -251,7 +249,7 @@ fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: } // Check argument - if let Some(value) = constant(cx, cx.typeck_results(), &args[0]) { + if let Some(value) = ConstEvalCtxt::new(cx).eval(&args[0]) { let (lint, help, suggestion) = if F32(1.0 / 2.0) == value || F64(1.0 / 2.0) == value { ( SUBOPTIMAL_FLOPS, @@ -291,7 +289,7 @@ fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: } fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) { - if let Some(value) = constant(cx, cx.typeck_results(), &args[0]) { + if let Some(value) = ConstEvalCtxt::new(cx).eval(&args[0]) { if value == Int(2) { if let Some(parent) = get_parent_expr(cx, expr) { if let Some(grandparent) = get_parent_expr(cx, parent) { @@ -397,8 +395,9 @@ fn detect_hypot(cx: &LateContext<'_>, receiver: &Expr<'_>) -> Option { ) = &add_rhs.kind && lmethod_name.as_str() == "powi" && rmethod_name.as_str() == "powi" - && let Some(lvalue) = constant(cx, cx.typeck_results(), largs_1) - && let Some(rvalue) = constant(cx, cx.typeck_results(), rargs_1) + && let ecx = ConstEvalCtxt::new(cx) + && let Some(lvalue) = ecx.eval(largs_1) + && let Some(rvalue) = ecx.eval(rargs_1) && Int(2) == lvalue && Int(2) == rvalue { @@ -438,7 +437,7 @@ fn check_expm1(cx: &LateContext<'_>, expr: &Expr<'_>) { rhs, ) = expr.kind && cx.typeck_results().expr_ty(lhs).is_floating_point() - && let Some(value) = constant(cx, cx.typeck_results(), rhs) + && let Some(value) = ConstEvalCtxt::new(cx).eval(rhs) && (F32(1.0) == value || F64(1.0) == value) && let ExprKind::MethodCall(path, self_arg, ..) = &lhs.kind && cx.typeck_results().expr_ty(self_arg).is_floating_point() @@ -552,7 +551,7 @@ fn is_testing_negative(cx: &LateContext<'_>, expr: &Expr<'_>, test: &Expr<'_>) - /// Returns true iff expr is some zero literal fn is_zero(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { - match constant_simple(cx, cx.typeck_results(), expr) { + match ConstEvalCtxt::new(cx).eval_simple(expr) { Some(Int(i)) => i == 0, Some(F32(f)) => f == 0.0, Some(F64(f)) => f == 0.0, @@ -696,8 +695,9 @@ fn check_radians(cx: &LateContext<'_>, expr: &Expr<'_>) { mul_lhs, mul_rhs, ) = &div_lhs.kind - && let Some(rvalue) = constant(cx, cx.typeck_results(), div_rhs) - && let Some(lvalue) = constant(cx, cx.typeck_results(), mul_rhs) + && let ecx = ConstEvalCtxt::new(cx) + && let Some(rvalue) = ecx.eval(div_rhs) + && let Some(lvalue) = ecx.eval(mul_rhs) { // TODO: also check for constant values near PI/180 or 180/PI if (F32(f32_consts::PI) == rvalue || F64(f64_consts::PI) == rvalue) diff --git a/clippy_lints/src/if_not_else.rs b/clippy_lints/src/if_not_else.rs index 2f6daeeb90d9d..0ebd8d0c237b6 100644 --- a/clippy_lints/src/if_not_else.rs +++ b/clippy_lints/src/if_not_else.rs @@ -1,7 +1,7 @@ //! lint on if branches that could be swapped so no `!` operation is necessary //! on the condition -use clippy_utils::consts::{constant_simple, Constant}; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::is_else_clause; use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; @@ -49,7 +49,7 @@ declare_clippy_lint! { declare_lint_pass!(IfNotElse => [IF_NOT_ELSE]); fn is_zero_const(expr: &Expr<'_>, cx: &LateContext<'_>) -> bool { - if let Some(value) = constant_simple(cx, cx.typeck_results(), expr) { + if let Some(value) = ConstEvalCtxt::new(cx).eval_simple(expr) { return Constant::Int(0) == value; } false diff --git a/clippy_lints/src/implicit_saturating_add.rs b/clippy_lints/src/implicit_saturating_add.rs index f225c6e7f049f..dd5908553e59b 100644 --- a/clippy_lints/src/implicit_saturating_add.rs +++ b/clippy_lints/src/implicit_saturating_add.rs @@ -1,4 +1,4 @@ -use clippy_utils::consts::{constant, Constant}; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::get_parent_expr; use clippy_utils::source::snippet_with_context; @@ -117,11 +117,11 @@ fn get_int_max(ty: Ty<'_>) -> Option { fn get_const<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> Option<(u128, BinOpKind, &'tcx Expr<'tcx>)> { if let ExprKind::Binary(op, l, r) = expr.kind { - let tr = cx.typeck_results(); - if let Some(Constant::Int(c)) = constant(cx, tr, r) { + let ecx = ConstEvalCtxt::new(cx); + if let Some(Constant::Int(c)) = ecx.eval(r) { return Some((c, op.node, l)); }; - if let Some(Constant::Int(c)) = constant(cx, tr, l) { + if let Some(Constant::Int(c)) = ecx.eval(l) { return Some((c, invert_op(op.node)?, r)); } } diff --git a/clippy_lints/src/index_refutable_slice.rs b/clippy_lints/src/index_refutable_slice.rs index 526b4e1fba0e9..2f9661c9ea385 100644 --- a/clippy_lints/src/index_refutable_slice.rs +++ b/clippy_lints/src/index_refutable_slice.rs @@ -1,6 +1,6 @@ use clippy_config::msrvs::{self, Msrv}; use clippy_config::Conf; -use clippy_utils::consts::{constant, Constant}; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::higher::IfLet; use clippy_utils::ty::is_copy; @@ -246,7 +246,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SliceIndexLintingVisitor<'a, 'tcx> { && let parent_id = cx.tcx.parent_hir_id(expr.hir_id) && let hir::Node::Expr(parent_expr) = cx.tcx.hir_node(parent_id) && let hir::ExprKind::Index(_, index_expr, _) = parent_expr.kind - && let Some(Constant::Int(index_value)) = constant(cx, cx.typeck_results(), index_expr) + && let Some(Constant::Int(index_value)) = ConstEvalCtxt::new(cx).eval(index_expr) && let Ok(index_value) = index_value.try_into() && index_value < max_suggested_slice diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs index 3b65901c165a6..3ac50b8f1fba5 100644 --- a/clippy_lints/src/indexing_slicing.rs +++ b/clippy_lints/src/indexing_slicing.rs @@ -1,7 +1,7 @@ //! lint on indexing and slicing operations use clippy_config::Conf; -use clippy_utils::consts::{constant, Constant}; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; use clippy_utils::ty::{deref_chain, get_adt_inherent_method}; use clippy_utils::{higher, is_from_proc_macro}; @@ -177,7 +177,7 @@ impl<'tcx> LateLintPass<'tcx> for IndexingSlicing { return; } // Index is a constant uint. - if let Some(constant) = constant(cx, cx.typeck_results(), index) { + if let Some(constant) = ConstEvalCtxt::new(cx).eval(index) { // only `usize` index is legal in rust array index // leave other type to rustc if let Constant::Int(off) = constant @@ -215,14 +215,15 @@ impl<'tcx> LateLintPass<'tcx> for IndexingSlicing { /// Returns a tuple of options with the start and end (exclusive) values of /// the range. If the start or end is not constant, None is returned. fn to_const_range(cx: &LateContext<'_>, range: higher::Range<'_>, array_size: u128) -> (Option, Option) { - let s = range.start.map(|expr| constant(cx, cx.typeck_results(), expr)); + let ecx = ConstEvalCtxt::new(cx); + let s = range.start.map(|expr| ecx.eval(expr)); let start = match s { Some(Some(Constant::Int(x))) => Some(x), Some(_) => None, None => Some(0), }; - let e = range.end.map(|expr| constant(cx, cx.typeck_results(), expr)); + let e = range.end.map(|expr| ecx.eval(expr)); let end = match e { Some(Some(Constant::Int(x))) => { if range.limits == RangeLimits::Closed { diff --git a/clippy_lints/src/invalid_upcast_comparisons.rs b/clippy_lints/src/invalid_upcast_comparisons.rs index 30f2285bdd235..1929fbded3b56 100644 --- a/clippy_lints/src/invalid_upcast_comparisons.rs +++ b/clippy_lints/src/invalid_upcast_comparisons.rs @@ -7,7 +7,7 @@ use rustc_span::Span; use clippy_utils::comparisons; use clippy_utils::comparisons::Rel; -use clippy_utils::consts::{constant_full_int, FullInt}; +use clippy_utils::consts::{ConstEvalCtxt, FullInt}; use clippy_utils::diagnostics::span_lint; use clippy_utils::source::snippet; @@ -95,7 +95,7 @@ fn upcast_comparison_bounds_err<'tcx>( invert: bool, ) { if let Some((lb, ub)) = lhs_bounds { - if let Some(norm_rhs_val) = constant_full_int(cx, cx.typeck_results(), rhs) { + if let Some(norm_rhs_val) = ConstEvalCtxt::new(cx).eval_full_int(rhs) { if rel == Rel::Eq || rel == Rel::Ne { if norm_rhs_val < lb || norm_rhs_val > ub { err_upcast_comparison(cx, span, lhs, rel == Rel::Ne); diff --git a/clippy_lints/src/loops/while_immutable_condition.rs b/clippy_lints/src/loops/while_immutable_condition.rs index e7b3a2c4973cf..cc1bd5929d0fc 100644 --- a/clippy_lints/src/loops/while_immutable_condition.rs +++ b/clippy_lints/src/loops/while_immutable_condition.rs @@ -1,5 +1,5 @@ use super::WHILE_IMMUTABLE_CONDITION; -use clippy_utils::consts::constant; +use clippy_utils::consts::ConstEvalCtxt; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::usage::mutated_variables; use rustc_hir::def::{DefKind, Res}; @@ -10,7 +10,7 @@ use rustc_lint::LateContext; use std::ops::ControlFlow; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, cond: &'tcx Expr<'_>, expr: &'tcx Expr<'_>) { - if constant(cx, cx.typeck_results(), cond).is_some() { + if ConstEvalCtxt::new(cx).eval(cond).is_some() { // A pure constant condition (e.g., `while false`) is not linted. return; } diff --git a/clippy_lints/src/manual_clamp.rs b/clippy_lints/src/manual_clamp.rs index a79ad018a042f..4e0b12f8d13f2 100644 --- a/clippy_lints/src/manual_clamp.rs +++ b/clippy_lints/src/manual_clamp.rs @@ -1,6 +1,6 @@ use clippy_config::msrvs::{self, Msrv}; use clippy_config::Conf; -use clippy_utils::consts::{constant, Constant}; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then}; use clippy_utils::higher::If; use clippy_utils::sugg::Sugg; @@ -122,8 +122,9 @@ impl<'tcx> ClampSuggestion<'tcx> { if max_type != min_type { return false; } - if let Some(max) = constant(cx, cx.typeck_results(), self.params.max) - && let Some(min) = constant(cx, cx.typeck_results(), self.params.min) + let ecx = ConstEvalCtxt::new(cx); + if let Some(max) = ecx.eval(self.params.max) + && let Some(min) = ecx.eval(self.params.min) && let Some(ord) = Constant::partial_cmp(cx.tcx, max_type, &min, &max) { ord != Ordering::Greater diff --git a/clippy_lints/src/manual_float_methods.rs b/clippy_lints/src/manual_float_methods.rs index 03416ba96de73..6bdc79129a9bc 100644 --- a/clippy_lints/src/manual_float_methods.rs +++ b/clippy_lints/src/manual_float_methods.rs @@ -1,4 +1,4 @@ -use clippy_utils::consts::{constant, Constant}; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet_opt; use clippy_utils::{is_from_proc_macro, path_to_local}; @@ -95,8 +95,9 @@ impl<'tcx> LateLintPass<'tcx> for ManualFloatMethods { || cx.tcx.features().declared(sym!(const_float_classify)) ) && let [first, second, const_1, const_2] = exprs - && let Some(const_1) = constant(cx, cx.typeck_results(), const_1) - && let Some(const_2) = constant(cx, cx.typeck_results(), const_2) + && let ecx = ConstEvalCtxt::new(cx) + && let Some(const_1) = ecx.eval(const_1) + && let Some(const_2) = ecx.eval(const_2) && path_to_local(first).is_some_and(|f| path_to_local(second).is_some_and(|s| f == s)) // The actual infinity check, we also allow `NEG_INFINITY` before` INFINITY` just in // case somebody does that for some reason diff --git a/clippy_lints/src/manual_rem_euclid.rs b/clippy_lints/src/manual_rem_euclid.rs index 78a750f0dcd04..c5eb1e1384f71 100644 --- a/clippy_lints/src/manual_rem_euclid.rs +++ b/clippy_lints/src/manual_rem_euclid.rs @@ -1,6 +1,6 @@ use clippy_config::msrvs::{self, Msrv}; use clippy_config::Conf; -use clippy_utils::consts::{constant_full_int, FullInt}; +use clippy_utils::consts::{ConstEvalCtxt, FullInt}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_context; use clippy_utils::{in_constant, path_to_local}; @@ -117,7 +117,7 @@ fn check_for_either_unsigned_int_constant<'a>( } fn check_for_unsigned_int_constant<'a>(cx: &'a LateContext<'_>, expr: &'a Expr<'_>) -> Option { - let int_const = constant_full_int(cx, cx.typeck_results(), expr)?; + let int_const = ConstEvalCtxt::new(cx).eval_full_int(expr)?; match int_const { FullInt::S(s) => s.try_into().ok(), FullInt::U(u) => Some(u), diff --git a/clippy_lints/src/manual_rotate.rs b/clippy_lints/src/manual_rotate.rs index a517a4d507526..07537fc65c08c 100644 --- a/clippy_lints/src/manual_rotate.rs +++ b/clippy_lints/src/manual_rotate.rs @@ -1,6 +1,6 @@ use std::fmt::Display; -use clippy_utils::consts::{constant, Constant}; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::sugg; use rustc_errors::Applicability; @@ -66,7 +66,7 @@ fn parse_shift<'tcx>( BinOpKind::Shr => ShiftDirection::Right, _ => return None, }; - let const_expr = constant(cx, cx.typeck_results(), r)?; + let const_expr = ConstEvalCtxt::new(cx).eval(r)?; if let Constant::Int(shift) = const_expr { return Some((dir, shift, l)); } diff --git a/clippy_lints/src/manual_strip.rs b/clippy_lints/src/manual_strip.rs index 324ad25752ad2..85cabd2800a65 100644 --- a/clippy_lints/src/manual_strip.rs +++ b/clippy_lints/src/manual_strip.rs @@ -1,6 +1,6 @@ use clippy_config::msrvs::{self, Msrv}; use clippy_config::Conf; -use clippy_utils::consts::{constant, Constant}; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet; use clippy_utils::usage::mutated_variables; @@ -147,7 +147,7 @@ fn len_arg<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx E // Returns the length of the `expr` if it's a constant string or char. fn constant_length(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option { - let value = constant(cx, cx.typeck_results(), expr)?; + let value = ConstEvalCtxt::new(cx).eval(expr)?; match value { Constant::Str(value) => Some(value.len() as u128), Constant::Char(value) => Some(value.len_utf8() as u128), diff --git a/clippy_lints/src/matches/manual_unwrap_or.rs b/clippy_lints/src/matches/manual_unwrap_or.rs index 85a08f81c2f34..2d4c8daf5cb66 100644 --- a/clippy_lints/src/matches/manual_unwrap_or.rs +++ b/clippy_lints/src/matches/manual_unwrap_or.rs @@ -1,4 +1,4 @@ -use clippy_utils::consts::constant_simple; +use clippy_utils::consts::ConstEvalCtxt; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt}; use clippy_utils::ty::is_type_diagnostic_item; @@ -69,7 +69,7 @@ fn check_and_lint<'tcx>( && let Some(ty_name) = find_type_name(cx, ty) && let Some(or_body_snippet) = snippet_opt(cx, else_expr.span) && let Some(indent) = indent_of(cx, expr.span) - && constant_simple(cx, cx.typeck_results(), else_expr).is_some() + && ConstEvalCtxt::new(cx).eval_simple(else_expr).is_some() { lint(cx, expr, let_expr, ty_name, or_body_snippet, indent); } diff --git a/clippy_lints/src/matches/overlapping_arms.rs b/clippy_lints/src/matches/overlapping_arms.rs index 4a6741da45f72..71f211be925bf 100644 --- a/clippy_lints/src/matches/overlapping_arms.rs +++ b/clippy_lints/src/matches/overlapping_arms.rs @@ -1,4 +1,4 @@ -use clippy_utils::consts::{constant, constant_full_int, mir_to_const, FullInt}; +use clippy_utils::consts::{mir_to_const, ConstEvalCtxt, FullInt}; use clippy_utils::diagnostics::span_lint_and_note; use core::cmp::Ordering; use rustc_hir::{Arm, Expr, PatKind, RangeEnd}; @@ -34,19 +34,19 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>) if let Arm { pat, guard: None, .. } = *arm { if let PatKind::Range(ref lhs, ref rhs, range_end) = pat.kind { let lhs_const = if let Some(lhs) = lhs { - constant(cx, cx.typeck_results(), lhs)? + ConstEvalCtxt::new(cx).eval(lhs)? } else { let min_val_const = ty.numeric_min_val(cx.tcx)?; mir_to_const(cx.tcx, mir::Const::from_ty_const(min_val_const, ty, cx.tcx))? }; let rhs_const = if let Some(rhs) = rhs { - constant(cx, cx.typeck_results(), rhs)? + ConstEvalCtxt::new(cx).eval(rhs)? } else { let max_val_const = ty.numeric_max_val(cx.tcx)?; mir_to_const(cx.tcx, mir::Const::from_ty_const(max_val_const, ty, cx.tcx))? }; - let lhs_val = lhs_const.int_value(cx, ty)?; - let rhs_val = rhs_const.int_value(cx, ty)?; + let lhs_val = lhs_const.int_value(cx.tcx, ty)?; + let rhs_val = rhs_const.int_value(cx.tcx, ty)?; let rhs_bound = match range_end { RangeEnd::Included => EndBound::Included(rhs_val), RangeEnd::Excluded => EndBound::Excluded(rhs_val), @@ -58,7 +58,7 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>) } if let PatKind::Lit(value) = pat.kind { - let value = constant_full_int(cx, cx.typeck_results(), value)?; + let value = ConstEvalCtxt::new(cx).eval_full_int(value)?; return Some(SpannedRange { span: pat.span, node: (value, EndBound::Included(value)), diff --git a/clippy_lints/src/methods/is_digit_ascii_radix.rs b/clippy_lints/src/methods/is_digit_ascii_radix.rs index 210e4ae0a7bc0..22d896433f07a 100644 --- a/clippy_lints/src/methods/is_digit_ascii_radix.rs +++ b/clippy_lints/src/methods/is_digit_ascii_radix.rs @@ -2,7 +2,7 @@ use super::IS_DIGIT_ASCII_RADIX; use clippy_config::msrvs::{self, Msrv}; -use clippy_utils::consts::{constant_full_int, FullInt}; +use clippy_utils::consts::{ConstEvalCtxt, FullInt}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use rustc_errors::Applicability; @@ -24,7 +24,7 @@ pub(super) fn check<'tcx>( return; } - if let Some(radix_val) = constant_full_int(cx, cx.typeck_results(), radix) { + if let Some(radix_val) = ConstEvalCtxt::new(cx).eval_full_int(radix) { let (num, replacement) = match radix_val { FullInt::S(10) | FullInt::U(10) => (10, "is_ascii_digit"), FullInt::S(16) | FullInt::U(16) => (16, "is_ascii_hexdigit"), diff --git a/clippy_lints/src/methods/is_empty.rs b/clippy_lints/src/methods/is_empty.rs index d921b7ea14f5d..cc82f6cfd6384 100644 --- a/clippy_lints/src/methods/is_empty.rs +++ b/clippy_lints/src/methods/is_empty.rs @@ -1,4 +1,4 @@ -use clippy_utils::consts::constant_is_empty; +use clippy_utils::consts::ConstEvalCtxt; use clippy_utils::diagnostics::span_lint; use clippy_utils::{find_binding_init, path_to_local}; use rustc_hir::{Expr, HirId}; @@ -18,7 +18,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &'_ Expr<'_>, receiver: &Expr<'_ if !receiver.span.eq_ctxt(init_expr.span) { return; } - if let Some(init_is_empty) = constant_is_empty(cx, init_expr) { + if let Some(init_is_empty) = ConstEvalCtxt::new(cx).eval_is_empty(init_expr) { span_lint( cx, CONST_IS_EMPTY, diff --git a/clippy_lints/src/methods/iter_nth_zero.rs b/clippy_lints/src/methods/iter_nth_zero.rs index 262a57ab591a6..9ff6eaa348710 100644 --- a/clippy_lints/src/methods/iter_nth_zero.rs +++ b/clippy_lints/src/methods/iter_nth_zero.rs @@ -1,4 +1,4 @@ -use clippy_utils::consts::{constant, Constant}; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::{is_lang_item_or_ctor, is_trait_method}; @@ -14,7 +14,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr if let OwnerNode::Item(item) = cx.tcx.hir_owner_node(cx.tcx.hir().get_parent_item(expr.hir_id)) && let def_id = item.owner_id.to_def_id() && is_trait_method(cx, expr, sym::Iterator) - && let Some(Constant::Int(0)) = constant(cx, cx.typeck_results(), arg) + && let Some(Constant::Int(0)) = ConstEvalCtxt::new(cx).eval(arg) && !is_lang_item_or_ctor(cx, def_id, LangItem::IteratorNext) { let mut app = Applicability::MachineApplicable; diff --git a/clippy_lints/src/methods/iter_skip_zero.rs b/clippy_lints/src/methods/iter_skip_zero.rs index 6b696b42a6931..39e440e784f6d 100644 --- a/clippy_lints/src/methods/iter_skip_zero.rs +++ b/clippy_lints/src/methods/iter_skip_zero.rs @@ -1,4 +1,4 @@ -use clippy_utils::consts::{constant, Constant}; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::{is_from_proc_macro, is_trait_method}; use rustc_errors::Applicability; @@ -11,7 +11,7 @@ use super::ITER_SKIP_ZERO; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, arg_expr: &Expr<'_>) { if !expr.span.from_expansion() && is_trait_method(cx, expr, sym::Iterator) - && let Some(arg) = constant(cx, cx.typeck_results(), arg_expr).and_then(|constant| { + && let Some(arg) = ConstEvalCtxt::new(cx).eval(arg_expr).and_then(|constant| { if let Constant::Int(arg) = constant { Some(arg) } else { diff --git a/clippy_lints/src/methods/iterator_step_by_zero.rs b/clippy_lints/src/methods/iterator_step_by_zero.rs index b631cd00cda43..9b358235a40df 100644 --- a/clippy_lints/src/methods/iterator_step_by_zero.rs +++ b/clippy_lints/src/methods/iterator_step_by_zero.rs @@ -1,4 +1,4 @@ -use clippy_utils::consts::{constant, Constant}; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint; use clippy_utils::is_trait_method; use rustc_hir as hir; @@ -9,7 +9,7 @@ use super::ITERATOR_STEP_BY_ZERO; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, arg: &'tcx hir::Expr<'_>) { if is_trait_method(cx, expr, sym::Iterator) { - if let Some(Constant::Int(0)) = constant(cx, cx.typeck_results(), arg) { + if let Some(Constant::Int(0)) = ConstEvalCtxt::new(cx).eval(arg) { span_lint( cx, ITERATOR_STEP_BY_ZERO, diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 1a7fda6a36439..1d7b10fe8f045 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -133,7 +133,7 @@ mod zst_offset; use clippy_config::msrvs::{self, Msrv}; use clippy_config::Conf; -use clippy_utils::consts::{constant, Constant}; +use clippy_utils::consts::{ConstEvalCtxt, 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}; @@ -4915,13 +4915,13 @@ impl Methods { str_split::check(cx, expr, recv, arg); }, ("splitn" | "rsplitn", [count_arg, pat_arg]) => { - if let Some(Constant::Int(count)) = constant(cx, cx.typeck_results(), count_arg) { + if let Some(Constant::Int(count)) = ConstEvalCtxt::new(cx).eval(count_arg) { suspicious_splitn::check(cx, name, expr, recv, count); str_splitn::check(cx, name, expr, recv, pat_arg, count, &self.msrv); } }, ("splitn_mut" | "rsplitn_mut", [count_arg, _]) => { - if let Some(Constant::Int(count)) = constant(cx, cx.typeck_results(), count_arg) { + if let Some(Constant::Int(count)) = ConstEvalCtxt::new(cx).eval(count_arg) { suspicious_splitn::check(cx, name, expr, recv, count); } }, diff --git a/clippy_lints/src/methods/repeat_once.rs b/clippy_lints/src/methods/repeat_once.rs index bb4cdd2a6fa10..7837517ed5d8a 100644 --- a/clippy_lints/src/methods/repeat_once.rs +++ b/clippy_lints/src/methods/repeat_once.rs @@ -1,4 +1,4 @@ -use clippy_utils::consts::{constant, Constant}; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet; use clippy_utils::ty::is_type_lang_item; @@ -14,7 +14,7 @@ pub(super) fn check<'tcx>( recv: &'tcx Expr<'_>, repeat_arg: &'tcx Expr<'_>, ) { - if constant(cx, cx.typeck_results(), repeat_arg) == Some(Constant::Int(1)) { + if ConstEvalCtxt::new(cx).eval(repeat_arg) == Some(Constant::Int(1)) { let ty = cx.typeck_results().expr_ty(recv).peel_refs(); if ty.is_str() { span_lint_and_sugg( diff --git a/clippy_lints/src/methods/str_splitn.rs b/clippy_lints/src/methods/str_splitn.rs index 4f42fb73547a7..12cabd43cb1b2 100644 --- a/clippy_lints/src/methods/str_splitn.rs +++ b/clippy_lints/src/methods/str_splitn.rs @@ -1,5 +1,5 @@ use clippy_config::msrvs::{self, Msrv}; -use clippy_utils::consts::{constant, Constant}; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::source::snippet_with_context; use clippy_utils::usage::local_used_after_expr; @@ -301,7 +301,7 @@ fn parse_iter_usage<'tcx>( }; }, ("nth" | "skip", [idx_expr]) if cx.tcx.trait_of_item(did) == Some(iter_id) => { - if let Some(Constant::Int(idx)) = constant(cx, cx.typeck_results(), idx_expr) { + if let Some(Constant::Int(idx)) = ConstEvalCtxt::new(cx).eval(idx_expr) { let span = if name.ident.as_str() == "nth" { e.span } else if let Some((_, Node::Expr(next_expr))) = iter.next() diff --git a/clippy_lints/src/methods/unnecessary_min_or_max.rs b/clippy_lints/src/methods/unnecessary_min_or_max.rs index 78851d4122f12..86c0a6322b666 100644 --- a/clippy_lints/src/methods/unnecessary_min_or_max.rs +++ b/clippy_lints/src/methods/unnecessary_min_or_max.rs @@ -3,7 +3,7 @@ use std::cmp::Ordering; use super::UNNECESSARY_MIN_OR_MAX; use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::consts::{constant, constant_with_source, Constant, ConstantSource, FullInt}; +use clippy_utils::consts::{ConstEvalCtxt, Constant, ConstantSource, FullInt}; use clippy_utils::source::snippet; use rustc_errors::Applicability; @@ -20,10 +20,9 @@ pub(super) fn check<'tcx>( arg: &'tcx Expr<'_>, ) { let typeck_results = cx.typeck_results(); - if let Some((left, ConstantSource::Local | ConstantSource::CoreConstant)) = - constant_with_source(cx, typeck_results, recv) - && let Some((right, ConstantSource::Local | ConstantSource::CoreConstant)) = - constant_with_source(cx, typeck_results, arg) + let ecx = ConstEvalCtxt::with_env(cx.tcx, cx.param_env, typeck_results); + if let Some((left, ConstantSource::Local | ConstantSource::CoreConstant)) = ecx.eval_with_source(recv) + && let Some((right, ConstantSource::Local | ConstantSource::CoreConstant)) = ecx.eval_with_source(arg) { let Some(ord) = Constant::partial_cmp(cx.tcx, typeck_results.expr_ty(recv), &left, &right) else { return; @@ -78,9 +77,9 @@ enum Extrema { fn detect_extrema<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option { let ty = cx.typeck_results().expr_ty(expr); - let cv = constant(cx, cx.typeck_results(), expr)?; + let cv = ConstEvalCtxt::new(cx).eval(expr)?; - match (cv.int_value(cx, ty)?, ty.kind()) { + match (cv.int_value(cx.tcx, ty)?, ty.kind()) { (FullInt::S(i), &ty::Int(ity)) if i == i128::MIN >> (128 - ity.bit_width()?) => Some(Extrema::Minimum), (FullInt::S(i), &ty::Int(ity)) if i == i128::MAX >> (128 - ity.bit_width()?) => Some(Extrema::Maximum), (FullInt::U(i), &ty::Uint(uty)) if i == u128::MAX >> (128 - uty.bit_width()?) => Some(Extrema::Maximum), diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index c3fbca1d560e6..e95864c6db8b5 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -1,4 +1,4 @@ -use clippy_utils::consts::{constant_simple, Constant}; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint; use clippy_utils::is_trait_method; use rustc_hir::{Expr, ExprKind}; @@ -106,15 +106,11 @@ fn fetch_const<'a, 'tcx>( if args.next().is_some() { return None; } - constant_simple(cx, cx.typeck_results(), first_arg).map_or_else( - || constant_simple(cx, cx.typeck_results(), second_arg).map(|c| (m, c, first_arg)), - |c| { - if constant_simple(cx, cx.typeck_results(), second_arg).is_none() { - // otherwise ignore - Some((m, c, second_arg)) - } else { - None - } - }, - ) + let ecx = ConstEvalCtxt::new(cx); + match (ecx.eval_simple(first_arg), ecx.eval_simple(second_arg)) { + (Some(c), None) => Some((m, c, second_arg)), + (None, Some(c)) => Some((m, c, first_arg)), + // otherwise ignore + _ => None, + } } diff --git a/clippy_lints/src/operators/absurd_extreme_comparisons.rs b/clippy_lints/src/operators/absurd_extreme_comparisons.rs index 9769da6d3e9b1..a0de5ea711ca0 100644 --- a/clippy_lints/src/operators/absurd_extreme_comparisons.rs +++ b/clippy_lints/src/operators/absurd_extreme_comparisons.rs @@ -3,7 +3,7 @@ use rustc_lint::LateContext; use rustc_middle::ty; use clippy_utils::comparisons::{normalize_comparison, Rel}; -use clippy_utils::consts::{constant, Constant}; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::source::snippet; use clippy_utils::ty::is_isize_or_usize; @@ -121,7 +121,7 @@ fn detect_absurd_comparison<'tcx>( fn detect_extreme_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option> { let ty = cx.typeck_results().expr_ty(expr); - let cv = constant(cx, cx.typeck_results(), expr)?; + let cv = ConstEvalCtxt::new(cx).eval(expr)?; let which = match (ty.kind(), cv) { (&ty::Bool, Constant::Bool(false)) | (&ty::Uint(_), Constant::Int(0)) => ExtremeType::Minimum, diff --git a/clippy_lints/src/operators/arithmetic_side_effects.rs b/clippy_lints/src/operators/arithmetic_side_effects.rs index a7e381be743d5..bc71a4790b9d4 100644 --- a/clippy_lints/src/operators/arithmetic_side_effects.rs +++ b/clippy_lints/src/operators/arithmetic_side_effects.rs @@ -1,6 +1,6 @@ use super::ARITHMETIC_SIDE_EFFECTS; use clippy_config::Conf; -use clippy_utils::consts::{constant, constant_simple, Constant}; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::{expr_or_init, is_from_proc_macro, is_lint_allowed, peel_hir_expr_refs, peel_hir_expr_unary}; @@ -162,7 +162,7 @@ impl ArithmeticSideEffects { { return Some(n.get()); } - if let Some(Constant::Int(n)) = constant(cx, cx.typeck_results(), expr) { + if let Some(Constant::Int(n)) = ConstEvalCtxt::new(cx).eval(expr) { return Some(n); } None @@ -200,7 +200,7 @@ impl ArithmeticSideEffects { lhs: &'tcx hir::Expr<'_>, rhs: &'tcx hir::Expr<'_>, ) { - if constant_simple(cx, cx.typeck_results(), expr).is_some() { + if ConstEvalCtxt::new(cx).eval_simple(expr).is_some() { return; } if !matches!( @@ -280,7 +280,7 @@ impl ArithmeticSideEffects { let Some(arg) = args.first() else { return; }; - if constant_simple(cx, cx.typeck_results(), receiver).is_some() { + if ConstEvalCtxt::new(cx).eval_simple(receiver).is_some() { return; } let instance_ty = cx.typeck_results().expr_ty(receiver); @@ -308,7 +308,7 @@ impl ArithmeticSideEffects { let hir::UnOp::Neg = un_op else { return; }; - if constant(cx, cx.typeck_results(), un_expr).is_some() { + if ConstEvalCtxt::new(cx).eval(un_expr).is_some() { return; } let ty = cx.typeck_results().expr_ty(expr).peel_refs(); diff --git a/clippy_lints/src/operators/bit_mask.rs b/clippy_lints/src/operators/bit_mask.rs index 545e680ce0de5..4414056a467ca 100644 --- a/clippy_lints/src/operators/bit_mask.rs +++ b/clippy_lints/src/operators/bit_mask.rs @@ -1,4 +1,4 @@ -use clippy_utils::consts::{constant, Constant}; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::LateContext; @@ -166,7 +166,7 @@ fn check_ineffective_gt(cx: &LateContext<'_>, span: Span, m: u128, c: u128, op: } fn fetch_int_literal(cx: &LateContext<'_>, lit: &Expr<'_>) -> Option { - match constant(cx, cx.typeck_results(), lit)? { + match ConstEvalCtxt::new(cx).eval(lit)? { Constant::Int(n) => Some(n), _ => None, } diff --git a/clippy_lints/src/operators/const_comparisons.rs b/clippy_lints/src/operators/const_comparisons.rs index 1f9f3b3c47305..c131752439628 100644 --- a/clippy_lints/src/operators/const_comparisons.rs +++ b/clippy_lints/src/operators/const_comparisons.rs @@ -2,7 +2,7 @@ use std::cmp::Ordering; -use clippy_utils::consts::{constant, Constant}; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::LateContext; use rustc_middle::ty::layout::HasTyCtxt; @@ -26,7 +26,8 @@ fn comparison_to_const<'tcx>( if let ExprKind::Binary(operator, left, right) = expr.kind && let Ok(cmp_op) = CmpOp::try_from(operator.node) { - match (constant(cx, typeck, left), constant(cx, typeck, right)) { + let ecx = ConstEvalCtxt::with_env(cx.tcx, cx.param_env, typeck); + match (ecx.eval(left), ecx.eval(right)) { (Some(_), Some(_)) => None, (_, Some(con)) => Some((cmp_op, left, right, con, typeck.expr_ty(right))), (Some(con), _) => Some((cmp_op.reverse(), right, left, con, typeck.expr_ty(left))), diff --git a/clippy_lints/src/operators/duration_subsec.rs b/clippy_lints/src/operators/duration_subsec.rs index ca3112ce5c468..e3029f8438e5f 100644 --- a/clippy_lints/src/operators/duration_subsec.rs +++ b/clippy_lints/src/operators/duration_subsec.rs @@ -1,4 +1,4 @@ -use clippy_utils::consts::{constant, Constant}; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::is_type_diagnostic_item; @@ -19,7 +19,7 @@ pub(crate) fn check<'tcx>( if op == BinOpKind::Div && let ExprKind::MethodCall(method_path, self_arg, [], _) = left.kind && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(self_arg).peel_refs(), sym::Duration) - && let Some(Constant::Int(divisor)) = constant(cx, cx.typeck_results(), right) + && let Some(Constant::Int(divisor)) = ConstEvalCtxt::new(cx).eval(right) { let suggested_fn = match (method_path.ident.as_str(), divisor) { ("subsec_micros", 1_000) | ("subsec_nanos", 1_000_000) => "subsec_millis", diff --git a/clippy_lints/src/operators/erasing_op.rs b/clippy_lints/src/operators/erasing_op.rs index fc2129b91036b..24bfe2b050bb5 100644 --- a/clippy_lints/src/operators/erasing_op.rs +++ b/clippy_lints/src/operators/erasing_op.rs @@ -1,4 +1,4 @@ -use clippy_utils::consts::{constant_simple, Constant}; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint; use clippy_utils::ty::same_type_and_consts; @@ -39,7 +39,7 @@ fn check_op<'tcx>( other: &Expr<'tcx>, parent: &Expr<'tcx>, ) { - if constant_simple(cx, tck, op) == Some(Constant::Int(0)) { + if ConstEvalCtxt::with_env(cx.tcx, cx.param_env, tck).eval_simple(op) == Some(Constant::Int(0)) { if different_types(tck, other, parent) { return; } diff --git a/clippy_lints/src/operators/float_cmp.rs b/clippy_lints/src/operators/float_cmp.rs index 0e5b440c50f27..df6e67455965e 100644 --- a/clippy_lints/src/operators/float_cmp.rs +++ b/clippy_lints/src/operators/float_cmp.rs @@ -1,4 +1,4 @@ -use clippy_utils::consts::{constant_with_source, Constant}; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::get_item_name; use clippy_utils::sugg::Sugg; @@ -17,12 +17,14 @@ pub(crate) fn check<'tcx>( right: &'tcx Expr<'_>, ) { if (op == BinOpKind::Eq || op == BinOpKind::Ne) && is_float(cx, left) { - let left_is_local = match constant_with_source(cx, cx.typeck_results(), left) { + let typeck = cx.typeck_results(); + let ecx = ConstEvalCtxt::with_env(cx.tcx, cx.param_env, typeck); + let left_is_local = match ecx.eval_with_source(left) { Some((c, s)) if !is_allowed(&c) => s.is_local(), Some(_) => return, None => true, }; - let right_is_local = match constant_with_source(cx, cx.typeck_results(), right) { + let right_is_local = match ecx.eval_with_source(right) { Some((c, s)) if !is_allowed(&c) => s.is_local(), Some(_) => return, None => true, diff --git a/clippy_lints/src/operators/identity_op.rs b/clippy_lints/src/operators/identity_op.rs index 0879dcd9bcdf6..830be50c8ba4f 100644 --- a/clippy_lints/src/operators/identity_op.rs +++ b/clippy_lints/src/operators/identity_op.rs @@ -1,4 +1,4 @@ -use clippy_utils::consts::{constant_full_int, constant_simple, Constant, FullInt}; +use clippy_utils::consts::{ConstEvalCtxt, Constant, FullInt}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::{clip, peel_hir_expr_refs, unsext}; @@ -184,14 +184,13 @@ fn is_allowed(cx: &LateContext<'_>, cmp: BinOpKind, left: &Expr<'_>, right: &Exp && cx.typeck_results().expr_ty(right).peel_refs().is_integral() // `1 << 0` is a common pattern in bit manipulation code && !(cmp == BinOpKind::Shl - && constant_simple(cx, cx.typeck_results(), right) == Some(Constant::Int(0)) - && constant_simple(cx, cx.typeck_results(), left) == Some(Constant::Int(1))) + && ConstEvalCtxt::new(cx).eval_simple(right) == Some(Constant::Int(0)) + && ConstEvalCtxt::new(cx).eval_simple(left) == Some(Constant::Int(1))) } fn check_remainder(cx: &LateContext<'_>, left: &Expr<'_>, right: &Expr<'_>, span: Span, arg: Span) { - let lhs_const = constant_full_int(cx, cx.typeck_results(), left); - let rhs_const = constant_full_int(cx, cx.typeck_results(), right); - if match (lhs_const, rhs_const) { + let ecx = ConstEvalCtxt::new(cx); + if match (ecx.eval_full_int(left), ecx.eval_full_int(right)) { (Some(FullInt::S(lv)), Some(FullInt::S(rv))) => lv.abs() < rv.abs(), (Some(FullInt::U(lv)), Some(FullInt::U(rv))) => lv < rv, _ => return, @@ -201,7 +200,7 @@ fn check_remainder(cx: &LateContext<'_>, left: &Expr<'_>, right: &Expr<'_>, span } fn check_op(cx: &LateContext<'_>, e: &Expr<'_>, m: i8, span: Span, arg: Span, parens: Parens, is_erased: bool) -> bool { - if let Some(Constant::Int(v)) = constant_simple(cx, cx.typeck_results(), e).map(Constant::peel_refs) { + if let Some(Constant::Int(v)) = ConstEvalCtxt::new(cx).eval_simple(e).map(Constant::peel_refs) { let check = match *cx.typeck_results().expr_ty(e).peel_refs().kind() { ty::Int(ity) => unsext(cx.tcx, -1_i128, ity), ty::Uint(uty) => clip(cx.tcx, !0, uty), diff --git a/clippy_lints/src/operators/modulo_arithmetic.rs b/clippy_lints/src/operators/modulo_arithmetic.rs index d65fffac5a828..c83bdda347a66 100644 --- a/clippy_lints/src/operators/modulo_arithmetic.rs +++ b/clippy_lints/src/operators/modulo_arithmetic.rs @@ -1,4 +1,4 @@ -use clippy_utils::consts::{constant, Constant}; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::sext; use rustc_hir::{BinOpKind, Expr, ExprKind, Node}; @@ -42,15 +42,11 @@ fn used_in_comparison_with_zero(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { }; if op.node == BinOpKind::Eq || op.node == BinOpKind::Ne { - if let Some(Constant::Int(0)) = constant(cx, cx.typeck_results(), rhs) { - return true; - } - if let Some(Constant::Int(0)) = constant(cx, cx.typeck_results(), lhs) { - return true; - } + let ecx = ConstEvalCtxt::new(cx); + matches!(ecx.eval(lhs), Some(Constant::Int(0))) || matches!(ecx.eval(rhs), Some(Constant::Int(0))) + } else { + false } - - false } struct OperandInfo { @@ -60,7 +56,7 @@ struct OperandInfo { } fn analyze_operand(operand: &Expr<'_>, cx: &LateContext<'_>, expr: &Expr<'_>) -> Option { - match constant(cx, cx.typeck_results(), operand) { + match ConstEvalCtxt::new(cx).eval(operand) { Some(Constant::Int(v)) => match *cx.typeck_results().expr_ty(expr).kind() { ty::Int(ity) => { let value = sext(cx.tcx, v, ity); diff --git a/clippy_lints/src/operators/numeric_arithmetic.rs b/clippy_lints/src/operators/numeric_arithmetic.rs index ea933168cfd5d..565294bb40a82 100644 --- a/clippy_lints/src/operators/numeric_arithmetic.rs +++ b/clippy_lints/src/operators/numeric_arithmetic.rs @@ -1,5 +1,5 @@ use super::FLOAT_ARITHMETIC; -use clippy_utils::consts::constant_simple; +use clippy_utils::consts::ConstEvalCtxt; use clippy_utils::diagnostics::span_lint; use rustc_hir as hir; use rustc_lint::LateContext; @@ -55,7 +55,7 @@ impl Context { return; } let ty = cx.typeck_results().expr_ty(arg); - if constant_simple(cx, cx.typeck_results(), expr).is_none() && ty.is_floating_point() { + if ConstEvalCtxt::new(cx).eval_simple(expr).is_none() && ty.is_floating_point() { span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected"); self.expr_id = Some(expr.hir_id); } diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index 829fb58bc652b..25cfe830c778b 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -1,6 +1,6 @@ use clippy_config::msrvs::{self, Msrv}; use clippy_config::Conf; -use clippy_utils::consts::{constant, Constant}; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then}; use clippy_utils::source::{snippet, snippet_with_applicability, SpanRangeExt}; use clippy_utils::sugg::Sugg; @@ -319,7 +319,7 @@ fn check_range_bounds<'a, 'tcx>(cx: &'a LateContext<'tcx>, ex: &'a Expr<'_>) -> _ => return None, }; if let Some(id) = path_to_local(l) { - if let Some(c) = constant(cx, cx.typeck_results(), r) { + if let Some(c) = ConstEvalCtxt::new(cx).eval(r) { return Some(RangeBounds { val: c, expr: r, @@ -331,7 +331,7 @@ fn check_range_bounds<'a, 'tcx>(cx: &'a LateContext<'tcx>, ex: &'a Expr<'_>) -> }); } } else if let Some(id) = path_to_local(r) { - if let Some(c) = constant(cx, cx.typeck_results(), l) { + if let Some(c) = ConstEvalCtxt::new(cx).eval(l) { return Some(RangeBounds { val: c, expr: l, @@ -451,8 +451,9 @@ fn check_reversed_empty_range(cx: &LateContext<'_>, expr: &Expr<'_>) { }) = higher::Range::hir(expr) && let ty = cx.typeck_results().expr_ty(start) && let ty::Int(_) | ty::Uint(_) = ty.kind() - && let Some(start_idx) = constant(cx, cx.typeck_results(), start) - && let Some(end_idx) = constant(cx, cx.typeck_results(), end) + && let ecx = ConstEvalCtxt::new(cx) + && let Some(start_idx) = ecx.eval(start) + && let Some(end_idx) = ecx.eval(end) && let Some(ordering) = Constant::partial_cmp(cx.tcx, ty, &start_idx, &end_idx) && is_empty_range(limits, ordering) { diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index 8cacb646f5148..95014b230431c 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -1,6 +1,6 @@ use std::fmt::Display; -use clippy_utils::consts::{constant, Constant}; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; use clippy_utils::source::snippet_opt; use clippy_utils::{def_path_def_ids, path_def_id, paths}; @@ -148,7 +148,7 @@ fn lint_syntax_error(cx: &LateContext<'_>, error: ®ex_syntax::Error, unescape } fn const_str<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> Option { - constant(cx, cx.typeck_results(), e).and_then(|c| match c { + ConstEvalCtxt::new(cx).eval(e).and_then(|c| match c { Constant::Str(s) => Some(s), _ => None, }) diff --git a/clippy_lints/src/repeat_vec_with_capacity.rs b/clippy_lints/src/repeat_vec_with_capacity.rs index 792d8fc88f0bb..678681ea4252d 100644 --- a/clippy_lints/src/repeat_vec_with_capacity.rs +++ b/clippy_lints/src/repeat_vec_with_capacity.rs @@ -1,4 +1,4 @@ -use clippy_utils::consts::{constant, Constant}; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::higher::VecArgs; use clippy_utils::macros::matching_root_macro_call; @@ -69,7 +69,7 @@ fn check_vec_macro(cx: &LateContext<'_>, expr: &Expr<'_>) { && let Some(VecArgs::Repeat(repeat_expr, len_expr)) = VecArgs::hir(cx, expr) && fn_def_id(cx, repeat_expr).is_some_and(|did| match_def_path(cx, did, &paths::VEC_WITH_CAPACITY)) && !len_expr.span.from_expansion() - && let Some(Constant::Int(2..)) = constant(cx, cx.typeck_results(), expr_or_init(cx, len_expr)) + && let Some(Constant::Int(2..)) = ConstEvalCtxt::new(cx).eval(expr_or_init(cx, len_expr)) { emit_lint( cx, diff --git a/clippy_lints/src/transmute/transmute_null_to_fn.rs b/clippy_lints/src/transmute/transmute_null_to_fn.rs index b26365e34ab94..7acf3be51fb7e 100644 --- a/clippy_lints/src/transmute/transmute_null_to_fn.rs +++ b/clippy_lints/src/transmute/transmute_null_to_fn.rs @@ -1,4 +1,4 @@ -use clippy_utils::consts::{constant, Constant}; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::{is_integer_literal, is_path_diagnostic_item}; use rustc_hir::{Expr, ExprKind}; @@ -33,10 +33,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'t // Catching: // transmute over constants that resolve to `null`. ExprKind::Path(ref _qpath) - if matches!( - constant(cx, cx.typeck_results(), casts_peeled), - Some(Constant::RawPtr(0)) - ) => + if matches!(ConstEvalCtxt::new(cx).eval(casts_peeled), Some(Constant::RawPtr(0))) => { lint_expr(cx, expr); true diff --git a/clippy_lints/src/transmute/transmuting_null.rs b/clippy_lints/src/transmute/transmuting_null.rs index 471bd44b5d5ee..544014bd32b30 100644 --- a/clippy_lints/src/transmute/transmuting_null.rs +++ b/clippy_lints/src/transmute/transmuting_null.rs @@ -1,4 +1,4 @@ -use clippy_utils::consts::{constant, Constant}; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint; use clippy_utils::{is_integer_literal, is_path_diagnostic_item}; use rustc_hir::{Expr, ExprKind}; @@ -17,7 +17,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'t // Catching transmute over constants that resolve to `null`. if let ExprKind::Path(ref _qpath) = arg.kind - && let Some(Constant::RawPtr(0)) = constant(cx, cx.typeck_results(), arg) + && let Some(Constant::RawPtr(0)) = ConstEvalCtxt::new(cx).eval(arg) { span_lint(cx, TRANSMUTING_NULL, expr.span, LINT_MSG); return true; diff --git a/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs b/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs index b017a6bf665c5..7c2e23995c1d3 100644 --- a/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs +++ b/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs @@ -1,4 +1,4 @@ -use clippy_utils::consts::{constant_simple, Constant}; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet; use clippy_utils::ty::match_type; @@ -93,7 +93,7 @@ impl<'tcx> LateLintPass<'tcx> for InterningDefinedSymbol { if let ExprKind::Call(func, [arg]) = &expr.kind && let ty::FnDef(def_id, _) = cx.typeck_results().expr_ty(func).kind() && match_def_path(cx, *def_id, &paths::SYMBOL_INTERN) - && let Some(Constant::Str(arg)) = constant_simple(cx, cx.typeck_results(), arg) + && let Some(Constant::Str(arg)) = ConstEvalCtxt::new(cx).eval_simple(arg) && let value = Symbol::intern(&arg).as_u32() && let Some(&def_id) = self.symbol_map.get(&value) { @@ -199,7 +199,7 @@ impl InterningDefinedSymbol { }); } // is a string constant - if let Some(Constant::Str(s)) = constant_simple(cx, cx.typeck_results(), expr) { + if let Some(Constant::Str(s)) = ConstEvalCtxt::new(cx).eval_simple(expr) { let value = Symbol::intern(&s).as_u32(); // ...which matches a symbol constant if let Some(&def_id) = self.symbol_map.get(&value) { diff --git a/clippy_lints/src/utils/internal_lints/invalid_paths.rs b/clippy_lints/src/utils/internal_lints/invalid_paths.rs index 980437259c3e9..0ffcb433481e4 100644 --- a/clippy_lints/src/utils/internal_lints/invalid_paths.rs +++ b/clippy_lints/src/utils/internal_lints/invalid_paths.rs @@ -1,4 +1,4 @@ -use clippy_utils::consts::{constant_simple, Constant}; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::def_path_res; use clippy_utils::diagnostics::span_lint; use rustc_hir as hir; @@ -32,9 +32,9 @@ impl<'tcx> LateLintPass<'tcx> for InvalidPaths { let mod_name = &cx.tcx.item_name(local_def_id.to_def_id()); if mod_name.as_str() == "paths" && let hir::ItemKind::Const(.., body_id) = item.kind - && let body = cx.tcx.hir().body(body_id) - && let typeck_results = cx.tcx.typeck_body(body_id) - && let Some(Constant::Vec(path)) = constant_simple(cx, typeck_results, body.value) + && let Some(Constant::Vec(path)) = + ConstEvalCtxt::with_env(cx.tcx, cx.tcx.param_env(item.owner_id), cx.tcx.typeck(item.owner_id)) + .eval_simple(cx.tcx.hir().body(body_id).value) && let Some(path) = path .iter() .map(|x| { diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index a831234906bfc..228db14d1b7c3 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -3,7 +3,7 @@ use std::ops::ControlFlow; use clippy_config::msrvs::{self, Msrv}; use clippy_config::Conf; -use clippy_utils::consts::{constant, Constant}; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::source::snippet_opt; use clippy_utils::ty::is_copy; @@ -159,7 +159,7 @@ impl UselessVec { let snippet = match *vec_args { higher::VecArgs::Repeat(elem, len) => { - if let Some(Constant::Int(len_constant)) = constant(cx, cx.typeck_results(), len) { + if let Some(Constant::Int(len_constant)) = ConstEvalCtxt::new(cx).eval(len) { // vec![ty; N] works when ty is Clone, [ty; N] requires it to be Copy also if !is_copy(cx, cx.typeck_results().expr_ty(elem)) { return; diff --git a/clippy_lints/src/zero_div_zero.rs b/clippy_lints/src/zero_div_zero.rs index 60d8a13d3599d..5eb207a0aedb0 100644 --- a/clippy_lints/src/zero_div_zero.rs +++ b/clippy_lints/src/zero_div_zero.rs @@ -1,4 +1,4 @@ -use clippy_utils::consts::{constant_simple, Constant}; +use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_and_help; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -36,8 +36,9 @@ impl<'tcx> LateLintPass<'tcx> for ZeroDiv { // TODO - constant_simple does not fold many operations involving floats. // That's probably fine for this lint - it's pretty unlikely that someone would // do something like 0.0/(2.0 - 2.0), but it would be nice to warn on that case too. - && let Some(lhs_value) = constant_simple(cx, cx.typeck_results(), left) - && let Some(rhs_value) = constant_simple(cx, cx.typeck_results(), right) + && let ecx = ConstEvalCtxt::new(cx) + && let Some(lhs_value) = ecx.eval_simple(left) + && let Some(rhs_value) = ecx.eval_simple(right) // FIXME(f16_f128): add these types when eq is available on all platforms && (Constant::F32(0.0) == lhs_value || Constant::F64(0.0) == lhs_value) && (Constant::F32(0.0) == rhs_value || Constant::F64(0.0) == rhs_value) diff --git a/clippy_utils/src/consts.rs b/clippy_utils/src/consts.rs index d465daa06e27d..e907e4058e5a2 100644 --- a/clippy_utils/src/consts.rs +++ b/clippy_utils/src/consts.rs @@ -14,14 +14,13 @@ use rustc_lexer::tokenize; use rustc_lint::LateContext; use rustc_middle::mir::interpret::{alloc_range, Scalar}; use rustc_middle::mir::ConstValue; -use rustc_middle::ty::{ - self, EarlyBinder, FloatTy, GenericArgsRef, IntTy, List, ParamEnv, ScalarInt, Ty, TyCtxt, TypeckResults, UintTy, -}; +use rustc_middle::ty::{self, FloatTy, IntTy, ParamEnv, ScalarInt, Ty, TyCtxt, TypeckResults, UintTy}; use rustc_middle::{bug, mir, span_bug}; use rustc_span::def_id::DefId; use rustc_span::symbol::Ident; use rustc_span::{sym, SyntaxContext}; use rustc_target::abi::Size; +use std::cell::Cell; use std::cmp::Ordering; use std::hash::{Hash, Hasher}; use std::iter; @@ -265,10 +264,10 @@ impl<'tcx> Constant<'tcx> { } /// Returns the integer value or `None` if `self` or `val_type` is not integer type. - pub fn int_value(&self, cx: &LateContext<'_>, val_type: Ty<'_>) -> Option { + pub fn int_value(&self, tcx: TyCtxt<'_>, val_type: Ty<'_>) -> Option { if let Constant::Int(const_int) = *self { match *val_type.kind() { - ty::Int(ity) => Some(FullInt::S(sext(cx.tcx, const_int, ity))), + ty::Int(ity) => Some(FullInt::S(sext(tcx, const_int, ity))), ty::Uint(_) => Some(FullInt::U(const_int)), _ => None, } @@ -324,6 +323,7 @@ pub fn lit_to_mir_constant<'tcx>(lit: &LitKind, ty: Option>) -> Constan } /// The source of a constant value. +#[derive(Clone, Copy)] pub enum ConstantSource { /// The value is determined solely from the expression. Local, @@ -333,54 +333,11 @@ pub enum ConstantSource { CoreConstant, } impl ConstantSource { - pub fn is_local(&self) -> bool { + pub fn is_local(self) -> bool { matches!(self, Self::Local) } } -/// Attempts to check whether the expression is a constant representing an empty slice, str, array, -/// etc… -pub fn constant_is_empty(lcx: &LateContext<'_>, e: &Expr<'_>) -> Option { - ConstEvalLateContext::new(lcx.tcx, lcx.param_env, lcx.typeck_results()).expr_is_empty(e) -} - -/// Attempts to evaluate the expression as a constant. -pub fn constant<'tcx>( - lcx: &LateContext<'tcx>, - typeck_results: &'tcx TypeckResults<'tcx>, - e: &Expr<'_>, -) -> Option> { - ConstEvalLateContext::new(lcx.tcx, lcx.param_env, typeck_results).expr(e) -} - -/// Attempts to evaluate the expression as a constant. -pub fn constant_with_source<'tcx>( - lcx: &LateContext<'tcx>, - typeck_results: &'tcx TypeckResults<'tcx>, - e: &Expr<'_>, -) -> Option<(Constant<'tcx>, ConstantSource)> { - let mut ctxt = ConstEvalLateContext::new(lcx.tcx, lcx.param_env, typeck_results); - let res = ctxt.expr(e); - res.map(|x| (x, ctxt.source)) -} - -/// Attempts to evaluate an expression only if its value is not dependent on other items. -pub fn constant_simple<'tcx>( - lcx: &LateContext<'tcx>, - typeck_results: &'tcx TypeckResults<'tcx>, - e: &Expr<'_>, -) -> Option> { - constant_with_source(lcx, typeck_results, e).and_then(|(c, s)| s.is_local().then_some(c)) -} - -pub fn constant_full_int<'tcx>( - lcx: &LateContext<'tcx>, - typeck_results: &'tcx TypeckResults<'tcx>, - e: &Expr<'_>, -) -> Option { - constant_simple(lcx, typeck_results, e)?.int_value(lcx, typeck_results.expr_ty(e)) -} - #[derive(Copy, Clone, Debug, Eq)] pub enum FullInt { S(i128), @@ -419,45 +376,87 @@ impl Ord for FullInt { } } -pub struct ConstEvalLateContext<'tcx> { +/// The context required to evaluate a constant expression. +/// +/// This is currently limited to constant folding and reading the value of named constants. +pub struct ConstEvalCtxt<'tcx> { tcx: TyCtxt<'tcx>, - typeck_results: &'tcx TypeckResults<'tcx>, param_env: ParamEnv<'tcx>, - source: ConstantSource, - args: GenericArgsRef<'tcx>, + typeck: &'tcx TypeckResults<'tcx>, + source: Cell, } -impl<'tcx> ConstEvalLateContext<'tcx> { - pub fn new(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, typeck_results: &'tcx TypeckResults<'tcx>) -> Self { +impl<'tcx> ConstEvalCtxt<'tcx> { + /// Creates the evaluation context from the lint context. This requires the lint context to be + /// in a body (i.e. `cx.enclosing_body.is_some()`). + pub fn new(cx: &LateContext<'tcx>) -> Self { + Self { + tcx: cx.tcx, + param_env: cx.param_env, + typeck: cx.typeck_results(), + source: Cell::new(ConstantSource::Local), + } + } + + /// Creates an evaluation context. + pub fn with_env(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, typeck: &'tcx TypeckResults<'tcx>) -> Self { Self { tcx, - typeck_results, param_env, - source: ConstantSource::Local, - args: List::empty(), + typeck, + source: Cell::new(ConstantSource::Local), + } + } + + /// Attempts to evaluate the expression and returns both the value and whether it's dependant on + /// other items. + pub fn eval_with_source(&self, e: &Expr<'_>) -> Option<(Constant<'tcx>, ConstantSource)> { + self.source.set(ConstantSource::Local); + self.expr(e).map(|c| (c, self.source.get())) + } + + /// Attempts to evaluate the expression. + pub fn eval(&self, e: &Expr<'_>) -> Option> { + self.expr(e) + } + + /// Attempts to evaluate the expression without accessing other items. + pub fn eval_simple(&self, e: &Expr<'_>) -> Option> { + match self.eval_with_source(e) { + Some((x, ConstantSource::Local)) => Some(x), + _ => None, + } + } + + /// Attempts to evaluate the expression as an integer without accessing other items. + pub fn eval_full_int(&self, e: &Expr<'_>) -> Option { + match self.eval_with_source(e) { + Some((x, ConstantSource::Local)) => x.int_value(self.tcx, self.typeck.expr_ty(e)), + _ => None, } } /// Simple constant folding: Insert an expression, get a constant or none. - pub fn expr(&mut self, e: &Expr<'_>) -> Option> { + fn expr(&self, e: &Expr<'_>) -> Option> { match e.kind { ExprKind::ConstBlock(ConstBlock { body, .. }) => self.expr(self.tcx.hir().body(body).value), ExprKind::DropTemps(e) => self.expr(e), ExprKind::Path(ref qpath) => { - let is_core_crate = if let Some(def_id) = self.typeck_results.qpath_res(qpath, e.hir_id()).opt_def_id() - { + let is_core_crate = if let Some(def_id) = self.typeck.qpath_res(qpath, e.hir_id()).opt_def_id() { self.tcx.crate_name(def_id.krate) == sym::core } else { false }; - self.fetch_path_and_apply(qpath, e.hir_id, self.typeck_results.expr_ty(e), |self_, result| { + self.fetch_path_and_apply(qpath, e.hir_id, self.typeck.expr_ty(e), |self_, result| { let result = mir_to_const(self_.tcx, result)?; // If source is already Constant we wouldn't want to override it with CoreConstant - self_.source = if is_core_crate && !matches!(self_.source, ConstantSource::Constant) { - ConstantSource::CoreConstant - } else { - ConstantSource::Constant - }; + self_.source.set( + if is_core_crate && !matches!(self_.source.get(), ConstantSource::Constant) { + ConstantSource::CoreConstant + } else { + ConstantSource::Constant + }, + ); Some(result) }) }, @@ -466,21 +465,21 @@ impl<'tcx> ConstEvalLateContext<'tcx> { if is_direct_expn_of(e.span, "cfg").is_some() { None } else { - Some(lit_to_mir_constant(&lit.node, self.typeck_results.expr_ty_opt(e))) + Some(lit_to_mir_constant(&lit.node, self.typeck.expr_ty_opt(e))) } }, ExprKind::Array(vec) => self.multi(vec).map(Constant::Vec), ExprKind::Tup(tup) => self.multi(tup).map(Constant::Tuple), ExprKind::Repeat(value, _) => { - let n = match self.typeck_results.expr_ty(e).kind() { + let n = match self.typeck.expr_ty(e).kind() { ty::Array(_, n) => n.try_eval_target_usize(self.tcx, self.param_env)?, _ => span_bug!(e.span, "typeck error"), }; self.expr(value).map(|v| Constant::Repeat(Box::new(v), n)) }, ExprKind::Unary(op, operand) => self.expr(operand).and_then(|o| match op { - UnOp::Not => self.constant_not(&o, self.typeck_results.expr_ty(e)), - UnOp::Neg => self.constant_negate(&o, self.typeck_results.expr_ty(e)), + UnOp::Not => self.constant_not(&o, self.typeck.expr_ty(e)), + UnOp::Neg => self.constant_negate(&o, self.typeck.expr_ty(e)), UnOp::Deref => Some(if let Constant::Ref(r) = o { *r } else { o }), }), ExprKind::If(cond, then, ref otherwise) => self.ifthenelse(cond, then, *otherwise), @@ -489,7 +488,7 @@ impl<'tcx> ConstEvalLateContext<'tcx> { // We only handle a few const functions for now. if args.is_empty() && let ExprKind::Path(qpath) = &callee.kind - && let Some(did) = self.typeck_results.qpath_res(qpath, callee.hir_id).opt_def_id() + && let Some(did) = self.typeck.qpath_res(qpath, callee.hir_id).opt_def_id() { match self.tcx.get_diagnostic_name(did) { Some(sym::i8_legacy_fn_max_value) => Some(Constant::Int(i8::MAX as u128)), @@ -524,20 +523,20 @@ impl<'tcx> ConstEvalLateContext<'tcx> { /// Simple constant folding to determine if an expression is an empty slice, str, array, … /// `None` will be returned if the constness cannot be determined, or if the resolution /// leaves the local crate. - pub fn expr_is_empty(&mut self, e: &Expr<'_>) -> Option { + pub fn eval_is_empty(&self, e: &Expr<'_>) -> Option { match e.kind { - ExprKind::ConstBlock(ConstBlock { body, .. }) => self.expr_is_empty(self.tcx.hir().body(body).value), - ExprKind::DropTemps(e) => self.expr_is_empty(e), + ExprKind::ConstBlock(ConstBlock { body, .. }) => self.eval_is_empty(self.tcx.hir().body(body).value), + ExprKind::DropTemps(e) => self.eval_is_empty(e), ExprKind::Path(ref qpath) => { if !self - .typeck_results + .typeck .qpath_res(qpath, e.hir_id) .opt_def_id() .is_some_and(DefId::is_local) { return None; } - self.fetch_path_and_apply(qpath, e.hir_id, self.typeck_results.expr_ty(e), |self_, result| { + self.fetch_path_and_apply(qpath, e.hir_id, self.typeck.expr_ty(e), |self_, result| { mir_is_empty(self_.tcx, result) }) }, @@ -554,7 +553,7 @@ impl<'tcx> ConstEvalLateContext<'tcx> { }, ExprKind::Array(vec) => self.multi(vec).map(|v| v.is_empty()), ExprKind::Repeat(..) => { - if let ty::Array(_, n) = self.typeck_results.expr_ty(e).kind() { + if let ty::Array(_, n) = self.typeck.expr_ty(e).kind() { Some(n.try_eval_target_usize(self.tcx, self.param_env)? == 0) } else { span_bug!(e.span, "typeck error"); @@ -607,16 +606,16 @@ impl<'tcx> ConstEvalLateContext<'tcx> { /// Create `Some(Vec![..])` of all constants, unless there is any /// non-constant part. - fn multi(&mut self, vec: &[Expr<'_>]) -> Option>> { + fn multi(&self, vec: &[Expr<'_>]) -> Option>> { vec.iter().map(|elem| self.expr(elem)).collect::>() } /// Lookup a possibly constant expression from an `ExprKind::Path` and apply a function on it. - fn fetch_path_and_apply(&mut self, qpath: &QPath<'_>, id: HirId, ty: Ty<'tcx>, f: F) -> Option + fn fetch_path_and_apply(&self, qpath: &QPath<'_>, id: HirId, ty: Ty<'tcx>, f: F) -> Option where - F: FnOnce(&mut Self, mir::Const<'tcx>) -> Option, + F: FnOnce(&Self, mir::Const<'tcx>) -> Option, { - let res = self.typeck_results.qpath_res(qpath, id); + let res = self.typeck.qpath_res(qpath, id); match res { Res::Def(DefKind::Const | DefKind::AssocConst, def_id) => { // Check if this constant is based on `cfg!(..)`, @@ -636,12 +635,7 @@ impl<'tcx> ConstEvalLateContext<'tcx> { return None; } - let args = self.typeck_results.node_args(id); - let args = if self.args.is_empty() { - args - } else { - EarlyBinder::bind(args).instantiate(self.tcx, self.args) - }; + let args = self.typeck.node_args(id); let result = self .tcx .const_eval_resolve(self.param_env, mir::UnevaluatedConst::new(def_id, args), qpath.span()) @@ -653,7 +647,7 @@ impl<'tcx> ConstEvalLateContext<'tcx> { } } - fn index(&mut self, lhs: &'_ Expr<'_>, index: &'_ Expr<'_>) -> Option> { + fn index(&self, lhs: &'_ Expr<'_>, index: &'_ Expr<'_>) -> Option> { let lhs = self.expr(lhs); let index = self.expr(index); @@ -683,7 +677,7 @@ impl<'tcx> ConstEvalLateContext<'tcx> { } /// A block can only yield a constant if it has exactly one constant expression. - fn block(&mut self, block: &Block<'_>) -> Option> { + fn block(&self, block: &Block<'_>) -> Option> { if block.stmts.is_empty() && let Some(expr) = block.expr { @@ -702,11 +696,11 @@ impl<'tcx> ConstEvalLateContext<'tcx> { .filter(|t| !matches!(t, Whitespace | LineComment { .. } | BlockComment { .. } | Semi)) .eq([OpenBrace]) { - self.source = ConstantSource::Constant; + self.source.set(ConstantSource::Constant); } } else { // Unable to access the source. Assume a non-local dependency. - self.source = ConstantSource::Constant; + self.source.set(ConstantSource::Constant); } } @@ -716,7 +710,7 @@ impl<'tcx> ConstEvalLateContext<'tcx> { } } - fn ifthenelse(&mut self, cond: &Expr<'_>, then: &Expr<'_>, otherwise: Option<&Expr<'_>>) -> Option> { + fn ifthenelse(&self, cond: &Expr<'_>, then: &Expr<'_>, otherwise: Option<&Expr<'_>>) -> Option> { if let Some(Constant::Bool(b)) = self.expr(cond) { if b { self.expr(then) @@ -728,11 +722,11 @@ impl<'tcx> ConstEvalLateContext<'tcx> { } } - fn binop(&mut self, op: BinOp, left: &Expr<'_>, right: &Expr<'_>) -> Option> { + fn binop(&self, op: BinOp, left: &Expr<'_>, right: &Expr<'_>) -> Option> { let l = self.expr(left)?; let r = self.expr(right); match (l, r) { - (Constant::Int(l), Some(Constant::Int(r))) => match *self.typeck_results.expr_ty_opt(left)?.kind() { + (Constant::Int(l), Some(Constant::Int(r))) => match *self.typeck.expr_ty_opt(left)?.kind() { ty::Int(ity) => { let (ty_min_value, _) = ity.min_max()?; let bits = ity.bits(); diff --git a/clippy_utils/src/eager_or_lazy.rs b/clippy_utils/src/eager_or_lazy.rs index 6c40029a9de70..a6dd12a28c5bc 100644 --- a/clippy_utils/src/eager_or_lazy.rs +++ b/clippy_utils/src/eager_or_lazy.rs @@ -9,7 +9,7 @@ //! - or-fun-call //! - option-if-let-else -use crate::consts::{constant, FullInt}; +use crate::consts::{ConstEvalCtxt, FullInt}; use crate::ty::{all_predicates_of, is_copy}; use crate::visitors::is_const_evaluatable; use rustc_hir::def::{DefKind, Res}; @@ -206,7 +206,7 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS }, // `-i32::MIN` panics with overflow checks - ExprKind::Unary(UnOp::Neg, right) if constant(self.cx, self.cx.typeck_results(), right).is_none() => { + ExprKind::Unary(UnOp::Neg, right) if ConstEvalCtxt::new(self.cx).eval(right).is_none() => { self.eagerness |= NoChange; }, @@ -232,7 +232,7 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS // Thus, we would realistically only delay the lint. ExprKind::Binary(op, _, right) if matches!(op.node, BinOpKind::Shl | BinOpKind::Shr) - && constant(self.cx, self.cx.typeck_results(), right).is_none() => + && ConstEvalCtxt::new(self.cx).eval(right).is_none() => { self.eagerness |= NoChange; }, @@ -240,9 +240,9 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS ExprKind::Binary(op, left, right) if matches!(op.node, BinOpKind::Div | BinOpKind::Rem) && let right_ty = self.cx.typeck_results().expr_ty(right) - && let left = constant(self.cx, self.cx.typeck_results(), left) - && let right = constant(self.cx, self.cx.typeck_results(), right) - .and_then(|c| c.int_value(self.cx, right_ty)) + && let ecx = ConstEvalCtxt::new(self.cx) + && let left = ecx.eval(left) + && let right = ecx.eval(right).and_then(|c| c.int_value(self.cx.tcx, right_ty)) && matches!( (left, right), // `1 / x`: x might be zero @@ -261,8 +261,8 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS ExprKind::Binary(op, left, right) if matches!(op.node, BinOpKind::Add | BinOpKind::Sub | BinOpKind::Mul) && !self.cx.typeck_results().expr_ty(e).is_floating_point() - && (constant(self.cx, self.cx.typeck_results(), left).is_none() - || constant(self.cx, self.cx.typeck_results(), right).is_none()) => + && let ecx = ConstEvalCtxt::new(self.cx) + && (ecx.eval(left).is_none() || ecx.eval(right).is_none()) => { self.eagerness |= NoChange; }, diff --git a/clippy_utils/src/higher.rs b/clippy_utils/src/higher.rs index 33c88efa0cd34..8970b4d122984 100644 --- a/clippy_utils/src/higher.rs +++ b/clippy_utils/src/higher.rs @@ -2,7 +2,7 @@ #![deny(clippy::missing_docs_in_private_items)] -use crate::consts::{constant_simple, Constant}; +use crate::consts::{ConstEvalCtxt, Constant}; use crate::ty::is_type_diagnostic_item; use crate::{is_expn_of, match_def_path, paths}; @@ -471,7 +471,7 @@ pub fn get_vec_init_kind<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) - return Some(VecInitKind::Default); } else if name.ident.name.as_str() == "with_capacity" { let arg = args.first()?; - return match constant_simple(cx, cx.typeck_results(), arg) { + return match ConstEvalCtxt::new(cx).eval_simple(arg) { Some(Constant::Int(num)) => Some(VecInitKind::WithConstCapacity(num)), _ => Some(VecInitKind::WithExprCapacity(arg.hir_id)), }; diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs index 28178a61a9323..f325e4eaf1544 100644 --- a/clippy_utils/src/hir_utils.rs +++ b/clippy_utils/src/hir_utils.rs @@ -1,4 +1,4 @@ -use crate::consts::constant_simple; +use crate::consts::ConstEvalCtxt; use crate::macros::macro_backtrace; use crate::source::{snippet_opt, walk_span_to_context, SpanRange, SpanRangeExt}; use crate::tokenize_with_text; @@ -255,8 +255,8 @@ impl HirEqInterExpr<'_, '_, '_> { if let Some((typeck_lhs, typeck_rhs)) = self.inner.maybe_typeck_results && typeck_lhs.expr_ty(left) == typeck_rhs.expr_ty(right) && let (Some(l), Some(r)) = ( - constant_simple(self.inner.cx, typeck_lhs, left), - constant_simple(self.inner.cx, typeck_rhs, right), + ConstEvalCtxt::with_env(self.inner.cx.tcx, self.inner.cx.param_env, typeck_lhs).eval_simple(left), + ConstEvalCtxt::with_env(self.inner.cx.tcx, self.inner.cx.param_env, typeck_rhs).eval_simple(right), ) && l == r { @@ -714,9 +714,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { #[expect(clippy::too_many_lines)] pub fn hash_expr(&mut self, e: &Expr<'_>) { - let simple_const = self - .maybe_typeck_results - .and_then(|typeck_results| constant_simple(self.cx, typeck_results, e)); + let simple_const = self.maybe_typeck_results.and_then(|typeck_results| { + ConstEvalCtxt::with_env(self.cx.tcx, self.cx.param_env, typeck_results).eval_simple(e) + }); // const hashing may result in the same hash as some unrelated node, so add a sort of // discriminant depending on which path we're choosing next diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index d43b15fc58aee..a71f8e3b6643b 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -125,7 +125,7 @@ use rustc_span::{sym, Span}; use rustc_target::abi::Integer; use visitors::Visitable; -use crate::consts::{constant, mir_to_const, Constant}; +use crate::consts::{mir_to_const, ConstEvalCtxt, Constant}; use crate::higher::Range; use crate::ty::{adt_and_variant_of_res, can_partially_move_ty, expr_sig, is_copy, is_recursively_primitive_type}; use crate::visitors::for_each_expr_without_closures; @@ -1578,7 +1578,7 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti && let bnd_ty = subst.type_at(0) && let Some(min_val) = bnd_ty.numeric_min_val(cx.tcx) && let Some(min_const) = mir_to_const(cx.tcx, Const::from_ty_const(min_val, bnd_ty, cx.tcx)) - && let Some(start_const) = constant(cx, cx.typeck_results(), start) + && let Some(start_const) = ConstEvalCtxt::new(cx).eval(start) { start_const == min_const } else { @@ -1591,7 +1591,7 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti && let bnd_ty = subst.type_at(0) && let Some(max_val) = bnd_ty.numeric_max_val(cx.tcx) && let Some(max_const) = mir_to_const(cx.tcx, Const::from_ty_const(max_val, bnd_ty, cx.tcx)) - && let Some(end_const) = constant(cx, cx.typeck_results(), end) + && let Some(end_const) = ConstEvalCtxt::new(cx).eval(end) { end_const == max_const } else { @@ -1622,7 +1622,9 @@ pub fn is_integer_const(cx: &LateContext<'_>, e: &Expr<'_>, value: u128) -> bool return true; } let enclosing_body = cx.tcx.hir().enclosing_body_owner(e.hir_id); - if let Some(Constant::Int(v)) = constant(cx, cx.tcx.typeck(enclosing_body), e) { + if let Some(Constant::Int(v)) = + ConstEvalCtxt::with_env(cx.tcx, cx.tcx.param_env(enclosing_body), cx.tcx.typeck(enclosing_body)).eval(e) + { return value == v; } false From ae696f847dee523df6afed14468de70fc6479552 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 8 Aug 2024 01:46:16 +0000 Subject: [PATCH 646/786] Split `ColorConfig` off of `HumanReadableErrorType` The previous setup tied two unrelated things together. Splitting these two is a better model. --- compiler/rustc_errors/src/emitter.rs | 17 ++--------- compiler/rustc_errors/src/json.rs | 9 ++++-- compiler/rustc_errors/src/json/tests.rs | 3 +- compiler/rustc_interface/src/tests.rs | 3 +- compiler/rustc_session/src/config.rs | 38 +++++++++++++++---------- compiler/rustc_session/src/session.rs | 30 ++++++++++--------- src/librustdoc/config.rs | 5 ++-- src/librustdoc/core.rs | 7 +++-- src/librustdoc/doctest.rs | 4 +-- 9 files changed, 62 insertions(+), 54 deletions(-) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 88ed3128164d1..5bd3b328cb8d0 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -43,20 +43,9 @@ const DEFAULT_COLUMN_WIDTH: usize = 140; /// Describes the way the content of the `rendered` field of the json output is generated #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum HumanReadableErrorType { - Default(ColorConfig), - AnnotateSnippet(ColorConfig), - Short(ColorConfig), -} - -impl HumanReadableErrorType { - /// Returns a (`short`, `color`) tuple - pub fn unzip(self) -> (bool, ColorConfig) { - match self { - HumanReadableErrorType::Default(cc) => (false, cc), - HumanReadableErrorType::Short(cc) => (true, cc), - HumanReadableErrorType::AnnotateSnippet(cc) => (false, cc), - } - } + Default, + AnnotateSnippet, + Short, } #[derive(Clone, Copy, Debug)] diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index 42a28bc789013..02a0de201edd4 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -55,6 +55,7 @@ pub struct JsonEmitter { ignored_directories_in_source_blocks: Vec, #[setters(skip)] json_rendered: HumanReadableErrorType, + color_config: ColorConfig, diagnostic_width: Option, macro_backtrace: bool, track_diagnostics: bool, @@ -68,6 +69,7 @@ impl JsonEmitter { fallback_bundle: LazyFallbackBundle, pretty: bool, json_rendered: HumanReadableErrorType, + color_config: ColorConfig, ) -> JsonEmitter { JsonEmitter { dst: IntoDynSyncSend(dst), @@ -79,6 +81,7 @@ impl JsonEmitter { ui_testing: false, ignored_directories_in_source_blocks: Vec::new(), json_rendered, + color_config, diagnostic_width: None, macro_backtrace: false, track_diagnostics: false, @@ -173,7 +176,7 @@ impl Emitter for JsonEmitter { } fn should_show_explain(&self) -> bool { - !matches!(self.json_rendered, HumanReadableErrorType::Short(_)) + !matches!(self.json_rendered, HumanReadableErrorType::Short) } } @@ -353,8 +356,8 @@ impl Diagnostic { let buf = BufWriter::default(); let mut dst: Destination = Box::new(buf.clone()); - let (short, color_config) = je.json_rendered.unzip(); - match color_config { + let short = matches!(je.json_rendered, HumanReadableErrorType::Short); + match je.color_config { ColorConfig::Always | ColorConfig::Auto => dst = Box::new(termcolor::Ansi::new(dst)), ColorConfig::Never => {} } diff --git a/compiler/rustc_errors/src/json/tests.rs b/compiler/rustc_errors/src/json/tests.rs index e3549fc3aa537..6af376d7afdb2 100644 --- a/compiler/rustc_errors/src/json/tests.rs +++ b/compiler/rustc_errors/src/json/tests.rs @@ -50,7 +50,8 @@ fn test_positions(code: &str, span: (u32, u32), expected_output: SpanTestData) { sm, fallback_bundle, true, // pretty - HumanReadableErrorType::Short(ColorConfig::Never), + HumanReadableErrorType::Short, + ColorConfig::Never, ); let span = Span::with_root_ctxt(BytePos(span.0), BytePos(span.1)); diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index ce3b2f77f210a..34f2dca7c42ff 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -315,7 +315,8 @@ fn test_search_paths_tracking_hash_different_order() { let early_dcx = EarlyDiagCtxt::new(JSON); const JSON: ErrorOutputType = ErrorOutputType::Json { pretty: false, - json_rendered: HumanReadableErrorType::Default(ColorConfig::Never), + json_rendered: HumanReadableErrorType::Default, + color_config: ColorConfig::Never, }; let push = |opts: &mut Options, search_path| { diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 20c14a985024c..95d171409d86d 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -602,7 +602,7 @@ impl OutputType { #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum ErrorOutputType { /// Output meant for the consumption of humans. - HumanReadable(HumanReadableErrorType), + HumanReadable(HumanReadableErrorType, ColorConfig), /// Output that's consumed by other tools such as `rustfix` or the `RLS`. Json { /// Render the JSON in a human readable way (with indents and newlines). @@ -610,12 +610,13 @@ pub enum ErrorOutputType { /// The JSON output includes a `rendered` field that includes the rendered /// human output. json_rendered: HumanReadableErrorType, + color_config: ColorConfig, }, } impl Default for ErrorOutputType { fn default() -> Self { - Self::HumanReadable(HumanReadableErrorType::Default(ColorConfig::Auto)) + Self::HumanReadable(HumanReadableErrorType::Default, ColorConfig::Auto) } } @@ -1631,6 +1632,7 @@ pub fn parse_color(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> Col /// Possible json config files pub struct JsonConfig { pub json_rendered: HumanReadableErrorType, + pub json_color: ColorConfig, json_artifact_notifications: bool, pub json_unused_externs: JsonUnusedExterns, json_future_incompat: bool, @@ -1668,8 +1670,7 @@ impl JsonUnusedExterns { /// The first value returned is how to render JSON diagnostics, and the second /// is whether or not artifact notifications are enabled. pub fn parse_json(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> JsonConfig { - let mut json_rendered: fn(ColorConfig) -> HumanReadableErrorType = - HumanReadableErrorType::Default; + let mut json_rendered = HumanReadableErrorType::Default; let mut json_color = ColorConfig::Never; let mut json_artifact_notifications = false; let mut json_unused_externs = JsonUnusedExterns::No; @@ -1696,7 +1697,8 @@ pub fn parse_json(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> Json } JsonConfig { - json_rendered: json_rendered(json_color), + json_rendered, + json_color, json_artifact_notifications, json_unused_externs, json_future_incompat, @@ -1708,6 +1710,7 @@ pub fn parse_error_format( early_dcx: &mut EarlyDiagCtxt, matches: &getopts::Matches, color: ColorConfig, + json_color: ColorConfig, json_rendered: HumanReadableErrorType, ) -> ErrorOutputType { // We need the `opts_present` check because the driver will send us Matches @@ -1717,18 +1720,22 @@ pub fn parse_error_format( let error_format = if matches.opts_present(&["error-format".to_owned()]) { match matches.opt_str("error-format").as_deref() { None | Some("human") => { - ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color)) + ErrorOutputType::HumanReadable(HumanReadableErrorType::Default, color) } Some("human-annotate-rs") => { - ErrorOutputType::HumanReadable(HumanReadableErrorType::AnnotateSnippet(color)) + ErrorOutputType::HumanReadable(HumanReadableErrorType::AnnotateSnippet, color) } - Some("json") => ErrorOutputType::Json { pretty: false, json_rendered }, - Some("pretty-json") => ErrorOutputType::Json { pretty: true, json_rendered }, - Some("short") => ErrorOutputType::HumanReadable(HumanReadableErrorType::Short(color)), - + Some("json") => { + ErrorOutputType::Json { pretty: false, json_rendered, color_config: json_color } + } + Some("pretty-json") => { + ErrorOutputType::Json { pretty: true, json_rendered, color_config: json_color } + } + Some("short") => ErrorOutputType::HumanReadable(HumanReadableErrorType::Short, color), Some(arg) => { early_dcx.abort_if_error_and_set_error_format(ErrorOutputType::HumanReadable( - HumanReadableErrorType::Default(color), + HumanReadableErrorType::Default, + color, )); early_dcx.early_fatal(format!( "argument for `--error-format` must be `human`, `json` or \ @@ -1737,7 +1744,7 @@ pub fn parse_error_format( } } } else { - ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color)) + ErrorOutputType::HumanReadable(HumanReadableErrorType::Default, color) }; match error_format { @@ -1791,7 +1798,7 @@ fn check_error_format_stability( if let ErrorOutputType::Json { pretty: true, .. } = error_format { early_dcx.early_fatal("`--error-format=pretty-json` is unstable"); } - if let ErrorOutputType::HumanReadable(HumanReadableErrorType::AnnotateSnippet(_)) = + if let ErrorOutputType::HumanReadable(HumanReadableErrorType::AnnotateSnippet, _) = error_format { early_dcx.early_fatal("`--error-format=human-annotate-rs` is unstable"); @@ -2392,12 +2399,13 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M let JsonConfig { json_rendered, + json_color, json_artifact_notifications, json_unused_externs, json_future_incompat, } = parse_json(early_dcx, matches); - let error_format = parse_error_format(early_dcx, matches, color, json_rendered); + let error_format = parse_error_format(early_dcx, matches, color, json_color, json_rendered); early_dcx.abort_if_error_and_set_error_format(error_format); diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index be67baf57f6dc..c0fa377f8ba52 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -950,10 +950,10 @@ fn default_emitter( t => t, }; match sopts.error_format { - config::ErrorOutputType::HumanReadable(kind) => { - let (short, color_config) = kind.unzip(); + config::ErrorOutputType::HumanReadable(kind, color_config) => { + let short = matches!(kind, HumanReadableErrorType::Short); - if let HumanReadableErrorType::AnnotateSnippet(_) = kind { + if let HumanReadableErrorType::AnnotateSnippet = kind { let emitter = AnnotateSnippetEmitter::new( Some(source_map), bundle, @@ -978,13 +978,14 @@ fn default_emitter( Box::new(emitter.ui_testing(sopts.unstable_opts.ui_testing)) } } - config::ErrorOutputType::Json { pretty, json_rendered } => Box::new( + config::ErrorOutputType::Json { pretty, json_rendered, color_config } => Box::new( JsonEmitter::new( Box::new(io::BufWriter::new(io::stderr())), source_map, fallback_bundle, pretty, json_rendered, + color_config, ) .registry(Some(registry)) .fluent_bundle(bundle) @@ -1425,20 +1426,23 @@ fn mk_emitter(output: ErrorOutputType) -> Box { let fallback_bundle = fallback_fluent_bundle(vec![rustc_errors::DEFAULT_LOCALE_RESOURCE], false); let emitter: Box = match output { - config::ErrorOutputType::HumanReadable(kind) => { - let (short, color_config) = kind.unzip(); + config::ErrorOutputType::HumanReadable(kind, color_config) => { + let short = matches!(kind, HumanReadableErrorType::Short); Box::new( HumanEmitter::new(stderr_destination(color_config), fallback_bundle) .short_message(short), ) } - config::ErrorOutputType::Json { pretty, json_rendered } => Box::new(JsonEmitter::new( - Box::new(io::BufWriter::new(io::stderr())), - Lrc::new(SourceMap::new(FilePathMapping::empty())), - fallback_bundle, - pretty, - json_rendered, - )), + config::ErrorOutputType::Json { pretty, json_rendered, color_config } => { + Box::new(JsonEmitter::new( + Box::new(io::BufWriter::new(io::stderr())), + Lrc::new(SourceMap::new(FilePathMapping::empty())), + fallback_bundle, + pretty, + json_rendered, + color_config, + )) + } }; emitter } diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index e4549796b3e83..9c7a9f8467f5a 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -362,9 +362,10 @@ impl Options { } let color = config::parse_color(early_dcx, matches); - let config::JsonConfig { json_rendered, json_unused_externs, .. } = + let config::JsonConfig { json_rendered, json_unused_externs, json_color, .. } = config::parse_json(early_dcx, matches); - let error_format = config::parse_error_format(early_dcx, matches, color, json_rendered); + let error_format = + config::parse_error_format(early_dcx, matches, color, json_color, json_rendered); let diagnostic_width = matches.opt_get("diagnostic-width").unwrap_or_default(); let codegen_options = CodegenOptions::build(early_dcx, matches); diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index fea31e7ecbc9a..ae3456e139991 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -138,8 +138,8 @@ pub(crate) fn new_dcx( false, ); let emitter: Box = match error_format { - ErrorOutputType::HumanReadable(kind) => { - let (short, color_config) = kind.unzip(); + ErrorOutputType::HumanReadable(kind, color_config) => { + let short = matches!(kind, HumanReadableErrorType::Short); Box::new( HumanEmitter::new(stderr_destination(color_config), fallback_bundle) .sm(source_map.map(|sm| sm as _)) @@ -150,7 +150,7 @@ pub(crate) fn new_dcx( .ui_testing(unstable_opts.ui_testing), ) } - ErrorOutputType::Json { pretty, json_rendered } => { + ErrorOutputType::Json { pretty, json_rendered, color_config } => { let source_map = source_map.unwrap_or_else(|| { Lrc::new(source_map::SourceMap::new(source_map::FilePathMapping::empty())) }); @@ -161,6 +161,7 @@ pub(crate) fn new_dcx( fallback_bundle, pretty, json_rendered, + color_config, ) .ui_testing(unstable_opts.ui_testing) .diagnostic_width(diagnostic_width) diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 41eb142dd1e29..6804439604814 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -422,8 +422,8 @@ fn run_test( path_for_rustdoc.to_str().expect("target path must be valid unicode") } }); - if let ErrorOutputType::HumanReadable(kind) = rustdoc_options.error_format { - let (short, color_config) = kind.unzip(); + if let ErrorOutputType::HumanReadable(kind, color_config) = rustdoc_options.error_format { + let short = matches!(kind, HumanReadableErrorType::Short); if short { compiler.arg("--error-format").arg("short"); From 95c1c34fff6675910986c93c3fea3c03e9810f6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 8 Aug 2024 14:43:27 +0000 Subject: [PATCH 647/786] review comments --- compiler/rustc_errors/src/emitter.rs | 6 ++++++ compiler/rustc_errors/src/json.rs | 4 ++-- compiler/rustc_session/src/session.rs | 4 ++-- src/librustdoc/core.rs | 2 +- src/librustdoc/doctest.rs | 2 +- 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 5bd3b328cb8d0..9f4d9263f0f40 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -48,6 +48,12 @@ pub enum HumanReadableErrorType { Short, } +impl HumanReadableErrorType { + pub fn short(&self) -> bool { + *self == HumanReadableErrorType::Short + } +} + #[derive(Clone, Copy, Debug)] struct Margin { /// The available whitespace in the left that can be consumed when centering. diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index 02a0de201edd4..32e59f9ab036a 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -176,7 +176,7 @@ impl Emitter for JsonEmitter { } fn should_show_explain(&self) -> bool { - !matches!(self.json_rendered, HumanReadableErrorType::Short) + !self.json_rendered.short() } } @@ -356,7 +356,7 @@ impl Diagnostic { let buf = BufWriter::default(); let mut dst: Destination = Box::new(buf.clone()); - let short = matches!(je.json_rendered, HumanReadableErrorType::Short); + let short = je.json_rendered.short(); match je.color_config { ColorConfig::Always | ColorConfig::Auto => dst = Box::new(termcolor::Ansi::new(dst)), ColorConfig::Never => {} diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index c0fa377f8ba52..672dddf871e02 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -951,7 +951,7 @@ fn default_emitter( }; match sopts.error_format { config::ErrorOutputType::HumanReadable(kind, color_config) => { - let short = matches!(kind, HumanReadableErrorType::Short); + let short = kind.short(); if let HumanReadableErrorType::AnnotateSnippet = kind { let emitter = AnnotateSnippetEmitter::new( @@ -1427,7 +1427,7 @@ fn mk_emitter(output: ErrorOutputType) -> Box { fallback_fluent_bundle(vec![rustc_errors::DEFAULT_LOCALE_RESOURCE], false); let emitter: Box = match output { config::ErrorOutputType::HumanReadable(kind, color_config) => { - let short = matches!(kind, HumanReadableErrorType::Short); + let short = kind.short(); Box::new( HumanEmitter::new(stderr_destination(color_config), fallback_bundle) .short_message(short), diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index ae3456e139991..08a4a3f3fb264 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -139,7 +139,7 @@ pub(crate) fn new_dcx( ); let emitter: Box = match error_format { ErrorOutputType::HumanReadable(kind, color_config) => { - let short = matches!(kind, HumanReadableErrorType::Short); + let short = kind.short(); Box::new( HumanEmitter::new(stderr_destination(color_config), fallback_bundle) .sm(source_map.map(|sm| sm as _)) diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 6804439604814..08d6a5a52b21a 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -423,7 +423,7 @@ fn run_test( } }); if let ErrorOutputType::HumanReadable(kind, color_config) = rustdoc_options.error_format { - let short = matches!(kind, HumanReadableErrorType::Short); + let short = kind.short(); if short { compiler.arg("--error-format").arg("short"); From 85b5e42d5e5d53b828a55bb01676bbdc495e5077 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 5 Aug 2024 15:25:40 -0400 Subject: [PATCH 648/786] Do normalize when computing struct tails in codegen --- compiler/rustc_codegen_llvm/src/builder.rs | 5 +++-- compiler/rustc_ty_utils/src/abi.rs | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 77e51f941508c..c4c1516b91142 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -12,7 +12,8 @@ use rustc_data_structures::small_c_str::SmallCStr; use rustc_hir::def_id::DefId; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::ty::layout::{ - FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, TyAndLayout, + FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, LayoutError, LayoutOfHelpers, + TyAndLayout, }; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_sanitizers::{cfi, kcfi}; @@ -531,7 +532,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { #[instrument(level = "trace", skip(self))] fn load_operand(&mut self, place: PlaceRef<'tcx, &'ll Value>) -> OperandRef<'tcx, &'ll Value> { if place.layout.is_unsized() { - let tail = self.tcx.struct_tail_with_normalize(place.layout.ty, |ty| ty, || {}); + let tail = self.tcx.struct_tail_erasing_lifetimes(place.layout.ty, self.param_env()); if matches!(tail.kind(), ty::Foreign(..)) { // Unsized locals and, at least conceptually, even unsized arguments must be copied // around, which requires dynamically determining their size. Therefore, we cannot diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index f1675f80717f0..218a44401e226 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -549,7 +549,7 @@ fn fn_abi_sanity_check<'tcx>( // With metadata. Must be unsized and not on the stack. assert!(arg.layout.is_unsized() && !on_stack); // Also, must not be `extern` type. - let tail = cx.tcx.struct_tail_with_normalize(arg.layout.ty, |ty| ty, || {}); + let tail = cx.tcx.struct_tail_erasing_lifetimes(arg.layout.ty, cx.param_env()); if matches!(tail.kind(), ty::Foreign(..)) { // These types do not have metadata, so having `meta_attrs` is bogus. // Conceptually, unsized arguments must be copied around, which requires dynamically From d9dd5509dcf56b22b6c1844ed3077f292e4a87bf Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 5 Aug 2024 15:53:37 -0400 Subject: [PATCH 649/786] Normalize when computing offset_of for slice tail --- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 13 ++++++- .../offset-of/offset-of-slice-normalized.rs | 37 +++++++++++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 tests/ui/offset-of/offset-of-slice-normalized.rs diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 8c1aa66332fc9..841d25b54cc88 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -404,8 +404,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { code: traits::ObligationCauseCode<'tcx>, ) { if !ty.references_error() { - let tail = - self.tcx.struct_tail_with_normalize(ty, |ty| self.normalize(span, ty), || {}); + let tail = self.tcx.struct_tail_with_normalize( + ty, + |ty| { + if self.next_trait_solver() { + self.try_structurally_resolve_type(span, ty) + } else { + self.normalize(span, ty) + } + }, + || {}, + ); // Sized types have static alignment, and so do slices. if tail.is_trivially_sized(self.tcx) || matches!(tail.kind(), ty::Slice(..)) { // Nothing else is required here. diff --git a/tests/ui/offset-of/offset-of-slice-normalized.rs b/tests/ui/offset-of/offset-of-slice-normalized.rs new file mode 100644 index 0000000000000..9d1fd9dd2ee14 --- /dev/null +++ b/tests/ui/offset-of/offset-of-slice-normalized.rs @@ -0,0 +1,37 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@ run-pass + +#![feature(offset_of_slice)] + +use std::mem::offset_of; + +trait Mirror { + type Assoc: ?Sized; +} +impl Mirror for T { + type Assoc = T; +} + +#[repr(C)] +struct S { + a: u8, + b: (u8, u8), + c: <[i32] as Mirror>::Assoc, +} + +#[repr(C)] +struct T { + x: i8, + y: S, +} + +type Tup = (i16, <[i32] as Mirror>::Assoc); + +fn main() { + assert_eq!(offset_of!(S, c), 4); + assert_eq!(offset_of!(T, y), 4); + assert_eq!(offset_of!(T, y.c), 8); + assert_eq!(offset_of!(Tup, 1), 4); +} From f81549c9ca465e87ab6902dee8cdb4989ee50077 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 5 Aug 2024 16:30:00 -0400 Subject: [PATCH 650/786] Normalize struct tail properly in disalignment check --- .../rustc_const_eval/src/util/alignment.rs | 2 +- ...rr => unaligned_references.current.stderr} | 26 ++-- .../ui/lint/unaligned_references.next.stderr | 133 ++++++++++++++++++ tests/ui/lint/unaligned_references.rs | 26 +++- 4 files changed, 172 insertions(+), 15 deletions(-) rename tests/ui/lint/{unaligned_references.stderr => unaligned_references.current.stderr} (93%) create mode 100644 tests/ui/lint/unaligned_references.next.stderr diff --git a/compiler/rustc_const_eval/src/util/alignment.rs b/compiler/rustc_const_eval/src/util/alignment.rs index 528274e6abac4..a8ef37432bb5a 100644 --- a/compiler/rustc_const_eval/src/util/alignment.rs +++ b/compiler/rustc_const_eval/src/util/alignment.rs @@ -22,7 +22,7 @@ where }; let ty = place.ty(local_decls, tcx).ty; - let unsized_tail = || tcx.struct_tail_with_normalize(ty, |ty| ty, || {}); + let unsized_tail = || tcx.struct_tail_erasing_lifetimes(ty, param_env); match tcx.layout_of(param_env.and(ty)) { Ok(layout) if layout.align.abi <= pack diff --git a/tests/ui/lint/unaligned_references.stderr b/tests/ui/lint/unaligned_references.current.stderr similarity index 93% rename from tests/ui/lint/unaligned_references.stderr rename to tests/ui/lint/unaligned_references.current.stderr index 328cafbd9864b..0f980c5301f37 100644 --- a/tests/ui/lint/unaligned_references.stderr +++ b/tests/ui/lint/unaligned_references.current.stderr @@ -1,5 +1,5 @@ error[E0793]: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:28:13 + --> $DIR/unaligned_references.rs:32:13 | LL | &self.x; | ^^^^^^^ @@ -9,7 +9,7 @@ LL | &self.x; = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error[E0793]: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:40:24 + --> $DIR/unaligned_references.rs:44:24 | LL | println!("{:?}", &*foo.0); | ^^^^^ @@ -19,7 +19,7 @@ LL | println!("{:?}", &*foo.0); = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error[E0793]: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:42:24 + --> $DIR/unaligned_references.rs:46:24 | LL | println!("{:?}", &*foo.0); | ^^^^^ @@ -29,7 +29,7 @@ LL | println!("{:?}", &*foo.0); = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error[E0793]: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:47:24 + --> $DIR/unaligned_references.rs:51:24 | LL | println!("{:?}", &*foo.0); | ^^^^^ @@ -39,7 +39,7 @@ LL | println!("{:?}", &*foo.0); = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error[E0793]: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:57:17 + --> $DIR/unaligned_references.rs:81:17 | LL | let _ = &good.ptr; | ^^^^^^^^^ @@ -49,7 +49,7 @@ LL | let _ = &good.ptr; = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error[E0793]: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:58:17 + --> $DIR/unaligned_references.rs:82:17 | LL | let _ = &good.data; | ^^^^^^^^^^ @@ -59,7 +59,7 @@ LL | let _ = &good.data; = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error[E0793]: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:60:17 + --> $DIR/unaligned_references.rs:84:17 | LL | let _ = &good.data as *const _; | ^^^^^^^^^^ @@ -69,7 +69,7 @@ LL | let _ = &good.data as *const _; = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error[E0793]: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:61:27 + --> $DIR/unaligned_references.rs:85:27 | LL | let _: *const _ = &good.data; | ^^^^^^^^^^ @@ -79,7 +79,7 @@ LL | let _: *const _ = &good.data; = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error[E0793]: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:63:17 + --> $DIR/unaligned_references.rs:87:17 | LL | let _ = good.data.clone(); | ^^^^^^^^^ @@ -89,7 +89,7 @@ LL | let _ = good.data.clone(); = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error[E0793]: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:65:17 + --> $DIR/unaligned_references.rs:89:17 | LL | let _ = &good.data2[0]; | ^^^^^^^^^^^^^^ @@ -99,7 +99,7 @@ LL | let _ = &good.data2[0]; = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error[E0793]: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:74:17 + --> $DIR/unaligned_references.rs:98:17 | LL | let _ = &packed2.x; | ^^^^^^^^^^ @@ -109,7 +109,7 @@ LL | let _ = &packed2.x; = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error[E0793]: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:113:20 + --> $DIR/unaligned_references.rs:137:20 | LL | let _ref = &m1.1.a; | ^^^^^^^ @@ -119,7 +119,7 @@ LL | let _ref = &m1.1.a; = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error[E0793]: reference to packed field is unaligned - --> $DIR/unaligned_references.rs:116:20 + --> $DIR/unaligned_references.rs:140:20 | LL | let _ref = &m2.1.a; | ^^^^^^^ diff --git a/tests/ui/lint/unaligned_references.next.stderr b/tests/ui/lint/unaligned_references.next.stderr new file mode 100644 index 0000000000000..0f980c5301f37 --- /dev/null +++ b/tests/ui/lint/unaligned_references.next.stderr @@ -0,0 +1,133 @@ +error[E0793]: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:32:13 + | +LL | &self.x; + | ^^^^^^^ + | + = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses + = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error[E0793]: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:44:24 + | +LL | println!("{:?}", &*foo.0); + | ^^^^^ + | + = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses + = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error[E0793]: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:46:24 + | +LL | println!("{:?}", &*foo.0); + | ^^^^^ + | + = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses + = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error[E0793]: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:51:24 + | +LL | println!("{:?}", &*foo.0); + | ^^^^^ + | + = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses + = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error[E0793]: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:81:17 + | +LL | let _ = &good.ptr; + | ^^^^^^^^^ + | + = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses + = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error[E0793]: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:82:17 + | +LL | let _ = &good.data; + | ^^^^^^^^^^ + | + = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses + = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error[E0793]: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:84:17 + | +LL | let _ = &good.data as *const _; + | ^^^^^^^^^^ + | + = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses + = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error[E0793]: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:85:27 + | +LL | let _: *const _ = &good.data; + | ^^^^^^^^^^ + | + = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses + = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error[E0793]: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:87:17 + | +LL | let _ = good.data.clone(); + | ^^^^^^^^^ + | + = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses + = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error[E0793]: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:89:17 + | +LL | let _ = &good.data2[0]; + | ^^^^^^^^^^^^^^ + | + = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses + = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error[E0793]: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:98:17 + | +LL | let _ = &packed2.x; + | ^^^^^^^^^^ + | + = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses + = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error[E0793]: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:137:20 + | +LL | let _ref = &m1.1.a; + | ^^^^^^^ + | + = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses + = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error[E0793]: reference to packed field is unaligned + --> $DIR/unaligned_references.rs:140:20 + | +LL | let _ref = &m2.1.a; + | ^^^^^^^ + | + = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses + = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error: aborting due to 13 previous errors + +For more information about this error, try `rustc --explain E0793`. diff --git a/tests/ui/lint/unaligned_references.rs b/tests/ui/lint/unaligned_references.rs index 3f6dab35475e8..321e3ed135c47 100644 --- a/tests/ui/lint/unaligned_references.rs +++ b/tests/ui/lint/unaligned_references.rs @@ -1,5 +1,9 @@ -use std::mem::ManuallyDrop; +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + use std::fmt::Debug; +use std::mem::ManuallyDrop; #[repr(packed)] pub struct Good { @@ -50,6 +54,26 @@ fn packed_dyn() { println!("{:?}", &*foo.0); // no error! } +// Test for #115396 +fn packed_slice_behind_alias() { + trait Mirror { + type Assoc: ?Sized; + } + impl Mirror for T { + type Assoc = T; + } + + struct W(::Assoc); + + #[repr(packed)] + struct Unaligned(ManuallyDrop>); + + // Even if the actual alignment is 1, we cannot know that when looking at `dyn Debug.` + let ref local: Unaligned<[_; 3]> = Unaligned(ManuallyDrop::new(W([3, 5, 8u8]))); + let foo: &Unaligned<[u8]> = local; + let x = &foo.0; // Fine, since the tail of `foo` is `[_]` +} + fn main() { unsafe { let good = Good { data: 0, ptr: &0, data2: [0, 0], aligned: [0; 32] }; From c2a0d9ca6eccbfaf1c6cd189dca0216a0ac66c75 Mon Sep 17 00:00:00 2001 From: schvv31n Date: Thu, 8 Aug 2024 17:13:15 +0100 Subject: [PATCH 651/786] rustdoc: fixed #101105 modules are now stripped based on the same logic that's used to strip other item kinds --- src/librustdoc/passes/stripper.rs | 9 ++++++++- tests/rustdoc-json/pub_mod_in_private_mod.rs | 6 ++++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 tests/rustdoc-json/pub_mod_in_private_mod.rs diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs index d1e2b9978f7de..f807c3362c4cb 100644 --- a/src/librustdoc/passes/stripper.rs +++ b/src/librustdoc/passes/stripper.rs @@ -95,7 +95,14 @@ impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> { } clean::ModuleItem(..) => { - if i.item_id.is_local() && i.visibility(self.tcx) != Some(Visibility::Public) { + if i.item_id.is_local() + && !is_item_reachable( + self.tcx, + self.is_json_output, + self.effective_visibilities, + i.item_id, + ) + { debug!("Stripper: stripping module {:?}", i.name); let old = mem::replace(&mut self.update_retained, false); let ret = strip_item(self.fold_item_recur(i)); diff --git a/tests/rustdoc-json/pub_mod_in_private_mod.rs b/tests/rustdoc-json/pub_mod_in_private_mod.rs new file mode 100644 index 0000000000000..112ab9c68f002 --- /dev/null +++ b/tests/rustdoc-json/pub_mod_in_private_mod.rs @@ -0,0 +1,6 @@ +// See https://github.com/rust-lang/rust/issues/101105 + +//@ !has "$.index[*][?(@.name=='nucleus')]" +mod corpus { + pub mod nucleus {} +} From b9164319769c52bd98607d80b4c7c53e06bf6887 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 8 Aug 2024 11:56:12 -0400 Subject: [PATCH 652/786] Rename struct_tail_erasing_lifetimes to struct_tail_for_codegen --- compiler/rustc_codegen_cranelift/src/common.rs | 2 +- compiler/rustc_codegen_cranelift/src/unsize.rs | 2 +- compiler/rustc_codegen_llvm/src/builder.rs | 2 +- compiler/rustc_codegen_llvm/src/debuginfo/utils.rs | 2 +- compiler/rustc_codegen_ssa/src/base.rs | 2 +- compiler/rustc_codegen_ssa/src/traits/type_.rs | 2 +- compiler/rustc_const_eval/src/interpret/call.rs | 5 ++--- compiler/rustc_const_eval/src/interpret/cast.rs | 2 +- .../rustc_const_eval/src/interpret/validity.rs | 2 +- compiler/rustc_const_eval/src/util/alignment.rs | 2 +- compiler/rustc_hir_analysis/src/check/wfcheck.rs | 2 +- compiler/rustc_middle/src/ty/layout.rs | 4 ++-- compiler/rustc_middle/src/ty/util.rs | 14 +++++--------- compiler/rustc_monomorphize/src/collector.rs | 4 ++-- compiler/rustc_ty_utils/src/abi.rs | 2 +- compiler/rustc_ty_utils/src/layout.rs | 2 +- .../clippy_utils/src/qualify_min_const_fn.rs | 2 +- 17 files changed, 24 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index 0931713993691..a1b29a4222579 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs @@ -107,7 +107,7 @@ pub(crate) fn has_ptr_meta<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { return false; } - let tail = tcx.struct_tail_erasing_lifetimes(ty, ParamEnv::reveal_all()); + let tail = tcx.struct_tail_for_codegen(ty, ParamEnv::reveal_all()); match tail.kind() { ty::Foreign(..) => false, ty::Str | ty::Slice(..) | ty::Dynamic(..) => true, diff --git a/compiler/rustc_codegen_cranelift/src/unsize.rs b/compiler/rustc_codegen_cranelift/src/unsize.rs index 967aa53abbda5..e09cd16e89a64 100644 --- a/compiler/rustc_codegen_cranelift/src/unsize.rs +++ b/compiler/rustc_codegen_cranelift/src/unsize.rs @@ -22,7 +22,7 @@ pub(crate) fn unsized_info<'tcx>( old_info: Option, ) -> Value { let (source, target) = - fx.tcx.struct_lockstep_tails_erasing_lifetimes(source, target, ParamEnv::reveal_all()); + fx.tcx.struct_lockstep_tails_for_codegen(source, target, ParamEnv::reveal_all()); match (&source.kind(), &target.kind()) { (&ty::Array(_, len), &ty::Slice(_)) => fx .bcx diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index c4c1516b91142..0f44c5dba5e55 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -532,7 +532,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { #[instrument(level = "trace", skip(self))] fn load_operand(&mut self, place: PlaceRef<'tcx, &'ll Value>) -> OperandRef<'tcx, &'ll Value> { if place.layout.is_unsized() { - let tail = self.tcx.struct_tail_erasing_lifetimes(place.layout.ty, self.param_env()); + let tail = self.tcx.struct_tail_for_codegen(place.layout.ty, self.param_env()); if matches!(tail.kind(), ty::Foreign(..)) { // Unsized locals and, at least conceptually, even unsized arguments must be copied // around, which requires dynamically determining their size. Therefore, we cannot diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs index d51e15d12e2fc..e542aa96e8a23 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs @@ -62,7 +62,7 @@ pub(crate) fn fat_pointer_kind<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, pointee_ty: Ty<'tcx>, ) -> Option { - let pointee_tail_ty = cx.tcx.struct_tail_erasing_lifetimes(pointee_ty, cx.param_env()); + let pointee_tail_ty = cx.tcx.struct_tail_for_codegen(pointee_ty, cx.param_env()); let layout = cx.layout_of(pointee_tail_ty); trace!( "fat_pointer_kind: {:?} has layout {:?} (is_unsized? {})", diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index f4e44e63d73cc..f1e7f87f56767 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -143,7 +143,7 @@ pub fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( ) -> Bx::Value { let cx = bx.cx(); let (source, target) = - cx.tcx().struct_lockstep_tails_erasing_lifetimes(source, target, bx.param_env()); + cx.tcx().struct_lockstep_tails_for_codegen(source, target, bx.param_env()); match (source.kind(), target.kind()) { (&ty::Array(_, len), &ty::Slice(_)) => { cx.const_usize(len.eval_target_usize(cx.tcx(), ty::ParamEnv::reveal_all())) diff --git a/compiler/rustc_codegen_ssa/src/traits/type_.rs b/compiler/rustc_codegen_ssa/src/traits/type_.rs index 80dad79179a36..7c042c0c6219a 100644 --- a/compiler/rustc_codegen_ssa/src/traits/type_.rs +++ b/compiler/rustc_codegen_ssa/src/traits/type_.rs @@ -91,7 +91,7 @@ pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> { return false; } - let tail = self.tcx().struct_tail_erasing_lifetimes(ty, param_env); + let tail = self.tcx().struct_tail_for_codegen(ty, param_env); match tail.kind() { ty::Foreign(..) => false, ty::Str | ty::Slice(..) | ty::Dynamic(..) => true, diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index b5f3d07d90b35..fdbdfc7e1b8b3 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -678,9 +678,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } else { // Doesn't have to be a `dyn Trait`, but the unsized tail must be `dyn Trait`. // (For that reason we also cannot use `unpack_dyn_trait`.) - let receiver_tail = self - .tcx - .struct_tail_erasing_lifetimes(receiver_place.layout.ty, self.param_env); + let receiver_tail = + self.tcx.struct_tail_for_codegen(receiver_place.layout.ty, self.param_env); let ty::Dynamic(receiver_trait, _, ty::Dyn) = receiver_tail.kind() else { span_bug!( self.cur_span(), diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index b2f07de0ac4e2..c3d7f2234ed95 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -386,7 +386,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ) -> InterpResult<'tcx> { // A -> A conversion let (src_pointee_ty, dest_pointee_ty) = - self.tcx.struct_lockstep_tails_erasing_lifetimes(source_ty, cast_ty, self.param_env); + self.tcx.struct_lockstep_tails_for_codegen(source_ty, cast_ty, self.param_env); match (&src_pointee_ty.kind(), &dest_pointee_ty.kind()) { (&ty::Array(_, length), &ty::Slice(_)) => { diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 460f5448634b5..fadc4ee6c8a0c 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -343,7 +343,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { meta: MemPlaceMeta, pointee: TyAndLayout<'tcx>, ) -> InterpResult<'tcx> { - let tail = self.ecx.tcx.struct_tail_erasing_lifetimes(pointee.ty, self.ecx.param_env); + let tail = self.ecx.tcx.struct_tail_for_codegen(pointee.ty, self.ecx.param_env); match tail.kind() { ty::Dynamic(data, _, ty::Dyn) => { let vtable = meta.unwrap_meta().to_pointer(self.ecx)?; diff --git a/compiler/rustc_const_eval/src/util/alignment.rs b/compiler/rustc_const_eval/src/util/alignment.rs index a8ef37432bb5a..5ad55968398eb 100644 --- a/compiler/rustc_const_eval/src/util/alignment.rs +++ b/compiler/rustc_const_eval/src/util/alignment.rs @@ -22,7 +22,7 @@ where }; let ty = place.ty(local_decls, tcx).ty; - let unsized_tail = || tcx.struct_tail_erasing_lifetimes(ty, param_env); + let unsized_tail = || tcx.struct_tail_for_codegen(ty, param_env); match tcx.layout_of(param_env.and(ty)) { Ok(layout) if layout.align.abi <= pack diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index c878095ba0d70..a9f8630741a81 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1276,7 +1276,7 @@ fn check_item_type( UnsizedHandling::Forbid => true, UnsizedHandling::Allow => false, UnsizedHandling::AllowIfForeignTail => { - let tail = tcx.struct_tail_erasing_lifetimes(item_ty, wfcx.param_env); + let tail = tcx.struct_tail_for_codegen(item_ty, wfcx.param_env); !matches!(tail.kind(), ty::Foreign(_)) } }; diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index d7d27975f60a9..9204405d58f11 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -869,7 +869,7 @@ where metadata } } else { - match tcx.struct_tail_erasing_lifetimes(pointee, cx.param_env()).kind() { + match tcx.struct_tail_for_codegen(pointee, cx.param_env()).kind() { ty::Slice(_) | ty::Str => tcx.types.usize, ty::Dynamic(data, _, ty::Dyn) => mk_dyn_vtable(data.principal()), _ => bug!("TyAndLayout::field({:?}): not applicable", this), @@ -1348,7 +1348,7 @@ impl<'tcx> TyCtxt<'tcx> { layout = layout.field(&cx, index); if !layout.is_sized() { // If it is not sized, then the tail must still have at least a known static alignment. - let tail = self.struct_tail_erasing_lifetimes(layout.ty, param_env); + let tail = self.struct_tail_for_codegen(layout.ty, param_env); if !matches!(tail.kind(), ty::Slice(..)) { bug!( "offset of not-statically-aligned field (type {:?}) cannot be computed statically", diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 3cf8531bb62d5..365f434a264e2 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -186,11 +186,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Should only be called if `ty` has no inference variables and does not /// need its lifetimes preserved (e.g. as part of codegen); otherwise /// normalization attempt may cause compiler bugs. - pub fn struct_tail_erasing_lifetimes( - self, - ty: Ty<'tcx>, - param_env: ty::ParamEnv<'tcx>, - ) -> Ty<'tcx> { + pub fn struct_tail_for_codegen(self, ty: Ty<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> { let tcx = self; tcx.struct_tail_with_normalize(ty, |ty| tcx.normalize_erasing_regions(param_env, ty), || {}) } @@ -203,7 +199,7 @@ impl<'tcx> TyCtxt<'tcx> { /// handle `::Assoc` and `impl Trait`); pass the identity /// function to indicate no normalization should take place. /// - /// See also `struct_tail_erasing_lifetimes`, which is suitable for use + /// See also `struct_tail_for_codegen`, which is suitable for use /// during codegen. pub fn struct_tail_with_normalize( self, @@ -272,13 +268,13 @@ impl<'tcx> TyCtxt<'tcx> { /// Same as applying `struct_tail` on `source` and `target`, but only /// keeps going as long as the two types are instances of the same /// structure definitions. - /// For `(Foo>, Foo)`, the result will be `(Foo, Trait)`, + /// For `(Foo>, Foo)`, the result will be `(Foo, dyn Trait)`, /// whereas struct_tail produces `T`, and `Trait`, respectively. /// /// Should only be called if the types have no inference variables and do /// not need their lifetimes preserved (e.g., as part of codegen); otherwise, /// normalization attempt may cause compiler bugs. - pub fn struct_lockstep_tails_erasing_lifetimes( + pub fn struct_lockstep_tails_for_codegen( self, source: Ty<'tcx>, target: Ty<'tcx>, @@ -296,7 +292,7 @@ impl<'tcx> TyCtxt<'tcx> { /// For `(Foo>, Foo)`, the result will be `(Foo, Trait)`, /// whereas struct_tail produces `T`, and `Trait`, respectively. /// - /// See also `struct_lockstep_tails_erasing_lifetimes`, which is suitable for use + /// See also `struct_lockstep_tails_for_codegen`, which is suitable for use /// during codegen. pub fn struct_lockstep_tails_with_normalize( self, diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index df2abf6dc9cc4..0ae635f9b73e5 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1019,7 +1019,7 @@ fn find_vtable_types_for_unsizing<'tcx>( if ty.is_sized(tcx.tcx, param_env) { return false; } - let tail = tcx.struct_tail_erasing_lifetimes(ty, param_env); + let tail = tcx.struct_tail_for_codegen(ty, param_env); match tail.kind() { ty::Foreign(..) => false, ty::Str | ty::Slice(..) | ty::Dynamic(..) => true, @@ -1029,7 +1029,7 @@ fn find_vtable_types_for_unsizing<'tcx>( if type_has_metadata(inner_source) { (inner_source, inner_target) } else { - tcx.struct_lockstep_tails_erasing_lifetimes(inner_source, inner_target, param_env) + tcx.struct_lockstep_tails_for_codegen(inner_source, inner_target, param_env) } }; diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 218a44401e226..d90c3bedc7017 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -549,7 +549,7 @@ fn fn_abi_sanity_check<'tcx>( // With metadata. Must be unsized and not on the stack. assert!(arg.layout.is_unsized() && !on_stack); // Also, must not be `extern` type. - let tail = cx.tcx.struct_tail_erasing_lifetimes(arg.layout.ty, cx.param_env()); + let tail = cx.tcx.struct_tail_for_codegen(arg.layout.ty, cx.param_env()); if matches!(tail.kind(), ty::Foreign(..)) { // These types do not have metadata, so having `meta_attrs` is bogus. // Conceptually, unsized arguments must be copied around, which requires dynamically diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 3ef10f4e43c4b..1eb03fc3bd6a1 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -244,7 +244,7 @@ fn layout_of_uncached<'tcx>( metadata } else { - let unsized_part = tcx.struct_tail_erasing_lifetimes(pointee, param_env); + let unsized_part = tcx.struct_tail_for_codegen(pointee, param_env); match unsized_part.kind() { ty::Foreign(..) => { diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index f206b2ceebcb1..553af913ef9df 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -142,7 +142,7 @@ fn check_rvalue<'tcx>( // 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)); + let unsized_ty = tcx.struct_tail_for_codegen(pointee_ty, tcx.param_env(def_id)); if let ty::Slice(_) | ty::Str = unsized_ty.kind() { check_operand(tcx, op, span, body, msrv)?; // Casting/coercing things to slices is fine. From 85ec34182415f8ba475cc157f405c785db05e4be Mon Sep 17 00:00:00 2001 From: Shina <53410646+s7tya@users.noreply.github.com> Date: Fri, 9 Aug 2024 01:24:39 +0900 Subject: [PATCH 653/786] bump up rustc-perf's version --- src/tools/rustc-perf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rustc-perf b/src/tools/rustc-perf index c64bb60dd1636..d5055e78042c7 160000 --- a/src/tools/rustc-perf +++ b/src/tools/rustc-perf @@ -1 +1 @@ -Subproject commit c64bb60dd1636922b1ccbb82867bed934a99dbcb +Subproject commit d5055e78042c739deeb3fe0bef83fde0e5cc2594 From e608b2fcf57b3f8475b7963367ba8a98079d2e49 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Thu, 8 Aug 2024 18:55:00 +0200 Subject: [PATCH 654/786] Bump nightly version -> 2024-08-08 --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 69fb11a4824af..5fbe4e544a9e4 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2024-07-25" +channel = "nightly-2024-08-08" components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] profile = "minimal" From 1bf30eb5aa621541f1e3ab3a470db96a35210df0 Mon Sep 17 00:00:00 2001 From: schvv31n Date: Thu, 8 Aug 2024 17:55:52 +0100 Subject: [PATCH 655/786] rustdoc-json: added a test for #107278 --- tests/rustdoc-json/impls/pub_for_hidden_private.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 tests/rustdoc-json/impls/pub_for_hidden_private.rs diff --git a/tests/rustdoc-json/impls/pub_for_hidden_private.rs b/tests/rustdoc-json/impls/pub_for_hidden_private.rs new file mode 100644 index 0000000000000..261ffbfeb4a4c --- /dev/null +++ b/tests/rustdoc-json/impls/pub_for_hidden_private.rs @@ -0,0 +1,10 @@ +//@ compile-flags: --document-private-items --document-hidden-items + +pub trait TheTrait {} + +#[doc(hidden)] +struct Value {} + +//@ has '$.index[*][?(@.docs=="THE IMPL")]' +/// THE IMPL +impl TheTrait for Value {} From 8be2688e456f5d79448564e55f35272821d6246b Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Thu, 8 Aug 2024 19:14:09 +0200 Subject: [PATCH 656/786] Update Cargo.lock --- Cargo.lock | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fb762cd2fe629..4bd99b7fbe7ac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -564,7 +564,7 @@ dependencies = [ "termize", "tokio", "toml 0.7.8", - "ui_test 0.24.0", + "ui_test 0.25.0", "walkdir", ] @@ -572,6 +572,7 @@ dependencies = [ name = "clippy_config" version = "0.1.82" dependencies = [ + "itertools", "rustc-semver", "serde", "toml 0.7.8", @@ -4936,9 +4937,9 @@ dependencies = [ [[package]] name = "spanned" -version = "0.2.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed14ba8b4b82241bd5daba2c49185d4a0581a0058355fe96537338f002b8605d" +checksum = "86af297923fbcfd107c20a189a6e9c872160df71a7190ae4a7a6c5dce4b2feb6" dependencies = [ "bstr", "color-eyre", @@ -5562,9 +5563,9 @@ dependencies = [ [[package]] name = "ui_test" -version = "0.24.0" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc1c6c78d55482388711c8d417b8e547263046a607512278fed274c54633bbe4" +checksum = "f7e4f339f62edc873975c47115f9e71c5454ddaa37c1142b42fc0b2672c8dacb" dependencies = [ "annotate-snippets 0.11.4", "anyhow", From ec1c424293c04258da127ed4dfc8d4289834efe6 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 7 Aug 2024 12:36:41 -0400 Subject: [PATCH 657/786] Don't implement AsyncFn for FnDef/FnPtr that wouldnt implement Fn --- .../src/solve/assembly/structural_traits.rs | 60 ++++++++++++------- .../src/traits/select/candidate_assembly.rs | 16 ++++- .../fn-exception-target-features.rs | 17 ++++++ .../fn-exception-target-features.stderr | 17 ++++++ .../async-closures/fn-exception.rs | 21 +++++++ .../async-closures/fn-exception.stderr | 31 ++++++++++ 6 files changed, 139 insertions(+), 23 deletions(-) create mode 100644 tests/ui/async-await/async-closures/fn-exception-target-features.rs create mode 100644 tests/ui/async-await/async-closures/fn-exception-target-features.stderr create mode 100644 tests/ui/async-await/async-closures/fn-exception.rs create mode 100644 tests/ui/async-await/async-closures/fn-exception.stderr diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index e69d8d84d7d89..00837f7cdd87d 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -458,28 +458,23 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable { - let bound_sig = self_ty.fn_sig(cx); - let sig = bound_sig.skip_binder(); - let future_trait_def_id = cx.require_lang_item(TraitSolverLangItem::Future); - // `FnDef` and `FnPtr` only implement `AsyncFn*` when their - // return type implements `Future`. - let nested = vec![ - bound_sig - .rebind(ty::TraitRef::new(cx, future_trait_def_id, [sig.output()])) - .upcast(cx), - ]; - let future_output_def_id = cx.require_lang_item(TraitSolverLangItem::FutureOutput); - let future_output_ty = Ty::new_projection(cx, future_output_def_id, [sig.output()]); - Ok(( - bound_sig.rebind(AsyncCallableRelevantTypes { - tupled_inputs_ty: Ty::new_tup(cx, sig.inputs().as_slice()), - output_coroutine_ty: sig.output(), - coroutine_return_ty: future_output_ty, - }), - nested, - )) + ty::FnDef(def_id, _) => { + let sig = self_ty.fn_sig(cx); + if sig.skip_binder().is_fn_trait_compatible() && !cx.has_target_features(def_id) { + fn_item_to_async_callable(cx, sig) + } else { + Err(NoSolution) + } + } + ty::FnPtr(..) => { + let sig = self_ty.fn_sig(cx); + if sig.skip_binder().is_fn_trait_compatible() { + fn_item_to_async_callable(cx, sig) + } else { + Err(NoSolution) + } } + ty::Closure(_, args) => { let args = args.as_closure(); let bound_sig = args.sig(); @@ -563,6 +558,29 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable( + cx: I, + bound_sig: ty::Binder>, +) -> Result<(ty::Binder>, Vec), NoSolution> { + let sig = bound_sig.skip_binder(); + let future_trait_def_id = cx.require_lang_item(TraitSolverLangItem::Future); + // `FnDef` and `FnPtr` only implement `AsyncFn*` when their + // return type implements `Future`. + let nested = vec![ + bound_sig.rebind(ty::TraitRef::new(cx, future_trait_def_id, [sig.output()])).upcast(cx), + ]; + let future_output_def_id = cx.require_lang_item(TraitSolverLangItem::FutureOutput); + let future_output_ty = Ty::new_projection(cx, future_output_def_id, [sig.output()]); + Ok(( + bound_sig.rebind(AsyncCallableRelevantTypes { + tupled_inputs_ty: Ty::new_tup(cx, sig.inputs().as_slice()), + output_coroutine_ty: sig.output(), + coroutine_return_ty: future_output_ty, + }), + nested, + )) +} + /// Given a coroutine-closure, project to its returned coroutine when we are *certain* /// that the closure's kind is compatible with the goal. fn coroutine_closure_to_certain_coroutine( 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 2085d3da44341..9de62031311b7 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -467,8 +467,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } candidates.vec.push(AsyncClosureCandidate); } - ty::FnDef(..) | ty::FnPtr(..) => { - candidates.vec.push(AsyncClosureCandidate); + // Provide an impl, but only for suitable `fn` pointers. + ty::FnPtr(sig) => { + if sig.is_fn_trait_compatible() { + candidates.vec.push(AsyncClosureCandidate); + } + } + // Provide an impl for suitable functions, rejecting `#[target_feature]` functions (RFC 2396). + ty::FnDef(def_id, _) => { + let tcx = self.tcx(); + if tcx.fn_sig(def_id).skip_binder().is_fn_trait_compatible() + && tcx.codegen_fn_attrs(def_id).target_features.is_empty() + { + candidates.vec.push(AsyncClosureCandidate); + } } _ => {} } diff --git a/tests/ui/async-await/async-closures/fn-exception-target-features.rs b/tests/ui/async-await/async-closures/fn-exception-target-features.rs new file mode 100644 index 0000000000000..de62fc8bf7e3c --- /dev/null +++ b/tests/ui/async-await/async-closures/fn-exception-target-features.rs @@ -0,0 +1,17 @@ +//@ edition: 2021 +//@ only-x86_64 + +#![feature(async_closure, target_feature_11)] +// `target_feature_11` just to test safe functions w/ target features. + +use std::pin::Pin; +use std::future::Future; + +#[target_feature(enable = "sse2")] +fn target_feature() -> Pin + 'static>> { todo!() } + +fn test(f: impl async Fn()) {} + +fn main() { + test(target_feature); //~ ERROR the trait bound +} diff --git a/tests/ui/async-await/async-closures/fn-exception-target-features.stderr b/tests/ui/async-await/async-closures/fn-exception-target-features.stderr new file mode 100644 index 0000000000000..396167f407055 --- /dev/null +++ b/tests/ui/async-await/async-closures/fn-exception-target-features.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `fn() -> Pin + 'static)>> {target_feature}: AsyncFn<()>` is not satisfied + --> $DIR/fn-exception-target-features.rs:16:10 + | +LL | test(target_feature); + | ---- ^^^^^^^^^^^^^^ the trait `AsyncFn<()>` is not implemented for fn item `fn() -> Pin + 'static)>> {target_feature}` + | | + | required by a bound introduced by this call + | +note: required by a bound in `test` + --> $DIR/fn-exception-target-features.rs:13:17 + | +LL | fn test(f: impl async Fn()) {} + | ^^^^^^^^^^ required by this bound in `test` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/async-closures/fn-exception.rs b/tests/ui/async-await/async-closures/fn-exception.rs new file mode 100644 index 0000000000000..0e06ebf48a4be --- /dev/null +++ b/tests/ui/async-await/async-closures/fn-exception.rs @@ -0,0 +1,21 @@ +//@ edition: 2021 + +#![feature(async_closure)] + +use std::pin::Pin; +use std::future::Future; + +unsafe extern "Rust" { + pub unsafe fn unsafety() -> Pin + 'static>>; +} + +unsafe extern "C" { + pub safe fn abi() -> Pin + 'static>>; +} + +fn test(f: impl async Fn()) {} + +fn main() { + test(unsafety); //~ ERROR the trait bound + test(abi); //~ ERROR the trait bound +} diff --git a/tests/ui/async-await/async-closures/fn-exception.stderr b/tests/ui/async-await/async-closures/fn-exception.stderr new file mode 100644 index 0000000000000..bacd079af0f2d --- /dev/null +++ b/tests/ui/async-await/async-closures/fn-exception.stderr @@ -0,0 +1,31 @@ +error[E0277]: the trait bound `unsafe fn() -> Pin + 'static)>> {unsafety}: AsyncFn<()>` is not satisfied + --> $DIR/fn-exception.rs:19:10 + | +LL | test(unsafety); + | ---- ^^^^^^^^ the trait `AsyncFn<()>` is not implemented for fn item `unsafe fn() -> Pin + 'static)>> {unsafety}` + | | + | required by a bound introduced by this call + | +note: required by a bound in `test` + --> $DIR/fn-exception.rs:16:17 + | +LL | fn test(f: impl async Fn()) {} + | ^^^^^^^^^^ required by this bound in `test` + +error[E0277]: the trait bound `extern "C" fn() -> Pin + 'static)>> {abi}: AsyncFn<()>` is not satisfied + --> $DIR/fn-exception.rs:20:10 + | +LL | test(abi); + | ---- ^^^ the trait `AsyncFn<()>` is not implemented for fn item `extern "C" fn() -> Pin + 'static)>> {abi}` + | | + | required by a bound introduced by this call + | +note: required by a bound in `test` + --> $DIR/fn-exception.rs:16:17 + | +LL | fn test(f: impl async Fn()) {} + | ^^^^^^^^^^ required by this bound in `test` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. From 60ffec8b4a1bdeeef3cd3793b829659979b90bbf Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 8 Aug 2024 19:25:20 +0000 Subject: [PATCH 658/786] Rustup to rustc 1.82.0-nightly (8b3870784 2024-08-07) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index f5cf169c7f7c9..827956c98cf29 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2024-08-07" +channel = "nightly-2024-08-08" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From c966370b1959707be06dd2cbfb1436233fa595a3 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 8 Aug 2024 21:51:50 +0200 Subject: [PATCH 659/786] Tweak wording Co-authored-by: lcnr --- compiler/rustc_data_structures/src/steal.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_data_structures/src/steal.rs b/compiler/rustc_data_structures/src/steal.rs index f305a8ad12000..0f2c0eee27d2f 100644 --- a/compiler/rustc_data_structures/src/steal.rs +++ b/compiler/rustc_data_structures/src/steal.rs @@ -53,7 +53,10 @@ impl Steal { } /// Writers of rustc drivers often encounter stealing issues. This function makes it possible to - /// handle these errors gracefully. This is not used within rustc as the time of writing. + /// handle these errors gracefully. + /// + /// This should not be used within rustc as it leaks information not tracked + /// by the query system, breaking incremental compilation. pub fn is_stolen(&self) -> bool { self.value.borrow().is_none() } From fdc6a5562b07192992592577a49333766b104bf1 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 8 Aug 2024 21:54:20 +0200 Subject: [PATCH 660/786] Fix rustc test suite --- scripts/test_rustc_tests.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/test_rustc_tests.sh b/scripts/test_rustc_tests.sh index b85d474516807..bb5af9127b96e 100755 --- a/scripts/test_rustc_tests.sh +++ b/scripts/test_rustc_tests.sh @@ -39,6 +39,7 @@ rm tests/ui/simd/dont-invalid-bitcast-x86_64.rs # unimplemented llvm.x86.sse41.r # exotic linkages rm tests/incremental/hashes/function_interfaces.rs rm tests/incremental/hashes/statics.rs +rm -r tests/run-make/naked-symbol-visibility # variadic arguments rm tests/ui/abi/mir/mir_codegen_calls_variadic.rs # requires float varargs From 7c4150fce0510218304b726174029fbb2c33ee03 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Thu, 8 Aug 2024 11:36:48 -0700 Subject: [PATCH 661/786] rustdoc: do not run doctests with invalid langstrings --- src/librustdoc/html/markdown.rs | 20 +++++++++++++++---- src/librustdoc/html/markdown/tests.rs | 6 +++--- ...octest-no-run-invalid-langstring-124577.rs | 11 ++++++++++ 3 files changed, 30 insertions(+), 7 deletions(-) create mode 100644 tests/rustdoc/doctest/doctest-no-run-invalid-langstring-124577.rs diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 97d97808b9314..bb8d39aaf1dcc 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -924,6 +924,7 @@ pub(crate) struct TagIterator<'a, 'tcx> { data: &'a str, is_in_attribute_block: bool, extra: Option<&'a ExtraInfo<'tcx>>, + is_error: bool, } #[derive(Clone, Debug, Eq, PartialEq)] @@ -950,13 +951,20 @@ struct Indices { impl<'a, 'tcx> TagIterator<'a, 'tcx> { pub(crate) fn new(data: &'a str, extra: Option<&'a ExtraInfo<'tcx>>) -> Self { - Self { inner: data.char_indices().peekable(), data, is_in_attribute_block: false, extra } + Self { + inner: data.char_indices().peekable(), + data, + is_in_attribute_block: false, + extra, + is_error: false, + } } - fn emit_error(&self, err: impl Into) { + fn emit_error(&mut self, err: impl Into) { if let Some(extra) = self.extra { extra.error_invalid_codeblock_attr(err); } + self.is_error = true; } fn skip_separators(&mut self) -> Option { @@ -1154,6 +1162,9 @@ impl<'a, 'tcx> Iterator for TagIterator<'a, 'tcx> { type Item = LangStringToken<'a>; fn next(&mut self) -> Option { + if self.is_error { + return None; + } let Some(start) = self.skip_separators() else { if self.is_in_attribute_block { self.emit_error("unclosed attribute block (`{}`): missing `}` at the end"); @@ -1342,14 +1353,15 @@ impl LangString { } }; - call(&mut TagIterator::new(string, extra)); + let mut tag_iter = TagIterator::new(string, extra); + call(&mut tag_iter); // ignore-foo overrides ignore if !ignores.is_empty() { data.ignore = Ignore::Some(ignores); } - data.rust &= !seen_custom_tag && (!seen_other_tags || seen_rust_tags); + data.rust &= !seen_custom_tag && (!seen_other_tags || seen_rust_tags) && !tag_iter.is_error; data } diff --git a/src/librustdoc/html/markdown/tests.rs b/src/librustdoc/html/markdown/tests.rs index 971120d4991c1..e490099a92e14 100644 --- a/src/librustdoc/html/markdown/tests.rs +++ b/src/librustdoc/html/markdown/tests.rs @@ -61,7 +61,7 @@ fn test_lang_string_parse() { ..Default::default() }); // error - t(LangString { original: "{rust}".into(), rust: true, ..Default::default() }); + t(LangString { original: "{rust}".into(), rust: false, ..Default::default() }); t(LangString { original: "{.rust}".into(), rust: true, @@ -233,7 +233,7 @@ fn test_lang_string_parse() { ..Default::default() }); // error - t(LangString { original: "{class=first=second}".into(), rust: true, ..Default::default() }); + t(LangString { original: "{class=first=second}".into(), rust: false, ..Default::default() }); // error t(LangString { original: "{class=first.second}".into(), @@ -261,7 +261,7 @@ fn test_lang_string_parse() { ..Default::default() }); // error - t(LangString { original: r#"{class=f"irst"}"#.into(), rust: true, ..Default::default() }); + t(LangString { original: r#"{class=f"irst"}"#.into(), rust: false, ..Default::default() }); } #[test] diff --git a/tests/rustdoc/doctest/doctest-no-run-invalid-langstring-124577.rs b/tests/rustdoc/doctest/doctest-no-run-invalid-langstring-124577.rs new file mode 100644 index 0000000000000..b3e993e8ee939 --- /dev/null +++ b/tests/rustdoc/doctest/doctest-no-run-invalid-langstring-124577.rs @@ -0,0 +1,11 @@ +//@ compile-flags:--test +#![allow(rustdoc::invalid_codeblock_attributes)] + +// https://github.com/rust-lang/rust/pull/124577#issuecomment-2276034737 + +// Test that invalid langstrings don't get run. + +/// ```{rust,ignore} +/// panic!(); +/// ``` +pub struct Foo; From 2756bd6ff77232a198adeb6e4083866484a469f3 Mon Sep 17 00:00:00 2001 From: Daniel Paoliello Date: Fri, 2 Aug 2024 13:53:09 -0700 Subject: [PATCH 662/786] Add support for raw-dylib --- Cargo.lock | 14 +++- Cargo.toml | 1 + build_system/tests.rs | 1 + config.txt | 1 + example/raw-dylib.rs | 31 ++++++++ .../0029-stdlib-rawdylib-processprng.patch | 47 ----------- ...use-raw-dylib-for-Windows-futex-APIs.patch | 37 --------- src/archive.rs | 79 +++++++++++++++++-- 8 files changed, 120 insertions(+), 91 deletions(-) create mode 100644 example/raw-dylib.rs delete mode 100644 patches/0029-stdlib-rawdylib-processprng.patch delete mode 100644 patches/0030-stdlib-Revert-use-raw-dylib-for-Windows-futex-APIs.patch diff --git a/Cargo.lock b/Cargo.lock index b065720c9ce11..741a1748fec98 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,6 +20,15 @@ version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +[[package]] +name = "ar_archive_writer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f2bcb7cf51decfbbfc7ef476e28b0775b13e5eb1190f8b7df145cd53d4f4374" +dependencies = [ + "object", +] + [[package]] name = "arbitrary" version = "1.3.2" @@ -289,9 +298,9 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "object" -version = "0.36.1" +version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce" +checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e" dependencies = [ "crc32fast", "hashbrown 0.14.5", @@ -358,6 +367,7 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" name = "rustc_codegen_cranelift" version = "0.1.0" dependencies = [ + "ar_archive_writer", "cranelift-codegen", "cranelift-frontend", "cranelift-jit", diff --git a/Cargo.toml b/Cargo.toml index a0df502dadc47..c86919dcdfb7e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ cranelift-object = { version = "0.110.1" } target-lexicon = "0.12.0" gimli = { version = "0.28", default-features = false, features = ["write"]} object = { version = "0.36", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } +ar_archive_writer = "0.3" indexmap = "2.0.0" libloading = { version = "0.8.0", optional = true } diff --git a/build_system/tests.rs b/build_system/tests.rs index afc8a923863a2..3a88824bf3635 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -106,6 +106,7 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[ ]); runner.run_out_command("gen_block_iterate", &[]); }), + TestCase::build_bin_and_run("aot.raw-dylib", "example/raw-dylib.rs", &[]), ]; pub(crate) static RAND_REPO: GitRepo = GitRepo::github( diff --git a/config.txt b/config.txt index 0b7cac1883761..527ec5303b602 100644 --- a/config.txt +++ b/config.txt @@ -45,6 +45,7 @@ aot.issue-59326 aot.polymorphize_coroutine aot.neon aot.gen_block_iterate +aot.raw-dylib testsuite.extended_sysroot test.rust-random/rand diff --git a/example/raw-dylib.rs b/example/raw-dylib.rs new file mode 100644 index 0000000000000..4711884f76af6 --- /dev/null +++ b/example/raw-dylib.rs @@ -0,0 +1,31 @@ +// Tests the raw-dylib feature for Windows. +// https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute + +fn main() { + #[cfg(windows)] + { + #[link(name = "kernel32", kind = "raw-dylib")] + extern "C" { + fn GetModuleFileNameA( + module: *mut std::ffi::c_void, + filename: *mut u8, + size: u32, + ) -> u32; + } + + // Get the filename of the current executable.... + let mut buffer = [0u8; 1024]; + let size = unsafe { + GetModuleFileNameA(core::ptr::null_mut(), buffer.as_mut_ptr(), buffer.len() as u32) + }; + if size == 0 { + eprintln!("failed to get module file name: {}", std::io::Error::last_os_error()); + return; + } else { + // ...and make sure that it matches the test name. + let filename = + std::ffi::CStr::from_bytes_with_nul(&buffer[..size as usize + 1]).unwrap(); + assert!(filename.to_str().unwrap().ends_with("raw-dylib.exe")); + } + } +} diff --git a/patches/0029-stdlib-rawdylib-processprng.patch b/patches/0029-stdlib-rawdylib-processprng.patch deleted file mode 100644 index 584dbdb647f60..0000000000000 --- a/patches/0029-stdlib-rawdylib-processprng.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 9f65e742ba3e41474e6126c6c4469c48eaa6ca7e Mon Sep 17 00:00:00 2001 -From: Chris Denton -Date: Tue, 20 Feb 2024 16:01:40 -0300 -Subject: [PATCH] Don't use raw-dylib in std - ---- - library/std/src/sys/pal/windows/c.rs | 2 +- - library/std/src/sys/pal/windows/rand.rs | 3 +-- - 2 files changed, 2 insertions(+), 3 deletions(-) - -diff --git a/library/std/src/sys/pal/windows/c.rs b/library/std/src/sys/pal/windows/c.rs -index ad8e01bfa9b..9ca8e4c16ce 100644 ---- a/library/std/src/sys/pal/windows/c.rs -+++ b/library/std/src/sys/pal/windows/c.rs -@@ -312,7 +312,7 @@ pub unsafe fn NtWriteFile( - - // Use raw-dylib to import ProcessPrng as we can't rely on there being an import library. - cfg_if::cfg_if! { --if #[cfg(not(target_vendor = "win7"))] { -+if #[cfg(any())] { - #[cfg(target_arch = "x86")] - #[link(name = "bcryptprimitives", kind = "raw-dylib", import_name_type = "undecorated")] - extern "system" { -diff --git a/library/std/src/sys/pal/windows/rand.rs b/library/std/src/sys/pal/windows/rand.rs -index e427546222a..f2fe42a4d51 100644 ---- a/library/std/src/sys/pal/windows/rand.rs -+++ b/library/std/src/sys/pal/windows/rand.rs -@@ -2,7 +2,7 @@ - - use crate::sys::c; - --#[cfg(not(target_vendor = "win7"))] -+#[cfg(any())] - #[inline] - pub fn hashmap_random_keys() -> (u64, u64) { - let mut v = (0, 0); -@@ -13,7 +13,6 @@ pub fn hashmap_random_keys() -> (u64, u64) { - v - } - --#[cfg(target_vendor = "win7")] - pub fn hashmap_random_keys() -> (u64, u64) { - use crate::ffi::c_void; - use crate::io; --- -2.42.0.windows.2 - diff --git a/patches/0030-stdlib-Revert-use-raw-dylib-for-Windows-futex-APIs.patch b/patches/0030-stdlib-Revert-use-raw-dylib-for-Windows-futex-APIs.patch deleted file mode 100644 index 21f5ee9cc6ea0..0000000000000 --- a/patches/0030-stdlib-Revert-use-raw-dylib-for-Windows-futex-APIs.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0d741cf82c3c908616abd39dc84ebf7d8702e0c3 Mon Sep 17 00:00:00 2001 -From: Chris Denton -Date: Tue, 16 Apr 2024 15:51:34 +0000 -Subject: [PATCH] Revert use raw-dylib for Windows futex APIs - ---- - library/std/src/sys/pal/windows/c.rs | 14 +------------- - 1 file changed, 1 insertion(+), 13 deletions(-) - -diff --git a/library/std/src/sys/pal/windows/c.rs b/library/std/src/sys/pal/windows/c.rs -index 9d58ce05f01..1c828bac4b6 100644 ---- a/library/std/src/sys/pal/windows/c.rs -+++ b/library/std/src/sys/pal/windows/c.rs -@@ -357,19 +357,7 @@ pub fn GetTempPath2W(bufferlength: u32, buffer: PWSTR) -> u32 { - } - - #[cfg(not(target_vendor = "win7"))] --// Use raw-dylib to import synchronization functions to workaround issues with the older mingw import library. --#[cfg_attr( -- target_arch = "x86", -- link( -- name = "api-ms-win-core-synch-l1-2-0", -- kind = "raw-dylib", -- import_name_type = "undecorated" -- ) --)] --#[cfg_attr( -- not(target_arch = "x86"), -- link(name = "api-ms-win-core-synch-l1-2-0", kind = "raw-dylib") --)] -+#[link(name = "synchronization")] - extern "system" { - pub fn WaitOnAddress( - address: *const c_void, --- -2.42.0.windows.2 - diff --git a/src/archive.rs b/src/archive.rs index 084654af09dd7..5eedab4f2cbaa 100644 --- a/src/archive.rs +++ b/src/archive.rs @@ -1,8 +1,13 @@ +use std::borrow::Borrow; +use std::fs; use std::path::Path; +use ar_archive_writer::{COFFShortExport, MachineTypes}; use rustc_codegen_ssa::back::archive::{ - ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, DEFAULT_OBJECT_READER, + create_mingw_dll_import_lib, ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, + DEFAULT_OBJECT_READER, }; +use rustc_codegen_ssa::common::is_mingw_gnu_toolchain; use rustc_session::Session; pub(crate) struct ArArchiveBuilderBuilder; @@ -15,10 +20,74 @@ impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder { fn create_dll_import_lib( &self, sess: &Session, - _lib_name: &str, - _import_name_and_ordinal_vector: Vec<(String, Option)>, - _output_path: &Path, + lib_name: &str, + import_name_and_ordinal_vector: Vec<(String, Option)>, + output_path: &Path, ) { - sess.dcx().fatal("raw-dylib is not yet supported by rustc_codegen_cranelift"); + if is_mingw_gnu_toolchain(&sess.target) { + // The binutils linker used on -windows-gnu targets cannot read the import + // libraries generated by LLVM: in our attempts, the linker produced an .EXE + // that loaded but crashed with an AV upon calling one of the imported + // functions. Therefore, use binutils to create the import library instead, + // by writing a .DEF file to the temp dir and calling binutils's dlltool. + create_mingw_dll_import_lib( + sess, + lib_name, + import_name_and_ordinal_vector, + output_path, + ); + } else { + let mut file = + match fs::OpenOptions::new().write(true).create_new(true).open(&output_path) { + Ok(file) => file, + Err(error) => { + sess.dcx().fatal(format!( + "failed to create import library file `{path}`: {error}", + path = output_path.display(), + )); + } + }; + + let machine = match sess.target.arch.borrow() { + "x86" => MachineTypes::I386, + "x86_64" => MachineTypes::AMD64, + "arm" => MachineTypes::ARMNT, + "aarch64" => MachineTypes::ARM64, + _ => { + sess.dcx().fatal(format!( + "unsupported target architecture `{arch}`", + arch = sess.target.arch, + )); + } + }; + + let exports = import_name_and_ordinal_vector + .iter() + .map(|(name, ordinal)| COFFShortExport { + name: name.to_string(), + ext_name: None, + symbol_name: None, + alias_target: None, + ordinal: ordinal.unwrap_or(0), + noname: ordinal.is_some(), + data: false, + private: false, + constant: false, + }) + .collect::>(); + + if let Err(error) = ar_archive_writer::write_import_library( + &mut file, + lib_name, + &exports, + machine, + !sess.target.is_like_msvc, + ) { + sess.dcx().fatal(format!( + "failed to create import library `{path}`: `{error}`", + path = output_path.display(), + )); + } + } } } From 524e7689a9a98e0d3769fac4b3567dbbbf4b5d78 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 3 Aug 2024 14:11:31 -0400 Subject: [PATCH 663/786] Add comment that bors did not see pushed before it merged --- compiler/rustc_interface/src/passes.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 023352156eb45..96a6f52d60b6c 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -818,8 +818,14 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { }); sess.time("layout_testing", || layout_test::test_layout(tcx)); sess.time("abi_testing", || abi_test::test_abi(tcx)); + + // If `-Zvalidate-mir` is set, we also want to compute the final MIR for each item + // (either its `mir_for_ctfe` or `optimized_mir`) since that helps uncover any bugs + // in MIR optimizations that may only be reachable through codegen, or other codepaths + // that requires the optimized/ctfe MIR, such as polymorphization, coroutine bodies, + // or evaluating consts. if tcx.sess.opts.unstable_opts.validate_mir { - sess.time("ensuring_optimized_MIR_is_computable", || { + sess.time("ensuring_final_MIR_is_computable", || { tcx.hir().par_body_owners(|def_id| { tcx.instance_mir(ty::InstanceKind::Item(def_id.into())); }); From 65b029b4680313aee06362552e31187b00b6929b Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 3 Aug 2024 15:33:02 -0400 Subject: [PATCH 664/786] Don't inline tainted MIR bodies --- compiler/rustc_mir_transform/src/inline.rs | 4 +++ .../polymorphization/inline-tainted-body.rs} | 10 +++++-- .../inline-tainted-body.stderr | 30 +++++++++++++++++++ 3 files changed, 42 insertions(+), 2 deletions(-) rename tests/{crashes/122909.rs => ui/polymorphization/inline-tainted-body.rs} (58%) create mode 100644 tests/ui/polymorphization/inline-tainted-body.stderr diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 0f012242c3738..324ddc5e799d5 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -505,6 +505,10 @@ impl<'tcx> Inliner<'tcx> { ) -> Result<(), &'static str> { let tcx = self.tcx; + if let Some(_) = callee_body.tainted_by_errors { + return Err("Body is tainted"); + } + let mut threshold = if self.caller_is_inline_forwarder { self.tcx.sess.opts.unstable_opts.inline_mir_forwarder_threshold.unwrap_or(30) } else if cross_crate_inlinable { diff --git a/tests/crashes/122909.rs b/tests/ui/polymorphization/inline-tainted-body.rs similarity index 58% rename from tests/crashes/122909.rs rename to tests/ui/polymorphization/inline-tainted-body.rs index 9d17ed83ea99b..13aec97e22bdd 100644 --- a/tests/crashes/122909.rs +++ b/tests/ui/polymorphization/inline-tainted-body.rs @@ -1,15 +1,21 @@ //@ compile-flags: -Zvalidate-mir -Zinline-mir=yes -//@ known-bug: #122909 +#![feature(unboxed_closures)] -use std::sync::{Arc, Context, Weak}; +use std::sync::Arc; pub struct WeakOnce(); +//~^ ERROR type parameter `T` is never used + impl WeakOnce { extern "rust-call" fn try_get(&self) -> Option> {} + //~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument + //~| ERROR mismatched types pub fn get(&self) -> Arc { self.try_get() .unwrap_or_else(|| panic!("Singleton {} not available", std::any::type_name::())) } } + +fn main() {} diff --git a/tests/ui/polymorphization/inline-tainted-body.stderr b/tests/ui/polymorphization/inline-tainted-body.stderr new file mode 100644 index 0000000000000..5c3bd70adae00 --- /dev/null +++ b/tests/ui/polymorphization/inline-tainted-body.stderr @@ -0,0 +1,30 @@ +error[E0392]: type parameter `T` is never used + --> $DIR/inline-tainted-body.rs:7:21 + | +LL | pub struct WeakOnce(); + | ^ unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + +error: functions with the "rust-call" ABI must take a single non-self tuple argument + --> $DIR/inline-tainted-body.rs:11:35 + | +LL | extern "rust-call" fn try_get(&self) -> Option> {} + | ^^^^^ + +error[E0308]: mismatched types + --> $DIR/inline-tainted-body.rs:11:45 + | +LL | extern "rust-call" fn try_get(&self) -> Option> {} + | ------- ^^^^^^^^^^^^^^ expected `Option>`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + | + = note: expected enum `Option>` + found unit type `()` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0308, E0392. +For more information about an error, try `rustc --explain E0308`. From 11b801bc4e410e77e6935a0c4544d4a90b868214 Mon Sep 17 00:00:00 2001 From: Min <45393763+MinxuanZ@users.noreply.github.com> Date: Thu, 8 Aug 2024 15:36:58 +0800 Subject: [PATCH 665/786] [MIPS] fix the name of signal 19 in mips --- library/std/src/sys/pal/unix/process/process_unix/tests.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/std/src/sys/pal/unix/process/process_unix/tests.rs b/library/std/src/sys/pal/unix/process/process_unix/tests.rs index e5e1f956bc351..1ca1ae7f3f45e 100644 --- a/library/std/src/sys/pal/unix/process/process_unix/tests.rs +++ b/library/std/src/sys/pal/unix/process/process_unix/tests.rs @@ -24,6 +24,9 @@ fn exitstatus_display_tests() { // The purpose of this test is to test our string formatting, not our understanding of the wait // status magic numbers. So restrict these to Linux. if cfg!(target_os = "linux") { + #[cfg(any(target_arch = "mips", target_arch = "mips64"))] + t(0x0137f, "stopped (not terminated) by signal: 19 (SIGPWR)"); + #[cfg(not(any(target_arch = "mips", target_arch = "mips64")))] t(0x0137f, "stopped (not terminated) by signal: 19 (SIGSTOP)"); t(0x0ffff, "continued (WIFCONTINUED)"); } From a3f8edff20a7d8aadd98d2553bd9ad12508a9980 Mon Sep 17 00:00:00 2001 From: Min <45393763+MinxuanZ@users.noreply.github.com> Date: Thu, 8 Aug 2024 15:53:53 +0800 Subject: [PATCH 666/786] [SPARC] fix the name of signal 19 in sparc arch --- .../std/src/sys/pal/unix/process/process_unix/tests.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/library/std/src/sys/pal/unix/process/process_unix/tests.rs b/library/std/src/sys/pal/unix/process/process_unix/tests.rs index 1ca1ae7f3f45e..f6044c4455c27 100644 --- a/library/std/src/sys/pal/unix/process/process_unix/tests.rs +++ b/library/std/src/sys/pal/unix/process/process_unix/tests.rs @@ -26,8 +26,16 @@ fn exitstatus_display_tests() { if cfg!(target_os = "linux") { #[cfg(any(target_arch = "mips", target_arch = "mips64"))] t(0x0137f, "stopped (not terminated) by signal: 19 (SIGPWR)"); - #[cfg(not(any(target_arch = "mips", target_arch = "mips64")))] + + #[cfg(any(target_arch = "sparc", target_arch = "sparc64"))] + t(0x0137f, "stopped (not terminated) by signal: 19 (SIGCONT)"); + + #[cfg(not(any(target_arch = "mips", + target_arch = "sparc", + target_arch = "mips64", + target_arch = "sprac64")))] t(0x0137f, "stopped (not terminated) by signal: 19 (SIGSTOP)"); + t(0x0ffff, "continued (WIFCONTINUED)"); } From 625432c837875e40b4167c0a5c7702b2f3c671a0 Mon Sep 17 00:00:00 2001 From: monstercatss Date: Fri, 9 Aug 2024 09:36:22 +0800 Subject: [PATCH 667/786] fix format --- .../std/src/sys/pal/unix/process/process_unix/tests.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/library/std/src/sys/pal/unix/process/process_unix/tests.rs b/library/std/src/sys/pal/unix/process/process_unix/tests.rs index f6044c4455c27..9410b1a87da0a 100644 --- a/library/std/src/sys/pal/unix/process/process_unix/tests.rs +++ b/library/std/src/sys/pal/unix/process/process_unix/tests.rs @@ -30,10 +30,12 @@ fn exitstatus_display_tests() { #[cfg(any(target_arch = "sparc", target_arch = "sparc64"))] t(0x0137f, "stopped (not terminated) by signal: 19 (SIGCONT)"); - #[cfg(not(any(target_arch = "mips", - target_arch = "sparc", - target_arch = "mips64", - target_arch = "sprac64")))] + #[cfg(not(any( + target_arch = "mips", + target_arch = "mips64", + target_arch = "sparc", + target_arch = "sparc64" + )))] t(0x0137f, "stopped (not terminated) by signal: 19 (SIGSTOP)"); t(0x0ffff, "continued (WIFCONTINUED)"); From 0106f5bcbab8ded01bc4b027d8381d2a3a7cc265 Mon Sep 17 00:00:00 2001 From: monstercatss Date: Fri, 9 Aug 2024 10:12:54 +0800 Subject: [PATCH 668/786] delete space --- library/std/src/sys/pal/unix/process/process_unix/tests.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/sys/pal/unix/process/process_unix/tests.rs b/library/std/src/sys/pal/unix/process/process_unix/tests.rs index 9410b1a87da0a..f4d6ac6b4e340 100644 --- a/library/std/src/sys/pal/unix/process/process_unix/tests.rs +++ b/library/std/src/sys/pal/unix/process/process_unix/tests.rs @@ -31,13 +31,13 @@ fn exitstatus_display_tests() { t(0x0137f, "stopped (not terminated) by signal: 19 (SIGCONT)"); #[cfg(not(any( - target_arch = "mips", + target_arch = "mips", target_arch = "mips64", target_arch = "sparc", target_arch = "sparc64" )))] t(0x0137f, "stopped (not terminated) by signal: 19 (SIGSTOP)"); - + t(0x0ffff, "continued (WIFCONTINUED)"); } From bca0c5f2a939999dcb8d83d06a793f39f4815736 Mon Sep 17 00:00:00 2001 From: burlinchen Date: Fri, 9 Aug 2024 11:10:30 +0800 Subject: [PATCH 669/786] fix: Ensure `Guard`'s `drop` method is removed at `opt-level=s` for `Copy` types Added `#[inline]` to the `drop` method in the `Guard` implementation to ensure that the method is removed by the compiler at optimization level `opt-level=s` for `Copy` types. This change aims to align the method's behavior with optimization expectations and ensure it does not affect performance. --- library/core/src/array/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 5c826b9993f86..61c713c9e81cf 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -889,6 +889,7 @@ impl Guard<'_, T> { } impl Drop for Guard<'_, T> { + #[inline] fn drop(&mut self) { debug_assert!(self.initialized <= self.array_mut.len()); From b20d9f0403f0cb97148a8ae24cda4e27523114df Mon Sep 17 00:00:00 2001 From: B I Mohammed Abbas Date: Fri, 9 Aug 2024 09:05:09 +0530 Subject: [PATCH 670/786] VxWorks: Add safety comment for vxCpuEnabledGet Co-authored-by: Trevor Gross --- library/std/src/sys/pal/unix/thread.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs index 6f17c73908dad..0fa610eebb4ef 100644 --- a/library/std/src/sys/pal/unix/thread.rs +++ b/library/std/src/sys/pal/unix/thread.rs @@ -477,8 +477,8 @@ pub fn available_parallelism() -> io::Result> { fn vxCpuEnabledGet() -> libc::cpuset_t; } + // SAFETY: `vxCpuEnabledGet` always fetches a mask with at least one bit set unsafe{ - // always fetches a valid bitmask let set = vxCpuEnabledGet(); Ok(NonZero::new_unchecked(set.count_ones() as usize)) } From b589f86a09c823208cbe95755f0cb0883e28d0de 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, 9 Aug 2024 05:03:36 +0000 Subject: [PATCH 671/786] tests: add regression test for incorrect `BytePos` manipulation triggering assertion Issue: --- .../ui/typeck/suggest-arg-comma-delete-ice.rs | 19 ++++++++++ .../suggest-arg-comma-delete-ice.stderr | 38 +++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 tests/ui/typeck/suggest-arg-comma-delete-ice.rs create mode 100644 tests/ui/typeck/suggest-arg-comma-delete-ice.stderr diff --git a/tests/ui/typeck/suggest-arg-comma-delete-ice.rs b/tests/ui/typeck/suggest-arg-comma-delete-ice.rs new file mode 100644 index 0000000000000..48d02e13eca09 --- /dev/null +++ b/tests/ui/typeck/suggest-arg-comma-delete-ice.rs @@ -0,0 +1,19 @@ +//! Previously, we tried to remove extra arg commas when providing extra arg removal suggestions. +//! One of the edge cases is having to account for an arg that has a closing delimiter `)` +//! following it. However, the previous suggestion code assumed that the delimiter is in fact +//! exactly the 1-byte `)` character. This assumption was proven incorrect, because we recover +//! from Unicode-confusable delimiters in the parser, which means that the ending delimiter could be +//! a multi-byte codepoint that looks *like* a `)`. Subtracing 1 byte could land us in the middle of +//! a codepoint, triggering a codepoint boundary assertion. +//! +//! issue: rust-lang/rust#128717 + +fn main() { + // The following example has been modified from #128717 to remove irrelevant Unicode as they do + // not otherwise partake in the right delimiter calculation causing the codepoint boundary + // assertion. + main(rahh); + //~^ ERROR unknown start of token + //~| ERROR this function takes 0 arguments but 1 argument was supplied + //~| ERROR cannot find value `rahh` in this scope +} diff --git a/tests/ui/typeck/suggest-arg-comma-delete-ice.stderr b/tests/ui/typeck/suggest-arg-comma-delete-ice.stderr new file mode 100644 index 0000000000000..53608391f3c89 --- /dev/null +++ b/tests/ui/typeck/suggest-arg-comma-delete-ice.stderr @@ -0,0 +1,38 @@ +error: unknown start of token: \u{ff09} + --> $DIR/suggest-arg-comma-delete-ice.rs:15:14 + | +LL | main(rahh); + | ^^ + | +help: Unicode character ')' (Fullwidth Right Parenthesis) looks like ')' (Right Parenthesis), but it is not + | +LL | main(rahh); + | ~ + +error[E0425]: cannot find value `rahh` in this scope + --> $DIR/suggest-arg-comma-delete-ice.rs:15:10 + | +LL | main(rahh); + | ^^^^ not found in this scope + +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/suggest-arg-comma-delete-ice.rs:15:5 + | +LL | main(rahh); + | ^^^^ ---- unexpected argument + | +note: function defined here + --> $DIR/suggest-arg-comma-delete-ice.rs:11:4 + | +LL | fn main() { + | ^^^^ +help: remove the extra argument + | +LL - main(rahh); +LL + main(); + | + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0061, E0425. +For more information about an error, try `rustc --explain E0061`. From 879bfd7ad0f5f79e7bc90320dfb80dfabe91ac2b 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, 9 Aug 2024 05:01:27 +0000 Subject: [PATCH 672/786] hir_typeck: use `end_point` over `BytePos` manipulations Parser has error recovery for Unicode-confusables, which includes the right parentheses `)`. If a multi-byte right parentheses look-alike reaches the argument removal suggestion diagnostics, it would trigger an assertion because the diagnostics used `- BytePos(1)` which can land within a multi-byte codepoint. This is fixed by using `SourceMap::end_point` to find the final right delimiter codepoint, which correctly respects codepoint boundaries. --- compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index cef003e0a43de..89e7227eda2c7 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -22,7 +22,7 @@ use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_session::Session; use rustc_span::symbol::{kw, Ident}; -use rustc_span::{sym, BytePos, Span, DUMMY_SP}; +use rustc_span::{sym, Span, DUMMY_SP}; use rustc_trait_selection::error_reporting::infer::{FailureCode, ObligationCauseExt}; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext}; @@ -1140,8 +1140,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .get(arg_idx + 1) .map(|&(_, sp)| sp) .unwrap_or_else(|| { - // Subtract one to move before `)` - call_expr.span.with_lo(call_expr.span.hi() - BytePos(1)) + // Try to move before `)`. Note that `)` here is not necessarily + // the latin right paren, it could be a Unicode-confusable that + // looks like a `)`, so we must not use `- BytePos(1)` + // manipulations here. + self.tcx().sess.source_map().end_point(call_expr.span) }); // Include next comma From 92520a9d4d74d23b29bd65f3372f1d0e5a0ec9cb 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, 9 Aug 2024 05:48:58 +0000 Subject: [PATCH 673/786] tests: add regression test for #128845 For codepoint boundary assertion triggered by a let stmt compound assignment removal suggestion when encountering recovered multi-byte compound ops. Issue: --- .../suggest-remove-compount-assign-let-ice.rs | 16 ++++++++++++ ...gest-remove-compount-assign-let-ice.stderr | 26 +++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 tests/ui/parser/suggest-remove-compount-assign-let-ice.rs create mode 100644 tests/ui/parser/suggest-remove-compount-assign-let-ice.stderr diff --git a/tests/ui/parser/suggest-remove-compount-assign-let-ice.rs b/tests/ui/parser/suggest-remove-compount-assign-let-ice.rs new file mode 100644 index 0000000000000..1affee5678e44 --- /dev/null +++ b/tests/ui/parser/suggest-remove-compount-assign-let-ice.rs @@ -0,0 +1,16 @@ +//! Previously we would try to issue a suggestion for `let x = 1`, i.e. a compound assignment +//! within a `let` binding, to remove the ``. The suggestion code unfortunately incorrectly +//! assumed that the `` is an exactly-1-byte ASCII character, but this assumption is incorrect +//! because we also recover Unicode-confusables like `➖=` as `-=`. In this example, the suggestion +//! code used a `+ BytePos(1)` to calculate the span of the `` codepoint that looks like `-` but +//! the mult-byte Unicode look-alike would cause the suggested removal span to be inside a +//! multi-byte codepoint boundary, triggering a codepoint boundary assertion. +//! +//! issue: rust-lang/rust#128845 + +fn main() { + // Adapted from #128845 but with irrelevant components removed and simplified. + let x ➖= 1; + //~^ ERROR unknown start of token: \u{2796} + //~| ERROR: can't reassign to an uninitialized variable +} diff --git a/tests/ui/parser/suggest-remove-compount-assign-let-ice.stderr b/tests/ui/parser/suggest-remove-compount-assign-let-ice.stderr new file mode 100644 index 0000000000000..59716d69b50f9 --- /dev/null +++ b/tests/ui/parser/suggest-remove-compount-assign-let-ice.stderr @@ -0,0 +1,26 @@ +error: unknown start of token: \u{2796} + --> $DIR/suggest-remove-compount-assign-let-ice.rs:13:11 + | +LL | let x ➖= 1; + | ^^ + | +help: Unicode character '➖' (Heavy Minus Sign) looks like '-' (Minus/Hyphen), but it is not + | +LL | let x -= 1; + | ~ + +error: can't reassign to an uninitialized variable + --> $DIR/suggest-remove-compount-assign-let-ice.rs:13:11 + | +LL | let x ➖= 1; + | ^^^ + | + = help: if you meant to overwrite, remove the `let` binding +help: initialize the variable + | +LL - let x ➖= 1; +LL + let x = 1; + | + +error: aborting due to 2 previous errors + From d65f1316bba2b3cdccce3f0d7d3e2eb27b5fbe49 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, 9 Aug 2024 05:48:52 +0000 Subject: [PATCH 674/786] parser: ensure let stmt compound assignment removal suggestion respect codepoint boundaries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously we would try to issue a suggestion for `let x = 1`, i.e. a compound assignment within a `let` binding, to remove the ``. The suggestion code unfortunately incorrectly assumed that the `` is an exactly-1-byte ASCII character, but this assumption is incorrect because we also recover Unicode-confusables like `➖=` as `-=`. In this example, the suggestion code used a `+ BytePos(1)` to calculate the span of the `` codepoint that looks like `-` but the mult-byte Unicode look-alike would cause the suggested removal span to be inside a multi-byte codepoint boundary, triggering a codepoint boundary assertion. Issue: --- compiler/rustc_parse/src/parser/stmt.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index b3efb87a4a26a..a3b782d651d3f 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -408,10 +408,14 @@ impl<'a> Parser<'a> { fn parse_initializer(&mut self, eq_optional: bool) -> PResult<'a, Option>> { let eq_consumed = match self.token.kind { token::BinOpEq(..) => { - // Recover `let x = 1` as `let x = 1` + // Recover `let x = 1` as `let x = 1` We must not use `+ BytePos(1)` here + // because `` can be a multi-byte lookalike that was recovered, e.g. `➖=` (the + // `➖` is a U+2796 Heavy Minus Sign Unicode Character) that was recovered as a + // `-=`. + let extra_op_span = self.psess.source_map().start_point(self.token.span); self.dcx().emit_err(errors::CompoundAssignmentExpressionInLet { span: self.token.span, - suggestion: self.token.span.with_hi(self.token.span.lo() + BytePos(1)), + suggestion: extra_op_span, }); self.bump(); true From 38874a692738f23b17d20a81bb906701303c0474 Mon Sep 17 00:00:00 2001 From: Folkert Date: Thu, 8 Aug 2024 23:55:59 +0200 Subject: [PATCH 675/786] use stable sort to sort multipart diagnostics --- compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs | 2 +- compiler/rustc_errors/src/diagnostic.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 7a925705806fc..a58c7c43246b5 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1124,8 +1124,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { err.multipart_suggestion( "consider moving the expression out of the loop so it is only moved once", vec![ - (parent.span, "value".to_string()), (span.shrink_to_lo(), format!("let mut value = {value};{indent}")), + (parent.span, "value".to_string()), ], Applicability::MaybeIncorrect, ); diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 67ca6d50cca4b..fae8b5647fc9a 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -920,8 +920,8 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { applicability: Applicability, style: SuggestionStyle, ) -> &mut Self { - suggestion.sort_unstable(); - suggestion.dedup_by(|(s1, m1), (s2, m2)| s1.source_equal(*s2) && m1 == m2); + let mut seen = crate::FxHashSet::default(); + suggestion.retain(|(span, msg)| seen.insert((span.lo(), span.hi(), msg.clone()))); let parts = suggestion .into_iter() From a7c415c67fcb91d3101a793752e98c87642d6af6 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Thu, 8 Aug 2024 15:01:11 +0300 Subject: [PATCH 676/786] add `builder-config` into tarball sources This will be useful for certain scenarios where developers want to know how the tarball sources were generated. We also want this to check for CI rustc incompatible options on bootstrap. Signed-off-by: onur-ozkan --- src/bootstrap/src/utils/tarball.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/bootstrap/src/utils/tarball.rs b/src/bootstrap/src/utils/tarball.rs index bfe2f084552e6..3f7f6214cf682 100644 --- a/src/bootstrap/src/utils/tarball.rs +++ b/src/bootstrap/src/utils/tarball.rs @@ -317,6 +317,12 @@ impl<'a> Tarball<'a> { channel::write_commit_hash_file(&self.overlay_dir, &info.sha); channel::write_commit_info_file(&self.overlay_dir, info); } + + // Add config file if present. + if let Some(config) = &self.builder.config.config { + self.add_renamed_file(config, &self.overlay_dir, "builder-config"); + } + for file in self.overlay.legal_and_readme() { self.builder.install(&self.builder.src.join(file), &self.overlay_dir, 0o644); } From ff0d37cb01636da96956553ea823e4c486923d70 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Thu, 8 Aug 2024 15:06:43 +0300 Subject: [PATCH 677/786] use absolute path for `config.toml` Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/config.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 14beef20bad6e..f0a5583016719 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1325,7 +1325,11 @@ impl Config { // Give a hard error if `--config` or `RUST_BOOTSTRAP_CONFIG` are set to a missing path, // but not if `config.toml` hasn't been created. let mut toml = if !using_default_path || toml_path.exists() { - config.config = Some(toml_path.clone()); + config.config = Some(if cfg!(not(feature = "bootstrap-self-test")) { + toml_path.canonicalize().unwrap() + } else { + toml_path.clone() + }); get_toml(&toml_path) } else { config.config = None; From dec5b463fbe506302d7a63fa8c52dfc22b4b110f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 6 Aug 2024 22:45:42 +0200 Subject: [PATCH 678/786] do not make function addresses unique with cross_crate_inline_threshold=always (even if that breaks backtraces) --- src/tools/miri/src/machine.rs | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index df4154bcb5892..411619ed6b914 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -24,6 +24,7 @@ use rustc_middle::{ Instance, Ty, TyCtxt, }, }; +use rustc_session::config::InliningThreshold; use rustc_span::def_id::{CrateNum, DefId}; use rustc_span::{Span, SpanData, Symbol}; use rustc_target::abi::{Align, Size}; @@ -1525,24 +1526,29 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { instance: Option>, ) -> usize { let unique = if let Some(instance) = instance { - // Functions cannot be identified by pointers, as asm-equal functions can get deduplicated - // by the linker (we set the "unnamed_addr" attribute for LLVM) and functions can be - // duplicated across crates. We thus generate a new `AllocId` for every mention of a - // function. This means that `main as fn() == main as fn()` is false, while `let x = main as - // fn(); x == x` is true. However, as a quality-of-life feature it can be useful to identify - // certain functions uniquely, e.g. for backtraces. So we identify whether codegen will - // actually emit duplicate functions. It does that when they have non-lifetime generics, or - // when they can be inlined. All other functions are given a unique address. - // This is not a stable guarantee! The `inline` attribute is a hint and cannot be relied - // upon for anything. But if we don't do this, backtraces look terrible. + // Functions cannot be identified by pointers, as asm-equal functions can get + // deduplicated by the linker (we set the "unnamed_addr" attribute for LLVM) and + // functions can be duplicated across crates. We thus generate a new `AllocId` for every + // mention of a function. This means that `main as fn() == main as fn()` is false, while + // `let x = main as fn(); x == x` is true. However, as a quality-of-life feature it can + // be useful to identify certain functions uniquely, e.g. for backtraces. So we identify + // whether codegen will actually emit duplicate functions. It does that when they have + // non-lifetime generics, or when they can be inlined. All other functions are given a + // unique address. This is not a stable guarantee! The `inline` attribute is a hint and + // cannot be relied upon for anything. But if we don't do this, the + // `__rust_begin_short_backtrace`/`__rust_end_short_backtrace` logic breaks and panic + // backtraces look terrible. let is_generic = instance .args .into_iter() .any(|kind| !matches!(kind.unpack(), ty::GenericArgKind::Lifetime(_))); - let can_be_inlined = match ecx.tcx.codegen_fn_attrs(instance.def_id()).inline { - InlineAttr::Never => false, - _ => true, - }; + let can_be_inlined = matches!( + ecx.tcx.sess.opts.unstable_opts.cross_crate_inline_threshold, + InliningThreshold::Always + ) || !matches!( + ecx.tcx.codegen_fn_attrs(instance.def_id()).inline, + InlineAttr::Never + ); !is_generic && !can_be_inlined } else { // Non-functions are never unique. From f72cb0415bdb6fe3699fb44f9b41da1d34c74189 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 9 Aug 2024 12:17:01 +0200 Subject: [PATCH 679/786] Make `Build::run` comment more accurate --- 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 453fb39327d63..d3aff8f89a0ca 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -986,7 +986,8 @@ impl Build { } /// Execute a command and return its output. - /// This method should be used for all command executions in bootstrap. + /// Note: Ideally, you should use one of the BootstrapCommand::run* functions to + /// execute commands. They internally call this method. #[track_caller] fn run( &self, From ce1d7d1bf2ff9820a9ff959cdf13f463ee2bf3f5 Mon Sep 17 00:00:00 2001 From: shina <53410646+s7tya@users.noreply.github.com> Date: Fri, 9 Aug 2024 20:03:14 +0900 Subject: [PATCH 680/786] impl compare command and benchmark command to rustc-perf-wrapper --- src/tools/rustc-perf-wrapper/src/main.rs | 116 ++++++++++++++++------- 1 file changed, 81 insertions(+), 35 deletions(-) diff --git a/src/tools/rustc-perf-wrapper/src/main.rs b/src/tools/rustc-perf-wrapper/src/main.rs index 991f4ea15ed63..951d36b788b53 100644 --- a/src/tools/rustc-perf-wrapper/src/main.rs +++ b/src/tools/rustc-perf-wrapper/src/main.rs @@ -1,3 +1,4 @@ +use std::fs::create_dir_all; use std::path::PathBuf; use std::process::Command; @@ -17,9 +18,6 @@ pub struct Args { #[clap(subcommand)] cmd: PerfCommand, - #[clap(flatten)] - opts: SharedOpts, - #[clap(flatten)] ctx: BuildContext, } @@ -28,22 +26,37 @@ pub struct Args { enum PerfCommand { /// Run `profile_local eprintln`. /// This executes the compiler on the given benchmarks and stores its stderr output. - Eprintln, + Eprintln { + #[clap(flatten)] + opts: SharedOpts, + }, /// Run `profile_local samply` /// This executes the compiler on the given benchmarks and profiles it with `samply`. /// You need to install `samply`, e.g. using `cargo install samply`. - Samply, + Samply { + #[clap(flatten)] + opts: SharedOpts, + }, /// Run `profile_local cachegrind`. /// This executes the compiler on the given benchmarks under `Cachegrind`. - Cachegrind, -} - -impl PerfCommand { - fn is_profiling(&self) -> bool { - match self { - PerfCommand::Eprintln | PerfCommand::Samply | PerfCommand::Cachegrind => true, - } - } + Cachegrind { + #[clap(flatten)] + opts: SharedOpts, + }, + Benchmark { + /// Identifier to associate benchmark results with + id: String, + + #[clap(flatten)] + opts: SharedOpts, + }, + Compare { + /// The name of the base artifact to be compared. + base: String, + + /// The name of the modified artifact to be compared. + modified: String, + }, } #[derive(Debug, clap::Parser)] @@ -52,6 +65,11 @@ struct SharedOpts { /// If unspecified, all benchmarks will be executed. #[clap(long, global = true, value_delimiter = ',')] include: Vec, + + /// Select the benchmarks matching a prefix in this comma-separated list that you don't want to run. + #[clap(long, global = true, value_delimiter = ',')] + exclude: Vec, + /// Select the scenarios that should be benchmarked. #[clap( long, @@ -87,35 +105,67 @@ fn main() { fn run(args: Args) { let mut cmd = Command::new(args.ctx.collector); + let db_path = args.ctx.results_dir.join("results.db"); + match &args.cmd { - PerfCommand::Eprintln => { - cmd.arg("profile_local").arg("eprintln"); + PerfCommand::Eprintln { opts } + | PerfCommand::Samply { opts } + | PerfCommand::Cachegrind { opts } => { + cmd.arg("profile_local"); + cmd.arg(match &args.cmd { + PerfCommand::Eprintln { .. } => "eprintln", + PerfCommand::Samply { .. } => "samply", + PerfCommand::Cachegrind { .. } => "cachegrind", + _ => unreachable!(), + }); + + cmd.arg("--out-dir").arg(&args.ctx.results_dir); + + apply_shared_opts(&mut cmd, opts); + execute_benchmark(&mut cmd, &args.ctx.compiler); + + println!("You can find the results at `{}`", args.ctx.results_dir.display()); } - PerfCommand::Samply => { - cmd.arg("profile_local").arg("samply"); + PerfCommand::Benchmark { id, opts } => { + cmd.arg("bench_local"); + cmd.arg("--db").arg(&db_path); + cmd.arg("--id").arg(id); + + apply_shared_opts(&mut cmd, opts); + create_dir_all(&args.ctx.results_dir).unwrap(); + execute_benchmark(&mut cmd, &args.ctx.compiler); } - PerfCommand::Cachegrind => { - cmd.arg("profile_local").arg("cachegrind"); + PerfCommand::Compare { base, modified } => { + cmd.arg("bench_cmp"); + cmd.arg("--db").arg(&db_path); + cmd.arg(base).arg(modified); + + create_dir_all(&args.ctx.results_dir).unwrap(); + cmd.status().expect("error while running rustc-perf bench_cmp"); } } - if args.cmd.is_profiling() { - cmd.arg("--out-dir").arg(&args.ctx.results_dir); - } +} - if !args.opts.include.is_empty() { - cmd.arg("--include").arg(args.opts.include.join(",")); +fn apply_shared_opts(cmd: &mut Command, opts: &SharedOpts) { + if !opts.include.is_empty() { + cmd.arg("--include").arg(opts.include.join(",")); } - if !args.opts.profiles.is_empty() { + if !opts.exclude.is_empty() { + cmd.arg("--exclude").arg(opts.exclude.join(",")); + } + if !opts.profiles.is_empty() { cmd.arg("--profiles") - .arg(args.opts.profiles.iter().map(|p| p.to_string()).collect::>().join(",")); + .arg(opts.profiles.iter().map(|p| p.to_string()).collect::>().join(",")); } - if !args.opts.scenarios.is_empty() { + if !opts.scenarios.is_empty() { cmd.arg("--scenarios") - .arg(args.opts.scenarios.iter().map(|p| p.to_string()).collect::>().join(",")); + .arg(opts.scenarios.iter().map(|p| p.to_string()).collect::>().join(",")); } - cmd.arg(&args.ctx.compiler); +} - println!("Running `rustc-perf` using `{}`", args.ctx.compiler.display()); +fn execute_benchmark(cmd: &mut Command, compiler: &PathBuf) { + cmd.arg(compiler); + println!("Running `rustc-perf` using `{}`", compiler.display()); const MANIFEST_DIR: &str = env!("CARGO_MANIFEST_DIR"); @@ -125,8 +175,4 @@ fn run(args: Args) { // with compile-time benchmarks. let cmd = cmd.current_dir(rustc_perf_dir); cmd.status().expect("error while running rustc-perf collector"); - - if args.cmd.is_profiling() { - println!("You can find the results at `{}`", args.ctx.results_dir.display()); - } } From 6e9afb8dde7a9810fe444efc6e0e282c23be0a24 Mon Sep 17 00:00:00 2001 From: Kyle Huey Date: Mon, 27 May 2024 20:10:46 -0700 Subject: [PATCH 681/786] Enable zstd for debug compression. Set LLVM_ENABLE_ZSTD alongside LLVM_ENABLE_ZLIB so that --compress-debug-sections=zstd is an option. Use static linking to avoid a new runtime dependency. Add an llvm.libzstd bootstrap option for LLVM with zstd. Set it off by default except for the dist builder. Handle llvm-config --system-libs output that contains static libraries. --- compiler/rustc_llvm/build.rs | 29 +++++++++++++++++-- config.example.toml | 3 ++ src/bootstrap/download-ci-llvm-stamp | 2 +- src/bootstrap/src/core/build_steps/llvm.rs | 12 ++++++-- src/bootstrap/src/core/config/config.rs | 6 ++++ src/bootstrap/src/utils/change_tracker.rs | 5 ++++ .../host-x86_64/dist-x86_64-linux/Dockerfile | 1 + 7 files changed, 51 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs index 4c1f78e6bee34..b2ff9efb41cba 100644 --- a/compiler/rustc_llvm/build.rs +++ b/compiler/rustc_llvm/build.rs @@ -259,6 +259,7 @@ fn main() { cmd.args(&components); for lib in output(&mut cmd).split_whitespace() { + let mut is_static = false; let name = if let Some(stripped) = lib.strip_prefix("-l") { stripped } else if let Some(stripped) = lib.strip_prefix('-') { @@ -266,8 +267,24 @@ fn main() { } else if Path::new(lib).exists() { // On MSVC llvm-config will print the full name to libraries, but // we're only interested in the name part - let name = Path::new(lib).file_name().unwrap().to_str().unwrap(); - name.trim_end_matches(".lib") + // On Unix when we get a static library llvm-config will print the + // full name and we *are* interested in the path, but we need to + // handle it separately. For example, when statically linking to + // libzstd llvm-config will output something like + // -lrt -ldl -lm -lz /usr/local/lib/libzstd.a -lxml2 + // and we transform the zstd part into + // cargo:rustc-link-search-native=/usr/local/lib + // cargo:rustc-link-lib=static=zstd + let path = Path::new(lib); + if lib.ends_with(".a") { + is_static = true; + println!("cargo:rustc-link-search=native={}", path.parent().unwrap().display()); + let name = path.file_stem().unwrap().to_str().unwrap(); + name.trim_start_matches("lib") + } else { + let name = path.file_name().unwrap().to_str().unwrap(); + name.trim_end_matches(".lib") + } } else if lib.ends_with(".lib") { // Some MSVC libraries just come up with `.lib` tacked on, so chop // that off @@ -285,7 +302,13 @@ fn main() { continue; } - let kind = if name.starts_with("LLVM") { llvm_kind } else { "dylib" }; + let kind = if name.starts_with("LLVM") { + llvm_kind + } else if is_static { + "static" + } else { + "dylib" + }; println!("cargo:rustc-link-lib={kind}={name}"); } diff --git a/config.example.toml b/config.example.toml index 1a7bdc4737fbf..1b7de662e84ab 100644 --- a/config.example.toml +++ b/config.example.toml @@ -87,6 +87,9 @@ # library provided by LLVM. #static-libstdcpp = false +# Enable LLVM to use zstd for compression. +#libzstd = false + # Whether to use Ninja to build LLVM. This runs much faster than make. #ninja = true diff --git a/src/bootstrap/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp index 258a034745134..11316004412e6 100644 --- a/src/bootstrap/download-ci-llvm-stamp +++ b/src/bootstrap/download-ci-llvm-stamp @@ -1,4 +1,4 @@ Change this file to make users of the `download-ci-llvm` configuration download a new version of LLVM from CI, even if the LLVM submodule hasn’t changed. -Last change is for: https://github.com/rust-lang/rust/pull/126298 +Last change is for: https://github.com/rust-lang/rust/pull/125642 diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index 81e591be6997c..ffae245dfb578 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -368,9 +368,7 @@ impl Step for Llvm { cfg.define("LLVM_PROFDATA_FILE", path); } - // Disable zstd to avoid a dependency on libzstd.so. - cfg.define("LLVM_ENABLE_ZSTD", "OFF"); - + // Libraries for ELF section compression. if !target.is_windows() { cfg.define("LLVM_ENABLE_ZLIB", "ON"); } else { @@ -824,6 +822,14 @@ fn configure_llvm(builder: &Builder<'_>, target: TargetSelection, cfg: &mut cmak } } + // Libraries for ELF section compression. + if builder.config.llvm_libzstd { + cfg.define("LLVM_ENABLE_ZSTD", "FORCE_ON"); + cfg.define("LLVM_USE_STATIC_ZSTD", "TRUE"); + } else { + cfg.define("LLVM_ENABLE_ZSTD", "OFF"); + } + if let Some(ref linker) = builder.config.llvm_use_linker { cfg.define("LLVM_USE_LINKER", linker); } diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 14beef20bad6e..263d59518b1d3 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -218,6 +218,7 @@ pub struct Config { pub llvm_thin_lto: bool, pub llvm_release_debuginfo: bool, pub llvm_static_stdcpp: bool, + pub llvm_libzstd: bool, /// `None` if `llvm_from_ci` is true and we haven't yet downloaded llvm. #[cfg(not(test))] llvm_link_shared: Cell>, @@ -878,6 +879,7 @@ define_config! { plugins: Option = "plugins", ccache: Option = "ccache", static_libstdcpp: Option = "static-libstdcpp", + libzstd: Option = "libzstd", ninja: Option = "ninja", targets: Option = "targets", experimental_targets: Option = "experimental-targets", @@ -1153,6 +1155,7 @@ impl Config { llvm_optimize: true, ninja_in_file: true, llvm_static_stdcpp: false, + llvm_libzstd: false, backtrace: true, rust_optimize: RustOptimize::Bool(true), rust_optimize_tests: true, @@ -1787,6 +1790,7 @@ impl Config { plugins, ccache, static_libstdcpp, + libzstd, ninja, targets, experimental_targets, @@ -1821,6 +1825,7 @@ impl Config { set(&mut config.llvm_thin_lto, thin_lto); set(&mut config.llvm_release_debuginfo, release_debuginfo); set(&mut config.llvm_static_stdcpp, static_libstdcpp); + set(&mut config.llvm_libzstd, libzstd); if let Some(v) = link_shared { config.llvm_link_shared.set(Some(v)); } @@ -1871,6 +1876,7 @@ impl Config { check_ci_llvm!(optimize_toml); check_ci_llvm!(thin_lto); check_ci_llvm!(release_debuginfo); + check_ci_llvm!(libzstd); check_ci_llvm!(targets); check_ci_llvm!(experimental_targets); check_ci_llvm!(clang_cl); diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index b8f70fdf6a805..84dac25188e1e 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -220,4 +220,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ severity: ChangeSeverity::Warning, summary: "For tarball sources, default value for `rust.channel` will be taken from `src/ci/channel` file.", }, + ChangeInfo { + change_id: 125642, + severity: ChangeSeverity::Info, + summary: "New option `llvm.libzstd` to control whether llvm is built with zstd support.", + }, ]; diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile index 4aa1a3ccc2a5d..5188035d54a46 100644 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile @@ -79,6 +79,7 @@ ENV RUST_CONFIGURE_ARGS \ --set target.x86_64-unknown-linux-gnu.ranlib=/rustroot/bin/llvm-ranlib \ --set llvm.thin-lto=true \ --set llvm.ninja=false \ + --set llvm.libzstd=true \ --set rust.jemalloc \ --set rust.use-lld=true \ --set rust.lto=thin \ From 9f3376eaf2d25069205f033fb362d96f4ee11065 Mon Sep 17 00:00:00 2001 From: Kyle Huey Date: Fri, 12 Jul 2024 09:00:05 -0700 Subject: [PATCH 682/786] Test --compress-debug-sections with rust-lld. --- .../rust-lld-compress-debug-sections/main.rs | 1 + .../rust-lld-compress-debug-sections/rmake.rs | 39 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 tests/run-make/rust-lld-compress-debug-sections/main.rs create mode 100644 tests/run-make/rust-lld-compress-debug-sections/rmake.rs diff --git a/tests/run-make/rust-lld-compress-debug-sections/main.rs b/tests/run-make/rust-lld-compress-debug-sections/main.rs new file mode 100644 index 0000000000000..f328e4d9d04c3 --- /dev/null +++ b/tests/run-make/rust-lld-compress-debug-sections/main.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/tests/run-make/rust-lld-compress-debug-sections/rmake.rs b/tests/run-make/rust-lld-compress-debug-sections/rmake.rs new file mode 100644 index 0000000000000..df9691ccbcf39 --- /dev/null +++ b/tests/run-make/rust-lld-compress-debug-sections/rmake.rs @@ -0,0 +1,39 @@ +// Checks the `compress-debug-sections` option on rust-lld. + +//@ needs-rust-lld +//@ only-linux +//@ ignore-cross-compile + +// FIXME: This test isn't comprehensive and isn't covering all possible combinations. + +use run_make_support::{assert_contains, cmd, llvm_readobj, run_in_tmpdir, rustc}; + +fn check_compression(compression: &str, to_find: &str) { + run_in_tmpdir(|| { + let out = rustc() + .arg("-Zlinker-features=+lld") + .arg("-Clink-self-contained=+linker") + .arg("-Zunstable-options") + .arg("-Cdebuginfo=full") + .link_arg(&format!("-Wl,--compress-debug-sections={compression}")) + .input("main.rs") + .run_unchecked(); + let stderr = out.stderr_utf8(); + if stderr.is_empty() { + llvm_readobj().arg("-t").arg("main").run().assert_stdout_contains(to_find); + } else { + assert_contains( + stderr, + format!( + "LLVM was not built with LLVM_ENABLE_{to_find} \ + or did not find {compression} at build time" + ), + ); + } + }); +} + +fn main() { + check_compression("zlib", "ZLIB"); + check_compression("zstd", "ZSTD"); +} From 7bb345e677c0c11390da69389e9da472e45844fe Mon Sep 17 00:00:00 2001 From: Kyle Huey Date: Wed, 17 Jul 2024 12:59:09 -0700 Subject: [PATCH 683/786] Add zlib and zstd dev packages for building lld. --- src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile index 9025e9bb0a3af..19683317126ab 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile @@ -17,6 +17,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ pkg-config \ xz-utils \ mingw-w64 \ + zlib1g-dev \ + libzstd-dev \ && rm -rf /var/lib/apt/lists/* COPY scripts/sccache.sh /scripts/ From 8db318cc960d3a4ddd508bdbb930304d7a967332 Mon Sep 17 00:00:00 2001 From: Kyle Huey Date: Sun, 28 Jul 2024 18:36:05 +0000 Subject: [PATCH 684/786] Install zstd in dist builder image. Build libzstd from source because the EPEL package is built without fPIC. --- .../host-x86_64/dist-x86_64-linux/Dockerfile | 4 +++ src/ci/docker/scripts/zstd.sh | 29 +++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100755 src/ci/docker/scripts/zstd.sh diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile index 5188035d54a46..61e9694f1e2ae 100644 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile @@ -62,6 +62,10 @@ COPY host-x86_64/dist-x86_64-linux/build-clang.sh /tmp/ RUN ./build-clang.sh ENV CC=clang CXX=clang++ +# rustc's LLVM needs zstd. +COPY scripts/zstd.sh /tmp/ +RUN ./zstd.sh + COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh diff --git a/src/ci/docker/scripts/zstd.sh b/src/ci/docker/scripts/zstd.sh new file mode 100755 index 0000000000000..a3d37ccc31120 --- /dev/null +++ b/src/ci/docker/scripts/zstd.sh @@ -0,0 +1,29 @@ +#!/bin/bash +set -ex + +hide_output() { + set +x + on_err=" +echo ERROR: An error was encountered with the build. +cat /tmp/zstd_build.log +exit 1 +" + trap "$on_err" ERR + bash -c "while true; do sleep 30; echo \$(date) - building ...; done" & + PING_LOOP_PID=$! + "$@" &> /tmp/zstd_build.log + trap - ERR + kill $PING_LOOP_PID + rm /tmp/zstd_build.log + set -x +} + +ZSTD=1.5.6 +curl -L https://github.com/facebook/zstd/releases/download/v$ZSTD/zstd-$ZSTD.tar.gz | tar xzf - + +cd zstd-$ZSTD +CFLAGS=-fPIC hide_output make -j$(nproc) VERBOSE=1 +hide_output make install + +cd .. +rm -rf zstd-$ZSTD From a380d5e8f68de64441274ca2e56dd3a08a60a121 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 9 Aug 2024 12:17:22 +0200 Subject: [PATCH 685/786] Do not print verbose error when a bootstrap command fails without verbose mode --- src/bootstrap/src/lib.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index d3aff8f89a0ca..2062d435bfc99 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -1058,20 +1058,28 @@ Executed at: {executed_at}"#, CommandOutput::did_not_start(stdout, stderr) } }; + + let fail = |message: &str| { + if self.is_verbose() { + println!("{message}"); + } else { + println!("Command has failed. Rerun with -v to see more details."); + } + exit!(1); + }; + if !output.is_success() { match command.failure_behavior { BehaviorOnFailure::DelayFail => { if self.fail_fast { - println!("{message}"); - exit!(1); + fail(&message); } let mut failures = self.delayed_failures.borrow_mut(); failures.push(message); } BehaviorOnFailure::Exit => { - println!("{message}"); - exit!(1); + fail(&message); } BehaviorOnFailure::Ignore => { // If failures are allowed, either the error has been printed already From 1be60b5d2b6ac569d51abd376e6f04e2fc07692c Mon Sep 17 00:00:00 2001 From: Lukas Bergdoll Date: Fri, 9 Aug 2024 15:05:37 +0200 Subject: [PATCH 686/786] Fix linkchecker issue --- library/alloc/src/slice.rs | 2 +- library/core/src/slice/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index aaa6a2abbd904..ef7469c68de62 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -192,7 +192,7 @@ impl [T] { /// Sorting types that only implement [`PartialOrd`] such as [`f32`] and [`f64`] require /// additional precautions. For example, `f32::NAN != f32::NAN`, which doesn't fulfill the /// reflexivity requirement of [`Ord`]. By using an alternative comparison function with - /// [`slice::sort_by`] such as [`f32::total_cmp`] or [`f64::total_cmp`] that defines a [total + /// `slice::sort_by` such as [`f32::total_cmp`] or [`f64::total_cmp`] that defines a [total /// order] users can sort slices containing floating-point values. Alternatively, if all values /// in the slice are guaranteed to be in a subset for which [`PartialOrd::partial_cmp`] forms a /// [total order], it's possible to sort the slice with `sort_by(|a, b| diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index e75a9a88045e9..d9945e860e6fc 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -2893,7 +2893,7 @@ impl [T] { /// Sorting types that only implement [`PartialOrd`] such as [`f32`] and [`f64`] require /// additional precautions. For example, `f32::NAN != f32::NAN`, which doesn't fulfill the /// reflexivity requirement of [`Ord`]. By using an alternative comparison function with - /// [`slice::sort_unstable_by`] such as [`f32::total_cmp`] or [`f64::total_cmp`] that defines a + /// `slice::sort_unstable_by` such as [`f32::total_cmp`] or [`f64::total_cmp`] that defines a /// [total order] users can sort slices containing floating-point values. Alternatively, if all /// values in the slice are guaranteed to be in a subset for which [`PartialOrd::partial_cmp`] /// forms a [total order], it's possible to sort the slice with `sort_unstable_by(|a, b| From 03ee7b59991a107b08d4a2da50b1654dba48e225 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 9 Aug 2024 16:19:19 +0200 Subject: [PATCH 687/786] Move verbose help parsing to `main` To remove a side effect (process exit) when parsing config. --- src/bootstrap/src/bin/main.rs | 6 +++++- src/bootstrap/src/core/config/flags.rs | 24 +++++++++++++++++------- src/bootstrap/src/core/config/mod.rs | 2 +- src/bootstrap/src/lib.rs | 2 +- 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs index dc8b5487a61e8..48f0159486a0c 100644 --- a/src/bootstrap/src/bin/main.rs +++ b/src/bootstrap/src/bin/main.rs @@ -11,7 +11,7 @@ use std::str::FromStr; use std::{env, process}; use bootstrap::{ - find_recent_config_change_ids, human_readable_changes, t, Build, Config, Subcommand, + find_recent_config_change_ids, human_readable_changes, t, Build, Config, Flags, Subcommand, CONFIG_CHANGE_HISTORY, }; @@ -19,6 +19,10 @@ fn main() { let args = env::args().skip(1).collect::>(); let config = Config::parse(&args); + if Flags::try_parse_verbose_help(&args) { + return; + } + let mut build_lock; let _build_lock_guard; diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs index 19f752da81c13..3948fe0d98c86 100644 --- a/src/bootstrap/src/core/config/flags.rs +++ b/src/bootstrap/src/core/config/flags.rs @@ -183,9 +183,9 @@ pub struct Flags { } impl Flags { - pub fn parse(args: &[String]) -> Self { - let first = String::from("x.py"); - let it = std::iter::once(&first).chain(args.iter()); + /// Check if ` -h -v` was passed. + /// If yes, print the available paths and return `true`. + pub fn try_parse_verbose_help(args: &[String]) -> bool { // We need to check for ` -h -v`, in which case we list the paths #[derive(Parser)] #[command(disable_help_flag(true))] @@ -198,10 +198,10 @@ impl Flags { cmd: Kind, } if let Ok(HelpVerboseOnly { help: true, verbose: 1.., cmd: subcommand }) = - HelpVerboseOnly::try_parse_from(it.clone()) + HelpVerboseOnly::try_parse_from(normalize_args(args)) { println!("NOTE: updating submodules before printing available paths"); - let config = Config::parse(&[String::from("build")]); + let config = Config::parse(Self::parse(&[String::from("build")])); let build = Build::new(config); let paths = Builder::get_help(&build, subcommand); if let Some(s) = paths { @@ -209,13 +209,23 @@ impl Flags { } else { panic!("No paths available for subcommand `{}`", subcommand.as_str()); } - crate::exit!(0); + true + } else { + false } + } - Flags::parse_from(it) + pub fn parse(args: &[String]) -> Self { + Flags::parse_from(normalize_args(args)) } } +fn normalize_args(args: &[String]) -> Vec { + let first = String::from("x.py"); + let it = std::iter::once(first).chain(args.iter().cloned()); + it.collect() +} + #[derive(Debug, Clone, Default, clap::Subcommand)] pub enum Subcommand { #[command(aliases = ["b"], long_about = "\n diff --git a/src/bootstrap/src/core/config/mod.rs b/src/bootstrap/src/core/config/mod.rs index 23556e8bc5d38..9f09dd13f2985 100644 --- a/src/bootstrap/src/core/config/mod.rs +++ b/src/bootstrap/src/core/config/mod.rs @@ -1,6 +1,6 @@ #[allow(clippy::module_inception)] mod config; -pub(crate) mod flags; +pub mod flags; #[cfg(test)] mod tests; diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 453fb39327d63..6edfc2ccdaf65 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -43,7 +43,7 @@ mod core; mod utils; pub use core::builder::PathSet; -pub use core::config::flags::Subcommand; +pub use core::config::flags::{Flags, Subcommand}; pub use core::config::Config; pub use utils::change_tracker::{ From 5431a93ddc1c8482d9a801d1627991d16c2318d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 9 Aug 2024 16:19:25 +0200 Subject: [PATCH 688/786] Pass `Flags` to `Config::parse` explicitly --- src/bootstrap/src/bin/main.rs | 4 +++- src/bootstrap/src/core/builder/tests.rs | 5 +++-- src/bootstrap/src/core/config/config.rs | 7 +++---- src/bootstrap/src/core/config/tests.rs | 19 ++++++++++--------- src/bootstrap/src/utils/helpers/tests.rs | 8 +++++--- 5 files changed, 24 insertions(+), 19 deletions(-) diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs index 48f0159486a0c..f03f03e2d9398 100644 --- a/src/bootstrap/src/bin/main.rs +++ b/src/bootstrap/src/bin/main.rs @@ -17,12 +17,14 @@ use bootstrap::{ fn main() { let args = env::args().skip(1).collect::>(); - let config = Config::parse(&args); if Flags::try_parse_verbose_help(&args) { return; } + let flags = Flags::parse(&args); + let config = Config::parse(flags); + let mut build_lock; let _build_lock_guard; diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index f19a4dd6d490f..e06df65c1bc9d 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -3,13 +3,14 @@ use std::thread; use super::*; use crate::core::build_steps::doc::DocumentationFormat; use crate::core::config::Config; +use crate::Flags; fn configure(cmd: &str, host: &[&str], target: &[&str]) -> Config { configure_with_args(&[cmd.to_owned()], host, target) } fn configure_with_args(cmd: &[String], host: &[&str], target: &[&str]) -> Config { - let mut config = Config::parse(cmd); + let mut config = Config::parse(Flags::parse(cmd)); // don't save toolstates config.save_toolstates = None; config.dry_run = DryRun::SelfCheck; @@ -23,7 +24,7 @@ fn configure_with_args(cmd: &[String], host: &[&str], target: &[&str]) -> Config let submodule_build = Build::new(Config { // don't include LLVM, so CI doesn't require ninja/cmake to be installed rust_codegen_backends: vec![], - ..Config::parse(&["check".to_owned()]) + ..Config::parse(Flags::parse(&["check".to_owned()])) }); submodule_build.require_submodule("src/doc/book", None); config.submodules = Some(false); diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 14beef20bad6e..bc7025de916ce 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1188,7 +1188,7 @@ impl Config { } } - pub fn parse(args: &[String]) -> Config { + pub fn parse(flags: Flags) -> Config { #[cfg(test)] fn get_toml(_: &Path) -> TomlConfig { TomlConfig::default() @@ -1218,11 +1218,10 @@ impl Config { exit!(2); }) } - Self::parse_inner(args, get_toml) + Self::parse_inner(flags, get_toml) } - pub(crate) fn parse_inner(args: &[String], get_toml: impl Fn(&Path) -> TomlConfig) -> Config { - let mut flags = Flags::parse(args); + pub(crate) fn parse_inner(mut flags: Flags, get_toml: impl Fn(&Path) -> TomlConfig) -> Config { let mut config = Config::default_opts(); // Set flags. diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs index 6e695d269cf2c..40f3e5e7222fa 100644 --- a/src/bootstrap/src/core/config/tests.rs +++ b/src/bootstrap/src/core/config/tests.rs @@ -12,9 +12,10 @@ use crate::core::build_steps::clippy::get_clippy_rules_in_order; use crate::core::config::{LldMode, Target, TargetSelection, TomlConfig}; fn parse(config: &str) -> Config { - Config::parse_inner(&["check".to_string(), "--config=/does/not/exist".to_string()], |&_| { - toml::from_str(&config).unwrap() - }) + Config::parse_inner( + Flags::parse(&["check".to_string(), "--config=/does/not/exist".to_string()]), + |&_| toml::from_str(&config).unwrap(), + ) } #[test] @@ -108,7 +109,7 @@ fn clap_verify() { #[test] fn override_toml() { let config = Config::parse_inner( - &[ + Flags::parse(&[ "check".to_owned(), "--config=/does/not/exist".to_owned(), "--set=change-id=1".to_owned(), @@ -121,7 +122,7 @@ fn override_toml() { "--set=target.x86_64-unknown-linux-gnu.rpath=false".to_owned(), "--set=target.aarch64-unknown-linux-gnu.sanitizers=false".to_owned(), "--set=target.aarch64-apple-darwin.runner=apple".to_owned(), - ], + ]), |&_| { toml::from_str( r#" @@ -201,12 +202,12 @@ runner = "x86_64-runner" #[should_panic] fn override_toml_duplicate() { Config::parse_inner( - &[ + Flags::parse(&[ "check".to_owned(), "--config=/does/not/exist".to_string(), "--set=change-id=1".to_owned(), "--set=change-id=2".to_owned(), - ], + ]), |&_| toml::from_str("change-id = 0").unwrap(), ); } @@ -226,7 +227,7 @@ fn profile_user_dist() { .and_then(|table: toml::Value| TomlConfig::deserialize(table)) .unwrap() } - Config::parse_inner(&["check".to_owned()], get_toml); + Config::parse_inner(Flags::parse(&["check".to_owned()]), get_toml); } #[test] @@ -301,7 +302,7 @@ fn order_of_clippy_rules() { "-Aclippy::foo1".to_string(), "-Aclippy::foo2".to_string(), ]; - let config = Config::parse(&args); + let config = Config::parse(Flags::parse(&args)); let actual = match &config.cmd { crate::Subcommand::Clippy { allow, deny, warn, forbid, .. } => { diff --git a/src/bootstrap/src/utils/helpers/tests.rs b/src/bootstrap/src/utils/helpers/tests.rs index f0cb324674fc6..103c4d26a1854 100644 --- a/src/bootstrap/src/utils/helpers/tests.rs +++ b/src/bootstrap/src/utils/helpers/tests.rs @@ -5,7 +5,7 @@ use std::path::PathBuf; use crate::utils::helpers::{ check_cfg_arg, extract_beta_rev, hex_encode, make, program_out_of_date, symlink_dir, }; -use crate::Config; +use crate::{Config, Flags}; #[test] fn test_make() { @@ -58,7 +58,8 @@ fn test_check_cfg_arg() { #[test] fn test_program_out_of_date() { - let config = Config::parse(&["check".to_owned(), "--config=/does/not/exist".to_owned()]); + let config = + Config::parse(Flags::parse(&["check".to_owned(), "--config=/does/not/exist".to_owned()])); let tempfile = config.tempdir().join(".tmp-stamp-file"); File::create(&tempfile).unwrap().write_all(b"dummy value").unwrap(); assert!(tempfile.exists()); @@ -73,7 +74,8 @@ fn test_program_out_of_date() { #[test] fn test_symlink_dir() { - let config = Config::parse(&["check".to_owned(), "--config=/does/not/exist".to_owned()]); + let config = + Config::parse(Flags::parse(&["check".to_owned(), "--config=/does/not/exist".to_owned()])); let tempdir = config.tempdir().join(".tmp-dir"); let link_path = config.tempdir().join(".tmp-link"); From 1d19c2c009529fff08a95cbe548bcb1a6e02651c Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 9 Aug 2024 07:57:46 -0700 Subject: [PATCH 689/786] rustdoc: move invalid langstring test to UI --- .../doctest/doctest-no-run-invalid-langstring-124577.rs | 1 + .../doctest/doctest-no-run-invalid-langstring-124577.stdout | 5 +++++ 2 files changed, 6 insertions(+) rename tests/{rustdoc => rustdoc-ui}/doctest/doctest-no-run-invalid-langstring-124577.rs (94%) create mode 100644 tests/rustdoc-ui/doctest/doctest-no-run-invalid-langstring-124577.stdout diff --git a/tests/rustdoc/doctest/doctest-no-run-invalid-langstring-124577.rs b/tests/rustdoc-ui/doctest/doctest-no-run-invalid-langstring-124577.rs similarity index 94% rename from tests/rustdoc/doctest/doctest-no-run-invalid-langstring-124577.rs rename to tests/rustdoc-ui/doctest/doctest-no-run-invalid-langstring-124577.rs index b3e993e8ee939..571bc94e30f98 100644 --- a/tests/rustdoc/doctest/doctest-no-run-invalid-langstring-124577.rs +++ b/tests/rustdoc-ui/doctest/doctest-no-run-invalid-langstring-124577.rs @@ -1,4 +1,5 @@ //@ compile-flags:--test +//@ check-pass #![allow(rustdoc::invalid_codeblock_attributes)] // https://github.com/rust-lang/rust/pull/124577#issuecomment-2276034737 diff --git a/tests/rustdoc-ui/doctest/doctest-no-run-invalid-langstring-124577.stdout b/tests/rustdoc-ui/doctest/doctest-no-run-invalid-langstring-124577.stdout new file mode 100644 index 0000000000000..e5c27bebbdb23 --- /dev/null +++ b/tests/rustdoc-ui/doctest/doctest-no-run-invalid-langstring-124577.stdout @@ -0,0 +1,5 @@ + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s + From d61b0e782f1a37594f06467ba8a88605d01ac774 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 9 Aug 2024 15:38:46 +0000 Subject: [PATCH 690/786] Rustup to rustc 1.82.0-nightly (3e9bd8b56 2024-08-08) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 827956c98cf29..96c467e091cff 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2024-08-08" +channel = "nightly-2024-08-09" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From d515e881a7b7ad5ba0e55c82391b881dc4058925 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 9 Aug 2024 15:51:43 +0000 Subject: [PATCH 691/786] Disable f16 and f128 in compiler-builtins when running rustc tests --- ...le-f16-and-f128-in-compiler-builtins.patch | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch diff --git a/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch b/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch new file mode 100644 index 0000000000000..ada35145e2937 --- /dev/null +++ b/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch @@ -0,0 +1,25 @@ +From 175d52c5e1779764b66777db1e6f172c2dc365ff Mon Sep 17 00:00:00 2001 +From: bjorn3 <17426603+bjorn3@users.noreply.github.com> +Date: Fri, 9 Aug 2024 15:44:51 +0000 +Subject: [PATCH] Disable f16 and f128 in compiler-builtins + +--- + library/sysroot/Cargo.toml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/library/sysroot/Cargo.toml b/library/sysroot/Cargo.toml +index 7165c3e48af..968552ad435 100644 +--- a/library/sysroot/Cargo.toml ++++ b/library/sysroot/Cargo.toml +@@ -11,7 +11,7 @@ test = { path = "../test" } + + # Forward features to the `std` crate as necessary + [features] +-default = ["std_detect_file_io", "std_detect_dlsym_getauxval", "panic-unwind"] ++default = ["std_detect_file_io", "std_detect_dlsym_getauxval", "panic-unwind", "compiler-builtins-no-f16-f128"] + backtrace = ["std/backtrace"] + compiler-builtins-c = ["std/compiler-builtins-c"] + compiler-builtins-mem = ["std/compiler-builtins-mem"] +-- +2.34.1 + From 0e20a762f12f1f0262d9d7e5b438b89e95d29d30 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 9 Aug 2024 15:59:30 +0000 Subject: [PATCH 692/786] Stop using a custom Cargo.toml and Cargo.lock for the standard library The rust-src component now ships a working copy of both. --- build_system/prepare.rs | 30 --- patches/stdlib-lock.toml | 455 --------------------------------------- 2 files changed, 485 deletions(-) delete mode 100644 patches/stdlib-lock.toml diff --git a/build_system/prepare.rs b/build_system/prepare.rs index 5525a5f63e93b..be0bed0f4e636 100644 --- a/build_system/prepare.rs +++ b/build_system/prepare.rs @@ -22,36 +22,6 @@ pub(crate) fn prepare_stdlib(dirs: &Dirs, rustc: &Path) { assert!(sysroot_src_orig.exists()); apply_patches(dirs, "stdlib", &sysroot_src_orig, &STDLIB_SRC.to_path(dirs)); - - std::fs::write( - STDLIB_SRC.to_path(dirs).join("Cargo.toml"), - r#" -[workspace] -resolver = "1" -members = ["./library/sysroot"] - -[patch.crates-io] -rustc-std-workspace-core = { path = "./library/rustc-std-workspace-core" } -rustc-std-workspace-alloc = { path = "./library/rustc-std-workspace-alloc" } -rustc-std-workspace-std = { path = "./library/rustc-std-workspace-std" } - -# Mandatory for correctly compiling compiler-builtins -[profile.dev.package.compiler_builtins] -debug-assertions = false -overflow-checks = false -codegen-units = 10000 - -[profile.release.package.compiler_builtins] -debug-assertions = false -overflow-checks = false -codegen-units = 10000 -"#, - ) - .unwrap(); - - let source_lockfile = RelPath::PATCHES.to_path(dirs).join("stdlib-lock.toml"); - let target_lockfile = STDLIB_SRC.to_path(dirs).join("Cargo.lock"); - fs::copy(source_lockfile, target_lockfile).unwrap(); } pub(crate) struct GitRepo { diff --git a/patches/stdlib-lock.toml b/patches/stdlib-lock.toml deleted file mode 100644 index b68e9c2f0d075..0000000000000 --- a/patches/stdlib-lock.toml +++ /dev/null @@ -1,455 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" -dependencies = [ - "compiler_builtins", - "gimli 0.29.0", - "rustc-std-workspace-alloc", - "rustc-std-workspace-core", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" -dependencies = [ - "compiler_builtins", - "rustc-std-workspace-core", -] - -[[package]] -name = "alloc" -version = "0.0.0" -dependencies = [ - "compiler_builtins", - "core", - "rand", - "rand_xorshift", -] - -[[package]] -name = "allocator-api2" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" - -[[package]] -name = "cc" -version = "1.0.97" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -dependencies = [ - "compiler_builtins", - "rustc-std-workspace-core", -] - -[[package]] -name = "compiler_builtins" -version = "0.1.114" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb58b199190fcfe0846f55a3b545cd6b07a34bdd5930a476ff856f3ebcc5558a" -dependencies = [ - "cc", - "rustc-std-workspace-core", -] - -[[package]] -name = "core" -version = "0.0.0" -dependencies = [ - "rand", - "rand_xorshift", -] - -[[package]] -name = "cupid" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bad352a84b567cc38a5854e3aa8ee903cb8519a25d0b799b739bafffd1f91a1" -dependencies = [ - "gcc", - "rustc_version", -] - -[[package]] -name = "dlmalloc" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "203540e710bfadb90e5e29930baf5d10270cec1f43ab34f46f78b147b2de715a" -dependencies = [ - "compiler_builtins", - "libc", - "rustc-std-workspace-core", -] - -[[package]] -name = "fortanix-sgx-abi" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57cafc2274c10fab234f176b25903ce17e690fca7597090d50880e047a0389c5" -dependencies = [ - "compiler_builtins", - "rustc-std-workspace-core", -] - -[[package]] -name = "gcc" -version = "0.3.55" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" - -[[package]] -name = "getopts" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" -dependencies = [ - "rustc-std-workspace-core", - "rustc-std-workspace-std", - "unicode-width", -] - -[[package]] -name = "gimli" -version = "0.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" -dependencies = [ - "compiler_builtins", - "rustc-std-workspace-alloc", - "rustc-std-workspace-core", -] - -[[package]] -name = "gimli" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" -dependencies = [ - "compiler_builtins", - "rustc-std-workspace-alloc", - "rustc-std-workspace-core", -] - -[[package]] -name = "hashbrown" -version = "0.14.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" -dependencies = [ - "allocator-api2", - "compiler_builtins", - "rustc-std-workspace-alloc", - "rustc-std-workspace-core", -] - -[[package]] -name = "hermit-abi" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" -dependencies = [ - "compiler_builtins", - "rustc-std-workspace-alloc", - "rustc-std-workspace-core", -] - -[[package]] -name = "libc" -version = "0.2.153" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" -dependencies = [ - "rustc-std-workspace-core", -] - -[[package]] -name = "memchr" -version = "2.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" -dependencies = [ - "compiler_builtins", - "rustc-std-workspace-core", -] - -[[package]] -name = "miniz_oxide" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" -dependencies = [ - "adler", - "compiler_builtins", - "rustc-std-workspace-alloc", - "rustc-std-workspace-core", -] - -[[package]] -name = "object" -version = "0.36.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" -dependencies = [ - "compiler_builtins", - "memchr", - "rustc-std-workspace-alloc", - "rustc-std-workspace-core", -] - -[[package]] -name = "panic_abort" -version = "0.0.0" -dependencies = [ - "alloc", - "cfg-if", - "compiler_builtins", - "core", - "libc", -] - -[[package]] -name = "panic_unwind" -version = "0.0.0" -dependencies = [ - "alloc", - "cfg-if", - "compiler_builtins", - "core", - "libc", - "unwind", -] - -[[package]] -name = "proc_macro" -version = "0.0.0" -dependencies = [ - "core", - "std", -] - -[[package]] -name = "profiler_builtins" -version = "0.0.0" -dependencies = [ - "cc", - "compiler_builtins", - "core", -] - -[[package]] -name = "r-efi" -version = "4.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9e935efc5854715dfc0a4c9ef18dc69dee0ec3bf9cc3ab740db831c0fdd86a3" -dependencies = [ - "compiler_builtins", - "rustc-std-workspace-core", -] - -[[package]] -name = "r-efi-alloc" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31d6f09fe2b6ad044bc3d2c34ce4979796581afd2f1ebc185837e02421e02fd7" -dependencies = [ - "compiler_builtins", - "r-efi", - "rustc-std-workspace-core", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" - -[[package]] -name = "rand_xorshift" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" -dependencies = [ - "rand_core", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" -dependencies = [ - "compiler_builtins", - "rustc-std-workspace-core", -] - -[[package]] -name = "rustc-std-workspace-alloc" -version = "1.99.0" -dependencies = [ - "alloc", -] - -[[package]] -name = "rustc-std-workspace-core" -version = "1.99.0" -dependencies = [ - "core", -] - -[[package]] -name = "rustc-std-workspace-std" -version = "1.99.0" -dependencies = [ - "std", -] - -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -dependencies = [ - "semver", -] - -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" - -[[package]] -name = "std" -version = "0.0.0" -dependencies = [ - "addr2line", - "alloc", - "cfg-if", - "compiler_builtins", - "core", - "dlmalloc", - "fortanix-sgx-abi", - "hashbrown", - "hermit-abi", - "libc", - "miniz_oxide", - "object", - "panic_abort", - "panic_unwind", - "profiler_builtins", - "r-efi", - "r-efi-alloc", - "rand", - "rand_xorshift", - "rustc-demangle", - "std_detect", - "unwind", - "wasi", -] - -[[package]] -name = "std_detect" -version = "0.1.5" -dependencies = [ - "cfg-if", - "compiler_builtins", - "cupid", - "libc", - "rustc-std-workspace-alloc", - "rustc-std-workspace-core", -] - -[[package]] -name = "sysroot" -version = "0.0.0" -dependencies = [ - "proc_macro", - "std", - "test", -] - -[[package]] -name = "test" -version = "0.0.0" -dependencies = [ - "core", - "getopts", - "libc", - "std", -] - -[[package]] -name = "unicode-width" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" -dependencies = [ - "compiler_builtins", - "rustc-std-workspace-core", - "rustc-std-workspace-std", -] - -[[package]] -name = "unwind" -version = "0.0.0" -dependencies = [ - "cfg-if", - "compiler_builtins", - "core", - "libc", - "unwinding", -] - -[[package]] -name = "unwinding" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37a19a21a537f635c16c7576f22d0f2f7d63353c1337ad4ce0d8001c7952a25b" -dependencies = [ - "compiler_builtins", - "gimli 0.28.1", - "rustc-std-workspace-core", -] - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -dependencies = [ - "compiler_builtins", - "rustc-std-workspace-alloc", - "rustc-std-workspace-core", -] From ae09340350fd8b7aa7a00a81132a7e77772504cb Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 9 Aug 2024 18:05:57 +0200 Subject: [PATCH 693/786] make LocalWaker::will_wake consistent with Waker::will_wake --- library/core/src/task/wake.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 8ce3eb2ea3921..29932c0d1ffeb 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -502,6 +502,8 @@ impl Waker { #[must_use] #[stable(feature = "futures_api", since = "1.36.0")] pub fn will_wake(&self, other: &Waker) -> bool { + // We optimize this by comparing vtable addresses instead of vtable contents. + // This is permitted since the function is documented as best-effort. let RawWaker { data: a_data, vtable: a_vtable } = self.waker; let RawWaker { data: b_data, vtable: b_vtable } = other.waker; a_data == b_data && ptr::eq(a_vtable, b_vtable) @@ -761,7 +763,11 @@ impl LocalWaker { #[must_use] #[unstable(feature = "local_waker", issue = "118959")] pub fn will_wake(&self, other: &LocalWaker) -> bool { - self.waker == other.waker + // We optimize this by comparing vtable addresses instead of vtable contents. + // This is permitted since the function is documented as best-effort. + let RawWaker { data: a_data, vtable: a_vtable } = self.waker; + let RawWaker { data: b_data, vtable: b_vtable } = other.waker; + a_data == b_data && ptr::eq(a_vtable, b_vtable) } /// Creates a new `LocalWaker` from [`RawWaker`]. From 69b3f5a426a5c1c05236a45b36f6679d95fbe01b Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 9 Aug 2024 16:13:39 +0000 Subject: [PATCH 694/786] Couple of minor cleanups --- build_system/build_sysroot.rs | 1 - build_system/tests.rs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/build_system/build_sysroot.rs b/build_system/build_sysroot.rs index ed8b5b906d28f..e41f6c5e709e2 100644 --- a/build_system/build_sysroot.rs +++ b/build_system/build_sysroot.rs @@ -312,7 +312,6 @@ fn build_rtstartup(dirs: &Dirs, compiler: &Compiler) -> Option { let obj = RTSTARTUP_SYSROOT.to_path(dirs).join(format!("{file}.o")); let mut build_rtstartup_cmd = Command::new(&compiler.rustc); build_rtstartup_cmd - .arg("-Ainternal_features") // Missing #[allow(internal_features)] .arg("--target") .arg(&compiler.triple) .arg("--emit=obj") diff --git a/build_system/tests.rs b/build_system/tests.rs index 3a88824bf3635..38c3786a94a42 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -438,7 +438,7 @@ impl<'a> TestRunner<'a> { cmd.arg("-L"); cmd.arg(format!("crate={}", BUILD_EXAMPLE_OUT_DIR.to_path(&self.dirs).display())); cmd.arg("--out-dir"); - cmd.arg(format!("{}", BUILD_EXAMPLE_OUT_DIR.to_path(&self.dirs).display())); + cmd.arg(BUILD_EXAMPLE_OUT_DIR.to_path(&self.dirs)); cmd.arg("-Cdebuginfo=2"); cmd.arg("--target"); cmd.arg(&self.target_compiler.triple); From 9a233bb9dd0783b4819650ed87112dbaf944f353 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 9 Aug 2024 18:08:34 +0200 Subject: [PATCH 695/786] interpret: make identity upcasts a NOP again to avoid them generating a new random vtable --- .../rustc_const_eval/src/interpret/cast.rs | 6 ++ .../consts/const-eval/raw-bytes.32bit.stderr | 22 +++-- .../consts/const-eval/raw-bytes.64bit.stderr | 22 +++-- tests/ui/consts/const-eval/raw-bytes.rs | 4 +- .../ub-incorrect-vtable.32bit.stderr | 40 +++++---- .../ub-incorrect-vtable.64bit.stderr | 40 +++++---- .../consts/const-eval/ub-incorrect-vtable.rs | 4 +- tests/ui/consts/const-eval/ub-wide-ptr.rs | 14 ++-- tests/ui/consts/const-eval/ub-wide-ptr.stderr | 83 +++++++++++++------ 9 files changed, 158 insertions(+), 77 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index b2f07de0ac4e2..f6428104e7a42 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -400,6 +400,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } (ty::Dynamic(data_a, _, ty::Dyn), ty::Dynamic(data_b, _, ty::Dyn)) => { let val = self.read_immediate(src)?; + // MIR building generates odd NOP casts, prevent them from causing unexpected trouble. + // See . + // FIXME: ideally we wouldn't have to do this. + if data_a == data_b { + return self.write_immediate(*val, dest); + } // Take apart the old pointer, and find the dynamic type. let (old_data, old_vptr) = val.to_scalar_pair(); let old_data = old_data.to_pointer(self)?; diff --git a/tests/ui/consts/const-eval/raw-bytes.32bit.stderr b/tests/ui/consts/const-eval/raw-bytes.32bit.stderr index 25f17f9c38a97..27c85cc8ce41a 100644 --- a/tests/ui/consts/const-eval/raw-bytes.32bit.stderr +++ b/tests/ui/consts/const-eval/raw-bytes.32bit.stderr @@ -436,17 +436,27 @@ LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──╼╾──╼ } -error[E0080]: evaluation of constant value failed - --> $DIR/raw-bytes.rs:196:62 +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:196:1 | LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to some allocation, but got a null pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a vtable pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾ALLOC_ID╼ 00 00 00 00 │ ╾──╼.... + } -error[E0080]: evaluation of constant value failed - --> $DIR/raw-bytes.rs:199:65 +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:199:1 | LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using ALLOC32 as vtable pointer but it does not point to a vtable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC27, but expected a vtable pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──╼╾──╼ + } error[E0080]: it is undefined behavior to use this value --> $DIR/raw-bytes.rs:204:1 diff --git a/tests/ui/consts/const-eval/raw-bytes.64bit.stderr b/tests/ui/consts/const-eval/raw-bytes.64bit.stderr index 0fb9694895d8e..2b0ce99a88173 100644 --- a/tests/ui/consts/const-eval/raw-bytes.64bit.stderr +++ b/tests/ui/consts/const-eval/raw-bytes.64bit.stderr @@ -436,17 +436,27 @@ LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──────╼╾──────╼ } -error[E0080]: evaluation of constant value failed - --> $DIR/raw-bytes.rs:196:62 +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:196:1 | LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to some allocation, but got a null pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a vtable pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾ALLOC_ID╼ 00 00 00 00 00 00 00 00 │ ╾──────╼........ + } -error[E0080]: evaluation of constant value failed - --> $DIR/raw-bytes.rs:199:65 +error[E0080]: it is undefined behavior to use this value + --> $DIR/raw-bytes.rs:199:1 | LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using ALLOC32 as vtable pointer but it does not point to a vtable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC27, but expected a vtable pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──────╼╾──────╼ + } error[E0080]: it is undefined behavior to use this value --> $DIR/raw-bytes.rs:204:1 diff --git a/tests/ui/consts/const-eval/raw-bytes.rs b/tests/ui/consts/const-eval/raw-bytes.rs index de1a81b00243b..0df732df30e1d 100644 --- a/tests/ui/consts/const-eval/raw-bytes.rs +++ b/tests/ui/consts/const-eval/raw-bytes.rs @@ -194,10 +194,10 @@ const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool //~| expected a boolean const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) }; -//~^ ERROR evaluation of constant value failed +//~^ ERROR it is undefined behavior to use this value //~| null pointer const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; -//~^ ERROR evaluation of constant value failed +//~^ ERROR it is undefined behavior to use this value //~| vtable // Uninhabited types diff --git a/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr b/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr index 439ccb24e6167..5c47cbfdf3b1e 100644 --- a/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr +++ b/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr @@ -1,46 +1,56 @@ -error[E0080]: evaluation of constant value failed - --> $DIR/ub-incorrect-vtable.rs:19:14 +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-incorrect-vtable.rs:18:1 + | +LL | const INVALID_VTABLE_ALIGNMENT: &dyn Trait = + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC1, but expected a vtable pointer | -LL | unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using ALLOC8 as vtable pointer but it does not point to a vtable + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾ALLOC0╼ ╾ALLOC1╼ │ ╾──╼╾──╼ + } -error[E0080]: evaluation of constant value failed - --> $DIR/ub-incorrect-vtable.rs:24:14 +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-incorrect-vtable.rs:23:1 + | +LL | const INVALID_VTABLE_SIZE: &dyn Trait = + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC3, but expected a vtable pointer | -LL | unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using ALLOC9 as vtable pointer but it does not point to a vtable + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾ALLOC2╼ ╾ALLOC3╼ │ ╾──╼╾──╼ + } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:33:1 | LL | const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC1, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC5, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾ALLOC0╼ ╾ALLOC1╼ │ ╾──╼╾──╼ + ╾ALLOC4╼ ╾ALLOC5╼ │ ╾──╼╾──╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:38:1 | LL | const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC3, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC7, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾ALLOC2╼ ╾ALLOC3╼ │ ╾──╼╾──╼ + ╾ALLOC6╼ ╾ALLOC7╼ │ ╾──╼╾──╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:44:1 | LL | const INVALID_VTABLE_UB: W<&dyn Trait> = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC5, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC9, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾ALLOC4╼ ╾ALLOC5╼ │ ╾──╼╾──╼ + ╾ALLOC8╼ ╾ALLOC9╼ │ ╾──╼╾──╼ } error[E0080]: it is undefined behavior to use this value @@ -51,7 +61,7 @@ LL | const G: Wide = unsafe { Transmute { t: FOO }.u }; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 4) { - ╾ALLOC6╼ ╾ALLOC7╼ │ ╾──╼╾──╼ + ╾ALLOC10╼ ╾ALLOC11╼ │ ╾──╼╾──╼ } error: aborting due to 6 previous errors diff --git a/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr b/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr index 89bf959703a04..f400073aca215 100644 --- a/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr +++ b/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr @@ -1,46 +1,56 @@ -error[E0080]: evaluation of constant value failed - --> $DIR/ub-incorrect-vtable.rs:19:14 +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-incorrect-vtable.rs:18:1 + | +LL | const INVALID_VTABLE_ALIGNMENT: &dyn Trait = + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC1, but expected a vtable pointer | -LL | unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using ALLOC8 as vtable pointer but it does not point to a vtable + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾ALLOC0╼ ╾ALLOC1╼ │ ╾──────╼╾──────╼ + } -error[E0080]: evaluation of constant value failed - --> $DIR/ub-incorrect-vtable.rs:24:14 +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-incorrect-vtable.rs:23:1 + | +LL | const INVALID_VTABLE_SIZE: &dyn Trait = + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC3, but expected a vtable pointer | -LL | unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using ALLOC9 as vtable pointer but it does not point to a vtable + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾ALLOC2╼ ╾ALLOC3╼ │ ╾──────╼╾──────╼ + } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:33:1 | LL | const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC1, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC5, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾ALLOC0╼ ╾ALLOC1╼ │ ╾──────╼╾──────╼ + ╾ALLOC4╼ ╾ALLOC5╼ │ ╾──────╼╾──────╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:38:1 | LL | const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC3, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC7, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾ALLOC2╼ ╾ALLOC3╼ │ ╾──────╼╾──────╼ + ╾ALLOC6╼ ╾ALLOC7╼ │ ╾──────╼╾──────╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-incorrect-vtable.rs:44:1 | LL | const INVALID_VTABLE_UB: W<&dyn Trait> = - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC5, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC9, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾ALLOC4╼ ╾ALLOC5╼ │ ╾──────╼╾──────╼ + ╾ALLOC8╼ ╾ALLOC9╼ │ ╾──────╼╾──────╼ } error[E0080]: it is undefined behavior to use this value @@ -51,7 +61,7 @@ LL | const G: Wide = unsafe { Transmute { t: FOO }.u }; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { - ╾ALLOC6╼ ╾ALLOC7╼ │ ╾──────╼╾──────╼ + ╾ALLOC10╼ ╾ALLOC11╼ │ ╾──────╼╾──────╼ } error: aborting due to 6 previous errors diff --git a/tests/ui/consts/const-eval/ub-incorrect-vtable.rs b/tests/ui/consts/const-eval/ub-incorrect-vtable.rs index 4325495a3801b..8058f7693a71c 100644 --- a/tests/ui/consts/const-eval/ub-incorrect-vtable.rs +++ b/tests/ui/consts/const-eval/ub-incorrect-vtable.rs @@ -17,12 +17,12 @@ trait Trait {} const INVALID_VTABLE_ALIGNMENT: &dyn Trait = unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) }; -//~^ ERROR evaluation of constant value failed +//~^^ ERROR it is undefined behavior to use this value //~| vtable const INVALID_VTABLE_SIZE: &dyn Trait = unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) }; -//~^ ERROR evaluation of constant value failed +//~^^ ERROR it is undefined behavior to use this value //~| vtable #[repr(transparent)] diff --git a/tests/ui/consts/const-eval/ub-wide-ptr.rs b/tests/ui/consts/const-eval/ub-wide-ptr.rs index 3956146f6aef2..991d4424dcf99 100644 --- a/tests/ui/consts/const-eval/ub-wide-ptr.rs +++ b/tests/ui/consts/const-eval/ub-wide-ptr.rs @@ -123,13 +123,13 @@ const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4u //~^ ERROR it is undefined behavior to use this value //~| vtable const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) }; -//~^ ERROR evaluation of constant value failed +//~^ ERROR it is undefined behavior to use this value //~| vtable const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) }; -//~^ ERROR evaluation of constant value failed +//~^ ERROR it is undefined behavior to use this value //~| vtable const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) }; -//~^ ERROR evaluation of constant value failed +//~^ ERROR it is undefined behavior to use this value //~| vtable const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) }; //~^ ERROR it is undefined behavior to use this value @@ -142,10 +142,10 @@ const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool // # raw trait object const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) }; -//~^ ERROR evaluation of constant value failed +//~^ ERROR it is undefined behavior to use this value //~| null pointer const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; -//~^ ERROR evaluation of constant value failed +//~^ ERROR it is undefined behavior to use this value //~| vtable const RAW_TRAIT_OBJ_CONTENT_INVALID: *const dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) } as *const dyn Trait; // ok because raw // Officially blessed way to get the vtable @@ -154,12 +154,12 @@ const DYN_METADATA: ptr::DynMetadata = ptr::metadata::(ptr:: static mut RAW_TRAIT_OBJ_VTABLE_NULL_THROUGH_REF: *const dyn Trait = unsafe { mem::transmute::<_, &dyn Trait>((&92u8, 0usize)) - //~^ ERROR could not evaluate static initializer + //~^^ ERROR it is undefined behavior to use this value //~| null pointer }; static mut RAW_TRAIT_OBJ_VTABLE_INVALID_THROUGH_REF: *const dyn Trait = unsafe { mem::transmute::<_, &dyn Trait>((&92u8, &3u64)) - //~^ ERROR could not evaluate static initializer + //~^^ ERROR it is undefined behavior to use this value //~| vtable }; diff --git a/tests/ui/consts/const-eval/ub-wide-ptr.stderr b/tests/ui/consts/const-eval/ub-wide-ptr.stderr index c29cc836fffdb..92f0029a5b3eb 100644 --- a/tests/ui/consts/const-eval/ub-wide-ptr.stderr +++ b/tests/ui/consts/const-eval/ub-wide-ptr.stderr @@ -218,29 +218,44 @@ LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u HEX_DUMP } -error[E0080]: evaluation of constant value failed - --> $DIR/ub-wide-ptr.rs:125:57 +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:125:1 | LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using ALLOC20 as vtable pointer but it does not point to a vtable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC17, but expected a vtable pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } -error[E0080]: evaluation of constant value failed - --> $DIR/ub-wide-ptr.rs:128:57 +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:128:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using ALLOC21 as vtable pointer but it does not point to a vtable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC19, but expected a vtable pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } -error[E0080]: evaluation of constant value failed - --> $DIR/ub-wide-ptr.rs:131:56 +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:131:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using ALLOC22 as vtable pointer but it does not point to a vtable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC21, but expected a vtable pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:134:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC17, but expected a vtable pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC23, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { @@ -258,29 +273,49 @@ LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, HEX_DUMP } -error[E0080]: evaluation of constant value failed - --> $DIR/ub-wide-ptr.rs:144:62 +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:144:1 | LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to some allocation, but got a null pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a vtable pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } -error[E0080]: evaluation of constant value failed - --> $DIR/ub-wide-ptr.rs:147:65 +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:147:1 | LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using ALLOC23 as vtable pointer but it does not point to a vtable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC28, but expected a vtable pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } -error[E0080]: could not evaluate static initializer - --> $DIR/ub-wide-ptr.rs:156:5 +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:155:1 | -LL | mem::transmute::<_, &dyn Trait>((&92u8, 0usize)) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to some allocation, but got a null pointer +LL | static mut RAW_TRAIT_OBJ_VTABLE_NULL_THROUGH_REF: *const dyn Trait = unsafe { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a vtable pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } -error[E0080]: could not evaluate static initializer - --> $DIR/ub-wide-ptr.rs:161:5 +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:160:1 | -LL | mem::transmute::<_, &dyn Trait>((&92u8, &3u64)) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using ALLOC24 as vtable pointer but it does not point to a vtable +LL | static mut RAW_TRAIT_OBJ_VTABLE_INVALID_THROUGH_REF: *const dyn Trait = unsafe { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC31, but expected a vtable pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } error: aborting due to 29 previous errors From 6e5873c08c13b7aebae6e277caa39177e6c2b5e3 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 9 Aug 2024 17:23:50 +0000 Subject: [PATCH 696/786] Use ar_archive_writer from sysroot for cg_clif --- compiler/rustc_codegen_cranelift/Cargo.lock | 10 ---------- compiler/rustc_codegen_cranelift/Cargo.toml | 1 - compiler/rustc_codegen_cranelift/src/lib.rs | 1 + 3 files changed, 1 insertion(+), 11 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/Cargo.lock b/compiler/rustc_codegen_cranelift/Cargo.lock index 741a1748fec98..02d4d98dc4212 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.lock +++ b/compiler/rustc_codegen_cranelift/Cargo.lock @@ -20,15 +20,6 @@ version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" -[[package]] -name = "ar_archive_writer" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f2bcb7cf51decfbbfc7ef476e28b0775b13e5eb1190f8b7df145cd53d4f4374" -dependencies = [ - "object", -] - [[package]] name = "arbitrary" version = "1.3.2" @@ -367,7 +358,6 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" name = "rustc_codegen_cranelift" version = "0.1.0" dependencies = [ - "ar_archive_writer", "cranelift-codegen", "cranelift-frontend", "cranelift-jit", diff --git a/compiler/rustc_codegen_cranelift/Cargo.toml b/compiler/rustc_codegen_cranelift/Cargo.toml index c86919dcdfb7e..a0df502dadc47 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.toml +++ b/compiler/rustc_codegen_cranelift/Cargo.toml @@ -17,7 +17,6 @@ cranelift-object = { version = "0.110.1" } target-lexicon = "0.12.0" gimli = { version = "0.28", default-features = false, features = ["write"]} object = { version = "0.36", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } -ar_archive_writer = "0.3" indexmap = "2.0.0" libloading = { version = "0.8.0", optional = true } diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index f737af25b62ee..21930fa2ddb49 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -12,6 +12,7 @@ #![warn(unused_lifetimes)] // tidy-alphabetical-end +extern crate ar_archive_writer; extern crate jobserver; #[macro_use] extern crate rustc_middle; From 57dd967e7122b55f14027122828cdd8b60a86ad4 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 9 Aug 2024 17:25:32 +0000 Subject: [PATCH 697/786] Update tidy for new cranelift-bitset crate --- src/tools/tidy/src/deps.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index e23e931b0eb04..89011bbb48f5c 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -192,6 +192,7 @@ const EXCEPTIONS_RUSTBOOK: ExceptionList = &[ const EXCEPTIONS_CRANELIFT: ExceptionList = &[ // tidy-alphabetical-start ("cranelift-bforest", "Apache-2.0 WITH LLVM-exception"), + ("cranelift-bitset", "Apache-2.0 WITH LLVM-exception"), ("cranelift-codegen", "Apache-2.0 WITH LLVM-exception"), ("cranelift-codegen-meta", "Apache-2.0 WITH LLVM-exception"), ("cranelift-codegen-shared", "Apache-2.0 WITH LLVM-exception"), @@ -511,6 +512,7 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[ "bumpalo", "cfg-if", "cranelift-bforest", + "cranelift-bitset", "cranelift-codegen", "cranelift-codegen-meta", "cranelift-codegen-shared", From b735547025dad853829a7dbf6b6697090e3f657c Mon Sep 17 00:00:00 2001 From: kraktus <56031107+kraktus@users.noreply.github.com> Date: Fri, 9 Aug 2024 20:50:00 +0200 Subject: [PATCH 698/786] rustdoc-json-types `Discriminant`: fix typo "when to complex" should obviously be "too complex" --- src/rustdoc-json-types/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index a93ac6ccaf1df..999134a40909d 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -634,7 +634,7 @@ pub struct Discriminant { /// hexadecimal, and underscores), making it unsuitable to be machine /// interpreted. /// - /// In some cases, when the value is to complex, this may be `"{ _ }"`. + /// In some cases, when the value is too complex, this may be `"{ _ }"`. /// When this occurs is unstable, and may change without notice. pub expr: String, /// The numerical value of the discriminant. Stored as a string due to From 6ef0ac2b5c3f1183c42f9f3a3a5970783af10ecc Mon Sep 17 00:00:00 2001 From: Kajetan Puchalski Date: Fri, 9 Aug 2024 21:26:27 +0100 Subject: [PATCH 699/786] gitignore: Add Zed and Helix editors --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index f2cdd8762f230..a36cb51de33ff 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,8 @@ Session.vim .vscode .project .vim/ +.helix/ +.zed/ .favorites.json .settings/ .vs/ From 7d1de7f9942e4f91f3fc6dbfd56491caccd02f64 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Wed, 24 Jan 2024 16:48:54 +0100 Subject: [PATCH 700/786] core: optimise Debug impl for ascii::Char Rather than writing character at a time, optimise Debug implementation for core::ascii::Char such that it writes the entire representation as with a single write_str call. With that, add tests for Display and Debug implementations. --- library/core/src/ascii/ascii_char.rs | 32 +++++++++++----------------- library/core/tests/ascii_char.rs | 28 ++++++++++++++++++++++++ library/core/tests/lib.rs | 1 + 3 files changed, 42 insertions(+), 19 deletions(-) create mode 100644 library/core/tests/ascii_char.rs diff --git a/library/core/src/ascii/ascii_char.rs b/library/core/src/ascii/ascii_char.rs index 34a05ac38884d..375358dddf5c1 100644 --- a/library/core/src/ascii/ascii_char.rs +++ b/library/core/src/ascii/ascii_char.rs @@ -3,7 +3,7 @@ //! suggestions from rustc if you get anything slightly wrong in here, and overall //! helps with clarity as we're also referring to `char` intentionally in here. -use crate::fmt::{self, Write}; +use crate::fmt; use crate::mem::transmute; /// One of the 128 Unicode characters from U+0000 through U+007F, @@ -583,9 +583,10 @@ impl fmt::Display for AsciiChar { #[unstable(feature = "ascii_char", issue = "110998")] impl fmt::Debug for AsciiChar { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - #[inline] - fn backslash(a: AsciiChar) -> ([AsciiChar; 4], u8) { - ([AsciiChar::ReverseSolidus, a, AsciiChar::Null, AsciiChar::Null], 2) + use AsciiChar::{Apostrophe, Null, ReverseSolidus as Backslash}; + + fn backslash(a: AsciiChar) -> ([AsciiChar; 6], usize) { + ([Apostrophe, Backslash, a, Apostrophe, Null, Null], 4) } let (buf, len) = match self { @@ -595,24 +596,17 @@ impl fmt::Debug for AsciiChar { AsciiChar::LineFeed => backslash(AsciiChar::SmallN), AsciiChar::ReverseSolidus => backslash(AsciiChar::ReverseSolidus), AsciiChar::Apostrophe => backslash(AsciiChar::Apostrophe), - _ => { - let byte = self.to_u8(); - if !byte.is_ascii_control() { - ([*self, AsciiChar::Null, AsciiChar::Null, AsciiChar::Null], 1) - } else { - const HEX_DIGITS: [AsciiChar; 16] = *b"0123456789abcdef".as_ascii().unwrap(); + _ if self.to_u8().is_ascii_control() => { + const HEX_DIGITS: [AsciiChar; 16] = *b"0123456789abcdef".as_ascii().unwrap(); - let hi = HEX_DIGITS[usize::from(byte >> 4)]; - let lo = HEX_DIGITS[usize::from(byte & 0xf)]; - ([AsciiChar::ReverseSolidus, AsciiChar::SmallX, hi, lo], 4) - } + let byte = self.to_u8(); + let hi = HEX_DIGITS[usize::from(byte >> 4)]; + let lo = HEX_DIGITS[usize::from(byte & 0xf)]; + ([Apostrophe, Backslash, AsciiChar::SmallX, hi, lo, Apostrophe], 6) } + _ => ([Apostrophe, *self, Apostrophe, Null, Null, Null], 3), }; - f.write_char('\'')?; - for byte in &buf[..len as usize] { - f.write_str(byte.as_str())?; - } - f.write_char('\'') + f.write_str(buf[..len].as_str()) } } diff --git a/library/core/tests/ascii_char.rs b/library/core/tests/ascii_char.rs new file mode 100644 index 0000000000000..75b5fd4b9e61d --- /dev/null +++ b/library/core/tests/ascii_char.rs @@ -0,0 +1,28 @@ +use core::ascii::Char; +use core::fmt::Write; + +/// Tests Display implementation for ascii::Char. +#[test] +fn test_display() { + let want = (0..128u8).map(|b| b as char).collect::(); + let mut got = String::with_capacity(128); + for byte in 0..128 { + write!(&mut got, "{}", Char::from_u8(byte).unwrap()).unwrap(); + } + assert_eq!(want, got); +} + +/// Tests Debug implementation for ascii::Char. +#[test] +fn test_debug_control() { + for byte in 0..128u8 { + let mut want = format!("{:?}", byte as char); + // `char` uses `'\u{#}'` representation where ascii::char uses `'\x##'`. + // Transform former into the latter. + if let Some(rest) = want.strip_prefix("'\\u{") { + want = format!("'\\x{:0>2}'", rest.strip_suffix("}'").unwrap()); + } + let chr = core::ascii::Char::from_u8(byte).unwrap(); + assert_eq!(want, format!("{chr:?}"), "byte: {byte}"); + } +} diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 1e336bf96b8fa..8872b4cbfd5ba 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -122,6 +122,7 @@ mod alloc; mod any; mod array; mod ascii; +mod ascii_char; mod asserting; mod async_iter; mod atomic; From 2cc029edf5239e1754f2cde3de4f69c45c134550 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Fri, 9 Aug 2024 21:17:32 +0000 Subject: [PATCH 701/786] Only link libc on *nix platforms --- tests/run-make/fmt-write-bloat/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/run-make/fmt-write-bloat/main.rs b/tests/run-make/fmt-write-bloat/main.rs index e86c48014c3aa..6f206d6515a37 100644 --- a/tests/run-make/fmt-write-bloat/main.rs +++ b/tests/run-make/fmt-write-bloat/main.rs @@ -5,7 +5,7 @@ use core::fmt; use core::fmt::Write; -#[link(name = "c")] +#[cfg_attr(not(windows), link(name = "c"))] extern "C" {} struct Dummy; From ef90df69044df03daece7ad367792a6424420f90 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Fri, 9 Aug 2024 21:21:43 +0000 Subject: [PATCH 702/786] Update reason why fmt-write-bloat ignores windows --- tests/run-make/fmt-write-bloat/rmake.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/run-make/fmt-write-bloat/rmake.rs b/tests/run-make/fmt-write-bloat/rmake.rs index 4ae226ec0e234..6875ef9ddc05e 100644 --- a/tests/run-make/fmt-write-bloat/rmake.rs +++ b/tests/run-make/fmt-write-bloat/rmake.rs @@ -15,9 +15,12 @@ //! `NO_DEBUG_ASSERTIONS=1`). If debug assertions are disabled, then we can check for the absence of //! additional `usize` formatting and padding related symbols. -// Reason: This test is `ignore-windows` because the `no_std` test (using `#[link(name = "c")])` -// doesn't link on windows. //@ ignore-windows +// Reason: +// - MSVC targets really need to parse the .pdb file (aka the debug information). +// On Windows there's an API for that (dbghelp) which maybe we can use +// - MinGW targets have a lot of symbols included in their runtime which we can't avoid. +// We would need to make the symbols we're looking for more specific for this test to work. //@ ignore-cross-compile use run_make_support::env::no_debug_assertions; From 1c02e2b5f17fa9f093bc9c46b54c993d52040e40 Mon Sep 17 00:00:00 2001 From: Evelyn Harthbrooke Date: Fri, 9 Aug 2024 16:59:36 -0600 Subject: [PATCH 703/786] fix incorrect value --- compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs index f37781c3f638a..65f2a1e306987 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs @@ -17,7 +17,7 @@ pub fn target() -> Target { llvm_target: macos_llvm_target(arch).into(), metadata: crate::spec::TargetMetadata { description: Some("ARM64 macOS (11.0+, Big Sur+)".into()), - tier: Some(2), + tier: Some(1), host_tools: Some(true), std: Some(true), }, From 4dc13c54714ed854023a03cb9b09b81a6e01f08b Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 9 Aug 2024 16:15:40 -0700 Subject: [PATCH 704/786] diagnostics: do not warn when a lifetime bound infers itself --- compiler/rustc_lint/src/builtin.rs | 21 +++++++--- .../edition-lint-infer-outlives-macro.rs | 0 .../edition-lint-infer-outlives-macro.fixed | 0 .../edition-lint-infer-outlives-macro.rs | 0 .../edition-lint-infer-outlives-macro.stderr | 0 .../edition-lint-infer-outlives-multispan.rs | 0 ...ition-lint-infer-outlives-multispan.stderr | 0 .../edition-lint-infer-outlives.fixed | 0 .../edition-lint-infer-outlives.rs | 0 .../edition-lint-infer-outlives.stderr | 0 .../explicit-outlives-recursive-119228.fixed | 41 +++++++++++++++++++ .../explicit-outlives-recursive-119228.rs | 41 +++++++++++++++++++ 12 files changed, 97 insertions(+), 6 deletions(-) rename tests/ui/rust-2018/{ => edition-lint-inter-outlives}/auxiliary/edition-lint-infer-outlives-macro.rs (100%) rename tests/ui/rust-2018/{ => edition-lint-inter-outlives}/edition-lint-infer-outlives-macro.fixed (100%) rename tests/ui/rust-2018/{ => edition-lint-inter-outlives}/edition-lint-infer-outlives-macro.rs (100%) rename tests/ui/rust-2018/{ => edition-lint-inter-outlives}/edition-lint-infer-outlives-macro.stderr (100%) rename tests/ui/rust-2018/{ => edition-lint-inter-outlives}/edition-lint-infer-outlives-multispan.rs (100%) rename tests/ui/rust-2018/{ => edition-lint-inter-outlives}/edition-lint-infer-outlives-multispan.stderr (100%) rename tests/ui/rust-2018/{ => edition-lint-inter-outlives}/edition-lint-infer-outlives.fixed (100%) rename tests/ui/rust-2018/{ => edition-lint-inter-outlives}/edition-lint-infer-outlives.rs (100%) rename tests/ui/rust-2018/{ => edition-lint-inter-outlives}/edition-lint-infer-outlives.stderr (100%) create mode 100644 tests/ui/rust-2018/edition-lint-inter-outlives/explicit-outlives-recursive-119228.fixed create mode 100644 tests/ui/rust-2018/edition-lint-inter-outlives/explicit-outlives-recursive-119228.rs diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index d8674817cb5eb..6b36944b20889 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1924,14 +1924,13 @@ declare_lint_pass!(ExplicitOutlivesRequirements => [EXPLICIT_OUTLIVES_REQUIREMEN impl ExplicitOutlivesRequirements { fn lifetimes_outliving_lifetime<'tcx>( tcx: TyCtxt<'tcx>, - inferred_outlives: &'tcx [(ty::Clause<'tcx>, Span)], + inferred_outlives: impl Iterator, Span)>, item: DefId, lifetime: DefId, ) -> Vec> { let item_generics = tcx.generics_of(item); inferred_outlives - .iter() .filter_map(|(clause, _)| match clause.kind().skip_binder() { ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => match *a { ty::ReEarlyParam(ebr) @@ -1947,11 +1946,10 @@ impl ExplicitOutlivesRequirements { } fn lifetimes_outliving_type<'tcx>( - inferred_outlives: &'tcx [(ty::Clause<'tcx>, Span)], + inferred_outlives: impl Iterator, Span)>, index: u32, ) -> Vec> { inferred_outlives - .iter() .filter_map(|(clause, _)| match clause.kind().skip_binder() { ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(a, b)) => { a.is_param(index).then_some(b) @@ -2094,7 +2092,11 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { ( Self::lifetimes_outliving_lifetime( cx.tcx, - inferred_outlives, + // don't warn if the inferred span actually came from the predicate we're looking at + // this happens if the type is recursively defined + inferred_outlives + .iter() + .filter(|(_, span)| !predicate.span.contains(*span)), item.owner_id.to_def_id(), region_def_id, ), @@ -2116,7 +2118,14 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { }; let index = ty_generics.param_def_id_to_index[&def_id]; ( - Self::lifetimes_outliving_type(inferred_outlives, index), + Self::lifetimes_outliving_type( + // don't warn if the inferred span actually came from the predicate we're looking at + // this happens if the type is recursively defined + inferred_outlives.iter().filter(|(_, span)| { + !predicate.span.contains(*span) + }), + index, + ), &predicate.bounds, predicate.span, predicate.origin == PredicateOrigin::WhereClause, diff --git a/tests/ui/rust-2018/auxiliary/edition-lint-infer-outlives-macro.rs b/tests/ui/rust-2018/edition-lint-inter-outlives/auxiliary/edition-lint-infer-outlives-macro.rs similarity index 100% rename from tests/ui/rust-2018/auxiliary/edition-lint-infer-outlives-macro.rs rename to tests/ui/rust-2018/edition-lint-inter-outlives/auxiliary/edition-lint-infer-outlives-macro.rs diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives-macro.fixed b/tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives-macro.fixed similarity index 100% rename from tests/ui/rust-2018/edition-lint-infer-outlives-macro.fixed rename to tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives-macro.fixed diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives-macro.rs b/tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives-macro.rs similarity index 100% rename from tests/ui/rust-2018/edition-lint-infer-outlives-macro.rs rename to tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives-macro.rs diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives-macro.stderr b/tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives-macro.stderr similarity index 100% rename from tests/ui/rust-2018/edition-lint-infer-outlives-macro.stderr rename to tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives-macro.stderr diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives-multispan.rs b/tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives-multispan.rs similarity index 100% rename from tests/ui/rust-2018/edition-lint-infer-outlives-multispan.rs rename to tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives-multispan.rs diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives-multispan.stderr b/tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives-multispan.stderr similarity index 100% rename from tests/ui/rust-2018/edition-lint-infer-outlives-multispan.stderr rename to tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives-multispan.stderr diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives.fixed b/tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives.fixed similarity index 100% rename from tests/ui/rust-2018/edition-lint-infer-outlives.fixed rename to tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives.fixed diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives.rs b/tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives.rs similarity index 100% rename from tests/ui/rust-2018/edition-lint-infer-outlives.rs rename to tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives.rs diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives.stderr b/tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives.stderr similarity index 100% rename from tests/ui/rust-2018/edition-lint-infer-outlives.stderr rename to tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives.stderr diff --git a/tests/ui/rust-2018/edition-lint-inter-outlives/explicit-outlives-recursive-119228.fixed b/tests/ui/rust-2018/edition-lint-inter-outlives/explicit-outlives-recursive-119228.fixed new file mode 100644 index 0000000000000..7b9fac8f408af --- /dev/null +++ b/tests/ui/rust-2018/edition-lint-inter-outlives/explicit-outlives-recursive-119228.fixed @@ -0,0 +1,41 @@ +//@ run-rustfix +//@ check-pass +#![deny(explicit_outlives_requirements)] + +pub trait TypeCx { + type Ty; +} + +pub struct Pat { + pub ty: Cx::Ty, +} + +// Simple recursive case: no warning +pub struct MyTypeContextSimpleRecursive<'thir, 'tcx: 'thir> { + pub pat: Pat>, +} +impl<'thir, 'tcx: 'thir> TypeCx for MyTypeContextSimpleRecursive<'thir, 'tcx> { + type Ty = (); +} + +// Non-recursive case: we want a warning +pub struct MyTypeContextNotRecursive<'thir, 'tcx: 'thir> { + pub tcx: &'tcx (), + pub thir: &'thir (), +} +impl<'thir, 'tcx: 'thir> TypeCx for MyTypeContextNotRecursive<'thir, 'tcx> { + type Ty = (); +} + + +// Mixed-recursive case: we want a warning +pub struct MyTypeContextMixedRecursive<'thir, 'tcx: 'thir> { + pub pat: Pat>, + pub tcx: &'tcx (), + pub thir: &'thir (), +} +impl<'thir, 'tcx: 'thir> TypeCx for MyTypeContextMixedRecursive<'thir, 'tcx> { + type Ty = (); +} + +fn main() {} diff --git a/tests/ui/rust-2018/edition-lint-inter-outlives/explicit-outlives-recursive-119228.rs b/tests/ui/rust-2018/edition-lint-inter-outlives/explicit-outlives-recursive-119228.rs new file mode 100644 index 0000000000000..7b9fac8f408af --- /dev/null +++ b/tests/ui/rust-2018/edition-lint-inter-outlives/explicit-outlives-recursive-119228.rs @@ -0,0 +1,41 @@ +//@ run-rustfix +//@ check-pass +#![deny(explicit_outlives_requirements)] + +pub trait TypeCx { + type Ty; +} + +pub struct Pat { + pub ty: Cx::Ty, +} + +// Simple recursive case: no warning +pub struct MyTypeContextSimpleRecursive<'thir, 'tcx: 'thir> { + pub pat: Pat>, +} +impl<'thir, 'tcx: 'thir> TypeCx for MyTypeContextSimpleRecursive<'thir, 'tcx> { + type Ty = (); +} + +// Non-recursive case: we want a warning +pub struct MyTypeContextNotRecursive<'thir, 'tcx: 'thir> { + pub tcx: &'tcx (), + pub thir: &'thir (), +} +impl<'thir, 'tcx: 'thir> TypeCx for MyTypeContextNotRecursive<'thir, 'tcx> { + type Ty = (); +} + + +// Mixed-recursive case: we want a warning +pub struct MyTypeContextMixedRecursive<'thir, 'tcx: 'thir> { + pub pat: Pat>, + pub tcx: &'tcx (), + pub thir: &'thir (), +} +impl<'thir, 'tcx: 'thir> TypeCx for MyTypeContextMixedRecursive<'thir, 'tcx> { + type Ty = (); +} + +fn main() {} From f595539b8101f03cfbc6d75c0b3a9ec2ffb72679 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Fri, 9 Aug 2024 20:01:25 -0400 Subject: [PATCH 705/786] Fix dump-ice-to-disk for RUSTC_ICE=0 users --- tests/run-make/dump-ice-to-disk/rmake.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/run-make/dump-ice-to-disk/rmake.rs b/tests/run-make/dump-ice-to-disk/rmake.rs index 2fb5c825064b0..1e2885fb137e5 100644 --- a/tests/run-make/dump-ice-to-disk/rmake.rs +++ b/tests/run-make/dump-ice-to-disk/rmake.rs @@ -9,7 +9,7 @@ use run_make_support::{cwd, has_extension, has_prefix, rfs, rustc, shallow_find_files}; fn main() { - rustc().input("lib.rs").arg("-Ztreat-err-as-bug=1").run_fail(); + rustc().env("RUSTC_ICE", cwd()).input("lib.rs").arg("-Ztreat-err-as-bug=1").run_fail(); let default = get_text_from_ice(".").lines().count(); clear_ice_files(); From d6c0ebef5089407eefbd45199f1dbcf65ee2d0c6 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Fri, 21 Jun 2024 12:28:03 -0400 Subject: [PATCH 706/786] Polymorphize RawVec --- library/alloc/src/raw_vec.rs | 554 ++++++++++++------ library/alloc/src/raw_vec/tests.rs | 27 +- library/core/src/mem/mod.rs | 5 + src/etc/gdb_providers.py | 17 +- tests/debuginfo/strings-and-strs.rs | 2 +- ..._to_slice.PreCodegen.after.panic-abort.mir | 94 ++- ...to_slice.PreCodegen.after.panic-unwind.mir | 94 ++- 7 files changed, 511 insertions(+), 282 deletions(-) diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 5b84df9ecef30..8bcb12b3bc770 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -1,7 +1,7 @@ #![unstable(feature = "raw_vec_internals", reason = "unstable const warnings", issue = "none")] -use core::alloc::LayoutError; -use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties}; +use core::marker::PhantomData; +use core::mem::{ManuallyDrop, MaybeUninit, SizedTypeProperties}; use core::ptr::{self, NonNull, Unique}; use core::{cmp, hint}; @@ -66,7 +66,19 @@ impl Cap { /// `Box<[T]>`, since `capacity()` won't yield the length. #[allow(missing_debug_implementations)] pub(crate) struct RawVec { - ptr: Unique, + inner: RawVecInner, + _marker: PhantomData, +} + +/// Like a `RawVec`, but only generic over the allocator, not the type. +/// +/// As such, all the methods need the layout passed-in as a parameter. +/// +/// Having this separation reduces the amount of code we need to monomorphize, +/// as most operations don't need the actual type, just its layout. +#[allow(missing_debug_implementations)] +struct RawVecInner { + ptr: Unique, /// Never used for ZSTs; it's `capacity()`'s responsibility to return usize::MAX in that case. /// /// # Safety @@ -90,8 +102,9 @@ impl RawVec { /// `RawVec` with capacity `usize::MAX`. Useful for implementing /// delayed allocation. #[must_use] + #[rustc_const_stable(feature = "raw_vec_internals_const", since = "1.81")] pub const fn new() -> Self { - Self::new_in(Global) + Self { inner: RawVecInner::new::(), _marker: PhantomData } } /// Creates a `RawVec` (on the system heap) with exactly the @@ -113,10 +126,7 @@ impl RawVec { #[must_use] #[inline] pub fn with_capacity(capacity: usize) -> Self { - match Self::try_allocate_in(capacity, AllocInit::Uninitialized, Global) { - Ok(res) => res, - Err(err) => handle_error(err), - } + Self { inner: RawVecInner::with_capacity(capacity, T::LAYOUT), _marker: PhantomData } } /// Like `with_capacity`, but guarantees the buffer is zeroed. @@ -124,29 +134,56 @@ impl RawVec { #[must_use] #[inline] pub fn with_capacity_zeroed(capacity: usize) -> Self { - Self::with_capacity_zeroed_in(capacity, Global) + Self { + inner: RawVecInner::with_capacity_zeroed_in(capacity, Global, T::LAYOUT), + _marker: PhantomData, + } } } -impl RawVec { - // Tiny Vecs are dumb. Skip to: - // - 8 if the element size is 1, because any heap allocators is likely - // to round up a request of less than 8 bytes to at least 8 bytes. - // - 4 if elements are moderate-sized (<= 1 KiB). - // - 1 otherwise, to avoid wasting too much space for very short Vecs. - pub(crate) const MIN_NON_ZERO_CAP: usize = if mem::size_of::() == 1 { +impl RawVecInner { + #[must_use] + #[rustc_const_stable(feature = "raw_vec_internals_const", since = "1.81")] + const fn new() -> Self { + Self::new_in(Global, core::mem::align_of::()) + } + + #[cfg(not(any(no_global_oom_handling, test)))] + #[must_use] + #[inline] + fn with_capacity(capacity: usize, elem_layout: Layout) -> Self { + match Self::try_allocate_in(capacity, AllocInit::Uninitialized, Global, elem_layout) { + Ok(res) => res, + Err(err) => handle_error(err), + } + } +} + +// Tiny Vecs are dumb. Skip to: +// - 8 if the element size is 1, because any heap allocators is likely +// to round up a request of less than 8 bytes to at least 8 bytes. +// - 4 if elements are moderate-sized (<= 1 KiB). +// - 1 otherwise, to avoid wasting too much space for very short Vecs. +const fn min_non_zero_cap(size: usize) -> usize { + if size == 1 { 8 - } else if mem::size_of::() <= 1024 { + } else if size <= 1024 { 4 } else { 1 - }; + } +} + +impl RawVec { + #[cfg(not(no_global_oom_handling))] + pub(crate) const MIN_NON_ZERO_CAP: usize = min_non_zero_cap(size_of::()); /// Like `new`, but parameterized over the choice of allocator for /// the returned `RawVec`. + #[inline] + #[rustc_const_stable(feature = "raw_vec_internals_const", since = "1.81")] pub const fn new_in(alloc: A) -> Self { - // `cap: 0` means "unallocated". zero-sized types are ignored. - Self { ptr: Unique::dangling(), cap: Cap::ZERO, alloc } + Self { inner: RawVecInner::new_in(alloc, align_of::()), _marker: PhantomData } } /// Like `with_capacity`, but parameterized over the choice of @@ -154,9 +191,9 @@ impl RawVec { #[cfg(not(no_global_oom_handling))] #[inline] pub fn with_capacity_in(capacity: usize, alloc: A) -> Self { - match Self::try_allocate_in(capacity, AllocInit::Uninitialized, alloc) { - Ok(res) => res, - Err(err) => handle_error(err), + Self { + inner: RawVecInner::with_capacity_in(capacity, alloc, T::LAYOUT), + _marker: PhantomData, } } @@ -164,7 +201,10 @@ impl RawVec { /// allocator for the returned `RawVec`. #[inline] pub fn try_with_capacity_in(capacity: usize, alloc: A) -> Result { - Self::try_allocate_in(capacity, AllocInit::Uninitialized, alloc) + match RawVecInner::try_with_capacity_in(capacity, alloc, T::LAYOUT) { + Ok(inner) => Ok(Self { inner, _marker: PhantomData }), + Err(e) => Err(e), + } } /// Like `with_capacity_zeroed`, but parameterized over the choice @@ -172,9 +212,9 @@ impl RawVec { #[cfg(not(no_global_oom_handling))] #[inline] pub fn with_capacity_zeroed_in(capacity: usize, alloc: A) -> Self { - match Self::try_allocate_in(capacity, AllocInit::Zeroed, alloc) { - Ok(res) => res, - Err(err) => handle_error(err), + Self { + inner: RawVecInner::with_capacity_zeroed_in(capacity, alloc, T::LAYOUT), + _marker: PhantomData, } } @@ -200,45 +240,7 @@ impl RawVec { let me = ManuallyDrop::new(self); unsafe { let slice = ptr::slice_from_raw_parts_mut(me.ptr() as *mut MaybeUninit, len); - Box::from_raw_in(slice, ptr::read(&me.alloc)) - } - } - - fn try_allocate_in( - capacity: usize, - init: AllocInit, - alloc: A, - ) -> Result { - // Don't allocate here because `Drop` will not deallocate when `capacity` is 0. - - if T::IS_ZST || capacity == 0 { - Ok(Self::new_in(alloc)) - } else { - // We avoid `unwrap_or_else` here because it bloats the amount of - // LLVM IR generated. - let layout = match Layout::array::(capacity) { - Ok(layout) => layout, - Err(_) => return Err(CapacityOverflow.into()), - }; - - if let Err(err) = alloc_guard(layout.size()) { - return Err(err); - } - - let result = match init { - AllocInit::Uninitialized => alloc.allocate(layout), - #[cfg(not(no_global_oom_handling))] - AllocInit::Zeroed => alloc.allocate_zeroed(layout), - }; - let ptr = match result { - Ok(ptr) => ptr, - Err(_) => return Err(AllocError { layout, non_exhaustive: () }.into()), - }; - - // Allocators currently return a `NonNull<[u8]>` whose length - // matches the size requested. If that ever changes, the capacity - // here should change to `ptr.len() / mem::size_of::()`. - Ok(Self { ptr: Unique::from(ptr.cast()), cap: unsafe { Cap(capacity) }, alloc }) + Box::from_raw_in(slice, ptr::read(&me.inner.alloc)) } } @@ -254,8 +256,13 @@ impl RawVec { /// guaranteed. #[inline] pub unsafe fn from_raw_parts_in(ptr: *mut T, capacity: usize, alloc: A) -> Self { - let cap = if T::IS_ZST { Cap::ZERO } else { unsafe { Cap(capacity) } }; - Self { ptr: unsafe { Unique::new_unchecked(ptr) }, cap, alloc } + // SAFETY: Precondition passed to the caller + unsafe { + Self { + inner: RawVecInner::from_raw_parts_in(ptr, capacity, alloc), + _marker: PhantomData, + } + } } /// A convenience method for hoisting the non-null precondition out of [`RawVec::from_raw_parts_in`]. @@ -264,9 +271,11 @@ impl RawVec { /// /// See [`RawVec::from_raw_parts_in`]. #[inline] - pub(crate) unsafe fn from_nonnull_in(ptr: NonNull, capacity: usize, alloc: A) -> Self { - let cap = if T::IS_ZST { Cap::ZERO } else { unsafe { Cap(capacity) } }; - Self { ptr: Unique::from(ptr), cap, alloc } + pub unsafe fn from_nonnull_in(ptr: NonNull, capacity: usize, alloc: A) -> Self { + // SAFETY: Precondition passed to the caller + unsafe { + Self { inner: RawVecInner::from_nonnull_in(ptr, capacity, alloc), _marker: PhantomData } + } } /// Gets a raw pointer to the start of the allocation. Note that this is @@ -274,43 +283,26 @@ impl RawVec { /// be careful. #[inline] pub fn ptr(&self) -> *mut T { - self.ptr.as_ptr() + self.inner.ptr() } #[inline] pub fn non_null(&self) -> NonNull { - NonNull::from(self.ptr) + self.inner.non_null() } /// Gets the capacity of the allocation. /// /// This will always be `usize::MAX` if `T` is zero-sized. - #[inline(always)] + #[inline] pub fn capacity(&self) -> usize { - if T::IS_ZST { usize::MAX } else { self.cap.0 } + self.inner.capacity(size_of::()) } /// Returns a shared reference to the allocator backing this `RawVec`. + #[inline] pub fn allocator(&self) -> &A { - &self.alloc - } - - fn current_memory(&self) -> Option<(NonNull, Layout)> { - if T::IS_ZST || self.cap.0 == 0 { - None - } else { - // We could use Layout::array here which ensures the absence of isize and usize overflows - // and could hypothetically handle differences between stride and size, but this memory - // has already been allocated so we know it can't overflow and currently Rust does not - // support such types. So we can do better by skipping some checks and avoid an unwrap. - const { assert!(mem::size_of::() % mem::align_of::() == 0) }; - unsafe { - let align = mem::align_of::(); - let size = mem::size_of::().unchecked_mul(self.cap.0); - let layout = Layout::from_size_align_unchecked(size, align); - Some((self.ptr.cast().into(), layout)) - } - } + self.inner.allocator() } /// Ensures that the buffer contains at least enough space to hold `len + @@ -335,24 +327,7 @@ impl RawVec { #[cfg(not(no_global_oom_handling))] #[inline] pub fn reserve(&mut self, len: usize, additional: usize) { - // Callers expect this function to be very cheap when there is already sufficient capacity. - // Therefore, we move all the resizing and error-handling logic from grow_amortized and - // handle_reserve behind a call, while making sure that this function is likely to be - // inlined as just a comparison and a call if the comparison fails. - #[cold] - fn do_reserve_and_handle( - slf: &mut RawVec, - len: usize, - additional: usize, - ) { - if let Err(err) = slf.grow_amortized(len, additional) { - handle_error(err); - } - } - - if self.needs_to_grow(len, additional) { - do_reserve_and_handle(self, len, additional); - } + self.inner.reserve(len, additional, T::LAYOUT) } /// A specialized version of `self.reserve(len, 1)` which requires the @@ -360,21 +335,12 @@ impl RawVec { #[cfg(not(no_global_oom_handling))] #[inline(never)] pub fn grow_one(&mut self) { - if let Err(err) = self.grow_amortized(self.cap.0, 1) { - handle_error(err); - } + self.inner.grow_one(T::LAYOUT) } /// The same as `reserve`, but returns on errors instead of panicking or aborting. pub fn try_reserve(&mut self, len: usize, additional: usize) -> Result<(), TryReserveError> { - if self.needs_to_grow(len, additional) { - self.grow_amortized(len, additional)?; - } - unsafe { - // Inform the optimizer that the reservation has succeeded or wasn't needed - hint::assert_unchecked(!self.needs_to_grow(len, additional)); - } - Ok(()) + self.inner.try_reserve(len, additional, T::LAYOUT) } /// Ensures that the buffer contains at least enough space to hold `len + @@ -396,9 +362,7 @@ impl RawVec { /// Aborts on OOM. #[cfg(not(no_global_oom_handling))] pub fn reserve_exact(&mut self, len: usize, additional: usize) { - if let Err(err) = self.try_reserve_exact(len, additional) { - handle_error(err); - } + self.inner.reserve_exact(len, additional, T::LAYOUT) } /// The same as `reserve_exact`, but returns on errors instead of panicking or aborting. @@ -407,14 +371,7 @@ impl RawVec { len: usize, additional: usize, ) -> Result<(), TryReserveError> { - if self.needs_to_grow(len, additional) { - self.grow_exact(len, additional)?; - } - unsafe { - // Inform the optimizer that the reservation has succeeded or wasn't needed - hint::assert_unchecked(!self.needs_to_grow(len, additional)); - } - Ok(()) + self.inner.try_reserve_exact(len, additional, T::LAYOUT) } /// Shrinks the buffer down to the specified capacity. If the given amount @@ -430,22 +387,226 @@ impl RawVec { #[cfg(not(no_global_oom_handling))] #[inline] pub fn shrink_to_fit(&mut self, cap: usize) { - if let Err(err) = self.shrink(cap) { + self.inner.shrink_to_fit(cap, T::LAYOUT) + } +} + +unsafe impl<#[may_dangle] T, A: Allocator> Drop for RawVec { + /// Frees the memory owned by the `RawVec` *without* trying to drop its contents. + fn drop(&mut self) { + // SAFETY: We are in a Drop impl, self.inner will not be used again. + unsafe { self.inner.deallocate(T::LAYOUT) } + } +} + +impl RawVecInner { + #[inline] + #[rustc_const_stable(feature = "raw_vec_internals_const", since = "1.81")] + const fn new_in(alloc: A, align: usize) -> Self { + let ptr = unsafe { core::mem::transmute(align) }; + // `cap: 0` means "unallocated". zero-sized types are ignored. + Self { ptr, cap: Cap::ZERO, alloc } + } + + #[cfg(not(no_global_oom_handling))] + #[inline] + fn with_capacity_in(capacity: usize, alloc: A, elem_layout: Layout) -> Self { + match Self::try_allocate_in(capacity, AllocInit::Uninitialized, alloc, elem_layout) { + Ok(res) => res, + Err(err) => handle_error(err), + } + } + + #[inline] + fn try_with_capacity_in( + capacity: usize, + alloc: A, + elem_layout: Layout, + ) -> Result { + Self::try_allocate_in(capacity, AllocInit::Uninitialized, alloc, elem_layout) + } + + #[cfg(not(no_global_oom_handling))] + #[inline] + fn with_capacity_zeroed_in(capacity: usize, alloc: A, elem_layout: Layout) -> Self { + match Self::try_allocate_in(capacity, AllocInit::Zeroed, alloc, elem_layout) { + Ok(res) => res, + Err(err) => handle_error(err), + } + } + + fn try_allocate_in( + capacity: usize, + init: AllocInit, + alloc: A, + elem_layout: Layout, + ) -> Result { + // We avoid `unwrap_or_else` here because it bloats the amount of + // LLVM IR generated. + let layout = match layout_array(capacity, elem_layout) { + Ok(layout) => layout, + Err(_) => return Err(CapacityOverflow.into()), + }; + + // Don't allocate here because `Drop` will not deallocate when `capacity` is 0. + if layout.size() == 0 { + return Ok(Self::new_in(alloc, elem_layout.align())); + } + + if let Err(err) = alloc_guard(layout.size()) { + return Err(err); + } + + let result = match init { + AllocInit::Uninitialized => alloc.allocate(layout), + #[cfg(not(no_global_oom_handling))] + AllocInit::Zeroed => alloc.allocate_zeroed(layout), + }; + let ptr = match result { + Ok(ptr) => ptr, + Err(_) => return Err(AllocError { layout, non_exhaustive: () }.into()), + }; + + // Allocators currently return a `NonNull<[u8]>` whose length + // matches the size requested. If that ever changes, the capacity + // here should change to `ptr.len() / mem::size_of::()`. + Ok(Self { ptr: Unique::from(ptr.cast()), cap: unsafe { Cap(capacity) }, alloc }) + } + + #[inline] + unsafe fn from_raw_parts_in(ptr: *mut T, capacity: usize, alloc: A) -> Self { + let cap = if T::IS_ZST { Cap::ZERO } else { unsafe { Cap(capacity) } }; + Self { ptr: unsafe { Unique::new_unchecked(ptr.cast()) }, cap, alloc } + } + + #[inline] + unsafe fn from_nonnull_in(ptr: NonNull, capacity: usize, alloc: A) -> Self { + let cap = if T::IS_ZST { Cap::ZERO } else { unsafe { Cap(capacity) } }; + Self { ptr: Unique::from(ptr.cast()), cap, alloc } + } + + #[inline] + fn ptr(&self) -> *mut T { + self.non_null::().as_ptr() + } + + #[inline] + fn non_null(&self) -> NonNull { + self.ptr.cast().into() + } + + #[inline] + fn capacity(&self, elem_size: usize) -> usize { + if elem_size == 0 { usize::MAX } else { self.cap.0 } + } + + #[inline] + fn allocator(&self) -> &A { + &self.alloc + } + + #[inline] + fn current_memory(&self, elem_layout: Layout) -> Option<(NonNull, Layout)> { + if elem_layout.size() == 0 || self.cap.0 == 0 { + None + } else { + // We could use Layout::array here which ensures the absence of isize and usize overflows + // and could hypothetically handle differences between stride and size, but this memory + // has already been allocated so we know it can't overflow and currently Rust does not + // support such types. So we can do better by skipping some checks and avoid an unwrap. + unsafe { + let alloc_size = elem_layout.size().unchecked_mul(self.cap.0); + let layout = Layout::from_size_align_unchecked(alloc_size, elem_layout.align()); + Some((self.ptr.into(), layout)) + } + } + } + + #[cfg(not(no_global_oom_handling))] + #[inline] + fn reserve(&mut self, len: usize, additional: usize, elem_layout: Layout) { + // Callers expect this function to be very cheap when there is already sufficient capacity. + // Therefore, we move all the resizing and error-handling logic from grow_amortized and + // handle_reserve behind a call, while making sure that this function is likely to be + // inlined as just a comparison and a call if the comparison fails. + #[cold] + fn do_reserve_and_handle( + slf: &mut RawVecInner, + len: usize, + additional: usize, + elem_layout: Layout, + ) { + if let Err(err) = slf.grow_amortized(len, additional, elem_layout) { + handle_error(err); + } + } + + if self.needs_to_grow(len, additional, elem_layout) { + do_reserve_and_handle(self, len, additional, elem_layout); + } + } + + #[cfg(not(no_global_oom_handling))] + #[inline] + fn grow_one(&mut self, elem_layout: Layout) { + if let Err(err) = self.grow_amortized(self.cap.0, 1, elem_layout) { handle_error(err); } } -} -impl RawVec { - /// Returns if the buffer needs to grow to fulfill the needed extra capacity. - /// Mainly used to make inlining reserve-calls possible without inlining `grow`. - fn needs_to_grow(&self, len: usize, additional: usize) -> bool { - additional > self.capacity().wrapping_sub(len) + fn try_reserve( + &mut self, + len: usize, + additional: usize, + elem_layout: Layout, + ) -> Result<(), TryReserveError> { + if self.needs_to_grow(len, additional, elem_layout) { + self.grow_amortized(len, additional, elem_layout)?; + } + unsafe { + // Inform the optimizer that the reservation has succeeded or wasn't needed + hint::assert_unchecked(!self.needs_to_grow(len, additional, elem_layout)); + } + Ok(()) } - /// # Safety: - /// - /// `cap` must not exceed `isize::MAX`. + #[cfg(not(no_global_oom_handling))] + fn reserve_exact(&mut self, len: usize, additional: usize, elem_layout: Layout) { + if let Err(err) = self.try_reserve_exact(len, additional, elem_layout) { + handle_error(err); + } + } + + fn try_reserve_exact( + &mut self, + len: usize, + additional: usize, + elem_layout: Layout, + ) -> Result<(), TryReserveError> { + if self.needs_to_grow(len, additional, elem_layout) { + self.grow_exact(len, additional, elem_layout)?; + } + unsafe { + // Inform the optimizer that the reservation has succeeded or wasn't needed + hint::assert_unchecked(!self.needs_to_grow(len, additional, elem_layout)); + } + Ok(()) + } + + #[cfg(not(no_global_oom_handling))] + #[inline] + fn shrink_to_fit(&mut self, cap: usize, elem_layout: Layout) { + if let Err(err) = self.shrink(cap, elem_layout) { + handle_error(err); + } + } + + #[inline] + fn needs_to_grow(&self, len: usize, additional: usize, elem_layout: Layout) -> bool { + additional > self.capacity(elem_layout.size()).wrapping_sub(len) + } + + #[inline] unsafe fn set_ptr_and_cap(&mut self, ptr: NonNull<[u8]>, cap: usize) { // Allocators currently return a `NonNull<[u8]>` whose length matches // the size requested. If that ever changes, the capacity here should @@ -454,18 +615,16 @@ impl RawVec { self.cap = unsafe { Cap(cap) }; } - // This method is usually instantiated many times. So we want it to be as - // small as possible, to improve compile times. But we also want as much of - // its contents to be statically computable as possible, to make the - // generated code run faster. Therefore, this method is carefully written - // so that all of the code that depends on `T` is within it, while as much - // of the code that doesn't depend on `T` as possible is in functions that - // are non-generic over `T`. - fn grow_amortized(&mut self, len: usize, additional: usize) -> Result<(), TryReserveError> { + fn grow_amortized( + &mut self, + len: usize, + additional: usize, + elem_layout: Layout, + ) -> Result<(), TryReserveError> { // This is ensured by the calling contexts. debug_assert!(additional > 0); - if T::IS_ZST { + if elem_layout.size() == 0 { // Since we return a capacity of `usize::MAX` when `elem_size` is // 0, getting to here necessarily means the `RawVec` is overfull. return Err(CapacityOverflow.into()); @@ -477,33 +636,34 @@ impl RawVec { // This guarantees exponential growth. The doubling cannot overflow // because `cap <= isize::MAX` and the type of `cap` is `usize`. let cap = cmp::max(self.cap.0 * 2, required_cap); - let cap = cmp::max(Self::MIN_NON_ZERO_CAP, cap); + let cap = cmp::max(min_non_zero_cap(elem_layout.size()), cap); - let new_layout = Layout::array::(cap); + let new_layout = layout_array(cap, elem_layout)?; - // `finish_grow` is non-generic over `T`. - let ptr = finish_grow(new_layout, self.current_memory(), &mut self.alloc)?; + let ptr = finish_grow(new_layout, self.current_memory(elem_layout), &mut self.alloc)?; // SAFETY: finish_grow would have resulted in a capacity overflow if we tried to allocate more than `isize::MAX` items + unsafe { self.set_ptr_and_cap(ptr, cap) }; Ok(()) } - // The constraints on this method are much the same as those on - // `grow_amortized`, but this method is usually instantiated less often so - // it's less critical. - fn grow_exact(&mut self, len: usize, additional: usize) -> Result<(), TryReserveError> { - if T::IS_ZST { + fn grow_exact( + &mut self, + len: usize, + additional: usize, + elem_layout: Layout, + ) -> Result<(), TryReserveError> { + if elem_layout.size() == 0 { // Since we return a capacity of `usize::MAX` when the type size is // 0, getting to here necessarily means the `RawVec` is overfull. return Err(CapacityOverflow.into()); } let cap = len.checked_add(additional).ok_or(CapacityOverflow)?; - let new_layout = Layout::array::(cap); + let new_layout = layout_array(cap, elem_layout)?; - // `finish_grow` is non-generic over `T`. - let ptr = finish_grow(new_layout, self.current_memory(), &mut self.alloc)?; - // SAFETY: `finish_grow` would have resulted in a capacity overflow if we tried to allocate more than `isize::MAX` items + let ptr = finish_grow(new_layout, self.current_memory(elem_layout), &mut self.alloc)?; + // SAFETY: finish_grow would have resulted in a capacity overflow if we tried to allocate more than `isize::MAX` items unsafe { self.set_ptr_and_cap(ptr, cap); } @@ -512,10 +672,10 @@ impl RawVec { #[cfg(not(no_global_oom_handling))] #[inline] - fn shrink(&mut self, cap: usize) -> Result<(), TryReserveError> { - assert!(cap <= self.capacity(), "Tried to shrink to a larger capacity"); + fn shrink(&mut self, cap: usize, elem_layout: Layout) -> Result<(), TryReserveError> { + assert!(cap <= self.capacity(elem_layout.size()), "Tried to shrink to a larger capacity"); // SAFETY: Just checked this isn't trying to grow - unsafe { self.shrink_unchecked(cap) } + unsafe { self.shrink_unchecked(cap, elem_layout) } } /// `shrink`, but without the capacity check. @@ -529,23 +689,27 @@ impl RawVec { /// # Safety /// `cap <= self.capacity()` #[cfg(not(no_global_oom_handling))] - unsafe fn shrink_unchecked(&mut self, cap: usize) -> Result<(), TryReserveError> { - let (ptr, layout) = if let Some(mem) = self.current_memory() { mem } else { return Ok(()) }; - // See current_memory() why this assert is here - const { assert!(mem::size_of::() % mem::align_of::() == 0) }; + unsafe fn shrink_unchecked( + &mut self, + cap: usize, + elem_layout: Layout, + ) -> Result<(), TryReserveError> { + let (ptr, layout) = + if let Some(mem) = self.current_memory(elem_layout) { mem } else { return Ok(()) }; // If shrinking to 0, deallocate the buffer. We don't reach this point // for the T::IS_ZST case since current_memory() will have returned // None. if cap == 0 { unsafe { self.alloc.deallocate(ptr, layout) }; - self.ptr = Unique::dangling(); + self.ptr = + unsafe { Unique::new_unchecked(ptr::without_provenance_mut(elem_layout.align())) }; self.cap = Cap::ZERO; } else { let ptr = unsafe { - // `Layout::array` cannot overflow here because it would have + // Layout cannot overflow here because it would have // overflowed earlier when capacity was larger. - let new_size = mem::size_of::().unchecked_mul(cap); + let new_size = elem_layout.size().unchecked_mul(cap); let new_layout = Layout::from_size_align_unchecked(new_size, layout.align()); self.alloc .shrink(ptr, layout, new_layout) @@ -558,24 +722,32 @@ impl RawVec { } Ok(()) } + + /// # Safety + /// + /// This function deallocates the owned allocation, but does not update `ptr` or `cap` to + /// prevent double-free or use-after-free. Essentially, do not do anything with the caller + /// after this function returns. + /// Ideally this function would take `self` by move, but it cannot because it exists to be + /// called from a `Drop` impl. + unsafe fn deallocate(&mut self, elem_layout: Layout) { + if let Some((ptr, layout)) = self.current_memory(elem_layout) { + unsafe { + self.alloc.deallocate(ptr, layout); + } + } + } } -// This function is outside `RawVec` to minimize compile times. See the comment -// above `RawVec::grow_amortized` for details. (The `A` parameter isn't -// significant, because the number of different `A` types seen in practice is -// much smaller than the number of `T` types.) #[inline(never)] fn finish_grow( - new_layout: Result, + new_layout: Layout, current_memory: Option<(NonNull, Layout)>, alloc: &mut A, ) -> Result, TryReserveError> where A: Allocator, { - // Check for the error here to minimize the size of `RawVec::grow_*`. - let new_layout = new_layout.map_err(|_| CapacityOverflow)?; - alloc_guard(new_layout.size())?; let memory = if let Some((ptr, old_layout)) = current_memory { @@ -592,15 +764,6 @@ where memory.map_err(|_| AllocError { layout: new_layout, non_exhaustive: () }.into()) } -unsafe impl<#[may_dangle] T, A: Allocator> Drop for RawVec { - /// Frees the memory owned by the `RawVec` *without* trying to drop its contents. - fn drop(&mut self) { - if let Some((ptr, layout)) = self.current_memory() { - unsafe { self.alloc.deallocate(ptr, layout) } - } - } -} - // Central function for reserve error handling. #[cfg(not(no_global_oom_handling))] #[cold] @@ -627,3 +790,8 @@ fn alloc_guard(alloc_size: usize) -> Result<(), TryReserveError> { Ok(()) } } + +#[inline] +fn layout_array(cap: usize, elem_layout: Layout) -> Result { + elem_layout.repeat(cap).map(|(layout, _pad)| layout).map_err(|_| CapacityOverflow.into()) +} diff --git a/library/alloc/src/raw_vec/tests.rs b/library/alloc/src/raw_vec/tests.rs index 48c6e5f46f8db..d78ded104fb09 100644 --- a/library/alloc/src/raw_vec/tests.rs +++ b/library/alloc/src/raw_vec/tests.rs @@ -43,9 +43,9 @@ fn allocator_param() { let a = BoundedAlloc { fuel: Cell::new(500) }; let mut v: RawVec = RawVec::with_capacity_in(50, a); - assert_eq!(v.alloc.fuel.get(), 450); + assert_eq!(v.inner.alloc.fuel.get(), 450); v.reserve(50, 150); // (causes a realloc, thus using 50 + 150 = 200 units of fuel) - assert_eq!(v.alloc.fuel.get(), 250); + assert_eq!(v.inner.alloc.fuel.get(), 250); } #[test] @@ -86,7 +86,7 @@ struct ZST; fn zst_sanity(v: &RawVec) { assert_eq!(v.capacity(), usize::MAX); assert_eq!(v.ptr(), core::ptr::Unique::::dangling().as_ptr()); - assert_eq!(v.current_memory(), None); + assert_eq!(v.inner.current_memory(T::LAYOUT), None); } #[test] @@ -106,22 +106,11 @@ fn zst() { let v: RawVec = RawVec::with_capacity_in(100, Global); zst_sanity(&v); - let v: RawVec = RawVec::try_allocate_in(0, AllocInit::Uninitialized, Global).unwrap(); - zst_sanity(&v); - - let v: RawVec = RawVec::try_allocate_in(100, AllocInit::Uninitialized, Global).unwrap(); - zst_sanity(&v); - - let mut v: RawVec = - RawVec::try_allocate_in(usize::MAX, AllocInit::Uninitialized, Global).unwrap(); + let mut v: RawVec = RawVec::with_capacity_in(usize::MAX, Global); zst_sanity(&v); // Check all these operations work as expected with zero-sized elements. - assert!(!v.needs_to_grow(100, usize::MAX - 100)); - assert!(v.needs_to_grow(101, usize::MAX - 100)); - zst_sanity(&v); - v.reserve(100, usize::MAX - 100); //v.reserve(101, usize::MAX - 100); // panics, in `zst_reserve_panic` below zst_sanity(&v); @@ -138,12 +127,12 @@ fn zst() { assert_eq!(v.try_reserve_exact(101, usize::MAX - 100), cap_err); zst_sanity(&v); - assert_eq!(v.grow_amortized(100, usize::MAX - 100), cap_err); - assert_eq!(v.grow_amortized(101, usize::MAX - 100), cap_err); + assert_eq!(v.inner.grow_amortized(100, usize::MAX - 100, ZST::LAYOUT), cap_err); + assert_eq!(v.inner.grow_amortized(101, usize::MAX - 100, ZST::LAYOUT), cap_err); zst_sanity(&v); - assert_eq!(v.grow_exact(100, usize::MAX - 100), cap_err); - assert_eq!(v.grow_exact(101, usize::MAX - 100), cap_err); + assert_eq!(v.inner.grow_exact(100, usize::MAX - 100, ZST::LAYOUT), cap_err); + assert_eq!(v.inner.grow_exact(101, usize::MAX - 100, ZST::LAYOUT), cap_err); zst_sanity(&v); } diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index ea2dcdce6e89e..7a9ca4011be84 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -5,6 +5,7 @@ #![stable(feature = "rust1", since = "1.0.0")] +use crate::alloc::Layout; use crate::marker::DiscriminantKind; use crate::{clone, cmp, fmt, hash, intrinsics, ptr}; @@ -1238,6 +1239,10 @@ pub trait SizedTypeProperties: Sized { #[doc(hidden)] #[unstable(feature = "sized_type_properties", issue = "none")] const IS_ZST: bool = size_of::() == 0; + + #[doc(hidden)] + #[unstable(feature = "sized_type_properties", issue = "none")] + const LAYOUT: Layout = Layout::new::(); } #[doc(hidden)] #[unstable(feature = "sized_type_properties", issue = "none")] diff --git a/src/etc/gdb_providers.py b/src/etc/gdb_providers.py index 227695cdadd58..e8f9dee07d3e9 100644 --- a/src/etc/gdb_providers.py +++ b/src/etc/gdb_providers.py @@ -56,7 +56,7 @@ def __init__(self, valobj): self._valobj = valobj vec = valobj["vec"] self._length = int(vec["len"]) - self._data_ptr = unwrap_unique_or_non_null(vec["buf"]["ptr"]) + self._data_ptr = unwrap_unique_or_non_null(vec["buf"]["inner"]["ptr"]) def to_string(self): return self._data_ptr.lazy_string(encoding="utf-8", length=self._length) @@ -74,7 +74,7 @@ def __init__(self, valobj): vec = buf[ZERO_FIELD] if is_windows else buf self._length = int(vec["len"]) - self._data_ptr = unwrap_unique_or_non_null(vec["buf"]["ptr"]) + self._data_ptr = unwrap_unique_or_non_null(vec["buf"]["inner"]["ptr"]) def to_string(self): return self._data_ptr.lazy_string(encoding="utf-8", length=self._length) @@ -96,6 +96,7 @@ def to_string(self): def display_hint(): return "string" + def _enumerate_array_elements(element_ptrs): for (i, element_ptr) in enumerate(element_ptrs): key = "[{}]".format(i) @@ -112,6 +113,7 @@ def _enumerate_array_elements(element_ptrs): yield key, element + class StdSliceProvider(printer_base): def __init__(self, valobj): self._valobj = valobj @@ -130,11 +132,14 @@ def children(self): def display_hint(): return "array" + class StdVecProvider(printer_base): def __init__(self, valobj): self._valobj = valobj self._length = int(valobj["len"]) - self._data_ptr = unwrap_unique_or_non_null(valobj["buf"]["ptr"]) + self._data_ptr = unwrap_unique_or_non_null(valobj["buf"]["inner"]["ptr"]) + ptr_ty = gdb.Type.pointer(valobj.type.template_argument(0)) + self._data_ptr = self._data_ptr.reinterpret_cast(ptr_ty) def to_string(self): return "Vec(size={})".format(self._length) @@ -155,11 +160,13 @@ def __init__(self, valobj): self._head = int(valobj["head"]) self._size = int(valobj["len"]) # BACKCOMPAT: rust 1.75 - cap = valobj["buf"]["cap"] + cap = valobj["buf"]["inner"]["cap"] if cap.type.code != gdb.TYPE_CODE_INT: cap = cap[ZERO_FIELD] self._cap = int(cap) - self._data_ptr = unwrap_unique_or_non_null(valobj["buf"]["ptr"]) + self._data_ptr = unwrap_unique_or_non_null(valobj["buf"]["inner"]["ptr"]) + ptr_ty = gdb.Type.pointer(valobj.type.template_argument(0)) + self._data_ptr = self._data_ptr.reinterpret_cast(ptr_ty) def to_string(self): return "VecDeque(size={})".format(self._size) diff --git a/tests/debuginfo/strings-and-strs.rs b/tests/debuginfo/strings-and-strs.rs index 4a6adc2fc5331..2d29ac12bd8a0 100644 --- a/tests/debuginfo/strings-and-strs.rs +++ b/tests/debuginfo/strings-and-strs.rs @@ -7,7 +7,7 @@ // gdb-command:run // gdb-command:print plain_string -// gdbr-check:$1 = alloc::string::String {vec: alloc::vec::Vec {buf: alloc::raw_vec::RawVec {ptr: core::ptr::unique::Unique {pointer: core::ptr::non_null::NonNull {pointer: 0x[...]}, _marker: core::marker::PhantomData}, cap: alloc::raw_vec::Cap (5), alloc: alloc::alloc::Global}, len: 5}} +// gdbr-check:$1 = alloc::string::String {vec: alloc::vec::Vec {buf: alloc::raw_vec::RawVec {inner: alloc::raw_vec::RawVecInner {ptr: core::ptr::unique::Unique {pointer: core::ptr::non_null::NonNull {pointer: 0x[...]}, _marker: core::marker::PhantomData}, cap: alloc::raw_vec::Cap (5), alloc: alloc::alloc::Global}, _marker: core::marker::PhantomData}, len: 5}} // gdb-command:print plain_str // gdbr-check:$2 = "Hello" diff --git a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir index 14ad951a47662..0fe4fd3707221 100644 --- a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir @@ -5,63 +5,93 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { let mut _0: &[u8]; scope 1 (inlined as Deref>::deref) { debug self => _1; - let mut _4: *const u8; - let mut _5: usize; + let mut _7: usize; scope 2 (inlined Vec::::as_ptr) { debug self => _1; let mut _2: &alloc::raw_vec::RawVec; scope 3 (inlined alloc::raw_vec::RawVec::::ptr) { debug self => _2; - let mut _3: std::ptr::NonNull; - scope 4 (inlined Unique::::as_ptr) { - debug ((self: Unique).0: std::ptr::NonNull) => _3; - debug ((self: Unique).1: std::marker::PhantomData) => const PhantomData::; - scope 5 (inlined NonNull::::as_ptr) { + let mut _3: &alloc::raw_vec::RawVecInner; + scope 4 (inlined alloc::raw_vec::RawVecInner::ptr::) { + debug self => _3; + let mut _6: std::ptr::NonNull; + scope 5 (inlined alloc::raw_vec::RawVecInner::non_null::) { debug self => _3; + let mut _4: std::ptr::NonNull; + scope 6 (inlined Unique::::cast::) { + debug ((self: Unique).0: std::ptr::NonNull) => _4; + debug ((self: Unique).1: std::marker::PhantomData) => const PhantomData::; + scope 7 (inlined NonNull::::cast::) { + debug self => _4; + scope 8 (inlined NonNull::::as_ptr) { + debug self => _4; + let mut _5: *const u8; + } + } + } + scope 9 (inlined #[track_caller] as Into>>::into) { + debug ((self: Unique).0: std::ptr::NonNull) => _6; + debug ((self: Unique).1: std::marker::PhantomData) => const PhantomData::; + scope 10 (inlined as From>>::from) { + debug ((unique: Unique).0: std::ptr::NonNull) => _6; + debug ((unique: Unique).1: std::marker::PhantomData) => const PhantomData::; + scope 11 (inlined Unique::::as_non_null_ptr) { + debug ((self: Unique).0: std::ptr::NonNull) => _6; + debug ((self: Unique).1: std::marker::PhantomData) => const PhantomData::; + } + } + } + } + scope 12 (inlined NonNull::::as_ptr) { + debug self => _6; } } } } - scope 6 (inlined std::slice::from_raw_parts::<'_, u8>) { - debug data => _4; - debug len => _5; - let _6: *const [u8]; - scope 7 (inlined core::ub_checks::check_language_ub) { - scope 8 (inlined core::ub_checks::check_language_ub::runtime) { + scope 13 (inlined std::slice::from_raw_parts::<'_, u8>) { + debug data => _5; + debug len => _7; + let _8: *const [u8]; + scope 14 (inlined core::ub_checks::check_language_ub) { + scope 15 (inlined core::ub_checks::check_language_ub::runtime) { } } - scope 9 (inlined std::mem::size_of::) { + scope 16 (inlined std::mem::size_of::) { } - scope 10 (inlined align_of::) { + scope 17 (inlined align_of::) { } - scope 11 (inlined slice_from_raw_parts::) { - debug data => _4; - debug len => _5; - scope 12 (inlined std::ptr::from_raw_parts::<[u8], u8>) { - debug data_pointer => _4; - debug metadata => _5; + scope 18 (inlined slice_from_raw_parts::) { + debug data => _5; + debug len => _7; + scope 19 (inlined std::ptr::from_raw_parts::<[u8], u8>) { + debug data_pointer => _5; + debug metadata => _7; } } } } bb0: { - StorageLive(_4); StorageLive(_2); _2 = &((*_1).0: alloc::raw_vec::RawVec); StorageLive(_3); - _3 = ((((*_1).0: alloc::raw_vec::RawVec).0: std::ptr::Unique).0: std::ptr::NonNull); - _4 = (_3.0: *const u8); - StorageDead(_3); - StorageDead(_2); - StorageLive(_5); - _5 = ((*_1).1: usize); + _3 = &(((*_1).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner); StorageLive(_6); - _6 = *const [u8] from (_4, _5); - _0 = &(*_6); - StorageDead(_6); - StorageDead(_5); + StorageLive(_4); + _4 = (((((*_1).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique).0: std::ptr::NonNull); + _5 = (_4.0: *const u8); + _6 = NonNull:: { pointer: _5 }; StorageDead(_4); + StorageDead(_6); + StorageDead(_3); + StorageDead(_2); + StorageLive(_7); + _7 = ((*_1).1: usize); + StorageLive(_8); + _8 = *const [u8] from (_5, _7); + _0 = &(*_8); + StorageDead(_8); + StorageDead(_7); return; } } diff --git a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir index 14ad951a47662..0fe4fd3707221 100644 --- a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir @@ -5,63 +5,93 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { let mut _0: &[u8]; scope 1 (inlined as Deref>::deref) { debug self => _1; - let mut _4: *const u8; - let mut _5: usize; + let mut _7: usize; scope 2 (inlined Vec::::as_ptr) { debug self => _1; let mut _2: &alloc::raw_vec::RawVec; scope 3 (inlined alloc::raw_vec::RawVec::::ptr) { debug self => _2; - let mut _3: std::ptr::NonNull; - scope 4 (inlined Unique::::as_ptr) { - debug ((self: Unique).0: std::ptr::NonNull) => _3; - debug ((self: Unique).1: std::marker::PhantomData) => const PhantomData::; - scope 5 (inlined NonNull::::as_ptr) { + let mut _3: &alloc::raw_vec::RawVecInner; + scope 4 (inlined alloc::raw_vec::RawVecInner::ptr::) { + debug self => _3; + let mut _6: std::ptr::NonNull; + scope 5 (inlined alloc::raw_vec::RawVecInner::non_null::) { debug self => _3; + let mut _4: std::ptr::NonNull; + scope 6 (inlined Unique::::cast::) { + debug ((self: Unique).0: std::ptr::NonNull) => _4; + debug ((self: Unique).1: std::marker::PhantomData) => const PhantomData::; + scope 7 (inlined NonNull::::cast::) { + debug self => _4; + scope 8 (inlined NonNull::::as_ptr) { + debug self => _4; + let mut _5: *const u8; + } + } + } + scope 9 (inlined #[track_caller] as Into>>::into) { + debug ((self: Unique).0: std::ptr::NonNull) => _6; + debug ((self: Unique).1: std::marker::PhantomData) => const PhantomData::; + scope 10 (inlined as From>>::from) { + debug ((unique: Unique).0: std::ptr::NonNull) => _6; + debug ((unique: Unique).1: std::marker::PhantomData) => const PhantomData::; + scope 11 (inlined Unique::::as_non_null_ptr) { + debug ((self: Unique).0: std::ptr::NonNull) => _6; + debug ((self: Unique).1: std::marker::PhantomData) => const PhantomData::; + } + } + } + } + scope 12 (inlined NonNull::::as_ptr) { + debug self => _6; } } } } - scope 6 (inlined std::slice::from_raw_parts::<'_, u8>) { - debug data => _4; - debug len => _5; - let _6: *const [u8]; - scope 7 (inlined core::ub_checks::check_language_ub) { - scope 8 (inlined core::ub_checks::check_language_ub::runtime) { + scope 13 (inlined std::slice::from_raw_parts::<'_, u8>) { + debug data => _5; + debug len => _7; + let _8: *const [u8]; + scope 14 (inlined core::ub_checks::check_language_ub) { + scope 15 (inlined core::ub_checks::check_language_ub::runtime) { } } - scope 9 (inlined std::mem::size_of::) { + scope 16 (inlined std::mem::size_of::) { } - scope 10 (inlined align_of::) { + scope 17 (inlined align_of::) { } - scope 11 (inlined slice_from_raw_parts::) { - debug data => _4; - debug len => _5; - scope 12 (inlined std::ptr::from_raw_parts::<[u8], u8>) { - debug data_pointer => _4; - debug metadata => _5; + scope 18 (inlined slice_from_raw_parts::) { + debug data => _5; + debug len => _7; + scope 19 (inlined std::ptr::from_raw_parts::<[u8], u8>) { + debug data_pointer => _5; + debug metadata => _7; } } } } bb0: { - StorageLive(_4); StorageLive(_2); _2 = &((*_1).0: alloc::raw_vec::RawVec); StorageLive(_3); - _3 = ((((*_1).0: alloc::raw_vec::RawVec).0: std::ptr::Unique).0: std::ptr::NonNull); - _4 = (_3.0: *const u8); - StorageDead(_3); - StorageDead(_2); - StorageLive(_5); - _5 = ((*_1).1: usize); + _3 = &(((*_1).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner); StorageLive(_6); - _6 = *const [u8] from (_4, _5); - _0 = &(*_6); - StorageDead(_6); - StorageDead(_5); + StorageLive(_4); + _4 = (((((*_1).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique).0: std::ptr::NonNull); + _5 = (_4.0: *const u8); + _6 = NonNull:: { pointer: _5 }; StorageDead(_4); + StorageDead(_6); + StorageDead(_3); + StorageDead(_2); + StorageLive(_7); + _7 = ((*_1).1: usize); + StorageLive(_8); + _8 = *const [u8] from (_5, _7); + _0 = &(*_8); + StorageDead(_8); + StorageDead(_7); return; } } From bd8e29c45c35af5d30622cd14f47c6c3aca6e257 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Thu, 11 Jul 2024 19:41:48 -0400 Subject: [PATCH 707/786] Paper over the clippy ICE --- .../clippy/tests/ui/borrow_interior_mutable_const/others.rs | 3 +-- .../tests/ui/borrow_interior_mutable_const/others.stderr | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.rs b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.rs index 0ea93dd84625c..452d1b198133e 100644 --- a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.rs +++ b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.rs @@ -10,7 +10,7 @@ use std::sync::Once; const ATOMIC: AtomicUsize = AtomicUsize::new(5); const CELL: Cell = Cell::new(6); -const ATOMIC_TUPLE: ([AtomicUsize; 1], Vec, u8) = ([ATOMIC], Vec::new(), 7); +const ATOMIC_TUPLE: ([AtomicUsize; 1], Option>, u8) = ([ATOMIC], None, 7); const INTEGER: u8 = 8; const STRING: String = String::new(); const STR: &str = "012345"; @@ -74,7 +74,6 @@ fn main() { let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR: interior mutability let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR: interior mutability let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR: interior mutability - let _ = &*ATOMIC_TUPLE.1; let _ = &ATOMIC_TUPLE.2; let _ = (&&&&ATOMIC_TUPLE).0; let _ = (&&&&ATOMIC_TUPLE).2; diff --git a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.stderr b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.stderr index 33c774667f942..9a9028c864986 100644 --- a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.stderr +++ b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.stderr @@ -92,7 +92,7 @@ LL | let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> tests/ui/borrow_interior_mutable_const/others.rs:82:13 + --> tests/ui/borrow_interior_mutable_const/others.rs:81:13 | LL | let _ = ATOMIC_TUPLE.0[0]; | ^^^^^^^^^^^^ @@ -100,7 +100,7 @@ LL | let _ = ATOMIC_TUPLE.0[0]; = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> tests/ui/borrow_interior_mutable_const/others.rs:87:5 + --> tests/ui/borrow_interior_mutable_const/others.rs:86:5 | LL | CELL.set(2); | ^^^^ @@ -108,7 +108,7 @@ LL | CELL.set(2); = help: assign this const to a local or static variable, and use the variable here error: a `const` item with interior mutability should not be borrowed - --> tests/ui/borrow_interior_mutable_const/others.rs:88:16 + --> tests/ui/borrow_interior_mutable_const/others.rs:87:16 | LL | assert_eq!(CELL.get(), 6); | ^^^^ From d5b55436e9644e0dc5fce70fe0fe84c3995a8b09 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Mon, 29 Jul 2024 19:22:48 -0400 Subject: [PATCH 708/786] Bless Miri --- .../miri/tests/pass/tree_borrows/vec_unique.uniq.stderr | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/tools/miri/tests/pass/tree_borrows/vec_unique.uniq.stderr b/src/tools/miri/tests/pass/tree_borrows/vec_unique.uniq.stderr index 7942e9884f401..e3796a742e9ae 100644 --- a/src/tools/miri/tests/pass/tree_borrows/vec_unique.uniq.stderr +++ b/src/tools/miri/tests/pass/tree_borrows/vec_unique.uniq.stderr @@ -2,7 +2,9 @@ Warning: this tree is indicative only. Some tags may have been hidden. 0.. 2 | Act | └─┬── -|-----| └─┬── -|-----| └─┬── -|-----| └──── +|-----| ├──── +|-----| ├──── +|-----| └─┬── +|-----| ├──── +|-----| └──── ────────────────────────────────────────────────── From 4e98bc673013aa1124c948a52b8259ca11d81fa3 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Mon, 29 Jul 2024 22:50:22 -0400 Subject: [PATCH 709/786] Hoist IS_ZST check out of RawVecInner::from_*_in --- library/alloc/src/raw_vec.rs | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 8bcb12b3bc770..151358a07c986 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -40,6 +40,13 @@ struct Cap(usize); impl Cap { const ZERO: Cap = unsafe { Cap(0) }; + + /// `Cap(cap)`, except if `T` is a ZST then `Cap::ZERO`. + /// + /// # Safety: cap must be <= `isize::MAX`. + unsafe fn new(cap: usize) -> Self { + if T::IS_ZST { Cap::ZERO } else { unsafe { Self(cap) } } + } } /// A low-level utility for more ergonomically allocating, reallocating, and deallocating @@ -258,6 +265,8 @@ impl RawVec { pub unsafe fn from_raw_parts_in(ptr: *mut T, capacity: usize, alloc: A) -> Self { // SAFETY: Precondition passed to the caller unsafe { + let ptr = ptr.cast(); + let capacity = Cap::new::(capacity); Self { inner: RawVecInner::from_raw_parts_in(ptr, capacity, alloc), _marker: PhantomData, @@ -274,6 +283,8 @@ impl RawVec { pub unsafe fn from_nonnull_in(ptr: NonNull, capacity: usize, alloc: A) -> Self { // SAFETY: Precondition passed to the caller unsafe { + let ptr = ptr.cast(); + let capacity = Cap::new::(capacity); Self { inner: RawVecInner::from_nonnull_in(ptr, capacity, alloc), _marker: PhantomData } } } @@ -474,15 +485,13 @@ impl RawVecInner { } #[inline] - unsafe fn from_raw_parts_in(ptr: *mut T, capacity: usize, alloc: A) -> Self { - let cap = if T::IS_ZST { Cap::ZERO } else { unsafe { Cap(capacity) } }; - Self { ptr: unsafe { Unique::new_unchecked(ptr.cast()) }, cap, alloc } + unsafe fn from_raw_parts_in(ptr: *mut u8, cap: Cap, alloc: A) -> Self { + Self { ptr: unsafe { Unique::new_unchecked(ptr) }, cap, alloc } } #[inline] - unsafe fn from_nonnull_in(ptr: NonNull, capacity: usize, alloc: A) -> Self { - let cap = if T::IS_ZST { Cap::ZERO } else { unsafe { Cap(capacity) } }; - Self { ptr: Unique::from(ptr.cast()), cap, alloc } + unsafe fn from_nonnull_in(ptr: NonNull, cap: Cap, alloc: A) -> Self { + Self { ptr: Unique::from(ptr), cap, alloc } } #[inline] From b44b367232ee0f1c8c4419ad6cae73f0815e9421 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Tue, 30 Jul 2024 17:44:26 -0400 Subject: [PATCH 710/786] Add a FIXME to the changed Miri test --- src/tools/miri/tests/pass/tree_borrows/vec_unique.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tools/miri/tests/pass/tree_borrows/vec_unique.rs b/src/tools/miri/tests/pass/tree_borrows/vec_unique.rs index 05090d685ab2e..9debe224d4583 100644 --- a/src/tools/miri/tests/pass/tree_borrows/vec_unique.rs +++ b/src/tools/miri/tests/pass/tree_borrows/vec_unique.rs @@ -1,3 +1,5 @@ +// FIXME: This test is broken since https://github.com/rust-lang/rust/pull/126793, +// possibly related to the additional struct between Vec and Unique. //@revisions: default uniq // We disable the GC for this test because it would change what is printed. //@compile-flags: -Zmiri-tree-borrows -Zmiri-provenance-gc=0 From da15248d26076fe3a6482dd1e25c54c2cc1ef577 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sat, 3 Aug 2024 14:48:33 -0400 Subject: [PATCH 711/786] Add an optimizer hint for the capacity that with_capacity_in returns --- library/alloc/src/raw_vec.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 151358a07c986..9c8fa7ceff4e5 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -423,7 +423,13 @@ impl RawVecInner { #[inline] fn with_capacity_in(capacity: usize, alloc: A, elem_layout: Layout) -> Self { match Self::try_allocate_in(capacity, AllocInit::Uninitialized, alloc, elem_layout) { - Ok(res) => res, + Ok(this) => { + unsafe { + // Make it more obvious that a subsquent Vec::reserve(capacity) will not allocate. + hint::assert_unchecked(!this.needs_to_grow(0, capacity, elem_layout)); + } + this + } Err(err) => handle_error(err), } } From 860c8cdeafb6cad648c5b3cfd79ea07be28b097b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 10 Aug 2024 00:54:16 +0000 Subject: [PATCH 712/786] Differentiate between methods and associated functions Accurately refer to assoc fn without receiver as assoc fn instead of methods. Add `AssocItem::descr` method to centralize where we call methods and associated functions. --- .../src/check/compare_impl_item.rs | 14 +++----------- compiler/rustc_middle/src/hir/map/mod.rs | 18 ++++++++++++------ compiler/rustc_middle/src/ty/assoc.rs | 9 +++++++++ .../async-await/in-trait/generics-mismatch.rs | 2 +- .../in-trait/generics-mismatch.stderr | 2 +- .../mismatched_ty_const_in_trait_impl.rs | 10 +++++----- .../mismatched_ty_const_in_trait_impl.stderr | 10 +++++----- tests/ui/delegation/not-supported.rs | 2 +- tests/ui/delegation/not-supported.stderr | 6 +++--- tests/ui/error-codes/E0049.stderr | 4 ++-- tests/ui/error-codes/E0195.rs | 4 ++-- tests/ui/error-codes/E0195.stderr | 6 +++--- .../gat-trait-path-missing-lifetime.rs | 2 +- .../gat-trait-path-missing-lifetime.stderr | 2 +- .../in-trait/trait-more-generics-than-impl.rs | 2 +- .../trait-more-generics-than-impl.stderr | 2 +- .../const-drop.precise.stderr | 4 ++-- .../const-drop.stock.stderr | 4 ++-- ...lt-bound-non-const-specialized-bound.stderr | 6 +++--- .../const-default-const-specialized.stderr | 4 ++-- .../specialization/default-keyword.stderr | 2 +- ...ssue-95186-specialize-on-tilde-const.stderr | 8 ++++---- ...same-trait-bound-different-constness.stderr | 8 ++++---- .../non-const-default-const-specialized.stderr | 4 ++-- .../specializing-constness-2.stderr | 4 ++-- .../ui/specialization/const_trait_impl.stderr | 10 +++++----- tests/ui/typeck/issue-36708.stderr | 2 +- 27 files changed, 79 insertions(+), 72 deletions(-) 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 53cde14f337be..35577613800b2 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -1117,7 +1117,7 @@ fn check_region_bounds_on_impl_item<'tcx>( .dcx() .create_err(LifetimesOrBoundsMismatchOnTrait { span, - item_kind: assoc_item_kind_str(&impl_m), + item_kind: impl_m.descr(), ident: impl_m.ident(tcx), generics_span, bounds_span, @@ -1294,7 +1294,7 @@ fn compare_number_of_generics<'tcx>( ("const", trait_own_counts.consts, impl_own_counts.consts), ]; - let item_kind = assoc_item_kind_str(&impl_); + let item_kind = impl_.descr(); let mut err_occurred = None; for (kind, trait_count, impl_count) in matchings { @@ -1676,7 +1676,7 @@ fn compare_generic_param_kinds<'tcx>( param_impl_span, E0053, "{} `{}` has an incompatible generic parameter for trait `{}`", - assoc_item_kind_str(&impl_item), + impl_item.descr(), trait_item.name, &tcx.def_path_str(tcx.parent(trait_item.def_id)) ); @@ -2249,14 +2249,6 @@ fn param_env_with_gat_bounds<'tcx>( ty::ParamEnv::new(tcx.mk_clauses(&predicates), Reveal::UserFacing) } -fn assoc_item_kind_str(impl_item: &ty::AssocItem) -> &'static str { - match impl_item.kind { - ty::AssocKind::Const => "const", - ty::AssocKind::Fn => "method", - ty::AssocKind::Type => "type", - } -} - /// Manually check here that `async fn foo()` wasn't matched against `fn foo()`, /// and extract a better error if so. fn try_report_async_mismatch<'tcx>( diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 4c243e6330b91..edab6b5ebde84 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -1165,17 +1165,23 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { } Node::ImplItem(ii) => { let kind = match ii.kind { - ImplItemKind::Const(..) => "assoc const", - ImplItemKind::Fn(..) => "method", - ImplItemKind::Type(_) => "assoc type", + ImplItemKind::Const(..) => "associated constant", + ImplItemKind::Fn(fn_sig, _) => match fn_sig.decl.implicit_self { + ImplicitSelfKind::None => "associated function", + _ => "method", + }, + ImplItemKind::Type(_) => "associated type", }; format!("{id} ({kind} `{}` in {})", ii.ident, path_str(ii.owner_id.def_id)) } Node::TraitItem(ti) => { let kind = match ti.kind { - TraitItemKind::Const(..) => "assoc constant", - TraitItemKind::Fn(..) => "trait method", - TraitItemKind::Type(..) => "assoc type", + TraitItemKind::Const(..) => "associated constant", + TraitItemKind::Fn(fn_sig, _) => match fn_sig.decl.implicit_self { + ImplicitSelfKind::None => "associated function", + _ => "trait method", + }, + TraitItemKind::Type(..) => "associated type", }; format!("{id} ({kind} `{}` in {})", ti.ident, path_str(ti.owner_id.def_id)) diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs index 0ce5c613c4ce3..db56e0016a2d6 100644 --- a/compiler/rustc_middle/src/ty/assoc.rs +++ b/compiler/rustc_middle/src/ty/assoc.rs @@ -98,6 +98,15 @@ impl AssocItem { } } + pub fn descr(&self) -> &'static str { + match self.kind { + ty::AssocKind::Const => "const", + ty::AssocKind::Fn if self.fn_has_self_parameter => "method", + ty::AssocKind::Fn => "associated function", + ty::AssocKind::Type => "type", + } + } + pub fn is_impl_trait_in_trait(&self) -> bool { self.opt_rpitit_info.is_some() } diff --git a/tests/ui/async-await/in-trait/generics-mismatch.rs b/tests/ui/async-await/in-trait/generics-mismatch.rs index d3d1284982a95..a5c81a9299810 100644 --- a/tests/ui/async-await/in-trait/generics-mismatch.rs +++ b/tests/ui/async-await/in-trait/generics-mismatch.rs @@ -6,7 +6,7 @@ trait Foo { impl Foo for () { async fn foo() {} - //~^ ERROR: method `foo` has an incompatible generic parameter for trait `Foo` [E0053] + //~^ ERROR: associated function `foo` has an incompatible generic parameter for trait `Foo` [E0053] } fn main() {} diff --git a/tests/ui/async-await/in-trait/generics-mismatch.stderr b/tests/ui/async-await/in-trait/generics-mismatch.stderr index c0357dc7f3e64..cb0f95e8d098b 100644 --- a/tests/ui/async-await/in-trait/generics-mismatch.stderr +++ b/tests/ui/async-await/in-trait/generics-mismatch.stderr @@ -1,4 +1,4 @@ -error[E0053]: method `foo` has an incompatible generic parameter for trait `Foo` +error[E0053]: associated function `foo` has an incompatible generic parameter for trait `Foo` --> $DIR/generics-mismatch.rs:8:18 | LL | trait Foo { diff --git a/tests/ui/const-generics/defaults/mismatched_ty_const_in_trait_impl.rs b/tests/ui/const-generics/defaults/mismatched_ty_const_in_trait_impl.rs index 5c9323261a973..9eb33acbb24d1 100644 --- a/tests/ui/const-generics/defaults/mismatched_ty_const_in_trait_impl.rs +++ b/tests/ui/const-generics/defaults/mismatched_ty_const_in_trait_impl.rs @@ -3,7 +3,7 @@ trait Trait { } impl Trait for () { fn foo() {} - //~^ error: method `foo` has an incompatible generic parameter for trait + //~^ error: associated function `foo` has an incompatible generic parameter for trait } trait Other { @@ -11,7 +11,7 @@ trait Other { } impl Other for () { fn bar() {} - //~^ error: method `bar` has an incompatible generic parameter for trait + //~^ error: associated function `bar` has an incompatible generic parameter for trait } trait Uwu { @@ -19,7 +19,7 @@ trait Uwu { } impl Uwu for () { fn baz() {} - //~^ error: method `baz` has an incompatible generic parameter for trait + //~^ error: associated function `baz` has an incompatible generic parameter for trait } trait Aaaaaa { @@ -27,7 +27,7 @@ trait Aaaaaa { } impl Aaaaaa for () { fn bbbb() {} - //~^ error: method `bbbb` has an incompatible generic parameter for trait + //~^ error: associated function `bbbb` has an incompatible generic parameter for trait } trait Names { @@ -35,7 +35,7 @@ trait Names { } impl Names for () { fn abcd() {} - //~^ error: method `abcd` has an incompatible generic parameter for trait + //~^ error: associated function `abcd` has an incompatible generic parameter for trait } fn main() {} diff --git a/tests/ui/const-generics/defaults/mismatched_ty_const_in_trait_impl.stderr b/tests/ui/const-generics/defaults/mismatched_ty_const_in_trait_impl.stderr index 3455f2c8ea97b..7ec162e1c295c 100644 --- a/tests/ui/const-generics/defaults/mismatched_ty_const_in_trait_impl.stderr +++ b/tests/ui/const-generics/defaults/mismatched_ty_const_in_trait_impl.stderr @@ -1,4 +1,4 @@ -error[E0053]: method `foo` has an incompatible generic parameter for trait `Trait` +error[E0053]: associated function `foo` has an incompatible generic parameter for trait `Trait` --> $DIR/mismatched_ty_const_in_trait_impl.rs:5:12 | LL | trait Trait { @@ -11,7 +11,7 @@ LL | impl Trait for () { LL | fn foo() {} | ^^^^^^^^^^^^ found const parameter of type `u64` -error[E0053]: method `bar` has an incompatible generic parameter for trait `Other` +error[E0053]: associated function `bar` has an incompatible generic parameter for trait `Other` --> $DIR/mismatched_ty_const_in_trait_impl.rs:13:12 | LL | trait Other { @@ -24,7 +24,7 @@ LL | impl Other for () { LL | fn bar() {} | ^ found type parameter -error[E0053]: method `baz` has an incompatible generic parameter for trait `Uwu` +error[E0053]: associated function `baz` has an incompatible generic parameter for trait `Uwu` --> $DIR/mismatched_ty_const_in_trait_impl.rs:21:12 | LL | trait Uwu { @@ -37,7 +37,7 @@ LL | impl Uwu for () { LL | fn baz() {} | ^^^^^^^^^^^^ found const parameter of type `i32` -error[E0053]: method `bbbb` has an incompatible generic parameter for trait `Aaaaaa` +error[E0053]: associated function `bbbb` has an incompatible generic parameter for trait `Aaaaaa` --> $DIR/mismatched_ty_const_in_trait_impl.rs:29:13 | LL | trait Aaaaaa { @@ -50,7 +50,7 @@ LL | impl Aaaaaa for () { LL | fn bbbb() {} | ^ found type parameter -error[E0053]: method `abcd` has an incompatible generic parameter for trait `Names` +error[E0053]: associated function `abcd` has an incompatible generic parameter for trait `Names` --> $DIR/mismatched_ty_const_in_trait_impl.rs:37:13 | LL | trait Names { diff --git a/tests/ui/delegation/not-supported.rs b/tests/ui/delegation/not-supported.rs index 5701cc6055db7..d5ac68ecf1b8a 100644 --- a/tests/ui/delegation/not-supported.rs +++ b/tests/ui/delegation/not-supported.rs @@ -53,7 +53,7 @@ mod generics { //~| ERROR method `foo2` has 0 type parameters but its trait declaration has 1 type parameter reuse ::foo3; //~^ ERROR early bound generics are not supported for associated delegation items - //~| ERROR lifetime parameters or bounds on method `foo3` do not match the trait declaration + //~| ERROR lifetime parameters or bounds on associated function `foo3` do not match the trait declaration } struct GenericS(T); diff --git a/tests/ui/delegation/not-supported.stderr b/tests/ui/delegation/not-supported.stderr index e7ba9fc6719a0..14d6b374bd2c4 100644 --- a/tests/ui/delegation/not-supported.stderr +++ b/tests/ui/delegation/not-supported.stderr @@ -84,14 +84,14 @@ LL | fn foo3<'a: 'a>(_: &'a u32) {} LL | reuse ::foo3; | ^^^^ -error[E0195]: lifetime parameters or bounds on method `foo3` do not match the trait declaration +error[E0195]: lifetime parameters or bounds on associated function `foo3` do not match the trait declaration --> $DIR/not-supported.rs:54:29 | LL | fn foo3<'a: 'a>(_: &'a u32) {} - | -------- lifetimes in impl do not match this method in trait + | -------- lifetimes in impl do not match this associated function in trait ... LL | reuse ::foo3; - | ^^^^ lifetimes do not match method in trait + | ^^^^ lifetimes do not match associated function in trait error: delegation to a function with effect parameter is not supported yet --> $DIR/not-supported.rs:112:18 diff --git a/tests/ui/error-codes/E0049.stderr b/tests/ui/error-codes/E0049.stderr index c0cd31faa90d6..83a30aa0a7874 100644 --- a/tests/ui/error-codes/E0049.stderr +++ b/tests/ui/error-codes/E0049.stderr @@ -1,4 +1,4 @@ -error[E0049]: method `foo` has 0 type parameters but its trait declaration has 1 type parameter +error[E0049]: associated function `foo` has 0 type parameters but its trait declaration has 1 type parameter --> $DIR/E0049.rs:8:11 | LL | fn foo(x: T) -> Self; @@ -7,7 +7,7 @@ LL | fn foo(x: T) -> Self; LL | fn foo(x: bool) -> Self { Bar } | ^ found 0 type parameters -error[E0049]: method `fuzz` has 0 type parameters but its trait declaration has 2 type parameters +error[E0049]: associated function `fuzz` has 0 type parameters but its trait declaration has 2 type parameters --> $DIR/E0049.rs:18:12 | LL | fn fuzz(x: A, y: B) -> Self; diff --git a/tests/ui/error-codes/E0195.rs b/tests/ui/error-codes/E0195.rs index f712ee42b8c5b..a7e51dff2f3fd 100644 --- a/tests/ui/error-codes/E0195.rs +++ b/tests/ui/error-codes/E0195.rs @@ -1,13 +1,13 @@ trait Trait { fn bar<'a,'b:'a>(x: &'a str, y: &'b str); - //~^ NOTE lifetimes in impl do not match this method in trait + //~^ NOTE lifetimes in impl do not match this associated function in trait } struct Foo; impl Trait for Foo { fn bar<'a,'b>(x: &'a str, y: &'b str) { //~ ERROR E0195 - //~^ NOTE lifetimes do not match method in trait + //~^ NOTE lifetimes do not match associated function in trait } } diff --git a/tests/ui/error-codes/E0195.stderr b/tests/ui/error-codes/E0195.stderr index b88064b7f90b2..9767dee9aecd1 100644 --- a/tests/ui/error-codes/E0195.stderr +++ b/tests/ui/error-codes/E0195.stderr @@ -1,11 +1,11 @@ -error[E0195]: lifetime parameters or bounds on method `bar` do not match the trait declaration +error[E0195]: lifetime parameters or bounds on associated function `bar` do not match the trait declaration --> $DIR/E0195.rs:9:11 | LL | fn bar<'a,'b:'a>(x: &'a str, y: &'b str); - | ---------- lifetimes in impl do not match this method in trait + | ---------- lifetimes in impl do not match this associated function in trait ... LL | fn bar<'a,'b>(x: &'a str, y: &'b str) { - | ^^^^^^^ lifetimes do not match method in trait + | ^^^^^^^ lifetimes do not match associated function in trait error: aborting due to 1 previous error 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 285493132b64d..946cb1a62b7da 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 @@ -8,7 +8,7 @@ impl X for T { //~ ERROR: not all trait items implemented fn foo<'a, T1: X>(t : T1) -> T1::Y<'a> { //~^ 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 associated function `foo` has 1 type parameter but its trait declaration has 0 type parameters 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 6a600aee11f2f..72c2bdc72a2f4 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 @@ -1,4 +1,4 @@ -error[E0049]: method `foo` has 1 type parameter but its trait declaration has 0 type parameters +error[E0049]: associated function `foo` has 1 type parameter but its trait declaration has 0 type parameters --> $DIR/gat-trait-path-missing-lifetime.rs:8:10 | LL | fn foo<'a>(t : Self::Y<'a>) -> Self::Y<'a> { t } diff --git a/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.rs b/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.rs index d9fac0238e16d..0477de3315a2b 100644 --- a/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.rs +++ b/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.rs @@ -6,7 +6,7 @@ trait Foo { impl Foo for S { fn bar() -> impl Sized {} - //~^ ERROR method `bar` has 0 type parameters but its trait declaration has 1 type parameter + //~^ ERROR associated function `bar` has 0 type parameters but its trait declaration has 1 type parameter } fn main() { diff --git a/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.stderr b/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.stderr index eed4c07710e06..ca67db403627e 100644 --- a/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.stderr +++ b/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.stderr @@ -1,4 +1,4 @@ -error[E0049]: method `bar` has 0 type parameters but its trait declaration has 1 type parameter +error[E0049]: associated function `bar` has 0 type parameters but its trait declaration has 1 type parameter --> $DIR/trait-more-generics-than-impl.rs:8:11 | LL | fn bar() -> impl Sized; diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr index 9d1ca5dbf2c03..b451555ec3ccd 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr @@ -40,7 +40,7 @@ error: `~const` can only be applied to `#[const_trait]` traits LL | const fn a(_: T) {} | ^^^^^^^^ -error[E0049]: method `foo` has 1 const parameter but its trait declaration has 0 const parameters +error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters --> $DIR/const-drop.rs:54:5 | LL | #[const_trait] @@ -49,7 +49,7 @@ LL | pub trait SomeTrait { LL | fn foo(); | - expected 0 const parameters -error[E0049]: method `foo` has 1 const parameter but its trait declaration has 0 const parameters +error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters --> $DIR/const-drop.rs:54:5 | LL | #[const_trait] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr index 2f93f9a6743b8..296614f7fd076 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr @@ -40,7 +40,7 @@ error: `~const` can only be applied to `#[const_trait]` traits LL | const fn a(_: T) {} | ^^^^^^^^ -error[E0049]: method `foo` has 1 const parameter but its trait declaration has 0 const parameters +error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters --> $DIR/const-drop.rs:54:5 | LL | #[const_trait] @@ -49,7 +49,7 @@ LL | pub trait SomeTrait { LL | fn foo(); | - expected 0 const parameters -error[E0049]: method `foo` has 1 const parameter but its trait declaration has 0 const parameters +error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters --> $DIR/const-drop.rs:54:5 | LL | #[const_trait] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.stderr index b4c4cf0a89059..7643697874f25 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.stderr @@ -1,4 +1,4 @@ -error[E0049]: method `bar` has 1 const parameter but its trait declaration has 0 const parameters +error[E0049]: associated function `bar` has 1 const parameter but its trait declaration has 0 const parameters --> $DIR/const-default-bound-non-const-specialized-bound.rs:16:1 | LL | #[const_trait] @@ -16,7 +16,7 @@ LL | | T: Foo, //FIXME ~ ERROR missing `~const` qualifier LL | | T: Specialize, | |__________________^ -error[E0049]: method `baz` has 1 const parameter but its trait declaration has 0 const parameters +error[E0049]: associated function `baz` has 1 const parameter but its trait declaration has 0 const parameters --> $DIR/const-default-bound-non-const-specialized-bound.rs:36:1 | LL | #[const_trait] @@ -25,7 +25,7 @@ LL | trait Baz { LL | fn baz(); | - expected 0 const parameters -error[E0049]: method `baz` has 1 const parameter but its trait declaration has 0 const parameters +error[E0049]: associated function `baz` has 1 const parameter but its trait declaration has 0 const parameters --> $DIR/const-default-bound-non-const-specialized-bound.rs:36:1 | LL | #[const_trait] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.stderr index cabf201405f55..9b2ae8d739c88 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.stderr @@ -1,4 +1,4 @@ -error[E0049]: method `value` has 1 const parameter but its trait declaration has 0 const parameters +error[E0049]: associated function `value` has 1 const parameter but its trait declaration has 0 const parameters --> $DIR/const-default-const-specialized.rs:10:1 | LL | #[const_trait] @@ -7,7 +7,7 @@ LL | trait Value { LL | fn value() -> u32; | - expected 0 const parameters -error[E0049]: method `value` has 1 const parameter but its trait declaration has 0 const parameters +error[E0049]: associated function `value` has 1 const parameter but its trait declaration has 0 const parameters --> $DIR/const-default-const-specialized.rs:10:1 | LL | #[const_trait] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/default-keyword.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/default-keyword.stderr index 52c8708f2c88d..18a25045f4b08 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/default-keyword.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/default-keyword.stderr @@ -1,4 +1,4 @@ -error[E0049]: method `foo` has 1 const parameter but its trait declaration has 0 const parameters +error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters --> $DIR/default-keyword.rs:7:1 | LL | #[const_trait] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95186-specialize-on-tilde-const.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95186-specialize-on-tilde-const.stderr index 1aa34637ca482..ecdc7b930e609 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95186-specialize-on-tilde-const.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95186-specialize-on-tilde-const.stderr @@ -1,4 +1,4 @@ -error[E0049]: method `foo` has 1 const parameter but its trait declaration has 0 const parameters +error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters --> $DIR/issue-95186-specialize-on-tilde-const.rs:14:1 | LL | #[const_trait] @@ -7,7 +7,7 @@ LL | trait Foo { LL | fn foo(); | - expected 0 const parameters -error[E0049]: method `foo` has 1 const parameter but its trait declaration has 0 const parameters +error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters --> $DIR/issue-95186-specialize-on-tilde-const.rs:14:1 | LL | #[const_trait] @@ -18,7 +18,7 @@ LL | fn foo(); | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0049]: method `bar` has 1 const parameter but its trait declaration has 0 const parameters +error[E0049]: associated function `bar` has 1 const parameter but its trait declaration has 0 const parameters --> $DIR/issue-95186-specialize-on-tilde-const.rs:30:1 | LL | #[const_trait] @@ -27,7 +27,7 @@ LL | trait Bar { LL | fn bar() {} | - expected 0 const parameters -error[E0049]: method `bar` has 1 const parameter but its trait declaration has 0 const parameters +error[E0049]: associated function `bar` has 1 const parameter but its trait declaration has 0 const parameters --> $DIR/issue-95186-specialize-on-tilde-const.rs:30:1 | LL | #[const_trait] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95187-same-trait-bound-different-constness.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95187-same-trait-bound-different-constness.stderr index 0e0f391b0865e..6679bb4653788 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95187-same-trait-bound-different-constness.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95187-same-trait-bound-different-constness.stderr @@ -1,4 +1,4 @@ -error[E0049]: method `bar` has 1 const parameter but its trait declaration has 0 const parameters +error[E0049]: associated function `bar` has 1 const parameter but its trait declaration has 0 const parameters --> $DIR/issue-95187-same-trait-bound-different-constness.rs:18:1 | LL | #[const_trait] @@ -7,7 +7,7 @@ LL | trait Bar { LL | fn bar(); | - expected 0 const parameters -error[E0049]: method `bar` has 1 const parameter but its trait declaration has 0 const parameters +error[E0049]: associated function `bar` has 1 const parameter but its trait declaration has 0 const parameters --> $DIR/issue-95187-same-trait-bound-different-constness.rs:18:1 | LL | #[const_trait] @@ -18,7 +18,7 @@ LL | fn bar(); | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0049]: method `baz` has 1 const parameter but its trait declaration has 0 const parameters +error[E0049]: associated function `baz` has 1 const parameter but its trait declaration has 0 const parameters --> $DIR/issue-95187-same-trait-bound-different-constness.rs:38:1 | LL | #[const_trait] @@ -27,7 +27,7 @@ LL | trait Baz { LL | fn baz(); | - expected 0 const parameters -error[E0049]: method `baz` has 1 const parameter but its trait declaration has 0 const parameters +error[E0049]: associated function `baz` has 1 const parameter but its trait declaration has 0 const parameters --> $DIR/issue-95187-same-trait-bound-different-constness.rs:38:1 | LL | #[const_trait] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.stderr index d49beb932591c..7f363922947fe 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.stderr @@ -1,4 +1,4 @@ -error[E0049]: method `value` has 1 const parameter but its trait declaration has 0 const parameters +error[E0049]: associated function `value` has 1 const parameter but its trait declaration has 0 const parameters --> $DIR/non-const-default-const-specialized.rs:9:1 | LL | #[const_trait] @@ -7,7 +7,7 @@ LL | trait Value { LL | fn value() -> u32; | - expected 0 const parameters -error[E0049]: method `value` has 1 const parameter but its trait declaration has 0 const parameters +error[E0049]: associated function `value` has 1 const parameter but its trait declaration has 0 const parameters --> $DIR/non-const-default-const-specialized.rs:9:1 | LL | #[const_trait] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.stderr index d082cd6de6097..bf273f349b4bc 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.stderr @@ -1,4 +1,4 @@ -error[E0049]: method `a` has 1 const parameter but its trait declaration has 0 const parameters +error[E0049]: associated function `a` has 1 const parameter but its trait declaration has 0 const parameters --> $DIR/specializing-constness-2.rs:9:1 | LL | #[const_trait] @@ -7,7 +7,7 @@ LL | pub trait A { LL | fn a() -> u32; | - expected 0 const parameters -error[E0049]: method `a` has 1 const parameter but its trait declaration has 0 const parameters +error[E0049]: associated function `a` has 1 const parameter but its trait declaration has 0 const parameters --> $DIR/specializing-constness-2.rs:9:1 | LL | #[const_trait] diff --git a/tests/ui/specialization/const_trait_impl.stderr b/tests/ui/specialization/const_trait_impl.stderr index e39138983c6e6..643f1de3e8d79 100644 --- a/tests/ui/specialization/const_trait_impl.stderr +++ b/tests/ui/specialization/const_trait_impl.stderr @@ -1,4 +1,4 @@ -error[E0049]: method `foo` has 1 const parameter but its trait declaration has 0 const parameters +error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters --> $DIR/const_trait_impl.rs:6:1 | LL | #[const_trait] @@ -7,7 +7,7 @@ LL | pub unsafe trait Sup { LL | fn foo() -> u32; | - expected 0 const parameters -error[E0049]: method `foo` has 1 const parameter but its trait declaration has 0 const parameters +error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters --> $DIR/const_trait_impl.rs:6:1 | LL | #[const_trait] @@ -36,7 +36,7 @@ error: `~const` can only be applied to `#[const_trait]` traits LL | impl const A for T { | ^^^^^^^ -error[E0049]: method `a` has 1 const parameter but its trait declaration has 0 const parameters +error[E0049]: associated function `a` has 1 const parameter but its trait declaration has 0 const parameters --> $DIR/const_trait_impl.rs:29:1 | LL | #[const_trait] @@ -45,7 +45,7 @@ LL | pub trait A { LL | fn a() -> u32; | - expected 0 const parameters -error[E0049]: method `a` has 1 const parameter but its trait declaration has 0 const parameters +error[E0049]: associated function `a` has 1 const parameter but its trait declaration has 0 const parameters --> $DIR/const_trait_impl.rs:29:1 | LL | #[const_trait] @@ -56,7 +56,7 @@ LL | fn a() -> u32; | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0049]: method `a` has 1 const parameter but its trait declaration has 0 const parameters +error[E0049]: associated function `a` has 1 const parameter but its trait declaration has 0 const parameters --> $DIR/const_trait_impl.rs:29:1 | LL | #[const_trait] diff --git a/tests/ui/typeck/issue-36708.stderr b/tests/ui/typeck/issue-36708.stderr index 3589796b6aac6..0aca575320f22 100644 --- a/tests/ui/typeck/issue-36708.stderr +++ b/tests/ui/typeck/issue-36708.stderr @@ -1,4 +1,4 @@ -error[E0049]: method `foo` has 1 type parameter but its trait declaration has 0 type parameters +error[E0049]: associated function `foo` has 1 type parameter but its trait declaration has 0 type parameters --> $DIR/issue-36708.rs:8:12 | LL | fn foo() {} From ed7bdbb17b9c03fe3530e5e3f21b7c6c7879dbca Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 9 Aug 2024 22:02:20 -0400 Subject: [PATCH 713/786] Store do_not_recommend-ness in impl header --- compiler/rustc_hir_analysis/src/collect.rs | 2 ++ compiler/rustc_middle/src/ty/context.rs | 6 ++++++ compiler/rustc_middle/src/ty/mod.rs | 1 + .../traits/fulfillment_errors.rs | 18 +++--------------- .../rustc_trait_selection/src/solve/fulfill.rs | 6 +----- 5 files changed, 13 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 47ff748547a90..07bf5d90b55fa 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1699,6 +1699,8 @@ fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option TyCtxt<'tcx> { pub fn impl_polarity(self, def_id: impl IntoQueryParam) -> ty::ImplPolarity { self.impl_trait_header(def_id).map_or(ty::ImplPolarity::Positive, |h| h.polarity) } + + /// Whether this is a trait implementation that has `#[diagnostic::do_not_recommend]` + pub fn do_not_recommend_impl(self, def_id: DefId) -> bool { + matches!(self.def_kind(def_id), DefKind::Impl { of_trait: true }) + && self.impl_trait_header(def_id).is_some_and(|header| header.do_not_recommend) + } } /// Parameter attributes that can only be determined by examining the body of a function instead diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 9736428e6f7c7..69b194045ad08 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -262,6 +262,7 @@ pub struct ImplTraitHeader<'tcx> { pub trait_ref: ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>, pub polarity: ImplPolarity, pub safety: hir::Safety, + pub do_not_recommend: bool, } #[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)] diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 1cee82f04ea0e..7f7de4a963b68 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -687,10 +687,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let mut applied_do_not_recommend = false; loop { if let ObligationCauseCode::ImplDerived(ref c) = base_cause { - if self.tcx.has_attrs_with_path( - c.impl_or_alias_def_id, - &[sym::diagnostic, sym::do_not_recommend], - ) { + if self.tcx.do_not_recommend_impl(c.impl_or_alias_def_id) { let code = (*c.derived.parent_code).clone(); obligation.cause.map_code(|_| code); obligation.predicate = c.derived.parent_trait_pred.upcast(self.tcx); @@ -1630,11 +1627,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { .tcx .all_impls(def_id) // ignore `do_not_recommend` items - .filter(|def_id| { - !self - .tcx - .has_attrs_with_path(*def_id, &[sym::diagnostic, sym::do_not_recommend]) - }) + .filter(|def_id| !self.tcx.do_not_recommend_impl(*def_id)) // Ignore automatically derived impls and `!Trait` impls. .filter_map(|def_id| self.tcx.impl_trait_header(def_id)) .filter_map(|header| { @@ -1904,12 +1897,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let impl_candidates = impl_candidates .into_iter() .cloned() - .filter(|cand| { - !self.tcx.has_attrs_with_path( - cand.impl_def_id, - &[sym::diagnostic, sym::do_not_recommend], - ) - }) + .filter(|cand| !self.tcx.do_not_recommend_impl(cand.impl_def_id)) .collect::>(); let def_id = trait_ref.def_id(); diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 49fa775a0a191..de8951ef72046 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -13,7 +13,6 @@ use rustc_middle::bug; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{self, TyCtxt}; use rustc_next_trait_solver::solve::{GenerateProofTree, SolverDelegateEvalExt as _}; -use rustc_span::symbol::sym; use super::delegate::SolverDelegate; use super::inspect::{self, ProofTreeInferCtxtExt, ProofTreeVisitor}; @@ -440,10 +439,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { source: CandidateSource::Impl(impl_def_id), result: _, } = candidate.kind() - && goal - .infcx() - .tcx - .has_attrs_with_path(impl_def_id, &[sym::diagnostic, sym::do_not_recommend]) + && goal.infcx().tcx.do_not_recommend_impl(impl_def_id) { return ControlFlow::Break(self.obligation.clone()); } From 20a16bb3c54ea7523ebd0c933fe5674aea50942e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 9 Aug 2024 21:14:07 -0400 Subject: [PATCH 714/786] Add test Co-authored-by: Georg Semmler --- ...ot_apply_attribute_without_feature_flag.rs | 21 +++++++++++++++++++ ...pply_attribute_without_feature_flag.stderr | 21 +++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.rs create mode 100644 tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.stderr diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.rs b/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.rs new file mode 100644 index 0000000000000..5548fa2f52e17 --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.rs @@ -0,0 +1,21 @@ +#![allow(unknown_or_malformed_diagnostic_attributes)] + +trait Foo {} + +#[diagnostic::do_not_recommend] +impl Foo for (A,) {} + +#[diagnostic::do_not_recommend] +impl Foo for (A, B) {} + +#[diagnostic::do_not_recommend] +impl Foo for (A, B, C) {} + +impl Foo for i32 {} + +fn check(a: impl Foo) {} + +fn main() { + check(()); + //~^ ERROR the trait bound `(): Foo` is not satisfied +} diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.stderr new file mode 100644 index 0000000000000..e56af28f3fb5d --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `(): Foo` is not satisfied + --> $DIR/do_not_apply_attribute_without_feature_flag.rs:19:11 + | +LL | check(()); + | ----- ^^ the trait `Foo` is not implemented for `()` + | | + | required by a bound introduced by this call + | + = help: the following other types implement trait `Foo`: + (A, B) + (A, B, C) + (A,) +note: required by a bound in `check` + --> $DIR/do_not_apply_attribute_without_feature_flag.rs:16:18 + | +LL | fn check(a: impl Foo) {} + | ^^^ required by this bound in `check` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. From 3dc083dfd80d0436560c34c41be815b88510ffdc Mon Sep 17 00:00:00 2001 From: burlinchen Date: Sat, 10 Aug 2024 10:44:24 +0800 Subject: [PATCH 715/786] test(std): Add codegen test for array::from_fn optimization This commit adds a new test file 'array-from_fn.rs' to the codegen test suite. The test checks the behavior of std::array::from_fn under different optimization levels: 1. At opt-level=0 (debug build), it verifies that the core::array::Guard is present in the generated code. 2. At opt-level=s (size optimization), it ensures that the Guard is optimized out. This test helps ensure that the compiler correctly optimizes array::from_fn calls in release builds while maintaining safety checks in debug builds. --- tests/codegen/array-from_fn.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 tests/codegen/array-from_fn.rs diff --git a/tests/codegen/array-from_fn.rs b/tests/codegen/array-from_fn.rs new file mode 100644 index 0000000000000..7202d0c67e690 --- /dev/null +++ b/tests/codegen/array-from_fn.rs @@ -0,0 +1,13 @@ +//@ revisions: NORMAL OPT +//@ [NORMAL] compile-flags: -C opt-level=0 -C debuginfo=2 +//@ [OPT] compile-flags: -C opt-level=s -C debuginfo=0 + +#![crate_type = "lib"] +#![feature(array_from_fn)] + +#[no_mangle] +pub fn iota() -> [u8; 16] { + // OPT-NOT: core..array..Guard + // NORMAL: core..array..Guard + std::array::from_fn(|i| i as _) +} From cd40769c02e31649bae3422ec7215783bc9d416f Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 20 Mar 2024 19:24:42 +0100 Subject: [PATCH 716/786] Stabilize `min_exhaustive_patterns` --- compiler/rustc_feature/src/accepted.rs | 2 ++ compiler/rustc_feature/src/unstable.rs | 3 --- .../src/build/matches/match_pair.rs | 13 +++++-------- .../src/thir/pattern/check_match.rs | 6 ++---- compiler/rustc_pattern_analysis/src/lib.rs | 1 - compiler/rustc_pattern_analysis/src/rustc.rs | 7 +------ .../rustc_pattern_analysis/src/usefulness.rs | 19 +++++++------------ .../tests/common/mod.rs | 4 ---- .../src/collections/vec_deque/into_iter.rs | 2 ++ tests/ui/pattern/usefulness/empty-types.rs | 1 - 10 files changed, 19 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index e42a655531b5d..44286cfeeefaa 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -267,6 +267,8 @@ declare_features! ( (accepted, min_const_generics, "1.51.0", Some(74878)), /// Allows calling `const unsafe fn` inside `unsafe` blocks in `const fn` functions. (accepted, min_const_unsafe_fn, "1.33.0", Some(55607)), + /// Allows exhaustive pattern matching on uninhabited types when matched by value. + (accepted, min_exhaustive_patterns, "CURRENT_RUSTC_VERSION", Some(119612)), /// Allows using `Self` and associated types in struct expressions and patterns. (accepted, more_struct_aliases, "1.16.0", Some(37544)), /// Allows using the MOVBE target feature. diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 88a4b5a838246..47810bc9165ef 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -519,9 +519,6 @@ declare_features! ( (unstable, macro_metavar_expr_concat, "1.81.0", Some(124225)), /// Allows `#[marker]` on certain traits allowing overlapping implementations. (unstable, marker_trait_attr, "1.30.0", Some(29864)), - /// Allows exhaustive pattern matching on types that contain uninhabited types in cases that are - /// unambiguously sound. - (unstable, min_exhaustive_patterns, "1.77.0", Some(119612)), /// A minimal, sound subset of specialization intended to be used by the /// standard library until the soundness issues with specialization /// are fixed. diff --git a/compiler/rustc_mir_build/src/build/matches/match_pair.rs b/compiler/rustc_mir_build/src/build/matches/match_pair.rs index 95fec154918a5..ab2bfcbca3aa6 100644 --- a/compiler/rustc_mir_build/src/build/matches/match_pair.rs +++ b/compiler/rustc_mir_build/src/build/matches/match_pair.rs @@ -208,14 +208,11 @@ impl<'pat, 'tcx> MatchPairTree<'pat, 'tcx> { subpairs = cx.field_match_pairs(downcast_place, subpatterns); let irrefutable = adt_def.variants().iter_enumerated().all(|(i, v)| { - i == variant_index || { - (cx.tcx.features().exhaustive_patterns - || cx.tcx.features().min_exhaustive_patterns) - && !v - .inhabited_predicate(cx.tcx, adt_def) - .instantiate(cx.tcx, args) - .apply_ignore_module(cx.tcx, cx.param_env) - } + i == variant_index + || !v + .inhabited_predicate(cx.tcx, adt_def) + .instantiate(cx.tcx, args) + .apply_ignore_module(cx.tcx, cx.param_env) }) && (adt_def.did().is_local() || !adt_def.is_variant_list_non_exhaustive()); if irrefutable { diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 64c6ff952c686..efaa75800fca4 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -695,9 +695,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { // Emit an extra note if the first uncovered witness would be uninhabited // if we disregard visibility. - let witness_1_is_privately_uninhabited = if (self.tcx.features().exhaustive_patterns - || self.tcx.features().min_exhaustive_patterns) - && let Some(witness_1) = witnesses.get(0) + let witness_1_is_privately_uninhabited = if let Some(witness_1) = witnesses.get(0) && let ty::Adt(adt, args) = witness_1.ty().kind() && adt.is_enum() && let Constructor::Variant(variant_index) = witness_1.ctor() @@ -1059,7 +1057,7 @@ fn report_non_exhaustive_match<'p, 'tcx>( err.note("`&str` cannot be matched exhaustively, so a wildcard `_` is necessary"); } else if cx.is_foreign_non_exhaustive_enum(ty) { err.note(format!("`{ty}` is marked as non-exhaustive, so a wildcard `_` is necessary to match exhaustively")); - } else if cx.is_uninhabited(ty.inner()) && cx.tcx.features().min_exhaustive_patterns { + } else if cx.is_uninhabited(ty.inner()) { // The type is uninhabited yet there is a witness: we must be in the `MaybeInvalid` // case. err.note(format!("`{ty}` is uninhabited but is not being matched by value, so a wildcard `_` is required")); diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs index a5c0b13c90be1..e37fa072b6d65 100644 --- a/compiler/rustc_pattern_analysis/src/lib.rs +++ b/compiler/rustc_pattern_analysis/src/lib.rs @@ -54,7 +54,6 @@ pub trait PatCx: Sized + fmt::Debug { type PatData: Clone; fn is_exhaustive_patterns_feature_on(&self) -> bool; - fn is_min_exhaustive_patterns_feature_on(&self) -> bool; /// The number of fields for this constructor. fn ctor_arity(&self, ctor: &Constructor, ty: &Self::Ty) -> usize; diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index 6290aeb252312..25f7cc17c11ff 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -237,9 +237,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { let tys = cx.variant_sub_tys(ty, variant).map(|(field, ty)| { let is_visible = adt.is_enum() || field.vis.is_accessible_from(cx.module, cx.tcx); - let is_uninhabited = (cx.tcx.features().exhaustive_patterns - || cx.tcx.features().min_exhaustive_patterns) - && cx.is_uninhabited(*ty); + let is_uninhabited = cx.is_uninhabited(*ty); let skip = is_uninhabited && (!is_visible || is_non_exhaustive); (ty, PrivateUninhabitedField(skip)) }); @@ -925,9 +923,6 @@ impl<'p, 'tcx: 'p> PatCx for RustcPatCtxt<'p, 'tcx> { fn is_exhaustive_patterns_feature_on(&self) -> bool { self.tcx.features().exhaustive_patterns } - fn is_min_exhaustive_patterns_feature_on(&self) -> bool { - self.tcx.features().min_exhaustive_patterns - } fn ctor_arity(&self, ctor: &crate::constructor::Constructor, ty: &Self::Ty) -> usize { self.ctor_arity(ctor, *ty) diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index 9710c9e1303dd..6535afcc39862 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -543,13 +543,11 @@ //! recurse into subpatterns. That second part is done through [`PlaceValidity`], most notably //! [`PlaceValidity::specialize`]. //! -//! Having said all that, in practice we don't fully follow what's been presented in this section. -//! Let's call "toplevel exception" the case where the match scrutinee itself has type `!` or -//! `EmptyEnum`. First, on stable rust, we require `_` patterns for empty types in all cases apart -//! from the toplevel exception. The `exhaustive_patterns` and `min_exaustive_patterns` allow -//! omitting patterns in the cases described above. There's a final detail: in the toplevel -//! exception or with the `exhaustive_patterns` feature, we ignore place validity when checking -//! whether a pattern is required for exhaustiveness. I (Nadrieril) hope to deprecate this behavior. +//! Having said all that, we don't fully follow what's been presented in this section. For +//! backwards-compatibility, we ignore place validity when checking whether a pattern is required +//! for exhaustiveness in two cases: when the `exhaustive_patterns` feature gate is on, or when the +//! match scrutinee itself has type `!` or `EmptyEnum`. I (Nadrieril) hope to deprecate this +//! exception. //! //! //! @@ -953,13 +951,10 @@ impl PlaceInfo { self.is_scrutinee && matches!(ctors_for_ty, ConstructorSet::NoConstructors); // Whether empty patterns are counted as useful or not. We only warn an empty arm unreachable if // it is guaranteed unreachable by the opsem (i.e. if the place is `known_valid`). - let empty_arms_are_unreachable = self.validity.is_known_valid() - && (is_toplevel_exception - || cx.is_exhaustive_patterns_feature_on() - || cx.is_min_exhaustive_patterns_feature_on()); + let empty_arms_are_unreachable = self.validity.is_known_valid(); // Whether empty patterns can be omitted for exhaustiveness. We ignore place validity in the // toplevel exception and `exhaustive_patterns` cases for backwards compatibility. - let can_omit_empty_arms = empty_arms_are_unreachable + let can_omit_empty_arms = self.validity.is_known_valid() || is_toplevel_exception || cx.is_exhaustive_patterns_feature_on(); diff --git a/compiler/rustc_pattern_analysis/tests/common/mod.rs b/compiler/rustc_pattern_analysis/tests/common/mod.rs index 01a56eaa78fcc..ec0bcd43ad24d 100644 --- a/compiler/rustc_pattern_analysis/tests/common/mod.rs +++ b/compiler/rustc_pattern_analysis/tests/common/mod.rs @@ -152,10 +152,6 @@ impl PatCx for Cx { false } - fn is_min_exhaustive_patterns_feature_on(&self) -> bool { - true - } - fn ctor_arity(&self, ctor: &Constructor, ty: &Self::Ty) -> usize { ty.sub_tys(ctor).len() } diff --git a/library/alloc/src/collections/vec_deque/into_iter.rs b/library/alloc/src/collections/vec_deque/into_iter.rs index 2d283dac9a97a..7be3de16b2da7 100644 --- a/library/alloc/src/collections/vec_deque/into_iter.rs +++ b/library/alloc/src/collections/vec_deque/into_iter.rs @@ -121,6 +121,7 @@ impl Iterator for IntoIter { { match self.try_fold(init, |b, item| Ok::(f(b, item))) { Ok(b) => b, + #[cfg(bootstrap)] Err(e) => match e {}, } } @@ -242,6 +243,7 @@ impl DoubleEndedIterator for IntoIter { { match self.try_rfold(init, |b, item| Ok::(f(b, item))) { Ok(b) => b, + #[cfg(bootstrap)] Err(e) => match e {}, } } diff --git a/tests/ui/pattern/usefulness/empty-types.rs b/tests/ui/pattern/usefulness/empty-types.rs index cc71f67831dd8..46024b1caebc7 100644 --- a/tests/ui/pattern/usefulness/empty-types.rs +++ b/tests/ui/pattern/usefulness/empty-types.rs @@ -1,5 +1,4 @@ //@ revisions: normal min_exh_pats exhaustive_patterns never_pats -// gate-test-min_exhaustive_patterns // // This tests correct handling of empty types in exhaustiveness checking. // From 99468bb7609ad5f598ef105860ceb32bc1b95074 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sat, 27 Jul 2024 11:08:16 +0200 Subject: [PATCH 717/786] Update tests --- ...atterns.opt1.SimplifyCfg-initial.after.mir | 10 +- ...atterns.opt2.SimplifyCfg-initial.after.mir | 15 - ...atterns.opt3.SimplifyCfg-initial.after.mir | 17 +- ...ch.UnreachablePropagation.panic-abort.diff | 16 +- ...h.UnreachablePropagation.panic-unwind.diff | 16 +- tests/mir-opt/unreachable.rs | 10 +- tests/mir-opt/unreachable_enum_branching.rs | 2 +- ....UnreachableEnumBranching.panic-abort.diff | 24 +- ...UnreachableEnumBranching.panic-unwind.diff | 24 +- .../run_pass/multivariant.rs | 3 +- .../huge_multispan_highlight.svg | 2 +- .../write-to-uninhabited-enum-variant.rs | 4 +- tests/ui/enum-discriminant/issue-61696.rs | 1 + tests/ui/enum-discriminant/niche.rs | 1 + .../feature-gate-exhaustive-patterns.rs | 2 +- .../feature-gate-exhaustive-patterns.stderr | 10 +- tests/ui/never_type/never-result.rs | 5 +- ...bited-union-ref.exhaustive_patterns.stderr | 6 +- ... always-inhabited-union-ref.normal.stderr} | 6 +- .../usefulness/always-inhabited-union-ref.rs | 3 +- ...tch-check-notes.exhaustive_patterns.stderr | 6 +- .../empty-match-check-notes.normal.stderr | 7 +- .../usefulness/empty-match-check-notes.rs | 6 +- .../empty-match.exhaustive_patterns.stderr | 1 + .../usefulness/empty-match.normal.stderr | 1 + .../empty-types.exhaustive_patterns.stderr | 100 ++--- .../usefulness/empty-types.never_pats.stderr | 357 ++++++++++-------- .../usefulness/empty-types.normal.stderr | 355 +++++++++-------- tests/ui/pattern/usefulness/empty-types.rs | 91 ++--- .../usefulness/explain-unreachable-pats.rs | 1 - .../explain-unreachable-pats.stderr | 24 +- tests/ui/pattern/usefulness/impl-trait.rs | 1 - tests/ui/pattern/usefulness/impl-trait.stderr | 32 +- ...privately-empty.exhaustive_patterns.stderr | 2 +- .../match-privately-empty.normal.stderr | 21 ++ .../usefulness/match-privately-empty.rs | 3 +- .../slice_of_empty.exhaustive_patterns.stderr | 2 +- .../usefulness/slice_of_empty.normal.stderr | 30 ++ tests/ui/pattern/usefulness/slice_of_empty.rs | 7 +- tests/ui/pattern/usefulness/uninhabited.rs | 1 - .../ui/reachable/unreachable-loop-patterns.rs | 2 - .../unreachable-loop-patterns.stderr | 4 +- .../ui/rfcs/rfc-0000-never_patterns/check.rs | 8 +- .../rfcs/rfc-0000-never_patterns/check.stderr | 22 +- .../typeck.fail.stderr | 16 +- .../ui/rfcs/rfc-0000-never_patterns/typeck.rs | 1 - .../unreachable.exh_pats.stderr | 14 +- .../unreachable.normal.stderr | 44 +++ .../rfc-0000-never_patterns/unreachable.rs | 15 +- .../unreachable.stderr | 55 +++ .../uninhabited/indirect_match_same_crate.rs | 11 +- .../indirect_match_same_crate.stderr | 79 ---- ...indirect_match_with_exhaustive_patterns.rs | 1 - ...rect_match_with_exhaustive_patterns.stderr | 8 +- ...tch_with_exhaustive_patterns_same_crate.rs | 1 - .../uninhabited/match_same_crate.rs | 7 +- .../uninhabited/match_same_crate.stderr | 64 ---- .../match_with_exhaustive_patterns.rs | 1 - .../match_with_exhaustive_patterns.stderr | 8 +- ...tch_with_exhaustive_patterns_same_crate.rs | 1 - .../uninhabited/patterns.rs | 1 - .../uninhabited/patterns_same_crate.rs | 1 - .../uninhabited/patterns_same_crate.stderr | 10 +- tests/ui/try-trait/try-operator-custom.rs | 3 - .../exhaustive-wo-nevertype-issue-51221.rs | 2 - ...ted-irrefutable.exhaustive_patterns.stderr | 4 +- .../uninhabited-irrefutable.normal.stderr | 26 ++ .../ui/uninhabited/uninhabited-irrefutable.rs | 3 +- .../uninhabited-matches-feature-gated.rs | 7 +- .../uninhabited-matches-feature-gated.stderr | 66 +--- tests/ui/uninhabited/uninhabited-patterns.rs | 1 - .../uninhabited/uninhabited-patterns.stderr | 8 +- 72 files changed, 878 insertions(+), 841 deletions(-) rename tests/ui/pattern/usefulness/{always-inhabited-union-ref.min_exhaustive_patterns.stderr => always-inhabited-union-ref.normal.stderr} (87%) create mode 100644 tests/ui/pattern/usefulness/match-privately-empty.normal.stderr create mode 100644 tests/ui/pattern/usefulness/slice_of_empty.normal.stderr create mode 100644 tests/ui/rfcs/rfc-0000-never_patterns/unreachable.normal.stderr create mode 100644 tests/ui/rfcs/rfc-0000-never_patterns/unreachable.stderr delete mode 100644 tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr delete mode 100644 tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr create mode 100644 tests/ui/uninhabited/uninhabited-irrefutable.normal.stderr diff --git a/tests/mir-opt/building/match/never_patterns.opt1.SimplifyCfg-initial.after.mir b/tests/mir-opt/building/match/never_patterns.opt1.SimplifyCfg-initial.after.mir index 78356a90743a6..bba4d9c0149a1 100644 --- a/tests/mir-opt/building/match/never_patterns.opt1.SimplifyCfg-initial.after.mir +++ b/tests/mir-opt/building/match/never_patterns.opt1.SimplifyCfg-initial.after.mir @@ -13,17 +13,17 @@ fn opt1(_1: &Result) -> &u32 { bb0: { PlaceMention(_1); - _2 = discriminant((*_1)); - switchInt(move _2) -> [0: bb2, 1: bb3, otherwise: bb1]; + falseEdge -> [real: bb4, imaginary: bb1]; } bb1: { - FakeRead(ForMatchedPlace(None), _1); - unreachable; + _2 = discriminant((*_1)); + switchInt(move _2) -> [1: bb3, otherwise: bb2]; } bb2: { - falseEdge -> [real: bb4, imaginary: bb3]; + FakeRead(ForMatchedPlace(None), _1); + unreachable; } bb3: { diff --git a/tests/mir-opt/building/match/never_patterns.opt2.SimplifyCfg-initial.after.mir b/tests/mir-opt/building/match/never_patterns.opt2.SimplifyCfg-initial.after.mir index 979fbb2860dcb..fc0769d6f7dcc 100644 --- a/tests/mir-opt/building/match/never_patterns.opt2.SimplifyCfg-initial.after.mir +++ b/tests/mir-opt/building/match/never_patterns.opt2.SimplifyCfg-initial.after.mir @@ -11,25 +11,10 @@ fn opt2(_1: &Result) -> &u32 { bb0: { PlaceMention(_1); - _2 = discriminant((*_1)); - switchInt(move _2) -> [0: bb2, 1: bb3, otherwise: bb1]; - } - - bb1: { - FakeRead(ForMatchedPlace(None), _1); - unreachable; - } - - bb2: { StorageLive(_3); _3 = &(((*_1) as Ok).0: u32); _0 = &(*_3); StorageDead(_3); return; } - - bb3: { - FakeRead(ForMatchedPlace(None), (((*_1) as Err).0: Void)); - unreachable; - } } diff --git a/tests/mir-opt/building/match/never_patterns.opt3.SimplifyCfg-initial.after.mir b/tests/mir-opt/building/match/never_patterns.opt3.SimplifyCfg-initial.after.mir index 93ebe600b3ff7..86347db4d92eb 100644 --- a/tests/mir-opt/building/match/never_patterns.opt3.SimplifyCfg-initial.after.mir +++ b/tests/mir-opt/building/match/never_patterns.opt3.SimplifyCfg-initial.after.mir @@ -12,24 +12,19 @@ fn opt3(_1: &Result) -> &u32 { bb0: { PlaceMention(_1); _2 = discriminant((*_1)); - switchInt(move _2) -> [0: bb3, 1: bb2, otherwise: bb1]; + switchInt(move _2) -> [1: bb2, otherwise: bb1]; } bb1: { - FakeRead(ForMatchedPlace(None), _1); - unreachable; - } - - bb2: { - FakeRead(ForMatchedPlace(None), (((*_1) as Err).0: Void)); - unreachable; - } - - bb3: { StorageLive(_3); _3 = &(((*_1) as Ok).0: u32); _0 = &(*_3); StorageDead(_3); return; } + + bb2: { + FakeRead(ForMatchedPlace(None), (((*_1) as Err).0: Void)); + unreachable; + } } diff --git a/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-abort.diff b/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-abort.diff index da7a2bd10e01a..1e1ddfae0eb9e 100644 --- a/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-abort.diff +++ b/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-abort.diff @@ -19,14 +19,16 @@ bb1: { _2 = discriminant(_1); -- switchInt(move _2) -> [0: bb4, 1: bb3, otherwise: bb2]; -+ _5 = Eq(_2, const 0_isize); +- switchInt(move _2) -> [1: bb3, otherwise: bb2]; ++ _5 = Ne(_2, const 1_isize); + assume(move _5); -+ goto -> bb4; ++ goto -> bb2; } bb2: { - unreachable; + _0 = const (); + StorageDead(_1); + return; } bb3: { @@ -35,11 +37,5 @@ - StorageLive(_4); unreachable; } - - bb4: { - _0 = const (); - StorageDead(_1); - return; - } } diff --git a/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-unwind.diff b/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-unwind.diff index a2121fc684f5b..809d24aa15a13 100644 --- a/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-unwind.diff +++ b/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-unwind.diff @@ -19,14 +19,16 @@ bb1: { _2 = discriminant(_1); -- switchInt(move _2) -> [0: bb4, 1: bb3, otherwise: bb2]; -+ _5 = Eq(_2, const 0_isize); +- switchInt(move _2) -> [1: bb3, otherwise: bb2]; ++ _5 = Ne(_2, const 1_isize); + assume(move _5); -+ goto -> bb4; ++ goto -> bb2; } bb2: { - unreachable; + _0 = const (); + StorageDead(_1); + return; } bb3: { @@ -35,11 +37,5 @@ - StorageLive(_4); unreachable; } - - bb4: { - _0 = const (); - StorageDead(_1); - return; - } } diff --git a/tests/mir-opt/unreachable.rs b/tests/mir-opt/unreachable.rs index 881e3542f0ac9..f7f4815ae7ce1 100644 --- a/tests/mir-opt/unreachable.rs +++ b/tests/mir-opt/unreachable.rs @@ -45,18 +45,16 @@ fn as_match() { // CHECK: bb0: { // CHECK: {{_.*}} = empty() // CHECK: bb1: { - // CHECK: [[eq:_.*]] = Eq({{.*}}, const 0_isize); + // CHECK: [[eq:_.*]] = Ne({{.*}}, const 1_isize); // CHECK-NEXT: assume(move [[eq]]); - // CHECK-NEXT: goto -> bb4; + // CHECK-NEXT: goto -> bb2; // CHECK: bb2: { - // CHECK-NEXT: unreachable; + // CHECK: return; // CHECK: bb3: { // CHECK-NEXT: unreachable; - // CHECK: bb4: { - // CHECK: return; match empty() { - None => {} Some(_x) => match _x {}, + None => {} } } diff --git a/tests/mir-opt/unreachable_enum_branching.rs b/tests/mir-opt/unreachable_enum_branching.rs index fac14042b1075..7647f9bf0779a 100644 --- a/tests/mir-opt/unreachable_enum_branching.rs +++ b/tests/mir-opt/unreachable_enum_branching.rs @@ -49,7 +49,7 @@ struct Plop { fn simple() { // CHECK-LABEL: fn simple( // CHECK: [[discr:_.*]] = discriminant( - // CHECK: switchInt(move [[discr]]) -> [0: [[unreachable:bb.*]], 1: [[unreachable]], 2: bb2, otherwise: [[unreachable]]]; + // CHECK: switchInt(move [[discr]]) -> [0: [[unreachable:bb.*]], 1: [[unreachable]], 2: bb1, otherwise: [[unreachable]]]; // CHECK: [[unreachable]]: { // CHECK-NEXT: unreachable; match Test1::C { diff --git a/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-abort.diff index 8aef991493672..5c08648fac3bb 100644 --- a/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-abort.diff +++ b/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-abort.diff @@ -14,40 +14,40 @@ StorageLive(_2); _2 = Test1::C; _3 = discriminant(_2); -- switchInt(move _3) -> [0: bb4, 1: bb3, 2: bb2, otherwise: bb1]; -+ switchInt(move _3) -> [0: bb1, 1: bb1, 2: bb2, otherwise: bb1]; +- switchInt(move _3) -> [0: bb3, 1: bb2, otherwise: bb1]; ++ switchInt(move _3) -> [0: bb5, 1: bb5, 2: bb1, otherwise: bb5]; } bb1: { - unreachable; - } - - bb2: { StorageLive(_5); _5 = const "C"; _1 = &(*_5); StorageDead(_5); - goto -> bb5; + goto -> bb4; } - bb3: { + bb2: { StorageLive(_4); _4 = const "B(Empty)"; _1 = &(*_4); StorageDead(_4); - goto -> bb5; + goto -> bb4; } - bb4: { + bb3: { _1 = const "A(Empty)"; - goto -> bb5; + goto -> bb4; } - bb5: { + bb4: { StorageDead(_2); StorageDead(_1); _0 = const (); return; ++ } ++ ++ bb5: { ++ unreachable; } } diff --git a/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-unwind.diff index 8aef991493672..5c08648fac3bb 100644 --- a/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-unwind.diff +++ b/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-unwind.diff @@ -14,40 +14,40 @@ StorageLive(_2); _2 = Test1::C; _3 = discriminant(_2); -- switchInt(move _3) -> [0: bb4, 1: bb3, 2: bb2, otherwise: bb1]; -+ switchInt(move _3) -> [0: bb1, 1: bb1, 2: bb2, otherwise: bb1]; +- switchInt(move _3) -> [0: bb3, 1: bb2, otherwise: bb1]; ++ switchInt(move _3) -> [0: bb5, 1: bb5, 2: bb1, otherwise: bb5]; } bb1: { - unreachable; - } - - bb2: { StorageLive(_5); _5 = const "C"; _1 = &(*_5); StorageDead(_5); - goto -> bb5; + goto -> bb4; } - bb3: { + bb2: { StorageLive(_4); _4 = const "B(Empty)"; _1 = &(*_4); StorageDead(_4); - goto -> bb5; + goto -> bb4; } - bb4: { + bb3: { _1 = const "A(Empty)"; - goto -> bb5; + goto -> bb4; } - bb5: { + bb4: { StorageDead(_2); StorageDead(_1); _0 = const (); return; ++ } ++ ++ bb5: { ++ unreachable; } } diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.rs b/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.rs index 52ed008137fce..74f37b514e4a4 100644 --- a/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.rs +++ b/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.rs @@ -1,10 +1,9 @@ // Test precise capture of a multi-variant enum (when remaining variants are // visibly uninhabited). -//@ revisions: min_exhaustive_patterns exhaustive_patterns +//@ revisions: normal exhaustive_patterns //@ edition:2021 //@ run-pass #![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))] -#![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))] #![feature(never_type)] pub fn main() { diff --git a/tests/ui/codemap_tests/huge_multispan_highlight.svg b/tests/ui/codemap_tests/huge_multispan_highlight.svg index 7b6dbb17c6f95..12058176dc0f1 100644 --- a/tests/ui/codemap_tests/huge_multispan_highlight.svg +++ b/tests/ui/codemap_tests/huge_multispan_highlight.svg @@ -1,4 +1,4 @@ - + { fn fold_with>(self, folder: &mut F) -> Self { match self.try_fold_with(folder) { Ok(t) => t, + #[cfg(bootstrap)] Err(e) => match e {}, } } @@ -115,6 +116,7 @@ pub trait TypeSuperFoldable: TypeFoldable { fn super_fold_with>(self, folder: &mut F) -> Self { match self.try_super_fold_with(folder) { Ok(t) => t, + #[cfg(bootstrap)] Err(e) => match e {}, } } diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 9d4520d4ee813..07daa32afa8a3 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -192,6 +192,7 @@ // // Language features: // tidy-alphabetical-start +#![cfg_attr(bootstrap, feature(min_exhaustive_patterns))] #![feature(abi_unadjusted)] #![feature(adt_const_params)] #![feature(allow_internal_unsafe)] @@ -225,7 +226,6 @@ #![feature(link_llvm_intrinsics)] #![feature(macro_metavar_expr)] #![feature(marker_trait_attr)] -#![feature(min_exhaustive_patterns)] #![feature(min_specialization)] #![feature(multiple_supertrait_upcastable)] #![feature(must_not_suspend)] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 7fc1bc46fef84..93a74ef739b90 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -272,6 +272,7 @@ // // Language features: // tidy-alphabetical-start +#![cfg_attr(bootstrap, feature(min_exhaustive_patterns))] #![feature(alloc_error_handler)] #![feature(allocator_internals)] #![feature(allow_internal_unsafe)] @@ -299,7 +300,6 @@ #![feature(link_cfg)] #![feature(linkage)] #![feature(macro_metavar_expr_concat)] -#![feature(min_exhaustive_patterns)] #![feature(min_specialization)] #![feature(must_not_suspend)] #![feature(needs_panic_runtime)] From 8615a6b006c41e02bdc6a46f1061e1e6daaefb22 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sat, 30 Mar 2024 12:21:59 +0100 Subject: [PATCH 719/786] Test that 0/unknown-length arrays are nonempty --- .../empty-match.exhaustive_patterns.stderr | 92 ++++++++++++++----- .../usefulness/empty-match.normal.stderr | 92 ++++++++++++++----- tests/ui/pattern/usefulness/empty-match.rs | 7 +- 3 files changed, 144 insertions(+), 47 deletions(-) diff --git a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr index bc12327a1b2a3..f2067f0341fcd 100644 --- a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr +++ b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: type `u8` is non-empty - --> $DIR/empty-match.rs:46:20 + --> $DIR/empty-match.rs:47:20 | LL | match_no_arms!(0u8); | ^^^ @@ -8,7 +8,7 @@ LL | match_no_arms!(0u8); = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `i8` is non-empty - --> $DIR/empty-match.rs:47:20 + --> $DIR/empty-match.rs:48:20 | LL | match_no_arms!(0i8); | ^^^ @@ -17,7 +17,7 @@ LL | match_no_arms!(0i8); = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `usize` is non-empty - --> $DIR/empty-match.rs:48:20 + --> $DIR/empty-match.rs:49:20 | LL | match_no_arms!(0usize); | ^^^^^^ @@ -26,7 +26,7 @@ LL | match_no_arms!(0usize); = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `isize` is non-empty - --> $DIR/empty-match.rs:49:20 + --> $DIR/empty-match.rs:50:20 | LL | match_no_arms!(0isize); | ^^^^^^ @@ -35,7 +35,7 @@ LL | match_no_arms!(0isize); = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty - --> $DIR/empty-match.rs:50:20 + --> $DIR/empty-match.rs:51:20 | LL | match_no_arms!(NonEmptyStruct1); | ^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL | struct NonEmptyStruct1; = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty - --> $DIR/empty-match.rs:51:20 + --> $DIR/empty-match.rs:52:20 | LL | match_no_arms!(NonEmptyStruct2(true)); | ^^^^^^^^^^^^^^^^^^^^^ @@ -63,7 +63,7 @@ LL | struct NonEmptyStruct2(bool); = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty - --> $DIR/empty-match.rs:52:20 + --> $DIR/empty-match.rs:53:20 | LL | match_no_arms!((NonEmptyUnion1 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -77,7 +77,7 @@ LL | union NonEmptyUnion1 { = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty - --> $DIR/empty-match.rs:53:20 + --> $DIR/empty-match.rs:54:20 | LL | match_no_arms!((NonEmptyUnion2 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -91,7 +91,7 @@ LL | union NonEmptyUnion2 { = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered - --> $DIR/empty-match.rs:54:20 + --> $DIR/empty-match.rs:55:20 | LL | match_no_arms!(NonEmptyEnum1::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered @@ -107,7 +107,7 @@ LL | Foo(bool), = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered - --> $DIR/empty-match.rs:55:20 + --> $DIR/empty-match.rs:56:20 | LL | match_no_arms!(NonEmptyEnum2::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered @@ -125,7 +125,7 @@ LL | Bar, = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered - --> $DIR/empty-match.rs:56:20 + --> $DIR/empty-match.rs:57:20 | LL | match_no_arms!(NonEmptyEnum5::V1); | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered @@ -148,8 +148,26 @@ LL | V5, = note: the matched value is of type `NonEmptyEnum5` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms +error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty + --> $DIR/empty-match.rs:58:20 + | +LL | match_no_arms!(array0_of_empty); + | ^^^^^^^^^^^^^^^ + | + = note: the matched value is of type `[!; 0]` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: type `[!; N]` is non-empty + --> $DIR/empty-match.rs:59:20 + | +LL | match_no_arms!(arrayN_of_empty); + | ^^^^^^^^^^^^^^^ + | + = note: the matched value is of type `[!; N]` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + error[E0004]: non-exhaustive patterns: `0_u8..=u8::MAX` not covered - --> $DIR/empty-match.rs:58:24 + --> $DIR/empty-match.rs:61:24 | LL | match_guarded_arm!(0u8); | ^^^ pattern `0_u8..=u8::MAX` not covered @@ -163,7 +181,7 @@ LL + 0_u8..=u8::MAX => todo!() | error[E0004]: non-exhaustive patterns: `i8::MIN..=i8::MAX` not covered - --> $DIR/empty-match.rs:59:24 + --> $DIR/empty-match.rs:62:24 | LL | match_guarded_arm!(0i8); | ^^^ pattern `i8::MIN..=i8::MAX` not covered @@ -177,7 +195,7 @@ LL + i8::MIN..=i8::MAX => todo!() | error[E0004]: non-exhaustive patterns: `0_usize..` not covered - --> $DIR/empty-match.rs:60:24 + --> $DIR/empty-match.rs:63:24 | LL | match_guarded_arm!(0usize); | ^^^^^^ pattern `0_usize..` not covered @@ -191,7 +209,7 @@ LL + 0_usize.. => todo!() | error[E0004]: non-exhaustive patterns: `_` not covered - --> $DIR/empty-match.rs:61:24 + --> $DIR/empty-match.rs:64:24 | LL | match_guarded_arm!(0isize); | ^^^^^^ pattern `_` not covered @@ -205,7 +223,7 @@ LL + _ => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered - --> $DIR/empty-match.rs:62:24 + --> $DIR/empty-match.rs:65:24 | LL | match_guarded_arm!(NonEmptyStruct1); | ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` not covered @@ -224,7 +242,7 @@ LL + NonEmptyStruct1 => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered - --> $DIR/empty-match.rs:63:24 + --> $DIR/empty-match.rs:66:24 | LL | match_guarded_arm!(NonEmptyStruct2(true)); | ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` not covered @@ -243,7 +261,7 @@ LL + NonEmptyStruct2(_) => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered - --> $DIR/empty-match.rs:64:24 + --> $DIR/empty-match.rs:67:24 | LL | match_guarded_arm!((NonEmptyUnion1 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered @@ -262,7 +280,7 @@ LL + NonEmptyUnion1 { .. } => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered - --> $DIR/empty-match.rs:65:24 + --> $DIR/empty-match.rs:68:24 | LL | match_guarded_arm!((NonEmptyUnion2 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered @@ -282,7 +300,7 @@ LL + NonEmptyUnion2 { .. } => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered - --> $DIR/empty-match.rs:66:24 + --> $DIR/empty-match.rs:69:24 | LL | match_guarded_arm!(NonEmptyEnum1::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered @@ -303,7 +321,7 @@ LL + NonEmptyEnum1::Foo(_) => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered - --> $DIR/empty-match.rs:67:24 + --> $DIR/empty-match.rs:70:24 | LL | match_guarded_arm!(NonEmptyEnum2::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered @@ -326,7 +344,7 @@ LL + NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered - --> $DIR/empty-match.rs:68:24 + --> $DIR/empty-match.rs:71:24 | LL | match_guarded_arm!(NonEmptyEnum5::V1); | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered @@ -354,6 +372,34 @@ LL ~ _ if false => {}, LL + _ => todo!() | -error: aborting due to 22 previous errors +error[E0004]: non-exhaustive patterns: `[]` not covered + --> $DIR/empty-match.rs:72:24 + | +LL | match_guarded_arm!(array0_of_empty); + | ^^^^^^^^^^^^^^^ pattern `[]` not covered + | + = note: the matched value is of type `[!; 0]` + = note: match arms with guards don't count towards exhaustivity +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ _ if false => {}, +LL + [] => todo!() + | + +error[E0004]: non-exhaustive patterns: `[]` not covered + --> $DIR/empty-match.rs:73:24 + | +LL | match_guarded_arm!(arrayN_of_empty); + | ^^^^^^^^^^^^^^^ pattern `[]` not covered + | + = note: the matched value is of type `[!; N]` + = note: match arms with guards don't count towards exhaustivity +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ _ if false => {}, +LL + [] => todo!() + | + +error: aborting due to 26 previous errors For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/empty-match.normal.stderr b/tests/ui/pattern/usefulness/empty-match.normal.stderr index bc12327a1b2a3..f2067f0341fcd 100644 --- a/tests/ui/pattern/usefulness/empty-match.normal.stderr +++ b/tests/ui/pattern/usefulness/empty-match.normal.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: type `u8` is non-empty - --> $DIR/empty-match.rs:46:20 + --> $DIR/empty-match.rs:47:20 | LL | match_no_arms!(0u8); | ^^^ @@ -8,7 +8,7 @@ LL | match_no_arms!(0u8); = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `i8` is non-empty - --> $DIR/empty-match.rs:47:20 + --> $DIR/empty-match.rs:48:20 | LL | match_no_arms!(0i8); | ^^^ @@ -17,7 +17,7 @@ LL | match_no_arms!(0i8); = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `usize` is non-empty - --> $DIR/empty-match.rs:48:20 + --> $DIR/empty-match.rs:49:20 | LL | match_no_arms!(0usize); | ^^^^^^ @@ -26,7 +26,7 @@ LL | match_no_arms!(0usize); = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `isize` is non-empty - --> $DIR/empty-match.rs:49:20 + --> $DIR/empty-match.rs:50:20 | LL | match_no_arms!(0isize); | ^^^^^^ @@ -35,7 +35,7 @@ LL | match_no_arms!(0isize); = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty - --> $DIR/empty-match.rs:50:20 + --> $DIR/empty-match.rs:51:20 | LL | match_no_arms!(NonEmptyStruct1); | ^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL | struct NonEmptyStruct1; = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty - --> $DIR/empty-match.rs:51:20 + --> $DIR/empty-match.rs:52:20 | LL | match_no_arms!(NonEmptyStruct2(true)); | ^^^^^^^^^^^^^^^^^^^^^ @@ -63,7 +63,7 @@ LL | struct NonEmptyStruct2(bool); = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty - --> $DIR/empty-match.rs:52:20 + --> $DIR/empty-match.rs:53:20 | LL | match_no_arms!((NonEmptyUnion1 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -77,7 +77,7 @@ LL | union NonEmptyUnion1 { = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty - --> $DIR/empty-match.rs:53:20 + --> $DIR/empty-match.rs:54:20 | LL | match_no_arms!((NonEmptyUnion2 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -91,7 +91,7 @@ LL | union NonEmptyUnion2 { = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered - --> $DIR/empty-match.rs:54:20 + --> $DIR/empty-match.rs:55:20 | LL | match_no_arms!(NonEmptyEnum1::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered @@ -107,7 +107,7 @@ LL | Foo(bool), = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered - --> $DIR/empty-match.rs:55:20 + --> $DIR/empty-match.rs:56:20 | LL | match_no_arms!(NonEmptyEnum2::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered @@ -125,7 +125,7 @@ LL | Bar, = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered - --> $DIR/empty-match.rs:56:20 + --> $DIR/empty-match.rs:57:20 | LL | match_no_arms!(NonEmptyEnum5::V1); | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered @@ -148,8 +148,26 @@ LL | V5, = note: the matched value is of type `NonEmptyEnum5` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms +error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty + --> $DIR/empty-match.rs:58:20 + | +LL | match_no_arms!(array0_of_empty); + | ^^^^^^^^^^^^^^^ + | + = note: the matched value is of type `[!; 0]` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: type `[!; N]` is non-empty + --> $DIR/empty-match.rs:59:20 + | +LL | match_no_arms!(arrayN_of_empty); + | ^^^^^^^^^^^^^^^ + | + = note: the matched value is of type `[!; N]` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + error[E0004]: non-exhaustive patterns: `0_u8..=u8::MAX` not covered - --> $DIR/empty-match.rs:58:24 + --> $DIR/empty-match.rs:61:24 | LL | match_guarded_arm!(0u8); | ^^^ pattern `0_u8..=u8::MAX` not covered @@ -163,7 +181,7 @@ LL + 0_u8..=u8::MAX => todo!() | error[E0004]: non-exhaustive patterns: `i8::MIN..=i8::MAX` not covered - --> $DIR/empty-match.rs:59:24 + --> $DIR/empty-match.rs:62:24 | LL | match_guarded_arm!(0i8); | ^^^ pattern `i8::MIN..=i8::MAX` not covered @@ -177,7 +195,7 @@ LL + i8::MIN..=i8::MAX => todo!() | error[E0004]: non-exhaustive patterns: `0_usize..` not covered - --> $DIR/empty-match.rs:60:24 + --> $DIR/empty-match.rs:63:24 | LL | match_guarded_arm!(0usize); | ^^^^^^ pattern `0_usize..` not covered @@ -191,7 +209,7 @@ LL + 0_usize.. => todo!() | error[E0004]: non-exhaustive patterns: `_` not covered - --> $DIR/empty-match.rs:61:24 + --> $DIR/empty-match.rs:64:24 | LL | match_guarded_arm!(0isize); | ^^^^^^ pattern `_` not covered @@ -205,7 +223,7 @@ LL + _ => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered - --> $DIR/empty-match.rs:62:24 + --> $DIR/empty-match.rs:65:24 | LL | match_guarded_arm!(NonEmptyStruct1); | ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` not covered @@ -224,7 +242,7 @@ LL + NonEmptyStruct1 => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered - --> $DIR/empty-match.rs:63:24 + --> $DIR/empty-match.rs:66:24 | LL | match_guarded_arm!(NonEmptyStruct2(true)); | ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` not covered @@ -243,7 +261,7 @@ LL + NonEmptyStruct2(_) => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered - --> $DIR/empty-match.rs:64:24 + --> $DIR/empty-match.rs:67:24 | LL | match_guarded_arm!((NonEmptyUnion1 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered @@ -262,7 +280,7 @@ LL + NonEmptyUnion1 { .. } => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered - --> $DIR/empty-match.rs:65:24 + --> $DIR/empty-match.rs:68:24 | LL | match_guarded_arm!((NonEmptyUnion2 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered @@ -282,7 +300,7 @@ LL + NonEmptyUnion2 { .. } => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered - --> $DIR/empty-match.rs:66:24 + --> $DIR/empty-match.rs:69:24 | LL | match_guarded_arm!(NonEmptyEnum1::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered @@ -303,7 +321,7 @@ LL + NonEmptyEnum1::Foo(_) => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered - --> $DIR/empty-match.rs:67:24 + --> $DIR/empty-match.rs:70:24 | LL | match_guarded_arm!(NonEmptyEnum2::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered @@ -326,7 +344,7 @@ LL + NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered - --> $DIR/empty-match.rs:68:24 + --> $DIR/empty-match.rs:71:24 | LL | match_guarded_arm!(NonEmptyEnum5::V1); | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered @@ -354,6 +372,34 @@ LL ~ _ if false => {}, LL + _ => todo!() | -error: aborting due to 22 previous errors +error[E0004]: non-exhaustive patterns: `[]` not covered + --> $DIR/empty-match.rs:72:24 + | +LL | match_guarded_arm!(array0_of_empty); + | ^^^^^^^^^^^^^^^ pattern `[]` not covered + | + = note: the matched value is of type `[!; 0]` + = note: match arms with guards don't count towards exhaustivity +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ _ if false => {}, +LL + [] => todo!() + | + +error[E0004]: non-exhaustive patterns: `[]` not covered + --> $DIR/empty-match.rs:73:24 + | +LL | match_guarded_arm!(arrayN_of_empty); + | ^^^^^^^^^^^^^^^ pattern `[]` not covered + | + = note: the matched value is of type `[!; N]` + = note: match arms with guards don't count towards exhaustivity +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ _ if false => {}, +LL + [] => todo!() + | + +error: aborting due to 26 previous errors For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/empty-match.rs b/tests/ui/pattern/usefulness/empty-match.rs index 9b22b47a12b1f..b34427a7c2388 100644 --- a/tests/ui/pattern/usefulness/empty-match.rs +++ b/tests/ui/pattern/usefulness/empty-match.rs @@ -5,7 +5,7 @@ #![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))] #![deny(unreachable_patterns)] -fn nonempty() { +fn nonempty(arrayN_of_empty: [!; N]) { macro_rules! match_no_arms { ($e:expr) => { match $e {} @@ -42,6 +42,7 @@ fn nonempty() { V4, V5, } + let array0_of_empty: [!; 0] = []; match_no_arms!(0u8); //~ ERROR type `u8` is non-empty match_no_arms!(0i8); //~ ERROR type `i8` is non-empty @@ -54,6 +55,8 @@ fn nonempty() { match_no_arms!(NonEmptyEnum1::Foo(true)); //~ ERROR `NonEmptyEnum1::Foo(_)` not covered match_no_arms!(NonEmptyEnum2::Foo(true)); //~ ERROR `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered match_no_arms!(NonEmptyEnum5::V1); //~ ERROR `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered + match_no_arms!(array0_of_empty); //~ ERROR type `[!; 0]` is non-empty + match_no_arms!(arrayN_of_empty); //~ ERROR type `[!; N]` is non-empty match_guarded_arm!(0u8); //~ ERROR `0_u8..=u8::MAX` not covered match_guarded_arm!(0i8); //~ ERROR `i8::MIN..=i8::MAX` not covered @@ -66,6 +69,8 @@ fn nonempty() { match_guarded_arm!(NonEmptyEnum1::Foo(true)); //~ ERROR `NonEmptyEnum1::Foo(_)` not covered match_guarded_arm!(NonEmptyEnum2::Foo(true)); //~ ERROR `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered match_guarded_arm!(NonEmptyEnum5::V1); //~ ERROR `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered + match_guarded_arm!(array0_of_empty); //~ ERROR `[]` not covered + match_guarded_arm!(arrayN_of_empty); //~ ERROR `[]` not covered } fn main() {} From e77612d3e4ff34d5096fbf7f8a1b9d3a4351770c Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 20 Mar 2024 22:51:29 +0100 Subject: [PATCH 720/786] Fixes in various places --- .../rustc_codegen_cranelift/example/mini_core_hello_world.rs | 1 + compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs | 1 + src/tools/clippy/clippy_utils/src/lib.rs | 1 + src/tools/clippy/tests/ui/single_match_else.fixed | 2 +- src/tools/clippy/tests/ui/single_match_else.rs | 2 +- src/tools/clippy/tests/ui/single_match_else.stderr | 4 ++-- src/tools/miri/src/eval.rs | 1 + src/tools/miri/tests/pass/async-fn.rs | 1 + src/tools/miri/tests/pass/enums.rs | 1 + src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs | 1 + src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs | 1 + 11 files changed, 12 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs index 7d361a9ab2bb6..e603ac566f4ec 100644 --- a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs +++ b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs @@ -585,6 +585,7 @@ pub enum E2 { V4, } +#[allow(unreachable_patterns)] fn check_niche_behavior() { if let E1::V2 { .. } = (E1::V1 { f: true }) { intrinsics::abort(); diff --git a/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs b/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs index 5a7ddc4cd7fa5..9f096e9022012 100644 --- a/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs +++ b/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs @@ -430,6 +430,7 @@ pub enum E2 { V4, } +#[allow(unreachable_patterns)] fn check_niche_behavior () { if let E1::V2 { .. } = (E1::V1 { f: true }) { intrinsics::abort(); diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index af74e4b67c162..28755ae0710ca 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -2931,6 +2931,7 @@ pub fn expr_use_ctxt<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> ExprU moved_before_use, same_ctxt, }, + #[allow(unreachable_patterns)] Some(ControlFlow::Break(_)) => unreachable!("type of node is ControlFlow"), None => ExprUseCtxt { node: Node::Crate(cx.tcx.hir().root_module()), diff --git a/src/tools/clippy/tests/ui/single_match_else.fixed b/src/tools/clippy/tests/ui/single_match_else.fixed index e840adf0fa34b..163be16ad8be7 100644 --- a/src/tools/clippy/tests/ui/single_match_else.fixed +++ b/src/tools/clippy/tests/ui/single_match_else.fixed @@ -89,7 +89,7 @@ fn main() { // lint here use std::convert::Infallible; - if let Ok(a) = Result::::Ok(1) { println!("${:?}", a) } else { + if let Ok(a) = Result::::Ok(1) { println!("${:?}", a) } else { println!("else block"); return; } diff --git a/src/tools/clippy/tests/ui/single_match_else.rs b/src/tools/clippy/tests/ui/single_match_else.rs index 430c4da20f12a..3f1fd2b31832f 100644 --- a/src/tools/clippy/tests/ui/single_match_else.rs +++ b/src/tools/clippy/tests/ui/single_match_else.rs @@ -98,7 +98,7 @@ fn main() { // lint here use std::convert::Infallible; - match Result::::Ok(1) { + match Result::::Ok(1) { Ok(a) => println!("${:?}", a), Err(_) => { println!("else block"); diff --git a/src/tools/clippy/tests/ui/single_match_else.stderr b/src/tools/clippy/tests/ui/single_match_else.stderr index f8f88379d6d12..61c348260d05e 100644 --- a/src/tools/clippy/tests/ui/single_match_else.stderr +++ b/src/tools/clippy/tests/ui/single_match_else.stderr @@ -64,7 +64,7 @@ LL + } error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` --> tests/ui/single_match_else.rs:101:5 | -LL | / match Result::::Ok(1) { +LL | / match Result::::Ok(1) { LL | | Ok(a) => println!("${:?}", a), LL | | Err(_) => { LL | | println!("else block"); @@ -75,7 +75,7 @@ LL | | } | help: try | -LL ~ if let Ok(a) = Result::::Ok(1) { println!("${:?}", a) } else { +LL ~ if let Ok(a) = Result::::Ok(1) { println!("${:?}", a) } else { LL + println!("else block"); LL + return; LL + } diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs index 1173da4697564..d781188cd0c2c 100644 --- a/src/tools/miri/src/eval.rs +++ b/src/tools/miri/src/eval.rs @@ -463,6 +463,7 @@ pub fn eval_entry<'tcx>( let res = match res { Err(res) => res, // `Ok` can never happen + #[cfg(bootstrap)] Ok(never) => match never {}, }; diff --git a/src/tools/miri/tests/pass/async-fn.rs b/src/tools/miri/tests/pass/async-fn.rs index 13400c88c7112..67ec2e26b3068 100644 --- a/src/tools/miri/tests/pass/async-fn.rs +++ b/src/tools/miri/tests/pass/async-fn.rs @@ -59,6 +59,7 @@ async fn hello_world() { } // This example comes from https://github.com/rust-lang/rust/issues/115145 +#[allow(unreachable_patterns)] async fn uninhabited_variant() { async fn unreachable(_: Never) {} diff --git a/src/tools/miri/tests/pass/enums.rs b/src/tools/miri/tests/pass/enums.rs index ac7aafc1bb2e3..1dafef025e958 100644 --- a/src/tools/miri/tests/pass/enums.rs +++ b/src/tools/miri/tests/pass/enums.rs @@ -43,6 +43,7 @@ fn discriminant_overflow() { } } +#[allow(unreachable_patterns)] fn more_discriminant_overflow() { pub enum Infallible {} diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs index bd43a62341d17..d76f53818716a 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs @@ -27,6 +27,7 @@ macro_rules! from_bytes { ($ty:tt, $value:expr) => { ($ty::from_le_bytes(match ($value).try_into() { Ok(it) => it, + #[allow(unreachable_patterns)] Err(_) => return Err(MirEvalError::InternalError("mismatched size".into())), })) }; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs index 057f553380567..9aa2eeebc1757 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs @@ -1161,6 +1161,7 @@ impl<'ctx> MirLowerCtx<'ctx> { ProjectionElem::OpaqueCast(it) => { ProjectionElem::OpaqueCast(it) } + #[allow(unreachable_patterns)] ProjectionElem::Index(it) => match it {}, }) .collect(), From f83b085a0c623652ec536e69fc98ae5ebffaca4c Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Wed, 7 Aug 2024 16:41:22 +0300 Subject: [PATCH 721/786] rustc_attr: remove redundant `#[allow(rustc::untranslatable_diagnostic)]` --- compiler/rustc_attr/src/builtin.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 12a19ae5c3db9..c0677ae117618 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -521,7 +521,6 @@ pub struct Condition { } /// Tests if a cfg-pattern matches the cfg set -#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable pub fn cfg_matches( cfg: &ast::MetaItem, sess: &Session, From 43f3a218eaa3eb7f4724b064102ad3374092c813 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Wed, 7 Aug 2024 18:28:52 +0300 Subject: [PATCH 722/786] rustc_const_eval: remove redundant `#[allow(rustc::untranslatable_diagnostic)]` --- compiler/rustc_const_eval/src/check_consts/ops.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index f47a2ec8f7598..063e12fc9ecb4 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -605,8 +605,6 @@ impl<'tcx> NonConstOp<'tcx> for StaticAccess { span, format!("referencing statics in {}s is unstable", ccx.const_kind(),), ); - // FIXME: make this translatable - #[allow(rustc::untranslatable_diagnostic)] err .note("`static` and `const` variables can refer to other `const` variables. A `const` variable, however, cannot refer to a `static` variable.") .help("to fix this, the value can be extracted to a `const` and then used."); From 3a18c6b55fa564bf94a0f6c8625e03e6910aca4f Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Wed, 7 Aug 2024 18:38:32 +0300 Subject: [PATCH 723/786] rustc_const_eval: make message about "const stable" translatable --- compiler/rustc_const_eval/messages.ftl | 2 ++ compiler/rustc_const_eval/src/check_consts/ops.rs | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index c64c73b232340..bf7144275eb3f 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -41,6 +41,8 @@ const_eval_const_context = {$kind -> *[other] {""} } +const_eval_const_stable = const-stable functions can only call other const-stable functions + const_eval_copy_nonoverlapping_overlapping = `copy_nonoverlapping` called on overlapping ranges diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index 063e12fc9ecb4..6bd1be1b70080 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -23,7 +23,7 @@ use rustc_trait_selection::traits::SelectionContext; use tracing::debug; use super::ConstCx; -use crate::errors; +use crate::{errors, fluent_generated}; #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Status { @@ -334,7 +334,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallUnstable { // FIXME: make this translatable #[allow(rustc::untranslatable_diagnostic)] if ccx.is_const_stable_const_fn() { - err.help("const-stable functions can only call other const-stable functions"); + err.help(fluent_generated::const_eval_const_stable); } else if ccx.tcx.sess.is_nightly_build() { if let Some(feature) = feature { err.help(format!("add `#![feature({feature})]` to the crate attributes to enable")); From a11922d56886147ab2a6600e0b647837e32f0f61 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Wed, 7 Aug 2024 18:42:55 +0300 Subject: [PATCH 724/786] rustc_const_eval: make LazyLock suggestion translatable --- compiler/rustc_const_eval/messages.ftl | 3 +++ compiler/rustc_const_eval/src/check_consts/ops.rs | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index bf7144275eb3f..1442f1832b9b5 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -203,6 +203,9 @@ const_eval_invalid_vtable_pointer = const_eval_invalid_vtable_trait = using vtable for trait `{$vtable_trait}` but trait `{$expected_trait}` was expected +const_eval_lazy_lock = + consider wrapping this expression in `std::sync::LazyLock::new(|| ...)` + const_eval_live_drop = destructor of `{$dropped_ty}` cannot be evaluated at compile-time .label = the destructor for this type cannot be evaluated in {const_eval_const_context}s diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index 6bd1be1b70080..c6361710ac9ca 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -310,7 +310,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { } if let ConstContext::Static(_) = ccx.const_kind() { - err.note("consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`"); + err.note(fluent_generated::const_eval_lazy_lock); } err From c36b21a4c8d91d34b6461a54acda090ffd8cdc75 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Wed, 7 Aug 2024 23:23:35 +0300 Subject: [PATCH 725/786] rustc_attr: make "compact `cfg(target(..))` is unstable" translatable --- compiler/rustc_attr/messages.ftl | 3 +++ compiler/rustc_attr/src/builtin.rs | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_attr/messages.ftl b/compiler/rustc_attr/messages.ftl index eb51e568f81a7..5d9ac23ec490e 100644 --- a/compiler/rustc_attr/messages.ftl +++ b/compiler/rustc_attr/messages.ftl @@ -104,6 +104,9 @@ attr_unknown_meta_item = attr_unknown_version_literal = unknown version literal format, assuming it refers to a future version +attr_unstable_cfg_target_compact = + compact `cfg(target(..))` is experimental and subject to change + attr_unsupported_literal_cfg_string = literal in `cfg` predicate value must be a string attr_unsupported_literal_deprecated_kv_pair = diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index c0677ae117618..f55bed25c6da8 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -20,6 +20,7 @@ use rustc_span::hygiene::Transparency; use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; +use crate::fluent_generated; use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause}; /// The version placeholder that recently stabilized features contain inside the @@ -592,7 +593,6 @@ pub fn parse_version(s: Symbol) -> Option { /// Evaluate a cfg-like condition (with `any` and `all`), using `eval` to /// evaluate individual items. -#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable pub fn eval_condition( cfg: &ast::MetaItem, sess: &Session, @@ -679,7 +679,7 @@ pub fn eval_condition( sess, sym::cfg_target_compact, cfg.span, - "compact `cfg(target(..))` is experimental and subject to change", + fluent_generated::attr_unstable_cfg_target_compact, ) .emit(); } From 334a097137ebcf319d02a6fb54777ce2002dbe35 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Wed, 7 Aug 2024 23:27:31 +0300 Subject: [PATCH 726/786] rustc_ast_lowering: make "using `_` for array lengths is unstable" translatable --- compiler/rustc_ast_lowering/messages.ftl | 3 +++ compiler/rustc_ast_lowering/src/lib.rs | 3 +-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl index 9ed93d481e773..9e4d5a3b88aa2 100644 --- a/compiler/rustc_ast_lowering/messages.ftl +++ b/compiler/rustc_ast_lowering/messages.ftl @@ -167,6 +167,9 @@ ast_lowering_template_modifier = template modifier ast_lowering_this_not_async = this is not `async` +ast_lowering_underscore_array_length_unstable = + using `_` for array lengths is unstable + ast_lowering_underscore_expr_lhs_assign = in expressions, `_` can only be used on the left-hand side of an assignment .label = `_` not allowed here diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 224787c335beb..81d17a9dec205 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2326,7 +2326,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.expr_block(block) } - #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn lower_array_length(&mut self, c: &AnonConst) -> hir::ArrayLen<'hir> { match c.value.kind { ExprKind::Underscore => { @@ -2340,7 +2339,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &self.tcx.sess, sym::generic_arg_infer, c.value.span, - "using `_` for array lengths is unstable", + fluent_generated::ast_lowering_underscore_array_length_unstable, ) .stash(c.value.span, StashKey::UnderscoreForArrayLengths); hir::ArrayLen::Body(self.lower_anon_const_to_const_arg(c)) From 290df4fa5613d3d6cce717509219b18870e3ff86 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Wed, 7 Aug 2024 23:31:59 +0300 Subject: [PATCH 727/786] rustc_ast_lowering: make "yield syntax is experimental" translatable --- compiler/rustc_ast_lowering/messages.ftl | 2 ++ compiler/rustc_ast_lowering/src/expr.rs | 7 +++---- tests/ui/coroutine/gen_block.none.stderr | 2 -- tests/ui/feature-gates/feature-gate-coroutines.none.stderr | 2 -- 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl index 9e4d5a3b88aa2..efee5a9d32da0 100644 --- a/compiler/rustc_ast_lowering/messages.ftl +++ b/compiler/rustc_ast_lowering/messages.ftl @@ -175,6 +175,8 @@ ast_lowering_underscore_expr_lhs_assign = .label = `_` not allowed here ast_lowering_use_angle_brackets = use angle brackets instead + +ast_lowering_yield = yield syntax is experimental ast_lowering_yield_in_closure = `yield` can only be used in `#[coroutine]` closures, or `gen` blocks .suggestion = use `#[coroutine]` to make this closure a coroutine diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 124fe6bd380d2..b5d8a547a8fb9 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -23,7 +23,7 @@ use super::{ ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs, ResolverAstLoweringExt, }; use crate::errors::YieldInClosure; -use crate::{FnDeclKind, ImplTraitPosition}; +use crate::{fluent_generated, FnDeclKind, ImplTraitPosition}; impl<'hir> LoweringContext<'_, 'hir> { fn lower_exprs(&mut self, exprs: &[AstP]) -> &'hir [hir::Expr<'hir>] { @@ -1540,7 +1540,6 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn lower_expr_yield(&mut self, span: Span, opt_expr: Option<&Expr>) -> hir::ExprKind<'hir> { let yielded = opt_expr.as_ref().map(|x| self.lower_expr(x)).unwrap_or_else(|| self.expr_unit(span)); @@ -1575,7 +1574,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &self.tcx.sess, sym::coroutines, span, - "yield syntax is experimental", + fluent_generated::ast_lowering_yield, ) .emit(); } @@ -1587,7 +1586,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &self.tcx.sess, sym::coroutines, span, - "yield syntax is experimental", + fluent_generated::ast_lowering_yield, ) .emit(); } diff --git a/tests/ui/coroutine/gen_block.none.stderr b/tests/ui/coroutine/gen_block.none.stderr index 64fa2be003de5..15123a49e4855 100644 --- a/tests/ui/coroutine/gen_block.none.stderr +++ b/tests/ui/coroutine/gen_block.none.stderr @@ -73,7 +73,6 @@ LL | let _ = || yield true; = note: see issue #43122 for more information = help: add `#![feature(coroutines)]` 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: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks --> $DIR/gen_block.rs:16:16 @@ -95,7 +94,6 @@ LL | let _ = #[coroutine] || yield true; = note: see issue #43122 for more information = help: add `#![feature(coroutines)]` 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: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 11 previous errors diff --git a/tests/ui/feature-gates/feature-gate-coroutines.none.stderr b/tests/ui/feature-gates/feature-gate-coroutines.none.stderr index 65e7737ef84d5..032d7adf77ab8 100644 --- a/tests/ui/feature-gates/feature-gate-coroutines.none.stderr +++ b/tests/ui/feature-gates/feature-gate-coroutines.none.stderr @@ -47,7 +47,6 @@ LL | yield true; = note: see issue #43122 for more information = help: add `#![feature(coroutines)]` 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: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks --> $DIR/feature-gate-coroutines.rs:5:5 @@ -69,7 +68,6 @@ LL | let _ = || yield true; = note: see issue #43122 for more information = help: add `#![feature(coroutines)]` 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: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks --> $DIR/feature-gate-coroutines.rs:10:16 From 67602980de67450b051c96ab97c63a5728d396dd Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Wed, 7 Aug 2024 23:38:08 +0300 Subject: [PATCH 728/786] rustc_ast_lowering: make asm-related unstability messages translatable --- compiler/rustc_ast_lowering/messages.ftl | 7 +++++++ compiler/rustc_ast_lowering/src/asm.rs | 21 ++++++++++++++------- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl index efee5a9d32da0..0a7f75039f64d 100644 --- a/compiler/rustc_ast_lowering/messages.ftl +++ b/compiler/rustc_ast_lowering/messages.ftl @@ -174,6 +174,13 @@ ast_lowering_underscore_expr_lhs_assign = in expressions, `_` can only be used on the left-hand side of an assignment .label = `_` not allowed here +ast_lowering_unstable_inline_assembly = inline assembly is not stable yet on this architecture +ast_lowering_unstable_inline_assembly_const_operands = + const operands for inline assembly are unstable +ast_lowering_unstable_inline_assembly_label_operands = + label operands for inline assembly are unstable +ast_lowering_unstable_may_unwind = the `may_unwind` option is unstable + ast_lowering_use_angle_brackets = use angle brackets instead ast_lowering_yield = yield syntax is experimental diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index ea7b8c114f490..8acca78379b2e 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -19,10 +19,12 @@ use super::errors::{ InvalidRegisterClass, RegisterClassOnlyClobber, RegisterConflict, }; use super::LoweringContext; -use crate::{ImplTraitContext, ImplTraitPosition, ParamMode, ResolverAstLoweringExt}; +use crate::{ + fluent_generated as fluent, ImplTraitContext, ImplTraitPosition, ParamMode, + ResolverAstLoweringExt, +}; impl<'a, 'hir> LoweringContext<'a, 'hir> { - #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable pub(crate) fn lower_inline_asm( &mut self, sp: Span, @@ -52,7 +54,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &self.tcx.sess, sym::asm_experimental_arch, sp, - "inline assembly is not stable yet on this architecture", + fluent::ast_lowering_unstable_inline_assembly, ) .emit(); } @@ -64,8 +66,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.dcx().emit_err(AttSyntaxOnlyX86 { span: sp }); } if asm.options.contains(InlineAsmOptions::MAY_UNWIND) && !self.tcx.features().asm_unwind { - feature_err(&self.tcx.sess, sym::asm_unwind, sp, "the `may_unwind` option is unstable") - .emit(); + feature_err( + &self.tcx.sess, + sym::asm_unwind, + sp, + fluent::ast_lowering_unstable_may_unwind, + ) + .emit(); } let mut clobber_abis = FxIndexMap::default(); @@ -182,7 +189,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { sess, sym::asm_const, *op_sp, - "const operands for inline assembly are unstable", + fluent::ast_lowering_unstable_inline_assembly_const_operands, ) .emit(); } @@ -246,7 +253,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { sess, sym::asm_goto, *op_sp, - "label operands for inline assembly are unstable", + fluent::ast_lowering_unstable_inline_assembly_label_operands, ) .emit(); } From 48413cf0783efb03c713ccc98151c3316344e22a Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Thu, 8 Aug 2024 23:54:09 +0300 Subject: [PATCH 729/786] rustc_borrowck: make dereference suggestion translatable --- compiler/rustc_borrowck/messages.ftl | 3 +++ compiler/rustc_borrowck/src/diagnostics/region_errors.rs | 5 ++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_borrowck/messages.ftl b/compiler/rustc_borrowck/messages.ftl index c14a617eb91fe..2b1c82a461eaf 100644 --- a/compiler/rustc_borrowck/messages.ftl +++ b/compiler/rustc_borrowck/messages.ftl @@ -62,6 +62,9 @@ borrowck_could_not_normalize = borrowck_could_not_prove = could not prove `{$predicate}` +borrowck_dereference_suggestion = + dereference the return value + borrowck_func_take_self_moved_place = `{$func}` takes ownership of the receiver `self`, which moves {$place_name} diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 82df9760d8e7c..6b6c7911d76df 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -35,7 +35,7 @@ use crate::session_diagnostics::{ LifetimeReturnCategoryErr, RequireStaticErr, VarHereDenote, }; use crate::universal_regions::DefiningTy; -use crate::{borrowck_errors, MirBorrowckCtxt}; +use crate::{borrowck_errors, fluent_generated, MirBorrowckCtxt}; impl<'tcx> ConstraintDescription for ConstraintCategory<'tcx> { fn description(&self) -> &'static str { @@ -1045,7 +1045,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { } #[allow(rustc::diagnostic_outside_of_impl)] - #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable /// When encountering a lifetime error caused by the return type of a closure, check the /// corresponding trait bound and see if dereferencing the closure return value would satisfy /// them. If so, we produce a structured suggestion. @@ -1166,7 +1165,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { if ocx.select_all_or_error().is_empty() && count > 0 { diag.span_suggestion_verbose( tcx.hir().body(*body).value.peel_blocks().span.shrink_to_lo(), - "dereference the return value", + fluent_generated::borrowck_dereference_suggestion, "*".repeat(count), Applicability::MachineApplicable, ); From 446e03e3c92dedcf90aea3069e40d19dae6772f2 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Thu, 8 Aug 2024 23:58:42 +0300 Subject: [PATCH 730/786] rustc_borrowck: make suggestion to move closure translatable --- compiler/rustc_borrowck/messages.ftl | 3 +++ compiler/rustc_borrowck/src/diagnostics/region_errors.rs | 3 +-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_borrowck/messages.ftl b/compiler/rustc_borrowck/messages.ftl index 2b1c82a461eaf..090bd2293d3a7 100644 --- a/compiler/rustc_borrowck/messages.ftl +++ b/compiler/rustc_borrowck/messages.ftl @@ -80,6 +80,9 @@ borrowck_higher_ranked_subtype_error = borrowck_lifetime_constraints_error = lifetime may not live long enough +borrowck_move_closure_suggestion = + consider adding 'move' keyword before the nested closure + borrowck_move_out_place_here = {$place} is moved here diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 6b6c7911d76df..74c74de340479 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -1173,7 +1173,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { } #[allow(rustc::diagnostic_outside_of_impl)] - #[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 = map.body_owned_by(self.mir_def_id()); @@ -1212,7 +1211,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { if let Some(closure_span) = closure_span { diag.span_suggestion_verbose( closure_span, - "consider adding 'move' keyword before the nested closure", + fluent_generated::borrowck_move_closure_suggestion, "move ", Applicability::MaybeIncorrect, ); From 1b6cc24c20557e1a34a5c889bd771924d5c572c5 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Fri, 9 Aug 2024 00:12:41 +0300 Subject: [PATCH 731/786] rustc_borrowck: make some suggestion about static lifetimes translatable --- compiler/rustc_borrowck/messages.ftl | 6 ++++++ compiler/rustc_borrowck/src/diagnostics/region_errors.rs | 5 ++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_borrowck/messages.ftl b/compiler/rustc_borrowck/messages.ftl index 090bd2293d3a7..7eed4e379c843 100644 --- a/compiler/rustc_borrowck/messages.ftl +++ b/compiler/rustc_borrowck/messages.ftl @@ -80,6 +80,9 @@ borrowck_higher_ranked_subtype_error = borrowck_lifetime_constraints_error = lifetime may not live long enough +borrowck_limitations_implies_static = + due to current limitations in the borrow checker, this implies a `'static` lifetime + borrowck_move_closure_suggestion = consider adding 'move' keyword before the nested closure @@ -169,6 +172,9 @@ borrowck_partial_var_move_by_use_in_coroutine = *[false] moved } due to use in coroutine +borrowck_restrict_to_static = + consider restricting the type parameter to the `'static` lifetime + borrowck_returned_async_block_escaped = returns an `async` block that contains a reference to a captured variable, which then escapes the closure body diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 74c74de340479..fe2a575ba8bb3 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -198,7 +198,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { // from higher-ranked trait bounds (HRTB). Try to locate span of the trait // and the span which bounded to the trait for adding 'static lifetime suggestion #[allow(rustc::diagnostic_outside_of_impl)] - #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn suggest_static_lifetime_for_gat_from_hrtb( &self, diag: &mut Diag<'_>, @@ -254,7 +253,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { let Trait(PolyTraitRef { trait_ref, span: trait_span, .. }, _) = bound else { return; }; diag.span_note( *trait_span, - "due to current limitations in the borrow checker, this implies a `'static` lifetime" + fluent_generated::borrowck_limitations_implies_static, ); let Some(generics_fn) = hir.get_generics(self.body.source.def_id().expect_local()) else { return; }; let Def(_, trait_res_defid) = trait_ref.path.res else { return; }; @@ -286,7 +285,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { if suggestions.len() > 0 { suggestions.dedup(); diag.multipart_suggestion_verbose( - "consider restricting the type parameter to the `'static` lifetime", + fluent_generated::borrowck_restrict_to_static, suggestions, Applicability::MaybeIncorrect, ); From 1481ab3f75573848a62a492b177054e8a96badfe Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Fri, 9 Aug 2024 00:21:00 +0300 Subject: [PATCH 732/786] rustc_borrowck: make "implicit static" suff translatable --- compiler/rustc_borrowck/messages.ftl | 9 +++++++++ compiler/rustc_borrowck/src/diagnostics/region_errors.rs | 7 +++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_borrowck/messages.ftl b/compiler/rustc_borrowck/messages.ftl index 7eed4e379c843..edb25e12864bc 100644 --- a/compiler/rustc_borrowck/messages.ftl +++ b/compiler/rustc_borrowck/messages.ftl @@ -77,6 +77,15 @@ borrowck_higher_ranked_lifetime_error = borrowck_higher_ranked_subtype_error = higher-ranked subtype error +borrowck_implicit_static = + this has an implicit `'static` lifetime requirement + +borrowck_implicit_static_introduced = + calling this method introduces the `impl`'s `'static` requirement + +borrowck_implicit_static_relax = + consider relaxing the implicit `'static` requirement + borrowck_lifetime_constraints_error = lifetime may not live long enough diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index fe2a575ba8bb3..a0be17e8b515a 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -975,7 +975,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { } #[allow(rustc::diagnostic_outside_of_impl)] - #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable #[instrument(skip(self, err), level = "debug")] fn suggest_constrain_dyn_trait_in_impl( &self, @@ -994,15 +993,15 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { for span in &traits { let mut multi_span: MultiSpan = vec![*span].into(); multi_span - .push_span_label(*span, "this has an implicit `'static` lifetime requirement"); + .push_span_label(*span, fluent_generated::borrowck_implicit_static); multi_span.push_span_label( ident.span, - "calling this method introduces the `impl`'s `'static` requirement", + fluent_generated::borrowck_implicit_static_introduced, ); err.subdiagnostic(RequireStaticErr::UsedImpl { multi_span }); err.span_suggestion_verbose( span.shrink_to_hi(), - "consider relaxing the implicit `'static` requirement", + fluent_generated::borrowck_implicit_static_relax, " + '_", Applicability::MaybeIncorrect, ); From f43cdcea221c208216b9fb200d280324c4c92405 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Fri, 9 Aug 2024 00:24:11 +0300 Subject: [PATCH 733/786] rustc_borrowck: fmt --- .../src/diagnostics/region_errors.rs | 60 ++++++++++--------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index a0be17e8b515a..451e8bcb16da4 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -35,7 +35,7 @@ use crate::session_diagnostics::{ LifetimeReturnCategoryErr, RequireStaticErr, VarHereDenote, }; use crate::universal_regions::DefiningTy; -use crate::{borrowck_errors, fluent_generated, MirBorrowckCtxt}; +use crate::{borrowck_errors, fluent_generated as fluent, MirBorrowckCtxt}; impl<'tcx> ConstraintDescription for ConstraintCategory<'tcx> { fn description(&self) -> &'static str { @@ -250,23 +250,28 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { debug!(?hrtb_bounds); hrtb_bounds.iter().for_each(|bound| { - let Trait(PolyTraitRef { trait_ref, span: trait_span, .. }, _) = bound else { return; }; - diag.span_note( - *trait_span, - fluent_generated::borrowck_limitations_implies_static, - ); - let Some(generics_fn) = hir.get_generics(self.body.source.def_id().expect_local()) else { return; }; - let Def(_, trait_res_defid) = trait_ref.path.res else { return; }; + let Trait(PolyTraitRef { trait_ref, span: trait_span, .. }, _) = bound else { + return; + }; + diag.span_note(*trait_span, fluent::borrowck_limitations_implies_static); + let Some(generics_fn) = hir.get_generics(self.body.source.def_id().expect_local()) + else { + return; + }; + let Def(_, trait_res_defid) = trait_ref.path.res else { + return; + }; debug!(?generics_fn); generics_fn.predicates.iter().for_each(|predicate| { - let BoundPredicate( - WhereBoundPredicate { - span: bounded_span, - bounded_ty, - bounds, - .. - } - ) = predicate else { return; }; + let BoundPredicate(WhereBoundPredicate { + span: bounded_span, + bounded_ty, + bounds, + .. + }) = predicate + else { + return; + }; bounds.iter().for_each(|bd| { if let Trait(PolyTraitRef { trait_ref: tr_ref, .. }, _) = bd && let Def(_, res_defid) = tr_ref.path.res @@ -276,16 +281,17 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { && generics_fn.params .iter() .rfind(|param| param.def_id.to_def_id() == defid) - .is_some() { - suggestions.push((bounded_span.shrink_to_hi(), " + 'static".to_string())); - } + .is_some() + { + suggestions.push((bounded_span.shrink_to_hi(), " + 'static".to_string())); + } }); }); }); if suggestions.len() > 0 { suggestions.dedup(); diag.multipart_suggestion_verbose( - fluent_generated::borrowck_restrict_to_static, + fluent::borrowck_restrict_to_static, suggestions, Applicability::MaybeIncorrect, ); @@ -992,16 +998,12 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { debug!("trait spans found: {:?}", traits); for span in &traits { let mut multi_span: MultiSpan = vec![*span].into(); - multi_span - .push_span_label(*span, fluent_generated::borrowck_implicit_static); - multi_span.push_span_label( - ident.span, - fluent_generated::borrowck_implicit_static_introduced, - ); + multi_span.push_span_label(*span, fluent::borrowck_implicit_static); + multi_span.push_span_label(ident.span, fluent::borrowck_implicit_static_introduced); err.subdiagnostic(RequireStaticErr::UsedImpl { multi_span }); err.span_suggestion_verbose( span.shrink_to_hi(), - fluent_generated::borrowck_implicit_static_relax, + fluent::borrowck_implicit_static_relax, " + '_", Applicability::MaybeIncorrect, ); @@ -1163,7 +1165,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { if ocx.select_all_or_error().is_empty() && count > 0 { diag.span_suggestion_verbose( tcx.hir().body(*body).value.peel_blocks().span.shrink_to_lo(), - fluent_generated::borrowck_dereference_suggestion, + fluent::borrowck_dereference_suggestion, "*".repeat(count), Applicability::MachineApplicable, ); @@ -1209,7 +1211,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> { if let Some(closure_span) = closure_span { diag.span_suggestion_verbose( closure_span, - fluent_generated::borrowck_move_closure_suggestion, + fluent::borrowck_move_closure_suggestion, "move ", Applicability::MaybeIncorrect, ); From fbc245901561ac46ecd8011442e8e07fcfbeeea9 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Fri, 9 Aug 2024 00:51:08 +0300 Subject: [PATCH 734/786] rustc_expand: remove some redundant `#[allow(rustc::untranslatable_diagnostic)]` --- compiler/rustc_expand/src/base.rs | 2 -- compiler/rustc_expand/src/expand.rs | 1 - 2 files changed, 3 deletions(-) diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index c195d69258899..5bc41d9836df7 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1398,8 +1398,6 @@ fn pretty_printing_compatibility_hack(item: &Item, sess: &Session) { }; if crate_matches { - // FIXME: make this translatable - #[allow(rustc::untranslatable_diagnostic)] sess.dcx().emit_fatal(errors::ProcMacroBackCompat { crate_name: "rental".to_string(), fixed_version: "0.5.6".to_string(), diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index d8cb367e3face..b8f0a2aa7dcc0 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1876,7 +1876,6 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { // Detect use of feature-gated or invalid attributes on macro invocations // since they will not be detected after macro expansion. - #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn check_attributes(&self, attrs: &[ast::Attribute], call: &ast::MacCall) { let features = self.cx.ecfg.features; let mut attrs = attrs.iter().peekable(); From 137307477f99d9119cd9d426d4789cc238f28757 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Fri, 9 Aug 2024 00:53:15 +0300 Subject: [PATCH 735/786] rustc_expand: make a message translatable --- compiler/rustc_expand/messages.ftl | 3 +++ compiler/rustc_expand/src/expand.rs | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl index 18d95a398fd4f..766d96e268f04 100644 --- a/compiler/rustc_expand/messages.ftl +++ b/compiler/rustc_expand/messages.ftl @@ -129,6 +129,9 @@ expand_module_multiple_candidates = expand_must_repeat_once = this must repeat at least once +expand_non_inline_modules_in_proc_macro_input_are_unstable = + non-inline modules in proc macro input are unstable + expand_not_a_meta_item = not a meta item diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index b8f0a2aa7dcc0..37679e17b90a8 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -39,6 +39,7 @@ use crate::errors::{ RecursionLimitReached, RemoveExprNotSupported, RemoveNodeNotSupported, UnsupportedKeyValue, WrongFragmentKind, }; +use crate::fluent_generated; use crate::mbe::diagnostics::annotate_err_with_kind; use crate::module::{mod_dir_path, parse_external_mod, DirOwnership, ParsedExternalMod}; use crate::placeholders::{placeholder, PlaceholderExpander}; @@ -882,7 +883,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } impl<'ast, 'a> Visitor<'ast> for GateProcMacroInput<'a> { - #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn visit_item(&mut self, item: &'ast ast::Item) { match &item.kind { ItemKind::Mod(_, mod_kind) @@ -892,7 +892,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { self.sess, sym::proc_macro_hygiene, item.span, - "non-inline modules in proc macro input are unstable", + fluent_generated::expand_non_inline_modules_in_proc_macro_input_are_unstable, ) .emit(); } From cbae581bb0c9d4f0b25e744ca2e4608ff615dd4c Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Fri, 9 Aug 2024 00:56:50 +0300 Subject: [PATCH 736/786] rustc_interface: remove a redundant `#[allow(rustc::untranslatable_diagnostic)]` --- compiler/rustc_interface/src/util.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 6f53b1c90313b..761d288a7c2eb 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -386,7 +386,6 @@ fn get_codegen_sysroot( } } -#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable pub(crate) fn check_attr_crate_type( sess: &Session, attrs: &[ast::Attribute], From 2babab6e438277a7a2644ee2994ae50c2393ccb1 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Fri, 9 Aug 2024 01:03:45 +0300 Subject: [PATCH 737/786] rustc_lint: remove some redundant `#[allow(rustc::untranslatable_diagnostic)]` --- compiler/rustc_lint/src/levels.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 72920fd045fd4..44117e5d7a573 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -717,7 +717,6 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { }; } - #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn add(&mut self, attrs: &[ast::Attribute], is_crate_node: bool, source_hir_id: Option) { let sess = self.sess; for (attr_index, attr) in attrs.iter().enumerate() { @@ -1039,7 +1038,6 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { let (level, src) = self.lint_level(builtin::UNKNOWN_LINTS); // FIXME: make this translatable #[allow(rustc::diagnostic_outside_of_impl)] - #[allow(rustc::untranslatable_diagnostic)] lint_level(self.sess, lint, level, src, Some(span.into()), |lint| { lint.primary_message(fluent::lint_unknown_gated_lint); lint.arg("name", lint_id.lint.name_lower()); From d5486360ae21121050ca2539e3b26b3a9b50a571 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Fri, 9 Aug 2024 01:08:55 +0300 Subject: [PATCH 738/786] rustc_metadata: remove a redundant `#[allow(rustc::untranslatable_diagnostic)]` --- compiler/rustc_metadata/src/creader.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 2fca443ffa035..14a1a7f67e56e 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -949,7 +949,6 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } } - #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn report_unused_deps(&mut self, krate: &ast::Crate) { // Make a point span rather than covering the whole file let span = krate.spans.inner_span.shrink_to_lo(); From 007cc2c23a058efb9c4db5233478f458cfe9ccfe Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Fri, 9 Aug 2024 01:22:25 +0300 Subject: [PATCH 739/786] rustc_metadata: make "link {arg,cfg} is unstable" translatable --- compiler/rustc_metadata/messages.ftl | 6 ++++++ compiler/rustc_metadata/src/native_libs.rs | 16 +++++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl index 415399ed06c7f..590bde8fef569 100644 --- a/compiler/rustc_metadata/messages.ftl +++ b/compiler/rustc_metadata/messages.ftl @@ -131,12 +131,18 @@ metadata_lib_framework_apple = metadata_lib_required = crate `{$crate_name}` required to be available in {$kind} format, but was not found in this form +metadata_link_arg_unstable = + link kind `link-arg` is unstable + metadata_link_cfg_form = link cfg must be of the form `cfg(/* predicate */)` metadata_link_cfg_single_predicate = link cfg must have a single predicate argument +metadata_link_cfg_unstable = + link cfg is unstable + metadata_link_framework_apple = link kind `framework` is only supported on Apple targets diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index b19493d12ff33..34497f5ac53f8 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -17,7 +17,7 @@ use rustc_span::def_id::{DefId, LOCAL_CRATE}; use rustc_span::symbol::{sym, Symbol}; use rustc_target::spec::abi::Abi; -use crate::errors; +use crate::{errors, fluent_generated}; pub fn find_native_static_library(name: &str, verbatim: bool, sess: &Session) -> PathBuf { let formats = if verbatim { @@ -87,7 +87,6 @@ struct Collector<'tcx> { } impl<'tcx> Collector<'tcx> { - #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn process_module(&mut self, module: &ForeignModule) { let ForeignModule { def_id, abi, ref foreign_items } = *module; let def_id = def_id.expect_local(); @@ -161,7 +160,7 @@ impl<'tcx> Collector<'tcx> { sess, sym::link_arg_attribute, span, - "link kind `link-arg` is unstable", + fluent_generated::metadata_link_arg_unstable, ) .emit(); } @@ -201,8 +200,13 @@ impl<'tcx> Collector<'tcx> { continue; }; if !features.link_cfg { - feature_err(sess, sym::link_cfg, item.span(), "link cfg is unstable") - .emit(); + feature_err( + sess, + sym::link_cfg, + item.span(), + fluent_generated::metadata_link_cfg_unstable, + ) + .emit(); } cfg = Some(link_cfg.clone()); } @@ -266,6 +270,8 @@ impl<'tcx> Collector<'tcx> { macro report_unstable_modifier($feature: ident) { if !features.$feature { + // FIXME: make this translatable + #[expect(rustc::untranslatable_diagnostic)] feature_err( sess, sym::$feature, From fcdb37435af3b7e758f9380ab2565ea58d8460c8 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Fri, 9 Aug 2024 18:22:41 +0300 Subject: [PATCH 740/786] rustc_passes: remove a redundant `#[allow(rustc::untranslatable_diagnostic)]` --- compiler/rustc_passes/src/entry.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs index 48f55d4c3a0d5..ecb345bb51a49 100644 --- a/compiler/rustc_passes/src/entry.rs +++ b/compiler/rustc_passes/src/entry.rs @@ -106,7 +106,6 @@ fn check_and_search_item(id: ItemId, ctxt: &mut EntryContext<'_>) { } } -#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId, EntryFnType)> { if let Some((def_id, _)) = visitor.start_fn { Some((def_id.to_def_id(), EntryFnType::Start)) From f09a2b047d9a62610f8c1731c75255d7fbb5b2f3 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Fri, 9 Aug 2024 18:22:21 +0300 Subject: [PATCH 741/786] rustc_passes: make some messages in check_attr translatable --- compiler/rustc_passes/messages.ftl | 6 ++++++ compiler/rustc_passes/src/check_attr.rs | 6 ++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 59c9d1e49f5b3..0318d34fb7322 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -223,6 +223,9 @@ passes_doc_masked_only_extern_crate = .not_an_extern_crate_label = not an `extern crate` item .note = read for more information +passes_doc_rust_logo = + the `#[doc(rust_logo)]` attribute is used for Rust branding + passes_doc_test_literal = `#![doc(test(...)]` does not take a literal passes_doc_test_takes_list = @@ -595,6 +598,9 @@ passes_remove_fields = *[other] fields } +passes_repr_align_function = + `repr(align)` attributes on functions are unstable + passes_repr_conflicting = conflicting representation hints diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index c8d4c190113b2..9e6b32685e6f8 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1142,7 +1142,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { /// of one item. Read the documentation of [`check_doc_inline`] for more information. /// /// [`check_doc_inline`]: Self::check_doc_inline - #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn check_doc_attrs( &self, attr: &Attribute, @@ -1220,7 +1219,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { &self.tcx.sess, sym::rustdoc_internals, meta.span(), - "the `#[doc(rust_logo)]` attribute is used for Rust branding", + fluent::passes_doc_rust_logo, ) .emit(); } @@ -1736,7 +1735,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } /// Checks if the `#[repr]` attributes on `item` are valid. - #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable fn check_repr( &self, attrs: &[Attribute], @@ -1793,7 +1791,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { &self.tcx.sess, sym::fn_align, hint.span(), - "`repr(align)` attributes on functions are unstable", + fluent::passes_repr_align_function, ) .emit(); } From 217ee32ac7f9f2f1cccd0b99360229a52c5948ea Mon Sep 17 00:00:00 2001 From: bohan Date: Fri, 9 Aug 2024 18:33:20 +0800 Subject: [PATCH 742/786] rm `import.used` --- compiler/rustc_resolve/src/build_reduced_graph.rs | 8 ++++---- compiler/rustc_resolve/src/check_unused.rs | 6 +++--- compiler/rustc_resolve/src/imports.rs | 5 ++--- compiler/rustc_resolve/src/lib.rs | 12 +++++++----- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 307625bcfb17c..d57dabdd78d91 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -374,7 +374,6 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { root_span, root_id, vis, - used: Default::default(), }); self.r.indeterminate_imports.push(import); @@ -890,8 +889,10 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { span: item.span, module_path: Vec::new(), vis, - used: Cell::new(used.then_some(Used::Other)), }); + if used { + self.r.import_use_map.insert(import, Used::Other); + } self.r.potentially_unused_imports.push(import); let imported_binding = self.r.import(binding, import); if parent == self.r.graph_root { @@ -1091,7 +1092,6 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { span, module_path: Vec::new(), vis: ty::Visibility::Restricted(CRATE_DEF_ID), - used: Default::default(), }) }; @@ -1256,8 +1256,8 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { span, module_path: Vec::new(), vis, - used: Cell::new(Some(Used::Other)), }); + self.r.import_use_map.insert(import, Used::Other); let import_binding = self.r.import(binding, import); self.r.define(self.r.graph_root, ident, MacroNS, import_binding); } else { diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index 75b8ecebdd914..1cee876b80fea 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -381,9 +381,9 @@ impl Resolver<'_, '_> { for import in self.potentially_unused_imports.iter() { match import.kind { - _ if import.used.get().is_some() - || import.vis.is_public() - || import.span.is_dummy() => + _ if import.vis.is_public() + || import.span.is_dummy() + || self.import_use_map.contains_key(import) => { if let ImportKind::MacroUse { .. } = import.kind { if !import.span.is_dummy() { diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 4a891d12281c4..42171edf75749 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -176,7 +176,6 @@ pub(crate) struct ImportData<'a> { /// The resolution of `module_path`. pub imported_module: Cell>>, pub vis: ty::Visibility, - pub used: Cell>, } /// All imports are unique and allocated on a same arena, @@ -484,7 +483,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }); self.record_use(target, dummy_binding, Used::Other); } else if import.imported_module.get().is_none() { - import.used.set(Some(Used::Other)); + self.import_use_map.insert(import, Used::Other); if let Some(id) = import.id() { self.used_imports.insert(id); } @@ -1347,7 +1346,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // module defined by a block). // Skip if the import is public or was used through non scope-based resolution, // e.g. through a module-relative path. - if import.used.get() == Some(Used::Other) + if self.import_use_map.get(&import) == Some(&Used::Other) || self.effective_visibilities.is_exported(self.local_def_id(id)) { return false; diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 89ac839651fb1..02fdc1ae6685e 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1016,6 +1016,8 @@ pub struct Resolver<'a, 'tcx> { partial_res_map: NodeMap, /// Resolutions for import nodes, which have multiple resolutions in different namespaces. import_res_map: NodeMap>>, + /// An import will be inserted into this map if it has been used. + import_use_map: FxHashMap, Used>, /// Resolutions for labels (node IDs of their corresponding blocks or loops). label_res_map: NodeMap, /// Resolutions for lifetimes. @@ -1422,6 +1424,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pat_span_map: Default::default(), partial_res_map: Default::default(), import_res_map: Default::default(), + import_use_map: Default::default(), label_res_map: Default::default(), lifetimes_res_map: Default::default(), extra_lifetime_params_map: Default::default(), @@ -1839,7 +1842,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } /// Test if AmbiguityError ambi is any identical to any one inside ambiguity_errors - fn matches_previous_ambiguity_error(&mut self, ambi: &AmbiguityError<'_>) -> bool { + fn matches_previous_ambiguity_error(&self, ambi: &AmbiguityError<'_>) -> bool { for ambiguity_error in &self.ambiguity_errors { // if the span location and ident as well as its span are the same if ambiguity_error.kind == ambi.kind @@ -1900,10 +1903,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } } - let old_used = import.used.get(); - let new_used = Some(used); - if new_used > old_used { - import.used.set(new_used); + let old_used = self.import_use_map.entry(import).or_insert(used); + if *old_used < used { + *old_used = used; } if let Some(id) = import.id() { self.used_imports.insert(id); From 6a90be31b13753b66e423dd8dc567fd301043b0f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 10 Aug 2024 15:03:24 +0200 Subject: [PATCH 743/786] Stop showing impl items for negative impls --- src/librustdoc/clean/types.rs | 4 ++++ src/librustdoc/html/format.rs | 5 ++--- src/librustdoc/html/render/mod.rs | 37 ++++++++++++++++++------------- 3 files changed, 27 insertions(+), 19 deletions(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 4850500a1bfae..ff5c16f2b3e9a 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -2446,6 +2446,10 @@ impl Impl { .map(|did| tcx.provided_trait_methods(did).map(|meth| meth.name).collect()) .unwrap_or_default() } + + pub(crate) fn is_negative_trait_impl(&self) -> bool { + matches!(self.polarity, ty::ImplPolarity::Negative) + } } #[derive(Clone, Debug)] diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index b5ab6a35fdb9d..6357cfee141fd 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1285,9 +1285,8 @@ impl clean::Impl { f.write_str(" ")?; if let Some(ref ty) = self.trait_ { - match self.polarity { - ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => {} - ty::ImplPolarity::Negative => write!(f, "!")?, + if self.is_negative_trait_impl() { + write!(f, "!")?; } ty.print(cx).fmt(f)?; write!(f, " for ")?; diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 9074e40a53614..7ce637d3ab42d 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1780,20 +1780,23 @@ fn render_impl( let mut impl_items = Buffer::empty_from(w); let mut default_impl_items = Buffer::empty_from(w); + let impl_ = i.inner_impl(); - for trait_item in &i.inner_impl().items { - doc_impl_item( - &mut default_impl_items, - &mut impl_items, - cx, - trait_item, - if trait_.is_some() { &i.impl_item } else { parent }, - link, - render_mode, - false, - trait_, - rendering_params, - ); + if !impl_.is_negative_trait_impl() { + for trait_item in &impl_.items { + doc_impl_item( + &mut default_impl_items, + &mut impl_items, + cx, + trait_item, + if trait_.is_some() { &i.impl_item } else { parent }, + link, + render_mode, + false, + trait_, + rendering_params, + ); + } } fn render_default_items( @@ -1844,13 +1847,15 @@ fn render_impl( // We don't emit documentation for default items if they appear in the // Implementations on Foreign Types or Implementors sections. if rendering_params.show_default_items { - if let Some(t) = trait_ { + if let Some(t) = trait_ + && !impl_.is_negative_trait_impl() + { render_default_items( &mut default_impl_items, &mut impl_items, cx, t, - i.inner_impl(), + impl_, &i.impl_item, render_mode, rendering_params, @@ -1882,7 +1887,7 @@ fn render_impl( } if let Some(ref dox) = i.impl_item.opt_doc_value() { - if trait_.is_none() && i.inner_impl().items.is_empty() { + if trait_.is_none() && impl_.items.is_empty() { w.write_str( "
\
This impl block contains no items.
\ From 5baf7c21cfb872a82714d0f59a78bd37b6db5236 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 10 Aug 2024 15:03:43 +0200 Subject: [PATCH 744/786] Add regression tests for negative impls not showing their items --- tests/rustdoc/negative-impl-no-items.rs | 26 +++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 tests/rustdoc/negative-impl-no-items.rs diff --git a/tests/rustdoc/negative-impl-no-items.rs b/tests/rustdoc/negative-impl-no-items.rs new file mode 100644 index 0000000000000..c628e54203368 --- /dev/null +++ b/tests/rustdoc/negative-impl-no-items.rs @@ -0,0 +1,26 @@ +// This test ensures that negative impls don't have items listed inside them. + +#![feature(negative_impls)] +#![crate_name = "foo"] + +pub struct Thing; + +//@ has 'foo/struct.Thing.html' +// We check the full path to ensure there is no `
` element. +//@ has - '//div[@id="trait-implementations-list"]/section[@id="impl-Iterator-for-Thing"]/h3' \ +// 'impl !Iterator for Thing' +impl !Iterator for Thing {} + +// This struct will allow us to compare both paths. +pub struct Witness; + +//@ has 'foo/struct.Witness.html' +//@ has - '//div[@id="trait-implementations-list"]/details//section[@id="impl-Iterator-for-Witness"]/h3' \ +// 'impl Iterator for Witness' +impl Iterator for Witness { + type Item = u8; + + fn next(&mut self) -> Option { + None + } +} From 03b6c2f2d4ac99d123e02786a69ba380498d80d8 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sat, 10 Aug 2024 12:19:38 -0400 Subject: [PATCH 745/786] Fix and enable disabled codegen-units tests --- src/tools/compiletest/src/runtest.rs | 8 +++- .../auxiliary/cgu_extern_closures.rs | 2 + .../item-collection/cross-crate-closures.rs | 21 ++++------ .../item-collection/non-generic-closures.rs | 30 ++++++------- .../methods-are-with-self-type.rs | 42 +++++++------------ 5 files changed, 45 insertions(+), 58 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index b1b6d6fc8eb18..ce6569f5537da 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -3027,11 +3027,17 @@ impl<'test> TestCx<'test> { const PREFIX: &str = "MONO_ITEM "; const CGU_MARKER: &str = "@@"; + // Some MonoItems can contain {closure@/path/to/checkout/tests/codgen-units/test.rs} + // To prevent the current dir from leaking, we just replace the entire path to the test + // file with TEST_PATH. let actual: Vec = proc_res .stdout .lines() .filter(|line| line.starts_with(PREFIX)) - .map(|line| str_to_mono_item(line, true)) + .map(|line| { + line.replace(&self.testpaths.file.display().to_string(), "TEST_PATH").to_string() + }) + .map(|line| str_to_mono_item(&line, true)) .collect(); let expected: Vec = errors::load_errors(&self.testpaths.file, None) 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 0192a3d4188c3..33a32d7fea9f3 100644 --- a/tests/codegen-units/item-collection/auxiliary/cgu_extern_closures.rs +++ b/tests/codegen-units/item-collection/auxiliary/cgu_extern_closures.rs @@ -1,3 +1,5 @@ +//@ compile-flags: -Zinline-mir=no + #![crate_type = "lib"] #[inline] diff --git a/tests/codegen-units/item-collection/cross-crate-closures.rs b/tests/codegen-units/item-collection/cross-crate-closures.rs index 2dab19401ed76..cb86cf18c0cf2 100644 --- a/tests/codegen-units/item-collection/cross-crate-closures.rs +++ b/tests/codegen-units/item-collection/cross-crate-closures.rs @@ -1,9 +1,6 @@ -// In the current version of the collector that still has to support -// legacy-codegen, closures do not generate their own MonoItems, so we are -// ignoring this test until MIR codegen has taken over completely -//@ ignore-test - -//@ compile-flags:-Zprint-mono-items=eager +// We need to disable MIR inlining in both this and its aux-build crate. The MIR inliner +// will just inline everything into our start function if we let it. As it should. +//@ compile-flags:-Zprint-mono-items=eager -Zinline-mir=no #![deny(dead_code)] #![feature(start)] @@ -11,15 +8,15 @@ //@ aux-build:cgu_extern_closures.rs extern crate cgu_extern_closures; -//~ MONO_ITEM fn cross_crate_closures::start[0] +//~ MONO_ITEM fn start @@ cross_crate_closures-cgu.0[Internal] #[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] + //~ MONO_ITEM fn cgu_extern_closures::inlined_fn @@ cross_crate_closures-cgu.0[Internal] + //~ MONO_ITEM fn cgu_extern_closures::inlined_fn::{closure#0} @@ cross_crate_closures-cgu.0[Internal] let _ = cgu_extern_closures::inlined_fn(1, 2); - //~ MONO_ITEM fn cgu_extern_closures::inlined_fn_generic[0] - //~ MONO_ITEM fn cgu_extern_closures::inlined_fn_generic[0]::{{closure}}[0] + //~ MONO_ITEM fn cgu_extern_closures::inlined_fn_generic:: @@ cross_crate_closures-cgu.0[Internal] + //~ MONO_ITEM fn cgu_extern_closures::inlined_fn_generic::::{closure#0} @@ cross_crate_closures-cgu.0[Internal] let _ = cgu_extern_closures::inlined_fn_generic(3, 4, 5i32); // Nothing should be generated for this call, we just link to the instance @@ -28,5 +25,3 @@ fn start(_: isize, _: *const *const u8) -> isize { 0 } - -//~ MONO_ITEM drop-glue i8 diff --git a/tests/codegen-units/item-collection/non-generic-closures.rs b/tests/codegen-units/item-collection/non-generic-closures.rs index 105348e9d09ef..dc0846f2cd302 100644 --- a/tests/codegen-units/item-collection/non-generic-closures.rs +++ b/tests/codegen-units/item-collection/non-generic-closures.rs @@ -1,49 +1,45 @@ -// In the current version of the collector that still has to support -// legacy-codegen, closures do not generate their own MonoItems, so we are -// ignoring this test until MIR codegen has taken over completely -//@ ignore-test - -// -//@ compile-flags:-Zprint-mono-items=eager +//@ compile-flags:-Zprint-mono-items=eager -Zinline-mir=no #![deny(dead_code)] #![feature(start)] -//~ MONO_ITEM fn non_generic_closures::temporary[0] +//~ MONO_ITEM fn temporary @@ non_generic_closures-cgu.0[Internal] fn temporary() { - //~ MONO_ITEM fn non_generic_closures::temporary[0]::{{closure}}[0] + //~ MONO_ITEM fn temporary::{closure#0} @@ non_generic_closures-cgu.0[Internal] (|a: u32| { let _ = a; })(4); } -//~ MONO_ITEM fn non_generic_closures::assigned_to_variable_but_not_executed[0] +//~ MONO_ITEM fn assigned_to_variable_but_not_executed @@ non_generic_closures-cgu.0[Internal] fn assigned_to_variable_but_not_executed() { - //~ MONO_ITEM fn non_generic_closures::assigned_to_variable_but_not_executed[0]::{{closure}}[0] let _x = |a: i16| { let _ = a + 1; }; } -//~ MONO_ITEM fn non_generic_closures::assigned_to_variable_executed_directly[0] +//~ MONO_ITEM fn assigned_to_variable_executed_indirectly @@ non_generic_closures-cgu.0[Internal] fn assigned_to_variable_executed_indirectly() { - //~ MONO_ITEM fn non_generic_closures::assigned_to_variable_executed_directly[0]::{{closure}}[0] + //~ MONO_ITEM fn assigned_to_variable_executed_indirectly::{closure#0} @@ non_generic_closures-cgu.0[Internal] + //~ MONO_ITEM fn <{closure@TEST_PATH:27:13: 27:21} as std::ops::FnOnce<(i32,)>>::call_once - shim @@ non_generic_closures-cgu.0[Internal] + //~ MONO_ITEM fn <{closure@TEST_PATH:27:13: 27:21} as std::ops::FnOnce<(i32,)>>::call_once - shim(vtable) @@ non_generic_closures-cgu.0[Internal] + //~ MONO_ITEM fn std::ptr::drop_in_place::<{closure@TEST_PATH:27:13: 27:21}> - shim(None) @@ non_generic_closures-cgu.0[Internal] let f = |a: i32| { let _ = a + 2; }; run_closure(&f); } -//~ MONO_ITEM fn non_generic_closures::assigned_to_variable_executed_indirectly[0] +//~ MONO_ITEM fn assigned_to_variable_executed_directly @@ non_generic_closures-cgu.0[Internal] fn assigned_to_variable_executed_directly() { - //~ MONO_ITEM fn non_generic_closures::assigned_to_variable_executed_indirectly[0]::{{closure}}[0] + //~ MONO_ITEM fn assigned_to_variable_executed_directly::{closure#0} @@ non_generic_closures-cgu.0[Internal] let f = |a: i64| { let _ = a + 3; }; f(4); } -//~ MONO_ITEM fn non_generic_closures::start[0] +//~ MONO_ITEM fn start @@ non_generic_closures-cgu.0[Internal] #[start] fn start(_: isize, _: *const *const u8) -> isize { temporary(); @@ -54,7 +50,7 @@ fn start(_: isize, _: *const *const u8) -> isize { 0 } -//~ MONO_ITEM fn non_generic_closures::run_closure[0] +//~ MONO_ITEM fn run_closure @@ non_generic_closures-cgu.0[Internal] fn run_closure(f: &Fn(i32)) { f(3); } 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 901e7507d738c..7c9045e8f1a76 100644 --- a/tests/codegen-units/partitioning/methods-are-with-self-type.rs +++ b/tests/codegen-units/partitioning/methods-are-with-self-type.rs @@ -1,30 +1,23 @@ -// Currently, all generic functions are instantiated in each codegen unit that -// uses them, even those not marked with #[inline], so this test does not make -// much sense at the moment. -//@ ignore-test - // We specify incremental here because we want to test the partitioning for incremental compilation //@ incremental //@ compile-flags:-Zprint-mono-items=lazy -#![allow(dead_code)] -#![feature(start)] +#![crate_type = "lib"] -struct SomeType; +pub struct SomeType; struct SomeGenericType(T1, T2); -mod mod1 { +pub mod mod1 { 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. impl SomeType { - //~ MONO_ITEM fn methods_are_with_self_type::mod1[0]::{{impl}}[0]::method[0] @@ methods_are_with_self_type[External] - fn method(&self) {} - - //~ MONO_ITEM fn methods_are_with_self_type::mod1[0]::{{impl}}[0]::associated_fn[0] @@ methods_are_with_self_type[External] - fn associated_fn() {} + //~ MONO_ITEM fn mod1::::method @@ methods_are_with_self_type[External] + pub fn method(&self) {} + //~ MONO_ITEM fn mod1::::associated_fn @@ methods_are_with_self_type[External] + pub fn associated_fn() {} } impl SomeGenericType { @@ -52,25 +45,20 @@ mod type2 { pub struct Struct; } -//~ MONO_ITEM fn methods_are_with_self_type::start[0] -#[start] -fn start(_: isize, _: *const *const u8) -> isize { - //~ MONO_ITEM fn methods_are_with_self_type::mod1[0]::{{impl}}[1]::method[0] @@ methods_are_with_self_type.volatile[WeakODR] +//~ MONO_ITEM fn start @@ methods_are_with_self_type[External] +pub fn start() { + //~ MONO_ITEM fn mod1::>::method @@ methods_are_with_self_type.volatile[External] SomeGenericType(0u32, 0u64).method(); - //~ MONO_ITEM fn methods_are_with_self_type::mod1[0]::{{impl}}[1]::associated_fn[0] @@ methods_are_with_self_type.volatile[WeakODR] + //~ MONO_ITEM fn mod1::>::associated_fn @@ methods_are_with_self_type.volatile[External] SomeGenericType::associated_fn('c', "&str"); - //~ MONO_ITEM fn methods_are_with_self_type::{{impl}}[0]::foo[0] @@ methods_are_with_self_type-type1.volatile[WeakODR] + //~ MONO_ITEM fn ::foo @@ methods_are_with_self_type-type1.volatile[External] type1::Struct.foo(); - //~ MONO_ITEM fn methods_are_with_self_type::{{impl}}[0]::foo[0] @@ methods_are_with_self_type-type2.volatile[WeakODR] + //~ MONO_ITEM fn ::foo @@ methods_are_with_self_type-type2.volatile[External] type2::Struct.foo(); - //~ MONO_ITEM fn methods_are_with_self_type::Trait[0]::default[0] @@ methods_are_with_self_type-type1.volatile[WeakODR] + //~ MONO_ITEM fn ::default @@ methods_are_with_self_type-type1.volatile[External] type1::Struct.default(); - //~ MONO_ITEM fn methods_are_with_self_type::Trait[0]::default[0] @@ methods_are_with_self_type-type2.volatile[WeakODR] + //~ MONO_ITEM fn ::default @@ methods_are_with_self_type-type2.volatile[External] type2::Struct.default(); - - 0 } - -//~ MONO_ITEM drop-glue i8 From 141d9dc3a57ebadc229b7eec7df4357c3aa15620 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Sat, 10 Aug 2024 18:06:10 +0000 Subject: [PATCH 746/786] remove unused imports from rmake tests --- tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs | 2 -- tests/run-make/arguments-non-c-like-enum/rmake.rs | 2 -- tests/run-make/c-link-to-rust-staticlib/rmake.rs | 2 -- tests/run-make/comment-section/rmake.rs | 4 +--- tests/run-make/compressed-debuginfo/rmake.rs | 2 +- tests/run-make/const_fn_mir/rmake.rs | 2 +- tests/run-make/crate-loading/rmake.rs | 3 +-- tests/run-make/dylib-soname/rmake.rs | 1 - tests/run-make/extern-flag-disambiguates/rmake.rs | 2 +- tests/run-make/ice-dep-cannot-find-dep/rmake.rs | 2 +- tests/run-make/incr-test-moved-file/rmake.rs | 2 +- tests/run-make/incremental-debugger-visualizer/rmake.rs | 2 -- tests/run-make/lto-readonly-lib/rmake.rs | 2 +- tests/run-make/multiple-emits/rmake.rs | 2 +- tests/run-make/naked-symbol-visibility/rmake.rs | 2 +- tests/run-make/print-check-cfg/rmake.rs | 1 - tests/run-make/print-native-static-libs/rmake.rs | 2 -- tests/run-make/redundant-libs/rmake.rs | 4 +--- tests/run-make/reproducible-build-2/rmake.rs | 2 +- tests/run-make/reset-codegen-1/rmake.rs | 2 +- tests/run-make/rlib-format-packed-bundled-libs-3/rmake.rs | 2 +- tests/run-make/run-in-tmpdir-self-test/rmake.rs | 2 +- tests/run-make/rust-lld-by-default-nightly/rmake.rs | 2 -- tests/run-make/rust-lld-compress-debug-sections/rmake.rs | 2 +- tests/run-make/rust-lld-custom-target/rmake.rs | 2 -- tests/run-make/rust-lld/rmake.rs | 2 -- tests/run-make/rustdoc-scrape-examples-remap/scrape.rs | 2 +- tests/run-make/sepcomp-cci-copies/rmake.rs | 5 +---- tests/run-make/sepcomp-inlining/rmake.rs | 5 +---- tests/run-make/sepcomp-separate/rmake.rs | 5 +---- 30 files changed, 20 insertions(+), 52 deletions(-) diff --git a/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs b/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs index fec4a4bb90b36..024ce975cd63a 100644 --- a/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs +++ b/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs @@ -3,8 +3,6 @@ // Check that the `CURRENT_RUSTC_VERSION` placeholder is correctly replaced by the current // `rustc` version and the `since` property in feature stability gating is properly respected. -use std::path::PathBuf; - use run_make_support::{aux_build, rfs, rustc, source_root}; fn main() { diff --git a/tests/run-make/arguments-non-c-like-enum/rmake.rs b/tests/run-make/arguments-non-c-like-enum/rmake.rs index 036691e850931..f8e077e0a79f7 100644 --- a/tests/run-make/arguments-non-c-like-enum/rmake.rs +++ b/tests/run-make/arguments-non-c-like-enum/rmake.rs @@ -4,8 +4,6 @@ use run_make_support::{cc, extra_c_flags, extra_cxx_flags, run, rustc, static_lib_name}; pub fn main() { - use std::path::Path; - rustc().input("nonclike.rs").crate_type("staticlib").run(); cc().input("test.c") .input(static_lib_name("nonclike")) diff --git a/tests/run-make/c-link-to-rust-staticlib/rmake.rs b/tests/run-make/c-link-to-rust-staticlib/rmake.rs index e21b976035bc1..6d045012e95fb 100644 --- a/tests/run-make/c-link-to-rust-staticlib/rmake.rs +++ b/tests/run-make/c-link-to-rust-staticlib/rmake.rs @@ -3,8 +3,6 @@ //@ ignore-cross-compile -use std::fs; - use run_make_support::rfs::remove_file; use run_make_support::{cc, extra_c_flags, run, rustc, static_lib_name}; diff --git a/tests/run-make/comment-section/rmake.rs b/tests/run-make/comment-section/rmake.rs index ecee441b35f66..1557f50dbd024 100644 --- a/tests/run-make/comment-section/rmake.rs +++ b/tests/run-make/comment-section/rmake.rs @@ -7,9 +7,7 @@ // FIXME(jieyouxu): check cross-compile setup //@ ignore-cross-compile -use std::path::PathBuf; - -use run_make_support::{cwd, env_var, llvm_readobj, rfs, run_in_tmpdir, rustc}; +use run_make_support::{cwd, env_var, llvm_readobj, rfs, rustc}; fn main() { let target = env_var("TARGET"); diff --git a/tests/run-make/compressed-debuginfo/rmake.rs b/tests/run-make/compressed-debuginfo/rmake.rs index 3a656f28c2241..5ba1a1852d51b 100644 --- a/tests/run-make/compressed-debuginfo/rmake.rs +++ b/tests/run-make/compressed-debuginfo/rmake.rs @@ -5,7 +5,7 @@ // FIXME: This test isn't comprehensive and isn't covering all possible combinations. -use run_make_support::{assert_contains, cmd, llvm_readobj, run_in_tmpdir, rustc}; +use run_make_support::{assert_contains, llvm_readobj, run_in_tmpdir, rustc}; fn check_compression(compression: &str, to_find: &str) { run_in_tmpdir(|| { diff --git a/tests/run-make/const_fn_mir/rmake.rs b/tests/run-make/const_fn_mir/rmake.rs index 1ba93421855d3..0c33b1ce34ef9 100644 --- a/tests/run-make/const_fn_mir/rmake.rs +++ b/tests/run-make/const_fn_mir/rmake.rs @@ -2,7 +2,7 @@ //@ needs-unwind -use run_make_support::{cwd, diff, rustc}; +use run_make_support::{diff, rustc}; fn main() { rustc().input("main.rs").emit("mir").output("dump-actual.mir").run(); diff --git a/tests/run-make/crate-loading/rmake.rs b/tests/run-make/crate-loading/rmake.rs index fd5b66ae87934..8c949c1389f33 100644 --- a/tests/run-make/crate-loading/rmake.rs +++ b/tests/run-make/crate-loading/rmake.rs @@ -2,8 +2,7 @@ //@ ignore-wasm32 //@ ignore-wasm64 -use run_make_support::rfs::copy; -use run_make_support::{assert_contains, rust_lib_name, rustc}; +use run_make_support::{rust_lib_name, rustc}; fn main() { rustc().input("multiple-dep-versions-1.rs").run(); diff --git a/tests/run-make/dylib-soname/rmake.rs b/tests/run-make/dylib-soname/rmake.rs index a0215a6906e47..cec0d46384246 100644 --- a/tests/run-make/dylib-soname/rmake.rs +++ b/tests/run-make/dylib-soname/rmake.rs @@ -4,7 +4,6 @@ //@ only-linux //@ ignore-cross-compile -use run_make_support::regex::Regex; use run_make_support::{cmd, run_in_tmpdir, rustc}; fn main() { diff --git a/tests/run-make/extern-flag-disambiguates/rmake.rs b/tests/run-make/extern-flag-disambiguates/rmake.rs index 2d7d7f69f66fa..89cda02eaeae6 100644 --- a/tests/run-make/extern-flag-disambiguates/rmake.rs +++ b/tests/run-make/extern-flag-disambiguates/rmake.rs @@ -1,6 +1,6 @@ //@ ignore-cross-compile -use run_make_support::{cwd, run, rustc}; +use run_make_support::{run, rustc}; // Attempt to build this dependency tree: // diff --git a/tests/run-make/ice-dep-cannot-find-dep/rmake.rs b/tests/run-make/ice-dep-cannot-find-dep/rmake.rs index 8ba3a0366b002..1c136773f0155 100644 --- a/tests/run-make/ice-dep-cannot-find-dep/rmake.rs +++ b/tests/run-make/ice-dep-cannot-find-dep/rmake.rs @@ -16,7 +16,7 @@ // If we used `rustc` the additional '-L rmake_out' option would allow rustc to // actually find the crate. -use run_make_support::{bare_rustc, rfs, rust_lib_name, rustc}; +use run_make_support::{bare_rustc, rust_lib_name, rustc}; fn main() { rustc().crate_name("a").crate_type("rlib").input("a.rs").arg("--verbose").run(); diff --git a/tests/run-make/incr-test-moved-file/rmake.rs b/tests/run-make/incr-test-moved-file/rmake.rs index f314e110a8c33..0ba1b0d58feeb 100644 --- a/tests/run-make/incr-test-moved-file/rmake.rs +++ b/tests/run-make/incr-test-moved-file/rmake.rs @@ -14,7 +14,7 @@ //@ ignore-nvptx64-nvidia-cuda // FIXME: can't find crate for 'std' -use run_make_support::{rfs, rust_lib_name, rustc}; +use run_make_support::{rfs, rustc}; fn main() { rfs::create_dir("incr"); diff --git a/tests/run-make/incremental-debugger-visualizer/rmake.rs b/tests/run-make/incremental-debugger-visualizer/rmake.rs index 58a7e415bc58b..07c920cc04a6f 100644 --- a/tests/run-make/incremental-debugger-visualizer/rmake.rs +++ b/tests/run-make/incremental-debugger-visualizer/rmake.rs @@ -2,8 +2,6 @@ // (in this case, foo.py and foo.natvis) are picked up when compiling incrementally. // See https://github.com/rust-lang/rust/pull/111641 -use std::io::Read; - use run_make_support::{invalid_utf8_contains, invalid_utf8_not_contains, rfs, rustc}; fn main() { diff --git a/tests/run-make/lto-readonly-lib/rmake.rs b/tests/run-make/lto-readonly-lib/rmake.rs index b9f0dc21dafc2..78f2b580e0df2 100644 --- a/tests/run-make/lto-readonly-lib/rmake.rs +++ b/tests/run-make/lto-readonly-lib/rmake.rs @@ -7,7 +7,7 @@ //@ ignore-cross-compile -use run_make_support::{rfs, run, rust_lib_name, rustc, test_while_readonly}; +use run_make_support::{run, rust_lib_name, rustc, test_while_readonly}; fn main() { rustc().input("lib.rs").run(); diff --git a/tests/run-make/multiple-emits/rmake.rs b/tests/run-make/multiple-emits/rmake.rs index 67c0ebb9864a5..8a5eb1d9d856a 100644 --- a/tests/run-make/multiple-emits/rmake.rs +++ b/tests/run-make/multiple-emits/rmake.rs @@ -1,4 +1,4 @@ -use run_make_support::{cwd, path, rustc}; +use run_make_support::{path, rustc}; fn main() { rustc().input("foo.rs").emit("asm,llvm-ir").output("out").run(); diff --git a/tests/run-make/naked-symbol-visibility/rmake.rs b/tests/run-make/naked-symbol-visibility/rmake.rs index a32e62326eb32..07ff253788d0a 100644 --- a/tests/run-make/naked-symbol-visibility/rmake.rs +++ b/tests/run-make/naked-symbol-visibility/rmake.rs @@ -3,7 +3,7 @@ use run_make_support::object::read::{File, Object, Symbol}; use run_make_support::object::ObjectSymbol; use run_make_support::targets::is_windows; -use run_make_support::{dynamic_lib_name, env_var, rfs, rustc}; +use run_make_support::{dynamic_lib_name, rfs, rustc}; fn main() { let rdylib_name = dynamic_lib_name("a_rust_dylib"); diff --git a/tests/run-make/print-check-cfg/rmake.rs b/tests/run-make/print-check-cfg/rmake.rs index b10336f88c649..f6f7f7cece6e7 100644 --- a/tests/run-make/print-check-cfg/rmake.rs +++ b/tests/run-make/print-check-cfg/rmake.rs @@ -4,7 +4,6 @@ extern crate run_make_support; use std::collections::HashSet; use std::iter::FromIterator; -use std::ops::Deref; use run_make_support::rustc; diff --git a/tests/run-make/print-native-static-libs/rmake.rs b/tests/run-make/print-native-static-libs/rmake.rs index b4e7c0e17ff8e..a51ac934c722e 100644 --- a/tests/run-make/print-native-static-libs/rmake.rs +++ b/tests/run-make/print-native-static-libs/rmake.rs @@ -12,8 +12,6 @@ //@ ignore-cross-compile //@ ignore-wasm -use std::io::BufRead; - use run_make_support::{is_msvc, rustc}; fn main() { diff --git a/tests/run-make/redundant-libs/rmake.rs b/tests/run-make/redundant-libs/rmake.rs index 43bb30bde702d..e984dee8df5ba 100644 --- a/tests/run-make/redundant-libs/rmake.rs +++ b/tests/run-make/redundant-libs/rmake.rs @@ -11,9 +11,7 @@ //@ ignore-cross-compile // Reason: the compiled binary is executed -use run_make_support::{ - build_native_dynamic_lib, build_native_static_lib, cwd, is_msvc, rfs, run, rustc, -}; +use run_make_support::{build_native_dynamic_lib, build_native_static_lib, run, rustc}; fn main() { build_native_dynamic_lib("foo"); diff --git a/tests/run-make/reproducible-build-2/rmake.rs b/tests/run-make/reproducible-build-2/rmake.rs index c500c4238b088..8b5825cad3026 100644 --- a/tests/run-make/reproducible-build-2/rmake.rs +++ b/tests/run-make/reproducible-build-2/rmake.rs @@ -13,7 +13,7 @@ // 2. When the sysroot gets copied, some symlinks must be re-created, // which is a privileged action on Windows. -use run_make_support::{bin_name, rfs, rust_lib_name, rustc}; +use run_make_support::{rfs, rust_lib_name, rustc}; fn main() { // test 1: fat lto diff --git a/tests/run-make/reset-codegen-1/rmake.rs b/tests/run-make/reset-codegen-1/rmake.rs index d19907a675e02..118b3a666ad86 100644 --- a/tests/run-make/reset-codegen-1/rmake.rs +++ b/tests/run-make/reset-codegen-1/rmake.rs @@ -9,7 +9,7 @@ use std::path::Path; -use run_make_support::{bin_name, rfs, rustc}; +use run_make_support::{bin_name, rustc}; fn compile(output_file: &str, emit: Option<&str>) { let mut rustc = rustc(); diff --git a/tests/run-make/rlib-format-packed-bundled-libs-3/rmake.rs b/tests/run-make/rlib-format-packed-bundled-libs-3/rmake.rs index d152047600f0c..67e839bec703d 100644 --- a/tests/run-make/rlib-format-packed-bundled-libs-3/rmake.rs +++ b/tests/run-make/rlib-format-packed-bundled-libs-3/rmake.rs @@ -6,7 +6,7 @@ // See https://github.com/rust-lang/rust/pull/105601 use run_make_support::{ - build_native_static_lib, is_msvc, llvm_ar, regex, rfs, rust_lib_name, rustc, static_lib_name, + build_native_static_lib, llvm_ar, regex, rfs, rust_lib_name, rustc, static_lib_name, }; //@ ignore-cross-compile diff --git a/tests/run-make/run-in-tmpdir-self-test/rmake.rs b/tests/run-make/run-in-tmpdir-self-test/rmake.rs index 83b99bfe86325..dba036f88669e 100644 --- a/tests/run-make/run-in-tmpdir-self-test/rmake.rs +++ b/tests/run-make/run-in-tmpdir-self-test/rmake.rs @@ -3,7 +3,7 @@ //! when returning from the closure. use std::fs; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use run_make_support::{cwd, run_in_tmpdir}; diff --git a/tests/run-make/rust-lld-by-default-nightly/rmake.rs b/tests/run-make/rust-lld-by-default-nightly/rmake.rs index 79424984c2139..02bbe8227f032 100644 --- a/tests/run-make/rust-lld-by-default-nightly/rmake.rs +++ b/tests/run-make/rust-lld-by-default-nightly/rmake.rs @@ -6,8 +6,6 @@ //@ ignore-stable //@ only-x86_64-unknown-linux-gnu -use std::process::Output; - use run_make_support::regex::Regex; use run_make_support::rustc; diff --git a/tests/run-make/rust-lld-compress-debug-sections/rmake.rs b/tests/run-make/rust-lld-compress-debug-sections/rmake.rs index df9691ccbcf39..ea4997fab8099 100644 --- a/tests/run-make/rust-lld-compress-debug-sections/rmake.rs +++ b/tests/run-make/rust-lld-compress-debug-sections/rmake.rs @@ -6,7 +6,7 @@ // FIXME: This test isn't comprehensive and isn't covering all possible combinations. -use run_make_support::{assert_contains, cmd, llvm_readobj, run_in_tmpdir, rustc}; +use run_make_support::{assert_contains, llvm_readobj, run_in_tmpdir, rustc}; fn check_compression(compression: &str, to_find: &str) { run_in_tmpdir(|| { diff --git a/tests/run-make/rust-lld-custom-target/rmake.rs b/tests/run-make/rust-lld-custom-target/rmake.rs index 17247125521ce..a6f7c33793afe 100644 --- a/tests/run-make/rust-lld-custom-target/rmake.rs +++ b/tests/run-make/rust-lld-custom-target/rmake.rs @@ -8,8 +8,6 @@ //@ needs-rust-lld //@ only-x86_64-unknown-linux-gnu -use std::process::Output; - use run_make_support::regex::Regex; use run_make_support::rustc; diff --git a/tests/run-make/rust-lld/rmake.rs b/tests/run-make/rust-lld/rmake.rs index d0bc19130d7cb..1f311af1ed591 100644 --- a/tests/run-make/rust-lld/rmake.rs +++ b/tests/run-make/rust-lld/rmake.rs @@ -4,8 +4,6 @@ //@ needs-rust-lld //@ ignore-s390x lld does not yet support s390x as target -use std::process::Output; - use run_make_support::regex::Regex; use run_make_support::{is_msvc, rustc}; diff --git a/tests/run-make/rustdoc-scrape-examples-remap/scrape.rs b/tests/run-make/rustdoc-scrape-examples-remap/scrape.rs index 4badc68845e96..eca07043b557c 100644 --- a/tests/run-make/rustdoc-scrape-examples-remap/scrape.rs +++ b/tests/run-make/rustdoc-scrape-examples-remap/scrape.rs @@ -1,6 +1,6 @@ use std::path::Path; -use run_make_support::{htmldocck, rfs, rustc, rustdoc, source_root}; +use run_make_support::{htmldocck, rfs, rustc, rustdoc}; pub fn scrape(extra_args: &[&str]) { let out_dir = Path::new("rustdoc"); diff --git a/tests/run-make/sepcomp-cci-copies/rmake.rs b/tests/run-make/sepcomp-cci-copies/rmake.rs index e244f54658073..a66cc2872b434 100644 --- a/tests/run-make/sepcomp-cci-copies/rmake.rs +++ b/tests/run-make/sepcomp-cci-copies/rmake.rs @@ -4,10 +4,7 @@ // created for each source module (see `rustc_const_eval::monomorphize::partitioning`). // See https://github.com/rust-lang/rust/pull/16367 -use run_make_support::{ - count_regex_matches_in_files_with_extension, cwd, has_extension, regex, rfs, rustc, - shallow_find_files, -}; +use run_make_support::{count_regex_matches_in_files_with_extension, regex, rustc}; fn main() { rustc().input("cci_lib.rs").run(); diff --git a/tests/run-make/sepcomp-inlining/rmake.rs b/tests/run-make/sepcomp-inlining/rmake.rs index b7a6bed05b846..ea4a4d210cc3e 100644 --- a/tests/run-make/sepcomp-inlining/rmake.rs +++ b/tests/run-make/sepcomp-inlining/rmake.rs @@ -5,10 +5,7 @@ // in only one compilation unit. // See https://github.com/rust-lang/rust/pull/16367 -use run_make_support::{ - count_regex_matches_in_files_with_extension, cwd, has_extension, regex, rfs, rustc, - shallow_find_files, -}; +use run_make_support::{count_regex_matches_in_files_with_extension, regex, rustc}; fn main() { rustc().input("foo.rs").emit("llvm-ir").codegen_units(3).arg("-Zinline-in-all-cgus").run(); diff --git a/tests/run-make/sepcomp-separate/rmake.rs b/tests/run-make/sepcomp-separate/rmake.rs index 90017572c4c18..49958044a612a 100644 --- a/tests/run-make/sepcomp-separate/rmake.rs +++ b/tests/run-make/sepcomp-separate/rmake.rs @@ -3,10 +3,7 @@ // wind up in three different compilation units. // See https://github.com/rust-lang/rust/pull/16367 -use run_make_support::{ - count_regex_matches_in_files_with_extension, cwd, has_extension, regex, rfs, rustc, - shallow_find_files, -}; +use run_make_support::{count_regex_matches_in_files_with_extension, regex, rustc}; fn main() { rustc().input("foo.rs").emit("llvm-ir").codegen_units(3).run(); From f4cb0de44eb2ad3d5b375b264d85e2c106995ce4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Sat, 10 Aug 2024 18:16:15 +0000 Subject: [PATCH 747/786] remove other warnings from rmake tests --- tests/run-make/crate-loading/rmake.rs | 2 +- .../non-unicode-in-incremental-dir/rmake.rs | 2 +- .../output-type-permutations/rmake.rs | 44 +++++++++---------- tests/run-make/rustdoc-io-error/rmake.rs | 2 +- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/tests/run-make/crate-loading/rmake.rs b/tests/run-make/crate-loading/rmake.rs index 8c949c1389f33..d7abd5872c94a 100644 --- a/tests/run-make/crate-loading/rmake.rs +++ b/tests/run-make/crate-loading/rmake.rs @@ -8,7 +8,7 @@ fn main() { rustc().input("multiple-dep-versions-1.rs").run(); rustc().input("multiple-dep-versions-2.rs").extra_filename("2").metadata("2").run(); - let out = rustc() + rustc() .input("multiple-dep-versions.rs") .extern_("dependency", rust_lib_name("dependency")) .extern_("dep_2_reexport", rust_lib_name("dependency2")) diff --git a/tests/run-make/non-unicode-in-incremental-dir/rmake.rs b/tests/run-make/non-unicode-in-incremental-dir/rmake.rs index ef316f1103638..42bd4b1b79990 100644 --- a/tests/run-make/non-unicode-in-incremental-dir/rmake.rs +++ b/tests/run-make/non-unicode-in-incremental-dir/rmake.rs @@ -8,7 +8,7 @@ fn main() { match std::fs::create_dir(&non_unicode) { // If an error occurs, check if creating a directory with a valid Unicode name would // succeed. - Err(e) if std::fs::create_dir("valid_unicode").is_ok() => { + Err(_) if std::fs::create_dir("valid_unicode").is_ok() => { // Filesystem doesn't appear support non-Unicode paths. return; } diff --git a/tests/run-make/output-type-permutations/rmake.rs b/tests/run-make/output-type-permutations/rmake.rs index 76fd8c1c2603a..c0569af6e84a3 100644 --- a/tests/run-make/output-type-permutations/rmake.rs +++ b/tests/run-make/output-type-permutations/rmake.rs @@ -113,7 +113,7 @@ fn main() { assert_expected_output_files( Expectations { expected_files: s!["foo"], - allowed_files: s![], + allowed_files: vec![], test_dir: "asm-emit".to_string(), }, || { @@ -123,7 +123,7 @@ fn main() { assert_expected_output_files( Expectations { expected_files: s!["foo"], - allowed_files: s![], + allowed_files: vec![], test_dir: "asm-emit2".to_string(), }, || { @@ -133,7 +133,7 @@ fn main() { assert_expected_output_files( Expectations { expected_files: s!["foo"], - allowed_files: s![], + allowed_files: vec![], test_dir: "asm-emit3".to_string(), }, || { @@ -144,7 +144,7 @@ fn main() { assert_expected_output_files( Expectations { expected_files: s!["foo"], - allowed_files: s![], + allowed_files: vec![], test_dir: "llvm-ir-emit".to_string(), }, || { @@ -154,7 +154,7 @@ fn main() { assert_expected_output_files( Expectations { expected_files: s!["foo"], - allowed_files: s![], + allowed_files: vec![], test_dir: "llvm-ir-emit2".to_string(), }, || { @@ -164,7 +164,7 @@ fn main() { assert_expected_output_files( Expectations { expected_files: s!["foo"], - allowed_files: s![], + allowed_files: vec![], test_dir: "llvm-ir-emit3".to_string(), }, || { @@ -175,7 +175,7 @@ fn main() { assert_expected_output_files( Expectations { expected_files: s!["foo"], - allowed_files: s![], + allowed_files: vec![], test_dir: "llvm-bc-emit".to_string(), }, || { @@ -185,7 +185,7 @@ fn main() { assert_expected_output_files( Expectations { expected_files: s!["foo"], - allowed_files: s![], + allowed_files: vec![], test_dir: "llvm-bc-emit2".to_string(), }, || { @@ -195,7 +195,7 @@ fn main() { assert_expected_output_files( Expectations { expected_files: s!["foo"], - allowed_files: s![], + allowed_files: vec![], test_dir: "llvm-bc-emit3".to_string(), }, || { @@ -206,7 +206,7 @@ fn main() { assert_expected_output_files( Expectations { expected_files: s!["foo"], - allowed_files: s![], + allowed_files: vec![], test_dir: "obj-emit".to_string(), }, || { @@ -216,7 +216,7 @@ fn main() { assert_expected_output_files( Expectations { expected_files: s!["foo"], - allowed_files: s![], + allowed_files: vec![], test_dir: "obj-emit2".to_string(), }, || { @@ -226,7 +226,7 @@ fn main() { assert_expected_output_files( Expectations { expected_files: s!["foo"], - allowed_files: s![], + allowed_files: vec![], test_dir: "obj-emit3".to_string(), }, || { @@ -268,7 +268,7 @@ fn main() { assert_expected_output_files( Expectations { expected_files: s!["foo"], - allowed_files: s![], + allowed_files: vec![], test_dir: "rlib".to_string(), }, || { @@ -278,7 +278,7 @@ fn main() { assert_expected_output_files( Expectations { expected_files: s!["foo"], - allowed_files: s![], + allowed_files: vec![], test_dir: "rlib2".to_string(), }, || { @@ -288,7 +288,7 @@ fn main() { assert_expected_output_files( Expectations { expected_files: s!["foo"], - allowed_files: s![], + allowed_files: vec![], test_dir: "rlib3".to_string(), }, || { @@ -375,7 +375,7 @@ fn main() { assert_expected_output_files( Expectations { expected_files: s!["foo"], - allowed_files: s![], + allowed_files: vec![], test_dir: "staticlib".to_string(), }, || { @@ -385,7 +385,7 @@ fn main() { assert_expected_output_files( Expectations { expected_files: s!["foo"], - allowed_files: s![], + allowed_files: vec![], test_dir: "staticlib2".to_string(), }, || { @@ -395,7 +395,7 @@ fn main() { assert_expected_output_files( Expectations { expected_files: s!["foo"], - allowed_files: s![], + allowed_files: vec![], test_dir: "staticlib3".to_string(), }, || { @@ -449,7 +449,7 @@ fn main() { assert_expected_output_files( Expectations { expected_files: s!["ir", rust_lib_name("bar")], - allowed_files: s![], + allowed_files: vec![], test_dir: "rlib-ir".to_string(), }, || { @@ -466,7 +466,7 @@ fn main() { assert_expected_output_files( Expectations { expected_files: s!["ir", "asm", "bc", "obj", "link"], - allowed_files: s![], + allowed_files: vec![], test_dir: "staticlib-all".to_string(), }, || { @@ -484,7 +484,7 @@ fn main() { assert_expected_output_files( Expectations { expected_files: s!["ir", "asm", "bc", "obj", "link"], - allowed_files: s![], + allowed_files: vec![], test_dir: "staticlib-all2".to_string(), }, || { @@ -523,7 +523,7 @@ fn main() { assert_expected_output_files( Expectations { expected_files: s!["bar.bc", rust_lib_name("bar"), "foo.bc"], - allowed_files: s![], + allowed_files: vec![], test_dir: "rlib-emits".to_string(), }, || { diff --git a/tests/run-make/rustdoc-io-error/rmake.rs b/tests/run-make/rustdoc-io-error/rmake.rs index d64c5106ffb67..96dafa8adfd91 100644 --- a/tests/run-make/rustdoc-io-error/rmake.rs +++ b/tests/run-make/rustdoc-io-error/rmake.rs @@ -20,7 +20,7 @@ use run_make_support::{path, rustdoc}; fn main() { let out_dir = path("rustdoc-io-error"); - let output = fs::create_dir(&out_dir).unwrap(); + fs::create_dir(&out_dir).unwrap(); let mut permissions = fs::metadata(&out_dir).unwrap().permissions(); let original_permissions = permissions.clone(); From 3ee43259ac9ddb7d5e050e9c7e65c848550045da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Tue, 12 Mar 2024 02:12:28 +0100 Subject: [PATCH 748/786] Link `std` statically in `rustc_driver` --- compiler/rustc/src/main.rs | 3 ++ .../rustc_metadata/src/dependency_format.rs | 36 +++++++++++++++---- src/bootstrap/src/bin/rustc.rs | 20 +++++++++-- src/bootstrap/src/core/build_steps/compile.rs | 7 +++- src/bootstrap/src/core/builder.rs | 2 +- src/tools/clippy/src/main.rs | 3 ++ src/tools/clippy/tests/compile-test.rs | 3 ++ src/tools/rustdoc/main.rs | 3 ++ src/tools/rustfmt/src/git-rustfmt/main.rs | 4 +++ 9 files changed, 70 insertions(+), 11 deletions(-) diff --git a/compiler/rustc/src/main.rs b/compiler/rustc/src/main.rs index 29766fc9d87cb..e9a7397557eb1 100644 --- a/compiler/rustc/src/main.rs +++ b/compiler/rustc/src/main.rs @@ -1,3 +1,6 @@ +// We need this feature as it changes `dylib` linking behavior and allows us to link to `rustc_driver`. +#![feature(rustc_private)] + // A note about jemalloc: rustc uses jemalloc when built for CI and // distribution. The obvious way to do this is with the `#[global_allocator]` // mechanism. However, for complicated reasons (see diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs index 17fd260fd794a..95b1a40d8925d 100644 --- a/compiler/rustc_metadata/src/dependency_format.rs +++ b/compiler/rustc_metadata/src/dependency_format.rs @@ -51,7 +51,7 @@ //! Additionally, the algorithm is geared towards finding *any* solution rather //! than finding a number of solutions (there are normally quite a few). -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::def_id::CrateNum; use rustc_middle::bug; use rustc_middle::middle::dependency_format::{Dependencies, DependencyList, Linkage}; @@ -160,18 +160,43 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { Linkage::Dynamic | Linkage::IncludedFromDylib => {} } + let all_dylibs = || { + tcx.crates(()).iter().filter(|&&cnum| { + !tcx.dep_kind(cnum).macros_only() && tcx.used_crate_source(cnum).dylib.is_some() + }) + }; + + let mut upstream_in_dylibs = FxHashSet::default(); + + if tcx.features().rustc_private { + // We need this to prevent users of `rustc_driver` from linking dynamically to `std` + // which does not work as `std` is also statically linked into `rustc_driver`. + + // Find all libraries statically linked to upstream dylibs. + for &cnum in all_dylibs() { + let deps = tcx.dylib_dependency_formats(cnum); + for &(depnum, style) in deps.iter() { + if let RequireStatic = style { + upstream_in_dylibs.insert(depnum); + } + } + } + } + let mut formats = FxHashMap::default(); // Sweep all crates for found dylibs. Add all dylibs, as well as their // dependencies, ensuring there are no conflicts. The only valid case for a // dependency to be relied upon twice is for both cases to rely on a dylib. - for &cnum in tcx.crates(()).iter() { - if tcx.dep_kind(cnum).macros_only() { + for &cnum in all_dylibs() { + if upstream_in_dylibs.contains(&cnum) { + info!("skipping dylib: {}", tcx.crate_name(cnum)); + // If this dylib is also available statically linked to another dylib + // we try to use that instead. continue; } + let name = tcx.crate_name(cnum); - let src = tcx.used_crate_source(cnum); - if src.dylib.is_some() { info!("adding dylib: {}", name); add_library(tcx, cnum, RequireDynamic, &mut formats, &mut unavailable_as_static); let deps = tcx.dylib_dependency_formats(cnum); @@ -180,7 +205,6 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { add_library(tcx, depnum, style, &mut formats, &mut unavailable_as_static); } } - } // Collect what we've got so far in the return vector. let last_crate = tcx.crates(()).len(); diff --git a/src/bootstrap/src/bin/rustc.rs b/src/bootstrap/src/bin/rustc.rs index 011c289d932db..f3198338dc352 100644 --- a/src/bootstrap/src/bin/rustc.rs +++ b/src/bootstrap/src/bin/rustc.rs @@ -89,6 +89,23 @@ fn main() { rustc_real }; + // Get the name of the crate we're compiling, if any. + let crate_name = parse_value_from_args(&orig_args, "--crate-name"); + + // We want everything statically linked into `rustc_driver`, so remove `-C prefer-dynamic` + if crate_name == Some("rustc_driver") && stage != "0" { + // Remove `-C prefer-dynamic` to link `std` statically into `rustc_driver` + if let Some(pos) = args.iter().enumerate().position(|(i, a)| { + a == "-C" && args.get(i + 1).map(|a| a == "prefer-dynamic").unwrap_or(false) + }) { + args.remove(pos); + args.remove(pos); + } + if let Some(pos) = args.iter().position(|a| a == "-Cprefer-dynamic") { + args.remove(pos); + } + } + let mut cmd = match env::var_os("RUSTC_WRAPPER_REAL") { Some(wrapper) if !wrapper.is_empty() => { let mut cmd = Command::new(wrapper); @@ -99,9 +116,6 @@ fn main() { }; cmd.args(&args).env(dylib_path_var(), env::join_paths(&dylib_path).unwrap()); - // Get the name of the crate we're compiling, if any. - let crate_name = parse_value_from_args(&orig_args, "--crate-name"); - if let Some(crate_name) = crate_name { if let Some(target) = env::var_os("RUSTC_TIME") { if target == "all" diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index c09180e542ff6..76006bfe0e5e3 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -1836,7 +1836,12 @@ impl Step for Assemble { let src_libdir = builder.sysroot_libdir(build_compiler, host); for f in builder.read_dir(&src_libdir) { let filename = f.file_name().into_string().unwrap(); - if (is_dylib(&filename) || is_debug_info(&filename)) && !proc_macros.contains(&filename) + let can_be_rustc_dep = filename.starts_with("rustc_driver-") + || filename.starts_with("librustc_driver-") + || build_compiler.stage == 0; + if can_be_rustc_dep + && (is_dylib(&filename) || is_debug_info(&filename)) + && !proc_macros.contains(&filename) { builder.copy_link(&f.path(), &rustc_libdir.join(&filename)); } diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 84c23c059e97e..41837c0eb89b0 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -2162,7 +2162,7 @@ impl<'a> Builder<'a> { // When we build Rust dylibs they're all intended for intermediate // usage, so make sure we pass the -Cprefer-dynamic flag instead of // linking all deps statically into the dylib. - if matches!(mode, Mode::Std | Mode::Rustc) { + if matches!(mode, Mode::Std) { rustflags.arg("-Cprefer-dynamic"); } diff --git a/src/tools/clippy/src/main.rs b/src/tools/clippy/src/main.rs index c9af2138a7233..c9853e53f3b38 100644 --- a/src/tools/clippy/src/main.rs +++ b/src/tools/clippy/src/main.rs @@ -1,3 +1,6 @@ +// We need this feature as it changes `dylib` linking behavior and allows us to link to +// `rustc_driver`. +#![feature(rustc_private)] // warn on lints, that are included in `rust-lang/rust`s bootstrap #![warn(rust_2018_idioms, unused_lifetimes)] diff --git a/src/tools/clippy/tests/compile-test.rs b/src/tools/clippy/tests/compile-test.rs index c7080e5dcdc9e..64253514fbe67 100644 --- a/src/tools/clippy/tests/compile-test.rs +++ b/src/tools/clippy/tests/compile-test.rs @@ -1,3 +1,6 @@ +// We need this feature as it changes `dylib` linking behavior and allows us to link to +// `rustc_driver`. +#![feature(rustc_private)] #![warn(rust_2018_idioms, unused_lifetimes)] #![allow(unused_extern_crates)] diff --git a/src/tools/rustdoc/main.rs b/src/tools/rustdoc/main.rs index 5b499a1fa1fa8..d4099cafe5df0 100644 --- a/src/tools/rustdoc/main.rs +++ b/src/tools/rustdoc/main.rs @@ -1,3 +1,6 @@ +// We need this feature as it changes `dylib` linking behavior and allows us to link to `rustc_driver`. +#![feature(rustc_private)] + fn main() { rustdoc::main() } diff --git a/src/tools/rustfmt/src/git-rustfmt/main.rs b/src/tools/rustfmt/src/git-rustfmt/main.rs index 3059d917c6b9e..5674f40bef91f 100644 --- a/src/tools/rustfmt/src/git-rustfmt/main.rs +++ b/src/tools/rustfmt/src/git-rustfmt/main.rs @@ -1,3 +1,7 @@ +// We need this feature as it changes `dylib` linking behavior and allows us to link to +// `rustc_driver`. +#![feature(rustc_private)] + #[macro_use] extern crate tracing; From 736a249954aedaff9b3562f073e295d6c4c6d94d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 22 Mar 2024 11:42:53 +0100 Subject: [PATCH 749/786] Ask the user to use `feature(rustc_private)` when linking to `rustc_driver` --- compiler/rustc_metadata/messages.ftl | 3 +++ .../rustc_metadata/src/dependency_format.rs | 21 ++++++++++++------- compiler/rustc_metadata/src/errors.rs | 6 ++++++ compiler/rustc_span/src/symbol.rs | 1 + 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl index 415399ed06c7f..24fe1ebc07e40 100644 --- a/compiler/rustc_metadata/messages.ftl +++ b/compiler/rustc_metadata/messages.ftl @@ -41,6 +41,9 @@ metadata_crate_dep_multiple = metadata_crate_dep_not_static = `{$crate_name}` was unavailable as a static crate, preventing fully static linking +metadata_crate_dep_rustc_driver = + `feature(rustc_private)` is needed to link to the compiler's `rustc_driver` library + metadata_crate_location_unknown_type = extern location for {$crate_name} is of an unknown type: {$path} diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs index 95b1a40d8925d..39fa23766b5d2 100644 --- a/compiler/rustc_metadata/src/dependency_format.rs +++ b/compiler/rustc_metadata/src/dependency_format.rs @@ -59,12 +59,14 @@ use rustc_middle::ty::TyCtxt; use rustc_session::config::CrateType; use rustc_session::cstore::CrateDepKind; use rustc_session::cstore::LinkagePreference::{self, RequireDynamic, RequireStatic}; +use rustc_span::sym; use tracing::info; use crate::creader::CStore; use crate::errors::{ BadPanicStrategy, CrateDepMultiple, IncompatiblePanicInDropStrategy, LibRequired, - NonStaticCrateDep, RequiredPanicStrategy, RlibRequired, RustcLibRequired, TwoPanicRuntimes, + NonStaticCrateDep, RequiredPanicStrategy, RlibRequired, RustcDriverHelp, RustcLibRequired, + TwoPanicRuntimes, }; pub(crate) fn calculate(tcx: TyCtxt<'_>) -> Dependencies { @@ -197,14 +199,14 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { } let name = tcx.crate_name(cnum); - info!("adding dylib: {}", name); - add_library(tcx, cnum, RequireDynamic, &mut formats, &mut unavailable_as_static); - let deps = tcx.dylib_dependency_formats(cnum); - for &(depnum, style) in deps.iter() { - info!("adding {:?}: {}", style, tcx.crate_name(depnum)); - add_library(tcx, depnum, style, &mut formats, &mut unavailable_as_static); - } + info!("adding dylib: {}", name); + add_library(tcx, cnum, RequireDynamic, &mut formats, &mut unavailable_as_static); + let deps = tcx.dylib_dependency_formats(cnum); + for &(depnum, style) in deps.iter() { + info!("adding {:?}: {}", style, tcx.crate_name(depnum)); + add_library(tcx, depnum, style, &mut formats, &mut unavailable_as_static); } + } // Collect what we've got so far in the return vector. let last_crate = tcx.crates(()).len(); @@ -292,12 +294,15 @@ fn add_library( // This error is probably a little obscure, but I imagine that it // can be refined over time. if link2 != link || link == RequireStatic { + let linking_to_rustc_driver = tcx.sess.psess.unstable_features.is_nightly_build() + && tcx.crates(()).iter().any(|&cnum| tcx.crate_name(cnum) == sym::rustc_driver); tcx.dcx().emit_err(CrateDepMultiple { crate_name: tcx.crate_name(cnum), non_static_deps: unavailable_as_static .drain(..) .map(|cnum| NonStaticCrateDep { crate_name: tcx.crate_name(cnum) }) .collect(), + rustc_driver_help: linking_to_rustc_driver.then_some(RustcDriverHelp), }); } } diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index 89970dddf9fd4..42dec978b78cd 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -38,6 +38,8 @@ pub struct CrateDepMultiple { pub crate_name: Symbol, #[subdiagnostic] pub non_static_deps: Vec, + #[subdiagnostic] + pub rustc_driver_help: Option, } #[derive(Subdiagnostic)] @@ -46,6 +48,10 @@ pub struct NonStaticCrateDep { pub crate_name: Symbol, } +#[derive(Subdiagnostic)] +#[help(metadata_crate_dep_rustc_driver)] +pub struct RustcDriverHelp; + #[derive(Diagnostic)] #[diag(metadata_two_panic_runtimes)] pub struct TwoPanicRuntimes { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 32fca6733bb55..9cb729ec48588 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1619,6 +1619,7 @@ symbols! { rustc_dirty, rustc_do_not_const_check, rustc_doc_primitive, + rustc_driver, rustc_dummy, rustc_dump_def_parents, rustc_dump_item_bounds, From 486864f23593d7aedddf1831f748660311f9ff3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sat, 10 Aug 2024 08:11:22 +0200 Subject: [PATCH 750/786] Don't statically link `std` into `rustc_driver` for `windows-gnu` --- src/bootstrap/src/bin/rustc.rs | 8 +++++--- src/bootstrap/src/core/build_steps/compile.rs | 12 +++++++++++- src/bootstrap/src/core/builder.rs | 14 ++++++++++++++ 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/bootstrap/src/bin/rustc.rs b/src/bootstrap/src/bin/rustc.rs index f3198338dc352..d04e2fbeb7853 100644 --- a/src/bootstrap/src/bin/rustc.rs +++ b/src/bootstrap/src/bin/rustc.rs @@ -92,9 +92,11 @@ fn main() { // Get the name of the crate we're compiling, if any. let crate_name = parse_value_from_args(&orig_args, "--crate-name"); - // We want everything statically linked into `rustc_driver`, so remove `-C prefer-dynamic` - if crate_name == Some("rustc_driver") && stage != "0" { - // Remove `-C prefer-dynamic` to link `std` statically into `rustc_driver` + // When statically linking `std` into `rustc_driver`, remove `-C prefer-dynamic` + if env::var("RUSTC_LINK_STD_INTO_RUSTC_DRIVER").unwrap() == "1" + && crate_name == Some("rustc_driver") + && stage != "0" + { if let Some(pos) = args.iter().enumerate().position(|(i, a)| { a == "-C" && args.get(i + 1).map(|a| a == "prefer-dynamic").unwrap_or(false) }) { diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 76006bfe0e5e3..2e521ff754407 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -1830,15 +1830,25 @@ impl Step for Assemble { }) .collect::>(); + let link_std_into_rustc_driver = builder.link_std_into_rustc_driver(target_compiler.host); let sysroot = builder.sysroot(target_compiler); let rustc_libdir = builder.rustc_libdir(target_compiler); t!(fs::create_dir_all(&rustc_libdir)); let src_libdir = builder.sysroot_libdir(build_compiler, host); for f in builder.read_dir(&src_libdir) { let filename = f.file_name().into_string().unwrap(); + + // For the later stages which gets distributed only copy over the + // `rustc_driver` library so we don't end up with an extra copy of `std`. + // If we're not statically linking `std` into `rustc_driver`, just copy every library + // to ensure `std` is included. + // We still need `std` for the initial stage as the bootstrap compiler may not + // have the new `rustc_private` linking behavior. let can_be_rustc_dep = filename.starts_with("rustc_driver-") || filename.starts_with("librustc_driver-") - || build_compiler.stage == 0; + || build_compiler.stage == 0 + || !link_std_into_rustc_driver; + if can_be_rustc_dep && (is_dylib(&filename) || is_debug_info(&filename)) && !proc_macros.contains(&filename) diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 41837c0eb89b0..ccdeb442af4af 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -1106,6 +1106,12 @@ impl<'a> Builder<'a> { StepDescription::run(v, self, paths); } + /// Returns if `std` should be statically linked into `rustc_driver`. + /// It's currently not done on `windows-gnu` due to linker bugs. + pub fn link_std_into_rustc_driver(&self, target: TargetSelection) -> bool { + !target.triple.ends_with("-windows-gnu") + } + /// Obtain a compiler at a given stage and for a given host (i.e., this is the target that the /// compiler will run on, *not* the target it will build code for). Explicitly does not take /// `Compiler` since all `Compiler` instances are meant to be obtained through this function, @@ -2165,6 +2171,14 @@ impl<'a> Builder<'a> { if matches!(mode, Mode::Std) { rustflags.arg("-Cprefer-dynamic"); } + if matches!(mode, Mode::Rustc) && !self.link_std_into_rustc_driver(target) { + rustflags.arg("-Cprefer-dynamic"); + } + + cargo.env( + "RUSTC_LINK_STD_INTO_RUSTC_DRIVER", + if self.link_std_into_rustc_driver(target) { "1" } else { "0" }, + ); // When building incrementally we default to a lower ThinLTO import limit // (unless explicitly specified otherwise). This will produce a somewhat From 56beb1d744cf5d5b6ab9e802efdf716e15b088f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sat, 10 Aug 2024 08:29:12 +0200 Subject: [PATCH 751/786] Update the unstable book --- .../src/language-features/rustc-private.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/doc/unstable-book/src/language-features/rustc-private.md diff --git a/src/doc/unstable-book/src/language-features/rustc-private.md b/src/doc/unstable-book/src/language-features/rustc-private.md new file mode 100644 index 0000000000000..97fce5980e40b --- /dev/null +++ b/src/doc/unstable-book/src/language-features/rustc-private.md @@ -0,0 +1,11 @@ +# `rustc_private` + +The tracking issue for this feature is: [#27812] + +[#27812]: https://github.com/rust-lang/rust/issues/27812 + +------------------------ + +This feature allows access to unstable internal compiler crates. + +Additionally it changes the linking behavior of crates which have this feature enabled. It will prevent linking to a dylib if there's a static variant of it already statically linked into another dylib dependency. This is required to successfully link to `rustc_driver`. From dd3f7578ee52af74de732f8a8e6dc5d02b284daa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sat, 10 Aug 2024 23:56:43 +0200 Subject: [PATCH 752/786] Exclude just `std` from rustc deps --- src/bootstrap/src/core/build_steps/compile.rs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 2e521ff754407..db0aa1ecff123 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -1838,17 +1838,13 @@ impl Step for Assemble { for f in builder.read_dir(&src_libdir) { let filename = f.file_name().into_string().unwrap(); - // For the later stages which gets distributed only copy over the - // `rustc_driver` library so we don't end up with an extra copy of `std`. - // If we're not statically linking `std` into `rustc_driver`, just copy every library - // to ensure `std` is included. + // For the later stages which gets distributed avoid copying `std` if we're + // statically linking `std` into `rustc_driver`. // We still need `std` for the initial stage as the bootstrap compiler may not // have the new `rustc_private` linking behavior. - let can_be_rustc_dep = filename.starts_with("rustc_driver-") - || filename.starts_with("librustc_driver-") - || build_compiler.stage == 0 - || !link_std_into_rustc_driver; - + let is_std = filename.starts_with("std-") || filename.starts_with("libstd-"); + let can_be_rustc_dep = + !is_std || !link_std_into_rustc_driver || build_compiler.stage == 0; // cfg(bootstrap) if can_be_rustc_dep && (is_dylib(&filename) || is_debug_info(&filename)) && !proc_macros.contains(&filename) From 960e7b55e1b784d7647fdd4f547b4d015671ba06 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: Sat, 10 Aug 2024 03:29:43 +0000 Subject: [PATCH 753/786] tests: tidy up `dump-ice-to-disk` and make assertion failures extremely verbose --- tests/run-make/dump-ice-to-disk/rmake.rs | 285 ++++++++++++++--------- 1 file changed, 172 insertions(+), 113 deletions(-) diff --git a/tests/run-make/dump-ice-to-disk/rmake.rs b/tests/run-make/dump-ice-to-disk/rmake.rs index 260abf3aa6fdc..2716525223fe8 100644 --- a/tests/run-make/dump-ice-to-disk/rmake.rs +++ b/tests/run-make/dump-ice-to-disk/rmake.rs @@ -1,137 +1,196 @@ -// This test checks if internal compilation error (ICE) log files work as expected. -// - Get the number of lines from the log files without any configuration options, -// then check that the line count doesn't change if the backtrace gets configured to be short -// or full. -// - Check that disabling ICE logging results in zero files created. -// - Check that the ICE files contain some of the expected strings. -// - exercise the -Zmetrics-dir nightly flag -// - verify what happens when both the nightly flag and env variable are set -// - test the RUST_BACKTRACE=0 behavior against the file creation +//! This test checks if Internal Compilation Error (ICE) dump files `rustc-ice*.txt` work as +//! expected. +//! +//! - Basic sanity checks on a default ICE dump. +//! - Get the number of lines from the dump files without any `RUST_BACKTRACE` options, then check +//! ICE dump file (line count) is not affected by `RUSTC_BACKTRACE` settings. +//! - Check that disabling ICE dumping results in zero dump files created. +//! - Check that the ICE dump contain some of the expected strings. +//! - Check that `RUST_BACKTRACE=0` prevents ICE dump from created. +//! - Exercise the `-Zmetrics-dir` nightly flag (#128914): +//! - When `-Zmetrics=dir=PATH` is present but `RUSTC_ICE` is not set, check that the ICE dump +//! is placed under `PATH`. +//! - When `RUSTC_ICE=RUSTC_ICE_PATH` and `-Zmetrics-dir=METRICS_PATH` are both provided, check +//! that `RUSTC_ICE_PATH` takes precedence and no ICE dump is emitted under `METRICS_PATH`. +//! +//! See . -// See https://github.com/rust-lang/rust/pull/108714 +// FIXME(#128911): @jieyouxu: This test is sometimes for whatever forsaken reason flakey in CI, and +// I cannot reproduce it locally. The error messages upon assertion failure in this test is +// intentionally extremely verbose to aid debugging that issue. -use run_make_support::{cwd, has_extension, has_prefix, rfs, rustc, shallow_find_files}; +use std::cell::OnceCell; +use std::path::{Path, PathBuf}; -fn main() { - rustc().env("RUSTC_ICE", cwd()).input("lib.rs").arg("-Ztreat-err-as-bug=1").run_fail(); - let default = get_text_from_ice(".").lines().count(); - - clear_ice_files(); - rustc().env("RUSTC_ICE", cwd()).input("lib.rs").arg("-Ztreat-err-as-bug=1").run_fail(); - let ice_text = get_text_from_ice(cwd()); - let default_set = ice_text.lines().count(); - let content = ice_text; - let ice_files = shallow_find_files(cwd(), |path| { - has_prefix(path, "rustc-ice") && has_extension(path, "txt") - }); +use run_make_support::{ + cwd, filename_contains, has_extension, has_prefix, rfs, run_in_tmpdir, rustc, + shallow_find_files, +}; + +#[derive(Debug)] +struct IceDump { + name: &'static str, + path: PathBuf, + message: String, +} + +impl IceDump { + fn lines_count(&self) -> usize { + self.message.lines().count() + } +} + +#[track_caller] +fn assert_ice_len_equals(left: &IceDump, right: &IceDump) { + let left_len = left.lines_count(); + let right_len = right.lines_count(); + + if left_len != right_len { + eprintln!("=== {} ICE MESSAGE ({} lines) ====", left.name, left_len); + eprintln!("{}", left.message); + + eprintln!("=== {} ICE MESSAGE ({} lines) ====", right.name, right_len); + eprintln!("{}", right.message); + + eprintln!("===================================="); + panic!( + "ICE message length mismatch: {} has {} lines but {} has {} lines", + left.name, left_len, right.name, right_len + ); + } +} + +fn find_ice_dumps_in_dir>(dir: P) -> Vec { + shallow_find_files(dir, |path| has_prefix(path, "rustc-ice") && has_extension(path, "txt")) +} + +// Assert only one `rustc-ice*.txt` ICE file exists, and extract the ICE message from the ICE file. +#[track_caller] +fn extract_exactly_one_ice_file>(name: &'static str, dir: P) -> IceDump { + let ice_files = find_ice_dumps_in_dir(dir); assert_eq!(ice_files.len(), 1); // There should only be 1 ICE file. - let ice_file_name = - ice_files.first().and_then(|f| f.file_name()).and_then(|n| n.to_str()).unwrap(); - // Ensure that the ICE dump path doesn't contain `:`, because they cause problems on Windows. - assert!(!ice_file_name.contains(":"), "{ice_file_name}"); - assert_eq!(default, default_set); - assert!(default > 0); - // Some of the expected strings in an ICE file should appear. - assert!(content.contains("thread 'rustc' panicked at")); - assert!(content.contains("stack backtrace:")); - - test_backtrace_short(default); - test_backtrace_full(default); - test_backtrace_disabled(default); - - clear_ice_files(); - // The ICE dump is explicitly disabled. Therefore, this should produce no files. - rustc().env("RUSTC_ICE", "0").input("lib.rs").arg("-Ztreat-err-as-bug=1").run_fail(); - let ice_files = shallow_find_files(cwd(), |path| { - has_prefix(path, "rustc-ice") && has_extension(path, "txt") + let path = ice_files.get(0).unwrap(); + let message = rfs::read_to_string(path); + IceDump { name, path: path.to_path_buf(), message } +} + +fn main() { + // Establish baseline ICE message. + let mut default_ice_dump = OnceCell::new(); + run_in_tmpdir(|| { + rustc().env("RUSTC_ICE", cwd()).input("lib.rs").arg("-Ztreat-err-as-bug=1").run_fail(); + let dump = extract_exactly_one_ice_file("baseline", cwd()); + // Ensure that the ICE dump path doesn't contain `:`, because they cause problems on + // Windows. + assert!(!filename_contains(&dump.path, ":"), "{} contains `:`", dump.path.display()); + // Some of the expected strings in an ICE file should appear. + assert!(dump.message.contains("thread 'rustc' panicked at")); + assert!(dump.message.contains("stack backtrace:")); + default_ice_dump.set(dump).unwrap(); }); - assert!(ice_files.is_empty()); // There should be 0 ICE files. + let default_ice_dump = default_ice_dump.get().unwrap(); - metrics_dir(default); -} + test_backtrace_short(default_ice_dump); + test_backtrace_full(default_ice_dump); + test_backtrace_disabled(default_ice_dump); + test_ice_dump_disabled(); -fn test_backtrace_short(baseline: usize) { - clear_ice_files(); - rustc() - .env("RUSTC_ICE", cwd()) - .input("lib.rs") - .env("RUST_BACKTRACE", "short") - .arg("-Ztreat-err-as-bug=1") - .run_fail(); - let short = get_text_from_ice(cwd()).lines().count(); - // backtrace length in dump shouldn't be changed by RUST_BACKTRACE - assert_eq!(short, baseline); + test_metrics_dir(default_ice_dump); } -fn test_backtrace_full(baseline: usize) { - clear_ice_files(); - rustc() - .env("RUSTC_ICE", cwd()) - .input("lib.rs") - .env("RUST_BACKTRACE", "full") - .arg("-Ztreat-err-as-bug=1") - .run_fail(); - let full = get_text_from_ice(cwd()).lines().count(); - // backtrace length in dump shouldn't be changed by RUST_BACKTRACE - assert_eq!(full, baseline); +#[track_caller] +fn test_backtrace_short(baseline: &IceDump) { + run_in_tmpdir(|| { + rustc() + .env("RUSTC_ICE", cwd()) + .input("lib.rs") + .env("RUST_BACKTRACE", "short") + .arg("-Ztreat-err-as-bug=1") + .run_fail(); + let dump = extract_exactly_one_ice_file("RUST_BACKTRACE=short", cwd()); + // Backtrace length in dump shouldn't be changed by `RUST_BACKTRACE`. + assert_ice_len_equals(baseline, &dump); + }); } -fn test_backtrace_disabled(baseline: usize) { - clear_ice_files(); - rustc() - .env("RUSTC_ICE", cwd()) - .input("lib.rs") - .env("RUST_BACKTRACE", "0") - .arg("-Ztreat-err-as-bug=1") - .run_fail(); - let disabled = get_text_from_ice(cwd()).lines().count(); - // backtrace length in dump shouldn't be changed by RUST_BACKTRACE - assert_eq!(disabled, baseline); +#[track_caller] +fn test_backtrace_full(baseline: &IceDump) { + run_in_tmpdir(|| { + rustc() + .env("RUSTC_ICE", cwd()) + .input("lib.rs") + .env("RUST_BACKTRACE", "full") + .arg("-Ztreat-err-as-bug=1") + .run_fail(); + let dump = extract_exactly_one_ice_file("RUST_BACKTRACE=full", cwd()); + // Backtrace length in dump shouldn't be changed by `RUST_BACKTRACE`. + assert_ice_len_equals(baseline, &dump); + }); } -fn metrics_dir(baseline: usize) { - test_flag_only(baseline); - test_flag_and_env(baseline); +#[track_caller] +fn test_backtrace_disabled(baseline: &IceDump) { + run_in_tmpdir(|| { + rustc() + .env("RUSTC_ICE", cwd()) + .input("lib.rs") + .env("RUST_BACKTRACE", "0") + .arg("-Ztreat-err-as-bug=1") + .run_fail(); + let dump = extract_exactly_one_ice_file("RUST_BACKTRACE=disabled", cwd()); + // Backtrace length in dump shouldn't be changed by `RUST_BACKTRACE`. + assert_ice_len_equals(baseline, &dump); + }); } -fn test_flag_only(baseline: usize) { - clear_ice_files(); - let metrics_arg = format!("-Zmetrics-dir={}", cwd().display()); - rustc().input("lib.rs").arg("-Ztreat-err-as-bug=1").arg(metrics_arg).run_fail(); - let output = get_text_from_ice(cwd()).lines().count(); - assert_eq!(output, baseline); +#[track_caller] +fn test_ice_dump_disabled() { + // The ICE dump is explicitly disabled. Therefore, this should produce no files. + run_in_tmpdir(|| { + rustc().env("RUSTC_ICE", "0").input("lib.rs").arg("-Ztreat-err-as-bug=1").run_fail(); + let ice_files = find_ice_dumps_in_dir(cwd()); + assert!(ice_files.is_empty(), "there should be no ICE files if `RUSTC_ICE=0` is set"); + }); } -fn test_flag_and_env(baseline: usize) { - clear_ice_files(); - let metrics_arg = format!("-Zmetrics-dir={}", cwd().display()); - let real_dir = cwd().join("actually_put_ice_here"); - rfs::create_dir(real_dir.clone()); - rustc() - .input("lib.rs") - .env("RUSTC_ICE", real_dir.clone()) - .arg("-Ztreat-err-as-bug=1") - .arg(metrics_arg) - .run_fail(); - let output = get_text_from_ice(real_dir).lines().count(); - assert_eq!(output, baseline); +#[track_caller] +fn test_metrics_dir(baseline: &IceDump) { + test_flag_only(baseline); + test_flag_and_env(baseline); } -fn clear_ice_files() { - let ice_files = shallow_find_files(cwd(), |path| { - has_prefix(path, "rustc-ice") && has_extension(path, "txt") +#[track_caller] +fn test_flag_only(baseline: &IceDump) { + run_in_tmpdir(|| { + let metrics_arg = format!("-Zmetrics-dir={}", cwd().display()); + rustc() + .env_remove("RUSTC_ICE") // prevent interference from environment + .input("lib.rs") + .arg("-Ztreat-err-as-bug=1") + .arg(metrics_arg) + .run_fail(); + let dump = extract_exactly_one_ice_file("-Zmetrics-dir only", cwd()); + assert_ice_len_equals(baseline, &dump); }); - for file in ice_files { - rfs::remove_file(file); - } } #[track_caller] -fn get_text_from_ice(dir: impl AsRef) -> String { - let ice_files = - shallow_find_files(dir, |path| has_prefix(path, "rustc-ice") && has_extension(path, "txt")); - assert_eq!(ice_files.len(), 1); // There should only be 1 ICE file. - let ice_file = ice_files.get(0).unwrap(); - let output = rfs::read_to_string(ice_file); - output +fn test_flag_and_env(baseline: &IceDump) { + run_in_tmpdir(|| { + let metrics_arg = format!("-Zmetrics-dir={}", cwd().display()); + let real_dir = cwd().join("actually_put_ice_here"); + rfs::create_dir(&real_dir); + rustc() + .input("lib.rs") + .env("RUSTC_ICE", &real_dir) + .arg("-Ztreat-err-as-bug=1") + .arg(metrics_arg) + .run_fail(); + + let cwd_ice_files = find_ice_dumps_in_dir(cwd()); + assert!(cwd_ice_files.is_empty(), "RUSTC_ICE should override -Zmetrics-dir"); + + let dump = extract_exactly_one_ice_file("RUSTC_ICE overrides -Zmetrics-dir", real_dir); + assert_ice_len_equals(baseline, &dump); + }); } From b22253c45489716a27164b3584a580140afa6967 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sun, 11 Aug 2024 05:43:32 +0200 Subject: [PATCH 754/786] Keep rustc's std copy --- src/bootstrap/src/core/build_steps/compile.rs | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index db0aa1ecff123..c09180e542ff6 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -1830,24 +1830,13 @@ impl Step for Assemble { }) .collect::>(); - let link_std_into_rustc_driver = builder.link_std_into_rustc_driver(target_compiler.host); let sysroot = builder.sysroot(target_compiler); let rustc_libdir = builder.rustc_libdir(target_compiler); t!(fs::create_dir_all(&rustc_libdir)); let src_libdir = builder.sysroot_libdir(build_compiler, host); for f in builder.read_dir(&src_libdir) { let filename = f.file_name().into_string().unwrap(); - - // For the later stages which gets distributed avoid copying `std` if we're - // statically linking `std` into `rustc_driver`. - // We still need `std` for the initial stage as the bootstrap compiler may not - // have the new `rustc_private` linking behavior. - let is_std = filename.starts_with("std-") || filename.starts_with("libstd-"); - let can_be_rustc_dep = - !is_std || !link_std_into_rustc_driver || build_compiler.stage == 0; // cfg(bootstrap) - if can_be_rustc_dep - && (is_dylib(&filename) || is_debug_info(&filename)) - && !proc_macros.contains(&filename) + if (is_dylib(&filename) || is_debug_info(&filename)) && !proc_macros.contains(&filename) { builder.copy_link(&f.path(), &rustc_libdir.join(&filename)); } From dcd6170c89ae9b273b57d8a25529baa19a4cf0a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Sun, 11 Aug 2024 09:34:26 +0000 Subject: [PATCH 755/786] use `rfs` in rustdoc io rmake test --- tests/run-make/rustdoc-io-error/rmake.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/tests/run-make/rustdoc-io-error/rmake.rs b/tests/run-make/rustdoc-io-error/rmake.rs index 96dafa8adfd91..a5fae36e733da 100644 --- a/tests/run-make/rustdoc-io-error/rmake.rs +++ b/tests/run-make/rustdoc-io-error/rmake.rs @@ -14,22 +14,20 @@ // `mkfs.ext4 -d`, as well as mounting a loop device for the rootfs. //@ ignore-windows - the `set_readonly` functions doesn't work on folders. -use std::fs; - -use run_make_support::{path, rustdoc}; +use run_make_support::{path, rfs, rustdoc}; fn main() { let out_dir = path("rustdoc-io-error"); - fs::create_dir(&out_dir).unwrap(); - let mut permissions = fs::metadata(&out_dir).unwrap().permissions(); + rfs::create_dir(&out_dir); + let mut permissions = rfs::metadata(&out_dir).permissions(); let original_permissions = permissions.clone(); permissions.set_readonly(true); - fs::set_permissions(&out_dir, permissions).unwrap(); + rfs::set_permissions(&out_dir, permissions); let output = rustdoc().input("foo.rs").output(&out_dir).env("RUST_BACKTRACE", "1").run_fail(); - fs::set_permissions(&out_dir, original_permissions).unwrap(); + rfs::set_permissions(&out_dir, original_permissions); output .assert_exit_code(1) From 6dc300ba4531b855132ac8b3ac38f7bb73c8fe52 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, 11 Aug 2024 11:11:22 +0000 Subject: [PATCH 756/786] tests: ignore `dump-ice-to-disk` on windows --- tests/run-make/dump-ice-to-disk/rmake.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/run-make/dump-ice-to-disk/rmake.rs b/tests/run-make/dump-ice-to-disk/rmake.rs index 2716525223fe8..48b4071e06541 100644 --- a/tests/run-make/dump-ice-to-disk/rmake.rs +++ b/tests/run-make/dump-ice-to-disk/rmake.rs @@ -15,9 +15,10 @@ //! //! See . -// FIXME(#128911): @jieyouxu: This test is sometimes for whatever forsaken reason flakey in CI, and -// I cannot reproduce it locally. The error messages upon assertion failure in this test is -// intentionally extremely verbose to aid debugging that issue. +//@ ignore-windows +// FIXME(#128911): @jieyouxu: This test is sometimes for whatever forsaken reason flakey in +// `i686-mingw`, and I cannot reproduce it locally. The error messages upon assertion failure in +// this test is intentionally extremely verbose to aid debugging that issue. use std::cell::OnceCell; use std::path::{Path, PathBuf}; From 715728f546ec13fd7e59fd09eef96a15d936fc2a Mon Sep 17 00:00:00 2001 From: beetrees Date: Sun, 4 Aug 2024 15:01:58 +0100 Subject: [PATCH 757/786] Refactor `powerpc64` call ABI handling --- .../rustc_target/src/abi/call/powerpc64.rs | 67 ++------- tests/assembly/powerpc64-struct-abi.rs | 132 ++++++++++++++++++ 2 files changed, 144 insertions(+), 55 deletions(-) create mode 100644 tests/assembly/powerpc64-struct-abi.rs diff --git a/compiler/rustc_target/src/abi/call/powerpc64.rs b/compiler/rustc_target/src/abi/call/powerpc64.rs index 11a6cb52babc9..749eea0ef6350 100644 --- a/compiler/rustc_target/src/abi/call/powerpc64.rs +++ b/compiler/rustc_target/src/abi/call/powerpc64.rs @@ -41,64 +41,23 @@ where }) } -fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>, abi: ABI) +fn classify<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, abi: ABI, is_ret: bool) where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout, { - if !ret.layout.is_sized() { + if arg.is_ignore() || !arg.layout.is_sized() { // Not touching this... return; } - if !ret.layout.is_aggregate() { - ret.extend_integer_width_to(64); + if !arg.layout.is_aggregate() { + arg.extend_integer_width_to(64); return; } // The ELFv1 ABI doesn't return aggregates in registers - if abi == ELFv1 { - ret.make_indirect(); - return; - } - - if let Some(uniform) = is_homogeneous_aggregate(cx, ret, abi) { - ret.cast_to(uniform); - return; - } - - let size = ret.layout.size; - let bits = size.bits(); - if bits <= 128 { - let unit = if cx.data_layout().endian == Endian::Big { - Reg { kind: RegKind::Integer, size } - } else if bits <= 8 { - Reg::i8() - } else if bits <= 16 { - Reg::i16() - } else if bits <= 32 { - Reg::i32() - } else { - Reg::i64() - }; - - ret.cast_to(Uniform::new(unit, size)); - return; - } - - ret.make_indirect(); -} - -fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, abi: ABI) -where - Ty: TyAbiInterface<'a, C> + Copy, - C: HasDataLayout, -{ - if !arg.layout.is_sized() { - // Not touching this... - return; - } - if !arg.layout.is_aggregate() { - arg.extend_integer_width_to(64); + if is_ret && abi == ELFv1 { + arg.make_indirect(); return; } @@ -108,7 +67,10 @@ where } let size = arg.layout.size; - if size.bits() <= 64 { + if is_ret && size.bits() > 128 { + // Non-homogeneous aggregates larger than two doublewords are returned indirectly. + arg.make_indirect(); + } else if size.bits() <= 64 { // Aggregates smaller than a doubleword should appear in // the least-significant bits of the parameter doubleword. arg.cast_to(Reg { kind: RegKind::Integer, size }) @@ -138,14 +100,9 @@ where } }; - if !fn_abi.ret.is_ignore() { - classify_ret(cx, &mut fn_abi.ret, abi); - } + classify(cx, &mut fn_abi.ret, abi, true); for arg in fn_abi.args.iter_mut() { - if arg.is_ignore() { - continue; - } - classify_arg(cx, arg, abi); + classify(cx, arg, abi, false); } } diff --git a/tests/assembly/powerpc64-struct-abi.rs b/tests/assembly/powerpc64-struct-abi.rs new file mode 100644 index 0000000000000..9a3540d8b4163 --- /dev/null +++ b/tests/assembly/powerpc64-struct-abi.rs @@ -0,0 +1,132 @@ +//@ revisions: elfv1-be elfv2-be elfv2-le +//@ assembly-output: emit-asm +//@ compile-flags: -O +//@[elfv1-be] compile-flags: --target powerpc64-unknown-linux-gnu +//@[elfv1-be] needs-llvm-components: powerpc +//@[elfv2-be] compile-flags: --target powerpc64-unknown-linux-musl +//@[elfv2-be] needs-llvm-components: powerpc +//@[elfv2-le] compile-flags: --target powerpc64le-unknown-linux-gnu +//@[elfv2-le] needs-llvm-components: powerpc +//@[elfv1-be] filecheck-flags: --check-prefix be +//@[elfv2-be] filecheck-flags: --check-prefix be + +#![feature(no_core, lang_items)] +#![no_std] +#![no_core] +#![crate_type = "lib"] + +#[lang = "sized"] +trait Sized {} + +#[lang = "copy"] +trait Copy {} + +#[lang = "freeze"] +trait Freeze {} + +#[lang = "unpin"] +trait Unpin {} + +impl Copy for u8 {} +impl Copy for u16 {} +impl Copy for u32 {} +impl Copy for FiveU32s {} +impl Copy for FiveU16s {} +impl Copy for ThreeU8s {} + +#[repr(C)] +struct FiveU32s(u32, u32, u32, u32, u32); + +#[repr(C)] +struct FiveU16s(u16, u16, u16, u16, u16); + +#[repr(C)] +struct ThreeU8s(u8, u8, u8); + +// CHECK-LABEL: read_large +// be: lwz [[REG1:.*]], 16(4) +// be-NEXT: stw [[REG1]], 16(3) +// be-NEXT: ld [[REG2:.*]], 8(4) +// be-NEXT: ld [[REG3:.*]], 0(4) +// be-NEXT: std [[REG2]], 8(3) +// be-NEXT: std [[REG3]], 0(3) +// elfv2-le: lxvd2x [[REG1:.*]], 0, 4 +// elfv2-le-NEXT: lwz [[REG2:.*]], 16(4) +// elfv2-le-NEXT: stw [[REG2]], 16(3) +// elfv2-le-NEXT: stxvd2x [[REG1]], 0, 3 +// CHECK-NEXT: blr +#[no_mangle] +extern "C" fn read_large(x: &FiveU32s) -> FiveU32s { + *x +} + +// CHECK-LABEL: read_medium +// elfv1-be: lhz [[REG1:.*]], 8(4) +// elfv1-be-NEXT: ld [[REG2:.*]], 0(4) +// elfv1-be-NEXT: sth [[REG1]], 8(3) +// elfv1-be-NEXT: std [[REG2]], 0(3) +// elfv2-be: lhz [[REG1:.*]], 8(3) +// elfv2-be-NEXT: ld 3, 0(3) +// elfv2-be-NEXT: sldi 4, [[REG1]], 48 +// elfv2-le: ld [[REG1:.*]], 0(3) +// elfv2-le-NEXT: lhz 4, 8(3) +// elfv2-le-NEXT: mr 3, [[REG1]] +// CHECK-NEXT: blr +#[no_mangle] +extern "C" fn read_medium(x: &FiveU16s) -> FiveU16s { + *x +} + +// CHECK-LABEL: read_small +// elfv1-be: lbz [[REG1:.*]], 2(4) +// elfv1-be-NEXT: lhz [[REG2:.*]], 0(4) +// elfv1-be-NEXT: stb [[REG1]], 2(3) +// elfv1-be-NEXT: sth [[REG2]], 0(3) +// elfv2-be: lhz [[REG1:.*]], 0(3) +// elfv2-be-NEXT: lbz 3, 2(3) +// elfv2-be-NEXT: rldimi 3, [[REG1]], 8, 0 +// elfv2-le: lbz [[REG1:.*]], 2(3) +// elfv2-le-NEXT: lhz 3, 0(3) +// elfv2-le-NEXT: rldimi 3, [[REG1]], 16, 0 +// CHECK-NEXT: blr +#[no_mangle] +extern "C" fn read_small(x: &ThreeU8s) -> ThreeU8s { + *x +} + +// CHECK-LABEL: write_large +// CHECK: std 3, 0(6) +// be-NEXT: rldicl [[REG1:.*]], 5, 32, 32 +// CHECK-NEXT: std 4, 8(6) +// be-NEXT: stw [[REG1]], 16(6) +// elfv2-le-NEXT: stw 5, 16(6) +// CHECK-NEXT: blr +#[no_mangle] +extern "C" fn write_large(x: FiveU32s, dest: &mut FiveU32s) { + *dest = x; +} + +// CHECK-LABEL: write_medium +// CHECK: std 3, 0(5) +// be-NEXT: rldicl [[REG1:.*]], 4, 16, 48 +// be-NEXT: sth [[REG1]], 8(5) +// elfv2-le-NEXT: sth 4, 8(5) +// CHECK-NEXT: blr +#[no_mangle] +extern "C" fn write_medium(x: FiveU16s, dest: &mut FiveU16s) { + *dest = x; +} + +// CHECK-LABEL: write_small +// be: stb 3, 2(4) +// be-NEXT: srwi [[REG1:.*]], 3, 8 +// be-NEXT: sth [[REG1]], 0(4) +// The order these instructions are emitted in changed in LLVM 18. +// elfv2-le-DAG: sth 3, 0(4) +// elfv2-le-DAG: srwi [[REG1:.*]], 3, 16 +// elfv2-le-NEXT: stb [[REG1]], 2(4) +// CHECK-NEXT: blr +#[no_mangle] +extern "C" fn write_small(x: ThreeU8s, dest: &mut ThreeU8s) { + *dest = x; +} From c361c924a08c2e34c705ec3ee1ad2099315338d8 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 11 Aug 2024 12:10:36 -0400 Subject: [PATCH 758/786] Use assert_matches around the compiler --- .../rustc_borrowck/src/diagnostics/explain_borrow.rs | 6 ++++-- compiler/rustc_codegen_llvm/src/asm.rs | 4 +++- compiler/rustc_codegen_llvm/src/intrinsic.rs | 3 ++- compiler/rustc_codegen_llvm/src/lib.rs | 1 + compiler/rustc_codegen_ssa/src/back/write.rs | 3 ++- compiler/rustc_codegen_ssa/src/lib.rs | 1 + compiler/rustc_codegen_ssa/src/mir/operand.rs | 3 ++- compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 4 +++- compiler/rustc_codegen_ssa/src/traits/builder.rs | 6 ++++-- compiler/rustc_const_eval/src/check_consts/check.rs | 5 +++-- compiler/rustc_const_eval/src/interpret/call.rs | 3 ++- compiler/rustc_const_eval/src/interpret/intrinsics.rs | 8 +++++--- compiler/rustc_const_eval/src/interpret/operand.rs | 2 +- compiler/rustc_data_structures/src/graph/scc/mod.rs | 3 ++- compiler/rustc_data_structures/src/lib.rs | 1 + compiler/rustc_errors/src/lib.rs | 4 +++- compiler/rustc_hir_analysis/src/check/intrinsicck.rs | 10 ++++++---- compiler/rustc_hir_analysis/src/coherence/builtin.rs | 3 ++- compiler/rustc_hir_analysis/src/collect/generics_of.rs | 9 +++++---- .../rustc_hir_analysis/src/collect/predicates_of.rs | 4 +++- compiler/rustc_hir_analysis/src/delegation.rs | 4 +++- compiler/rustc_hir_analysis/src/impl_wf_check.rs | 4 +++- compiler/rustc_hir_analysis/src/lib.rs | 1 + compiler/rustc_infer/src/infer/outlives/verify.rs | 4 +++- compiler/rustc_infer/src/lib.rs | 1 + compiler/rustc_middle/src/ty/consts/kind.rs | 10 ++++++---- compiler/rustc_mir_dataflow/src/impls/initialized.rs | 4 +++- compiler/rustc_mir_dataflow/src/lib.rs | 1 + compiler/rustc_mir_dataflow/src/value_analysis.rs | 5 +++-- compiler/rustc_mir_transform/src/promote_consts.rs | 4 ++-- compiler/rustc_mir_transform/src/shim.rs | 2 +- compiler/rustc_parse/src/lib.rs | 1 + compiler/rustc_parse/src/parser/mod.rs | 3 ++- compiler/rustc_parse/src/parser/tests.rs | 3 ++- compiler/rustc_target/src/spec/abi/tests.rs | 4 +++- .../rustc_trait_selection/src/solve/inspect/analyse.rs | 6 ++++-- compiler/rustc_trait_selection/src/solve/normalize.rs | 3 ++- compiler/rustc_trait_selection/src/traits/misc.rs | 4 +++- compiler/rustc_ty_utils/src/layout_sanity_check.rs | 2 +- 39 files changed, 100 insertions(+), 49 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 3590e12274ca6..d85959c9a291e 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -3,6 +3,8 @@ #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] +use std::assert_matches::assert_matches; + use rustc_errors::{Applicability, Diag}; use rustc_hir as hir; use rustc_hir::intravisit::Visitor; @@ -116,7 +118,7 @@ impl<'tcx> BorrowExplanation<'tcx> { // path_span must be `Some` as otherwise the if condition is true let path_span = path_span.unwrap(); // path_span is only present in the case of closure capture - assert!(matches!(later_use_kind, LaterUseKind::ClosureCapture)); + assert_matches!(later_use_kind, LaterUseKind::ClosureCapture); if !borrow_span.is_some_and(|sp| sp.overlaps(var_or_use_span)) { let path_label = "used here by closure"; let capture_kind_label = message; @@ -147,7 +149,7 @@ impl<'tcx> BorrowExplanation<'tcx> { // path_span must be `Some` as otherwise the if condition is true let path_span = path_span.unwrap(); // path_span is only present in the case of closure capture - assert!(matches!(later_use_kind, LaterUseKind::ClosureCapture)); + assert_matches!(later_use_kind, LaterUseKind::ClosureCapture); if borrow_span.map(|sp| !sp.overlaps(var_or_use_span)).unwrap_or(true) { let path_label = "used here by closure"; let capture_kind_label = message; diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index aea8395441a86..f931698c38f91 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -1,3 +1,5 @@ +use std::assert_matches::assert_matches; + use libc::{c_char, c_uint}; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_codegen_ssa::mir::operand::OperandValue; @@ -89,7 +91,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { // if the target feature needed by the register class is // disabled. This is necessary otherwise LLVM will try // to actually allocate a register for the dummy output. - assert!(matches!(reg, InlineAsmRegOrRegClass::Reg(_))); + assert_matches!(reg, InlineAsmRegOrRegClass::Reg(_)); clobbers.push(format!("~{}", reg_to_llvm(reg, None))); continue; } else { diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 57d5f6fdf503f..f5558723d11bf 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -1,3 +1,4 @@ +use std::assert_matches::assert_matches; use std::cmp::Ordering; use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh, wants_wasm_eh}; @@ -1142,7 +1143,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( if cfg!(debug_assertions) { for (ty, arg) in arg_tys.iter().zip(args) { if ty.is_simd() { - assert!(matches!(arg.val, OperandValue::Immediate(_))); + assert_matches!(arg.val, OperandValue::Immediate(_)); } } } diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 518a86e0cb06d..43164390a1c6c 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -8,6 +8,7 @@ #![allow(internal_features)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] +#![feature(assert_matches)] #![feature(exact_size_is_empty)] #![feature(extern_types)] #![feature(hash_raw_entry)] diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index bea12747a5199..70b45a852ca0e 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -1,4 +1,5 @@ use std::any::Any; +use std::assert_matches::assert_matches; use std::marker::PhantomData; use std::path::{Path, PathBuf}; use std::sync::mpsc::{channel, Receiver, Sender}; @@ -1963,7 +1964,7 @@ impl SharedEmitterMain { sess.dcx().abort_if_errors(); } Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)) => { - assert!(matches!(level, Level::Error | Level::Warning | Level::Note)); + assert_matches!(level, Level::Error | Level::Warning | Level::Note); let msg = msg.strip_prefix("error: ").unwrap_or(&msg).to_string(); let mut err = Diag::<()>::new(sess.dcx(), level, msg); diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 1b029660433bd..cb6d9d6f66e78 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -4,6 +4,7 @@ #![allow(rustc::untranslatable_diagnostic)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] +#![feature(assert_matches)] #![feature(box_patterns)] #![feature(if_let_guard)] #![feature(let_chains)] diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index 2bc2d0f70bfaf..c57ad1384ac98 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -1,3 +1,4 @@ +use std::assert_matches::assert_matches; use std::fmt; use arrayvec::ArrayVec; @@ -389,7 +390,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { } // Newtype vector of array, e.g. #[repr(simd)] struct S([i32; 4]); (OperandValue::Immediate(llval), Abi::Aggregate { sized: true }) => { - assert!(matches!(self.layout.abi, Abi::Vector { .. })); + assert_matches!(self.layout.abi, Abi::Vector { .. }); let llfield_ty = bx.cx().backend_type(field); diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index d91a118bc71a3..3c2c29ac7f7d2 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -1,3 +1,5 @@ +use std::assert_matches::assert_matches; + use arrayvec::ArrayVec; use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout}; @@ -220,7 +222,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { match operand.val { OperandValue::Ref(source_place_val) => { assert_eq!(source_place_val.llextra, None); - assert!(matches!(operand_kind, OperandValueKind::Ref)); + assert_matches!(operand_kind, OperandValueKind::Ref); Some(bx.load_operand(source_place_val.with_type(cast)).val) } OperandValue::ZeroSized => { diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index 2b802240e03b9..6cf84a012f061 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -1,3 +1,5 @@ +use std::assert_matches::assert_matches; + use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::ty::layout::{HasParamEnv, TyAndLayout}; use rustc_middle::ty::{Instance, Ty}; @@ -254,10 +256,10 @@ pub trait BuilderMethods<'a, 'tcx>: } else { (in_ty, dest_ty) }; - assert!(matches!( + assert_matches!( self.cx().type_kind(float_ty), TypeKind::Half | TypeKind::Float | TypeKind::Double | TypeKind::FP128 - )); + ); assert_eq!(self.cx().type_kind(int_ty), TypeKind::Integer); if let Some(false) = self.cx().sess().opts.unstable_opts.saturating_float_casts { diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index 3ded81b90ffc1..844f3f3d6113c 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -1,5 +1,6 @@ //! The `Visitor` responsible for actually checking a `mir::Body` for invalid operations. +use std::assert_matches::assert_matches; use std::mem; use std::ops::Deref; @@ -590,7 +591,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { if is_int_bool_or_char(lhs_ty) && is_int_bool_or_char(rhs_ty) { // Int, bool, and char operations are fine. } else if lhs_ty.is_fn_ptr() || lhs_ty.is_unsafe_ptr() { - assert!(matches!( + assert_matches!( op, BinOp::Eq | BinOp::Ne @@ -599,7 +600,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { | BinOp::Ge | BinOp::Gt | BinOp::Offset - )); + ); self.check_op(ops::RawPtrComparison); } else if lhs_ty.is_floating_point() || rhs_ty.is_floating_point() { diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index fdbdfc7e1b8b3..917a2fa7c6dd4 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -1,5 +1,6 @@ //! Manages calling a concrete function (with known MIR body) with argument passing, //! and returning the return value to the caller. +use std::assert_matches::assert_matches; use std::borrow::Cow; use either::{Left, Right}; @@ -557,7 +558,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { unwind, )? { assert!(!self.tcx.intrinsic(fallback.def_id()).unwrap().must_be_overridden); - assert!(matches!(fallback.def, ty::InstanceKind::Item(_))); + assert_matches!(fallback.def, ty::InstanceKind::Item(_)); return self.init_fn_call( FnVal::Instance(fallback), (caller_abi, caller_fn_abi), diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 9210ec4e16fd0..3be1b745d0057 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -2,6 +2,8 @@ //! looking at their MIR. Intrinsics/functions supported here are shared by CTFE //! and miri. +use std::assert_matches::assert_matches; + use rustc_hir::def_id::DefId; use rustc_middle::mir::{self, BinOp, ConstValue, NonDivergingIntrinsic}; use rustc_middle::ty::layout::{LayoutOf as _, TyAndLayout, ValidityRequirement}; @@ -510,7 +512,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { dest: &MPlaceTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { assert_eq!(a.layout.ty, b.layout.ty); - assert!(matches!(a.layout.ty.kind(), ty::Int(..) | ty::Uint(..))); + assert_matches!(a.layout.ty.kind(), ty::Int(..) | ty::Uint(..)); // Performs an exact division, resulting in undefined behavior where // `x % y != 0` or `y == 0` or `x == T::MIN && y == -1`. @@ -536,8 +538,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { r: &ImmTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx, Scalar> { assert_eq!(l.layout.ty, r.layout.ty); - assert!(matches!(l.layout.ty.kind(), ty::Int(..) | ty::Uint(..))); - assert!(matches!(mir_op, BinOp::Add | BinOp::Sub)); + assert_matches!(l.layout.ty.kind(), ty::Int(..) | ty::Uint(..)); + assert_matches!(mir_op, BinOp::Add | BinOp::Sub); let (val, overflowed) = self.binary_op(mir_op.wrapping_to_overflowing().unwrap(), l, r)?.to_scalar_pair(); diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 4ced009ab39b6..ad87d6953d3f2 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -342,7 +342,7 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> { } // extract fields from types with `ScalarPair` ABI (Immediate::ScalarPair(a_val, b_val), Abi::ScalarPair(a, b)) => { - assert!(matches!(layout.abi, Abi::Scalar(..))); + assert_matches!(layout.abi, Abi::Scalar(..)); Immediate::from(if offset.bytes() == 0 { debug_assert_eq!(layout.size, a.size(cx)); a_val diff --git a/compiler/rustc_data_structures/src/graph/scc/mod.rs b/compiler/rustc_data_structures/src/graph/scc/mod.rs index 96fc8ae3887f5..2a457ffb70b08 100644 --- a/compiler/rustc_data_structures/src/graph/scc/mod.rs +++ b/compiler/rustc_data_structures/src/graph/scc/mod.rs @@ -8,6 +8,7 @@ //! Typical examples would include: minimum element in SCC, maximum element //! reachable from it, etc. +use std::assert_matches::debug_assert_matches; use std::fmt::Debug; use std::ops::Range; @@ -569,7 +570,7 @@ where // This None marks that we still have the initialize this node's frame. debug!(?depth, ?node); - debug_assert!(matches!(self.node_states[node], NodeState::NotVisited)); + debug_assert_matches!(self.node_states[node], NodeState::NotVisited); // Push `node` onto the stack. self.node_states[node] = NodeState::BeingVisited { diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 403136e78f4eb..a35f5b1f17db4 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -18,6 +18,7 @@ #![feature(array_windows)] #![feature(ascii_char)] #![feature(ascii_char_variants)] +#![feature(assert_matches)] #![feature(auto_traits)] #![feature(cfg_match)] #![feature(core_intrinsics)] diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index ceebcd46a6f7f..48fdc644e8db9 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -10,6 +10,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(array_windows)] +#![feature(assert_matches)] #![feature(associated_type_defaults)] #![feature(box_into_inner)] #![feature(box_patterns)] @@ -28,6 +29,7 @@ extern crate self as rustc_errors; +use std::assert_matches::assert_matches; use std::backtrace::{Backtrace, BacktraceStatus}; use std::borrow::Cow; use std::cell::Cell; @@ -1490,7 +1492,7 @@ impl DiagCtxtInner { // Future breakages aren't emitted if they're `Level::Allow` or // `Level::Expect`, but they still need to be constructed and // stashed below, so they'll trigger the must_produce_diag check. - assert!(matches!(diagnostic.level, Error | Warning | Allow | Expect(_))); + assert_matches!(diagnostic.level, Error | Warning | Allow | Expect(_)); self.future_breakage_diagnostics.push(diagnostic.clone()); } diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs index 847a1e6470679..79ecdee448603 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs @@ -1,3 +1,5 @@ +use std::assert_matches::debug_assert_matches; + use rustc_ast::InlineAsmTemplatePiece; use rustc_data_structures::fx::FxIndexSet; use rustc_hir::{self as hir, LangItem}; @@ -457,17 +459,17 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { } // Typeck has checked that Const operands are integers. hir::InlineAsmOperand::Const { anon_const } => { - debug_assert!(matches!( + debug_assert_matches!( self.tcx.type_of(anon_const.def_id).instantiate_identity().kind(), ty::Error(_) | ty::Int(_) | ty::Uint(_) - )); + ); } // Typeck has checked that SymFn refers to a function. hir::InlineAsmOperand::SymFn { anon_const } => { - debug_assert!(matches!( + debug_assert_matches!( self.tcx.type_of(anon_const.def_id).instantiate_identity().kind(), ty::Error(_) | ty::FnDef(..) - )); + ); } // AST lowering guarantees that SymStatic points to a static. hir::InlineAsmOperand::SymStatic { .. } => {} diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index bdb5f5b720529..fecd78bc38f47 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -1,6 +1,7 @@ //! Check properties that are required by built-in traits and set //! up data structures required by type-checking/codegen. +use std::assert_matches::assert_matches; use std::collections::BTreeMap; use rustc_data_structures::fx::FxHashSet; @@ -129,7 +130,7 @@ fn visit_implementation_of_const_param_ty( checker: &Checker<'_>, kind: LangItem, ) -> Result<(), ErrorGuaranteed> { - assert!(matches!(kind, LangItem::ConstParamTy | LangItem::UnsizedConstParamTy)); + assert_matches!(kind, LangItem::ConstParamTy | LangItem::UnsizedConstParamTy); let tcx = checker.tcx; let header = checker.impl_header; diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 60e2c2eb30e56..28d6cab4b439a 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -1,3 +1,4 @@ +use std::assert_matches::assert_matches; use std::ops::ControlFlow; use hir::intravisit::{self, Visitor}; @@ -207,9 +208,9 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { .. }) => { if in_trait { - assert!(matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn)) + assert_matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn); } else { - assert!(matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn | DefKind::Fn)) + assert_matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn | DefKind::Fn); } Some(fn_def_id.to_def_id()) } @@ -218,9 +219,9 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { .. }) => { if in_assoc_ty { - assert!(matches!(tcx.def_kind(parent), DefKind::AssocTy)); + assert_matches!(tcx.def_kind(parent), DefKind::AssocTy); } else { - assert!(matches!(tcx.def_kind(parent), DefKind::TyAlias)); + assert_matches!(tcx.def_kind(parent), DefKind::TyAlias); } debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent); // Opaque types are always nested within another item, and diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index a5a56cb845d79..6ac4802b19514 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -1,3 +1,5 @@ +use std::assert_matches::assert_matches; + use hir::{HirId, Node}; use rustc_data_structures::fx::FxIndexSet; use rustc_hir as hir; @@ -601,7 +603,7 @@ pub(super) fn implied_predicates_with_filter( let Some(trait_def_id) = trait_def_id.as_local() else { // if `assoc_name` is None, then the query should've been redirected to an // external provider - assert!(matches!(filter, PredicateFilter::SelfThatDefines(_))); + assert_matches!(filter, PredicateFilter::SelfThatDefines(_)); return tcx.explicit_super_predicates_of(trait_def_id); }; diff --git a/compiler/rustc_hir_analysis/src/delegation.rs b/compiler/rustc_hir_analysis/src/delegation.rs index ca62ef92b83de..20aaa43219f34 100644 --- a/compiler/rustc_hir_analysis/src/delegation.rs +++ b/compiler/rustc_hir_analysis/src/delegation.rs @@ -1,3 +1,5 @@ +use std::assert_matches::debug_assert_matches; + use rustc_data_structures::fx::FxHashMap; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -63,7 +65,7 @@ enum FnKind { } fn fn_kind<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> FnKind { - debug_assert!(matches!(tcx.def_kind(def_id), DefKind::Fn | DefKind::AssocFn)); + debug_assert_matches!(tcx.def_kind(def_id), DefKind::Fn | DefKind::AssocFn); let parent = tcx.parent(def_id); match tcx.def_kind(parent) { diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs index a8ae620f7a49d..ab441ed4cde99 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs @@ -8,6 +8,8 @@ //! specialization errors. These things can (and probably should) be //! fixed, but for the moment it's easier to do these checks early. +use std::assert_matches::debug_assert_matches; + use min_specialization::check_min_specialization; use rustc_data_structures::fx::FxHashSet; use rustc_errors::codes::*; @@ -54,7 +56,7 @@ mod min_specialization; pub fn check_impl_wf(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) -> Result<(), ErrorGuaranteed> { let min_specialization = tcx.features().min_specialization; let mut res = Ok(()); - debug_assert!(matches!(tcx.def_kind(impl_def_id), DefKind::Impl { .. })); + debug_assert_matches!(tcx.def_kind(impl_def_id), DefKind::Impl { .. }); res = res.and(enforce_impl_params_are_constrained(tcx, impl_def_id)); if min_specialization { res = res.and(check_min_specialization(tcx, impl_def_id)); diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 061db14ad0a61..291d57f2a176f 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -62,6 +62,7 @@ This API is completely unstable and subject to change. #![allow(rustc::untranslatable_diagnostic)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] +#![feature(assert_matches)] #![feature(control_flow_enum)] #![feature(if_let_guard)] #![feature(iter_intersperse)] diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs index c3d37d9986f6c..1908e1e09c3d5 100644 --- a/compiler/rustc_infer/src/infer/outlives/verify.rs +++ b/compiler/rustc_infer/src/infer/outlives/verify.rs @@ -1,3 +1,5 @@ +use std::assert_matches::assert_matches; + use rustc_middle::ty::{self, OutlivesPredicate, Ty, TyCtxt}; use rustc_type_ir::outlives::{compute_alias_components_recursive, Component}; use smallvec::smallvec; @@ -181,7 +183,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { &self, generic_ty: Ty<'tcx>, ) -> Vec> { - assert!(matches!(generic_ty.kind(), ty::Param(_) | ty::Placeholder(_))); + assert_matches!(generic_ty.kind(), ty::Param(_) | ty::Placeholder(_)); self.declared_generic_bounds_from_env_for_erased_ty(generic_ty) } diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index b65ac8596675a..25ac8ba974bb6 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -18,6 +18,7 @@ #![allow(rustc::untranslatable_diagnostic)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] +#![feature(assert_matches)] #![feature(box_patterns)] #![feature(control_flow_enum)] #![feature(extend_one)] diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index 7f096dd36f8f2..c7c2e8afa1e71 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -1,3 +1,5 @@ +use std::assert_matches::assert_matches; + use rustc_macros::{extension, HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; use super::Const; @@ -80,7 +82,7 @@ impl<'tcx> Expr<'tcx> { } pub fn binop_args(self) -> (Ty<'tcx>, Ty<'tcx>, Const<'tcx>, Const<'tcx>) { - assert!(matches!(self.kind, ExprKind::Binop(_))); + assert_matches!(self.kind, ExprKind::Binop(_)); match self.args().as_slice() { [lhs_ty, rhs_ty, lhs_ct, rhs_ct] => ( @@ -101,7 +103,7 @@ impl<'tcx> Expr<'tcx> { } pub fn unop_args(self) -> (Ty<'tcx>, Const<'tcx>) { - assert!(matches!(self.kind, ExprKind::UnOp(_))); + assert_matches!(self.kind, ExprKind::UnOp(_)); match self.args().as_slice() { [ty, ct] => (ty.expect_ty(), ct.expect_const()), @@ -125,7 +127,7 @@ impl<'tcx> Expr<'tcx> { } pub fn call_args(self) -> (Ty<'tcx>, Const<'tcx>, impl Iterator>) { - assert!(matches!(self.kind, ExprKind::FunctionCall)); + assert_matches!(self.kind, ExprKind::FunctionCall); match self.args().as_slice() { [func_ty, func, rest @ ..] => ( @@ -152,7 +154,7 @@ impl<'tcx> Expr<'tcx> { } pub fn cast_args(self) -> (Ty<'tcx>, Const<'tcx>, Ty<'tcx>) { - assert!(matches!(self.kind, ExprKind::Cast(_))); + assert_matches!(self.kind, ExprKind::Cast(_)); match self.args().as_slice() { [value_ty, value, to_ty] => { diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs index e9e8ddefa020b..7822fb17f7298 100644 --- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs +++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs @@ -1,3 +1,5 @@ +use std::assert_matches::assert_matches; + use rustc_index::bit_set::{BitSet, ChunkedBitSet}; use rustc_index::Idx; use rustc_middle::bug; @@ -496,7 +498,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, '_, 'tcx> { }); if self.skip_unreachable_unwind.contains(location.block) { let mir::TerminatorKind::Drop { target, unwind, .. } = terminator.kind else { bug!() }; - assert!(matches!(unwind, mir::UnwindAction::Cleanup(_))); + assert_matches!(unwind, mir::UnwindAction::Cleanup(_)); TerminatorEdges::Single(target) } else { terminator.edges() diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index b0808ba2067e3..8708bebeeb087 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -1,4 +1,5 @@ // tidy-alphabetical-start +#![feature(assert_matches)] #![feature(associated_type_defaults)] #![feature(box_patterns)] #![feature(exact_size_is_empty)] diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index ca8a2777045f4..139fd592f69a3 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -32,6 +32,7 @@ //! Because of that, we can assume that the only way to change the value behind a tracked place is //! by direct assignment. +use std::assert_matches::assert_matches; use std::fmt::{Debug, Formatter}; use std::ops::Range; @@ -54,7 +55,7 @@ use crate::{Analysis, AnalysisDomain, JoinSemiLattice, SwitchIntEdgeEffects}; pub trait ValueAnalysis<'tcx> { /// For each place of interest, the analysis tracks a value of the given type. - type Value: Clone + JoinSemiLattice + HasBottom + HasTop; + type Value: Clone + JoinSemiLattice + HasBottom + HasTop + Debug; const NAME: &'static str; @@ -344,7 +345,7 @@ impl<'tcx, T: ValueAnalysis<'tcx>> AnalysisDomain<'tcx> for ValueAnalysisWrapper fn initialize_start_block(&self, body: &Body<'tcx>, state: &mut Self::Domain) { // The initial state maps all tracked places of argument projections to ⊤ and the rest to ⊥. - assert!(matches!(state, State::Unreachable)); + assert_matches!(state, State::Unreachable); *state = State::new_reachable(); for arg in body.args_iter() { state.flood(PlaceRef { local: arg, projection: &[] }, self.0.map()); diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index dc8e50ac8cd28..48a3266ae6f0d 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -468,7 +468,7 @@ impl<'tcx> Validator<'_, 'tcx> { if let ty::RawPtr(_, _) | ty::FnPtr(..) = lhs_ty.kind() { // Raw and fn pointer operations are not allowed inside consts and thus not promotable. - assert!(matches!( + assert_matches!( op, BinOp::Eq | BinOp::Ne @@ -477,7 +477,7 @@ impl<'tcx> Validator<'_, 'tcx> { | BinOp::Ge | BinOp::Gt | BinOp::Offset - )); + ); return Err(Unpromotable); } diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index f41f3ef656c51..29185e79bce88 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -996,7 +996,7 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> { /// } /// ``` fn build_fn_ptr_addr_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> Body<'tcx> { - assert!(matches!(self_ty.kind(), ty::FnPtr(..)), "expected fn ptr, found {self_ty}"); + assert_matches!(self_ty.kind(), ty::FnPtr(..), "expected fn ptr, found {self_ty}"); let span = tcx.def_span(def_id); let Some(sig) = tcx.fn_sig(def_id).instantiate(tcx, &[self_ty.into()]).no_bound_vars() else { span_bug!(span, "FnPtr::addr with bound vars for `{self_ty}`"); diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index e6b04080c8d85..370792714936a 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -5,6 +5,7 @@ #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] #![feature(array_windows)] +#![feature(assert_matches)] #![feature(box_patterns)] #![feature(debug_closure_helpers)] #![feature(if_let_guard)] diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 4b8e4c25e16c2..b7dc21bfc0775 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -10,6 +10,7 @@ mod path; mod stmt; mod ty; +use std::assert_matches::debug_assert_matches; use std::ops::Range; use std::{fmt, mem, slice}; @@ -1385,7 +1386,7 @@ impl<'a> Parser<'a> { // can capture these tokens if necessary. self.bump(); if self.token_cursor.stack.len() == target_depth { - debug_assert!(matches!(self.token.kind, token::CloseDelim(_))); + debug_assert_matches!(self.token.kind, token::CloseDelim(_)); break; } } diff --git a/compiler/rustc_parse/src/parser/tests.rs b/compiler/rustc_parse/src/parser/tests.rs index 2d82742f66c02..cb8e8d309887b 100644 --- a/compiler/rustc_parse/src/parser/tests.rs +++ b/compiler/rustc_parse/src/parser/tests.rs @@ -1,3 +1,4 @@ +use std::assert_matches::assert_matches; use std::io::prelude::*; use std::iter::Peekable; use std::path::{Path, PathBuf}; @@ -1747,7 +1748,7 @@ fn out_of_line_mod() { .unwrap(); let ast::ItemKind::Mod(_, mod_kind) = &item.kind else { panic!() }; - assert!(matches!(mod_kind, ast::ModKind::Loaded(items, ..) if items.len() == 2)); + assert_matches!(mod_kind, ast::ModKind::Loaded(items, ..) if items.len() == 2); }); } diff --git a/compiler/rustc_target/src/spec/abi/tests.rs b/compiler/rustc_target/src/spec/abi/tests.rs index 251a12fe7aa6b..4823058dd6970 100644 --- a/compiler/rustc_target/src/spec/abi/tests.rs +++ b/compiler/rustc_target/src/spec/abi/tests.rs @@ -1,3 +1,5 @@ +use std::assert_matches::assert_matches; + use super::*; #[allow(non_snake_case)] @@ -16,7 +18,7 @@ fn lookup_cdecl() { #[test] fn lookup_baz() { let abi = lookup("baz"); - assert!(matches!(abi, Err(AbiUnsupported::Unrecognized))) + assert_matches!(abi, Err(AbiUnsupported::Unrecognized)); } #[test] diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index e8de8457440ff..1a459aa484ff1 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -9,6 +9,8 @@ //! coherence right now and was annoying to implement, so I am leaving it //! as is until we start using it for something else. +use std::assert_matches::assert_matches; + use rustc_ast_ir::try_visit; use rustc_ast_ir::visit::VisitorResult; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk}; @@ -273,10 +275,10 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { steps.push(step) } inspect::ProbeStep::MakeCanonicalResponse { shallow_certainty: c } => { - assert!(matches!( + assert_matches!( shallow_certainty.replace(c), None | Some(Certainty::Maybe(MaybeCause::Ambiguity)) - )); + ); } inspect::ProbeStep::NestedProbe(ref probe) => { match probe.kind { diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs index 419d7e704dee3..c93c40b482680 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::assert_matches::assert_matches; use std::fmt::Debug; use std::marker::PhantomData; @@ -63,7 +64,7 @@ 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(..))); + assert_matches!(alias_ty.kind(), ty::Alias(..)); let infcx = self.at.infcx; let tcx = infcx.tcx; diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs index 9a127e752a61a..3e65194577e0d 100644 --- a/compiler/rustc_trait_selection/src/traits/misc.rs +++ b/compiler/rustc_trait_selection/src/traits/misc.rs @@ -1,5 +1,7 @@ //! Miscellaneous type-system utilities that are too small to deserve their own modules. +use std::assert_matches::assert_matches; + use hir::LangItem; use rustc_ast::Mutability; use rustc_data_structures::fx::FxIndexSet; @@ -92,7 +94,7 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>( lang_item: LangItem, parent_cause: ObligationCause<'tcx>, ) -> Result<(), ConstParamTyImplementationError<'tcx>> { - assert!(matches!(lang_item, LangItem::ConstParamTy | LangItem::UnsizedConstParamTy)); + assert_matches!(lang_item, LangItem::ConstParamTy | LangItem::UnsizedConstParamTy); let inner_tys: Vec<_> = match *self_type.kind() { // Trivially okay as these types are all: diff --git a/compiler/rustc_ty_utils/src/layout_sanity_check.rs b/compiler/rustc_ty_utils/src/layout_sanity_check.rs index d8e0443c50b85..2223aca28d1f6 100644 --- a/compiler/rustc_ty_utils/src/layout_sanity_check.rs +++ b/compiler/rustc_ty_utils/src/layout_sanity_check.rs @@ -249,7 +249,7 @@ pub(super) fn sanity_check_layout<'tcx>( if let Variants::Multiple { variants, .. } = &layout.variants { for variant in variants.iter() { // No nested "multiple". - assert!(matches!(variant.variants, Variants::Single { .. })); + assert_matches!(variant.variants, Variants::Single { .. }); // Variants should have the same or a smaller size as the full thing, // and same for alignment. if variant.size > layout.size { From cfadfabfcd9644628422396fcc8a67244df435c1 Mon Sep 17 00:00:00 2001 From: Andreas Jonson Date: Tue, 30 Jul 2024 11:06:26 +0200 Subject: [PATCH 759/786] Add range attribute to scalar function results and arguments --- compiler/rustc_codegen_llvm/src/abi.rs | 61 +++++++++++++---- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 6 ++ compiler/rustc_codegen_llvm/src/llvm/mod.rs | 17 ++++- .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 12 ++++ tests/codegen/call-metadata.rs | 1 + tests/codegen/cast-optimized.rs | 2 - tests/codegen/common_prim_int_ptr.rs | 4 +- tests/codegen/enum/enum-match.rs | 2 +- tests/codegen/function-arguments.rs | 6 +- .../issues/issue-68667-unwrap-combinators.rs | 2 +- tests/codegen/range-attribute.rs | 68 +++++++++++++++++++ tests/codegen/repr/transparent.rs | 2 +- 12 files changed, 159 insertions(+), 24 deletions(-) create mode 100644 tests/codegen/range-attribute.rs diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index b8f4203126381..6d57d851d6330 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -415,9 +415,32 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { i += 1; i - 1 }; + + let apply_range_attr = |idx: AttributePlace, scalar: rustc_target::abi::Scalar| { + if cx.sess().opts.optimize != config::OptLevel::No + && llvm_util::get_version() >= (19, 0, 0) + && matches!(scalar.primitive(), Int(..)) + // If the value is a boolean, the range is 0..2 and that ultimately + // become 0..0 when the type becomes i1, which would be rejected + // by the LLVM verifier. + && !scalar.is_bool() + // LLVM also rejects full range. + && !scalar.is_always_valid(cx) + { + attributes::apply_to_llfn( + llfn, + idx, + &[llvm::CreateRangeAttr(cx.llcx, scalar.size(cx), scalar.valid_range(cx))], + ); + } + }; + match &self.ret.mode { PassMode::Direct(attrs) => { attrs.apply_attrs_to_llfn(llvm::AttributePlace::ReturnValue, cx, llfn); + if let abi::Abi::Scalar(scalar) = self.ret.layout.abi { + apply_range_attr(llvm::AttributePlace::ReturnValue, scalar); + } } PassMode::Indirect { attrs, meta_attrs: _, on_stack } => { assert!(!on_stack); @@ -456,8 +479,13 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { ); attributes::apply_to_llfn(llfn, llvm::AttributePlace::Argument(i), &[byval]); } - PassMode::Direct(attrs) - | PassMode::Indirect { attrs, meta_attrs: None, on_stack: false } => { + PassMode::Direct(attrs) => { + let i = apply(attrs); + if let abi::Abi::Scalar(scalar) = arg.layout.abi { + apply_range_attr(llvm::AttributePlace::Argument(i), scalar); + } + } + PassMode::Indirect { attrs, meta_attrs: None, on_stack: false } => { apply(attrs); } PassMode::Indirect { attrs, meta_attrs: Some(meta_attrs), on_stack } => { @@ -466,8 +494,12 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { apply(meta_attrs); } PassMode::Pair(a, b) => { - apply(a); - apply(b); + let i = apply(a); + let ii = apply(b); + if let abi::Abi::ScalarPair(scalar_a, scalar_b) = arg.layout.abi { + apply_range_attr(llvm::AttributePlace::Argument(i), scalar_a); + apply_range_attr(llvm::AttributePlace::Argument(ii), scalar_b); + } } PassMode::Cast { cast, pad_i32 } => { if *pad_i32 { @@ -517,15 +549,18 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { } _ => {} } - if let abi::Abi::Scalar(scalar) = self.ret.layout.abi { - // If the value is a boolean, the range is 0..2 and that ultimately - // become 0..0 when the type becomes i1, which would be rejected - // by the LLVM verifier. - if let Int(..) = scalar.primitive() { - if !scalar.is_bool() && !scalar.is_always_valid(bx) { - bx.range_metadata(callsite, scalar.valid_range(bx)); - } - } + if bx.cx.sess().opts.optimize != config::OptLevel::No + && llvm_util::get_version() < (19, 0, 0) + && let abi::Abi::Scalar(scalar) = self.ret.layout.abi + && matches!(scalar.primitive(), Int(..)) + // If the value is a boolean, the range is 0..2 and that ultimately + // become 0..0 when the type becomes i1, which would be rejected + // by the LLVM verifier. + && !scalar.is_bool() + // LLVM also rejects full range. + && !scalar.is_always_valid(bx) + { + bx.range_metadata(callsite, scalar.valid_range(bx)); } for arg in self.args.iter() { match &arg.mode { diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 80b13c0e1d4b9..faabbcb020d5f 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1575,6 +1575,12 @@ extern "C" { pub fn LLVMRustCreateAllocSizeAttr(C: &Context, size_arg: u32) -> &Attribute; pub fn LLVMRustCreateAllocKindAttr(C: &Context, size_arg: u64) -> &Attribute; pub fn LLVMRustCreateMemoryEffectsAttr(C: &Context, effects: MemoryEffects) -> &Attribute; + pub fn LLVMRustCreateRangeAttribute( + C: &Context, + num_bits: c_uint, + lower_words: *const u64, + upper_words: *const u64, + ) -> &Attribute; // Operations on functions pub fn LLVMRustGetOrInsertFunction<'a>( diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs index 72691907c0d91..d0db350a149e8 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs @@ -8,7 +8,7 @@ use std::string::FromUtf8Error; use libc::c_uint; use rustc_data_structures::small_c_str::SmallCStr; use rustc_llvm::RustString; -use rustc_target::abi::Align; +use rustc_target::abi::{Align, Size, WrappingRange}; pub use self::AtomicRmwBinOp::*; pub use self::CallConv::*; @@ -105,6 +105,21 @@ pub fn CreateAllocKindAttr(llcx: &Context, kind_arg: AllocKindFlags) -> &Attribu unsafe { LLVMRustCreateAllocKindAttr(llcx, kind_arg.bits()) } } +pub fn CreateRangeAttr(llcx: &Context, size: Size, range: WrappingRange) -> &Attribute { + let lower = range.start; + let upper = range.end.wrapping_add(1); + let lower_words = [lower as u64, (lower >> 64) as u64]; + let upper_words = [upper as u64, (upper >> 64) as u64]; + unsafe { + LLVMRustCreateRangeAttribute( + llcx, + size.bits().try_into().unwrap(), + lower_words.as_ptr(), + upper_words.as_ptr(), + ) + } +} + #[derive(Copy, Clone)] pub enum AttributePlace { ReturnValue, diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 2ff7335a0fc81..79a68b2ff0e67 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -397,6 +397,18 @@ LLVMRustCreateAllocSizeAttr(LLVMContextRef C, uint32_t ElementSizeArg) { std::nullopt)); } +extern "C" LLVMAttributeRef +LLVMRustCreateRangeAttribute(LLVMContextRef C, unsigned NumBits, + const uint64_t LowerWords[], + const uint64_t UpperWords[]) { +#if LLVM_VERSION_GE(19, 0) + return LLVMCreateConstantRangeAttribute(C, Attribute::Range, NumBits, + LowerWords, UpperWords); +#else + report_fatal_error("LLVM 19.0 is required for Range Attribute"); +#endif +} + // These values **must** match ffi::AllocKindFlags. // It _happens_ to match the LLVM values of llvm::AllocFnKind, // but that's happenstance and we do explicit conversions before diff --git a/tests/codegen/call-metadata.rs b/tests/codegen/call-metadata.rs index b2168990ff834..73c4b33e2cfb7 100644 --- a/tests/codegen/call-metadata.rs +++ b/tests/codegen/call-metadata.rs @@ -2,6 +2,7 @@ // scalar value. //@ compile-flags: -O -C no-prepopulate-passes +//@ ignore-llvm-version: 19 - 99 #![crate_type = "lib"] diff --git a/tests/codegen/cast-optimized.rs b/tests/codegen/cast-optimized.rs index 313b2b4f0d6f6..59cf40935cd54 100644 --- a/tests/codegen/cast-optimized.rs +++ b/tests/codegen/cast-optimized.rs @@ -20,8 +20,6 @@ pub fn u32_index(c: u32) -> [bool; 22] { // CHECK-LABEL: @char_as_u32_index #[no_mangle] pub fn char_as_u32_index(c: char) -> [bool; 22] { - // CHECK: %[[B:.+]] = icmp ult i32 %c, 1114112 - // CHECK: call void @llvm.assume(i1 %[[B]]) let c = c as u32; let mut array = [false; 22]; diff --git a/tests/codegen/common_prim_int_ptr.rs b/tests/codegen/common_prim_int_ptr.rs index 87fa89abb8667..aa7ebb4c9119d 100644 --- a/tests/codegen/common_prim_int_ptr.rs +++ b/tests/codegen/common_prim_int_ptr.rs @@ -28,7 +28,7 @@ pub fn insert_box(x: Box<()>) -> Result> { // CHECK-LABEL: @extract_int // CHECK-NOT: nonnull -// CHECK-SAME: (i{{[0-9]+}} {{[^,]+}} [[DISCRIMINANT:%[0-9]+]], ptr {{[^,]+}} [[PAYLOAD:%[0-9]+]]) +// CHECK-SAME: (i{{[0-9]+}} {{[^%]+}} [[DISCRIMINANT:%[0-9]+]], ptr {{[^,]+}} [[PAYLOAD:%[0-9]+]]) #[no_mangle] pub unsafe fn extract_int(x: Result>) -> usize { // CHECK: [[TEMP:%.+]] = ptrtoint ptr [[PAYLOAD]] to [[USIZE:i[0-9]+]] @@ -40,7 +40,7 @@ pub unsafe fn extract_int(x: Result>) -> usize { } // CHECK-LABEL: @extract_box -// CHECK-SAME: (i{{[0-9]+}} {{[^,]+}} [[DISCRIMINANT:%[0-9]+]], ptr {{[^,]+}} [[PAYLOAD:%[0-9]+]]) +// CHECK-SAME: (i{{[0-9]+}} {{[^%]+}} [[DISCRIMINANT:%[0-9]+]], ptr {{[^,]+}} [[PAYLOAD:%[0-9]+]]) #[no_mangle] pub unsafe fn extract_box(x: Result>) -> Box { // CHECK: ret ptr [[PAYLOAD]] diff --git a/tests/codegen/enum/enum-match.rs b/tests/codegen/enum/enum-match.rs index 8da5de63e67da..a24b98050d232 100644 --- a/tests/codegen/enum/enum-match.rs +++ b/tests/codegen/enum/enum-match.rs @@ -34,7 +34,7 @@ pub enum Enum1 { // CHECK: define noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match1{{.*}} // CHECK-NEXT: start: -// CHECK-NEXT: %1 = add i8 %0, -2 +// CHECK-NEXT: %1 = add{{( nsw)?}} i8 %0, -2 // CHECK-NEXT: %2 = zext i8 %1 to i64 // CHECK-NEXT: %3 = icmp ult i8 %1, 2 // CHECK-NEXT: %4 = add nuw nsw i64 %2, 1 diff --git a/tests/codegen/function-arguments.rs b/tests/codegen/function-arguments.rs index 56504df403473..bf9f405192b69 100644 --- a/tests/codegen/function-arguments.rs +++ b/tests/codegen/function-arguments.rs @@ -50,7 +50,7 @@ pub fn maybeuninit_enum_bool(x: MaybeUninit) -> MaybeUninit { x } -// CHECK: noundef i32 @char(i32 noundef %x) +// CHECK: noundef{{( range\(i32 0, 1114112\))?}} i32 @char(i32 noundef{{( range\(i32 0, 1114112\))?}} %x) #[no_mangle] pub fn char(x: char) -> char { x @@ -68,7 +68,7 @@ pub fn int(x: u64) -> u64 { x } -// CHECK: noundef i64 @nonzero_int(i64 noundef %x) +// CHECK: noundef{{( range\(i64 1, 0\))?}} i64 @nonzero_int(i64 noundef{{( range\(i64 1, 0\))?}} %x) #[no_mangle] pub fn nonzero_int(x: NonZero) -> NonZero { x @@ -250,7 +250,7 @@ pub fn return_slice(x: &[u16]) -> &[u16] { x } -// CHECK: { i16, i16 } @enum_id_1(i16 noundef %x.0, i16 %x.1) +// CHECK: { i16, i16 } @enum_id_1(i16 noundef{{( range\(i16 0, 3\))?}} %x.0, i16 %x.1) #[no_mangle] pub fn enum_id_1(x: Option>) -> Option> { x diff --git a/tests/codegen/issues/issue-68667-unwrap-combinators.rs b/tests/codegen/issues/issue-68667-unwrap-combinators.rs index 6bd4c566a0c28..21a5a5bf4ee94 100644 --- a/tests/codegen/issues/issue-68667-unwrap-combinators.rs +++ b/tests/codegen/issues/issue-68667-unwrap-combinators.rs @@ -5,7 +5,7 @@ // MIR inlining now optimizes this code. // CHECK-LABEL: @unwrap_combinators -// CHECK: icmp +// CHECK: {{icmp|trunc}} // CHECK-NEXT: icmp // CHECK-NEXT: select i1 // CHECK-NEXT: ret i1 diff --git a/tests/codegen/range-attribute.rs b/tests/codegen/range-attribute.rs new file mode 100644 index 0000000000000..bb19bec0fb932 --- /dev/null +++ b/tests/codegen/range-attribute.rs @@ -0,0 +1,68 @@ +// Checks that range metadata gets emitted on functions result and arguments +// with scalar value. + +//@ compile-flags: -O -C no-prepopulate-passes +//@ min-llvm-version: 19 + +#![crate_type = "lib"] + +use std::num::NonZero; + +// Hack to get the correct size for usize +// CHECK: @helper([[USIZE:i[0-9]+]] noundef %_1) +#[no_mangle] +pub fn helper(_: usize) {} + +// CHECK: noundef range(i128 1, 0) i128 @nonzero_int(i128 noundef range(i128 1, 0) %x) +#[no_mangle] +pub fn nonzero_int(x: NonZero) -> NonZero { + x +} + +// CHECK: noundef range(i8 0, 3) i8 @optional_bool(i8 noundef range(i8 0, 3) %x) +#[no_mangle] +pub fn optional_bool(x: Option) -> Option { + x +} + +pub enum Enum0 { + A(bool), + B, + C, +} + +// CHECK: noundef range(i8 0, 4) i8 @enum0_value(i8 noundef range(i8 0, 4) %x) +#[no_mangle] +pub fn enum0_value(x: Enum0) -> Enum0 { + x +} + +pub enum Enum1 { + A(u64), + B(u64), + C(u64), +} + +// CHECK: { [[ENUM1_TYP:i[0-9]+]], i64 } @enum1_value([[ENUM1_TYP]] noundef range([[ENUM1_TYP]] 0, 3) %x.0, i64 noundef %x.1) +#[no_mangle] +pub fn enum1_value(x: Enum1) -> Enum1 { + x +} + +pub enum Enum2 { + A(Enum0), + B(Enum0), + C(Enum0), +} + +// CHECK: { i8, i8 } @enum2_value(i8 noundef range(i8 0, 3) %x.0, i8 noundef %x.1) +#[no_mangle] +pub fn enum2_value(x: Enum2) -> Enum2 { + x +} + +// CHECK: noundef [[USIZE]] @takes_slice(ptr noalias noundef nonnull readonly align 4 %x.0, [[USIZE]] noundef %x.1) +#[no_mangle] +pub fn takes_slice(x: &[i32]) -> usize { + x.len() +} diff --git a/tests/codegen/repr/transparent.rs b/tests/codegen/repr/transparent.rs index 4b41332db4512..9140b8542ecac 100644 --- a/tests/codegen/repr/transparent.rs +++ b/tests/codegen/repr/transparent.rs @@ -74,7 +74,7 @@ pub enum Bool { FileNotFound, } -// CHECK: define{{( dso_local)?}} noundef{{( zeroext)?}} i8 @test_Gpz(i8 noundef{{( zeroext)?}} %_1) +// CHECK: define{{( dso_local)?}} noundef{{( zeroext)?( range\(i8 0, 3\))?}} i8 @test_Gpz(i8 noundef{{( zeroext)?( range\(i8 0, 3\))?}} %_1) #[no_mangle] pub extern "C" fn test_Gpz(_: GenericPlusZst) -> GenericPlusZst { loop {} From 28a8301de98f9b8d8a3d34d554c319a4c6204f62 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Fri, 9 Aug 2024 21:54:48 -0400 Subject: [PATCH 760/786] Fix debuginfo providers/tests --- src/etc/lldb_providers.py | 8 ++++---- src/etc/natvis/liballoc.natvis | 18 +++++++++--------- src/etc/natvis/libstd.natvis | 6 +++--- tests/debuginfo/pretty-std.rs | 12 ++++++------ 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/etc/lldb_providers.py b/src/etc/lldb_providers.py index c6330117380b1..8750d7682d136 100644 --- a/src/etc/lldb_providers.py +++ b/src/etc/lldb_providers.py @@ -389,11 +389,11 @@ def get_child_at_index(self, index): def update(self): # type: () -> None self.length = self.valobj.GetChildMemberWithName("len").GetValueAsUnsigned() - self.buf = self.valobj.GetChildMemberWithName("buf") + self.buf = self.valobj.GetChildMemberWithName("buf").GetChildMemberWithName("inner") self.data_ptr = unwrap_unique_or_non_null(self.buf.GetChildMemberWithName("ptr")) - self.element_type = self.data_ptr.GetType().GetPointeeType() + self.element_type = self.valobj.GetType().GetTemplateArgumentType(0) self.element_type_size = self.element_type.GetByteSize() def has_children(self): @@ -474,7 +474,7 @@ def update(self): # type: () -> None self.head = self.valobj.GetChildMemberWithName("head").GetValueAsUnsigned() self.size = self.valobj.GetChildMemberWithName("len").GetValueAsUnsigned() - self.buf = self.valobj.GetChildMemberWithName("buf") + self.buf = self.valobj.GetChildMemberWithName("buf").GetChildMemberWithName("inner") cap = self.buf.GetChildMemberWithName("cap") if cap.GetType().num_fields == 1: cap = cap.GetChildAtIndex(0) @@ -482,7 +482,7 @@ def update(self): self.data_ptr = unwrap_unique_or_non_null(self.buf.GetChildMemberWithName("ptr")) - self.element_type = self.data_ptr.GetType().GetPointeeType() + self.element_type = self.valobj.GetType().GetTemplateArgumentType(0) self.element_type_size = self.element_type.GetByteSize() def has_children(self): diff --git a/src/etc/natvis/liballoc.natvis b/src/etc/natvis/liballoc.natvis index da307809f7b04..49d82dfad820b 100644 --- a/src/etc/natvis/liballoc.natvis +++ b/src/etc/natvis/liballoc.natvis @@ -4,10 +4,10 @@ {{ len={len} }} len - buf.cap.__0 + buf.inner.cap.__0 len - buf.ptr.pointer.pointer + ($T1*)buf.inner.ptr.pointer.pointer @@ -15,7 +15,7 @@ {{ len={len} }} len - buf.cap.__0 + buf.inner.cap.__0 len @@ -23,7 +23,7 @@ - buf.ptr.pointer.pointer[(i + head) % buf.cap.__0] + (($T1*)buf.inner.ptr.pointer.pointer)[(i + head) % buf.inner.cap.__0] i = i + 1 @@ -41,17 +41,17 @@ - {(char*)vec.buf.ptr.pointer.pointer,[vec.len]s8} - (char*)vec.buf.ptr.pointer.pointer,[vec.len]s8 + {(char*)vec.buf.inner.ptr.pointer.pointer,[vec.len]s8} + (char*)vec.buf.inner.ptr.pointer.pointer,[vec.len]s8 vec.len - vec.buf.cap.__0 + vec.buf.inner.cap.__0 - {(char*)vec.buf.ptr.pointer.pointer,[vec.len]s8} + {(char*)vec.buf.inner.ptr.pointer.pointer,[vec.len]s8} vec.len - (char*)vec.buf.ptr.pointer.pointer + (char*)vec.buf.inner.ptr.pointer.pointer diff --git a/src/etc/natvis/libstd.natvis b/src/etc/natvis/libstd.natvis index 4371b99531817..4719a479c476b 100644 --- a/src/etc/natvis/libstd.natvis +++ b/src/etc/natvis/libstd.natvis @@ -104,14 +104,14 @@ - {(char*)inner.inner.bytes.buf.ptr.pointer.pointer,[inner.inner.bytes.len]} + {(char*)inner.inner.bytes.buf.inner.ptr.pointer.pointer,[inner.inner.bytes.len]} - {(char*)inner.inner.bytes.buf.ptr.pointer.pointer,[inner.inner.bytes.len]} + {(char*)inner.inner.bytes.buf.inner.ptr.pointer.pointer,[inner.inner.bytes.len]} inner.inner.bytes.len - (char*)inner.inner.bytes.buf.ptr.pointer.pointer + (char*)inner.inner.bytes.buf.inner.ptr.pointer.pointer diff --git a/tests/debuginfo/pretty-std.rs b/tests/debuginfo/pretty-std.rs index 70827d551ca39..45c6dbf343955 100644 --- a/tests/debuginfo/pretty-std.rs +++ b/tests/debuginfo/pretty-std.rs @@ -81,10 +81,10 @@ // cdb-check:vec,d [...] : { len=4 } [Type: [...]::Vec] // cdb-check: [len] : 4 [Type: [...]] // cdb-check: [capacity] : [...] [Type: [...]] -// cdb-check: [0] : 4 [Type: unsigned __int64] -// cdb-check: [1] : 5 [Type: unsigned __int64] -// cdb-check: [2] : 6 [Type: unsigned __int64] -// cdb-check: [3] : 7 [Type: unsigned __int64] +// cdb-check: [0] : 4 [Type: u64] +// cdb-check: [1] : 5 [Type: u64] +// cdb-check: [2] : 6 [Type: u64] +// cdb-check: [3] : 7 [Type: u64] // cdb-command: dx str_slice // cdb-check:str_slice : "IAMA string slice!" [Type: ref$] @@ -141,8 +141,8 @@ // cdb-check: [] [Type: alloc::collections::vec_deque::VecDeque] // cdb-check: [len] : 0x2 [Type: unsigned [...]] // cdb-check: [capacity] : 0x8 [Type: unsigned [...]] -// cdb-check: [0x0] : 90 [Type: int] -// cdb-check: [0x1] : 20 [Type: int] +// cdb-check: [0x0] : 90 [Type: i32] +// cdb-check: [0x1] : 20 [Type: i32] #![allow(unused_variables)] use std::collections::{LinkedList, VecDeque}; From c5205e9d56d3c632e83e1e5f0853d3bd82f16c0e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 11 Aug 2024 12:28:15 -0400 Subject: [PATCH 761/786] Normalize struct tail properly in borrowck and hir typeck --- .../src/type_check/canonical.rs | 47 +++++++++++++++++++ compiler/rustc_borrowck/src/type_check/mod.rs | 13 +---- compiler/rustc_hir_typeck/src/cast.rs | 2 + ...different-regions-id-trait.current.stderr} | 2 +- ...obj-different-regions-id-trait.next.stderr | 15 ++++++ ...to-trait-obj-different-regions-id-trait.rs | 3 ++ 6 files changed, 70 insertions(+), 12 deletions(-) rename tests/ui/cast/{ptr-to-trait-obj-different-regions-id-trait.stderr => ptr-to-trait-obj-different-regions-id-trait.current.stderr} (91%) create mode 100644 tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.next.stderr diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index 86cd8b918fc6e..2558cf6347d7c 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -7,6 +7,7 @@ use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, Upcast}; use rustc_span::def_id::DefId; use rustc_span::Span; +use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp; use rustc_trait_selection::traits::query::type_op::{self, TypeOpOutput}; use rustc_trait_selection::traits::ObligationCause; @@ -165,6 +166,52 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { result.unwrap_or(value) } + #[instrument(skip(self), level = "debug")] + pub(super) fn struct_tail( + &mut self, + ty: Ty<'tcx>, + location: impl NormalizeLocation, + ) -> Ty<'tcx> { + let tcx = self.tcx(); + if self.infcx.next_trait_solver() { + let body = self.body; + let param_env = self.param_env; + self.fully_perform_op( + location.to_locations(), + ConstraintCategory::Boring, + CustomTypeOp::new( + |ocx| { + let structurally_normalize = |ty| { + ocx.structurally_normalize( + &ObligationCause::misc( + location.to_locations().span(body), + body.source.def_id().expect_local(), + ), + param_env, + ty, + ) + .unwrap_or_else(|_| bug!("struct tail should have been computable, since we computed it in HIR")) + }; + + let tail = tcx.struct_tail_with_normalize( + ty, + structurally_normalize, + || {}, + ); + + Ok(tail) + }, + "normalizing struct tail", + ), + ) + .unwrap_or_else(|guar| Ty::new_error(tcx, guar)) + } else { + let mut normalize = |ty| self.normalize(ty, location); + let tail = tcx.struct_tail_with_normalize(ty, &mut normalize, || {}); + normalize(tail) + } + } + #[instrument(skip(self), level = "debug")] pub(super) fn ascribe_user_type( &mut self, diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index b13773ffe1460..6bab0f33c198c 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -2329,17 +2329,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let cast_ty_to = CastTy::from_ty(*ty); match (cast_ty_from, cast_ty_to) { (Some(CastTy::Ptr(src)), Some(CastTy::Ptr(dst))) => { - let mut normalize = |t| self.normalize(t, location); - - // N.B. `struct_tail_with_normalize` only "structurally resolves" - // the type. It is not fully normalized, so we have to normalize it - // afterwards. - let src_tail = - tcx.struct_tail_with_normalize(src.ty, &mut normalize, || ()); - let src_tail = normalize(src_tail); - let dst_tail = - tcx.struct_tail_with_normalize(dst.ty, &mut normalize, || ()); - let dst_tail = normalize(dst_tail); + let src_tail = self.struct_tail(src.ty, location); + let dst_tail = self.struct_tail(dst.ty, location); // This checks (lifetime part of) vtable validity for pointer casts, // which is irrelevant when there are aren't principal traits on both sides (aka only auto traits). diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index de70273390466..7cd97166ed1e9 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -97,6 +97,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return Ok(Some(PointerKind::Thin)); } + let t = self.try_structurally_resolve_type(span, t); + Ok(match *t.kind() { ty::Slice(_) | ty::Str => Some(PointerKind::Length), ty::Dynamic(tty, _, ty::Dyn) => Some(PointerKind::VTable(tty)), diff --git a/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.stderr b/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.current.stderr similarity index 91% rename from tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.stderr rename to tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.current.stderr index d1d598e603f18..5a5b4bfcacf43 100644 --- a/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.stderr +++ b/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.current.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/ptr-to-trait-obj-different-regions-id-trait.rs:21:17 + --> $DIR/ptr-to-trait-obj-different-regions-id-trait.rs:24:17 | LL | fn m<'a>() { | -- lifetime `'a` defined here diff --git a/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.next.stderr b/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.next.stderr new file mode 100644 index 0000000000000..5a5b4bfcacf43 --- /dev/null +++ b/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.next.stderr @@ -0,0 +1,15 @@ +error: lifetime may not live long enough + --> $DIR/ptr-to-trait-obj-different-regions-id-trait.rs:24:17 + | +LL | fn m<'a>() { + | -- lifetime `'a` defined here +LL | let unsend: *const dyn Cat<'a> = &(); +LL | let _send = unsend as *const S>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + | + = note: requirement occurs because of the type `S>`, which makes the generic argument `dyn Cat<'_>` invariant + = note: the struct `S` is invariant over the parameter `T` + = help: see for more information about variance + +error: aborting due to 1 previous error + diff --git a/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.rs b/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.rs index cdd55e243927c..f968dca4fd310 100644 --- a/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.rs +++ b/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.rs @@ -1,3 +1,6 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver //@ check-fail // // Make sure we can't trick the compiler by using a projection. From b5d2079fb9c9ac9f0fe594f65452b4097e71c2de Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 11 Aug 2024 12:30:38 -0400 Subject: [PATCH 762/786] Rename normalization functions to raw --- .../rustc_borrowck/src/type_check/canonical.rs | 4 ++-- .../rustc_const_eval/src/const_eval/valtrees.rs | 2 +- compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs | 2 +- compiler/rustc_middle/src/ty/layout.rs | 2 +- compiler/rustc_middle/src/ty/sty.rs | 6 +++--- compiler/rustc_middle/src/ty/util.rs | 16 +++++++++------- .../rustc_trait_selection/src/traits/project.rs | 2 +- 7 files changed, 18 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index 2558cf6347d7c..b58691fbeae3a 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -193,7 +193,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { .unwrap_or_else(|_| bug!("struct tail should have been computable, since we computed it in HIR")) }; - let tail = tcx.struct_tail_with_normalize( + let tail = tcx.struct_tail_raw( ty, structurally_normalize, || {}, @@ -207,7 +207,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { .unwrap_or_else(|guar| Ty::new_error(tcx, guar)) } else { let mut normalize = |ty| self.normalize(ty, location); - let tail = tcx.struct_tail_with_normalize(ty, &mut normalize, || {}); + let tail = tcx.struct_tail_raw(ty, &mut normalize, || {}); normalize(tail) } } diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index 8227c04594883..460c9797f3663 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -195,7 +195,7 @@ fn reconstruct_place_meta<'tcx>( let mut last_valtree = valtree; // Traverse the type, and update `last_valtree` as we go. - let tail = tcx.struct_tail_with_normalize( + let tail = tcx.struct_tail_raw( layout.ty, |ty| ty, || { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 841d25b54cc88..b169f75796b3a 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -404,7 +404,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { code: traits::ObligationCauseCode<'tcx>, ) { if !ty.references_error() { - let tail = self.tcx.struct_tail_with_normalize( + let tail = self.tcx.struct_tail_raw( ty, |ty| { if self.next_trait_solver() { diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 9204405d58f11..684574825e345 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -362,7 +362,7 @@ impl<'tcx> SizeSkeleton<'tcx> { ty::Ref(_, pointee, _) | ty::RawPtr(pointee, _) => { let non_zero = !ty.is_unsafe_ptr(); - let tail = tcx.struct_tail_with_normalize( + let tail = tcx.struct_tail_raw( pointee, |ty| match tcx.try_normalize_erasing_regions(param_env, ty) { Ok(ty) => ty, diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 8c97de1c59b26..8781a670acb30 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1590,7 +1590,7 @@ impl<'tcx> Ty<'tcx> { tcx: TyCtxt<'tcx>, normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>, ) -> Result, Ty<'tcx>> { - let tail = tcx.struct_tail_with_normalize(self, normalize, || {}); + let tail = tcx.struct_tail_raw(self, normalize, || {}); match tail.kind() { // Sized types ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) @@ -1614,10 +1614,10 @@ impl<'tcx> Ty<'tcx> { | ty::Foreign(..) // `dyn*` has metadata = (). | ty::Dynamic(_, _, ty::DynStar) - // If returned by `struct_tail_with_normalize` this is a unit struct + // If returned by `struct_tail_raw` this is a unit struct // without any fields, or not a struct, and therefore is Sized. | ty::Adt(..) - // If returned by `struct_tail_with_normalize` this is the empty tuple, + // If returned by `struct_tail_raw` this is the empty tuple, // a.k.a. unit type, which is Sized | ty::Tuple(..) => Ok(tcx.types.unit), diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 365f434a264e2..fc5e0c44d96fc 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -176,7 +176,7 @@ impl<'tcx> TyCtxt<'tcx> { /// if input `ty` is not a structure at all. pub fn struct_tail_without_normalization(self, ty: Ty<'tcx>) -> Ty<'tcx> { let tcx = self; - tcx.struct_tail_with_normalize(ty, |ty| ty, || {}) + tcx.struct_tail_raw(ty, |ty| ty, || {}) } /// Returns the deeply last field of nested structures, or the same type if @@ -188,7 +188,7 @@ impl<'tcx> TyCtxt<'tcx> { /// normalization attempt may cause compiler bugs. pub fn struct_tail_for_codegen(self, ty: Ty<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> { let tcx = self; - tcx.struct_tail_with_normalize(ty, |ty| tcx.normalize_erasing_regions(param_env, ty), || {}) + tcx.struct_tail_raw(ty, |ty| tcx.normalize_erasing_regions(param_env, ty), || {}) } /// Returns the deeply last field of nested structures, or the same type if @@ -196,12 +196,14 @@ impl<'tcx> TyCtxt<'tcx> { /// and its type can be used to determine unsizing strategy. /// /// This is parameterized over the normalization strategy (i.e. how to - /// handle `::Assoc` and `impl Trait`); pass the identity - /// function to indicate no normalization should take place. + /// handle `::Assoc` and `impl Trait`). You almost certainly do + /// **NOT** want to pass the identity function here, unless you know what + /// you're doing, or you're within normalization code itself and will handle + /// an unnormalized tail recursively. /// /// See also `struct_tail_for_codegen`, which is suitable for use /// during codegen. - pub fn struct_tail_with_normalize( + pub fn struct_tail_raw( self, mut ty: Ty<'tcx>, mut normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>, @@ -281,7 +283,7 @@ impl<'tcx> TyCtxt<'tcx> { param_env: ty::ParamEnv<'tcx>, ) -> (Ty<'tcx>, Ty<'tcx>) { let tcx = self; - tcx.struct_lockstep_tails_with_normalize(source, target, |ty| { + tcx.struct_lockstep_tails_raw(source, target, |ty| { tcx.normalize_erasing_regions(param_env, ty) }) } @@ -294,7 +296,7 @@ impl<'tcx> TyCtxt<'tcx> { /// /// See also `struct_lockstep_tails_for_codegen`, which is suitable for use /// during codegen. - pub fn struct_lockstep_tails_with_normalize( + pub fn struct_lockstep_tails_raw( self, source: Ty<'tcx>, target: Ty<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 4b62a5c59b2f0..0e4233ba7bc56 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1110,7 +1110,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( | ty::Error(_) => false, } } else if tcx.is_lang_item(trait_ref.def_id, LangItem::PointeeTrait) { - let tail = selcx.tcx().struct_tail_with_normalize( + let tail = selcx.tcx().struct_tail_raw( self_ty, |ty| { // We throw away any obligations we get from this, since we normalize From f15997ffeca4c7da66e7de9e348ccb8d3cccc946 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 11 Aug 2024 19:21:33 -0400 Subject: [PATCH 763/786] Remove struct_tail_no_normalization --- compiler/rustc_const_eval/src/const_eval/eval_queries.rs | 2 +- compiler/rustc_hir_typeck/src/expectation.rs | 3 ++- compiler/rustc_middle/src/ty/util.rs | 8 -------- compiler/rustc_trait_selection/src/traits/project.rs | 4 ++-- compiler/rustc_ty_utils/src/layout.rs | 6 +++++- 5 files changed, 10 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index ff27e4000163a..96b3ec6f18728 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -226,7 +226,7 @@ pub(super) fn op_to_const<'tcx>( let pointee_ty = imm.layout.ty.builtin_deref(false).unwrap(); // `false` = no raw ptrs debug_assert!( matches!( - ecx.tcx.struct_tail_without_normalization(pointee_ty).kind(), + ecx.tcx.struct_tail_for_codegen(pointee_ty, ecx.param_env).kind(), ty::Str | ty::Slice(..), ), "`ConstValue::Slice` is for slice-tailed types only, but got {}", diff --git a/compiler/rustc_hir_typeck/src/expectation.rs b/compiler/rustc_hir_typeck/src/expectation.rs index 91deae4174b00..76ae41db5c51c 100644 --- a/compiler/rustc_hir_typeck/src/expectation.rs +++ b/compiler/rustc_hir_typeck/src/expectation.rs @@ -70,7 +70,8 @@ impl<'a, 'tcx> Expectation<'tcx> { /// See the test case `test/ui/coerce-expect-unsized.rs` and #20169 /// for examples of where this comes up,. pub(super) fn rvalue_hint(fcx: &FnCtxt<'a, 'tcx>, ty: Ty<'tcx>) -> Expectation<'tcx> { - match fcx.tcx.struct_tail_without_normalization(ty).kind() { + // FIXME: This is not right, even in the old solver... + match fcx.tcx.struct_tail_raw(ty, |ty| ty, || {}).kind() { ty::Slice(_) | ty::Str | ty::Dynamic(..) => ExpectRvalueLikeUnsized(ty), _ => ExpectHasType(ty), } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index fc5e0c44d96fc..6be3dc423deb3 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -171,14 +171,6 @@ impl<'tcx> TyCtxt<'tcx> { } } - /// Attempts to returns the deeply last field of nested structures, but - /// does not apply any normalization in its search. Returns the same type - /// if input `ty` is not a structure at all. - pub fn struct_tail_without_normalization(self, ty: Ty<'tcx>) -> Ty<'tcx> { - let tcx = self; - tcx.struct_tail_raw(ty, |ty| ty, || {}) - } - /// Returns the deeply last field of nested structures, or the same type if /// not a structure at all. Corresponds to the only possible unsized field, /// and its type can be used to determine unsizing strategy. diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 0e4233ba7bc56..8a17d7ed64184 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1149,10 +1149,10 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( | ty::Never // Extern types have unit metadata, according to RFC 2850 | ty::Foreign(_) - // If returned by `struct_tail_without_normalization` this is a unit struct + // If returned by `struct_tail` this is a unit struct // without any fields, or not a struct, and therefore is Sized. | ty::Adt(..) - // If returned by `struct_tail_without_normalization` this is the empty tuple. + // If returned by `struct_tail` this is the empty tuple. | ty::Tuple(..) // Integers and floats are always Sized, and so have unit type metadata. | ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..)) => true, diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 1eb03fc3bd6a1..244a6afcf979a 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -219,9 +219,13 @@ fn layout_of_uncached<'tcx>( // its struct tail cannot be normalized either, so try to get a // more descriptive layout error here, which will lead to less confusing // diagnostics. + // + // We use the raw struct tail function here to get the first tail + // that is an alias, which is likely the cause of the normalization + // error. match tcx.try_normalize_erasing_regions( param_env, - tcx.struct_tail_without_normalization(pointee), + tcx.struct_tail_raw(pointee, |ty| ty, || {}), ) { Ok(_) => {} Err(better_err) => { From 46b4c5adc5698c3e9543e17a1ed0f8073bafd1d3 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 12 Aug 2024 10:27:19 +1000 Subject: [PATCH 764/786] Fix bug in `Parser::look_ahead`. The special case was failing to handle invisible delimiters on one path. Fixes #128895. --- compiler/rustc_parse/src/parser/mod.rs | 10 +++-- .../parse-invis-delim-issue-128895.rs | 44 +++++++++++++++++++ .../parse-invis-delim-issue-128895.rs | 14 ++++++ 3 files changed, 64 insertions(+), 4 deletions(-) create mode 100644 tests/ui/proc-macro/auxiliary/parse-invis-delim-issue-128895.rs create mode 100644 tests/ui/proc-macro/parse-invis-delim-issue-128895.rs diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 4b8e4c25e16c2..5e29cee9db6cf 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1166,10 +1166,12 @@ impl<'a> Parser<'a> { match self.token_cursor.tree_cursor.look_ahead(0) { Some(tree) => { // Indexing stayed within the current token tree. - return match tree { - TokenTree::Token(token, _) => looker(token), - TokenTree::Delimited(dspan, _, delim, _) => { - looker(&Token::new(token::OpenDelim(*delim), dspan.open)) + match tree { + TokenTree::Token(token, _) => return looker(token), + &TokenTree::Delimited(dspan, _, delim, _) => { + if delim != Delimiter::Invisible { + return looker(&Token::new(token::OpenDelim(delim), dspan.open)); + } } }; } diff --git a/tests/ui/proc-macro/auxiliary/parse-invis-delim-issue-128895.rs b/tests/ui/proc-macro/auxiliary/parse-invis-delim-issue-128895.rs new file mode 100644 index 0000000000000..07e135ee8ebef --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/parse-invis-delim-issue-128895.rs @@ -0,0 +1,44 @@ +//@ force-host +//@ no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::*; + +// This proc macro ignores its input and returns this token stream +// +// impl <«A1»: Comparable> Comparable for («A1»,) {} +// +// where `«`/`»` are invisible delimiters. This was being misparsed in bug +// #128895. +#[proc_macro] +pub fn main(_input: TokenStream) -> TokenStream { + let a1 = TokenTree::Group( + Group::new( + Delimiter::None, + std::iter::once(TokenTree::Ident(Ident::new("A1", Span::call_site()))).collect(), + ) + ); + vec![ + TokenTree::Ident(Ident::new("impl", Span::call_site())), + TokenTree::Punct(Punct::new('<', Spacing::Alone)), + a1.clone(), + TokenTree::Punct(Punct::new(':', Spacing::Alone)), + TokenTree::Ident(Ident::new("Comparable", Span::call_site())), + TokenTree::Punct(Punct::new('>', Spacing::Alone)), + TokenTree::Ident(Ident::new("Comparable", Span::call_site())), + TokenTree::Ident(Ident::new("for", Span::call_site())), + TokenTree::Group( + Group::new( + Delimiter::Parenthesis, + vec![ + a1.clone(), + TokenTree::Punct(Punct::new(',', Spacing::Alone)), + ].into_iter().collect::(), + ) + ), + TokenTree::Group(Group::new(Delimiter::Brace, TokenStream::new())), + ].into_iter().collect::() +} diff --git a/tests/ui/proc-macro/parse-invis-delim-issue-128895.rs b/tests/ui/proc-macro/parse-invis-delim-issue-128895.rs new file mode 100644 index 0000000000000..3d5af5fee217d --- /dev/null +++ b/tests/ui/proc-macro/parse-invis-delim-issue-128895.rs @@ -0,0 +1,14 @@ +//@ aux-build:parse-invis-delim-issue-128895.rs +//@ check-pass + +#![no_std] // Don't load unnecessary hygiene information from std +extern crate std; + +#[macro_use] +extern crate parse_invis_delim_issue_128895; + +trait Comparable {} + +parse_invis_delim_issue_128895::main!(); + +fn main() {} From 8542cd67f0581dbace80f451a90caf9257802cb1 Mon Sep 17 00:00:00 2001 From: joboet Date: Sun, 4 Aug 2024 10:32:57 +0200 Subject: [PATCH 765/786] std: do not overwrite style in `get_backtrace_style` If another thread calls `set_backtrace_style` while a `get_backtrace_style` is reading the environment variables, `get_backtrace_style` will overwrite the value. Use an atomic CAS to avoid this. --- library/std/src/panic.rs | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index 4c496ade81cda..6f0952c41ede5 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -440,13 +440,12 @@ impl BacktraceStyle { } fn from_u8(s: u8) -> Option { - Some(match s { - 0 => return None, - 1 => BacktraceStyle::Short, - 2 => BacktraceStyle::Full, - 3 => BacktraceStyle::Off, - _ => unreachable!(), - }) + match s { + 1 => Some(BacktraceStyle::Short), + 2 => Some(BacktraceStyle::Full), + 3 => Some(BacktraceStyle::Off), + _ => None, + } } } @@ -465,7 +464,7 @@ static SHOULD_CAPTURE: AtomicU8 = AtomicU8::new(0); pub fn set_backtrace_style(style: BacktraceStyle) { if cfg!(feature = "backtrace") { // If the `backtrace` feature of this crate is enabled, set the backtrace style. - SHOULD_CAPTURE.store(style.as_u8(), Ordering::Release); + SHOULD_CAPTURE.store(style.as_u8(), Ordering::Relaxed); } } @@ -498,7 +497,9 @@ pub fn get_backtrace_style() -> Option { // to optimize away callers. return None; } - if let Some(style) = BacktraceStyle::from_u8(SHOULD_CAPTURE.load(Ordering::Acquire)) { + + let current = SHOULD_CAPTURE.load(Ordering::Relaxed); + if let Some(style) = BacktraceStyle::from_u8(current) { return Some(style); } @@ -509,8 +510,11 @@ pub fn get_backtrace_style() -> Option { None if crate::sys::FULL_BACKTRACE_DEFAULT => BacktraceStyle::Full, None => BacktraceStyle::Off, }; - set_backtrace_style(format); - Some(format) + + match SHOULD_CAPTURE.compare_exchange(0, format.as_u8(), Ordering::Relaxed, Ordering::Relaxed) { + Ok(_) => Some(format), + Err(new) => BacktraceStyle::from_u8(new), + } } #[cfg(test)] From 99c0d768b0399b8f4f95dc285bd21e2e7ca1b10a Mon Sep 17 00:00:00 2001 From: joboet Date: Mon, 12 Aug 2024 10:23:26 +0200 Subject: [PATCH 766/786] std: use `/scheme/rand` on Redox --- library/std/src/sys/pal/unix/rand.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys/pal/unix/rand.rs b/library/std/src/sys/pal/unix/rand.rs index 9cb96e0888899..cc0852aab4396 100644 --- a/library/std/src/sys/pal/unix/rand.rs +++ b/library/std/src/sys/pal/unix/rand.rs @@ -49,7 +49,7 @@ cfg_if::cfg_if! { } const PATH: &'static str = if cfg!(target_os = "redox") { - "rand:" + "/scheme/rand" } else { "/dev/urandom" }; From 4763d12207561037847cc7dea4b695f3c129f1d7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 9 Aug 2024 18:09:05 +0200 Subject: [PATCH 767/786] ignore some vtable/fn ptr equality tests in Miri, their result is not fully predictable --- library/alloc/tests/task.rs | 4 ++-- library/core/tests/ptr.rs | 9 ++++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/library/alloc/tests/task.rs b/library/alloc/tests/task.rs index 034039a1eae9d..390dec14484ba 100644 --- a/library/alloc/tests/task.rs +++ b/library/alloc/tests/task.rs @@ -4,7 +4,7 @@ use alloc::task::{LocalWake, Wake}; use core::task::{LocalWaker, Waker}; #[test] -#[cfg_attr(miri, should_panic)] // `will_wake` doesn't guarantee that this test will work, and indeed on Miri it fails +#[cfg_attr(miri, ignore)] // `will_wake` doesn't guarantee that this test will work, and indeed on Miri it can fail fn test_waker_will_wake_clone() { struct NoopWaker; @@ -20,7 +20,7 @@ fn test_waker_will_wake_clone() { } #[test] -#[cfg_attr(miri, should_panic)] // `will_wake` doesn't guarantee that this test will work, and indeed on Miri it fails +#[cfg_attr(miri, ignore)] // `will_wake` doesn't guarantee that this test will work, and indeed on Miri it can fail fn test_local_waker_will_wake_clone() { struct NoopWaker; diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs index bc1940ebf32b5..78d1b137e63f5 100644 --- a/library/core/tests/ptr.rs +++ b/library/core/tests/ptr.rs @@ -810,9 +810,12 @@ fn ptr_metadata() { assert_ne!(address_1, address_2); // Different erased type => different vtable pointer assert_ne!(address_2, address_3); - // Same erased type and same trait => same vtable pointer - assert_eq!(address_3, address_4); - assert_eq!(address_3, address_5); + // Same erased type and same trait => same vtable pointer. + // This is *not guaranteed*, so we skip it in Miri. + if !cfg!(miri) { + assert_eq!(address_3, address_4); + assert_eq!(address_3, address_5); + } } } From 75743dc5a057cdc0678d88523edbbf3fdd1bf901 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 12 Aug 2024 11:10:26 +0200 Subject: [PATCH 768/786] make the codegen test also cover an ill-behaved arch, and add links --- compiler/rustc_codegen_llvm/src/builder.rs | 2 ++ tests/codegen/intrinsics/nontemporal.rs | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 20bf580a716a9..8e7a99e46a5b0 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -737,6 +737,8 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { // a hint, and use regular stores everywhere else. // (In the future, we could alternatively ensure that an sfence gets emitted after a sequence of movnt // before any kind of synchronizing operation. But it's not clear how to do that with LLVM.) + // For more context, see and + // . const WELL_BEHAVED_NONTEMPORAL_ARCHS: &[&str] = &["aarch64", "arm", "riscv32", "riscv64"]; diff --git a/tests/codegen/intrinsics/nontemporal.rs b/tests/codegen/intrinsics/nontemporal.rs index 828cb7e828761..ff2d629606688 100644 --- a/tests/codegen/intrinsics/nontemporal.rs +++ b/tests/codegen/intrinsics/nontemporal.rs @@ -1,6 +1,14 @@ //@ compile-flags: -O -//@ compile-flags: --target aarch64-unknown-linux-gnu -//@ needs-llvm-components: aarch64 +//@revisions: with_nontemporal without_nontemporal +//@[with_nontemporal] compile-flags: --target aarch64-unknown-linux-gnu +//@[with_nontemporal] needs-llvm-components: aarch64 +//@[without_nontemporal] compile-flags: --target x86_64-unknown-linux-gnu +//@[without_nontemporal] needs-llvm-components: x86 + +// Ensure that we *do* emit the `!nontemporal` flag on architectures where it +// is well-behaved, but do *not* emit it on architectures where it is ill-behaved. +// For more context, see and +// . #![feature(no_core, lang_items, intrinsics)] #![no_core] @@ -21,7 +29,8 @@ extern "rust-intrinsic" { #[no_mangle] pub fn a(a: &mut u32, b: u32) { // CHECK-LABEL: define{{.*}}void @a - // CHECK: store i32 %b, ptr %a, align 4, !nontemporal + // with_nontemporal: store i32 %b, ptr %a, align 4, !nontemporal + // without_nontemporal-NOT: nontemporal unsafe { nontemporal_store(a, b); } From 6839a8f6d55ebb00b1904cda37d03caf15144440 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 12 Aug 2024 11:32:21 +0200 Subject: [PATCH 769/786] bootstrap: clear miri ui-test deps when miri sysroot gets rebuilt --- src/bootstrap/src/core/build_steps/test.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 597d7733abe75..6ed001d8fd5f7 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -434,7 +434,7 @@ impl Miri { builder: &Builder<'_>, compiler: Compiler, target: TargetSelection, - ) -> String { + ) -> PathBuf { let miri_sysroot = builder.out.join(compiler.host.triple).join("miri-sysroot"); let mut cargo = builder::Cargo::new( builder, @@ -467,7 +467,7 @@ impl Miri { // Output is "\n". let sysroot = stdout.trim_end(); builder.verbose(|| println!("`cargo miri setup --print-sysroot` said: {sysroot:?}")); - sysroot.to_owned() + PathBuf::from(sysroot) } } @@ -520,12 +520,14 @@ impl Step for Miri { builder.ensure(compile::Std::new(target_compiler, host)); let host_sysroot = builder.sysroot(target_compiler); - // Miri has its own "target dir" for ui test dependencies. Make sure it gets cleared - // properly when rustc changes. Similar to `Builder::cargo`, we skip this in dry runs to - // make sure the relevant compiler has been set up properly. + // Miri has its own "target dir" for ui test dependencies. Make sure it gets cleared when + // the sysroot gets rebuilt, to avoid "found possibly newer version of crate `std`" errors. if !builder.config.dry_run() { let ui_test_dep_dir = builder.stage_out(host_compiler, Mode::ToolStd).join("miri_ui"); - builder.clear_if_dirty(&ui_test_dep_dir, &builder.rustc(host_compiler)); + // The mtime of `miri_sysroot` changes when the sysroot gets rebuilt (also see + // ). + // We can hence use that directly as a signal to clear the ui test dir. + builder.clear_if_dirty(&ui_test_dep_dir, &miri_sysroot); } // Run `cargo test`. From 83727eca21146682e3c40c2af77dc0f7c2a297d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Thu, 8 Aug 2024 18:03:55 +0000 Subject: [PATCH 770/786] don't use rustflags for `--rustc-args` --- src/bootstrap/src/core/builder.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index ccdeb442af4af..d79ff52e06edd 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -2226,11 +2226,6 @@ impl<'a> Builder<'a> { rustdocflags.arg("--cfg=parallel_compiler"); } - // Pass the value of `--rustc-args` from test command. If it's not a test command, this won't set anything. - self.config.cmd.rustc_args().iter().for_each(|v| { - rustflags.arg(v); - }); - Cargo { command: cargo, compiler, From 754f565fe298047695e150b7a01faca3264d9e6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Thu, 8 Aug 2024 18:15:58 +0000 Subject: [PATCH 771/786] don't use `--rustc-args` to test the stdlib's size optimizations feature --- src/ci/docker/scripts/x86_64-gnu-llvm.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ci/docker/scripts/x86_64-gnu-llvm.sh b/src/ci/docker/scripts/x86_64-gnu-llvm.sh index b3921f114217d..98290f5a72cd8 100755 --- a/src/ci/docker/scripts/x86_64-gnu-llvm.sh +++ b/src/ci/docker/scripts/x86_64-gnu-llvm.sh @@ -18,9 +18,9 @@ if [[ -z "${PR_CI_JOB}" ]]; then # compiler, and is sensitive to the addition of new flags. ../x.py --stage 1 test tests/ui-fulldeps - # The tests are run a second time with the size optimizations enabled. - ../x.py --stage 1 test library/std library/alloc library/core \ - --rustc-args "--cfg feature=\"optimize_for_size\"" + # Rebuild the stdlib with the size optimizations enabled and run tests again. + RUSTFLAGS_NOT_BOOTSTRAP="--cfg feature=\"optimize_for_size\"" ../x.py --stage 1 test \ + library/std library/alloc library/core fi # NOTE: intentionally uses all of `x.py`, `x`, and `x.ps1` to make sure they all work on Linux. From bc9ca2902ea3fa25b93989ccfae737a40db3c544 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Thu, 8 Aug 2024 18:59:11 +0000 Subject: [PATCH 772/786] clarify that `--rustc-args` is for compiletest tests --- src/bootstrap/src/core/config/flags.rs | 2 +- src/etc/completions/x.py.fish | 2 +- src/etc/completions/x.py.ps1 | 2 +- src/etc/completions/x.py.zsh | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs index 19f752da81c13..e42b86bc3ae63 100644 --- a/src/bootstrap/src/core/config/flags.rs +++ b/src/bootstrap/src/core/config/flags.rs @@ -347,7 +347,7 @@ pub enum Subcommand { /// extra arguments to be passed for the test tool being used /// (e.g. libtest, compiletest or rustdoc) test_args: Vec, - /// extra options to pass the compiler when running tests + /// extra options to pass the compiler when running compiletest tests #[arg(long, value_name = "ARGS", allow_hyphen_values(true))] rustc_args: Vec, #[arg(long)] diff --git a/src/etc/completions/x.py.fish b/src/etc/completions/x.py.fish index 805fc8aa8ccd0..a0f147c6c8175 100644 --- a/src/etc/completions/x.py.fish +++ b/src/etc/completions/x.py.fish @@ -266,7 +266,7 @@ complete -c x.py -n "__fish_seen_subcommand_from doc" -l enable-bolt-settings -d complete -c x.py -n "__fish_seen_subcommand_from doc" -l skip-stage0-validation -d 'Skip stage0 compiler validation' complete -c x.py -n "__fish_seen_subcommand_from doc" -s h -l help -d 'Print help (see more with \'--help\')' complete -c x.py -n "__fish_seen_subcommand_from test" -l test-args -d 'extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)' -r -complete -c x.py -n "__fish_seen_subcommand_from test" -l rustc-args -d 'extra options to pass the compiler when running tests' -r +complete -c x.py -n "__fish_seen_subcommand_from test" -l rustc-args -d 'extra options to pass the compiler when running compiletest tests' -r complete -c x.py -n "__fish_seen_subcommand_from test" -l extra-checks -d 'comma-separated list of other files types to check (accepts py, py:lint, py:fmt, shell)' -r complete -c x.py -n "__fish_seen_subcommand_from test" -l compare-mode -d 'mode describing what file the actual ui output will be compared to' -r complete -c x.py -n "__fish_seen_subcommand_from test" -l pass -d 'force {check,build,run}-pass tests to this mode' -r diff --git a/src/etc/completions/x.py.ps1 b/src/etc/completions/x.py.ps1 index ce590d2fa4897..1b6004a07ff7a 100644 --- a/src/etc/completions/x.py.ps1 +++ b/src/etc/completions/x.py.ps1 @@ -338,7 +338,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { } 'x.py;test' { [CompletionResult]::new('--test-args', 'test-args', [CompletionResultType]::ParameterName, 'extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)') - [CompletionResult]::new('--rustc-args', 'rustc-args', [CompletionResultType]::ParameterName, 'extra options to pass the compiler when running tests') + [CompletionResult]::new('--rustc-args', 'rustc-args', [CompletionResultType]::ParameterName, 'extra options to pass the compiler when running compiletest tests') [CompletionResult]::new('--extra-checks', 'extra-checks', [CompletionResultType]::ParameterName, 'comma-separated list of other files types to check (accepts py, py:lint, py:fmt, shell)') [CompletionResult]::new('--compare-mode', 'compare-mode', [CompletionResultType]::ParameterName, 'mode describing what file the actual ui output will be compared to') [CompletionResult]::new('--pass', 'pass', [CompletionResultType]::ParameterName, 'force {check,build,run}-pass tests to this mode') diff --git a/src/etc/completions/x.py.zsh b/src/etc/completions/x.py.zsh index fc8be4f788127..6e029f4ba7428 100644 --- a/src/etc/completions/x.py.zsh +++ b/src/etc/completions/x.py.zsh @@ -337,7 +337,7 @@ _arguments "${_arguments_options[@]}" \ (test) _arguments "${_arguments_options[@]}" \ '*--test-args=[extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)]:ARGS: ' \ -'*--rustc-args=[extra options to pass the compiler when running tests]:ARGS: ' \ +'*--rustc-args=[extra options to pass the compiler when running compiletest tests]:ARGS: ' \ '--extra-checks=[comma-separated list of other files types to check (accepts py, py\:lint, py\:fmt, shell)]:EXTRA_CHECKS: ' \ '--compare-mode=[mode describing what file the actual ui output will be compared to]:COMPARE MODE: ' \ '--pass=[force {check,build,run}-pass tests to this mode]:check | build | run: ' \ From 0ad798aec713a0d3b2b5aa677a343d767ea550b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Mon, 12 Aug 2024 15:10:14 +0000 Subject: [PATCH 773/786] remove unexpected `--rustc-args` from `./x miri` --- src/bootstrap/src/core/config/flags.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs index e42b86bc3ae63..c3b96e1225729 100644 --- a/src/bootstrap/src/core/config/flags.rs +++ b/src/bootstrap/src/core/config/flags.rs @@ -392,9 +392,6 @@ pub enum Subcommand { /// extra arguments to be passed for the test tool being used /// (e.g. libtest, compiletest or rustdoc) test_args: Vec, - /// extra options to pass the compiler when running tests - #[arg(long, value_name = "ARGS", allow_hyphen_values(true))] - rustc_args: Vec, #[arg(long)] /// do not run doc tests no_doc: bool, @@ -501,7 +498,7 @@ impl Subcommand { pub fn rustc_args(&self) -> Vec<&str> { match *self { - Subcommand::Test { ref rustc_args, .. } | Subcommand::Miri { ref rustc_args, .. } => { + Subcommand::Test { ref rustc_args, .. } => { rustc_args.iter().flat_map(|s| s.split_whitespace()).collect() } _ => vec![], From 5e872568a8a225b462aef7d52e2349c1984f9028 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Mon, 12 Aug 2024 15:11:25 +0000 Subject: [PATCH 774/786] rename `./x test`'s `--rustc-args` to `--compiletest-rustc-args` --- compiler/rustc_codegen_gcc/build_system/src/test.rs | 4 ++-- src/bootstrap/src/core/build_steps/test.rs | 2 +- src/bootstrap/src/core/builder/tests.rs | 4 ++-- src/bootstrap/src/core/config/flags.rs | 8 ++++---- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_codegen_gcc/build_system/src/test.rs b/compiler/rustc_codegen_gcc/build_system/src/test.rs index dabf6c5aa3ee4..83fa8059b1a05 100644 --- a/compiler/rustc_codegen_gcc/build_system/src/test.rs +++ b/compiler/rustc_codegen_gcc/build_system/src/test.rs @@ -552,7 +552,7 @@ fn asm_tests(env: &Env, args: &TestArg) -> Result<(), String> { &"--stage", &"0", &"tests/assembly/asm", - &"--rustc-args", + &"--compiletest-rustc-args", &rustc_args, ], Some(&rust_dir), @@ -1020,7 +1020,7 @@ where &"--stage", &"0", &format!("tests/{}", test_type), - &"--rustc-args", + &"--compiletest-rustc-args", &rustc_args, ], Some(&rust_path), diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 597d7733abe75..18204f9ec778d 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1815,7 +1815,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the let mut flags = if is_rustdoc { Vec::new() } else { vec!["-Crpath".to_string()] }; flags.push(format!("-Cdebuginfo={}", builder.config.rust_debuginfo_level_tests)); - flags.extend(builder.config.cmd.rustc_args().iter().map(|s| s.to_string())); + flags.extend(builder.config.cmd.compiletest_rustc_args().iter().map(|s| s.to_string())); if suite != "mir-opt" { if let Some(linker) = builder.linker(target) { diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index f19a4dd6d490f..5b50036f0f84a 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -632,7 +632,7 @@ mod dist { config.paths = vec!["library/std".into()]; config.cmd = Subcommand::Test { test_args: vec![], - rustc_args: vec![], + compiletest_rustc_args: vec![], no_fail_fast: false, no_doc: true, doc: false, @@ -703,7 +703,7 @@ mod dist { let mut config = configure(&["A-A"], &["A-A"]); config.cmd = Subcommand::Test { test_args: vec![], - rustc_args: vec![], + compiletest_rustc_args: vec![], no_fail_fast: false, doc: true, no_doc: false, diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs index c3b96e1225729..2371a6fa00816 100644 --- a/src/bootstrap/src/core/config/flags.rs +++ b/src/bootstrap/src/core/config/flags.rs @@ -349,7 +349,7 @@ pub enum Subcommand { test_args: Vec, /// extra options to pass the compiler when running compiletest tests #[arg(long, value_name = "ARGS", allow_hyphen_values(true))] - rustc_args: Vec, + compiletest_rustc_args: Vec, #[arg(long)] /// do not run doc tests no_doc: bool, @@ -496,10 +496,10 @@ impl Subcommand { } } - pub fn rustc_args(&self) -> Vec<&str> { + pub fn compiletest_rustc_args(&self) -> Vec<&str> { match *self { - Subcommand::Test { ref rustc_args, .. } => { - rustc_args.iter().flat_map(|s| s.split_whitespace()).collect() + Subcommand::Test { ref compiletest_rustc_args, .. } => { + compiletest_rustc_args.iter().flat_map(|s| s.split_whitespace()).collect() } _ => vec![], } From ee5d15ce43ac17ebbba74781012a2fe13d36bb65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Mon, 12 Aug 2024 15:13:04 +0000 Subject: [PATCH 775/786] regenerate `./x` completions to pick up changes to `./x miri` and `./x test` commands --- src/etc/completions/x.py.fish | 3 +-- src/etc/completions/x.py.ps1 | 3 +-- src/etc/completions/x.py.sh | 10 +++------- src/etc/completions/x.py.zsh | 3 +-- 4 files changed, 6 insertions(+), 13 deletions(-) diff --git a/src/etc/completions/x.py.fish b/src/etc/completions/x.py.fish index a0f147c6c8175..297dc11cd6145 100644 --- a/src/etc/completions/x.py.fish +++ b/src/etc/completions/x.py.fish @@ -266,7 +266,7 @@ complete -c x.py -n "__fish_seen_subcommand_from doc" -l enable-bolt-settings -d complete -c x.py -n "__fish_seen_subcommand_from doc" -l skip-stage0-validation -d 'Skip stage0 compiler validation' complete -c x.py -n "__fish_seen_subcommand_from doc" -s h -l help -d 'Print help (see more with \'--help\')' complete -c x.py -n "__fish_seen_subcommand_from test" -l test-args -d 'extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)' -r -complete -c x.py -n "__fish_seen_subcommand_from test" -l rustc-args -d 'extra options to pass the compiler when running compiletest tests' -r +complete -c x.py -n "__fish_seen_subcommand_from test" -l compiletest-rustc-args -d 'extra options to pass the compiler when running compiletest tests' -r complete -c x.py -n "__fish_seen_subcommand_from test" -l extra-checks -d 'comma-separated list of other files types to check (accepts py, py:lint, py:fmt, shell)' -r complete -c x.py -n "__fish_seen_subcommand_from test" -l compare-mode -d 'mode describing what file the actual ui output will be compared to' -r complete -c x.py -n "__fish_seen_subcommand_from test" -l pass -d 'force {check,build,run}-pass tests to this mode' -r @@ -313,7 +313,6 @@ complete -c x.py -n "__fish_seen_subcommand_from test" -l enable-bolt-settings - complete -c x.py -n "__fish_seen_subcommand_from test" -l skip-stage0-validation -d 'Skip stage0 compiler validation' complete -c x.py -n "__fish_seen_subcommand_from test" -s h -l help -d 'Print help (see more with \'--help\')' complete -c x.py -n "__fish_seen_subcommand_from miri" -l test-args -d 'extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)' -r -complete -c x.py -n "__fish_seen_subcommand_from miri" -l rustc-args -d 'extra options to pass the compiler when running tests' -r complete -c x.py -n "__fish_seen_subcommand_from miri" -l config -d 'TOML configuration file for build' -r -F complete -c x.py -n "__fish_seen_subcommand_from miri" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" complete -c x.py -n "__fish_seen_subcommand_from miri" -l build -d 'build target of the stage0 compiler' -r -f diff --git a/src/etc/completions/x.py.ps1 b/src/etc/completions/x.py.ps1 index 1b6004a07ff7a..4b424471a2672 100644 --- a/src/etc/completions/x.py.ps1 +++ b/src/etc/completions/x.py.ps1 @@ -338,7 +338,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { } 'x.py;test' { [CompletionResult]::new('--test-args', 'test-args', [CompletionResultType]::ParameterName, 'extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)') - [CompletionResult]::new('--rustc-args', 'rustc-args', [CompletionResultType]::ParameterName, 'extra options to pass the compiler when running compiletest tests') + [CompletionResult]::new('--compiletest-rustc-args', 'compiletest-rustc-args', [CompletionResultType]::ParameterName, 'extra options to pass the compiler when running compiletest tests') [CompletionResult]::new('--extra-checks', 'extra-checks', [CompletionResultType]::ParameterName, 'comma-separated list of other files types to check (accepts py, py:lint, py:fmt, shell)') [CompletionResult]::new('--compare-mode', 'compare-mode', [CompletionResultType]::ParameterName, 'mode describing what file the actual ui output will be compared to') [CompletionResult]::new('--pass', 'pass', [CompletionResultType]::ParameterName, 'force {check,build,run}-pass tests to this mode') @@ -392,7 +392,6 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { } 'x.py;miri' { [CompletionResult]::new('--test-args', 'test-args', [CompletionResultType]::ParameterName, 'extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)') - [CompletionResult]::new('--rustc-args', 'rustc-args', [CompletionResultType]::ParameterName, 'extra options to pass the compiler when running tests') [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') diff --git a/src/etc/completions/x.py.sh b/src/etc/completions/x.py.sh index a4234905476ad..60ba8d3ba7032 100644 --- a/src/etc/completions/x.py.sh +++ b/src/etc/completions/x.py.sh @@ -1300,7 +1300,7 @@ _x.py() { return 0 ;; x.py__miri) - opts="-v -i -j -h --no-fail-fast --test-args --rustc-args --no-doc --doc --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --no-fail-fast --test-args --no-doc --doc --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -1310,10 +1310,6 @@ _x.py() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; - --rustc-args) - COMPREPLY=($(compgen -f "${cur}")) - return 0 - ;; --config) COMPREPLY=($(compgen -f "${cur}")) return 0 @@ -1862,7 +1858,7 @@ _x.py() { return 0 ;; x.py__test) - opts="-v -i -j -h --no-fail-fast --test-args --rustc-args --no-doc --doc --bless --extra-checks --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --no-fail-fast --test-args --compiletest-rustc-args --no-doc --doc --bless --extra-checks --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -1872,7 +1868,7 @@ _x.py() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; - --rustc-args) + --compiletest-rustc-args) COMPREPLY=($(compgen -f "${cur}")) return 0 ;; diff --git a/src/etc/completions/x.py.zsh b/src/etc/completions/x.py.zsh index 6e029f4ba7428..688f692da2414 100644 --- a/src/etc/completions/x.py.zsh +++ b/src/etc/completions/x.py.zsh @@ -337,7 +337,7 @@ _arguments "${_arguments_options[@]}" \ (test) _arguments "${_arguments_options[@]}" \ '*--test-args=[extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)]:ARGS: ' \ -'*--rustc-args=[extra options to pass the compiler when running compiletest tests]:ARGS: ' \ +'*--compiletest-rustc-args=[extra options to pass the compiler when running compiletest tests]:ARGS: ' \ '--extra-checks=[comma-separated list of other files types to check (accepts py, py\:lint, py\:fmt, shell)]:EXTRA_CHECKS: ' \ '--compare-mode=[mode describing what file the actual ui output will be compared to]:COMPARE MODE: ' \ '--pass=[force {check,build,run}-pass tests to this mode]:check | build | run: ' \ @@ -393,7 +393,6 @@ _arguments "${_arguments_options[@]}" \ (miri) _arguments "${_arguments_options[@]}" \ '*--test-args=[extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)]:ARGS: ' \ -'*--rustc-args=[extra options to pass the compiler when running tests]:ARGS: ' \ '--config=[TOML configuration file for build]:FILE:_files' \ '--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:( )' \ From 2abfa35acd11667e1a86e9661d8e6ace3f845e37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Mon, 12 Aug 2024 15:26:24 +0000 Subject: [PATCH 776/786] add change tracker notice --- src/bootstrap/src/utils/change_tracker.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index 84dac25188e1e..c629f04c00ecd 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -225,4 +225,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ severity: ChangeSeverity::Info, summary: "New option `llvm.libzstd` to control whether llvm is built with zstd support.", }, + ChangeInfo { + change_id: 128841, + severity: ChangeSeverity::Warning, + summary: "./x test --rustc-args was renamed to --compiletest-rustc-args as it only applies there. ./x miri --rustc-args was also removed.", + }, ]; From 6863db5219267d7a8a8e82053ee4d1eb19840575 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Mon, 12 Aug 2024 18:46:06 +0200 Subject: [PATCH 777/786] Remove unused script from run-make tests --- tests/run-make/git_clone_sha1.sh | 23 ----------------------- 1 file changed, 23 deletions(-) delete mode 100644 tests/run-make/git_clone_sha1.sh diff --git a/tests/run-make/git_clone_sha1.sh b/tests/run-make/git_clone_sha1.sh deleted file mode 100644 index 626e4e4276121..0000000000000 --- a/tests/run-make/git_clone_sha1.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash -x - -# Usage: $0 project_name url sha1 -# Get the crate with the specified sha1. -# -# all arguments are required. -# -# See below link for git usage: -# https://stackoverflow.com/questions/3489173#14091182 - -# Mandatory arguments: -PROJECT_NAME=$1 -URL=$2 -SHA1=$3 - -function err_exit() { - echo "ERROR:" $* - exit 1 -} - -git clone $URL $PROJECT_NAME || err_exit -cd $PROJECT_NAME || err_exit -git reset --hard $SHA1 || err_exit From 027b19fa9b85c3330d2eb38970c22e44873db2fc Mon Sep 17 00:00:00 2001 From: schvv31n Date: Mon, 12 Aug 2024 18:32:31 +0100 Subject: [PATCH 778/786] std::fmt::FormatterFn -> std::fmt::FromFn --- library/alloc/src/fmt.rs | 2 +- library/core/src/fmt/builders.rs | 19 ++++++++++++++----- library/core/src/fmt/mod.rs | 2 +- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/library/alloc/src/fmt.rs b/library/alloc/src/fmt.rs index 4b9b90fc1f157..571fcd177aae7 100644 --- a/library/alloc/src/fmt.rs +++ b/library/alloc/src/fmt.rs @@ -581,7 +581,7 @@ pub use core::fmt::Alignment; #[stable(feature = "rust1", since = "1.0.0")] pub use core::fmt::Error; #[unstable(feature = "debug_closure_helpers", issue = "117729")] -pub use core::fmt::FormatterFn; +pub use core::fmt::{from_fn, FromFn}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::fmt::{write, Arguments}; #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/core/src/fmt/builders.rs b/library/core/src/fmt/builders.rs index 794ca1851b13d..467fa17a6f367 100644 --- a/library/core/src/fmt/builders.rs +++ b/library/core/src/fmt/builders.rs @@ -1018,7 +1018,8 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { } } -/// Implements [`fmt::Debug`] and [`fmt::Display`] using a function. +/// Creates a type whose [`fmt::Debug`] and [`fmt::Display`] impls are provided with the function +/// `f`. /// /// # Examples /// @@ -1030,17 +1031,25 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// assert_eq!(format!("{}", value), "a"); /// assert_eq!(format!("{:?}", value), "'a'"); /// -/// let wrapped = fmt::FormatterFn(|f| write!(f, "{value:?}")); +/// let wrapped = fmt::from_fn(|f| write!(f, "{value:?}")); /// assert_eq!(format!("{}", wrapped), "'a'"); /// assert_eq!(format!("{:?}", wrapped), "'a'"); /// ``` #[unstable(feature = "debug_closure_helpers", issue = "117729")] -pub struct FormatterFn(pub F) +pub fn from_fn) -> fmt::Result>(f: F) -> FromFn { + FromFn(f) +} + +/// Implements [`fmt::Debug`] and [`fmt::Display`] using a function. +/// +/// Created with [`from_fn`]. +#[unstable(feature = "debug_closure_helpers", issue = "117729")] +pub struct FromFn(F) where F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result; #[unstable(feature = "debug_closure_helpers", issue = "117729")] -impl fmt::Debug for FormatterFn +impl fmt::Debug for FromFn where F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result, { @@ -1050,7 +1059,7 @@ where } #[unstable(feature = "debug_closure_helpers", issue = "117729")] -impl fmt::Display for FormatterFn +impl fmt::Display for FromFn where F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result, { diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 60c0dc7685253..485ad4aee1971 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -34,7 +34,7 @@ pub enum Alignment { } #[unstable(feature = "debug_closure_helpers", issue = "117729")] -pub use self::builders::FormatterFn; +pub use self::builders::{from_fn, FromFn}; #[stable(feature = "debug_builders", since = "1.2.0")] pub use self::builders::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple}; From 66c93ac8bad2e17a11debffef6776049cade50b5 Mon Sep 17 00:00:00 2001 From: Ramon de C Valle Date: Mon, 12 Aug 2024 14:59:50 -0700 Subject: [PATCH 779/786] CFI: Move CFI ui tests to cfi directory Moves the CFI ui tests to the cfi directory and removes the cfi prefix from tests file names similarly to how the cfi codegen tests are organized. --- .../assoc-ty-lifetime-issue-123053.rs} | 0 .../sanitizer/{cfi-async-closures.rs => cfi/async-closures.rs} | 0 .../{cfi-can-reveal-opaques.rs => cfi/can-reveal-opaques.rs} | 0 .../canonical-jump-tables-requires-cfi.rs} | 0 .../canonical-jump-tables-requires-cfi.stderr} | 0 tests/ui/sanitizer/{cfi-closures.rs => cfi/closures.rs} | 0 .../{cfi-complex-receiver.rs => cfi/complex-receiver.rs} | 0 tests/ui/sanitizer/{cfi-coroutine.rs => cfi/coroutine.rs} | 0 .../ui/sanitizer/{cfi-drop-in-place.rs => cfi/drop-in-place.rs} | 0 .../{cfi-drop-no-principal.rs => cfi/drop-no-principal.rs} | 0 tests/ui/sanitizer/{cfi-fn-ptr.rs => cfi/fn-ptr.rs} | 0 .../generalize-pointers-attr-cfg.rs} | 0 .../generalize-pointers-requires-cfi.rs} | 0 .../generalize-pointers-requires-cfi.stderr} | 0 .../invalid-attr-encoding.rs} | 0 .../invalid-attr-encoding.stderr} | 2 +- .../is-incompatible-with-kcfi.aarch64.stderr} | 0 .../is-incompatible-with-kcfi.rs} | 0 .../is-incompatible-with-kcfi.x86_64.stderr} | 0 .../normalize-integers-attr-cfg.rs} | 0 .../normalize-integers-requires-cfi.rs} | 0 .../normalize-integers-requires-cfi.stderr} | 0 tests/ui/sanitizer/{cfi-requires-lto.rs => cfi/requires-lto.rs} | 0 .../{cfi-requires-lto.stderr => cfi/requires-lto.stderr} | 0 tests/ui/sanitizer/{cfi-self-ref.rs => cfi/self-ref.rs} | 0 .../{cfi-sized-associated-ty.rs => cfi/sized-associated-ty.rs} | 0 tests/ui/sanitizer/{cfi-supertraits.rs => cfi/supertraits.rs} | 0 tests/ui/sanitizer/{cfi-virtual-auto.rs => cfi/virtual-auto.rs} | 0 .../with-rustc-lto-requires-single-codegen-unit.rs} | 0 .../with-rustc-lto-requires-single-codegen-unit.stderr} | 0 30 files changed, 1 insertion(+), 1 deletion(-) rename tests/ui/sanitizer/{cfi-assoc-ty-lifetime-issue-123053.rs => cfi/assoc-ty-lifetime-issue-123053.rs} (100%) rename tests/ui/sanitizer/{cfi-async-closures.rs => cfi/async-closures.rs} (100%) rename tests/ui/sanitizer/{cfi-can-reveal-opaques.rs => cfi/can-reveal-opaques.rs} (100%) rename tests/ui/sanitizer/{cfi-canonical-jump-tables-requires-cfi.rs => cfi/canonical-jump-tables-requires-cfi.rs} (100%) rename tests/ui/sanitizer/{cfi-canonical-jump-tables-requires-cfi.stderr => cfi/canonical-jump-tables-requires-cfi.stderr} (100%) rename tests/ui/sanitizer/{cfi-closures.rs => cfi/closures.rs} (100%) rename tests/ui/sanitizer/{cfi-complex-receiver.rs => cfi/complex-receiver.rs} (100%) rename tests/ui/sanitizer/{cfi-coroutine.rs => cfi/coroutine.rs} (100%) rename tests/ui/sanitizer/{cfi-drop-in-place.rs => cfi/drop-in-place.rs} (100%) rename tests/ui/sanitizer/{cfi-drop-no-principal.rs => cfi/drop-no-principal.rs} (100%) rename tests/ui/sanitizer/{cfi-fn-ptr.rs => cfi/fn-ptr.rs} (100%) rename tests/ui/sanitizer/{cfi-generalize-pointers-attr-cfg.rs => cfi/generalize-pointers-attr-cfg.rs} (100%) rename tests/ui/sanitizer/{cfi-generalize-pointers-requires-cfi.rs => cfi/generalize-pointers-requires-cfi.rs} (100%) rename tests/ui/sanitizer/{cfi-generalize-pointers-requires-cfi.stderr => cfi/generalize-pointers-requires-cfi.stderr} (100%) rename tests/ui/sanitizer/{cfi-invalid-attr-cfi-encoding.rs => cfi/invalid-attr-encoding.rs} (100%) rename tests/ui/sanitizer/{cfi-invalid-attr-cfi-encoding.stderr => cfi/invalid-attr-encoding.stderr} (79%) rename tests/ui/sanitizer/{cfi-is-incompatible-with-kcfi.aarch64.stderr => cfi/is-incompatible-with-kcfi.aarch64.stderr} (100%) rename tests/ui/sanitizer/{cfi-is-incompatible-with-kcfi.rs => cfi/is-incompatible-with-kcfi.rs} (100%) rename tests/ui/sanitizer/{cfi-is-incompatible-with-kcfi.x86_64.stderr => cfi/is-incompatible-with-kcfi.x86_64.stderr} (100%) rename tests/ui/sanitizer/{cfi-normalize-integers-attr-cfg.rs => cfi/normalize-integers-attr-cfg.rs} (100%) rename tests/ui/sanitizer/{cfi-normalize-integers-requires-cfi.rs => cfi/normalize-integers-requires-cfi.rs} (100%) rename tests/ui/sanitizer/{cfi-normalize-integers-requires-cfi.stderr => cfi/normalize-integers-requires-cfi.stderr} (100%) rename tests/ui/sanitizer/{cfi-requires-lto.rs => cfi/requires-lto.rs} (100%) rename tests/ui/sanitizer/{cfi-requires-lto.stderr => cfi/requires-lto.stderr} (100%) rename tests/ui/sanitizer/{cfi-self-ref.rs => cfi/self-ref.rs} (100%) rename tests/ui/sanitizer/{cfi-sized-associated-ty.rs => cfi/sized-associated-ty.rs} (100%) rename tests/ui/sanitizer/{cfi-supertraits.rs => cfi/supertraits.rs} (100%) rename tests/ui/sanitizer/{cfi-virtual-auto.rs => cfi/virtual-auto.rs} (100%) rename tests/ui/sanitizer/{cfi-with-rustc-lto-requires-single-codegen-unit.rs => cfi/with-rustc-lto-requires-single-codegen-unit.rs} (100%) rename tests/ui/sanitizer/{cfi-with-rustc-lto-requires-single-codegen-unit.stderr => cfi/with-rustc-lto-requires-single-codegen-unit.stderr} (100%) diff --git a/tests/ui/sanitizer/cfi-assoc-ty-lifetime-issue-123053.rs b/tests/ui/sanitizer/cfi/assoc-ty-lifetime-issue-123053.rs similarity index 100% rename from tests/ui/sanitizer/cfi-assoc-ty-lifetime-issue-123053.rs rename to tests/ui/sanitizer/cfi/assoc-ty-lifetime-issue-123053.rs diff --git a/tests/ui/sanitizer/cfi-async-closures.rs b/tests/ui/sanitizer/cfi/async-closures.rs similarity index 100% rename from tests/ui/sanitizer/cfi-async-closures.rs rename to tests/ui/sanitizer/cfi/async-closures.rs diff --git a/tests/ui/sanitizer/cfi-can-reveal-opaques.rs b/tests/ui/sanitizer/cfi/can-reveal-opaques.rs similarity index 100% rename from tests/ui/sanitizer/cfi-can-reveal-opaques.rs rename to tests/ui/sanitizer/cfi/can-reveal-opaques.rs diff --git a/tests/ui/sanitizer/cfi-canonical-jump-tables-requires-cfi.rs b/tests/ui/sanitizer/cfi/canonical-jump-tables-requires-cfi.rs similarity index 100% rename from tests/ui/sanitizer/cfi-canonical-jump-tables-requires-cfi.rs rename to tests/ui/sanitizer/cfi/canonical-jump-tables-requires-cfi.rs diff --git a/tests/ui/sanitizer/cfi-canonical-jump-tables-requires-cfi.stderr b/tests/ui/sanitizer/cfi/canonical-jump-tables-requires-cfi.stderr similarity index 100% rename from tests/ui/sanitizer/cfi-canonical-jump-tables-requires-cfi.stderr rename to tests/ui/sanitizer/cfi/canonical-jump-tables-requires-cfi.stderr diff --git a/tests/ui/sanitizer/cfi-closures.rs b/tests/ui/sanitizer/cfi/closures.rs similarity index 100% rename from tests/ui/sanitizer/cfi-closures.rs rename to tests/ui/sanitizer/cfi/closures.rs diff --git a/tests/ui/sanitizer/cfi-complex-receiver.rs b/tests/ui/sanitizer/cfi/complex-receiver.rs similarity index 100% rename from tests/ui/sanitizer/cfi-complex-receiver.rs rename to tests/ui/sanitizer/cfi/complex-receiver.rs diff --git a/tests/ui/sanitizer/cfi-coroutine.rs b/tests/ui/sanitizer/cfi/coroutine.rs similarity index 100% rename from tests/ui/sanitizer/cfi-coroutine.rs rename to tests/ui/sanitizer/cfi/coroutine.rs diff --git a/tests/ui/sanitizer/cfi-drop-in-place.rs b/tests/ui/sanitizer/cfi/drop-in-place.rs similarity index 100% rename from tests/ui/sanitizer/cfi-drop-in-place.rs rename to tests/ui/sanitizer/cfi/drop-in-place.rs diff --git a/tests/ui/sanitizer/cfi-drop-no-principal.rs b/tests/ui/sanitizer/cfi/drop-no-principal.rs similarity index 100% rename from tests/ui/sanitizer/cfi-drop-no-principal.rs rename to tests/ui/sanitizer/cfi/drop-no-principal.rs diff --git a/tests/ui/sanitizer/cfi-fn-ptr.rs b/tests/ui/sanitizer/cfi/fn-ptr.rs similarity index 100% rename from tests/ui/sanitizer/cfi-fn-ptr.rs rename to tests/ui/sanitizer/cfi/fn-ptr.rs diff --git a/tests/ui/sanitizer/cfi-generalize-pointers-attr-cfg.rs b/tests/ui/sanitizer/cfi/generalize-pointers-attr-cfg.rs similarity index 100% rename from tests/ui/sanitizer/cfi-generalize-pointers-attr-cfg.rs rename to tests/ui/sanitizer/cfi/generalize-pointers-attr-cfg.rs diff --git a/tests/ui/sanitizer/cfi-generalize-pointers-requires-cfi.rs b/tests/ui/sanitizer/cfi/generalize-pointers-requires-cfi.rs similarity index 100% rename from tests/ui/sanitizer/cfi-generalize-pointers-requires-cfi.rs rename to tests/ui/sanitizer/cfi/generalize-pointers-requires-cfi.rs diff --git a/tests/ui/sanitizer/cfi-generalize-pointers-requires-cfi.stderr b/tests/ui/sanitizer/cfi/generalize-pointers-requires-cfi.stderr similarity index 100% rename from tests/ui/sanitizer/cfi-generalize-pointers-requires-cfi.stderr rename to tests/ui/sanitizer/cfi/generalize-pointers-requires-cfi.stderr diff --git a/tests/ui/sanitizer/cfi-invalid-attr-cfi-encoding.rs b/tests/ui/sanitizer/cfi/invalid-attr-encoding.rs similarity index 100% rename from tests/ui/sanitizer/cfi-invalid-attr-cfi-encoding.rs rename to tests/ui/sanitizer/cfi/invalid-attr-encoding.rs diff --git a/tests/ui/sanitizer/cfi-invalid-attr-cfi-encoding.stderr b/tests/ui/sanitizer/cfi/invalid-attr-encoding.stderr similarity index 79% rename from tests/ui/sanitizer/cfi-invalid-attr-cfi-encoding.stderr rename to tests/ui/sanitizer/cfi/invalid-attr-encoding.stderr index 93ec134241e31..1aa6bef17b1e2 100644 --- a/tests/ui/sanitizer/cfi-invalid-attr-cfi-encoding.stderr +++ b/tests/ui/sanitizer/cfi/invalid-attr-encoding.stderr @@ -1,5 +1,5 @@ error: malformed `cfi_encoding` attribute input - --> $DIR/cfi-invalid-attr-cfi-encoding.rs:10:1 + --> $DIR/invalid-attr-encoding.rs:10:1 | LL | #[cfi_encoding] | ^^^^^^^^^^^^^^^ help: must be of the form: `#[cfi_encoding = "encoding"]` diff --git a/tests/ui/sanitizer/cfi-is-incompatible-with-kcfi.aarch64.stderr b/tests/ui/sanitizer/cfi/is-incompatible-with-kcfi.aarch64.stderr similarity index 100% rename from tests/ui/sanitizer/cfi-is-incompatible-with-kcfi.aarch64.stderr rename to tests/ui/sanitizer/cfi/is-incompatible-with-kcfi.aarch64.stderr diff --git a/tests/ui/sanitizer/cfi-is-incompatible-with-kcfi.rs b/tests/ui/sanitizer/cfi/is-incompatible-with-kcfi.rs similarity index 100% rename from tests/ui/sanitizer/cfi-is-incompatible-with-kcfi.rs rename to tests/ui/sanitizer/cfi/is-incompatible-with-kcfi.rs diff --git a/tests/ui/sanitizer/cfi-is-incompatible-with-kcfi.x86_64.stderr b/tests/ui/sanitizer/cfi/is-incompatible-with-kcfi.x86_64.stderr similarity index 100% rename from tests/ui/sanitizer/cfi-is-incompatible-with-kcfi.x86_64.stderr rename to tests/ui/sanitizer/cfi/is-incompatible-with-kcfi.x86_64.stderr diff --git a/tests/ui/sanitizer/cfi-normalize-integers-attr-cfg.rs b/tests/ui/sanitizer/cfi/normalize-integers-attr-cfg.rs similarity index 100% rename from tests/ui/sanitizer/cfi-normalize-integers-attr-cfg.rs rename to tests/ui/sanitizer/cfi/normalize-integers-attr-cfg.rs diff --git a/tests/ui/sanitizer/cfi-normalize-integers-requires-cfi.rs b/tests/ui/sanitizer/cfi/normalize-integers-requires-cfi.rs similarity index 100% rename from tests/ui/sanitizer/cfi-normalize-integers-requires-cfi.rs rename to tests/ui/sanitizer/cfi/normalize-integers-requires-cfi.rs diff --git a/tests/ui/sanitizer/cfi-normalize-integers-requires-cfi.stderr b/tests/ui/sanitizer/cfi/normalize-integers-requires-cfi.stderr similarity index 100% rename from tests/ui/sanitizer/cfi-normalize-integers-requires-cfi.stderr rename to tests/ui/sanitizer/cfi/normalize-integers-requires-cfi.stderr diff --git a/tests/ui/sanitizer/cfi-requires-lto.rs b/tests/ui/sanitizer/cfi/requires-lto.rs similarity index 100% rename from tests/ui/sanitizer/cfi-requires-lto.rs rename to tests/ui/sanitizer/cfi/requires-lto.rs diff --git a/tests/ui/sanitizer/cfi-requires-lto.stderr b/tests/ui/sanitizer/cfi/requires-lto.stderr similarity index 100% rename from tests/ui/sanitizer/cfi-requires-lto.stderr rename to tests/ui/sanitizer/cfi/requires-lto.stderr diff --git a/tests/ui/sanitizer/cfi-self-ref.rs b/tests/ui/sanitizer/cfi/self-ref.rs similarity index 100% rename from tests/ui/sanitizer/cfi-self-ref.rs rename to tests/ui/sanitizer/cfi/self-ref.rs diff --git a/tests/ui/sanitizer/cfi-sized-associated-ty.rs b/tests/ui/sanitizer/cfi/sized-associated-ty.rs similarity index 100% rename from tests/ui/sanitizer/cfi-sized-associated-ty.rs rename to tests/ui/sanitizer/cfi/sized-associated-ty.rs diff --git a/tests/ui/sanitizer/cfi-supertraits.rs b/tests/ui/sanitizer/cfi/supertraits.rs similarity index 100% rename from tests/ui/sanitizer/cfi-supertraits.rs rename to tests/ui/sanitizer/cfi/supertraits.rs diff --git a/tests/ui/sanitizer/cfi-virtual-auto.rs b/tests/ui/sanitizer/cfi/virtual-auto.rs similarity index 100% rename from tests/ui/sanitizer/cfi-virtual-auto.rs rename to tests/ui/sanitizer/cfi/virtual-auto.rs diff --git a/tests/ui/sanitizer/cfi-with-rustc-lto-requires-single-codegen-unit.rs b/tests/ui/sanitizer/cfi/with-rustc-lto-requires-single-codegen-unit.rs similarity index 100% rename from tests/ui/sanitizer/cfi-with-rustc-lto-requires-single-codegen-unit.rs rename to tests/ui/sanitizer/cfi/with-rustc-lto-requires-single-codegen-unit.rs diff --git a/tests/ui/sanitizer/cfi-with-rustc-lto-requires-single-codegen-unit.stderr b/tests/ui/sanitizer/cfi/with-rustc-lto-requires-single-codegen-unit.stderr similarity index 100% rename from tests/ui/sanitizer/cfi-with-rustc-lto-requires-single-codegen-unit.stderr rename to tests/ui/sanitizer/cfi/with-rustc-lto-requires-single-codegen-unit.stderr From a7be5bf683be4b69cc92e42bc2ae695724dc47e0 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sun, 11 Aug 2024 10:14:57 +0000 Subject: [PATCH 780/786] std::fs: get_mode implementation for haiku. --- library/std/src/sys/pal/unix/fs.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs index bdb83f0785784..ff7ee4fdfa81b 100644 --- a/library/std/src/sys/pal/unix/fs.rs +++ b/library/std/src/sys/pal/unix/fs.rs @@ -1561,6 +1561,7 @@ impl fmt::Debug for File { target_os = "vxworks", target_os = "solaris", target_os = "illumos", + target_os = "haiku", target_vendor = "apple", ))] fn get_mode(fd: c_int) -> Option<(bool, bool)> { @@ -1585,6 +1586,7 @@ impl fmt::Debug for File { target_os = "vxworks", target_os = "solaris", target_os = "illumos", + target_os = "haiku", target_vendor = "apple", )))] fn get_mode(_fd: c_int) -> Option<(bool, bool)> { From 70e0f69632591add54bc1e4d625e7bbb9fa02095 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Mon, 12 Aug 2024 23:44:42 +0100 Subject: [PATCH 781/786] trying common codepath for every unixes --- library/std/src/sys/pal/unix/fs.rs | 29 ----------------------------- src/llvm-project | 2 +- 2 files changed, 1 insertion(+), 30 deletions(-) diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs index ff7ee4fdfa81b..be13e1ae9b32f 100644 --- a/library/std/src/sys/pal/unix/fs.rs +++ b/library/std/src/sys/pal/unix/fs.rs @@ -1552,18 +1552,6 @@ impl fmt::Debug for File { None } - #[cfg(any( - target_os = "linux", - target_os = "freebsd", - target_os = "hurd", - target_os = "netbsd", - target_os = "openbsd", - target_os = "vxworks", - target_os = "solaris", - target_os = "illumos", - target_os = "haiku", - target_vendor = "apple", - ))] fn get_mode(fd: c_int) -> Option<(bool, bool)> { let mode = unsafe { libc::fcntl(fd, libc::F_GETFL) }; if mode == -1 { @@ -1577,23 +1565,6 @@ impl fmt::Debug for File { } } - #[cfg(not(any( - target_os = "linux", - target_os = "freebsd", - target_os = "hurd", - target_os = "netbsd", - target_os = "openbsd", - target_os = "vxworks", - target_os = "solaris", - target_os = "illumos", - target_os = "haiku", - target_vendor = "apple", - )))] - fn get_mode(_fd: c_int) -> Option<(bool, bool)> { - // FIXME(#24570): implement this for other Unix platforms - None - } - let fd = self.as_raw_fd(); let mut b = f.debug_struct("File"); b.field("fd", &fd); diff --git a/src/llvm-project b/src/llvm-project index ccf4c38bdd73f..57ae1a3474057 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit ccf4c38bdd73f1a37ec266c73bdaef80e39f8cf6 +Subproject commit 57ae1a3474057fead2c438928ed368b3740bf0ec From 6d91017b026af9531e3b066e06ff04230acbffda Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 13 Aug 2024 16:20:43 +1000 Subject: [PATCH 782/786] Extract a helper method for blessing in `Diff` --- src/tools/run-make-support/src/diff/mod.rs | 35 ++++++++++++---------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/src/tools/run-make-support/src/diff/mod.rs b/src/tools/run-make-support/src/diff/mod.rs index b0ed4d5445c48..61c724c952072 100644 --- a/src/tools/run-make-support/src/diff/mod.rs +++ b/src/tools/run-make-support/src/diff/mod.rs @@ -112,14 +112,8 @@ impl Diff { let (expected_name, actual_name, output, actual) = self.run_common(); if !output.is_empty() { - // If we can bless (meaning we have a file to write into and the `RUSTC_BLESS_TEST` - // environment variable set), then we write into the file and return. - if let Some(ref expected_file) = self.expected_file { - if std::env::var("RUSTC_BLESS_TEST").is_ok() { - println!("Blessing `{}`", expected_file.display()); - fs::write(expected_file, actual); - return; - } + if self.maybe_bless_expected_file(&actual) { + return; } panic!( "test failed: `{}` is different from `{}`\n\n{}", @@ -134,14 +128,8 @@ impl Diff { let (expected_name, actual_name, output, actual) = self.run_common(); if output.is_empty() { - // If we can bless (meaning we have a file to write into and the `RUSTC_BLESS_TEST` - // environment variable set), then we write into the file and return. - if let Some(ref expected_file) = self.expected_file { - if std::env::var("RUSTC_BLESS_TEST").is_ok() { - println!("Blessing `{}`", expected_file.display()); - fs::write(expected_file, actual); - return; - } + if self.maybe_bless_expected_file(&actual) { + return; } panic!( "test failed: `{}` is not different from `{}`\n\n{}", @@ -149,4 +137,19 @@ impl Diff { ) } } + + /// If we have an expected file to write into, and `RUSTC_BLESS_TEST` is + /// set, then write the actual output into the file and return `true`. + fn maybe_bless_expected_file(&self, actual: &str) -> bool { + let Some(ref expected_file) = self.expected_file else { + return false; + }; + if std::env::var("RUSTC_BLESS_TEST").is_err() { + return false; + } + + println!("Blessing `{}`", expected_file.display()); + fs::write(expected_file, actual); + true + } } From cc58cf6443a1982aa613a6f3b4032fc31aefd6b9 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 13 Aug 2024 16:17:25 +1000 Subject: [PATCH 783/786] Fix blessing of rmake tests --- src/tools/compiletest/src/runtest.rs | 15 +++++++-------- src/tools/run-make-support/src/diff/mod.rs | 13 +++++++++---- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index ce6569f5537da..59fce44d1c725 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -3735,15 +3735,14 @@ impl<'test> TestCx<'test> { } if self.config.bless { - cmd.env("RUSTC_BLESS_TEST", "--bless"); - // Assume this option is active if the environment variable is "defined", with _any_ value. - // As an example, a `Makefile` can use this option by: + // If we're running in `--bless` mode, set an environment variable to tell + // `run_make_support` to bless snapshot files instead of checking them. // - // ifdef RUSTC_BLESS_TEST - // cp "$(TMPDIR)"/actual_something.ext expected_something.ext - // else - // $(DIFF) expected_something.ext "$(TMPDIR)"/actual_something.ext - // endif + // The value is this test's source directory, because the support code + // will need that path in order to bless the _original_ snapshot files, + // not the copies in `rmake_out`. + // (See .) + cmd.env("RUSTC_BLESS_TEST", &self.testpaths.file); } if self.config.target.contains("msvc") && !self.config.cc.is_empty() { diff --git a/src/tools/run-make-support/src/diff/mod.rs b/src/tools/run-make-support/src/diff/mod.rs index 61c724c952072..ee48e3733668d 100644 --- a/src/tools/run-make-support/src/diff/mod.rs +++ b/src/tools/run-make-support/src/diff/mod.rs @@ -140,16 +140,21 @@ impl Diff { /// If we have an expected file to write into, and `RUSTC_BLESS_TEST` is /// set, then write the actual output into the file and return `true`. + /// + /// We assume that `RUSTC_BLESS_TEST` contains the path to the original test's + /// source directory. That lets us bless the original snapshot file in the + /// source tree, not the copy in `rmake_out` that we would normally use. fn maybe_bless_expected_file(&self, actual: &str) -> bool { let Some(ref expected_file) = self.expected_file else { return false; }; - if std::env::var("RUSTC_BLESS_TEST").is_err() { + let Ok(bless_dir) = std::env::var("RUSTC_BLESS_TEST") else { return false; - } + }; - println!("Blessing `{}`", expected_file.display()); - fs::write(expected_file, actual); + let bless_file = Path::new(&bless_dir).join(expected_file); + println!("Blessing `{}`", bless_file.display()); + fs::write(bless_file, actual); true } } From 0cfbfa9532275a9b26ab21e706cbdc71f74c3450 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sun, 11 Aug 2024 21:03:32 +0200 Subject: [PATCH 784/786] Create a `TargetSelection` method for recognizing `*-windows-gnu` targets --- src/bootstrap/src/core/build_steps/compile.rs | 4 ++-- src/bootstrap/src/core/build_steps/dist.rs | 14 +++++++------- src/bootstrap/src/core/config/config.rs | 4 ++++ 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index c09180e542ff6..89f3725ba8a5e 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -432,7 +432,7 @@ fn copy_self_contained_objects( DependencyType::TargetSelfContained, ); } - } else if target.ends_with("windows-gnu") { + } else if target.is_windows_gnu() { for obj in ["crt2.o", "dllcrt2.o"].iter() { let src = compiler_file(builder, &builder.cc(target), target, CLang::C, obj); let target = libdir_self_contained.join(obj); @@ -793,7 +793,7 @@ impl Step for StartupObjects { fn run(self, builder: &Builder<'_>) -> Vec<(PathBuf, DependencyType)> { let for_compiler = self.compiler; let target = self.target; - if !target.ends_with("windows-gnu") { + if !target.is_windows_gnu() { return vec![]; } diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 43306eab1b144..da77b5243d4fd 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -1509,7 +1509,7 @@ impl Step for Extended { tarballs.push(builder.ensure(Rustc { compiler: builder.compiler(stage, target) })); tarballs.push(builder.ensure(Std { compiler, target }).expect("missing std")); - if target.ends_with("windows-gnu") { + if target.is_windows_gnu() { tarballs.push(builder.ensure(Mingw { host: target }).expect("missing mingw")); } @@ -1683,7 +1683,7 @@ impl Step for Extended { prepare(tool); } } - if target.ends_with("windows-gnu") { + if target.is_windows_gnu() { prepare("rust-mingw"); } @@ -1830,7 +1830,7 @@ impl Step for Extended { .arg("-t") .arg(etc.join("msi/remove-duplicates.xsl")) .run(builder); - if target.ends_with("windows-gnu") { + if target.is_windows_gnu() { command(&heat) .current_dir(&exe) .arg("dir") @@ -1876,7 +1876,7 @@ impl Step for Extended { if built_tools.contains("miri") { cmd.arg("-dMiriDir=miri"); } - if target.ends_with("windows-gnu") { + if target.is_windows_gnu() { cmd.arg("-dGccDir=rust-mingw"); } cmd.run(builder); @@ -1901,7 +1901,7 @@ impl Step for Extended { } candle("AnalysisGroup.wxs".as_ref()); - if target.ends_with("windows-gnu") { + if target.is_windows_gnu() { candle("GccGroup.wxs".as_ref()); } @@ -1941,7 +1941,7 @@ impl Step for Extended { cmd.arg("DocsGroup.wixobj"); } - if target.ends_with("windows-gnu") { + if target.is_windows_gnu() { cmd.arg("GccGroup.wixobj"); } // ICE57 wrongly complains about the shortcuts @@ -1973,7 +1973,7 @@ fn add_env(builder: &Builder<'_>, cmd: &mut BootstrapCommand, target: TargetSele if target.contains("windows-gnullvm") { cmd.env("CFG_MINGW", "1").env("CFG_ABI", "LLVM"); - } else if target.contains("windows-gnu") { + } else if target.is_windows_gnu() { cmd.env("CFG_MINGW", "1").env("CFG_ABI", "GNU"); } else { cmd.env("CFG_MINGW", "0").env("CFG_ABI", "MSVC"); diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 35ee4a29c6822..13ba42719bbdc 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -514,6 +514,10 @@ impl TargetSelection { self.contains("windows") } + pub fn is_windows_gnu(&self) -> bool { + self.ends_with("windows-gnu") + } + /// Path to the file defining the custom target, if any. pub fn filepath(&self) -> Option<&Path> { self.file.as_ref().map(Path::new) From 1c0c2c3ad66f06f1d112ad7388d439846fded606 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sun, 11 Aug 2024 21:11:17 +0200 Subject: [PATCH 785/786] Implement `AsRef` for `TargetSelection` --- src/bootstrap/src/core/build_steps/clean.rs | 4 +-- src/bootstrap/src/core/build_steps/compile.rs | 14 +++++----- src/bootstrap/src/core/build_steps/dist.rs | 24 ++++++----------- src/bootstrap/src/core/build_steps/doc.rs | 9 +++---- src/bootstrap/src/core/build_steps/test.rs | 8 +++--- src/bootstrap/src/core/builder.rs | 8 +++--- src/bootstrap/src/core/config/config.rs | 16 ++++++++--- src/bootstrap/src/core/download.rs | 8 +++--- src/bootstrap/src/lib.rs | 27 +++++++++---------- 9 files changed, 57 insertions(+), 61 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/clean.rs b/src/bootstrap/src/core/build_steps/clean.rs index 4931036718227..f608e5d715e49 100644 --- a/src/bootstrap/src/core/build_steps/clean.rs +++ b/src/bootstrap/src/core/build_steps/clean.rs @@ -121,7 +121,7 @@ fn clean(build: &Build, all: bool, stage: Option) { fn clean_specific_stage(build: &Build, stage: u32) { for host in &build.hosts { - let entries = match build.out.join(host.triple).read_dir() { + let entries = match build.out.join(host).read_dir() { Ok(iter) => iter, Err(_) => continue, }; @@ -148,7 +148,7 @@ fn clean_default(build: &Build) { rm_rf(&build.out.join("bootstrap-shims-dump")); rm_rf(&build.out.join("rustfmt.stamp")); - let mut hosts: Vec<_> = build.hosts.iter().map(|t| build.out.join(t.triple)).collect(); + let mut hosts: Vec<_> = build.hosts.iter().map(|t| build.out.join(t)).collect(); // After cross-compilation, artifacts of the host architecture (which may differ from build.host) // might not get removed. // Adding its path (linked one for easier accessibility) will solve this problem. diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 89f3725ba8a5e..4353cfadd8d35 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -246,7 +246,7 @@ impl Step for Std { .rustc_snapshot_sysroot() .join("lib") .join("rustlib") - .join(compiler.host.triple) + .join(compiler.host) .join("bin"); if src_sysroot_bin.exists() { let target_sysroot_bin = @@ -651,8 +651,8 @@ impl Step for StdLink { compiler: self.compiler, force_recompile: self.force_recompile, }); - let libdir = sysroot.join(lib).join("rustlib").join(target.triple).join("lib"); - let hostdir = sysroot.join(lib).join("rustlib").join(compiler.host.triple).join("lib"); + let libdir = sysroot.join(lib).join("rustlib").join(target).join("lib"); + let hostdir = sysroot.join(lib).join("rustlib").join(compiler.host).join("lib"); (libdir, hostdir) } else { let libdir = builder.sysroot_libdir(target_compiler, target); @@ -670,12 +670,12 @@ impl Step for StdLink { .build .config .initial_rustc - .starts_with(builder.out.join(compiler.host.triple).join("stage0/bin")) + .starts_with(builder.out.join(compiler.host).join("stage0/bin")) { // Copy bin files from stage0/bin to stage0-sysroot/bin - let sysroot = builder.out.join(compiler.host.triple).join("stage0-sysroot"); + let sysroot = builder.out.join(compiler.host).join("stage0-sysroot"); - let host = compiler.host.triple; + let host = compiler.host; let stage0_bin_dir = builder.out.join(host).join("stage0/bin"); let sysroot_bin_dir = sysroot.join("bin"); t!(fs::create_dir_all(&sysroot_bin_dir)); @@ -1554,7 +1554,7 @@ impl Step for Sysroot { /// For all other stages, it's the same stage directory that the compiler lives in. fn run(self, builder: &Builder<'_>) -> PathBuf { let compiler = self.compiler; - let host_dir = builder.out.join(compiler.host.triple); + let host_dir = builder.out.join(compiler.host); let sysroot_dir = |stage| { if stage == 0 { diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index da77b5243d4fd..530eb9b446a43 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -275,12 +275,8 @@ fn make_win_dist( } //Copy platform tools to platform-specific bin directory - let target_bin_dir = plat_root - .join("lib") - .join("rustlib") - .join(target.triple) - .join("bin") - .join("self-contained"); + let target_bin_dir = + plat_root.join("lib").join("rustlib").join(target).join("bin").join("self-contained"); fs::create_dir_all(&target_bin_dir).expect("creating target_bin_dir failed"); for src in target_tools { builder.copy_link_to_folder(&src, &target_bin_dir); @@ -295,12 +291,8 @@ fn make_win_dist( ); //Copy platform libs to platform-specific lib directory - let target_lib_dir = plat_root - .join("lib") - .join("rustlib") - .join(target.triple) - .join("lib") - .join("self-contained"); + let target_lib_dir = + plat_root.join("lib").join("rustlib").join(target).join("lib").join("self-contained"); fs::create_dir_all(&target_lib_dir).expect("creating target_lib_dir failed"); for src in target_libs { builder.copy_link_to_folder(&src, &target_lib_dir); @@ -450,7 +442,7 @@ impl Step for Rustc { // component for now. maybe_install_llvm_runtime(builder, host, image); - let dst_dir = image.join("lib/rustlib").join(&*host.triple).join("bin"); + let dst_dir = image.join("lib/rustlib").join(host).join("bin"); t!(fs::create_dir_all(&dst_dir)); // Copy over lld if it's there @@ -607,7 +599,7 @@ fn verify_uefi_rlib_format(builder: &Builder<'_>, target: TargetSelection, stamp /// Copy stamped files into an image's `target/lib` directory. fn copy_target_libs(builder: &Builder<'_>, target: TargetSelection, image: &Path, stamp: &Path) { - let dst = image.join("lib/rustlib").join(target.triple).join("lib"); + let dst = image.join("lib/rustlib").join(target).join("lib"); let self_contained_dst = dst.join("self-contained"); t!(fs::create_dir_all(&dst)); t!(fs::create_dir_all(&self_contained_dst)); @@ -769,7 +761,7 @@ impl Step for Analysis { let src = builder .stage_out(compiler, Mode::Std) - .join(target.triple) + .join(target) .join(builder.cargo_dir()) .join("deps") .join("save-analysis"); @@ -2087,7 +2079,7 @@ fn maybe_install_llvm( /// Maybe add libLLVM.so to the target lib-dir for linking. pub fn maybe_install_llvm_target(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) { - let dst_libdir = sysroot.join("lib/rustlib").join(&*target.triple).join("lib"); + let dst_libdir = sysroot.join("lib/rustlib").join(target).join("lib"); // We do not need to copy LLVM files into the sysroot if it is not // dynamically linked; it is already included into librustc_llvm // statically. diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index 2cd5db706c26a..301633559fe71 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -699,13 +699,12 @@ fn doc_std( let compiler = builder.compiler(stage, builder.config.build); let target_doc_dir_name = if format == DocumentationFormat::Json { "json-doc" } else { "doc" }; - let target_dir = - builder.stage_out(compiler, Mode::Std).join(target.triple).join(target_doc_dir_name); + let target_dir = builder.stage_out(compiler, Mode::Std).join(target).join(target_doc_dir_name); // This is directory where the compiler will place the output of the command. // We will then copy the files from this directory into the final `out` directory, the specified // as a function parameter. - let out_dir = target_dir.join(target.triple).join("doc"); + let out_dir = target_dir.join(target).join("doc"); let mut cargo = builder::Cargo::new(builder, compiler, Mode::Std, SourceType::InTree, target, Kind::Doc); @@ -846,7 +845,7 @@ impl Step for Rustc { let mut to_open = None; - let out_dir = builder.stage_out(compiler, Mode::Rustc).join(target.triple).join("doc"); + let out_dir = builder.stage_out(compiler, Mode::Rustc).join(target).join("doc"); for krate in &*self.crates { // Create all crate output directories first to make sure rustdoc uses // relative links. @@ -992,7 +991,7 @@ macro_rules! tool_doc { // see https://github.com/rust-lang/rust/pull/122066#issuecomment-1983049222 // cargo.rustdocflag("--generate-link-to-definition"); - let out_dir = builder.stage_out(compiler, Mode::ToolRustc).join(target.triple).join("doc"); + let out_dir = builder.stage_out(compiler, Mode::ToolRustc).join(target).join("doc"); $(for krate in $crates { let dir_name = krate.replace("-", "_"); t!(fs::create_dir_all(out_dir.join(&*dir_name))); diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 6ed001d8fd5f7..d5e7ab1323f81 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -149,7 +149,7 @@ You can skip linkcheck with --skip src/tools/linkchecker" let _guard = builder.msg(Kind::Test, compiler.stage, "Linkcheck", bootstrap_host, bootstrap_host); let _time = helpers::timeit(builder); - linkchecker.delay_failure().arg(builder.out.join(host.triple).join("doc")).run(builder); + linkchecker.delay_failure().arg(builder.out.join(host).join("doc")).run(builder); } fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { @@ -435,7 +435,7 @@ impl Miri { compiler: Compiler, target: TargetSelection, ) -> PathBuf { - let miri_sysroot = builder.out.join(compiler.host.triple).join("miri-sysroot"); + let miri_sysroot = builder.out.join(compiler.host).join("miri-sysroot"); let mut cargo = builder::Cargo::new( builder, compiler, @@ -1115,7 +1115,7 @@ HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to } fn testdir(builder: &Builder<'_>, host: TargetSelection) -> PathBuf { - builder.out.join(host.triple).join("test") + builder.out.join(host).join("test") } macro_rules! default_test { @@ -2685,7 +2685,7 @@ impl Step for Crate { if builder.download_rustc() && compiler.stage > 0 { let sysroot = builder .out - .join(compiler.host.triple) + .join(compiler.host) .join(format!("stage{}-test-sysroot", compiler.stage)); cargo.env("RUSTC_SYSROOT", sysroot); } diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index ccdeb442af4af..fcf5367680184 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -1171,7 +1171,7 @@ impl<'a> Builder<'a> { .sysroot(self.compiler) .join(lib) .join("rustlib") - .join(self.target.triple) + .join(self.target) .join("lib"); // Avoid deleting the rustlib/ directory we just copied // (in `impl Step for Sysroot`). @@ -1254,7 +1254,7 @@ impl<'a> Builder<'a> { // Ensure that the downloaded LLVM libraries can be found. if self.config.llvm_from_ci { - let ci_llvm_lib = self.out.join(&*compiler.host.triple).join("ci-llvm").join("lib"); + let ci_llvm_lib = self.out.join(compiler.host).join("ci-llvm").join("lib"); dylib_dirs.push(ci_llvm_lib); } @@ -1504,9 +1504,9 @@ impl<'a> Builder<'a> { Mode::Rustc | Mode::ToolRustc => self.compiler_doc_out(target), Mode::Std => { if self.config.cmd.json() { - out_dir.join(target.triple).join("json-doc") + out_dir.join(target).join("json-doc") } else { - out_dir.join(target.triple).join("doc") + out_dir.join(target).join("doc") } } _ => panic!("doc mode {mode:?} not expected"), diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 13ba42719bbdc..36de8324f67e3 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -546,6 +546,14 @@ impl PartialEq<&str> for TargetSelection { } } +// Targets are often used as directory names throughout bootstrap. +// This impl makes it more ergonomics to use them as such. +impl AsRef for TargetSelection { + fn as_ref(&self) -> &Path { + self.triple.as_ref() + } +} + /// Per-target configuration stored in the global configuration structure. #[derive(Debug, Default, Clone, PartialEq, Eq)] pub struct Target { @@ -1473,7 +1481,7 @@ impl Config { config.download_beta_toolchain(); config .out - .join(config.build.triple) + .join(config.build) .join("stage0") .join("bin") .join(exe("rustc", config.build)) @@ -1488,7 +1496,7 @@ impl Config { config.download_beta_toolchain(); config .out - .join(config.build.triple) + .join(config.build) .join("stage0") .join("bin") .join(exe("cargo", config.build)) @@ -2281,13 +2289,13 @@ impl Config { /// The absolute path to the downloaded LLVM artifacts. pub(crate) fn ci_llvm_root(&self) -> PathBuf { assert!(self.llvm_from_ci); - self.out.join(&*self.build.triple).join("ci-llvm") + self.out.join(self.build).join("ci-llvm") } /// Directory where the extracted `rustc-dev` component is stored. pub(crate) fn ci_rustc_dir(&self) -> PathBuf { assert!(self.download_rustc()); - self.out.join(self.build.triple).join("ci-rustc") + self.out.join(self.build).join("ci-rustc") } /// Determine whether llvm should be linked dynamically. diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index 4d1aea3cd956a..8131666fcb225 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -379,7 +379,7 @@ impl Config { let version = &self.stage0_metadata.compiler.version; let host = self.build; - let bin_root = self.out.join(host.triple).join("stage0"); + let bin_root = self.out.join(host).join("stage0"); let clippy_stamp = bin_root.join(".clippy-stamp"); let cargo_clippy = bin_root.join("bin").join(exe("cargo-clippy", host)); if cargo_clippy.exists() && !program_out_of_date(&clippy_stamp, date) { @@ -412,7 +412,7 @@ impl Config { let channel = format!("{version}-{date}"); let host = self.build; - let bin_root = self.out.join(host.triple).join("rustfmt"); + let bin_root = self.out.join(host).join("rustfmt"); let rustfmt_path = bin_root.join("bin").join(exe("rustfmt", host)); let rustfmt_stamp = bin_root.join(".rustfmt-stamp"); if rustfmt_path.exists() && !program_out_of_date(&rustfmt_stamp, &channel) { @@ -519,7 +519,7 @@ impl Config { extra_components: &[&str], download_component: fn(&Config, String, &str, &str), ) { - let host = self.build.triple; + let host = self.build; let bin_root = self.out.join(host).join(sysroot); let rustc_stamp = bin_root.join(".rustc-stamp"); @@ -592,7 +592,7 @@ impl Config { t!(fs::create_dir_all(&cache_dir)); } - let bin_root = self.out.join(self.build.triple).join(destination); + let bin_root = self.out.join(self.build).join(destination); let tarball = cache_dir.join(&filename); let (base_url, url, should_verify) = match mode { DownloadSource::CI => { diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index e8a61ab4cf58e..bfd0e42acfd32 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -452,7 +452,7 @@ impl Build { } // Make a symbolic link so we can use a consistent directory in the documentation. - let build_triple = build.out.join(build.build.triple); + let build_triple = build.out.join(build.build); t!(fs::create_dir_all(&build_triple)); let host = build.out.join("host"); if host.is_symlink() { @@ -807,10 +807,7 @@ impl Build { } fn tools_dir(&self, compiler: Compiler) -> PathBuf { - let out = self - .out - .join(&*compiler.host.triple) - .join(format!("stage{}-tools-bin", compiler.stage)); + let out = self.out.join(compiler.host).join(format!("stage{}-tools-bin", compiler.stage)); t!(fs::create_dir_all(&out)); out } @@ -827,14 +824,14 @@ impl Build { Mode::ToolBootstrap => "-bootstrap-tools", Mode::ToolStd | Mode::ToolRustc => "-tools", }; - self.out.join(&*compiler.host.triple).join(format!("stage{}{}", compiler.stage, suffix)) + self.out.join(compiler.host).join(format!("stage{}{}", compiler.stage, suffix)) } /// Returns the root output directory for all Cargo output in a given stage, /// running a particular compiler, whether or not we're building the /// standard library, and targeting the specified architecture. fn cargo_out(&self, compiler: Compiler, mode: Mode, target: TargetSelection) -> PathBuf { - self.stage_out(compiler, mode).join(&*target.triple).join(self.cargo_dir()) + self.stage_out(compiler, mode).join(target).join(self.cargo_dir()) } /// Root output directory of LLVM for `target` @@ -845,36 +842,36 @@ impl Build { if self.config.llvm_from_ci && self.config.build == target { self.config.ci_llvm_root() } else { - self.out.join(&*target.triple).join("llvm") + self.out.join(target).join("llvm") } } fn lld_out(&self, target: TargetSelection) -> PathBuf { - self.out.join(&*target.triple).join("lld") + self.out.join(target).join("lld") } /// Output directory for all documentation for a target fn doc_out(&self, target: TargetSelection) -> PathBuf { - self.out.join(&*target.triple).join("doc") + self.out.join(target).join("doc") } /// Output directory for all JSON-formatted documentation for a target fn json_doc_out(&self, target: TargetSelection) -> PathBuf { - self.out.join(&*target.triple).join("json-doc") + self.out.join(target).join("json-doc") } fn test_out(&self, target: TargetSelection) -> PathBuf { - self.out.join(&*target.triple).join("test") + self.out.join(target).join("test") } /// Output directory for all documentation for a target fn compiler_doc_out(&self, target: TargetSelection) -> PathBuf { - self.out.join(&*target.triple).join("compiler-doc") + self.out.join(target).join("compiler-doc") } /// Output directory for some generated md crate documentation for a target (temporary) fn md_doc_out(&self, target: TargetSelection) -> PathBuf { - self.out.join(&*target.triple).join("md-doc") + self.out.join(target).join("md-doc") } /// Returns `true` if this is an external version of LLVM not managed by bootstrap. @@ -954,7 +951,7 @@ impl Build { /// Directory for libraries built from C/C++ code and shared between stages. fn native_dir(&self, target: TargetSelection) -> PathBuf { - self.out.join(&*target.triple).join("native") + self.out.join(target).join("native") } /// Root output directory for rust_test_helpers library compiled for From ddb8551e03a1310a841da05b0418b49fd6287482 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Tue, 13 Aug 2024 17:56:37 +0300 Subject: [PATCH 786/786] Preparing for merge from rust-lang/rust --- src/tools/rust-analyzer/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/rust-version b/src/tools/rust-analyzer/rust-version index 001b900b207e3..d4f1703d850c5 100644 --- a/src/tools/rust-analyzer/rust-version +++ b/src/tools/rust-analyzer/rust-version @@ -1 +1 @@ -1b51d80027919563004918eaadfa0d890ac0eb93 +80eb5a8e910e5185d47cdefe3732d839c78a5e7e