From 2b22f5fb4398378d999db98ea270ceb415dfff22 Mon Sep 17 00:00:00 2001
From: Erlend Tobiassen <erlend.tobiassen@gmail.com>
Date: Tue, 22 Jan 2019 13:17:10 +0100
Subject: [PATCH] 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 f33ec10f538..a7eacf97af0 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 21d89d83bbd..83a54c190f6 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)