Repository: rust-analyzer/rust-analyzer (rust)

Issue:
ra_syntax: doesn't parse correctly fully qualified syntax for an assoc type
Example:
```rust
pub fn foo<S: Iterator>() -> String
where
    <S as Iterator>::Item: Eq,
{
    "".to_owned()
}
```
generates lot's of errors:
```
Syntax Error: expected a block
Syntax Error: expected an item
Syntax Error: expected EXCL
...
```

Pull request description:
Fix where clauses using fully qualified path syntax
Fixes #311.

Patch:
diff --git a/crates/ra_syntax/src/grammar/type_params.rs b/crates/ra_syntax/src/grammar/type_params.rs
index 863f8e00c6..7db25bebad 100644
--- a/crates/ra_syntax/src/grammar/type_params.rs
+++ b/crates/ra_syntax/src/grammar/type_params.rs
@@ -96,6 +96,7 @@ pub(super) fn bounds_without_colon(p: &mut Parser) {
 //    'a: 'b + 'c,
 //    T: Clone + Copy + 'static,
 //    Iterator::Item: 'a,
+//    <T as Iterator>::Item: 'a
 // {}
 pub(super) fn opt_where_clause(p: &mut Parser) {
     if !p.at(WHERE_KW) {
@@ -104,7 +105,11 @@ 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) {
+        if !(paths::is_path_start(p)
+            || p.current() == LIFETIME
+            || p.current() == FOR_KW
+            || p.current() == L_ANGLE)
+        {
             break;
         }
         where_predicate(p);


Test patch:
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0056_where_clause.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0056_where_clause.rs
index 592a005f9e..19d7e571b0 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0056_where_clause.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0056_where_clause.rs
@@ -3,4 +3,5 @@ where
    'a: 'b + 'c,
    T: Clone + Copy + 'static,
    Iterator::Item: 'a,
+   <T as Iterator>::Item: 'a
 {}
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0056_where_clause.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0056_where_clause.txt
index 54c3d64f1e..68485dc0ba 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0056_where_clause.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0056_where_clause.txt
@@ -1,5 +1,5 @@
-SOURCE_FILE@[0; 87)
-  FN_DEF@[0; 86)
+SOURCE_FILE@[0; 116)
+  FN_DEF@[0; 115)
     FN_KW@[0; 2)
     WHITESPACE@[2; 3)
     NAME@[3; 6)
@@ -8,7 +8,7 @@ SOURCE_FILE@[0; 87)
       L_PAREN@[6; 7)
       R_PAREN@[7; 8)
     WHITESPACE@[8; 9)
-    WHERE_CLAUSE@[9; 83)
+    WHERE_CLAUSE@[9; 112)
       WHERE_KW@[9; 14)
       WHITESPACE@[14; 18)
       WHERE_PRED@[18; 29)
@@ -64,8 +64,36 @@ SOURCE_FILE@[0; 87)
         WHITESPACE@[79; 80)
         LIFETIME@[80; 82) "'a"
       COMMA@[82; 83)
-    WHITESPACE@[83; 84)
-    BLOCK@[84; 86)
-      L_CURLY@[84; 85)
-      R_CURLY@[85; 86)
-  WHITESPACE@[86; 87)
+      WHITESPACE@[83; 87)
+      WHERE_PRED@[87; 112)
+        PATH_TYPE@[87; 108)
+          PATH@[87; 108)
+            PATH@[87; 102)
+              PATH_SEGMENT@[87; 102)
+                L_ANGLE@[87; 88)
+                PATH_TYPE@[88; 89)
+                  PATH@[88; 89)
+                    PATH_SEGMENT@[88; 89)
+                      NAME_REF@[88; 89)
+                        IDENT@[88; 89) "T"
+                WHITESPACE@[89; 90)
+                AS_KW@[90; 92)
+                WHITESPACE@[92; 93)
+                PATH_TYPE@[93; 101)
+                  PATH@[93; 101)
+                    PATH_SEGMENT@[93; 101)
+                      NAME_REF@[93; 101)
+                        IDENT@[93; 101) "Iterator"
+                R_ANGLE@[101; 102)
+            COLONCOLON@[102; 104)
+            PATH_SEGMENT@[104; 108)
+              NAME_REF@[104; 108)
+                IDENT@[104; 108) "Item"
+        COLON@[108; 109)
+        WHITESPACE@[109; 110)
+        LIFETIME@[110; 112) "'a"
+    WHITESPACE@[112; 113)
+    BLOCK@[113; 115)
+      L_CURLY@[113; 114)
+      R_CURLY@[114; 115)
+  WHITESPACE@[115; 116)
diff --git a/crates/ra_syntax/tests/data/parser/ok/0036_fully_qualified.rs b/crates/ra_syntax/tests/data/parser/ok/0036_fully_qualified.rs
new file mode 100644
index 0000000000..6da27933ec
--- /dev/null
+++ b/crates/ra_syntax/tests/data/parser/ok/0036_fully_qualified.rs
@@ -0,0 +1,8 @@
+// https://github.com/rust-analyzer/rust-analyzer/issues/311
+
+pub fn foo<S: Iterator>() -> String
+where
+    <S as Iterator>::Item: Eq,
+{
+    "".to_owned()
+}
diff --git a/crates/ra_syntax/tests/data/parser/ok/0036_fully_qualified.txt b/crates/ra_syntax/tests/data/parser/ok/0036_fully_qualified.txt
new file mode 100644
index 0000000000..208e5e51c4
--- /dev/null
+++ b/crates/ra_syntax/tests/data/parser/ok/0036_fully_qualified.txt
@@ -0,0 +1,88 @@
+SOURCE_FILE@[0; 157)
+  COMMENT@[0; 60)
+  WHITESPACE@[60; 62)
+  FN_DEF@[62; 156)
+    VISIBILITY@[62; 65)
+      PUB_KW@[62; 65)
+    WHITESPACE@[65; 66)
+    FN_KW@[66; 68)
+    WHITESPACE@[68; 69)
+    NAME@[69; 72)
+      IDENT@[69; 72) "foo"
+    TYPE_PARAM_LIST@[72; 85)
+      L_ANGLE@[72; 73)
+      TYPE_PARAM@[73; 84)
+        NAME@[73; 74)
+          IDENT@[73; 74) "S"
+        COLON@[74; 75)
+        WHITESPACE@[75; 76)
+        PATH_TYPE@[76; 84)
+          PATH@[76; 84)
+            PATH_SEGMENT@[76; 84)
+              NAME_REF@[76; 84)
+                IDENT@[76; 84) "Iterator"
+      R_ANGLE@[84; 85)
+    PARAM_LIST@[85; 87)
+      L_PAREN@[85; 86)
+      R_PAREN@[86; 87)
+    WHITESPACE@[87; 88)
+    RET_TYPE@[88; 97)
+      THIN_ARROW@[88; 90)
+      WHITESPACE@[90; 91)
+      PATH_TYPE@[91; 97)
+        PATH@[91; 97)
+          PATH_SEGMENT@[91; 97)
+            NAME_REF@[91; 97)
+              IDENT@[91; 97) "String"
+    WHITESPACE@[97; 98)
+    WHERE_CLAUSE@[98; 134)
+      WHERE_KW@[98; 103)
+      WHITESPACE@[103; 108)
+      WHERE_PRED@[108; 133)
+        PATH_TYPE@[108; 129)
+          PATH@[108; 129)
+            PATH@[108; 123)
+              PATH_SEGMENT@[108; 123)
+                L_ANGLE@[108; 109)
+                PATH_TYPE@[109; 110)
+                  PATH@[109; 110)
+                    PATH_SEGMENT@[109; 110)
+                      NAME_REF@[109; 110)
+                        IDENT@[109; 110) "S"
+                WHITESPACE@[110; 111)
+                AS_KW@[111; 113)
+                WHITESPACE@[113; 114)
+                PATH_TYPE@[114; 122)
+                  PATH@[114; 122)
+                    PATH_SEGMENT@[114; 122)
+                      NAME_REF@[114; 122)
+                        IDENT@[114; 122) "Iterator"
+                R_ANGLE@[122; 123)
+            COLONCOLON@[123; 125)
+            PATH_SEGMENT@[125; 129)
+              NAME_REF@[125; 129)
+                IDENT@[125; 129) "Item"
+        COLON@[129; 130)
+        WHITESPACE@[130; 131)
+        PATH_TYPE@[131; 133)
+          PATH@[131; 133)
+            PATH_SEGMENT@[131; 133)
+              NAME_REF@[131; 133)
+                IDENT@[131; 133) "Eq"
+      COMMA@[133; 134)
+    WHITESPACE@[134; 135)
+    BLOCK@[135; 156)
+      L_CURLY@[135; 136)
+      WHITESPACE@[136; 141)
+      METHOD_CALL_EXPR@[141; 154)
+        LITERAL@[141; 143)
+          STRING@[141; 143)
+        DOT@[143; 144)
+        NAME_REF@[144; 152)
+          IDENT@[144; 152) "to_owned"
+        ARG_LIST@[152; 154)
+          L_PAREN@[152; 153)
+          R_PAREN@[153; 154)
+      WHITESPACE@[154; 155)
+      R_CURLY@[155; 156)
+  WHITESPACE@[156; 157)