Implementation of RFC 2086 - Allow Irrefutable Let patterns
This commit is contained in:
parent
4122885e0f
commit
4fe40635ef
8 changed files with 139 additions and 22 deletions
|
|
@ -0,0 +1,23 @@
|
|||
# `irrefutable_let_pattern`
|
||||
|
||||
The tracking issue for this feature is: [#44495]
|
||||
|
||||
[#44495]: https://github.com/rust-lang/rust/issues/44495
|
||||
|
||||
------------------------
|
||||
|
||||
This feature changes the way that the irrefutable pattern is handled
|
||||
in the `if let` and `while let` forms. The old way was to always error
|
||||
but now with a tag the error-by-default lint can be switched off.
|
||||
|
||||
```rust
|
||||
#![feature(irrefutable_let_pattern)]
|
||||
|
||||
fn main() {
|
||||
#[allow(irrefutable_let_pattern)]
|
||||
if let _ = 5 {}
|
||||
|
||||
#[allow(irrefutable_let_pattern)]
|
||||
while let _ = 5 {}
|
||||
}
|
||||
```
|
||||
|
|
@ -273,6 +273,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,
|
||||
|
|
@ -336,6 +342,7 @@ impl LintPass for HardwiredLints {
|
|||
BARE_TRAIT_OBJECTS,
|
||||
ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
|
||||
UNSTABLE_NAME_COLLISIONS,
|
||||
IRREFUTABLE_LET_PATTERNS,
|
||||
DUPLICATE_ASSOCIATED_TYPE_BINDINGS,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -369,43 +369,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_pattern {
|
||||
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_pattern {
|
||||
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!(),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -467,6 +467,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_pattern, "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_pattern
|
||||
|
||||
// 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.
|
||||
|
||||
fn main() {
|
||||
#[allow(irrefutable_let_pattern)]
|
||||
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_pattern
|
||||
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_pattern)]
|
||||
|
||||
// should-fail-irrefutable_let_pattern_with_gate
|
||||
fn main() {
|
||||
if let _ = 5 {}
|
||||
//~^ ERROR irrefutable if-let pattern [irrefutable_let_pattern]
|
||||
}
|
||||
22
src/test/run-pass/allow_irrefutable_let_patterns.rs
Normal file
22
src/test/run-pass/allow_irrefutable_let_patterns.rs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
// 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_pattern)]
|
||||
|
||||
// must-compile-successfully-irrefutable_let_pattern_with_gate
|
||||
fn main() {
|
||||
#[allow(irrefutable_let_pattern)]
|
||||
if let _ = 5 {}
|
||||
|
||||
#[allow(irrefutable_let_pattern)]
|
||||
while let _ = 5 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue