blob: aaaf28c506034342a51caec2ffe9f821859a2157 [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
40#[cfg(not(feature = "type-macros"))]
David Tolnay881a5ef2017-01-07 11:27:45 -080041#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnay0047c712016-12-21 21:59:25 -050042pub struct Mac {
43 _private: (),
David Tolnayb79ee962016-09-04 09:39:20 -070044}
45
David Tolnay9bf4af82017-01-07 11:17:46 -080046#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnayb79ee962016-09-04 09:39:20 -070047pub struct MutTy {
48 pub ty: Ty,
49 pub mutability: Mutability,
50}
51
David Tolnay9bf4af82017-01-07 11:17:46 -080052#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
David Tolnayb79ee962016-09-04 09:39:20 -070053pub enum Mutability {
54 Mutable,
55 Immutable,
56}
57
David Tolnay771ecf42016-09-23 19:26:37 -070058/// A "Path" is essentially Rust's notion of a name.
59///
60/// It's represented as a sequence of identifiers,
61/// along with a bunch of supporting information.
62///
63/// E.g. `std::cmp::PartialEq`
David Tolnay9bf4af82017-01-07 11:17:46 -080064#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnayb79ee962016-09-04 09:39:20 -070065pub struct Path {
David Tolnayf06fdde2016-12-22 17:07:59 -050066 /// A `::foo` path, is relative to the crate root rather than current
67 /// module (like paths in an import).
David Tolnayb79ee962016-09-04 09:39:20 -070068 pub global: bool,
David Tolnayf06fdde2016-12-22 17:07:59 -050069 /// The segments in the path: the things separated by `::`.
David Tolnayb79ee962016-09-04 09:39:20 -070070 pub segments: Vec<PathSegment>,
71}
72
David Tolnaydaaf7742016-10-03 11:11:43 -070073impl<T> From<T> for Path
74 where T: Into<PathSegment>
75{
David Tolnay84aa0752016-10-02 23:01:13 -070076 fn from(segment: T) -> Self {
77 Path {
78 global: false,
79 segments: vec![segment.into()],
80 }
81 }
82}
83
David Tolnayb79ee962016-09-04 09:39:20 -070084/// A segment of a path: an identifier, an optional lifetime, and a set of types.
85///
86/// E.g. `std`, `String` or `Box<T>`
David Tolnay9bf4af82017-01-07 11:17:46 -080087#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnayb79ee962016-09-04 09:39:20 -070088pub struct PathSegment {
David Tolnayf06fdde2016-12-22 17:07:59 -050089 /// The identifier portion of this path segment.
David Tolnayb79ee962016-09-04 09:39:20 -070090 pub ident: Ident,
David Tolnayf06fdde2016-12-22 17:07:59 -050091 /// Type/lifetime parameters attached to this path. They come in
92 /// two flavors: `Path<A,B,C>` and `Path(A,B) -> C`. Note that
93 /// this is more than just simple syntactic sugar; the use of
94 /// parens affects the region binding rules, so we preserve the
95 /// distinction.
David Tolnayb79ee962016-09-04 09:39:20 -070096 pub parameters: PathParameters,
97}
98
David Tolnaydaaf7742016-10-03 11:11:43 -070099impl<T> From<T> for PathSegment
100 where T: Into<Ident>
101{
David Tolnay84aa0752016-10-02 23:01:13 -0700102 fn from(ident: T) -> Self {
David Tolnayb79ee962016-09-04 09:39:20 -0700103 PathSegment {
David Tolnay84aa0752016-10-02 23:01:13 -0700104 ident: ident.into(),
David Tolnayb79ee962016-09-04 09:39:20 -0700105 parameters: PathParameters::none(),
106 }
107 }
108}
109
110/// Parameters of a path segment.
111///
112/// E.g. `<A, B>` as in `Foo<A, B>` or `(A, B)` as in `Foo(A, B)`
David Tolnay9bf4af82017-01-07 11:17:46 -0800113#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnayb79ee962016-09-04 09:39:20 -0700114pub enum PathParameters {
115 /// The `<'a, A, B, C>` in `foo::bar::baz::<'a, A, B, C>`
116 AngleBracketed(AngleBracketedParameterData),
117 /// The `(A, B)` and `C` in `Foo(A, B) -> C`
118 Parenthesized(ParenthesizedParameterData),
119}
120
121impl PathParameters {
122 pub fn none() -> Self {
123 PathParameters::AngleBracketed(AngleBracketedParameterData::default())
124 }
David Tolnay5332d4b2016-10-30 14:25:22 -0700125
126 pub fn is_empty(&self) -> bool {
127 match *self {
128 PathParameters::AngleBracketed(ref bracketed) => {
David Tolnayc1fea502016-10-30 17:54:02 -0700129 bracketed.lifetimes.is_empty() && bracketed.types.is_empty() &&
130 bracketed.bindings.is_empty()
David Tolnay5332d4b2016-10-30 14:25:22 -0700131 }
132 PathParameters::Parenthesized(_) => false,
133 }
134 }
David Tolnayb79ee962016-09-04 09:39:20 -0700135}
136
137/// A path like `Foo<'a, T>`
David Tolnay9bf4af82017-01-07 11:17:46 -0800138#[derive(Debug, Clone, Eq, PartialEq, Default, Hash)]
David Tolnayb79ee962016-09-04 09:39:20 -0700139pub struct AngleBracketedParameterData {
140 /// The lifetime parameters for this path segment.
141 pub lifetimes: Vec<Lifetime>,
142 /// The type parameters for this path segment, if present.
143 pub types: Vec<Ty>,
144 /// Bindings (equality constraints) on associated types, if present.
145 ///
146 /// E.g., `Foo<A=Bar>`.
147 pub bindings: Vec<TypeBinding>,
148}
149
150/// Bind a type to an associated type: `A=Foo`.
David Tolnay9bf4af82017-01-07 11:17:46 -0800151#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnayb79ee962016-09-04 09:39:20 -0700152pub struct TypeBinding {
153 pub ident: Ident,
154 pub ty: Ty,
155}
156
157/// A path like `Foo(A,B) -> C`
David Tolnay9bf4af82017-01-07 11:17:46 -0800158#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnayb79ee962016-09-04 09:39:20 -0700159pub struct ParenthesizedParameterData {
160 /// `(A, B)`
161 pub inputs: Vec<Ty>,
162 /// `C`
163 pub output: Option<Ty>,
164}
165
David Tolnay9bf4af82017-01-07 11:17:46 -0800166#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnayb79ee962016-09-04 09:39:20 -0700167pub struct PolyTraitRef {
168 /// The `'a` in `<'a> Foo<&'a T>`
169 pub bound_lifetimes: Vec<LifetimeDef>,
170 /// The `Foo<&'a T>` in `<'a> Foo<&'a T>`
171 pub trait_ref: Path,
172}
173
174/// The explicit Self type in a "qualified path". The actual
175/// path, including the trait and the associated item, is stored
176/// separately. `position` represents the index of the associated
177/// item qualified with this Self type.
178///
179/// ```rust,ignore
180/// <Vec<T> as a::b::Trait>::AssociatedItem
181/// ^~~~~ ~~~~~~~~~~~~~~^
182/// ty position = 3
183///
184/// <Vec<T>>::AssociatedItem
185/// ^~~~~ ^
186/// ty position = 0
187/// ```
David Tolnay9bf4af82017-01-07 11:17:46 -0800188#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnayb79ee962016-09-04 09:39:20 -0700189pub struct QSelf {
190 pub ty: Box<Ty>,
David Tolnaydaaf7742016-10-03 11:11:43 -0700191 pub position: usize,
David Tolnayb79ee962016-09-04 09:39:20 -0700192}
193
David Tolnay9bf4af82017-01-07 11:17:46 -0800194#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnayb79ee962016-09-04 09:39:20 -0700195pub struct BareFnTy {
David Tolnayb8d8ef52016-10-29 14:30:08 -0700196 pub unsafety: Unsafety,
197 pub abi: Option<Abi>,
David Tolnayb79ee962016-09-04 09:39:20 -0700198 pub lifetimes: Vec<LifetimeDef>,
David Tolnay62f374c2016-10-02 13:37:00 -0700199 pub inputs: Vec<BareFnArg>,
David Tolnayb79ee962016-09-04 09:39:20 -0700200 pub output: FunctionRetTy,
David Tolnay292e6002016-10-29 22:03:51 -0700201 pub variadic: bool,
David Tolnayb79ee962016-09-04 09:39:20 -0700202}
203
David Tolnay9bf4af82017-01-07 11:17:46 -0800204#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
David Tolnayb8d8ef52016-10-29 14:30:08 -0700205pub enum Unsafety {
206 Unsafe,
207 Normal,
208}
209
David Tolnay9bf4af82017-01-07 11:17:46 -0800210#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnayb8d8ef52016-10-29 14:30:08 -0700211pub enum Abi {
212 Named(String),
David Tolnay76195ce2016-10-30 16:53:48 -0700213 Rust,
David Tolnayb8d8ef52016-10-29 14:30:08 -0700214}
215
David Tolnay62f374c2016-10-02 13:37:00 -0700216/// An argument in a function type.
David Tolnayb79ee962016-09-04 09:39:20 -0700217///
218/// E.g. `bar: usize` as in `fn foo(bar: usize)`
David Tolnay9bf4af82017-01-07 11:17:46 -0800219#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnay62f374c2016-10-02 13:37:00 -0700220pub struct BareFnArg {
221 pub name: Option<Ident>,
David Tolnayb79ee962016-09-04 09:39:20 -0700222 pub ty: Ty,
223}
224
David Tolnay9bf4af82017-01-07 11:17:46 -0800225#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnayb79ee962016-09-04 09:39:20 -0700226pub enum FunctionRetTy {
227 /// Return type is not specified.
228 ///
229 /// Functions default to `()` and
230 /// closures default to inference. Span points to where return
231 /// type would be inserted.
232 Default,
233 /// Everything else
234 Ty(Ty),
235}
236
David Tolnay86eca752016-09-04 11:26:41 -0700237#[cfg(feature = "parsing")]
David Tolnay9d8f1972016-09-04 11:58:48 -0700238pub mod parsing {
239 use super::*;
David Tolnaya6ac1812017-01-23 00:29:11 -0800240 use {TyParamBound, TraitBoundModifier};
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700241 #[cfg(feature = "full")]
242 use ConstExpr;
David Tolnay3cb23a92016-10-07 23:02:21 -0700243 use constant::parsing::const_expr;
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700244 #[cfg(feature = "full")]
245 use expr::parsing::expr;
David Tolnay9d8f1972016-09-04 11:58:48 -0700246 use generics::parsing::{lifetime, lifetime_def, ty_param_bound, bound_lifetimes};
David Tolnay55337722016-09-11 12:58:56 -0700247 use ident::parsing::ident;
David Tolnayb8d8ef52016-10-29 14:30:08 -0700248 use lit::parsing::quoted_string;
David Tolnay0047c712016-12-21 21:59:25 -0500249 #[cfg(feature = "type-macros")]
250 use mac::parsing::mac;
251 #[cfg(not(feature = "type-macros"))]
252 use nom::IResult;
David Tolnay9d8f1972016-09-04 11:58:48 -0700253 use std::str;
David Tolnayda4049b2016-09-04 10:59:23 -0700254
David Tolnayb5a7b142016-09-13 22:46:39 -0700255 named!(pub ty -> Ty, alt!(
David Tolnayd040d772016-10-25 21:33:51 -0700256 ty_paren // must be before ty_tup
257 |
David Tolnay0047c712016-12-21 21:59:25 -0500258 ty_mac // must be before ty_path
259 |
David Tolnay4f0f2512016-10-30 09:28:14 -0700260 ty_path // must be before ty_poly_trait_ref
261 |
David Tolnay9d8f1972016-09-04 11:58:48 -0700262 ty_vec
David Tolnayda4049b2016-09-04 10:59:23 -0700263 |
David Tolnayfa94b6f2016-10-05 23:26:11 -0700264 ty_array
David Tolnayb79ee962016-09-04 09:39:20 -0700265 |
David Tolnay9d8f1972016-09-04 11:58:48 -0700266 ty_ptr
267 |
268 ty_rptr
269 |
270 ty_bare_fn
271 |
272 ty_never
273 |
274 ty_tup
275 |
David Tolnay4f0f2512016-10-30 09:28:14 -0700276 ty_poly_trait_ref
David Tolnay9d8f1972016-09-04 11:58:48 -0700277 |
David Tolnay9d8f1972016-09-04 11:58:48 -0700278 ty_impl_trait
David Tolnay9d8f1972016-09-04 11:58:48 -0700279 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700280
David Tolnay0047c712016-12-21 21:59:25 -0500281 #[cfg(feature = "type-macros")]
282 named!(ty_mac -> Ty, map!(mac, Ty::Mac));
283
284 #[cfg(not(feature = "type-macros"))]
285 fn ty_mac(_: &str) -> IResult<&str, Ty> {
286 IResult::Error
287 }
288
David Tolnayb5a7b142016-09-13 22:46:39 -0700289 named!(ty_vec -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700290 punct!("[") >>
291 elem: ty >>
292 punct!("]") >>
David Tolnay16709ba2016-10-05 23:11:32 -0700293 (Ty::Slice(Box::new(elem)))
David Tolnay9d8f1972016-09-04 11:58:48 -0700294 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700295
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700296 #[cfg(not(feature = "full"))]
David Tolnayfa94b6f2016-10-05 23:26:11 -0700297 named!(ty_array -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700298 punct!("[") >>
299 elem: ty >>
300 punct!(";") >>
David Tolnay3cb23a92016-10-07 23:02:21 -0700301 len: const_expr >>
David Tolnayc94c38a2016-09-05 17:02:03 -0700302 punct!("]") >>
David Tolnayfa94b6f2016-10-05 23:26:11 -0700303 (Ty::Array(Box::new(elem), len))
304 ));
305
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700306 #[cfg(feature = "full")]
307 named!(ty_array -> Ty, do_parse!(
308 punct!("[") >>
309 elem: ty >>
310 punct!(";") >>
311 len: alt!(
312 terminated!(const_expr, punct!("]"))
313 |
314 terminated!(expr, punct!("]")) => { ConstExpr::Other }
315 ) >>
316 (Ty::Array(Box::new(elem), len))
317 ));
318
David Tolnayb5a7b142016-09-13 22:46:39 -0700319 named!(ty_ptr -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700320 punct!("*") >>
David Tolnayb5a7b142016-09-13 22:46:39 -0700321 mutability: alt!(
David Tolnay10413f02016-09-30 09:12:02 -0700322 keyword!("const") => { |_| Mutability::Immutable }
David Tolnay9d8f1972016-09-04 11:58:48 -0700323 |
David Tolnay10413f02016-09-30 09:12:02 -0700324 keyword!("mut") => { |_| Mutability::Mutable }
David Tolnay9d8f1972016-09-04 11:58:48 -0700325 ) >>
326 target: ty >>
327 (Ty::Ptr(Box::new(MutTy {
328 ty: target,
329 mutability: mutability,
330 })))
331 ));
332
David Tolnayb5a7b142016-09-13 22:46:39 -0700333 named!(ty_rptr -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700334 punct!("&") >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700335 life: option!(lifetime) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700336 mutability: mutability >>
337 target: ty >>
338 (Ty::Rptr(life, Box::new(MutTy {
339 ty: target,
340 mutability: mutability,
341 })))
342 ));
343
David Tolnayb5a7b142016-09-13 22:46:39 -0700344 named!(ty_bare_fn -> Ty, do_parse!(
David Tolnay4f121832016-10-25 21:33:36 -0700345 lifetimes: opt_vec!(do_parse!(
346 keyword!("for") >>
347 punct!("<") >>
348 lifetimes: terminated_list!(punct!(","), lifetime_def) >>
349 punct!(">") >>
350 (lifetimes)
David Tolnay6b7aaf02016-09-04 10:39:25 -0700351 )) >>
David Tolnayb8d8ef52016-10-29 14:30:08 -0700352 unsafety: unsafety >>
353 abi: option!(abi) >>
David Tolnay4f121832016-10-25 21:33:36 -0700354 keyword!("fn") >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700355 punct!("(") >>
David Tolnay292e6002016-10-29 22:03:51 -0700356 inputs: separated_list!(punct!(","), fn_arg) >>
357 trailing_comma: option!(punct!(",")) >>
358 variadic: option!(cond_reduce!(trailing_comma.is_some(), punct!("..."))) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700359 punct!(")") >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700360 output: option!(preceded!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700361 punct!("->"),
362 ty
363 )) >>
364 (Ty::BareFn(Box::new(BareFnTy {
David Tolnayb8d8ef52016-10-29 14:30:08 -0700365 unsafety: unsafety,
366 abi: abi,
David Tolnay9d8f1972016-09-04 11:58:48 -0700367 lifetimes: lifetimes,
David Tolnay62f374c2016-10-02 13:37:00 -0700368 inputs: inputs,
369 output: match output {
370 Some(ty) => FunctionRetTy::Ty(ty),
371 None => FunctionRetTy::Default,
David Tolnay9d8f1972016-09-04 11:58:48 -0700372 },
David Tolnay292e6002016-10-29 22:03:51 -0700373 variadic: variadic.is_some(),
David Tolnay9d8f1972016-09-04 11:58:48 -0700374 })))
375 ));
376
David Tolnayb5a7b142016-09-13 22:46:39 -0700377 named!(ty_never -> Ty, map!(punct!("!"), |_| Ty::Never));
David Tolnay9d8f1972016-09-04 11:58:48 -0700378
David Tolnayb5a7b142016-09-13 22:46:39 -0700379 named!(ty_tup -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700380 punct!("(") >>
David Tolnayff46fd22016-10-08 13:53:28 -0700381 elems: terminated_list!(punct!(","), ty) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700382 punct!(")") >>
383 (Ty::Tup(elems))
384 ));
385
David Tolnay6414da72016-10-08 00:55:17 -0700386 named!(ty_path -> Ty, do_parse!(
387 qpath: qpath >>
David Tolnayf6c74402016-10-08 02:31:26 -0700388 parenthesized: cond!(
389 qpath.1.segments.last().unwrap().parameters == PathParameters::none(),
390 option!(parenthesized_parameter_data)
391 ) >>
David Tolnay6414da72016-10-08 00:55:17 -0700392 bounds: many0!(preceded!(punct!("+"), ty_param_bound)) >>
393 ({
David Tolnayf6c74402016-10-08 02:31:26 -0700394 let (qself, mut path) = qpath;
395 if let Some(Some(parenthesized)) = parenthesized {
396 path.segments.last_mut().unwrap().parameters = parenthesized;
397 }
David Tolnay6414da72016-10-08 00:55:17 -0700398 if bounds.is_empty() {
David Tolnay02c907f2017-01-23 00:06:37 -0800399 Ty::Path(qself, path)
David Tolnay6414da72016-10-08 00:55:17 -0700400 } else {
David Tolnay02c907f2017-01-23 00:06:37 -0800401 let path = TyParamBound::Trait(
402 PolyTraitRef {
403 bound_lifetimes: Vec::new(),
404 trait_ref: path,
405 },
406 TraitBoundModifier::None,
407 );
408 let bounds = Some(path).into_iter().chain(bounds).collect();
409 Ty::TraitObject(bounds)
David Tolnay6414da72016-10-08 00:55:17 -0700410 }
411 })
412 ));
David Tolnay9d8f1972016-09-04 11:58:48 -0700413
David Tolnayf6c74402016-10-08 02:31:26 -0700414 named!(parenthesized_parameter_data -> PathParameters, do_parse!(
415 punct!("(") >>
David Tolnayff46fd22016-10-08 13:53:28 -0700416 inputs: terminated_list!(punct!(","), ty) >>
David Tolnayf6c74402016-10-08 02:31:26 -0700417 punct!(")") >>
418 output: option!(preceded!(
419 punct!("->"),
420 ty
421 )) >>
422 (PathParameters::Parenthesized(
423 ParenthesizedParameterData {
424 inputs: inputs,
425 output: output,
426 },
427 ))
428 ));
429
David Tolnay9636c052016-10-02 17:11:17 -0700430 named!(pub qpath -> (Option<QSelf>, Path), alt!(
431 map!(path, |p| (None, p))
432 |
433 do_parse!(
434 punct!("<") >>
435 this: map!(ty, Box::new) >>
436 path: option!(preceded!(
437 keyword!("as"),
438 path
439 )) >>
440 punct!(">") >>
441 punct!("::") >>
442 rest: separated_nonempty_list!(punct!("::"), path_segment) >>
443 ({
444 match path {
445 Some(mut path) => {
446 let pos = path.segments.len();
447 path.segments.extend(rest);
448 (Some(QSelf { ty: this, position: pos }), path)
449 }
450 None => {
451 (Some(QSelf { ty: this, position: 0 }), Path {
452 global: false,
453 segments: rest,
454 })
455 }
David Tolnayb79ee962016-09-04 09:39:20 -0700456 }
David Tolnay9636c052016-10-02 17:11:17 -0700457 })
458 )
David Tolnay6cd2a232016-10-24 22:41:08 -0700459 |
460 map!(keyword!("self"), |_| (None, "self".into()))
David Tolnay9d8f1972016-09-04 11:58:48 -0700461 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700462
David Tolnay4f0f2512016-10-30 09:28:14 -0700463 named!(ty_poly_trait_ref -> Ty, map!(
David Tolnay8eb6c452016-10-30 13:19:15 -0700464 separated_nonempty_list!(punct!("+"), ty_param_bound),
David Tolnay02c907f2017-01-23 00:06:37 -0800465 Ty::TraitObject
David Tolnay6414da72016-10-08 00:55:17 -0700466 ));
467
David Tolnayb5a7b142016-09-13 22:46:39 -0700468 named!(ty_impl_trait -> Ty, do_parse!(
David Tolnay10413f02016-09-30 09:12:02 -0700469 keyword!("impl") >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700470 elem: separated_nonempty_list!(punct!("+"), ty_param_bound) >>
471 (Ty::ImplTrait(elem))
472 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700473
David Tolnayb5a7b142016-09-13 22:46:39 -0700474 named!(ty_paren -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700475 punct!("(") >>
476 elem: ty >>
477 punct!(")") >>
478 (Ty::Paren(Box::new(elem)))
479 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700480
David Tolnay47a877c2016-10-01 16:50:55 -0700481 named!(pub mutability -> Mutability, alt!(
David Tolnaybd76e572016-10-02 13:43:16 -0700482 keyword!("mut") => { |_| Mutability::Mutable }
David Tolnayf6ccb832016-09-04 15:00:56 -0700483 |
484 epsilon!() => { |_| Mutability::Immutable }
David Tolnay9d8f1972016-09-04 11:58:48 -0700485 ));
486
David Tolnayb5a7b142016-09-13 22:46:39 -0700487 named!(pub path -> Path, do_parse!(
David Tolnayf6ccb832016-09-04 15:00:56 -0700488 global: option!(punct!("::")) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700489 segments: separated_nonempty_list!(punct!("::"), path_segment) >>
490 (Path {
491 global: global.is_some(),
492 segments: segments,
493 })
494 ));
495
David Tolnay9636c052016-10-02 17:11:17 -0700496 named!(path_segment -> PathSegment, alt!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700497 do_parse!(
David Tolnay9636c052016-10-02 17:11:17 -0700498 id: option!(ident) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700499 punct!("<") >>
500 lifetimes: separated_list!(punct!(","), lifetime) >>
501 types: opt_vec!(preceded!(
502 cond!(!lifetimes.is_empty(), punct!(",")),
503 separated_nonempty_list!(
504 punct!(","),
505 terminated!(ty, not!(peek!(punct!("="))))
506 )
507 )) >>
508 bindings: opt_vec!(preceded!(
509 cond!(!lifetimes.is_empty() || !types.is_empty(), punct!(",")),
510 separated_nonempty_list!(punct!(","), type_binding)
511 )) >>
David Tolnay82a47d52016-10-30 13:01:38 -0700512 cond!(!lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty(), option!(punct!(","))) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700513 punct!(">") >>
514 (PathSegment {
David Tolnay9636c052016-10-02 17:11:17 -0700515 ident: id.unwrap_or_else(|| "".into()),
David Tolnay9d8f1972016-09-04 11:58:48 -0700516 parameters: PathParameters::AngleBracketed(
517 AngleBracketedParameterData {
518 lifetimes: lifetimes,
519 types: types,
520 bindings: bindings,
521 }
522 ),
523 })
524 )
525 |
David Tolnay84aa0752016-10-02 23:01:13 -0700526 map!(ident, Into::into)
David Tolnay77807222016-10-24 22:30:15 -0700527 |
David Tolnaye14e3be2016-10-24 22:53:07 -0700528 map!(alt!(
529 keyword!("super")
530 |
531 keyword!("self")
532 |
533 keyword!("Self")
534 ), Into::into)
David Tolnay9d8f1972016-09-04 11:58:48 -0700535 ));
536
David Tolnayb5a7b142016-09-13 22:46:39 -0700537 named!(type_binding -> TypeBinding, do_parse!(
David Tolnay55337722016-09-11 12:58:56 -0700538 id: ident >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700539 punct!("=") >>
540 ty: ty >>
541 (TypeBinding {
David Tolnay55337722016-09-11 12:58:56 -0700542 ident: id,
David Tolnay9d8f1972016-09-04 11:58:48 -0700543 ty: ty,
544 })
545 ));
546
David Tolnayb5a7b142016-09-13 22:46:39 -0700547 named!(pub poly_trait_ref -> PolyTraitRef, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700548 bound_lifetimes: bound_lifetimes >>
549 trait_ref: path >>
David Tolnay4f0f2512016-10-30 09:28:14 -0700550 parenthesized: option!(cond_reduce!(
David Tolnayf6c74402016-10-08 02:31:26 -0700551 trait_ref.segments.last().unwrap().parameters == PathParameters::none(),
David Tolnay4f0f2512016-10-30 09:28:14 -0700552 parenthesized_parameter_data
553 )) >>
David Tolnayf6c74402016-10-08 02:31:26 -0700554 ({
555 let mut trait_ref = trait_ref;
David Tolnay4f0f2512016-10-30 09:28:14 -0700556 if let Some(parenthesized) = parenthesized {
David Tolnayf6c74402016-10-08 02:31:26 -0700557 trait_ref.segments.last_mut().unwrap().parameters = parenthesized;
558 }
559 PolyTraitRef {
560 bound_lifetimes: bound_lifetimes,
561 trait_ref: trait_ref,
562 }
David Tolnay9d8f1972016-09-04 11:58:48 -0700563 })
564 ));
565
David Tolnay62f374c2016-10-02 13:37:00 -0700566 named!(pub fn_arg -> BareFnArg, do_parse!(
David Tolnayb0417d72016-10-25 21:46:35 -0700567 name: option!(do_parse!(
568 name: ident >>
569 punct!(":") >>
570 not!(peek!(tag!(":"))) >> // not ::
571 (name)
572 )) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700573 ty: ty >>
David Tolnay62f374c2016-10-02 13:37:00 -0700574 (BareFnArg {
575 name: name,
David Tolnay9d8f1972016-09-04 11:58:48 -0700576 ty: ty,
577 })
578 ));
David Tolnayb8d8ef52016-10-29 14:30:08 -0700579
580 named!(pub unsafety -> Unsafety, alt!(
581 keyword!("unsafe") => { |_| Unsafety::Unsafe }
582 |
583 epsilon!() => { |_| Unsafety::Normal }
584 ));
585
586 named!(pub abi -> Abi, do_parse!(
587 keyword!("extern") >>
588 name: option!(quoted_string) >>
589 (match name {
590 Some(name) => Abi::Named(name),
David Tolnay76195ce2016-10-30 16:53:48 -0700591 None => Abi::Rust,
David Tolnayb8d8ef52016-10-29 14:30:08 -0700592 })
593 ));
David Tolnay9d8f1972016-09-04 11:58:48 -0700594}
David Tolnay87d0b442016-09-04 11:52:12 -0700595
596#[cfg(feature = "printing")]
597mod printing {
598 use super::*;
599 use quote::{Tokens, ToTokens};
600
601 impl ToTokens for Ty {
602 fn to_tokens(&self, tokens: &mut Tokens) {
603 match *self {
David Tolnay16709ba2016-10-05 23:11:32 -0700604 Ty::Slice(ref inner) => {
David Tolnay87d0b442016-09-04 11:52:12 -0700605 tokens.append("[");
606 inner.to_tokens(tokens);
607 tokens.append("]");
608 }
David Tolnayfa94b6f2016-10-05 23:26:11 -0700609 Ty::Array(ref inner, ref len) => {
David Tolnay87d0b442016-09-04 11:52:12 -0700610 tokens.append("[");
611 inner.to_tokens(tokens);
612 tokens.append(";");
David Tolnayfa94b6f2016-10-05 23:26:11 -0700613 len.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700614 tokens.append("]");
615 }
616 Ty::Ptr(ref target) => {
617 tokens.append("*");
618 match target.mutability {
619 Mutability::Mutable => tokens.append("mut"),
620 Mutability::Immutable => tokens.append("const"),
621 }
622 target.ty.to_tokens(tokens);
623 }
624 Ty::Rptr(ref lifetime, ref target) => {
625 tokens.append("&");
626 lifetime.to_tokens(tokens);
David Tolnay47a877c2016-10-01 16:50:55 -0700627 target.mutability.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700628 target.ty.to_tokens(tokens);
629 }
630 Ty::BareFn(ref func) => {
631 func.to_tokens(tokens);
632 }
633 Ty::Never => {
634 tokens.append("!");
635 }
636 Ty::Tup(ref elems) => {
637 tokens.append("(");
David Tolnay94ebdf92016-09-04 13:33:16 -0700638 tokens.append_separated(elems, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700639 if elems.len() == 1 {
640 tokens.append(",");
641 }
642 tokens.append(")");
643 }
David Tolnayf69904a2016-09-04 14:46:07 -0700644 Ty::Path(None, ref path) => {
645 path.to_tokens(tokens);
646 }
647 Ty::Path(Some(ref qself), ref path) => {
648 tokens.append("<");
649 qself.ty.to_tokens(tokens);
650 if qself.position > 0 {
651 tokens.append("as");
David Tolnaydaaf7742016-10-03 11:11:43 -0700652 for (i, segment) in path.segments
653 .iter()
654 .take(qself.position)
655 .enumerate() {
David Tolnayf69904a2016-09-04 14:46:07 -0700656 if i > 0 || path.global {
657 tokens.append("::");
David Tolnay87d0b442016-09-04 11:52:12 -0700658 }
David Tolnayf69904a2016-09-04 14:46:07 -0700659 segment.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700660 }
David Tolnayf69904a2016-09-04 14:46:07 -0700661 }
662 tokens.append(">");
663 for segment in path.segments.iter().skip(qself.position) {
664 tokens.append("::");
665 segment.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700666 }
667 }
David Tolnay02c907f2017-01-23 00:06:37 -0800668 Ty::TraitObject(ref bounds) => {
David Tolnay6414da72016-10-08 00:55:17 -0700669 tokens.append_separated(bounds, "+");
670 }
David Tolnay87d0b442016-09-04 11:52:12 -0700671 Ty::ImplTrait(ref bounds) => {
672 tokens.append("impl");
David Tolnay94ebdf92016-09-04 13:33:16 -0700673 tokens.append_separated(bounds, "+");
David Tolnay87d0b442016-09-04 11:52:12 -0700674 }
675 Ty::Paren(ref inner) => {
676 tokens.append("(");
677 inner.to_tokens(tokens);
678 tokens.append(")");
679 }
680 Ty::Infer => {
681 tokens.append("_");
682 }
David Tolnay0047c712016-12-21 21:59:25 -0500683 Ty::Mac(ref mac) => mac.to_tokens(tokens),
David Tolnay87d0b442016-09-04 11:52:12 -0700684 }
685 }
686 }
687
David Tolnay47a877c2016-10-01 16:50:55 -0700688 impl ToTokens for Mutability {
689 fn to_tokens(&self, tokens: &mut Tokens) {
690 if let Mutability::Mutable = *self {
691 tokens.append("mut");
692 }
693 }
694 }
695
David Tolnay87d0b442016-09-04 11:52:12 -0700696 impl ToTokens for Path {
697 fn to_tokens(&self, tokens: &mut Tokens) {
698 for (i, segment) in self.segments.iter().enumerate() {
699 if i > 0 || self.global {
700 tokens.append("::");
701 }
702 segment.to_tokens(tokens);
703 }
704 }
705 }
706
707 impl ToTokens for PathSegment {
708 fn to_tokens(&self, tokens: &mut Tokens) {
709 self.ident.to_tokens(tokens);
David Tolnay5332d4b2016-10-30 14:25:22 -0700710 if self.ident.as_ref().is_empty() && self.parameters.is_empty() {
711 tokens.append("<");
712 tokens.append(">");
713 } else {
714 self.parameters.to_tokens(tokens);
715 }
David Tolnay87d0b442016-09-04 11:52:12 -0700716 }
717 }
718
719 impl ToTokens for PathParameters {
720 fn to_tokens(&self, tokens: &mut Tokens) {
721 match *self {
722 PathParameters::AngleBracketed(ref parameters) => {
723 parameters.to_tokens(tokens);
724 }
725 PathParameters::Parenthesized(ref parameters) => {
726 parameters.to_tokens(tokens);
727 }
728 }
729 }
730 }
731
732 impl ToTokens for AngleBracketedParameterData {
733 fn to_tokens(&self, tokens: &mut Tokens) {
734 let has_lifetimes = !self.lifetimes.is_empty();
735 let has_types = !self.types.is_empty();
736 let has_bindings = !self.bindings.is_empty();
737 if !has_lifetimes && !has_types && !has_bindings {
738 return;
739 }
740
741 tokens.append("<");
742
743 let mut first = true;
744 for lifetime in &self.lifetimes {
745 if !first {
746 tokens.append(",");
747 }
748 lifetime.to_tokens(tokens);
749 first = false;
750 }
751 for ty in &self.types {
752 if !first {
753 tokens.append(",");
754 }
755 ty.to_tokens(tokens);
756 first = false;
757 }
758 for binding in &self.bindings {
759 if !first {
760 tokens.append(",");
761 }
762 binding.to_tokens(tokens);
763 first = false;
764 }
765
766 tokens.append(">");
767 }
768 }
769
770 impl ToTokens for TypeBinding {
771 fn to_tokens(&self, tokens: &mut Tokens) {
772 self.ident.to_tokens(tokens);
773 tokens.append("=");
774 self.ty.to_tokens(tokens);
775 }
776 }
777
778 impl ToTokens for ParenthesizedParameterData {
779 fn to_tokens(&self, tokens: &mut Tokens) {
780 tokens.append("(");
David Tolnay94ebdf92016-09-04 13:33:16 -0700781 tokens.append_separated(&self.inputs, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700782 tokens.append(")");
783 if let Some(ref output) = self.output {
784 tokens.append("->");
785 output.to_tokens(tokens);
786 }
787 }
788 }
789
790 impl ToTokens for PolyTraitRef {
791 fn to_tokens(&self, tokens: &mut Tokens) {
792 if !self.bound_lifetimes.is_empty() {
David Tolnaye8796aa2016-09-04 14:48:22 -0700793 tokens.append("for");
David Tolnay87d0b442016-09-04 11:52:12 -0700794 tokens.append("<");
David Tolnay94ebdf92016-09-04 13:33:16 -0700795 tokens.append_separated(&self.bound_lifetimes, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700796 tokens.append(">");
797 }
798 self.trait_ref.to_tokens(tokens);
799 }
800 }
801
802 impl ToTokens for BareFnTy {
803 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay87d0b442016-09-04 11:52:12 -0700804 if !self.lifetimes.is_empty() {
David Tolnay4f121832016-10-25 21:33:36 -0700805 tokens.append("for");
David Tolnay87d0b442016-09-04 11:52:12 -0700806 tokens.append("<");
David Tolnay42602292016-10-01 22:25:45 -0700807 tokens.append_separated(&self.lifetimes, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700808 tokens.append(">");
809 }
David Tolnayb8d8ef52016-10-29 14:30:08 -0700810 self.unsafety.to_tokens(tokens);
811 self.abi.to_tokens(tokens);
David Tolnay4f121832016-10-25 21:33:36 -0700812 tokens.append("fn");
David Tolnay87d0b442016-09-04 11:52:12 -0700813 tokens.append("(");
David Tolnay42602292016-10-01 22:25:45 -0700814 tokens.append_separated(&self.inputs, ",");
David Tolnay292e6002016-10-29 22:03:51 -0700815 if self.variadic {
816 if !self.inputs.is_empty() {
817 tokens.append(",");
818 }
819 tokens.append("...");
820 }
David Tolnay87d0b442016-09-04 11:52:12 -0700821 tokens.append(")");
David Tolnay42602292016-10-01 22:25:45 -0700822 if let FunctionRetTy::Ty(ref ty) = self.output {
823 tokens.append("->");
824 ty.to_tokens(tokens);
825 }
826 }
827 }
828
David Tolnay62f374c2016-10-02 13:37:00 -0700829 impl ToTokens for BareFnArg {
David Tolnay42602292016-10-01 22:25:45 -0700830 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay62f374c2016-10-02 13:37:00 -0700831 if let Some(ref name) = self.name {
832 name.to_tokens(tokens);
David Tolnay42602292016-10-01 22:25:45 -0700833 tokens.append(":");
834 }
835 self.ty.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700836 }
837 }
David Tolnayb8d8ef52016-10-29 14:30:08 -0700838
839 impl ToTokens for Unsafety {
840 fn to_tokens(&self, tokens: &mut Tokens) {
841 match *self {
842 Unsafety::Unsafe => tokens.append("unsafe"),
843 Unsafety::Normal => {
844 // nothing
845 }
846 }
847 }
848 }
849
850 impl ToTokens for Abi {
851 fn to_tokens(&self, tokens: &mut Tokens) {
852 tokens.append("extern");
853 match *self {
854 Abi::Named(ref named) => named.to_tokens(tokens),
David Tolnay76195ce2016-10-30 16:53:48 -0700855 Abi::Rust => {}
David Tolnayb8d8ef52016-10-29 14:30:08 -0700856 }
857 }
858 }
David Tolnay0047c712016-12-21 21:59:25 -0500859
860 #[cfg(not(feature = "type-macros"))]
861 impl ToTokens for Mac {
862 fn to_tokens(&self, _tokens: &mut Tokens) {
863 unreachable!()
864 }
865 }
David Tolnay87d0b442016-09-04 11:52:12 -0700866}