1- use crate :: build:: scope:: BreakableScope ;
1+ use crate :: build:: scope:: BreakableTarget ;
22use crate :: build:: { BlockAnd , BlockAndExtension , BlockFrame , Builder } ;
33use crate :: hair:: * ;
4+ use rustc:: middle:: region;
45use rustc:: mir:: * ;
56
67impl < ' a , ' tcx > Builder < ' a , ' tcx > {
78 /// Builds a block of MIR statements to evaluate the HAIR `expr`.
89 /// If the original expression was an AST statement,
910 /// (e.g., `some().code(&here());`) then `opt_stmt_span` is the
1011 /// 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 < ( ) > {
1919 let this = self ;
2020 let expr_span = expr. span ;
2121 let source_info = this. source_info ( expr. span ) ;
@@ -30,7 +30,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
3030 } => {
3131 let value = this. hir . mirror ( value) ;
3232 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 )
3434 } )
3535 }
3636 ExprKind :: Assign { lhs, rhs } => {
@@ -98,70 +98,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
9898 block. unit ( )
9999 }
100100 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)
115102 }
116103 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)
136105 }
137106 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)
165108 }
166109 ExprKind :: InlineAsm {
167110 asm,
@@ -199,7 +142,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
199142 block. unit ( )
200143 }
201144 _ => {
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+ ) ;
203150
204151 // Issue #54382: When creating temp for the value of
205152 // expression like:
@@ -208,48 +155,34 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
208155 //
209156 // it is usually better to focus on `the_value` rather
210157 // 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+ }
221168 }
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 {
233170 tail_result_is_ignored : true
234171 } ) ;
172+ return Some ( expr. span ) ;
235173 }
236174 }
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+ } ) ( ) ;
244177
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+ }
251185
252- unpack ! ( block = this. build_drop( block, drop_point, temp, expr_ty) ) ;
253186 block. unit ( )
254187 }
255188 }
0 commit comments