From 34cccb2697c37f56325a4b1d10dd700ab3edc71d Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 17 Nov 2025 13:57:31 +1100 Subject: [PATCH] Document the `let this = self;` idiom used in MIR building --- compiler/rustc_mir_build/src/builder/block.rs | 2 +- .../src/builder/expr/as_constant.rs | 2 +- .../src/builder/expr/as_operand.rs | 4 ++-- .../src/builder/expr/as_place.rs | 2 +- .../src/builder/expr/as_rvalue.rs | 6 +++--- .../rustc_mir_build/src/builder/expr/as_temp.rs | 2 +- .../rustc_mir_build/src/builder/expr/into.rs | 2 +- .../rustc_mir_build/src/builder/expr/stmt.rs | 2 +- .../rustc_mir_build/src/builder/matches/mod.rs | 2 +- compiler/rustc_mir_build/src/builder/mod.rs | 17 +++++++++++++++++ 10 files changed, 29 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_mir_build/src/builder/block.rs b/compiler/rustc_mir_build/src/builder/block.rs index cc99d2b42eebc..88533ad226487 100644 --- a/compiler/rustc_mir_build/src/builder/block.rs +++ b/compiler/rustc_mir_build/src/builder/block.rs @@ -39,7 +39,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { expr: Option, region_scope: Scope, ) -> BlockAnd<()> { - let this = self; + let this = self; // See "LET_THIS_SELF". // This convoluted structure is to avoid using recursion as we walk down a list // of statements. Basically, the structure we get back is something like: diff --git a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs index eb0546cd0e374..186fde4883df8 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs @@ -19,7 +19,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// Compile `expr`, yielding a compile-time constant. Assumes that /// `expr` is a valid compile-time constant! pub(crate) fn as_constant(&mut self, expr: &Expr<'tcx>) -> ConstOperand<'tcx> { - let this = self; + let this = self; // See "LET_THIS_SELF". let tcx = this.tcx; let Expr { ty, temp_scope_id: _, span, ref kind } = *expr; match kind { diff --git a/compiler/rustc_mir_build/src/builder/expr/as_operand.rs b/compiler/rustc_mir_build/src/builder/expr/as_operand.rs index 39ddf0edf5d2a..5989a15b93462 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_operand.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_operand.rs @@ -119,7 +119,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { local_info: LocalInfo<'tcx>, needs_temporary: NeedsTemporary, ) -> BlockAnd> { - let this = self; + let this = self; // See "LET_THIS_SELF". let expr = &this.thir[expr_id]; if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind { @@ -161,7 +161,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { scope: TempLifetime, expr_id: ExprId, ) -> BlockAnd> { - let this = self; + let this = self; // See "LET_THIS_SELF". let expr = &this.thir[expr_id]; debug!("as_call_operand(block={:?}, expr={:?})", block, expr); diff --git a/compiler/rustc_mir_build/src/builder/expr/as_place.rs b/compiler/rustc_mir_build/src/builder/expr/as_place.rs index 6c53562283387..e9a28e07490c3 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_place.rs @@ -423,7 +423,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let expr = &self.thir[expr_id]; debug!("expr_as_place(block={:?}, expr={:?}, mutability={:?})", block, expr, mutability); - let this = self; + let this = self; // See "LET_THIS_SELF". let expr_span = expr.span; let source_info = this.source_info(expr_span); match expr.kind { diff --git a/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs index 91814bca76f15..3164818bfa8d7 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs @@ -47,7 +47,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { scope: TempLifetime, expr_id: ExprId, ) -> BlockAnd> { - let this = self; + let this = self; // See "LET_THIS_SELF". let expr = &this.thir[expr_id]; debug!("expr_as_rvalue(block={:?}, scope={:?}, expr={:?})", block, scope, expr); @@ -676,7 +676,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { scope: TempLifetime, outer_source_info: SourceInfo, ) -> BlockAnd> { - let this = self; + let this = self; // See "LET_THIS_SELF". let value_expr = &this.thir[value]; let elem_ty = value_expr.ty; if this.check_constness(&value_expr.kind) { @@ -716,7 +716,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { mut block: BasicBlock, arg: ExprId, ) -> BlockAnd> { - let this = self; + let this = self; // See "LET_THIS_SELF". let source_info = this.source_info(upvar_span); let temp = this.local_decls.push(LocalDecl::new(upvar_ty, upvar_span)); diff --git a/compiler/rustc_mir_build/src/builder/expr/as_temp.rs b/compiler/rustc_mir_build/src/builder/expr/as_temp.rs index 754ab0c0a16e5..d8ac19e34aae8 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_temp.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_temp.rs @@ -34,7 +34,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { expr_id: ExprId, mutability: Mutability, ) -> BlockAnd { - let this = self; + let this = self; // See "LET_THIS_SELF". let expr = &this.thir[expr_id]; let expr_span = expr.span; diff --git a/compiler/rustc_mir_build/src/builder/expr/into.rs b/compiler/rustc_mir_build/src/builder/expr/into.rs index bb65ef28bdc8c..3e8be7bbe5d61 100644 --- a/compiler/rustc_mir_build/src/builder/expr/into.rs +++ b/compiler/rustc_mir_build/src/builder/expr/into.rs @@ -32,7 +32,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // since we frequently have to reference `self` from within a // closure, where `self` would be shadowed, it's easier to // just use the name `this` uniformly - let this = self; + let this = self; // See "LET_THIS_SELF". let expr = &this.thir[expr_id]; let expr_span = expr.span; let source_info = this.source_info(expr_span); diff --git a/compiler/rustc_mir_build/src/builder/expr/stmt.rs b/compiler/rustc_mir_build/src/builder/expr/stmt.rs index db0d3a449712b..66ee139398499 100644 --- a/compiler/rustc_mir_build/src/builder/expr/stmt.rs +++ b/compiler/rustc_mir_build/src/builder/expr/stmt.rs @@ -18,7 +18,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { expr_id: ExprId, statement_scope: Option, ) -> BlockAnd<()> { - let this = self; + let this = self; // See "LET_THIS_SELF". let expr = &this.thir[expr_id]; let expr_span = expr.span; let source_info = this.source_info(expr.span); diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs index 03a4256add841..433c3e5aaaeec 100644 --- a/compiler/rustc_mir_build/src/builder/matches/mod.rs +++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs @@ -109,7 +109,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { expr_id: ExprId, // Condition expression to lower args: ThenElseArgs, ) -> BlockAnd<()> { - let this = self; + let this = self; // See "LET_THIS_SELF". let expr = &this.thir[expr_id]; let expr_span = expr.span; diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs index 7ce2abaf804a9..092c34da2ba46 100644 --- a/compiler/rustc_mir_build/src/builder/mod.rs +++ b/compiler/rustc_mir_build/src/builder/mod.rs @@ -2,6 +2,23 @@ //! "Go to file" feature to silently ignore all files in the module, probably //! because it assumes that "build" is a build-output directory. //! See . +//! +//! ## The `let this = self;` idiom (LET_THIS_SELF) +//! +//! Throughout MIR building there are several places where a `Builder` method +//! needs to borrow `self`, and then re-expose it to a closure as `|this|`. +//! +//! In complex builder methods, potentially with multiple levels of nesting, it +//! would thus become necessary to mentally keep track of whether the builder +//! is `self` (at the top level) or `this` (nested in a closure), or to replace +//! one with the other when moving code in or out of a closure. +//! +//! (The borrow checker will prevent incorrect usage, but having to go back and +//! satisfy the borrow checker still creates contributor friction.) +//! +//! To reduce that friction, some builder methods therefore start with +//! `let this = self;` or similar, allowing subsequent code to uniformly refer +//! to the builder as `this` (and never `self`), even when not nested. use itertools::Itertools; use rustc_abi::{ExternAbi, FieldIdx};