Skip to content

Commit 68a13bf

Browse files
committed
Explain never patterns in resolve
1 parent 223cda4 commit 68a13bf

File tree

1 file changed

+31
-1
lines changed

1 file changed

+31
-1
lines changed

compiler/rustc_resolve/src/late.rs

+31-1
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)