mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-22 18:15:07 +03:00
Implementation of RFC 2086 - Allow Irrefutable Let patterns
This commit is contained in:
committed by
Jake Goulding
parent
4122885e0f
commit
4fe40635ef
@@ -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 @@
|
||||
"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 @@ fn get_lints(&self) -> LintArray {
|
||||
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 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
|
||||
// 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]
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user