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