@@ -4174,30 +4174,8 @@ impl<'a> LoweringContext<'a> {
4174
4174
let node = match p. node {
4175
4175
PatKind :: Wild => hir:: PatKind :: Wild ,
4176
4176
PatKind :: Ident ( ref binding_mode, ident, ref sub) => {
4177
- match self . resolver . get_partial_res ( p. id ) . map ( |d| d. base_res ( ) ) {
4178
- // `None` can occur in body-less function signatures
4179
- res @ None | res @ Some ( Res :: Local ( _) ) => {
4180
- let canonical_id = match res {
4181
- Some ( Res :: Local ( id) ) => id,
4182
- _ => p. id ,
4183
- } ;
4184
-
4185
- hir:: PatKind :: Binding (
4186
- self . lower_binding_mode ( binding_mode) ,
4187
- self . lower_node_id ( canonical_id) ,
4188
- ident,
4189
- sub. as_ref ( ) . map ( |x| self . lower_pat ( x) ) ,
4190
- )
4191
- }
4192
- Some ( res) => hir:: PatKind :: Path ( hir:: QPath :: Resolved (
4193
- None ,
4194
- P ( hir:: Path {
4195
- span : ident. span ,
4196
- res : self . lower_res ( res) ,
4197
- segments : hir_vec ! [ hir:: PathSegment :: from_ident( ident) ] ,
4198
- } ) ,
4199
- ) ) ,
4200
- }
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)
4201
4179
}
4202
4180
PatKind :: Lit ( ref e) => hir:: PatKind :: Lit ( P ( self . lower_expr ( e) ) ) ,
4203
4181
PatKind :: TupleStruct ( ref path, ref pats) => {
@@ -4259,11 +4237,7 @@ impl<'a> LoweringContext<'a> {
4259
4237
P ( self . lower_expr ( e2) ) ,
4260
4238
self . lower_range_end ( end) ,
4261
4239
) ,
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
- ) ,
4240
+ PatKind :: Slice ( ref pats) => self . lower_pat_slice ( pats) ,
4267
4241
PatKind :: Rest => {
4268
4242
// If we reach here the `..` pattern is not semantically allowed.
4269
4243
self . ban_illegal_rest_pat ( p. span )
@@ -4272,11 +4246,7 @@ impl<'a> LoweringContext<'a> {
4272
4246
PatKind :: Mac ( _) => panic ! ( "Shouldn't exist here" ) ,
4273
4247
} ;
4274
4248
4275
- P ( hir:: Pat {
4276
- hir_id : self . lower_node_id ( p. id ) ,
4277
- node,
4278
- span : p. span ,
4279
- } )
4249
+ self . pat_bound ( p, node)
4280
4250
}
4281
4251
4282
4252
fn lower_pat_tuple (
@@ -4310,6 +4280,102 @@ impl<'a> LoweringContext<'a> {
4310
4280
( elems. into ( ) , rest. map ( |( ddpos, _) | ddpos) )
4311
4281
}
4312
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_bound_wild ( 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_bound_wild ( sub) ) ;
4301
+ let node = self . lower_pat_ident ( pat, bm, ident, lower_sub) ;
4302
+ slice = Some ( self . pat_bound ( 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_bound_wild ( 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_bound_wild ( & mut self , p : & Pat ) -> P < hir:: Pat > {
4367
+ self . pat_bound ( p, hir:: PatKind :: Wild )
4368
+ }
4369
+
4370
+ /// Construct a `Pat` with the `HirId` of `p.id` lowered.
4371
+ fn pat_bound ( & mut self , p : & Pat , node : hir:: PatKind ) -> P < hir:: Pat > {
4372
+ P ( hir:: Pat {
4373
+ hir_id : self . lower_node_id ( p. id ) ,
4374
+ node,
4375
+ span : p. span ,
4376
+ } )
4377
+ }
4378
+
4313
4379
/// Emit a friendly error for extra `..` patterns in a tuple/tuple struct/slice pattern.
4314
4380
fn ban_extra_rest_pat ( & self , sp : Span , prev_sp : Span , ctx : & str ) {
4315
4381
self . diagnostic ( )
0 commit comments