@@ -336,6 +336,9 @@ impl BlockFrame {
336
336
}
337
337
}
338
338
339
+ #[ derive( Debug ) ]
340
+ struct BlockContext ( Vec < BlockFrame > ) ;
341
+
339
342
struct Builder < ' a , ' gcx : ' a +' tcx , ' tcx : ' a > {
340
343
hir : Cx < ' a , ' gcx , ' tcx > ,
341
344
cfg : CFG < ' tcx > ,
@@ -359,7 +362,7 @@ struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
359
362
/// start just throwing new entries onto that vector in order to
360
363
/// distinguish the context of EXPR1 from the context of EXPR2 in
361
364
/// `{ STMTS; EXPR1 } + EXPR2`
362
- block_context : Vec < BlockFrame > ,
365
+ block_context : BlockContext ,
363
366
364
367
/// The current unsafe block in scope, even if it is hidden by
365
368
/// a PushUnsafeBlock
@@ -409,6 +412,55 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
409
412
}
410
413
}
411
414
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
+
412
464
#[ derive( Debug ) ]
413
465
enum LocalsForNode {
414
466
/// 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> {
764
816
fn_span : span,
765
817
arg_count,
766
818
scopes : vec ! [ ] ,
767
- block_context : vec ! [ ] ,
819
+ block_context : BlockContext :: new ( ) ,
768
820
source_scopes : IndexVec :: new ( ) ,
769
821
source_scope : OUTERMOST_SOURCE_SCOPE ,
770
822
source_scope_local_data : IndexVec :: new ( ) ,
0 commit comments