diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl index 3f8df16e03f77..c8ec10cad17c4 100644 --- a/compiler/rustc_resolve/messages.ftl +++ b/compiler/rustc_resolve/messages.ftl @@ -36,6 +36,10 @@ resolve_attempt_to_use_non_constant_value_in_constant_with_suggestion = resolve_attempt_to_use_non_constant_value_in_constant_without_suggestion = this would need to be a `{$suggestion}` +resolve_binding_in_never_pattern = + never patterns cannot contain variable bindings + .suggestion = use a wildcard `_` instead + resolve_binding_shadows_something_unacceptable = {$shadowing_binding}s cannot shadow {$shadowed_binding}s .label = cannot be named the same as {$article} {$shadowed_binding} diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index b570066138502..4a0c522b6ec5d 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -959,6 +959,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { .create_err(errs::TraitImplDuplicate { span, name, trait_item_span, old_span }), ResolutionError::InvalidAsmSym => self.dcx().create_err(errs::InvalidAsmSym { span }), ResolutionError::LowercaseSelf => self.dcx().create_err(errs::LowercaseSelf { span }), + ResolutionError::BindingInNeverPattern => { + self.dcx().create_err(errs::BindingInNeverPattern { span }) + } } } diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index 1fdb193e571f1..821b1e946f31c 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -486,6 +486,15 @@ pub(crate) struct LowercaseSelf { pub(crate) span: Span, } +#[derive(Debug)] +#[derive(Diagnostic)] +#[diag(resolve_binding_in_never_pattern)] +pub(crate) struct BindingInNeverPattern { + #[primary_span] + #[suggestion(code = "_", applicability = "machine-applicable", style = "short")] + pub(crate) span: Span, +} + #[derive(Diagnostic)] #[diag(resolve_trait_impl_duplicate, code = "E0201")] pub(crate) struct TraitImplDuplicate { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 82f502279112b..5102c096d4ba7 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -65,6 +65,8 @@ enum IsRepeatExpr { Yes, } +struct IsNeverPattern; + /// Describes whether an `AnonConst` is a type level const arg or /// some other form of anon const (i.e. inline consts or enum discriminants) #[derive(Copy, Clone, Debug, PartialEq, Eq)] @@ -3246,12 +3248,31 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { self.resolve_pattern_top(&local.pat, PatternSource::Let); } - /// build a map from pattern identifiers to binding-info's. - /// 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. - fn binding_mode_map(&mut self, pat: &Pat) -> FxIndexMap { + /// Build a map from pattern identifiers to binding-info's, and check the bindings are + /// 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` could look like: + /// ```rust + /// # #![feature(never_type)] + /// # #![feature(never_patterns)] + /// # fn bar(_x: u32) {} + /// let foo: Result = 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, + ) -> Result, IsNeverPattern> { let mut binding_map = FxIndexMap::default(); + let mut is_never_pat = false; pat.walk(&mut |pat| { match pat.kind { @@ -3263,18 +3284,27 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { PatKind::Or(ref ps) => { // Check the consistency of this or-pattern and // then add all bindings to the larger map. - for bm in self.check_consistent_bindings(ps) { - binding_map.extend(bm); + match self.compute_and_check_or_pat_binding_map(ps) { + Ok(bm) => binding_map.extend(bm), + Err(IsNeverPattern) => is_never_pat = true, } return false; } + PatKind::Never => is_never_pat = true, _ => {} } true }); - binding_map + if is_never_pat { + for (_, binding) in binding_map { + self.report_error(binding.span, ResolutionError::BindingInNeverPattern); + } + Err(IsNeverPattern) + } else { + Ok(binding_map) + } } fn is_base_res_local(&self, nid: NodeId) -> bool { @@ -3284,33 +3314,52 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ) } - /// Checks that all of the arms in an or-pattern have exactly the - /// same set of bindings, with the same binding modes for each. - fn check_consistent_bindings( + /// Compute the binding map for an or-pattern. Checks that all of the arms in the or-pattern + /// 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` could look like: + /// ```rust + /// # #![feature(never_type)] + /// # #![feature(never_patterns)] + /// # fn foo() -> Result { 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], - ) -> Vec> { - // pats is consistent. + ) -> Result, IsNeverPattern> { let mut missing_vars = FxIndexMap::default(); let mut inconsistent_vars = FxIndexMap::default(); - // 1) Compute the binding maps of all arms. - let maps = pats.iter().map(|pat| self.binding_mode_map(pat)).collect::>(); + // 1) Compute the binding maps of all arms; we must ignore never patterns here. + let not_never_pats = pats + .iter() + .filter_map(|pat| { + let binding_map = self.compute_and_check_binding_map(pat).ok()?; + Some((binding_map, pat)) + }) + .collect::>(); // 2) Record any missing bindings or binding mode inconsistencies. - for (map_outer, pat_outer) in maps.iter().zip(pats.iter()) { + for (map_outer, pat_outer) in not_never_pats.iter() { // Check against all arms except for the same pattern which is always self-consistent. - let inners = maps + let inners = not_never_pats .iter() - .zip(pats.iter()) .filter(|(_, pat)| pat.id != pat_outer.id) - .flat_map(|(map, _)| map) - .map(|(key, binding)| (key.name, map_outer.get(key), binding)); - - let inners = inners.collect::>(); + .flat_map(|(map, _)| map); - for (name, info, &binding_inner) in inners { - match info { + for (key, binding_inner) in inners { + let name = key.name; + match map_outer.get(key) { None => { // The inner binding is missing in the outer. let binding_error = @@ -3351,19 +3400,32 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { self.report_error(v.0, ResolutionError::VariableBoundWithDifferentMode(name, v.1)); } - // 5) Finally bubble up all the binding maps. - maps + // 5) Bubble up the final binding map. + if not_never_pats.is_empty() { + // All the patterns are never patterns, so the whole or-pattern is one too. + Err(IsNeverPattern) + } else { + let mut binding_map = FxIndexMap::default(); + for (bm, _) in not_never_pats { + binding_map.extend(bm); + } + Ok(binding_map) + } } - /// Check the consistency of the outermost or-patterns. - fn check_consistent_bindings_top(&mut self, pat: &'ast Pat) { + /// Check the consistency of bindings wrt or-patterns and never patterns. + fn check_consistent_bindings(&mut self, pat: &'ast Pat) { + let mut is_or_or_never = false; pat.walk(&mut |pat| match pat.kind { - PatKind::Or(ref ps) => { - self.check_consistent_bindings(ps); + PatKind::Or(..) | PatKind::Never => { + is_or_or_never = true; false } _ => true, - }) + }); + if is_or_or_never { + let _ = self.compute_and_check_binding_map(pat); + } } fn resolve_arm(&mut self, arm: &'ast Arm) { @@ -3392,7 +3454,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { visit::walk_pat(self, pat); self.resolve_pattern_inner(pat, pat_src, bindings); // This has to happen *after* we determine which pat_idents are variants: - self.check_consistent_bindings_top(pat); + self.check_consistent_bindings(pat); } /// Resolve bindings in a pattern. This is a helper to `resolve_pattern`. diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 90aa7d79bf045..313a6b6c683d6 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -265,6 +265,8 @@ enum ResolutionError<'a> { InvalidAsmSym, /// `self` used instead of `Self` in a generic parameter LowercaseSelf, + /// A never pattern has a binding. + BindingInNeverPattern, } enum VisResolutionError<'a> { diff --git a/tests/ui/feature-gates/feature-gate-never_patterns.rs b/tests/ui/feature-gates/feature-gate-never_patterns.rs index f3910622313d5..d23405ada2d4d 100644 --- a/tests/ui/feature-gates/feature-gate-never_patterns.rs +++ b/tests/ui/feature-gates/feature-gate-never_patterns.rs @@ -7,7 +7,6 @@ fn main() { let res: Result = Ok(0); let (Ok(_x) | Err(&!)) = res.as_ref(); //~^ ERROR `!` patterns are experimental - //~| ERROR: is not bound in all patterns unsafe { let ptr: *const Void = NonNull::dangling().as_ptr(); diff --git a/tests/ui/feature-gates/feature-gate-never_patterns.stderr b/tests/ui/feature-gates/feature-gate-never_patterns.stderr index 1b5485d22fbf2..9f94e96203518 100644 --- a/tests/ui/feature-gates/feature-gate-never_patterns.stderr +++ b/tests/ui/feature-gates/feature-gate-never_patterns.stderr @@ -1,5 +1,5 @@ error: unexpected `,` in pattern - --> $DIR/feature-gate-never_patterns.rs:34:16 + --> $DIR/feature-gate-never_patterns.rs:33:16 | LL | Some(_), | ^ @@ -13,14 +13,6 @@ help: ...or a vertical bar to match on multiple alternatives LL | Some(_) | | -error[E0408]: variable `_x` is not bound in all patterns - --> $DIR/feature-gate-never_patterns.rs:8:19 - | -LL | let (Ok(_x) | Err(&!)) = res.as_ref(); - | -- ^^^^^^^ pattern doesn't bind `_x` - | | - | variable not in all patterns - error[E0658]: `!` patterns are experimental --> $DIR/feature-gate-never_patterns.rs:8:24 | @@ -32,7 +24,7 @@ LL | let (Ok(_x) | Err(&!)) = res.as_ref(); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `!` patterns are experimental - --> $DIR/feature-gate-never_patterns.rs:15:13 + --> $DIR/feature-gate-never_patterns.rs:14:13 | LL | ! | ^ @@ -42,7 +34,7 @@ LL | ! = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `!` patterns are experimental - --> $DIR/feature-gate-never_patterns.rs:21:13 + --> $DIR/feature-gate-never_patterns.rs:20:13 | LL | ! | ^ @@ -52,7 +44,7 @@ LL | ! = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `!` patterns are experimental - --> $DIR/feature-gate-never_patterns.rs:26:13 + --> $DIR/feature-gate-never_patterns.rs:25:13 | LL | ! => {} | ^ @@ -62,25 +54,25 @@ LL | ! => {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: `match` arm with no body - --> $DIR/feature-gate-never_patterns.rs:39:9 + --> $DIR/feature-gate-never_patterns.rs:38:9 | LL | Some(_) | ^^^^^^^- help: add a body after the pattern: `=> todo!(),` error: `match` arm with no body - --> $DIR/feature-gate-never_patterns.rs:44:9 + --> $DIR/feature-gate-never_patterns.rs:43:9 | LL | Some(_) if false, | ^^^^^^^- help: add a body after the pattern: `=> todo!(),` error: `match` arm with no body - --> $DIR/feature-gate-never_patterns.rs:46:9 + --> $DIR/feature-gate-never_patterns.rs:45:9 | LL | Some(_) if false | ^^^^^^^- help: add a body after the pattern: `=> todo!(),` error[E0658]: `!` patterns are experimental - --> $DIR/feature-gate-never_patterns.rs:51:13 + --> $DIR/feature-gate-never_patterns.rs:50:13 | LL | Err(!), | ^ @@ -90,7 +82,7 @@ LL | Err(!), = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `!` patterns are experimental - --> $DIR/feature-gate-never_patterns.rs:55:13 + --> $DIR/feature-gate-never_patterns.rs:54:13 | LL | Err(!) if false, | ^ @@ -100,24 +92,23 @@ LL | Err(!) if false, = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: `match` arm with no body - --> $DIR/feature-gate-never_patterns.rs:65:9 + --> $DIR/feature-gate-never_patterns.rs:64:9 | LL | Some(_) | ^^^^^^^- help: add a body after the pattern: `=> todo!(),` error: `match` arm with no body - --> $DIR/feature-gate-never_patterns.rs:71:9 + --> $DIR/feature-gate-never_patterns.rs:70:9 | LL | Some(_) if false | ^^^^^^^- help: add a body after the pattern: `=> todo!(),` error: a guard on a never pattern will never be run - --> $DIR/feature-gate-never_patterns.rs:55:19 + --> $DIR/feature-gate-never_patterns.rs:54:19 | LL | Err(!) if false, | ^^^^^ help: remove this guard -error: aborting due to 14 previous errors +error: aborting due to 13 previous errors -Some errors have detailed explanations: E0408, E0658. -For more information about an error, try `rustc --explain E0408`. +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/pattern/never_patterns.rs b/tests/ui/pattern/never_patterns.rs index 915f3e75e7bf3..8f44f8a655931 100644 --- a/tests/ui/pattern/never_patterns.rs +++ b/tests/ui/pattern/never_patterns.rs @@ -7,12 +7,9 @@ fn main() {} // The classic use for empty types. fn safe_unwrap_result(res: Result) { - let Ok(_x) = res; - // FIXME(never_patterns): These should be allowed + let Ok(_x) = res; //~ ERROR refutable pattern in local binding let (Ok(_x) | Err(!)) = &res; - //~^ ERROR: is not bound in all patterns let (Ok(_x) | Err(&!)) = res.as_ref(); - //~^ ERROR: is not bound in all patterns } // Check we only accept `!` where we want to. @@ -74,26 +71,3 @@ fn never_pattern_location(void: Void) { Some(&(_, !)), } } - -fn never_and_bindings() { - let x: Result = Ok(false); - - // FIXME(never_patterns): Never patterns in or-patterns don't need to share the same bindings. - match x { - Ok(_x) | Err(&!) => {} - //~^ ERROR: is not bound in all patterns - } - let (Ok(_x) | Err(&!)) = x; - //~^ ERROR: is not bound in all patterns - - // FIXME(never_patterns): A never pattern mustn't have bindings. - match x { - Ok(_) => {} - Err(&(_b, !)), - } - match x { - Ok(_a) | Err(&(_b, !)) => {} - //~^ ERROR: is not bound in all patterns - //~| ERROR: is not bound in all patterns - } -} diff --git a/tests/ui/pattern/never_patterns.stderr b/tests/ui/pattern/never_patterns.stderr index 11e50debfd39a..20eeb01cf7140 100644 --- a/tests/ui/pattern/never_patterns.stderr +++ b/tests/ui/pattern/never_patterns.stderr @@ -1,51 +1,17 @@ -error[E0408]: variable `_x` is not bound in all patterns - --> $DIR/never_patterns.rs:12:19 +error[E0005]: refutable pattern in local binding + --> $DIR/never_patterns.rs:10:9 | -LL | let (Ok(_x) | Err(!)) = &res; - | -- ^^^^^^ pattern doesn't bind `_x` - | | - | variable not in all patterns - -error[E0408]: variable `_x` is not bound in all patterns - --> $DIR/never_patterns.rs:14:19 - | -LL | let (Ok(_x) | Err(&!)) = res.as_ref(); - | -- ^^^^^^^ pattern doesn't bind `_x` - | | - | variable not in all patterns - -error[E0408]: variable `_x` is not bound in all patterns - --> $DIR/never_patterns.rs:83:18 - | -LL | Ok(_x) | Err(&!) => {} - | -- ^^^^^^^ pattern doesn't bind `_x` - | | - | variable not in all patterns - -error[E0408]: variable `_x` is not bound in all patterns - --> $DIR/never_patterns.rs:86:19 - | -LL | let (Ok(_x) | Err(&!)) = x; - | -- ^^^^^^^ pattern doesn't bind `_x` - | | - | variable not in all patterns - -error[E0408]: variable `_b` is not bound in all patterns - --> $DIR/never_patterns.rs:95:9 +LL | let Ok(_x) = res; + | ^^^^^^ pattern `Err(_)` not covered | -LL | Ok(_a) | Err(&(_b, !)) => {} - | ^^^^^^ -- variable not in all patterns - | | - | pattern doesn't bind `_b` - -error[E0408]: variable `_a` is not bound in all patterns - --> $DIR/never_patterns.rs:95:18 + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `Result` +help: you might want to use `let else` to handle the variant that isn't matched | -LL | Ok(_a) | Err(&(_b, !)) => {} - | -- ^^^^^^^^^^^^^ pattern doesn't bind `_a` - | | - | variable not in all patterns +LL | let Ok(_x) = res else { todo!() }; + | ++++++++++++++++ -error: aborting due to 6 previous errors +error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0408`. +For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/bindings.rs b/tests/ui/rfcs/rfc-0000-never_patterns/bindings.rs new file mode 100644 index 0000000000000..f2e238ecb136a --- /dev/null +++ b/tests/ui/rfcs/rfc-0000-never_patterns/bindings.rs @@ -0,0 +1,46 @@ +#![feature(never_patterns)] +#![allow(incomplete_features)] + +enum Void {} + +fn main() { + let x: Result = Ok(false); + + match x { + Ok(_x) | Err(&!) => {} + } + let (Ok(_x) | Err(&!)) = x; + + match x { + Ok(_) => {} + Err(&(_a, _b, !)), + //~^ ERROR: never patterns cannot contain variable bindings + //~| ERROR: never patterns cannot contain variable bindings + } + match x { + Ok(_ok) | Err(&(_a, _b, !)) => {} + //~^ ERROR: never patterns cannot contain variable bindings + //~| ERROR: never patterns cannot contain variable bindings + } +} + +fn void(void: Void) { + let (_a | !) = void; + let (! | _a) = void; + let ((_a, _) | (_a, _ | !)) = (true, void); + let (_a | (! | !,)) = (void,); + let ((_a,) | (!,)) = (void,); + + let (_a, (! | !)) = (true, void); + //~^ ERROR: never patterns cannot contain variable bindings + let (_a, (_b | !)) = (true, void); + + let _a @ ! = void; + //~^ ERROR: never patterns cannot contain variable bindings + let _a @ (_b | !) = void; + let (_a @ (), !) = ((), void); + //~^ ERROR: never patterns cannot contain variable bindings + let (_a | + (_b @ (_, !))) = (true, void); + //~^ ERROR: never patterns cannot contain variable bindings +} diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/bindings.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/bindings.stderr new file mode 100644 index 0000000000000..b69ba80af88ea --- /dev/null +++ b/tests/ui/rfcs/rfc-0000-never_patterns/bindings.stderr @@ -0,0 +1,50 @@ +error: never patterns cannot contain variable bindings + --> $DIR/bindings.rs:16:15 + | +LL | Err(&(_a, _b, !)), + | ^^ help: use a wildcard `_` instead + +error: never patterns cannot contain variable bindings + --> $DIR/bindings.rs:16:19 + | +LL | Err(&(_a, _b, !)), + | ^^ help: use a wildcard `_` instead + +error: never patterns cannot contain variable bindings + --> $DIR/bindings.rs:21:25 + | +LL | Ok(_ok) | Err(&(_a, _b, !)) => {} + | ^^ help: use a wildcard `_` instead + +error: never patterns cannot contain variable bindings + --> $DIR/bindings.rs:21:29 + | +LL | Ok(_ok) | Err(&(_a, _b, !)) => {} + | ^^ help: use a wildcard `_` instead + +error: never patterns cannot contain variable bindings + --> $DIR/bindings.rs:34:10 + | +LL | let (_a, (! | !)) = (true, void); + | ^^ help: use a wildcard `_` instead + +error: never patterns cannot contain variable bindings + --> $DIR/bindings.rs:38:9 + | +LL | let _a @ ! = void; + | ^^ help: use a wildcard `_` instead + +error: never patterns cannot contain variable bindings + --> $DIR/bindings.rs:41:10 + | +LL | let (_a @ (), !) = ((), void); + | ^^ help: use a wildcard `_` instead + +error: never patterns cannot contain variable bindings + --> $DIR/bindings.rs:44:14 + | +LL | (_b @ (_, !))) = (true, void); + | ^^ help: use a wildcard `_` instead + +error: aborting due to 8 previous errors + diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/parse.rs b/tests/ui/rfcs/rfc-0000-never_patterns/parse.rs index f254b9c201c1c..566bb07164640 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/parse.rs +++ b/tests/ui/rfcs/rfc-0000-never_patterns/parse.rs @@ -71,6 +71,7 @@ fn parse(x: Void) { let ! = x; let y @ ! = x; + //~^ ERROR: never patterns cannot contain variable bindings } fn foo(!: Void) {} diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/parse.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/parse.stderr index e81a13a3967cb..17d1b7e0d43b8 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/parse.stderr +++ b/tests/ui/rfcs/rfc-0000-never_patterns/parse.stderr @@ -22,6 +22,12 @@ error: top-level or-patterns are not allowed in `let` bindings LL | let Ok(_) | Err(!) = &res; // Disallowed; see #82048. | ^^^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(Ok(_) | Err(!))` +error: never patterns cannot contain variable bindings + --> $DIR/parse.rs:73:9 + | +LL | let y @ ! = x; + | ^ help: use a wildcard `_` instead + error: a guard on a never pattern will never be run --> $DIR/parse.rs:31:20 | @@ -40,5 +46,5 @@ error: a guard on a never pattern will never be run LL | never!() if true, | ^^^^ help: remove this guard -error: aborting due to 7 previous errors +error: aborting due to 8 previous errors