Skip to content

Commit

Permalink
Merge #1848
Browse files Browse the repository at this point in the history
1848: Parse `..` as a full pattern r=matklad a=ecstatic-morse

Resolves #1479.

This PR implements [RFC 2707](rust-lang/rfcs#2707) in the parser. It introduces a new `DotDotPat` AST node modeled on `PlaceholderPat` and changes the parsing of tuple and slice patterns to conform to the RFC.

Notably, this PR does *not* change the resulting AST when `..` appears in a struct pattern (e.g. `Struct { a, b: c, .. }`). I *think* this is the behavior mandated by RFC 2707, but someone should confirm this.

Co-authored-by: Dylan MacKenzie <ecstaticmorse@gmail.com>
  • Loading branch information
bors[bot] and ecstatic-morse committed Sep 15, 2019
2 parents bcdba77 + 0956323 commit 2d79a1a
Show file tree
Hide file tree
Showing 12 changed files with 573 additions and 17 deletions.
1 change: 1 addition & 0 deletions crates/ra_hir/src/expr/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,7 @@ where
}

// FIXME: implement
ast::Pat::DotDotPat(_) => Pat::Missing,
ast::Pat::BoxPat(_) => Pat::Missing,
ast::Pat::LiteralPat(_) => Pat::Missing,
ast::Pat::SlicePat(_) | ast::Pat::RangePat(_) => Pat::Missing,
Expand Down
52 changes: 42 additions & 10 deletions crates/ra_parser/src/grammar/patterns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use super::*;

pub(super) const PATTERN_FIRST: TokenSet = expressions::LITERAL_FIRST
.union(paths::PATH_FIRST)
.union(token_set![BOX_KW, REF_KW, MUT_KW, L_PAREN, L_BRACK, AMP, UNDERSCORE, MINUS]);
.union(token_set![BOX_KW, REF_KW, MUT_KW, L_PAREN, L_BRACK, AMP, UNDERSCORE, MINUS, DOT]);

pub(crate) fn pattern(p: &mut Parser) {
pattern_r(p, PAT_RECOVERY_SET);
Expand Down Expand Up @@ -73,6 +73,7 @@ fn atom_pat(p: &mut Parser, recovery_set: TokenSet) -> Option<CompletedMarker> {
_ if paths::is_use_path_start(p) => path_pat(p),
_ if is_literal_pat_start(p) => literal_pat(p),

T![.] if p.at(T![..]) => dot_dot_pat(p),
T![_] => placeholder_pat(p),
T![&] => ref_pat(p),
T!['('] => tuple_pat(p),
Expand Down Expand Up @@ -163,7 +164,9 @@ fn record_field_pat_list(p: &mut Parser) {
p.bump_any();
while !p.at(EOF) && !p.at(T!['}']) {
match p.current() {
// A trailing `..` is *not* treated as a DOT_DOT_PAT.
T![.] if p.at(T![..]) => p.bump(T![..]),

IDENT if p.nth(1) == T![:] => record_field_pat(p),
T!['{'] => error_block(p, "expected ident"),
T![box] => {
Expand Down Expand Up @@ -201,6 +204,39 @@ fn placeholder_pat(p: &mut Parser) -> CompletedMarker {
m.complete(p, PLACEHOLDER_PAT)
}

// test dot_dot_pat
// fn main() {
// let .. = ();
// //
// // Tuples
// //
// let (a, ..) = ();
// let (a, ..,) = ();
// let Tuple(a, ..) = ();
// let Tuple(a, ..,) = ();
// let (.., ..) = ();
// let Tuple(.., ..) = ();
// let (.., a, ..) = ();
// let Tuple(.., a, ..) = ();
// //
// // Slices
// //
// let [..] = ();
// let [head, ..] = ();
// let [head, tail @ ..] = ();
// let [head, .., cons] = ();
// let [head, mid @ .., cons] = ();
// let [head, .., .., cons] = ();
// let [head, .., mid, tail @ ..] = ();
// let [head, .., mid, .., cons] = ();
// }
fn dot_dot_pat(p: &mut Parser) -> CompletedMarker {
assert!(p.at(T![..]));
let m = p.start();
p.bump(T![..]);
m.complete(p, DOT_DOT_PAT)
}

// test ref_pat
// fn main() {
// let &a = ();
Expand Down Expand Up @@ -241,16 +277,12 @@ fn slice_pat(p: &mut Parser) -> CompletedMarker {

fn pat_list(p: &mut Parser, ket: SyntaxKind) {
while !p.at(EOF) && !p.at(ket) {
match p.current() {
T![.] if p.at(T![..]) => p.bump(T![..]),
_ => {
if !p.at_ts(PATTERN_FIRST) {
p.error("expected a pattern");
break;
}
pattern(p)
}
if !p.at_ts(PATTERN_FIRST) {
p.error("expected a pattern");
break;
}

pattern(p);
if !p.at(ket) {
p.expect(T![,]);
}
Expand Down
1 change: 1 addition & 0 deletions crates/ra_parser/src/syntax_kind/generated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ pub enum SyntaxKind {
BOX_PAT,
BIND_PAT,
PLACEHOLDER_PAT,
DOT_DOT_PAT,
PATH_PAT,
RECORD_PAT,
RECORD_FIELD_PAT_LIST,
Expand Down
37 changes: 35 additions & 2 deletions crates/ra_syntax/src/ast/generated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,29 @@ impl AstNode for ContinueExpr {
}
impl ContinueExpr {}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct DotDotPat {
pub(crate) syntax: SyntaxNode,
}
impl AstNode for DotDotPat {
fn can_cast(kind: SyntaxKind) -> bool {
match kind {
DOT_DOT_PAT => true,
_ => false,
}
}
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
} else {
None
}
}
fn syntax(&self) -> &SyntaxNode {
&self.syntax
}
}
impl DotDotPat {}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct DynTraitType {
pub(crate) syntax: SyntaxNode,
}
Expand Down Expand Up @@ -2128,6 +2151,7 @@ pub enum Pat {
BoxPat(BoxPat),
BindPat(BindPat),
PlaceholderPat(PlaceholderPat),
DotDotPat(DotDotPat),
PathPat(PathPat),
RecordPat(RecordPat),
TupleStructPat(TupleStructPat),
Expand Down Expand Up @@ -2156,6 +2180,11 @@ impl From<PlaceholderPat> for Pat {
Pat::PlaceholderPat(node)
}
}
impl From<DotDotPat> for Pat {
fn from(node: DotDotPat) -> Pat {
Pat::DotDotPat(node)
}
}
impl From<PathPat> for Pat {
fn from(node: PathPat) -> Pat {
Pat::PathPat(node)
Expand Down Expand Up @@ -2194,8 +2223,10 @@ impl From<LiteralPat> for Pat {
impl AstNode for Pat {
fn can_cast(kind: SyntaxKind) -> bool {
match kind {
REF_PAT | BOX_PAT | BIND_PAT | PLACEHOLDER_PAT | PATH_PAT | RECORD_PAT
| TUPLE_STRUCT_PAT | TUPLE_PAT | SLICE_PAT | RANGE_PAT | LITERAL_PAT => true,
REF_PAT | BOX_PAT | BIND_PAT | PLACEHOLDER_PAT | DOT_DOT_PAT | PATH_PAT
| RECORD_PAT | TUPLE_STRUCT_PAT | TUPLE_PAT | SLICE_PAT | RANGE_PAT | LITERAL_PAT => {
true
}
_ => false,
}
}
Expand All @@ -2205,6 +2236,7 @@ impl AstNode for Pat {
BOX_PAT => Pat::BoxPat(BoxPat { syntax }),
BIND_PAT => Pat::BindPat(BindPat { syntax }),
PLACEHOLDER_PAT => Pat::PlaceholderPat(PlaceholderPat { syntax }),
DOT_DOT_PAT => Pat::DotDotPat(DotDotPat { syntax }),
PATH_PAT => Pat::PathPat(PathPat { syntax }),
RECORD_PAT => Pat::RecordPat(RecordPat { syntax }),
TUPLE_STRUCT_PAT => Pat::TupleStructPat(TupleStructPat { syntax }),
Expand All @@ -2222,6 +2254,7 @@ impl AstNode for Pat {
Pat::BoxPat(it) => &it.syntax,
Pat::BindPat(it) => &it.syntax,
Pat::PlaceholderPat(it) => &it.syntax,
Pat::DotDotPat(it) => &it.syntax,
Pat::PathPat(it) => &it.syntax,
Pat::RecordPat(it) => &it.syntax,
Pat::TupleStructPat(it) => &it.syntax,
Expand Down
3 changes: 3 additions & 0 deletions crates/ra_syntax/src/grammar.ron
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ Grammar(
"BOX_PAT",
"BIND_PAT",
"PLACEHOLDER_PAT",
"DOT_DOT_PAT",
"PATH_PAT",
"RECORD_PAT",
"RECORD_FIELD_PAT_LIST",
Expand Down Expand Up @@ -532,6 +533,7 @@ Grammar(
traits: ["NameOwner"]
),
"PlaceholderPat": (),
"DotDotPat": (),
"PathPat": ( options: [ "Path" ] ),
"RecordPat": ( options: ["RecordFieldPatList", "Path"] ),
"RecordFieldPatList": (
Expand Down Expand Up @@ -559,6 +561,7 @@ Grammar(
"BoxPat",
"BindPat",
"PlaceholderPat",
"DotDotPat",
"PathPat",
"RecordPat",
"TupleStructPat",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ SOURCE_FILE@[0; 103)
NAME_REF@[87; 90)
IDENT@[87; 90) "Bar"
L_PAREN@[90; 91) "("
DOTDOT@[91; 93) ".."
DOT_DOT_PAT@[91; 93)
DOTDOT@[91; 93) ".."
R_PAREN@[93; 94) ")"
WHITESPACE@[94; 95) " "
EQ@[95; 96) "="
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ SOURCE_FILE@[0; 39)
IDENT@[24; 25) "b"
COMMA@[25; 26) ","
WHITESPACE@[26; 27) " "
DOTDOT@[27; 29) ".."
DOT_DOT_PAT@[27; 29)
DOTDOT@[27; 29) ".."
R_BRACK@[29; 30) "]"
WHITESPACE@[30; 31) " "
EQ@[31; 32) "="
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ SOURCE_FILE@[0; 97)
UNDERSCORE@[78; 79) "_"
COMMA@[79; 80) ","
WHITESPACE@[80; 81) " "
DOTDOT@[81; 83) ".."
DOT_DOT_PAT@[81; 83)
DOTDOT@[81; 83) ".."
WHITESPACE@[83; 84) " "
COMMA@[84; 85) ","
WHITESPACE@[85; 86) " "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ SOURCE_FILE@[0; 39)
IDENT@[24; 25) "b"
COMMA@[25; 26) ","
WHITESPACE@[26; 27) " "
DOTDOT@[27; 29) ".."
DOT_DOT_PAT@[27; 29)
DOTDOT@[27; 29) ".."
R_PAREN@[29; 30) ")"
WHITESPACE@[30; 31) " "
EQ@[31; 32) "="
Expand Down
25 changes: 25 additions & 0 deletions crates/ra_syntax/test_data/parser/inline/ok/0144_dot_dot_pat.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
fn main() {
let .. = ();
//
// Tuples
//
let (a, ..) = ();
let (a, ..,) = ();
let Tuple(a, ..) = ();
let Tuple(a, ..,) = ();
let (.., ..) = ();
let Tuple(.., ..) = ();
let (.., a, ..) = ();
let Tuple(.., a, ..) = ();
//
// Slices
//
let [..] = ();
let [head, ..] = ();
let [head, tail @ ..] = ();
let [head, .., cons] = ();
let [head, mid @ .., cons] = ();
let [head, .., .., cons] = ();
let [head, .., mid, tail @ ..] = ();
let [head, .., mid, .., cons] = ();
}
Loading

0 comments on commit 2d79a1a

Please sign in to comment.