]> git.lizzy.rs Git - rust.git/blob - crates/parser/src/grammar/types.rs
Align parser names with grammar
[rust.git] / crates / parser / src / grammar / types.rs
1 //! FIXME: write short doc here
2
3 use super::*;
4
5 pub(super) const TYPE_FIRST: TokenSet = paths::PATH_FIRST.union(token_set![
6     T!['('],
7     T!['['],
8     T![<],
9     T![!],
10     T![*],
11     T![&],
12     T![_],
13     T![fn],
14     T![unsafe],
15     T![extern],
16     T![for],
17     T![impl],
18     T![dyn],
19 ]);
20
21 const TYPE_RECOVERY_SET: TokenSet = token_set![R_PAREN, COMMA, L_DOLLAR];
22
23 pub(crate) fn type_(p: &mut Parser) {
24     type_with_bounds_cond(p, true);
25 }
26
27 pub(super) fn type_no_bounds(p: &mut Parser) {
28     type_with_bounds_cond(p, false);
29 }
30
31 fn type_with_bounds_cond(p: &mut Parser, allow_bounds: bool) {
32     match p.current() {
33         T!['('] => paren_or_tuple_type(p),
34         T![!] => never_type(p),
35         T![*] => ptr_type(p),
36         T!['['] => array_or_slice_type(p),
37         T![&] => ref_type(p),
38         T![_] => infer_type(p),
39         T![fn] | T![unsafe] | T![extern] => fn_ptr_type(p),
40         T![for] => for_type(p),
41         T![impl] => impl_trait_type(p),
42         T![dyn] => dyn_trait_type(p),
43         // Some path types are not allowed to have bounds (no plus)
44         T![<] => path_type_(p, allow_bounds),
45         _ if paths::is_use_path_start(p) => path_or_macro_type_(p, allow_bounds),
46         _ => {
47             p.err_recover("expected type", TYPE_RECOVERY_SET);
48         }
49     }
50 }
51
52 pub(super) fn ascription(p: &mut Parser) {
53     p.expect(T![:]);
54     type_(p)
55 }
56
57 fn paren_or_tuple_type(p: &mut Parser) {
58     assert!(p.at(T!['(']));
59     let m = p.start();
60     p.bump(T!['(']);
61     let mut n_types: u32 = 0;
62     let mut trailing_comma: bool = false;
63     while !p.at(EOF) && !p.at(T![')']) {
64         n_types += 1;
65         type_(p);
66         if p.eat(T![,]) {
67             trailing_comma = true;
68         } else {
69             trailing_comma = false;
70             break;
71         }
72     }
73     p.expect(T![')']);
74
75     let kind = if n_types == 1 && !trailing_comma {
76         // test paren_type
77         // type T = (i32);
78         PAREN_TYPE
79     } else {
80         // test unit_type
81         // type T = ();
82
83         // test singleton_tuple_type
84         // type T = (i32,);
85         TUPLE_TYPE
86     };
87     m.complete(p, kind);
88 }
89
90 // test never_type
91 // type Never = !;
92 fn never_type(p: &mut Parser) {
93     assert!(p.at(T![!]));
94     let m = p.start();
95     p.bump(T![!]);
96     m.complete(p, NEVER_TYPE);
97 }
98
99 fn ptr_type(p: &mut Parser) {
100     assert!(p.at(T![*]));
101     let m = p.start();
102     p.bump(T![*]);
103
104     match p.current() {
105         // test pointer_type_mut
106         // type M = *mut ();
107         // type C = *mut ();
108         T![mut] | T![const] => p.bump_any(),
109         _ => {
110             // test_err pointer_type_no_mutability
111             // type T = *();
112             p.error(
113                 "expected mut or const in raw pointer type \
114                  (use `*mut T` or `*const T` as appropriate)",
115             );
116         }
117     };
118
119     type_no_bounds(p);
120     m.complete(p, PTR_TYPE);
121 }
122
123 fn array_or_slice_type(p: &mut Parser) {
124     assert!(p.at(T!['[']));
125     let m = p.start();
126     p.bump(T!['[']);
127
128     type_(p);
129     let kind = match p.current() {
130         // test slice_type
131         // type T = [()];
132         T![']'] => {
133             p.bump(T![']']);
134             SLICE_TYPE
135         }
136
137         // test array_type
138         // type T = [(); 92];
139         T![;] => {
140             p.bump(T![;]);
141             expressions::expr(p);
142             p.expect(T![']']);
143             ARRAY_TYPE
144         }
145         // test_err array_type_missing_semi
146         // type T = [() 92];
147         _ => {
148             p.error("expected `;` or `]`");
149             SLICE_TYPE
150         }
151     };
152     m.complete(p, kind);
153 }
154
155 // test reference_type;
156 // type A = &();
157 // type B = &'static ();
158 // type C = &mut ();
159 fn ref_type(p: &mut Parser) {
160     assert!(p.at(T![&]));
161     let m = p.start();
162     p.bump(T![&]);
163     p.eat(LIFETIME);
164     p.eat(T![mut]);
165     type_no_bounds(p);
166     m.complete(p, REF_TYPE);
167 }
168
169 // test placeholder_type
170 // type Placeholder = _;
171 fn infer_type(p: &mut Parser) {
172     assert!(p.at(T![_]));
173     let m = p.start();
174     p.bump(T![_]);
175     m.complete(p, INFER_TYPE);
176 }
177
178 // test fn_pointer_type
179 // type A = fn();
180 // type B = unsafe fn();
181 // type C = unsafe extern "C" fn();
182 // type D = extern "C" fn ( u8 , ... ) -> u8;
183 fn fn_ptr_type(p: &mut Parser) {
184     let m = p.start();
185     p.eat(T![unsafe]);
186     if p.at(T![extern]) {
187         abi(p);
188     }
189     // test_err fn_pointer_type_missing_fn
190     // type F = unsafe ();
191     if !p.eat(T![fn]) {
192         m.abandon(p);
193         p.error("expected `fn`");
194         return;
195     }
196     if p.at(T!['(']) {
197         params::param_list_fn_ptr(p);
198     } else {
199         p.error("expected parameters")
200     }
201     // test fn_pointer_type_with_ret
202     // type F = fn() -> ();
203     opt_ret_type(p);
204     m.complete(p, FN_PTR_TYPE);
205 }
206
207 pub(super) fn for_binder(p: &mut Parser) {
208     assert!(p.at(T![for]));
209     p.bump(T![for]);
210     if p.at(T![<]) {
211         type_params::opt_generic_param_list(p);
212     } else {
213         p.error("expected `<`");
214     }
215 }
216
217 // test for_type
218 // type A = for<'a> fn() -> ();
219 // type B = for<'a> unsafe extern "C" fn(&'a ()) -> ();
220 // type Obj = for<'a> PartialEq<&'a i32>;
221 pub(super) fn for_type(p: &mut Parser) {
222     assert!(p.at(T![for]));
223     let m = p.start();
224     for_binder(p);
225     match p.current() {
226         T![fn] | T![unsafe] | T![extern] => {}
227         // OK: legacy trait object format
228         _ if paths::is_use_path_start(p) => {}
229         _ => {
230             p.error("expected a function pointer or path");
231         }
232     }
233     type_no_bounds(p);
234     m.complete(p, FOR_TYPE);
235 }
236
237 // test impl_trait_type
238 // type A = impl Iterator<Item=Foo<'a>> + 'a;
239 fn impl_trait_type(p: &mut Parser) {
240     assert!(p.at(T![impl]));
241     let m = p.start();
242     p.bump(T![impl]);
243     type_params::bounds_without_colon(p);
244     m.complete(p, IMPL_TRAIT_TYPE);
245 }
246
247 // test dyn_trait_type
248 // type A = dyn Iterator<Item=Foo<'a>> + 'a;
249 fn dyn_trait_type(p: &mut Parser) {
250     assert!(p.at(T![dyn]));
251     let m = p.start();
252     p.bump(T![dyn]);
253     type_params::bounds_without_colon(p);
254     m.complete(p, DYN_TRAIT_TYPE);
255 }
256
257 // test path_type
258 // type A = Foo;
259 // type B = ::Foo;
260 // type C = self::Foo;
261 // type D = super::Foo;
262 pub(super) fn path_type(p: &mut Parser) {
263     path_type_(p, true)
264 }
265
266 // test macro_call_type
267 // type A = foo!();
268 // type B = crate::foo!();
269 fn path_or_macro_type_(p: &mut Parser, allow_bounds: bool) {
270     assert!(paths::is_path_start(p));
271     let m = p.start();
272     paths::type_path(p);
273
274     let kind = if p.at(T![!]) && !p.at(T![!=]) {
275         items::macro_call_after_excl(p);
276         MACRO_CALL
277     } else {
278         PATH_TYPE
279     };
280
281     let path = m.complete(p, kind);
282
283     if allow_bounds {
284         opt_path_type_bounds_as_dyn_trait_type(p, path);
285     }
286 }
287
288 pub(super) fn path_type_(p: &mut Parser, allow_bounds: bool) {
289     assert!(paths::is_path_start(p));
290     let m = p.start();
291     paths::type_path(p);
292
293     // test path_type_with_bounds
294     // fn foo() -> Box<T + 'f> {}
295     // fn foo() -> Box<dyn T + 'f> {}
296     let path = m.complete(p, PATH_TYPE);
297     if allow_bounds {
298         opt_path_type_bounds_as_dyn_trait_type(p, path);
299     }
300 }
301
302 /// This turns a parsed PATH_TYPE optionally into a DYN_TRAIT_TYPE
303 /// with a TYPE_BOUND_LIST
304 fn opt_path_type_bounds_as_dyn_trait_type(p: &mut Parser, path_type_marker: CompletedMarker) {
305     if !p.at(T![+]) {
306         return;
307     }
308
309     // First create a TYPE_BOUND from the completed PATH_TYPE
310     let m = path_type_marker.precede(p).complete(p, TYPE_BOUND);
311
312     // Next setup a marker for the TYPE_BOUND_LIST
313     let m = m.precede(p);
314
315     // This gets consumed here so it gets properly set
316     // in the TYPE_BOUND_LIST
317     p.eat(T![+]);
318
319     // Parse rest of the bounds into the TYPE_BOUND_LIST
320     let m = type_params::bounds_without_colon_m(p, m);
321
322     // Finally precede everything with DYN_TRAIT_TYPE
323     m.precede(p).complete(p, DYN_TRAIT_TYPE);
324 }