1
- use crate :: build:: scope:: BreakableScope ;
1
+ use crate :: build:: scope:: BreakableTarget ;
2
2
use crate :: build:: { BlockAnd , BlockAndExtension , BlockFrame , Builder } ;
3
3
use crate :: hair:: * ;
4
+ use rustc:: middle:: region;
4
5
use rustc:: mir:: * ;
5
6
6
7
impl < ' a , ' tcx > Builder < ' a , ' tcx > {
7
8
/// Builds a block of MIR statements to evaluate the HAIR `expr`.
8
9
/// If the original expression was an AST statement,
9
10
/// (e.g., `some().code(&here());`) then `opt_stmt_span` is the
10
11
/// span of that statement (including its semicolon, if any).
11
- /// Diagnostics use this span (which may be larger than that of
12
- /// `expr`) to identify when statement temporaries are dropped.
13
- pub fn stmt_expr ( & mut self ,
14
- mut block : BasicBlock ,
15
- expr : Expr < ' tcx > ,
16
- opt_stmt_span : Option < StatementSpan > )
17
- -> BlockAnd < ( ) >
18
- {
12
+ /// The scope is used if a statement temporary must be dropped.
13
+ pub fn stmt_expr (
14
+ & mut self ,
15
+ mut block : BasicBlock ,
16
+ expr : Expr < ' tcx > ,
17
+ statement_scope : Option < region:: Scope > ,
18
+ ) -> BlockAnd < ( ) > {
19
19
let this = self ;
20
20
let expr_span = expr. span ;
21
21
let source_info = this. source_info ( expr. span ) ;
@@ -30,7 +30,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
30
30
} => {
31
31
let value = this. hir . mirror ( value) ;
32
32
this. in_scope ( ( region_scope, source_info) , lint_level, |this| {
33
- this. stmt_expr ( block, value, opt_stmt_span )
33
+ this. stmt_expr ( block, value, statement_scope )
34
34
} )
35
35
}
36
36
ExprKind :: Assign { lhs, rhs } => {
@@ -98,70 +98,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
98
98
block. unit ( )
99
99
}
100
100
ExprKind :: Continue { label } => {
101
- let BreakableScope {
102
- continue_block,
103
- region_scope,
104
- ..
105
- } = * this. find_breakable_scope ( expr_span, label) ;
106
- let continue_block = continue_block
107
- . expect ( "Attempted to continue in non-continuable breakable block" ) ;
108
- this. exit_scope (
109
- expr_span,
110
- ( region_scope, source_info) ,
111
- block,
112
- continue_block,
113
- ) ;
114
- this. cfg . start_new_block ( ) . unit ( )
101
+ this. break_scope ( block, None , BreakableTarget :: Continue ( label) , source_info)
115
102
}
116
103
ExprKind :: Break { label, value } => {
117
- let ( break_block, region_scope, destination) = {
118
- let BreakableScope {
119
- break_block,
120
- region_scope,
121
- ref break_destination,
122
- ..
123
- } = * this. find_breakable_scope ( expr_span, label) ;
124
- ( break_block, region_scope, break_destination. clone ( ) )
125
- } ;
126
- if let Some ( value) = value {
127
- debug ! ( "stmt_expr Break val block_context.push(SubExpr) : {:?}" , expr2) ;
128
- this. block_context . push ( BlockFrame :: SubExpr ) ;
129
- unpack ! ( block = this. into( & destination, block, value) ) ;
130
- this. block_context . pop ( ) ;
131
- } else {
132
- this. cfg . push_assign_unit ( block, source_info, & destination)
133
- }
134
- this. exit_scope ( expr_span, ( region_scope, source_info) , block, break_block) ;
135
- this. cfg . start_new_block ( ) . unit ( )
104
+ this. break_scope ( block, value, BreakableTarget :: Break ( label) , source_info)
136
105
}
137
106
ExprKind :: Return { value } => {
138
- block = match value {
139
- Some ( value) => {
140
- debug ! ( "stmt_expr Return val block_context.push(SubExpr) : {:?}" , expr2) ;
141
- this. block_context . push ( BlockFrame :: SubExpr ) ;
142
- let result = unpack ! (
143
- this. into(
144
- & Place :: RETURN_PLACE ,
145
- block,
146
- value
147
- )
148
- ) ;
149
- this. block_context . pop ( ) ;
150
- result
151
- }
152
- None => {
153
- this. cfg . push_assign_unit (
154
- block,
155
- source_info,
156
- & Place :: RETURN_PLACE ,
157
- ) ;
158
- block
159
- }
160
- } ;
161
- let region_scope = this. region_scope_of_return_scope ( ) ;
162
- let return_block = this. return_block ( ) ;
163
- this. exit_scope ( expr_span, ( region_scope, source_info) , block, return_block) ;
164
- this. cfg . start_new_block ( ) . unit ( )
107
+ this. break_scope ( block, value, BreakableTarget :: Return , source_info)
165
108
}
166
109
ExprKind :: InlineAsm {
167
110
asm,
@@ -199,7 +142,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
199
142
block. unit ( )
200
143
}
201
144
_ => {
202
- let expr_ty = expr. ty ;
145
+ assert ! (
146
+ statement_scope. is_some( ) ,
147
+ "Should not be calling `stmt_expr` on a general expression \
148
+ without a statement scope",
149
+ ) ;
203
150
204
151
// Issue #54382: When creating temp for the value of
205
152
// expression like:
@@ -208,48 +155,34 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
208
155
//
209
156
// it is usually better to focus on `the_value` rather
210
157
// than the entirety of block(s) surrounding it.
211
- let mut temp_span = expr_span ;
212
- let mut temp_in_tail_of_block = false ;
213
- if let ExprKind :: Block { body } = expr . kind {
214
- if let Some ( tail_expr ) = & body . expr {
215
- let mut expr = tail_expr ;
216
- while let rustc :: hir :: ExprKind :: Block ( subblock , _label ) = & expr . node {
217
- if let Some ( subtail_expr ) = & subblock . expr {
218
- expr = subtail_expr
219
- } else {
220
- break ;
158
+ let adjusted_span = ( || {
159
+ if let ExprKind :: Block { body } = expr . kind {
160
+ if let Some ( tail_expr ) = & body . expr {
161
+ let mut expr = tail_expr ;
162
+ while let rustc :: hir :: ExprKind :: Block ( subblock , _label ) = & expr . node {
163
+ if let Some ( subtail_expr ) = & subblock . expr {
164
+ expr = subtail_expr
165
+ } else {
166
+ break ;
167
+ }
221
168
}
222
- }
223
- temp_span = expr. span ;
224
- temp_in_tail_of_block = true ;
225
- }
226
- }
227
-
228
- let temp = {
229
- let mut local_decl = LocalDecl :: new_temp ( expr. ty . clone ( ) , temp_span) ;
230
- if temp_in_tail_of_block {
231
- if this. block_context . currently_ignores_tail_results ( ) {
232
- local_decl = local_decl. block_tail ( BlockTailInfo {
169
+ this. block_context . push ( BlockFrame :: TailExpr {
233
170
tail_result_is_ignored : true
234
171
} ) ;
172
+ return Some ( expr. span ) ;
235
173
}
236
174
}
237
- let temp = this. local_decls . push ( local_decl) ;
238
- let place = Place :: from ( temp) ;
239
- debug ! ( "created temp {:?} for expr {:?} in block_context: {:?}" ,
240
- temp, expr, this. block_context) ;
241
- place
242
- } ;
243
- unpack ! ( block = this. into( & temp, block, expr) ) ;
175
+ None
176
+ } ) ( ) ;
244
177
245
- // Attribute drops of the statement's temps to the
246
- // semicolon at the statement's end.
247
- let drop_point = this. hir . tcx ( ) . sess . source_map ( ) . end_point ( match opt_stmt_span {
248
- None => expr_span,
249
- Some ( StatementSpan ( span) ) => span,
250
- } ) ;
178
+ let temp = unpack ! ( block =
179
+ this. as_temp( block, statement_scope, expr, Mutability :: Not ) ) ;
180
+
181
+ if let Some ( span) = adjusted_span {
182
+ this. local_decls [ temp] . source_info . span = span;
183
+ this. block_context . pop ( ) ;
184
+ }
251
185
252
- unpack ! ( block = this. build_drop( block, drop_point, temp, expr_ty) ) ;
253
186
block. unit ( )
254
187
}
255
188
}
0 commit comments