@@ -3196,6 +3196,21 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
3196
3196
/// consistent when encountering or-patterns and never patterns.
3197
3197
/// This is done hygienically: this could arise for a macro that expands into an or-pattern
3198
3198
/// where one 'x' was from the user and one 'x' came from the macro.
3199
+ ///
3200
+ /// A never pattern by definition indicates an unreachable case. For example, matching on
3201
+ /// `Result<T, &!>` could look like:
3202
+ /// ```rust
3203
+ /// # #![feature(never_type)]
3204
+ /// # #![feature(never_patterns)]
3205
+ /// # fn bar(_x: u32) {}
3206
+ /// let foo: Result<u32, &!> = Ok(0);
3207
+ /// match foo {
3208
+ /// Ok(x) => bar(x),
3209
+ /// Err(&!),
3210
+ /// }
3211
+ /// ```
3212
+ /// This extends to product types: `(x, !)` is likewise unreachable. So it doesn't make sense to
3213
+ /// have a binding here, and we tell the user to use `_` instead.
3199
3214
fn compute_and_check_binding_map (
3200
3215
& mut self ,
3201
3216
pat : & Pat ,
@@ -3247,14 +3262,29 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
3247
3262
/// have exactly the same set of bindings, with the same binding modes for each.
3248
3263
/// Returns the computed binding map and a boolean indicating whether the pattern is a never
3249
3264
/// pattern.
3265
+ ///
3266
+ /// A never pattern by definition indicates an unreachable case. For example, destructuring a
3267
+ /// `Result<T, &!>` could look like:
3268
+ /// ```rust
3269
+ /// # #![feature(never_type)]
3270
+ /// # #![feature(never_patterns)]
3271
+ /// # fn foo() -> Result<bool, &'static !> { Ok(true) }
3272
+ /// let (Ok(x) | Err(&!)) = foo();
3273
+ /// # let _ = x;
3274
+ /// ```
3275
+ /// Because the `Err(&!)` branch is never reached, it does not need to have the same bindings as
3276
+ /// the other branches of the or-pattern. So we must ignore never pattern when checking the
3277
+ /// bindings of an or-pattern.
3278
+ /// Moreover, if all the subpatterns are never patterns (e.g. `Ok(!) | Err(!)`), then the
3279
+ /// pattern as a whole counts as a never pattern (since it's definitionallly unreachable).
3250
3280
fn compute_and_check_or_pat_binding_map (
3251
3281
& mut self ,
3252
3282
pats : & [ P < Pat > ] ,
3253
3283
) -> Result < FxIndexMap < Ident , BindingInfo > , IsNeverPattern > {
3254
3284
let mut missing_vars = FxIndexMap :: default ( ) ;
3255
3285
let mut inconsistent_vars = FxIndexMap :: default ( ) ;
3256
3286
3257
- // 1) Compute the binding maps of all arms; never patterns don't participate in this .
3287
+ // 1) Compute the binding maps of all arms; we must ignore never patterns here .
3258
3288
let not_never_pats = pats
3259
3289
. iter ( )
3260
3290
. filter_map ( |pat| {
0 commit comments