@@ -65,6 +65,8 @@ enum IsRepeatExpr {
65
65
Yes ,
66
66
}
67
67
68
+ struct IsNeverPattern ;
69
+
68
70
/// Describes whether an `AnonConst` is a type level const arg or
69
71
/// some other form of anon const (i.e. inline consts or enum discriminants)
70
72
#[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
@@ -3190,12 +3192,16 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
3190
3192
self . resolve_pattern_top ( & local. pat , PatternSource :: Let ) ;
3191
3193
}
3192
3194
3193
- /// build a map from pattern identifiers to binding-info's.
3194
- /// this is done hygienically. This could arise for a macro
3195
- /// that expands into an or-pattern where one 'x' was from the
3196
- /// user and one 'x' came from the macro.
3197
- fn binding_mode_map ( & mut self , pat : & Pat ) -> FxIndexMap < Ident , BindingInfo > {
3195
+ /// Build a map from pattern identifiers to binding-info's, and check the bindings are
3196
+ /// consistent when encountering or-patterns and never patterns.
3197
+ /// This is done hygienically: this could arise for a macro that expands into an or-pattern
3198
+ /// where one 'x' was from the user and one 'x' came from the macro.
3199
+ fn compute_and_check_binding_map (
3200
+ & mut self ,
3201
+ pat : & Pat ,
3202
+ ) -> Result < FxIndexMap < Ident , BindingInfo > , IsNeverPattern > {
3198
3203
let mut binding_map = FxIndexMap :: default ( ) ;
3204
+ let mut is_never_pat = false ;
3199
3205
3200
3206
pat. walk ( & mut |pat| {
3201
3207
match pat. kind {
@@ -3207,18 +3213,26 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
3207
3213
PatKind :: Or ( ref ps) => {
3208
3214
// Check the consistency of this or-pattern and
3209
3215
// then add all bindings to the larger map.
3210
- for bm in self . check_consistent_bindings ( ps) {
3211
- binding_map. extend ( bm) ;
3212
- }
3216
+ let ( bm , np ) = self . compute_and_check_or_pat_binding_map ( ps) ;
3217
+ binding_map. extend ( bm) ;
3218
+ is_never_pat |= np ;
3213
3219
return false ;
3214
3220
}
3221
+ PatKind :: Never => is_never_pat = true ,
3215
3222
_ => { }
3216
3223
}
3217
3224
3218
3225
true
3219
3226
} ) ;
3220
3227
3221
- binding_map
3228
+ if is_never_pat {
3229
+ for ( _, binding) in binding_map {
3230
+ self . report_error ( binding. span , ResolutionError :: BindingInNeverPattern ) ;
3231
+ }
3232
+ Err ( IsNeverPattern )
3233
+ } else {
3234
+ Ok ( binding_map)
3235
+ }
3222
3236
}
3223
3237
3224
3238
fn is_base_res_local ( & self , nid : NodeId ) -> bool {
@@ -3228,33 +3242,37 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
3228
3242
)
3229
3243
}
3230
3244
3231
- /// Checks that all of the arms in an or-pattern have exactly the
3232
- /// same set of bindings, with the same binding modes for each.
3233
- fn check_consistent_bindings (
3245
+ /// Compute the binding map for an or-pattern. Checks that all of the arms in the or-pattern
3246
+ /// have exactly the same set of bindings, with the same binding modes for each.
3247
+ /// Returns the computed binding map and a boolean indicating whether the pattern is a never
3248
+ /// pattern.
3249
+ fn compute_and_check_or_pat_binding_map (
3234
3250
& mut self ,
3235
3251
pats : & [ P < Pat > ] ,
3236
- ) -> Vec < FxIndexMap < Ident , BindingInfo > > {
3237
- // pats is consistent.
3252
+ ) -> ( FxIndexMap < Ident , BindingInfo > , bool ) {
3238
3253
let mut missing_vars = FxIndexMap :: default ( ) ;
3239
3254
let mut inconsistent_vars = FxIndexMap :: default ( ) ;
3240
3255
3241
- // 1) Compute the binding maps of all arms.
3242
- let maps = pats. iter ( ) . map ( |pat| self . binding_mode_map ( pat) ) . collect :: < Vec < _ > > ( ) ;
3256
+ // 1) Compute the binding maps of all arms; never patterns don't participate in this.
3257
+ let not_never_pats = pats
3258
+ . iter ( )
3259
+ . filter_map ( |pat| {
3260
+ let binding_map = self . compute_and_check_binding_map ( pat) . ok ( ) ?;
3261
+ Some ( ( binding_map, pat) )
3262
+ } )
3263
+ . collect :: < Vec < _ > > ( ) ;
3243
3264
3244
3265
// 2) Record any missing bindings or binding mode inconsistencies.
3245
- for ( map_outer, pat_outer) in maps . iter ( ) . zip ( pats . iter ( ) ) {
3266
+ for ( map_outer, pat_outer) in not_never_pats . iter ( ) {
3246
3267
// Check against all arms except for the same pattern which is always self-consistent.
3247
- let inners = maps
3268
+ let inners = not_never_pats
3248
3269
. iter ( )
3249
- . zip ( pats. iter ( ) )
3250
3270
. filter ( |( _, pat) | pat. id != pat_outer. id )
3251
- . flat_map ( |( map, _) | map)
3252
- . map ( |( key, binding) | ( key. name , map_outer. get ( key) , binding) ) ;
3253
-
3254
- let inners = inners. collect :: < Vec < _ > > ( ) ;
3271
+ . flat_map ( |( map, _) | map) ;
3255
3272
3256
- for ( name, info, & binding_inner) in inners {
3257
- match info {
3273
+ for ( key, binding_inner) in inners {
3274
+ let name = key. name ;
3275
+ match map_outer. get ( key) {
3258
3276
None => {
3259
3277
// The inner binding is missing in the outer.
3260
3278
let binding_error =
@@ -3295,19 +3313,18 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
3295
3313
self . report_error ( v. 0 , ResolutionError :: VariableBoundWithDifferentMode ( name, v. 1 ) ) ;
3296
3314
}
3297
3315
3298
- // 5) Finally bubble up all the binding maps.
3299
- maps
3316
+ // 5) Bubble up the final binding map.
3317
+ let is_never_pat = not_never_pats. is_empty ( ) ;
3318
+ let mut binding_map = FxIndexMap :: default ( ) ;
3319
+ for ( bm, _) in not_never_pats {
3320
+ binding_map. extend ( bm) ;
3321
+ }
3322
+ ( binding_map, is_never_pat)
3300
3323
}
3301
3324
3302
- /// Check the consistency of the outermost or-patterns.
3303
- fn check_consistent_bindings_top ( & mut self , pat : & ' ast Pat ) {
3304
- pat. walk ( & mut |pat| match pat. kind {
3305
- PatKind :: Or ( ref ps) => {
3306
- self . check_consistent_bindings ( ps) ;
3307
- false
3308
- }
3309
- _ => true ,
3310
- } )
3325
+ /// Check the consistency of bindings wrt or-patterns and never patterns.
3326
+ fn check_consistent_bindings ( & mut self , pat : & ' ast Pat ) {
3327
+ let _ = self . compute_and_check_binding_map ( pat) ;
3311
3328
}
3312
3329
3313
3330
fn resolve_arm ( & mut self , arm : & ' ast Arm ) {
@@ -3336,7 +3353,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
3336
3353
visit:: walk_pat ( self , pat) ;
3337
3354
self . resolve_pattern_inner ( pat, pat_src, bindings) ;
3338
3355
// This has to happen *after* we determine which pat_idents are variants:
3339
- self . check_consistent_bindings_top ( pat) ;
3356
+ self . check_consistent_bindings ( pat) ;
3340
3357
}
3341
3358
3342
3359
/// Resolve bindings in a pattern. This is a helper to `resolve_pattern`.
0 commit comments