blob: 7345da7180d0aaf19066bc74c7e519b011da72c9 [file] [log] [blame]
David Tolnayb79ee962016-09-04 09:39:20 -07001use super::*;
2
Alex Crichton62a0a592017-05-22 13:58:53 -07003ast_enum_of_structs! {
4 /// The different kinds of types recognized by the compiler
5 pub enum Ty {
6 /// A variable-length array (`[T]`)
7 pub Slice(TySlice {
8 pub ty: Box<Ty>,
9 }),
10 /// A fixed length array (`[T; n]`)
11 pub Array(TyArray {
12 pub ty: Box<Ty>,
13 pub amt: ConstExpr,
14 }),
15 /// A raw pointer (`*const T` or `*mut T`)
16 pub Ptr(TyPtr {
17 pub ty: Box<MutTy>,
18 }),
19 /// A reference (`&'a T` or `&'a mut T`)
20 pub Rptr(TyRptr {
21 pub lifetime: Option<Lifetime>,
22 pub ty: Box<MutTy>,
23 }),
24 /// A bare function (e.g. `fn(usize) -> bool`)
25 pub BareFn(TyBareFn {
26 pub ty: Box<BareFnTy>,
27 }),
28 /// The never type (`!`)
29 pub Never(TyNever {}),
30 /// A tuple (`(A, B, C, D, ...)`)
31 pub Tup(TyTup {
32 pub tys: Vec<Ty>,
33 }),
34 /// A path (`module::module::...::Type`), optionally
35 /// "qualified", e.g. `<Vec<T> as SomeTrait>::SomeType`.
36 ///
37 /// Type parameters are stored in the Path itself
38 pub Path(TyPath {
39 pub qself: Option<QSelf>,
40 pub path: Path,
41 }),
42 /// A trait object type `Bound1 + Bound2 + Bound3`
43 /// where `Bound` is a trait or a lifetime.
44 pub TraitObject(TyTraitObject {
45 pub bounds: Vec<TyParamBound>,
46 }),
47 /// An `impl Bound1 + Bound2 + Bound3` type
48 /// where `Bound` is a trait or a lifetime.
49 pub ImplTrait(TyImplTrait {
50 pub bounds: Vec<TyParamBound>,
51 }),
52 /// No-op; kept solely so that we can pretty-print faithfully
53 pub Paren(TyParen {
54 pub ty: Box<Ty>,
55 }),
56 /// TyKind::Infer means the type should be inferred instead of it having been
57 /// specified. This can appear anywhere in a type.
58 pub Infer(TyInfer {}),
59 /// A macro in the type position.
60 pub Mac(Mac),
61 }
62}
63
64ast_struct! {
65 pub struct MutTy {
66 pub ty: Ty,
67 pub mutability: Mutability,
68 }
69}
70
71ast_enum! {
Alex Crichton2e0229c2017-05-23 09:34:50 -070072 #[cfg_attr(feature = "clone-impls", derive(Copy))]
Alex Crichton62a0a592017-05-22 13:58:53 -070073 pub enum Mutability {
74 Mutable,
75 Immutable,
76 }
77}
78
79ast_struct! {
80 /// A "Path" is essentially Rust's notion of a name.
David Tolnayb79ee962016-09-04 09:39:20 -070081 ///
Alex Crichton62a0a592017-05-22 13:58:53 -070082 /// It's represented as a sequence of identifiers,
83 /// along with a bunch of supporting information.
84 ///
85 /// E.g. `std::cmp::PartialEq`
86 pub struct Path {
87 /// A `::foo` path, is relative to the crate root rather than current
88 /// module (like paths in an import).
89 pub global: bool,
90 /// The segments in the path: the things separated by `::`.
91 pub segments: Vec<PathSegment>,
92 }
David Tolnayb79ee962016-09-04 09:39:20 -070093}
94
David Tolnaydaaf7742016-10-03 11:11:43 -070095impl<T> From<T> for Path
96 where T: Into<PathSegment>
97{
David Tolnay84aa0752016-10-02 23:01:13 -070098 fn from(segment: T) -> Self {
99 Path {
100 global: false,
101 segments: vec![segment.into()],
102 }
103 }
104}
105
Alex Crichton62a0a592017-05-22 13:58:53 -0700106ast_struct! {
107 /// A segment of a path: an identifier, an optional lifetime, and a set of types.
108 ///
109 /// E.g. `std`, `String` or `Box<T>`
110 pub struct PathSegment {
111 /// The identifier portion of this path segment.
112 pub ident: Ident,
113 /// Type/lifetime parameters attached to this path. They come in
114 /// two flavors: `Path<A,B,C>` and `Path(A,B) -> C`. Note that
115 /// this is more than just simple syntactic sugar; the use of
116 /// parens affects the region binding rules, so we preserve the
117 /// distinction.
118 pub parameters: PathParameters,
119 }
David Tolnayb79ee962016-09-04 09:39:20 -0700120}
121
David Tolnaydaaf7742016-10-03 11:11:43 -0700122impl<T> From<T> for PathSegment
123 where T: Into<Ident>
124{
David Tolnay84aa0752016-10-02 23:01:13 -0700125 fn from(ident: T) -> Self {
David Tolnayb79ee962016-09-04 09:39:20 -0700126 PathSegment {
David Tolnay84aa0752016-10-02 23:01:13 -0700127 ident: ident.into(),
David Tolnayb79ee962016-09-04 09:39:20 -0700128 parameters: PathParameters::none(),
129 }
130 }
131}
132
Alex Crichton62a0a592017-05-22 13:58:53 -0700133ast_enum! {
134 /// Parameters of a path segment.
135 ///
136 /// E.g. `<A, B>` as in `Foo<A, B>` or `(A, B)` as in `Foo(A, B)`
137 pub enum PathParameters {
138 /// The `<'a, A, B, C>` in `foo::bar::baz::<'a, A, B, C>`
139 AngleBracketed(AngleBracketedParameterData),
140 /// The `(A, B)` and `C` in `Foo(A, B) -> C`
141 Parenthesized(ParenthesizedParameterData),
142 }
David Tolnayb79ee962016-09-04 09:39:20 -0700143}
144
145impl PathParameters {
146 pub fn none() -> Self {
147 PathParameters::AngleBracketed(AngleBracketedParameterData::default())
148 }
David Tolnay5332d4b2016-10-30 14:25:22 -0700149
150 pub fn is_empty(&self) -> bool {
151 match *self {
152 PathParameters::AngleBracketed(ref bracketed) => {
David Tolnayc1fea502016-10-30 17:54:02 -0700153 bracketed.lifetimes.is_empty() && bracketed.types.is_empty() &&
154 bracketed.bindings.is_empty()
David Tolnay5332d4b2016-10-30 14:25:22 -0700155 }
156 PathParameters::Parenthesized(_) => false,
157 }
158 }
David Tolnayb79ee962016-09-04 09:39:20 -0700159}
160
Alex Crichton62a0a592017-05-22 13:58:53 -0700161ast_struct! {
162 /// A path like `Foo<'a, T>`
163 #[derive(Default)]
164 pub struct AngleBracketedParameterData {
165 /// The lifetime parameters for this path segment.
166 pub lifetimes: Vec<Lifetime>,
167 /// The type parameters for this path segment, if present.
168 pub types: Vec<Ty>,
169 /// Bindings (equality constraints) on associated types, if present.
170 ///
171 /// E.g., `Foo<A=Bar>`.
172 pub bindings: Vec<TypeBinding>,
173 }
174}
175
176ast_struct! {
177 /// Bind a type to an associated type: `A=Foo`.
178 pub struct TypeBinding {
179 pub ident: Ident,
180 pub ty: Ty,
181 }
182}
183
184
185ast_struct! {
186 /// A path like `Foo(A,B) -> C`
187 pub struct ParenthesizedParameterData {
188 /// `(A, B)`
189 pub inputs: Vec<Ty>,
190 /// `C`
191 pub output: Option<Ty>,
192 }
193}
194
195ast_struct! {
196 pub struct PolyTraitRef {
197 /// The `'a` in `<'a> Foo<&'a T>`
198 pub bound_lifetimes: Vec<LifetimeDef>,
199 /// The `Foo<&'a T>` in `<'a> Foo<&'a T>`
200 pub trait_ref: Path,
201 }
202}
203
204ast_struct! {
205 /// The explicit Self type in a "qualified path". The actual
206 /// path, including the trait and the associated item, is stored
207 /// separately. `position` represents the index of the associated
208 /// item qualified with this Self type.
David Tolnayb79ee962016-09-04 09:39:20 -0700209 ///
Alex Crichton62a0a592017-05-22 13:58:53 -0700210 /// ```rust,ignore
211 /// <Vec<T> as a::b::Trait>::AssociatedItem
212 /// ^~~~~ ~~~~~~~~~~~~~~^
213 /// ty position = 3
David Tolnayb79ee962016-09-04 09:39:20 -0700214 ///
Alex Crichton62a0a592017-05-22 13:58:53 -0700215 /// <Vec<T>>::AssociatedItem
216 /// ^~~~~ ^
217 /// ty position = 0
218 /// ```
219 pub struct QSelf {
220 pub ty: Box<Ty>,
221 pub position: usize,
222 }
223}
224
225ast_struct! {
226 pub struct BareFnTy {
227 pub unsafety: Unsafety,
228 pub abi: Option<Abi>,
229 pub lifetimes: Vec<LifetimeDef>,
230 pub inputs: Vec<BareFnArg>,
231 pub output: FunctionRetTy,
232 pub variadic: bool,
233 }
234}
235
236ast_enum! {
Alex Crichton2e0229c2017-05-23 09:34:50 -0700237 #[cfg_attr(feature = "clone-impls", derive(Copy))]
Alex Crichton62a0a592017-05-22 13:58:53 -0700238 pub enum Unsafety {
239 Unsafe,
240 Normal,
241 }
242}
243
244ast_enum! {
245 pub enum Abi {
246 Named(String),
247 Rust,
248 }
249}
250
251ast_struct! {
252 /// An argument in a function type.
253 ///
254 /// E.g. `bar: usize` as in `fn foo(bar: usize)`
255 pub struct BareFnArg {
256 pub name: Option<Ident>,
257 pub ty: Ty,
258 }
259}
260
261
262ast_enum! {
263 pub enum FunctionRetTy {
264 /// Return type is not specified.
265 ///
266 /// Functions default to `()` and
267 /// closures default to inference. Span points to where return
268 /// type would be inserted.
269 Default,
270 /// Everything else
271 Ty(Ty),
272 }
David Tolnayb79ee962016-09-04 09:39:20 -0700273}
274
David Tolnay86eca752016-09-04 11:26:41 -0700275#[cfg(feature = "parsing")]
David Tolnay9d8f1972016-09-04 11:58:48 -0700276pub mod parsing {
277 use super::*;
David Tolnaya6ac1812017-01-23 00:29:11 -0800278 use {TyParamBound, TraitBoundModifier};
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700279 #[cfg(feature = "full")]
280 use ConstExpr;
David Tolnayf945fb52017-02-27 12:53:54 -0800281 #[cfg(feature = "full")]
David Tolnay3cb23a92016-10-07 23:02:21 -0700282 use constant::parsing::const_expr;
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700283 #[cfg(feature = "full")]
284 use expr::parsing::expr;
David Tolnay9d8f1972016-09-04 11:58:48 -0700285 use generics::parsing::{lifetime, lifetime_def, ty_param_bound, bound_lifetimes};
David Tolnay55337722016-09-11 12:58:56 -0700286 use ident::parsing::ident;
David Tolnayb8d8ef52016-10-29 14:30:08 -0700287 use lit::parsing::quoted_string;
David Tolnay0047c712016-12-21 21:59:25 -0500288 use mac::parsing::mac;
David Tolnay9d8f1972016-09-04 11:58:48 -0700289 use std::str;
David Tolnayda4049b2016-09-04 10:59:23 -0700290
David Tolnayb5a7b142016-09-13 22:46:39 -0700291 named!(pub ty -> Ty, alt!(
David Tolnayd040d772016-10-25 21:33:51 -0700292 ty_paren // must be before ty_tup
293 |
David Tolnay0047c712016-12-21 21:59:25 -0500294 ty_mac // must be before ty_path
295 |
David Tolnay4f0f2512016-10-30 09:28:14 -0700296 ty_path // must be before ty_poly_trait_ref
297 |
David Tolnay9d8f1972016-09-04 11:58:48 -0700298 ty_vec
David Tolnayda4049b2016-09-04 10:59:23 -0700299 |
David Tolnayfa94b6f2016-10-05 23:26:11 -0700300 ty_array
David Tolnayb79ee962016-09-04 09:39:20 -0700301 |
David Tolnay9d8f1972016-09-04 11:58:48 -0700302 ty_ptr
303 |
304 ty_rptr
305 |
306 ty_bare_fn
307 |
308 ty_never
309 |
310 ty_tup
311 |
David Tolnay4f0f2512016-10-30 09:28:14 -0700312 ty_poly_trait_ref
David Tolnay9d8f1972016-09-04 11:58:48 -0700313 |
David Tolnay9d8f1972016-09-04 11:58:48 -0700314 ty_impl_trait
David Tolnay9d8f1972016-09-04 11:58:48 -0700315 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700316
David Tolnay0047c712016-12-21 21:59:25 -0500317 named!(ty_mac -> Ty, map!(mac, Ty::Mac));
318
David Tolnayb5a7b142016-09-13 22:46:39 -0700319 named!(ty_vec -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700320 punct!("[") >>
321 elem: ty >>
322 punct!("]") >>
Alex Crichton62a0a592017-05-22 13:58:53 -0700323 (TySlice { ty: Box::new(elem) }.into())
David Tolnay9d8f1972016-09-04 11:58:48 -0700324 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700325
David Tolnayfa94b6f2016-10-05 23:26:11 -0700326 named!(ty_array -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700327 punct!("[") >>
328 elem: ty >>
329 punct!(";") >>
David Tolnay514f1292017-02-27 12:30:57 -0800330 len: array_len >>
David Tolnayc94c38a2016-09-05 17:02:03 -0700331 punct!("]") >>
Alex Crichton62a0a592017-05-22 13:58:53 -0700332 (TyArray { ty: Box::new(elem), amt: len }.into())
David Tolnayfa94b6f2016-10-05 23:26:11 -0700333 ));
334
David Tolnay514f1292017-02-27 12:30:57 -0800335 #[cfg(not(feature = "full"))]
David Tolnayf945fb52017-02-27 12:53:54 -0800336 use constant::parsing::const_expr as array_len;
David Tolnay514f1292017-02-27 12:30:57 -0800337
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700338 #[cfg(feature = "full")]
David Tolnay514f1292017-02-27 12:30:57 -0800339 named!(array_len -> ConstExpr, alt!(
340 terminated!(const_expr, after_array_len)
341 |
342 terminated!(expr, after_array_len) => { ConstExpr::Other }
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700343 ));
344
David Tolnay514f1292017-02-27 12:30:57 -0800345 #[cfg(feature = "full")]
346 named!(after_array_len -> &str, peek!(punct!("]")));
347
David Tolnayb5a7b142016-09-13 22:46:39 -0700348 named!(ty_ptr -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700349 punct!("*") >>
David Tolnayb5a7b142016-09-13 22:46:39 -0700350 mutability: alt!(
David Tolnay10413f02016-09-30 09:12:02 -0700351 keyword!("const") => { |_| Mutability::Immutable }
David Tolnay9d8f1972016-09-04 11:58:48 -0700352 |
David Tolnay10413f02016-09-30 09:12:02 -0700353 keyword!("mut") => { |_| Mutability::Mutable }
David Tolnay9d8f1972016-09-04 11:58:48 -0700354 ) >>
355 target: ty >>
Alex Crichton62a0a592017-05-22 13:58:53 -0700356 (TyPtr {
357 ty: Box::new(MutTy {
358 ty: target,
359 mutability: mutability,
360 }),
361 }.into())
David Tolnay9d8f1972016-09-04 11:58:48 -0700362 ));
363
David Tolnayb5a7b142016-09-13 22:46:39 -0700364 named!(ty_rptr -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700365 punct!("&") >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700366 life: option!(lifetime) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700367 mutability: mutability >>
368 target: ty >>
Alex Crichton62a0a592017-05-22 13:58:53 -0700369 (TyRptr {
370 lifetime: life,
371 ty: Box::new(MutTy {
372 ty: target,
373 mutability: mutability,
374 }),
375 }.into())
David Tolnay9d8f1972016-09-04 11:58:48 -0700376 ));
377
David Tolnayb5a7b142016-09-13 22:46:39 -0700378 named!(ty_bare_fn -> Ty, do_parse!(
David Tolnay4f121832016-10-25 21:33:36 -0700379 lifetimes: opt_vec!(do_parse!(
380 keyword!("for") >>
381 punct!("<") >>
382 lifetimes: terminated_list!(punct!(","), lifetime_def) >>
383 punct!(">") >>
384 (lifetimes)
David Tolnay6b7aaf02016-09-04 10:39:25 -0700385 )) >>
David Tolnayb8d8ef52016-10-29 14:30:08 -0700386 unsafety: unsafety >>
387 abi: option!(abi) >>
David Tolnay4f121832016-10-25 21:33:36 -0700388 keyword!("fn") >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700389 punct!("(") >>
David Tolnay292e6002016-10-29 22:03:51 -0700390 inputs: separated_list!(punct!(","), fn_arg) >>
391 trailing_comma: option!(punct!(",")) >>
392 variadic: option!(cond_reduce!(trailing_comma.is_some(), punct!("..."))) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700393 punct!(")") >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700394 output: option!(preceded!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700395 punct!("->"),
396 ty
397 )) >>
Alex Crichton62a0a592017-05-22 13:58:53 -0700398 (TyBareFn {
399 ty: Box::new(BareFnTy {
400 unsafety: unsafety,
401 abi: abi,
402 lifetimes: lifetimes,
403 inputs: inputs,
404 output: match output {
405 Some(ty) => FunctionRetTy::Ty(ty),
406 None => FunctionRetTy::Default,
407 },
408 variadic: variadic.is_some(),
409 }),
410 }.into())
David Tolnay9d8f1972016-09-04 11:58:48 -0700411 ));
412
Alex Crichton62a0a592017-05-22 13:58:53 -0700413 named!(ty_never -> Ty, map!(punct!("!"), |_| TyNever {}.into()));
David Tolnay9d8f1972016-09-04 11:58:48 -0700414
David Tolnayb5a7b142016-09-13 22:46:39 -0700415 named!(ty_tup -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700416 punct!("(") >>
David Tolnayff46fd22016-10-08 13:53:28 -0700417 elems: terminated_list!(punct!(","), ty) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700418 punct!(")") >>
Alex Crichton62a0a592017-05-22 13:58:53 -0700419 (TyTup { tys: elems }.into())
David Tolnay9d8f1972016-09-04 11:58:48 -0700420 ));
421
David Tolnay6414da72016-10-08 00:55:17 -0700422 named!(ty_path -> Ty, do_parse!(
423 qpath: qpath >>
David Tolnayf6c74402016-10-08 02:31:26 -0700424 parenthesized: cond!(
Alex Crichton2e0229c2017-05-23 09:34:50 -0700425 qpath.1.segments.last().unwrap().parameters.is_empty(),
David Tolnayf6c74402016-10-08 02:31:26 -0700426 option!(parenthesized_parameter_data)
427 ) >>
David Tolnay6414da72016-10-08 00:55:17 -0700428 bounds: many0!(preceded!(punct!("+"), ty_param_bound)) >>
429 ({
David Tolnayf6c74402016-10-08 02:31:26 -0700430 let (qself, mut path) = qpath;
431 if let Some(Some(parenthesized)) = parenthesized {
432 path.segments.last_mut().unwrap().parameters = parenthesized;
433 }
David Tolnay6414da72016-10-08 00:55:17 -0700434 if bounds.is_empty() {
Alex Crichton62a0a592017-05-22 13:58:53 -0700435 TyPath { qself: qself, path: path }.into()
David Tolnay6414da72016-10-08 00:55:17 -0700436 } else {
David Tolnay02c907f2017-01-23 00:06:37 -0800437 let path = TyParamBound::Trait(
438 PolyTraitRef {
439 bound_lifetimes: Vec::new(),
440 trait_ref: path,
441 },
442 TraitBoundModifier::None,
443 );
444 let bounds = Some(path).into_iter().chain(bounds).collect();
Alex Crichton62a0a592017-05-22 13:58:53 -0700445 TyTraitObject { bounds: bounds }.into()
David Tolnay6414da72016-10-08 00:55:17 -0700446 }
447 })
448 ));
David Tolnay9d8f1972016-09-04 11:58:48 -0700449
David Tolnayf6c74402016-10-08 02:31:26 -0700450 named!(parenthesized_parameter_data -> PathParameters, do_parse!(
451 punct!("(") >>
David Tolnayff46fd22016-10-08 13:53:28 -0700452 inputs: terminated_list!(punct!(","), ty) >>
David Tolnayf6c74402016-10-08 02:31:26 -0700453 punct!(")") >>
454 output: option!(preceded!(
455 punct!("->"),
456 ty
457 )) >>
458 (PathParameters::Parenthesized(
459 ParenthesizedParameterData {
460 inputs: inputs,
461 output: output,
462 },
463 ))
464 ));
465
David Tolnay9636c052016-10-02 17:11:17 -0700466 named!(pub qpath -> (Option<QSelf>, Path), alt!(
467 map!(path, |p| (None, p))
468 |
469 do_parse!(
470 punct!("<") >>
471 this: map!(ty, Box::new) >>
472 path: option!(preceded!(
473 keyword!("as"),
474 path
475 )) >>
476 punct!(">") >>
477 punct!("::") >>
478 rest: separated_nonempty_list!(punct!("::"), path_segment) >>
479 ({
480 match path {
481 Some(mut path) => {
482 let pos = path.segments.len();
483 path.segments.extend(rest);
484 (Some(QSelf { ty: this, position: pos }), path)
485 }
486 None => {
487 (Some(QSelf { ty: this, position: 0 }), Path {
488 global: false,
489 segments: rest,
490 })
491 }
David Tolnayb79ee962016-09-04 09:39:20 -0700492 }
David Tolnay9636c052016-10-02 17:11:17 -0700493 })
494 )
David Tolnay6cd2a232016-10-24 22:41:08 -0700495 |
496 map!(keyword!("self"), |_| (None, "self".into()))
David Tolnay9d8f1972016-09-04 11:58:48 -0700497 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700498
David Tolnay4f0f2512016-10-30 09:28:14 -0700499 named!(ty_poly_trait_ref -> Ty, map!(
David Tolnay8eb6c452016-10-30 13:19:15 -0700500 separated_nonempty_list!(punct!("+"), ty_param_bound),
Alex Crichton62a0a592017-05-22 13:58:53 -0700501 |x| TyTraitObject { bounds: x }.into()
David Tolnay6414da72016-10-08 00:55:17 -0700502 ));
503
David Tolnayb5a7b142016-09-13 22:46:39 -0700504 named!(ty_impl_trait -> Ty, do_parse!(
David Tolnay10413f02016-09-30 09:12:02 -0700505 keyword!("impl") >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700506 elem: separated_nonempty_list!(punct!("+"), ty_param_bound) >>
Alex Crichton62a0a592017-05-22 13:58:53 -0700507 (TyImplTrait { bounds: elem }.into())
David Tolnay9d8f1972016-09-04 11:58:48 -0700508 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700509
David Tolnayb5a7b142016-09-13 22:46:39 -0700510 named!(ty_paren -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700511 punct!("(") >>
512 elem: ty >>
513 punct!(")") >>
Alex Crichton62a0a592017-05-22 13:58:53 -0700514 (TyParen { ty: Box::new(elem) }.into())
David Tolnay9d8f1972016-09-04 11:58:48 -0700515 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700516
David Tolnay47a877c2016-10-01 16:50:55 -0700517 named!(pub mutability -> Mutability, alt!(
David Tolnaybd76e572016-10-02 13:43:16 -0700518 keyword!("mut") => { |_| Mutability::Mutable }
David Tolnayf6ccb832016-09-04 15:00:56 -0700519 |
520 epsilon!() => { |_| Mutability::Immutable }
David Tolnay9d8f1972016-09-04 11:58:48 -0700521 ));
522
David Tolnayb5a7b142016-09-13 22:46:39 -0700523 named!(pub path -> Path, do_parse!(
David Tolnayf6ccb832016-09-04 15:00:56 -0700524 global: option!(punct!("::")) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700525 segments: separated_nonempty_list!(punct!("::"), path_segment) >>
526 (Path {
527 global: global.is_some(),
528 segments: segments,
529 })
530 ));
531
David Tolnay9636c052016-10-02 17:11:17 -0700532 named!(path_segment -> PathSegment, alt!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700533 do_parse!(
David Tolnay9636c052016-10-02 17:11:17 -0700534 id: option!(ident) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700535 punct!("<") >>
536 lifetimes: separated_list!(punct!(","), lifetime) >>
537 types: opt_vec!(preceded!(
538 cond!(!lifetimes.is_empty(), punct!(",")),
539 separated_nonempty_list!(
540 punct!(","),
David Tolnay1f16b602017-02-07 20:06:55 -0500541 terminated!(ty, not!(punct!("=")))
David Tolnay9d8f1972016-09-04 11:58:48 -0700542 )
543 )) >>
544 bindings: opt_vec!(preceded!(
545 cond!(!lifetimes.is_empty() || !types.is_empty(), punct!(",")),
546 separated_nonempty_list!(punct!(","), type_binding)
547 )) >>
David Tolnay82a47d52016-10-30 13:01:38 -0700548 cond!(!lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty(), option!(punct!(","))) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700549 punct!(">") >>
550 (PathSegment {
David Tolnay9636c052016-10-02 17:11:17 -0700551 ident: id.unwrap_or_else(|| "".into()),
David Tolnay9d8f1972016-09-04 11:58:48 -0700552 parameters: PathParameters::AngleBracketed(
553 AngleBracketedParameterData {
554 lifetimes: lifetimes,
555 types: types,
556 bindings: bindings,
557 }
558 ),
559 })
560 )
561 |
David Tolnay84aa0752016-10-02 23:01:13 -0700562 map!(ident, Into::into)
David Tolnay77807222016-10-24 22:30:15 -0700563 |
David Tolnaye14e3be2016-10-24 22:53:07 -0700564 map!(alt!(
565 keyword!("super")
566 |
567 keyword!("self")
568 |
569 keyword!("Self")
570 ), Into::into)
David Tolnay9d8f1972016-09-04 11:58:48 -0700571 ));
572
Arnavionf2dada12017-04-20 23:55:20 -0700573 named!(pub mod_style_path -> Path, do_parse!(
574 global: option!(punct!("::")) >>
575 segments: separated_nonempty_list!(punct!("::"), mod_style_path_segment) >>
576 (Path {
577 global: global.is_some(),
578 segments: segments,
579 })
580 ));
581
582 named!(mod_style_path_segment -> PathSegment, alt!(
583 map!(ident, Into::into)
584 |
585 map!(alt!(
586 keyword!("super")
587 |
588 keyword!("self")
589 |
590 keyword!("Self")
591 ), Into::into)
592 ));
593
David Tolnayb5a7b142016-09-13 22:46:39 -0700594 named!(type_binding -> TypeBinding, do_parse!(
David Tolnay55337722016-09-11 12:58:56 -0700595 id: ident >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700596 punct!("=") >>
597 ty: ty >>
598 (TypeBinding {
David Tolnay55337722016-09-11 12:58:56 -0700599 ident: id,
David Tolnay9d8f1972016-09-04 11:58:48 -0700600 ty: ty,
601 })
602 ));
603
David Tolnayb5a7b142016-09-13 22:46:39 -0700604 named!(pub poly_trait_ref -> PolyTraitRef, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700605 bound_lifetimes: bound_lifetimes >>
606 trait_ref: path >>
David Tolnay4f0f2512016-10-30 09:28:14 -0700607 parenthesized: option!(cond_reduce!(
Alex Crichton2e0229c2017-05-23 09:34:50 -0700608 trait_ref.segments.last().unwrap().parameters.is_empty(),
David Tolnay4f0f2512016-10-30 09:28:14 -0700609 parenthesized_parameter_data
610 )) >>
David Tolnayf6c74402016-10-08 02:31:26 -0700611 ({
612 let mut trait_ref = trait_ref;
David Tolnay4f0f2512016-10-30 09:28:14 -0700613 if let Some(parenthesized) = parenthesized {
David Tolnayf6c74402016-10-08 02:31:26 -0700614 trait_ref.segments.last_mut().unwrap().parameters = parenthesized;
615 }
616 PolyTraitRef {
617 bound_lifetimes: bound_lifetimes,
618 trait_ref: trait_ref,
619 }
David Tolnay9d8f1972016-09-04 11:58:48 -0700620 })
621 ));
622
David Tolnay62f374c2016-10-02 13:37:00 -0700623 named!(pub fn_arg -> BareFnArg, do_parse!(
David Tolnayb0417d72016-10-25 21:46:35 -0700624 name: option!(do_parse!(
625 name: ident >>
626 punct!(":") >>
David Tolnay1f16b602017-02-07 20:06:55 -0500627 not!(tag!(":")) >> // not ::
David Tolnayb0417d72016-10-25 21:46:35 -0700628 (name)
629 )) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700630 ty: ty >>
David Tolnay62f374c2016-10-02 13:37:00 -0700631 (BareFnArg {
632 name: name,
David Tolnay9d8f1972016-09-04 11:58:48 -0700633 ty: ty,
634 })
635 ));
David Tolnayb8d8ef52016-10-29 14:30:08 -0700636
637 named!(pub unsafety -> Unsafety, alt!(
638 keyword!("unsafe") => { |_| Unsafety::Unsafe }
639 |
640 epsilon!() => { |_| Unsafety::Normal }
641 ));
642
643 named!(pub abi -> Abi, do_parse!(
644 keyword!("extern") >>
645 name: option!(quoted_string) >>
646 (match name {
647 Some(name) => Abi::Named(name),
David Tolnay76195ce2016-10-30 16:53:48 -0700648 None => Abi::Rust,
David Tolnayb8d8ef52016-10-29 14:30:08 -0700649 })
650 ));
David Tolnay9d8f1972016-09-04 11:58:48 -0700651}
David Tolnay87d0b442016-09-04 11:52:12 -0700652
653#[cfg(feature = "printing")]
654mod printing {
655 use super::*;
656 use quote::{Tokens, ToTokens};
657
Alex Crichton62a0a592017-05-22 13:58:53 -0700658 impl ToTokens for TySlice {
David Tolnay87d0b442016-09-04 11:52:12 -0700659 fn to_tokens(&self, tokens: &mut Tokens) {
Alex Crichton62a0a592017-05-22 13:58:53 -0700660 tokens.append("[");
661 self.ty.to_tokens(tokens);
662 tokens.append("]");
663 }
664 }
665
666 impl ToTokens for TyArray {
667 fn to_tokens(&self, tokens: &mut Tokens) {
668 tokens.append("[");
669 self.ty.to_tokens(tokens);
670 tokens.append(";");
671 self.amt.to_tokens(tokens);
672 tokens.append("]");
673 }
674 }
675
676 impl ToTokens for TyPtr {
677 fn to_tokens(&self, tokens: &mut Tokens) {
678 tokens.append("*");
679 match self.ty.mutability {
680 Mutability::Mutable => tokens.append("mut"),
681 Mutability::Immutable => tokens.append("const"),
David Tolnay87d0b442016-09-04 11:52:12 -0700682 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700683 self.ty.ty.to_tokens(tokens);
684 }
685 }
686
687 impl ToTokens for TyRptr {
688 fn to_tokens(&self, tokens: &mut Tokens) {
689 tokens.append("&");
690 self.lifetime.to_tokens(tokens);
691 match self.ty.mutability {
692 Mutability::Mutable => tokens.append("mut"),
693 Mutability::Immutable => {}
694 }
695 self.ty.ty.to_tokens(tokens);
696 }
697 }
698
699 impl ToTokens for TyBareFn {
700 fn to_tokens(&self, tokens: &mut Tokens) {
701 self.ty.to_tokens(tokens)
702 }
703 }
704
705 impl ToTokens for TyNever {
706 fn to_tokens(&self, tokens: &mut Tokens) {
707 tokens.append("!");
708 }
709 }
710
711 impl ToTokens for TyTup {
712 fn to_tokens(&self, tokens: &mut Tokens) {
713 tokens.append("(");
714 tokens.append_separated(&self.tys, ",");
715 if self.tys.len() == 1 {
716 tokens.append(",");
717 }
718 tokens.append(")");
719 }
720 }
721
722 impl ToTokens for TyPath {
723 fn to_tokens(&self, tokens: &mut Tokens) {
724 let qself = match self.qself {
725 Some(ref qself) => qself,
726 None => return self.path.to_tokens(tokens),
727 };
728 tokens.append("<");
729 qself.ty.to_tokens(tokens);
730 if qself.position > 0 {
731 tokens.append("as");
732 for (i, segment) in self.path.segments
733 .iter()
734 .take(qself.position)
735 .enumerate() {
736 if i > 0 || self.path.global {
737 tokens.append("::");
738 }
739 segment.to_tokens(tokens);
740 }
741 }
742 tokens.append(">");
743 for segment in self.path.segments.iter().skip(qself.position) {
744 tokens.append("::");
745 segment.to_tokens(tokens);
746 }
747 }
748 }
749
750 impl ToTokens for TyTraitObject {
751 fn to_tokens(&self, tokens: &mut Tokens) {
752 tokens.append_separated(&self.bounds, "+");
753 }
754 }
755
756 impl ToTokens for TyImplTrait {
757 fn to_tokens(&self, tokens: &mut Tokens) {
758 tokens.append("impl");
759 tokens.append_separated(&self.bounds, "+");
760 }
761 }
762
763 impl ToTokens for TyParen {
764 fn to_tokens(&self, tokens: &mut Tokens) {
765 tokens.append("(");
766 self.ty.to_tokens(tokens);
767 tokens.append(")");
768 }
769 }
770
771 impl ToTokens for TyInfer {
772 fn to_tokens(&self, tokens: &mut Tokens) {
773 tokens.append("_");
David Tolnay87d0b442016-09-04 11:52:12 -0700774 }
775 }
776
David Tolnay47a877c2016-10-01 16:50:55 -0700777 impl ToTokens for Mutability {
778 fn to_tokens(&self, tokens: &mut Tokens) {
779 if let Mutability::Mutable = *self {
780 tokens.append("mut");
781 }
782 }
783 }
784
David Tolnay87d0b442016-09-04 11:52:12 -0700785 impl ToTokens for Path {
786 fn to_tokens(&self, tokens: &mut Tokens) {
787 for (i, segment) in self.segments.iter().enumerate() {
788 if i > 0 || self.global {
789 tokens.append("::");
790 }
791 segment.to_tokens(tokens);
792 }
793 }
794 }
795
796 impl ToTokens for PathSegment {
797 fn to_tokens(&self, tokens: &mut Tokens) {
798 self.ident.to_tokens(tokens);
David Tolnay5332d4b2016-10-30 14:25:22 -0700799 if self.ident.as_ref().is_empty() && self.parameters.is_empty() {
800 tokens.append("<");
801 tokens.append(">");
802 } else {
803 self.parameters.to_tokens(tokens);
804 }
David Tolnay87d0b442016-09-04 11:52:12 -0700805 }
806 }
807
808 impl ToTokens for PathParameters {
809 fn to_tokens(&self, tokens: &mut Tokens) {
810 match *self {
811 PathParameters::AngleBracketed(ref parameters) => {
812 parameters.to_tokens(tokens);
813 }
814 PathParameters::Parenthesized(ref parameters) => {
815 parameters.to_tokens(tokens);
816 }
817 }
818 }
819 }
820
821 impl ToTokens for AngleBracketedParameterData {
822 fn to_tokens(&self, tokens: &mut Tokens) {
823 let has_lifetimes = !self.lifetimes.is_empty();
824 let has_types = !self.types.is_empty();
825 let has_bindings = !self.bindings.is_empty();
826 if !has_lifetimes && !has_types && !has_bindings {
827 return;
828 }
829
830 tokens.append("<");
831
832 let mut first = true;
833 for lifetime in &self.lifetimes {
834 if !first {
835 tokens.append(",");
836 }
837 lifetime.to_tokens(tokens);
838 first = false;
839 }
840 for ty in &self.types {
841 if !first {
842 tokens.append(",");
843 }
844 ty.to_tokens(tokens);
845 first = false;
846 }
847 for binding in &self.bindings {
848 if !first {
849 tokens.append(",");
850 }
851 binding.to_tokens(tokens);
852 first = false;
853 }
854
855 tokens.append(">");
856 }
857 }
858
859 impl ToTokens for TypeBinding {
860 fn to_tokens(&self, tokens: &mut Tokens) {
861 self.ident.to_tokens(tokens);
862 tokens.append("=");
863 self.ty.to_tokens(tokens);
864 }
865 }
866
867 impl ToTokens for ParenthesizedParameterData {
868 fn to_tokens(&self, tokens: &mut Tokens) {
869 tokens.append("(");
David Tolnay94ebdf92016-09-04 13:33:16 -0700870 tokens.append_separated(&self.inputs, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700871 tokens.append(")");
872 if let Some(ref output) = self.output {
873 tokens.append("->");
874 output.to_tokens(tokens);
875 }
876 }
877 }
878
879 impl ToTokens for PolyTraitRef {
880 fn to_tokens(&self, tokens: &mut Tokens) {
881 if !self.bound_lifetimes.is_empty() {
David Tolnaye8796aa2016-09-04 14:48:22 -0700882 tokens.append("for");
David Tolnay87d0b442016-09-04 11:52:12 -0700883 tokens.append("<");
David Tolnay94ebdf92016-09-04 13:33:16 -0700884 tokens.append_separated(&self.bound_lifetimes, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700885 tokens.append(">");
886 }
887 self.trait_ref.to_tokens(tokens);
888 }
889 }
890
891 impl ToTokens for BareFnTy {
892 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay87d0b442016-09-04 11:52:12 -0700893 if !self.lifetimes.is_empty() {
David Tolnay4f121832016-10-25 21:33:36 -0700894 tokens.append("for");
David Tolnay87d0b442016-09-04 11:52:12 -0700895 tokens.append("<");
David Tolnay42602292016-10-01 22:25:45 -0700896 tokens.append_separated(&self.lifetimes, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700897 tokens.append(">");
898 }
David Tolnayb8d8ef52016-10-29 14:30:08 -0700899 self.unsafety.to_tokens(tokens);
900 self.abi.to_tokens(tokens);
David Tolnay4f121832016-10-25 21:33:36 -0700901 tokens.append("fn");
David Tolnay87d0b442016-09-04 11:52:12 -0700902 tokens.append("(");
David Tolnay42602292016-10-01 22:25:45 -0700903 tokens.append_separated(&self.inputs, ",");
David Tolnay292e6002016-10-29 22:03:51 -0700904 if self.variadic {
905 if !self.inputs.is_empty() {
906 tokens.append(",");
907 }
908 tokens.append("...");
909 }
David Tolnay87d0b442016-09-04 11:52:12 -0700910 tokens.append(")");
David Tolnay42602292016-10-01 22:25:45 -0700911 if let FunctionRetTy::Ty(ref ty) = self.output {
912 tokens.append("->");
913 ty.to_tokens(tokens);
914 }
915 }
916 }
917
David Tolnay62f374c2016-10-02 13:37:00 -0700918 impl ToTokens for BareFnArg {
David Tolnay42602292016-10-01 22:25:45 -0700919 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay62f374c2016-10-02 13:37:00 -0700920 if let Some(ref name) = self.name {
921 name.to_tokens(tokens);
David Tolnay42602292016-10-01 22:25:45 -0700922 tokens.append(":");
923 }
924 self.ty.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700925 }
926 }
David Tolnayb8d8ef52016-10-29 14:30:08 -0700927
928 impl ToTokens for Unsafety {
929 fn to_tokens(&self, tokens: &mut Tokens) {
930 match *self {
931 Unsafety::Unsafe => tokens.append("unsafe"),
932 Unsafety::Normal => {
933 // nothing
934 }
935 }
936 }
937 }
938
939 impl ToTokens for Abi {
940 fn to_tokens(&self, tokens: &mut Tokens) {
941 tokens.append("extern");
942 match *self {
943 Abi::Named(ref named) => named.to_tokens(tokens),
David Tolnay76195ce2016-10-30 16:53:48 -0700944 Abi::Rust => {}
David Tolnayb8d8ef52016-10-29 14:30:08 -0700945 }
946 }
947 }
David Tolnay87d0b442016-09-04 11:52:12 -0700948}