diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 9064ac3f07f7..b55268d07526 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -75,6 +75,7 @@ macro_rules! thir_with_elements { thir_with_elements! { arms: ArmId => Arm<'tcx> => "a{}", + blocks: BlockId => Block => "b{}", exprs: ExprId => Expr<'tcx> => "e{}", stmts: StmtId => Stmt<'tcx> => "s{}", } @@ -168,7 +169,7 @@ pub enum StmtKind<'tcx> { initializer: Option, /// `let pat: ty = else { } - else_block: Option, + else_block: Option, /// The lint level for this `let` statement. lint_level: LintLevel, @@ -292,7 +293,7 @@ pub enum ExprKind<'tcx> { }, /// A block. Block { - body: Block, + block: BlockId, }, /// An assignment: `lhs = rhs`. Assign { @@ -802,5 +803,5 @@ mod size_asserts { static_assert_size!(Block, 56); static_assert_size!(Expr<'_>, 88); static_assert_size!(Pat<'_>, 24); - static_assert_size!(Stmt<'_>, 120); + static_assert_size!(Stmt<'_>, 72); } diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index 97249fdd1756..758a42ea320f 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -75,7 +75,7 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp visitor.visit_arm(&visitor.thir()[arm]); } } - Block { ref body } => visitor.visit_block(body), + Block { block } => visitor.visit_block(&visitor.thir()[block]), Assign { lhs, rhs } | AssignOp { lhs, rhs, op: _ } => { visitor.visit_expr(&visitor.thir()[lhs]); visitor.visit_expr(&visitor.thir()[rhs]); @@ -174,7 +174,7 @@ pub fn walk_stmt<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, stmt: &Stm } visitor.visit_pat(pattern); if let Some(block) = else_block { - visitor.visit_block(block) + visitor.visit_block(&visitor.thir()[*block]) } } } diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs index 6875600129a8..09045ef63a12 100644 --- a/compiler/rustc_mir_build/src/build/block.rs +++ b/compiler/rustc_mir_build/src/build/block.rs @@ -10,7 +10,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, destination: Place<'tcx>, block: BasicBlock, - ast_block: &Block, + ast_block: BlockId, source_info: SourceInfo, ) -> BlockAnd<()> { let Block { @@ -21,7 +21,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { expr, targeted_by_break, safety_mode, - } = *ast_block; + } = self.thir[ast_block]; let expr = expr.map(|expr| &self.thir[expr]); self.in_opt_scope(opt_destruction_scope.map(|de| (de, source_info)), move |this| { this.in_scope((region_scope, source_info), LintLevel::Inherited, move |this| { @@ -130,7 +130,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block, init, initializer_span, - else_block, + *else_block, visibility_scope, *remainder_scope, remainder_span, diff --git a/compiler/rustc_mir_build/src/build/expr/as_temp.rs b/compiler/rustc_mir_build/src/build/expr/as_temp.rs index 724b72f8769b..e5dafb820bf8 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_temp.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_temp.rs @@ -83,8 +83,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Don't bother with StorageLive and Dead for these temporaries, // they are never assigned. ExprKind::Break { .. } | ExprKind::Continue { .. } | ExprKind::Return { .. } => (), - ExprKind::Block { body: Block { expr: None, targeted_by_break: false, .. } } - if expr_ty.is_never() => {} + ExprKind::Block { block } + if let Block { expr: None, targeted_by_break: false, .. } = this.thir[block] + && expr_ty.is_never() => {} _ => { this.cfg .push(block, Statement { source_info, kind: StatementKind::StorageLive(temp) }); diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index 7ebcc53693ff..1e35167fce27 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -46,7 +46,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }) }) } - ExprKind::Block { body: ref ast_block } => { + ExprKind::Block { block: ast_block } => { this.ast_block(destination, block, ast_block, source_info) } ExprKind::Match { scrutinee, ref arms } => { diff --git a/compiler/rustc_mir_build/src/build/expr/stmt.rs b/compiler/rustc_mir_build/src/build/expr/stmt.rs index a7e1331aabca..00dbcaeb0c96 100644 --- a/compiler/rustc_mir_build/src/build/expr/stmt.rs +++ b/compiler/rustc_mir_build/src/build/expr/stmt.rs @@ -116,14 +116,22 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // it is usually better to focus on `the_value` rather // than the entirety of block(s) surrounding it. let adjusted_span = (|| { - if let ExprKind::Block { body } = &expr.kind && let Some(tail_ex) = body.expr { + if let ExprKind::Block { block } = expr.kind + && let Some(tail_ex) = this.thir[block].expr + { let mut expr = &this.thir[tail_ex]; - while let ExprKind::Block { - body: Block { expr: Some(nested_expr), .. }, - } - | ExprKind::Scope { value: nested_expr, .. } = expr.kind - { - expr = &this.thir[nested_expr]; + loop { + match expr.kind { + ExprKind::Block { block } + if let Some(nested_expr) = this.thir[block].expr => + { + expr = &this.thir[nested_expr]; + } + ExprKind::Scope { value: nested_expr, .. } => { + expr = &this.thir[nested_expr]; + } + _ => break, + } } this.block_context.push(BlockFrame::TailExpr { tail_result_is_ignored: true, diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index ce38283724da..080dab030316 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -2280,15 +2280,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { mut block: BasicBlock, init: &Expr<'tcx>, initializer_span: Span, - else_block: &Block, + else_block: BlockId, visibility_scope: Option, remainder_scope: region::Scope, remainder_span: Span, pattern: &Pat<'tcx>, ) -> BlockAnd<()> { + let else_block_span = self.thir[else_block].span; let (matching, failure) = self.in_if_then_scope(remainder_scope, |this| { let scrutinee = unpack!(block = this.lower_scrutinee(block, init, initializer_span)); - let pat = Pat { ty: init.ty, span: else_block.span, kind: Box::new(PatKind::Wild) }; + let pat = Pat { ty: init.ty, span: else_block_span, kind: Box::new(PatKind::Wild) }; let mut wildcard = Candidate::new(scrutinee.clone(), &pat, false); this.declare_bindings( visibility_scope, @@ -2318,7 +2319,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ); // This block is for the failure case let failure = this.bind_pattern( - this.source_info(else_block.span), + this.source_info(else_block_span), wildcard, None, &fake_borrow_temps, @@ -2334,19 +2335,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // This place is not really used because this destination place // should never be used to take values at the end of the failure // block. - let dummy_place = self.temp(self.tcx.types.never, else_block.span); + let dummy_place = self.temp(self.tcx.types.never, else_block_span); let failure_block; unpack!( failure_block = self.ast_block( dummy_place, failure, else_block, - self.source_info(else_block.span), + self.source_info(else_block_span), ) ); self.cfg.terminate( failure_block, - self.source_info(else_block.span), + self.source_info(else_block_span), TerminatorKind::Unreachable, ); matching.unit() diff --git a/compiler/rustc_mir_build/src/thir/cx/block.rs b/compiler/rustc_mir_build/src/thir/cx/block.rs index dccaa61ed89d..54c4b9eda70d 100644 --- a/compiler/rustc_mir_build/src/thir/cx/block.rs +++ b/compiler/rustc_mir_build/src/thir/cx/block.rs @@ -9,13 +9,13 @@ use rustc_index::vec::Idx; use rustc_middle::ty::CanonicalUserTypeAnnotation; impl<'tcx> Cx<'tcx> { - pub(crate) fn mirror_block(&mut self, block: &'tcx hir::Block<'tcx>) -> Block { + pub(crate) fn mirror_block(&mut self, block: &'tcx hir::Block<'tcx>) -> BlockId { // We have to eagerly lower the "spine" of the statements // in order to get the lexical scoping correctly. let stmts = self.mirror_stmts(block.hir_id.local_id, block.stmts); let opt_destruction_scope = self.region_scope_tree.opt_destruction_scope(block.hir_id.local_id); - Block { + let block = Block { targeted_by_break: block.targeted_by_break, region_scope: region::Scope { id: block.hir_id.local_id, @@ -34,7 +34,9 @@ impl<'tcx> Cx<'tcx> { BlockSafety::ExplicitUnsafe(block.hir_id) } }, - } + }; + + self.thir.blocks.push(block) } fn mirror_stmts( diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 0db8748cb25d..5e1f1c8e84e8 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -108,8 +108,8 @@ impl<'tcx> Cx<'tcx> { // // ^ error message points at this expression. // } let mut adjust_span = |expr: &mut Expr<'tcx>| { - if let ExprKind::Block { body } = &expr.kind { - if let Some(last_expr) = body.expr { + if let ExprKind::Block { block } = expr.kind { + if let Some(last_expr) = self.thir[block].expr { span = self.thir[last_expr].span; expr.span = span; } @@ -369,7 +369,7 @@ impl<'tcx> Cx<'tcx> { ExprKind::AddressOf { mutability, arg: self.mirror_expr(arg) } } - hir::ExprKind::Block(ref blk, _) => ExprKind::Block { body: self.mirror_block(blk) }, + hir::ExprKind::Block(ref blk, _) => ExprKind::Block { block: self.mirror_block(blk) }, hir::ExprKind::Assign(ref lhs, ref rhs, _) => { ExprKind::Assign { lhs: self.mirror_expr(lhs), rhs: self.mirror_expr(rhs) } @@ -680,8 +680,8 @@ impl<'tcx> Cx<'tcx> { let body = self.thir.exprs.push(Expr { ty: block_ty, temp_lifetime, - span: block.span, - kind: ExprKind::Block { body: block }, + span: self.thir[block].span, + kind: ExprKind::Block { block }, }); ExprKind::Loop { body } } diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs index 7c2f4db94ff7..e8ce8e6f23ec 100644 --- a/compiler/rustc_ty_utils/src/consts.rs +++ b/compiler/rustc_ty_utils/src/consts.rs @@ -311,8 +311,15 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { // bar::<{ N + 1 }>(); // } // ``` - ExprKind::Block { body: thir::Block { stmts: box [], expr: Some(e), .. } } => { - self.recurse_build(*e)? + ExprKind::Block { block } => { + if let thir::Block { stmts: box [], expr: Some(e), .. } = &self.body.blocks[*block] { + self.recurse_build(*e)? + } else { + self.maybe_supported_error( + node.span, + "blocks are not supported in generic constant", + )? + } } // `ExprKind::Use` happens when a `hir::ExprKind::Cast` is a // "coercion cast" i.e. using a coercion or is a no-op. @@ -349,10 +356,6 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { node.span, "array construction is not supported in generic constants", )?, - ExprKind::Block { .. } => self.maybe_supported_error( - node.span, - "blocks are not supported in generic constant", - )?, ExprKind::NeverToAny { .. } => self.maybe_supported_error( node.span, "converting nevers to any is not supported in generic constant", diff --git a/src/test/ui/thir-tree.stdout b/src/test/ui/thir-tree.stdout index 3c84be8e8f8d..960b7f7f4dde 100644 --- a/src/test/ui/thir-tree.stdout +++ b/src/test/ui/thir-tree.stdout @@ -1,6 +1,17 @@ DefId(0:3 ~ thir_tree[8f1d]::main): Thir { arms: [], + blocks: [ + Block { + targeted_by_break: false, + region_scope: Node(1), + opt_destruction_scope: None, + span: $DIR/thir-tree.rs:4:15: 4:17 (#0), + stmts: [], + expr: None, + safety_mode: Safe, + }, + ], exprs: [ Expr { ty: (), @@ -9,15 +20,7 @@ Thir { ), span: $DIR/thir-tree.rs:4:15: 4:17 (#0), kind: Block { - body: Block { - targeted_by_break: false, - region_scope: Node(1), - opt_destruction_scope: None, - span: $DIR/thir-tree.rs:4:15: 4:17 (#0), - stmts: [], - expr: None, - safety_mode: Safe, - }, + block: b0, }, }, Expr {