From 69e0f2f314cfc68e42172c940baaceeb509ea612 Mon Sep 17 00:00:00 2001 From: panstromek Date: Thu, 5 Nov 2026 14:16:22 +0100 Subject: [PATCH 1/3] ref: avoid None terminator in parse_block_def in custom mir parser --- compiler/rustc_mir_build/src/builder/custom/parse.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_mir_build/src/builder/custom/parse.rs b/compiler/rustc_mir_build/src/builder/custom/parse.rs index 0cc73e381ea2b..c1819dca3ebb8 100644 --- a/compiler/rustc_mir_build/src/builder/custom/parse.rs +++ b/compiler/rustc_mir_build/src/builder/custom/parse.rs @@ -303,23 +303,24 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> { ExprKind::Block { block } => &self.thir[*block], ); - let mut data = BasicBlockData::maybe_unterminated(None, is_cleanup); + let mut statements = vec![]; for stmt_id in &*block.stmts { let stmt = self.statement_as_expr(*stmt_id)?; let span = self.thir[stmt].span; let statement = self.parse_statement(stmt)?; - data.statements + statements .push(Statement::new(SourceInfo { span, scope: self.source_scope }, statement)); } let Some(trailing) = block.expr else { return Err(self.expr_error(expr_id, "terminator")) }; let span = self.thir[trailing].span; let terminator = self.parse_terminator(trailing)?; - data.terminator = Some(Terminator { + + let terminator = Terminator { source_info: SourceInfo { span, scope: self.source_scope }, kind: terminator, - }); + }; - Ok(data) + Ok(BasicBlockData::new_stmts(statements, terminator, is_cleanup)) } } From 8da94e58c5a97928e8243a1ed8dec4a3add52a77 Mon Sep 17 00:00:00 2001 From: panstromek Date: Thu, 5 Nov 2026 14:26:45 +0100 Subject: [PATCH 2/3] refactor custom mir parse_body to avoid creating blocks with None terminator This used only because block declarations with `is_cleanup` property are parsed separately from the basic block data, so we do this by parsing declarations into a separate explicit vec first, and later transform it into the bb data when parsing blocks themselves. --- .../rustc_mir_build/src/builder/custom/mod.rs | 7 +++++-- .../src/builder/custom/parse.rs | 19 ++++++++++--------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_mir_build/src/builder/custom/mod.rs b/compiler/rustc_mir_build/src/builder/custom/mod.rs index 6d0c415b7358a..91da85000a796 100644 --- a/compiler/rustc_mir_build/src/builder/custom/mod.rs +++ b/compiler/rustc_mir_build/src/builder/custom/mod.rs @@ -20,7 +20,7 @@ use rustc_attr_ir as attrs; use rustc_data_structures::fx::FxHashMap; use rustc_hir::HirId; use rustc_hir::def_id::DefId; -use rustc_index::{IndexSlice, IndexVec}; +use rustc_index::{IndexSlice, IndexVec, indexvec}; use rustc_middle::mir::*; use rustc_middle::thir::*; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -64,7 +64,6 @@ pub(super) fn build_custom_mir<'tcx>( }; body.local_decls.push(LocalDecl::new(return_ty, return_ty_span)); - body.basic_blocks_mut().push(BasicBlockData::maybe_unterminated(None, false)); body.source_scopes.push(SourceScopeData { span, parent_scope: None, @@ -80,6 +79,8 @@ pub(super) fn build_custom_mir<'tcx>( thir, source_scope: OUTERMOST_SOURCE_SCOPE, body: &mut body, + // Single `false` for entry block which is declared implicitly + block_decls: indexvec![false], local_map: FxHashMap::default(), block_map: FxHashMap::default(), }; @@ -138,6 +139,8 @@ struct ParseCtxt<'a, 'tcx> { thir: &'a Thir<'tcx>, source_scope: SourceScope, body: &'a mut Body<'tcx>, + /// list of declared blocks, with a flag indicating whether it is a cleanup block + block_decls: IndexVec, local_map: FxHashMap, block_map: FxHashMap, } diff --git a/compiler/rustc_mir_build/src/builder/custom/parse.rs b/compiler/rustc_mir_build/src/builder/custom/parse.rs index c1819dca3ebb8..d1d65bb75f192 100644 --- a/compiler/rustc_mir_build/src/builder/custom/parse.rs +++ b/compiler/rustc_mir_build/src/builder/custom/parse.rs @@ -180,9 +180,13 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> { ExprKind::Block { block } => &self.thir[*block].stmts, ); for (i, block_def) in block_defs.iter().enumerate() { - let is_cleanup = self.body.basic_blocks_mut()[BasicBlock::from_usize(i)].is_cleanup; + let bb = BasicBlock::from_usize(i); + let is_cleanup = self.block_decls[bb]; let block = self.parse_block_def(self.statement_as_expr(*block_def)?, is_cleanup)?; - self.body.basic_blocks_mut()[BasicBlock::from_usize(i)] = block; + let inserted_bb = self.body.basic_blocks_mut().push(block); + // just a sanity check to make sure that we inserted the block + // to the correct position (basic block idx) + assert_eq!(inserted_bb, bb); } Ok(()) @@ -199,14 +203,11 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> { match &self.thir[stmt].kind { StmtKind::Let { pattern, initializer: Some(initializer), .. } => { let (var, ..) = self.parse_var(pattern)?; - let data = BasicBlockData::maybe_unterminated( - None, - parse_by_kind!(self, *initializer, _, "basic block declaration", - @variant(mir_basic_block, Normal) => false, - @variant(mir_basic_block, Cleanup) => true, - ), + let is_cleanup = parse_by_kind!(self, *initializer, _, "basic block declaration", + @variant(mir_basic_block, Normal) => false, + @variant(mir_basic_block, Cleanup) => true, ); - let block = self.body.basic_blocks_mut().push(data); + let block = self.block_decls.push(is_cleanup); self.block_map.insert(var, block); Ok(()) } From c84c4c8d8ef821137f7e3196650328484e5a2464 Mon Sep 17 00:00:00 2001 From: panstromek Date: Mon, 9 Nov 2026 17:36:14 +0100 Subject: [PATCH 3/3] add some asserts to custom mir parser to make some if its invariants explicit --- compiler/rustc_mir_build/src/builder/custom/parse.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compiler/rustc_mir_build/src/builder/custom/parse.rs b/compiler/rustc_mir_build/src/builder/custom/parse.rs index d1d65bb75f192..55252ea5c95d9 100644 --- a/compiler/rustc_mir_build/src/builder/custom/parse.rs +++ b/compiler/rustc_mir_build/src/builder/custom/parse.rs @@ -188,6 +188,10 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> { // to the correct position (basic block idx) assert_eq!(inserted_bb, bb); } + // check that declarations, definitions and block_map counts match + assert_eq!(self.block_decls.len(), self.body.basic_blocks.len()); + // +1 because block_map doesn't contain the entry block + assert_eq!(self.block_decls.len(), self.block_map.len() + 1); Ok(()) }