@@ -336,6 +336,9 @@ impl BlockFrame {
336336 }
337337 }
338338
339+ #[ derive( Debug ) ]
340+ struct BlockContext ( Vec < BlockFrame > ) ;
341+
339342struct Builder < ' a , ' gcx : ' a +' tcx , ' tcx : ' a > {
340343 hir : Cx < ' a , ' gcx , ' tcx > ,
341344 cfg : CFG < ' tcx > ,
@@ -359,7 +362,7 @@ struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
359362 /// start just throwing new entries onto that vector in order to
360363 /// distinguish the context of EXPR1 from the context of EXPR2 in
361364 /// `{ STMTS; EXPR1 } + EXPR2`
362- block_context : Vec < BlockFrame > ,
365+ block_context : BlockContext ,
363366
364367 /// The current unsafe block in scope, even if it is hidden by
365368 /// a PushUnsafeBlock
@@ -409,6 +412,55 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
409412 }
410413}
411414
415+ impl BlockContext {
416+ fn new ( ) -> Self { BlockContext ( vec ! [ ] ) }
417+ fn push ( & mut self , bf : BlockFrame ) { self . 0 . push ( bf) ; }
418+ fn pop ( & mut self ) -> Option < BlockFrame > { self . 0 . pop ( ) }
419+
420+ /// Traverses the frames on the BlockContext, searching for either
421+ /// the first block-tail expression frame with no intervening
422+ /// statement frame.
423+ ///
424+ /// Notably, this skips over `SubExpr` frames; this method is
425+ /// meant to be used in the context of understanding the
426+ /// relationship of a temp (created within some complicated
427+ /// expression) with its containing expression, and whether the
428+ /// value of that *containing expression* (not the temp!) is
429+ /// ignored.
430+ fn currently_in_block_tail ( & self ) -> Option < BlockTailInfo > {
431+ for bf in self . 0 . iter ( ) . rev ( ) {
432+ match bf {
433+ BlockFrame :: SubExpr => continue ,
434+ BlockFrame :: Statement { .. } => break ,
435+ & BlockFrame :: TailExpr { tail_result_is_ignored } =>
436+ return Some ( BlockTailInfo { tail_result_is_ignored } )
437+ }
438+ }
439+
440+ return None ;
441+ }
442+
443+ /// Looks at the topmost frame on the BlockContext and reports
444+ /// whether its one that would discard a block tail result.
445+ ///
446+ /// Unlike `currently_within_ignored_tail_expression`, this does
447+ /// *not* skip over `SubExpr` frames: here, we want to know
448+ /// whether the block result itself is discarded.
449+ fn currently_ignores_tail_results ( & self ) -> bool {
450+ match self . 0 . last ( ) {
451+ // no context: conservatively assume result is read
452+ None => false ,
453+
454+ // sub-expression: block result feeds into some computation
455+ Some ( BlockFrame :: SubExpr ) => false ,
456+
457+ // otherwise: use accumulated is_ignored state.
458+ Some ( BlockFrame :: TailExpr { tail_result_is_ignored : ignored } ) |
459+ Some ( BlockFrame :: Statement { ignores_expr_result : ignored } ) => * ignored,
460+ }
461+ }
462+ }
463+
412464#[ derive( Debug ) ]
413465enum LocalsForNode {
414466 /// In the usual case, a node-id for an identifier maps to at most
@@ -764,7 +816,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
764816 fn_span : span,
765817 arg_count,
766818 scopes : vec ! [ ] ,
767- block_context : vec ! [ ] ,
819+ block_context : BlockContext :: new ( ) ,
768820 source_scopes : IndexVec :: new ( ) ,
769821 source_scope : OUTERMOST_SOURCE_SCOPE ,
770822 source_scope_local_data : IndexVec :: new ( ) ,
0 commit comments