diff options
6 files changed, 112 insertions, 19 deletions
diff --git a/crates/libsyntax2/src/grammar/expressions/atom.rs b/crates/libsyntax2/src/grammar/expressions/atom.rs index e62b16654..4f03862b1 100644 --- a/crates/libsyntax2/src/grammar/expressions/atom.rs +++ b/crates/libsyntax2/src/grammar/expressions/atom.rs | |||
@@ -38,7 +38,7 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<CompletedMark | |||
38 | Some(m) => return Some(m), | 38 | Some(m) => return Some(m), |
39 | None => (), | 39 | None => (), |
40 | } | 40 | } |
41 | if paths::is_path_start(p) { | 41 | if paths::is_path_start(p) || p.at(L_ANGLE) { |
42 | return Some(path_expr(p, r)); | 42 | return Some(path_expr(p, r)); |
43 | } | 43 | } |
44 | let la = p.nth(1); | 44 | let la = p.nth(1); |
diff --git a/crates/libsyntax2/src/grammar/expressions/mod.rs b/crates/libsyntax2/src/grammar/expressions/mod.rs index 30a78d0c4..e56f3d30e 100644 --- a/crates/libsyntax2/src/grammar/expressions/mod.rs +++ b/crates/libsyntax2/src/grammar/expressions/mod.rs | |||
@@ -332,7 +332,7 @@ fn arg_list(p: &mut Parser) { | |||
332 | // let _ = format!(); | 332 | // let _ = format!(); |
333 | // } | 333 | // } |
334 | fn path_expr(p: &mut Parser, r: Restrictions) -> CompletedMarker { | 334 | fn path_expr(p: &mut Parser, r: Restrictions) -> CompletedMarker { |
335 | assert!(paths::is_path_start(p)); | 335 | assert!(paths::is_path_start(p) || p.at(L_ANGLE)); |
336 | let m = p.start(); | 336 | let m = p.start(); |
337 | paths::expr_path(p); | 337 | paths::expr_path(p); |
338 | match p.current() { | 338 | match p.current() { |
diff --git a/crates/libsyntax2/src/grammar/paths.rs b/crates/libsyntax2/src/grammar/paths.rs index aa5ecf4b8..97ab1880b 100644 --- a/crates/libsyntax2/src/grammar/paths.rs +++ b/crates/libsyntax2/src/grammar/paths.rs | |||
@@ -27,9 +27,6 @@ enum Mode { | |||
27 | } | 27 | } |
28 | 28 | ||
29 | fn path(p: &mut Parser, mode: Mode) { | 29 | fn path(p: &mut Parser, mode: Mode) { |
30 | if !is_path_start(p) { | ||
31 | return; | ||
32 | } | ||
33 | let path = p.start(); | 30 | let path = p.start(); |
34 | path_segment(p, mode, true); | 31 | path_segment(p, mode, true); |
35 | let mut qual = path.complete(p, PATH); | 32 | let mut qual = path.complete(p, PATH); |
@@ -51,21 +48,36 @@ fn path(p: &mut Parser, mode: Mode) { | |||
51 | } | 48 | } |
52 | 49 | ||
53 | fn path_segment(p: &mut Parser, mode: Mode, first: bool) { | 50 | fn path_segment(p: &mut Parser, mode: Mode, first: bool) { |
54 | let segment = p.start(); | 51 | let m = p.start(); |
55 | if first { | 52 | // test qual_paths |
56 | p.eat(COLONCOLON); | 53 | // type X = <A as B>::Output; |
57 | } | 54 | // fn foo() { <usize as Default>::default(); } |
58 | match p.current() { | 55 | if first && p.eat(L_ANGLE) { |
59 | IDENT => { | 56 | types::type_(p); |
60 | name_ref(p); | 57 | if p.eat(AS_KW) { |
61 | path_generic_args(p, mode); | 58 | if is_path_start(p) { |
59 | types::path_type(p); | ||
60 | } else { | ||
61 | p.error("expected a trait"); | ||
62 | } | ||
62 | } | 63 | } |
63 | SELF_KW | SUPER_KW => p.bump(), | 64 | p.expect(R_ANGLE); |
64 | _ => { | 65 | } else { |
65 | p.err_and_bump("expected identifier"); | 66 | if first { |
67 | p.eat(COLONCOLON); | ||
66 | } | 68 | } |
67 | }; | 69 | match p.current() { |
68 | segment.complete(p, PATH_SEGMENT); | 70 | IDENT => { |
71 | name_ref(p); | ||
72 | path_generic_args(p, mode); | ||
73 | } | ||
74 | SELF_KW | SUPER_KW => p.bump(), | ||
75 | _ => { | ||
76 | p.err_and_bump("expected identifier"); | ||
77 | } | ||
78 | }; | ||
79 | } | ||
80 | m.complete(p, PATH_SEGMENT); | ||
69 | } | 81 | } |
70 | 82 | ||
71 | fn path_generic_args(p: &mut Parser, mode: Mode) { | 83 | fn path_generic_args(p: &mut Parser, mode: Mode) { |
diff --git a/crates/libsyntax2/src/grammar/types.rs b/crates/libsyntax2/src/grammar/types.rs index 88631fefe..f58b545c7 100644 --- a/crates/libsyntax2/src/grammar/types.rs +++ b/crates/libsyntax2/src/grammar/types.rs | |||
@@ -12,6 +12,7 @@ pub(super) fn type_(p: &mut Parser) { | |||
12 | FOR_KW => for_type(p), | 12 | FOR_KW => for_type(p), |
13 | IMPL_KW => impl_trait_type(p), | 13 | IMPL_KW => impl_trait_type(p), |
14 | DYN_KW => dyn_trait_type(p), | 14 | DYN_KW => dyn_trait_type(p), |
15 | L_ANGLE => path_type(p), | ||
15 | _ if paths::is_path_start(p) => path_type(p), | 16 | _ if paths::is_path_start(p) => path_type(p), |
16 | _ => { | 17 | _ => { |
17 | p.err_and_bump("expected type"); | 18 | p.err_and_bump("expected type"); |
@@ -214,7 +215,7 @@ fn dyn_trait_type(p: &mut Parser) { | |||
214 | // type C = self::Foo; | 215 | // type C = self::Foo; |
215 | // type D = super::Foo; | 216 | // type D = super::Foo; |
216 | pub(super) fn path_type(p: &mut Parser) { | 217 | pub(super) fn path_type(p: &mut Parser) { |
217 | assert!(paths::is_path_start(p)); | 218 | assert!(paths::is_path_start(p) || p.at(L_ANGLE)); |
218 | let m = p.start(); | 219 | let m = p.start(); |
219 | paths::type_path(p); | 220 | paths::type_path(p); |
220 | // test path_type_with_bounds | 221 | // test path_type_with_bounds |
diff --git a/crates/libsyntax2/tests/data/parser/inline/0101_qual_paths.rs b/crates/libsyntax2/tests/data/parser/inline/0101_qual_paths.rs new file mode 100644 index 000000000..d140692e2 --- /dev/null +++ b/crates/libsyntax2/tests/data/parser/inline/0101_qual_paths.rs | |||
@@ -0,0 +1,2 @@ | |||
1 | type X = <A as B>::Output; | ||
2 | fn foo() { <usize as Default>::default(); } | ||
diff --git a/crates/libsyntax2/tests/data/parser/inline/0101_qual_paths.txt b/crates/libsyntax2/tests/data/parser/inline/0101_qual_paths.txt new file mode 100644 index 000000000..58b545bdd --- /dev/null +++ b/crates/libsyntax2/tests/data/parser/inline/0101_qual_paths.txt | |||
@@ -0,0 +1,78 @@ | |||
1 | FILE@[0; 71) | ||
2 | TYPE_DEF@[0; 26) | ||
3 | TYPE_KW@[0; 4) | ||
4 | WHITESPACE@[4; 5) | ||
5 | NAME@[5; 6) | ||
6 | IDENT@[5; 6) "X" | ||
7 | WHITESPACE@[6; 7) | ||
8 | EQ@[7; 8) | ||
9 | WHITESPACE@[8; 9) | ||
10 | PATH_TYPE@[9; 25) | ||
11 | PATH@[9; 25) | ||
12 | PATH@[9; 17) | ||
13 | PATH_SEGMENT@[9; 17) | ||
14 | L_ANGLE@[9; 10) | ||
15 | PATH_TYPE@[10; 11) | ||
16 | PATH@[10; 11) | ||
17 | PATH_SEGMENT@[10; 11) | ||
18 | NAME_REF@[10; 11) | ||
19 | IDENT@[10; 11) "A" | ||
20 | WHITESPACE@[11; 12) | ||
21 | AS_KW@[12; 14) | ||
22 | WHITESPACE@[14; 15) | ||
23 | PATH_TYPE@[15; 16) | ||
24 | PATH@[15; 16) | ||
25 | PATH_SEGMENT@[15; 16) | ||
26 | NAME_REF@[15; 16) | ||
27 | IDENT@[15; 16) "B" | ||
28 | R_ANGLE@[16; 17) | ||
29 | COLONCOLON@[17; 19) | ||
30 | PATH_SEGMENT@[19; 25) | ||
31 | NAME_REF@[19; 25) | ||
32 | IDENT@[19; 25) "Output" | ||
33 | SEMI@[25; 26) | ||
34 | WHITESPACE@[26; 27) | ||
35 | FN_DEF@[27; 70) | ||
36 | FN_KW@[27; 29) | ||
37 | WHITESPACE@[29; 30) | ||
38 | NAME@[30; 33) | ||
39 | IDENT@[30; 33) "foo" | ||
40 | PARAM_LIST@[33; 35) | ||
41 | L_PAREN@[33; 34) | ||
42 | R_PAREN@[34; 35) | ||
43 | WHITESPACE@[35; 36) | ||
44 | BLOCK_EXPR@[36; 70) | ||
45 | L_CURLY@[36; 37) | ||
46 | WHITESPACE@[37; 38) | ||
47 | EXPR_STMT@[38; 68) | ||
48 | CALL_EXPR@[38; 67) | ||
49 | PATH_EXPR@[38; 65) | ||
50 | PATH@[38; 65) | ||
51 | PATH@[38; 56) | ||
52 | PATH_SEGMENT@[38; 56) | ||
53 | L_ANGLE@[38; 39) | ||
54 | PATH_TYPE@[39; 44) | ||
55 | PATH@[39; 44) | ||
56 | PATH_SEGMENT@[39; 44) | ||
57 | NAME_REF@[39; 44) | ||
58 | IDENT@[39; 44) "usize" | ||
59 | WHITESPACE@[44; 45) | ||
60 | AS_KW@[45; 47) | ||
61 | WHITESPACE@[47; 48) | ||
62 | PATH_TYPE@[48; 55) | ||
63 | PATH@[48; 55) | ||
64 | PATH_SEGMENT@[48; 55) | ||
65 | NAME_REF@[48; 55) | ||
66 | IDENT@[48; 55) "Default" | ||
67 | R_ANGLE@[55; 56) | ||
68 | COLONCOLON@[56; 58) | ||
69 | PATH_SEGMENT@[58; 65) | ||
70 | NAME_REF@[58; 65) | ||
71 | IDENT@[58; 65) "default" | ||
72 | ARG_LIST@[65; 67) | ||
73 | L_PAREN@[65; 66) | ||
74 | R_PAREN@[66; 67) | ||
75 | SEMI@[67; 68) | ||
76 | WHITESPACE@[68; 69) | ||
77 | R_CURLY@[69; 70) | ||
78 | WHITESPACE@[70; 71) | ||