1 //! FIXME: write short doc here
5 pub(super) const TYPE_FIRST: TokenSet = paths::PATH_FIRST.union(token_set![
21 const TYPE_RECOVERY_SET: TokenSet = token_set![R_PAREN, COMMA, L_DOLLAR];
23 pub(crate) fn type_(p: &mut Parser) {
24 type_with_bounds_cond(p, true);
27 pub(super) fn type_no_bounds(p: &mut Parser) {
28 type_with_bounds_cond(p, false);
31 fn type_with_bounds_cond(p: &mut Parser, allow_bounds: bool) {
33 T!['('] => paren_or_tuple_type(p),
34 T![!] => never_type(p),
36 T!['['] => array_or_slice_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),
47 p.err_recover("expected type", TYPE_RECOVERY_SET);
52 pub(super) fn ascription(p: &mut Parser) {
57 fn paren_or_tuple_type(p: &mut Parser) {
58 assert!(p.at(T!['(']));
61 let mut n_types: u32 = 0;
62 let mut trailing_comma: bool = false;
63 while !p.at(EOF) && !p.at(T![')']) {
67 trailing_comma = true;
69 trailing_comma = false;
75 let kind = if n_types == 1 && !trailing_comma {
83 // test singleton_tuple_type
92 fn never_type(p: &mut Parser) {
96 m.complete(p, NEVER_TYPE);
99 fn ptr_type(p: &mut Parser) {
100 assert!(p.at(T![*]));
105 // test pointer_type_mut
108 T![mut] | T![const] => p.bump_any(),
110 // test_err pointer_type_no_mutability
113 "expected mut or const in raw pointer type \
114 (use `*mut T` or `*const T` as appropriate)",
120 m.complete(p, PTR_TYPE);
123 fn array_or_slice_type(p: &mut Parser) {
124 assert!(p.at(T!['[']));
129 let kind = match p.current() {
138 // type T = [(); 92];
141 expressions::expr(p);
145 // test_err array_type_missing_semi
148 p.error("expected `;` or `]`");
155 // test reference_type;
157 // type B = &'static ();
159 fn ref_type(p: &mut Parser) {
160 assert!(p.at(T![&]));
166 m.complete(p, REF_TYPE);
169 // test placeholder_type
170 // type Placeholder = _;
171 fn infer_type(p: &mut Parser) {
172 assert!(p.at(T![_]));
175 m.complete(p, INFER_TYPE);
178 // test fn_pointer_type
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) {
186 if p.at(T![extern]) {
189 // test_err fn_pointer_type_missing_fn
190 // type F = unsafe ();
193 p.error("expected `fn`");
197 params::param_list_fn_ptr(p);
199 p.error("expected parameters")
201 // test fn_pointer_type_with_ret
202 // type F = fn() -> ();
204 m.complete(p, FN_PTR_TYPE);
207 pub(super) fn for_binder(p: &mut Parser) {
208 assert!(p.at(T![for]));
211 type_params::opt_generic_param_list(p);
213 p.error("expected `<`");
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]));
226 T![fn] | T![unsafe] | T![extern] => {}
227 // OK: legacy trait object format
228 _ if paths::is_use_path_start(p) => {}
230 p.error("expected a function pointer or path");
234 m.complete(p, FOR_TYPE);
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]));
243 type_params::bounds_without_colon(p);
244 m.complete(p, IMPL_TRAIT_TYPE);
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]));
253 type_params::bounds_without_colon(p);
254 m.complete(p, DYN_TRAIT_TYPE);
260 // type C = self::Foo;
261 // type D = super::Foo;
262 pub(super) fn path_type(p: &mut Parser) {
266 // test macro_call_type
268 // type B = crate::foo!();
269 fn path_or_macro_type_(p: &mut Parser, allow_bounds: bool) {
270 assert!(paths::is_path_start(p));
274 let kind = if p.at(T![!]) && !p.at(T![!=]) {
275 items::macro_call_after_excl(p);
281 let path = m.complete(p, kind);
284 opt_path_type_bounds_as_dyn_trait_type(p, path);
288 pub(super) fn path_type_(p: &mut Parser, allow_bounds: bool) {
289 assert!(paths::is_path_start(p));
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);
298 opt_path_type_bounds_as_dyn_trait_type(p, path);
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) {
309 // First create a TYPE_BOUND from the completed PATH_TYPE
310 let m = path_type_marker.precede(p).complete(p, TYPE_BOUND);
312 // Next setup a marker for the TYPE_BOUND_LIST
313 let m = m.precede(p);
315 // This gets consumed here so it gets properly set
316 // in the TYPE_BOUND_LIST
319 // Parse rest of the bounds into the TYPE_BOUND_LIST
320 let m = type_params::bounds_without_colon_m(p, m);
322 // Finally precede everything with DYN_TRAIT_TYPE
323 m.precede(p).complete(p, DYN_TRAIT_TYPE);