@@ -58,6 +58,7 @@ use std::mem;
5858use  smallvec:: SmallVec ; 
5959use  syntax:: attr; 
6060use  syntax:: ast; 
61+ use  syntax:: ptr:: P  as  AstP ; 
6162use  syntax:: ast:: * ; 
6263use  syntax:: errors; 
6364use  syntax:: ext:: hygiene:: ExpnId ; 
@@ -468,7 +469,7 @@ impl<'a> LoweringContext<'a> {
468469            fn  visit_pat ( & mut  self ,  p :  & ' tcx  Pat )  { 
469470                match  p. node  { 
470471                    // Doesn't generate a HIR node 
471-                     PatKind :: Paren ( ..)  => { } , 
472+                     PatKind :: Paren ( ..)  |  PatKind :: Rest   => { } , 
472473                    _ => { 
473474                        if  let  Some ( owner)  = self . hir_id_owner  { 
474475                            self . lctx . lower_node_id_with_owner ( p. id ,  owner) ; 
@@ -1157,7 +1158,7 @@ impl<'a> LoweringContext<'a> {
11571158        & mut  self , 
11581159        capture_clause :  CaptureBy , 
11591160        closure_node_id :  NodeId , 
1160-         ret_ty :  Option < syntax :: ptr :: P < Ty > > , 
1161+         ret_ty :  Option < AstP < Ty > > , 
11611162        span :  Span , 
11621163        body :  impl  FnOnce ( & mut  LoweringContext < ' _ > )  -> hir:: Expr , 
11631164    )  -> hir:: ExprKind  { 
@@ -4173,45 +4174,20 @@ impl<'a> LoweringContext<'a> {
41734174        let  node = match  p. node  { 
41744175            PatKind :: Wild  => hir:: PatKind :: Wild , 
41754176            PatKind :: Ident ( ref  binding_mode,  ident,  ref  sub)  => { 
4176-                 match  self . resolver . get_partial_res ( p. id ) . map ( |d| d. base_res ( ) )  { 
4177-                     // `None` can occur in body-less function signatures 
4178-                     res @ None  | res @ Some ( Res :: Local ( _) )  => { 
4179-                         let  canonical_id = match  res { 
4180-                             Some ( Res :: Local ( id) )  => id, 
4181-                             _ => p. id , 
4182-                         } ; 
4183- 
4184-                         hir:: PatKind :: Binding ( 
4185-                             self . lower_binding_mode ( binding_mode) , 
4186-                             self . lower_node_id ( canonical_id) , 
4187-                             ident, 
4188-                             sub. as_ref ( ) . map ( |x| self . lower_pat ( x) ) , 
4189-                         ) 
4190-                     } 
4191-                     Some ( res)  => hir:: PatKind :: Path ( hir:: QPath :: Resolved ( 
4192-                         None , 
4193-                         P ( hir:: Path  { 
4194-                             span :  ident. span , 
4195-                             res :  self . lower_res ( res) , 
4196-                             segments :  hir_vec ! [ hir:: PathSegment :: from_ident( ident) ] , 
4197-                         } ) , 
4198-                     ) ) , 
4199-                 } 
4177+                 let  lower_sub = |this :  & mut  Self | sub. as_ref ( ) . map ( |x| this. lower_pat ( x) ) ; 
4178+                 self . lower_pat_ident ( p,  binding_mode,  ident,  lower_sub) 
42004179            } 
42014180            PatKind :: Lit ( ref  e)  => hir:: PatKind :: Lit ( P ( self . lower_expr ( e) ) ) , 
4202-             PatKind :: TupleStruct ( ref  path,  ref  pats,  ddpos )  => { 
4181+             PatKind :: TupleStruct ( ref  path,  ref  pats)  => { 
42034182                let  qpath = self . lower_qpath ( 
42044183                    p. id , 
42054184                    & None , 
42064185                    path, 
42074186                    ParamMode :: Optional , 
42084187                    ImplTraitContext :: disallowed ( ) , 
42094188                ) ; 
4210-                 hir:: PatKind :: TupleStruct ( 
4211-                     qpath, 
4212-                     pats. iter ( ) . map ( |x| self . lower_pat ( x) ) . collect ( ) , 
4213-                     ddpos, 
4214-                 ) 
4189+                 let  ( pats,  ddpos)  = self . lower_pat_tuple ( pats,  "tuple struct" ) ; 
4190+                 hir:: PatKind :: TupleStruct ( qpath,  pats,  ddpos) 
42154191            } 
42164192            PatKind :: Path ( ref  qself,  ref  path)  => { 
42174193                let  qpath = self . lower_qpath ( 
@@ -4248,8 +4224,9 @@ impl<'a> LoweringContext<'a> {
42484224                    . collect ( ) ; 
42494225                hir:: PatKind :: Struct ( qpath,  fs,  etc) 
42504226            } 
4251-             PatKind :: Tuple ( ref  elts,  ddpos)  => { 
4252-                 hir:: PatKind :: Tuple ( elts. iter ( ) . map ( |x| self . lower_pat ( x) ) . collect ( ) ,  ddpos) 
4227+             PatKind :: Tuple ( ref  pats)  => { 
4228+                 let  ( pats,  ddpos)  = self . lower_pat_tuple ( pats,  "tuple" ) ; 
4229+                 hir:: PatKind :: Tuple ( pats,  ddpos) 
42534230            } 
42544231            PatKind :: Box ( ref  inner)  => hir:: PatKind :: Box ( self . lower_pat ( inner) ) , 
42554232            PatKind :: Ref ( ref  inner,  mutbl)  => { 
@@ -4260,22 +4237,167 @@ impl<'a> LoweringContext<'a> {
42604237                P ( self . lower_expr ( e2) ) , 
42614238                self . lower_range_end ( end) , 
42624239            ) , 
4263-             PatKind :: Slice ( ref  before ,   ref  slice ,   ref  after )  => hir :: PatKind :: Slice ( 
4264-                 before . iter ( ) . map ( |x|  self . lower_pat ( x ) ) . collect ( ) , 
4265-                 slice . as_ref ( ) . map ( |x|  self . lower_pat ( x ) ) , 
4266-                 after . iter ( ) . map ( |x|  self . lower_pat ( x ) ) . collect ( ) , 
4267-             ) , 
4240+             PatKind :: Slice ( ref  pats )  => self . lower_pat_slice ( pats ) , 
4241+             PatKind :: Rest  =>  { 
4242+                 // If we reach here the `..` pattern is not semantically allowed. 
4243+                 self . ban_illegal_rest_pat ( p . span ) 
4244+             } 
42684245            PatKind :: Paren ( ref  inner)  => return  self . lower_pat ( inner) , 
42694246            PatKind :: Mac ( _)  => panic ! ( "Shouldn't exist here" ) , 
42704247        } ; 
42714248
4249+         self . pat_with_node_id_of ( p,  node) 
4250+     } 
4251+ 
4252+     fn  lower_pat_tuple ( 
4253+         & mut  self , 
4254+         pats :  & [ AstP < Pat > ] , 
4255+         ctx :  & str , 
4256+     )  -> ( HirVec < P < hir:: Pat > > ,  Option < usize > )  { 
4257+         let  mut  elems = Vec :: with_capacity ( pats. len ( ) ) ; 
4258+         let  mut  rest = None ; 
4259+ 
4260+         let  mut  iter = pats. iter ( ) . enumerate ( ) ; 
4261+         while  let  Some ( ( idx,  pat) )  = iter. next ( )  { 
4262+             // Interpret the first `..` pattern as a subtuple pattern. 
4263+             if  pat. is_rest ( )  { 
4264+                 rest = Some ( ( idx,  pat. span ) ) ; 
4265+                 break ; 
4266+             } 
4267+             // It was not a subslice pattern so lower it normally. 
4268+             elems. push ( self . lower_pat ( pat) ) ; 
4269+         } 
4270+ 
4271+         while  let  Some ( ( _,  pat) )  = iter. next ( )  { 
4272+             // There was a previous subtuple pattern; make sure we don't allow more. 
4273+             if  pat. is_rest ( )  { 
4274+                 self . ban_extra_rest_pat ( pat. span ,  rest. unwrap ( ) . 1 ,  ctx) ; 
4275+             }  else  { 
4276+                 elems. push ( self . lower_pat ( pat) ) ; 
4277+             } 
4278+         } 
4279+ 
4280+         ( elems. into ( ) ,  rest. map ( |( ddpos,  _) | ddpos) ) 
4281+     } 
4282+ 
4283+     fn  lower_pat_slice ( & mut  self ,  pats :  & [ AstP < Pat > ] )  -> hir:: PatKind  { 
4284+         let  mut  before = Vec :: new ( ) ; 
4285+         let  mut  after = Vec :: new ( ) ; 
4286+         let  mut  slice = None ; 
4287+         let  mut  prev_rest_span = None ; 
4288+ 
4289+         let  mut  iter = pats. iter ( ) ; 
4290+         while  let  Some ( pat)  = iter. next ( )  { 
4291+             // Interpret the first `((ref mut?)? x @)? ..` pattern as a subslice pattern. 
4292+             match  pat. node  { 
4293+                 PatKind :: Rest  => { 
4294+                     prev_rest_span = Some ( pat. span ) ; 
4295+                     slice = Some ( self . pat_wild_with_node_id_of ( pat) ) ; 
4296+                     break ; 
4297+                 } , 
4298+                 PatKind :: Ident ( ref  bm,  ident,  Some ( ref  sub) )  if  sub. is_rest ( )  => { 
4299+                     prev_rest_span = Some ( sub. span ) ; 
4300+                     let  lower_sub = |this :  & mut  Self | Some ( this. pat_wild_with_node_id_of ( sub) ) ; 
4301+                     let  node = self . lower_pat_ident ( pat,  bm,  ident,  lower_sub) ; 
4302+                     slice = Some ( self . pat_with_node_id_of ( pat,  node) ) ; 
4303+                     break ; 
4304+                 } , 
4305+                 _ => { } 
4306+             } 
4307+ 
4308+             // It was not a subslice pattern so lower it normally. 
4309+             before. push ( self . lower_pat ( pat) ) ; 
4310+         } 
4311+ 
4312+         while  let  Some ( pat)  = iter. next ( )  { 
4313+             // There was a previous subslice pattern; make sure we don't allow more. 
4314+             let  rest_span = match  pat. node  { 
4315+                 PatKind :: Rest  => Some ( pat. span ) , 
4316+                 PatKind :: Ident ( ..,  Some ( ref  sub) )  if  sub. is_rest ( )  => { 
4317+                     // The `HirValidator` is merciless; add a `_` pattern to avoid ICEs. 
4318+                     after. push ( self . pat_wild_with_node_id_of ( pat) ) ; 
4319+                     Some ( sub. span ) 
4320+                 } , 
4321+                 _ => None , 
4322+             } ; 
4323+             if  let  Some ( rest_span)  = rest_span { 
4324+                 self . ban_extra_rest_pat ( rest_span,  prev_rest_span. unwrap ( ) ,  "slice" ) ; 
4325+             }  else  { 
4326+                 after. push ( self . lower_pat ( pat) ) ; 
4327+             } 
4328+         } 
4329+ 
4330+         hir:: PatKind :: Slice ( before. into ( ) ,  slice,  after. into ( ) ) 
4331+     } 
4332+ 
4333+     fn  lower_pat_ident ( 
4334+         & mut  self , 
4335+         p :  & Pat , 
4336+         binding_mode :  & BindingMode , 
4337+         ident :  Ident , 
4338+         lower_sub :  impl  FnOnce ( & mut  Self )  -> Option < P < hir:: Pat > > , 
4339+     )  -> hir:: PatKind  { 
4340+         match  self . resolver . get_partial_res ( p. id ) . map ( |d| d. base_res ( ) )  { 
4341+             // `None` can occur in body-less function signatures 
4342+             res @ None  | res @ Some ( Res :: Local ( _) )  => { 
4343+                 let  canonical_id = match  res { 
4344+                     Some ( Res :: Local ( id) )  => id, 
4345+                     _ => p. id , 
4346+                 } ; 
4347+ 
4348+                 hir:: PatKind :: Binding ( 
4349+                     self . lower_binding_mode ( binding_mode) , 
4350+                     self . lower_node_id ( canonical_id) , 
4351+                     ident, 
4352+                     lower_sub ( self ) , 
4353+                 ) 
4354+             } 
4355+             Some ( res)  => hir:: PatKind :: Path ( hir:: QPath :: Resolved ( 
4356+                 None , 
4357+                 P ( hir:: Path  { 
4358+                     span :  ident. span , 
4359+                     res :  self . lower_res ( res) , 
4360+                     segments :  hir_vec ! [ hir:: PathSegment :: from_ident( ident) ] , 
4361+                 } ) , 
4362+             ) ) , 
4363+         } 
4364+     } 
4365+ 
4366+     fn  pat_wild_with_node_id_of ( & mut  self ,  p :  & Pat )  -> P < hir:: Pat >  { 
4367+         self . pat_with_node_id_of ( p,  hir:: PatKind :: Wild ) 
4368+     } 
4369+ 
4370+     /// Construct a `Pat` with the `HirId` of `p.id` lowered. 
4371+ fn  pat_with_node_id_of ( & mut  self ,  p :  & Pat ,  node :  hir:: PatKind )  -> P < hir:: Pat >  { 
42724372        P ( hir:: Pat  { 
42734373            hir_id :  self . lower_node_id ( p. id ) , 
42744374            node, 
42754375            span :  p. span , 
42764376        } ) 
42774377    } 
42784378
4379+     /// Emit a friendly error for extra `..` patterns in a tuple/tuple struct/slice pattern. 
4380+ fn  ban_extra_rest_pat ( & self ,  sp :  Span ,  prev_sp :  Span ,  ctx :  & str )  { 
4381+         self . diagnostic ( ) 
4382+             . struct_span_err ( sp,  & format ! ( "`..` can only be used once per {} pattern" ,  ctx) ) 
4383+             . span_label ( sp,  & format ! ( "can only be used once per {} pattern" ,  ctx) ) 
4384+             . span_label ( prev_sp,  "previously used here" ) 
4385+             . emit ( ) ; 
4386+     } 
4387+ 
4388+     /// Used to ban the `..` pattern in places it shouldn't be semantically. 
4389+ fn  ban_illegal_rest_pat ( & self ,  sp :  Span )  -> hir:: PatKind  { 
4390+         self . diagnostic ( ) 
4391+             . struct_span_err ( sp,  "`..` patterns are not allowed here" ) 
4392+             . note ( "only allowed in tuple, tuple struct, and slice patterns" ) 
4393+             . emit ( ) ; 
4394+ 
4395+         // We're not in a list context so `..` can be reasonably treated 
4396+         // as `_` because it should always be valid and roughly matches the 
4397+         // intent of `..` (notice that the rest of a single slot is that slot). 
4398+         hir:: PatKind :: Wild 
4399+     } 
4400+ 
42794401    fn  lower_range_end ( & mut  self ,  e :  & RangeEnd )  -> hir:: RangeEnd  { 
42804402        match  * e { 
42814403            RangeEnd :: Included ( _)  => hir:: RangeEnd :: Included , 
0 commit comments