Skip to content

Commit 61365c0

Browse files
committed
Auto merge of #82495 - LeSeulArtichaut:eager-thir, r=oli-obk
Eagerly construct bodies of THIR With this PR: - the THIR is no longer constructed lazily, but is entirely built before being passed to the MIR Builder - the THIR is now allocated in arenas instead of `Box`es However, this PR doesn't make any changes to the way patterns are constructed: they are still boxed, and exhaustiveness checking is unchanged. Implements MCP rust-lang/compiler-team#409. Closes rust-lang/project-thir-unsafeck#1. r? `@ghost` cc `@nikomatsakis` `@oli-obk`
2 parents 5c6d3bf + d6c737a commit 61365c0

24 files changed

+1560
-1750
lines changed

compiler/rustc_mir_build/src/build/block.rs

+23-30
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ use crate::build::matches::ArmHasGuard;
22
use crate::build::ForGuard::OutsideGuard;
33
use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
44
use crate::thir::*;
5-
use rustc_hir as hir;
65
use rustc_middle::mir::*;
76
use rustc_session::lint::builtin::UNSAFE_OP_IN_UNSAFE_FN;
87
use rustc_session::lint::Level;
@@ -13,7 +12,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1312
&mut self,
1413
destination: Place<'tcx>,
1514
block: BasicBlock,
16-
ast_block: &'tcx hir::Block<'tcx>,
15+
ast_block: &Block<'_, 'tcx>,
1716
source_info: SourceInfo,
1817
) -> BlockAnd<()> {
1918
let Block {
@@ -24,7 +23,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
2423
expr,
2524
targeted_by_break,
2625
safety_mode,
27-
} = self.hir.mirror(ast_block);
26+
} = *ast_block;
2827
self.in_opt_scope(opt_destruction_scope.map(|de| (de, source_info)), move |this| {
2928
this.in_scope((region_scope, source_info), LintLevel::Inherited, move |this| {
3029
if targeted_by_break {
@@ -50,8 +49,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
5049
destination: Place<'tcx>,
5150
mut block: BasicBlock,
5251
span: Span,
53-
stmts: Vec<StmtRef<'tcx>>,
54-
expr: Option<ExprRef<'tcx>>,
52+
stmts: &[Stmt<'_, 'tcx>],
53+
expr: Option<&Expr<'_, 'tcx>>,
5554
safety_mode: BlockSafety,
5655
) -> BlockAnd<()> {
5756
let this = self;
@@ -79,18 +78,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
7978
this.update_source_scope_for_safety_mode(span, safety_mode);
8079

8180
let source_info = this.source_info(span);
82-
for stmt in stmts {
83-
let Stmt { kind, opt_destruction_scope } = this.hir.mirror(stmt);
81+
for Stmt { kind, opt_destruction_scope } in stmts {
8482
match kind {
85-
StmtKind::Expr { scope, expr } => {
83+
&StmtKind::Expr { scope, expr } => {
8684
this.block_context.push(BlockFrame::Statement { ignores_expr_result: true });
8785
unpack!(
8886
block = this.in_opt_scope(
8987
opt_destruction_scope.map(|de| (de, source_info)),
9088
|this| {
9189
let si = (scope, source_info);
9290
this.in_scope(si, LintLevel::Inherited, |this| {
93-
let expr = this.hir.mirror(expr);
9491
this.stmt_expr(block, expr, Some(scope))
9592
})
9693
}
@@ -102,45 +99,44 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
10299
this.block_context.push(BlockFrame::Statement { ignores_expr_result });
103100

104101
// Enter the remainder scope, i.e., the bindings' destruction scope.
105-
this.push_scope((remainder_scope, source_info));
102+
this.push_scope((*remainder_scope, source_info));
106103
let_scope_stack.push(remainder_scope);
107104

108105
// Declare the bindings, which may create a source scope.
109-
let remainder_span =
110-
remainder_scope.span(this.hir.tcx(), &this.hir.region_scope_tree);
106+
let remainder_span = remainder_scope.span(this.tcx, this.region_scope_tree);
111107

112108
let visibility_scope =
113109
Some(this.new_source_scope(remainder_span, LintLevel::Inherited, None));
114110

115111
// Evaluate the initializer, if present.
116112
if let Some(init) = initializer {
117-
let initializer_span = init.span();
113+
let initializer_span = init.span;
118114

119115
unpack!(
120116
block = this.in_opt_scope(
121117
opt_destruction_scope.map(|de| (de, source_info)),
122118
|this| {
123-
let scope = (init_scope, source_info);
124-
this.in_scope(scope, lint_level, |this| {
119+
let scope = (*init_scope, source_info);
120+
this.in_scope(scope, *lint_level, |this| {
125121
this.declare_bindings(
126122
visibility_scope,
127123
remainder_span,
128-
&pattern,
124+
pattern,
129125
ArmHasGuard(false),
130126
Some((None, initializer_span)),
131127
);
132-
this.expr_into_pattern(block, pattern, init)
128+
this.expr_into_pattern(block, pattern.clone(), init)
133129
})
134130
}
135131
)
136132
);
137133
} else {
138-
let scope = (init_scope, source_info);
139-
unpack!(this.in_scope(scope, lint_level, |this| {
134+
let scope = (*init_scope, source_info);
135+
unpack!(this.in_scope(scope, *lint_level, |this| {
140136
this.declare_bindings(
141137
visibility_scope,
142138
remainder_span,
143-
&pattern,
139+
pattern,
144140
ArmHasGuard(false),
145141
None,
146142
);
@@ -171,18 +167,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
171167

172168
// Then, the block may have an optional trailing expression which is a “return” value
173169
// of the block, which is stored into `destination`.
174-
let tcx = this.hir.tcx();
170+
let tcx = this.tcx;
175171
let destination_ty = destination.ty(&this.local_decls, tcx).ty;
176172
if let Some(expr) = expr {
177173
let tail_result_is_ignored =
178174
destination_ty.is_unit() || this.block_context.currently_ignores_tail_results();
179-
let span = match expr {
180-
ExprRef::Thir(expr) => expr.span,
181-
ExprRef::Mirror(ref expr) => expr.span,
182-
};
183-
this.block_context.push(BlockFrame::TailExpr { tail_result_is_ignored, span });
175+
this.block_context
176+
.push(BlockFrame::TailExpr { tail_result_is_ignored, span: expr.span });
184177

185-
unpack!(block = this.into(destination, block, expr));
178+
unpack!(block = this.expr_into_dest(destination, block, expr));
186179
let popped = this.block_context.pop();
187180

188181
assert!(popped.map_or(false, |bf| bf.is_tail_expr()));
@@ -194,13 +187,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
194187
if destination_ty.is_unit() {
195188
// We only want to assign an implicit `()` as the return value of the block if the
196189
// block does not diverge. (Otherwise, we may try to assign a unit to a `!`-type.)
197-
this.cfg.push_assign_unit(block, source_info, destination, this.hir.tcx());
190+
this.cfg.push_assign_unit(block, source_info, destination, this.tcx);
198191
}
199192
}
200193
// Finally, we pop all the let scopes before exiting out from the scope of block
201194
// itself.
202195
for scope in let_scope_stack.into_iter().rev() {
203-
unpack!(block = this.pop_scope((scope, source_info), block));
196+
unpack!(block = this.pop_scope((*scope, source_info), block));
204197
}
205198
// Restore the original source scope.
206199
this.source_scope = outer_source_scope;
@@ -220,7 +213,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
220213
Safety::Safe => {}
221214
// no longer treat `unsafe fn`s as `unsafe` contexts (see RFC #2585)
222215
Safety::FnUnsafe
223-
if self.hir.tcx().lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, hir_id).0
216+
if self.tcx.lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, hir_id).0
224217
!= Level::Allow => {}
225218
_ => return,
226219
}

compiler/rustc_mir_build/src/build/expr/as_constant.rs

+5-11
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,9 @@ use rustc_middle::ty::CanonicalUserTypeAnnotation;
88
impl<'a, 'tcx> Builder<'a, 'tcx> {
99
/// Compile `expr`, yielding a compile-time constant. Assumes that
1010
/// `expr` is a valid compile-time constant!
11-
crate fn as_constant<M>(&mut self, expr: M) -> Constant<'tcx>
12-
where
13-
M: Mirror<'tcx, Output = Expr<'tcx>>,
14-
{
15-
let expr = self.hir.mirror(expr);
16-
self.expr_as_constant(expr)
17-
}
18-
19-
fn expr_as_constant(&mut self, expr: Expr<'tcx>) -> Constant<'tcx> {
11+
crate fn as_constant(&mut self, expr: &Expr<'_, 'tcx>) -> Constant<'tcx> {
2012
let this = self;
21-
let Expr { ty, temp_lifetime: _, span, kind } = expr;
13+
let Expr { ty, temp_lifetime: _, span, ref kind } = *expr;
2214
match kind {
2315
ExprKind::Scope { region_scope: _, lint_level: _, value } => this.as_constant(value),
2416
ExprKind::Literal { literal, user_ty, const_id: _ } => {
@@ -33,7 +25,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
3325
Constant { span, user_ty, literal }
3426
}
3527
ExprKind::StaticRef { literal, .. } => Constant { span, user_ty: None, literal },
36-
ExprKind::ConstBlock { value } => Constant { span, user_ty: None, literal: value },
28+
ExprKind::ConstBlock { value } => {
29+
Constant { span: span, user_ty: None, literal: value }
30+
}
3731
_ => span_bug!(span, "expression is not a valid constant {:?}", kind),
3832
}
3933
}

compiler/rustc_mir_build/src/build/expr/as_operand.rs

+20-49
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1414
/// after the current enclosing `ExprKind::Scope` has ended, so
1515
/// please do *not* return it from functions to avoid bad
1616
/// miscompiles.
17-
crate fn as_local_operand<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Operand<'tcx>>
18-
where
19-
M: Mirror<'tcx, Output = Expr<'tcx>>,
20-
{
17+
crate fn as_local_operand(
18+
&mut self,
19+
block: BasicBlock,
20+
expr: &Expr<'_, 'tcx>,
21+
) -> BlockAnd<Operand<'tcx>> {
2122
let local_scope = self.local_scope();
2223
self.as_operand(block, Some(local_scope), expr)
2324
}
@@ -70,14 +71,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
7071
/// value to the stack.
7172
///
7273
/// See #68034 for more details.
73-
crate fn as_local_call_operand<M>(
74+
crate fn as_local_call_operand(
7475
&mut self,
7576
block: BasicBlock,
76-
expr: M,
77-
) -> BlockAnd<Operand<'tcx>>
78-
where
79-
M: Mirror<'tcx, Output = Expr<'tcx>>,
80-
{
77+
expr: &Expr<'_, 'tcx>,
78+
) -> BlockAnd<Operand<'tcx>> {
8179
let local_scope = self.local_scope();
8280
self.as_call_operand(block, Some(local_scope), expr)
8381
}
@@ -88,41 +86,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
8886
/// this time.
8987
///
9088
/// The operand is known to be live until the end of `scope`.
91-
crate fn as_operand<M>(
92-
&mut self,
93-
block: BasicBlock,
94-
scope: Option<region::Scope>,
95-
expr: M,
96-
) -> BlockAnd<Operand<'tcx>>
97-
where
98-
M: Mirror<'tcx, Output = Expr<'tcx>>,
99-
{
100-
let expr = self.hir.mirror(expr);
101-
self.expr_as_operand(block, scope, expr)
102-
}
103-
89+
///
10490
/// Like `as_local_call_operand`, except that the argument will
10591
/// not be valid once `scope` ends.
106-
fn as_call_operand<M>(
107-
&mut self,
108-
block: BasicBlock,
109-
scope: Option<region::Scope>,
110-
expr: M,
111-
) -> BlockAnd<Operand<'tcx>>
112-
where
113-
M: Mirror<'tcx, Output = Expr<'tcx>>,
114-
{
115-
let expr = self.hir.mirror(expr);
116-
self.expr_as_call_operand(block, scope, expr)
117-
}
118-
119-
fn expr_as_operand(
92+
crate fn as_operand(
12093
&mut self,
12194
mut block: BasicBlock,
12295
scope: Option<region::Scope>,
123-
expr: Expr<'tcx>,
96+
expr: &Expr<'_, 'tcx>,
12497
) -> BlockAnd<Operand<'tcx>> {
125-
debug!("expr_as_operand(block={:?}, expr={:?})", block, expr);
98+
debug!("as_operand(block={:?}, expr={:?})", block, expr);
12699
let this = self;
127100

128101
if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind {
@@ -133,7 +106,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
133106
}
134107

135108
let category = Category::of(&expr.kind).unwrap();
136-
debug!("expr_as_operand: category={:?} for={:?}", category, expr.kind);
109+
debug!("as_operand: category={:?} for={:?}", category, expr.kind);
137110
match category {
138111
Category::Constant => {
139112
let constant = this.as_constant(expr);
@@ -146,13 +119,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
146119
}
147120
}
148121

149-
fn expr_as_call_operand(
122+
crate fn as_call_operand(
150123
&mut self,
151124
mut block: BasicBlock,
152125
scope: Option<region::Scope>,
153-
expr: Expr<'tcx>,
126+
expr: &Expr<'_, 'tcx>,
154127
) -> BlockAnd<Operand<'tcx>> {
155-
debug!("expr_as_call_operand(block={:?}, expr={:?})", block, expr);
128+
debug!("as_call_operand(block={:?}, expr={:?})", block, expr);
156129
let this = self;
157130

158131
if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind {
@@ -163,22 +136,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
163136
});
164137
}
165138

166-
let tcx = this.hir.tcx();
139+
let tcx = this.tcx;
167140

168141
if tcx.features().unsized_fn_params {
169142
let ty = expr.ty;
170143
let span = expr.span;
171-
let param_env = this.hir.param_env;
144+
let param_env = this.param_env;
172145

173146
if !ty.is_sized(tcx.at(span), param_env) {
174147
// !sized means !copy, so this is an unsized move
175148
assert!(!ty.is_copy_modulo_regions(tcx.at(span), param_env));
176149

177150
// As described above, detect the case where we are passing a value of unsized
178151
// type, and that value is coming from the deref of a box.
179-
if let ExprKind::Deref { ref arg } = expr.kind {
180-
let arg = this.hir.mirror(arg.clone());
181-
152+
if let ExprKind::Deref { arg } = expr.kind {
182153
// Generate let tmp0 = arg0
183154
let operand = unpack!(block = this.as_temp(block, scope, arg, Mutability::Mut));
184155

@@ -193,6 +164,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
193164
}
194165
}
195166

196-
this.expr_as_operand(block, scope, expr)
167+
this.as_operand(block, scope, expr)
197168
}
198169
}

0 commit comments

Comments
 (0)