Skip to content

Commit 4146136

Browse files
committed
Extract an arguments struct for Builder::then_else_break
Most of this method's arguments are usually or always forwarded as-is to recursive invocations. Wrapping them in a dedicated struct allows us to document each struct field, and lets us use struct-update syntax to indicate which arguments are being modified when making a recursive call.
1 parent da02fff commit 4146136

File tree

2 files changed

+72
-66
lines changed

2 files changed

+72
-66
lines changed

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

+5-3
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
8181
let then_blk = unpack!(this.then_else_break(
8282
block,
8383
cond,
84-
Some(condition_scope),
84+
Some(condition_scope), // Temp scope
8585
condition_scope,
8686
source_info,
87-
true,
87+
true, // Declare `let` bindings normally
8888
));
8989

9090
this.expr_into_dest(destination, then_blk, then)
@@ -146,9 +146,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
146146
this.then_else_break(
147147
block,
148148
lhs,
149-
Some(condition_scope),
149+
Some(condition_scope), // Temp scope
150150
condition_scope,
151151
source_info,
152+
// This flag controls how inner `let` expressions are lowered,
153+
// but either way there shouldn't be any of those in here.
152154
true,
153155
)
154156
});

compiler/rustc_mir_build/src/build/matches/mod.rs

+67-63
Original file line numberDiff line numberDiff line change
@@ -30,76 +30,92 @@ mod util;
3030
use std::borrow::Borrow;
3131
use std::mem;
3232

33+
/// Arguments to [`Builder::then_else_break_inner`] that are usually forwarded
34+
/// to recursive invocations.
35+
#[derive(Clone, Copy)]
36+
struct ThenElseArgs {
37+
/// Used as the temp scope for lowering `expr`. If absent (for match guards),
38+
/// `self.local_scope()` is used.
39+
temp_scope_override: Option<region::Scope>,
40+
/// Scope to pass to [`Builder::break_for_else`]. Must match the scope used
41+
/// by the enclosing call to [`Builder::in_if_then_scope`].
42+
break_scope: region::Scope,
43+
variable_source_info: SourceInfo,
44+
/// Forwarded to [`Builder::lower_let_expr`] when lowering [`ExprKind::Let`].
45+
/// When false (for match guards), `let` bindings won't be declared.
46+
declare_let_bindings: bool,
47+
}
48+
3349
impl<'a, 'tcx> Builder<'a, 'tcx> {
3450
/// Lowers a condition in a way that ensures that variables bound in any let
3551
/// expressions are definitely initialized in the if body.
3652
///
37-
/// If `declare_bindings` is false then variables created in `let`
53+
/// If `declare_let_bindings` is false then variables created in `let`
3854
/// expressions will not be declared. This is for if let guards on arms with
3955
/// an or pattern, where the guard is lowered multiple times.
4056
pub(crate) fn then_else_break(
4157
&mut self,
42-
mut block: BasicBlock,
58+
block: BasicBlock,
4359
expr_id: ExprId,
4460
temp_scope_override: Option<region::Scope>,
4561
break_scope: region::Scope,
4662
variable_source_info: SourceInfo,
47-
declare_bindings: bool,
63+
declare_let_bindings: bool,
64+
) -> BlockAnd<()> {
65+
self.then_else_break_inner(
66+
block,
67+
expr_id,
68+
ThenElseArgs {
69+
temp_scope_override,
70+
break_scope,
71+
variable_source_info,
72+
declare_let_bindings,
73+
},
74+
)
75+
}
76+
77+
fn then_else_break_inner(
78+
&mut self,
79+
block: BasicBlock, // Block that the condition and branch will be lowered into
80+
expr_id: ExprId, // Condition expression to lower
81+
args: ThenElseArgs,
4882
) -> BlockAnd<()> {
4983
let this = self;
5084
let expr = &this.thir[expr_id];
5185
let expr_span = expr.span;
5286

5387
match expr.kind {
5488
ExprKind::LogicalOp { op: LogicalOp::And, lhs, rhs } => {
55-
let lhs_then_block = unpack!(this.then_else_break(
56-
block,
57-
lhs,
58-
temp_scope_override,
59-
break_scope,
60-
variable_source_info,
61-
declare_bindings,
62-
));
63-
64-
let rhs_then_block = unpack!(this.then_else_break(
65-
lhs_then_block,
66-
rhs,
67-
temp_scope_override,
68-
break_scope,
69-
variable_source_info,
70-
declare_bindings,
71-
));
72-
89+
let lhs_then_block = unpack!(this.then_else_break_inner(block, lhs, args));
90+
let rhs_then_block = unpack!(this.then_else_break_inner(lhs_then_block, rhs, args));
7391
rhs_then_block.unit()
7492
}
7593
ExprKind::LogicalOp { op: LogicalOp::Or, lhs, rhs } => {
7694
let local_scope = this.local_scope();
7795
let (lhs_success_block, failure_block) =
7896
this.in_if_then_scope(local_scope, expr_span, |this| {
79-
this.then_else_break(
97+
this.then_else_break_inner(
8098
block,
8199
lhs,
82-
temp_scope_override,
83-
local_scope,
84-
variable_source_info,
85-
true,
100+
ThenElseArgs {
101+
break_scope: local_scope,
102+
declare_let_bindings: true,
103+
..args
104+
},
86105
)
87106
});
88-
let rhs_success_block = unpack!(this.then_else_break(
107+
let rhs_success_block = unpack!(this.then_else_break_inner(
89108
failure_block,
90109
rhs,
91-
temp_scope_override,
92-
break_scope,
93-
variable_source_info,
94-
true,
110+
ThenElseArgs { declare_let_bindings: true, ..args },
95111
));
96112

97113
// Make the LHS and RHS success arms converge to a common block.
98114
// (We can't just make LHS goto RHS, because `rhs_success_block`
99115
// might contain statements that we don't want on the LHS path.)
100116
let success_block = this.cfg.start_new_block();
101-
this.cfg.goto(lhs_success_block, variable_source_info, success_block);
102-
this.cfg.goto(rhs_success_block, variable_source_info, success_block);
117+
this.cfg.goto(lhs_success_block, args.variable_source_info, success_block);
118+
this.cfg.goto(rhs_success_block, args.variable_source_info, success_block);
103119
success_block.unit()
104120
}
105121
ExprKind::Unary { op: UnOp::Not, arg } => {
@@ -111,50 +127,38 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
111127
if this.tcx.sess.instrument_coverage() {
112128
this.cfg.push_coverage_span_marker(block, this.source_info(expr_span));
113129
}
114-
this.then_else_break(
130+
this.then_else_break_inner(
115131
block,
116132
arg,
117-
temp_scope_override,
118-
local_scope,
119-
variable_source_info,
120-
true,
133+
ThenElseArgs {
134+
break_scope: local_scope,
135+
declare_let_bindings: true,
136+
..args
137+
},
121138
)
122139
});
123-
this.break_for_else(success_block, break_scope, variable_source_info);
140+
this.break_for_else(success_block, args.break_scope, args.variable_source_info);
124141
failure_block.unit()
125142
}
126143
ExprKind::Scope { region_scope, lint_level, value } => {
127144
let region_scope = (region_scope, this.source_info(expr_span));
128145
this.in_scope(region_scope, lint_level, |this| {
129-
this.then_else_break(
130-
block,
131-
value,
132-
temp_scope_override,
133-
break_scope,
134-
variable_source_info,
135-
declare_bindings,
136-
)
146+
this.then_else_break_inner(block, value, args)
137147
})
138148
}
139-
ExprKind::Use { source } => this.then_else_break(
140-
block,
141-
source,
142-
temp_scope_override,
143-
break_scope,
144-
variable_source_info,
145-
declare_bindings,
146-
),
149+
ExprKind::Use { source } => this.then_else_break_inner(block, source, args),
147150
ExprKind::Let { expr, ref pat } => this.lower_let_expr(
148151
block,
149152
expr,
150153
pat,
151-
break_scope,
152-
Some(variable_source_info.scope),
153-
variable_source_info.span,
154-
declare_bindings,
154+
args.break_scope,
155+
Some(args.variable_source_info.scope),
156+
args.variable_source_info.span,
157+
args.declare_let_bindings,
155158
),
156159
_ => {
157-
let temp_scope = temp_scope_override.unwrap_or_else(|| this.local_scope());
160+
let mut block = block;
161+
let temp_scope = args.temp_scope_override.unwrap_or_else(|| this.local_scope());
158162
let mutability = Mutability::Mut;
159163
let place =
160164
unpack!(block = this.as_temp(block, Some(temp_scope), expr_id, mutability));
@@ -166,7 +170,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
166170

167171
let source_info = this.source_info(expr_span);
168172
this.cfg.terminate(block, source_info, term);
169-
this.break_for_else(else_block, break_scope, source_info);
173+
this.break_for_else(else_block, args.break_scope, source_info);
170174

171175
then_block.unit()
172176
}
@@ -2105,10 +2109,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
21052109
this.then_else_break(
21062110
block,
21072111
guard,
2108-
None,
2112+
None, // Use `self.local_scope()` as the temp scope
21092113
match_scope,
21102114
this.source_info(arm.span),
2111-
false,
2115+
false, // For guards, `let` bindings are declared separately
21122116
)
21132117
});
21142118

0 commit comments

Comments
 (0)