diff options
Diffstat (limited to 'crates/ra_syntax/src/grammar/types.rs')
-rw-r--r-- | crates/ra_syntax/src/grammar/types.rs | 247 |
1 files changed, 247 insertions, 0 deletions
diff --git a/crates/ra_syntax/src/grammar/types.rs b/crates/ra_syntax/src/grammar/types.rs new file mode 100644 index 000000000..27e5b086e --- /dev/null +++ b/crates/ra_syntax/src/grammar/types.rs | |||
@@ -0,0 +1,247 @@ | |||
1 | use super::*; | ||
2 | |||
3 | pub(super) const TYPE_FIRST: TokenSet = | ||
4 | token_set_union![ | ||
5 | token_set![ | ||
6 | L_PAREN, EXCL, STAR, L_BRACK, AMP, UNDERSCORE, FN_KW, UNSAFE_KW, EXTERN_KW, FOR_KW, IMPL_KW, DYN_KW, L_ANGLE, | ||
7 | ], | ||
8 | paths::PATH_FIRST, | ||
9 | ]; | ||
10 | |||
11 | const TYPE_RECOVERY_SET: TokenSet = | ||
12 | token_set![R_PAREN, COMMA]; | ||
13 | |||
14 | pub(super) fn type_(p: &mut Parser) { | ||
15 | match p.current() { | ||
16 | L_PAREN => paren_or_tuple_type(p), | ||
17 | EXCL => never_type(p), | ||
18 | STAR => pointer_type(p), | ||
19 | L_BRACK => array_or_slice_type(p), | ||
20 | AMP => reference_type(p), | ||
21 | UNDERSCORE => placeholder_type(p), | ||
22 | FN_KW | UNSAFE_KW | EXTERN_KW => fn_pointer_type(p), | ||
23 | FOR_KW => for_type(p), | ||
24 | IMPL_KW => impl_trait_type(p), | ||
25 | DYN_KW => dyn_trait_type(p), | ||
26 | L_ANGLE => path_type(p), | ||
27 | _ if paths::is_path_start(p) => path_type(p), | ||
28 | _ => { | ||
29 | p.err_recover("expected type", TYPE_RECOVERY_SET); | ||
30 | } | ||
31 | } | ||
32 | } | ||
33 | |||
34 | pub(super) fn ascription(p: &mut Parser) { | ||
35 | p.expect(COLON); | ||
36 | type_(p) | ||
37 | } | ||
38 | |||
39 | fn type_no_plus(p: &mut Parser) { | ||
40 | type_(p); | ||
41 | } | ||
42 | |||
43 | fn paren_or_tuple_type(p: &mut Parser) { | ||
44 | assert!(p.at(L_PAREN)); | ||
45 | let m = p.start(); | ||
46 | p.bump(); | ||
47 | let mut n_types: u32 = 0; | ||
48 | let mut trailing_comma: bool = false; | ||
49 | while !p.at(EOF) && !p.at(R_PAREN) { | ||
50 | n_types += 1; | ||
51 | type_(p); | ||
52 | if p.eat(COMMA) { | ||
53 | trailing_comma = true; | ||
54 | } else { | ||
55 | trailing_comma = false; | ||
56 | break; | ||
57 | } | ||
58 | } | ||
59 | p.expect(R_PAREN); | ||
60 | |||
61 | let kind = if n_types == 1 && !trailing_comma { | ||
62 | // test paren_type | ||
63 | // type T = (i32); | ||
64 | PAREN_TYPE | ||
65 | } else { | ||
66 | // test unit_type | ||
67 | // type T = (); | ||
68 | |||
69 | // test singleton_tuple_type | ||
70 | // type T = (i32,); | ||
71 | TUPLE_TYPE | ||
72 | }; | ||
73 | m.complete(p, kind); | ||
74 | } | ||
75 | |||
76 | // test never_type | ||
77 | // type Never = !; | ||
78 | fn never_type(p: &mut Parser) { | ||
79 | assert!(p.at(EXCL)); | ||
80 | let m = p.start(); | ||
81 | p.bump(); | ||
82 | m.complete(p, NEVER_TYPE); | ||
83 | } | ||
84 | |||
85 | fn pointer_type(p: &mut Parser) { | ||
86 | assert!(p.at(STAR)); | ||
87 | let m = p.start(); | ||
88 | p.bump(); | ||
89 | |||
90 | match p.current() { | ||
91 | // test pointer_type_mut | ||
92 | // type M = *mut (); | ||
93 | // type C = *mut (); | ||
94 | MUT_KW | CONST_KW => p.bump(), | ||
95 | _ => { | ||
96 | // test pointer_type_no_mutability | ||
97 | // type T = *(); | ||
98 | p.error( | ||
99 | "expected mut or const in raw pointer type \ | ||
100 | (use `*mut T` or `*const T` as appropriate)", | ||
101 | ); | ||
102 | } | ||
103 | }; | ||
104 | |||
105 | type_no_plus(p); | ||
106 | m.complete(p, POINTER_TYPE); | ||
107 | } | ||
108 | |||
109 | fn array_or_slice_type(p: &mut Parser) { | ||
110 | assert!(p.at(L_BRACK)); | ||
111 | let m = p.start(); | ||
112 | p.bump(); | ||
113 | |||
114 | type_(p); | ||
115 | let kind = match p.current() { | ||
116 | // test slice_type | ||
117 | // type T = [()]; | ||
118 | R_BRACK => { | ||
119 | p.bump(); | ||
120 | SLICE_TYPE | ||
121 | } | ||
122 | |||
123 | // test array_type | ||
124 | // type T = [(); 92]; | ||
125 | SEMI => { | ||
126 | p.bump(); | ||
127 | expressions::expr(p); | ||
128 | p.expect(R_BRACK); | ||
129 | ARRAY_TYPE | ||
130 | } | ||
131 | // test array_type_missing_semi | ||
132 | // type T = [() 92]; | ||
133 | _ => { | ||
134 | p.error("expected `;` or `]`"); | ||
135 | SLICE_TYPE | ||
136 | } | ||
137 | }; | ||
138 | m.complete(p, kind); | ||
139 | } | ||
140 | |||
141 | // test reference_type; | ||
142 | // type A = &(); | ||
143 | // type B = &'static (); | ||
144 | // type C = &mut (); | ||
145 | fn reference_type(p: &mut Parser) { | ||
146 | assert!(p.at(AMP)); | ||
147 | let m = p.start(); | ||
148 | p.bump(); | ||
149 | p.eat(LIFETIME); | ||
150 | p.eat(MUT_KW); | ||
151 | type_no_plus(p); | ||
152 | m.complete(p, REFERENCE_TYPE); | ||
153 | } | ||
154 | |||
155 | // test placeholder_type | ||
156 | // type Placeholder = _; | ||
157 | fn placeholder_type(p: &mut Parser) { | ||
158 | assert!(p.at(UNDERSCORE)); | ||
159 | let m = p.start(); | ||
160 | p.bump(); | ||
161 | m.complete(p, PLACEHOLDER_TYPE); | ||
162 | } | ||
163 | |||
164 | // test fn_pointer_type | ||
165 | // type A = fn(); | ||
166 | // type B = unsafe fn(); | ||
167 | // type C = unsafe extern "C" fn(); | ||
168 | fn fn_pointer_type(p: &mut Parser) { | ||
169 | let m = p.start(); | ||
170 | p.eat(UNSAFE_KW); | ||
171 | if p.at(EXTERN_KW) { | ||
172 | abi(p); | ||
173 | } | ||
174 | // test fn_pointer_type_missing_fn | ||
175 | // type F = unsafe (); | ||
176 | if !p.eat(FN_KW) { | ||
177 | m.abandon(p); | ||
178 | p.error("expected `fn`"); | ||
179 | return; | ||
180 | } | ||
181 | if p.at(L_PAREN) { | ||
182 | params::param_list_opt_patterns(p); | ||
183 | } else { | ||
184 | p.error("expected parameters") | ||
185 | } | ||
186 | // test fn_pointer_type_with_ret | ||
187 | // type F = fn() -> (); | ||
188 | opt_fn_ret_type(p); | ||
189 | m.complete(p, FN_POINTER_TYPE); | ||
190 | } | ||
191 | |||
192 | // test for_type | ||
193 | // type A = for<'a> fn() -> (); | ||
194 | pub(super) fn for_type(p: &mut Parser) { | ||
195 | assert!(p.at(FOR_KW)); | ||
196 | let m = p.start(); | ||
197 | p.bump(); | ||
198 | type_params::opt_type_param_list(p); | ||
199 | match p.current() { | ||
200 | FN_KW | UNSAFE_KW | EXTERN_KW => fn_pointer_type(p), | ||
201 | _ if paths::is_path_start(p) => path_type_(p, false), | ||
202 | _ => p.error("expected a path"), | ||
203 | |||
204 | } | ||
205 | m.complete(p, FOR_TYPE); | ||
206 | } | ||
207 | |||
208 | // test impl_trait_type | ||
209 | // type A = impl Iterator<Item=Foo<'a>> + 'a; | ||
210 | fn impl_trait_type(p: &mut Parser) { | ||
211 | assert!(p.at(IMPL_KW)); | ||
212 | let m = p.start(); | ||
213 | p.bump(); | ||
214 | type_params::bounds_without_colon(p); | ||
215 | m.complete(p, IMPL_TRAIT_TYPE); | ||
216 | } | ||
217 | |||
218 | // test dyn_trait_type | ||
219 | // type A = dyn Iterator<Item=Foo<'a>> + 'a; | ||
220 | fn dyn_trait_type(p: &mut Parser) { | ||
221 | assert!(p.at(DYN_KW)); | ||
222 | let m = p.start(); | ||
223 | p.bump(); | ||
224 | type_params::bounds_without_colon(p); | ||
225 | m.complete(p, DYN_TRAIT_TYPE); | ||
226 | } | ||
227 | |||
228 | // test path_type | ||
229 | // type A = Foo; | ||
230 | // type B = ::Foo; | ||
231 | // type C = self::Foo; | ||
232 | // type D = super::Foo; | ||
233 | pub(super) fn path_type(p: &mut Parser) { | ||
234 | path_type_(p, true) | ||
235 | } | ||
236 | |||
237 | pub(super) fn path_type_(p: &mut Parser, allow_bounds: bool) { | ||
238 | assert!(paths::is_path_start(p) || p.at(L_ANGLE)); | ||
239 | let m = p.start(); | ||
240 | paths::type_path(p); | ||
241 | // test path_type_with_bounds | ||
242 | // fn foo() -> Box<T + 'f> {} | ||
243 | if allow_bounds && p.eat(PLUS) { | ||
244 | type_params::bounds_without_colon(p); | ||
245 | } | ||
246 | m.complete(p, PATH_TYPE); | ||
247 | } | ||