diff options
| author | Nadrieril <nadrieril+git@gmail.com> | 2024-01-10 22:07:48 +0100 |
|---|---|---|
| committer | Nadrieril <nadrieril+git@gmail.com> | 2024-01-10 22:10:08 +0100 |
| commit | 68a13bf7fd0e456969ea591fc216bf44eea9890d (patch) | |
| tree | 6f5e1ff11ea05d1e0fb58193c00adbcc40ffbb42 /compiler/rustc_resolve/src | |
| parent | 223cda41071416c20d3d1db458ce7c6c789e2b08 (diff) | |
| download | rust-68a13bf7fd0e456969ea591fc216bf44eea9890d.tar.gz rust-68a13bf7fd0e456969ea591fc216bf44eea9890d.zip | |
Explain never patterns in resolve
Diffstat (limited to 'compiler/rustc_resolve/src')
| -rw-r--r-- | compiler/rustc_resolve/src/late.rs | 32 |
1 files changed, 31 insertions, 1 deletions
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 5c246893d87..e100c925478 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -3196,6 +3196,21 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { /// consistent when encountering or-patterns and never patterns. /// This is done hygienically: this could arise for a macro that expands into an or-pattern /// where one 'x' was from the user and one 'x' came from the macro. + /// + /// A never pattern by definition indicates an unreachable case. For example, matching on + /// `Result<T, &!>` could look like: + /// ```rust + /// # #![feature(never_type)] + /// # #![feature(never_patterns)] + /// # fn bar(_x: u32) {} + /// let foo: Result<u32, &!> = Ok(0); + /// match foo { + /// Ok(x) => bar(x), + /// Err(&!), + /// } + /// ``` + /// This extends to product types: `(x, !)` is likewise unreachable. So it doesn't make sense to + /// have a binding here, and we tell the user to use `_` instead. fn compute_and_check_binding_map( &mut self, pat: &Pat, @@ -3247,6 +3262,21 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { /// have exactly the same set of bindings, with the same binding modes for each. /// Returns the computed binding map and a boolean indicating whether the pattern is a never /// pattern. + /// + /// A never pattern by definition indicates an unreachable case. For example, destructuring a + /// `Result<T, &!>` could look like: + /// ```rust + /// # #![feature(never_type)] + /// # #![feature(never_patterns)] + /// # fn foo() -> Result<bool, &'static !> { Ok(true) } + /// let (Ok(x) | Err(&!)) = foo(); + /// # let _ = x; + /// ``` + /// Because the `Err(&!)` branch is never reached, it does not need to have the same bindings as + /// the other branches of the or-pattern. So we must ignore never pattern when checking the + /// bindings of an or-pattern. + /// Moreover, if all the subpatterns are never patterns (e.g. `Ok(!) | Err(!)`), then the + /// pattern as a whole counts as a never pattern (since it's definitionallly unreachable). fn compute_and_check_or_pat_binding_map( &mut self, pats: &[P<Pat>], @@ -3254,7 +3284,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { let mut missing_vars = FxIndexMap::default(); let mut inconsistent_vars = FxIndexMap::default(); - // 1) Compute the binding maps of all arms; never patterns don't participate in this. + // 1) Compute the binding maps of all arms; we must ignore never patterns here. let not_never_pats = pats .iter() .filter_map(|pat| { |
