Skip to content

Commit

Permalink
Auto merge of #49469 - Nokel81:allow-irrefutable-let-patterns, r=niko…
Browse files Browse the repository at this point in the history
…matsakis

Implementation of RFC 2086 - Allow Irrefutable Let patterns

This is the set of changes for RFC2086. Tracking issue #44495. Rendered [here](rust-lang/rfcs#2086)
  • Loading branch information
bors committed Jun 26, 2018
2 parents 773ce53 + 9168034 commit 309fd8a
Show file tree
Hide file tree
Showing 8 changed files with 143 additions and 22 deletions.
Original file line number Diff line number Diff line change
@@ -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; }
}
```
7 changes: 7 additions & 0 deletions src/librustc/lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
57 changes: 35 additions & 22 deletions src/librustc_mir/hair/pattern/check_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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!(),
}
Expand Down
3 changes: 3 additions & 0 deletions src/libsyntax/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),

Expand Down
Original file line number Diff line number Diff line change
@@ -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]
}
Original file line number Diff line number Diff line change
@@ -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]
}
Original file line number Diff line number Diff line change
@@ -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 changes: 21 additions & 0 deletions src/test/run-pass/allow_irrefutable_let_patterns.rs
Original file line number Diff line number Diff line change
@@ -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;
}
}

0 comments on commit 309fd8a

Please sign in to comment.