blob: 2a8ca73b85317c83cf2d16a170ea4733b804c78d [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 Tolnayfe2cc9a2016-10-30 12:47:36 -0700240 #[cfg(feature = "full")]
241 use ConstExpr;
David Tolnay3cb23a92016-10-07 23:02:21 -0700242 use constant::parsing::const_expr;
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700243 #[cfg(feature = "full")]
244 use expr::parsing::expr;
David Tolnay9d8f1972016-09-04 11:58:48 -0700245 use generics::parsing::{lifetime, lifetime_def, ty_param_bound, bound_lifetimes};
David Tolnay55337722016-09-11 12:58:56 -0700246 use ident::parsing::ident;
David Tolnayb8d8ef52016-10-29 14:30:08 -0700247 use lit::parsing::quoted_string;
David Tolnay0047c712016-12-21 21:59:25 -0500248 #[cfg(feature = "type-macros")]
249 use mac::parsing::mac;
250 #[cfg(not(feature = "type-macros"))]
251 use nom::IResult;
David Tolnay9d8f1972016-09-04 11:58:48 -0700252 use std::str;
David Tolnayda4049b2016-09-04 10:59:23 -0700253
David Tolnayb5a7b142016-09-13 22:46:39 -0700254 named!(pub ty -> Ty, alt!(
David Tolnayd040d772016-10-25 21:33:51 -0700255 ty_paren // must be before ty_tup
256 |
David Tolnay0047c712016-12-21 21:59:25 -0500257 ty_mac // must be before ty_path
258 |
David Tolnay4f0f2512016-10-30 09:28:14 -0700259 ty_path // must be before ty_poly_trait_ref
260 |
David Tolnay9d8f1972016-09-04 11:58:48 -0700261 ty_vec
David Tolnayda4049b2016-09-04 10:59:23 -0700262 |
David Tolnayfa94b6f2016-10-05 23:26:11 -0700263 ty_array
David Tolnayb79ee962016-09-04 09:39:20 -0700264 |
David Tolnay9d8f1972016-09-04 11:58:48 -0700265 ty_ptr
266 |
267 ty_rptr
268 |
269 ty_bare_fn
270 |
271 ty_never
272 |
273 ty_tup
274 |
David Tolnay4f0f2512016-10-30 09:28:14 -0700275 ty_poly_trait_ref
David Tolnay9d8f1972016-09-04 11:58:48 -0700276 |
David Tolnay9d8f1972016-09-04 11:58:48 -0700277 ty_impl_trait
David Tolnay9d8f1972016-09-04 11:58:48 -0700278 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700279
David Tolnay0047c712016-12-21 21:59:25 -0500280 #[cfg(feature = "type-macros")]
281 named!(ty_mac -> Ty, map!(mac, Ty::Mac));
282
283 #[cfg(not(feature = "type-macros"))]
284 fn ty_mac(_: &str) -> IResult<&str, Ty> {
285 IResult::Error
286 }
287
David Tolnayb5a7b142016-09-13 22:46:39 -0700288 named!(ty_vec -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700289 punct!("[") >>
290 elem: ty >>
291 punct!("]") >>
David Tolnay16709ba2016-10-05 23:11:32 -0700292 (Ty::Slice(Box::new(elem)))
David Tolnay9d8f1972016-09-04 11:58:48 -0700293 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700294
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700295 #[cfg(not(feature = "full"))]
David Tolnayfa94b6f2016-10-05 23:26:11 -0700296 named!(ty_array -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700297 punct!("[") >>
298 elem: ty >>
299 punct!(";") >>
David Tolnay3cb23a92016-10-07 23:02:21 -0700300 len: const_expr >>
David Tolnayc94c38a2016-09-05 17:02:03 -0700301 punct!("]") >>
David Tolnayfa94b6f2016-10-05 23:26:11 -0700302 (Ty::Array(Box::new(elem), len))
303 ));
304
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700305 #[cfg(feature = "full")]
306 named!(ty_array -> Ty, do_parse!(
307 punct!("[") >>
308 elem: ty >>
309 punct!(";") >>
310 len: alt!(
311 terminated!(const_expr, punct!("]"))
312 |
313 terminated!(expr, punct!("]")) => { ConstExpr::Other }
314 ) >>
315 (Ty::Array(Box::new(elem), len))
316 ));
317
David Tolnayb5a7b142016-09-13 22:46:39 -0700318 named!(ty_ptr -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700319 punct!("*") >>
David Tolnayb5a7b142016-09-13 22:46:39 -0700320 mutability: alt!(
David Tolnay10413f02016-09-30 09:12:02 -0700321 keyword!("const") => { |_| Mutability::Immutable }
David Tolnay9d8f1972016-09-04 11:58:48 -0700322 |
David Tolnay10413f02016-09-30 09:12:02 -0700323 keyword!("mut") => { |_| Mutability::Mutable }
David Tolnay9d8f1972016-09-04 11:58:48 -0700324 ) >>
325 target: ty >>
326 (Ty::Ptr(Box::new(MutTy {
327 ty: target,
328 mutability: mutability,
329 })))
330 ));
331
David Tolnayb5a7b142016-09-13 22:46:39 -0700332 named!(ty_rptr -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700333 punct!("&") >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700334 life: option!(lifetime) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700335 mutability: mutability >>
336 target: ty >>
337 (Ty::Rptr(life, Box::new(MutTy {
338 ty: target,
339 mutability: mutability,
340 })))
341 ));
342
David Tolnayb5a7b142016-09-13 22:46:39 -0700343 named!(ty_bare_fn -> Ty, do_parse!(
David Tolnay4f121832016-10-25 21:33:36 -0700344 lifetimes: opt_vec!(do_parse!(
345 keyword!("for") >>
346 punct!("<") >>
347 lifetimes: terminated_list!(punct!(","), lifetime_def) >>
348 punct!(">") >>
349 (lifetimes)
David Tolnay6b7aaf02016-09-04 10:39:25 -0700350 )) >>
David Tolnayb8d8ef52016-10-29 14:30:08 -0700351 unsafety: unsafety >>
352 abi: option!(abi) >>
David Tolnay4f121832016-10-25 21:33:36 -0700353 keyword!("fn") >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700354 punct!("(") >>
David Tolnay292e6002016-10-29 22:03:51 -0700355 inputs: separated_list!(punct!(","), fn_arg) >>
356 trailing_comma: option!(punct!(",")) >>
357 variadic: option!(cond_reduce!(trailing_comma.is_some(), punct!("..."))) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700358 punct!(")") >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700359 output: option!(preceded!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700360 punct!("->"),
361 ty
362 )) >>
363 (Ty::BareFn(Box::new(BareFnTy {
David Tolnayb8d8ef52016-10-29 14:30:08 -0700364 unsafety: unsafety,
365 abi: abi,
David Tolnay9d8f1972016-09-04 11:58:48 -0700366 lifetimes: lifetimes,
David Tolnay62f374c2016-10-02 13:37:00 -0700367 inputs: inputs,
368 output: match output {
369 Some(ty) => FunctionRetTy::Ty(ty),
370 None => FunctionRetTy::Default,
David Tolnay9d8f1972016-09-04 11:58:48 -0700371 },
David Tolnay292e6002016-10-29 22:03:51 -0700372 variadic: variadic.is_some(),
David Tolnay9d8f1972016-09-04 11:58:48 -0700373 })))
374 ));
375
David Tolnayb5a7b142016-09-13 22:46:39 -0700376 named!(ty_never -> Ty, map!(punct!("!"), |_| Ty::Never));
David Tolnay9d8f1972016-09-04 11:58:48 -0700377
David Tolnayb5a7b142016-09-13 22:46:39 -0700378 named!(ty_tup -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700379 punct!("(") >>
David Tolnayff46fd22016-10-08 13:53:28 -0700380 elems: terminated_list!(punct!(","), ty) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700381 punct!(")") >>
382 (Ty::Tup(elems))
383 ));
384
David Tolnay6414da72016-10-08 00:55:17 -0700385 named!(ty_path -> Ty, do_parse!(
386 qpath: qpath >>
David Tolnayf6c74402016-10-08 02:31:26 -0700387 parenthesized: cond!(
388 qpath.1.segments.last().unwrap().parameters == PathParameters::none(),
389 option!(parenthesized_parameter_data)
390 ) >>
David Tolnay6414da72016-10-08 00:55:17 -0700391 bounds: many0!(preceded!(punct!("+"), ty_param_bound)) >>
392 ({
David Tolnayf6c74402016-10-08 02:31:26 -0700393 let (qself, mut path) = qpath;
394 if let Some(Some(parenthesized)) = parenthesized {
395 path.segments.last_mut().unwrap().parameters = parenthesized;
396 }
David Tolnay6414da72016-10-08 00:55:17 -0700397 if bounds.is_empty() {
David Tolnay02c907f2017-01-23 00:06:37 -0800398 Ty::Path(qself, path)
David Tolnay6414da72016-10-08 00:55:17 -0700399 } else {
David Tolnay02c907f2017-01-23 00:06:37 -0800400 let path = TyParamBound::Trait(
401 PolyTraitRef {
402 bound_lifetimes: Vec::new(),
403 trait_ref: path,
404 },
405 TraitBoundModifier::None,
406 );
407 let bounds = Some(path).into_iter().chain(bounds).collect();
408 Ty::TraitObject(bounds)
David Tolnay6414da72016-10-08 00:55:17 -0700409 }
410 })
411 ));
David Tolnay9d8f1972016-09-04 11:58:48 -0700412
David Tolnayf6c74402016-10-08 02:31:26 -0700413 named!(parenthesized_parameter_data -> PathParameters, do_parse!(
414 punct!("(") >>
David Tolnayff46fd22016-10-08 13:53:28 -0700415 inputs: terminated_list!(punct!(","), ty) >>
David Tolnayf6c74402016-10-08 02:31:26 -0700416 punct!(")") >>
417 output: option!(preceded!(
418 punct!("->"),
419 ty
420 )) >>
421 (PathParameters::Parenthesized(
422 ParenthesizedParameterData {
423 inputs: inputs,
424 output: output,
425 },
426 ))
427 ));
428
David Tolnay9636c052016-10-02 17:11:17 -0700429 named!(pub qpath -> (Option<QSelf>, Path), alt!(
430 map!(path, |p| (None, p))
431 |
432 do_parse!(
433 punct!("<") >>
434 this: map!(ty, Box::new) >>
435 path: option!(preceded!(
436 keyword!("as"),
437 path
438 )) >>
439 punct!(">") >>
440 punct!("::") >>
441 rest: separated_nonempty_list!(punct!("::"), path_segment) >>
442 ({
443 match path {
444 Some(mut path) => {
445 let pos = path.segments.len();
446 path.segments.extend(rest);
447 (Some(QSelf { ty: this, position: pos }), path)
448 }
449 None => {
450 (Some(QSelf { ty: this, position: 0 }), Path {
451 global: false,
452 segments: rest,
453 })
454 }
David Tolnayb79ee962016-09-04 09:39:20 -0700455 }
David Tolnay9636c052016-10-02 17:11:17 -0700456 })
457 )
David Tolnay6cd2a232016-10-24 22:41:08 -0700458 |
459 map!(keyword!("self"), |_| (None, "self".into()))
David Tolnay9d8f1972016-09-04 11:58:48 -0700460 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700461
David Tolnay4f0f2512016-10-30 09:28:14 -0700462 named!(ty_poly_trait_ref -> Ty, map!(
David Tolnay8eb6c452016-10-30 13:19:15 -0700463 separated_nonempty_list!(punct!("+"), ty_param_bound),
David Tolnay02c907f2017-01-23 00:06:37 -0800464 Ty::TraitObject
David Tolnay6414da72016-10-08 00:55:17 -0700465 ));
466
David Tolnayb5a7b142016-09-13 22:46:39 -0700467 named!(ty_impl_trait -> Ty, do_parse!(
David Tolnay10413f02016-09-30 09:12:02 -0700468 keyword!("impl") >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700469 elem: separated_nonempty_list!(punct!("+"), ty_param_bound) >>
470 (Ty::ImplTrait(elem))
471 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700472
David Tolnayb5a7b142016-09-13 22:46:39 -0700473 named!(ty_paren -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700474 punct!("(") >>
475 elem: ty >>
476 punct!(")") >>
477 (Ty::Paren(Box::new(elem)))
478 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700479
David Tolnay47a877c2016-10-01 16:50:55 -0700480 named!(pub mutability -> Mutability, alt!(
David Tolnaybd76e572016-10-02 13:43:16 -0700481 keyword!("mut") => { |_| Mutability::Mutable }
David Tolnayf6ccb832016-09-04 15:00:56 -0700482 |
483 epsilon!() => { |_| Mutability::Immutable }
David Tolnay9d8f1972016-09-04 11:58:48 -0700484 ));
485
David Tolnayb5a7b142016-09-13 22:46:39 -0700486 named!(pub path -> Path, do_parse!(
David Tolnayf6ccb832016-09-04 15:00:56 -0700487 global: option!(punct!("::")) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700488 segments: separated_nonempty_list!(punct!("::"), path_segment) >>
489 (Path {
490 global: global.is_some(),
491 segments: segments,
492 })
493 ));
494
David Tolnay9636c052016-10-02 17:11:17 -0700495 named!(path_segment -> PathSegment, alt!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700496 do_parse!(
David Tolnay9636c052016-10-02 17:11:17 -0700497 id: option!(ident) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700498 punct!("<") >>
499 lifetimes: separated_list!(punct!(","), lifetime) >>
500 types: opt_vec!(preceded!(
501 cond!(!lifetimes.is_empty(), punct!(",")),
502 separated_nonempty_list!(
503 punct!(","),
504 terminated!(ty, not!(peek!(punct!("="))))
505 )
506 )) >>
507 bindings: opt_vec!(preceded!(
508 cond!(!lifetimes.is_empty() || !types.is_empty(), punct!(",")),
509 separated_nonempty_list!(punct!(","), type_binding)
510 )) >>
David Tolnay82a47d52016-10-30 13:01:38 -0700511 cond!(!lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty(), option!(punct!(","))) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700512 punct!(">") >>
513 (PathSegment {
David Tolnay9636c052016-10-02 17:11:17 -0700514 ident: id.unwrap_or_else(|| "".into()),
David Tolnay9d8f1972016-09-04 11:58:48 -0700515 parameters: PathParameters::AngleBracketed(
516 AngleBracketedParameterData {
517 lifetimes: lifetimes,
518 types: types,
519 bindings: bindings,
520 }
521 ),
522 })
523 )
524 |
David Tolnay84aa0752016-10-02 23:01:13 -0700525 map!(ident, Into::into)
David Tolnay77807222016-10-24 22:30:15 -0700526 |
David Tolnaye14e3be2016-10-24 22:53:07 -0700527 map!(alt!(
528 keyword!("super")
529 |
530 keyword!("self")
531 |
532 keyword!("Self")
533 ), Into::into)
David Tolnay9d8f1972016-09-04 11:58:48 -0700534 ));
535
David Tolnayb5a7b142016-09-13 22:46:39 -0700536 named!(type_binding -> TypeBinding, do_parse!(
David Tolnay55337722016-09-11 12:58:56 -0700537 id: ident >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700538 punct!("=") >>
539 ty: ty >>
540 (TypeBinding {
David Tolnay55337722016-09-11 12:58:56 -0700541 ident: id,
David Tolnay9d8f1972016-09-04 11:58:48 -0700542 ty: ty,
543 })
544 ));
545
David Tolnayb5a7b142016-09-13 22:46:39 -0700546 named!(pub poly_trait_ref -> PolyTraitRef, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700547 bound_lifetimes: bound_lifetimes >>
548 trait_ref: path >>
David Tolnay4f0f2512016-10-30 09:28:14 -0700549 parenthesized: option!(cond_reduce!(
David Tolnayf6c74402016-10-08 02:31:26 -0700550 trait_ref.segments.last().unwrap().parameters == PathParameters::none(),
David Tolnay4f0f2512016-10-30 09:28:14 -0700551 parenthesized_parameter_data
552 )) >>
David Tolnayf6c74402016-10-08 02:31:26 -0700553 ({
554 let mut trait_ref = trait_ref;
David Tolnay4f0f2512016-10-30 09:28:14 -0700555 if let Some(parenthesized) = parenthesized {
David Tolnayf6c74402016-10-08 02:31:26 -0700556 trait_ref.segments.last_mut().unwrap().parameters = parenthesized;
557 }
558 PolyTraitRef {
559 bound_lifetimes: bound_lifetimes,
560 trait_ref: trait_ref,
561 }
David Tolnay9d8f1972016-09-04 11:58:48 -0700562 })
563 ));
564
David Tolnay62f374c2016-10-02 13:37:00 -0700565 named!(pub fn_arg -> BareFnArg, do_parse!(
David Tolnayb0417d72016-10-25 21:46:35 -0700566 name: option!(do_parse!(
567 name: ident >>
568 punct!(":") >>
569 not!(peek!(tag!(":"))) >> // not ::
570 (name)
571 )) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700572 ty: ty >>
David Tolnay62f374c2016-10-02 13:37:00 -0700573 (BareFnArg {
574 name: name,
David Tolnay9d8f1972016-09-04 11:58:48 -0700575 ty: ty,
576 })
577 ));
David Tolnayb8d8ef52016-10-29 14:30:08 -0700578
579 named!(pub unsafety -> Unsafety, alt!(
580 keyword!("unsafe") => { |_| Unsafety::Unsafe }
581 |
582 epsilon!() => { |_| Unsafety::Normal }
583 ));
584
585 named!(pub abi -> Abi, do_parse!(
586 keyword!("extern") >>
587 name: option!(quoted_string) >>
588 (match name {
589 Some(name) => Abi::Named(name),
David Tolnay76195ce2016-10-30 16:53:48 -0700590 None => Abi::Rust,
David Tolnayb8d8ef52016-10-29 14:30:08 -0700591 })
592 ));
David Tolnay9d8f1972016-09-04 11:58:48 -0700593}
David Tolnay87d0b442016-09-04 11:52:12 -0700594
595#[cfg(feature = "printing")]
596mod printing {
597 use super::*;
598 use quote::{Tokens, ToTokens};
599
600 impl ToTokens for Ty {
601 fn to_tokens(&self, tokens: &mut Tokens) {
602 match *self {
David Tolnay16709ba2016-10-05 23:11:32 -0700603 Ty::Slice(ref inner) => {
David Tolnay87d0b442016-09-04 11:52:12 -0700604 tokens.append("[");
605 inner.to_tokens(tokens);
606 tokens.append("]");
607 }
David Tolnayfa94b6f2016-10-05 23:26:11 -0700608 Ty::Array(ref inner, ref len) => {
David Tolnay87d0b442016-09-04 11:52:12 -0700609 tokens.append("[");
610 inner.to_tokens(tokens);
611 tokens.append(";");
David Tolnayfa94b6f2016-10-05 23:26:11 -0700612 len.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700613 tokens.append("]");
614 }
615 Ty::Ptr(ref target) => {
616 tokens.append("*");
617 match target.mutability {
618 Mutability::Mutable => tokens.append("mut"),
619 Mutability::Immutable => tokens.append("const"),
620 }
621 target.ty.to_tokens(tokens);
622 }
623 Ty::Rptr(ref lifetime, ref target) => {
624 tokens.append("&");
625 lifetime.to_tokens(tokens);
David Tolnay47a877c2016-10-01 16:50:55 -0700626 target.mutability.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700627 target.ty.to_tokens(tokens);
628 }
629 Ty::BareFn(ref func) => {
630 func.to_tokens(tokens);
631 }
632 Ty::Never => {
633 tokens.append("!");
634 }
635 Ty::Tup(ref elems) => {
636 tokens.append("(");
David Tolnay94ebdf92016-09-04 13:33:16 -0700637 tokens.append_separated(elems, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700638 if elems.len() == 1 {
639 tokens.append(",");
640 }
641 tokens.append(")");
642 }
David Tolnayf69904a2016-09-04 14:46:07 -0700643 Ty::Path(None, ref path) => {
644 path.to_tokens(tokens);
645 }
646 Ty::Path(Some(ref qself), ref path) => {
647 tokens.append("<");
648 qself.ty.to_tokens(tokens);
649 if qself.position > 0 {
650 tokens.append("as");
David Tolnaydaaf7742016-10-03 11:11:43 -0700651 for (i, segment) in path.segments
652 .iter()
653 .take(qself.position)
654 .enumerate() {
David Tolnayf69904a2016-09-04 14:46:07 -0700655 if i > 0 || path.global {
656 tokens.append("::");
David Tolnay87d0b442016-09-04 11:52:12 -0700657 }
David Tolnayf69904a2016-09-04 14:46:07 -0700658 segment.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700659 }
David Tolnayf69904a2016-09-04 14:46:07 -0700660 }
661 tokens.append(">");
662 for segment in path.segments.iter().skip(qself.position) {
663 tokens.append("::");
664 segment.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700665 }
666 }
David Tolnay02c907f2017-01-23 00:06:37 -0800667 Ty::TraitObject(ref bounds) => {
David Tolnay6414da72016-10-08 00:55:17 -0700668 tokens.append_separated(bounds, "+");
669 }
David Tolnay87d0b442016-09-04 11:52:12 -0700670 Ty::ImplTrait(ref bounds) => {
671 tokens.append("impl");
David Tolnay94ebdf92016-09-04 13:33:16 -0700672 tokens.append_separated(bounds, "+");
David Tolnay87d0b442016-09-04 11:52:12 -0700673 }
674 Ty::Paren(ref inner) => {
675 tokens.append("(");
676 inner.to_tokens(tokens);
677 tokens.append(")");
678 }
679 Ty::Infer => {
680 tokens.append("_");
681 }
David Tolnay0047c712016-12-21 21:59:25 -0500682 Ty::Mac(ref mac) => mac.to_tokens(tokens),
David Tolnay87d0b442016-09-04 11:52:12 -0700683 }
684 }
685 }
686
David Tolnay47a877c2016-10-01 16:50:55 -0700687 impl ToTokens for Mutability {
688 fn to_tokens(&self, tokens: &mut Tokens) {
689 if let Mutability::Mutable = *self {
690 tokens.append("mut");
691 }
692 }
693 }
694
David Tolnay87d0b442016-09-04 11:52:12 -0700695 impl ToTokens for Path {
696 fn to_tokens(&self, tokens: &mut Tokens) {
697 for (i, segment) in self.segments.iter().enumerate() {
698 if i > 0 || self.global {
699 tokens.append("::");
700 }
701 segment.to_tokens(tokens);
702 }
703 }
704 }
705
706 impl ToTokens for PathSegment {
707 fn to_tokens(&self, tokens: &mut Tokens) {
708 self.ident.to_tokens(tokens);
David Tolnay5332d4b2016-10-30 14:25:22 -0700709 if self.ident.as_ref().is_empty() && self.parameters.is_empty() {
710 tokens.append("<");
711 tokens.append(">");
712 } else {
713 self.parameters.to_tokens(tokens);
714 }
David Tolnay87d0b442016-09-04 11:52:12 -0700715 }
716 }
717
718 impl ToTokens for PathParameters {
719 fn to_tokens(&self, tokens: &mut Tokens) {
720 match *self {
721 PathParameters::AngleBracketed(ref parameters) => {
722 parameters.to_tokens(tokens);
723 }
724 PathParameters::Parenthesized(ref parameters) => {
725 parameters.to_tokens(tokens);
726 }
727 }
728 }
729 }
730
731 impl ToTokens for AngleBracketedParameterData {
732 fn to_tokens(&self, tokens: &mut Tokens) {
733 let has_lifetimes = !self.lifetimes.is_empty();
734 let has_types = !self.types.is_empty();
735 let has_bindings = !self.bindings.is_empty();
736 if !has_lifetimes && !has_types && !has_bindings {
737 return;
738 }
739
740 tokens.append("<");
741
742 let mut first = true;
743 for lifetime in &self.lifetimes {
744 if !first {
745 tokens.append(",");
746 }
747 lifetime.to_tokens(tokens);
748 first = false;
749 }
750 for ty in &self.types {
751 if !first {
752 tokens.append(",");
753 }
754 ty.to_tokens(tokens);
755 first = false;
756 }
757 for binding in &self.bindings {
758 if !first {
759 tokens.append(",");
760 }
761 binding.to_tokens(tokens);
762 first = false;
763 }
764
765 tokens.append(">");
766 }
767 }
768
769 impl ToTokens for TypeBinding {
770 fn to_tokens(&self, tokens: &mut Tokens) {
771 self.ident.to_tokens(tokens);
772 tokens.append("=");
773 self.ty.to_tokens(tokens);
774 }
775 }
776
777 impl ToTokens for ParenthesizedParameterData {
778 fn to_tokens(&self, tokens: &mut Tokens) {
779 tokens.append("(");
David Tolnay94ebdf92016-09-04 13:33:16 -0700780 tokens.append_separated(&self.inputs, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700781 tokens.append(")");
782 if let Some(ref output) = self.output {
783 tokens.append("->");
784 output.to_tokens(tokens);
785 }
786 }
787 }
788
789 impl ToTokens for PolyTraitRef {
790 fn to_tokens(&self, tokens: &mut Tokens) {
791 if !self.bound_lifetimes.is_empty() {
David Tolnaye8796aa2016-09-04 14:48:22 -0700792 tokens.append("for");
David Tolnay87d0b442016-09-04 11:52:12 -0700793 tokens.append("<");
David Tolnay94ebdf92016-09-04 13:33:16 -0700794 tokens.append_separated(&self.bound_lifetimes, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700795 tokens.append(">");
796 }
797 self.trait_ref.to_tokens(tokens);
798 }
799 }
800
801 impl ToTokens for BareFnTy {
802 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay87d0b442016-09-04 11:52:12 -0700803 if !self.lifetimes.is_empty() {
David Tolnay4f121832016-10-25 21:33:36 -0700804 tokens.append("for");
David Tolnay87d0b442016-09-04 11:52:12 -0700805 tokens.append("<");
David Tolnay42602292016-10-01 22:25:45 -0700806 tokens.append_separated(&self.lifetimes, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700807 tokens.append(">");
808 }
David Tolnayb8d8ef52016-10-29 14:30:08 -0700809 self.unsafety.to_tokens(tokens);
810 self.abi.to_tokens(tokens);
David Tolnay4f121832016-10-25 21:33:36 -0700811 tokens.append("fn");
David Tolnay87d0b442016-09-04 11:52:12 -0700812 tokens.append("(");
David Tolnay42602292016-10-01 22:25:45 -0700813 tokens.append_separated(&self.inputs, ",");
David Tolnay292e6002016-10-29 22:03:51 -0700814 if self.variadic {
815 if !self.inputs.is_empty() {
816 tokens.append(",");
817 }
818 tokens.append("...");
819 }
David Tolnay87d0b442016-09-04 11:52:12 -0700820 tokens.append(")");
David Tolnay42602292016-10-01 22:25:45 -0700821 if let FunctionRetTy::Ty(ref ty) = self.output {
822 tokens.append("->");
823 ty.to_tokens(tokens);
824 }
825 }
826 }
827
David Tolnay62f374c2016-10-02 13:37:00 -0700828 impl ToTokens for BareFnArg {
David Tolnay42602292016-10-01 22:25:45 -0700829 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay62f374c2016-10-02 13:37:00 -0700830 if let Some(ref name) = self.name {
831 name.to_tokens(tokens);
David Tolnay42602292016-10-01 22:25:45 -0700832 tokens.append(":");
833 }
834 self.ty.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700835 }
836 }
David Tolnayb8d8ef52016-10-29 14:30:08 -0700837
838 impl ToTokens for Unsafety {
839 fn to_tokens(&self, tokens: &mut Tokens) {
840 match *self {
841 Unsafety::Unsafe => tokens.append("unsafe"),
842 Unsafety::Normal => {
843 // nothing
844 }
845 }
846 }
847 }
848
849 impl ToTokens for Abi {
850 fn to_tokens(&self, tokens: &mut Tokens) {
851 tokens.append("extern");
852 match *self {
853 Abi::Named(ref named) => named.to_tokens(tokens),
David Tolnay76195ce2016-10-30 16:53:48 -0700854 Abi::Rust => {}
David Tolnayb8d8ef52016-10-29 14:30:08 -0700855 }
856 }
857 }
David Tolnay0047c712016-12-21 21:59:25 -0500858
859 #[cfg(not(feature = "type-macros"))]
860 impl ToTokens for Mac {
861 fn to_tokens(&self, _tokens: &mut Tokens) {
862 unreachable!()
863 }
864 }
David Tolnay87d0b442016-09-04 11:52:12 -0700865}