Skip to content

Commit 4fe4063

Browse files
Nokel81shepmaster
authored andcommitted
Implementation of RFC 2086 - Allow Irrefutable Let patterns
1 parent 4122885 commit 4fe4063

File tree

8 files changed

+139
-22
lines changed

8 files changed

+139
-22
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# `irrefutable_let_pattern`
2+
3+
The tracking issue for this feature is: [#44495]
4+
5+
[#44495]: https://github.com/rust-lang/rust/issues/44495
6+
7+
------------------------
8+
9+
This feature changes the way that the irrefutable pattern is handled
10+
in the `if let` and `while let` forms. The old way was to always error
11+
but now with a tag the error-by-default lint can be switched off.
12+
13+
```rust
14+
#![feature(irrefutable_let_pattern)]
15+
16+
fn main() {
17+
#[allow(irrefutable_let_pattern)]
18+
if let _ = 5 {}
19+
20+
#[allow(irrefutable_let_pattern)]
21+
while let _ = 5 {}
22+
}
23+
```

src/librustc/lint/builtin.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,12 @@ declare_lint! {
273273
"detects name collision with an existing but unstable method"
274274
}
275275

276+
declare_lint! {
277+
pub IRREFUTABLE_LET_PATTERNS,
278+
Deny,
279+
"detects irrefutable patterns in if-let and while-let statements"
280+
}
281+
276282
declare_lint! {
277283
pub UNUSED_LABELS,
278284
Allow,
@@ -336,6 +342,7 @@ impl LintPass for HardwiredLints {
336342
BARE_TRAIT_OBJECTS,
337343
ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
338344
UNSTABLE_NAME_COLLISIONS,
345+
IRREFUTABLE_LET_PATTERNS,
339346
DUPLICATE_ASSOCIATED_TYPE_BINDINGS,
340347
)
341348
}

src/librustc_mir/hair/pattern/check_match.rs

Lines changed: 35 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -369,43 +369,56 @@ fn check_arms<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
369369
NotUseful => {
370370
match source {
371371
hir::MatchSource::IfLetDesugar { .. } => {
372-
if printed_if_let_err {
373-
// we already printed an irrefutable if-let pattern error.
374-
// We don't want two, that's just confusing.
372+
if cx.tcx.features().irrefutable_let_pattern {
373+
cx.tcx.lint_node(
374+
lint::builtin::IRREFUTABLE_LET_PATTERNS,
375+
hir_pat.id, pat.span,
376+
"irrefutable if-let pattern");
375377
} else {
376-
// find the first arm pattern so we can use its span
377-
let &(ref first_arm_pats, _) = &arms[0];
378-
let first_pat = &first_arm_pats[0];
379-
let span = first_pat.0.span;
380-
struct_span_err!(cx.tcx.sess, span, E0162,
381-
"irrefutable if-let pattern")
382-
.span_label(span, "irrefutable pattern")
383-
.emit();
384-
printed_if_let_err = true;
378+
if printed_if_let_err {
379+
// we already printed an irrefutable if-let pattern error.
380+
// We don't want two, that's just confusing.
381+
} else {
382+
// find the first arm pattern so we can use its span
383+
let &(ref first_arm_pats, _) = &arms[0];
384+
let first_pat = &first_arm_pats[0];
385+
let span = first_pat.0.span;
386+
struct_span_err!(cx.tcx.sess, span, E0162,
387+
"irrefutable if-let pattern")
388+
.span_label(span, "irrefutable pattern")
389+
.emit();
390+
printed_if_let_err = true;
391+
}
385392
}
386393
},
387394

388395
hir::MatchSource::WhileLetDesugar => {
389-
// find the first arm pattern so we can use its span
390-
let &(ref first_arm_pats, _) = &arms[0];
391-
let first_pat = &first_arm_pats[0];
392-
let span = first_pat.0.span;
393-
394396
// check which arm we're on.
395397
match arm_index {
396398
// The arm with the user-specified pattern.
397399
0 => {
398400
cx.tcx.lint_node(
399-
lint::builtin::UNREACHABLE_PATTERNS,
401+
lint::builtin::UNREACHABLE_PATTERNS,
400402
hir_pat.id, pat.span,
401403
"unreachable pattern");
402404
},
403405
// The arm with the wildcard pattern.
404406
1 => {
405-
struct_span_err!(cx.tcx.sess, span, E0165,
406-
"irrefutable while-let pattern")
407-
.span_label(span, "irrefutable pattern")
408-
.emit();
407+
if cx.tcx.features().irrefutable_let_pattern {
408+
cx.tcx.lint_node(
409+
lint::builtin::IRREFUTABLE_LET_PATTERNS,
410+
hir_pat.id, pat.span,
411+
"irrefutable while-let pattern");
412+
} else {
413+
// find the first arm pattern so we can use its span
414+
let &(ref first_arm_pats, _) = &arms[0];
415+
let first_pat = &first_arm_pats[0];
416+
let span = first_pat.0.span;
417+
struct_span_err!(cx.tcx.sess, span, E0165,
418+
"irrefutable while-let pattern")
419+
.span_label(span, "irrefutable pattern")
420+
.emit();
421+
}
409422
},
410423
_ => bug!(),
411424
}

src/libsyntax/feature_gate.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,9 @@ declare_features! (
467467
// Scoped attributes
468468
(active, tool_attributes, "1.25.0", Some(44690), None),
469469

470+
// allow irrefutable patterns in if-let and while-let statements (RFC 2086)
471+
(active, irrefutable_let_pattern, "1.27.0", Some(44495), None),
472+
470473
// Allows use of the :literal macro fragment specifier (RFC 1576)
471474
(active, macro_literal_matcher, "1.27.0", Some(35625), None),
472475

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// gate-test-irrefutable_let_pattern
2+
3+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
4+
// file at the top-level directory of this distribution and at
5+
// http://rust-lang.org/COPYRIGHT.
6+
//
7+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
8+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
9+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
10+
// option. This file may not be copied, modified, or distributed
11+
// except according to those terms.
12+
13+
fn main() {
14+
#[allow(irrefutable_let_pattern)]
15+
if let _ = 5 {}
16+
//~^ ERROR 15:12: 15:13: irrefutable if-let pattern [E0162]
17+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// should-fail-irrefutable_let_pattern
12+
fn main() {
13+
if let _ = 5 {}
14+
//~^ ERROR irrefutable if-let pattern [E0162]
15+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(irrefutable_let_pattern)]
12+
13+
// should-fail-irrefutable_let_pattern_with_gate
14+
fn main() {
15+
if let _ = 5 {}
16+
//~^ ERROR irrefutable if-let pattern [irrefutable_let_pattern]
17+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(irrefutable_let_pattern)]
12+
13+
// must-compile-successfully-irrefutable_let_pattern_with_gate
14+
fn main() {
15+
#[allow(irrefutable_let_pattern)]
16+
if let _ = 5 {}
17+
18+
#[allow(irrefutable_let_pattern)]
19+
while let _ = 5 {
20+
break;
21+
}
22+
}

0 commit comments

Comments
 (0)