@@ -24,7 +24,7 @@ use tracing::debug;
24
24
#[ derive( Debug , Copy , Clone ) ]
25
25
struct Context {
26
26
/// The scope that contains any new variables declared.
27
- var_parent : Option < Scope > ,
27
+ var_parent : ( Option < Scope > , ScopeCompatibility ) ,
28
28
29
29
/// Region parent of expressions, etc.
30
30
parent : Option < Scope > ,
@@ -56,14 +56,18 @@ struct ExtendedTemporaryScope {
56
56
57
57
/// Records the lifetime of a local variable as `cx.var_parent`
58
58
fn record_var_lifetime ( visitor : & mut ScopeResolutionVisitor < ' _ > , var_id : hir:: ItemLocalId ) {
59
- match visitor. cx . var_parent {
59
+ let ( var_parent_scope, var_parent_compat) = visitor. cx . var_parent ;
60
+ match var_parent_scope {
60
61
None => {
61
62
// this can happen in extern fn declarations like
62
63
//
63
64
// extern fn isalnum(c: c_int) -> c_int
64
65
}
65
66
Some ( parent_scope) => visitor. scope_tree . record_var_scope ( var_id, parent_scope) ,
66
67
}
68
+ if let ScopeCompatibility :: FutureIncompatible { shortens_to } = var_parent_compat {
69
+ visitor. scope_tree . record_future_incompatible_var_scope ( var_id, shortens_to) ;
70
+ }
67
71
}
68
72
69
73
fn resolve_block < ' tcx > (
@@ -101,7 +105,7 @@ fn resolve_block<'tcx>(
101
105
// itself has returned.
102
106
103
107
visitor. enter_node_scope_with_dtor ( blk. hir_id . local_id , terminating) ;
104
- visitor. cx . var_parent = visitor. cx . parent ;
108
+ visitor. cx . var_parent = ( visitor. cx . parent , ScopeCompatibility :: FutureCompatible ) ;
105
109
106
110
{
107
111
// This block should be kept approximately in sync with
@@ -120,7 +124,8 @@ fn resolve_block<'tcx>(
120
124
local_id : blk. hir_id . local_id ,
121
125
data : ScopeData :: Remainder ( FirstStatementIndex :: new ( i) ) ,
122
126
} ) ;
123
- visitor. cx . var_parent = visitor. cx . parent ;
127
+ visitor. cx . var_parent =
128
+ ( visitor. cx . parent , ScopeCompatibility :: FutureCompatible ) ;
124
129
visitor. visit_stmt ( statement) ;
125
130
// We need to back out temporarily to the last enclosing scope
126
131
// for the `else` block, so that even the temporaries receiving
@@ -144,7 +149,8 @@ fn resolve_block<'tcx>(
144
149
local_id : blk. hir_id . local_id ,
145
150
data : ScopeData :: Remainder ( FirstStatementIndex :: new ( i) ) ,
146
151
} ) ;
147
- visitor. cx . var_parent = visitor. cx . parent ;
152
+ visitor. cx . var_parent =
153
+ ( visitor. cx . parent , ScopeCompatibility :: FutureCompatible ) ;
148
154
visitor. visit_stmt ( statement)
149
155
}
150
156
hir:: StmtKind :: Item ( ..) => {
@@ -208,15 +214,15 @@ fn resolve_arm<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, arm: &'tcx hir:
208
214
let prev_cx = visitor. cx ;
209
215
210
216
visitor. enter_node_scope_with_dtor ( arm. hir_id . local_id , true ) ;
211
- visitor. cx . var_parent = visitor. cx . parent ;
217
+ visitor. cx . var_parent = ( visitor. cx . parent , ScopeCompatibility :: FutureCompatible ) ;
212
218
213
219
resolve_pat ( visitor, arm. pat ) ;
214
220
if let Some ( guard) = arm. guard {
215
221
// We introduce a new scope to contain bindings and temporaries from `if let` guards, to
216
222
// ensure they're dropped before the arm's pattern's bindings. This extends to the end of
217
223
// the arm body and is the scope of its locals as well.
218
224
visitor. enter_scope ( Scope { local_id : arm. hir_id . local_id , data : ScopeData :: MatchGuard } ) ;
219
- visitor. cx . var_parent = visitor. cx . parent ;
225
+ visitor. cx . var_parent = ( visitor. cx . parent , ScopeCompatibility :: FutureCompatible ) ;
220
226
resolve_cond ( visitor, guard) ;
221
227
}
222
228
resolve_expr ( visitor, arm. body , false ) ;
@@ -373,7 +379,7 @@ fn resolve_expr<'tcx>(
373
379
ScopeData :: IfThen
374
380
} ;
375
381
visitor. enter_scope ( Scope { local_id : then. hir_id . local_id , data } ) ;
376
- visitor. cx . var_parent = visitor. cx . parent ;
382
+ visitor. cx . var_parent = ( visitor. cx . parent , ScopeCompatibility :: FutureCompatible ) ;
377
383
resolve_cond ( visitor, cond) ;
378
384
resolve_expr ( visitor, then, true ) ;
379
385
visitor. cx = expr_cx;
@@ -388,7 +394,7 @@ fn resolve_expr<'tcx>(
388
394
ScopeData :: IfThen
389
395
} ;
390
396
visitor. enter_scope ( Scope { local_id : then. hir_id . local_id , data } ) ;
391
- visitor. cx . var_parent = visitor. cx . parent ;
397
+ visitor. cx . var_parent = ( visitor. cx . parent , ScopeCompatibility :: FutureCompatible ) ;
392
398
resolve_cond ( visitor, cond) ;
393
399
resolve_expr ( visitor, then, true ) ;
394
400
visitor. cx = expr_cx;
@@ -498,7 +504,7 @@ fn resolve_local<'tcx>(
498
504
//
499
505
// Processing of `let a` will have already decided to extend the lifetime of this
500
506
// `super let` to its own var_scope. We use that scope.
501
- visitor. cx . var_parent = scope. scope ;
507
+ visitor. cx . var_parent = ( scope. scope , scope . compat ) ;
502
508
// Inherit compatibility from the original `let` statement. If the original `let`
503
509
// was regular, lifetime extension should apply as normal. If the original `let` was
504
510
// `super`, blocks within the initializer will be affected by #145838.
@@ -512,9 +518,11 @@ fn resolve_local<'tcx>(
512
518
//
513
519
// Iterate up to the enclosing destruction scope to find the same scope that will also
514
520
// be used for the result of the block itself.
515
- if let Some ( inner_scope) = visitor. cx . var_parent {
516
- ( visitor. cx . var_parent , _) =
517
- visitor. scope_tree . default_temporary_scope ( inner_scope)
521
+ if let ( Some ( inner_scope) , _) = visitor. cx . var_parent {
522
+ // NB(@dianne): This could use the incompatibility reported by
523
+ // `default_temporary_scope` to make `tail_expr_drop_order` more comprehensive.
524
+ visitor. cx . var_parent =
525
+ ( visitor. scope_tree . default_temporary_scope ( inner_scope) . 0 , ScopeCompatibility :: FutureCompatible ) ;
518
526
}
519
527
// Blocks within the initializer will be affected by #145838.
520
528
( LetKind :: Super , ScopeCompatibility :: FutureCompatible )
@@ -524,7 +532,7 @@ fn resolve_local<'tcx>(
524
532
525
533
if let Some ( expr) = init {
526
534
let scope = ExtendedTemporaryScope {
527
- scope : visitor. cx . var_parent ,
535
+ scope : visitor. cx . var_parent . 0 ,
528
536
let_kind : source_let_kind,
529
537
compat,
530
538
} ;
@@ -536,8 +544,8 @@ fn resolve_local<'tcx>(
536
544
expr. hir_id ,
537
545
RvalueCandidate {
538
546
target : expr. hir_id . local_id ,
539
- lifetime : visitor. cx . var_parent ,
540
- compat : ScopeCompatibility :: FutureCompatible ,
547
+ lifetime : visitor. cx . var_parent . 0 ,
548
+ compat : visitor . cx . var_parent . 1 ,
541
549
} ,
542
550
) ;
543
551
}
@@ -818,7 +826,7 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> {
818
826
self . enter_body ( body. value . hir_id , |this| {
819
827
if this. tcx . hir_body_owner_kind ( owner_id) . is_fn_or_closure ( ) {
820
828
// The arguments and `self` are parented to the fn.
821
- this. cx . var_parent = this. cx . parent ;
829
+ this. cx . var_parent = ( this. cx . parent , ScopeCompatibility :: FutureCompatible ) ;
822
830
for param in body. params {
823
831
this. visit_pat ( param. pat ) ;
824
832
}
@@ -844,7 +852,7 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> {
844
852
// would *not* let the `f()` temporary escape into an outer scope
845
853
// (i.e., `'static`), which means that after `g` returns, it drops,
846
854
// and all the associated destruction scope rules apply.
847
- this. cx . var_parent = None ;
855
+ this. cx . var_parent = ( None , ScopeCompatibility :: FutureCompatible ) ;
848
856
this. enter_scope ( Scope {
849
857
local_id : body. value . hir_id . local_id ,
850
858
data : ScopeData :: Destruction ,
@@ -896,7 +904,7 @@ pub(crate) fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> &ScopeTree {
896
904
let mut visitor = ScopeResolutionVisitor {
897
905
tcx,
898
906
scope_tree : ScopeTree :: default ( ) ,
899
- cx : Context { parent : None , var_parent : None } ,
907
+ cx : Context { parent : None , var_parent : ( None , ScopeCompatibility :: FutureCompatible ) } ,
900
908
extended_super_lets : Default :: default ( ) ,
901
909
} ;
902
910
0 commit comments