diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-01-22 13:49:33 +0000 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-01-22 13:49:33 +0000 |
commit | 9e0abfc0c9b9d36c45c9d8567c632c0167b31084 (patch) | |
tree | dca47e7881e8a19507e6effb7642109b2e0be992 /crates/ra_syntax/src/grammar | |
parent | e396cb3548c8a36ba505cc08248333c225e56d2a (diff) | |
parent | 84f888e93ddfcaa573f65ddf49180a4665f14b50 (diff) |
Merge #592
592: Allow types to the left of `:` in where predicates r=matklad a=regiontog
Adresses #584
Co-authored-by: Erlend Tobiassen <[email protected]>
Diffstat (limited to 'crates/ra_syntax/src/grammar')
-rw-r--r-- | crates/ra_syntax/src/grammar/type_params.rs | 45 |
1 files changed, 28 insertions, 17 deletions
diff --git a/crates/ra_syntax/src/grammar/type_params.rs b/crates/ra_syntax/src/grammar/type_params.rs index 7db25beba..1ec813b3e 100644 --- a/crates/ra_syntax/src/grammar/type_params.rs +++ b/crates/ra_syntax/src/grammar/type_params.rs | |||
@@ -104,22 +104,36 @@ pub(super) fn opt_where_clause(p: &mut Parser) { | |||
104 | } | 104 | } |
105 | let m = p.start(); | 105 | let m = p.start(); |
106 | p.bump(); | 106 | p.bump(); |
107 | loop { | 107 | |
108 | if !(paths::is_path_start(p) | 108 | while is_where_predicate(p) { |
109 | || p.current() == LIFETIME | 109 | where_predicate(p); |
110 | || p.current() == FOR_KW | 110 | |
111 | || p.current() == L_ANGLE) | 111 | let comma = p.eat(COMMA); |
112 | { | 112 | |
113 | if is_where_clause_end(p) { | ||
113 | break; | 114 | break; |
114 | } | 115 | } |
115 | where_predicate(p); | 116 | |
116 | if p.current() != L_CURLY && p.current() != SEMI && p.current() != EQ { | 117 | if !comma { |
117 | p.expect(COMMA); | 118 | p.error("expected comma"); |
118 | } | 119 | } |
119 | } | 120 | } |
121 | |||
120 | m.complete(p, WHERE_CLAUSE); | 122 | m.complete(p, WHERE_CLAUSE); |
121 | } | 123 | } |
122 | 124 | ||
125 | fn is_where_predicate(p: &mut Parser) -> bool { | ||
126 | match p.current() { | ||
127 | LIFETIME => true, | ||
128 | IMPL_KW => false, | ||
129 | token => types::TYPE_FIRST.contains(token), | ||
130 | } | ||
131 | } | ||
132 | |||
133 | fn is_where_clause_end(p: &mut Parser) -> bool { | ||
134 | p.current() == L_CURLY || p.current() == SEMI || p.current() == EQ | ||
135 | } | ||
136 | |||
123 | fn where_predicate(p: &mut Parser) { | 137 | fn where_predicate(p: &mut Parser) { |
124 | let m = p.start(); | 138 | let m = p.start(); |
125 | match p.current() { | 139 | match p.current() { |
@@ -131,20 +145,17 @@ fn where_predicate(p: &mut Parser) { | |||
131 | p.error("expected colon"); | 145 | p.error("expected colon"); |
132 | } | 146 | } |
133 | } | 147 | } |
148 | IMPL_KW => { | ||
149 | p.error("expected lifetime or type"); | ||
150 | } | ||
134 | _ => { | 151 | _ => { |
135 | // test where_pred_for | 152 | // test where_pred_for |
136 | // fn test<F>() | 153 | // fn test<F>() |
137 | // where | 154 | // where |
138 | // for<'a> F: Fn(&'a str) | 155 | // for<'a> F: Fn(&'a str) |
139 | // { } | 156 | // { } |
140 | if p.at(FOR_KW) { | 157 | types::type_(p); |
141 | types::for_binder(p); | 158 | |
142 | } | ||
143 | if paths::is_path_start(p) || p.at(L_ANGLE) { | ||
144 | types::path_type_(p, false); | ||
145 | } else { | ||
146 | p.error("expected a type"); | ||
147 | } | ||
148 | if p.at(COLON) { | 159 | if p.at(COLON) { |
149 | bounds(p); | 160 | bounds(p); |
150 | } else { | 161 | } else { |