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

Issue:
Got expected expression in valid function call
The [following](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=b1ae23cc8a80a49157ef2343c3b5aaeb) (valid) code results in errors in the [syntax tree](https://gist.github.com/regiontog/458888f109d188e983ae0964cf3c1a30#file-gistfile1-txt-L102).

```rust
struct Foo;

impl Foo {
    fn bar() -> bool {
        unimplemented!()
    }
}

fn baz(_: bool) {}

fn main() {
    baz(<Foo>::bar())
}
```

Pull request:
Support universal function call syntax in function calls
Fix #596

Patch:
diff --git a/crates/ra_syntax/src/grammar/expressions.rs b/crates/ra_syntax/src/grammar/expressions.rs
index 2236555e0f..7ee32fa7c2 100644
--- a/crates/ra_syntax/src/grammar/expressions.rs
+++ b/crates/ra_syntax/src/grammar/expressions.rs
@@ -305,6 +305,8 @@ fn postfix_expr(
 // fn foo() {
 //     let _ = f();
 //     let _ = f()(1)(1, 2,);
+//     let _ = f(<Foo>::func());
+//     f(<Foo as Trait>::func());
 // }
 fn call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
     assert!(p.at(L_PAREN));
diff --git a/crates/ra_syntax/src/grammar/expressions/atom.rs b/crates/ra_syntax/src/grammar/expressions/atom.rs
index 167a76551d..6d6d89f707 100644
--- a/crates/ra_syntax/src/grammar/expressions/atom.rs
+++ b/crates/ra_syntax/src/grammar/expressions/atom.rs
@@ -36,26 +36,22 @@ pub(crate) fn literal(p: &mut Parser) -> Option<CompletedMarker> {
 }
 
 // E.g. for after the break in `if break {}`, this should not match
-pub(super) const ATOM_EXPR_FIRST: TokenSet = LITERAL_FIRST.union(token_set![
-    L_PAREN,
-    L_CURLY,
-    L_BRACK,
-    PIPE,
-    MOVE_KW,
-    IF_KW,
-    WHILE_KW,
-    MATCH_KW,
-    UNSAFE_KW,
-    RETURN_KW,
-    IDENT,
-    SELF_KW,
-    SUPER_KW,
-    CRATE_KW,
-    COLONCOLON,
-    BREAK_KW,
-    CONTINUE_KW,
-    LIFETIME,
-]);
+pub(super) const ATOM_EXPR_FIRST: TokenSet =
+    LITERAL_FIRST.union(paths::PATH_FIRST).union(token_set![
+        L_PAREN,
+        L_CURLY,
+        L_BRACK,
+        PIPE,
+        MOVE_KW,
+        IF_KW,
+        WHILE_KW,
+        MATCH_KW,
+        UNSAFE_KW,
+        RETURN_KW,
+        BREAK_KW,
+        CONTINUE_KW,
+        LIFETIME,
+    ]);
 
 const EXPR_RECOVERY_SET: TokenSet = token_set![LET_KW];
 


Test patch:
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0042_call_expr.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0042_call_expr.rs
index 0c9a20718a..ffbf46d6d1 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0042_call_expr.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0042_call_expr.rs
@@ -1,4 +1,6 @@
 fn foo() {
     let _ = f();
     let _ = f()(1)(1, 2,);
+    let _ = f(<Foo>::func());
+    f(<Foo as Trait>::func());
 }
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0042_call_expr.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0042_call_expr.txt
index 6364dc73c3..0ddf393f23 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0042_call_expr.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0042_call_expr.txt
@@ -1,5 +1,5 @@
-SOURCE_FILE@[0; 57)
-  FN_DEF@[0; 56)
+SOURCE_FILE@[0; 118)
+  FN_DEF@[0; 117)
     FN_KW@[0; 2)
     WHITESPACE@[2; 3)
     NAME@[3; 6)
@@ -8,7 +8,7 @@ SOURCE_FILE@[0; 57)
       L_PAREN@[6; 7)
       R_PAREN@[7; 8)
     WHITESPACE@[8; 9)
-    BLOCK@[9; 56)
+    BLOCK@[9; 117)
       L_CURLY@[9; 10)
       WHITESPACE@[10; 15)
       LET_STMT@[15; 27)
@@ -65,6 +65,83 @@ SOURCE_FILE@[0; 57)
             COMMA@[51; 52)
             R_PAREN@[52; 53)
         SEMI@[53; 54)
-      WHITESPACE@[54; 55)
-      R_CURLY@[55; 56)
-  WHITESPACE@[56; 57)
+      WHITESPACE@[54; 59)
+      LET_STMT@[59; 84)
+        LET_KW@[59; 62)
+        WHITESPACE@[62; 63)
+        PLACEHOLDER_PAT@[63; 64)
+          UNDERSCORE@[63; 64)
+        WHITESPACE@[64; 65)
+        EQ@[65; 66)
+        WHITESPACE@[66; 67)
+        CALL_EXPR@[67; 83)
+          PATH_EXPR@[67; 68)
+            PATH@[67; 68)
+              PATH_SEGMENT@[67; 68)
+                NAME_REF@[67; 68)
+                  IDENT@[67; 68) "f"
+          ARG_LIST@[68; 83)
+            L_PAREN@[68; 69)
+            CALL_EXPR@[69; 82)
+              PATH_EXPR@[69; 80)
+                PATH@[69; 80)
+                  PATH@[69; 74)
+                    PATH_SEGMENT@[69; 74)
+                      L_ANGLE@[69; 70)
+                      PATH_TYPE@[70; 73)
+                        PATH@[70; 73)
+                          PATH_SEGMENT@[70; 73)
+                            NAME_REF@[70; 73)
+                              IDENT@[70; 73) "Foo"
+                      R_ANGLE@[73; 74)
+                  COLONCOLON@[74; 76)
+                  PATH_SEGMENT@[76; 80)
+                    NAME_REF@[76; 80)
+                      IDENT@[76; 80) "func"
+              ARG_LIST@[80; 82)
+                L_PAREN@[80; 81)
+                R_PAREN@[81; 82)
+            R_PAREN@[82; 83)
+        SEMI@[83; 84)
+      WHITESPACE@[84; 89)
+      EXPR_STMT@[89; 115)
+        CALL_EXPR@[89; 114)
+          PATH_EXPR@[89; 90)
+            PATH@[89; 90)
+              PATH_SEGMENT@[89; 90)
+                NAME_REF@[89; 90)
+                  IDENT@[89; 90) "f"
+          ARG_LIST@[90; 114)
+            L_PAREN@[90; 91)
+            CALL_EXPR@[91; 113)
+              PATH_EXPR@[91; 111)
+                PATH@[91; 111)
+                  PATH@[91; 105)
+                    PATH_SEGMENT@[91; 105)
+                      L_ANGLE@[91; 92)
+                      PATH_TYPE@[92; 95)
+                        PATH@[92; 95)
+                          PATH_SEGMENT@[92; 95)
+                            NAME_REF@[92; 95)
+                              IDENT@[92; 95) "Foo"
+                      WHITESPACE@[95; 96)
+                      AS_KW@[96; 98)
+                      WHITESPACE@[98; 99)
+                      PATH_TYPE@[99; 104)
+                        PATH@[99; 104)
+                          PATH_SEGMENT@[99; 104)
+                            NAME_REF@[99; 104)
+                              IDENT@[99; 104) "Trait"
+                      R_ANGLE@[104; 105)
+                  COLONCOLON@[105; 107)
+                  PATH_SEGMENT@[107; 111)
+                    NAME_REF@[107; 111)
+                      IDENT@[107; 111) "func"
+              ARG_LIST@[111; 113)
+                L_PAREN@[111; 112)
+                R_PAREN@[112; 113)
+            R_PAREN@[113; 114)
+        SEMI@[114; 115)
+      WHITESPACE@[115; 116)
+      R_CURLY@[116; 117)
+  WHITESPACE@[117; 118)
diff --git a/crates/ra_syntax/tests/data/parser/ok/0042_ufcs_call_list.rs b/crates/ra_syntax/tests/data/parser/ok/0042_ufcs_call_list.rs
new file mode 100644
index 0000000000..6c02e65ed7
--- /dev/null
+++ b/crates/ra_syntax/tests/data/parser/ok/0042_ufcs_call_list.rs
@@ -0,0 +1,15 @@
+// https://github.com/rust-analyzer/rust-analyzer/issues/596
+
+struct Foo;
+
+impl Foo {
+    fn bar() -> bool {
+        unimplemented!()
+    }
+}
+
+fn baz(_: bool) {}
+
+fn main() {
+    baz(<Foo>::bar())
+}
diff --git a/crates/ra_syntax/tests/data/parser/ok/0042_ufcs_call_list.txt b/crates/ra_syntax/tests/data/parser/ok/0042_ufcs_call_list.txt
new file mode 100644
index 0000000000..d1d890e501
--- /dev/null
+++ b/crates/ra_syntax/tests/data/parser/ok/0042_ufcs_call_list.txt
@@ -0,0 +1,123 @@
+SOURCE_FILE@[0; 199)
+  COMMENT@[0; 60)
+  WHITESPACE@[60; 62)
+  STRUCT_DEF@[62; 73)
+    STRUCT_KW@[62; 68)
+    WHITESPACE@[68; 69)
+    NAME@[69; 72)
+      IDENT@[69; 72) "Foo"
+    SEMI@[72; 73)
+  WHITESPACE@[73; 75)
+  IMPL_BLOCK@[75; 141)
+    IMPL_KW@[75; 79)
+    WHITESPACE@[79; 80)
+    PATH_TYPE@[80; 83)
+      PATH@[80; 83)
+        PATH_SEGMENT@[80; 83)
+          NAME_REF@[80; 83)
+            IDENT@[80; 83) "Foo"
+    WHITESPACE@[83; 84)
+    ITEM_LIST@[84; 141)
+      L_CURLY@[84; 85)
+      WHITESPACE@[85; 90)
+      FN_DEF@[90; 139)
+        FN_KW@[90; 92)
+        WHITESPACE@[92; 93)
+        NAME@[93; 96)
+          IDENT@[93; 96) "bar"
+        PARAM_LIST@[96; 98)
+          L_PAREN@[96; 97)
+          R_PAREN@[97; 98)
+        WHITESPACE@[98; 99)
+        RET_TYPE@[99; 106)
+          THIN_ARROW@[99; 101)
+          WHITESPACE@[101; 102)
+          PATH_TYPE@[102; 106)
+            PATH@[102; 106)
+              PATH_SEGMENT@[102; 106)
+                NAME_REF@[102; 106)
+                  IDENT@[102; 106) "bool"
+        WHITESPACE@[106; 107)
+        BLOCK@[107; 139)
+          L_CURLY@[107; 108)
+          WHITESPACE@[108; 117)
+          MACRO_CALL@[117; 133)
+            PATH@[117; 130)
+              PATH_SEGMENT@[117; 130)
+                NAME_REF@[117; 130)
+                  IDENT@[117; 130) "unimplemented"
+            EXCL@[130; 131)
+            TOKEN_TREE@[131; 133)
+              L_PAREN@[131; 132)
+              R_PAREN@[132; 133)
+          WHITESPACE@[133; 138)
+          R_CURLY@[138; 139)
+      WHITESPACE@[139; 140)
+      R_CURLY@[140; 141)
+  WHITESPACE@[141; 143)
+  FN_DEF@[143; 161)
+    FN_KW@[143; 145)
+    WHITESPACE@[145; 146)
+    NAME@[146; 149)
+      IDENT@[146; 149) "baz"
+    PARAM_LIST@[149; 158)
+      L_PAREN@[149; 150)
+      PARAM@[150; 157)
+        PLACEHOLDER_PAT@[150; 151)
+          UNDERSCORE@[150; 151)
+        COLON@[151; 152)
+        WHITESPACE@[152; 153)
+        PATH_TYPE@[153; 157)
+          PATH@[153; 157)
+            PATH_SEGMENT@[153; 157)
+              NAME_REF@[153; 157)
+                IDENT@[153; 157) "bool"
+      R_PAREN@[157; 158)
+    WHITESPACE@[158; 159)
+    BLOCK@[159; 161)
+      L_CURLY@[159; 160)
+      R_CURLY@[160; 161)
+  WHITESPACE@[161; 163)
+  FN_DEF@[163; 198)
+    FN_KW@[163; 165)
+    WHITESPACE@[165; 166)
+    NAME@[166; 170)
+      IDENT@[166; 170) "main"
+    PARAM_LIST@[170; 172)
+      L_PAREN@[170; 171)
+      R_PAREN@[171; 172)
+    WHITESPACE@[172; 173)
+    BLOCK@[173; 198)
+      L_CURLY@[173; 174)
+      WHITESPACE@[174; 179)
+      CALL_EXPR@[179; 196)
+        PATH_EXPR@[179; 182)
+          PATH@[179; 182)
+            PATH_SEGMENT@[179; 182)
+              NAME_REF@[179; 182)
+                IDENT@[179; 182) "baz"
+        ARG_LIST@[182; 196)
+          L_PAREN@[182; 183)
+          CALL_EXPR@[183; 195)
+            PATH_EXPR@[183; 193)
+              PATH@[183; 193)
+                PATH@[183; 188)
+                  PATH_SEGMENT@[183; 188)
+                    L_ANGLE@[183; 184)
+                    PATH_TYPE@[184; 187)
+                      PATH@[184; 187)
+                        PATH_SEGMENT@[184; 187)
+                          NAME_REF@[184; 187)
+                            IDENT@[184; 187) "Foo"
+                    R_ANGLE@[187; 188)
+                COLONCOLON@[188; 190)
+                PATH_SEGMENT@[190; 193)
+                  NAME_REF@[190; 193)
+                    IDENT@[190; 193) "bar"
+            ARG_LIST@[193; 195)
+              L_PAREN@[193; 194)
+              R_PAREN@[194; 195)
+          R_PAREN@[195; 196)
+      WHITESPACE@[196; 197)
+      R_CURLY@[197; 198)
+  WHITESPACE@[198; 199)