Skip to content

Commit 5d11755

Browse files
committed
Add 'ast::PatKind::Rest'.
1 parent 299ef86 commit 5d11755

File tree

5 files changed

+35
-2
lines changed

5 files changed

+35
-2
lines changed

src/librustc/hir/lowering.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4265,6 +4265,10 @@ impl<'a> LoweringContext<'a> {
42654265
slice.as_ref().map(|x| self.lower_pat(x)),
42664266
after.iter().map(|x| self.lower_pat(x)).collect(),
42674267
),
4268+
PatKind::Rest => {
4269+
// If we reach here the `..` pattern is not semantically allowed.
4270+
self.ban_illegal_rest_pat(p.span)
4271+
}
42684272
PatKind::Paren(ref inner) => return self.lower_pat(inner),
42694273
PatKind::Mac(_) => panic!("Shouldn't exist here"),
42704274
};
@@ -4276,6 +4280,19 @@ impl<'a> LoweringContext<'a> {
42764280
})
42774281
}
42784282

4283+
/// Used to ban the `..` pattern in places it shouldn't be semantically.
4284+
fn ban_illegal_rest_pat(&self, sp: Span) -> hir::PatKind {
4285+
self.diagnostic()
4286+
.struct_span_err(sp, "`..` patterns are not allowed here")
4287+
.note("only allowed in tuple, tuple struct, and slice patterns")
4288+
.emit();
4289+
4290+
// We're not in a list context so `..` can be reasonably treated
4291+
// as `_` because it should always be valid and roughly matches the
4292+
// intent of `..` (notice that the rest of a single slot is that slot).
4293+
hir::PatKind::Wild
4294+
}
4295+
42794296
fn lower_range_end(&mut self, e: &RangeEnd) -> hir::RangeEnd {
42804297
match *e {
42814298
RangeEnd::Included(_) => hir::RangeEnd::Included,

src/libsyntax/ast.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,7 @@ impl Pat {
572572
&& after.iter().all(|p| p.walk(it))
573573
}
574574
PatKind::Wild
575+
| PatKind::Rest
575576
| PatKind::Lit(_)
576577
| PatKind::Range(..)
577578
| PatKind::Ident(..)
@@ -661,6 +662,20 @@ pub enum PatKind {
661662
/// `PatKind::Slice(box [a, b], Some(i), box [y, z])`
662663
Slice(Vec<P<Pat>>, Option<P<Pat>>, Vec<P<Pat>>),
663664

665+
/// A rest pattern `..`.
666+
///
667+
/// Syntactically it is valid anywhere.
668+
///
669+
/// Semantically however, it only has meaning immediately inside:
670+
/// - a slice pattern: `[a, .., b]`,
671+
/// - a binding pattern immediately inside a slice pattern: `[a, r @ ..]`,
672+
/// - a tuple pattern: `(a, .., b)`,
673+
/// - a tuple struct/variant pattern: `$path(a, .., b)`.
674+
///
675+
/// In all of these cases, an additional restriction applies,
676+
/// only one rest pattern may occur in the pattern sequences.
677+
Rest,
678+
664679
/// Parentheses in patterns used for grouping (i.e., `(PAT)`).
665680
Paren(P<Pat>),
666681

src/libsyntax/mut_visit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1020,7 +1020,7 @@ pub fn noop_visit_pat<T: MutVisitor>(pat: &mut P<Pat>, vis: &mut T) {
10201020
let Pat { id, node, span } = pat.deref_mut();
10211021
vis.visit_id(id);
10221022
match node {
1023-
PatKind::Wild => {}
1023+
PatKind::Wild | PatKind::Rest => {}
10241024
PatKind::Ident(_binding_mode, ident, sub) => {
10251025
vis.visit_ident(ident);
10261026
visit_opt(sub, |sub| vis.visit_pat(sub));

src/libsyntax/print/pprust.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2478,6 +2478,7 @@ impl<'a> State<'a> {
24782478
|s, p| s.print_pat(p));
24792479
self.s.word("]");
24802480
}
2481+
PatKind::Rest => self.s.word(".."),
24812482
PatKind::Paren(ref inner) => {
24822483
self.popen();
24832484
self.print_pat(inner);

src/libsyntax/visit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,7 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) {
463463
visitor.visit_expr(lower_bound);
464464
visitor.visit_expr(upper_bound);
465465
}
466-
PatKind::Wild => (),
466+
PatKind::Wild | PatKind::Rest => {},
467467
PatKind::Slice(ref prepatterns, ref slice_pattern, ref postpatterns) => {
468468
walk_list!(visitor, visit_pat, prepatterns);
469469
walk_list!(visitor, visit_pat, slice_pattern);

0 commit comments

Comments
 (0)