@@ -18,6 +18,7 @@ use rustc_middle::ty::query::Providers;
1818use rustc_middle:: ty:: TyCtxt ;
1919use rustc_span:: source_map;
2020use rustc_span:: Span ;
21+ use smallvec:: SmallVec ;
2122
2223use std:: mem;
2324
@@ -203,6 +204,106 @@ fn resolve_stmt<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, stmt: &'tcx h
203204 visitor. cx . parent = prev_parent;
204205}
205206
207+ fn mark_local_terminating_scopes < ' tcx > ( expr : & ' tcx hir:: Expr < ' tcx > ) -> FxHashSet < hir:: ItemLocalId > {
208+ struct LocalAccessResolutionVisitor < ' a > {
209+ locals : & ' a mut FxHashSet < hir:: ItemLocalId > ,
210+ }
211+ impl < ' a > LocalAccessResolutionVisitor < ' a > {
212+ fn probe < ' b > ( & mut self , expr : & ' b Expr < ' b > ) {
213+ if self . locals . contains ( & expr. hir_id . local_id ) {
214+ return ;
215+ }
216+ let mut nested_expr = expr;
217+ let mut ops = SmallVec :: < [ _ ; 4 ] > :: new ( ) ;
218+ enum OpTy {
219+ Ref ,
220+ Deref ,
221+ Project ,
222+ Local ,
223+ }
224+ loop {
225+ match nested_expr. kind {
226+ hir:: ExprKind :: Path ( hir:: QPath :: Resolved (
227+ _,
228+ hir:: Path { res : hir:: def:: Res :: Local ( _) , .. } ,
229+ ) ) => {
230+ ops. push ( ( nested_expr, OpTy :: Local ) ) ;
231+ break ;
232+ }
233+ hir:: ExprKind :: AddrOf ( _, _, subexpr) => {
234+ ops. push ( ( nested_expr, OpTy :: Ref ) ) ;
235+ nested_expr = subexpr;
236+ }
237+ hir:: ExprKind :: Unary ( hir:: UnOp :: Deref , subexpr) => {
238+ ops. push ( ( nested_expr, OpTy :: Deref ) ) ;
239+ nested_expr = subexpr;
240+ }
241+ hir:: ExprKind :: Field ( subexpr, _) => {
242+ ops. push ( ( nested_expr, OpTy :: Project ) ) ;
243+ nested_expr = subexpr;
244+ }
245+ hir:: ExprKind :: Index ( subexpr, idxexpr) => {
246+ ops. push ( ( nested_expr, OpTy :: Project ) ) ;
247+ nested_expr = subexpr;
248+ intravisit:: walk_expr ( self , idxexpr) ;
249+ }
250+ _ => {
251+ drop ( ops) ;
252+ intravisit:: walk_expr ( self , expr) ;
253+ return ;
254+ }
255+ }
256+ }
257+ let mut ref_level = SmallVec :: < [ _ ; 4 ] > :: new ( ) ;
258+ let mut ops_iter = ops. into_iter ( ) . rev ( ) ;
259+ ops_iter. next ( ) . unwrap ( ) ;
260+ for ( expr, op) in ops_iter {
261+ match op {
262+ OpTy :: Ref => {
263+ ref_level. push ( expr) ;
264+ }
265+ OpTy :: Deref => {
266+ if let Some ( ref_expr) = ref_level. pop ( ) {
267+ self . locals . insert ( ref_expr. hir_id . local_id ) ;
268+ }
269+ }
270+ OpTy :: Project => {
271+ ref_level. clear ( ) ;
272+ }
273+ OpTy :: Local => {
274+ panic ! ( "unexpected encounter of Local" )
275+ }
276+ }
277+ }
278+ self . locals . insert ( expr. hir_id . local_id ) ;
279+ }
280+ }
281+ impl < ' a , ' b > Visitor < ' a > for LocalAccessResolutionVisitor < ' b > {
282+ type Map = intravisit:: ErasedMap < ' a > ;
283+ fn nested_visit_map ( & mut self ) -> NestedVisitorMap < Self :: Map > {
284+ NestedVisitorMap :: None
285+ }
286+ fn visit_expr ( & mut self , expr : & ' a Expr < ' a > ) {
287+ match expr. kind {
288+ hir:: ExprKind :: AddrOf ( ..)
289+ | hir:: ExprKind :: Unary ( hir:: UnOp :: Deref , _)
290+ | hir:: ExprKind :: Field ( ..)
291+ | hir:: ExprKind :: Index ( ..)
292+ | hir:: ExprKind :: Path ( ..) => self . probe ( expr) ,
293+ hir:: ExprKind :: Block ( ..)
294+ | hir:: ExprKind :: Closure ( ..)
295+ | hir:: ExprKind :: ConstBlock ( ..) => { }
296+ _ => intravisit:: walk_expr ( self , expr) ,
297+ }
298+ }
299+ }
300+ let mut locals = Default :: default ( ) ;
301+ let mut resolution_visitor = LocalAccessResolutionVisitor { locals : & mut locals } ;
302+ resolution_visitor. visit_expr ( expr) ;
303+ // visitor.terminating_scopes.extend(locals.iter().copied());
304+ locals
305+ }
306+
206307fn resolve_expr < ' tcx > ( visitor : & mut RegionResolutionVisitor < ' tcx > , expr : & ' tcx hir:: Expr < ' tcx > ) {
207308 debug ! ( "resolve_expr - pre-increment {} expr = {:?}" , visitor. expr_and_pat_count, expr) ;
208309
@@ -396,7 +497,15 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h
396497 let expr_cx = visitor. cx ;
397498 visitor. enter_scope ( Scope { id : then. hir_id . local_id , data : ScopeData :: IfThen } ) ;
398499 visitor. cx . var_parent = visitor. cx . parent ;
399- visitor. visit_expr ( cond) ;
500+ {
501+ visitor. visit_expr ( cond) ;
502+ let lifetime = Scope { id : cond. hir_id . local_id , data : ScopeData :: Node } ;
503+ for local in mark_local_terminating_scopes ( cond) {
504+ if local != cond. hir_id . local_id {
505+ visitor. scope_tree . record_local_access_scope ( local, lifetime) ;
506+ }
507+ }
508+ }
400509 visitor. visit_expr ( then) ;
401510 visitor. cx = expr_cx;
402511 visitor. visit_expr ( otherwise) ;
@@ -406,11 +515,39 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h
406515 let expr_cx = visitor. cx ;
407516 visitor. enter_scope ( Scope { id : then. hir_id . local_id , data : ScopeData :: IfThen } ) ;
408517 visitor. cx . var_parent = visitor. cx . parent ;
409- visitor. visit_expr ( cond) ;
518+ {
519+ visitor. visit_expr ( cond) ;
520+ let lifetime = Scope { id : cond. hir_id . local_id , data : ScopeData :: Node } ;
521+ for local in mark_local_terminating_scopes ( cond) {
522+ if local != cond. hir_id . local_id {
523+ visitor. scope_tree . record_local_access_scope ( local, lifetime) ;
524+ }
525+ }
526+ }
410527 visitor. visit_expr ( then) ;
411528 visitor. cx = expr_cx;
412529 }
413530
531+ hir:: ExprKind :: Match ( subexpr, arms, _) => {
532+ visitor. visit_expr ( subexpr) ;
533+ let lifetime = Scope { id : subexpr. hir_id . local_id , data : ScopeData :: Node } ;
534+ for local in mark_local_terminating_scopes ( subexpr) {
535+ if local != subexpr. hir_id . local_id {
536+ visitor. scope_tree . record_local_access_scope ( local, lifetime) ;
537+ }
538+ }
539+ walk_list ! ( visitor, visit_arm, arms) ;
540+ }
541+
542+ hir:: ExprKind :: Index ( subexpr, idxexpr) => {
543+ visitor. visit_expr ( subexpr) ;
544+ visitor. visit_expr ( idxexpr) ;
545+ visitor. scope_tree . record_eager_scope (
546+ idxexpr. hir_id . local_id ,
547+ Scope { id : expr. hir_id . local_id , data : ScopeData :: Node } ,
548+ ) ;
549+ }
550+
414551 _ => intravisit:: walk_expr ( visitor, expr) ,
415552 }
416553
@@ -683,10 +820,17 @@ fn resolve_local<'tcx>(
683820 visitor. scope_tree . record_rvalue_scope ( expr. hir_id . local_id , blk_scope) ;
684821
685822 match expr. kind {
686- hir:: ExprKind :: AddrOf ( _, _, ref subexpr)
687- | hir:: ExprKind :: Unary ( hir:: UnOp :: Deref , ref subexpr)
688- | hir:: ExprKind :: Field ( ref subexpr, _)
689- | hir:: ExprKind :: Index ( ref subexpr, _) => {
823+ hir:: ExprKind :: AddrOf ( _, _, subexpr)
824+ | hir:: ExprKind :: Unary ( hir:: UnOp :: Deref , subexpr)
825+ | hir:: ExprKind :: Field ( subexpr, _)
826+ | hir:: ExprKind :: Index ( subexpr, _) => {
827+ if let hir:: ExprKind :: Path ( hir:: QPath :: Resolved (
828+ _,
829+ hir:: Path { res : hir:: def:: Res :: Local ( _) , .. } ,
830+ ) ) = & subexpr. kind
831+ {
832+ return ;
833+ }
690834 expr = & subexpr;
691835 }
692836 _ => {
0 commit comments