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