@@ -55,6 +55,14 @@ impl<'a> From<(&'a hir::LetExpr<'a>, HirId)> for Declaration<'a> {
5555    } 
5656} 
5757
58+ /// The `GatherLocalsVisitor` is responsible for initializing local variable types 
59+ /// in the [`ty::TypeckResults`] for all subpatterns in statements and expressions 
60+ /// like `let`, `match`, and params of function bodies. It also adds `Sized` bounds 
61+ /// for these types (with exceptions for unzied feature gates like `unsized_fn_params`). 
62+ /// 
63+ /// Failure to visit locals will cause an ICE in writeback when the local's type is 
64+ /// resolved. Visiting locals twice will ICE in the `GatherLocalsVisitor`, since it 
65+ /// will overwrite the type previously stored in the local. 
5866pub ( super )  struct  GatherLocalsVisitor < ' a ,  ' tcx >  { 
5967    fcx :  & ' a  FnCtxt < ' a ,  ' tcx > , 
6068    // parameters are special cases of patterns, but we want to handle them as 
@@ -63,22 +71,50 @@ pub(super) struct GatherLocalsVisitor<'a, 'tcx> {
6371    outermost_fn_param_pat :  Option < ( Span ,  HirId ) > , 
6472} 
6573
74+ // N.B. additional `gather_*` functions should be careful to only walk the pattern 
75+ // for new expressions, since visiting sub-expressions or nested bodies may initialize 
76+ // locals which are not conceptually owned by the gathered statement or expression. 
6677impl < ' a ,  ' tcx >  GatherLocalsVisitor < ' a ,  ' tcx >  { 
67-     pub ( super )  fn  new ( fcx :  & ' a  FnCtxt < ' a ,  ' tcx > )  -> Self  { 
68-         Self  {  fcx,  outermost_fn_param_pat :  None  } 
78+     pub ( crate )  fn  gather_from_local ( fcx :  & ' a  FnCtxt < ' a ,  ' tcx > ,  local :  & ' tcx  hir:: LetStmt < ' tcx > )  { 
79+         let  mut  visitor = GatherLocalsVisitor  {  fcx,  outermost_fn_param_pat :  None  } ; 
80+         visitor. declare ( local. into ( ) ) ; 
81+         visitor. visit_pat ( local. pat ) ; 
82+     } 
83+ 
84+     pub ( crate )  fn  gather_from_let_expr ( 
85+         fcx :  & ' a  FnCtxt < ' a ,  ' tcx > , 
86+         let_expr :  & ' tcx  hir:: LetExpr < ' tcx > , 
87+         expr_hir_id :  hir:: HirId , 
88+     )  { 
89+         let  mut  visitor = GatherLocalsVisitor  {  fcx,  outermost_fn_param_pat :  None  } ; 
90+         visitor. declare ( ( let_expr,  expr_hir_id) . into ( ) ) ; 
91+         visitor. visit_pat ( let_expr. pat ) ; 
92+     } 
93+ 
94+     pub ( crate )  fn  gather_from_param ( fcx :  & ' a  FnCtxt < ' a ,  ' tcx > ,  param :  & ' tcx  hir:: Param < ' tcx > )  { 
95+         let  mut  visitor = GatherLocalsVisitor  { 
96+             fcx, 
97+             outermost_fn_param_pat :  Some ( ( param. ty_span ,  param. hir_id ) ) , 
98+         } ; 
99+         visitor. visit_pat ( param. pat ) ; 
100+     } 
101+ 
102+     pub ( crate )  fn  gather_from_arm ( fcx :  & ' a  FnCtxt < ' a ,  ' tcx > ,  local :  & ' tcx  hir:: Arm < ' tcx > )  { 
103+         let  mut  visitor = GatherLocalsVisitor  {  fcx,  outermost_fn_param_pat :  None  } ; 
104+         visitor. visit_pat ( local. pat ) ; 
69105    } 
70106
71107    fn  assign ( & mut  self ,  span :  Span ,  nid :  HirId ,  ty_opt :  Option < Ty < ' tcx > > )  -> Ty < ' tcx >  { 
72108        match  ty_opt { 
73109            None  => { 
74110                // Infer the variable's type. 
75111                let  var_ty = self . fcx . next_ty_var ( span) ; 
76-                 self . fcx . locals . borrow_mut ( ) . insert ( nid,  var_ty) ; 
112+                 assert_eq ! ( self . fcx. locals. borrow_mut( ) . insert( nid,  var_ty) ,   None ) ; 
77113                var_ty
78114            } 
79115            Some ( typ)  => { 
80116                // Take type that the user specified. 
81-                 self . fcx . locals . borrow_mut ( ) . insert ( nid,  typ) ; 
117+                 assert_eq ! ( self . fcx. locals. borrow_mut( ) . insert( nid,  typ) ,   None ) ; 
82118                typ
83119            } 
84120        } 
@@ -133,13 +169,6 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
133169        intravisit:: walk_expr ( self ,  expr) 
134170    } 
135171
136-     fn  visit_param ( & mut  self ,  param :  & ' tcx  hir:: Param < ' tcx > )  { 
137-         let  old_outermost_fn_param_pat =
138-             self . outermost_fn_param_pat . replace ( ( param. ty_span ,  param. hir_id ) ) ; 
139-         intravisit:: walk_param ( self ,  param) ; 
140-         self . outermost_fn_param_pat  = old_outermost_fn_param_pat; 
141-     } 
142- 
143172    // Add pattern bindings. 
144173    fn  visit_pat ( & mut  self ,  p :  & ' tcx  hir:: Pat < ' tcx > )  { 
145174        if  let  PatKind :: Binding ( _,  _,  ident,  _)  = p. kind  { 
0 commit comments