Implementation of RFC 2086 - Allow Irrefutable Let patterns

This commit is contained in:
Sebastian Malton 2018-06-03 23:31:49 -04:00 committed by Jake Goulding
parent 4122885e0f
commit 4fe40635ef
8 changed files with 139 additions and 22 deletions

View file

@ -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 {}
}
```

View file

@ -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,
)
}

View file

@ -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!(),
}

View file

@ -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),

View file

@ -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]
}

View file

@ -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]
}

View file

@ -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]
}

View 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;
}
}