Skip to content

Commit bb997e6

Browse files
committed
Add never_patterns feature gate
1 parent fec80b4 commit bb997e6

File tree

40 files changed

+303
-27
lines changed

40 files changed

+303
-27
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,7 @@ impl Pat {
646646
// These patterns do not contain subpatterns, skip.
647647
PatKind::Wild
648648
| PatKind::Rest
649+
| PatKind::Never
649650
| PatKind::Lit(_)
650651
| PatKind::Range(..)
651652
| PatKind::Ident(..)
@@ -796,6 +797,9 @@ pub enum PatKind {
796797
/// only one rest pattern may occur in the pattern sequences.
797798
Rest,
798799

800+
// A never pattern `!`
801+
Never,
802+
799803
/// Parentheses in patterns used for grouping (i.e., `(PAT)`).
800804
Paren(P<Pat>),
801805

compiler/rustc_ast/src/mut_visit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1249,7 +1249,7 @@ pub fn noop_visit_pat<T: MutVisitor>(pat: &mut P<Pat>, vis: &mut T) {
12491249
let Pat { id, kind, span, tokens } = pat.deref_mut();
12501250
vis.visit_id(id);
12511251
match kind {
1252-
PatKind::Wild | PatKind::Rest => {}
1252+
PatKind::Wild | PatKind::Rest | PatKind::Never => {}
12531253
PatKind::Ident(_binding_mode, ident, sub) => {
12541254
vis.visit_ident(ident);
12551255
visit_opt(sub, |sub| vis.visit_pat(sub));

compiler/rustc_ast/src/visit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,7 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) {
559559
walk_list!(visitor, visit_expr, lower_bound);
560560
walk_list!(visitor, visit_expr, upper_bound);
561561
}
562-
PatKind::Wild | PatKind::Rest => {}
562+
PatKind::Wild | PatKind::Rest | PatKind::Never => {}
563563
PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => {
564564
walk_list!(visitor, visit_pat, elems);
565565
}

compiler/rustc_ast_lowering/src/pat.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
2424
let node = loop {
2525
match &pattern.kind {
2626
PatKind::Wild => break hir::PatKind::Wild,
27+
PatKind::Never => break hir::PatKind::Never,
2728
PatKind::Ident(binding_mode, ident, sub) => {
2829
let lower_sub = |this: &mut Self| sub.as_ref().map(|s| this.lower_pat(s));
2930
break self.lower_pat_ident(pattern, *binding_mode, *ident, lower_sub);

compiler/rustc_ast_passes/src/feature_gate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
555555
gate_all!(explicit_tail_calls, "`become` expression is experimental");
556556
gate_all!(generic_const_items, "generic const items are experimental");
557557
gate_all!(unnamed_fields, "unnamed fields are not yet fully implemented");
558+
gate_all!(never_patterns, "`!` patterns are experimental");
558559

559560
if !visitor.features.negative_bounds {
560561
for &span in spans.get(&sym::negative_bounds).iter().copied().flatten() {

compiler/rustc_ast_pretty/src/pprust/state.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1446,6 +1446,7 @@ impl<'a> State<'a> {
14461446
is that it doesn't matter */
14471447
match &pat.kind {
14481448
PatKind::Wild => self.word("_"),
1449+
PatKind::Never => self.word("!"),
14491450
PatKind::Ident(BindingAnnotation(by_ref, mutbl), ident, sub) => {
14501451
if *by_ref == ByRef::Yes {
14511452
self.word_nbsp("ref");

compiler/rustc_feature/src/unstable.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ macro_rules! declare_features {
147147
// was set.
148148
//
149149
// Note that the features are grouped into internal/user-facing and then
150-
// sorted by version inside those groups. This is enforced with tidy.
150+
// sorted alphabetically inside those groups. This is enforced with tidy.
151151
//
152152
// N.B., `tools/tidy/src/features.rs` parses this information directly out of the
153153
// source, so take care when modifying it.
@@ -510,6 +510,8 @@ declare_features! (
510510
(unstable, native_link_modifiers_as_needed, "1.53.0", Some(81490), None),
511511
/// Allow negative trait implementations.
512512
(unstable, negative_impls, "1.44.0", Some(68318), None),
513+
/// Allows the `!` pattern.
514+
(incomplete, never_patterns, "CURRENT_RUSTC_VERSION", Some(118155), None),
513515
/// Allows the `!` type. Does not imply 'exhaustive_patterns' (below) any more.
514516
(unstable, never_type, "1.13.0", Some(35121), None),
515517
/// Allows diverging expressions to fall back to `!` rather than `()`.

compiler/rustc_hir/src/hir.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1002,7 +1002,7 @@ impl<'hir> Pat<'hir> {
10021002

10031003
use PatKind::*;
10041004
match self.kind {
1005-
Wild | Lit(_) | Range(..) | Binding(.., None) | Path(_) => true,
1005+
Wild | Never | Lit(_) | Range(..) | Binding(.., None) | Path(_) => true,
10061006
Box(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_short_(it),
10071007
Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk_short_(it)),
10081008
TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().all(|p| p.walk_short_(it)),
@@ -1029,7 +1029,7 @@ impl<'hir> Pat<'hir> {
10291029

10301030
use PatKind::*;
10311031
match self.kind {
1032-
Wild | Lit(_) | Range(..) | Binding(.., None) | Path(_) => {}
1032+
Wild | Never | Lit(_) | Range(..) | Binding(.., None) | Path(_) => {}
10331033
Box(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_(it),
10341034
Struct(_, fields, _) => fields.iter().for_each(|field| field.pat.walk_(it)),
10351035
TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().for_each(|p| p.walk_(it)),
@@ -1142,6 +1142,9 @@ pub enum PatKind<'hir> {
11421142
/// Invariant: `pats.len() >= 2`.
11431143
Or(&'hir [Pat<'hir>]),
11441144

1145+
/// A never pattern `!`.
1146+
Never,
1147+
11451148
/// A path pattern for a unit struct/variant or a (maybe-associated) constant.
11461149
Path(QPath<'hir>),
11471150

compiler/rustc_hir/src/intravisit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -660,7 +660,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) {
660660
walk_list!(visitor, visit_expr, lower_bound);
661661
walk_list!(visitor, visit_expr, upper_bound);
662662
}
663-
PatKind::Wild => (),
663+
PatKind::Never | PatKind::Wild => (),
664664
PatKind::Slice(prepatterns, ref slice_pattern, postpatterns) => {
665665
walk_list!(visitor, visit_pat, prepatterns);
666666
walk_list!(visitor, visit_pat, slice_pattern);

compiler/rustc_hir_analysis/src/check/region.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,7 @@ fn resolve_local<'tcx>(
662662
PatKind::Ref(_, _)
663663
| PatKind::Binding(hir::BindingAnnotation(hir::ByRef::No, _), ..)
664664
| PatKind::Wild
665+
| PatKind::Never
665666
| PatKind::Path(_)
666667
| PatKind::Lit(_)
667668
| PatKind::Range(_, _, _) => false,

0 commit comments

Comments
 (0)