blob: 2440a28f2bf20c5195e1e0959c085a4513cb78cc [file] [log] [blame]
David Tolnayb79ee962016-09-04 09:39:20 -07001use super::*;
2
David Tolnay771ecf42016-09-23 19:26:37 -07003/// The different kinds of types recognized by the compiler
David Tolnay9bf4af82017-01-07 11:17:46 -08004#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnayb79ee962016-09-04 09:39:20 -07005pub enum Ty {
6 /// A variable-length array (`[T]`)
David Tolnay16709ba2016-10-05 23:11:32 -07007 Slice(Box<Ty>),
David Tolnayb79ee962016-09-04 09:39:20 -07008 /// A fixed length array (`[T; n]`)
David Tolnay3cb23a92016-10-07 23:02:21 -07009 Array(Box<Ty>, ConstExpr),
David Tolnayb79ee962016-09-04 09:39:20 -070010 /// A raw pointer (`*const T` or `*mut T`)
11 Ptr(Box<MutTy>),
12 /// A reference (`&'a T` or `&'a mut T`)
13 Rptr(Option<Lifetime>, Box<MutTy>),
14 /// A bare function (e.g. `fn(usize) -> bool`)
15 BareFn(Box<BareFnTy>),
16 /// The never type (`!`)
17 Never,
18 /// A tuple (`(A, B, C, D, ...)`)
19 Tup(Vec<Ty>),
20 /// A path (`module::module::...::Type`), optionally
21 /// "qualified", e.g. `<Vec<T> as SomeTrait>::SomeType`.
22 ///
23 /// Type parameters are stored in the Path itself
24 Path(Option<QSelf>, Path),
David Tolnay02c907f2017-01-23 00:06:37 -080025 /// A trait object type `Bound1 + Bound2 + Bound3`
26 /// where `Bound` is a trait or a lifetime.
27 TraitObject(Vec<TyParamBound>),
28 /// An `impl Bound1 + Bound2 + Bound3` type
29 /// where `Bound` is a trait or a lifetime.
David Tolnayb79ee962016-09-04 09:39:20 -070030 ImplTrait(Vec<TyParamBound>),
31 /// No-op; kept solely so that we can pretty-print faithfully
32 Paren(Box<Ty>),
33 /// TyKind::Infer means the type should be inferred instead of it having been
34 /// specified. This can appear anywhere in a type.
35 Infer,
David Tolnay0047c712016-12-21 21:59:25 -050036 /// A macro in the type position.
37 Mac(Mac),
38}
39
David Tolnay9bf4af82017-01-07 11:17:46 -080040#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnayb79ee962016-09-04 09:39:20 -070041pub struct MutTy {
42 pub ty: Ty,
43 pub mutability: Mutability,
44}
45
David Tolnay9bf4af82017-01-07 11:17:46 -080046#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
David Tolnayb79ee962016-09-04 09:39:20 -070047pub enum Mutability {
48 Mutable,
49 Immutable,
50}
51
David Tolnay771ecf42016-09-23 19:26:37 -070052/// A "Path" is essentially Rust's notion of a name.
53///
54/// It's represented as a sequence of identifiers,
55/// along with a bunch of supporting information.
56///
57/// E.g. `std::cmp::PartialEq`
David Tolnay9bf4af82017-01-07 11:17:46 -080058#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnayb79ee962016-09-04 09:39:20 -070059pub struct Path {
David Tolnayf06fdde2016-12-22 17:07:59 -050060 /// A `::foo` path, is relative to the crate root rather than current
61 /// module (like paths in an import).
David Tolnayb79ee962016-09-04 09:39:20 -070062 pub global: bool,
David Tolnayf06fdde2016-12-22 17:07:59 -050063 /// The segments in the path: the things separated by `::`.
David Tolnayb79ee962016-09-04 09:39:20 -070064 pub segments: Vec<PathSegment>,
65}
66
David Tolnaydaaf7742016-10-03 11:11:43 -070067impl<T> From<T> for Path
68 where T: Into<PathSegment>
69{
David Tolnay84aa0752016-10-02 23:01:13 -070070 fn from(segment: T) -> Self {
71 Path {
72 global: false,
73 segments: vec![segment.into()],
74 }
75 }
76}
77
David Tolnayb79ee962016-09-04 09:39:20 -070078/// A segment of a path: an identifier, an optional lifetime, and a set of types.
79///
80/// E.g. `std`, `String` or `Box<T>`
David Tolnay9bf4af82017-01-07 11:17:46 -080081#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnayb79ee962016-09-04 09:39:20 -070082pub struct PathSegment {
David Tolnayf06fdde2016-12-22 17:07:59 -050083 /// The identifier portion of this path segment.
David Tolnayb79ee962016-09-04 09:39:20 -070084 pub ident: Ident,
David Tolnayf06fdde2016-12-22 17:07:59 -050085 /// Type/lifetime parameters attached to this path. They come in
86 /// two flavors: `Path<A,B,C>` and `Path(A,B) -> C`. Note that
87 /// this is more than just simple syntactic sugar; the use of
88 /// parens affects the region binding rules, so we preserve the
89 /// distinction.
David Tolnayb79ee962016-09-04 09:39:20 -070090 pub parameters: PathParameters,
91}
92
David Tolnaydaaf7742016-10-03 11:11:43 -070093impl<T> From<T> for PathSegment
94 where T: Into<Ident>
95{
David Tolnay84aa0752016-10-02 23:01:13 -070096 fn from(ident: T) -> Self {
David Tolnayb79ee962016-09-04 09:39:20 -070097 PathSegment {
David Tolnay84aa0752016-10-02 23:01:13 -070098 ident: ident.into(),
David Tolnayb79ee962016-09-04 09:39:20 -070099 parameters: PathParameters::none(),
100 }
101 }
102}
103
104/// Parameters of a path segment.
105///
106/// E.g. `<A, B>` as in `Foo<A, B>` or `(A, B)` as in `Foo(A, B)`
David Tolnay9bf4af82017-01-07 11:17:46 -0800107#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnayb79ee962016-09-04 09:39:20 -0700108pub enum PathParameters {
109 /// The `<'a, A, B, C>` in `foo::bar::baz::<'a, A, B, C>`
110 AngleBracketed(AngleBracketedParameterData),
111 /// The `(A, B)` and `C` in `Foo(A, B) -> C`
112 Parenthesized(ParenthesizedParameterData),
113}
114
115impl PathParameters {
116 pub fn none() -> Self {
117 PathParameters::AngleBracketed(AngleBracketedParameterData::default())
118 }
David Tolnay5332d4b2016-10-30 14:25:22 -0700119
120 pub fn is_empty(&self) -> bool {
121 match *self {
122 PathParameters::AngleBracketed(ref bracketed) => {
David Tolnayc1fea502016-10-30 17:54:02 -0700123 bracketed.lifetimes.is_empty() && bracketed.types.is_empty() &&
124 bracketed.bindings.is_empty()
David Tolnay5332d4b2016-10-30 14:25:22 -0700125 }
126 PathParameters::Parenthesized(_) => false,
127 }
128 }
David Tolnayb79ee962016-09-04 09:39:20 -0700129}
130
131/// A path like `Foo<'a, T>`
David Tolnay9bf4af82017-01-07 11:17:46 -0800132#[derive(Debug, Clone, Eq, PartialEq, Default, Hash)]
David Tolnayb79ee962016-09-04 09:39:20 -0700133pub struct AngleBracketedParameterData {
134 /// The lifetime parameters for this path segment.
135 pub lifetimes: Vec<Lifetime>,
136 /// The type parameters for this path segment, if present.
137 pub types: Vec<Ty>,
138 /// Bindings (equality constraints) on associated types, if present.
139 ///
140 /// E.g., `Foo<A=Bar>`.
141 pub bindings: Vec<TypeBinding>,
142}
143
144/// Bind a type to an associated type: `A=Foo`.
David Tolnay9bf4af82017-01-07 11:17:46 -0800145#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnayb79ee962016-09-04 09:39:20 -0700146pub struct TypeBinding {
147 pub ident: Ident,
148 pub ty: Ty,
149}
150
151/// A path like `Foo(A,B) -> C`
David Tolnay9bf4af82017-01-07 11:17:46 -0800152#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnayb79ee962016-09-04 09:39:20 -0700153pub struct ParenthesizedParameterData {
154 /// `(A, B)`
155 pub inputs: Vec<Ty>,
156 /// `C`
157 pub output: Option<Ty>,
158}
159
David Tolnay9bf4af82017-01-07 11:17:46 -0800160#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnayb79ee962016-09-04 09:39:20 -0700161pub struct PolyTraitRef {
162 /// The `'a` in `<'a> Foo<&'a T>`
163 pub bound_lifetimes: Vec<LifetimeDef>,
164 /// The `Foo<&'a T>` in `<'a> Foo<&'a T>`
165 pub trait_ref: Path,
166}
167
168/// The explicit Self type in a "qualified path". The actual
169/// path, including the trait and the associated item, is stored
170/// separately. `position` represents the index of the associated
171/// item qualified with this Self type.
172///
173/// ```rust,ignore
174/// <Vec<T> as a::b::Trait>::AssociatedItem
175/// ^~~~~ ~~~~~~~~~~~~~~^
176/// ty position = 3
177///
178/// <Vec<T>>::AssociatedItem
179/// ^~~~~ ^
180/// ty position = 0
181/// ```
David Tolnay9bf4af82017-01-07 11:17:46 -0800182#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnayb79ee962016-09-04 09:39:20 -0700183pub struct QSelf {
184 pub ty: Box<Ty>,
David Tolnaydaaf7742016-10-03 11:11:43 -0700185 pub position: usize,
David Tolnayb79ee962016-09-04 09:39:20 -0700186}
187
David Tolnay9bf4af82017-01-07 11:17:46 -0800188#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnayb79ee962016-09-04 09:39:20 -0700189pub struct BareFnTy {
David Tolnayb8d8ef52016-10-29 14:30:08 -0700190 pub unsafety: Unsafety,
191 pub abi: Option<Abi>,
David Tolnayb79ee962016-09-04 09:39:20 -0700192 pub lifetimes: Vec<LifetimeDef>,
David Tolnay62f374c2016-10-02 13:37:00 -0700193 pub inputs: Vec<BareFnArg>,
David Tolnayb79ee962016-09-04 09:39:20 -0700194 pub output: FunctionRetTy,
David Tolnay292e6002016-10-29 22:03:51 -0700195 pub variadic: bool,
David Tolnayb79ee962016-09-04 09:39:20 -0700196}
197
David Tolnay9bf4af82017-01-07 11:17:46 -0800198#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
David Tolnayb8d8ef52016-10-29 14:30:08 -0700199pub enum Unsafety {
200 Unsafe,
201 Normal,
202}
203
David Tolnay9bf4af82017-01-07 11:17:46 -0800204#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnayb8d8ef52016-10-29 14:30:08 -0700205pub enum Abi {
206 Named(String),
David Tolnay76195ce2016-10-30 16:53:48 -0700207 Rust,
David Tolnayb8d8ef52016-10-29 14:30:08 -0700208}
209
David Tolnay62f374c2016-10-02 13:37:00 -0700210/// An argument in a function type.
David Tolnayb79ee962016-09-04 09:39:20 -0700211///
212/// E.g. `bar: usize` as in `fn foo(bar: usize)`
David Tolnay9bf4af82017-01-07 11:17:46 -0800213#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnay62f374c2016-10-02 13:37:00 -0700214pub struct BareFnArg {
215 pub name: Option<Ident>,
David Tolnayb79ee962016-09-04 09:39:20 -0700216 pub ty: Ty,
217}
218
David Tolnay9bf4af82017-01-07 11:17:46 -0800219#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnayb79ee962016-09-04 09:39:20 -0700220pub enum FunctionRetTy {
221 /// Return type is not specified.
222 ///
223 /// Functions default to `()` and
224 /// closures default to inference. Span points to where return
225 /// type would be inserted.
226 Default,
227 /// Everything else
228 Ty(Ty),
229}
230
David Tolnay86eca752016-09-04 11:26:41 -0700231#[cfg(feature = "parsing")]
David Tolnay9d8f1972016-09-04 11:58:48 -0700232pub mod parsing {
233 use super::*;
David Tolnaya6ac1812017-01-23 00:29:11 -0800234 use {TyParamBound, TraitBoundModifier};
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700235 #[cfg(feature = "full")]
236 use ConstExpr;
David Tolnayf945fb52017-02-27 12:53:54 -0800237 #[cfg(feature = "full")]
David Tolnay3cb23a92016-10-07 23:02:21 -0700238 use constant::parsing::const_expr;
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700239 #[cfg(feature = "full")]
240 use expr::parsing::expr;
David Tolnay9d8f1972016-09-04 11:58:48 -0700241 use generics::parsing::{lifetime, lifetime_def, ty_param_bound, bound_lifetimes};
David Tolnay55337722016-09-11 12:58:56 -0700242 use ident::parsing::ident;
Michael Layzell416724e2017-05-24 21:12:34 -0400243 use lit::parsing::string;
David Tolnay0047c712016-12-21 21:59:25 -0500244 use mac::parsing::mac;
Michael Layzell416724e2017-05-24 21:12:34 -0400245 #[cfg(feature = "full")]
246 use synom::{IResult, TokenTree};
David Tolnayda4049b2016-09-04 10:59:23 -0700247
David Tolnayb5a7b142016-09-13 22:46:39 -0700248 named!(pub ty -> Ty, alt!(
David Tolnayd040d772016-10-25 21:33:51 -0700249 ty_paren // must be before ty_tup
250 |
David Tolnay0047c712016-12-21 21:59:25 -0500251 ty_mac // must be before ty_path
252 |
David Tolnay4f0f2512016-10-30 09:28:14 -0700253 ty_path // must be before ty_poly_trait_ref
254 |
David Tolnay9d8f1972016-09-04 11:58:48 -0700255 ty_vec
David Tolnayda4049b2016-09-04 10:59:23 -0700256 |
David Tolnayfa94b6f2016-10-05 23:26:11 -0700257 ty_array
David Tolnayb79ee962016-09-04 09:39:20 -0700258 |
David Tolnay9d8f1972016-09-04 11:58:48 -0700259 ty_ptr
260 |
261 ty_rptr
262 |
263 ty_bare_fn
264 |
265 ty_never
266 |
267 ty_tup
268 |
David Tolnay4f0f2512016-10-30 09:28:14 -0700269 ty_poly_trait_ref
David Tolnay9d8f1972016-09-04 11:58:48 -0700270 |
David Tolnay9d8f1972016-09-04 11:58:48 -0700271 ty_impl_trait
David Tolnay9d8f1972016-09-04 11:58:48 -0700272 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700273
David Tolnay0047c712016-12-21 21:59:25 -0500274 named!(ty_mac -> Ty, map!(mac, Ty::Mac));
275
Michael Layzell416724e2017-05-24 21:12:34 -0400276 named!(ty_vec -> Ty, delim!(Bracket, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700277 elem: ty >>
David Tolnay16709ba2016-10-05 23:11:32 -0700278 (Ty::Slice(Box::new(elem)))
Michael Layzell416724e2017-05-24 21:12:34 -0400279 )));
David Tolnayb79ee962016-09-04 09:39:20 -0700280
Michael Layzell416724e2017-05-24 21:12:34 -0400281 named!(ty_array -> Ty, delim!(Bracket, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700282 elem: ty >>
283 punct!(";") >>
David Tolnay514f1292017-02-27 12:30:57 -0800284 len: array_len >>
David Tolnayfa94b6f2016-10-05 23:26:11 -0700285 (Ty::Array(Box::new(elem), len))
Michael Layzell416724e2017-05-24 21:12:34 -0400286 )));
David Tolnayfa94b6f2016-10-05 23:26:11 -0700287
David Tolnay514f1292017-02-27 12:30:57 -0800288 #[cfg(not(feature = "full"))]
David Tolnayf945fb52017-02-27 12:53:54 -0800289 use constant::parsing::const_expr as array_len;
David Tolnay514f1292017-02-27 12:30:57 -0800290
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700291 #[cfg(feature = "full")]
David Tolnay514f1292017-02-27 12:30:57 -0800292 named!(array_len -> ConstExpr, alt!(
Michael Layzell416724e2017-05-24 21:12:34 -0400293 terminated!(const_expr, input_end!())
David Tolnay514f1292017-02-27 12:30:57 -0800294 |
Michael Layzell416724e2017-05-24 21:12:34 -0400295 terminated!(expr, input_end!()) => { ConstExpr::Other }
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700296 ));
297
David Tolnayb5a7b142016-09-13 22:46:39 -0700298 named!(ty_ptr -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700299 punct!("*") >>
David Tolnayb5a7b142016-09-13 22:46:39 -0700300 mutability: alt!(
David Tolnay10413f02016-09-30 09:12:02 -0700301 keyword!("const") => { |_| Mutability::Immutable }
David Tolnay9d8f1972016-09-04 11:58:48 -0700302 |
David Tolnay10413f02016-09-30 09:12:02 -0700303 keyword!("mut") => { |_| Mutability::Mutable }
David Tolnay9d8f1972016-09-04 11:58:48 -0700304 ) >>
305 target: ty >>
306 (Ty::Ptr(Box::new(MutTy {
307 ty: target,
308 mutability: mutability,
309 })))
310 ));
311
David Tolnayb5a7b142016-09-13 22:46:39 -0700312 named!(ty_rptr -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700313 punct!("&") >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700314 life: option!(lifetime) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700315 mutability: mutability >>
316 target: ty >>
317 (Ty::Rptr(life, Box::new(MutTy {
318 ty: target,
319 mutability: mutability,
320 })))
321 ));
322
David Tolnayb5a7b142016-09-13 22:46:39 -0700323 named!(ty_bare_fn -> Ty, do_parse!(
David Tolnay4f121832016-10-25 21:33:36 -0700324 lifetimes: opt_vec!(do_parse!(
325 keyword!("for") >>
326 punct!("<") >>
327 lifetimes: terminated_list!(punct!(","), lifetime_def) >>
328 punct!(">") >>
329 (lifetimes)
David Tolnay6b7aaf02016-09-04 10:39:25 -0700330 )) >>
David Tolnayb8d8ef52016-10-29 14:30:08 -0700331 unsafety: unsafety >>
332 abi: option!(abi) >>
David Tolnay4f121832016-10-25 21:33:36 -0700333 keyword!("fn") >>
Michael Layzell416724e2017-05-24 21:12:34 -0400334 inputs_and_variadic: delim!(Parenthesis, do_parse!(
335 inputs: separated_list!(punct!(","), fn_arg) >>
336 trailing_comma: option!(punct!(",")) >>
337 variadic: option!(cond_reduce!(trailing_comma.is_some(), punct!("..."))) >>
338 ((inputs, variadic.is_some()))
339 )) >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700340 output: option!(preceded!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700341 punct!("->"),
342 ty
343 )) >>
344 (Ty::BareFn(Box::new(BareFnTy {
David Tolnayb8d8ef52016-10-29 14:30:08 -0700345 unsafety: unsafety,
346 abi: abi,
David Tolnay9d8f1972016-09-04 11:58:48 -0700347 lifetimes: lifetimes,
Michael Layzell416724e2017-05-24 21:12:34 -0400348 inputs: inputs_and_variadic.0,
David Tolnay62f374c2016-10-02 13:37:00 -0700349 output: match output {
350 Some(ty) => FunctionRetTy::Ty(ty),
351 None => FunctionRetTy::Default,
David Tolnay9d8f1972016-09-04 11:58:48 -0700352 },
Michael Layzell416724e2017-05-24 21:12:34 -0400353 variadic: inputs_and_variadic.1,
David Tolnay9d8f1972016-09-04 11:58:48 -0700354 })))
355 ));
356
David Tolnayb5a7b142016-09-13 22:46:39 -0700357 named!(ty_never -> Ty, map!(punct!("!"), |_| Ty::Never));
David Tolnay9d8f1972016-09-04 11:58:48 -0700358
David Tolnayb5a7b142016-09-13 22:46:39 -0700359 named!(ty_tup -> Ty, do_parse!(
Michael Layzell416724e2017-05-24 21:12:34 -0400360 elems: delim!(Parenthesis, terminated_list!(punct!(","), ty)) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700361 (Ty::Tup(elems))
362 ));
363
David Tolnay6414da72016-10-08 00:55:17 -0700364 named!(ty_path -> Ty, do_parse!(
365 qpath: qpath >>
David Tolnayf6c74402016-10-08 02:31:26 -0700366 parenthesized: cond!(
367 qpath.1.segments.last().unwrap().parameters == PathParameters::none(),
368 option!(parenthesized_parameter_data)
369 ) >>
David Tolnay6414da72016-10-08 00:55:17 -0700370 bounds: many0!(preceded!(punct!("+"), ty_param_bound)) >>
371 ({
David Tolnayf6c74402016-10-08 02:31:26 -0700372 let (qself, mut path) = qpath;
373 if let Some(Some(parenthesized)) = parenthesized {
374 path.segments.last_mut().unwrap().parameters = parenthesized;
375 }
David Tolnay6414da72016-10-08 00:55:17 -0700376 if bounds.is_empty() {
David Tolnay02c907f2017-01-23 00:06:37 -0800377 Ty::Path(qself, path)
David Tolnay6414da72016-10-08 00:55:17 -0700378 } else {
David Tolnay02c907f2017-01-23 00:06:37 -0800379 let path = TyParamBound::Trait(
380 PolyTraitRef {
381 bound_lifetimes: Vec::new(),
382 trait_ref: path,
383 },
384 TraitBoundModifier::None,
385 );
386 let bounds = Some(path).into_iter().chain(bounds).collect();
387 Ty::TraitObject(bounds)
David Tolnay6414da72016-10-08 00:55:17 -0700388 }
389 })
390 ));
David Tolnay9d8f1972016-09-04 11:58:48 -0700391
David Tolnayf6c74402016-10-08 02:31:26 -0700392 named!(parenthesized_parameter_data -> PathParameters, do_parse!(
Michael Layzell416724e2017-05-24 21:12:34 -0400393 inputs: delim!(Parenthesis, terminated_list!(punct!(","), ty)) >>
David Tolnayf6c74402016-10-08 02:31:26 -0700394 output: option!(preceded!(
395 punct!("->"),
396 ty
397 )) >>
398 (PathParameters::Parenthesized(
399 ParenthesizedParameterData {
400 inputs: inputs,
401 output: output,
402 },
403 ))
404 ));
405
David Tolnay9636c052016-10-02 17:11:17 -0700406 named!(pub qpath -> (Option<QSelf>, Path), alt!(
407 map!(path, |p| (None, p))
408 |
409 do_parse!(
410 punct!("<") >>
411 this: map!(ty, Box::new) >>
412 path: option!(preceded!(
413 keyword!("as"),
414 path
415 )) >>
416 punct!(">") >>
417 punct!("::") >>
418 rest: separated_nonempty_list!(punct!("::"), path_segment) >>
419 ({
420 match path {
421 Some(mut path) => {
422 let pos = path.segments.len();
423 path.segments.extend(rest);
424 (Some(QSelf { ty: this, position: pos }), path)
425 }
426 None => {
427 (Some(QSelf { ty: this, position: 0 }), Path {
428 global: false,
429 segments: rest,
430 })
431 }
David Tolnayb79ee962016-09-04 09:39:20 -0700432 }
David Tolnay9636c052016-10-02 17:11:17 -0700433 })
434 )
David Tolnay6cd2a232016-10-24 22:41:08 -0700435 |
436 map!(keyword!("self"), |_| (None, "self".into()))
David Tolnay9d8f1972016-09-04 11:58:48 -0700437 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700438
David Tolnay4f0f2512016-10-30 09:28:14 -0700439 named!(ty_poly_trait_ref -> Ty, map!(
David Tolnay8eb6c452016-10-30 13:19:15 -0700440 separated_nonempty_list!(punct!("+"), ty_param_bound),
David Tolnay02c907f2017-01-23 00:06:37 -0800441 Ty::TraitObject
David Tolnay6414da72016-10-08 00:55:17 -0700442 ));
443
David Tolnayb5a7b142016-09-13 22:46:39 -0700444 named!(ty_impl_trait -> Ty, do_parse!(
David Tolnay10413f02016-09-30 09:12:02 -0700445 keyword!("impl") >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700446 elem: separated_nonempty_list!(punct!("+"), ty_param_bound) >>
447 (Ty::ImplTrait(elem))
448 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700449
David Tolnayb5a7b142016-09-13 22:46:39 -0700450 named!(ty_paren -> Ty, do_parse!(
Michael Layzell416724e2017-05-24 21:12:34 -0400451 elem: delim!(Parenthesis, ty) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700452 (Ty::Paren(Box::new(elem)))
453 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700454
David Tolnay47a877c2016-10-01 16:50:55 -0700455 named!(pub mutability -> Mutability, alt!(
David Tolnaybd76e572016-10-02 13:43:16 -0700456 keyword!("mut") => { |_| Mutability::Mutable }
David Tolnayf6ccb832016-09-04 15:00:56 -0700457 |
458 epsilon!() => { |_| Mutability::Immutable }
David Tolnay9d8f1972016-09-04 11:58:48 -0700459 ));
460
David Tolnayb5a7b142016-09-13 22:46:39 -0700461 named!(pub path -> Path, do_parse!(
David Tolnayf6ccb832016-09-04 15:00:56 -0700462 global: option!(punct!("::")) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700463 segments: separated_nonempty_list!(punct!("::"), path_segment) >>
464 (Path {
465 global: global.is_some(),
466 segments: segments,
467 })
468 ));
469
David Tolnay9636c052016-10-02 17:11:17 -0700470 named!(path_segment -> PathSegment, alt!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700471 do_parse!(
David Tolnay9636c052016-10-02 17:11:17 -0700472 id: option!(ident) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700473 punct!("<") >>
474 lifetimes: separated_list!(punct!(","), lifetime) >>
475 types: opt_vec!(preceded!(
476 cond!(!lifetimes.is_empty(), punct!(",")),
477 separated_nonempty_list!(
478 punct!(","),
David Tolnay1f16b602017-02-07 20:06:55 -0500479 terminated!(ty, not!(punct!("=")))
David Tolnay9d8f1972016-09-04 11:58:48 -0700480 )
481 )) >>
482 bindings: opt_vec!(preceded!(
483 cond!(!lifetimes.is_empty() || !types.is_empty(), punct!(",")),
484 separated_nonempty_list!(punct!(","), type_binding)
485 )) >>
David Tolnay82a47d52016-10-30 13:01:38 -0700486 cond!(!lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty(), option!(punct!(","))) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700487 punct!(">") >>
488 (PathSegment {
David Tolnay9636c052016-10-02 17:11:17 -0700489 ident: id.unwrap_or_else(|| "".into()),
David Tolnay9d8f1972016-09-04 11:58:48 -0700490 parameters: PathParameters::AngleBracketed(
491 AngleBracketedParameterData {
492 lifetimes: lifetimes,
493 types: types,
494 bindings: bindings,
495 }
496 ),
497 })
498 )
499 |
David Tolnay84aa0752016-10-02 23:01:13 -0700500 map!(ident, Into::into)
David Tolnay77807222016-10-24 22:30:15 -0700501 |
David Tolnaye14e3be2016-10-24 22:53:07 -0700502 map!(alt!(
503 keyword!("super")
504 |
505 keyword!("self")
506 |
507 keyword!("Self")
508 ), Into::into)
David Tolnay9d8f1972016-09-04 11:58:48 -0700509 ));
510
Arnavionf2dada12017-04-20 23:55:20 -0700511 named!(pub mod_style_path -> Path, do_parse!(
512 global: option!(punct!("::")) >>
513 segments: separated_nonempty_list!(punct!("::"), mod_style_path_segment) >>
514 (Path {
515 global: global.is_some(),
516 segments: segments,
517 })
518 ));
519
520 named!(mod_style_path_segment -> PathSegment, alt!(
521 map!(ident, Into::into)
522 |
523 map!(alt!(
524 keyword!("super")
525 |
526 keyword!("self")
527 |
528 keyword!("Self")
529 ), Into::into)
530 ));
531
David Tolnayb5a7b142016-09-13 22:46:39 -0700532 named!(type_binding -> TypeBinding, do_parse!(
David Tolnay55337722016-09-11 12:58:56 -0700533 id: ident >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700534 punct!("=") >>
535 ty: ty >>
536 (TypeBinding {
David Tolnay55337722016-09-11 12:58:56 -0700537 ident: id,
David Tolnay9d8f1972016-09-04 11:58:48 -0700538 ty: ty,
539 })
540 ));
541
David Tolnayb5a7b142016-09-13 22:46:39 -0700542 named!(pub poly_trait_ref -> PolyTraitRef, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700543 bound_lifetimes: bound_lifetimes >>
544 trait_ref: path >>
David Tolnay4f0f2512016-10-30 09:28:14 -0700545 parenthesized: option!(cond_reduce!(
David Tolnayf6c74402016-10-08 02:31:26 -0700546 trait_ref.segments.last().unwrap().parameters == PathParameters::none(),
David Tolnay4f0f2512016-10-30 09:28:14 -0700547 parenthesized_parameter_data
548 )) >>
David Tolnayf6c74402016-10-08 02:31:26 -0700549 ({
550 let mut trait_ref = trait_ref;
David Tolnay4f0f2512016-10-30 09:28:14 -0700551 if let Some(parenthesized) = parenthesized {
David Tolnayf6c74402016-10-08 02:31:26 -0700552 trait_ref.segments.last_mut().unwrap().parameters = parenthesized;
553 }
554 PolyTraitRef {
555 bound_lifetimes: bound_lifetimes,
556 trait_ref: trait_ref,
557 }
David Tolnay9d8f1972016-09-04 11:58:48 -0700558 })
559 ));
560
David Tolnay62f374c2016-10-02 13:37:00 -0700561 named!(pub fn_arg -> BareFnArg, do_parse!(
David Tolnayb0417d72016-10-25 21:46:35 -0700562 name: option!(do_parse!(
563 name: ident >>
Michael Layzell416724e2017-05-24 21:12:34 -0400564 not!(punct!("::")) >>
David Tolnayb0417d72016-10-25 21:46:35 -0700565 punct!(":") >>
David Tolnayb0417d72016-10-25 21:46:35 -0700566 (name)
567 )) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700568 ty: ty >>
David Tolnay62f374c2016-10-02 13:37:00 -0700569 (BareFnArg {
570 name: name,
David Tolnay9d8f1972016-09-04 11:58:48 -0700571 ty: ty,
572 })
573 ));
David Tolnayb8d8ef52016-10-29 14:30:08 -0700574
575 named!(pub unsafety -> Unsafety, alt!(
576 keyword!("unsafe") => { |_| Unsafety::Unsafe }
577 |
578 epsilon!() => { |_| Unsafety::Normal }
579 ));
580
581 named!(pub abi -> Abi, do_parse!(
582 keyword!("extern") >>
Michael Layzell416724e2017-05-24 21:12:34 -0400583 name: option!(string) >>
David Tolnayb8d8ef52016-10-29 14:30:08 -0700584 (match name {
585 Some(name) => Abi::Named(name),
David Tolnay76195ce2016-10-30 16:53:48 -0700586 None => Abi::Rust,
David Tolnayb8d8ef52016-10-29 14:30:08 -0700587 })
588 ));
David Tolnay9d8f1972016-09-04 11:58:48 -0700589}
David Tolnay87d0b442016-09-04 11:52:12 -0700590
591#[cfg(feature = "printing")]
592mod printing {
593 use super::*;
594 use quote::{Tokens, ToTokens};
595
596 impl ToTokens for Ty {
597 fn to_tokens(&self, tokens: &mut Tokens) {
598 match *self {
David Tolnay16709ba2016-10-05 23:11:32 -0700599 Ty::Slice(ref inner) => {
David Tolnay87d0b442016-09-04 11:52:12 -0700600 tokens.append("[");
601 inner.to_tokens(tokens);
602 tokens.append("]");
603 }
David Tolnayfa94b6f2016-10-05 23:26:11 -0700604 Ty::Array(ref inner, ref len) => {
David Tolnay87d0b442016-09-04 11:52:12 -0700605 tokens.append("[");
606 inner.to_tokens(tokens);
607 tokens.append(";");
David Tolnayfa94b6f2016-10-05 23:26:11 -0700608 len.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700609 tokens.append("]");
610 }
611 Ty::Ptr(ref target) => {
612 tokens.append("*");
613 match target.mutability {
614 Mutability::Mutable => tokens.append("mut"),
615 Mutability::Immutable => tokens.append("const"),
616 }
617 target.ty.to_tokens(tokens);
618 }
619 Ty::Rptr(ref lifetime, ref target) => {
620 tokens.append("&");
621 lifetime.to_tokens(tokens);
David Tolnay47a877c2016-10-01 16:50:55 -0700622 target.mutability.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700623 target.ty.to_tokens(tokens);
624 }
625 Ty::BareFn(ref func) => {
626 func.to_tokens(tokens);
627 }
628 Ty::Never => {
629 tokens.append("!");
630 }
631 Ty::Tup(ref elems) => {
632 tokens.append("(");
David Tolnay94ebdf92016-09-04 13:33:16 -0700633 tokens.append_separated(elems, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700634 if elems.len() == 1 {
635 tokens.append(",");
636 }
637 tokens.append(")");
638 }
David Tolnayf69904a2016-09-04 14:46:07 -0700639 Ty::Path(None, ref path) => {
640 path.to_tokens(tokens);
641 }
642 Ty::Path(Some(ref qself), ref path) => {
643 tokens.append("<");
644 qself.ty.to_tokens(tokens);
645 if qself.position > 0 {
646 tokens.append("as");
David Tolnaydaaf7742016-10-03 11:11:43 -0700647 for (i, segment) in path.segments
David Tolnay05120ef2017-03-12 18:29:26 -0700648 .iter()
649 .take(qself.position)
650 .enumerate() {
David Tolnayf69904a2016-09-04 14:46:07 -0700651 if i > 0 || path.global {
652 tokens.append("::");
David Tolnay87d0b442016-09-04 11:52:12 -0700653 }
David Tolnayf69904a2016-09-04 14:46:07 -0700654 segment.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700655 }
David Tolnayf69904a2016-09-04 14:46:07 -0700656 }
657 tokens.append(">");
658 for segment in path.segments.iter().skip(qself.position) {
659 tokens.append("::");
660 segment.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700661 }
662 }
David Tolnay02c907f2017-01-23 00:06:37 -0800663 Ty::TraitObject(ref bounds) => {
David Tolnay6414da72016-10-08 00:55:17 -0700664 tokens.append_separated(bounds, "+");
665 }
David Tolnay87d0b442016-09-04 11:52:12 -0700666 Ty::ImplTrait(ref bounds) => {
667 tokens.append("impl");
David Tolnay94ebdf92016-09-04 13:33:16 -0700668 tokens.append_separated(bounds, "+");
David Tolnay87d0b442016-09-04 11:52:12 -0700669 }
670 Ty::Paren(ref inner) => {
671 tokens.append("(");
672 inner.to_tokens(tokens);
673 tokens.append(")");
674 }
675 Ty::Infer => {
676 tokens.append("_");
677 }
David Tolnay0047c712016-12-21 21:59:25 -0500678 Ty::Mac(ref mac) => mac.to_tokens(tokens),
David Tolnay87d0b442016-09-04 11:52:12 -0700679 }
680 }
681 }
682
David Tolnay47a877c2016-10-01 16:50:55 -0700683 impl ToTokens for Mutability {
684 fn to_tokens(&self, tokens: &mut Tokens) {
685 if let Mutability::Mutable = *self {
686 tokens.append("mut");
687 }
688 }
689 }
690
David Tolnay87d0b442016-09-04 11:52:12 -0700691 impl ToTokens for Path {
692 fn to_tokens(&self, tokens: &mut Tokens) {
693 for (i, segment) in self.segments.iter().enumerate() {
694 if i > 0 || self.global {
695 tokens.append("::");
696 }
697 segment.to_tokens(tokens);
698 }
699 }
700 }
701
702 impl ToTokens for PathSegment {
703 fn to_tokens(&self, tokens: &mut Tokens) {
704 self.ident.to_tokens(tokens);
David Tolnay5332d4b2016-10-30 14:25:22 -0700705 if self.ident.as_ref().is_empty() && self.parameters.is_empty() {
706 tokens.append("<");
707 tokens.append(">");
708 } else {
709 self.parameters.to_tokens(tokens);
710 }
David Tolnay87d0b442016-09-04 11:52:12 -0700711 }
712 }
713
714 impl ToTokens for PathParameters {
715 fn to_tokens(&self, tokens: &mut Tokens) {
716 match *self {
717 PathParameters::AngleBracketed(ref parameters) => {
718 parameters.to_tokens(tokens);
719 }
720 PathParameters::Parenthesized(ref parameters) => {
721 parameters.to_tokens(tokens);
722 }
723 }
724 }
725 }
726
727 impl ToTokens for AngleBracketedParameterData {
728 fn to_tokens(&self, tokens: &mut Tokens) {
729 let has_lifetimes = !self.lifetimes.is_empty();
730 let has_types = !self.types.is_empty();
731 let has_bindings = !self.bindings.is_empty();
732 if !has_lifetimes && !has_types && !has_bindings {
733 return;
734 }
735
736 tokens.append("<");
737
738 let mut first = true;
739 for lifetime in &self.lifetimes {
740 if !first {
741 tokens.append(",");
742 }
743 lifetime.to_tokens(tokens);
744 first = false;
745 }
746 for ty in &self.types {
747 if !first {
748 tokens.append(",");
749 }
750 ty.to_tokens(tokens);
751 first = false;
752 }
753 for binding in &self.bindings {
754 if !first {
755 tokens.append(",");
756 }
757 binding.to_tokens(tokens);
758 first = false;
759 }
760
761 tokens.append(">");
762 }
763 }
764
765 impl ToTokens for TypeBinding {
766 fn to_tokens(&self, tokens: &mut Tokens) {
767 self.ident.to_tokens(tokens);
768 tokens.append("=");
769 self.ty.to_tokens(tokens);
770 }
771 }
772
773 impl ToTokens for ParenthesizedParameterData {
774 fn to_tokens(&self, tokens: &mut Tokens) {
775 tokens.append("(");
David Tolnay94ebdf92016-09-04 13:33:16 -0700776 tokens.append_separated(&self.inputs, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700777 tokens.append(")");
778 if let Some(ref output) = self.output {
779 tokens.append("->");
780 output.to_tokens(tokens);
781 }
782 }
783 }
784
785 impl ToTokens for PolyTraitRef {
786 fn to_tokens(&self, tokens: &mut Tokens) {
787 if !self.bound_lifetimes.is_empty() {
David Tolnaye8796aa2016-09-04 14:48:22 -0700788 tokens.append("for");
David Tolnay87d0b442016-09-04 11:52:12 -0700789 tokens.append("<");
David Tolnay94ebdf92016-09-04 13:33:16 -0700790 tokens.append_separated(&self.bound_lifetimes, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700791 tokens.append(">");
792 }
793 self.trait_ref.to_tokens(tokens);
794 }
795 }
796
797 impl ToTokens for BareFnTy {
798 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay87d0b442016-09-04 11:52:12 -0700799 if !self.lifetimes.is_empty() {
David Tolnay4f121832016-10-25 21:33:36 -0700800 tokens.append("for");
David Tolnay87d0b442016-09-04 11:52:12 -0700801 tokens.append("<");
David Tolnay42602292016-10-01 22:25:45 -0700802 tokens.append_separated(&self.lifetimes, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700803 tokens.append(">");
804 }
David Tolnayb8d8ef52016-10-29 14:30:08 -0700805 self.unsafety.to_tokens(tokens);
806 self.abi.to_tokens(tokens);
David Tolnay4f121832016-10-25 21:33:36 -0700807 tokens.append("fn");
David Tolnay87d0b442016-09-04 11:52:12 -0700808 tokens.append("(");
David Tolnay42602292016-10-01 22:25:45 -0700809 tokens.append_separated(&self.inputs, ",");
David Tolnay292e6002016-10-29 22:03:51 -0700810 if self.variadic {
811 if !self.inputs.is_empty() {
812 tokens.append(",");
813 }
814 tokens.append("...");
815 }
David Tolnay87d0b442016-09-04 11:52:12 -0700816 tokens.append(")");
David Tolnay42602292016-10-01 22:25:45 -0700817 if let FunctionRetTy::Ty(ref ty) = self.output {
818 tokens.append("->");
819 ty.to_tokens(tokens);
820 }
821 }
822 }
823
David Tolnay62f374c2016-10-02 13:37:00 -0700824 impl ToTokens for BareFnArg {
David Tolnay42602292016-10-01 22:25:45 -0700825 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay62f374c2016-10-02 13:37:00 -0700826 if let Some(ref name) = self.name {
827 name.to_tokens(tokens);
David Tolnay42602292016-10-01 22:25:45 -0700828 tokens.append(":");
829 }
830 self.ty.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700831 }
832 }
David Tolnayb8d8ef52016-10-29 14:30:08 -0700833
834 impl ToTokens for Unsafety {
835 fn to_tokens(&self, tokens: &mut Tokens) {
836 match *self {
837 Unsafety::Unsafe => tokens.append("unsafe"),
838 Unsafety::Normal => {
839 // nothing
840 }
841 }
842 }
843 }
844
845 impl ToTokens for Abi {
846 fn to_tokens(&self, tokens: &mut Tokens) {
847 tokens.append("extern");
848 match *self {
849 Abi::Named(ref named) => named.to_tokens(tokens),
David Tolnay76195ce2016-10-30 16:53:48 -0700850 Abi::Rust => {}
David Tolnayb8d8ef52016-10-29 14:30:08 -0700851 }
852 }
853 }
David Tolnay87d0b442016-09-04 11:52:12 -0700854}