From 1059ec74e2147559b43aab9b12f84849319910cc Mon Sep 17 00:00:00 2001 From: Erlend Tobiassen Date: Tue, 22 Jan 2019 01:11:35 +0100 Subject: Allow types to the left of : in where predicates. --- crates/ra_syntax/src/grammar/type_params.rs | 51 +++++++++++++++-------------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/crates/ra_syntax/src/grammar/type_params.rs b/crates/ra_syntax/src/grammar/type_params.rs index 7db25beba..fe9dba2ae 100644 --- a/crates/ra_syntax/src/grammar/type_params.rs +++ b/crates/ra_syntax/src/grammar/type_params.rs @@ -104,22 +104,32 @@ pub(super) fn opt_where_clause(p: &mut Parser) { } let m = p.start(); p.bump(); - loop { - if !(paths::is_path_start(p) - || p.current() == LIFETIME - || p.current() == FOR_KW - || p.current() == L_ANGLE) - { - break; - } - where_predicate(p); - if p.current() != L_CURLY && p.current() != SEMI && p.current() != EQ { - p.expect(COMMA); + + if is_where_clause_end(p) { + // Empty where clause + } else { + loop { + where_predicate(p); + + let comma = p.eat(COMMA); + + if is_where_clause_end(p) { + break; + } + + if !comma { + p.error("expected comma") + } } } + m.complete(p, WHERE_CLAUSE); } +fn is_where_clause_end(p: &mut Parser) -> bool { + p.current() == L_CURLY || p.current() == SEMI || p.current() == EQ +} + fn where_predicate(p: &mut Parser) { let m = p.start(); match p.current() { @@ -131,20 +141,13 @@ fn where_predicate(p: &mut Parser) { p.error("expected colon"); } } + IMPL_KW => { + p.error("expected lifetime or type"); + return; + } _ => { - // test where_pred_for - // fn test() - // where - // for<'a> F: Fn(&'a str) - // { } - if p.at(FOR_KW) { - types::for_binder(p); - } - if paths::is_path_start(p) || p.at(L_ANGLE) { - types::path_type_(p, false); - } else { - p.error("expected a type"); - } + types::type_(p); + if p.at(COLON) { bounds(p); } else { -- cgit v1.2.3 From 1aba42128f79993a092a8c0b3747acdc8f1b1be7 Mon Sep 17 00:00:00 2001 From: Erlend Tobiassen Date: Tue, 22 Jan 2019 01:25:00 +0100 Subject: Don't leave a marker hanging without completing it. --- crates/ra_syntax/src/grammar/type_params.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/ra_syntax/src/grammar/type_params.rs b/crates/ra_syntax/src/grammar/type_params.rs index fe9dba2ae..f33ec10f5 100644 --- a/crates/ra_syntax/src/grammar/type_params.rs +++ b/crates/ra_syntax/src/grammar/type_params.rs @@ -118,7 +118,7 @@ pub(super) fn opt_where_clause(p: &mut Parser) { } if !comma { - p.error("expected comma") + p.error("expected comma"); } } } @@ -143,7 +143,6 @@ fn where_predicate(p: &mut Parser) { } IMPL_KW => { p.error("expected lifetime or type"); - return; } _ => { types::type_(p); -- cgit v1.2.3 From 2b22f5fb4398378d999db98ea270ceb415dfff22 Mon Sep 17 00:00:00 2001 From: Erlend Tobiassen Date: Tue, 22 Jan 2019 13:17:10 +0100 Subject: Optimistically bail out of where clause loop if not at start of a type or lifetime --- crates/ra_syntax/src/grammar/type_params.rs | 28 ++++++++++++++++------------ crates/ra_syntax/src/grammar/types.rs | 8 ++++++++ 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/crates/ra_syntax/src/grammar/type_params.rs b/crates/ra_syntax/src/grammar/type_params.rs index f33ec10f5..a7eacf97a 100644 --- a/crates/ra_syntax/src/grammar/type_params.rs +++ b/crates/ra_syntax/src/grammar/type_params.rs @@ -105,27 +105,31 @@ pub(super) fn opt_where_clause(p: &mut Parser) { let m = p.start(); p.bump(); - if is_where_clause_end(p) { - // Empty where clause - } else { - loop { - where_predicate(p); + while is_where_predicate(p) { + where_predicate(p); - let comma = p.eat(COMMA); + let comma = p.eat(COMMA); - if is_where_clause_end(p) { - break; - } + if is_where_clause_end(p) { + break; + } - if !comma { - p.error("expected comma"); - } + if !comma { + p.error("expected comma"); } } m.complete(p, WHERE_CLAUSE); } +fn is_where_predicate(p: &mut Parser) -> bool { + match p.current() { + LIFETIME => true, + IMPL_KW => false, + _ => types::is_type_start(p), + } +} + fn is_where_clause_end(p: &mut Parser) -> bool { p.current() == L_CURLY || p.current() == SEMI || p.current() == EQ } diff --git a/crates/ra_syntax/src/grammar/types.rs b/crates/ra_syntax/src/grammar/types.rs index 21d89d83b..83a54c190 100644 --- a/crates/ra_syntax/src/grammar/types.rs +++ b/crates/ra_syntax/src/grammar/types.rs @@ -36,6 +36,14 @@ fn type_with_bounds_cond(p: &mut Parser, allow_bounds: bool) { } } +pub(super) fn is_type_start(p: &mut Parser) -> bool { + match p.current() { + L_PAREN | EXCL | STAR | L_BRACK | AMP | UNDERSCORE | FN_KW | FOR_KW | IMPL_KW | DYN_KW + | L_ANGLE => true, + _ => paths::is_path_start(p), + } +} + pub(super) fn ascription(p: &mut Parser) { p.expect(COLON); type_(p) -- cgit v1.2.3 From 8198cde13b8dc7c04190e5341bce3f6a0315e99b Mon Sep 17 00:00:00 2001 From: Erlend Tobiassen Date: Tue, 22 Jan 2019 14:32:23 +0100 Subject: Update tests after allowing where predicate to accept types --- crates/ra_syntax/src/grammar/type_params.rs | 5 +++ .../data/parser/err/0027_incomplere_where_for.txt | 17 ++++----- .../data/parser/inline/ok/0003_where_pred_for.txt | 25 +++++++------- .../tests/data/parser/ok/0038_where_pred_type.rs | 1 + .../tests/data/parser/ok/0038_where_pred_type.txt | 40 ++++++++++++++++++++++ 5 files changed, 68 insertions(+), 20 deletions(-) create mode 100644 crates/ra_syntax/tests/data/parser/ok/0038_where_pred_type.rs create mode 100644 crates/ra_syntax/tests/data/parser/ok/0038_where_pred_type.txt diff --git a/crates/ra_syntax/src/grammar/type_params.rs b/crates/ra_syntax/src/grammar/type_params.rs index a7eacf97a..369125b39 100644 --- a/crates/ra_syntax/src/grammar/type_params.rs +++ b/crates/ra_syntax/src/grammar/type_params.rs @@ -149,6 +149,11 @@ fn where_predicate(p: &mut Parser) { p.error("expected lifetime or type"); } _ => { + // test where_pred_for + // fn test() + // where + // for<'a> F: Fn(&'a str) + // { } types::type_(p); if p.at(COLON) { diff --git a/crates/ra_syntax/tests/data/parser/err/0027_incomplere_where_for.txt b/crates/ra_syntax/tests/data/parser/err/0027_incomplere_where_for.txt index 694295a60..8a2a73b9b 100644 --- a/crates/ra_syntax/tests/data/parser/err/0027_incomplere_where_for.txt +++ b/crates/ra_syntax/tests/data/parser/err/0027_incomplere_where_for.txt @@ -12,14 +12,15 @@ SOURCE_FILE@[0; 30) WHERE_KW@[13; 18) WHITESPACE@[18; 19) WHERE_PRED@[19; 26) - FOR_KW@[19; 22) - TYPE_PARAM_LIST@[22; 26) - L_ANGLE@[22; 23) - LIFETIME_PARAM@[23; 25) - LIFETIME@[23; 25) "'a" - R_ANGLE@[25; 26) - err: `expected a type` - err: `expected colon` + FOR_TYPE@[19; 26) + FOR_KW@[19; 22) + TYPE_PARAM_LIST@[22; 26) + L_ANGLE@[22; 23) + LIFETIME_PARAM@[23; 25) + LIFETIME@[23; 25) "'a" + R_ANGLE@[25; 26) + err: `expected a path` + err: `expected colon` WHITESPACE@[26; 27) BLOCK@[27; 29) L_CURLY@[27; 28) diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0003_where_pred_for.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0003_where_pred_for.txt index 921bdacf4..41420ea92 100644 --- a/crates/ra_syntax/tests/data/parser/inline/ok/0003_where_pred_for.txt +++ b/crates/ra_syntax/tests/data/parser/inline/ok/0003_where_pred_for.txt @@ -18,18 +18,19 @@ SOURCE_FILE@[0; 49) WHERE_KW@[13; 18) WHITESPACE@[18; 22) WHERE_PRED@[22; 44) - FOR_KW@[22; 25) - TYPE_PARAM_LIST@[25; 29) - L_ANGLE@[25; 26) - LIFETIME_PARAM@[26; 28) - LIFETIME@[26; 28) "'a" - R_ANGLE@[28; 29) - WHITESPACE@[29; 30) - PATH_TYPE@[30; 31) - PATH@[30; 31) - PATH_SEGMENT@[30; 31) - NAME_REF@[30; 31) - IDENT@[30; 31) "F" + FOR_TYPE@[22; 31) + FOR_KW@[22; 25) + TYPE_PARAM_LIST@[25; 29) + L_ANGLE@[25; 26) + LIFETIME_PARAM@[26; 28) + LIFETIME@[26; 28) "'a" + R_ANGLE@[28; 29) + WHITESPACE@[29; 30) + PATH_TYPE@[30; 31) + PATH@[30; 31) + PATH_SEGMENT@[30; 31) + NAME_REF@[30; 31) + IDENT@[30; 31) "F" COLON@[31; 32) WHITESPACE@[32; 33) PATH_TYPE@[33; 44) diff --git a/crates/ra_syntax/tests/data/parser/ok/0038_where_pred_type.rs b/crates/ra_syntax/tests/data/parser/ok/0038_where_pred_type.rs new file mode 100644 index 000000000..8bfc341a5 --- /dev/null +++ b/crates/ra_syntax/tests/data/parser/ok/0038_where_pred_type.rs @@ -0,0 +1 @@ +fn test() where (u64, u64): Foo {} \ No newline at end of file diff --git a/crates/ra_syntax/tests/data/parser/ok/0038_where_pred_type.txt b/crates/ra_syntax/tests/data/parser/ok/0038_where_pred_type.txt new file mode 100644 index 000000000..4842e9b90 --- /dev/null +++ b/crates/ra_syntax/tests/data/parser/ok/0038_where_pred_type.txt @@ -0,0 +1,40 @@ +SOURCE_FILE@[0; 34) + FN_DEF@[0; 34) + FN_KW@[0; 2) + WHITESPACE@[2; 3) + NAME@[3; 7) + IDENT@[3; 7) "test" + PARAM_LIST@[7; 9) + L_PAREN@[7; 8) + R_PAREN@[8; 9) + WHITESPACE@[9; 10) + WHERE_CLAUSE@[10; 31) + WHERE_KW@[10; 15) + WHITESPACE@[15; 16) + WHERE_PRED@[16; 31) + TUPLE_TYPE@[16; 26) + L_PAREN@[16; 17) + PATH_TYPE@[17; 20) + PATH@[17; 20) + PATH_SEGMENT@[17; 20) + NAME_REF@[17; 20) + IDENT@[17; 20) "u64" + COMMA@[20; 21) + WHITESPACE@[21; 22) + PATH_TYPE@[22; 25) + PATH@[22; 25) + PATH_SEGMENT@[22; 25) + NAME_REF@[22; 25) + IDENT@[22; 25) "u64" + R_PAREN@[25; 26) + COLON@[26; 27) + WHITESPACE@[27; 28) + PATH_TYPE@[28; 31) + PATH@[28; 31) + PATH_SEGMENT@[28; 31) + NAME_REF@[28; 31) + IDENT@[28; 31) "Foo" + WHITESPACE@[31; 32) + BLOCK@[32; 34) + L_CURLY@[32; 33) + R_CURLY@[33; 34) -- cgit v1.2.3 From 9f3d133813e519ea769c23565843587dea8d55b2 Mon Sep 17 00:00:00 2001 From: Erlend Tobiassen Date: Tue, 22 Jan 2019 14:36:57 +0100 Subject: Prefer TYPE_FIRST --- crates/ra_syntax/src/grammar/types.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/ra_syntax/src/grammar/types.rs b/crates/ra_syntax/src/grammar/types.rs index 83a54c190..c626abcfd 100644 --- a/crates/ra_syntax/src/grammar/types.rs +++ b/crates/ra_syntax/src/grammar/types.rs @@ -37,10 +37,10 @@ fn type_with_bounds_cond(p: &mut Parser, allow_bounds: bool) { } pub(super) fn is_type_start(p: &mut Parser) -> bool { - match p.current() { - L_PAREN | EXCL | STAR | L_BRACK | AMP | UNDERSCORE | FN_KW | FOR_KW | IMPL_KW | DYN_KW - | L_ANGLE => true, - _ => paths::is_path_start(p), + if TYPE_FIRST.contains(p.current()) { + true + } else { + paths::is_path_start(p) } } -- cgit v1.2.3 From 84f888e93ddfcaa573f65ddf49180a4665f14b50 Mon Sep 17 00:00:00 2001 From: Erlend Tobiassen Date: Tue, 22 Jan 2019 14:46:06 +0100 Subject: No need for is_type_start --- crates/ra_syntax/src/grammar/type_params.rs | 2 +- crates/ra_syntax/src/grammar/types.rs | 8 -------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/crates/ra_syntax/src/grammar/type_params.rs b/crates/ra_syntax/src/grammar/type_params.rs index 369125b39..1ec813b3e 100644 --- a/crates/ra_syntax/src/grammar/type_params.rs +++ b/crates/ra_syntax/src/grammar/type_params.rs @@ -126,7 +126,7 @@ fn is_where_predicate(p: &mut Parser) -> bool { match p.current() { LIFETIME => true, IMPL_KW => false, - _ => types::is_type_start(p), + token => types::TYPE_FIRST.contains(token), } } diff --git a/crates/ra_syntax/src/grammar/types.rs b/crates/ra_syntax/src/grammar/types.rs index c626abcfd..21d89d83b 100644 --- a/crates/ra_syntax/src/grammar/types.rs +++ b/crates/ra_syntax/src/grammar/types.rs @@ -36,14 +36,6 @@ fn type_with_bounds_cond(p: &mut Parser, allow_bounds: bool) { } } -pub(super) fn is_type_start(p: &mut Parser) -> bool { - if TYPE_FIRST.contains(p.current()) { - true - } else { - paths::is_path_start(p) - } -} - pub(super) fn ascription(p: &mut Parser) { p.expect(COLON); type_(p) -- cgit v1.2.3