]>
Commit | Line | Data |
---|---|---|
e74abb32 XL |
1 | use super::*; |
2 | use crate::punctuated::Punctuated; | |
3 | #[cfg(feature = "extra-traits")] | |
4 | use crate::tt::TokenStreamHelper; | |
5 | use proc_macro2::TokenStream; | |
6 | #[cfg(feature = "extra-traits")] | |
7 | use std::hash::{Hash, Hasher}; | |
8 | ||
9 | ast_enum_of_structs! { | |
10 | /// The possible types that a Rust value could have. | |
11 | /// | |
12 | /// *This type is available if Syn is built with the `"derive"` or `"full"` | |
13 | /// feature.* | |
14 | /// | |
15 | /// # Syntax tree enum | |
16 | /// | |
17 | /// This type is a [syntax tree enum]. | |
18 | /// | |
19 | /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums | |
20 | // | |
21 | // TODO: change syntax-tree-enum link to an intra rustdoc link, currently | |
22 | // blocked on https://github.com/rust-lang/rust/issues/62833 | |
23 | pub enum Type #manual_extra_traits { | |
24 | /// A fixed size array type: `[T; n]`. | |
25 | Array(TypeArray), | |
26 | ||
27 | /// A bare function type: `fn(usize) -> bool`. | |
28 | BareFn(TypeBareFn), | |
29 | ||
30 | /// A type contained within invisible delimiters. | |
31 | Group(TypeGroup), | |
32 | ||
33 | /// An `impl Bound1 + Bound2 + Bound3` type where `Bound` is a trait or | |
34 | /// a lifetime. | |
35 | ImplTrait(TypeImplTrait), | |
36 | ||
37 | /// Indication that a type should be inferred by the compiler: `_`. | |
38 | Infer(TypeInfer), | |
39 | ||
40 | /// A macro in the type position. | |
41 | Macro(TypeMacro), | |
42 | ||
43 | /// The never type: `!`. | |
44 | Never(TypeNever), | |
45 | ||
46 | /// A parenthesized type equivalent to the inner type. | |
47 | Paren(TypeParen), | |
48 | ||
49 | /// A path like `std::slice::Iter`, optionally qualified with a | |
50 | /// self-type as in `<Vec<T> as SomeTrait>::Associated`. | |
51 | Path(TypePath), | |
52 | ||
53 | /// A raw pointer type: `*const T` or `*mut T`. | |
54 | Ptr(TypePtr), | |
55 | ||
56 | /// A reference type: `&'a T` or `&'a mut T`. | |
57 | Reference(TypeReference), | |
58 | ||
59 | /// A dynamically sized slice type: `[T]`. | |
60 | Slice(TypeSlice), | |
61 | ||
62 | /// A trait object type `Bound1 + Bound2 + Bound3` where `Bound` is a | |
63 | /// trait or a lifetime. | |
64 | TraitObject(TypeTraitObject), | |
65 | ||
66 | /// A tuple type: `(A, B, C, String)`. | |
67 | Tuple(TypeTuple), | |
68 | ||
69 | /// Tokens in type position not interpreted by Syn. | |
70 | Verbatim(TokenStream), | |
71 | ||
72 | #[doc(hidden)] | |
73 | __Nonexhaustive, | |
74 | } | |
75 | } | |
76 | ||
77 | ast_struct! { | |
78 | /// A fixed size array type: `[T; n]`. | |
79 | /// | |
80 | /// *This type is available if Syn is built with the `"derive"` or | |
81 | /// `"full"` feature.* | |
82 | pub struct TypeArray { | |
83 | pub bracket_token: token::Bracket, | |
84 | pub elem: Box<Type>, | |
85 | pub semi_token: Token![;], | |
86 | pub len: Expr, | |
87 | } | |
88 | } | |
89 | ||
90 | ast_struct! { | |
91 | /// A bare function type: `fn(usize) -> bool`. | |
92 | /// | |
93 | /// *This type is available if Syn is built with the `"derive"` or | |
94 | /// `"full"` feature.* | |
95 | pub struct TypeBareFn { | |
96 | pub lifetimes: Option<BoundLifetimes>, | |
97 | pub unsafety: Option<Token![unsafe]>, | |
98 | pub abi: Option<Abi>, | |
99 | pub fn_token: Token![fn], | |
100 | pub paren_token: token::Paren, | |
101 | pub inputs: Punctuated<BareFnArg, Token![,]>, | |
102 | pub variadic: Option<Variadic>, | |
103 | pub output: ReturnType, | |
104 | } | |
105 | } | |
106 | ||
107 | ast_struct! { | |
108 | /// A type contained within invisible delimiters. | |
109 | /// | |
110 | /// *This type is available if Syn is built with the `"derive"` or | |
111 | /// `"full"` feature.* | |
112 | pub struct TypeGroup { | |
113 | pub group_token: token::Group, | |
114 | pub elem: Box<Type>, | |
115 | } | |
116 | } | |
117 | ||
118 | ast_struct! { | |
119 | /// An `impl Bound1 + Bound2 + Bound3` type where `Bound` is a trait or | |
120 | /// a lifetime. | |
121 | /// | |
122 | /// *This type is available if Syn is built with the `"derive"` or | |
123 | /// `"full"` feature.* | |
124 | pub struct TypeImplTrait { | |
125 | pub impl_token: Token![impl], | |
126 | pub bounds: Punctuated<TypeParamBound, Token![+]>, | |
127 | } | |
128 | } | |
129 | ||
130 | ast_struct! { | |
131 | /// Indication that a type should be inferred by the compiler: `_`. | |
132 | /// | |
133 | /// *This type is available if Syn is built with the `"derive"` or | |
134 | /// `"full"` feature.* | |
135 | pub struct TypeInfer { | |
136 | pub underscore_token: Token![_], | |
137 | } | |
138 | } | |
139 | ||
140 | ast_struct! { | |
141 | /// A macro in the type position. | |
142 | /// | |
143 | /// *This type is available if Syn is built with the `"derive"` or | |
144 | /// `"full"` feature.* | |
145 | pub struct TypeMacro { | |
146 | pub mac: Macro, | |
147 | } | |
148 | } | |
149 | ||
150 | ast_struct! { | |
151 | /// The never type: `!`. | |
152 | /// | |
153 | /// *This type is available if Syn is built with the `"derive"` or | |
154 | /// `"full"` feature.* | |
155 | pub struct TypeNever { | |
156 | pub bang_token: Token![!], | |
157 | } | |
158 | } | |
159 | ||
160 | ast_struct! { | |
161 | /// A parenthesized type equivalent to the inner type. | |
162 | /// | |
163 | /// *This type is available if Syn is built with the `"derive"` or | |
164 | /// `"full"` feature.* | |
165 | pub struct TypeParen { | |
166 | pub paren_token: token::Paren, | |
167 | pub elem: Box<Type>, | |
168 | } | |
169 | } | |
170 | ||
171 | ast_struct! { | |
172 | /// A path like `std::slice::Iter`, optionally qualified with a | |
173 | /// self-type as in `<Vec<T> as SomeTrait>::Associated`. | |
174 | /// | |
175 | /// *This type is available if Syn is built with the `"derive"` or | |
176 | /// `"full"` feature.* | |
177 | pub struct TypePath { | |
178 | pub qself: Option<QSelf>, | |
179 | pub path: Path, | |
180 | } | |
181 | } | |
182 | ||
183 | ast_struct! { | |
184 | /// A raw pointer type: `*const T` or `*mut T`. | |
185 | /// | |
186 | /// *This type is available if Syn is built with the `"derive"` or | |
187 | /// `"full"` feature.* | |
188 | pub struct TypePtr { | |
189 | pub star_token: Token![*], | |
190 | pub const_token: Option<Token![const]>, | |
191 | pub mutability: Option<Token![mut]>, | |
192 | pub elem: Box<Type>, | |
193 | } | |
194 | } | |
195 | ||
196 | ast_struct! { | |
197 | /// A reference type: `&'a T` or `&'a mut T`. | |
198 | /// | |
199 | /// *This type is available if Syn is built with the `"derive"` or | |
200 | /// `"full"` feature.* | |
201 | pub struct TypeReference { | |
202 | pub and_token: Token![&], | |
203 | pub lifetime: Option<Lifetime>, | |
204 | pub mutability: Option<Token![mut]>, | |
205 | pub elem: Box<Type>, | |
206 | } | |
207 | } | |
208 | ||
209 | ast_struct! { | |
210 | /// A dynamically sized slice type: `[T]`. | |
211 | /// | |
212 | /// *This type is available if Syn is built with the `"derive"` or | |
213 | /// `"full"` feature.* | |
214 | pub struct TypeSlice { | |
215 | pub bracket_token: token::Bracket, | |
216 | pub elem: Box<Type>, | |
217 | } | |
218 | } | |
219 | ||
220 | ast_struct! { | |
221 | /// A trait object type `Bound1 + Bound2 + Bound3` where `Bound` is a | |
222 | /// trait or a lifetime. | |
223 | /// | |
224 | /// *This type is available if Syn is built with the `"derive"` or | |
225 | /// `"full"` feature.* | |
226 | pub struct TypeTraitObject { | |
227 | pub dyn_token: Option<Token![dyn]>, | |
228 | pub bounds: Punctuated<TypeParamBound, Token![+]>, | |
229 | } | |
230 | } | |
231 | ||
232 | ast_struct! { | |
233 | /// A tuple type: `(A, B, C, String)`. | |
234 | /// | |
235 | /// *This type is available if Syn is built with the `"derive"` or | |
236 | /// `"full"` feature.* | |
237 | pub struct TypeTuple { | |
238 | pub paren_token: token::Paren, | |
239 | pub elems: Punctuated<Type, Token![,]>, | |
240 | } | |
241 | } | |
242 | ||
243 | #[cfg(feature = "extra-traits")] | |
244 | impl Eq for Type {} | |
245 | ||
246 | #[cfg(feature = "extra-traits")] | |
247 | impl PartialEq for Type { | |
248 | fn eq(&self, other: &Self) -> bool { | |
249 | match (self, other) { | |
250 | (Type::Array(this), Type::Array(other)) => this == other, | |
251 | (Type::BareFn(this), Type::BareFn(other)) => this == other, | |
252 | (Type::Group(this), Type::Group(other)) => this == other, | |
253 | (Type::ImplTrait(this), Type::ImplTrait(other)) => this == other, | |
254 | (Type::Infer(this), Type::Infer(other)) => this == other, | |
255 | (Type::Macro(this), Type::Macro(other)) => this == other, | |
256 | (Type::Never(this), Type::Never(other)) => this == other, | |
257 | (Type::Paren(this), Type::Paren(other)) => this == other, | |
258 | (Type::Path(this), Type::Path(other)) => this == other, | |
259 | (Type::Ptr(this), Type::Ptr(other)) => this == other, | |
260 | (Type::Reference(this), Type::Reference(other)) => this == other, | |
261 | (Type::Slice(this), Type::Slice(other)) => this == other, | |
262 | (Type::TraitObject(this), Type::TraitObject(other)) => this == other, | |
263 | (Type::Tuple(this), Type::Tuple(other)) => this == other, | |
264 | (Type::Verbatim(this), Type::Verbatim(other)) => { | |
265 | TokenStreamHelper(this) == TokenStreamHelper(other) | |
266 | } | |
267 | _ => false, | |
268 | } | |
269 | } | |
270 | } | |
271 | ||
272 | #[cfg(feature = "extra-traits")] | |
273 | impl Hash for Type { | |
274 | fn hash<H>(&self, hash: &mut H) | |
275 | where | |
276 | H: Hasher, | |
277 | { | |
278 | match self { | |
279 | Type::Array(ty) => { | |
280 | hash.write_u8(0); | |
281 | ty.hash(hash); | |
282 | } | |
283 | Type::BareFn(ty) => { | |
284 | hash.write_u8(1); | |
285 | ty.hash(hash); | |
286 | } | |
287 | Type::Group(ty) => { | |
288 | hash.write_u8(2); | |
289 | ty.hash(hash); | |
290 | } | |
291 | Type::ImplTrait(ty) => { | |
292 | hash.write_u8(3); | |
293 | ty.hash(hash); | |
294 | } | |
295 | Type::Infer(ty) => { | |
296 | hash.write_u8(4); | |
297 | ty.hash(hash); | |
298 | } | |
299 | Type::Macro(ty) => { | |
300 | hash.write_u8(5); | |
301 | ty.hash(hash); | |
302 | } | |
303 | Type::Never(ty) => { | |
304 | hash.write_u8(6); | |
305 | ty.hash(hash); | |
306 | } | |
307 | Type::Paren(ty) => { | |
308 | hash.write_u8(7); | |
309 | ty.hash(hash); | |
310 | } | |
311 | Type::Path(ty) => { | |
312 | hash.write_u8(8); | |
313 | ty.hash(hash); | |
314 | } | |
315 | Type::Ptr(ty) => { | |
316 | hash.write_u8(9); | |
317 | ty.hash(hash); | |
318 | } | |
319 | Type::Reference(ty) => { | |
320 | hash.write_u8(10); | |
321 | ty.hash(hash); | |
322 | } | |
323 | Type::Slice(ty) => { | |
324 | hash.write_u8(11); | |
325 | ty.hash(hash); | |
326 | } | |
327 | Type::TraitObject(ty) => { | |
328 | hash.write_u8(12); | |
329 | ty.hash(hash); | |
330 | } | |
331 | Type::Tuple(ty) => { | |
332 | hash.write_u8(13); | |
333 | ty.hash(hash); | |
334 | } | |
335 | Type::Verbatim(ty) => { | |
336 | hash.write_u8(14); | |
337 | TokenStreamHelper(ty).hash(hash); | |
338 | } | |
339 | Type::__Nonexhaustive => unreachable!(), | |
340 | } | |
341 | } | |
342 | } | |
343 | ||
344 | ast_struct! { | |
345 | /// The binary interface of a function: `extern "C"`. | |
346 | /// | |
347 | /// *This type is available if Syn is built with the `"derive"` or `"full"` | |
348 | /// feature.* | |
349 | pub struct Abi { | |
350 | pub extern_token: Token![extern], | |
351 | pub name: Option<LitStr>, | |
352 | } | |
353 | } | |
354 | ||
355 | ast_struct! { | |
356 | /// An argument in a function type: the `usize` in `fn(usize) -> bool`. | |
357 | /// | |
358 | /// *This type is available if Syn is built with the `"derive"` or `"full"` | |
359 | /// feature.* | |
360 | pub struct BareFnArg { | |
361 | pub attrs: Vec<Attribute>, | |
362 | pub name: Option<(Ident, Token![:])>, | |
363 | pub ty: Type, | |
364 | } | |
365 | } | |
366 | ||
367 | ast_struct! { | |
368 | /// The variadic argument of a foreign function. | |
369 | /// | |
370 | /// ```rust | |
371 | /// # struct c_char; | |
372 | /// # struct c_int; | |
373 | /// # | |
374 | /// extern "C" { | |
375 | /// fn printf(format: *const c_char, ...) -> c_int; | |
376 | /// // ^^^ | |
377 | /// } | |
378 | /// ``` | |
379 | /// | |
380 | /// *This type is available if Syn is built with the `"derive"` or `"full"` | |
381 | /// feature.* | |
382 | pub struct Variadic { | |
383 | pub attrs: Vec<Attribute>, | |
384 | pub dots: Token![...], | |
385 | } | |
386 | } | |
387 | ||
388 | ast_enum! { | |
389 | /// Return type of a function signature. | |
390 | /// | |
391 | /// *This type is available if Syn is built with the `"derive"` or `"full"` | |
392 | /// feature.* | |
393 | pub enum ReturnType { | |
394 | /// Return type is not specified. | |
395 | /// | |
396 | /// Functions default to `()` and closures default to type inference. | |
397 | Default, | |
398 | /// A particular type is returned. | |
399 | Type(Token![->], Box<Type>), | |
400 | } | |
401 | } | |
402 | ||
403 | #[cfg(feature = "parsing")] | |
404 | pub mod parsing { | |
405 | use super::*; | |
406 | ||
407 | use crate::ext::IdentExt; | |
408 | use crate::parse::{Parse, ParseStream, Result}; | |
409 | use crate::path; | |
60c5eb7d XL |
410 | use proc_macro2::{Punct, Spacing, TokenTree}; |
411 | use std::iter::FromIterator; | |
e74abb32 XL |
412 | |
413 | impl Parse for Type { | |
414 | fn parse(input: ParseStream) -> Result<Self> { | |
415 | ambig_ty(input, true) | |
416 | } | |
417 | } | |
418 | ||
419 | impl Type { | |
420 | /// In some positions, types may not contain the `+` character, to | |
421 | /// disambiguate them. For example in the expression `1 as T`, T may not | |
422 | /// contain a `+` character. | |
423 | /// | |
424 | /// This parser does not allow a `+`, while the default parser does. | |
425 | pub fn without_plus(input: ParseStream) -> Result<Self> { | |
426 | ambig_ty(input, false) | |
427 | } | |
428 | } | |
429 | ||
430 | fn ambig_ty(input: ParseStream, allow_plus: bool) -> Result<Type> { | |
431 | if input.peek(token::Group) { | |
432 | return input.parse().map(Type::Group); | |
433 | } | |
434 | ||
435 | let mut lifetimes = None::<BoundLifetimes>; | |
436 | let mut lookahead = input.lookahead1(); | |
437 | if lookahead.peek(Token![for]) { | |
438 | lifetimes = input.parse()?; | |
439 | lookahead = input.lookahead1(); | |
440 | if !lookahead.peek(Ident) | |
441 | && !lookahead.peek(Token![fn]) | |
442 | && !lookahead.peek(Token![unsafe]) | |
443 | && !lookahead.peek(Token![extern]) | |
444 | && !lookahead.peek(Token![super]) | |
445 | && !lookahead.peek(Token![self]) | |
446 | && !lookahead.peek(Token![Self]) | |
447 | && !lookahead.peek(Token![crate]) | |
448 | { | |
449 | return Err(lookahead.error()); | |
450 | } | |
451 | } | |
452 | ||
453 | if lookahead.peek(token::Paren) { | |
454 | let content; | |
455 | let paren_token = parenthesized!(content in input); | |
456 | if content.is_empty() { | |
457 | return Ok(Type::Tuple(TypeTuple { | |
458 | paren_token, | |
459 | elems: Punctuated::new(), | |
460 | })); | |
461 | } | |
462 | if content.peek(Lifetime) { | |
463 | return Ok(Type::Paren(TypeParen { | |
464 | paren_token, | |
465 | elem: Box::new(Type::TraitObject(content.parse()?)), | |
466 | })); | |
467 | } | |
468 | if content.peek(Token![?]) { | |
469 | return Ok(Type::TraitObject(TypeTraitObject { | |
470 | dyn_token: None, | |
471 | bounds: { | |
472 | let mut bounds = Punctuated::new(); | |
473 | bounds.push_value(TypeParamBound::Trait(TraitBound { | |
474 | paren_token: Some(paren_token), | |
475 | ..content.parse()? | |
476 | })); | |
477 | while let Some(plus) = input.parse()? { | |
478 | bounds.push_punct(plus); | |
479 | bounds.push_value(input.parse()?); | |
480 | } | |
481 | bounds | |
482 | }, | |
483 | })); | |
484 | } | |
485 | let mut first: Type = content.parse()?; | |
486 | if content.peek(Token![,]) { | |
487 | return Ok(Type::Tuple(TypeTuple { | |
488 | paren_token, | |
489 | elems: { | |
490 | let mut elems = Punctuated::new(); | |
491 | elems.push_value(first); | |
492 | elems.push_punct(content.parse()?); | |
493 | let rest: Punctuated<Type, Token![,]> = | |
494 | content.parse_terminated(Parse::parse)?; | |
495 | elems.extend(rest); | |
496 | elems | |
497 | }, | |
498 | })); | |
499 | } | |
500 | if allow_plus && input.peek(Token![+]) { | |
501 | loop { | |
502 | let first = match first { | |
503 | Type::Path(TypePath { qself: None, path }) => { | |
504 | TypeParamBound::Trait(TraitBound { | |
505 | paren_token: Some(paren_token), | |
506 | modifier: TraitBoundModifier::None, | |
507 | lifetimes: None, | |
508 | path, | |
509 | }) | |
510 | } | |
511 | Type::TraitObject(TypeTraitObject { | |
512 | dyn_token: None, | |
513 | bounds, | |
514 | }) => { | |
515 | if bounds.len() > 1 || bounds.trailing_punct() { | |
516 | first = Type::TraitObject(TypeTraitObject { | |
517 | dyn_token: None, | |
518 | bounds, | |
519 | }); | |
520 | break; | |
521 | } | |
522 | match bounds.into_iter().next().unwrap() { | |
523 | TypeParamBound::Trait(trait_bound) => { | |
524 | TypeParamBound::Trait(TraitBound { | |
525 | paren_token: Some(paren_token), | |
526 | ..trait_bound | |
527 | }) | |
528 | } | |
529 | other => other, | |
530 | } | |
531 | } | |
532 | _ => break, | |
533 | }; | |
534 | return Ok(Type::TraitObject(TypeTraitObject { | |
535 | dyn_token: None, | |
536 | bounds: { | |
537 | let mut bounds = Punctuated::new(); | |
538 | bounds.push_value(first); | |
539 | while let Some(plus) = input.parse()? { | |
540 | bounds.push_punct(plus); | |
541 | bounds.push_value(input.parse()?); | |
542 | } | |
543 | bounds | |
544 | }, | |
545 | })); | |
546 | } | |
547 | } | |
548 | Ok(Type::Paren(TypeParen { | |
549 | paren_token, | |
550 | elem: Box::new(first), | |
551 | })) | |
552 | } else if lookahead.peek(Token![fn]) | |
553 | || lookahead.peek(Token![unsafe]) | |
554 | || lookahead.peek(Token![extern]) && !input.peek2(Token![::]) | |
555 | { | |
556 | let mut bare_fn: TypeBareFn = input.parse()?; | |
557 | bare_fn.lifetimes = lifetimes; | |
558 | Ok(Type::BareFn(bare_fn)) | |
559 | } else if lookahead.peek(Ident) | |
560 | || input.peek(Token![super]) | |
561 | || input.peek(Token![self]) | |
562 | || input.peek(Token![Self]) | |
563 | || input.peek(Token![crate]) | |
564 | || input.peek(Token![extern]) | |
565 | || lookahead.peek(Token![::]) | |
566 | || lookahead.peek(Token![<]) | |
567 | { | |
568 | if input.peek(Token![dyn]) { | |
569 | let mut trait_object: TypeTraitObject = input.parse()?; | |
570 | if lifetimes.is_some() { | |
571 | match trait_object.bounds.iter_mut().next().unwrap() { | |
572 | TypeParamBound::Trait(trait_bound) => { | |
573 | trait_bound.lifetimes = lifetimes; | |
574 | } | |
575 | TypeParamBound::Lifetime(_) => unreachable!(), | |
576 | } | |
577 | } | |
578 | return Ok(Type::TraitObject(trait_object)); | |
579 | } | |
580 | ||
581 | let ty: TypePath = input.parse()?; | |
582 | if ty.qself.is_some() { | |
583 | return Ok(Type::Path(ty)); | |
584 | } | |
585 | ||
586 | if input.peek(Token![!]) && !input.peek(Token![!=]) { | |
587 | let mut contains_arguments = false; | |
588 | for segment in &ty.path.segments { | |
589 | match segment.arguments { | |
590 | PathArguments::None => {} | |
591 | PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => { | |
592 | contains_arguments = true; | |
593 | } | |
594 | } | |
595 | } | |
596 | ||
597 | if !contains_arguments { | |
598 | let bang_token: Token![!] = input.parse()?; | |
599 | let (delimiter, tokens) = mac::parse_delimiter(input)?; | |
600 | return Ok(Type::Macro(TypeMacro { | |
601 | mac: Macro { | |
602 | path: ty.path, | |
603 | bang_token, | |
604 | delimiter, | |
605 | tokens, | |
606 | }, | |
607 | })); | |
608 | } | |
609 | } | |
610 | ||
611 | if lifetimes.is_some() || allow_plus && input.peek(Token![+]) { | |
612 | let mut bounds = Punctuated::new(); | |
613 | bounds.push_value(TypeParamBound::Trait(TraitBound { | |
614 | paren_token: None, | |
615 | modifier: TraitBoundModifier::None, | |
616 | lifetimes, | |
617 | path: ty.path, | |
618 | })); | |
619 | if allow_plus { | |
620 | while input.peek(Token![+]) { | |
621 | bounds.push_punct(input.parse()?); | |
622 | if input.peek(Token![>]) { | |
623 | break; | |
624 | } | |
625 | bounds.push_value(input.parse()?); | |
626 | } | |
627 | } | |
628 | return Ok(Type::TraitObject(TypeTraitObject { | |
629 | dyn_token: None, | |
630 | bounds, | |
631 | })); | |
632 | } | |
633 | ||
634 | Ok(Type::Path(ty)) | |
635 | } else if lookahead.peek(token::Bracket) { | |
636 | let content; | |
637 | let bracket_token = bracketed!(content in input); | |
638 | let elem: Type = content.parse()?; | |
639 | if content.peek(Token![;]) { | |
640 | Ok(Type::Array(TypeArray { | |
641 | bracket_token, | |
642 | elem: Box::new(elem), | |
643 | semi_token: content.parse()?, | |
644 | len: content.parse()?, | |
645 | })) | |
646 | } else { | |
647 | Ok(Type::Slice(TypeSlice { | |
648 | bracket_token, | |
649 | elem: Box::new(elem), | |
650 | })) | |
651 | } | |
652 | } else if lookahead.peek(Token![*]) { | |
653 | input.parse().map(Type::Ptr) | |
654 | } else if lookahead.peek(Token![&]) { | |
655 | input.parse().map(Type::Reference) | |
656 | } else if lookahead.peek(Token![!]) && !input.peek(Token![=]) { | |
657 | input.parse().map(Type::Never) | |
658 | } else if lookahead.peek(Token![impl]) { | |
659 | input.parse().map(Type::ImplTrait) | |
660 | } else if lookahead.peek(Token![_]) { | |
661 | input.parse().map(Type::Infer) | |
662 | } else if lookahead.peek(Lifetime) { | |
663 | input.parse().map(Type::TraitObject) | |
664 | } else { | |
665 | Err(lookahead.error()) | |
666 | } | |
667 | } | |
668 | ||
669 | impl Parse for TypeSlice { | |
670 | fn parse(input: ParseStream) -> Result<Self> { | |
671 | let content; | |
672 | Ok(TypeSlice { | |
673 | bracket_token: bracketed!(content in input), | |
674 | elem: content.parse()?, | |
675 | }) | |
676 | } | |
677 | } | |
678 | ||
679 | impl Parse for TypeArray { | |
680 | fn parse(input: ParseStream) -> Result<Self> { | |
681 | let content; | |
682 | Ok(TypeArray { | |
683 | bracket_token: bracketed!(content in input), | |
684 | elem: content.parse()?, | |
685 | semi_token: content.parse()?, | |
686 | len: content.parse()?, | |
687 | }) | |
688 | } | |
689 | } | |
690 | ||
691 | impl Parse for TypePtr { | |
692 | fn parse(input: ParseStream) -> Result<Self> { | |
693 | let star_token: Token![*] = input.parse()?; | |
694 | ||
695 | let lookahead = input.lookahead1(); | |
696 | let (const_token, mutability) = if lookahead.peek(Token![const]) { | |
697 | (Some(input.parse()?), None) | |
698 | } else if lookahead.peek(Token![mut]) { | |
699 | (None, Some(input.parse()?)) | |
700 | } else { | |
701 | return Err(lookahead.error()); | |
702 | }; | |
703 | ||
704 | Ok(TypePtr { | |
705 | star_token, | |
706 | const_token, | |
707 | mutability, | |
708 | elem: Box::new(input.call(Type::without_plus)?), | |
709 | }) | |
710 | } | |
711 | } | |
712 | ||
713 | impl Parse for TypeReference { | |
714 | fn parse(input: ParseStream) -> Result<Self> { | |
715 | Ok(TypeReference { | |
716 | and_token: input.parse()?, | |
717 | lifetime: input.parse()?, | |
718 | mutability: input.parse()?, | |
719 | // & binds tighter than +, so we don't allow + here. | |
720 | elem: Box::new(input.call(Type::without_plus)?), | |
721 | }) | |
722 | } | |
723 | } | |
724 | ||
725 | impl Parse for TypeBareFn { | |
726 | fn parse(input: ParseStream) -> Result<Self> { | |
727 | let args; | |
60c5eb7d | 728 | let mut variadic = None; |
e74abb32 XL |
729 | Ok(TypeBareFn { |
730 | lifetimes: input.parse()?, | |
731 | unsafety: input.parse()?, | |
732 | abi: input.parse()?, | |
733 | fn_token: input.parse()?, | |
734 | paren_token: parenthesized!(args in input), | |
735 | inputs: { | |
736 | let mut inputs = Punctuated::new(); | |
60c5eb7d XL |
737 | |
738 | while !args.is_empty() { | |
739 | let attrs = args.call(Attribute::parse_outer)?; | |
740 | ||
741 | if inputs.empty_or_trailing() && args.peek(Token![...]) { | |
742 | variadic = Some(Variadic { | |
743 | attrs, | |
744 | dots: args.parse()?, | |
745 | }); | |
746 | break; | |
747 | } | |
748 | ||
749 | inputs.push_value(BareFnArg { | |
750 | attrs, | |
751 | ..args.parse()? | |
752 | }); | |
e74abb32 XL |
753 | if args.is_empty() { |
754 | break; | |
755 | } | |
60c5eb7d | 756 | |
e74abb32 XL |
757 | inputs.push_punct(args.parse()?); |
758 | } | |
60c5eb7d | 759 | |
e74abb32 XL |
760 | inputs |
761 | }, | |
60c5eb7d | 762 | variadic, |
e74abb32 XL |
763 | output: input.call(ReturnType::without_plus)?, |
764 | }) | |
765 | } | |
766 | } | |
767 | ||
768 | impl Parse for TypeNever { | |
769 | fn parse(input: ParseStream) -> Result<Self> { | |
770 | Ok(TypeNever { | |
771 | bang_token: input.parse()?, | |
772 | }) | |
773 | } | |
774 | } | |
775 | ||
776 | impl Parse for TypeInfer { | |
777 | fn parse(input: ParseStream) -> Result<Self> { | |
778 | Ok(TypeInfer { | |
779 | underscore_token: input.parse()?, | |
780 | }) | |
781 | } | |
782 | } | |
783 | ||
784 | impl Parse for TypeTuple { | |
785 | fn parse(input: ParseStream) -> Result<Self> { | |
786 | let content; | |
60c5eb7d XL |
787 | let paren_token = parenthesized!(content in input); |
788 | ||
789 | if content.is_empty() { | |
790 | return Ok(TypeTuple { | |
791 | paren_token, | |
792 | elems: Punctuated::new(), | |
793 | }); | |
794 | } | |
795 | ||
796 | let first: Type = content.parse()?; | |
e74abb32 | 797 | Ok(TypeTuple { |
60c5eb7d XL |
798 | paren_token, |
799 | elems: { | |
800 | let mut elems = Punctuated::new(); | |
801 | elems.push_value(first); | |
802 | elems.push_punct(content.parse()?); | |
803 | let rest: Punctuated<Type, Token![,]> = | |
804 | content.parse_terminated(Parse::parse)?; | |
805 | elems.extend(rest); | |
806 | elems | |
807 | }, | |
e74abb32 XL |
808 | }) |
809 | } | |
810 | } | |
811 | ||
812 | impl Parse for TypeMacro { | |
813 | fn parse(input: ParseStream) -> Result<Self> { | |
814 | Ok(TypeMacro { | |
815 | mac: input.parse()?, | |
816 | }) | |
817 | } | |
818 | } | |
819 | ||
820 | impl Parse for TypePath { | |
821 | fn parse(input: ParseStream) -> Result<Self> { | |
822 | let (qself, mut path) = path::parsing::qpath(input, false)?; | |
823 | ||
824 | if path.segments.last().unwrap().arguments.is_empty() && input.peek(token::Paren) { | |
825 | let args: ParenthesizedGenericArguments = input.parse()?; | |
826 | let parenthesized = PathArguments::Parenthesized(args); | |
827 | path.segments.last_mut().unwrap().arguments = parenthesized; | |
828 | } | |
829 | ||
830 | Ok(TypePath { qself, path }) | |
831 | } | |
832 | } | |
833 | ||
834 | impl ReturnType { | |
835 | pub fn without_plus(input: ParseStream) -> Result<Self> { | |
836 | Self::parse(input, false) | |
837 | } | |
838 | ||
839 | pub fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> { | |
840 | if input.peek(Token![->]) { | |
841 | let arrow = input.parse()?; | |
842 | let ty = ambig_ty(input, allow_plus)?; | |
843 | Ok(ReturnType::Type(arrow, Box::new(ty))) | |
844 | } else { | |
845 | Ok(ReturnType::Default) | |
846 | } | |
847 | } | |
848 | } | |
849 | ||
850 | impl Parse for ReturnType { | |
851 | fn parse(input: ParseStream) -> Result<Self> { | |
852 | Self::parse(input, true) | |
853 | } | |
854 | } | |
855 | ||
856 | impl Parse for TypeTraitObject { | |
857 | fn parse(input: ParseStream) -> Result<Self> { | |
858 | Self::parse(input, true) | |
859 | } | |
860 | } | |
861 | ||
862 | fn at_least_one_type(bounds: &Punctuated<TypeParamBound, Token![+]>) -> bool { | |
863 | for bound in bounds { | |
864 | if let TypeParamBound::Trait(_) = *bound { | |
865 | return true; | |
866 | } | |
867 | } | |
868 | false | |
869 | } | |
870 | ||
871 | impl TypeTraitObject { | |
872 | pub fn without_plus(input: ParseStream) -> Result<Self> { | |
873 | Self::parse(input, false) | |
874 | } | |
875 | ||
876 | // Only allow multiple trait references if allow_plus is true. | |
877 | pub fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> { | |
878 | Ok(TypeTraitObject { | |
879 | dyn_token: input.parse()?, | |
880 | bounds: { | |
881 | let mut bounds = Punctuated::new(); | |
882 | if allow_plus { | |
883 | loop { | |
884 | bounds.push_value(input.parse()?); | |
885 | if !input.peek(Token![+]) { | |
886 | break; | |
887 | } | |
888 | bounds.push_punct(input.parse()?); | |
889 | if input.peek(Token![>]) { | |
890 | break; | |
891 | } | |
892 | } | |
893 | } else { | |
894 | bounds.push_value(input.parse()?); | |
895 | } | |
896 | // Just lifetimes like `'a + 'b` is not a TraitObject. | |
897 | if !at_least_one_type(&bounds) { | |
898 | return Err(input.error("expected at least one type")); | |
899 | } | |
900 | bounds | |
901 | }, | |
902 | }) | |
903 | } | |
904 | } | |
905 | ||
906 | impl Parse for TypeImplTrait { | |
907 | fn parse(input: ParseStream) -> Result<Self> { | |
908 | Ok(TypeImplTrait { | |
909 | impl_token: input.parse()?, | |
910 | // NOTE: rust-lang/rust#34511 includes discussion about whether | |
911 | // or not + should be allowed in ImplTrait directly without (). | |
912 | bounds: { | |
913 | let mut bounds = Punctuated::new(); | |
914 | loop { | |
915 | bounds.push_value(input.parse()?); | |
916 | if !input.peek(Token![+]) { | |
917 | break; | |
918 | } | |
919 | bounds.push_punct(input.parse()?); | |
920 | } | |
921 | bounds | |
922 | }, | |
923 | }) | |
924 | } | |
925 | } | |
926 | ||
927 | impl Parse for TypeGroup { | |
928 | fn parse(input: ParseStream) -> Result<Self> { | |
929 | let group = crate::group::parse_group(input)?; | |
930 | Ok(TypeGroup { | |
931 | group_token: group.token, | |
932 | elem: group.content.parse()?, | |
933 | }) | |
934 | } | |
935 | } | |
936 | ||
937 | impl Parse for TypeParen { | |
938 | fn parse(input: ParseStream) -> Result<Self> { | |
939 | Self::parse(input, false) | |
940 | } | |
941 | } | |
942 | ||
943 | impl TypeParen { | |
944 | fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> { | |
945 | let content; | |
946 | Ok(TypeParen { | |
947 | paren_token: parenthesized!(content in input), | |
948 | elem: Box::new(ambig_ty(&content, allow_plus)?), | |
949 | }) | |
950 | } | |
951 | } | |
952 | ||
953 | impl Parse for BareFnArg { | |
954 | fn parse(input: ParseStream) -> Result<Self> { | |
955 | Ok(BareFnArg { | |
956 | attrs: input.call(Attribute::parse_outer)?, | |
957 | name: { | |
958 | if (input.peek(Ident) || input.peek(Token![_])) | |
959 | && input.peek2(Token![:]) | |
960 | && !input.peek2(Token![::]) | |
961 | { | |
962 | let name = input.call(Ident::parse_any)?; | |
963 | let colon: Token![:] = input.parse()?; | |
964 | Some((name, colon)) | |
965 | } else { | |
966 | None | |
967 | } | |
968 | }, | |
60c5eb7d XL |
969 | ty: match input.parse::<Option<Token![...]>>()? { |
970 | Some(dot3) => { | |
971 | let args = vec![ | |
972 | TokenTree::Punct(Punct::new('.', Spacing::Joint)), | |
973 | TokenTree::Punct(Punct::new('.', Spacing::Joint)), | |
974 | TokenTree::Punct(Punct::new('.', Spacing::Alone)), | |
975 | ]; | |
976 | let tokens = TokenStream::from_iter(args.into_iter().zip(&dot3.spans).map( | |
977 | |(mut arg, span)| { | |
978 | arg.set_span(*span); | |
979 | arg | |
980 | }, | |
981 | )); | |
982 | Type::Verbatim(tokens) | |
983 | } | |
984 | None => input.parse()?, | |
985 | }, | |
e74abb32 XL |
986 | }) |
987 | } | |
988 | } | |
989 | ||
990 | impl Parse for Abi { | |
991 | fn parse(input: ParseStream) -> Result<Self> { | |
992 | Ok(Abi { | |
993 | extern_token: input.parse()?, | |
994 | name: input.parse()?, | |
995 | }) | |
996 | } | |
997 | } | |
998 | ||
999 | impl Parse for Option<Abi> { | |
1000 | fn parse(input: ParseStream) -> Result<Self> { | |
1001 | if input.peek(Token![extern]) { | |
1002 | input.parse().map(Some) | |
1003 | } else { | |
1004 | Ok(None) | |
1005 | } | |
1006 | } | |
1007 | } | |
1008 | } | |
1009 | ||
1010 | #[cfg(feature = "printing")] | |
1011 | mod printing { | |
1012 | use super::*; | |
1013 | ||
1014 | use proc_macro2::TokenStream; | |
1015 | use quote::{ToTokens, TokenStreamExt}; | |
1016 | ||
1017 | use crate::attr::FilterAttrs; | |
1018 | use crate::print::TokensOrDefault; | |
1019 | ||
1020 | impl ToTokens for TypeSlice { | |
1021 | fn to_tokens(&self, tokens: &mut TokenStream) { | |
1022 | self.bracket_token.surround(tokens, |tokens| { | |
1023 | self.elem.to_tokens(tokens); | |
1024 | }); | |
1025 | } | |
1026 | } | |
1027 | ||
1028 | impl ToTokens for TypeArray { | |
1029 | fn to_tokens(&self, tokens: &mut TokenStream) { | |
1030 | self.bracket_token.surround(tokens, |tokens| { | |
1031 | self.elem.to_tokens(tokens); | |
1032 | self.semi_token.to_tokens(tokens); | |
1033 | self.len.to_tokens(tokens); | |
1034 | }); | |
1035 | } | |
1036 | } | |
1037 | ||
1038 | impl ToTokens for TypePtr { | |
1039 | fn to_tokens(&self, tokens: &mut TokenStream) { | |
1040 | self.star_token.to_tokens(tokens); | |
1041 | match &self.mutability { | |
1042 | Some(tok) => tok.to_tokens(tokens), | |
1043 | None => { | |
1044 | TokensOrDefault(&self.const_token).to_tokens(tokens); | |
1045 | } | |
1046 | } | |
1047 | self.elem.to_tokens(tokens); | |
1048 | } | |
1049 | } | |
1050 | ||
1051 | impl ToTokens for TypeReference { | |
1052 | fn to_tokens(&self, tokens: &mut TokenStream) { | |
1053 | self.and_token.to_tokens(tokens); | |
1054 | self.lifetime.to_tokens(tokens); | |
1055 | self.mutability.to_tokens(tokens); | |
1056 | self.elem.to_tokens(tokens); | |
1057 | } | |
1058 | } | |
1059 | ||
1060 | impl ToTokens for TypeBareFn { | |
1061 | fn to_tokens(&self, tokens: &mut TokenStream) { | |
1062 | self.lifetimes.to_tokens(tokens); | |
1063 | self.unsafety.to_tokens(tokens); | |
1064 | self.abi.to_tokens(tokens); | |
1065 | self.fn_token.to_tokens(tokens); | |
1066 | self.paren_token.surround(tokens, |tokens| { | |
1067 | self.inputs.to_tokens(tokens); | |
1068 | if let Some(variadic) = &self.variadic { | |
1069 | if !self.inputs.empty_or_trailing() { | |
1070 | let span = variadic.dots.spans[0]; | |
1071 | Token![,](span).to_tokens(tokens); | |
1072 | } | |
1073 | variadic.to_tokens(tokens); | |
1074 | } | |
1075 | }); | |
1076 | self.output.to_tokens(tokens); | |
1077 | } | |
1078 | } | |
1079 | ||
1080 | impl ToTokens for TypeNever { | |
1081 | fn to_tokens(&self, tokens: &mut TokenStream) { | |
1082 | self.bang_token.to_tokens(tokens); | |
1083 | } | |
1084 | } | |
1085 | ||
1086 | impl ToTokens for TypeTuple { | |
1087 | fn to_tokens(&self, tokens: &mut TokenStream) { | |
1088 | self.paren_token.surround(tokens, |tokens| { | |
1089 | self.elems.to_tokens(tokens); | |
1090 | }); | |
1091 | } | |
1092 | } | |
1093 | ||
1094 | impl ToTokens for TypePath { | |
1095 | fn to_tokens(&self, tokens: &mut TokenStream) { | |
1096 | private::print_path(tokens, &self.qself, &self.path); | |
1097 | } | |
1098 | } | |
1099 | ||
1100 | impl ToTokens for TypeTraitObject { | |
1101 | fn to_tokens(&self, tokens: &mut TokenStream) { | |
1102 | self.dyn_token.to_tokens(tokens); | |
1103 | self.bounds.to_tokens(tokens); | |
1104 | } | |
1105 | } | |
1106 | ||
1107 | impl ToTokens for TypeImplTrait { | |
1108 | fn to_tokens(&self, tokens: &mut TokenStream) { | |
1109 | self.impl_token.to_tokens(tokens); | |
1110 | self.bounds.to_tokens(tokens); | |
1111 | } | |
1112 | } | |
1113 | ||
1114 | impl ToTokens for TypeGroup { | |
1115 | fn to_tokens(&self, tokens: &mut TokenStream) { | |
1116 | self.group_token.surround(tokens, |tokens| { | |
1117 | self.elem.to_tokens(tokens); | |
1118 | }); | |
1119 | } | |
1120 | } | |
1121 | ||
1122 | impl ToTokens for TypeParen { | |
1123 | fn to_tokens(&self, tokens: &mut TokenStream) { | |
1124 | self.paren_token.surround(tokens, |tokens| { | |
1125 | self.elem.to_tokens(tokens); | |
1126 | }); | |
1127 | } | |
1128 | } | |
1129 | ||
1130 | impl ToTokens for TypeInfer { | |
1131 | fn to_tokens(&self, tokens: &mut TokenStream) { | |
1132 | self.underscore_token.to_tokens(tokens); | |
1133 | } | |
1134 | } | |
1135 | ||
1136 | impl ToTokens for TypeMacro { | |
1137 | fn to_tokens(&self, tokens: &mut TokenStream) { | |
1138 | self.mac.to_tokens(tokens); | |
1139 | } | |
1140 | } | |
1141 | ||
1142 | impl ToTokens for ReturnType { | |
1143 | fn to_tokens(&self, tokens: &mut TokenStream) { | |
1144 | match self { | |
1145 | ReturnType::Default => {} | |
1146 | ReturnType::Type(arrow, ty) => { | |
1147 | arrow.to_tokens(tokens); | |
1148 | ty.to_tokens(tokens); | |
1149 | } | |
1150 | } | |
1151 | } | |
1152 | } | |
1153 | ||
1154 | impl ToTokens for BareFnArg { | |
1155 | fn to_tokens(&self, tokens: &mut TokenStream) { | |
1156 | tokens.append_all(self.attrs.outer()); | |
1157 | if let Some((name, colon)) = &self.name { | |
1158 | name.to_tokens(tokens); | |
1159 | colon.to_tokens(tokens); | |
1160 | } | |
1161 | self.ty.to_tokens(tokens); | |
1162 | } | |
1163 | } | |
1164 | ||
1165 | impl ToTokens for Variadic { | |
1166 | fn to_tokens(&self, tokens: &mut TokenStream) { | |
1167 | tokens.append_all(self.attrs.outer()); | |
1168 | self.dots.to_tokens(tokens); | |
1169 | } | |
1170 | } | |
1171 | ||
1172 | impl ToTokens for Abi { | |
1173 | fn to_tokens(&self, tokens: &mut TokenStream) { | |
1174 | self.extern_token.to_tokens(tokens); | |
1175 | self.name.to_tokens(tokens); | |
1176 | } | |
1177 | } | |
1178 | } |