Auto merge of #49469 - Nokel81:allow-irrefutable-let-patterns, r=nikomatsakis
Implementation of RFC 2086 - Allow Irrefutable Let patterns This is the set of changes for RFC2086. Tracking issue #44495. Rendered [here](https://github.com/rust-lang/rfcs/pull/2086)
This commit is contained in:
commit
309fd8a6fb
8 changed files with 143 additions and 22 deletions
|
@ -0,0 +1,28 @@
|
|||
# `irrefutable_let_patterns`
|
||||
|
||||
The tracking issue for this feature is: [#44495]
|
||||
|
||||
[#44495]: https://github.com/rust-lang/rust/issues/44495
|
||||
|
||||
------------------------
|
||||
|
||||
This feature changes the way that "irrefutable patterns" are handled
|
||||
in the `if let` and `while let` forms. An *irrefutable pattern* is one
|
||||
that cannot fail to match -- for example, the `_` pattern matches any
|
||||
value, and hence it is "irrefutable". Without this feature, using an
|
||||
irrefutable pattern in an `if let` gives a hard error (since often
|
||||
this indicates programmer error). But when the feature is enabled, the
|
||||
error becomes a lint (since in some cases irrefutable patterns are
|
||||
expected). This means you can use `#[allow]` to silence the lint:
|
||||
|
||||
```rust
|
||||
#![feature(irrefutable_let_patterns)]
|
||||
|
||||
#[allow(irrefutable_let_patterns)]
|
||||
fn main() {
|
||||
// These two examples used to be errors, but now they
|
||||
// trigger a lint (that is allowed):
|
||||
if let _ = 5 {}
|
||||
while let _ = 5 { break; }
|
||||
}
|
||||
```
|
|
@ -280,6 +280,12 @@ declare_lint! {
|
|||
"detects name collision with an existing but unstable method"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub IRREFUTABLE_LET_PATTERNS,
|
||||
Deny,
|
||||
"detects irrefutable patterns in if-let and while-let statements"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub UNUSED_LABELS,
|
||||
Allow,
|
||||
|
@ -361,6 +367,7 @@ impl LintPass for HardwiredLints {
|
|||
BARE_TRAIT_OBJECTS,
|
||||
ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
|
||||
UNSTABLE_NAME_COLLISIONS,
|
||||
IRREFUTABLE_LET_PATTERNS,
|
||||
DUPLICATE_ASSOCIATED_TYPE_BINDINGS,
|
||||
DUPLICATE_MACRO_EXPORTS,
|
||||
INTRA_DOC_LINK_RESOLUTION_FAILURE,
|
||||
|
|
|
@ -371,43 +371,56 @@ fn check_arms<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
|
|||
NotUseful => {
|
||||
match source {
|
||||
hir::MatchSource::IfLetDesugar { .. } => {
|
||||
if printed_if_let_err {
|
||||
// we already printed an irrefutable if-let pattern error.
|
||||
// We don't want two, that's just confusing.
|
||||
if cx.tcx.features().irrefutable_let_patterns {
|
||||
cx.tcx.lint_node(
|
||||
lint::builtin::IRREFUTABLE_LET_PATTERNS,
|
||||
hir_pat.id, pat.span,
|
||||
"irrefutable if-let pattern");
|
||||
} else {
|
||||
// find the first arm pattern so we can use its span
|
||||
let &(ref first_arm_pats, _) = &arms[0];
|
||||
let first_pat = &first_arm_pats[0];
|
||||
let span = first_pat.0.span;
|
||||
struct_span_err!(cx.tcx.sess, span, E0162,
|
||||
"irrefutable if-let pattern")
|
||||
.span_label(span, "irrefutable pattern")
|
||||
.emit();
|
||||
printed_if_let_err = true;
|
||||
if printed_if_let_err {
|
||||
// we already printed an irrefutable if-let pattern error.
|
||||
// We don't want two, that's just confusing.
|
||||
} else {
|
||||
// find the first arm pattern so we can use its span
|
||||
let &(ref first_arm_pats, _) = &arms[0];
|
||||
let first_pat = &first_arm_pats[0];
|
||||
let span = first_pat.0.span;
|
||||
struct_span_err!(cx.tcx.sess, span, E0162,
|
||||
"irrefutable if-let pattern")
|
||||
.span_label(span, "irrefutable pattern")
|
||||
.emit();
|
||||
printed_if_let_err = true;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
hir::MatchSource::WhileLetDesugar => {
|
||||
// find the first arm pattern so we can use its span
|
||||
let &(ref first_arm_pats, _) = &arms[0];
|
||||
let first_pat = &first_arm_pats[0];
|
||||
let span = first_pat.0.span;
|
||||
|
||||
// check which arm we're on.
|
||||
match arm_index {
|
||||
// The arm with the user-specified pattern.
|
||||
0 => {
|
||||
cx.tcx.lint_node(
|
||||
lint::builtin::UNREACHABLE_PATTERNS,
|
||||
lint::builtin::UNREACHABLE_PATTERNS,
|
||||
hir_pat.id, pat.span,
|
||||
"unreachable pattern");
|
||||
},
|
||||
// The arm with the wildcard pattern.
|
||||
1 => {
|
||||
struct_span_err!(cx.tcx.sess, span, E0165,
|
||||
"irrefutable while-let pattern")
|
||||
.span_label(span, "irrefutable pattern")
|
||||
.emit();
|
||||
if cx.tcx.features().irrefutable_let_patterns {
|
||||
cx.tcx.lint_node(
|
||||
lint::builtin::IRREFUTABLE_LET_PATTERNS,
|
||||
hir_pat.id, pat.span,
|
||||
"irrefutable while-let pattern");
|
||||
} else {
|
||||
// find the first arm pattern so we can use its span
|
||||
let &(ref first_arm_pats, _) = &arms[0];
|
||||
let first_pat = &first_arm_pats[0];
|
||||
let span = first_pat.0.span;
|
||||
struct_span_err!(cx.tcx.sess, span, E0165,
|
||||
"irrefutable while-let pattern")
|
||||
.span_label(span, "irrefutable pattern")
|
||||
.emit();
|
||||
}
|
||||
},
|
||||
_ => bug!(),
|
||||
}
|
||||
|
|
|
@ -458,6 +458,9 @@ declare_features! (
|
|||
// Scoped attributes
|
||||
(active, tool_attributes, "1.25.0", Some(44690), None),
|
||||
|
||||
// allow irrefutable patterns in if-let and while-let statements (RFC 2086)
|
||||
(active, irrefutable_let_patterns, "1.27.0", Some(44495), None),
|
||||
|
||||
// Allows use of the :literal macro fragment specifier (RFC 1576)
|
||||
(active, macro_literal_matcher, "1.27.0", Some(35625), None),
|
||||
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
// gate-test-irrefutable_let_patterns
|
||||
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#[allow(irrefutable_let_patterns)]
|
||||
fn main() {
|
||||
if let _ = 5 {}
|
||||
//~^ ERROR 15:12: 15:13: irrefutable if-let pattern [E0162]
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// should-fail-irrefutable_let_patterns
|
||||
fn main() {
|
||||
if let _ = 5 {}
|
||||
//~^ ERROR irrefutable if-let pattern [E0162]
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(irrefutable_let_patterns)]
|
||||
|
||||
// should-fail-irrefutable_let_patterns_with_gate
|
||||
fn main() {
|
||||
if let _ = 5 {}
|
||||
//~^ ERROR irrefutable if-let pattern [irrefutable_let_patterns]
|
||||
}
|
21
src/test/run-pass/allow_irrefutable_let_patterns.rs
Normal file
21
src/test/run-pass/allow_irrefutable_let_patterns.rs
Normal file
|
@ -0,0 +1,21 @@
|
|||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(irrefutable_let_patterns)]
|
||||
|
||||
// must-compile-successfully-irrefutable_let_patterns_with_gate
|
||||
#[allow(irrefutable_let_patterns)]
|
||||
fn main() {
|
||||
if let _ = 5 {}
|
||||
|
||||
while let _ = 5 {
|
||||
break;
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue