@@ -3196,6 +3196,21 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
31963196 /// consistent when encountering or-patterns and never patterns.
31973197 /// This is done hygienically: this could arise for a macro that expands into an or-pattern
31983198 /// 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.
31993214 fn compute_and_check_binding_map (
32003215 & mut self ,
32013216 pat : & Pat ,
@@ -3247,14 +3262,29 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
32473262 /// have exactly the same set of bindings, with the same binding modes for each.
32483263 /// Returns the computed binding map and a boolean indicating whether the pattern is a never
32493264 /// 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).
32503280 fn compute_and_check_or_pat_binding_map (
32513281 & mut self ,
32523282 pats : & [ P < Pat > ] ,
32533283 ) -> Result < FxIndexMap < Ident , BindingInfo > , IsNeverPattern > {
32543284 let mut missing_vars = FxIndexMap :: default ( ) ;
32553285 let mut inconsistent_vars = FxIndexMap :: default ( ) ;
32563286
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 .
32583288 let not_never_pats = pats
32593289 . iter ( )
32603290 . filter_map ( |pat| {
0 commit comments