From 6b3a9f4b4ca95e7dabfd5fafe419686635be7af2 Mon Sep 17 00:00:00 2001 From: Simon Olofsson Date: Thu, 1 Oct 2026 16:14:30 +0200 Subject: [PATCH 01/34] thir.md: update example output --- src/doc/rustc-dev-guide/src/thir.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/thir.md b/src/doc/rustc-dev-guide/src/thir.md index 8b80d0be16874..21ca10ef3519e 100644 --- a/src/doc/rustc-dev-guide/src/thir.md +++ b/src/doc/rustc-dev-guide/src/thir.md @@ -59,7 +59,7 @@ fn main() { } ``` -Here is how that gets represented in THIR (as of Jul 2026): +Here is how that gets represented in THIR (as of October 2026): ```rust,no_run DefId(0:3 ~ main[26fd]::main): @@ -67,7 +67,7 @@ Thir { body_type: Fn( fn(), ), - attributes: {}, + loop_hint_attrs: {}, // no match arms arms: [], blocks: [ From d8eeadd7f0f4d2bba21e1ef9c83340143f4ecc0b Mon Sep 17 00:00:00 2001 From: Simon Olofsson Date: Thu, 1 Oct 2026 16:25:56 +0200 Subject: [PATCH 02/34] thir.md: update date-check, add tail call checking --- src/doc/rustc-dev-guide/src/thir.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/thir.md b/src/doc/rustc-dev-guide/src/thir.md index 21ca10ef3519e..8234bb0c8cd87 100644 --- a/src/doc/rustc-dev-guide/src/thir.md +++ b/src/doc/rustc-dev-guide/src/thir.md @@ -2,13 +2,15 @@ The THIR ("Typed High-Level Intermediate Representation"), previously called HAIR for "High-Level Abstract IR", is another IR used by rustc that is generated after -[type checking]. It is (as of January 2024) used for -[MIR construction], [exhaustiveness checking], and [unsafety checking]. +[type checking]. It is (as of October 2026) used for +[MIR construction], [exhaustiveness checking], [unsafety checking], and +[explicit tail call checking]. [type checking]: ./hir-typeck/summary.md [MIR construction]: ./mir/construction.md [exhaustiveness checking]: ./pat-exhaustive-checking.md [unsafety checking]: ./unsafety-checking.md +[explicit tail call checking]: https://github.com/rust-lang/rust/issues/112788 As the name might suggest, the THIR is a lowered version of the [HIR] where all the types have been filled in, which is possible after type checking has completed. From 6ae045a9b9ab71ab0da5babc3ab73d6436a61d53 Mon Sep 17 00:00:00 2001 From: Simon Olofsson Date: Thu, 1 Oct 2026 16:45:17 +0200 Subject: [PATCH 03/34] thir.md: thir_body is a query --- src/doc/rustc-dev-guide/src/thir.md | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/thir.md b/src/doc/rustc-dev-guide/src/thir.md index 8234bb0c8cd87..63679b50ecf40 100644 --- a/src/doc/rustc-dev-guide/src/thir.md +++ b/src/doc/rustc-dev-guide/src/thir.md @@ -41,12 +41,9 @@ But it has some other interesting features that distinguish it from the HIR: [`ExprId`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/thir/struct.ExprId.html [body owners]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/enum.BodyOwnerKind.html -The THIR lives in [`rustc_mir_build::thir`][thir-docs]. -To construct a [`thir::Expr`], -you can use the [`thir_body`] function, passing in the memory arena where the THIR -will be allocated. -Dropping this arena will result in the THIR being destroyed, -which is useful to keep peak memory in check. +The THIR lives in [`rustc_middle::thir`][thir-docs]. +To construct a [`thir::Expr`], you can use the [`thir_body`] query. +The THIR is freed after unsafety checking, to keep peak memory in check. Having a THIR representation of all bodies of a crate in memory at the same time would be very heavy. @@ -226,6 +223,6 @@ Thir { } ``` -[thir-docs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_build/thir/index.html +[thir-docs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/thir/index.html [`thir::Expr`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/thir/struct.Expr.html [`thir_body`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.thir_body From 1f6dc4dbe333ffa105b5f1982b40c78096cd0de2 Mon Sep 17 00:00:00 2001 From: The rustc-josh-sync Cronjob Bot Date: Mon, 5 Oct 2026 04:32:19 +0000 Subject: [PATCH 04/34] Prepare for merging from rust-lang/rust This updates the rust-version file to 260f1acad9d7f70b5b56a636a9dc5a7f76150417. --- src/doc/rustc-dev-guide/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/rust-version b/src/doc/rustc-dev-guide/rust-version index af092f4d3417d..271b3a644cfb8 100644 --- a/src/doc/rustc-dev-guide/rust-version +++ b/src/doc/rustc-dev-guide/rust-version @@ -1 +1 @@ -7d2cd0fbc092625ea371da704f15f80216d2220e +260f1acad9d7f70b5b56a636a9dc5a7f76150417 From a8b032f0b086080b02f8cd39bc9eb1827425ba35 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 5 Oct 2026 17:54:26 +0200 Subject: [PATCH 05/34] add type system invariant --- src/doc/rustc-dev-guide/src/solve/invariants.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/doc/rustc-dev-guide/src/solve/invariants.md b/src/doc/rustc-dev-guide/src/solve/invariants.md index 4a2c22fec83fe..3379f77626d58 100644 --- a/src/doc/rustc-dev-guide/src/solve/invariants.md +++ b/src/doc/rustc-dev-guide/src/solve/invariants.md @@ -74,6 +74,16 @@ Many of the currently known unsound issues end up relying on this invariant bein It is however very difficult to imagine a sound type system without this invariant, so the issue is that the invariant is broken, not that we incorrectly rely on it. +#### Successful normalization must not result in unconstrained inference variables ✅ + +If a normalization goal succeeds, it must not result in unconstrained type or const inference variables. This not being the case causes type equality to not be transitive. + +This requirement also has to hold for invalid code to avoid compiler ICE: +- this is subtly broken with the old solver: https://github.com/rust-lang/rust/issues/135122 +- and with both solvers for inherent associated types: https://github.com/rust-lang/rust/issues/163812 + +Also see for https://github.com/rust-lang/rust/issues/141713 an unsoundness where this goes wrong with builtin impls and lifetimes. + ### The type system is complete ❌ The type system is not complete. From 75b0be8f54ac2dd093082bb9b9dfaf65a981cbd7 Mon Sep 17 00:00:00 2001 From: Yilin Chen <1479826151@qq.com> Date: Wed, 7 Oct 2026 14:51:24 +0800 Subject: [PATCH 06/34] remove redundant unsafe --- library/core/src/hint.rs | 4 +- .../crates/core_arch/src/arm_shared/hints.rs | 42 +++++++++++++------ 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index 90326e649058b..616bdd9a97b7c 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -300,11 +300,11 @@ pub fn spin_loop() { all(target_feature = "v6", target_feature = "mclass"), ) ) => { - // SAFETY: the `cfg` attr ensures that we only execute this on arm + // The `cfg` attr ensures that we only execute this on arm // targets with support for the this feature. On ARMv6 in Thumb // mode, T2 is required (see Arm DDI0406C Section A8.8.427), // otherwise ARMv6-M or ARMv6K is enough - unsafe { crate::arch::arm::__yield() } + crate::arch::arm::__yield() } target_arch = "loongarch32" => crate::arch::loongarch32::ibar::<0>(), target_arch = "loongarch64" => crate::arch::loongarch64::ibar::<0>(), diff --git a/library/stdarch/crates/core_arch/src/arm_shared/hints.rs b/library/stdarch/crates/core_arch/src/arm_shared/hints.rs index ce64e8341e7eb..a531a0a632321 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/hints.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/hints.rs @@ -17,8 +17,11 @@ ))] #[inline(always)] #[unstable(feature = "stdarch_arm_hints", issue = "117218")] -pub unsafe fn __wfi() { - hint(HINT_WFI); +pub fn __wfi() { + // SAFETY: The right HINT_WFI constant is passed to the llvm intrinsic。 + unsafe { + hint(HINT_WFI); + } } /// Generates a WFE (wait for event) hint instruction, or nothing. @@ -36,8 +39,11 @@ pub unsafe fn __wfi() { ))] #[inline(always)] #[unstable(feature = "stdarch_arm_hints", issue = "117218")] -pub unsafe fn __wfe() { - hint(HINT_WFE); +pub fn __wfe() { + // SAFETY: The right HINT_WFE constant is passed to the llvm intrinsic。 + unsafe { + hint(HINT_WFE); + } } /// Generates a SEV (send a global event) hint instruction. @@ -54,8 +60,11 @@ pub unsafe fn __wfe() { ))] #[inline(always)] #[unstable(feature = "stdarch_arm_hints", issue = "117218")] -pub unsafe fn __sev() { - hint(HINT_SEV); +pub fn __sev() { + // SAFETY: The right HINT_SEV constant is passed to the llvm intrinsic。 + unsafe { + hint(HINT_SEV); + } } /// Generates a send a local event hint instruction. @@ -72,8 +81,11 @@ pub unsafe fn __sev() { ))] #[inline(always)] #[unstable(feature = "stdarch_arm_hints", issue = "117218")] -pub unsafe fn __sevl() { - hint(HINT_SEVL); +pub fn __sevl() { + // SAFETY: The right HINT_SEVL constant is passed to the llvm intrinsic。 + unsafe { + hint(HINT_SEVL); + } } /// Generates a YIELD hint instruction. @@ -94,8 +106,11 @@ pub unsafe fn __sevl() { ))] #[inline(always)] #[unstable(feature = "stdarch_arm_hints", issue = "117218")] -pub unsafe fn __yield() { - hint(HINT_YIELD); +pub fn __yield() { + // SAFETY: The right HINT_YIELD constant is passed to the llvm intrinsic。 + unsafe { + hint(HINT_YIELD); + } } /// Generates an unspecified no-op instruction. @@ -106,8 +121,11 @@ pub unsafe fn __yield() { /// will increase execution time. #[inline(always)] #[unstable(feature = "stdarch_arm_hints", issue = "117218")] -pub unsafe fn __nop() { - crate::arch::asm!("nop", options(nomem, nostack, preserves_flags)); +pub fn __nop() { + // SAFETY: `nop` performs no operation. + unsafe { + crate::arch::asm!("nop", options(nomem, nostack, preserves_flags)); + } } unsafe extern "llvm-intrinsic" { From 7243c36d71139aefc24c9c5f2834df0c7996a6ad Mon Sep 17 00:00:00 2001 From: The rustc-josh-sync Cronjob Bot Date: Sat, 10 Oct 2026 14:55:30 +0000 Subject: [PATCH 07/34] Prepare for merging from rust-lang/rust This updates the rust-version file to 5ec56e3902656f2460259fc3ac0f6e2255f94417. --- src/doc/rustc-dev-guide/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/rust-version b/src/doc/rustc-dev-guide/rust-version index 271b3a644cfb8..faf94e8aea8c9 100644 --- a/src/doc/rustc-dev-guide/rust-version +++ b/src/doc/rustc-dev-guide/rust-version @@ -1 +1 @@ -260f1acad9d7f70b5b56a636a9dc5a7f76150417 +5ec56e3902656f2460259fc3ac0f6e2255f94417 From ee3e2e70f6b3124c69eaf924364f13fc0a27d7da Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 10 Oct 2026 16:59:20 +0200 Subject: [PATCH 08/34] reflow src/compiler-debugging.md --- .../rustc-dev-guide/src/compiler-debugging.md | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/compiler-debugging.md b/src/doc/rustc-dev-guide/src/compiler-debugging.md index 3c355c0d3b972..7f9238cc2ed08 100644 --- a/src/doc/rustc-dev-guide/src/compiler-debugging.md +++ b/src/doc/rustc-dev-guide/src/compiler-debugging.md @@ -52,14 +52,14 @@ If this is not desirable, you can prevent the ICE file from being created with ` ## Getting a backtrace [getting-a-backtrace]: #getting-a-backtrace -When you have an ICE (panic in the compiler), you can set -`RUST_BACKTRACE=1` to get the stack trace of the `panic!` like in normal Rust programs. +When you have an ICE (panic in the compiler), +you can set `RUST_BACKTRACE=1` to get the stack trace of the `panic!` like in normal Rust programs. IIRC backtraces **don't work** on MinGW, sorry. If you have trouble or the backtraces are full of `unknown`, you might want to find some way to use Linux, Mac, or MSVC on Windows. -In the default configuration (without `debug` set to `true`), you don't have line numbers -enabled, so the backtrace looks like this: +In the default configuration (without `debug` set to `true`), you don't have line numbers enabled, +so the backtrace looks like this: ```text stack backtrace: @@ -104,19 +104,18 @@ These are unstable flags that are only enabled on nightly. Many of them are useful for debugging. To get a full listing of `-Z` flags, use `-Z help`. -One useful flag is `-Z verbose-internals`, which generally enables printing more -info that could be useful for debugging. +One useful flag is `-Z verbose-internals`, +which generally enables printing more info that could be useful for debugging. Right below you can find elaborate explainers on a selected few. ### Getting a backtrace for errors [getting-a-backtrace-for-errors]: #getting-a-backtrace-for-errors -If you want to get a backtrace to the point where the compiler emits an -error message, you can pass the `-Z treat-err-as-bug=n`, which will make -the compiler panic on the `nth` error. -If you leave off `=n`, the compiler will -assume `1` for `n` and thus panic on the first error it encounters. +If you want to get a backtrace to the point where the compiler emits an error message, +you can pass the `-Z treat-err-as-bug=n`, which will make the compiler panic on the `nth` error. +If you leave off `=n`, +the compiler will assume `1` for `n` and thus panic on the first error it encounters. For example: @@ -315,8 +314,8 @@ $ firefox maybe_init_suffix.pdf # Or your favorite pdf viewer ``` Graphviz also comes with a preprocessor program, -[`unflatten`](https://graphviz.org/docs/cli/unflatten/), that -sometimes helps making the outputs look less oddly spread out. +[`unflatten`](https://graphviz.org/docs/cli/unflatten/), +that sometimes helps making the outputs look less oddly spread out. It reads a dot file and outputs another dot file, so you can use it in a pipe, e.g: ``` @@ -398,8 +397,8 @@ Debugging the borrow checker has [its own chapter](borrow-check/debugging.md). ## Configuring CodeLLDB for debugging `rustc` If you are using VSCode, and have edited your `bootstrap.toml` to request debugging -level 1 or 2 for the parts of the code you're interested in, then you should be -able to use the [CodeLLDB] extension in VSCode to debug it. +level 1 or 2 for the parts of the code you're interested in, +then you should be able to use the [CodeLLDB] extension in VSCode to debug it. Here is a sample `launch.json` file, being used to run a stage 1 compiler direct from the directory where it is built (does not have to be "installed"): From 5c1fb39f5e5b16386925467f0aa499ced050d668 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 9 Oct 2026 18:18:45 +0200 Subject: [PATCH 09/34] Remove indirection for `Expr` in `Body` --- compiler/rustc_ast_lowering/src/item.rs | 2 +- .../src/diagnostics/conflict_errors.rs | 14 +++++++------- .../src/diagnostics/explain_borrow.rs | 4 ++-- .../src/diagnostics/move_errors.rs | 4 ++-- compiler/rustc_hir/src/hir.rs | 4 ++-- compiler/rustc_hir/src/intravisit.rs | 6 +++--- .../rustc_hir_analysis/src/check/region.rs | 6 +++--- compiler/rustc_hir_analysis/src/collect.rs | 2 +- compiler/rustc_hir_pretty/src/lib.rs | 2 +- compiler/rustc_hir_typeck/src/check.rs | 2 +- compiler/rustc_hir_typeck/src/demand.rs | 2 +- compiler/rustc_hir_typeck/src/expr.rs | 4 ++-- .../rustc_hir_typeck/src/expr_use_visitor.rs | 2 +- compiler/rustc_hir_typeck/src/fallback.rs | 2 +- compiler/rustc_hir_typeck/src/inline_asm.rs | 2 +- compiler/rustc_hir_typeck/src/lib.rs | 4 ++-- compiler/rustc_hir_typeck/src/upvar.rs | 2 +- compiler/rustc_lint/src/async_closures.rs | 2 +- compiler/rustc_lint/src/context.rs | 2 +- .../rustc_lint/src/for_loops_over_fallibles.rs | 2 +- compiler/rustc_lint/src/late.rs | 2 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 2 +- compiler/rustc_mir_build/src/thir/cx/mod.rs | 2 +- .../src/coverage/hir_info.rs | 7 +++++-- compiler/rustc_passes/src/input_stats.rs | 2 +- .../error_reporting/infer/need_type_info.rs | 4 ++-- .../traits/fulfillment_errors.rs | 2 +- .../src/error_reporting/traits/suggestions.rs | 18 +++++++++--------- compiler/rustc_ty_utils/src/opaque_types.rs | 2 +- src/librustdoc/visit_ast.rs | 2 +- .../clippy_lints/src/fallible_impl_from.rs | 2 +- .../src/loops/needless_range_loop.rs | 2 +- .../clippy_lints/src/needless_for_each.rs | 2 +- .../clippy/clippy_lints/src/ptr/ptr_arg.rs | 2 +- .../src/lint_without_lint_pass.rs | 2 +- tests/ui/stats/input-stats.stderr | 4 ++-- 36 files changed, 65 insertions(+), 62 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 9cea3519cf94e..babca94628891 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1216,7 +1216,7 @@ impl<'hir> LoweringContext<'_, 'hir> { params: &'hir [hir::Param<'hir>], value: hir::Expr<'hir>, ) -> hir::BodyId { - let body = hir::Body { params, value: self.arena.alloc(value) }; + let body = hir::Body { params, value }; let id = body.id(); assert_eq!(id.hir_id.owner, self.curr_owner.owner_id()); self.curr_owner.bodies.push((id.hir_id.local_id, self.arena.alloc(body))); diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 2f8ff159ceb0a..bd8d69bceed97 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -408,7 +408,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { } let tcx = self.infcx.tcx; if let Some(body) = tcx.hir_maybe_body_owned_by(self.mir_def_id()) { - let expr = body.value; + let expr = &body.value; let place = &self.move_data.move_paths[mpi].place; let span = place.as_local().map(|local| self.body.local_decls[local].source_info.span); let mut finder = ExpressionFinder { @@ -2134,7 +2134,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { let mut expr_finder = FindUselessClone::new(tcx, self.mir_def_id()); - let body = tcx.hir_body(body_id).value; + let body = &tcx.hir_body(body_id).value; expr_finder.visit_expr(body); struct Holds<'tcx> { @@ -2323,7 +2323,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { let tcx = self.infcx.tcx; let body_id = tcx.hir_node(self.mir_hir_id()).body_id()?; let mut expr_finder = FindExprBySpan::new(span, tcx); - expr_finder.visit_expr(tcx.hir_body(body_id).value); + expr_finder.visit_expr(&tcx.hir_body(body_id).value); expr_finder.result } @@ -2554,7 +2554,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { } } let mut finder = ExprFinder { tcx, expr_span: span, issue_span, .. }; - finder.visit_expr(tcx.hir_body(body_id).value); + finder.visit_expr(&tcx.hir_body(body_id).value); if let Some(body_expr) = finder.body_expr && let Some(loop_span) = finder.loop_span @@ -2705,7 +2705,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { // Get the body the error happens in let Some(body_id) = tcx.hir_node(self.mir_hir_id()).body_id() else { return }; - let body_expr = tcx.hir_body(body_id).value; + let body_expr = &tcx.hir_body(body_id).value; struct ClosureFinder<'hir> { tcx: TyCtxt<'hir>, @@ -2809,7 +2809,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { } let mut finder = VariableUseFinder { local_id, spans: Vec::new() }; - finder.visit_expr(tcx.hir_body(closure.body).value); + finder.visit_expr(&tcx.hir_body(closure.body).value); spans = finder.spans; } else { @@ -4747,7 +4747,7 @@ fn find_for_loop_span<'hir>( } } let mut finder = ExprFinder { tcx, issue_span, result: None }; - finder.visit_expr(tcx.hir_body(body_id).value); + finder.visit_expr(&tcx.hir_body(body_id).value); finder.result } diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 2bc361968a761..706a60d84f402 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -73,7 +73,7 @@ impl<'tcx> BorrowExplanation<'tcx> { { let body = tcx.hir_body(body_id); let mut expr_finder = FindExprBySpan::new(span, tcx); - expr_finder.visit_expr(body.value); + expr_finder.visit_expr(&body.value); if let Some(mut expr) = expr_finder.result { while let hir::ExprKind::AddrOf(_, _, inner) | hir::ExprKind::Unary(hir::UnOp::Deref, inner) @@ -308,7 +308,7 @@ impl<'tcx> BorrowExplanation<'tcx> { && let hir_body = tcx.hir_body(body_id) && let mut expr_finder = (FindLetExpr { span: old, result: None, tcx }) && let Some((let_expr_span, let_expr_pat, let_expr_init)) = { - expr_finder.visit_expr(hir_body.value); + expr_finder.visit_expr(&hir_body.value); expr_finder.result } && !let_expr_span.contains(new) diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 4d65410455118..c78c91e9ce0be 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -339,7 +339,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { // Find the closure that captured the binding. let mut expr_finder = FindExprBySpan::new(args_span, tcx); expr_finder.include_closures = true; - expr_finder.visit_expr(tcx.hir_body(body_id).value); + expr_finder.visit_expr(&tcx.hir_body(body_id).value); let Some(closure_expr) = expr_finder.result else { return }; let ExprKind::Closure(closure) = closure_expr.kind else { return }; // We'll only suggest cloning the binding if it's a `move` closure. @@ -349,7 +349,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { let use_span = use_spans.var_or_use(); let mut expr_finder = FindExprBySpan::new(use_span, tcx); expr_finder.include_closures = true; - expr_finder.visit_expr(tcx.hir_body(body_id).value); + expr_finder.visit_expr(&tcx.hir_body(body_id).value); let Some(use_expr) = expr_finder.result else { return }; let parent = tcx.parent_hir_node(use_expr.hir_id); if let Node::Expr(expr) = parent diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index ceb7f38c2a416..bb9f44fbdbb24 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1957,7 +1957,7 @@ pub struct BodyId { #[derive(Debug, Clone, Copy, StableHash)] pub struct Body<'hir> { pub params: &'hir [Param<'hir>], - pub value: &'hir Expr<'hir>, + pub value: Expr<'hir>, } impl<'hir> Body<'hir> { @@ -5275,7 +5275,7 @@ mod size_asserts { use super::*; // tidy-alphabetical-start static_assert_size!(Block<'_>, 48); - static_assert_size!(Body<'_>, 24); + static_assert_size!(Body<'_>, 80); static_assert_size!(Expr<'_>, 64); static_assert_size!(ExprKind<'_>, 48); static_assert_size!(FnDecl<'_>, 40); diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index b404d1708b85b..5d02c895f9a8f 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -296,7 +296,7 @@ pub trait Visitor<'v>: Sized { walk_item(self, i) } - fn visit_body(&mut self, b: &Body<'v>) -> Self::Result { + fn visit_body(&mut self, b: &'v Body<'v>) -> Self::Result { walk_body(self, b) } @@ -662,10 +662,10 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V:: V::Result::output() } -pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &Body<'v>) -> V::Result { +pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &'v Body<'v>) -> V::Result { let Body { params, value } = body; walk_list!(visitor, visit_param, *params); - visitor.visit_expr(*value) + visitor.visit_expr(value) } pub fn walk_ident<'v, V: Visitor<'v>>(visitor: &mut V, ident: Ident) -> V::Result { diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 96acfd2f97177..b4be6c3fd5d01 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -762,7 +762,7 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> { resolve_block(self, b, false); } - fn visit_body(&mut self, body: &hir::Body<'tcx>) { + fn visit_body(&mut self, body: &'tcx hir::Body<'tcx>) { let body_id = body.id(); let owner_id = self.tcx.hir_body_owner_def_id(body_id); @@ -783,7 +783,7 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> { } // The body of the every fn is a root scope. - resolve_expr(this, body.value, true); + resolve_expr(this, &body.value, true); } else { // All bodies have an outer temporary drop scope, but temporaries // and `super let` bindings in constant initializers may be extended @@ -808,7 +808,7 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> { local_id: body.value.hir_id.local_id, data: ScopeData::Destruction, }); - resolve_local(this, None, Some(body.value), LetKind::Regular); + resolve_local(this, None, Some(&body.value), LetKind::Regular); } }) } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index b81b7aafb8c1d..3583606672dab 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1705,7 +1705,7 @@ fn coroutine_for_closure(tcx: TyCtxt<'_>, def_id: LocalDefId) -> DefId { bug!() }; - let &hir::Expr { + let hir::Expr { kind: hir::ExprKind::Closure(&rustc_hir::Closure { def_id, diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index d8c57bfbdb56b..a697c919f1202 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -63,7 +63,7 @@ impl PpAnn for &dyn rustc_hir::intravisit::HirTyCtxt<'_> { Nested::TraitItem(id) => state.print_trait_item(self.hir_trait_item(id)), Nested::ImplItem(id) => state.print_impl_item(self.hir_impl_item(id)), Nested::ForeignItem(id) => state.print_foreign_item(self.hir_foreign_item(id)), - Nested::Body(id) => state.print_expr(self.hir_body(id).value), + Nested::Body(id) => state.print_expr(&self.hir_body(id).value), Nested::BodyParamPat(id, i) => state.print_pat(self.hir_body(id).params[i].pat), } } diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index 8061e522f43aa..912c2b72a907a 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -127,7 +127,7 @@ pub(super) fn check_fn<'a, 'tcx>( } fcx.is_whole_body.set(true); - fcx.check_return_or_body_tail(body.value, false); + fcx.check_return_or_body_tail(&body.value, false); // Finalize the return check by taking the LUB of the return types // we saw and assigning it to the expected return type. This isn't diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index e1ad43f0c00c9..36e0a22c76133 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -333,7 +333,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut expr_finder = FindExprs { hir_id: local_hir_id, uses: init.into_iter().collect() }; let body = self.tcx.hir_body_owned_by(self.body_def_id); - expr_finder.visit_expr(body.value); + expr_finder.visit_expr(&body.value); // Replaces all of the variables in the given type with a fresh inference variable. let mut fudger = BottomUpFolder { diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index a301cb6a397d9..098990e8da2bb 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1723,7 +1723,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let def_id = block.def_id; let fcx = FnCtxt::new(self, self.param_env, def_id); - let ty = fcx.check_expr_with_expectation(body.value, expected); + let ty = fcx.check_expr_with_expectation(&body.value, expected); fcx.require_type_is_sized(ty, body.value.span, ObligationCauseCode::SizedConstOrStatic); fcx.write_ty(block.hir_id, ty); ty @@ -3730,7 +3730,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let body = self.tcx.hir_body(anon_const.body); let fcx = FnCtxt::new(self, self.param_env, anon_const.def_id); - let ty = fcx.check_expr(body.value); + let ty = fcx.check_expr(&body.value); let target_ty = match self.structurally_resolve_type(body.value.span, ty).kind() { ty::FnDef(..) => { diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 0c49ec002671d..3186533ad4b5f 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -316,7 +316,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx self.walk_pat(¶m_place, param.pat, false)?; } - self.consume_expr(body.value)?; + self.consume_expr(&body.value)?; Ok(()) } diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index 8dd38d2eaa407..6459948143fde 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -341,7 +341,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> { let reachable_vids = graph::depth_first_search_as_undirected(coercions, vid).collect(); AnnotateUnitFallbackVisitor { reachable_vids, fcx: self } - .visit_expr(body.value) + .visit_expr(&body.value) .break_value() }) .collect(); diff --git a/compiler/rustc_hir_typeck/src/inline_asm.rs b/compiler/rustc_hir_typeck/src/inline_asm.rs index b3c7071199963..597107f94162d 100644 --- a/compiler/rustc_hir_typeck/src/inline_asm.rs +++ b/compiler/rustc_hir_typeck/src/inline_asm.rs @@ -584,7 +584,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { } } hir::InlineAsmOperand::Const { anon_const } => { - let ty = self.expr_ty(self.tcx().hir_body(anon_const.body).value); + let ty = self.expr_ty(&self.tcx().hir_body(anon_const.body).value); match ty.kind() { ty::Error(_) => {} _ if ty.is_integral() => {} diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 2945a6b3b5136..67a4c63da4f93 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -133,7 +133,7 @@ fn typeck_with_inspect<'tcx>( if let hir::Node::Item(hir::Item { kind: hir::ItemKind::GlobalAsm { .. }, .. }) = node { // Check the fake body of a global ASM. There's not much to do here except // for visit the asm expr of the body. - let ty = fcx.check_expr(body.value); + let ty = fcx.check_expr(&body.value); fcx.write_ty(id, ty); } else if let Some(hir::FnSig { header, decl, span: _ }) = node.fn_sig() { let fn_sig = if decl.output.is_suggestable_infer_ty().is_some() { @@ -204,7 +204,7 @@ fn typeck_with_inspect<'tcx>( ); } - fcx.check_expr_coercible_to_type_or_error(body.value, expected_type, None, |err, _| { + fcx.check_expr_coercible_to_type_or_error(&body.value, expected_type, None, |err, _| { extend_err_with_const_context(err, tcx, node, expected_type); }); diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 98155d9a8d5ef..9cde49aac0ffc 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -575,7 +575,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // for the inner coroutine may actually be more restrictive. if infer_kind { let ty::Coroutine(_, coroutine_args) = - *self.typeck_results.borrow().expr_ty(body.value).kind() + *self.typeck_results.borrow().expr_ty(&body.value).kind() else { bug!(); }; diff --git a/compiler/rustc_lint/src/async_closures.rs b/compiler/rustc_lint/src/async_closures.rs index 36ab33b44c0ff..d9733753a33e8 100644 --- a/compiler/rustc_lint/src/async_closures.rs +++ b/compiler/rustc_lint/src/async_closures.rs @@ -68,7 +68,7 @@ impl<'tcx> LateLintPass<'tcx> for AsyncClosureUsage { return; }; - let mut body = cx.tcx.hir_body(body).value; + let mut body = &cx.tcx.hir_body(body).value; // Only peel blocks that have no expressions. while let hir::ExprKind::Block(&hir::Block { stmts: [], expr: Some(tail), .. }, None) = diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 15c60c920ce37..87802a2afb53f 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -924,7 +924,7 @@ impl<'tcx> LateContext<'tcx> { hir::Node::Item(item) => match item.kind { // FIXME(mgca): figure out how to handle ConstArgKind::Path (or don't but add warning in docs here) hir::ItemKind::Const(.., hir::ConstItemRhs::Body(body_id)) - | hir::ItemKind::Static(.., body_id) => Some(self.tcx.hir_body(body_id).value), + | hir::ItemKind::Static(.., body_id) => Some(&self.tcx.hir_body(body_id).value), _ => None, }, _ => None, diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs index bb0f2a2793ab8..71cab7125695a 100644 --- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs +++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs @@ -165,7 +165,7 @@ fn suggest_question_mark<'tcx>( // Check that the function/closure/constant we are in has a `Result` type. // Otherwise suggesting using `?` may not be a good idea. { - let ty = cx.typeck_results().expr_ty(cx.tcx.hir_body(body_id).value); + let ty = cx.typeck_results().expr_ty(&cx.tcx.hir_body(body_id).value); let ty::Adt(ret_adt, ..) = ty.kind() else { return false }; if !cx.tcx.is_diagnostic_item(sym::Result, ret_adt.did()) { return false; diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index 93ce4118c0ab7..c932a19eb33d9 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -122,7 +122,7 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas }); } - fn visit_body(&mut self, body: &hir::Body<'tcx>) { + fn visit_body(&mut self, body: &'tcx hir::Body<'tcx>) { lint_callback!(self, check_body, body); hir_visit::walk_body(self, body); lint_callback!(self, check_body_post, body); diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 38dbf8d428a20..f9f4c52b79d3b 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -2839,7 +2839,7 @@ pub(crate) fn provide(providers: &mut Providers) { /// use a different method for pretty-printing. Ideally this function /// should only ever be used as a fallback. pub fn rendered_const<'tcx>(tcx: TyCtxt<'tcx>, body: &hir::Body<'_>, def_id: LocalDefId) -> String { - let value = body.value; + let value = &body.value; #[derive(PartialEq, Eq)] enum Classification { diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index ad1227bb51df0..9ee80e229ed71 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -53,7 +53,7 @@ pub(crate) fn thir_body<'tcx>( } } - let expr = cx.mirror_expr(body.value); + let expr = cx.mirror_expr(&body.value); Ok((tcx.alloc_steal_thir(cx.thir), expr)) } diff --git a/compiler/rustc_mir_transform/src/coverage/hir_info.rs b/compiler/rustc_mir_transform/src/coverage/hir_info.rs index d863aa4c4b80e..5bb102f8c3223 100644 --- a/compiler/rustc_mir_transform/src/coverage/hir_info.rs +++ b/compiler/rustc_mir_transform/src/coverage/hir_info.rs @@ -99,7 +99,10 @@ fn hash_mir_source<'tcx>(tcx: TyCtxt<'tcx>, hir_body: &'tcx hir::Body<'tcx>) -> .as_u64() } -fn extract_hole_spans_from_hir<'tcx>(tcx: TyCtxt<'tcx>, hir_body: &hir::Body<'tcx>) -> Vec { +fn extract_hole_spans_from_hir<'tcx>( + tcx: TyCtxt<'tcx>, + hir_body: &'tcx hir::Body<'tcx>, +) -> Vec { struct HolesVisitor<'tcx> { tcx: TyCtxt<'tcx>, hole_spans: Vec, @@ -156,7 +159,7 @@ fn extract_hole_spans_from_hir<'tcx>(tcx: TyCtxt<'tcx>, hir_body: &hir::Body<'tc fn find_nodes_to_ignore<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, - hir_body: &hir::Body<'tcx>, + hir_body: &'tcx hir::Body<'tcx>, ) -> FxHashSet { /// Top-level visitor used by [`find_nodes_to_ignore`]. struct FindNodesToIgnoreVisitor<'tcx> { diff --git a/compiler/rustc_passes/src/input_stats.rs b/compiler/rustc_passes/src/input_stats.rs index d8524efb35bc2..9392469251848 100644 --- a/compiler/rustc_passes/src/input_stats.rs +++ b/compiler/rustc_passes/src/input_stats.rs @@ -272,7 +272,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { hir_visit::walk_item(self, i) } - fn visit_body(&mut self, b: &hir::Body<'v>) { + fn visit_body(&mut self, b: &'v hir::Body<'v>) { self.record("Body", None, b); hir_visit::walk_body(self, b); } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs index e4cf2a40bd3fc..a2c2b5f82e6ef 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs @@ -522,7 +522,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if let Some(body) = self.tcx.hir_maybe_body_owned_by(self.tcx.typeck_root_def_id_local(body_def_id)) { - let expr = body.value; + let expr = &body.value; local_visitor.visit_expr(expr); body_from_expansion = body.value.span.from_expansion(); } @@ -1380,7 +1380,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> { /// For closures, we first visit the parameters and then the content, /// as we prefer those. - fn visit_body(&mut self, body: &Body<'tcx>) { + fn visit_body(&mut self, body: &'tcx Body<'tcx>) { for param in body.params { debug!( "param: span {:?}, ty_span {:?}, pat.span {:?}", 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 1614899ece03d..d1d999a477a65 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 @@ -4080,7 +4080,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } else if let ty::AliasConstKind::Anon { def_id } = alias_const.kind && let Some(local_def_id) = def_id.as_local() && let Some(local_body) = self.tcx.hir_maybe_body_owned_by(local_def_id) - && expr_needs_parens(local_body.value) + && expr_needs_parens(&local_body.value) { format!("[(); ({snippet}) as usize]:") } else { diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index a2aae724228ba..ce0c498c06ea6 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -1271,7 +1271,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { parenthesized_cast(span) } else if let Some(body) = self.tcx.hir_maybe_body_owned_by(obligation.cause.body_def_id) { let mut expr_finder = FindExprBySpan::new(span, self.tcx); - expr_finder.visit_expr(body.value); + expr_finder.visit_expr(&body.value); if let Some(expr) = expr_finder.result && let hir::ExprKind::AddrOf(_, _, expr) = expr.kind { @@ -1311,7 +1311,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let Some(body) = self.tcx.hir_maybe_body_owned_by(obligation.cause.body_def_id) else { return; }; - expr_finder.visit_expr(body.value); + expr_finder.visit_expr(&body.value); let Some(expr) = expr_finder.result else { return; }; @@ -1641,7 +1641,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }; let mut expr_finder = FindExprBySpan::new(obligation.cause.span, self.tcx); - expr_finder.visit_expr(body.value); + expr_finder.visit_expr(&body.value); let Some(expr) = expr_finder.result else { return true; }; @@ -2018,7 +2018,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { return false; }; let mut expr_finder = FindExprBySpan::new(span, self.tcx); - expr_finder.visit_expr(body.value); + expr_finder.visit_expr(&body.value); if let Some(ty) = expr_finder.ty_result { if let hir::Node::Expr(expr) = self.tcx.parent_hir_node(ty.hir_id) @@ -2243,7 +2243,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let Some(body) = self.tcx.hir_maybe_body_owned_by(obligation.cause.body_def_id) else { return false; }; - expr_finder.visit_expr(body.value); + expr_finder.visit_expr(&body.value); let mut maybe_suggest = |suggested_ty, count, suggestions| { // Remapping bound vars here let trait_pred_and_suggested_ty = @@ -2783,7 +2783,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }; let body = self.tcx.hir_body(body_id); let mut expr_finder = FindExprBySpan::new(span, self.tcx); - expr_finder.visit_expr(body.value); + expr_finder.visit_expr(&body.value); let Some(expr) = expr_finder.result else { return; }; @@ -5215,7 +5215,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { && let Some(body) = self.tcx.hir_maybe_body_owned_by(obligation.cause.body_def_id) && let Some(expr) = { let mut finder = FindExprBySpan::new(span, self.tcx); - finder.visit_expr(body.value); + finder.visit_expr(&body.value); finder.result } && let hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, borrowed) = @@ -5659,7 +5659,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { { expr } else { - body.value + &body.value }; if let hir::ExprKind::MethodCall(path_segment, rcvr, [], span) = expr.kind && path_segment.ident.name == sym::clone @@ -6935,7 +6935,7 @@ impl<'v> Visitor<'v> for ReturnsVisitor<'v> { } } - fn visit_body(&mut self, body: &hir::Body<'v>) { + fn visit_body(&mut self, body: &'v hir::Body<'v>) { assert!(!self.in_block_tail); self.in_block_tail = true; hir::intravisit::walk_body(self, body); diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index 5415662154daf..96edc32145111 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -68,7 +68,7 @@ impl<'tcx> OpaqueTypeCollector<'tcx> { let Some(body) = self.tcx.hir_maybe_body_owned_by(self.item) else { return; }; - let body = body.value; + let body = &body.value; struct TaitInBodyFinder<'a, 'tcx> { collector: &'a mut OpaqueTypeCollector<'tcx>, } diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index df55626ffb05d..78b602e25dce8 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -720,7 +720,7 @@ impl<'tcx> Visitor<'tcx> for RustdocVisitor<'_, 'tcx> { // Unneeded. } - fn visit_body(&mut self, b: &hir::Body<'tcx>) { + fn visit_body(&mut self, b: &'tcx hir::Body<'tcx>) { let prev = mem::replace(&mut self.inside_body, true); walk_body(self, b); self.inside_body = prev; diff --git a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs index 99137c8591e47..095846ab5dfb5 100644 --- a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs +++ b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs @@ -105,7 +105,7 @@ fn lint_impl_body(cx: &LateContext<'_>, item_def_id: hir::OwnerId, impl_span: Sp typeck_results: cx.tcx.typeck(impl_item_def_id), result: Vec::new(), }; - fpu.visit_expr(body.value); + fpu.visit_expr(&body.value); // if we've found one, lint if !fpu.result.is_empty() { diff --git a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs index fb648050439b9..ee9f26b7961f8 100644 --- a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs @@ -450,7 +450,7 @@ impl<'tcx> Visitor<'tcx> for VarVisitor<'_, 'tcx> { }, ExprKind::Closure(&Closure { body, .. }) => { let body = self.cx.tcx.hir_body(body); - self.visit_expr(body.value); + self.visit_expr(&body.value); }, _ => walk_expr(self, expr), } diff --git a/src/tools/clippy/clippy_lints/src/needless_for_each.rs b/src/tools/clippy/clippy_lints/src/needless_for_each.rs index 13a3c99274d5f..ff61edbd26ce7 100644 --- a/src/tools/clippy/clippy_lints/src/needless_for_each.rs +++ b/src/tools/clippy/clippy_lints/src/needless_for_each.rs @@ -101,7 +101,7 @@ fn check_expr(cx: &LateContext<'_>, expr: &Expr<'_>, outer_span: Span) { } let mut ret_collector = RetCollector::default(); - ret_collector.visit_expr(body.value); + ret_collector.visit_expr(&body.value); // Skip the lint if `return` is used in `Loop` in order not to suggest using `'label`. if ret_collector.ret_in_loop { diff --git a/src/tools/clippy/clippy_lints/src/ptr/ptr_arg.rs b/src/tools/clippy/clippy_lints/src/ptr/ptr_arg.rs index b5fcc10f613ee..96ab0345db0e0 100644 --- a/src/tools/clippy/clippy_lints/src/ptr/ptr_arg.rs +++ b/src/tools/clippy/clippy_lints/src/ptr/ptr_arg.rs @@ -449,7 +449,7 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &Body<'tcx>, args: &[ results, skip_count, }; - v.visit_expr(body.value); + v.visit_expr(&body.value); v.results } diff --git a/src/tools/clippy/clippy_lints_internal/src/lint_without_lint_pass.rs b/src/tools/clippy/clippy_lints_internal/src/lint_without_lint_pass.rs index 9eba3834d0eb9..f21e588a893d8 100644 --- a/src/tools/clippy/clippy_lints_internal/src/lint_without_lint_pass.rs +++ b/src/tools/clippy/clippy_lints_internal/src/lint_without_lint_pass.rs @@ -162,7 +162,7 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass { .owner_id .def_id, ); - collector.visit_expr(body.value); + collector.visit_expr(&body.value); } } } diff --git a/tests/ui/stats/input-stats.stderr b/tests/ui/stats/input-stats.stderr index 420b01102e41e..45c42dd89ced7 100644 --- a/tests/ui/stats/input-stats.stderr +++ b/tests/ui/stats/input-stats.stderr @@ -94,6 +94,7 @@ hir-stats GenericParam 400 (NN.N%) 5 80 hir-stats Block 288 (NN.N%) 6 48 hir-stats GenericBound 256 (NN.N%) 4 64 hir-stats - Trait 256 (NN.N%) 4 +hir-stats Body 240 (NN.N%) 3 80 hir-stats Attribute 160 (NN.N%) 4 40 hir-stats Variant 144 (NN.N%) 2 72 hir-stats GenericArgs 144 (NN.N%) 3 48 @@ -107,7 +108,6 @@ hir-stats Arm 80 (NN.N%) 2 40 hir-stats WherePredicate 72 (NN.N%) 3 24 hir-stats - BoundPredicate 72 (NN.N%) 3 hir-stats InlineAsm 72 (NN.N%) 1 72 -hir-stats Body 72 (NN.N%) 3 24 hir-stats Param 64 (NN.N%) 2 32 hir-stats Local 64 (NN.N%) 1 64 hir-stats GenericArg 64 (NN.N%) 4 16 @@ -120,5 +120,5 @@ hir-stats TraitItemId 8 (NN.N%) 2 4 hir-stats ImplItemId 8 (NN.N%) 2 4 hir-stats ForeignItemId 4 (NN.N%) 1 4 hir-stats ---------------------------------------------------------------- -hir-stats Total 8_592 172 +hir-stats Total 8_760 172 hir-stats ================================================================ From 319d43156dc59b68e1bf9fbdc152af7055e05143 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sat, 10 Oct 2026 17:03:35 +0200 Subject: [PATCH 10/34] Fix clippy --- compiler/rustc_lint/src/passes.rs | 4 ++-- .../clippy/clippy_lints/src/async_yields_async.rs | 4 ++-- .../clippy/clippy_lints/src/attrs/inline_always.rs | 2 +- src/tools/clippy/clippy_lints/src/booleans.rs | 2 +- src/tools/clippy/clippy_lints/src/casts/mod.rs | 2 +- .../clippy_lints/src/casts/needless_type_cast.rs | 8 ++++---- .../clippy_lints/src/cognitive_complexity.rs | 2 +- .../clippy_lints/src/collection_is_never_read.rs | 2 +- .../clippy_lints/src/default_numeric_fallback.rs | 2 +- .../clippy/clippy_lints/src/doc/missing_headers.rs | 2 +- src/tools/clippy/clippy_lints/src/eta_reduction.rs | 6 +++--- .../clippy/clippy_lints/src/from_over_into.rs | 2 +- .../clippy/clippy_lints/src/functions/must_use.rs | 2 +- .../src/functions/not_unsafe_ptr_arg_deref.rs | 2 +- .../clippy_lints/src/functions/ref_option.rs | 2 +- .../clippy/clippy_lints/src/implicit_hasher.rs | 2 +- .../clippy/clippy_lints/src/implicit_return.rs | 6 +++--- src/tools/clippy/clippy_lints/src/infinite_iter.rs | 2 +- src/tools/clippy/clippy_lints/src/lifetimes.rs | 2 +- .../clippy/clippy_lints/src/loops/infinite_loop.rs | 2 +- .../clippy/clippy_lints/src/loops/never_loop.rs | 4 ++-- .../src/loops/unused_enumerate_index.rs | 2 +- .../src/loops/while_let_on_iterator.rs | 2 +- .../clippy_lints/src/macro_metavars_in_unsafe.rs | 2 +- .../clippy/clippy_lints/src/manual_noop_waker.rs | 2 +- .../clippy_lints/src/manual_option_as_slice.rs | 2 +- src/tools/clippy/clippy_lints/src/manual_pop_if.rs | 6 +++--- .../clippy_lints/src/matches/manual_filter.rs | 2 +- .../src/matches/match_single_binding.rs | 2 +- .../src/methods/bind_instead_of_map.rs | 2 +- .../clippy/clippy_lints/src/methods/filter_map.rs | 6 +++--- .../src/methods/filter_map_bool_then.rs | 4 ++-- .../clippy_lints/src/methods/format_collect.rs | 2 +- .../clippy/clippy_lints/src/methods/iter_filter.rs | 2 +- .../src/methods/iter_overeager_cloned.rs | 2 +- .../src/methods/lines_filter_map_ok.rs | 2 +- .../clippy_lints/src/methods/manual_inspect.rs | 2 +- .../src/methods/manual_is_variant_and.rs | 2 +- .../clippy/clippy_lints/src/methods/map_clone.rs | 2 +- src/tools/clippy/clippy_lints/src/methods/mod.rs | 2 +- .../src/methods/needless_character_iteration.rs | 2 +- .../src/methods/option_as_ref_deref.rs | 2 +- .../clippy_lints/src/methods/option_map_or_none.rs | 2 +- .../src/methods/result_map_or_else_none.rs | 2 +- .../clippy_lints/src/methods/return_and_then.rs | 2 +- .../clippy_lints/src/methods/suspicious_map.rs | 4 ++-- .../src/methods/unnecessary_filter_map.rs | 12 ++++++------ .../clippy_lints/src/methods/unnecessary_fold.rs | 4 ++-- .../clippy_lints/src/methods/unnecessary_map_or.rs | 2 +- .../src/methods/unnecessary_sort_by.rs | 2 +- .../clippy_lints/src/methods/useless_asref.rs | 2 +- .../src/missing_asserts_for_indexing.rs | 2 +- .../src/multiple_unsafe_ops_per_block.rs | 2 +- .../clippy/clippy_lints/src/non_canonical_impls.rs | 2 +- .../clippy/clippy_lints/src/non_copy_const.rs | 4 ++-- .../clippy/clippy_lints/src/panic_in_result_fn.rs | 2 +- src/tools/clippy/clippy_lints/src/ptr/mod.rs | 2 +- .../clippy/clippy_lints/src/ptr/mut_from_ref.rs | 4 ++-- src/tools/clippy/clippy_lints/src/ptr/ptr_arg.rs | 4 ++-- .../clippy_lints/src/redundant_async_block.rs | 2 +- .../clippy_lints/src/redundant_closure_call.rs | 14 +++++++------- .../clippy_lints/src/returns/needless_return.rs | 2 +- .../returns/needless_return_with_question_mark.rs | 2 +- .../src/significant_drop_tightening.rs | 2 +- .../clippy/clippy_lints/src/single_option_map.rs | 2 +- .../clippy/clippy_lints/src/string_patterns.rs | 2 +- .../clippy_lints/src/suspicious_trait_impl.rs | 2 +- .../clippy_lints/src/transmute/transmuting_null.rs | 2 +- .../clippy_lints/src/tuple_array_conversions.rs | 2 +- .../clippy_lints/src/unconditional_recursion.rs | 2 +- .../clippy_lints/src/unnecessary_literal_bound.rs | 2 +- .../clippy/clippy_lints/src/unnecessary_wraps.rs | 2 +- src/tools/clippy/clippy_lints/src/unused_self.rs | 2 +- src/tools/clippy/clippy_lints/src/utils/author.rs | 4 ++-- .../clippy/clippy_utils/src/check_proc_macro.rs | 4 ++-- src/tools/clippy/clippy_utils/src/consts.rs | 8 ++++---- src/tools/clippy/clippy_utils/src/hir_utils.rs | 10 +++++----- src/tools/clippy/clippy_utils/src/lib.rs | 4 ++-- src/tools/clippy/clippy_utils/src/visitors.rs | 2 +- 79 files changed, 120 insertions(+), 120 deletions(-) diff --git a/compiler/rustc_lint/src/passes.rs b/compiler/rustc_lint/src/passes.rs index 98ab44c37e26a..30a81f3c5f3ef 100644 --- a/compiler/rustc_lint/src/passes.rs +++ b/compiler/rustc_lint/src/passes.rs @@ -7,8 +7,8 @@ macro_rules! late_lint_methods { ($macro:path, $args:tt) => ( // `_post` methods are called *after* recursing into the node. $macro!($args, [ - fn check_body(a: &rustc_hir::Body<'tcx>); - fn check_body_post(a: &rustc_hir::Body<'tcx>); + fn check_body(a: &'tcx rustc_hir::Body<'tcx>); + fn check_body_post(a: &'tcx rustc_hir::Body<'tcx>); fn check_crate(); fn check_crate_post(); fn check_mod(a: &'tcx rustc_hir::Mod<'tcx>, b: rustc_span::def_id::LocalModId); diff --git a/src/tools/clippy/clippy_lints/src/async_yields_async.rs b/src/tools/clippy/clippy_lints/src/async_yields_async.rs index c13818363640e..1d2fc60abf4c2 100644 --- a/src/tools/clippy/clippy_lints/src/async_yields_async.rs +++ b/src/tools/clippy/clippy_lints/src/async_yields_async.rs @@ -63,12 +63,12 @@ impl<'tcx> LateLintPass<'tcx> for AsyncYieldsAsync { // XXXkhuey maybe we should? return; }, - CoroutineSource::Block => cx.tcx.hir_body(*body_id).value, + CoroutineSource::Block => &cx.tcx.hir_body(*body_id).value, CoroutineSource::Closure => { // Like `async fn`, async closures are wrapped in an additional block // to move all of the closure's arguments into the future. - let async_closure_body = cx.tcx.hir_body(*body_id).value; + let async_closure_body = &cx.tcx.hir_body(*body_id).value; let ExprKind::Block(block, _) = async_closure_body.kind else { return; }; diff --git a/src/tools/clippy/clippy_lints/src/attrs/inline_always.rs b/src/tools/clippy/clippy_lints/src/attrs/inline_always.rs index fd03ec47da543..fc7a3b9b335e5 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/inline_always.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/inline_always.rs @@ -13,7 +13,7 @@ pub(super) fn check(cx: &LateContext<'_>, span: Span, name: Symbol, attrs: &[Att } if let Some(span) = find_attr!(attrs, Inline(InlineAttr::Always, span) => *span) - && body.is_none_or(|body| is_relevant_expr(cx, cx.tcx.hir_body(body).value)) + && body.is_none_or(|body| is_relevant_expr(cx, &cx.tcx.hir_body(body).value)) { span_lint( cx, diff --git a/src/tools/clippy/clippy_lints/src/booleans.rs b/src/tools/clippy/clippy_lints/src/booleans.rs index b2c21377a0a3f..601085d1ac72b 100644 --- a/src/tools/clippy/clippy_lints/src/booleans.rs +++ b/src/tools/clippy/clippy_lints/src/booleans.rs @@ -459,7 +459,7 @@ fn simplify_not(cx: &LateContext<'_>, curr_msrv: Msrv, expr: &Expr<'_>) -> Optio .map(|param| param.span.get_text(cx).map(|t| t.to_string())) .collect::>>()? .join(", "); - let negated = simplify_not(cx, curr_msrv, body.value)?; + let negated = simplify_not(cx, curr_msrv, &body.value)?; Some(format!("|{params}| {negated}")) }, ExprKind::Unary(UnOp::Not, expr) => expr.span.get_text(cx).map(|t| t.to_string()), diff --git a/src/tools/clippy/clippy_lints/src/casts/mod.rs b/src/tools/clippy/clippy_lints/src/casts/mod.rs index 35806284d3b31..59d3c4ed88f4f 100644 --- a/src/tools/clippy/clippy_lints/src/casts/mod.rs +++ b/src/tools/clippy/clippy_lints/src/casts/mod.rs @@ -953,7 +953,7 @@ impl<'tcx> LateLintPass<'tcx> for Casts { ptr_cast_constness::check_null_ptr_cast_method(cx, expr); } - fn check_body(&mut self, cx: &LateContext<'tcx>, body: &rustc_hir::Body<'tcx>) { + fn check_body(&mut self, cx: &LateContext<'tcx>, body: &'tcx rustc_hir::Body<'tcx>) { needless_type_cast::check(cx, body); } } diff --git a/src/tools/clippy/clippy_lints/src/casts/needless_type_cast.rs b/src/tools/clippy/clippy_lints/src/casts/needless_type_cast.rs index 09f72b18d18f0..077a58037849a 100644 --- a/src/tools/clippy/clippy_lints/src/casts/needless_type_cast.rs +++ b/src/tools/clippy/clippy_lints/src/casts/needless_type_cast.rs @@ -24,10 +24,10 @@ struct UsageInfo<'a> { in_generic_context: bool, } -pub(super) fn check<'a>(cx: &LateContext<'a>, body: &Body<'a>) { +pub(super) fn check<'a>(cx: &LateContext<'a>, body: &'a Body<'a>) { let mut bindings: FxHashMap> = FxHashMap::default(); - for_each_expr_without_closures(body.value, |expr| { + for_each_expr_without_closures(&body.value, |expr| { match expr.kind { ExprKind::Block(block, _) => { for stmt in block.stmts { @@ -246,10 +246,10 @@ fn can_coerce_to_target_type(expr: &Expr<'_>) -> bool { } } -fn check_binding_usages<'a>(cx: &LateContext<'a>, body: &Body<'a>, hir_id: HirId, binding_info: &BindingInfo<'a>) { +fn check_binding_usages<'a>(cx: &LateContext<'a>, body: &'a Body<'a>, hir_id: HirId, binding_info: &BindingInfo<'a>) { let mut usages = Vec::new(); - for_each_expr(cx.tcx, body.value, |expr| { + for_each_expr(cx.tcx, &body.value, |expr| { if let ExprKind::Path(ref qpath) = expr.kind && !expr.span.from_expansion() && let Res::Local(id) = cx.qpath_res(qpath, expr.hir_id) diff --git a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs index a28e9d58f2caf..4a64995e69745 100644 --- a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs +++ b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs @@ -154,7 +154,7 @@ impl<'tcx> LateLintPass<'tcx> for CognitiveComplexity { }, } } else { - body.value + &body.value }; self.check(cx, kind, decl, expr, span); diff --git a/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs b/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs index 099100bf9d1f6..607ebbc246e7c 100644 --- a/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs +++ b/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs @@ -120,7 +120,7 @@ fn has_no_read_access<'tcx, T: Visitable<'tcx>>(cx: &LateContext<'tcx>, id: HirI // To keep things simple, we only check the first param to see if its read. && let Body { params: [param, ..], value } = cx.tcx.hir_body(closure.body) { - !has_no_read_access(cx, param.hir_id, *value) + !has_no_read_access(cx, param.hir_id, value) } else { false } diff --git a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs index 5bfe936880a85..af98312e011c8 100644 --- a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs +++ b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs @@ -50,7 +50,7 @@ declare_clippy_lint! { declare_lint_pass!(DefaultNumericFallback => [DEFAULT_NUMERIC_FALLBACK]); impl<'tcx> LateLintPass<'tcx> for DefaultNumericFallback { - fn check_body(&mut self, cx: &LateContext<'tcx>, body: &Body<'tcx>) { + fn check_body(&mut self, cx: &LateContext<'tcx>, body: &'tcx Body<'tcx>) { // NOTE: this is different from `clippy_utils::is_inside_always_const_context`. // Inline const supports type inference. let is_parent_const = matches!( diff --git a/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs b/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs index 5a69a5e0d2e84..a2b1f801d8b65 100644 --- a/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs +++ b/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs @@ -74,7 +74,7 @@ pub fn check( && let Some(future) = cx.tcx.lang_items().future_trait() && let typeck = cx.tcx.typeck_body(body_id) && let body = cx.tcx.hir_body(body_id) - && let ret_ty = typeck.expr_ty(body.value) + && let ret_ty = typeck.expr_ty(&body.value) && implements_trait_with_env( cx.tcx, ty::TypingEnv::non_body_analysis(cx.tcx, owner_id.def_id), diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs index e3674fcf0d0b6..98ce2e3cd1d7c 100644 --- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs +++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs @@ -100,7 +100,7 @@ fn check_closure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tcx if body.value.span.from_expansion() { if body.params.is_empty() - && let Some(VecArgs::Vec(&[])) = VecArgs::hir(cx, body.value) + && let Some(VecArgs::Vec(&[])) = VecArgs::hir(cx, &body.value) { let vec_crate = if is_no_std_crate(cx) { "alloc" } else { "std" }; // replace `|| vec![]` with `Vec::new` @@ -124,7 +124,7 @@ fn check_closure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tcx return; } - if is_adjusted(cx, body.value) { + if is_adjusted(cx, &body.value) { return; } @@ -170,7 +170,7 @@ fn check_closure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tcx _ => { if typeck.type_dependent_def_id(body.value.hir_id).is_some() && let subs = typeck.node_args(body.value.hir_id) - && let output = typeck.expr_ty(body.value) + && let output = typeck.expr_ty(&body.value) && let ty::Tuple(tys) = *subs.type_at(1).kind() { cx.tcx.mk_fn_sig_safe_rust_abi(tys, output) diff --git a/src/tools/clippy/clippy_lints/src/from_over_into.rs b/src/tools/clippy/clippy_lints/src/from_over_into.rs index ed936e7f14aec..fd7985e462eed 100644 --- a/src/tools/clippy/clippy_lints/src/from_over_into.rs +++ b/src/tools/clippy/clippy_lints/src/from_over_into.rs @@ -232,7 +232,7 @@ fn convert_to_from( lower: Vec::new(), }; - if finder.visit_expr(body.value).is_break() { + if finder.visit_expr(&body.value).is_break() { return None; } diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs index 4cb798c67a7d2..12ad676581171 100644 --- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs +++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs @@ -327,7 +327,7 @@ fn is_mutated_static(e: &hir::Expr<'_>) -> bool { } fn mutates_static<'tcx>(cx: &LateContext<'tcx>, body: &'tcx hir::Body<'_>) -> bool { - for_each_expr_without_closures(body.value, |e| { + for_each_expr_without_closures(&body.value, |e| { use hir::ExprKind::{AddrOf, Assign, AssignOp, Call, MethodCall}; match e.kind { diff --git a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs index 7555a6719b6de..42c4aba60c5af 100644 --- a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs +++ b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs @@ -50,7 +50,7 @@ fn check_raw_ptr<'tcx>( if !raw_ptrs.is_empty() { let typeck = cx.tcx.typeck_body(body.id()); - let _: Option = for_each_expr(cx.tcx, body.value, |e| { + let _: Option = for_each_expr(cx.tcx, &body.value, |e| { match e.kind { hir::ExprKind::Call(f, args) if is_unsafe_fn(cx, typeck.expr_ty(f)) => { for arg in args { diff --git a/src/tools/clippy/clippy_lints/src/functions/ref_option.rs b/src/tools/clippy/clippy_lints/src/functions/ref_option.rs index 733f10b3506f8..f6fa5ebcd5e3b 100644 --- a/src/tools/clippy/clippy_lints/src/functions/ref_option.rs +++ b/src/tools/clippy/clippy_lints/src/functions/ref_option.rs @@ -96,7 +96,7 @@ pub(crate) fn check_fn<'a>( }; // Figure out the signature of the closure - let ty::Closure(_, args) = cx.typeck_results().expr_ty(body.value).kind() else { + let ty::Closure(_, args) = cx.typeck_results().expr_ty(&body.value).kind() else { return; }; let sig = args.as_closure().sig().skip_binder(); diff --git a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs index ea443487df9ba..70f0fa0a3b478 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs @@ -312,7 +312,7 @@ impl<'a, 'b, 'tcx> ImplicitHasherConstructorVisitor<'a, 'b, 'tcx> { impl<'tcx> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'_, '_, 'tcx> { type NestedFilter = nested_filter::OnlyBodies; - fn visit_body(&mut self, body: &Body<'tcx>) { + fn visit_body(&mut self, body: &'tcx Body<'tcx>) { let old_maybe_typeck_results = self.maybe_typeck_results.replace(self.cx.tcx.typeck_body(body.id())); walk_body(self, body); self.maybe_typeck_results = old_maybe_typeck_results; diff --git a/src/tools/clippy/clippy_lints/src/implicit_return.rs b/src/tools/clippy/clippy_lints/src/implicit_return.rs index 633a3e9e42bd8..4867cbabcc4bc 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_return.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_return.rs @@ -234,7 +234,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitReturn { return; } - let res_ty = cx.typeck_results().expr_ty(body.value); + let res_ty = cx.typeck_results().expr_ty(&body.value); if res_ty.is_unit() || res_ty.is_never() { return; } @@ -244,10 +244,10 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitReturn { Some(e) => e, None => return, } - } else if let Some(expr) = get_async_closure_expr(cx.tcx, body.value) { + } else if let Some(expr) = get_async_closure_expr(cx.tcx, &body.value) { expr } else { - body.value + &body.value }; if is_from_proc_macro(cx, expr) { diff --git a/src/tools/clippy/clippy_lints/src/infinite_iter.rs b/src/tools/clippy/clippy_lints/src/infinite_iter.rs index e9b30ab93b9b9..aa75a16ae8cb8 100644 --- a/src/tools/clippy/clippy_lints/src/infinite_iter.rs +++ b/src/tools/clippy/clippy_lints/src/infinite_iter.rs @@ -161,7 +161,7 @@ fn is_infinite(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness { && let ExprKind::Closure(&Closure { body, .. }) = args[0].kind { let body = cx.tcx.hir_body(body); - return is_infinite(cx, body.value); + return is_infinite(cx, &body.value); } Finite }, diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs index 408d78ae623c0..174139fbcbb66 100644 --- a/src/tools/clippy/clippy_lints/src/lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs @@ -345,7 +345,7 @@ fn could_use_elision<'tcx>( } let mut checker = BodyLifetimeChecker::new(cx); - if checker.visit_expr(body.value).is_break() { + if checker.visit_expr(&body.value).is_break() { return None; } } diff --git a/src/tools/clippy/clippy_lints/src/loops/infinite_loop.rs b/src/tools/clippy/clippy_lints/src/loops/infinite_loop.rs index 404ff33838b15..9745f4393e3e3 100644 --- a/src/tools/clippy/clippy_lints/src/loops/infinite_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/infinite_loop.rs @@ -49,7 +49,7 @@ pub(super) fn check<'tcx>( if let FnRetTy::DefaultReturn(ret_span) = parent_fn_ret && cx .enclosing_body - .is_some_and(|id| matches!(is_never_expr(cx, cx.tcx.hir_body(id).value), Some(RequiresSemi::No))) + .is_some_and(|id| matches!(is_never_expr(cx, &cx.tcx.hir_body(id).value), Some(RequiresSemi::No))) { diag.span_suggestion( ret_span, diff --git a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs index 43fa115f7e749..09dcff2c5c8e1 100644 --- a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs @@ -91,8 +91,8 @@ pub(super) fn check_iterator_reduction<'tcx>( recv: &'tcx Expr<'tcx>, closure: &'tcx Closure<'tcx>, ) { - let closure_body = cx.tcx.hir_body(closure.body).value; - let body_ty = cx.typeck_results().expr_ty(closure_body); + let closure_body = &cx.tcx.hir_body(closure.body).value; + let body_ty = cx.typeck_results().expr_ty(&closure_body); if body_ty.is_never() && !contains_return(closure_body) { span_lint_and_then( cx, diff --git a/src/tools/clippy/clippy_lints/src/loops/unused_enumerate_index.rs b/src/tools/clippy/clippy_lints/src/loops/unused_enumerate_index.rs index 3d46991d1c224..0b136f60bceac 100644 --- a/src/tools/clippy/clippy_lints/src/loops/unused_enumerate_index.rs +++ b/src/tools/clippy/clippy_lints/src/loops/unused_enumerate_index.rs @@ -80,6 +80,6 @@ pub(super) fn check_method<'tcx>( } else { None }; - check(cx, recv, param.pat, ty_spans, body.value); + check(cx, recv, param.pat, ty_spans, &body.value); } } diff --git a/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs b/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs index 68b4865de4752..ff82e2f55812f 100644 --- a/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs +++ b/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs @@ -351,7 +351,7 @@ fn needs_mutable_borrow(cx: &LateContext<'_>, iter_expr: &IterExpr, loop_expr: & loop_id: loop_expr.hir_id, after_loop: false, }; - v.visit_expr(cx.tcx.hir_body(cx.enclosing_body.unwrap()).value) + v.visit_expr(&cx.tcx.hir_body(cx.enclosing_body.unwrap()).value) .is_break() } } diff --git a/src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs b/src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs index 82af5d67e6f23..462aff30f1d41 100644 --- a/src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs +++ b/src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs @@ -212,7 +212,7 @@ impl<'tcx> Visitor<'tcx> for BodyVisitor<'_, 'tcx> { } impl<'tcx> LateLintPass<'tcx> for ExprMetavarsInUnsafe { - fn check_body(&mut self, cx: &LateContext<'tcx>, body: &rustc_hir::Body<'tcx>) { + fn check_body(&mut self, cx: &LateContext<'tcx>, body: &'tcx rustc_hir::Body<'tcx>) { if is_lint_allowed(cx, MACRO_METAVARS_IN_UNSAFE, body.value.hir_id) { return; } diff --git a/src/tools/clippy/clippy_lints/src/manual_noop_waker.rs b/src/tools/clippy/clippy_lints/src/manual_noop_waker.rs index deedde8cdc302..4f38a32d1c8ac 100644 --- a/src/tools/clippy/clippy_lints/src/manual_noop_waker.rs +++ b/src/tools/clippy/clippy_lints/src/manual_noop_waker.rs @@ -64,7 +64,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualNoopWaker { if let ImplItemKind::Fn(_, body_id) = &impl_item.kind { let body = cx.tcx.hir_body(*body_id); - if !is_empty_block(body.value) { + if !is_empty_block(&body.value) { return; } } diff --git a/src/tools/clippy/clippy_lints/src/manual_option_as_slice.rs b/src/tools/clippy/clippy_lints/src/manual_option_as_slice.rs index c4a3ac96b1f89..ab3e4645f56f0 100644 --- a/src/tools/clippy/clippy_lints/src/manual_option_as_slice.rs +++ b/src/tools/clippy/clippy_lints/src/manual_option_as_slice.rs @@ -178,7 +178,7 @@ fn check_arms(cx: &LateContext<'_>, none_arm: &Arm<'_>, some_arm: &Arm<'_>) -> b fn returns_empty_slice(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { match expr.kind { ExprKind::Path(_) => expr.res(cx).is_diag_item(cx, sym::default_fn), - ExprKind::Closure(cl) => is_empty_slice(cx, cx.tcx.hir_body(cl.body).value), + ExprKind::Closure(cl) => is_empty_slice(cx, &cx.tcx.hir_body(cl.body).value), _ => false, } } diff --git a/src/tools/clippy/clippy_lints/src/manual_pop_if.rs b/src/tools/clippy/clippy_lints/src/manual_pop_if.rs index afafe25f8ffd0..cdaef65d3c574 100644 --- a/src/tools/clippy/clippy_lints/src/manual_pop_if.rs +++ b/src/tools/clippy/clippy_lints/src/manual_pop_if.rs @@ -219,7 +219,7 @@ fn check_is_some_and_pattern<'tcx>( return Some(ManualPopIfPattern { kind, collection_expr, - predicate: body.value, + predicate: &body.value, param_name: ident.name, if_span: if_expr_span, spans: MultiSpan::from(vec![if_expr_span.with_hi(cond.span.hi()), pop_span]), @@ -370,7 +370,7 @@ fn check_map_unwrap_or_pattern<'tcx>( && kind.is_diag_item(cx, collection_expr) && let ExprKind::Closure(closure) = closure_arg.kind && let body = cx.tcx.hir_body(closure.body) - && cx.typeck_results().expr_ty(body.value).is_bool() + && cx.typeck_results().expr_ty(&body.value).is_bool() && let Some((pop_collection, pop_span, suggestable)) = check_pop_unwrap(cx, then_block, pop_method) && eq_expr_value(cx, if_expr_span.ctxt(), collection_expr, pop_collection) && let Some(param) = body.params.first() @@ -379,7 +379,7 @@ fn check_map_unwrap_or_pattern<'tcx>( return Some(ManualPopIfPattern { kind, collection_expr, - predicate: body.value, + predicate: &body.value, param_name: ident.name, if_span: if_expr_span, spans: MultiSpan::from(vec![if_expr_span.with_hi(cond.span.hi()), pop_span]), diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_filter.rs b/src/tools/clippy/clippy_lints/src/matches/manual_filter.rs index 94a2910cef3b9..571bb095252ab 100644 --- a/src/tools/clippy/clippy_lints/src/matches/manual_filter.rs +++ b/src/tools/clippy/clippy_lints/src/matches/manual_filter.rs @@ -106,7 +106,7 @@ pub(crate) fn check_and_then_method<'tcx>( && let Some(fn_arg_span) = closure.fn_arg_span && let [param] = body.params && let expr_span_ctxt = expr.span.ctxt() - && let Some(some_expr) = get_cond_expr(cx, param.pat, body.value, expr_span_ctxt) + && let Some(some_expr) = get_cond_expr(cx, param.pat, &body.value, expr_span_ctxt) { span_lint_and_then( cx, diff --git a/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs b/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs index 2a15d732939c3..a997d3a93be66 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs @@ -227,7 +227,7 @@ impl<'tcx> Visitor<'tcx> for VarBindingVisitor<'_, 'tcx> { self.identifiers.remove(&ident.name); }); } - self.visit_expr(body.value)?; + self.visit_expr(&body.value)?; self.identifiers = before; ControlFlow::Continue(()) }, diff --git a/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs b/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs index d298bb1a11d9e..b5c730ee992d7 100644 --- a/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs +++ b/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs @@ -166,7 +166,7 @@ impl BindInsteadOfMap { match arg.kind { hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, .. }) => { let closure_body = cx.tcx.hir_body(body); - let closure_expr = peel_blocks(closure_body.value); + let closure_expr = peel_blocks(&closure_body.value); if self.lint_closure_autofixable(cx, expr, recv, closure_expr, fn_decl_span) { true diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map.rs index f42b73fce6bdc..29fc0180d5fb5 100644 --- a/src/tools/clippy/clippy_lints/src/methods/filter_map.rs +++ b/src/tools/clippy/clippy_lints/src/methods/filter_map.rs @@ -23,7 +23,7 @@ fn is_method(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symbol) -> bool ExprKind::MethodCall(segment, _, _, _) => segment.ident.name == method_name, ExprKind::Closure(Closure { body, .. }) => { let body = cx.tcx.hir_body(*body); - let closure_expr = peel_blocks(body.value); + let closure_expr = peel_blocks(&body.value); match closure_expr.kind { ExprKind::MethodCall(PathSegment { ident, .. }, receiver, ..) => { if ident.name == method_name @@ -189,7 +189,7 @@ impl<'tcx> OffendingFilterExpr<'tcx> { // ^^^^ ^^^^^^^ ^ ^^^^^^^^^^^^^^ // scrutinee variant_span variant_ident else_ let (scrutinee, else_, variant_ident, variant_span) = - match higher::IfLetOrMatch::parse(cx, map_body.value) { + match higher::IfLetOrMatch::parse(cx, &map_body.value) { // For `if let` we want to check that the variant matching arm references the local created by // its pattern Some(higher::IfLetOrMatch::IfLet(sc, pat, then, Some(else_), ..)) @@ -418,7 +418,7 @@ fn is_find_or_filter<'a>( } && let PatKind::Binding(_, filter_param_id, _, None) = filter_pat.kind - && let Some(offending_expr) = OffendingFilterExpr::hir(cx, filter_body.value, filter_param_id) + && let Some(offending_expr) = OffendingFilterExpr::hir(cx, &filter_body.value, filter_param_id) && let ExprKind::Closure(&Closure { body: map_body_id, .. }) = map_arg.kind && let map_body = cx.tcx.hir_body(map_body_id) diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs index 00c7ca82d10dd..1c637dceca978 100644 --- a/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs +++ b/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs @@ -17,7 +17,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, arg: & if cx.ty_based_def(expr).opt_parent(cx).is_diag_item(cx, sym::Iterator) && let ExprKind::Closure(closure) = arg.kind && let body = cx.tcx.hir_body(closure.body) - && let value = peel_blocks(body.value) + && let value = peel_blocks(&body.value) // Indexing should be fine as `filter_map` always has 1 input, we unfortunately need both // `inputs` and `params` here as we need both the type and the span && let param_ty = closure.fn_decl.inputs[0] @@ -33,7 +33,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, arg: & && is_copy(cx, param_ty) && let ExprKind::MethodCall(_, recv, [then_arg], _) = value.kind && let ExprKind::Closure(then_closure) = then_arg.kind - && let then_body = peel_blocks(cx.tcx.hir_body(then_closure.body).value) + && let then_body = peel_blocks(&cx.tcx.hir_body(then_closure.body).value) && let Some(def_id) = cx.typeck_results().type_dependent_def_id(value.hir_id) && cx.tcx.is_diagnostic_item(sym::bool_then, def_id) && !expr.span.in_external_macro(cx.sess().source_map()) diff --git a/src/tools/clippy/clippy_lints/src/methods/format_collect.rs b/src/tools/clippy/clippy_lints/src/methods/format_collect.rs index 112906a7d01e1..a49f8f5c9f9c0 100644 --- a/src/tools/clippy/clippy_lints/src/methods/format_collect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/format_collect.rs @@ -21,7 +21,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, map_arg: &Expr<'_>, m if cx.typeck_results().expr_ty(expr).is_lang_item(cx, LangItem::String) && let ExprKind::Closure(closure) = map_arg.kind && let body = cx.tcx.hir_body(closure.body) - && let Some(value) = peel_non_expn_blocks(body.value) + && let Some(value) = peel_non_expn_blocks(&body.value) && let Some(mac) = root_macro_call_first_node(cx, value) && is_format_macro(cx, mac.def_id) { diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_filter.rs b/src/tools/clippy/clippy_lints/src/methods/iter_filter.rs index 1f5b48a6f78f2..8743fd50d386e 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iter_filter.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iter_filter.rs @@ -96,7 +96,7 @@ fn is_method( }, ExprKind::Closure(&hir::Closure { body, .. }) => { let body = cx.tcx.hir_body(body); - let closure_expr = peel_blocks(body.value); + let closure_expr = peel_blocks(&body.value); let params = body.params.iter().map(|param| param.pat).collect::>(); is_method(cx, closure_expr, type_symbol, method_name, params.as_slice()) }, diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs b/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs index 241791e57c8e6..e21004f87a264 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs @@ -67,7 +67,7 @@ pub(super) fn check<'tcx>( return; }; - if param_captured_by_move_block(cx, body.value, p) { + if param_captured_by_move_block(cx, &body.value, p) { return; } diff --git a/src/tools/clippy/clippy_lints/src/methods/lines_filter_map_ok.rs b/src/tools/clippy/clippy_lints/src/methods/lines_filter_map_ok.rs index 607979719f894..770097b91378c 100644 --- a/src/tools/clippy/clippy_lints/src/methods/lines_filter_map_ok.rs +++ b/src/tools/clippy/clippy_lints/src/methods/lines_filter_map_ok.rs @@ -49,7 +49,7 @@ pub(super) fn check_filter_or_flat_map( { method.ident.name == sym::ok && receiver.res_local_id() == Some(param.pat.hir_id) - && cx.ty_based_def(*value).is_diag_item(cx, sym::result_ok_method) + && cx.ty_based_def(value).is_diag_item(cx, sym::result_ok_method) } else { false } diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs b/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs index aff6477c32547..f324e5437232e 100644 --- a/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs @@ -47,7 +47,7 @@ pub(crate) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>, name: let can_lint = for_each_expr_without_closures(block.stmts, |e| { if let ExprKind::Closure(c) = e.kind { // Nested closures don't need to treat returns specially. - let _: Option = for_each_expr(cx.tcx, cx.tcx.hir_body(c.body).value, |e| { + let _: Option = for_each_expr(cx.tcx, &cx.tcx.hir_body(c.body).value, |e| { if e.res_local_id() == Some(arg_id) { let (kind, same_ctxt) = check_use(cx, ctxt, e); match (kind, same_ctxt && e.span.ctxt() == ctxt) { diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_is_variant_and.rs b/src/tools/clippy/clippy_lints/src/methods/manual_is_variant_and.rs index bd2b1ba299185..26d1188faff43 100644 --- a/src/tools/clippy/clippy_lints/src/methods/manual_is_variant_and.rs +++ b/src/tools/clippy/clippy_lints/src/methods/manual_is_variant_and.rs @@ -149,7 +149,7 @@ impl<'hir> MapFunc<'hir> { fn sugg(self, cx: &LateContext<'hir>, invert: bool, app: &mut Applicability) -> String { match self { Self::Closure(closure) => { - let body = Sugg::hir_with_applicability(cx, cx.tcx.hir_body(closure.body).value, "..", app); + let body = Sugg::hir_with_applicability(cx, &cx.tcx.hir_body(closure.body).value, "..", app); format!( "{} {}", snippet_with_applicability(cx, closure.fn_decl_span, "|..|", app), diff --git a/src/tools/clippy/clippy_lints/src/methods/map_clone.rs b/src/tools/clippy/clippy_lints/src/methods/map_clone.rs index 072f56b897014..c91f81a80c429 100644 --- a/src/tools/clippy/clippy_lints/src/methods/map_clone.rs +++ b/src/tools/clippy/clippy_lints/src/methods/map_clone.rs @@ -49,7 +49,7 @@ pub(super) fn check(cx: &LateContext<'_>, e: &hir::Expr<'_>, recv: &hir::Expr<'_ match arg.kind { hir::ExprKind::Closure(&hir::Closure { body, .. }) => { let closure_body = cx.tcx.hir_body(body); - let closure_expr = peel_blocks(closure_body.value); + let closure_expr = peel_blocks(&closure_body.value); match closure_body.params[0].pat.kind { hir::PatKind::Ref(inner, Pinnedness::Not, Mutability::Not) => { if let hir::PatKind::Binding(hir::BindingMode::NONE, .., name, None) = inner.kind diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index f4b8c08321da9..1edf3bd2a7199 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -5487,7 +5487,7 @@ impl Methods { && let body = cx.tcx.hir_body(arg.body) && let [param] = body.params => { - string_lit_chars_any::check(cx, expr, recv, param, peel_blocks(body.value), self.msrv); + string_lit_chars_any::check(cx, expr, recv, param, peel_blocks(&body.value), self.msrv); }, Some((sym::map, _, [map_arg], _, map_call_span)) => { map_all_any_identity::check(cx, expr, recv, map_call_span, map_arg, call_span, arg, "any"); diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_character_iteration.rs b/src/tools/clippy/clippy_lints/src/methods/needless_character_iteration.rs index aac4a344f5f99..6ad961ec9dbd1 100644 --- a/src/tools/clippy/clippy_lints/src/methods/needless_character_iteration.rs +++ b/src/tools/clippy/clippy_lints/src/methods/needless_character_iteration.rs @@ -108,7 +108,7 @@ pub(super) fn check(cx: &LateContext<'_>, call_expr: &Expr<'_>, recv: &Expr<'_>, while let ExprKind::MethodCall(_, new_recv, _, _) = recv.kind { recv = new_recv; } - let body_expr = peel_blocks(body.value); + let body_expr = peel_blocks(&body.value); handle_expr( cx, diff --git a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs index 31f294ff27d37..c26e3c0052ae9 100644 --- a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs +++ b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs @@ -47,7 +47,7 @@ pub(super) fn check( }), hir::ExprKind::Closure(&hir::Closure { body, .. }) => { let closure_body = cx.tcx.hir_body(body); - let closure_expr = peel_blocks(closure_body.value); + let closure_expr = peel_blocks(&closure_body.value); match &closure_expr.kind { hir::ExprKind::MethodCall(_, receiver, [], _) => { diff --git a/src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs b/src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs index aa1ef9a37374a..b155412057104 100644 --- a/src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs +++ b/src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs @@ -61,7 +61,7 @@ pub(super) fn check<'tcx>( if let hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, .. }) = map_arg.kind && let arg_snippet = snippet(cx, fn_decl_span, "..") && let body = cx.tcx.hir_body(body) - && let Some((func, [arg_char])) = reduce_unit_expression(body.value) + && let Some((func, [arg_char])) = reduce_unit_expression(&body.value) && let Some(id) = func.res(cx).opt_def_id().map(|ctor_id| cx.tcx.parent(ctor_id)) && Some(id) == cx.tcx.lang_items().option_some_variant() { diff --git a/src/tools/clippy/clippy_lints/src/methods/result_map_or_else_none.rs b/src/tools/clippy/clippy_lints/src/methods/result_map_or_else_none.rs index 4f496de99bb1e..15752016e5b82 100644 --- a/src/tools/clippy/clippy_lints/src/methods/result_map_or_else_none.rs +++ b/src/tools/clippy/clippy_lints/src/methods/result_map_or_else_none.rs @@ -25,7 +25,7 @@ pub(super) fn check<'tcx>( && let hir::ExprKind::Closure(&hir::Closure { body, .. }) = def_arg.kind && let body = cx.tcx.hir_body(body) // And finally we check that we return a `None` in the "else case". - && is_none_expr(cx, peel_blocks(body.value)) + && is_none_expr(cx, peel_blocks(&body.value)) { let msg = "called `map_or_else(|_| None, Some)` on a `Result` value"; let self_snippet = snippet(cx, recv.span, ".."); diff --git a/src/tools/clippy/clippy_lints/src/methods/return_and_then.rs b/src/tools/clippy/clippy_lints/src/methods/return_and_then.rs index 404ad551919f5..e08115940999c 100644 --- a/src/tools/clippy/clippy_lints/src/methods/return_and_then.rs +++ b/src/tools/clippy/clippy_lints/src/methods/return_and_then.rs @@ -44,7 +44,7 @@ pub(super) fn check<'tcx>( }; let closure_arg = fn_decl.inputs[0]; - let closure_expr = peel_blocks(cx.tcx.hir_body(body).value); + let closure_expr = peel_blocks(&cx.tcx.hir_body(body).value); let mut applicability = Applicability::MachineApplicable; let arg_snip = snippet_with_applicability(cx, closure_arg.span, "_", &mut applicability); diff --git a/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs b/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs index 35cd23c49ecef..26cf5d6017d5a 100644 --- a/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs +++ b/src/tools/clippy/clippy_lints/src/methods/suspicious_map.rs @@ -15,9 +15,9 @@ pub fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, count_recv: &hir::Expr< .is_diag_item(cx, sym::Iterator) && let hir::ExprKind::Closure(closure) = expr_or_init(cx, map_arg).kind && let closure_body = cx.tcx.hir_body(closure.body) - && !cx.typeck_results().expr_ty(closure_body.value).is_unit() + && !cx.typeck_results().expr_ty(&closure_body.value).is_unit() { - if let Some(map_mutated_vars) = mutated_variables(closure_body.value, cx) + if let Some(map_mutated_vars) = mutated_variables(&closure_body.value, cx) // A variable is used mutably inside of the closure. Suppress the lint. && !map_mutated_vars.is_empty() { diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs index 31f21492dfedd..e70d825f75bbc 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs @@ -27,12 +27,12 @@ pub(super) fn check<'tcx>( if let hir::ExprKind::Closure(&hir::Closure { body, .. }) = arg.kind { let body = cx.tcx.hir_body(body); let arg_id = body.params[0].pat.hir_id; - let mutates_arg = mutated_variables(body.value, cx).is_none_or(|used_mutably| used_mutably.contains(&arg_id)); - let (clone_or_copy_needed, _) = clone_or_copy_needed(cx, body.params[0].pat, body.value); + let mutates_arg = mutated_variables(&body.value, cx).is_none_or(|used_mutably| used_mutably.contains(&arg_id)); + let (clone_or_copy_needed, _) = clone_or_copy_needed(cx, body.params[0].pat, &body.value); - let (mut found_mapping, mut found_filtering) = check_expression(cx, arg_id, body.value); + let (mut found_mapping, mut found_filtering) = check_expression(cx, arg_id, &body.value); - let _: Option = for_each_expr_without_closures(body.value, |e| { + let _: Option = for_each_expr_without_closures(&body.value, |e| { if let hir::ExprKind::Ret(Some(e)) = &e.kind { let (found_mapping_res, found_filtering_res) = check_expression(cx, arg_id, e); found_mapping |= found_mapping_res; @@ -46,7 +46,7 @@ pub(super) fn check<'tcx>( let sugg = if !found_filtering { // Check if the closure is .filter_map(|x| Some(x)) if kind.is_filter_map() - && let Some(arg) = as_some_expr(cx, body.value) + && let Some(arg) = as_some_expr(cx, &body.value) && let hir::ExprKind::Path(_) = arg.kind { span_lint( @@ -62,7 +62,7 @@ pub(super) fn check<'tcx>( Kind::FindMap => "map(..).next()", } } else if !found_mapping && !mutates_arg && (!clone_or_copy_needed || is_copy(cx, in_ty)) { - let ty = cx.typeck_results().expr_ty(body.value); + let ty = cx.typeck_results().expr_ty(&body.value); if option_arg_ty(cx, ty).is_some_and(|t| t == in_ty) { match kind { Kind::FilterMap => "filter(..)", diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs index c7207bb4dd4bc..914388129914c 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs @@ -126,7 +126,7 @@ fn check_fold_with_op( if let hir::ExprKind::Closure(&hir::Closure { body, .. }) = acc.kind // Extract the body of the closure passed to fold && let closure_body = cx.tcx.hir_body(body) - && let closure_expr = peel_blocks(closure_body.value) + && let closure_expr = peel_blocks(&closure_body.value) // Check if the closure body is of the form `acc some_expr(x)` && let hir::ExprKind::Binary(ref bin_op, left_expr, right_expr) = closure_expr.kind @@ -353,7 +353,7 @@ fn check_option_fold<'tcx>( let mut acc_uses: Vec = Vec::new(); let mut acc_uses_ok = true; if let Some(acc_id) = acc_id { - for_each_expr(cx.tcx, closure_body.value, |sub_expr| { + for_each_expr(cx.tcx, &closure_body.value, |sub_expr| { if sub_expr.res_local_id() == Some(acc_id) { if sub_expr.span.ctxt() == ctxt { acc_uses.push(sub_expr.span); diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or.rs index dff23e1cce061..79c76ad747657 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or.rs @@ -54,7 +54,7 @@ fn closure_bool_constant(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option let [_] = body.params else { return None; }; - bool_constant(cx, body.value) + bool_constant(cx, &body.value) } /// Checks whether a `Result::{map_or, map_or_else}` call is a variant query. diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs index 48333cd2d85f3..852c6f1414b29 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs @@ -256,7 +256,7 @@ fn detect_lint(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>) -> Option< && let ExprKind::MethodCall(method_path, left_expr, [right_expr], _) = closure_body.value.kind && method_path.ident.name == sym::cmp && let Some(ord_trait) = cx.tcx.get_diagnostic_item(sym::Ord) - && cx.ty_based_def(closure_body.value).opt_parent(cx).opt_def_id() == Some(ord_trait) + && cx.ty_based_def(&closure_body.value).opt_parent(cx).opt_def_id() == Some(ord_trait) { let (closure_body, closure_arg, reverse) = if mirrored_exprs(left_expr, right_expr, &binding_map, BindingSource::Left) { diff --git a/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs b/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs index 057bb3a3a538d..70ff2dcccd348 100644 --- a/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs +++ b/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs @@ -152,7 +152,7 @@ fn is_calling_clone(cx: &LateContext<'_>, arg: &hir::Expr<'_>) -> bool { && let [param] = closure_body.params && let hir::PatKind::Binding(_, local_id, ..) = strip_pat_refs(param.pat).kind => { - let closure_expr = peel_blocks(closure_body.value); + let closure_expr = peel_blocks(&closure_body.value); match closure_expr.kind { hir::ExprKind::MethodCall(method, obj, [], _) => { if method.ident.name == sym::clone diff --git a/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs b/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs index bb615ff4ef110..c2e62f1128653 100644 --- a/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs +++ b/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs @@ -436,7 +436,7 @@ impl LateLintPass<'_> for MissingAssertsForIndexing { fn check_body(&mut self, cx: &LateContext<'_>, body: &Body<'_>) { let mut map = UnindexMap::default(); - for_each_expr_without_closures(body.value, |expr| { + for_each_expr_without_closures(&body.value, |expr| { check_index(cx, expr, &mut map); check_assert(cx, expr, &mut map); ControlFlow::::Continue(()) diff --git a/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs b/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs index 19c3abd2576f6..4967d2aefd53b 100644 --- a/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs +++ b/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs @@ -276,7 +276,7 @@ impl<'tcx> Visitor<'tcx> for UnsafeExprCollector<'tcx> { walk_expr(self, expr); } - fn visit_body(&mut self, body: &hir::Body<'tcx>) { + fn visit_body(&mut self, body: &'tcx hir::Body<'tcx>) { let saved_typeck_results = self.typeck_results; self.typeck_results = self.tcx.typeck_body(body.id()); walk_body(self, body); diff --git a/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs b/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs index 32cf04908911f..1509400d6c97c 100644 --- a/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs +++ b/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs @@ -187,7 +187,7 @@ impl LateLintPass<'_> for NonCanonicalImpls { && implements_trait(cx, trait_impl.self_ty(), copy_trait, &[]) { for (assoc, body, _) in assoc_fns { - check_clone_on_copy(cx, assoc, body.value); + check_clone_on_copy(cx, assoc, &body.value); } } }, diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs index a9d747e2757f7..8abefc0df0034 100644 --- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs +++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs @@ -964,9 +964,9 @@ fn get_const_hir_value<'tcx>( _ => return None, }; match ct_rhs { - ConstItemRhs::Body(body_id) => Some((tcx.typeck(did), tcx.hir_body(body_id).value)), + ConstItemRhs::Body(body_id) => Some((tcx.typeck(did), &tcx.hir_body(body_id).value)), ConstItemRhs::Direct(ct_arg) => match ct_arg.kind { - ConstArgKind::Anon(anon_const) => Some((tcx.typeck(did), tcx.hir_body(anon_const.body).value)), + ConstArgKind::Anon(anon_const) => Some((tcx.typeck(did), &tcx.hir_body(anon_const.body).value)), _ => None, }, } diff --git a/src/tools/clippy/clippy_lints/src/panic_in_result_fn.rs b/src/tools/clippy/clippy_lints/src/panic_in_result_fn.rs index 185acc53fa52d..144a0ac7a63eb 100644 --- a/src/tools/clippy/clippy_lints/src/panic_in_result_fn.rs +++ b/src/tools/clippy/clippy_lints/src/panic_in_result_fn.rs @@ -63,7 +63,7 @@ impl<'tcx> LateLintPass<'tcx> for PanicInResultFn { fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, body: &'tcx hir::Body<'tcx>) { let mut panics = Vec::new(); - let _: Option = for_each_expr(cx.tcx, body.value, |e| { + let _: Option = for_each_expr(cx.tcx, &body.value, |e| { let Some(macro_call) = root_macro_call_first_node(cx, e) else { return ControlFlow::Continue(Descend::Yes); }; diff --git a/src/tools/clippy/clippy_lints/src/ptr/mod.rs b/src/tools/clippy/clippy_lints/src/ptr/mod.rs index 04393dcf60d58..ce55c3f89514a 100644 --- a/src/tools/clippy/clippy_lints/src/ptr/mod.rs +++ b/src/tools/clippy/clippy_lints/src/ptr/mod.rs @@ -149,7 +149,7 @@ impl<'tcx> LateLintPass<'tcx> for Ptr { } } - fn check_body(&mut self, cx: &LateContext<'tcx>, body: &Body<'tcx>) { + fn check_body(&mut self, cx: &LateContext<'tcx>, body: &'tcx Body<'tcx>) { let mut parents = cx.tcx.hir_parent_iter(body.value.hir_id); let (item_id, sig, is_trait_item) = match parents.next() { Some((_, Node::Item(i))) => { diff --git a/src/tools/clippy/clippy_lints/src/ptr/mut_from_ref.rs b/src/tools/clippy/clippy_lints/src/ptr/mut_from_ref.rs index bc0fac8684cf1..ad44efd120fe5 100644 --- a/src/tools/clippy/clippy_lints/src/ptr/mut_from_ref.rs +++ b/src/tools/clippy/clippy_lints/src/ptr/mut_from_ref.rs @@ -7,7 +7,7 @@ use rustc_hir::{self as hir, Body, FnRetTy, FnSig, GenericArg, Lifetime, Mutabil use rustc_lint::LateContext; use rustc_span::Span; -pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, sig: &FnSig<'_>, body: Option<&Body<'tcx>>) { +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, sig: &FnSig<'_>, body: Option<&'tcx Body<'tcx>>) { let FnRetTy::Return(ty) = sig.decl.output else { return }; for (out, mutability, out_span) in get_lifetimes(ty) { if mutability != Some(Mutability::Mut) { @@ -26,7 +26,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, sig: &FnSig<'_>, body: Option< .collect(); if let Some(args_immut_refs) = args_immut_refs && !args_immut_refs.is_empty() - && body.is_none_or(|body| sig.header.is_unsafe() || contains_unsafe_block(cx, body.value)) + && body.is_none_or(|body| sig.header.is_unsafe() || contains_unsafe_block(cx, &body.value)) { span_lint_and_then( cx, diff --git a/src/tools/clippy/clippy_lints/src/ptr/ptr_arg.rs b/src/tools/clippy/clippy_lints/src/ptr/ptr_arg.rs index 96ab0345db0e0..c78ff74744b7d 100644 --- a/src/tools/clippy/clippy_lints/src/ptr/ptr_arg.rs +++ b/src/tools/clippy/clippy_lints/src/ptr/ptr_arg.rs @@ -24,7 +24,7 @@ use std::{fmt, iter}; pub(super) fn check_body<'tcx>( cx: &LateContext<'tcx>, - body: &Body<'tcx>, + body: &'tcx Body<'tcx>, item_id: OwnerId, sig: &FnSig<'tcx>, is_trait_item: bool, @@ -306,7 +306,7 @@ fn check_fn_args<'cx, 'tcx: 'cx>( } #[expect(clippy::too_many_lines)] -fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &Body<'tcx>, args: &[PtrArg<'tcx>]) -> Vec { +fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &'tcx Body<'tcx>, args: &[PtrArg<'tcx>]) -> Vec { struct V<'cx, 'tcx> { cx: &'cx LateContext<'tcx>, /// Map from a local id to which argument it came from (index into `Self::args` and diff --git a/src/tools/clippy/clippy_lints/src/redundant_async_block.rs b/src/tools/clippy/clippy_lints/src/redundant_async_block.rs index d696296301893..e2076d1731261 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_async_block.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_async_block.rs @@ -89,7 +89,7 @@ fn desugar_async_block<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Op .all(|place| matches!(place.info.capture_kind, UpvarCapture::ByValue)) }) }) - .then_some(body.value) + .then_some(&body.value) } else { None } diff --git a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs index 25c137dec7375..2cb17fcd586b5 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs @@ -94,29 +94,29 @@ fn find_innermost_closure<'tcx>( while let ExprKind::Closure(closure) = expr.kind && let body = cx.tcx.hir_body(closure.body) - && !contains_early_return(body.value) + && !contains_early_return(&body.value) && steps > 0 { - let mut unwrapped_body_value = body.value; + let mut unwrapped_body_value = &body.value; let mut asyncness = ty::Asyncness::No; let mut capture_clause = closure.capture_clause; if let ExprKind::Closure(inner_closure) = body.value.kind { if matches!(inner_closure.kind, DESUGARED_ASYNC_CLOSURE_KIND) { asyncness = ty::Asyncness::Yes; - unwrapped_body_value = cx.tcx.hir_body(inner_closure.body).value; + unwrapped_body_value = &cx.tcx.hir_body(inner_closure.body).value; } else if matches!(inner_closure.kind, DESUGARED_ASYNC_BLOCK_CLOSURE_KIND) { asyncness = ty::Asyncness::Yes; capture_clause = inner_closure.capture_clause; - unwrapped_body_value = cx.tcx.hir_body(inner_closure.body).value; + unwrapped_body_value = &cx.tcx.hir_body(inner_closure.body).value; } - if contains_early_return(unwrapped_body_value) { + if contains_early_return(&unwrapped_body_value) { break; } } - expr = body.value; + expr = &body.value; data = Some(( unwrapped_body_value, closure.fn_decl, @@ -201,7 +201,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { if let ExprKind::Closure(closure) = body.kind { // Like `async fn`, async closures are wrapped in an additional block // to move all of the closure's arguments into the future. - body = cx.tcx.hir_body(closure.body).value; + body = &cx.tcx.hir_body(closure.body).value; } // `async x` is a syntax error, so it becomes `async { x }` diff --git a/src/tools/clippy/clippy_lints/src/returns/needless_return.rs b/src/tools/clippy/clippy_lints/src/returns/needless_return.rs index 64a136d96a610..e3df1934e5ad1 100644 --- a/src/tools/clippy/clippy_lints/src/returns/needless_return.rs +++ b/src/tools/clippy/clippy_lints/src/returns/needless_return.rs @@ -70,7 +70,7 @@ pub(super) fn check_fn<'tcx>(cx: &LateContext<'tcx>, kind: FnKind<'tcx>, body: & } else { RetReplacement::Empty }; - check_final_expr(cx, body.value, vec![], replacement, None); + check_final_expr(cx, &body.value, vec![], replacement, None); }, FnKind::ItemFn(..) | FnKind::Method(..) => { check_block_return(cx, &body.value.kind, sp, vec![]); diff --git a/src/tools/clippy/clippy_lints/src/returns/needless_return_with_question_mark.rs b/src/tools/clippy/clippy_lints/src/returns/needless_return_with_question_mark.rs index d0ac03766b670..86683860cbb47 100644 --- a/src/tools/clippy/clippy_lints/src/returns/needless_return_with_question_mark.rs +++ b/src/tools/clippy/clippy_lints/src/returns/needless_return_with_question_mark.rs @@ -22,7 +22,7 @@ pub(super) fn check_stmt<'tcx>(cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { && maybe_constr.res(cx).ctor_parent(cx).is_lang_item(cx, ResultErr) // Ensure this is not the final stmt, otherwise removing it would cause a compile error - && let block = cx.tcx.hir_body_owned_by(cx.tcx.hir_enclosing_body_owner(expr.hir_id)).value + && let block = &cx.tcx.hir_body_owned_by(cx.tcx.hir_enclosing_body_owner(expr.hir_id)).value && let ExprKind::Block(block, _) = peel_async_body(block).kind && !is_inside_let_else(cx.tcx, expr) && let [.., final_stmt] = block.stmts diff --git a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs index 064c78d9d1eec..5e48b67fdb4db 100644 --- a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs +++ b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs @@ -73,7 +73,7 @@ impl<'tcx> LateLintPass<'tcx> for SignificantDropTightening<'tcx> { _: hir::def_id::LocalDefId, ) { self.apas.clear(); - let initial_dummy_stmt = dummy_stmt_expr(body.value); + let initial_dummy_stmt = dummy_stmt_expr(&body.value); let mut ap = AuxParams::new(&mut self.apas, &initial_dummy_stmt); StmtsChecker::new(&mut ap, cx, &mut self.type_cache).visit_body(body); for apa in ap.apas.values() { diff --git a/src/tools/clippy/clippy_lints/src/single_option_map.rs b/src/tools/clippy/clippy_lints/src/single_option_map.rs index 3ecb389fec896..66b62de82e2cd 100644 --- a/src/tools/clippy/clippy_lints/src/single_option_map.rs +++ b/src/tools/clippy/clippy_lints/src/single_option_map.rs @@ -50,7 +50,7 @@ impl<'tcx> LateLintPass<'tcx> for SingleOptionMap { if let FnRetTy::Return(_ret) = decl.output && matches!(kind, FnKind::ItemFn(_, _, _) | FnKind::Method(_, _)) { - let func_body = peel_blocks(body.value); + let func_body = peel_blocks(&body.value); if let ExprKind::MethodCall(method_name, callee, args, _span) = func_body.kind && method_name.ident.name == sym::map && let callee_type = cx.typeck_results().expr_ty(callee) diff --git a/src/tools/clippy/clippy_lints/src/string_patterns.rs b/src/tools/clippy/clippy_lints/src/string_patterns.rs index 5f29ea35beaf1..74c416ee3f21b 100644 --- a/src/tools/clippy/clippy_lints/src/string_patterns.rs +++ b/src/tools/clippy/clippy_lints/src/string_patterns.rs @@ -146,7 +146,7 @@ fn check_manual_pattern_char_comparison(cx: &LateContext<'_>, method_arg: &Expr< // We want to retrieve all the comparisons done. // They are ordered in a nested way and so we need to traverse the AST to collect them all. - if for_each_expr(cx.tcx, body.value, |sub_expr| -> ControlFlow<(), Descend> { + if for_each_expr(cx.tcx, &body.value, |sub_expr| -> ControlFlow<(), Descend> { match sub_expr.kind { ExprKind::Binary(op, left, right) if op.node == BinOpKind::Eq => { if left.res_local_id() == Some(binding) diff --git a/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs b/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs index 0ba88b8ae9048..e248d287987b6 100644 --- a/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs +++ b/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs @@ -92,7 +92,7 @@ fn check_expr_inner<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, bin ] .iter() .find(|&(ts, _)| ts.iter().any(|&t| Some(trait_id) == cx.tcx.lang_items().get(t))) - && count_binops(body.value) == 1 + && count_binops(&body.value) == 1 { span_lint( cx, diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs b/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs index 55089fbf1bcac..d9b593e2fa43e 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs @@ -67,7 +67,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'t // `std::mem::transmute(const { u64::MIN as *const u64 });` if let ExprKind::ConstBlock(ConstBlock { body, .. }) = arg.kind { // Strip out the const and run again - let block = cx.tcx.hir_body(body).value; + let block = &cx.tcx.hir_body(body).value; return check(cx, expr, block, to_ty); } diff --git a/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs b/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs index 94fcfef353db3..3af5bab642fb4 100644 --- a/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs +++ b/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs @@ -286,7 +286,7 @@ fn find_binding_use_scope<'tcx>( Some((_, Node::ImplItem(i))) if let ImplItemKind::Fn(_, body) = i.kind => body, _ => break None, }; - break Some(BindingUseRange::Param(tcx.hir_body(body).value)); + break Some(BindingUseRange::Param(&tcx.hir_body(body).value)); }, Some((_, Node::LetStmt(_))) if let Some((id, Node::Stmt(_))) = iter.next() diff --git a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs index e3b76b2b83452..8e84f39ee6530 100644 --- a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs +++ b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs @@ -450,7 +450,7 @@ impl<'tcx> LateLintPass<'tcx> for UnconditionalRecursion { ) { // If the function is a method... if let FnKind::Method(name, _) = kind - && let expr = expr_or_init(cx, body.value).peel_blocks() + && let expr = expr_or_init(cx, &body.value).peel_blocks() // Doesn't have a conditional return. && !has_conditional_return(body, expr) { diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_literal_bound.rs b/src/tools/clippy/clippy_lints/src/unnecessary_literal_bound.rs index 59987ad7ad817..02191ea8dd747 100644 --- a/src/tools/clippy/clippy_lints/src/unnecessary_literal_bound.rs +++ b/src/tools/clippy/clippy_lints/src/unnecessary_literal_bound.rs @@ -142,7 +142,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryLiteralBound { } // Check for all return statements returning literals - if check_explicit_returns_static_str(body.value) && check_implicit_returns_static_str(body) { + if check_explicit_returns_static_str(&body.value) && check_implicit_returns_static_str(body) { span_lint_and_sugg( cx, UNNECESSARY_LITERAL_BOUND, diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs index 0afb5c4d1d0ff..27019e756478a 100644 --- a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs +++ b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs @@ -118,7 +118,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps { // Check if all return expression respect the following condition and collect them. let mut suggs = Vec::new(); - let can_sugg = find_all_ret_expressions(cx, body.value, |ret_expr| { + let can_sugg = find_all_ret_expressions(cx, &body.value, |ret_expr| { if !ret_expr.span.from_expansion() // Check if a function call. && let ExprKind::Call(func, [arg]) = ret_expr.kind diff --git a/src/tools/clippy/clippy_lints/src/unused_self.rs b/src/tools/clippy/clippy_lints/src/unused_self.rs index 1e2d9ab27c3e6..8dc659f822206 100644 --- a/src/tools/clippy/clippy_lints/src/unused_self.rs +++ b/src/tools/clippy/clippy_lints/src/unused_self.rs @@ -64,7 +64,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedSelf { && let body = cx.tcx.hir_body(*body_id) && let [self_param, ..] = body.params && !is_local_used(cx, body, self_param.pat.hir_id) - && !is_todo_unimplemented_stub(cx, body.value) + && !is_todo_unimplemented_stub(cx, &body.value) { span_lint_and_help( cx, diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index a32a641c34ee5..84fe5c10eb4a8 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -140,7 +140,7 @@ fn check_item(cx: &LateContext<'_>, hir_id: HirId) { cx, hir_id, |v| { - v.expr(&v.bind("expr", body.value)); + v.expr(&v.bind("expr", &body.value)); }, Some(body), ); @@ -727,7 +727,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { } fn body(&self, body_id: &Binding) { - let expr = self.cx.tcx.hir_body(body_id.value).value; + let expr = &self.cx.tcx.hir_body(body_id.value).value; bind!(self, expr); chain!(self, "{expr} = &cx.tcx.hir_body({body_id}).value"); self.expr(expr); diff --git a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs index 828fb1d3313b4..48ec0c838f8c3 100644 --- a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs +++ b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs @@ -206,7 +206,7 @@ fn expr_search_pat(tcx: TyCtxt<'_>, e: &Expr<'_>) -> (Pat, Pat) { }, ExprKind::Closure(&Closure { body, .. }) => ( Pat::Str(""), - expr_search_pat_inner(tcx, tcx.hir_body(body).value, outer_span).1, + expr_search_pat_inner(tcx, &tcx.hir_body(body).value, outer_span).1, ), ExprKind::Block( Block { @@ -342,7 +342,7 @@ fn fn_kind_pat(tcx: TyCtxt<'_>, kind: &FnKind<'_>, body: &Body<'_>, hir_id: HirI let (mut start_pat, end_pat) = match kind { FnKind::ItemFn(.., header) => (fn_header_search_pat(*header), Pat::Str("")), FnKind::Method(.., sig) => (fn_header_search_pat(sig.header), Pat::Str("")), - FnKind::Closure => return (Pat::Str(""), expr_search_pat(tcx, body.value).1), + FnKind::Closure => return (Pat::Str(""), expr_search_pat(tcx, &body.value).1), }; match tcx.hir_node(hir_id) { Node::Item(Item { vis_span, .. }) diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index 0c7a9b36d97c5..239cf7cae8bf2 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -622,7 +622,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> { fn expr(&self, e: &Expr<'_>) -> Option { self.check_ctxt(e.span.ctxt()); match e.kind { - ExprKind::ConstBlock(ConstBlock { body, .. }) => self.expr(self.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) => self.qpath(qpath, e.hir_id), ExprKind::Block(block, _) => { @@ -695,7 +695,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> { /// leaves the local crate. pub fn eval_is_empty(&self, e: &Expr<'_>) -> Option { match e.kind { - ExprKind::ConstBlock(ConstBlock { body, .. }) => self.eval_is_empty(self.tcx.hir_body(body).value), + ExprKind::ConstBlock(ConstBlock { body, .. }) => self.eval_is_empty(&self.tcx.hir_body(body).value), ExprKind::DropTemps(e) => self.eval_is_empty(e), ExprKind::Lit(lit) => { if is_direct_expn_of(e.span, sym::cfg).is_some() { @@ -1184,9 +1184,9 @@ pub fn is_zero_integer_const(cx: &LateContext<'_>, expr: &Expr<'_>, ctxt: Syntax pub fn const_item_rhs_to_expr<'tcx>(tcx: TyCtxt<'tcx>, ct_rhs: ConstItemRhs<'tcx>) -> Option<&'tcx Expr<'tcx>> { match ct_rhs { - ConstItemRhs::Body(body_id) => Some(tcx.hir_body(body_id).value), + ConstItemRhs::Body(body_id) => Some(&tcx.hir_body(body_id).value), ConstItemRhs::Direct(const_arg) => match const_arg.kind { - ConstArgKind::Anon(anon) => Some(tcx.hir_body(anon.body).value), + ConstArgKind::Anon(anon) => Some(&tcx.hir_body(anon.body).value), ConstArgKind::Struct(..) | ConstArgKind::Tup(..) | ConstArgKind::Literal { .. } diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 4ef0a795b4766..15a778519f1cc 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -491,8 +491,8 @@ impl HirEqInterExpr<'_, '_, '_> { self.inner.cx.tcx.typeck_body(right), )); let res = self.eq_expr( - self.inner.cx.tcx.hir_body(left).value, - self.inner.cx.tcx.hir_body(right).value, + &self.inner.cx.tcx.hir_body(left).value, + &self.inner.cx.tcx.hir_body(right).value, ); self.inner.maybe_typeck_results = old_maybe_typeck_results; res @@ -1246,7 +1246,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { }) => { mem::discriminant(capture_clause).hash(&mut self.s); // closures inherit TypeckResults - self.hash_expr(self.cx.tcx.hir_body(*body).value); + self.hash_expr(&self.cx.tcx.hir_body(*body).value); }, ExprKind::ConstBlock(l_id) => { self.hash_body(l_id.body); @@ -1669,7 +1669,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { pub fn hash_body(&mut self, body_id: BodyId) { // swap out TypeckResults when hashing a body let old_maybe_typeck_results = self.maybe_typeck_results.replace(self.cx.tcx.typeck_body(body_id)); - self.hash_expr(self.cx.tcx.hir_body(body_id).value); + self.hash_expr(&self.cx.tcx.hir_body(body_id).value); self.maybe_typeck_results = old_maybe_typeck_results; } @@ -1805,7 +1805,7 @@ pub fn has_ambiguous_literal_in_expr(cx: &LateContext<'_>, expr: &Expr<'_>) -> b ExprKind::Closure(Closure { body, .. }) => { let body = cx.tcx.hir_body(*body); - let closure_expr = crate::peel_blocks(body.value); + let closure_expr = crate::peel_blocks(&body.value); has_ambiguous_literal_in_expr(cx, closure_expr) }, diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index cc73396f72246..3e62654d23f75 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -1779,7 +1779,7 @@ pub fn get_async_closure_expr<'tcx>(tcx: TyCtxt<'tcx>, expr: &Expr<'_>) -> Optio /// Peels away all the compiler generated code surrounding the body of an async function, pub fn get_async_fn_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Option<&'tcx Expr<'tcx>> { - get_async_closure_expr(tcx, body.value) + get_async_closure_expr(tcx, &body.value) } // check if expr is calling method or function with #[must_use] attribute @@ -1842,7 +1842,7 @@ fn is_body_identity_function<'hir>(cx: &LateContext<'_>, func: &Body<'hir>) -> b true }; - let mut expr = func.value; + let mut expr = &func.value; loop { match expr.kind { ExprKind::Block( diff --git a/src/tools/clippy/clippy_utils/src/visitors.rs b/src/tools/clippy/clippy_utils/src/visitors.rs index c5a101caebc21..df0435c62d457 100644 --- a/src/tools/clippy/clippy_utils/src/visitors.rs +++ b/src/tools/clippy/clippy_utils/src/visitors.rs @@ -299,7 +299,7 @@ where /// Checks if the given resolved path is used in the given body. pub fn is_res_used(cx: &LateContext<'_>, res: Res, body: BodyId) -> bool { - for_each_expr(cx.tcx, cx.tcx.hir_body(body).value, |e| { + for_each_expr(cx.tcx, &cx.tcx.hir_body(body).value, |e| { if let ExprKind::Path(p) = &e.kind && cx.qpath_res(p, e.hir_id) == res { From ac1b3f8478aa1e21819fa2344de5d920b0191f65 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 10 Oct 2026 17:12:39 +0200 Subject: [PATCH 11/34] sembr src/rustc-driver/intro.md --- src/doc/rustc-dev-guide/src/rustc-driver/intro.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/rustc-driver/intro.md b/src/doc/rustc-dev-guide/src/rustc-driver/intro.md index 687b2d49d094a..e3a19cfd96251 100644 --- a/src/doc/rustc-dev-guide/src/rustc-driver/intro.md +++ b/src/doc/rustc-dev-guide/src/rustc-driver/intro.md @@ -4,7 +4,8 @@ The [`rustc_driver`] is essentially `rustc`'s `main` function. It acts as the glue for running the various phases of the compiler in the correct order, -using the interface defined in the [`rustc_interface`] crate. Where possible, using [`rustc_driver`] rather than [`rustc_interface`] is recommended. +using the interface defined in the [`rustc_interface`] crate. +Where possible, using [`rustc_driver`] rather than [`rustc_interface`] is recommended. The main entry point of [`rustc_driver`] is [`rustc_driver::compiler_entrypoint`][rd_ce]. This builder accepts the same command-line args as rustc as well as an implementation of [`Callbacks`] and a couple of other optional options. From 885e56288b964172234c51d474e4837593e33a6d Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 10 Oct 2026 17:13:13 +0200 Subject: [PATCH 12/34] sembr src/solve/invariants.md --- .../rustc-dev-guide/src/solve/invariants.md | 74 +++++++++++-------- 1 file changed, 42 insertions(+), 32 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/solve/invariants.md b/src/doc/rustc-dev-guide/src/solve/invariants.md index 3379f77626d58..72aec4138a358 100644 --- a/src/doc/rustc-dev-guide/src/solve/invariants.md +++ b/src/doc/rustc-dev-guide/src/solve/invariants.md @@ -3,22 +3,22 @@ FIXME: This file talks about invariants of the type system as a whole, not only the solver There are a lot of invariants - things the type system guarantees to be true at all times - -which are desirable or expected from other languages and type systems. Unfortunately, quite -a few of them do not hold in Rust right now. This is either fundamental to its design or -caused by bugs, and something that may change in the future. +which are desirable or expected from other languages and type systems. +Unfortunately, quite a few of them do not hold in Rust right now. +This is either fundamental to its design or caused by bugs, +and something that may change in the future. It is important to know about the things you can assume while working on, and with, the -type system, so here's an incomplete and unofficial list of invariants of -the core type system: +type system, so here's an incomplete and unofficial list of invariants of the core type system: - ✅: this invariant mostly holds, with some weird exceptions or current bugs - ❌: this invariant does not hold, and is unlikely to do so in the future; do not rely on it for soundness or have to be incredibly careful when doing so ### `wf(X)` implies `wf(normalize(X))` ✅ -If a type containing aliases is well-formed, it should also be -well-formed after normalizing said aliases. We rely on this as -otherwise we would have to re-check for well-formedness for these +If a type containing aliases is well-formed, +it should also be well-formed after normalizing said aliases. +We rely on this as otherwise we would have to re-check for well-formedness for these types. This currently does not hold due to a type system unsoundness: [#84533](https://github.com/rust-lang/rust/issues/84533). @@ -26,8 +26,8 @@ This currently does not hold due to a type system unsoundness: [#84533](https:// ### Structural equality modulo regions implies semantic equality ✅ If you have a some type and equate it to itself after replacing any regions with unique -inference variables in both the lhs and rhs, the now potentially structurally different -types should still be equal to each other. +inference variables in both the lhs and rhs, +the now potentially structurally different types should still be equal to each other. This is needed to prevent goals from succeeding in HIR typeck and then failing in MIR borrowck. If this invariant is broken, MIR typeck ends up failing with an ICE. @@ -46,20 +46,24 @@ This unfortunately does not hold - at least in the new solver - due to a few ann ### The trait solver has to be *locally sound* ✅ -This means that we must never return *success* for goals for which no `impl` exists. That would -mean we assume a trait is implemented even though it is not, which is very likely to result in -actual unsoundness. When using `where`-bounds to prove a goal, the `impl` will be provided by the -user of the item. - -This invariant only holds if we check region constraints. As we do not check region constraints -during implicit negative overlap check in coherence, this invariant is broken there. As this check -relies on *completeness* of the trait solver, it is not able to use the current region constraints +This means that we must never return *success* for goals for which no `impl` exists. +That would mean we assume a trait is implemented even though it is not, +which is very likely to result in +actual unsoundness. +When using `where`-bounds to prove a goal, the `impl` will be provided by the user of the item. + +This invariant only holds if we check region constraints. +As we do not check region constraints during implicit negative overlap check in coherence, +this invariant is broken there. +As this check relies on *completeness* of the trait solver, +it is not able to use the current region constraints check - `InferCtxt::resolve_regions` - as its handling of type outlives goals is incomplete. ### Normalization of semantically equal aliases in empty environments results in a unique type ✅ -Normalization for alias types/consts has to have a unique result. Otherwise we can easily -implement transmute in safe code. Given the following function, we have to make sure that +Normalization for alias types/consts has to have a unique result. +Otherwise we can easily implement transmute in safe code. +Given the following function, we have to make sure that the input and output types always get normalized to the same concrete type. ```rust @@ -76,7 +80,8 @@ the issue is that the invariant is broken, not that we incorrectly rely on it. #### Successful normalization must not result in unconstrained inference variables ✅ -If a normalization goal succeeds, it must not result in unconstrained type or const inference variables. This not being the case causes type equality to not be transitive. +If a normalization goal succeeds, it must not result in unconstrained type or const inference variables. +This not being the case causes type equality to not be transitive. This requirement also has to hold for invalid code to avoid compiler ICE: - this is subtly broken with the old solver: https://github.com/rust-lang/rust/issues/135122 @@ -101,11 +106,13 @@ Having a goal which succeeds during HIR typeck but fails when being reevaluated Having a goal which succeeds during HIR typeck but fails after being instantiated is unsound, e.g. [#140212](https://github.com/rust-lang/rust/issues/140212). -It is interesting that we allow some incompleteness in the trait solver while still maintaining this limitation. It would be nice if there was a clear way to separate the "allowed incompleteness" from behavior which would break this invariant. +It is interesting that we allow some incompleteness in the trait solver while still maintaining this limitation. +It would be nice if there was a clear way to separate the "allowed incompleteness" from behavior which would break this invariant. #### Normalization must not change results -This invariant is relied on to allow the normalization of generic aliases. Breaking +This invariant is relied on to allow the normalization of generic aliases. +Breaking it can easily result in unsoundness, e.g. [#57893](https://github.com/rust-lang/rust/issues/57893). #### Goals may still overflow after instantiation @@ -117,8 +124,8 @@ It's unclear how these should be handled :3 ### Trait goals in empty environments are proven by a unique impl ✅ If a trait goal holds with an empty environment, there should be a unique `impl`, -either user-defined or builtin, which is used to prove that goal. This is -necessary to select unique methods and associated items. +either user-defined or builtin, which is used to prove that goal. +This is necessary to select unique methods and associated items. We do however break this invariant in a few cases, some of which are due to bugs, some by design: - *marker traits* are allowed to overlap as they do not have associated items @@ -131,7 +138,8 @@ We do however break this invariant in a few cases, some of which are due to bugs If a goal can be proven in a generic environment, the goal should still hold after instantiating it with fully concrete types and no where-clauses in scope. -This is assumed by codegen which ICEs when encountering non-overflow ambiguity. This invariant is currently broken by specialization ([#147507](https://github.com/rust-lang/rust/issues/147507)) and by marker traits ([#149502](https://github.com/rust-lang/rust/issues/149502)). +This is assumed by codegen which ICEs when encountering non-overflow ambiguity. +This invariant is currently broken by specialization ([#147507](https://github.com/rust-lang/rust/issues/147507)) and by marker traits ([#149502](https://github.com/rust-lang/rust/issues/149502)). #### The type system is complete during the implicit negative overlap check in coherence ✅ @@ -149,15 +157,16 @@ We have to be careful as it is quite easy to break: ### Trait solving must not depend on lifetimes being different ✅ -If a goal holds with lifetimes being different, it must also hold with these lifetimes being the same. We otherwise get post-monomorphization errors during codegen or unsoundness due to invalid vtables. +If a goal holds with lifetimes being different, it must also hold with these lifetimes being the same. +We otherwise get post-monomorphization errors during codegen or unsoundness due to invalid vtables. We could also just get inconsistent behavior when first proving a goal with different lifetimes which are later constrained to be equal. ### Trait solving in bodies must not depend on lifetimes being equal ✅ We also have to be careful with relying on equality of regions in the trait solver. -This is fine for codegen, as we treat all erased regions as equal. We can however -lose equality information from HIR to MIR typeck. +This is fine for codegen, as we treat all erased regions as equal. +We can however lose equality information from HIR to MIR typeck. This currently does not hold with the new solver: [trait-system-refactor-initiative#27](https://github.com/rust-lang/trait-system-refactor-initiative/issues/27). @@ -172,8 +181,8 @@ and improving inference can result in inference changes, breaking existing proje ### Semantic equality implies structural equality ✅ Two types being equal in the type system must mean that they have the -same `TypeId` after instantiating their generic parameters with concrete -arguments. We can otherwise use their different `TypeId`s to impact trait selection. +same `TypeId` after instantiating their generic parameters with concrete arguments. +We can otherwise use their different `TypeId`s to impact trait selection. We lookup types using structural equality during codegen, but this shouldn't necessarily be unsound - may result in redundant method codegen or backend type check errors? @@ -186,7 +195,8 @@ for example `for<'a> fn(&'a str)` vs `fn(&'static str)` must have a different `T ## Evaluation of const items is deterministic ✅ -As the values of const items can feed into the type system, it is important that the value of a const item is always the same in every crate. If this isn't the case then we can wind up with associated types with "equal" const arguments and so are "equal" associated types, and yet when normalized during codegen in different crates actually wind up as different types. +As the values of const items can feed into the type system, it is important that the value of a const item is always the same in every crate. +If this isn't the case then we can wind up with associated types with "equal" const arguments and so are "equal" associated types, and yet when normalized during codegen in different crates actually wind up as different types. Notably this does *not* extend to const *functions*, as the type system only works with the results of const *items* it's actually fine for const functions to be non deterministic so long as that doesn't affect the final value of a const item. From 4fa1e59d72744ecb092d31e2eeb867a00592bc0f Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 10 Oct 2026 17:19:17 +0200 Subject: [PATCH 13/34] improve solve/invariants.md --- src/doc/rustc-dev-guide/src/solve/invariants.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/solve/invariants.md b/src/doc/rustc-dev-guide/src/solve/invariants.md index 72aec4138a358..c867105b22baa 100644 --- a/src/doc/rustc-dev-guide/src/solve/invariants.md +++ b/src/doc/rustc-dev-guide/src/solve/invariants.md @@ -196,7 +196,7 @@ for example `for<'a> fn(&'a str)` vs `fn(&'static str)` must have a different `T ## Evaluation of const items is deterministic ✅ As the values of const items can feed into the type system, it is important that the value of a const item is always the same in every crate. -If this isn't the case then we can wind up with associated types with "equal" const arguments and so are "equal" associated types, and yet when normalized during codegen in different crates actually wind up as different types. +If this isn't the case, we could wind up with associated types with "equal" const arguments and so are "equal" associated types, and yet when normalized during codegen in different crates actually wind up as different types. Notably this does *not* extend to const *functions*, as the type system only works with the results of const *items* it's actually fine for const functions to be non deterministic so long as that doesn't affect the final value of a const item. From e85e06f9317f1ad6f7aacb2f9138fe8d23bd026e Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 10 Oct 2026 17:19:32 +0200 Subject: [PATCH 14/34] reflow src/solve/invariants.md --- src/doc/rustc-dev-guide/src/solve/invariants.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/solve/invariants.md b/src/doc/rustc-dev-guide/src/solve/invariants.md index c867105b22baa..fb1fe5ced27d7 100644 --- a/src/doc/rustc-dev-guide/src/solve/invariants.md +++ b/src/doc/rustc-dev-guide/src/solve/invariants.md @@ -18,8 +18,7 @@ type system, so here's an incomplete and unofficial list of invariants of the co If a type containing aliases is well-formed, it should also be well-formed after normalizing said aliases. -We rely on this as otherwise we would have to re-check for well-formedness for these -types. +We rely on this as otherwise we would have to re-check for well-formedness for these types. This currently does not hold due to a type system unsoundness: [#84533](https://github.com/rust-lang/rust/issues/84533). @@ -48,8 +47,7 @@ This unfortunately does not hold - at least in the new solver - due to a few ann This means that we must never return *success* for goals for which no `impl` exists. That would mean we assume a trait is implemented even though it is not, -which is very likely to result in -actual unsoundness. +which is very likely to result in actual unsoundness. When using `where`-bounds to prove a goal, the `impl` will be provided by the user of the item. This invariant only holds if we check region constraints. From 78ae36c1f65d6fc5084da452e6f3776e326584b9 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 10 Oct 2026 17:21:46 +0200 Subject: [PATCH 15/34] reflow src/tests/directives.md --- .../rustc-dev-guide/src/tests/directives.md | 74 +++++++++---------- 1 file changed, 36 insertions(+), 38 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/directives.md b/src/doc/rustc-dev-guide/src/tests/directives.md index a12b602d9c2d6..02ff273ada8a2 100644 --- a/src/doc/rustc-dev-guide/src/tests/directives.md +++ b/src/doc/rustc-dev-guide/src/tests/directives.md @@ -118,8 +118,8 @@ comparison](ui.md#output-comparison) and [Rustfix tests](ui.md#rustfix-tests) fo ### Controlling when tests are run -These directives are used to ignore the test in some situations, which -means the test won't be compiled or run. +These directives are used to ignore the test in some situations, +which means the test won't be compiled or run. * `ignore-X` where `X` is a target detail or other criteria on which to ignore the test (see below) * `only-X` is like `ignore-X`, but will *only* run the test on that target or stage @@ -127,8 +127,8 @@ means the test won't be compiled or run. main test files but that `compiletest` should not try to build the file itself. Please backlink to which main test is actually using the auxiliary file. * `ignore-test` always ignores the test. - This can be used to temporarily disable - a test if it is currently not working, but you want to keep it in-tree to re-enable it later. + This can be used to temporarily disable a test if it is currently not working, + but you want to keep it in-tree to re-enable it later. Some examples of `X` in `ignore-X` or `only-X`: @@ -150,8 +150,8 @@ Some examples of `X` in `ignore-X` or `only-X`: - When the [parallel frontend] is enabled: `ignore-parallel-frontend` - Specific [compare modes]: `compare-mode-polonius`, `compare-mode-next-solver`, `compare-mode-split-dwarf`, `compare-mode-split-dwarf-single` -- The two different test modes used by coverage tests: - `ignore-coverage-map`, `ignore-coverage-run` +- The two different test modes used by coverage tests: `ignore-coverage-map`, + `ignore-coverage-run` - When testing a dist toolchain: `dist` - This needs to be enabled with `COMPILETEST_ENABLE_DIST_TESTS=1` - The `rustc_abi` of the target: e.g. `rustc_abi-x86_64-sse2` @@ -160,9 +160,8 @@ The following directives will check rustc build settings and target settings: - `needs-asm-support` — ignores if the **host** architecture doesn't have stable support for `asm!`. - For tests that cross-compile to explicit targets - via `--target`, use `needs-llvm-components` instead to ensure the appropriate - backend is available. + For tests that cross-compile to explicit targets via `--target`, + use `needs-llvm-components` instead to ensure the appropriate backend is available. - `needs-asm-ret` - ignores if the target does not have a `ret` instruction in its assembly syntax. Most target architectures have this instruction, @@ -174,10 +173,10 @@ The following directives will check rustc build settings and target settings: for the target (`build.sanitizers = true` in `bootstrap.toml`) - `needs-sanitizer-{address,hwaddress,leak,memory,thread}` — ignores if the corresponding sanitizer is not enabled for the target (AddressSanitizer, - hardware-assisted AddressSanitizer, LeakSanitizer, MemorySanitizer or - ThreadSanitizer respectively) -- `needs-run-enabled` — ignores if it is a test that gets executed, and running - has been disabled. + hardware-assisted AddressSanitizer, LeakSanitizer, + MemorySanitizer or ThreadSanitizer respectively) +- `needs-run-enabled` — ignores if it is a test that gets executed, + and running has been disabled. Running tests can be disabled with the `x test --run=never` flag, or running on fuchsia. - `needs-unwind` — ignores if the target does not support unwinding - `needs-rust-lld` — ignores if the rust lld support is not enabled (`rust.lld = @@ -230,8 +229,8 @@ The following directives will check LLVM support: `COMPILETEST_REQUIRE_ALL_LLVM_COMPONENTS` is set) if the component does not exist. - `needs-forced-clang-based-tests` — test is ignored unless the environment variable `RUSTBUILD_FORCE_CLANG_BASED_TESTS` is set, which enables building clang alongside LLVM - - This is only set in two CI jobs ([`test-x86_64-gnu-debug`] and - [`test-aarch64-gnu-debug`]), which only runs a subset of `run-make` tests. + - This is only set in two CI jobs ([`test-x86_64-gnu-debug`] and [`test-aarch64-gnu-debug`]), + which only runs a subset of `run-make` tests. Other tests with this directive will not run at all, which is usually not what you want. See also [Debuginfo tests](compiletest.md#debuginfo-tests) for directives for ignoring debuggers. @@ -327,15 +326,15 @@ See [Pretty-printer](compiletest.md#pretty-printer-tests). ### Tool-specific directives -The following directives affect how certain command-line tools are invoked, in -test suites that use those tools: +The following directives affect how certain command-line tools are invoked, +in test suites that use those tools: - `skip-filecheck` avoids running LLVM's `FileCheck` tool in tests that would normally run it to check output. - Used by codegen tests, assembly tests, and mir-opt tests. - `filecheck-flags` adds extra flags when running LLVM's `FileCheck` tool. - Used by [codegen tests](compiletest.md#codegen-tests), - [assembly tests](compiletest.md#assembly-tests), and - [MIR-opt tests](compiletest.md#mir-opt-tests). + [assembly tests](compiletest.md#assembly-tests), + and [MIR-opt tests](compiletest.md#mir-opt-tests). - `llvm-cov-flags` adds extra flags when running LLVM's `llvm-cov` tool. - Used by [coverage tests](compiletest.md#coverage-tests) in `coverage-run` mode. @@ -353,8 +352,8 @@ The following directives control how the [tidy script](../conventions.md#formatt Directive values support substituting a few variables which will be replaced with their corresponding value. -For example, if you need to pass a compiler flag -with a path to a specific file, something like the following could work: +For example, if you need to pass a compiler flag with a path to a specific file, +something like the following could work: ```rust,ignore //@ compile-flags: --remap-path-prefix={{src-base}}=/the/src @@ -408,8 +407,8 @@ When `compiletest` encounters a test file, it parses the file a line at a time by calling every parser defined in the `Config` struct's implementation block, also in [`src/tools/compiletest/src/directives.rs`] (note that the `Config` struct's declaration block is found in [`src/tools/compiletest/src/common.rs`]). -`TestProps`'s `load_from()` method will try passing the current line of text to -each parser, which, in turn typically checks to see if the line begins with a +`TestProps`'s `load_from()` method will try passing the current line of text to each parser, +which, in turn typically checks to see if the line begins with a particular commented (`//@`) directive such as `//@ must-compile-successfully` or `//@ failure-status`. Whitespace after the comment marker is optional. @@ -422,16 +421,15 @@ Parsers defined in `impl Config` are typically named `parse_` (note kebab-case `` transformed to snake-case ``). `impl Config` also defines several 'low-level' parsers which make it simple to parse common patterns like simple presence or not -(`parse_name_directive()`), `directive:parameter(s)` -(`parse_name_value_directive()`), optional parsing only if a particular `cfg` -attribute is defined (`has_cfg_prefix()`) and many more. +(`parse_name_directive()`), `directive:parameter(s)` (`parse_name_value_directive()`), +optional parsing only if a particular `cfg` attribute is defined (`has_cfg_prefix()`) and many more. The low-level parsers are found near the end of the `impl Config` block; be sure to look through them and their associated parsers immediately above to see how they are used to avoid writing additional parsing code unnecessarily. -As a concrete example, here is the implementation for the -`parse_failure_status()` parser, in [`src/tools/compiletest/src/directives.rs`]: +As a concrete example, here is the implementation for the `parse_failure_status()` parser, +in [`src/tools/compiletest/src/directives.rs`]: ```diff @@ -232,6 +232,7 @@ pub struct TestProps { @@ -475,19 +473,19 @@ As a concrete example, here is the implementation for the ### Implementing the behavior change -When a test invokes a particular directive, it is expected that some behavior -will change as a result. +When a test invokes a particular directive, +it is expected that some behavior will change as a result. What behavior, obviously, will depend on the purpose of the directive. In the case of `failure-status`, the behavior that changes is -that `compiletest` expects the failure code defined by the directive invoked in -the test, rather than the default value. +that `compiletest` expects the failure code defined by the directive invoked in the test, +rather than the default value. Although specific to `failure-status` (as every directive will have a different implementation in order to invoke behavior change) perhaps it is helpful to see the behavior change implementation of one case, simply as an example. To implement `failure-status`, the `check_correct_failure_status()` function found -in the `TestCx` implementation block, located in -[`src/tools/compiletest/src/runtest.rs`], was modified as per below: +in the `TestCx` implementation block, located in [`src/tools/compiletest/src/runtest.rs`], +was modified as per below: ```diff @@ -295,11 +295,14 @@ impl<'test> TestCx<'test> { @@ -529,10 +527,10 @@ in the `TestCx` implementation block, located in Note the use of `self.props.failure_status` to access the directive property. In tests which do not specify the failure status directive, `self.props.failure_status` will evaluate to the default value of 101 at the time of this writing. -But for a test which specifies a directive of, for -example, `//@ failure-status: 1`, `self.props.failure_status` will evaluate to -1, as `parse_failure_status()` will have overridden the `TestProps` default -value, for that test specifically. +But for a test which specifies a directive of, for example, +`//@ failure-status: 1`, `self.props.failure_status` will evaluate to 1, +as `parse_failure_status()` will have overridden the `TestProps` default value, +for that test specifically. [`src/tools/compiletest/src/directives.rs`]: https://github.com/rust-lang/rust/tree/HEAD/src/tools/compiletest/src/directives.rs [`src/tools/compiletest/src/common.rs`]: https://github.com/rust-lang/rust/tree/HEAD/src/tools/compiletest/src/common.rs From 9d0b35c74dc9091d60c65705526df69d367301e1 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 10 Oct 2026 17:28:35 +0200 Subject: [PATCH 16/34] improve tests/directives.md --- src/doc/rustc-dev-guide/src/tests/directives.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/directives.md b/src/doc/rustc-dev-guide/src/tests/directives.md index 02ff273ada8a2..ed6c8b9f93951 100644 --- a/src/doc/rustc-dev-guide/src/tests/directives.md +++ b/src/doc/rustc-dev-guide/src/tests/directives.md @@ -150,8 +150,8 @@ Some examples of `X` in `ignore-X` or `only-X`: - When the [parallel frontend] is enabled: `ignore-parallel-frontend` - Specific [compare modes]: `compare-mode-polonius`, `compare-mode-next-solver`, `compare-mode-split-dwarf`, `compare-mode-split-dwarf-single` -- The two different test modes used by coverage tests: `ignore-coverage-map`, - `ignore-coverage-run` +- The two different test modes used by coverage tests: + `ignore-coverage-map` and `ignore-coverage-run` - When testing a dist toolchain: `dist` - This needs to be enabled with `COMPILETEST_ENABLE_DIST_TESTS=1` - The `rustc_abi` of the target: e.g. `rustc_abi-x86_64-sse2` @@ -408,7 +408,7 @@ by calling every parser defined in the `Config` struct's implementation block, also in [`src/tools/compiletest/src/directives.rs`] (note that the `Config` struct's declaration block is found in [`src/tools/compiletest/src/common.rs`]). `TestProps`'s `load_from()` method will try passing the current line of text to each parser, -which, in turn typically checks to see if the line begins with a +which, in turn, typically checks to see if the line begins with a particular commented (`//@`) directive such as `//@ must-compile-successfully` or `//@ failure-status`. Whitespace after the comment marker is optional. From d84ad96e56770a850f8ff7dba102707beba331de Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 10 Oct 2026 17:29:17 +0200 Subject: [PATCH 17/34] reflow src/thir.md --- src/doc/rustc-dev-guide/src/thir.md | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/thir.md b/src/doc/rustc-dev-guide/src/thir.md index 63679b50ecf40..17d10e3ebb834 100644 --- a/src/doc/rustc-dev-guide/src/thir.md +++ b/src/doc/rustc-dev-guide/src/thir.md @@ -3,8 +3,8 @@ The THIR ("Typed High-Level Intermediate Representation"), previously called HAIR for "High-Level Abstract IR", is another IR used by rustc that is generated after [type checking]. It is (as of October 2026) used for -[MIR construction], [exhaustiveness checking], [unsafety checking], and -[explicit tail call checking]. +[MIR construction], [exhaustiveness checking], [unsafety checking], +and [explicit tail call checking]. [type checking]: ./hir-typeck/summary.md [MIR construction]: ./mir/construction.md @@ -21,15 +21,14 @@ But it has some other interesting features that distinguish it from the HIR: Specifically, all [body owners] have THIR created. Consequently, the THIR has no representation for items like `struct`s or `trait`s. -- Each body of THIR is only stored temporarily and is dropped as soon as it's no longer - needed, as opposed to being stored until the end of the compilation process (which +- Each body of THIR is only stored temporarily and is dropped as soon as it's no longer needed, + as opposed to being stored until the end of the compilation process (which is what is done with the HIR). -- Besides making the types of all nodes available, the THIR also has additional - desugaring compared to the HIR. - For example, automatic references and dereferences - are made explicit, and method calls and overloaded operators are converted into - plain function calls. +- Besides making the types of all nodes available, + the THIR also has additional desugaring compared to the HIR. + For example, automatic references and dereferences are made explicit, + and method calls and overloaded operators are converted into plain function calls. Destruction scopes are also made explicit. - Statements, expressions, match arms, blocks, and parameters are stored separately. From e4e2eae5fd9ea7a4639f2e1b8284fea00b5499a7 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 10 Oct 2026 17:40:42 +0200 Subject: [PATCH 18/34] sembr src/hir-typeck/coercions.md --- src/doc/rustc-dev-guide/src/hir-typeck/coercions.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/hir-typeck/coercions.md b/src/doc/rustc-dev-guide/src/hir-typeck/coercions.md index b977e8f3082be..ffa1d8cb0fbf5 100644 --- a/src/doc/rustc-dev-guide/src/hir-typeck/coercions.md +++ b/src/doc/rustc-dev-guide/src/hir-typeck/coercions.md @@ -248,7 +248,8 @@ the lub type relation will switch to invariance. This enforces that the binders of the higher ranked types are equivalent which avoids the need to pick a "most general" binder, which would be quite difficult to do. -It also avoids the process of computing a mutual supertype being *order dependent*. Given the types `a` and `b`, it may be nice if computing the mutual supertype of `a` and `b` would yield the same result as computing the mutual supertype of `b` and `a`. +It also avoids the process of computing a mutual supertype being *order dependent*. +Given the types `a` and `b`, it may be nice if computing the mutual supertype of `a` and `b` would yield the same result as computing the mutual supertype of `b` and `a`. The current issues with higher ranked types and subtyping would cause this property to not hold if we were to use the naive method of computing a mutual supertype. From 311a2a57fbcd850277b45e96530b4df5e12ea907 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 10 Oct 2026 18:12:19 +0200 Subject: [PATCH 19/34] sembr: reduce indentation --- src/doc/rustc-dev-guide/ci/sembr/src/main.rs | 33 ++++++++++---------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/doc/rustc-dev-guide/ci/sembr/src/main.rs b/src/doc/rustc-dev-guide/ci/sembr/src/main.rs index 54c716959e154..500609c414d9f 100644 --- a/src/doc/rustc-dev-guide/ci/sembr/src/main.rs +++ b/src/doc/rustc-dev-guide/ci/sembr/src/main.rs @@ -112,23 +112,24 @@ fn comply(content: &str) -> String { if in_code_block || ignore(&line) { continue; } - if REGEX_SPLIT.is_match(&line) { - let indent = if let Some(regex_match) = REGEX_LIST_ENTRY.find(&line) { - regex_match.len() - } else { - line.find(|ch: char| !ch.is_whitespace()).unwrap() - }; - let mut newly_split_lines = line.split_inclusive(&*REGEX_SPLIT); - let first = newly_split_lines.next().unwrap().trim_end().to_owned(); - let mut remaining: Vec<_> = newly_split_lines - .map(|portion| format!("{:indent$}{}", "", portion.trim_end())) - .collect(); - let mut new_lines = Vec::new(); - new_lines.push(first); - new_lines.append(&mut remaining); - new_content.splice(new_n..=new_n, new_lines.clone()); - new_n += new_lines.len() - 1; + if !REGEX_SPLIT.is_match(&line) { + continue; } + let indent = if let Some(regex_match) = REGEX_LIST_ENTRY.find(&line) { + regex_match.len() + } else { + line.find(|ch: char| !ch.is_whitespace()).unwrap() + }; + let mut newly_split_lines = line.split_inclusive(&*REGEX_SPLIT); + let first = newly_split_lines.next().unwrap().trim_end().to_owned(); + let mut remaining: Vec<_> = newly_split_lines + .map(|portion| format!("{:indent$}{}", "", portion.trim_end())) + .collect(); + let mut new_lines = Vec::new(); + new_lines.push(first); + new_lines.append(&mut remaining); + new_content.splice(new_n..=new_n, new_lines.clone()); + new_n += new_lines.len() - 1; } new_content.join("\n") + "\n" } From cf021fda8fd48b5df6fe8f56892de0a4dc99a937 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sun, 11 Oct 2026 10:39:13 +0200 Subject: [PATCH 20/34] overlong sentence should be split if it has a comma --- src/doc/rustc-dev-guide/ci/sembr/src/main.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/ci/sembr/src/main.rs b/src/doc/rustc-dev-guide/ci/sembr/src/main.rs index 500609c414d9f..b74fce76012d4 100644 --- a/src/doc/rustc-dev-guide/ci/sembr/src/main.rs +++ b/src/doc/rustc-dev-guide/ci/sembr/src/main.rs @@ -174,6 +174,15 @@ fn reformat(content: &str, limit: usize) -> String { if ignore(line) || REGEX_SPLIT.is_match(line) { continue; } + const SEP: &str = ", "; + if line.contains(SEP) && line.len() > limit { + let indent = line.find(|ch: char| !ch.is_whitespace()).unwrap(); + let (before_sep, after_sep) = line.rsplit_once(SEP).unwrap(); + new_content[new_n] = format!("{before_sep}{}", SEP.trim_end()); + new_n += 1; + new_content.insert(new_n, format!("{:indent$}{after_sep}", "")); + continue; + } let Some(next_line) = content.get(n + 1) else { continue; }; @@ -192,7 +201,6 @@ fn reformat(content: &str, limit: usize) -> String { skip_next = true; continue; } - const SEP: &str = ", "; let indent = next_line.find(|ch: char| !ch.is_whitespace()).unwrap(); if next_line.contains(SEP) { let (before_sep, after_sep) = next_line.split_once(SEP).unwrap(); @@ -327,6 +335,8 @@ comma (filler), of next line split on comma (filler), of next line + this overlong, sentence, should be split in two + [a target]: https://example.com [another target]: https://example.com "; @@ -370,6 +380,9 @@ of next line split on comma (filler), of next line + this overlong, sentence, + should be split in two + [a target]: https://example.com [another target]: https://example.com "; From a385ff20dea743e670a0250427266e6a1a23057a Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sun, 11 Oct 2026 10:40:22 +0200 Subject: [PATCH 21/34] sembr src/hir-typeck/method-lookup.md --- .../src/hir-typeck/method-lookup.md | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/hir-typeck/method-lookup.md b/src/doc/rustc-dev-guide/src/hir-typeck/method-lookup.md index 6204f7f24ed45..3e38e29f588b9 100644 --- a/src/doc/rustc-dev-guide/src/hir-typeck/method-lookup.md +++ b/src/doc/rustc-dev-guide/src/hir-typeck/method-lookup.md @@ -39,9 +39,9 @@ Therefore, it does not include inference variables or other information. ### Steps -The first thing that the probe phase does is to create a series of -*steps*. This is done by progressively dereferencing the receiver type -until it cannot be deref'd anymore, as well as applying an optional "unsize" step. +The first thing that the probe phase does is to create a series of *steps*. +This is done by progressively dereferencing the receiver type until it cannot be deref'd anymore, +as well as applying an optional "unsize" step. So if the receiver has type `Rc>`, this might yield: 1. `Rc>` @@ -51,8 +51,8 @@ So if the receiver has type `Rc>`, this might yield: ### Candidate assembly -We then search along those steps to create a list of *candidates*. A -`Candidate` is a method item that might plausibly be the method being invoked. +We then search along those steps to create a list of *candidates*. +A `Candidate` is a method item that might plausibly be the method being invoked. For each candidate, we'll derive a "transformed self type" that takes into account explicit self. Candidates are grouped into two kinds, inherent and extension. @@ -71,8 +71,8 @@ trait methods (`to_string()`, in this case) are inherently associated with it. Another case is type parameters, in which case the methods of their bounds are inherent. However, this part of the rules is subject to change: when DST's "impl Trait for Trait" is complete, trait object -dispatch could be subsumed into trait matching, and the type parameter -behavior should be reconsidered in light of where clauses. +dispatch could be subsumed into trait matching, +and the type parameter behavior should be reconsidered in light of where clauses. Is this still accurate? --> @@ -96,11 +96,11 @@ Then we might have two candidates: Finally, to actually pick the method, we will search down the steps, trying to match the receiver type against the candidate types. -At each step, we also consider an auto-ref and auto-mut-ref to see whether -that makes any of the candidates match. +At each step, +we also consider an auto-ref and auto-mut-ref to see whether that makes any of the candidates match. For each resulting receiver type, we consider inherent candidates before extension candidates. -If there are multiple matching candidates in a group, we report an -error, except that multiple impls of the same trait are treated as a single match. +If there are multiple matching candidates in a group, we report an error, +except that multiple impls of the same trait are treated as a single match. Otherwise we pick the first match we find. In the case of our example, the first step is `Rc>`, From 863b9374ce140673e1ab72b33de06c617ddcd579 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sun, 11 Oct 2026 11:05:56 +0200 Subject: [PATCH 22/34] sembr src/queries/incremental-compilation.md --- .../src/queries/incremental-compilation.md | 58 +++++++++---------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/queries/incremental-compilation.md b/src/doc/rustc-dev-guide/src/queries/incremental-compilation.md index 079a2b2e00a7f..143f331e7d628 100644 --- a/src/doc/rustc-dev-guide/src/queries/incremental-compilation.md +++ b/src/doc/rustc-dev-guide/src/queries/incremental-compilation.md @@ -1,7 +1,7 @@ # Incremental compilation -The incremental compilation scheme is, in essence, a surprisingly -simple extension to the overall query system. +The incremental compilation scheme is, in essence, +a surprisingly simple extension to the overall query system. We'll start by describing a slightly simplified variant of the real thing – the "basic algorithm" – and then describe some possible improvements. @@ -10,8 +10,8 @@ and then describe some possible improvements. The basic algorithm is called the **red-green** algorithm[^salsa]. The high-level idea is that, after each run of the compiler, we will save the results of all -the queries that we do, as well as the **query DAG**. The -**query DAG** is a [DAG] that indexes which queries executed which other queries. +the queries that we do, as well as the **query DAG**. +The **query DAG** is a [DAG] that indexes which queries executed which other queries. So, for example, there would be an [edge] from a query Q1 to another query Q2 if computing Q1 required computing Q2 (note that because queries cannot depend on themselves, this results in a DAG and not a general graph). @@ -32,35 +32,35 @@ because queries cannot depend on themselves, this results in a DAG and not a gen > In short, the word query is here not just used to mean the definition of a query, > but also for a specific instance of that query with given arguments. -On the next run of the compiler, then, we can sometimes reuse these -query results to avoid re-executing a query. +On the next run of the compiler, then, +we can sometimes reuse these query results to avoid re-executing a query. We do this by assigning every query a **color**: -- If a query is colored **red**, that means that its result during - this compilation has **changed** from the previous compilation. -- If a query is colored **green**, that means that its result is - the **same** as the previous compilation. +- If a query is colored **red**, + that means that its result during this compilation has **changed** from the previous compilation. +- If a query is colored **green**, + that means that its result is the **same** as the previous compilation. There are two key insights here: -- First, if all the inputs to query Q are colored green, then the - query Q **must** result in the same value as last time and hence +- First, if all the inputs to query Q are colored green, + then the query Q **must** result in the same value as last time and hence need not be re-executed (or else the compiler is not deterministic). -- Second, even if some inputs to a query changes, it may be that it - **still** produces the same result as the previous compilation. +- Second, even if some inputs to a query changes, + it may be that it **still** produces the same result as the previous compilation. In particular, the query may only use part of its input. - - Therefore, after executing a query, we always check whether it - produced the same result as the previous time. - **If it did,** we can still mark the query as green, and hence avoid re-executing - dependent queries. + - Therefore, after executing a query, + we always check whether it produced the same result as the previous time. + **If it did,** we can still mark the query as green, + and hence avoid re-executing dependent queries. ### The try-mark-green algorithm At the core of incremental compilation is an algorithm called "try-mark-green". It has the job of determining the color of a given query Q (which must not have yet been executed). In cases where Q has red inputs, determining Q's color may involve re-executing Q so that -we can compare its output, but if all of Q's inputs are green, then we -can conclude that Q must be green without re-executing it or inspecting its value at all. +we can compare its output, but if all of Q's inputs are green, +then we can conclude that Q must be green without re-executing it or inspecting its value at all. In the compiler, this allows us to avoid deserializing the result from disk when we don't need it, and in fact enables us to sometimes skip *serializing* the result as well (see the refinements section below). @@ -95,8 +95,7 @@ we not only track the queries that Q reads; we also track the **order** in which they were read. This allows try-mark-green to walk those queries back in the same order. This is important because once a subquery comes back as red, -we can no longer be sure that Q will continue -along the same path as before. +we can no longer be sure that Q will continue along the same path as before. That is, imagine a query like this: ```rust,ignore @@ -111,14 +110,14 @@ fn main_query(tcx) { Now imagine that in the first compilation, `main_query` starts by executing `subquery1`, and this returns true. -In that case, the next query `main_query` executes will be `subquery2`, and `subquery3` will -not be executed at all. +In that case, the next query `main_query` executes will be `subquery2`, +and `subquery3` will not be executed at all. -But now imagine that in the **next** compilation, the input has -changed such that `subquery1` returns **false**. In this case, `subquery2` would never execute. +But now imagine that in the **next** compilation, +the input has changed such that `subquery1` returns **false**. +In this case, `subquery2` would never execute. If try-mark-green were to visit `reads(main_query)` out of order, -however, it might visit `subquery2` before `subquery1`, and hence -execute it. +however, it might visit `subquery2` before `subquery1`, and hence execute it. This can lead to ICEs and other problems in the compiler. [dep_graph]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/dep_graph/index.html @@ -133,8 +132,7 @@ In practice, what we would do is to save **the hashes** of all the subqueries th Then, in select cases, we **also** save the results. This is why the incremental algorithm separates computing the **color** of a node, -which often does not require its value, from -computing the **result** of a node. +which often does not require its value, from computing the **result** of a node. Computing the result is done via a simple algorithm like so: - Check if a saved result for Q is available. From b6f2bc9bda8f29b13b92b0a83b65e25933122f68 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sun, 11 Oct 2026 11:10:53 +0200 Subject: [PATCH 23/34] sembr src/tests/ui.md --- src/doc/rustc-dev-guide/src/tests/ui.md | 167 ++++++++++++------------ 1 file changed, 84 insertions(+), 83 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/ui.md b/src/doc/rustc-dev-guide/src/tests/ui.md index 02986119756bd..bef2000abb284 100644 --- a/src/doc/rustc-dev-guide/src/tests/ui.md +++ b/src/doc/rustc-dev-guide/src/tests/ui.md @@ -5,17 +5,17 @@ UI tests are a particular [test suite](compiletest.md#test-suites) of compiletes ## Introduction The tests in [`tests/ui`] are a collection of general-purpose tests which -primarily focus on validating the console output of the compiler, but can be -used for many other purposes. +primarily focus on validating the console output of the compiler, +but can be used for many other purposes. For example, tests can also be configured to [run the resulting program](#controlling-passfail-expectations) to verify its behavior. -For a survey of each subdirectory's purpose under `tests/ui`, consult the -[README.md](https://github.com/rust-lang/rust/tree/HEAD/tests/ui/README.md). +For a survey of each subdirectory's purpose under `tests/ui`, +consult the [README.md](https://github.com/rust-lang/rust/tree/HEAD/tests/ui/README.md). This is useful if you write a new test, and are looking for a category to place it in. -If you need to work with `#![no_std]` cross-compiling tests, consult the -[`minicore` test auxiliary](./minicore.md) chapter. +If you need to work with `#![no_std]` cross-compiling tests, +consult the [`minicore` test auxiliary](./minicore.md) chapter. [`tests/ui`]: https://github.com/rust-lang/rust/blob/HEAD/tests/ui @@ -36,8 +36,8 @@ Compiletest [directives](directives.md) in the form of special comments prefixed with `//@` control how the test is compiled and what the expected behavior is. Tests are expected to fail to compile, since most tests are testing compiler errors. -You can change that behavior with a directive, see [Controlling -pass/fail expectations](#controlling-passfail-expectations). +You can change that behavior with a directive, +see [Controlling pass/fail expectations](#controlling-passfail-expectations). By default, a test is built as an executable binary. If you need a different crate type, you can use the `#![crate_type]` attribute to set it as needed. @@ -46,11 +46,11 @@ If you need a different crate type, you can use the `#![crate_type]` attribute t UI tests store the expected output from the compiler in `.stderr` and `.stdout` snapshots next to the test. -You normally generate these files with the `--bless` -CLI option, and then inspect them manually to verify they contain what you expect. +You normally generate these files with the `--bless` CLI option, +and then inspect them manually to verify they contain what you expect. -The output is normalized to ignore unwanted differences, see the -[Normalization](#normalization) section. +The output is normalized to ignore unwanted differences, +see the [Normalization](#normalization) section. If the file is missing, then compiletest expects the corresponding output to be empty. A common reason to use normalization, revisions, and most of the other following tools, @@ -94,17 +94,18 @@ will check for output files: Consider using the `normalize-stderr` directive instead (see [Normalization](#normalization)). - `dont-check-compiler-stderr` — Ignores stderr from the compiler. - `dont-check-compiler-stdout` — Ignores stdout from the compiler. -- `compare-output-by-lines` — Some tests have non-deterministic orders of output, so we need to compare by lines. +- `compare-output-by-lines` — Some tests have non-deterministic orders of output, +so we need to compare by lines. -UI tests run with `-Zdeduplicate-diagnostics=no` flag, which disables rustc's -built-in diagnostic deduplication mechanism. +UI tests run with `-Zdeduplicate-diagnostics=no` flag, +which disables rustc's built-in diagnostic deduplication mechanism. This means you may see some duplicate messages in the output. This helps illuminate situations where duplicate diagnostics are being generated. ### Normalization -The compiler output is normalized to eliminate output difference between -platforms, mainly about filenames. +The compiler output is normalized to eliminate output difference between platforms, +mainly about filenames. Compiletest makes the following replacements on the compiler output: @@ -135,8 +136,8 @@ more suitable for UI testing. For example, it will anonymize line numbers in the output (line numbers prefixing each source line are replaced with `LL`). -In extremely rare situations, this mode can be disabled with the directive `//@ -compile-flags: -Z ui-testing=no`. +In extremely rare situations, +this mode can be disabled with the directive `//@ compile-flags: -Z ui-testing=no`. When using `-Z ui-testing=no`, the `--diagnostic-width` argument should also be set to avoid tests failing or passing depending on the width of the terminal @@ -144,8 +145,8 @@ from which the UI test suite is being run. Note: The line and column numbers for `-->` lines pointing to the test are *not* normalized, and left as-is. -This ensures that the compiler continues to point to -the correct location, and keeps the stderr files readable. +This ensures that the compiler continues to point to the correct location, +and keeps the stderr files readable. Ideally all line/column information would be retained, but small changes to the source causes large diffs, and more frequent merge conflicts and test errors. @@ -160,8 +161,8 @@ provide custom normalization rules using `normalize-*` directives, e.g. //@ normalize-stderr-64bit: "fn\(\) \(64 bits\)" -> "fn\(\) \($$PTR bits\)" ``` -This tells the test, on 32-bit platforms, whenever the compiler writes `fn() (32 -bits)` to stderr, it should be normalized to read `fn() ($PTR bits)` instead. +This tells the test, on 32-bit platforms, whenever the compiler writes `fn() (32 bits)` to stderr, +it should be normalized to read `fn() ($PTR bits)` instead. Similar for 64-bit. The replacement is performed by regexes using default regex flavor provided by `regex` crate. @@ -192,10 +193,9 @@ fn main() { } ``` -Although UI tests have a `.stderr` file which contains the entire compiler -output, UI tests require that errors are also annotated within the source. -This redundancy helps avoid mistakes since the `.stderr` files are usually -auto-generated. +Although UI tests have a `.stderr` file which contains the entire compiler output, +UI tests require that errors are also annotated within the source. +This redundancy helps avoid mistakes since the `.stderr` files are usually auto-generated. It also helps to directly see where the error spans are expected to point to by looking at one file instead of having to compare the `.stderr` file with the source. Finally, they ensure that no additional unexpected errors are generated. @@ -210,14 +210,15 @@ There are several ways to match the message with the line (see the examples belo * `~`: Associates the error level and message with the *current* line * `~^`: Associates the error level and message with the *previous* error annotation line. - Each caret (`^`) that you add adds a line to this, so `~^^^` - is three lines above the error annotation line. + Each caret (`^`) that you add adds a line to this, + so `~^^^` is three lines above the error annotation line. * `~|`: Associates the error level and message with the *same* line as the - *previous comment*. This is more convenient than using multiple carets when + *previous comment*. + This is more convenient than using multiple carets when there are multiple messages associated with the same line. * `~v`: Associates the error level and message with the *next* error annotation line. - Each symbol (`v`) that you add adds a line to this, so `~vvv` - is three lines below the error annotation line. + Each symbol (`v`) that you add adds a line to this, + so `~vvv` is three lines below the error annotation line. Example: @@ -336,8 +337,8 @@ fn main() { } ``` -We want to ensure this shows "index out of bounds", but we cannot use the `ERROR` -annotation since the runtime error doesn't have any span. +We want to ensure this shows "index out of bounds", +but we cannot use the `ERROR` annotation since the runtime error doesn't have any span. Then it's time to use the `error-pattern` directive: ```rust,ignore @@ -353,15 +354,15 @@ fn main() { For strict testing of compile time output, try to use the line annotations `//~` as much as possible, including `//~?` annotations for diagnostics without spans. -If the compile time output is target dependent or too verbose, use directive -`//@ dont-require-annotations: ` to make the line annotation checking +If the compile time output is target dependent or too verbose, +use directive `//@ dont-require-annotations: ` to make the line annotation checking non-exhaustive. Some of the compiler messages can stay uncovered by annotations in this mode. For checking runtime output, `//@ check-run-results` may be preferable. -Only use `error-pattern` if none of the above works, such as when finding a -specific string pattern in a runtime panic output. +Only use `error-pattern` if none of the above works, +such as when finding a specific string pattern in a runtime panic output. Line annotations `//~` and `error-pattern` are compatible and can be used in the same test. @@ -386,28 +387,28 @@ by the compiler instead of or in addition to structured json. Other kinds only need to be line-annotated if at least one annotation of that kind appears in the test file. -For example, one `//~ NOTE` will also require all other `//~ NOTE`s in the file -to be written out explicitly. +For example, +one `//~ NOTE` will also require all other `//~ NOTE`s in the file to be written out explicitly. Use directive `//@ dont-require-annotations` to opt out of exhaustive annotations. E.g. use `//@ dont-require-annotations: NOTE` to annotate notes selectively. -Avoid using this directive for `ERROR`s and `WARN`ings, unless there's a serious reason, like -target-dependent compiler output. +Avoid using this directive for `ERROR`s and `WARN`ings, unless there's a serious reason, +like target-dependent compiler output. Some diagnostics are never required to be line-annotated, regardless of their kind or directives. Examples are secondary lines of multiline diagnostics, or ubiquitous diagnostics like `aborting due to N previous errors`. -UI tests use the `-A unused` flag by default to ignore all unused warnings, as -unused warnings are usually not the focus of a test. +UI tests use the `-A unused` flag by default to ignore all unused warnings, +as unused warnings are usually not the focus of a test. However, simple code samples often have unused warnings. -If the test is specifically testing an -unused warning, just add the appropriate `#![warn(unused)]` attribute as needed. +If the test is specifically testing an unused warning, +just add the appropriate `#![warn(unused)]` attribute as needed. ### `cfg` revisions -When using [revisions](compiletest.md#revisions), different messages can be -conditionally checked based on the current revision. +When using [revisions](compiletest.md#revisions), +different messages can be conditionally checked based on the current revision. This is done by placing the revision cfg name in brackets like this: ```rust,ignore @@ -429,10 +430,10 @@ fn main() { In this example, the second error message is only emitted in the `mir` revision. The `thir` revision only emits the first error. -If the `cfg` causes the compiler to emit different output, then a test can have -multiple `.stderr` files for the different outputs. -In the example above, there -would be a `.mir.stderr` and `.thir.stderr` file with the different outputs of +If the `cfg` causes the compiler to emit different output, +then a test can have multiple `.stderr` files for the different outputs. +In the example above, +there would be a `.mir.stderr` and `.thir.stderr` file with the different outputs of the different revisions. > Note: cfg revisions also work inside the source code with `#[cfg]` attributes. @@ -443,8 +444,8 @@ the different revisions. By default, a UI test is expected to **generate a compile error** because most of the tests are checking for invalid input and error diagnostics. -However, you can also make UI tests where compilation is expected to succeed, and you can -even run the resulting program. +However, you can also make UI tests where compilation is expected to succeed, +and you can even run the resulting program. Just add one of the following [directives](directives.md): - Pass directives: @@ -461,17 +462,17 @@ Just add one of the following [directives](directives.md): This will run `rustc` twice: - First time is to ensure that the compile succeeds without the codegen phase - Second time is to ensure that the full compile fails - - `//@ run-fail` — compilation should succeed, but running the resulting - binary should make it exit with a code in the range `1..=127` which + - `//@ run-fail` — compilation should succeed, + but running the resulting binary should make it exit with a code in the range `1..=127` which indicates regular failure. On targets without unwind support, crashes are also accepted. - - `//@ run-crash` — compilation should succeed, but running the resulting - binary should fail with a crash. + - `//@ run-crash` — compilation should succeed, + but running the resulting binary should fail with a crash. Crashing is defined as "not exiting with a code in the range `0..=127`". - Example on Linux: Termination by `SIGABRT` or `SIGSEGV`. - Example on Windows: Exiting with the code for `STATUS_ILLEGAL_INSTRUCTION` (`0xC000001D`). - - `//@ run-fail-or-crash` — compilation should succeed, but running the - resulting binary should either `run-fail` or `run-crash`. + - `//@ run-fail-or-crash` — compilation should succeed, + but running the resulting binary should either `run-fail` or `run-crash`. Useful if a test crashes on some targets but just fails on others. For `run-pass`, `run-fail`, `run-crash`, and `run-fail-or-crash` tests, @@ -488,8 +489,8 @@ Tests with the `*-pass` directives can be overridden with the `--pass` command-l ``` The `--pass` option only affects UI tests. -Using `--pass check` can run the UI -test suite much faster (roughly twice as fast on my system), though obviously +Using `--pass check` can run the UI test suite much faster (roughly twice as fast on my system), +though obviously not exercising as much. The `no-pass-override` directive can be used to ignore the `--pass` CLI flag if the @@ -510,8 +511,8 @@ Adding tests for known bugs is helpful for several reasons, including: This directive takes comma-separated issue numbers as arguments, or `"unknown"`: - `//@ known-bug: #123, #456` (when the issues are on rust-lang/rust) -- `//@ known-bug: rust-lang/chalk#123456` - (allows arbitrary text before the `#`, which is useful when the issue is on another repo) +- `//@ known-bug: rust-lang/chalk#123456` (allows arbitrary text before the `#`, + which is useful when the issue is on another repo) - `//@ known-bug: unknown` (when there is no known issue yet; preferably open one if it does not already exist) @@ -521,11 +522,11 @@ The test should still include other normal directives and stdout/stderr files. ## Test organization -When deciding where to place a test file, please try to find a subdirectory that -best matches what you are trying to exercise. +When deciding where to place a test file, +please try to find a subdirectory that best matches what you are trying to exercise. Do your best to keep things organized. -Admittedly, it can be difficult as some tests can overlap different -categories, and the existing layout may not fit well. +Admittedly, it can be difficult as some tests can overlap different categories, +and the existing layout may not fit well. Name the test by a concise description of what the test is checking. Avoid including the issue number in the test name. @@ -535,9 +536,9 @@ Ideally, the test should be added to a directory that helps identify what piece of code is being tested here (e.g., `tests/ui/borrowck/reject-move-out-of-borrow-via-pat.rs`) -When writing a new feature, you may want to **create a subdirectory to store -your tests**. For example, if you are implementing RFC 1234 ("Widgets"), then it -might make sense to put the tests in a directory like `tests/ui/rfc1234-widgets/`. +When writing a new feature, you may want to **create a subdirectory to store your tests**. +For example, if you are implementing RFC 1234 ("Widgets"), +then it might make sense to put the tests in a directory like `tests/ui/rfc1234-widgets/`. In other cases, there may already be a suitable directory. @@ -582,12 +583,12 @@ source file after the suggestion has been applied. Usually when creating a rustfix test you will generate the `.fixed` file automatically with the `x test --bless` option. -The `run-rustfix` directive will cause *all* suggestions to be applied, even if -they are not [`MachineApplicable`](../diagnostics.md#suggestions). -If this is a problem, then you can add the `rustfix-only-machine-applicable` directive in -addition to `run-rustfix`. -This should be used if there is a mixture of -different suggestion levels, and some of the non-machine-applicable ones do not apply cleanly. +The `run-rustfix` directive will cause *all* suggestions to be applied, +even if they are not [`MachineApplicable`](../diagnostics.md#suggestions). +If this is a problem, +then you can add the `rustfix-only-machine-applicable` directive in addition to `run-rustfix`. +This should be used if there is a mixture of different suggestion levels, +and some of the non-machine-applicable ones do not apply cleanly. ## Compare modes @@ -595,17 +596,17 @@ different suggestion levels, and some of the non-machine-applicable ones do not [Compare modes](compiletest.md#compare-modes) can be used to run all tests with different flags from what they are normally compiled with. In some cases, this might result in different output from the compiler. -To support this, different -output files can be saved which contain the output based on the compare mode. +To support this, +different output files can be saved which contain the output based on the compare mode. For example, when using the Polonius mode, a test `foo.rs` will first look for expected output in `foo.polonius.stderr`, falling back to the usual `foo.stderr` if not found. This is useful as different modes can sometimes result in different diagnostics and behavior. -This can help track which tests have -differences between the modes, and to visually inspect those diagnostic differences. +This can help track which tests have differences between the modes, +and to visually inspect those diagnostic differences. -If in the rare case you encounter a test that has different behavior, you can -run something like the following to generate the alternate stderr file: +If in the rare case you encounter a test that has different behavior, +you can run something like the following to generate the alternate stderr file: ```sh ./x test tests/ui --compare-mode=polonius --bless From 15a0b4f9139f1818a458f1a1d7ea150d0ca4c941 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sun, 11 Oct 2026 11:17:47 +0200 Subject: [PATCH 24/34] improve tests/ui.md --- src/doc/rustc-dev-guide/src/tests/ui.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/ui.md b/src/doc/rustc-dev-guide/src/tests/ui.md index bef2000abb284..3de2667102274 100644 --- a/src/doc/rustc-dev-guide/src/tests/ui.md +++ b/src/doc/rustc-dev-guide/src/tests/ui.md @@ -95,7 +95,7 @@ will check for output files: - `dont-check-compiler-stderr` — Ignores stderr from the compiler. - `dont-check-compiler-stdout` — Ignores stdout from the compiler. - `compare-output-by-lines` — Some tests have non-deterministic orders of output, -so we need to compare by lines. + so we need to compare by lines. UI tests run with `-Zdeduplicate-diagnostics=no` flag, which disables rustc's built-in diagnostic deduplication mechanism. @@ -590,7 +590,6 @@ then you can add the `rustfix-only-machine-applicable` directive in addition to This should be used if there is a mixture of different suggestion levels, and some of the non-machine-applicable ones do not apply cleanly. - ## Compare modes [Compare modes](compiletest.md#compare-modes) can be used to run all tests with From 243018861df8761554128819e455036f4ff85fed Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sun, 11 Oct 2026 11:18:11 +0200 Subject: [PATCH 25/34] sembr src/tests/misc.md --- src/doc/rustc-dev-guide/src/tests/misc.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/misc.md b/src/doc/rustc-dev-guide/src/tests/misc.md index 8fe49c82e9873..e8671257a4144 100644 --- a/src/doc/rustc-dev-guide/src/tests/misc.md +++ b/src/doc/rustc-dev-guide/src/tests/misc.md @@ -5,17 +5,17 @@ This is a bootstrap/compiler implementation detail, but it can also be useful for testing: -- `RUSTC_BOOTSTRAP=1` will "cheat" and bypass usual stability checking, allowing - you to use unstable features and cli flags on a stable `rustc`. -- `RUSTC_BOOTSTRAP=-1` will force a given `rustc` to pretend it is a stable - compiler, even if it's actually a nightly `rustc`. +- `RUSTC_BOOTSTRAP=1` will "cheat" and bypass usual stability checking, + allowing you to use unstable features and cli flags on a stable `rustc`. +- `RUSTC_BOOTSTRAP=-1` will force a given `rustc` to pretend it is a stable compiler, + even if it's actually a nightly `rustc`. This is useful because some behaviors of the compiler (e.g. diagnostics) can differ depending on whether the compiler is nightly or not. Note that setting `RUSTC_BOOTSTRAP` in ui tests (e.g. via `//@ rustc-env`) is pointless since ui -tests inherit the bootstrap env var from bootstrap (so it's set to `1` by default), and since -compiletest itself passes `-Z` flags (so `-1` breaks the test). To test stable-only behavior, you -need to write a `run-make` test instead. +tests inherit the bootstrap env var from bootstrap (so it's set to `1` by default), +and since compiletest itself passes `-Z` flags (so `-1` breaks the test). +To test stable-only behavior, you need to write a `run-make` test instead. For `run-make`/`run-make-cargo` tests, `//@ rustc-env` is not supported. You can do something like the following for individual `rustc` invocations. From fb8e41b7a1c8810c95035e20450b167b1e882d59 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sun, 11 Oct 2026 11:19:00 +0200 Subject: [PATCH 26/34] reflow src/tests/ui.md --- src/doc/rustc-dev-guide/src/tests/ui.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/ui.md b/src/doc/rustc-dev-guide/src/tests/ui.md index 3de2667102274..1ec6e84d30502 100644 --- a/src/doc/rustc-dev-guide/src/tests/ui.md +++ b/src/doc/rustc-dev-guide/src/tests/ui.md @@ -490,8 +490,7 @@ Tests with the `*-pass` directives can be overridden with the `--pass` command-l The `--pass` option only affects UI tests. Using `--pass check` can run the UI test suite much faster (roughly twice as fast on my system), -though obviously -not exercising as much. +though obviously not exercising as much. The `no-pass-override` directive can be used to ignore the `--pass` CLI flag if the test won't work properly with that override. From b0c6de4b6aa9570550b05ff1824fb36a0af875e6 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sun, 11 Oct 2026 11:19:25 +0200 Subject: [PATCH 27/34] sembr src/tests/compiletest.md --- .../rustc-dev-guide/src/tests/compiletest.md | 44 +++++++++++-------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/compiletest.md b/src/doc/rustc-dev-guide/src/tests/compiletest.md index ee42cf1fa1d87..5542cef8b70e8 100644 --- a/src/doc/rustc-dev-guide/src/tests/compiletest.md +++ b/src/doc/rustc-dev-guide/src/tests/compiletest.md @@ -4,8 +4,8 @@ `compiletest` is the main test harness of the Rust test suite. It allows test authors to organize large numbers of tests (the Rust compiler has many thousands), -efficient test execution (parallel execution is supported), and -allows the test author to configure behavior and expected results of both +efficient test execution (parallel execution is supported), +and allows the test author to configure behavior and expected results of both individual and groups of tests. > **Note for macOS users** @@ -139,10 +139,9 @@ The directives for pretty-printing tests are: If specified without a value, then it means the pretty-print output should match the original source. If specified with a value, as in `//@ pp-exact:foo.pp`, - it will ensure that the pretty-printed output matches the - contents of the given file. - Otherwise, if `pp-exact` is not specified, then - the pretty-printed output will be pretty-printed one more time, + it will ensure that the pretty-printed output matches the contents of the given file. + Otherwise, if `pp-exact` is not specified, + then the pretty-printed output will be pretty-printed one more time, and the output of the two pretty-printing rounds will be compared to ensure that the pretty-printed output converges to a steady state. @@ -194,12 +193,14 @@ change over time, and a test may no longer be checking the right thing but will Incremental tests may use the attribute `#[rustc_clean(...)]` attribute. This attribute compares the fingerprint from the current compilation session with the previous one. -The first revision should never have an active `rustc_clean` attribute, since it will always be dirty. +The first revision should never have an active `rustc_clean` attribute, +since it will always be dirty. In the default mode, it asserts that the fingerprints must be the same. The attribute takes the following arguments: -* `cfg=""` — checks the cfg condition ``, and only runs the check if the config condition evaluates to true. +* `cfg=""` — checks the cfg condition ``, +and only runs the check if the config condition evaluates to true. This can be used to only run the `rustc_clean` attribute in a specific revision. * `except=",,..."` — asserts that the query results for the listed queries must be different, rather than the same. @@ -314,7 +315,8 @@ the debugger currently being used: NOTE: The "Rust" version of LLDB doesn't exist anymore, so this will always be ignored. This should probably be removed. -By passing the `--debugger` option to compiletest, you can specify a single debugger to run tests with. +By passing the `--debugger` option to compiletest, +you can specify a single debugger to run tests with. For example, `./x test tests/debuginfo -- --debugger gdb` will only test GDB commands. > **Note on running lldb debuginfo tests locally with a prebuilt lldb @@ -363,8 +365,8 @@ See the [FileCheck] documentation for a tutorial and more information. See also the [assembly tests](#assembly-tests) for a similar set of tests. -By default, codegen tests will have `//@ needs-target-std` *implied* (that the -target needs to support std), +By default, +codegen tests will have `//@ needs-target-std` *implied* (that the target needs to support std), *unless* the `#![no_std]`/`#![no_core]` attribute was specified in the test source. You can override this behavior and explicitly write `//@ needs-target-std` to only run the test when target supports std, @@ -491,8 +493,8 @@ The recipe generates test cases and runs them in parallel. #### Using Rust recipes Each test should be in a separate directory with a `rmake.rs` Rust program, -called the *recipe*. A recipe will be compiled and executed by compiletest with -the `run_make_support` library linked in. +called the *recipe*. +A recipe will be compiled and executed by compiletest with the `run_make_support` library linked in. If you need new utilities or functionality, consider extending and improving the [`run_make_support`] library. @@ -614,8 +616,8 @@ worrying about the actual changes, as long as the `coverage-run` tests still pas #### `coverage-run` suite In `coverage-run` mode, these tests perform an end-to-end test of coverage reporting. -They compile a test program with coverage instrumentation, run that -program to produce raw coverage data, +They compile a test program with coverage instrumentation, +run that program to produce raw coverage data, and then use LLVM tools to process that data into a human-readable code coverage report. Instrumented binaries need to be linked against the LLVM profiler runtime, @@ -894,7 +896,8 @@ however compare-modes must be manually run individually via the `--compare-mode` ## Parallel frontend Compiletest can be run with the `--parallel-frontend-threads` flag to run the compiler in parallel mode. -This can be used to check that the compiler produces the same output in parallel mode as in non-parallel mode, and to check for any issues that might arise in parallel mode. +This can be used to check that the compiler produces the same output in parallel mode as in non-parallel mode, +and to check for any issues that might arise in parallel mode. To run the tests in parallel mode, you need to pass the `--parallel-frontend-threads` CLI flag: @@ -902,10 +905,13 @@ To run the tests in parallel mode, you need to pass the `--parallel-frontend-thr ./x test tests/ui -- --parallel-frontend-threads=N --iteration-count=M ``` -Where `N` is the number of threads to use for the parallel frontend, and `M` is the number of times to run each test in parallel mode (to increase the chances of catching any non-determinism). +Where `N` is the number of threads to use for the parallel frontend, +and `M` is the number of times to run each test in parallel mode (to increase the chances of catching any non-determinism). -Also, when running with `--parallel-frontend-threads`, the `compare-output-by-lines` directive would be implied for all tests, since the output from the parallel frontend can be non-deterministic in terms of the order of lines. +Also, when running with `--parallel-frontend-threads`, the `compare-output-by-lines` directive would be implied for all tests, +since the output from the parallel frontend can be non-deterministic in terms of the order of lines. -The parallel frontend is available in UI tests only at the moment, and is not currently supported in other test suites. +The parallel frontend is available in UI tests only at the moment, +and is not currently supported in other test suites. [`--extern` modifiers]: https://github.com/rust-lang/rust/issues/98405 From 1b71fad0ade7c46e1a222526fa170a69aeea372d Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sun, 11 Oct 2026 11:21:37 +0200 Subject: [PATCH 28/34] improve tests/compiletest.md --- src/doc/rustc-dev-guide/src/tests/compiletest.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/tests/compiletest.md b/src/doc/rustc-dev-guide/src/tests/compiletest.md index 5542cef8b70e8..43fbc88dbb92d 100644 --- a/src/doc/rustc-dev-guide/src/tests/compiletest.md +++ b/src/doc/rustc-dev-guide/src/tests/compiletest.md @@ -200,7 +200,7 @@ In the default mode, it asserts that the fingerprints must be the same. The attribute takes the following arguments: * `cfg=""` — checks the cfg condition ``, -and only runs the check if the config condition evaluates to true. + and only runs the check if the config condition evaluates to true. This can be used to only run the `rustc_clean` attribute in a specific revision. * `except=",,..."` — asserts that the query results for the listed queries must be different, rather than the same. From 181764796561dbb44966286d8b162d72e72438fa Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sun, 11 Oct 2026 11:21:44 +0200 Subject: [PATCH 29/34] reflow src/tests/compiletest.md --- src/doc/rustc-dev-guide/src/tests/compiletest.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/tests/compiletest.md b/src/doc/rustc-dev-guide/src/tests/compiletest.md index 43fbc88dbb92d..5c0fed0d21337 100644 --- a/src/doc/rustc-dev-guide/src/tests/compiletest.md +++ b/src/doc/rustc-dev-guide/src/tests/compiletest.md @@ -908,7 +908,8 @@ To run the tests in parallel mode, you need to pass the `--parallel-frontend-thr Where `N` is the number of threads to use for the parallel frontend, and `M` is the number of times to run each test in parallel mode (to increase the chances of catching any non-determinism). -Also, when running with `--parallel-frontend-threads`, the `compare-output-by-lines` directive would be implied for all tests, +Also, when running with `--parallel-frontend-threads`, +the `compare-output-by-lines` directive would be implied for all tests, since the output from the parallel frontend can be non-deterministic in terms of the order of lines. The parallel frontend is available in UI tests only at the moment, From 33031a769dd3fb99f117f0c1e339b7118d7745f8 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sun, 11 Oct 2026 11:22:17 +0200 Subject: [PATCH 30/34] sembr src/serialization.md --- src/doc/rustc-dev-guide/src/serialization.md | 95 ++++++++++---------- 1 file changed, 50 insertions(+), 45 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/serialization.md b/src/doc/rustc-dev-guide/src/serialization.md index 91b2cc92125e2..3bf3b8009ff2e 100644 --- a/src/doc/rustc-dev-guide/src/serialization.md +++ b/src/doc/rustc-dev-guide/src/serialization.md @@ -3,14 +3,14 @@ rustc has to [serialize] and deserialize various data during compilation. Specifically: -- "Crate metadata", consisting mainly of query outputs, are serialized - from a binary format into `rlib` and `rmeta` files that are output when - compiling a library crate. These `rlib` and `rmeta` files are then - deserialized by the crates which depend on that library. +- "Crate metadata", consisting mainly of query outputs, + are serialized from a binary format into `rlib` and `rmeta` files that are output when + compiling a library crate. + These `rlib` and `rmeta` files are then deserialized by the crates which depend on that library. - Certain query outputs are serialized in a binary format to [persist incremental compilation results]. -- [`CrateInfo`] is serialized to `JSON` when the `-Z no-link` flag is used, and - deserialized from `JSON` when the `-Z link-only` flag is used. +- [`CrateInfo`] is serialized to `JSON` when the `-Z no-link` flag is used, + and deserialized from `JSON` when the `-Z link-only` flag is used. [`CrateInfo`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/struct.CrateInfo.html [persist incremental compilation results]: queries/incremental-compilation-in-detail.md#the-real-world-how-persistence-makes-everything-complicated @@ -34,10 +34,10 @@ It also defines implementations of these for various common standard library [primitive types](https://doc.rust-lang.org/std/#primitives) such as integer types, floating point types, `bool`, `char`, `str`, etc. -For types that are constructed from those types, `Encodable` and `Decodable` -are usually implemented by [derives]. These generate implementations that -forward deserialization to the fields of the struct or enum. For a -struct those impls look something like this: +For types that are constructed from those types, +`Encodable` and `Decodable` are usually implemented by [derives]. +These generate implementations that forward deserialization to the fields of the struct or enum. +For a struct those impls look something like this: ```rust,ignore #![feature(rustc_private)] @@ -90,15 +90,17 @@ impl<'tcx, D: TyDecoder<'tcx>> Decodable for MyStruct<'tcx> { The [`TyEncodable`] and [`TyDecodable`] [derive macros][derives] will expand to such an implementation. -Decoding the actual `arena` allocated type is harder, because some of the -implementations can't be written due to the [orphan rules]. To work around this, -the [`RefDecodable`] trait is defined in [`rustc_middle`]. This can then be -implemented for any type. The `TyDecodable` macro will call `RefDecodable` to -decode references, but various generic code needs types to actually be +Decoding the actual `arena` allocated type is harder, +because some of the implementations can't be written due to the [orphan rules]. +To work around this, +the [`RefDecodable`] trait is defined in [`rustc_middle`]. +This can then be implemented for any type. +The `TyDecodable` macro will call `RefDecodable` to decode references, +but various generic code needs types to actually be `Decodable` with a specific decoder. -For interned types instead of manually implementing `RefDecodable`, using a new -type wrapper, like [`ty::Predicate`] and manually implementing `Encodable` and +For interned types instead of manually implementing `RefDecodable`, using a new type wrapper, +like [`ty::Predicate`] and manually implementing `Encodable` and `Decodable` may be simpler. [`Decodable`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_serialize/trait.Decodable.html @@ -119,23 +121,25 @@ type wrapper, like [`ty::Predicate`] and manually implementing `Encodable` and ## Derive macros -The [`rustc_macros`] crate defines various derives to help implement `Decodable` -and `Encodable`. +The [`rustc_macros`] crate defines various derives to help implement `Decodable` and `Encodable`. - The `Encodable` and `Decodable` macros generate implementations that apply to - all `Encoders` and `Decoders`. These should be used in crates that don't - depend on [`rustc_middle`], or that have to be serialized by a type that does + all `Encoders` and `Decoders`. + These should be used in crates that don't depend on [`rustc_middle`], + or that have to be serialized by a type that does not implement `TyEncoder`. - [`MetadataEncodable`] generates implementations that only allow decoding by [`rustc_metadata::rmeta::encoder::EncodeContext`]. - [`BlobDecodable`] and [`LazyDecodable`] serve as the decoding counterparts to - `MetadataEncodable`. They generate implementations that decode with the + `MetadataEncodable`. + They generate implementations that decode with the metadata blob decoders in `rustc_metadata::rmeta`; use `BlobDecodable` when the type has no lazy metadata handles, and `LazyDecodable` when it does. - `TyEncodable` and `TyDecodable` generate implementation that apply to any - `TyEncoder` or `TyDecoder`. These should be used for types that are only - serialized in crate metadata and/or the incremental cache, which is most - serializable types in `rustc_middle`. + `TyEncoder` or `TyDecoder`. + These should be used for types that are only + serialized in crate metadata and/or the incremental cache, + which is most serializable types in `rustc_middle`. [`BlobDecodable`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_macros/derive.BlobDecodable.html [`LazyDecodable`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_macros/derive.LazyDecodable.html @@ -147,32 +151,33 @@ and `Encodable`. ## Shorthands -`Ty` can be deeply recursive, if each `Ty` was encoded naively then crate -metadata would be very large. To handle this, each `TyEncoder` has a cache of -locations in its output where it has serialized types. If a type being encoded -is in the cache, then instead of serializing the type as usual, the byte offset -within the file being written is encoded instead. A similar scheme is used for -`ty::Predicate`. +`Ty` can be deeply recursive, +if each `Ty` was encoded naively then crate metadata would be very large. +To handle this, +each `TyEncoder` has a cache of locations in its output where it has serialized types. +If a type being encoded is in the cache, +then instead of serializing the type as usual, the byte offset +within the file being written is encoded instead. +A similar scheme is used for `ty::Predicate`. ## `LazyValue` -Crate metadata is initially loaded before the `TyCtxt<'tcx>` is created, so -some deserialization needs to be deferred from the initial loading of metadata. +Crate metadata is initially loaded before the `TyCtxt<'tcx>` is created, +so some deserialization needs to be deferred from the initial loading of metadata. The [`LazyValue`] type wraps the (relative) offset in the crate metadata -where a `T` has been serialized. There are also some variants, [`LazyArray`] -and [`LazyTable`]. +where a `T` has been serialized. +There are also some variants, [`LazyArray`] and [`LazyTable`]. The `LazyArray<[T]>` and `LazyTable` types provide some functionality over `Lazy>` and `Lazy>`: -- It's possible to encode a `LazyArray` directly from an `Iterator`, without - first collecting into a `Vec`. -- Indexing into a `LazyTable` does not require decoding entries other - than the one being read. +- It's possible to encode a `LazyArray` directly from an `Iterator`, + without first collecting into a `Vec`. +- Indexing into a `LazyTable` does not require decoding entries other than the one being read. -**note**: `LazyValue` does not cache its value after being deserialized the -first time. Instead the query system itself is the main way of caching these -results. +**note**: `LazyValue` does not cache its value after being deserialized the first time. +Instead the query system itself is the main way of caching these results. [`LazyArray`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_metadata/rmeta/struct.LazyValue.html [`LazyTable`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_metadata/rmeta/struct.LazyValue.html @@ -180,7 +185,7 @@ results. ## Specialization -A few types, most notably `DefId`, need to have different implementations for -different `Encoder`s. This is currently handled by ad-hoc specializations, for -example: `DefId` has a `default` implementation of `Encodable` and a +A few types, most notably `DefId`, need to have different implementations for different `Encoder`s. +This is currently handled by ad-hoc specializations, +for example: `DefId` has a `default` implementation of `Encodable` and a specialized one for `Encodable`. From 24bcd25418fe09fd57d267086469a825a26c1c44 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sun, 11 Oct 2026 12:37:46 +0200 Subject: [PATCH 31/34] improve serialization.md --- src/doc/rustc-dev-guide/src/serialization.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/serialization.md b/src/doc/rustc-dev-guide/src/serialization.md index 3bf3b8009ff2e..af788947313f4 100644 --- a/src/doc/rustc-dev-guide/src/serialization.md +++ b/src/doc/rustc-dev-guide/src/serialization.md @@ -37,7 +37,7 @@ types, floating point types, `bool`, `char`, `str`, etc. For types that are constructed from those types, `Encodable` and `Decodable` are usually implemented by [derives]. These generate implementations that forward deserialization to the fields of the struct or enum. -For a struct those impls look something like this: +For a struct, those impls look something like this: ```rust,ignore #![feature(rustc_private)] @@ -151,7 +151,7 @@ The [`rustc_macros`] crate defines various derives to help implement `Decodable` ## Shorthands -`Ty` can be deeply recursive, +`Ty` can be deeply recursive; if each `Ty` was encoded naively then crate metadata would be very large. To handle this, each `TyEncoder` has a cache of locations in its output where it has serialized types. @@ -173,11 +173,10 @@ The `LazyArray<[T]>` and `LazyTable` types provide some functionality over - It's possible to encode a `LazyArray` directly from an `Iterator`, without first collecting into a `Vec`. -- Indexing into a `LazyTable` does not require decoding entries other than the one being read. +- Indexing into a `LazyTable` does not require decoding entries, other than the one being read. **note**: `LazyValue` does not cache its value after being deserialized the first time. -Instead the query system itself is the main way of caching these results. +Instead, the query system itself is the main way of caching these results. [`LazyArray`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_metadata/rmeta/struct.LazyValue.html [`LazyTable`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_metadata/rmeta/struct.LazyValue.html From f916ff5a19f3efdbe8c488d4855816397e1b8538 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sun, 11 Oct 2026 12:38:30 +0200 Subject: [PATCH 32/34] reflow src/serialization.md --- src/doc/rustc-dev-guide/src/serialization.md | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/serialization.md b/src/doc/rustc-dev-guide/src/serialization.md index af788947313f4..891ff913c144f 100644 --- a/src/doc/rustc-dev-guide/src/serialization.md +++ b/src/doc/rustc-dev-guide/src/serialization.md @@ -96,12 +96,10 @@ To work around this, the [`RefDecodable`] trait is defined in [`rustc_middle`]. This can then be implemented for any type. The `TyDecodable` macro will call `RefDecodable` to decode references, -but various generic code needs types to actually be -`Decodable` with a specific decoder. +but various generic code needs types to actually be `Decodable` with a specific decoder. For interned types instead of manually implementing `RefDecodable`, using a new type wrapper, -like [`ty::Predicate`] and manually implementing `Encodable` and -`Decodable` may be simpler. +like [`ty::Predicate`] and manually implementing `Encodable` and `Decodable` may be simpler. [`Decodable`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_serialize/trait.Decodable.html [`Decoder`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_serialize/trait.Decoder.html @@ -126,8 +124,7 @@ The [`rustc_macros`] crate defines various derives to help implement `Decodable` - The `Encodable` and `Decodable` macros generate implementations that apply to all `Encoders` and `Decoders`. These should be used in crates that don't depend on [`rustc_middle`], - or that have to be serialized by a type that does - not implement `TyEncoder`. + or that have to be serialized by a type that does not implement `TyEncoder`. - [`MetadataEncodable`] generates implementations that only allow decoding by [`rustc_metadata::rmeta::encoder::EncodeContext`]. - [`BlobDecodable`] and [`LazyDecodable`] serve as the decoding counterparts to @@ -156,8 +153,8 @@ if each `Ty` was encoded naively then crate metadata would be very large. To handle this, each `TyEncoder` has a cache of locations in its output where it has serialized types. If a type being encoded is in the cache, -then instead of serializing the type as usual, the byte offset -within the file being written is encoded instead. +then instead of serializing the type as usual, +the byte offset within the file being written is encoded instead. A similar scheme is used for `ty::Predicate`. ## `LazyValue` @@ -173,7 +170,8 @@ The `LazyArray<[T]>` and `LazyTable` types provide some functionality over - It's possible to encode a `LazyArray` directly from an `Iterator`, without first collecting into a `Vec`. -- Indexing into a `LazyTable` does not require decoding entries, other than the one being read. +- Indexing into a `LazyTable` does not require decoding entries, + other than the one being read. **note**: `LazyValue` does not cache its value after being deserialized the first time. Instead, the query system itself is the main way of caching these results. From 25f124217746cfb6155d661a4d853fe1c6fa2cf9 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sun, 11 Oct 2026 12:38:48 +0200 Subject: [PATCH 33/34] sembr src/cli.md --- src/doc/rustc-dev-guide/src/cli.md | 35 +++++++++++++++--------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/cli.md b/src/doc/rustc-dev-guide/src/cli.md index 4c77007ea4415..54917c8a041fd 100644 --- a/src/doc/rustc-dev-guide/src/cli.md +++ b/src/doc/rustc-dev-guide/src/cli.md @@ -1,31 +1,32 @@ # Command-line Arguments -Command-line flags are documented in the [rustc book][cli-docs]. All *stable* -flags should be documented there. Unstable flags should be documented in the -[unstable book]. +Command-line flags are documented in the [rustc book][cli-docs]. +All *stable* flags should be documented there. +Unstable flags should be documented in the [unstable book]. See the [forge guide for new options] for details on the *procedure* for adding a new command-line argument. ## Guidelines -- Flags should be orthogonal to each other. For example, if we'd have a - json-emitting variant of multiple actions `foo` and `bar`, an additional +- Flags should be orthogonal to each other. + For example, if we'd have a json-emitting variant of multiple actions `foo` and `bar`, + an additional `--json` flag is better than adding `--foo-json` and `--bar-json`. -- Avoid flags with the `no-` prefix. Instead, use the [`parse_bool`] function, +- Avoid flags with the `no-` prefix. + Instead, use the [`parse_bool`] function, such as `-C embed-bitcode=no`. -- Consider the behavior if the flag is passed multiple times. In some - situations, the values should be accumulated (in order!). In other - situations, subsequent flags should override previous flags (for example, - the lint-level flags). And some flags (like `-o`) should generate an error +- Consider the behavior if the flag is passed multiple times. + In some situations, the values should be accumulated (in order!). + In other situations, subsequent flags should override previous flags (for example, + the lint-level flags). + And some flags (like `-o`) should generate an error if it is too ambiguous what multiple flags would mean. -- Always give options a long descriptive name, if only for more understandable - compiler scripts. -- The `--verbose` flag is for adding verbose information to `rustc` - output. For example, using it with the `--version` - flag gives information about the hashes of the compiler code. -- Experimental flags and options must be guarded behind the `-Z - unstable-options` flag. +- Always give options a long descriptive name, if only for more understandable compiler scripts. +- The `--verbose` flag is for adding verbose information to `rustc` output. + For example, + using it with the `--version` flag gives information about the hashes of the compiler code. +- Experimental flags and options must be guarded behind the `-Z unstable-options` flag. [cli-docs]: https://doc.rust-lang.org/rustc/command-line-arguments.html [forge guide for new options]: https://forge.rust-lang.org/compiler/proposals-and-stabilization.html#compiler-flags From 77b666a9190026c409dc2981f978f45e08bd5628 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sun, 11 Oct 2026 12:41:57 +0200 Subject: [PATCH 34/34] reflow src/cli.md --- src/doc/rustc-dev-guide/src/cli.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/cli.md b/src/doc/rustc-dev-guide/src/cli.md index 54917c8a041fd..15dbf6568b150 100644 --- a/src/doc/rustc-dev-guide/src/cli.md +++ b/src/doc/rustc-dev-guide/src/cli.md @@ -11,8 +11,7 @@ adding a new command-line argument. - Flags should be orthogonal to each other. For example, if we'd have a json-emitting variant of multiple actions `foo` and `bar`, - an additional - `--json` flag is better than adding `--foo-json` and `--bar-json`. + an additional `--json` flag is better than adding `--foo-json` and `--bar-json`. - Avoid flags with the `no-` prefix. Instead, use the [`parse_bool`] function, such as `-C embed-bitcode=no`.