Skip to content

Commit 17b4bf3

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 17b4bf3

File tree

2 files changed

+79
-74
lines changed

2 files changed

+79
-74
lines changed

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

+2-4
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
8181
let then_blk = unpack!(this.then_else_break(
8282
block,
8383
cond,
84-
Some(condition_scope),
84+
condition_scope,
8585
condition_scope,
8686
source_info,
87-
true,
8887
));
8988

9089
this.expr_into_dest(destination, then_blk, then)
@@ -146,10 +145,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
146145
this.then_else_break(
147146
block,
148147
lhs,
149-
Some(condition_scope),
148+
condition_scope,
150149
condition_scope,
151150
source_info,
152-
true,
153151
)
154152
});
155153
let (short_circuit, continuation, constant) = match op {

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

+77-70
Original file line numberDiff line numberDiff line change
@@ -30,76 +30,90 @@ 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`]. If false, variables created in `let`
45+
/// expressions will not be declared. This is for if let guards on arms with
46+
/// an or pattern, where the guard is lowered multiple times.
47+
declare_let_bindings: bool,
48+
}
49+
3350
impl<'a, 'tcx> Builder<'a, 'tcx> {
3451
/// Lowers a condition in a way that ensures that variables bound in any let
3552
/// expressions are definitely initialized in the if body.
36-
///
37-
/// If `declare_bindings` is false then variables created in `let`
38-
/// expressions will not be declared. This is for if let guards on arms with
39-
/// an or pattern, where the guard is lowered multiple times.
4053
pub(crate) fn then_else_break(
4154
&mut self,
42-
mut block: BasicBlock,
55+
block: BasicBlock,
4356
expr_id: ExprId,
44-
temp_scope_override: Option<region::Scope>,
57+
temp_scope: region::Scope,
4558
break_scope: region::Scope,
4659
variable_source_info: SourceInfo,
47-
declare_bindings: bool,
60+
) -> BlockAnd<()> {
61+
// Forward to the inner implementation, with args set up for ordinary
62+
// `if`-like lowering (i.e. not match guards).
63+
self.then_else_break_inner(
64+
block,
65+
expr_id,
66+
ThenElseArgs {
67+
temp_scope_override: Some(temp_scope),
68+
break_scope,
69+
variable_source_info,
70+
declare_let_bindings: true,
71+
},
72+
)
73+
}
74+
75+
fn then_else_break_inner(
76+
&mut self,
77+
block: BasicBlock, // Block that the condition and branch will be lowered into
78+
expr_id: ExprId, // Condition expression to lower
79+
args: ThenElseArgs,
4880
) -> BlockAnd<()> {
4981
let this = self;
5082
let expr = &this.thir[expr_id];
5183
let expr_span = expr.span;
5284

5385
match expr.kind {
5486
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-
87+
let lhs_then_block = unpack!(this.then_else_break_inner(block, lhs, args));
88+
let rhs_then_block = unpack!(this.then_else_break_inner(lhs_then_block, rhs, args));
7389
rhs_then_block.unit()
7490
}
7591
ExprKind::LogicalOp { op: LogicalOp::Or, lhs, rhs } => {
7692
let local_scope = this.local_scope();
7793
let (lhs_success_block, failure_block) =
7894
this.in_if_then_scope(local_scope, expr_span, |this| {
79-
this.then_else_break(
95+
this.then_else_break_inner(
8096
block,
8197
lhs,
82-
temp_scope_override,
83-
local_scope,
84-
variable_source_info,
85-
true,
98+
ThenElseArgs {
99+
break_scope: local_scope,
100+
declare_let_bindings: true,
101+
..args
102+
},
86103
)
87104
});
88-
let rhs_success_block = unpack!(this.then_else_break(
105+
let rhs_success_block = unpack!(this.then_else_break_inner(
89106
failure_block,
90107
rhs,
91-
temp_scope_override,
92-
break_scope,
93-
variable_source_info,
94-
true,
108+
ThenElseArgs { declare_let_bindings: true, ..args },
95109
));
96110

97111
// Make the LHS and RHS success arms converge to a common block.
98112
// (We can't just make LHS goto RHS, because `rhs_success_block`
99113
// might contain statements that we don't want on the LHS path.)
100114
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);
115+
this.cfg.goto(lhs_success_block, args.variable_source_info, success_block);
116+
this.cfg.goto(rhs_success_block, args.variable_source_info, success_block);
103117
success_block.unit()
104118
}
105119
ExprKind::Unary { op: UnOp::Not, arg } => {
@@ -111,50 +125,38 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
111125
if this.tcx.sess.instrument_coverage() {
112126
this.cfg.push_coverage_span_marker(block, this.source_info(expr_span));
113127
}
114-
this.then_else_break(
128+
this.then_else_break_inner(
115129
block,
116130
arg,
117-
temp_scope_override,
118-
local_scope,
119-
variable_source_info,
120-
true,
131+
ThenElseArgs {
132+
break_scope: local_scope,
133+
declare_let_bindings: true,
134+
..args
135+
},
121136
)
122137
});
123-
this.break_for_else(success_block, break_scope, variable_source_info);
138+
this.break_for_else(success_block, args.break_scope, args.variable_source_info);
124139
failure_block.unit()
125140
}
126141
ExprKind::Scope { region_scope, lint_level, value } => {
127142
let region_scope = (region_scope, this.source_info(expr_span));
128143
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-
)
144+
this.then_else_break_inner(block, value, args)
137145
})
138146
}
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-
),
147+
ExprKind::Use { source } => this.then_else_break_inner(block, source, args),
147148
ExprKind::Let { expr, ref pat } => this.lower_let_expr(
148149
block,
149150
expr,
150151
pat,
151-
break_scope,
152-
Some(variable_source_info.scope),
153-
variable_source_info.span,
154-
declare_bindings,
152+
args.break_scope,
153+
Some(args.variable_source_info.scope),
154+
args.variable_source_info.span,
155+
args.declare_let_bindings,
155156
),
156157
_ => {
157-
let temp_scope = temp_scope_override.unwrap_or_else(|| this.local_scope());
158+
let mut block = block;
159+
let temp_scope = args.temp_scope_override.unwrap_or_else(|| this.local_scope());
158160
let mutability = Mutability::Mut;
159161
let place =
160162
unpack!(block = this.as_temp(block, Some(temp_scope), expr_id, mutability));
@@ -166,7 +168,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
166168

167169
let source_info = this.source_info(expr_span);
168170
this.cfg.terminate(block, source_info, term);
169-
this.break_for_else(else_block, break_scope, source_info);
171+
this.break_for_else(else_block, args.break_scope, source_info);
170172

171173
then_block.unit()
172174
}
@@ -2102,13 +2104,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
21022104
let (post_guard_block, otherwise_post_guard_block) =
21032105
self.in_if_then_scope(match_scope, guard_span, |this| {
21042106
guard_span = this.thir[guard].span;
2105-
this.then_else_break(
2107+
// Directly invoke the "inner" impl, so that we don't need a
2108+
// wrapper function for just this one guard-specific call site.
2109+
this.then_else_break_inner(
21062110
block,
21072111
guard,
2108-
None,
2109-
match_scope,
2110-
this.source_info(arm.span),
2111-
false,
2112+
ThenElseArgs {
2113+
temp_scope_override: None, // Use `self.local_scope()`
2114+
break_scope: match_scope,
2115+
variable_source_info: this.source_info(arm.span),
2116+
// For guards, `let` bindings are declared separately.
2117+
declare_let_bindings: false,
2118+
},
21122119
)
21132120
});
21142121

0 commit comments

Comments
 (0)