1
1
use crate :: build:: scope:: BreakableScope ;
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 } => {
@@ -199,7 +199,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
199
199
block. unit ( )
200
200
}
201
201
_ => {
202
- let expr_ty = expr. ty ;
202
+ assert ! (
203
+ statement_scope. is_some( ) ,
204
+ "Should not be calling `stmt_expr` on a general expression \
205
+ without a statement scope",
206
+ ) ;
203
207
204
208
// Issue #54382: When creating temp for the value of
205
209
// expression like:
@@ -208,48 +212,34 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
208
212
//
209
213
// it is usually better to focus on `the_value` rather
210
214
// 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 ;
215
+ let adjusted_span = ( || {
216
+ if let ExprKind :: Block { body } = expr . kind {
217
+ if let Some ( tail_expr ) = & body . expr {
218
+ let mut expr = tail_expr ;
219
+ while let rustc :: hir :: ExprKind :: Block ( subblock , _label ) = & expr . node {
220
+ if let Some ( subtail_expr ) = & subblock . expr {
221
+ expr = subtail_expr
222
+ } else {
223
+ break ;
224
+ }
221
225
}
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 {
226
+ this. block_context . push ( BlockFrame :: TailExpr {
233
227
tail_result_is_ignored : true
234
228
} ) ;
229
+ return Some ( expr. span ) ;
235
230
}
236
231
}
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) ) ;
232
+ None
233
+ } ) ( ) ;
234
+
235
+ let temp = unpack ! ( block =
236
+ this. as_temp( block, statement_scope, expr, Mutability :: Not ) ) ;
244
237
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
- } ) ;
238
+ if let Some ( span) = adjusted_span {
239
+ this. local_decls [ temp] . source_info . span = span;
240
+ this. block_context . pop ( ) ;
241
+ }
251
242
252
- unpack ! ( block = this. build_drop( block, drop_point, temp, expr_ty) ) ;
253
243
block. unit ( )
254
244
}
255
245
}
0 commit comments