blob: 662d03840204d45c754ef5205677ff23398fa30c [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 Tolnayb79ee962016-09-04 09:39:20 -07004#[derive(Debug, Clone, Eq, PartialEq)]
5pub 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),
25 /// Something like `A+B`. Note that `B` must always be a path.
26 ObjectSum(Box<Ty>, Vec<TyParamBound>),
27 /// A type like `for<'a> Foo<&'a Bar>`
28 PolyTraitRef(Vec<TyParamBound>),
29 /// An `impl TraitA+TraitB` type.
30 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"))]
41#[derive(Debug, Clone, Eq, PartialEq)]
42pub struct Mac {
43 _private: (),
David Tolnayb79ee962016-09-04 09:39:20 -070044}
45
46#[derive(Debug, Clone, Eq, PartialEq)]
47pub struct MutTy {
48 pub ty: Ty,
49 pub mutability: Mutability,
50}
51
David Tolnayf4bbbd92016-09-23 14:41:55 -070052#[derive(Debug, Copy, Clone, Eq, PartialEq)]
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 Tolnayb79ee962016-09-04 09:39:20 -070064#[derive(Debug, Clone, Eq, PartialEq)]
65pub struct Path {
66 pub global: bool,
67 pub segments: Vec<PathSegment>,
68}
69
David Tolnaydaaf7742016-10-03 11:11:43 -070070impl<T> From<T> for Path
71 where T: Into<PathSegment>
72{
David Tolnay84aa0752016-10-02 23:01:13 -070073 fn from(segment: T) -> Self {
74 Path {
75 global: false,
76 segments: vec![segment.into()],
77 }
78 }
79}
80
David Tolnayb79ee962016-09-04 09:39:20 -070081/// A segment of a path: an identifier, an optional lifetime, and a set of types.
82///
83/// E.g. `std`, `String` or `Box<T>`
84#[derive(Debug, Clone, Eq, PartialEq)]
85pub struct PathSegment {
86 pub ident: Ident,
87 pub parameters: PathParameters,
88}
89
David Tolnaydaaf7742016-10-03 11:11:43 -070090impl<T> From<T> for PathSegment
91 where T: Into<Ident>
92{
David Tolnay84aa0752016-10-02 23:01:13 -070093 fn from(ident: T) -> Self {
David Tolnayb79ee962016-09-04 09:39:20 -070094 PathSegment {
David Tolnay84aa0752016-10-02 23:01:13 -070095 ident: ident.into(),
David Tolnayb79ee962016-09-04 09:39:20 -070096 parameters: PathParameters::none(),
97 }
98 }
99}
100
101/// Parameters of a path segment.
102///
103/// E.g. `<A, B>` as in `Foo<A, B>` or `(A, B)` as in `Foo(A, B)`
104#[derive(Debug, Clone, Eq, PartialEq)]
105pub enum PathParameters {
106 /// The `<'a, A, B, C>` in `foo::bar::baz::<'a, A, B, C>`
107 AngleBracketed(AngleBracketedParameterData),
108 /// The `(A, B)` and `C` in `Foo(A, B) -> C`
109 Parenthesized(ParenthesizedParameterData),
110}
111
112impl PathParameters {
113 pub fn none() -> Self {
114 PathParameters::AngleBracketed(AngleBracketedParameterData::default())
115 }
David Tolnay5332d4b2016-10-30 14:25:22 -0700116
117 pub fn is_empty(&self) -> bool {
118 match *self {
119 PathParameters::AngleBracketed(ref bracketed) => {
David Tolnayc1fea502016-10-30 17:54:02 -0700120 bracketed.lifetimes.is_empty() && bracketed.types.is_empty() &&
121 bracketed.bindings.is_empty()
David Tolnay5332d4b2016-10-30 14:25:22 -0700122 }
123 PathParameters::Parenthesized(_) => false,
124 }
125 }
David Tolnayb79ee962016-09-04 09:39:20 -0700126}
127
128/// A path like `Foo<'a, T>`
129#[derive(Debug, Clone, Eq, PartialEq, Default)]
130pub struct AngleBracketedParameterData {
131 /// The lifetime parameters for this path segment.
132 pub lifetimes: Vec<Lifetime>,
133 /// The type parameters for this path segment, if present.
134 pub types: Vec<Ty>,
135 /// Bindings (equality constraints) on associated types, if present.
136 ///
137 /// E.g., `Foo<A=Bar>`.
138 pub bindings: Vec<TypeBinding>,
139}
140
141/// Bind a type to an associated type: `A=Foo`.
142#[derive(Debug, Clone, Eq, PartialEq)]
143pub struct TypeBinding {
144 pub ident: Ident,
145 pub ty: Ty,
146}
147
148/// A path like `Foo(A,B) -> C`
149#[derive(Debug, Clone, Eq, PartialEq)]
150pub struct ParenthesizedParameterData {
151 /// `(A, B)`
152 pub inputs: Vec<Ty>,
153 /// `C`
154 pub output: Option<Ty>,
155}
156
157#[derive(Debug, Clone, Eq, PartialEq)]
158pub struct PolyTraitRef {
159 /// The `'a` in `<'a> Foo<&'a T>`
160 pub bound_lifetimes: Vec<LifetimeDef>,
161 /// The `Foo<&'a T>` in `<'a> Foo<&'a T>`
162 pub trait_ref: Path,
163}
164
165/// The explicit Self type in a "qualified path". The actual
166/// path, including the trait and the associated item, is stored
167/// separately. `position` represents the index of the associated
168/// item qualified with this Self type.
169///
170/// ```rust,ignore
171/// <Vec<T> as a::b::Trait>::AssociatedItem
172/// ^~~~~ ~~~~~~~~~~~~~~^
173/// ty position = 3
174///
175/// <Vec<T>>::AssociatedItem
176/// ^~~~~ ^
177/// ty position = 0
178/// ```
179#[derive(Debug, Clone, Eq, PartialEq)]
180pub struct QSelf {
181 pub ty: Box<Ty>,
David Tolnaydaaf7742016-10-03 11:11:43 -0700182 pub position: usize,
David Tolnayb79ee962016-09-04 09:39:20 -0700183}
184
185#[derive(Debug, Clone, Eq, PartialEq)]
186pub struct BareFnTy {
David Tolnayb8d8ef52016-10-29 14:30:08 -0700187 pub unsafety: Unsafety,
188 pub abi: Option<Abi>,
David Tolnayb79ee962016-09-04 09:39:20 -0700189 pub lifetimes: Vec<LifetimeDef>,
David Tolnay62f374c2016-10-02 13:37:00 -0700190 pub inputs: Vec<BareFnArg>,
David Tolnayb79ee962016-09-04 09:39:20 -0700191 pub output: FunctionRetTy,
David Tolnay292e6002016-10-29 22:03:51 -0700192 pub variadic: bool,
David Tolnayb79ee962016-09-04 09:39:20 -0700193}
194
David Tolnayb8d8ef52016-10-29 14:30:08 -0700195#[derive(Debug, Copy, Clone, Eq, PartialEq)]
196pub enum Unsafety {
197 Unsafe,
198 Normal,
199}
200
201#[derive(Debug, Clone, Eq, PartialEq)]
202pub enum Abi {
203 Named(String),
David Tolnay76195ce2016-10-30 16:53:48 -0700204 Rust,
David Tolnayb8d8ef52016-10-29 14:30:08 -0700205}
206
David Tolnay62f374c2016-10-02 13:37:00 -0700207/// An argument in a function type.
David Tolnayb79ee962016-09-04 09:39:20 -0700208///
209/// E.g. `bar: usize` as in `fn foo(bar: usize)`
210#[derive(Debug, Clone, Eq, PartialEq)]
David Tolnay62f374c2016-10-02 13:37:00 -0700211pub struct BareFnArg {
212 pub name: Option<Ident>,
David Tolnayb79ee962016-09-04 09:39:20 -0700213 pub ty: Ty,
214}
215
216#[derive(Debug, Clone, Eq, PartialEq)]
217pub enum FunctionRetTy {
218 /// Return type is not specified.
219 ///
220 /// Functions default to `()` and
221 /// closures default to inference. Span points to where return
222 /// type would be inserted.
223 Default,
224 /// Everything else
225 Ty(Ty),
226}
227
David Tolnay86eca752016-09-04 11:26:41 -0700228#[cfg(feature = "parsing")]
David Tolnay9d8f1972016-09-04 11:58:48 -0700229pub mod parsing {
230 use super::*;
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700231 #[cfg(feature = "full")]
232 use ConstExpr;
David Tolnay3cb23a92016-10-07 23:02:21 -0700233 use constant::parsing::const_expr;
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700234 #[cfg(feature = "full")]
235 use expr::parsing::expr;
David Tolnay9d8f1972016-09-04 11:58:48 -0700236 use generics::parsing::{lifetime, lifetime_def, ty_param_bound, bound_lifetimes};
David Tolnay55337722016-09-11 12:58:56 -0700237 use ident::parsing::ident;
David Tolnayb8d8ef52016-10-29 14:30:08 -0700238 use lit::parsing::quoted_string;
David Tolnay0047c712016-12-21 21:59:25 -0500239 #[cfg(feature = "type-macros")]
240 use mac::parsing::mac;
241 #[cfg(not(feature = "type-macros"))]
242 use nom::IResult;
David Tolnay9d8f1972016-09-04 11:58:48 -0700243 use std::str;
David Tolnayda4049b2016-09-04 10:59:23 -0700244
David Tolnayb5a7b142016-09-13 22:46:39 -0700245 named!(pub ty -> Ty, alt!(
David Tolnayd040d772016-10-25 21:33:51 -0700246 ty_paren // must be before ty_tup
247 |
David Tolnay0047c712016-12-21 21:59:25 -0500248 ty_mac // must be before ty_path
249 |
David Tolnay4f0f2512016-10-30 09:28:14 -0700250 ty_path // must be before ty_poly_trait_ref
251 |
David Tolnay9d8f1972016-09-04 11:58:48 -0700252 ty_vec
David Tolnayda4049b2016-09-04 10:59:23 -0700253 |
David Tolnayfa94b6f2016-10-05 23:26:11 -0700254 ty_array
David Tolnayb79ee962016-09-04 09:39:20 -0700255 |
David Tolnay9d8f1972016-09-04 11:58:48 -0700256 ty_ptr
257 |
258 ty_rptr
259 |
260 ty_bare_fn
261 |
262 ty_never
263 |
264 ty_tup
265 |
David Tolnay4f0f2512016-10-30 09:28:14 -0700266 ty_poly_trait_ref
David Tolnay9d8f1972016-09-04 11:58:48 -0700267 |
David Tolnay9d8f1972016-09-04 11:58:48 -0700268 ty_impl_trait
David Tolnay9d8f1972016-09-04 11:58:48 -0700269 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700270
David Tolnay0047c712016-12-21 21:59:25 -0500271 #[cfg(feature = "type-macros")]
272 named!(ty_mac -> Ty, map!(mac, Ty::Mac));
273
274 #[cfg(not(feature = "type-macros"))]
275 fn ty_mac(_: &str) -> IResult<&str, Ty> {
276 IResult::Error
277 }
278
David Tolnayb5a7b142016-09-13 22:46:39 -0700279 named!(ty_vec -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700280 punct!("[") >>
281 elem: ty >>
282 punct!("]") >>
David Tolnay16709ba2016-10-05 23:11:32 -0700283 (Ty::Slice(Box::new(elem)))
David Tolnay9d8f1972016-09-04 11:58:48 -0700284 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700285
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700286 #[cfg(not(feature = "full"))]
David Tolnayfa94b6f2016-10-05 23:26:11 -0700287 named!(ty_array -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700288 punct!("[") >>
289 elem: ty >>
290 punct!(";") >>
David Tolnay3cb23a92016-10-07 23:02:21 -0700291 len: const_expr >>
David Tolnayc94c38a2016-09-05 17:02:03 -0700292 punct!("]") >>
David Tolnayfa94b6f2016-10-05 23:26:11 -0700293 (Ty::Array(Box::new(elem), len))
294 ));
295
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700296 #[cfg(feature = "full")]
297 named!(ty_array -> Ty, do_parse!(
298 punct!("[") >>
299 elem: ty >>
300 punct!(";") >>
301 len: alt!(
302 terminated!(const_expr, punct!("]"))
303 |
304 terminated!(expr, punct!("]")) => { ConstExpr::Other }
305 ) >>
306 (Ty::Array(Box::new(elem), len))
307 ));
308
David Tolnayb5a7b142016-09-13 22:46:39 -0700309 named!(ty_ptr -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700310 punct!("*") >>
David Tolnayb5a7b142016-09-13 22:46:39 -0700311 mutability: alt!(
David Tolnay10413f02016-09-30 09:12:02 -0700312 keyword!("const") => { |_| Mutability::Immutable }
David Tolnay9d8f1972016-09-04 11:58:48 -0700313 |
David Tolnay10413f02016-09-30 09:12:02 -0700314 keyword!("mut") => { |_| Mutability::Mutable }
David Tolnay9d8f1972016-09-04 11:58:48 -0700315 ) >>
316 target: ty >>
317 (Ty::Ptr(Box::new(MutTy {
318 ty: target,
319 mutability: mutability,
320 })))
321 ));
322
David Tolnayb5a7b142016-09-13 22:46:39 -0700323 named!(ty_rptr -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700324 punct!("&") >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700325 life: option!(lifetime) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700326 mutability: mutability >>
327 target: ty >>
328 (Ty::Rptr(life, Box::new(MutTy {
329 ty: target,
330 mutability: mutability,
331 })))
332 ));
333
David Tolnayb5a7b142016-09-13 22:46:39 -0700334 named!(ty_bare_fn -> Ty, do_parse!(
David Tolnay4f121832016-10-25 21:33:36 -0700335 lifetimes: opt_vec!(do_parse!(
336 keyword!("for") >>
337 punct!("<") >>
338 lifetimes: terminated_list!(punct!(","), lifetime_def) >>
339 punct!(">") >>
340 (lifetimes)
David Tolnay6b7aaf02016-09-04 10:39:25 -0700341 )) >>
David Tolnayb8d8ef52016-10-29 14:30:08 -0700342 unsafety: unsafety >>
343 abi: option!(abi) >>
David Tolnay4f121832016-10-25 21:33:36 -0700344 keyword!("fn") >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700345 punct!("(") >>
David Tolnay292e6002016-10-29 22:03:51 -0700346 inputs: separated_list!(punct!(","), fn_arg) >>
347 trailing_comma: option!(punct!(",")) >>
348 variadic: option!(cond_reduce!(trailing_comma.is_some(), punct!("..."))) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700349 punct!(")") >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700350 output: option!(preceded!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700351 punct!("->"),
352 ty
353 )) >>
354 (Ty::BareFn(Box::new(BareFnTy {
David Tolnayb8d8ef52016-10-29 14:30:08 -0700355 unsafety: unsafety,
356 abi: abi,
David Tolnay9d8f1972016-09-04 11:58:48 -0700357 lifetimes: lifetimes,
David Tolnay62f374c2016-10-02 13:37:00 -0700358 inputs: inputs,
359 output: match output {
360 Some(ty) => FunctionRetTy::Ty(ty),
361 None => FunctionRetTy::Default,
David Tolnay9d8f1972016-09-04 11:58:48 -0700362 },
David Tolnay292e6002016-10-29 22:03:51 -0700363 variadic: variadic.is_some(),
David Tolnay9d8f1972016-09-04 11:58:48 -0700364 })))
365 ));
366
David Tolnayb5a7b142016-09-13 22:46:39 -0700367 named!(ty_never -> Ty, map!(punct!("!"), |_| Ty::Never));
David Tolnay9d8f1972016-09-04 11:58:48 -0700368
David Tolnayb5a7b142016-09-13 22:46:39 -0700369 named!(ty_tup -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700370 punct!("(") >>
David Tolnayff46fd22016-10-08 13:53:28 -0700371 elems: terminated_list!(punct!(","), ty) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700372 punct!(")") >>
373 (Ty::Tup(elems))
374 ));
375
David Tolnay6414da72016-10-08 00:55:17 -0700376 named!(ty_path -> Ty, do_parse!(
377 qpath: qpath >>
David Tolnayf6c74402016-10-08 02:31:26 -0700378 parenthesized: cond!(
379 qpath.1.segments.last().unwrap().parameters == PathParameters::none(),
380 option!(parenthesized_parameter_data)
381 ) >>
David Tolnay6414da72016-10-08 00:55:17 -0700382 bounds: many0!(preceded!(punct!("+"), ty_param_bound)) >>
383 ({
David Tolnayf6c74402016-10-08 02:31:26 -0700384 let (qself, mut path) = qpath;
385 if let Some(Some(parenthesized)) = parenthesized {
386 path.segments.last_mut().unwrap().parameters = parenthesized;
387 }
388 let path = Ty::Path(qself, path);
David Tolnay6414da72016-10-08 00:55:17 -0700389 if bounds.is_empty() {
390 path
391 } else {
392 Ty::ObjectSum(Box::new(path), bounds)
393 }
394 })
395 ));
David Tolnay9d8f1972016-09-04 11:58:48 -0700396
David Tolnayf6c74402016-10-08 02:31:26 -0700397 named!(parenthesized_parameter_data -> PathParameters, do_parse!(
398 punct!("(") >>
David Tolnayff46fd22016-10-08 13:53:28 -0700399 inputs: terminated_list!(punct!(","), ty) >>
David Tolnayf6c74402016-10-08 02:31:26 -0700400 punct!(")") >>
401 output: option!(preceded!(
402 punct!("->"),
403 ty
404 )) >>
405 (PathParameters::Parenthesized(
406 ParenthesizedParameterData {
407 inputs: inputs,
408 output: output,
409 },
410 ))
411 ));
412
David Tolnay9636c052016-10-02 17:11:17 -0700413 named!(pub qpath -> (Option<QSelf>, Path), alt!(
414 map!(path, |p| (None, p))
415 |
416 do_parse!(
417 punct!("<") >>
418 this: map!(ty, Box::new) >>
419 path: option!(preceded!(
420 keyword!("as"),
421 path
422 )) >>
423 punct!(">") >>
424 punct!("::") >>
425 rest: separated_nonempty_list!(punct!("::"), path_segment) >>
426 ({
427 match path {
428 Some(mut path) => {
429 let pos = path.segments.len();
430 path.segments.extend(rest);
431 (Some(QSelf { ty: this, position: pos }), path)
432 }
433 None => {
434 (Some(QSelf { ty: this, position: 0 }), Path {
435 global: false,
436 segments: rest,
437 })
438 }
David Tolnayb79ee962016-09-04 09:39:20 -0700439 }
David Tolnay9636c052016-10-02 17:11:17 -0700440 })
441 )
David Tolnay6cd2a232016-10-24 22:41:08 -0700442 |
443 map!(keyword!("self"), |_| (None, "self".into()))
David Tolnay9d8f1972016-09-04 11:58:48 -0700444 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700445
David Tolnay4f0f2512016-10-30 09:28:14 -0700446 named!(ty_poly_trait_ref -> Ty, map!(
David Tolnay8eb6c452016-10-30 13:19:15 -0700447 separated_nonempty_list!(punct!("+"), ty_param_bound),
448 Ty::PolyTraitRef
David Tolnay6414da72016-10-08 00:55:17 -0700449 ));
450
David Tolnayb5a7b142016-09-13 22:46:39 -0700451 named!(ty_impl_trait -> Ty, do_parse!(
David Tolnay10413f02016-09-30 09:12:02 -0700452 keyword!("impl") >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700453 elem: separated_nonempty_list!(punct!("+"), ty_param_bound) >>
454 (Ty::ImplTrait(elem))
455 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700456
David Tolnayb5a7b142016-09-13 22:46:39 -0700457 named!(ty_paren -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700458 punct!("(") >>
459 elem: ty >>
460 punct!(")") >>
461 (Ty::Paren(Box::new(elem)))
462 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700463
David Tolnay47a877c2016-10-01 16:50:55 -0700464 named!(pub mutability -> Mutability, alt!(
David Tolnaybd76e572016-10-02 13:43:16 -0700465 keyword!("mut") => { |_| Mutability::Mutable }
David Tolnayf6ccb832016-09-04 15:00:56 -0700466 |
467 epsilon!() => { |_| Mutability::Immutable }
David Tolnay9d8f1972016-09-04 11:58:48 -0700468 ));
469
David Tolnayb5a7b142016-09-13 22:46:39 -0700470 named!(pub path -> Path, do_parse!(
David Tolnayf6ccb832016-09-04 15:00:56 -0700471 global: option!(punct!("::")) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700472 segments: separated_nonempty_list!(punct!("::"), path_segment) >>
473 (Path {
474 global: global.is_some(),
475 segments: segments,
476 })
477 ));
478
David Tolnay9636c052016-10-02 17:11:17 -0700479 named!(path_segment -> PathSegment, alt!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700480 do_parse!(
David Tolnay9636c052016-10-02 17:11:17 -0700481 id: option!(ident) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700482 punct!("<") >>
483 lifetimes: separated_list!(punct!(","), lifetime) >>
484 types: opt_vec!(preceded!(
485 cond!(!lifetimes.is_empty(), punct!(",")),
486 separated_nonempty_list!(
487 punct!(","),
488 terminated!(ty, not!(peek!(punct!("="))))
489 )
490 )) >>
491 bindings: opt_vec!(preceded!(
492 cond!(!lifetimes.is_empty() || !types.is_empty(), punct!(",")),
493 separated_nonempty_list!(punct!(","), type_binding)
494 )) >>
David Tolnay82a47d52016-10-30 13:01:38 -0700495 cond!(!lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty(), option!(punct!(","))) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700496 punct!(">") >>
497 (PathSegment {
David Tolnay9636c052016-10-02 17:11:17 -0700498 ident: id.unwrap_or_else(|| "".into()),
David Tolnay9d8f1972016-09-04 11:58:48 -0700499 parameters: PathParameters::AngleBracketed(
500 AngleBracketedParameterData {
501 lifetimes: lifetimes,
502 types: types,
503 bindings: bindings,
504 }
505 ),
506 })
507 )
508 |
David Tolnay84aa0752016-10-02 23:01:13 -0700509 map!(ident, Into::into)
David Tolnay77807222016-10-24 22:30:15 -0700510 |
David Tolnaye14e3be2016-10-24 22:53:07 -0700511 map!(alt!(
512 keyword!("super")
513 |
514 keyword!("self")
515 |
516 keyword!("Self")
517 ), Into::into)
David Tolnay9d8f1972016-09-04 11:58:48 -0700518 ));
519
David Tolnayb5a7b142016-09-13 22:46:39 -0700520 named!(type_binding -> TypeBinding, do_parse!(
David Tolnay55337722016-09-11 12:58:56 -0700521 id: ident >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700522 punct!("=") >>
523 ty: ty >>
524 (TypeBinding {
David Tolnay55337722016-09-11 12:58:56 -0700525 ident: id,
David Tolnay9d8f1972016-09-04 11:58:48 -0700526 ty: ty,
527 })
528 ));
529
David Tolnayb5a7b142016-09-13 22:46:39 -0700530 named!(pub poly_trait_ref -> PolyTraitRef, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700531 bound_lifetimes: bound_lifetimes >>
532 trait_ref: path >>
David Tolnay4f0f2512016-10-30 09:28:14 -0700533 parenthesized: option!(cond_reduce!(
David Tolnayf6c74402016-10-08 02:31:26 -0700534 trait_ref.segments.last().unwrap().parameters == PathParameters::none(),
David Tolnay4f0f2512016-10-30 09:28:14 -0700535 parenthesized_parameter_data
536 )) >>
David Tolnayf6c74402016-10-08 02:31:26 -0700537 ({
538 let mut trait_ref = trait_ref;
David Tolnay4f0f2512016-10-30 09:28:14 -0700539 if let Some(parenthesized) = parenthesized {
David Tolnayf6c74402016-10-08 02:31:26 -0700540 trait_ref.segments.last_mut().unwrap().parameters = parenthesized;
541 }
542 PolyTraitRef {
543 bound_lifetimes: bound_lifetimes,
544 trait_ref: trait_ref,
545 }
David Tolnay9d8f1972016-09-04 11:58:48 -0700546 })
547 ));
548
David Tolnay62f374c2016-10-02 13:37:00 -0700549 named!(pub fn_arg -> BareFnArg, do_parse!(
David Tolnayb0417d72016-10-25 21:46:35 -0700550 name: option!(do_parse!(
551 name: ident >>
552 punct!(":") >>
553 not!(peek!(tag!(":"))) >> // not ::
554 (name)
555 )) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700556 ty: ty >>
David Tolnay62f374c2016-10-02 13:37:00 -0700557 (BareFnArg {
558 name: name,
David Tolnay9d8f1972016-09-04 11:58:48 -0700559 ty: ty,
560 })
561 ));
David Tolnayb8d8ef52016-10-29 14:30:08 -0700562
563 named!(pub unsafety -> Unsafety, alt!(
564 keyword!("unsafe") => { |_| Unsafety::Unsafe }
565 |
566 epsilon!() => { |_| Unsafety::Normal }
567 ));
568
569 named!(pub abi -> Abi, do_parse!(
570 keyword!("extern") >>
571 name: option!(quoted_string) >>
572 (match name {
573 Some(name) => Abi::Named(name),
David Tolnay76195ce2016-10-30 16:53:48 -0700574 None => Abi::Rust,
David Tolnayb8d8ef52016-10-29 14:30:08 -0700575 })
576 ));
David Tolnay9d8f1972016-09-04 11:58:48 -0700577}
David Tolnay87d0b442016-09-04 11:52:12 -0700578
579#[cfg(feature = "printing")]
580mod printing {
581 use super::*;
582 use quote::{Tokens, ToTokens};
583
584 impl ToTokens for Ty {
585 fn to_tokens(&self, tokens: &mut Tokens) {
586 match *self {
David Tolnay16709ba2016-10-05 23:11:32 -0700587 Ty::Slice(ref inner) => {
David Tolnay87d0b442016-09-04 11:52:12 -0700588 tokens.append("[");
589 inner.to_tokens(tokens);
590 tokens.append("]");
591 }
David Tolnayfa94b6f2016-10-05 23:26:11 -0700592 Ty::Array(ref inner, ref len) => {
David Tolnay87d0b442016-09-04 11:52:12 -0700593 tokens.append("[");
594 inner.to_tokens(tokens);
595 tokens.append(";");
David Tolnayfa94b6f2016-10-05 23:26:11 -0700596 len.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700597 tokens.append("]");
598 }
599 Ty::Ptr(ref target) => {
600 tokens.append("*");
601 match target.mutability {
602 Mutability::Mutable => tokens.append("mut"),
603 Mutability::Immutable => tokens.append("const"),
604 }
605 target.ty.to_tokens(tokens);
606 }
607 Ty::Rptr(ref lifetime, ref target) => {
608 tokens.append("&");
609 lifetime.to_tokens(tokens);
David Tolnay47a877c2016-10-01 16:50:55 -0700610 target.mutability.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700611 target.ty.to_tokens(tokens);
612 }
613 Ty::BareFn(ref func) => {
614 func.to_tokens(tokens);
615 }
616 Ty::Never => {
617 tokens.append("!");
618 }
619 Ty::Tup(ref elems) => {
620 tokens.append("(");
David Tolnay94ebdf92016-09-04 13:33:16 -0700621 tokens.append_separated(elems, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700622 if elems.len() == 1 {
623 tokens.append(",");
624 }
625 tokens.append(")");
626 }
David Tolnayf69904a2016-09-04 14:46:07 -0700627 Ty::Path(None, ref path) => {
628 path.to_tokens(tokens);
629 }
630 Ty::Path(Some(ref qself), ref path) => {
631 tokens.append("<");
632 qself.ty.to_tokens(tokens);
633 if qself.position > 0 {
634 tokens.append("as");
David Tolnaydaaf7742016-10-03 11:11:43 -0700635 for (i, segment) in path.segments
636 .iter()
637 .take(qself.position)
638 .enumerate() {
David Tolnayf69904a2016-09-04 14:46:07 -0700639 if i > 0 || path.global {
640 tokens.append("::");
David Tolnay87d0b442016-09-04 11:52:12 -0700641 }
David Tolnayf69904a2016-09-04 14:46:07 -0700642 segment.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700643 }
David Tolnayf69904a2016-09-04 14:46:07 -0700644 }
645 tokens.append(">");
646 for segment in path.segments.iter().skip(qself.position) {
647 tokens.append("::");
648 segment.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700649 }
650 }
David Tolnay6414da72016-10-08 00:55:17 -0700651 Ty::ObjectSum(ref ty, ref bounds) => {
652 ty.to_tokens(tokens);
653 for bound in bounds {
654 tokens.append("+");
655 bound.to_tokens(tokens);
656 }
657 }
658 Ty::PolyTraitRef(ref bounds) => {
659 tokens.append_separated(bounds, "+");
660 }
David Tolnay87d0b442016-09-04 11:52:12 -0700661 Ty::ImplTrait(ref bounds) => {
662 tokens.append("impl");
David Tolnay94ebdf92016-09-04 13:33:16 -0700663 tokens.append_separated(bounds, "+");
David Tolnay87d0b442016-09-04 11:52:12 -0700664 }
665 Ty::Paren(ref inner) => {
666 tokens.append("(");
667 inner.to_tokens(tokens);
668 tokens.append(")");
669 }
670 Ty::Infer => {
671 tokens.append("_");
672 }
David Tolnay0047c712016-12-21 21:59:25 -0500673 Ty::Mac(ref mac) => mac.to_tokens(tokens),
David Tolnay87d0b442016-09-04 11:52:12 -0700674 }
675 }
676 }
677
David Tolnay47a877c2016-10-01 16:50:55 -0700678 impl ToTokens for Mutability {
679 fn to_tokens(&self, tokens: &mut Tokens) {
680 if let Mutability::Mutable = *self {
681 tokens.append("mut");
682 }
683 }
684 }
685
David Tolnay87d0b442016-09-04 11:52:12 -0700686 impl ToTokens for Path {
687 fn to_tokens(&self, tokens: &mut Tokens) {
688 for (i, segment) in self.segments.iter().enumerate() {
689 if i > 0 || self.global {
690 tokens.append("::");
691 }
692 segment.to_tokens(tokens);
693 }
694 }
695 }
696
697 impl ToTokens for PathSegment {
698 fn to_tokens(&self, tokens: &mut Tokens) {
699 self.ident.to_tokens(tokens);
David Tolnay5332d4b2016-10-30 14:25:22 -0700700 if self.ident.as_ref().is_empty() && self.parameters.is_empty() {
701 tokens.append("<");
702 tokens.append(">");
703 } else {
704 self.parameters.to_tokens(tokens);
705 }
David Tolnay87d0b442016-09-04 11:52:12 -0700706 }
707 }
708
709 impl ToTokens for PathParameters {
710 fn to_tokens(&self, tokens: &mut Tokens) {
711 match *self {
712 PathParameters::AngleBracketed(ref parameters) => {
713 parameters.to_tokens(tokens);
714 }
715 PathParameters::Parenthesized(ref parameters) => {
716 parameters.to_tokens(tokens);
717 }
718 }
719 }
720 }
721
722 impl ToTokens for AngleBracketedParameterData {
723 fn to_tokens(&self, tokens: &mut Tokens) {
724 let has_lifetimes = !self.lifetimes.is_empty();
725 let has_types = !self.types.is_empty();
726 let has_bindings = !self.bindings.is_empty();
727 if !has_lifetimes && !has_types && !has_bindings {
728 return;
729 }
730
731 tokens.append("<");
732
733 let mut first = true;
734 for lifetime in &self.lifetimes {
735 if !first {
736 tokens.append(",");
737 }
738 lifetime.to_tokens(tokens);
739 first = false;
740 }
741 for ty in &self.types {
742 if !first {
743 tokens.append(",");
744 }
745 ty.to_tokens(tokens);
746 first = false;
747 }
748 for binding in &self.bindings {
749 if !first {
750 tokens.append(",");
751 }
752 binding.to_tokens(tokens);
753 first = false;
754 }
755
756 tokens.append(">");
757 }
758 }
759
760 impl ToTokens for TypeBinding {
761 fn to_tokens(&self, tokens: &mut Tokens) {
762 self.ident.to_tokens(tokens);
763 tokens.append("=");
764 self.ty.to_tokens(tokens);
765 }
766 }
767
768 impl ToTokens for ParenthesizedParameterData {
769 fn to_tokens(&self, tokens: &mut Tokens) {
770 tokens.append("(");
David Tolnay94ebdf92016-09-04 13:33:16 -0700771 tokens.append_separated(&self.inputs, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700772 tokens.append(")");
773 if let Some(ref output) = self.output {
774 tokens.append("->");
775 output.to_tokens(tokens);
776 }
777 }
778 }
779
780 impl ToTokens for PolyTraitRef {
781 fn to_tokens(&self, tokens: &mut Tokens) {
782 if !self.bound_lifetimes.is_empty() {
David Tolnaye8796aa2016-09-04 14:48:22 -0700783 tokens.append("for");
David Tolnay87d0b442016-09-04 11:52:12 -0700784 tokens.append("<");
David Tolnay94ebdf92016-09-04 13:33:16 -0700785 tokens.append_separated(&self.bound_lifetimes, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700786 tokens.append(">");
787 }
788 self.trait_ref.to_tokens(tokens);
789 }
790 }
791
792 impl ToTokens for BareFnTy {
793 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay87d0b442016-09-04 11:52:12 -0700794 if !self.lifetimes.is_empty() {
David Tolnay4f121832016-10-25 21:33:36 -0700795 tokens.append("for");
David Tolnay87d0b442016-09-04 11:52:12 -0700796 tokens.append("<");
David Tolnay42602292016-10-01 22:25:45 -0700797 tokens.append_separated(&self.lifetimes, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700798 tokens.append(">");
799 }
David Tolnayb8d8ef52016-10-29 14:30:08 -0700800 self.unsafety.to_tokens(tokens);
801 self.abi.to_tokens(tokens);
David Tolnay4f121832016-10-25 21:33:36 -0700802 tokens.append("fn");
David Tolnay87d0b442016-09-04 11:52:12 -0700803 tokens.append("(");
David Tolnay42602292016-10-01 22:25:45 -0700804 tokens.append_separated(&self.inputs, ",");
David Tolnay292e6002016-10-29 22:03:51 -0700805 if self.variadic {
806 if !self.inputs.is_empty() {
807 tokens.append(",");
808 }
809 tokens.append("...");
810 }
David Tolnay87d0b442016-09-04 11:52:12 -0700811 tokens.append(")");
David Tolnay42602292016-10-01 22:25:45 -0700812 if let FunctionRetTy::Ty(ref ty) = self.output {
813 tokens.append("->");
814 ty.to_tokens(tokens);
815 }
816 }
817 }
818
David Tolnay62f374c2016-10-02 13:37:00 -0700819 impl ToTokens for BareFnArg {
David Tolnay42602292016-10-01 22:25:45 -0700820 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay62f374c2016-10-02 13:37:00 -0700821 if let Some(ref name) = self.name {
822 name.to_tokens(tokens);
David Tolnay42602292016-10-01 22:25:45 -0700823 tokens.append(":");
824 }
825 self.ty.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700826 }
827 }
David Tolnayb8d8ef52016-10-29 14:30:08 -0700828
829 impl ToTokens for Unsafety {
830 fn to_tokens(&self, tokens: &mut Tokens) {
831 match *self {
832 Unsafety::Unsafe => tokens.append("unsafe"),
833 Unsafety::Normal => {
834 // nothing
835 }
836 }
837 }
838 }
839
840 impl ToTokens for Abi {
841 fn to_tokens(&self, tokens: &mut Tokens) {
842 tokens.append("extern");
843 match *self {
844 Abi::Named(ref named) => named.to_tokens(tokens),
David Tolnay76195ce2016-10-30 16:53:48 -0700845 Abi::Rust => {}
David Tolnayb8d8ef52016-10-29 14:30:08 -0700846 }
847 }
848 }
David Tolnay0047c712016-12-21 21:59:25 -0500849
850 #[cfg(not(feature = "type-macros"))]
851 impl ToTokens for Mac {
852 fn to_tokens(&self, _tokens: &mut Tokens) {
853 unreachable!()
854 }
855 }
David Tolnay87d0b442016-09-04 11:52:12 -0700856}