Auto merge of #119610 - Nadrieril:never_pattern_bindings, r=compiler-errors
never patterns: Check bindings wrt never patterns Never patterns: - Shouldn't contain bindings since they never match anything; - Don't count when checking that or-patterns have consistent bindings. r? `@compiler-errors`
This commit is contained in:
commit
714b29a17f
@ -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 =
|
resolve_attempt_to_use_non_constant_value_in_constant_without_suggestion =
|
||||||
this would need to be a `{$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 =
|
resolve_binding_shadows_something_unacceptable =
|
||||||
{$shadowing_binding}s cannot shadow {$shadowed_binding}s
|
{$shadowing_binding}s cannot shadow {$shadowed_binding}s
|
||||||
.label = cannot be named the same as {$article} {$shadowed_binding}
|
.label = cannot be named the same as {$article} {$shadowed_binding}
|
||||||
|
@ -959,6 +959,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||||||
.create_err(errs::TraitImplDuplicate { span, name, trait_item_span, old_span }),
|
.create_err(errs::TraitImplDuplicate { span, name, trait_item_span, old_span }),
|
||||||
ResolutionError::InvalidAsmSym => self.dcx().create_err(errs::InvalidAsmSym { span }),
|
ResolutionError::InvalidAsmSym => self.dcx().create_err(errs::InvalidAsmSym { span }),
|
||||||
ResolutionError::LowercaseSelf => self.dcx().create_err(errs::LowercaseSelf { span }),
|
ResolutionError::LowercaseSelf => self.dcx().create_err(errs::LowercaseSelf { span }),
|
||||||
|
ResolutionError::BindingInNeverPattern => {
|
||||||
|
self.dcx().create_err(errs::BindingInNeverPattern { span })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -486,6 +486,15 @@ pub(crate) struct LowercaseSelf {
|
|||||||
pub(crate) span: Span,
|
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)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(resolve_trait_impl_duplicate, code = "E0201")]
|
#[diag(resolve_trait_impl_duplicate, code = "E0201")]
|
||||||
pub(crate) struct TraitImplDuplicate {
|
pub(crate) struct TraitImplDuplicate {
|
||||||
|
@ -65,6 +65,8 @@ enum IsRepeatExpr {
|
|||||||
Yes,
|
Yes,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct IsNeverPattern;
|
||||||
|
|
||||||
/// Describes whether an `AnonConst` is a type level const arg or
|
/// Describes whether an `AnonConst` is a type level const arg or
|
||||||
/// some other form of anon const (i.e. inline consts or enum discriminants)
|
/// some other form of anon const (i.e. inline consts or enum discriminants)
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[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);
|
self.resolve_pattern_top(&local.pat, PatternSource::Let);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// build a map from pattern identifiers to binding-info's.
|
/// Build a map from pattern identifiers to binding-info's, and check the bindings are
|
||||||
/// this is done hygienically. This could arise for a macro
|
/// consistent when encountering or-patterns and never patterns.
|
||||||
/// that expands into an or-pattern where one 'x' was from the
|
/// This is done hygienically: this could arise for a macro that expands into an or-pattern
|
||||||
/// user and one 'x' came from the macro.
|
/// where one 'x' was from the user and one 'x' came from the macro.
|
||||||
fn binding_mode_map(&mut self, pat: &Pat) -> FxIndexMap<Ident, BindingInfo> {
|
///
|
||||||
|
/// 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,
|
||||||
|
) -> Result<FxIndexMap<Ident, BindingInfo>, IsNeverPattern> {
|
||||||
let mut binding_map = FxIndexMap::default();
|
let mut binding_map = FxIndexMap::default();
|
||||||
|
let mut is_never_pat = false;
|
||||||
|
|
||||||
pat.walk(&mut |pat| {
|
pat.walk(&mut |pat| {
|
||||||
match pat.kind {
|
match pat.kind {
|
||||||
@ -3263,18 +3284,27 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||||||
PatKind::Or(ref ps) => {
|
PatKind::Or(ref ps) => {
|
||||||
// Check the consistency of this or-pattern and
|
// Check the consistency of this or-pattern and
|
||||||
// then add all bindings to the larger map.
|
// then add all bindings to the larger map.
|
||||||
for bm in self.check_consistent_bindings(ps) {
|
match self.compute_and_check_or_pat_binding_map(ps) {
|
||||||
binding_map.extend(bm);
|
Ok(bm) => binding_map.extend(bm),
|
||||||
|
Err(IsNeverPattern) => is_never_pat = true,
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
PatKind::Never => is_never_pat = true,
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
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
|
/// Compute the binding map for an or-pattern. Checks that all of the arms in the or-pattern
|
||||||
/// same set of bindings, with the same binding modes for each.
|
/// have exactly the same set of bindings, with the same binding modes for each.
|
||||||
fn check_consistent_bindings(
|
/// 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,
|
&mut self,
|
||||||
pats: &[P<Pat>],
|
pats: &[P<Pat>],
|
||||||
) -> Vec<FxIndexMap<Ident, BindingInfo>> {
|
) -> Result<FxIndexMap<Ident, BindingInfo>, IsNeverPattern> {
|
||||||
// pats is consistent.
|
|
||||||
let mut missing_vars = FxIndexMap::default();
|
let mut missing_vars = FxIndexMap::default();
|
||||||
let mut inconsistent_vars = FxIndexMap::default();
|
let mut inconsistent_vars = FxIndexMap::default();
|
||||||
|
|
||||||
// 1) Compute the binding maps of all arms.
|
// 1) Compute the binding maps of all arms; we must ignore never patterns here.
|
||||||
let maps = pats.iter().map(|pat| self.binding_mode_map(pat)).collect::<Vec<_>>();
|
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::<Vec<_>>();
|
||||||
|
|
||||||
// 2) Record any missing bindings or binding mode inconsistencies.
|
// 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.
|
// Check against all arms except for the same pattern which is always self-consistent.
|
||||||
let inners = maps
|
let inners = not_never_pats
|
||||||
.iter()
|
.iter()
|
||||||
.zip(pats.iter())
|
|
||||||
.filter(|(_, pat)| pat.id != pat_outer.id)
|
.filter(|(_, pat)| pat.id != pat_outer.id)
|
||||||
.flat_map(|(map, _)| map)
|
.flat_map(|(map, _)| map);
|
||||||
.map(|(key, binding)| (key.name, map_outer.get(key), binding));
|
|
||||||
|
|
||||||
let inners = inners.collect::<Vec<_>>();
|
for (key, binding_inner) in inners {
|
||||||
|
let name = key.name;
|
||||||
for (name, info, &binding_inner) in inners {
|
match map_outer.get(key) {
|
||||||
match info {
|
|
||||||
None => {
|
None => {
|
||||||
// The inner binding is missing in the outer.
|
// The inner binding is missing in the outer.
|
||||||
let binding_error =
|
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));
|
self.report_error(v.0, ResolutionError::VariableBoundWithDifferentMode(name, v.1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5) Finally bubble up all the binding maps.
|
// 5) Bubble up the final binding map.
|
||||||
maps
|
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.
|
/// Check the consistency of bindings wrt or-patterns and never patterns.
|
||||||
fn check_consistent_bindings_top(&mut self, pat: &'ast Pat) {
|
fn check_consistent_bindings(&mut self, pat: &'ast Pat) {
|
||||||
|
let mut is_or_or_never = false;
|
||||||
pat.walk(&mut |pat| match pat.kind {
|
pat.walk(&mut |pat| match pat.kind {
|
||||||
PatKind::Or(ref ps) => {
|
PatKind::Or(..) | PatKind::Never => {
|
||||||
self.check_consistent_bindings(ps);
|
is_or_or_never = true;
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
_ => true,
|
_ => true,
|
||||||
})
|
});
|
||||||
|
if is_or_or_never {
|
||||||
|
let _ = self.compute_and_check_binding_map(pat);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_arm(&mut self, arm: &'ast Arm) {
|
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);
|
visit::walk_pat(self, pat);
|
||||||
self.resolve_pattern_inner(pat, pat_src, bindings);
|
self.resolve_pattern_inner(pat, pat_src, bindings);
|
||||||
// This has to happen *after* we determine which pat_idents are variants:
|
// 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`.
|
/// Resolve bindings in a pattern. This is a helper to `resolve_pattern`.
|
||||||
|
@ -265,6 +265,8 @@ enum ResolutionError<'a> {
|
|||||||
InvalidAsmSym,
|
InvalidAsmSym,
|
||||||
/// `self` used instead of `Self` in a generic parameter
|
/// `self` used instead of `Self` in a generic parameter
|
||||||
LowercaseSelf,
|
LowercaseSelf,
|
||||||
|
/// A never pattern has a binding.
|
||||||
|
BindingInNeverPattern,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum VisResolutionError<'a> {
|
enum VisResolutionError<'a> {
|
||||||
|
@ -7,7 +7,6 @@ fn main() {
|
|||||||
let res: Result<u32, Void> = Ok(0);
|
let res: Result<u32, Void> = Ok(0);
|
||||||
let (Ok(_x) | Err(&!)) = res.as_ref();
|
let (Ok(_x) | Err(&!)) = res.as_ref();
|
||||||
//~^ ERROR `!` patterns are experimental
|
//~^ ERROR `!` patterns are experimental
|
||||||
//~| ERROR: is not bound in all patterns
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr: *const Void = NonNull::dangling().as_ptr();
|
let ptr: *const Void = NonNull::dangling().as_ptr();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
error: unexpected `,` in pattern
|
error: unexpected `,` in pattern
|
||||||
--> $DIR/feature-gate-never_patterns.rs:34:16
|
--> $DIR/feature-gate-never_patterns.rs:33:16
|
||||||
|
|
|
|
||||||
LL | Some(_),
|
LL | Some(_),
|
||||||
| ^
|
| ^
|
||||||
@ -13,14 +13,6 @@ help: ...or a vertical bar to match on multiple alternatives
|
|||||||
LL | Some(_) |
|
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
|
error[E0658]: `!` patterns are experimental
|
||||||
--> $DIR/feature-gate-never_patterns.rs:8:24
|
--> $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
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
error[E0658]: `!` patterns are experimental
|
error[E0658]: `!` patterns are experimental
|
||||||
--> $DIR/feature-gate-never_patterns.rs:15:13
|
--> $DIR/feature-gate-never_patterns.rs:14:13
|
||||||
|
|
|
|
||||||
LL | !
|
LL | !
|
||||||
| ^
|
| ^
|
||||||
@ -42,7 +34,7 @@ LL | !
|
|||||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
error[E0658]: `!` patterns are experimental
|
error[E0658]: `!` patterns are experimental
|
||||||
--> $DIR/feature-gate-never_patterns.rs:21:13
|
--> $DIR/feature-gate-never_patterns.rs:20:13
|
||||||
|
|
|
|
||||||
LL | !
|
LL | !
|
||||||
| ^
|
| ^
|
||||||
@ -52,7 +44,7 @@ LL | !
|
|||||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
error[E0658]: `!` patterns are experimental
|
error[E0658]: `!` patterns are experimental
|
||||||
--> $DIR/feature-gate-never_patterns.rs:26:13
|
--> $DIR/feature-gate-never_patterns.rs:25:13
|
||||||
|
|
|
|
||||||
LL | ! => {}
|
LL | ! => {}
|
||||||
| ^
|
| ^
|
||||||
@ -62,25 +54,25 @@ LL | ! => {}
|
|||||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
error: `match` arm with no body
|
error: `match` arm with no body
|
||||||
--> $DIR/feature-gate-never_patterns.rs:39:9
|
--> $DIR/feature-gate-never_patterns.rs:38:9
|
||||||
|
|
|
|
||||||
LL | Some(_)
|
LL | Some(_)
|
||||||
| ^^^^^^^- help: add a body after the pattern: `=> todo!(),`
|
| ^^^^^^^- help: add a body after the pattern: `=> todo!(),`
|
||||||
|
|
||||||
error: `match` arm with no body
|
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,
|
LL | Some(_) if false,
|
||||||
| ^^^^^^^- help: add a body after the pattern: `=> todo!(),`
|
| ^^^^^^^- help: add a body after the pattern: `=> todo!(),`
|
||||||
|
|
||||||
error: `match` arm with no body
|
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
|
LL | Some(_) if false
|
||||||
| ^^^^^^^- help: add a body after the pattern: `=> todo!(),`
|
| ^^^^^^^- help: add a body after the pattern: `=> todo!(),`
|
||||||
|
|
||||||
error[E0658]: `!` patterns are experimental
|
error[E0658]: `!` patterns are experimental
|
||||||
--> $DIR/feature-gate-never_patterns.rs:51:13
|
--> $DIR/feature-gate-never_patterns.rs:50:13
|
||||||
|
|
|
|
||||||
LL | Err(!),
|
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
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
error[E0658]: `!` patterns are experimental
|
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,
|
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
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
error: `match` arm with no body
|
error: `match` arm with no body
|
||||||
--> $DIR/feature-gate-never_patterns.rs:65:9
|
--> $DIR/feature-gate-never_patterns.rs:64:9
|
||||||
|
|
|
|
||||||
LL | Some(_)
|
LL | Some(_)
|
||||||
| ^^^^^^^- help: add a body after the pattern: `=> todo!(),`
|
| ^^^^^^^- help: add a body after the pattern: `=> todo!(),`
|
||||||
|
|
||||||
error: `match` arm with no body
|
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
|
LL | Some(_) if false
|
||||||
| ^^^^^^^- help: add a body after the pattern: `=> todo!(),`
|
| ^^^^^^^- help: add a body after the pattern: `=> todo!(),`
|
||||||
|
|
||||||
error: a guard on a never pattern will never be run
|
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,
|
LL | Err(!) if false,
|
||||||
| ^^^^^ help: remove this guard
|
| ^^^^^ 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 this error, try `rustc --explain E0658`.
|
||||||
For more information about an error, try `rustc --explain E0408`.
|
|
||||||
|
@ -7,12 +7,9 @@ fn main() {}
|
|||||||
|
|
||||||
// The classic use for empty types.
|
// The classic use for empty types.
|
||||||
fn safe_unwrap_result<T>(res: Result<T, Void>) {
|
fn safe_unwrap_result<T>(res: Result<T, Void>) {
|
||||||
let Ok(_x) = res;
|
let Ok(_x) = res; //~ ERROR refutable pattern in local binding
|
||||||
// FIXME(never_patterns): These should be allowed
|
|
||||||
let (Ok(_x) | Err(!)) = &res;
|
let (Ok(_x) | Err(!)) = &res;
|
||||||
//~^ ERROR: is not bound in all patterns
|
|
||||||
let (Ok(_x) | Err(&!)) = res.as_ref();
|
let (Ok(_x) | Err(&!)) = res.as_ref();
|
||||||
//~^ ERROR: is not bound in all patterns
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check we only accept `!` where we want to.
|
// Check we only accept `!` where we want to.
|
||||||
@ -74,26 +71,3 @@ fn never_pattern_location(void: Void) {
|
|||||||
Some(&(_, !)),
|
Some(&(_, !)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn never_and_bindings() {
|
|
||||||
let x: Result<bool, &(u32, Void)> = 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,51 +1,17 @@
|
|||||||
error[E0408]: variable `_x` is not bound in all patterns
|
error[E0005]: refutable pattern in local binding
|
||||||
--> $DIR/never_patterns.rs:12:19
|
--> $DIR/never_patterns.rs:10:9
|
||||||
|
|
|
|
||||||
LL | let (Ok(_x) | Err(!)) = &res;
|
LL | let Ok(_x) = res;
|
||||||
| -- ^^^^^^ pattern doesn't bind `_x`
|
| ^^^^^^ pattern `Err(_)` not covered
|
||||||
| |
|
|
||||||
| 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();
|
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||||
| -- ^^^^^^^ pattern doesn't bind `_x`
|
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||||
| |
|
= note: the matched value is of type `Result<T, Void>`
|
||||||
| variable not in all patterns
|
help: you might want to use `let else` to handle the variant that isn't matched
|
||||||
|
|
||||||
error[E0408]: variable `_x` is not bound in all patterns
|
|
||||||
--> $DIR/never_patterns.rs:83:18
|
|
||||||
|
|
|
|
||||||
LL | Ok(_x) | Err(&!) => {}
|
LL | let Ok(_x) = res else { todo!() };
|
||||||
| -- ^^^^^^^ pattern doesn't bind `_x`
|
| ++++++++++++++++
|
||||||
| |
|
|
||||||
| variable not in all patterns
|
|
||||||
|
|
||||||
error[E0408]: variable `_x` is not bound in all patterns
|
error: aborting due to 1 previous error
|
||||||
--> $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
|
For more information about this error, try `rustc --explain E0005`.
|
||||||
--> $DIR/never_patterns.rs:95:9
|
|
||||||
|
|
|
||||||
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
|
|
||||||
|
|
|
||||||
LL | Ok(_a) | Err(&(_b, !)) => {}
|
|
||||||
| -- ^^^^^^^^^^^^^ pattern doesn't bind `_a`
|
|
||||||
| |
|
|
||||||
| variable not in all patterns
|
|
||||||
|
|
||||||
error: aborting due to 6 previous errors
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0408`.
|
|
||||||
|
46
tests/ui/rfcs/rfc-0000-never_patterns/bindings.rs
Normal file
46
tests/ui/rfcs/rfc-0000-never_patterns/bindings.rs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#![feature(never_patterns)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
enum Void {}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let x: Result<bool, &(u32, u32, Void)> = 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
|
||||||
|
}
|
50
tests/ui/rfcs/rfc-0000-never_patterns/bindings.stderr
Normal file
50
tests/ui/rfcs/rfc-0000-never_patterns/bindings.stderr
Normal file
@ -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
|
||||||
|
|
@ -71,6 +71,7 @@ fn parse(x: Void) {
|
|||||||
|
|
||||||
let ! = x;
|
let ! = x;
|
||||||
let y @ ! = x;
|
let y @ ! = x;
|
||||||
|
//~^ ERROR: never patterns cannot contain variable bindings
|
||||||
}
|
}
|
||||||
|
|
||||||
fn foo(!: Void) {}
|
fn foo(!: Void) {}
|
||||||
|
@ -22,6 +22,12 @@ error: top-level or-patterns are not allowed in `let` bindings
|
|||||||
LL | let Ok(_) | Err(!) = &res; // Disallowed; see #82048.
|
LL | let Ok(_) | Err(!) = &res; // Disallowed; see #82048.
|
||||||
| ^^^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(Ok(_) | Err(!))`
|
| ^^^^^^^^^^^^^^ 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
|
error: a guard on a never pattern will never be run
|
||||||
--> $DIR/parse.rs:31:20
|
--> $DIR/parse.rs:31:20
|
||||||
|
|
|
|
||||||
@ -40,5 +46,5 @@ error: a guard on a never pattern will never be run
|
|||||||
LL | never!() if true,
|
LL | never!() if true,
|
||||||
| ^^^^ help: remove this guard
|
| ^^^^ help: remove this guard
|
||||||
|
|
||||||
error: aborting due to 7 previous errors
|
error: aborting due to 8 previous errors
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user